private void initComponents() {
		formatLabel = new JLabel("How should your track info be displayed:");
		formatArea = new JTextArea(config.getFormat());
		formatLighter = new DefaultHighlighter();
		// TODO allow configuration of this color
		formatPainter = new DefaultHighlighter.DefaultHighlightPainter(new Color(200, 200, 255));
		formatArea.setHighlighter(formatLighter);
		formatArea.getDocument().addDocumentListener(new DocumentListener() {
			@Override
			public void removeUpdate(DocumentEvent e) {formatUpdated();}
			@Override
			public void insertUpdate(DocumentEvent e) {formatUpdated();}
			@Override
			public void changedUpdate(DocumentEvent e) {formatUpdated();}
		});
		
		ImageIcon infoIcon = null;
		try {
			InputStream is = getClass().getResourceAsStream("info.png");
			if (is == null) {
				LOG.error("Couldn't find the info image.");
			} else {
				infoIcon = new ImageIcon(ImageIO.read(is));
				is.close();
			}
		} catch (IOException e1) {
			LOG.error("Couldn't find the info image.", e1);
		}
		if (infoIcon == null) {
			formatInfoButton = new JButton("?");
		} else {
			formatInfoButton = new JButton(infoIcon);
			formatInfoButton.setBorder(BorderFactory.createEmptyBorder());
		}
		
		
		formatInfoButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) { showFormatHelp();}
		});
		
		templateLabel = new JLabel("Your template:");
		
		tagLabel = new JLabel("Available tags:");
		tagList = new JList<String>(new AbstractListModel<String>() {
			private static final long serialVersionUID = -8886588605378873151L;
			@Override
			public int getSize() {
				return properTags.size();
			}

			@Override
			public String getElementAt(int index) {
				return properTags.get(index);
			}
		});
		tagScrollPane = new JScrollPane(tagList);
		
		previewLabel = new JLabel("Preview:");
		previewField = new JTextField();
		previewField.setEditable(false);
		previewField.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
		previewField.setBackground(new Color(255, 255, 150));
		
		formatUpdated();
		highlightTags();
		
		nullMessageLabel = new JLabel("Message to display when no song is found:");
		nullMessageField = new JTextField(config.getNoTrackMessage() == null? "" : config.getNoTrackMessage());
		nullMessageField.getDocument().addDocumentListener(new DocumentListener() {
			public void action() {
				config.setNoTrackMessage(nullMessageField.getText());
			}
			@Override
			public void removeUpdate(DocumentEvent e) {action();}
			@Override
			public void insertUpdate(DocumentEvent e) {action();}
			@Override
			public void changedUpdate(DocumentEvent e) {action();}
		});
		
		hline = new JSeparator(SwingConstants.HORIZONTAL);
		fileLabel = new JLabel("Location of text file:");
		fileChooser = new JFileChooser();
		fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
		fileField = new JTextField(15);
		if (config.getOutputFile() != null) {
			fileField.setText(config.getOutputFile().getAbsolutePath());
		}
		fileField.getDocument().addDocumentListener(new DocumentListener() {
			public void action() {
				config.setOutputFile(new File(fileField.getText()));
			}
			@Override
			public void removeUpdate(DocumentEvent e) {action();}
			@Override
			public void insertUpdate(DocumentEvent e) {action();}
			@Override
			public void changedUpdate(DocumentEvent e) {action();}
		});
		fileButton = new JButton("Browse");
		fileButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {browseFile();}
		});
	}