/** * 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.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JPanel; import com.rapidminer.gui.actions.AboutAction; import com.rapidminer.gui.actions.BrowseAction; import com.rapidminer.gui.actions.RedoAction; import com.rapidminer.gui.actions.UndoAction; import com.rapidminer.gui.actions.WorkspaceAction; import com.rapidminer.gui.actions.startup.TutorialAction; import com.rapidminer.gui.look.Colors; import com.rapidminer.gui.osx.OSXAdapter; import com.rapidminer.gui.tools.ResourceActionAdapter; import com.rapidminer.gui.tools.ResourceLabel; import com.rapidminer.gui.tools.components.DropDownPopupButton.DropDownPopupButtonBuilder; import com.rapidminer.gui.tools.components.composite.PerspectiveToggleGroup; import com.rapidminer.gui.tools.components.composite.SplitButton; import com.rapidminer.tools.I18N; import com.rapidminer.tools.Observable; import com.rapidminer.tools.Observer; import com.rapidminer.tools.SystemInfoUtilities; import com.rapidminer.tools.SystemInfoUtilities.OperatingSystem; /** * Main tool bar of RapidMiner Studio. The tool bar consist of three columns. Action buttons such as * the save or run button are shown on the left, the perspective navigation is shown in the middle, * and additional resources are displayed on the right. * * @author Michael Knopf * @see MainFrame * @since 7.0.0 */ public class MainToolBar extends JPanel { private static final Dimension PERSPECTIVES_SIZE = new Dimension(120, 32); private static final long serialVersionUID = 1L; /** Split button containing all run actions. */ private SplitButton runActions; /** Panel which contains the perspective group and a label */ private JPanel perspectivesPanel; /** Panel which contains the resource button */ private JPanel resourcesPanel; /** Displays the available perspectives */ private PerspectiveToggleGroup perspectivesGroup; /** Maps the perspective name to the corresponding action */ private Map<String, Action> perspectiveActionMap = new HashMap<>(); /** The cached name of the current perspective */ private String perspectiveName; /** * Creates a new tool bar instance. The new instance only contains build-in actions and * perspectives. To display element registered by an extension, the {@link #update()} method * must be invoked (after the extension is fully initialized). * * @param mainframe * the mainframe that uses this tool bar */ public MainToolBar(final MainFrame mainframe) { // use default look and feel background setOpaque(true); setBackground(Colors.WINDOW_BACKGROUND); setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Colors.TAB_BORDER)); // The three columns are implemented via a grid-bag layout. The idea is that both the left // and the right column have the same weight and are both set to grow (fill) horizontally to // ensure an equal column whenever possible. As a consequence, the middle column (which is // not set to grow) is automatically aligned to the center of the tool bar. // // To make this work it is necessary that both the left and the right panel have the same // preferred width. setLayout(new GridBagLayout()); GridBagConstraints constrainst = new GridBagConstraints(); // left column constrainst.gridx = 0; constrainst.weightx = 1; constrainst.fill = GridBagConstraints.HORIZONTAL; // action button panel JPanel actionsPanel; { FlowLayout actionsLayout = new FlowLayout(FlowLayout.LEFT); actionsLayout.setVgap(0); actionsPanel = new JPanel(actionsLayout); actionsPanel.setOpaque(false); JButton newButton = new JButton(mainframe.NEW_ACTION); newButton.setHideActionText(true); actionsPanel.add(newButton); JButton openButton = new JButton(mainframe.OPEN_ACTION); openButton.setHideActionText(true); actionsPanel.add(openButton); SplitButton saveButtons = new SplitButton(mainframe.SAVE_ACTION, mainframe.SAVE_AS_ACTION); saveButtons.SetHideActionText(true); actionsPanel.add(saveButtons); actionsPanel.add(Box.createRigidArea(new Dimension(10, 0))); JButton undoButton = new JButton(new UndoAction(mainframe)); undoButton.setHideActionText(true); actionsPanel.add(undoButton); JButton redoButton = new JButton(new RedoAction(mainframe)); redoButton.setHideActionText(true); actionsPanel.add(redoButton); actionsPanel.add(Box.createRigidArea(new Dimension(10, 0))); runActions = new SplitButton(mainframe.RUN_ACTION); runActions.SetHideActionText(true); actionsPanel.add(runActions); JButton stopButton = new JButton(mainframe.STOP_ACTION); stopButton.setHideActionText(true); actionsPanel.add(stopButton); add(actionsPanel, constrainst); } // middle column constrainst.gridx += 1; constrainst.weightx = 0; constrainst.fill = GridBagConstraints.NONE; // perspectives panel { FlowLayout perspectiveLayout = new FlowLayout(FlowLayout.LEFT); perspectiveLayout.setVgap(0); perspectivesPanel = new JPanel(perspectiveLayout); perspectivesPanel.setOpaque(false); ResourceLabel viewPerspectiveLabel = new ResourceLabel("workspace_views"); viewPerspectiveLabel.setForeground(Color.GRAY); perspectivesPanel.add(viewPerspectiveLabel); final PerspectiveController perspectiveController = mainframe.getPerspectiveController(); PerspectiveModel perspectiveModel = perspectiveController.getModel(); perspectiveModel.addObserver(new Observer<List<Perspective>>() { @Override public void update(Observable<List<Perspective>> observable, List<Perspective> perspectives) { updatePerspectivePanel(perspectiveController, perspectives); Action perspectiveAction = perspectiveActionMap.get(perspectiveName); if (perspectiveAction != null) { perspectivesGroup.setSelected(perspectiveAction); } } }, true); perspectiveModel.addPerspectiveChangeListener(new PerspectiveChangeListener() { @Override public void perspectiveChangedTo(Perspective perspective) { perspectiveName = perspective.getName(); Action perspectiveAction = perspectiveActionMap.get(perspectiveName); if (perspectiveAction != null) { perspectivesGroup.setSelected(perspectiveAction); } } }); updatePerspectivePanel(perspectiveController, perspectiveController.getModel().getAllPerspectives()); add(perspectivesPanel, constrainst); } // right column constrainst.gridx += 1; constrainst.weightx = 1; constrainst.fill = GridBagConstraints.HORIZONTAL; { resourcesPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); resourcesPanel.setOpaque(false); resourcesPanel.setPreferredSize(actionsPanel.getPreferredSize()); resourcesPanel.add(createResourcesButton()); add(resourcesPanel, constrainst); } } /** * @return a dropdown button with a menu containing a links to the tutorial, the online * documentation, the forum, the support and the about box */ private Component createResourcesButton() { DropDownPopupButtonBuilder builder = new DropDownPopupButtonBuilder(); builder.with(new ResourceActionAdapter("toolbar_resources")); builder.add(new TutorialAction()); builder.add(new BrowseAction("toolbar_resources.documentation", URI.create("http://redirects.rapidminer.com/app/studio/7.2/documentation/main_tool_bar"))); builder.add(new BrowseAction("toolbar_resources.help_forum", URI.create("http://redirects.rapidminer.com/app/studio/7.2/forum/main_tool_bar"))); builder.add(new BrowseAction("toolbar_resources.support", URI.create("http://redirects.rapidminer.com/app/studio/7.2/support/main_tool_bar"))); // put "About RapidMiner Studio" action as last action if not on ox if (SystemInfoUtilities.getOperatingSystem() != OperatingSystem.OSX || !OSXAdapter.isAdapted()) { builder.addSeparator(); builder.add(new AboutAction((MainFrame) ApplicationFrame.getApplicationFrame())); } return builder.build(); } public void update() { List<MenuItemFactory> factories = RunActionRegistry.INSTANCE.getFacories(); for (int i = 0; i < factories.size(); i++) { runActions.getPopupMenu().addSeparator(); for (MenuItemFactory.MenuEntry entry : factories.get(i).create()) { if (entry.isAction()) { runActions.getPopupMenu().add(entry.getAction()); } else if (entry.isMenu()) { runActions.getPopupMenu().add(entry.getMenu()); } else if (entry.isComponent()) { runActions.getPopupMenu().add(entry.getComponent()); } } } } /** * Updates the {@link #perspectivesGroup} in regard to the perspective controller and the given * perspectives. * * @param perspectiveController * the controller which should be used * @param perspectives * all available perspectives */ private void updatePerspectivePanel(final PerspectiveController perspectiveController, Collection<Perspective> perspectives) { if (perspectivesGroup != null) { perspectivesPanel.remove(perspectivesGroup); } perspectiveActionMap.clear(); List<Action> primaryActionList = new ArrayList<>(); List<Action> secondaryActionList = new ArrayList<>(); for (Perspective p : perspectives) { String name = p.getName(); Action action = new WorkspaceAction(perspectiveController, p, name); action.putValue(Action.LARGE_ICON_KEY, null); action.putValue(Action.SMALL_ICON, null); if (p.isUserDefined()) { action.putValue(Action.ACTION_COMMAND_KEY, "perspective-" + name); action.putValue(Action.NAME, name); action.putValue(Action.SHORT_DESCRIPTION, I18N.getMessage(I18N.getGUIBundle(), "gui.action.workspace_user.tip", name)); } if (!p.isUserDefined()) { primaryActionList.add(action); } else { secondaryActionList.add(action); } perspectiveActionMap.put(p.getName(), action); } if (primaryActionList.size() > 1) { perspectivesGroup = new PerspectiveToggleGroup(perspectiveController, PERSPECTIVES_SIZE, primaryActionList.toArray(new Action[primaryActionList.size()])); } if (perspectivesGroup != null && secondaryActionList.size() > 0) { perspectivesGroup.addSeconderyActions(secondaryActionList.toArray(new Action[secondaryActionList.size()])); } if (perspectivesGroup != null) { perspectivesPanel.add(perspectivesGroup); perspectivesPanel.validate(); perspectivesPanel.repaint(); } } }