public JTimeSchedFrame() {
		super("jTimeSched");
		
		this.updateIconImage(false);
		this.setPreferredSize(new Dimension(600, 200));
		this.setMinimumSize(new Dimension(520, 150));
		
		
		// create tray-icon and set default close-behavior
		if (this.setupTrayIcon())
			this.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
		else
			this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		
		// add handler for GUI log
		JTimeSchedApp.getLogger().addHandler(new JTimeSchedGUILogHandler(this.tfLog));
		
		
		// backup project-file
		try {
			this.backupProjects();
		} catch (FileNotFoundException e) {
			// ignore this exception: no project file -> no backup
		} catch (Exception e) {
			e.printStackTrace();
	    	JTimeSchedApp.getLogger().warning("Unable to create backup of project file: " + e.getMessage());
		}
		
		// load project-file
		try {
			this.loadProjects();
		} catch (FileNotFoundException e) {
			JTimeSchedApp.getLogger().info("Projects file does not exist, starting with empty projects file.");
		} catch (Exception e) {
			e.printStackTrace();
			JTimeSchedApp.getLogger().severe("Error loading projects file: " + e.getMessage());
			
			JOptionPane.showMessageDialog(this,
					"An error occurred while loading the projects file.\n" +
					"Details: \"" + e.getMessage() + "\"\n\n" +
					"Please correct or remove the file '" + JTimeSchedApp.PRJ_FILE + "' " +
					"(or replace it with the backup file '" + JTimeSchedApp.PRJ_FILE_BACKUP + "', if present).\n\n" +
					"JTimeSched will quit now to avoid data corruption.",
					"Error loading projects file",
					JOptionPane.ERROR_MESSAGE);
			
			System.exit(1);
		}
		
		// check all projects for a today-time reset
		checkResetToday();
		
		
		// create model an associate data
		ProjectTableModel tstm = new ProjectTableModel(this.arPrj);
		
		// create table
		this.tblSched = new ProjectTable(this, tstm);
		
		// listen on table-clicks
		this.tblSched.addMouseListener(new TimeSchedTableMouseListener());
		this.tblSched.getTableHeader().addMouseListener(new TimeSchedTableHeaderMouseListener());
		
		this.tblSched.addKeyListener(new TimeSchedTableKeyListener());
		
		// add table to a scroll-pane
		JScrollPane spSched = new JScrollPane(this.tblSched);
		this.add(spSched, BorderLayout.CENTER);

		
		
		// bottom panel
		JPanel panelBottom = new JPanel();
		panelBottom.setLayout(new BoxLayout(panelBottom, BoxLayout.LINE_AXIS));
		JButton btnAdd = new JButton("Add project", JTimeSchedFrame.getImageIcon("project-add.png"));
		btnAdd.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				handleNewButton();
			}
		});
		panelBottom.add(btnAdd);
			
		// bottom panel
		panelBottom.add(Box.createRigidArea(new Dimension(10, 0)));
		panelBottom.add(Box.createHorizontalGlue());
		this.lblOverall = new JLabel("", SwingConstants.CENTER);
		this.lblOverall.setFont(this.lblOverall.getFont().deriveFont(Font.PLAIN));
		panelBottom.add(this.lblOverall);
		panelBottom.add(Box.createHorizontalGlue());
		panelBottom.add(Box.createRigidArea(new Dimension(10, 0)));
		
		// highlight editbox
		this.tfHighlight = new JTextField(6);
		this.tfHighlight.setToolTipText("highlight expression");
		this.tfHighlight.addFocusListener(new FocusListener(){
			@Override
			public void focusGained(FocusEvent fe) {
				tfHighlight.selectAll();
			}

			@Override
			public void focusLost(FocusEvent fe) {}
		});
		this.tfHighlight.addKeyListener(new KeyListener(){
			@Override
			public void keyPressed(KeyEvent ke) {}

			@Override
			public void keyReleased(KeyEvent ke) {
				tblSched.setHighlightString(tfHighlight.getText());
				tblSched.repaint();
			}

			@Override
			public void keyTyped(KeyEvent ke) {}
		});
		
		Dimension sizeTf = new Dimension(100, this.tfHighlight.getMinimumSize().height);
		this.tfHighlight.setMaximumSize(sizeTf);
		this.tfHighlight.setMaximumSize(sizeTf);
		panelBottom.add(this.tfHighlight);
		panelBottom.add(Box.createRigidArea(new Dimension(5, 0)));
		
		// log toggle button
		this.btnLogToggle = new JToggleButton(JTimeSchedFrame.getImageIcon("log-toggle.png"));
		this.btnLogToggle.setToolTipText("toggle log area");
		this.btnLogToggle.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				Boolean isVisible = spLog.isVisible();
				setSize(getWidth(), getHeight() + JTimeSchedFrame.LOGAREA_HEIGHT * (isVisible ? -1 : 1));
				spLog.setVisible(!isVisible);
				spLog.doLayout();
				doLayout();
			}}
		);
		panelBottom.add(this.btnLogToggle);
		
		
		// logging area
		this.tfLog.setEditable(false);
		//this.tfLog.setFont(this.tfLog.getFont().deriveFont(10.0f));
		this.spLog = new JScrollPane(this.tfLog);
		this.spLog.setVisible(false);
		this.spLog.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		this.spLog.setPreferredSize(new Dimension(100 /* ignored */, JTimeSchedFrame.LOGAREA_HEIGHT));
		
		
		// the whole bottom panel
		JPanel panelBottomAll = new JPanel(new BorderLayout());
		panelBottomAll.add(panelBottom, BorderLayout.NORTH);
		panelBottomAll.add(this.spLog, BorderLayout.SOUTH);
		this.add(panelBottomAll, BorderLayout.SOUTH);
		
		
		// load settings
		try {
			this.loadSettings();
		} catch (FileNotFoundException fnfe) {
			JTimeSchedApp.getLogger().info("Settings file does not exist, running with defaults.");
		} catch (Exception e) {
			e.printStackTrace();
			JTimeSchedApp.getLogger().warning("Error loading settings, running with defaults: " + e.getMessage());
		}
		
		
		// setup projects-save timer, interval 60 seconds
		saveTimer = new Timer(60*1000, new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent ae) {
				saveProjects();
			}
		});
		
		saveTimer.setRepeats(true);
		saveTimer.start();
		
		
		// setup GUI update timer
		Timer timer = new Timer(1*1000, new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent ae) {
				updateGUI();
			}
		});
		
		//timer.setInitialDelay(0);
		timer.setRepeats(true);
		timer.start();
		
		
		// initially refresh GUI values
		// Note: we need to do the initial update before the pack(), so
		// timer.setInitialDelay(0) for the update timer isn't enough
		this.updateGUI();
		
		this.pack();
		this.tblSched.requestFocusInWindow();
		this.setVisible(this.initiallyVisible);
	}