/*
GanttProject is an opensource project management tool.
Copyright (C) 2011 GanttProject Team
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 (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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package net.sourceforge.ganttproject.chart.gantt;
import java.awt.event.MouseEvent;
import java.util.List;
import javax.swing.Action;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import net.sourceforge.ganttproject.ChartComponentBase;
import net.sourceforge.ganttproject.GanttTree2;
import net.sourceforge.ganttproject.action.GPAction;
import net.sourceforge.ganttproject.chart.ChartModelImpl;
import net.sourceforge.ganttproject.chart.item.ChartItem;
import net.sourceforge.ganttproject.chart.item.TaskBoundaryChartItem;
import net.sourceforge.ganttproject.chart.item.TaskProgressChartItem;
import net.sourceforge.ganttproject.chart.item.TaskRegularAreaChartItem;
import net.sourceforge.ganttproject.chart.mouse.MouseListenerBase;
import net.sourceforge.ganttproject.gui.UIFacade;
import net.sourceforge.ganttproject.task.Task;
import net.sourceforge.ganttproject.task.TaskSelectionManager;
import net.sourceforge.ganttproject.task.algorithm.RetainRootsAlgorithm;
import net.sourceforge.ganttproject.util.MouseUtil;
class MouseListenerImpl extends MouseListenerBase {
private static final Function<Task, Task> getParentTask = new Function<Task, Task>() {
@Override
public Task apply(Task task) {
return task.getManager().getTaskHierarchy().getContainer(task);
}
};
private static final RetainRootsAlgorithm<Task> ourRetainRootsAlgorithm = new RetainRootsAlgorithm<Task>();
private final GanttTree2 myTree;
private final GanttChartController myChartImplementation;
private final UIFacade myUiFacade;
private final ChartComponentBase myChartComponent;
public MouseListenerImpl(GanttChartController chartImplementation, ChartModelImpl chartModel, UIFacade uiFacade,
ChartComponentBase chartComponent, GanttTree2 tree) {
super(uiFacade, chartComponent, chartImplementation);
myUiFacade = uiFacade;
myTree = tree;
myChartImplementation = chartImplementation;
myChartComponent = chartComponent;
}
private TaskSelectionManager getTaskSelectionManager() {
return myUiFacade.getTaskSelectionManager();
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
Task taskUnderPointer = myChartImplementation.findTaskUnderPointer(e.getX(), e.getY());
if (taskUnderPointer == null) {
getTaskSelectionManager().clear();
}
}
if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) {
myTree.getPropertiesAction().actionPerformed(null);
}
}
@Override
protected Action[] getPopupMenuActions(MouseEvent e) {
Action[] treeActions = myTree.getPopupMenuActions();
int sep = 0;
if (treeActions.length != 0) {
sep = 1;
}
Action[] chartActions = myChartComponent.getPopupMenuActions(e);
Action[] result = new Action[treeActions.length + sep + chartActions.length];
System.arraycopy(treeActions, 0, result, 0, treeActions.length);
System.arraycopy(chartActions, 0, result, treeActions.length + sep, chartActions.length);
return result;
}
@Override
public void mousePressed(MouseEvent e) {
myTree.stopEditing();
String text = MouseUtil.toString(e);
super.mousePressed(e);
// If there is no task under the mouse pointer, we consider dragging the
// chart
Task taskUnderPointer = myChartImplementation.findTaskUnderPointer(e.getX(), e.getY());
if (taskUnderPointer == null) {
if (text.equals(GPAction.getKeyStrokeText("mouse.drag.chart"))) {
startScrollView(e);
}
return;
}
// Process selection change before doing other interactions
if (text.equals(GPAction.getKeyStrokeText("mouse.select.single"))) {
getTaskSelectionManager().clear();
}
if (text.equals(GPAction.getKeyStrokeText("mouse.select.single"))
|| text.equals(GPAction.getKeyStrokeText("mouse.select.multiple"))) {
getTaskSelectionManager().addTask(taskUnderPointer);
}
// Now examine what exactly is under the pointer
ChartItem itemUnderPoint = myChartImplementation.getChartItemUnderMousePoint(e.getX(), e.getY());
if (itemUnderPoint instanceof TaskRegularAreaChartItem) {
// If it is a plain task area then either drag the task or create a
// dependency,
// depending on the settings.
if (text.equals(GPAction.getKeyStrokeText("mouse.drag.task"))) {
startDragTasks(e, taskUnderPointer);
return;
}
if (text.equals(GPAction.getKeyStrokeText("mouse.dependency"))) {
startDrawDependency(e, itemUnderPoint);
return;
}
} else {
// Otherwise process boundary change or progress change
handleEvent(itemUnderPoint, e);
}
}
private void startDrawDependency(MouseEvent e, ChartItem itemUnderPoint) {
myChartImplementation.beginDrawDependencyInteraction(e, (TaskRegularAreaChartItem) itemUnderPoint);
}
private void startDragTasks(MouseEvent e, Task taskUnderPointer) {
if (!getTaskSelectionManager().isTaskSelected(taskUnderPointer)) {
getTaskSelectionManager().clear();
getTaskSelectionManager().addTask(taskUnderPointer);
}
List<Task> roots = Lists.newArrayList();
ourRetainRootsAlgorithm.run(getTaskSelectionManager().getSelectedTasks().toArray(new Task[0]), getParentTask, roots);
myChartImplementation.beginMoveTaskInteractions(e, roots);
}
private void handleEvent(ChartItem itemUnderPoint, MouseEvent e) {
if (itemUnderPoint instanceof TaskBoundaryChartItem) {
TaskBoundaryChartItem taskBoundary = (TaskBoundaryChartItem) itemUnderPoint;
if (taskBoundary.isStartBoundary()) {
myChartImplementation.beginChangeTaskStartInteraction(e, taskBoundary);
} else {
myChartImplementation.beginChangeTaskEndInteraction(e, taskBoundary);
}
} else if (itemUnderPoint instanceof TaskProgressChartItem) {
myChartImplementation.beginChangeTaskProgressInteraction(e, (TaskProgressChartItem) itemUnderPoint);
}
}
}