package org.geogebra.desktop.gui.layout; import java.awt.Component; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import javax.swing.JComponent; import javax.swing.JSplitPane; import javax.swing.SwingUtilities; import org.geogebra.common.euclidian.EuclidianView; import org.geogebra.common.gui.Layout; import org.geogebra.common.io.layout.DockPanelData; import org.geogebra.common.io.layout.Perspective; import org.geogebra.common.main.App; import org.geogebra.common.main.settings.AbstractSettings; import org.geogebra.common.main.settings.SettingListener; import org.geogebra.common.plugin.Event; import org.geogebra.common.plugin.EventType; import org.geogebra.common.util.debug.Log; import org.geogebra.desktop.gui.GuiManagerD; import org.geogebra.desktop.main.AppD; /** * Manage layout related stuff. * * @author Florian Sonner */ public class LayoutD extends Layout implements SettingListener { private AppD app; private DockManagerD dockManager; /** * {@link #initialize(AppD)} has to be called once in order to use this * class. */ public LayoutD(App app) { initializeDefaultPerspectives(app, 0.25); this.perspectives = new ArrayList<Perspective>( getDefaultPerspectivesLength()); } /** * Initialize the layout component. * * @param appd * Application */ public void initialize(AppD appd) { if (!initializeCommon(appd)) { return; } this.app = appd; this.dockManager = new DockManagerD(this); } /** * Add a new dock panel to the list of known panels. * * Attention: This method has to be called as early as possible in the * application life cycle (e.g. before loading a file, before constructing * the ViewMenu). * * @param dockPanel */ public void registerPanel(DockPanelD dockPanel) { dockManager.registerPanel(dockPanel); } /** * Apply a new perspective. * * TODO consider applet parameters * * @param perspective */ @Override public boolean applyPerspective(Perspective perspective) { // ignore axes & grid settings for the document perspective app.getGuiManager() .setToolBarDefinition(perspective.getToolbarDefinition()); app.setShowToolBarNoUpdate(perspective.getShowToolBar()); app.setShowToolBarHelpNoUpdate(perspective.getShowToolBarHelp()); app.setToolbarPosition(perspective.getToolBarPosition(), false); app.setShowAlgebraInput(perspective.getShowInputPanel(), false); app.setInputPosition(perspective.getInputPosition(), false); app.setDockBarEast(perspective.isDockBarEast()); app.setShowDockBar(perspective.getShowDockBar(), false); // change the dock panel layout dockManager.applyPerspective(perspective.getSplitPaneData(), perspective.getDockPanelData()); // apply ev settings after focus on view boolean changed = setEVsettingsFromPerspective(app, perspective); if (!app.isIniting()) { app.updateToolBar(); app.updateMenubar(); app.updateContentPane(); } app.dispatchEvent(new Event(EventType.PERSPECTIVE_CHANGE, null)); return changed; } /** * Apply a new perspective using its id. * * This is a wrapper for #applyPerspective(Perspective) to simplify the * loading of default perspectives by name. * * @param id * The ID of the perspective. For default perspectives the * hard-coded ID is used, ie the translation key, for all other * perspectives the ID chosen by the user is used. * @throws IllegalArgumentException * If no perspective with the given name could be found. */ @Override public void applyPerspective(String id) throws IllegalArgumentException { Perspective perspective = getPerspective(id); if (perspective != null) { applyPerspective(perspective); } else { throw new IllegalArgumentException( "Could not find perspective with the given name."); } } /** * Create a perspective for the current layout. * * @param id * @return a perspective for the current layout. */ @Override public Perspective createPerspective(String id) { if (app == null || dockManager.getRoot() == null) { return null; } // return the default perspective in case we're creating new preferences // of // a virgin application. EuclidianView ev = app.getEuclidianView1(); Perspective perspective = new Perspective(id); // get the information about the split panes DockSplitPane.TreeReader spTreeReader = new DockSplitPane.TreeReader( app); perspective .setSplitPaneData(spTreeReader.getInfo(dockManager.getRoot())); // get the information about the dock panels DockPanelD[] panels = dockManager.getPanels(); DockPanelData[] dockPanelInfo = new DockPanelData[panels.length]; for (int i = 0; i < panels.length; ++i) { // just the width of the panels isn't updated every time the panel // is updated, so we have to take care of this by ourself if (!panels[i].isOpenInFrame() && panels[i].isVisible()) { DockSplitPane parent = panels[i].getParentSplitPane(); if (parent != null) { if (parent .getOrientation() == JSplitPane.HORIZONTAL_SPLIT) { panels[i].setEmbeddedSize(panels[i].getWidth()); } else { panels[i].setEmbeddedSize(panels[i].getHeight()); } } panels[i].setEmbeddedDef(panels[i].calculateEmbeddedDef()); } dockPanelInfo[i] = panels[i].createInfo(); } // Sort the dock panels as the entries with the smallest amount of // definition should // be read first by the loading algorithm. Arrays.sort(dockPanelInfo, new Comparator<DockPanelData>() { @Override public int compare(DockPanelData o1, DockPanelData o2) { int diff = o2.getEmbeddedDef().length() - o1.getEmbeddedDef().length(); return diff; } }); perspective.setDockPanelData(dockPanelInfo); perspective.setToolbarDefinition( ((GuiManagerD) app.getGuiManager()).getToolbarDefinition()); perspective.setShowToolBar(app.showToolBar()); perspective.setShowAxes(ev.getShowXaxis() && ev.getShowYaxis()); perspective.setShowGrid(ev.getShowGrid()); perspective.setShowInputPanel(app.showAlgebraInput()); perspective.setShowInputPanelCommands(app.showInputHelpToggle()); perspective.setInputPosition(app.getInputPosition()); perspective.setToolBarPosition(app.getToolbarPosition()); perspective.setShowToolBarHelp(app.showToolBarHelp()); perspective.setShowDockBar(app.isShowDockBar()); perspective.setDockBarEast(app.isDockBarEast()); return perspective; } /** * Get all current perspectives as array. * * @return all current perspectives as array. */ public Perspective[] getPerspectives() { Perspective[] array = new Perspective[perspectives.size()]; return perspectives.toArray(array); } /** * @param index * @return perspective at given index */ public Perspective getPerspective(int index) { if (index >= perspectives.size()) { throw new IndexOutOfBoundsException(); } return perspectives.get(index); } /** * @param id * name of the perspective * @return perspective with 'id' as name or null */ public Perspective getPerspective(String id) { for (int i = 0; i < getDefaultPerspectivesLength(); ++i) { if (id.equals(getDefaultPerspectives(i).getId())) { return getDefaultPerspectives(i); } } for (Perspective perspective : perspectives) { if (id.equals(perspective.getId())) { return perspective; } } return null; } /** * Add a new perspective to the list of available perspectives. * * @param perspective */ public void addPerspective(Perspective perspective) { perspectives.add(perspective); } /** * Remove a perspective identified by the object. * * @param perspective */ public void removePerspective(Perspective perspective) { if (perspectives.contains(perspective)) { perspectives.remove(perspective); } } /** * Remove a perspective identified by the index. * * @param index */ public void removePerspective(int index) { if (index >= 0 && index < perspectives.size()) { perspectives.remove(index); } else { Log.debug("Invalid perspective index: " + index); } } /** * Checks if the given component is in an external window. Used for key * dispatching. * * @param component * @return whether the given component is in an external window. Used for * key dispatching. */ public boolean inExternalWindow(Component component) { DockPanelD[] panels = dockManager.getPanels(); for (int i = 0; i < panels.length; ++i) { if (panels[i].isOpenInFrame()) { if (component == SwingUtilities.getRootPane(panels[i])) { return true; } } } return false; } /** * @param viewId * @return If just the view associated to viewId is visible */ @Override public boolean isOnlyVisible(int viewId) { DockPanelD[] panels = dockManager.getPanels(); boolean foundView = false; for (int i = 0; i < panels.length; ++i) { // check if the view is visible at all if (panels[i].getViewId() == viewId) { foundView = true; if (!panels[i].isVisible()) { return false; } } // abort if any other view is visible else { if (panels[i].isVisible()) { return false; } } } // if we reach this point each other view is invisible, but // if the view wasn't found at all we return false as well return foundView; } /** * Layout settings changed. */ @Override public void settingsChanged(AbstractSettings abstractSettings) { dockManager.updatePanels(); } /** * @return The application object. */ public AppD getApplication() { return app; } /** * @return The management class for the docking behavior. */ @Override public DockManagerD getDockManager() { return dockManager; } public JComponent getRootComponent() { if (dockManager == null) { return null; } return dockManager.getRoot(); } /** * Show the prompt which is used to save the current perspective. */ public void showSaveDialog() { // unused } }