/*OsmUi is a user interface for Osmosis Copyright (C) 2011 Verena Käfer, Peter Vollmer, Niklas Schnelle This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.osmui.ui; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.util.ArrayList; import java.util.List; import java.util.Observable; import java.util.Observer; import javax.swing.AbstractAction; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import com.mxgraph.model.mxCell; import com.mxgraph.swing.mxGraphComponent; import com.mxgraph.view.mxGraph; import de.osmui.model.osm.TTask; import de.osmui.model.pipelinemodel.AbstractTask; import de.osmui.model.pipelinemodel.JGPipelineModel; import de.osmui.ui.events.TaskSelectedEvent; import de.osmui.ui.events.TaskSelectedEventListener; import de.osmui.util.TaskManager; import de.osmui.util.exceptions.TaskNameUnknownException; /** * @author Niklas Schnelle, Peter Vollmer, Verena Käfer * * will be tested by system-tests * */ public class PipelineBox extends mxGraphComponent implements Observer, MouseListener, MouseWheelListener, TaskSelectedEventListener { private static final long serialVersionUID = -2865210986243818496L; private final ArrayList<TaskSelectedEventListener> selectedListeners; private AbstractTask selectedTask; private JPopupMenu popupMenu; private ActionListener popupActionListener; private double zoomPos; public PipelineBox(mxGraph graph) { super(graph); this.selectedListeners = new ArrayList<TaskSelectedEventListener>(); this.zoomPos = 1.0; this.graph.setAllowDanglingEdges(false); this.graph.setAllowLoops(false); this.graph.setAutoSizeCells(true); this.graph.setCellsBendable(false); this.graph.setCellsMovable(true); this.graph.setCellsResizable(false); this.graph.setEdgeLabelsMovable(false); this.graph.setDropEnabled(false); this.getGraphControl().addMouseListener(this); this.setAutoExtend(true); this.setAntiAlias(true); this.setAutoScroll(true); this.setAutoscrolls(true); this.setFoldingEnabled(false); this.setDoubleBuffered(true); this.setImportEnabled(false); this.setExportEnabled(false); // Register ourselves as listener registerTaskSelectedListener(this); addMouseWheelListener(this); this.popupMenu = new JPopupMenu(); popupActionListener = new ActionListener() { @Override public void actionPerformed(ActionEvent event) { JMenuItem item; if (event.getSource() instanceof JMenuItem) { item = (JMenuItem) event.getSource(); AbstractTask newTask; try { newTask = TaskManager.getInstance().createTask( item.getText()); MainFrame.getInstance().getTaskBox() .addTaskToModel(newTask); } catch (TaskNameUnknownException e) { // Do nothing } } } }; // Register Keyboard Actions this.getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( KeyStroke.getKeyStroke("DELETE"), "deleteCell"); this.getActionMap().put("deleteCell", new AbstractAction() { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { final mxGraph graph = getGraph(); // Removes the selected Cells graph.removeCells(); } }); } public void registerTaskSelectedListener(TaskSelectedEventListener l) { selectedListeners.add(l); } public void removeTaskSelectedListener(TaskSelectedEventListener l) { selectedListeners.remove(l); } public void fireTaskSelected(TaskSelectedEvent e) { for (TaskSelectedEventListener listener : selectedListeners) { listener.TaskSelected(e); } } /** * This is from the Observer interface we react to model changes here the * model notifies it's observers with AbstractTask objects when they are * added */ @Override public void update(Observable arg0, Object arg1) { if (arg1 instanceof AbstractTask) { AbstractTask task = (AbstractTask) arg1; // If the model is null the task was removed if (task.getModel() != null && !task.equals(selectedTask)) { this.graph.setSelectionCell(((JGPipelineModel) arg0) .getCellForTask(task)); fireTaskSelected(new TaskSelectedEvent(this, (AbstractTask) task)); selectedTask = task; } else if (task.getModel() == null) { selectedTask = null; fireTaskSelected(new TaskSelectedEvent(this, (AbstractTask) null)); } } } @Override public void mouseClicked(MouseEvent arg0) { //checkEvent(arg0); } // Need to specify the following methods but don't care // for the events so do nothing @Override public void mouseEntered(MouseEvent arg0) { } @Override public void mouseExited(MouseEvent arg0) { } private void checkEvent(MouseEvent event) { // According to java swing doku need to do this in mousePressed // and mouseReleased if (event.isPopupTrigger()) { popupMenu.show(event.getComponent(), event.getX(), event.getY()); } } @Override public void mousePressed(MouseEvent arg0) { mxCell cell = (mxCell) getCellAt(arg0.getX(), arg0.getY()); if ( cell == null) { fireTaskSelected(new TaskSelectedEvent(this, (AbstractTask) null)); } else if (cell.isVertex()){ fireTaskSelected(new TaskSelectedEvent(this, (AbstractTask) cell.getValue())); } checkEvent(arg0); } @Override public void mouseReleased(MouseEvent arg0) { checkEvent(arg0); } @Override public void TaskSelected(TaskSelectedEvent e) { String taskName = (e.getTask() != null && e.getTask().isConnectable()) ? e .getTask().getName() : ""; List<TTask> desc = TaskManager.getInstance().getCompatibleTasks( taskName); popupMenu.removeAll(); for (TTask currTask : desc) { popupMenu.add(currTask.getName()).addActionListener( popupActionListener); } } /** * Wee need to add saving the zoom position to the super class */ @Override public void zoomIn() { super.zoomIn(); zoomPos *= zoomFactor; } /** * Wee need to add saving the zoom position to the super class */ @Override public void zoomOut() { // JGprahx bug fails zooming in after having zoomed out too much, don't // allow this if (zoomPos > 0.3) { super.zoomOut(); zoomPos /= zoomFactor; } } @Override public void mouseWheelMoved(MouseWheelEvent evt) { if (evt.isControlDown() && evt.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) { int scrolled = evt.getWheelRotation(); if (scrolled < 0) { for (int s = 0; s > scrolled; --s) { this.zoomIn(); } } else { for (int s = 0; s < scrolled; ++s) { this.zoomOut(); } } } } }