public void initialise() {
		prefs = Preferences.userNodeForPackage(this.getClass());

		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e) {
			System.err.println("Unable to switch to native look and feel.");
		}

		try {
			filePath = new File(prefs.get(PREF_FILE_PATH, "."));
		} catch (Exception e) {
			filePath = null;
		}
		
		frmOpenaltimeter = new JFrame();
		frmOpenaltimeter.setIconImage(Toolkit.getDefaultToolkit().getImage(MainWindow.class.getResource("/logo_short_64.png")));
		frmOpenaltimeter.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent arg0) {
				controller.exit();
			}
		});
		frmOpenaltimeter.setTitle("openaltimeter");
		frmOpenaltimeter.setBounds(prefs.getInt(PREF_WINDOW_X, 70),
				                   prefs.getInt(PREF_WINDOW_Y, 70),
				                   prefs.getInt(PREF_WINDOW_WIDTH, 1100),
				                   prefs.getInt(PREF_WINDOW_HEIGHT, 700));
		frmOpenaltimeter.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		
		JMenuBar menuBar = new JMenuBar();
		frmOpenaltimeter.setJMenuBar(menuBar);

		JMenu mnFile = new JMenu("File");
		menuBar.add(mnFile);

		mntmSaveData = new JMenuItem("Save data ...");
		mntmSaveData.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.saveRaw();
			}
		});
		
		JMenuItem mntmLoadRawData = new JMenuItem("Load data ...");
		mntmLoadRawData.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.loadRawData();
			}
		});
		mnFile.add(mntmLoadRawData);
		
		mnFile.addSeparator();
		mntmSaveData.setEnabled(false);
		mnFile.add(mntmSaveData);
		
		mntmSaveSelectionData = new JMenuItem("Save selection data...");
		mntmSaveSelectionData.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.saveRawSelection(altimeterChart.getVisibleDomainLowerBound(), 
						altimeterChart.getVisibleDomainUpperBound());
			}
		});
		mntmSaveSelectionData.setEnabled(false);
		mnFile.add(mntmSaveSelectionData);
		
		JMenuItem mntmExit = new JMenuItem("Exit");
		mntmExit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.exit();
			}
		});
		
		mnFile.addSeparator();
		mnFile.add(mntmExit);
		
		JMenu mnView = new JMenu("View");
		menuBar.add(mnView);
		
		final JCheckBoxMenuItem chckbxmntmAltitude = new JCheckBoxMenuItem("Altitude");
		chckbxmntmAltitude.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.altitudePlotSelectedChange(chckbxmntmAltitude.isSelected());
			}
		});
		chckbxmntmAltitude.setSelected(true);
		mnView.add(chckbxmntmAltitude);
		
		chckbxmntmVoltage = new JCheckBoxMenuItem("Voltage");
		chckbxmntmVoltage.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.voltagePlotSelectedChange(chckbxmntmVoltage.isSelected());
			}
		});
		chckbxmntmVoltage.setSelected(prefs.getBoolean(PREF_SHOW_VOLTAGE, false));
		mnView.add(chckbxmntmVoltage);
		
		chckbxmntmServo = new JCheckBoxMenuItem("Servo");
		chckbxmntmServo.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.servoPlotSelectedChange(chckbxmntmServo.isSelected());
			}
		});
		chckbxmntmServo.setSelected(prefs.getBoolean(PREF_SHOW_SERVO, false));
		mnView.add(chckbxmntmServo);

		chckbxmntmTemperature = new JCheckBoxMenuItem("Temperature");
		chckbxmntmTemperature.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.temperaturePlotSelectedChange(chckbxmntmTemperature.isSelected());
			}
		});
		chckbxmntmTemperature.setSelected(prefs.getBoolean(PREF_SHOW_TEMPERATURE, false));
		mnView.add(chckbxmntmTemperature);
		
		mnView.addSeparator();
		
		ButtonGroup heightUnitsGroup = new ButtonGroup();
		
		// TODO: this currently limits us to two unit systems.
		HeightUnits units = controller.getHeightUnits();
		
		rdbtnmntmFeet = new JRadioButtonMenuItem("Feet");
		rdbtnmntmFeet.setEnabled(true);
		rdbtnmntmFeet.setSelected(units == HeightUnits.FT);
		rdbtnmntmFeet.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				HeightUnits hu;
				if (rdbtnmntmFeet.isSelected()) hu = HeightUnits.FT;
				else hu = HeightUnits.METERS;
				controller.unitSelectedChange(hu);
			}
		});
		heightUnitsGroup.add(rdbtnmntmFeet);
		mnView.add(rdbtnmntmFeet);
		
		rdbtnmntmMetres = new JRadioButtonMenuItem("Metres");
		rdbtnmntmMetres.setEnabled(true);
		rdbtnmntmMetres.setSelected(units == HeightUnits.METERS);
		rdbtnmntmMetres.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				HeightUnits hu;
				if (rdbtnmntmFeet.isSelected()) hu = HeightUnits.FT;
				else hu = HeightUnits.METERS;
				controller.unitSelectedChange(hu);			}
		});
		heightUnitsGroup.add(rdbtnmntmMetres);
		mnView.add(rdbtnmntmMetres);
		
		mnAnalysis = new JMenu("Analysis");
		menuBar.add(mnAnalysis);
		
		mntmMarkDlgLaunches = new JMenuItem("Analyse DLG flights ...");
		mntmMarkDlgLaunches.setEnabled(false);
		mntmMarkDlgLaunches.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.analyseDLGFlights();
			}
		});
		mnAnalysis.add(mntmMarkDlgLaunches);
		
		mntmClearDlgLaunch = new JMenuItem("Clear DLG analysis");
		mntmClearDlgLaunch.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				controller.clearDLGAnalysis();
			}
		});
		mnAnalysis.add(mntmClearDlgLaunch);
		
		mnAnalysis.addSeparator();
		
		mntmClearAnnotations = new JMenuItem("Clear height and vario annotations");
		mnAnalysis.add(mntmClearAnnotations);
		mntmClearAnnotations.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				altimeterChart.clearHeightAndVarioAnnotations();
			}
		});

		JMenu mnConnection = new JMenu("Connection");
		menuBar.add(mnConnection);

		mnSerialPort = new JMenu("Serial port");
		mnConnection.add(mnSerialPort);
		serialMenuGroup = new ButtonGroup();

		mntmConnect = new JMenuItem("Connect");
		mntmConnect.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.connect();
			}
		});
		mnConnection.add(mntmConnect);

		mntmDisconnect = new JMenuItem("Disconnect");
		mntmDisconnect.setEnabled(false);
		mntmDisconnect.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.disconnect();
			}
		});
		mnConnection.add(mntmDisconnect);

		JMenu mnLogger = new JMenu("Altimeter");
		menuBar.add(mnLogger);

		mntmDownloadData = new JMenuItem("Download data");
		mntmDownloadData.setEnabled(false);
		mntmDownloadData.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.downloadData();
			}
		});
		mnLogger.add(mntmDownloadData);

		mntmEraseLogger = new JMenuItem("Erase altimeter memory ...");
		mntmEraseLogger.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.erase();
			}
		});
		mntmEraseLogger.setEnabled(false);
		mnLogger.add(mntmEraseLogger);
		
		mntmSettings = new JMenuItem("Settings ...");
		mntmSettings.setEnabled(false);
		mntmSettings.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.runSettingsInterface();
			}
		});
		mnLogger.add(mntmSettings);
		
		mnLogger.addSeparator();
		
		mntmFlashFirmware = new JMenuItem("Flash firmware ...");
		mntmFlashFirmware.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.flashFirmware();
			}
		});
		mnLogger.add(mntmFlashFirmware);
		
		mnAdvanced = new JMenu("Advanced");
		mnAdvanced.setVisible(false);
		menuBar.add(mnAdvanced);
		
		mntmUploadSelectionerases = new JMenuItem("Upload selection (erases OA)");
		mntmUploadSelectionerases.setEnabled(false);
		mntmUploadSelectionerases.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				controller.uploadSelection(altimeterChart.getVisibleDomainLowerBound(),
						altimeterChart.getVisibleDomainUpperBound());
			}
		});
		mnAdvanced.add(mntmUploadSelectionerases);
		// os specific function
		if (controller.os != OS.OTHER) 
			mntmFlashFirmware.setEnabled(true);
		else  mntmFlashFirmware.setEnabled(false);

		JSplitPane splitPane = new JSplitPane();
		splitPane.setContinuousLayout(true);
		splitPane.setResizeWeight(0.6);
		splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
		splitPane.setDividerLocation(-1);
		frmOpenaltimeter.getContentPane().add(splitPane, BorderLayout.CENTER);

		altimeterChart = new AltimeterChart();
		altimeterChart.setHeightUnits(units);
		splitPane.setTopComponent(altimeterChart.getChartPanel());

		altimeterChart.setVoltagePlotVisible(prefs.getBoolean(PREF_SHOW_VOLTAGE, false));
		altimeterChart.setTemperaturePlotVisible(prefs.getBoolean(PREF_SHOW_TEMPERATURE, false));
		altimeterChart.setServoPlotVisible(prefs.getBoolean(PREF_SHOW_SERVO, false));

		// create the text pane, a document for it to view, and some styles
		logTextPane = new JTextPane();
		logTextPane.setPreferredSize(new Dimension(6, 100));
		logDocument = logTextPane.getStyledDocument(); 
	    Style defaultStyle = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
		Style messageStyle = logDocument.addStyle("message", defaultStyle);
		StyleConstants.setFontFamily(messageStyle, "Monospaced");
		StyleConstants.setFontSize(messageStyle, 12);
		StyleConstants.setForeground(messageStyle, Color.BLACK);
		Style altimeterStyle = logDocument.addStyle("altimeter", messageStyle);
		StyleConstants.setForeground(altimeterStyle, Color.BLUE);
		Style errorStyle = logDocument.addStyle("error", messageStyle);
		StyleConstants.setForeground(errorStyle, Color.RED);
		Style helpStyle = logDocument.addStyle("help", messageStyle);
		StyleConstants.setForeground(helpStyle, Color.DARK_GRAY);
		
		scrollPane = new JScrollPane(logTextPane);
		scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		splitPane.setRightComponent(scrollPane);
	
		frmOpenaltimeter.getContentPane().add(progressBar, BorderLayout.PAGE_END);
	}