/** * Copyright (c) 2014 Matthias Jaenicke <matthias.jaenicke@student.kit.edu>, * Matthias Plappert <undkc@student.kit.edu>, * Julien Duman <uncyc@student.kit.edu>, * Christian Dreher <uaeef@student.kit.edu>, * Wasilij Beskorovajnov <uajkm@student.kit.edu> and * Aydin Tekin <aydin.tekin@student.kit.edu> * * Released under the MIT license (refer to LICENSE.md) * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package edu.kit.iks.Cryptographics; import java.awt.BorderLayout; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Point; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.io.InputStream; import java.text.ParseException; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.plaf.synth.SynthLookAndFeel; import edu.kit.iks.CryptographicsLib.AbstractController; import edu.kit.iks.CryptographicsLib.AbstractVisualizationInfo; import edu.kit.iks.CryptographicsLib.Configuration; import edu.kit.iks.CryptographicsLib.Logger; import edu.kit.iks.CryptographicsLib.PopoverView; /** * An instance of this class is the main controller, delegating all performed * tasks to its subcontrollers like StartController (teaser) or controllers * visualizing a cryptographic procedure * * @author Christian Dreher */ public class MainController extends AbstractController { /** * Gets the configurations supplied by the instance * itself or overwritten by the config.xml file */ private Configuration config = Configuration.getInstance(); /** * A sandbox for subcontrollers to inflate their contents */ private JFrame frame; /** * An instance of the start controller, showing a teaser to draw attention */ private StartController startController; /** * An instance of a container controller, visualizing a cryptographic * procedure inside */ private VisualizationContainerController visualizationContainerController; /** * Just loads the frame. This controller is specially since it does not load a view. */ @Override public void loadView() { // Note: every method here is strictly bound // to the values defined in the config.xml. // If, for example, <mouseCursor> is set to true, // the method disableCursor() will keep the cursor // visible this.loadLookAndFeel(); this.loadFrame(); this.disableCursor(); } /* * (non-Javadoc) * @see edu.kit.iks.CryptographicsLib.AbstractController#unloadView() */ @Override public void unloadView() { this.frame = null; } /** * Gets the JFrame * * @return the JFrame */ public JFrame getJFrame() { return this.frame; } /* * (non-Javadoc) * @see edu.kit.iks.CryptographicsLib.AbstractController#isViewLoaded() */ @Override public boolean isViewLoaded() { return (this.frame != null); } /** * Starts the visualization of StartController */ public void presentStartAction() { // Unload visualization controllers not needed anymore if (this.visualizationContainerController != null) { if (this.visualizationContainerController.getHelpPopoverView() != null) { this.visualizationContainerController.dismissHelpPopover(); } this.frame.getContentPane().remove(this.visualizationContainerController.getView()); this.visualizationContainerController.unloadView(); this.removeChildController(this.visualizationContainerController); this.visualizationContainerController = null; } // Only initialize start controller once, nut load/unload view if (this.startController == null) { this.startController = new StartController(); this.addChildController(this.startController); } // Load view and append it to the frame this.startController.loadView(); this.frame.getContentPane().add(this.startController.getView(), BorderLayout.CENTER); // Important to call validate, as some elements may // be invisible otherwise this.frame.getContentPane().revalidate(); this.frame.getContentPane().repaint(); this.frame.validate(); } /** * Starts the visualization of a procedure with given {visualizationInfo} * * @param visualizationInfo * Metadata of the cryptographic procedure to instantiate the * controller from */ public void presentVisualizationAction( AbstractVisualizationInfo visualizationInfo) { // Unload the view but keep the instance in memory for // better response if (this.startController != null) { this.frame.getContentPane().remove(this.startController.getView()); this.startController.unloadView(); } // load VisualizationContainerController this.visualizationContainerController = new VisualizationContainerController( visualizationInfo); // load view this.visualizationContainerController.loadView(); this.addChildController(this.visualizationContainerController); this.frame.getContentPane().add(this.visualizationContainerController.getView(), BorderLayout.CENTER); this.visualizationContainerController.setCurrentVisualizationControllerIndex(0); this.frame.getContentPane().revalidate(); this.frame.getContentPane().repaint(); this.frame.revalidate(); } /** * Gets the start controller * * @return The start controller */ public StartController getStartController() { return this.startController; } /** * Gets the visualization container controller * * @return The visualization container controller */ public VisualizationContainerController getVisualizationContainerController() { return this.visualizationContainerController; } /** * Loads the JFrame */ private void loadFrame() { this.frame = new JFrame("Cryptographics"); this.frame.setName("main-view"); if (this.config.isFullscreenModeEnabled()) { this.frame.setExtendedState(JFrame.MAXIMIZED_BOTH); this.frame.setUndecorated(true); this.frame.setAlwaysOnTop(true); } else { this.frame.setSize(1366, 768); // Basic size for debugging Logger.debug("MainController", "loadFrame", "Fullscreen mode disabled due to debugging."); } this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.frame.setVisible(true); // Extract the glassPane. We use this for displaying popovers. JPanel popoverContainerView = (JPanel)this.frame.getGlassPane(); PopoverView.setContainerView(popoverContainerView); } /** * Loads the custom look and feel. */ private void loadLookAndFeel() { if (this.config.isLookAndFeelEnabled()) { SynthLookAndFeel lookAndFeel = new SynthLookAndFeel(); try { InputStream is = this.getClass().getResourceAsStream("/theme/manifest.xml"); lookAndFeel.load(is, this.getClass()); } catch (ParseException e) { Logger.error(e); } try { UIManager.setLookAndFeel(lookAndFeel); } catch (UnsupportedLookAndFeelException e) { Logger.error(e); } } else { Logger.debug("MainController", "loadLookAndFeel", "Look and feel disabled due to debugging."); } } /** * Disables the cursor */ private void disableCursor() { if (!this.config.isMouseCursorEnabled()) { Cursor nullCursor = null; Toolkit toolkit = Toolkit.getDefaultToolkit(); Dimension dimension = toolkit.getBestCursorSize(1, 1); if ((dimension.width | dimension.height) != 0) { nullCursor = toolkit.createCustomCursor(new BufferedImage(dimension.width, dimension.height, BufferedImage.TYPE_INT_ARGB), new Point(0, 0), "nullCursor"); } this.frame.setCursor(nullCursor); } else { Logger.debug("MainController", "disableCursor", "Curser is visible due to debugging."); } } }