/* * RapidMiner * * Copyright (C) 2001-2011 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.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.tools; import java.awt.Component; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.Iterator; import java.util.LinkedList; import javax.swing.AbstractAction; import javax.swing.AbstractButton; import javax.swing.JButton; import javax.swing.JPopupMenu; import javax.swing.SwingConstants; import javax.swing.event.EventListenerList; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import com.rapidminer.gui.tools.components.DropDownButton; /** * * @author Tobias Malbrecht */ public class ParentButtonPanel<T> extends ExtendedJToolBar { private static final int HISTORY_SIZE = 20; private static final long serialVersionUID = 7115627292465260984L; private LinkedList<T> backward = new LinkedList<T>(); private LinkedList<T> forward = new LinkedList<T>(); private ParentButtonModel<T> model; private T currentNode; private T selectedNode; private boolean selectionByHistory = false; private DropDownButton backwardButton = new DropDownButton(new ResourceAction(true, "select_backward") { private static final long serialVersionUID = 3096873810683015968L; @Override public void actionPerformed(ActionEvent e) { if (backward.size() > 1) { forward.addFirst(backward.removeFirst()); selectedNode = backward.getFirst(); selectionByHistory = true; fireAction(); } } }) { private static final long serialVersionUID = -770314831566061205L; @Override protected JPopupMenu getPopupMenu() { return createBackwardMenu(); } }; private DropDownButton forwardButton = new DropDownButton(new ResourceAction(true, "select_forward") { private static final long serialVersionUID = -5189987068889279439L; @Override public void actionPerformed(ActionEvent e) { if (forward.size() > 0) { backward.addFirst(forward.removeFirst()); selectedNode = backward.getFirst(); selectionByHistory = true; fireAction(); } } }) { private static final long serialVersionUID = -770314831566061205L; @Override protected JPopupMenu getPopupMenu() { return createForwardMenu(); } }; private JButton upButton = new JButton(new ResourceAction(true, "select_parent") { private static final long serialVersionUID = -5411675828764033039L; @Override public void actionPerformed(ActionEvent e) { selectedNode = model.getParent(currentNode); fireAction(); } }); public ParentButtonPanel() { this(null); } public ParentButtonPanel(ParentButtonModel<T> model) { setModel(model); setOpaque(false); } private final MouseListener borderListener = new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { if (!(e.getComponent() instanceof Separator)) { ((AbstractButton)e.getComponent()).setBorderPainted(true); } } @Override public void mouseExited(MouseEvent e) { if (!(e.getComponent() instanceof Separator)) { ((AbstractButton)e.getComponent()).setBorderPainted(false); } } }; @Override public Component add(Component c) { Component result = super.add(c); c.addMouseListener(borderListener); return result; } public void setSelectedNode(T node) { this.currentNode = node; upButton.setEnabled(model.getParent(currentNode) != null); backwardButton.setEnabled(backward.size() > 1); forwardButton.setEnabled(forward.size() > 0); setup(); } public void setModel(ParentButtonModel<T> model) { this.model = model; setup(); } private void setup() { removeAll(); backwardButton.addToToolBar(this); forwardButton.addToToolBar(this); add(upButton); addSeparator(); if (model != null) { LinkedList<T> nodes = new LinkedList<T>(); T node = currentNode; while (node != null) { nodes.addFirst(node); node = model.getParent(node); } for (T n : nodes) { add(makeButton(n)); add(makeDropdownButton(n)); } } revalidate(); repaint(); } private JPopupMenu createBackwardMenu() { JPopupMenu menu = new JPopupMenu("History"); boolean first = true; for (final T node : backward) { if (first) { first = false; continue; } menu.add(new AbstractAction(model.toString(node)) { private static final long serialVersionUID = 1L; { putValue(SMALL_ICON, model.getIcon(node)); } @Override public void actionPerformed(ActionEvent e) { selectedNode = node; Iterator<T> iterator = backward.iterator(); while (iterator.hasNext()) { T nextNode = iterator.next(); if (nextNode == node) { break; } iterator.remove(); forward.addFirst(nextNode); } selectionByHistory = true; fireAction(); } }); } return menu; } private JPopupMenu createForwardMenu() { JPopupMenu menu = new JPopupMenu("History"); for (final T node : forward) { menu.add(new AbstractAction(model.toString(node)) { private static final long serialVersionUID = 1L; { putValue(SMALL_ICON, model.getIcon(node)); } @Override public void actionPerformed(ActionEvent e) { selectedNode = node; Iterator<T> iterator = forward.iterator(); while (iterator.hasNext()) { T nextNode = iterator.next(); iterator.remove(); backward.addFirst(nextNode); if (nextNode == node) { break; } } selectionByHistory = true; fireAction(); } }); } return menu; } private JButton makeButton(final T node) { JButton button = new JButton(model.toString(node), model.getIcon(node)); button.setOpaque(false); button.setBorderPainted(false); button.setMargin(new Insets(0,0,0,0)); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { selectedNode = node; fireAction(); } }); return button; } private JButton makeDropdownButton(final T node) { final ArrowButton button = new ArrowButton(SwingConstants.EAST); button.setOpaque(false); button.setBorderPainted(false); button.setMargin(new Insets(0,0,0,0)); button.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { JPopupMenu menu = makeMenu(node); button.setDirection(SwingConstants.SOUTH); menu.addPopupMenuListener(new PopupMenuListener() { @Override public void popupMenuCanceled(PopupMenuEvent e) { } @Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { button.setDirection(SwingConstants.EAST); } @Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) { } }); menu.show(button, 0, button.getHeight()); } }); return button; } private JPopupMenu makeMenu(final T node) { JPopupMenu menu = new JPopupMenu(); for (int i = 0; i < model.getNumberOfChildren(node); i++) { final T child = model.getChild(node, i); menu.add(new AbstractAction(model.toString(child)) { private static final long serialVersionUID = 7232177147279985209L; { putValue(SMALL_ICON, model.getIcon(child)); } @Override public void actionPerformed(ActionEvent e) { selectedNode = child; fireAction(); } }); } return menu; } public T getSelectedNode() { return selectedNode; } private EventListenerList listeners = new EventListenerList(); public void addActionListener(ActionListener l) { listeners.add(ActionListener.class, l); } public void removeActionListener(ActionListener l) { listeners.remove(ActionListener.class, l); } private int eventId = 0; public void clearHistory() { backward.clear(); forward.clear(); } public void addToHistory(T node) { if (node == null) { return; } if (backward.size() > 0) { if (backward.getFirst() != node) { backward.remove(node); backward.addFirst(node); if (!selectionByHistory) { forward.clear(); } } } else { backward.remove(node); backward.addFirst(node); if (!selectionByHistory) { forward.clear(); } } while (backward.size() > HISTORY_SIZE) { backward.removeLast(); } selectionByHistory = false; backwardButton.setEnabled(backward.size() > 1); forwardButton.setEnabled(forward.size() > 0); } private void fireAction() { ActionEvent e = new ActionEvent(this, eventId++, "select"); for (ActionListener l : listeners.getListeners(ActionListener.class)) { l.actionPerformed(e); } upButton.setEnabled(model.getParent(currentNode) != null); backwardButton.setEnabled(backward.size() > 1); forwardButton.setEnabled(forward.size() > 0); } // @Override // public void paintComponent(Graphics g) { // //super.paintComponent(g); // g.setPaint(new GradientPaint(0, 0, Color.)) // } }