tpsLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
    public ConsoleUI(Model model, ActionListener startProcessesHandler,		     ActionListener stopProcessesHandler)	throws ConsoleException    {	getResources();	final Action[] actions = {	    new StartProcessesGrinderAction(startProcessesHandler),	    new StopProcessesGrinderAction(stopProcessesHandler),	    new StartAction(),	    new StopAction(),	    new SummaryAction(),	    new ExitAction(),	};	m_actionTable = new HashMap();	for (int i=0; i<actions.length; i++) {	    m_actionTable.put(actions[i].getValue(Action.NAME), actions[i]);	}	m_model = model;	// Create a scrolled pane of test graphs.        final JPanel testPanel = new JPanel();	testPanel.setLayout(new GridLayout(0, 2, 20, 0));	final Iterator testIterator = m_model.getTests().iterator();	while (testIterator.hasNext())	{	    final Test test = (Test)testIterator.next();	    final Integer testNumber = test.getTestNumber();	    final String description = test.getDescription();	    String label = "Test " + testNumber;	    if (description != null) {		label = label + " (" + description + ")";	    }	    final LabelledGraph testGraph = new LabelledGraph(label);	    m_model.addSampleListener(		testNumber,		new SampleListener() {			public void update(double tps, double averageTPS,					   double peakTPS, Statistics total) {			    testGraph.add(tps, averageTPS, peakTPS, total);			}		    }		);	    testPanel.add(testGraph);	}	// Make space for vertical scroll bar.	testPanel.setBorder(new EmptyBorder(0, 0, 0, 40));        final JScrollPane scrollPane =	    new JScrollPane(testPanel,			    JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,			    JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);	final LabelledGraph totalGraph = new LabelledGraph("Total",							   Color.darkGray);	final JLabel tpsLabel = new JLabel("", SwingConstants.CENTER);	tpsLabel.setForeground(Color.black);	tpsLabel.setFont(s_tpsFont);	m_model.addTotalSampleListener(	    new SampleListener() {		    public void update(double tps, double average,				       double peak, Statistics total) {			tpsLabel.setText(s_twoDPFormat.format(tps) + " TPS");			totalGraph.add(tps, average, peak, total);		    }		}	    );	final JSlider intervalSlider =	    new JSlider(100, 10000, m_model.getSampleInterval());	intervalSlider.setMajorTickSpacing(1000);	intervalSlider.setMinorTickSpacing(100);	intervalSlider.setPaintTicks(true);	intervalSlider.setSnapToTicks(true);	intervalSlider.addChangeListener(	    new ChangeListener() {		    public void stateChanged(ChangeEvent e) {			m_model.setSampleInterval(intervalSlider.getValue());		    }		}	    );	m_intervalLabel = new JLabel();	final JSlider ignoreSampleSlider =	    new JSlider(0, 9, m_model.getIgnoreSampleCount());	ignoreSampleSlider.setMajorTickSpacing(1);	ignoreSampleSlider.setSnapToTicks(true);	ignoreSampleSlider.setPaintTicks(true);	m_ignoreSampleLabel = new JLabel();	ignoreSampleSlider.addChangeListener(	    new ChangeListener() {		    public void stateChanged(ChangeEvent e) {			m_model.setIgnoreSampleCount(			    ignoreSampleSlider.getValue());		    }		}	    );	final JSlider collectSampleSlider =	    new JSlider(0, 50, m_model.getCollectSampleCount());	collectSampleSlider.setMajorTickSpacing(1);	collectSampleSlider.setSnapToTicks(true);	collectSampleSlider.setPaintTicks(true);	m_collectSampleLabel = new JLabel();	collectSampleSlider.addChangeListener(	    new ChangeListener() {		    public void stateChanged(ChangeEvent e) {			m_model.setCollectSampleCount(			    collectSampleSlider.getValue());		    }		}	    );	m_stateLabel = new JLabel();	final JPanel controlPanel = new JPanel();	controlPanel.setLayout(new GridLayout(0, 1));	controlPanel.add(m_intervalLabel);	controlPanel.add(intervalSlider);	controlPanel.add(m_ignoreSampleLabel);	controlPanel.add(ignoreSampleSlider);	controlPanel.add(m_collectSampleLabel);	controlPanel.add(collectSampleSlider);	controlPanel.add(m_stateLabel);	controlPanel.setBorder(new EmptyBorder(0, 10, 0, 10));	final JPanel controlAndTotalPanel = new JPanel();	controlAndTotalPanel.setLayout(	    new BoxLayout(controlAndTotalPanel, BoxLayout.Y_AXIS));		controlAndTotalPanel.add(controlPanel);	controlAndTotalPanel.add(Box.createRigidArea(new Dimension(0, 50)));	controlAndTotalPanel.add(tpsLabel);	controlAndTotalPanel.add(Box.createRigidArea(new Dimension(0, 30)));	controlAndTotalPanel.add(totalGraph);	final JPanel hackToFixLayout = new JPanel();	hackToFixLayout.add(controlAndTotalPanel);	final URL logoURL = getResource("logo.image");	final JPanel contentPanel = new JPanel();	contentPanel.setLayout(new BorderLayout());	contentPanel.add(hackToFixLayout, BorderLayout.WEST);	contentPanel.add(scrollPane, BorderLayout.CENTER);	if (logoURL != null) {	    final ImageIcon imageIcon = new ImageIcon(logoURL);	    final JLabel logo = new JLabel(imageIcon, SwingConstants.LEADING);	    contentPanel.add(logo, BorderLayout.EAST);	    m_logoImage = imageIcon.getImage();	}	// Create a panel to hold the tool bar and the test pane.        final JPanel toolBarPanel = new JPanel();	toolBarPanel.setLayout(new BorderLayout());	toolBarPanel.add(createToolBar(), BorderLayout.NORTH);	toolBarPanel.add(contentPanel, BorderLayout.CENTER);	// Create the frame, containing the a menu and the top level pane.	final JFrame frame = new JFrame(getResourceString("title"));        frame.addWindowListener(new WindowCloseAdapter());	final Container topLevelPane= frame.getContentPane();	topLevelPane.add(createMenuBar(), BorderLayout.NORTH);        topLevelPane.add(toolBarPanel, BorderLayout.CENTER);	if (m_logoImage != null) {	    frame.setIconImage(m_logoImage);	}	m_model.addModelListener(this);	update();        frame.pack();	// Arbitary sizing that looks good for Phil.	final int maxHeight = 600;	final Dimension d = frame.getSize();	if (d.height > maxHeight) {	    d.height = maxHeight;	    frame.setSize(d);	}        frame.show();    }