package ptft; /* * JPtftPanel.java * * Written by Will Braynen * Group for Logic and Formal Semantics, SUNY Stony Brook (www.ptft.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Created on May 12, 2004, 7:17 PM */ import javax.swing.*; import java.awt.*; import java.util.*; import java.text.*; // import ptft.cell.*; /** * A JPanel that houses the cellular automata grid and the GUI. * An instance of this panel can then be embedded in an applet or an * application. * * @author Will Braynen */ public class JPtftPanel extends JPanel { // fields protected ImageIcon m_pauseIcon; protected ImageIcon m_playIcon; protected ImageIcon m_pencilIcon; protected ImageIcon m_bucketIcon; protected ImageIcon m_gridIcon; protected CellFactory factory; private NamedColorArray m_strategies; private NamedColorArray m_ethnicities; //stuff to fix the broken GUI'ness protected JPaintCellularAutomata cellularAutomata; protected JGridButton gridButton; protected boolean runGenerations = false; protected boolean updatePayoffs = false; protected int payoffColorListIndex = 0; /** Creates new form JPtftPanel */ public JPtftPanel() { //init custom components to fix things dropped by NetBeans cellularAutomata = new ptft.JPaintCellularAutomata(); add(cellularAutomata, new java.awt.GridBagConstraints()); m_strategies = CellFactory.getInstance().getStrategy(); m_ethnicities = CellFactory.getInstance().getEthnicity(); // Create the GUI initComponents(); //finish init'ing custom components to fix broken things gridButton = new ptft.JGridButton(); gridButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/ptft/images/grid.gif"))); gridButton.setPreferredSize(new java.awt.Dimension(32, 32)); gridButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { gridButtonActionPerformed(evt); } }); java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 4; gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0); legendPanel.add(gridButton, gridBagConstraints); //hack the button panel because it doesn't want to size correctly on its own guiPanel.setPreferredSize(new java.awt.Dimension(475,30)); ethnicityList.setPreferredSize(new java.awt.Dimension(150,80)); //resize the gui automatically depending on the size of the components int width = (int)legendPanel.getPreferredSize().getWidth() + (int)cellularAutomata.getPreferredSize().getWidth() + 100; int height = (int)cellularAutomata.getPreferredSize().getHeight() + (int)guiPanel.getPreferredSize().getHeight() + 50; setPreferredSize(new java.awt.Dimension(width, height)); // cellularAutomata.createCells( m_strategies, m_ethnicities ); cellularAutomata.createCells(); cellularAutomata.segregate(); // Load the icons for the play/pause button (because its icon will // change dynamically. For static buttons, the icon can be set // using the form editor. m_playIcon = ImageToolkit.createImageIcon (this, "/ptft/images/play.gif"); m_pauseIcon = ImageToolkit.createImageIcon (this, "/ptft/images/pause.gif"); // set custom list cell renderer so our strategies and ethnicities can have color legends LegendListCellRenderer renderer= new LegendListCellRenderer(); renderer.setPreferredSize( new Dimension(50, 17) ); strategyList.setCellRenderer( renderer ); ethnicityList.setCellRenderer( renderer ); setPaintMode( false ); // for now, until I implement a more efficient JPaintCellularAutomata::floodFill pencilButton.setVisible( false ); bucketButton.setVisible( false ); setGridButtonColor(); } // end constructor /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents() {//GEN-BEGIN:initComponents java.awt.GridBagConstraints gridBagConstraints; paintTools = new javax.swing.ButtonGroup(); paintOrRandom = new javax.swing.ButtonGroup(); cellularAutomata = new ptft.JPaintCellularAutomata(); guiPanel = new javax.swing.JPanel(); restartButton = new javax.swing.JButton(); playButton = new javax.swing.JButton(); nextButton = new javax.swing.JButton(); segregateButton = new javax.swing.JButton(); toggleViewsButton = new javax.swing.JButton(); legendPanel = new javax.swing.JPanel(); strategyList = new JList (m_strategies.getNames()); ethnicityList = new JList (m_ethnicities.getNames()); gridButton = new ptft.JGridButton(); pencilButton = new javax.swing.JToggleButton(); bucketButton = new javax.swing.JToggleButton(); randomButton = new javax.swing.JRadioButton(); paintButton = new javax.swing.JRadioButton(); setLayout(new java.awt.GridBagLayout()); setMinimumSize(new java.awt.Dimension(750, 420)); setPreferredSize(new java.awt.Dimension(750, 450)); add(cellularAutomata, new java.awt.GridBagConstraints()); guiPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 4, 4)); guiPanel.setPreferredSize(new java.awt.Dimension(385, 30)); restartButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/ptft/images/stop.gif"))); restartButton.setToolTipText("Restart"); restartButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { restartButtonActionPerformed(evt); } }); guiPanel.add(restartButton); playButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/ptft/images/play.gif"))); playButton.setToolTipText("Evolve"); playButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { playButtonActionPerformed(evt); } }); guiPanel.add(playButton); nextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/ptft/images/next.gif"))); nextButton.setToolTipText("Evolve one generation"); nextButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { nextButtonActionPerformed(evt); } }); guiPanel.add(nextButton); segregateButton.setText("integrate"); segregateButton.setToolTipText("Integrate and segregate by ethnicity"); segregateButton.setMaximumSize(new java.awt.Dimension(85, 23)); segregateButton.setMinimumSize(new java.awt.Dimension(85, 23)); segregateButton.setPreferredSize(new java.awt.Dimension(85, 23)); segregateButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { segregateButtonActionPerformed(evt); } }); guiPanel.add(segregateButton); toggleViewsButton.setText("show ethnicities"); toggleViewsButton.setToolTipText("Cells change their strategies, not ethnicities"); toggleViewsButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { toggleViewsButtonActionPerformed(evt); } }); guiPanel.add(toggleViewsButton); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; add(guiPanel, gridBagConstraints); legendPanel.setLayout(new java.awt.GridBagLayout()); strategyList.setBackground(javax.swing.UIManager.getDefaults().getColor("Button.background")); strategyList.setBorder(new javax.swing.border.TitledBorder(null, "Strategies", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("MS Sans Serif", 1, 13))); strategyList.setFont(new java.awt.Font("Arial", 0, 13)); strategyList.setName("strategies"); strategyList.setPreferredSize(new java.awt.Dimension(130, 179)); strategyList.addListSelectionListener(new javax.swing.event.ListSelectionListener() { public void valueChanged(javax.swing.event.ListSelectionEvent evt) { listValueChanged(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.gridwidth = 3; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; legendPanel.add(strategyList, gridBagConstraints); ethnicityList.setBackground(javax.swing.UIManager.getDefaults().getColor("Button.background")); ethnicityList.setBorder(new javax.swing.border.TitledBorder(null, "Ethnicities", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("MS Sans Serif", 1, 13))); ethnicityList.setFont(new java.awt.Font("Arial", 0, 13)); ethnicityList.setPreferredSize(new java.awt.Dimension(50, 60)); ethnicityList.addListSelectionListener(new javax.swing.event.ListSelectionListener() { public void valueChanged(javax.swing.event.ListSelectionEvent evt) { listValueChanged(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.gridwidth = 3; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0); legendPanel.add(ethnicityList, gridBagConstraints); gridButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/ptft/images/grid.gif"))); gridButton.setPreferredSize(new java.awt.Dimension(32, 32)); gridButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { gridButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 4; gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0); legendPanel.add(gridButton, gridBagConstraints); pencilButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/ptft/images/pencil.gif"))); pencilButton.setSelected(true); paintTools.add(pencilButton); pencilButton.setPreferredSize(new java.awt.Dimension(32, 32)); pencilButton.setEnabled(false); pencilButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { pencilButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 4; gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0); legendPanel.add(pencilButton, gridBagConstraints); bucketButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/ptft/images/bucket.gif"))); paintTools.add(bucketButton); bucketButton.setPreferredSize(new java.awt.Dimension(32, 32)); bucketButton.setEnabled(false); bucketButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bucketButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 4; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0); legendPanel.add(bucketButton, gridBagConstraints); randomButton.setSelected(true); randomButton.setText("random"); paintOrRandom.add(randomButton); randomButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { randomButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; gridBagConstraints.gridwidth = 3; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0); legendPanel.add(randomButton, gridBagConstraints); paintButton.setText("paint"); paintOrRandom.add(paintButton); paintButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { paintButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 3; gridBagConstraints.gridwidth = 3; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; legendPanel.add(paintButton, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 0; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0); add(legendPanel, gridBagConstraints); }//GEN-END:initComponents private void payoffOkayButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_payoffOkayButtonActionPerformed payoffDialog.hide(); updatePayoffs = true; }//GEN-LAST:event_payoffOkayButtonActionPerformed private void payoffCancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_payoffCancelButtonActionPerformed payoffDialog.hide(); updatePayoffs = false; }//GEN-LAST:event_payoffCancelButtonActionPerformed private void payoffColorListActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_payoffColorListActionPerformed NamedColor nc = m_ethnicities.getNamedColor(payoffColorListIndex); nc.setMinPayoff(payoffSliderMin.getValue()); nc.setMaxPayoff(payoffSliderMax.getValue()); //update the sliders with the values of the new colors payoff payoffColorListIndex = payoffColorList.getSelectedIndex(); payoffSliderMin.setValue(m_ethnicities.getNamedColor(payoffColorListIndex).getMinPayoff()); payoffSliderMax.setValue(m_ethnicities.getNamedColor(payoffColorListIndex).getMaxPayoff()); }//GEN-LAST:event_payoffColorListActionPerformed public void showPayoffPercentageDialog() { payoffDialog.setSize(350,300); payoffSliderMin.setValue(m_ethnicities.getNamedColor(payoffColorListIndex).getMinPayoff()); payoffSliderMax.setValue(m_ethnicities.getNamedColor(payoffColorListIndex).getMaxPayoff()); payoffDialog.show(); } private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed runGenerations = false; generationDialog.hide(); }//GEN-LAST:event_cancelButtonActionPerformed private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed runGenerations = true; generationDialog.hide(); }//GEN-LAST:event_okButtonActionPerformed private void generationButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_generationButtonActionPerformed generationDialog.setSize(350,150); generationDialog.show(); if ( runGenerations ) { int i_stopGen = -1; int i_redrawEvery = -1; int i_stopDelay = 0; try { String redrawEvery = t_redrawEveryGeneration.getText(); if ( redrawEvery.length() > 0 ) { i_redrawEvery = Integer.parseInt(redrawEvery); } String stopDelay = t_stopDelay.getText(); if ( stopDelay.length() > 0 ) { i_stopDelay = (int)(Double.valueOf(stopDelay).doubleValue() * 1000); } String stopGen = t_stopGeneration.getText(); if ( stopGen.length() > 0 ) { i_stopGen = Integer.parseInt(stopGen); if ( i_stopGen > cellularAutomata.getGeneration() ) { long startTime = System.currentTimeMillis(); //actually run the generations this.runGenerations(i_stopGen,i_redrawEvery,i_stopDelay); long currentTime = System.currentTimeMillis(); SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); long elapsed = currentTime - startTime; //output how long it took to run all of the generations System.out.println("Elapsed Time to run generations: " + dateFormat.format(new Date(elapsed))); } } } catch ( NumberFormatException e ) { System.out.println("Invalid input."); } } t_stopGeneration.setText(""); }//GEN-LAST:event_generationButtonActionPerformed private void runGenerations( int stopGeneration, int redrawEvery, int waitMS ) { boolean pause = false; if ( redrawEvery > 0 && waitMS >= 0 ) { pause = true; } //run from the current generation to the specified generation int currentGen = cellularAutomata.getGeneration(); for ( int i = currentGen; i < stopGeneration; i++ ) { //play the next round, but don't redraw the grid this.next(false); //redraw the generation button so that it reflects the current generation updateGenerationButton(i+1); this.generationButton.paintImmediately(0,0,this.generationButton.getWidth(),this.generationButton.getHeight()); if ( pause && ((i - currentGen + 1) % redrawEvery == 0) ) { //force the gui to redraw the grid this.paintImmediately(0,0,this.getWidth(),this.getHeight()); try { //wait for a little bit to display the generation Thread.sleep(waitMS); } catch ( Exception e ) { e.printStackTrace(); } } } //repaint at the end to show the last generation generated in the grid cellularAutomata.repaint(); } private void listValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_listValueChanged if ( ! evt.getValueIsAdjusting() ) { // change the grid button's color setGridButtonColor(); if (cellularAutomata.isPaintModeEnabled()) // paint mode { // In paint mode we allow only single list selections. // Make that one selection the current strategy or ethnicity // with which to paint. // See on which list the user clicked if ((JList) evt.getSource() == strategyList) { int i = strategyList.getSelectedIndex(); if (i >= 0) { cellularAutomata.setActiveStrategy( i ); } } else if ((JList) evt.getSource() == ethnicityList) { int i = ethnicityList.getSelectedIndex(); if (i >= 0) { cellularAutomata.setActiveEthnicity( i ); } } } else // random pool mode { // In random pool mode we allow multiple list selections. // Make the random pool contain only the selected strategies // or ethnicities. But wait, we only have to worry about that // when the user pressed the restart button (aka "stop button") } } }//GEN-LAST:event_listValueChanged private void bucketButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bucketButtonActionPerformed // get ready to paint with a bucket setPaintMode( true, false ); }//GEN-LAST:event_bucketButtonActionPerformed private void pencilButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pencilButtonActionPerformed // get ready to paint with a pencil setPaintMode( true, true ); }//GEN-LAST:event_pencilButtonActionPerformed private void gridButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gridButtonActionPerformed // pause if (cellularAutomata.isRunning()) { cellularAutomata.pause(); playButton.setIcon (m_playIcon); } // if we are in paint mode, then the lists are in single-selection mode, // so we don't have to worry about anything. if (cellularAutomata.isStrategyDisplayed()) { cellularAutomata.setRandomStrategies( strategyList.getSelectedIndices() ); } else { cellularAutomata.setRandomEthnicities( ethnicityList.getSelectedIndices() ); // if we are in ethnicity view AND in random mode, then make sure // the segregate/integrate button says "segregate" on it if ( ! cellularAutomata.isPaintModeEnabled() && "integrate".equals( segregateButton.getText() )) { segregateButton.setText ("segregate"); } } repaint(); }//GEN-LAST:event_gridButtonActionPerformed public void setRandomMode() { setPaintMode( false ); // multiple list selection mode -- deselect everything strategyList.clearSelection(); ethnicityList.clearSelection(); randomButton.setSelected( true ); } private void randomButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_randomButtonActionPerformed setRandomMode(); }//GEN-LAST:event_randomButtonActionPerformed private void paintButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_paintButtonActionPerformed setPaintMode( true ); // make GUI consistent with single list selection mode int selectedStrategy = strategyList.getSelectedIndex(); int selectedEthnicity = ethnicityList.getSelectedIndex(); // if nothing is selected, default to the first item in the list if (selectedStrategy < 0) selectedStrategy = 0; if (selectedEthnicity < 0) selectedEthnicity = 0; // select a single list item strategyList.setSelectedIndex( selectedStrategy ); ethnicityList.setSelectedIndex( selectedEthnicity ); }//GEN-LAST:event_paintButtonActionPerformed public void next(boolean repaint) { if (cellularAutomata.isRunning()) { cellularAutomata.pause(); playButton.setIcon (m_playIcon); } cellularAutomata.playRound(repaint); if ( ! cellularAutomata.m_isStrategyDisplayed ) { cellularAutomata.toggleViews(); toggleViewsButton.setText ("show ethnicities"); } this.generationButton.setText("G: " + Integer.toString(cellularAutomata.getGeneration())); } // end next private void nextButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextButtonActionPerformed next(true); }//GEN-LAST:event_nextButtonActionPerformed public void restart() { if (cellularAutomata.isRunning()) { cellularAutomata.pause(); playButton.setIcon (m_playIcon); } cellularAutomata.restart(); // segregate segregate(); // // switch to strategy view // if ( ! cellularAutomata.m_isStrategyDisplayed ) // { // cellularAutomata.toggleViews(); // toggleViewsButton.setText ("show ethnicities"); // } setRandomMode(); updateGenerationButton(cellularAutomata.getGeneration()); repaint(); } // end restart public void updateGenerationButton(int generation) { this.generationButton.setText("G: " + Integer.toString(generation)); } private void restartButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_restartButtonActionPerformed restart(); }//GEN-LAST:event_restartButtonActionPerformed public void toggleViews() { cellularAutomata.toggleViews(); if (cellularAutomata.isStrategyDisplayed()) { toggleViewsButton.setText ("show ethnicities"); } else { toggleViewsButton.setText ("show strategies"); } setGridButtonColor(); } private void toggleViewsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_toggleViewsButtonActionPerformed toggleViews(); }//GEN-LAST:event_toggleViewsButtonActionPerformed public void segregate() { if (cellularAutomata.isSegregated()) { cellularAutomata.integrate(); segregateButton.setText ("segregate"); } else { cellularAutomata.segregate(); segregateButton.setText ("integrate"); } } // end segregate private void segregateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_segregateButtonActionPerformed segregate(); }//GEN-LAST:event_segregateButtonActionPerformed public void start() { // Show strategies so that the user can see the automata evolve. // If we don't, the user might think we are still paused because // cells only switch their strategy, not their ethnicity. if ( ! cellularAutomata.m_isStrategyDisplayed ) { cellularAutomata.toggleViews(); toggleViewsButton.setText ("show ethnicities"); } // Go cellularAutomata.start(); playButton.setIcon (m_pauseIcon); } // end play public void pause() { cellularAutomata.pause(); playButton.setIcon (m_playIcon); } // end pause private void playButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_playButtonActionPerformed if (cellularAutomata.isRunning()) { pause(); } else { start(); } }//GEN-LAST:event_playButtonActionPerformed public void setPaintMode( boolean isEnabled ) { setPaintMode( isEnabled, true ); } public void setPaintMode( boolean isEnabled, boolean isPencil ) { // pause so the user can paint if ( isEnabled ) pause(); // do nothing if this is the way things are already if (cellularAutomata.isPaintModeEnabled() == isEnabled && cellularAutomata.isPencil() == isPencil) return; // get ready to paint with a pencil or a bucket cellularAutomata.setPaintMode( isEnabled, isPencil ); // if painting, change strategyList and ethnicityList to single // selection mode and select the first item in each of the two lists if (isEnabled) { strategyList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); ethnicityList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); setGridButtonColor(); } else { strategyList.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION ); ethnicityList.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION ); gridButton.setGridColor( Color.white ); // default for disabled button } // enable or disable pain tool buttons: pencil and bucket pencilButton.setEnabled( isEnabled ); bucketButton.setEnabled( isEnabled ); //gridButton.setEnabled( isEnabled ); // update the button GUI -- select the appropriate paint tool button if (isPencil) { pencilButton.setSelected( true ); } else { bucketButton.setSelected( true ); } } // end setPaintMode public void setGridButtonColor() { // // See what is selected (which strategies or ethnicities) // int[] selectedIndices = cellularAutomata.isStrategyDisplayed() ? strategyList.getSelectedIndices() : ethnicityList.getSelectedIndices(); NamedColorArray colors = cellularAutomata.isStrategyDisplayed() ? m_strategies : m_ethnicities; // // paint mode: single selection mode => single-colored grid button // if (cellularAutomata.isPaintModeEnabled()) { // if nothing is selected, default to the first item in the list if (0 == selectedIndices.length) { selectedIndices = new int[1]; selectedIndices[0] = 0; } if (cellularAutomata.isStrategyDisplayed()) cellularAutomata.setActiveStrategy( selectedIndices[0] ); else cellularAutomata.setActiveEthnicity( selectedIndices[0] ); gridButton.setGridColor( colors.getColor( selectedIndices[0] )); } // // random mode: multiple-selection mode => multi-colored grid button // else { switch (selectedIndices.length) { // one selected => one color case 1: gridButton.setGridColor ( colors.getColor( selectedIndices[0] )); break; // two selected => two colors case 2: gridButton.setGridColor1( colors.getColor( selectedIndices[0] )); gridButton.setGridColor2( colors.getColor( selectedIndices[1] )); gridButton.setGridColor3( colors.getColor( selectedIndices[1] )); gridButton.setGridColor4( colors.getColor( selectedIndices[0] )); break; // three selected => three colors case 3: gridButton.setGridColor1( colors.getColor( selectedIndices[0] )); gridButton.setGridColor2( colors.getColor( selectedIndices[1] )); gridButton.setGridColor3( colors.getColor( selectedIndices[1] )); gridButton.setGridColor4( colors.getColor( selectedIndices[2] )); break; // nothing is selected (which should behave as if everything is selected) case 0: gridButton.setGridColor1( colors.getColor( 0 )); gridButton.setGridColor2( colors.getColor( 1 )); // we only have two ethnicities: gridButton.setGridColor3( colors.getColor( cellularAutomata.isStrategyDisplayed() ? 2 : 1 )); gridButton.setGridColor4( colors.getColor( cellularAutomata.isStrategyDisplayed() ? 3 : 0 )); break; // four or more (strategies) selected => four colors (maximum number of colors JGridButton supports) default: gridButton.setGridColor1( colors.getColor( selectedIndices[0] )); gridButton.setGridColor2( colors.getColor( selectedIndices[1] )); gridButton.setGridColor3( colors.getColor( selectedIndices[2] )); gridButton.setGridColor4( colors.getColor( selectedIndices[3] )); break; } // end switch on the number of list items (strategies / ethnicities) selected } // end else random mode gridButton.repaint(); } // end setGridButtonColor // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JToggleButton bucketButton; private ptft.JPaintCellularAutomata cellularAutomata; private javax.swing.JList ethnicityList; private ptft.JGridButton gridButton; private javax.swing.JPanel guiPanel; private javax.swing.JPanel legendPanel; private javax.swing.JButton nextButton; private javax.swing.JRadioButton paintButton; private javax.swing.ButtonGroup paintOrRandom; private javax.swing.ButtonGroup paintTools; private javax.swing.JToggleButton pencilButton; private javax.swing.JButton playButton; private javax.swing.JRadioButton randomButton; private javax.swing.JButton restartButton; private javax.swing.JButton segregateButton; private javax.swing.JList strategyList; private javax.swing.JButton toggleViewsButton; // End of variables declaration//GEN-END:variables protected class LegendListCellRenderer extends JLegendLabel implements ListCellRenderer { public LegendListCellRenderer() { setOpaque(true); setHorizontalAlignment(LEFT); setVerticalAlignment(CENTER); } // end constructor public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { if (isSelected) { setBackground(list.getSelectionBackground()); setForeground(list.getSelectionForeground()); } else { setBackground(list.getBackground()); setForeground(list.getForeground()); } String text; Color color; if (list == strategyList) { text = m_strategies.getName( index ); color = m_strategies.getColor( index ); } else // list == ethnicityList { text = m_ethnicities.getNameWithPayoffs( index ); color = m_ethnicities.getColor( index ); } setText( " " + text ); setFont( list.getFont() ); setFillColor( color ); return this; } // end getListCellRendererComponent } // end class LegendListCellRenderer public JCellularAutomata getCellularAutomata() { return cellularAutomata; } } // end class JPtftPanel