/******************************************************************************* * Copyright (c) 2016 Alex Shapiro - github.com/shpralex * This program and the accompanying materials * are made available under the terms of the The MIT License (MIT) * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. *******************************************************************************/ package com.sproutlife.panel; import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.io.IOException; import java.net.URL; import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.swing.JComboBox; import javax.swing.JMenuBar; import javax.swing.JSlider; import javax.swing.JSpinner; import javax.swing.JTabbedPane; import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.text.DefaultCaret; import com.sproutlife.GameController; import com.sproutlife.Settings; import com.sproutlife.action.ActionManager; import com.sproutlife.model.GameModel; import com.sproutlife.model.seed.SeedFactory.SeedType; import com.sproutlife.model.step.GameStep.StepType; import com.sproutlife.model.step.GameStepEvent; import com.sproutlife.model.step.GameStepListener; import com.sproutlife.panel.gamepanel.ImageManager; import com.sproutlife.panel.gamepanel.ImageManager.LogoStyle; import com.sproutlife.panel.gamepanel.ScrollPanel; import com.sproutlife.panel.gamepanel.ScrollPanel.ViewportResizedListener; import com.sproutlife.panel.gamepanel.ScrollPanelController; import com.sproutlife.panel.gamepanel.handler.DefaultHandlerSet; import com.sproutlife.panel.gamepanel.handler.InteractionHandler; import com.sproutlife.renderer.BoardRenderer; public class PanelController { GameController gameController; GameFrame gameFrame; ActionManager actionManager; MainControlPanel mainControlPanel; DisplayControlPanel displayControlPanel; SettingsControlPanel settingsControlPanel; StatsPanel statsPanel; TipsPanel tipsPanel; JMenuBar gameMenu; BoardRenderer boardRenderer; ScrollPanelController scrollController; ImageManager imageManager; InteractionHandler interactionHandler; public PanelController(GameController gameController) { this.gameController = gameController; this.actionManager = new ActionManager(this); this.interactionHandler = new InteractionHandler(this); interactionHandler.setHandlerSet(new DefaultHandlerSet(this)); this.scrollController = new ScrollPanelController(this); this.imageManager = new ImageManager(this, LogoStyle.Small); buildPanels(); } public void start() { initComponents(); addGeneralListeners(); addMainControlPanelListeners(); addDisplayControlPanelListeners(); addSettingsControlPanelListeners(); updateFromSettings(); } public GameController getGameController() { return gameController; }; /** * @return the actionManager */ public ActionManager getActionManager() { return actionManager; } public ScrollPanel getScrollPanel() { return getScrollController().getScrollPanel(); } public ScrollPanelController getScrollController() { return scrollController; } public ImageManager getImageManager() { return imageManager; } public InteractionHandler getInteractionHandler() { return interactionHandler; } public ReentrantReadWriteLock getInteractionLock() { return getGameController().getInteractionLock(); } public BoardRenderer getBoardRenderer() { return boardRenderer; } public GameModel getGameModel() { return getGameController().getGameModel(); } public GameFrame getGameFrame() { return gameFrame; } public MainControlPanel getMainControlPanel() { return mainControlPanel; } /** * @return the settingsControlPanel */ public SettingsControlPanel getSettingsControlPanel() { return settingsControlPanel; } /** * @return the displayControlPanel */ public DisplayControlPanel getDisplayControlPanel() { return displayControlPanel; } /** * @return the statsPanel */ public StatsPanel getStatsPanel() { return statsPanel; } /** * @return the tipsPanel */ public TipsPanel getTipsPanel() { return tipsPanel; } public JMenuBar getGameMenu() { return gameMenu; } public Settings getSettings() { return getGameController().getSettings(); } public void buildPanels() { gameFrame = new GameFrame(this); gameMenu = new GameMenu(this); gameFrame.setJMenuBar(gameMenu); boardRenderer = new BoardRenderer(getGameModel()); mainControlPanel = new MainControlPanel(this); displayControlPanel = new DisplayControlPanel(this); settingsControlPanel = new SettingsControlPanel(this); statsPanel = new StatsPanel(this); tipsPanel = new TipsPanel(this); ScrollPanel scrollPanel = getScrollPanel(); JTabbedPane rightPane = new JTabbedPane(); rightPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); rightPane.addTab("Main", mainControlPanel); rightPane.addTab("Display", displayControlPanel); rightPane.addTab("Settings", settingsControlPanel); rightPane.addTab("Stats", statsPanel); rightPane.addTab("Tips", tipsPanel); gameFrame.getSplitPane().setLeftComponent(scrollPanel); gameFrame.getSplitPane().setRightComponent(rightPane); } private void initComponents() { ToolTipManager.sharedInstance().setInitialDelay(0); gameFrame.setVisible(true); getBoardRenderer().setDefaultBlockSize(3); updateZoomValue(-3); getMainControlPanel().getZoomSlider().setValue(-3); updateBoardSizeFromPanelSize(getScrollPanel().getViewportSize()); getImageManager().setBackgroundColor(new Color(160,160,160)); initSettingsControlPanel(); initSeedTypeComboBox(); initStatsPanel(); loadTipText(); } private void initSettingsControlPanel() { getSettingsControlPanel().getMaxLifespanSpinner().setValue( getSettings().getInt(Settings.MAX_LIFESPAN)); getSettingsControlPanel().getChildOneEnergySpinner().setValue( getSettings().getInt(Settings.CHILD_ONE_ENERGY)); getSettingsControlPanel().getChildTwoEnergySpinner().setValue( getSettings().getInt(Settings.CHILD_TWO_ENERGY)); getSettingsControlPanel().getChildThreeEnergySpinner().setValue( getSettings().getInt(Settings.CHILD_THREE_ENERGY)); getSettingsControlPanel().getMutationRateSpinner().setValue( getSettings().getInt(Settings.MUTATION_RATE)); } private void initStatsPanel() { getStatsPanel().getStatsTextPane().setContentType("text/html"); getStatsPanel().getStatsTextPane().setText(getGameModel().getStats().getDisplayText()); //Fixes scroll issues on setText(), we want to keep the scroll position where it is DefaultCaret caret = (DefaultCaret) getStatsPanel().getStatsTextPane().getCaret(); caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE); } public void addGeneralListeners() { getScrollPanel().enableMouseListeners(); getScrollPanel().addViewportResizedListener(new ViewportResizedListener() { public void viewportResized(int viewportWidth, int viewportHeight) { if (getMainControlPanel().getAutoSizeGridCheckbox().isSelected()) { updateBoardSizeFromPanelSize(new Dimension(viewportWidth, viewportHeight)); } } }); getGameModel().setGameStepListener(new GameStepListener() { @Override public void stepPerformed(GameStepEvent event) { if (event.getStepType() == StepType.STEP_BUNDLE) { getImageManager().repaintNewImage(); if (getGameModel().getTime()%100==0) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { getStatsPanel().getStatsTextPane().setText( getGameModel().getStats().getDisplayText()); } }); } } } }); } private void addMainControlPanelListeners() { getMainControlPanel().getStartPauseButton().setAction( getActionManager().getPlayGameAction()); getMainControlPanel().getStepButton().addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { getInteractionLock().writeLock().lock(); getGameModel().performGameStep(); getInteractionLock().writeLock().unlock(); getImageManager().repaintNewImage(); } }); getMainControlPanel().getResetButton().setAction( getActionManager().getResetGameAction()); getMainControlPanel().getZoomSlider().addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { int value = ((JSlider) e.getSource()).getValue(); updateZoomValue(value); } }); getMainControlPanel().getSpeedSlider().addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { int value = ((JSlider) e.getSource()).getValue(); updateSpeedValue(value); } }); getMainControlPanel().getBoardWidthSpinner().addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { getMainControlPanel().getAutoSizeGridCheckbox().setSelected(false); int width = (int) getMainControlPanel().getBoardWidthSpinner().getValue(); int height = (int) getMainControlPanel().getBoardHeightSpinner().getValue(); updateBoardSize(width, height); } }); getMainControlPanel().getBoardHeightSpinner().addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { int width = (int) getMainControlPanel().getBoardWidthSpinner().getValue(); int height = (int) getMainControlPanel().getBoardHeightSpinner().getValue(); updateBoardSize(width, height); } }); getMainControlPanel().getClipGridToViewButton().addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { getBoardRenderer().setDefaultBlockSize(getBoardRenderer().getBlockSize()); updateBoardSizeFromPanelSize(getScrollPanel().getViewportSize()); } }); ItemListener lifeModeListener = new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (getMainControlPanel().getRdbtnFriendly().isSelected()) { getSettings().set(Settings.LIFE_MODE, "friendly"); } else if(getMainControlPanel().getRdbtnCooperative().isSelected()) { getSettings().set(Settings.LIFE_MODE, "cooperative"); } else { getSettings().set(Settings.LIFE_MODE, "competitive"); } } }; getMainControlPanel().getRdbtnCompetitive().addItemListener(lifeModeListener); getMainControlPanel().getRdbtnFriendly().addItemListener(lifeModeListener); getMainControlPanel().getRdbtnCooperative().addItemListener(lifeModeListener); getMainControlPanel().getSeedTypeComboBox().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { getSettings().set(Settings.SEED_TYPE, getMainControlPanel().getSeedTypeComboBox().getSelectedItem().toString()); } }); } public void addDisplayControlPanelListeners() { getDisplayControlPanel().getChckbxCellLayer().addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { getBoardRenderer().setPaintCellLayer(getDisplayControlPanel().getChckbxCellLayer().isSelected()); getImageManager().repaintNewImage(); } }); getDisplayControlPanel().getChckbxGenomeLayer().addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { getBoardRenderer().setPaintGenomeLayer(getDisplayControlPanel().getChckbxGenomeLayer().isSelected()); getImageManager().repaintNewImage(); } }); getDisplayControlPanel().getChckbxOrgHeadLayer().addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { getBoardRenderer().setPaintHeadLayer(getDisplayControlPanel().getChckbxOrgHeadLayer().isSelected()); getImageManager().repaintNewImage(); } }); getDisplayControlPanel().getChckbxOrgTailLayer().addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { getBoardRenderer().setPaintTailLayer(getDisplayControlPanel().getChckbxOrgTailLayer().isSelected()); getImageManager().repaintNewImage(); } }); getDisplayControlPanel().getChckbxOutlineSeeds().addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { getBoardRenderer().setOutlineSeeds(getDisplayControlPanel().getChckbxOutlineSeeds().isSelected()); getImageManager().repaintNewImage(); } }); } public void addSettingsControlPanelListeners() { getSettingsControlPanel().getMaxLifespanSpinner().addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { getSettings().set(Settings.MAX_LIFESPAN,((JSpinner) arg0.getSource()).getValue()); } }); getSettingsControlPanel().getChildOneEnergySpinner().addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { getSettings().set(Settings.CHILD_ONE_ENERGY,((JSpinner) arg0.getSource()).getValue()); } }); getSettingsControlPanel().getChildTwoEnergySpinner().addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { getSettings().set(Settings.CHILD_TWO_ENERGY,((JSpinner) arg0.getSource()).getValue()); } }); getSettingsControlPanel().getChildThreeEnergySpinner().addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { getSettings().set(Settings.CHILD_THREE_ENERGY,((JSpinner) arg0.getSource()).getValue()); } }); getSettingsControlPanel().getMutationRateSpinner().addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { getSettings().set(Settings.MUTATION_RATE,((JSpinner) arg0.getSource()).getValue()); } }); ItemListener sproutModeListener = new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (getSettingsControlPanel().getRdbtnVisual().isSelected()) { getSettings().set(Settings.SPROUT_DELAYED_MODE, true); } else if(getSettingsControlPanel().getRdbtnFunctional().isSelected()) { getSettings().set(Settings.SPROUT_DELAYED_MODE, false); } } }; getSettingsControlPanel().getRdbtnVisual().addItemListener(sproutModeListener); getSettingsControlPanel().getRdbtnFunctional().addItemListener(sproutModeListener); } public void updateFromSettings() { String lifeMode = getSettings().getString(Settings.LIFE_MODE); if ("cooperative".equals(lifeMode)) { getMainControlPanel().getRdbtnCooperative().setSelected(true); } else if ("friendly".equals(lifeMode)) { getMainControlPanel().getRdbtnFriendly().setSelected(true); } else { getMainControlPanel().getRdbtnCompetitive().setSelected(true); } } public void setPlayGame(boolean playGame) { getActionManager().getPlayGameAction().setPlayGame(playGame); } public void loadTipText() { try { URL tipsURL = TipsPanel.class.getResource("/tips/tips.html"); getTipsPanel().getTipsTextPane().setPage(tipsURL); } catch (IOException e) { //This error probably means that /resources/ was not added to the build path e.printStackTrace(); } } public void initSeedTypeComboBox() { JComboBox<SeedType> seedCb = ( JComboBox<SeedType>)getMainControlPanel().getSeedTypeComboBox(); seedCb.addItem(SeedType.Bentline1_RPentomino); seedCb.addItem(SeedType.Bentline1m_RPentomino); seedCb.addItem(SeedType.Bentline_U3x3); seedCb.addItem(SeedType.Bentline1_Plus); seedCb.addItem(SeedType.Square2_RPentomino); seedCb.addItem(SeedType.L2_RPentomino); seedCb.addItem(SeedType.L2B1_RPentomino); seedCb.addItem(SeedType.Boxlid3_RPentomino); seedCb.addItem(SeedType.Boxhat_RPentomino); seedCb.addItem(SeedType.OnebitB1_RPentomino); seedCb.addItem(SeedType.Glider_RPentomino); seedCb.addItem(SeedType.RPentomino_RPentomino); } public void updateSpeedValue(int value) { getGameModel().getGameThread().setAutoAdjust(false); int sleepDelay = 1; int iterations = 1; switch (value) { case -5 : sleepDelay = 500; break; case -4 : sleepDelay = 100; break; case -3 : sleepDelay = 20; break; case -2 : sleepDelay = 8; break; case -1 : sleepDelay = 4; break; case 0 : break; case 1 : iterations = 2; break; case 2 : iterations = 4; break; case 3 : iterations = 8; break; case 4 : iterations = 16; break; case 5 : iterations = 32; break; } getGameModel().getGameThread().setSleepDelay(sleepDelay); getGameModel().getGameThread().setIterations(iterations); } public void updateZoomValue(int value) { double zoom =1; if (value >=0 ) { zoom = Math.pow(1.2, value); getBoardRenderer().setBlockSize(6); } else { switch (value) { case -5 : getBoardRenderer().setBlockSize(1); break; case -4 : getBoardRenderer().setBlockSize(2); break; case -3 : getBoardRenderer().setBlockSize(3); break; case -2 : getBoardRenderer().setBlockSize(4); break; case -1 : getBoardRenderer().setBlockSize(5); break; } } //updateBoardSizeFromPanelSize(getScrollPanel().getViewportSize()); //double zoom = Math.pow(1.1, value); getBoardRenderer().setZoom(zoom); getScrollController().setScalingZoomFactor(zoom); //getScrollController().updateScrollBars(); updateImageWidthHeightLabel(); //getImageManager().repaintNewGraphImage(); } public void updateBoardSizeFromPanelSize(Dimension d) { //d.width-=40; //d.height-=40; getInteractionLock().writeLock().lock(); getBoardRenderer().setBounds(d); int boardWidth = (d.width-40)/getBoardRenderer().getDefaultBlockSize()-2; int boardHeight = (d.height-40)/getBoardRenderer().getDefaultBlockSize()-2; boolean autoSizeGrid = getMainControlPanel().getAutoSizeGridCheckbox().isSelected(); if (autoSizeGrid) { getMainControlPanel().getBoardWidthSpinner().setValue(boardWidth); getMainControlPanel().getBoardHeightSpinner().setValue(boardHeight); } getMainControlPanel().getAutoSizeGridCheckbox().setSelected(autoSizeGrid); Dimension boardSize = new Dimension(boardWidth,boardHeight); boardSize.width=Math.max(1, boardSize.width); boardSize.height=Math.max(1, boardSize.height); getGameModel().getEchosystem().setBoardSize(boardSize); getInteractionLock().writeLock().unlock(); getScrollController().updateScrollBars(); updateImageWidthHeightLabel(); getImageManager().repaintNewImage(); } public void updateBoardSize(int width, int height) { int displayWidth = (width+2)*getBoardRenderer().getDefaultBlockSize()+40; int displayHeight = (height+2)*getBoardRenderer().getDefaultBlockSize()+40; updateBoardSizeFromPanelSize(new Dimension(displayWidth,displayHeight)); } public void updateImageWidthHeightLabel() { int imageWidth = (int) getScrollController().getRendererRectangle().getWidth(); int imageHeight = (int) getScrollController().getRendererRectangle().getHeight(); imageWidth = Math.min(imageWidth,getScrollPanel().getViewportSize().width); imageHeight = Math.min(imageHeight,getScrollPanel().getViewportSize().height); getMainControlPanel().getImageWidthHeightLabel().setText(imageWidth+", "+imageHeight); } }