public REDemo(final JFrame parent) throws BadLocationException {
		super();

		JMenuBar bar = new JMenuBar();
		JMenu file = new JMenu("File");
		bar.add(file);
		JMenuItem quitItem = new JMenuItem("Exit");
		file.add(quitItem);
		quitItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				System.exit(0);
			}
		});

		JMenu options = new JMenu("Options");
		bar.add(options);
		JMenuItem fontItem = new JMenuItem("Font");
		options.add(fontItem);
		final FontChooser fontChooser = new FontChooser(parent);
		fontItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				fontChooser.setVisible(true);
				Font font = fontChooser.getSelectedFont();
				if (font == null) {
					System.out.println("Nothing selected");
					return;
				}
				System.out.println(font);
				for (Component c : fontChangers) {
					if (c != null) {
						c.setFont(font);
					}
				}
				parent.pack();
			}
		});
		parent.setJMenuBar(bar);

		JPanel top = new JPanel();
		pattLabel = new JLabel("Pattern:", JLabel.RIGHT);
		top.add(pattLabel);
		patternTF = new JTextField(40);
		patternTF.getDocument().addDocumentListener(new PatternListener());
		top.add(patternTF);
		top.add(new JLabel("Syntax OK?"));
		compiledOK = new JCheckBox();
		top.add(compiledOK);

		ChangeListener cl = new ChangeListener() {
			public void stateChanged(ChangeEvent ce) {
				tryMatch();
			}
		};
		JPanel switchPane = new JPanel();
		ButtonGroup buttonGroup = new ButtonGroup();
		match = new JRadioButton("Match");
		match.setSelected(true);
		match.addChangeListener(cl);
		buttonGroup.add(match);
		switchPane.add(match);
		findButton = new JRadioButton("Find");
		findButton.addChangeListener(cl);
		buttonGroup.add(findButton);
		switchPane.add(findButton);
		findAll = new JRadioButton("Find All");
		findAll.addChangeListener(cl);
		buttonGroup.add(findAll);
		switchPane.add(findAll);
		buttonGroup.setSelected(findButton.getModel(), true);

		JPanel strPane = new JPanel();
		stringLabel = new JLabel("String:", JLabel.RIGHT);
		strPane.add(stringLabel);
		stringTF = new JTextField(40);
		stringTF.getDocument().addDocumentListener(new StringListener());
		highlighter = stringTF.getHighlighter();
		onlyHighlight = highlighter.addHighlight(0, 0, DefaultHighlighter.DefaultPainter);
		strPane.add(stringTF);
		strPane.add(new JLabel("Matches:"));
		matchesTF = new JTextField(3);
		strPane.add(matchesTF);
		
		JPanel bottomPanel = new JPanel();
		final JButton copyButton = new JButton("Copy Pattern");
		bottomPanel.add(copyButton);
		copyButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				UtilGUI.setSystemClipboardContents(REDemo.this, patternTF.getText());
			}
		});
		final JButton copyDoubledButton = new JButton("Copy Pattern Backslashed");
		bottomPanel.add(copyDoubledButton);
		copyDoubledButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				UtilGUI.setSystemClipboardContents(REDemo.this, patternTF.getText().replaceAll("\\\\", "\\\\\\\\"));
			}
		});
		final JButton quitButton = new JButton("Exit");
		bottomPanel.add(quitButton);
		quitButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				System.exit(0);
			}
		});

		setLayout(new GridLayout(0, 1, 5, 5));
		add(top);
		add(strPane);
		add(switchPane);
		add(logTextArea = new JTextArea(5,40));
		add(bottomPanel);

		// Now that the components are created, add them to the list
		// that change fonts.
		fontChangers = new Component[]{
			pattLabel, patternTF, stringLabel, stringTF, 
			match, findButton, findAll,
			matchesTF, logTextArea
		};
	}