private MainFrame()
	{
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setVisible(true);
		setTitle("FBMS: File Backup and Management System");

		addWindowListener(new WindowAdapter()
		{
			@Override
			public void windowClosed(WindowEvent arg0)
			{
				instance = null;

				if(timer != null)
				{
					timer.stop();
					timer = null;
				}
			}
		});

		// Set size and position
		setSize(900, 400);
		setLocationRelativeTo(null);

		// Create main panel
		contentPane = new JPanel();
		contentPane.setLayout(new BorderLayout(0, 0));
		setContentPane(contentPane);

		// Set the icon
		setIconImage(new ImageIcon("res/icon.png").getImage());

		// Create menu
		menubar = new MainMenu();
		setJMenuBar(menubar);

		// Create toolbar
		toolbar = new MainToolBar();
		add(toolbar, BorderLayout.NORTH);

		// Create table columns
		columns = new Vector<>();
		columns.add("");
		columns.add("Name");
		columns.add("Size");
		columns.add("Created date");
		columns.add("Accessed date");
		columns.add("Modified date");
		columns.add("Revisions");
		columns.add("Revision sizes");

		// Create table
		table = new JTable();
		table.setShowGrid(false);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.getTableHeader().setReorderingAllowed(false);

		// Insert the data into a modified table model based on the default. This lets us disable
		// editing of table cells.
		DataRetriever folderRetriever = new DataRetriever(Main.backupDirectory);
		rows = folderRetriever.getFolderContentsTable();
		table.setModel(new DefaultTableModel(rows, columns)
		{
			@Override
			public boolean isCellEditable(int row, int column)
			{
				return false;
			}

			@Override
			public Class<?> getColumnClass(int column)
			{
				return getValueAt(0, column).getClass();
			}
		});

		// Set some default column sizes as larger, so dates fit in better
		table.getColumnModel().getColumn(0).setMinWidth(25);
		table.getColumnModel().getColumn(0).setMaxWidth(25);
		table.getColumnModel().getColumn(1).setMinWidth(100);
		table.getColumnModel().getColumn(3).setMinWidth(115);
		table.getColumnModel().getColumn(4).setMinWidth(115);
		table.getColumnModel().getColumn(5).setMinWidth(115);

		// Make the enter key active the cell instead of going to the next cell. Basically, we
		// create a new keyboard mapping for the enter key which does nothing, allowing the listener
		// to pick up the enter key later.
		final String solve = "Solve";
		KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
		table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(enter, solve);
		table.getActionMap().put(solve, null);

		// Create scrollpane for the table
		JScrollPane scrollPane = new JScrollPane(table);
		scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		table.setFillsViewportHeight(true);
		add(scrollPane, BorderLayout.CENTER);

		// Set the current directory
		currentDirectory = Main.backupDirectory;

		// In the backup directory, the location bar is set to a single slash. The direction of the
		// slash is platform dependent. Windows uses \\ while Unix and Mac use /.
		toolbar.locationBar.setText(File.separator);

		// Necessary to revalidate the frame so that we can see the table
		revalidate();

		table.addMouseListener(new TableSelectionListener());
		table.addKeyListener(new TableSelectionListener());

		logger.info("Main frame drawn");

		// Auto refresh the folder contents every 2 seconds
		timer = new Timer(2000, new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				Path selectedFileBackup = selectedFile;

				// Note that this will blank selectedFile
				redrawTable(currentDirectory);

				// Reselect the row (if any)
				if(selectedFileBackup != null)
				{
					// Figure out which row is supposed to be selected (by name)
					int selectedRowNumber = -1;
					for(Vector<Object> row : rows)
					{
						selectedRowNumber++;
						String fileName = (String) row.get(1);
						if(fileName.equals(selectedFileBackup.getFileName().toString()))
						{
							// Found the right row, so the selected file persists (otherwise the
							// file has presumably gone missing and we can't select that)
							selectedFile = selectedFileBackup;
							break;
						}
					}
					table.setRowSelectionInterval(selectedRowNumber, selectedRowNumber);
				}
			}
		});
		timer.start();
	}