/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * 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 * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.gui; import java.awt.event.ActionEvent; import java.io.File; import java.io.FilenameFilter; import java.util.logging.Level; import javax.swing.Action; import com.rapidminer.gui.processeditor.ProcessLogTab; import com.rapidminer.gui.processeditor.results.ResultTab; import com.rapidminer.gui.tools.ResourceAction; import com.rapidminer.tools.FileSystemService; import com.rapidminer.tools.LogService; import com.rapidminer.tools.Observable; import com.rapidminer.tools.usagestats.ActionStatisticsCollector; import com.vlsolutions.swing.docking.Dockable; import com.vlsolutions.swing.docking.DockableResolver; import com.vlsolutions.swing.docking.DockableState; import com.vlsolutions.swing.docking.DockingContext; import com.vlsolutions.swing.docking.DockingDesktop; import com.vlsolutions.swing.docking.ws.WSDockKey; /** * The {@link PerspectiveController} manages a {@link PerspectiveModel} to show, delete and * manipulates application {@link Perspective}s. The {@link PerspectiveModel} itself is an * {@link Observable} and can notify listeners about new registered perspectives and perspective * changes. * * @author Marcel Michel * @since 7.0.0 */ public class PerspectiveController { private final DockingContext context; private final PerspectiveModel model; private final Action restoreDefaultAction = new ResourceAction("restore_predefined_perspective_default") { private static final long serialVersionUID = 1L; @Override public void actionPerformed(final ActionEvent e) { if (!getModel().getSelectedPerspective().isUserDefined()) { getModel().restoreDefault(getModel().getSelectedPerspective().getName()); getModel().getSelectedPerspective().apply(context); } } }; /** * Creates a new {@link PerspectiveController} with the given docking context. * * @param context * the docking context which should be used */ public PerspectiveController(final DockingContext context) { this.context = context; this.model = new PerspectiveModel(); context.setDockableResolver(new DockableResolver() { @Override public Dockable resolveDockable(final String key) { if (key.startsWith(ResultTab.DOCKKEY_PREFIX)) { ResultTab tab = new ResultTab(key); tab.showResult(null); return tab; } else if (key.startsWith(ProcessLogTab.DOCKKEY_PREFIX)) { ProcessLogTab tab = new ProcessLogTab(key); tab.setDataTableViewer(null); return tab; } else { return null; } } }); this.model.makePredefined(); } /** * Displays the given perspective, identified by the name. * * @param perspective * the perspective which should be shown. */ public void showPerspective(final String perspectiveName) { showPerspective(model.getPerspective(perspectiveName)); } /** * Displays the given perspective. * * @param perspective * the perspective which should be shown. */ public void showPerspective(final Perspective perspective) { if (perspective != null) { Perspective oldPerspective = model.getSelectedPerspective(); if (oldPerspective == perspective) { return; } model.setSelectedPerspective(perspective); if (oldPerspective != null) { oldPerspective.store(context); ActionStatisticsCollector.getInstance().stopTimer(ActionStatisticsCollector.TYPE_PERSPECTIVE, oldPerspective.getName(), null); } perspective.apply(context); getRestoreDefaultAction().setEnabled(!perspective.isUserDefined()); ActionStatisticsCollector.getInstance().startTimer(ActionStatisticsCollector.TYPE_PERSPECTIVE, perspective.getName(), null); ActionStatisticsCollector.getInstance().log(ActionStatisticsCollector.TYPE_PERSPECTIVE, perspective.getName(), "show"); } } /** * Removes the given perspective. If the perspective which should be deleted is also the * selected perspective, the first perspective will be shown. * * @param name * the name of the perspective which should be removed */ public void removePerspective(String name) { Perspective perspective = model.getPerspective(name); if (perspective != null) { removePerspective(perspective); } } /** * Removes the given perspective. If the perspective which should be deleted is also the * selected perspective, the first perspective will be shown. * * @param perspective * the perspective which should be deleted */ public void removePerspective(Perspective perspective) { if (!perspective.isUserDefined()) { return; } model.deletePerspective(perspective); if (model.getSelectedPerspective() == perspective && !model.getAllPerspectives().isEmpty()) { showPerspective(model.getAllPerspectives().get(0)); } } /** * Removes all perspectives and the given dockable. */ public void removeFromAllPerspectives(final Dockable dockable) { context.unregisterDockable(dockable); // Should also be removed from the workspaces, but the // vldocking framework does not support this removeFromInvisiblePerspectives(dockable); } /** * Removes the given {@link Dockable} from all perspectives except the one currently displayed. * * @param dockable * the dockable to close */ public void removeFromInvisiblePerspectives(final Dockable dockable) { WSDockKey key = new WSDockKey(dockable.getDockKey().getKey()); for (Perspective persp : model.getAllPerspectives()) { if (persp == model.getSelectedPerspective()) { continue; } persp.getWorkspace().getDesktop(0).removeNode(key); } } /** * Shows the tab as a child of the given dockable in all perspectives. */ public void showTabInAllPerspectives(final Dockable dockable, final Dockable parent) { DockableState dstate = context.getDockableState(dockable); if (dstate != null && !dstate.isClosed()) { return; } DockingDesktop dockingDesktop = context.getDesktopList().get(0); context.registerDockable(dockable); WSDockKey parentKey = new WSDockKey(parent.getDockKey().getKey()); WSDockKey key = new WSDockKey(dockable.getDockKey().getKey()); for (Perspective persp : model.getAllPerspectives()) { if (persp == model.getSelectedPerspective()) { continue; } // We don't need to show it if // 1. We don't know the parent // 2. We already have the child boolean containsParent = persp.getWorkspace().getDesktop(0).containsNode(parentKey); boolean containsChild = persp.getWorkspace().getDesktop(0).containsNode(key); if (containsParent && !containsChild) { persp.getWorkspace().getDesktop(0).createTab(parentKey, key, 1); } } DockableState[] states = dockingDesktop.getDockables(); for (DockableState state : states) { if (state.getDockable() == parent && !state.isClosed()) { dockingDesktop.createTab(state.getDockable(), dockable, 1, true); break; } } } /** * Saves all perspectives to the file system. */ public void saveAll() { LogService.getRoot().log(Level.CONFIG, "com.rapidminer.gui.ApplicationPerspectives.saving_perspectives"); if (model.getSelectedPerspective() != null) { model.getSelectedPerspective().store(context); } for (Perspective perspective : model.getAllPerspectives()) { perspective.save(); } } /** * Loads the default and user perspectives from the file system. */ public void loadAll() { LogService.getRoot().log(Level.CONFIG, "com.rapidminer.gui.ApplicationPerspectives.loading_perspectives"); for (Perspective perspective : model.getAllPerspectives()) { perspective.load(); } File[] userPerspectiveFiles = FileSystemService.getUserRapidMinerDir().listFiles(new FilenameFilter() { @Override public boolean accept(final File dir, final String name) { return name.startsWith("vlperspective-user-"); } }); for (File file : userPerspectiveFiles) { String name = file.getName(); name = name.substring("vlperspective-user-".length()); name = name.substring(0, name.length() - ".xml".length()); Perspective perspective = createUserPerspective(name, false); perspective.load(); } } /** * Creates a user-defined perspectives, and possibly switches to this new perspective * immediately. The new perspective will be a copy of the current one. */ public Perspective createUserPerspective(final String name, final boolean show) { Perspective perspective = model.addPerspective(name, true); perspective.store(context); if (show) { showPerspective(name); } return perspective; } /** * Getter for the underlying model. * * @return The used {@link PerspectiveModel} */ public PerspectiveModel getModel() { return model; } /** * Getter for the restore default action for a predefined perspective. * * @return the restore default {@link Action} */ public Action getRestoreDefaultAction() { return restoreDefaultAction; } }