/*******************************************************************************
* Copyright (c) 2016 Weasis Team and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nicolas Roduit - initial API and implementation
*******************************************************************************/
package org.weasis.core.ui.editor.image;
import java.awt.Cursor;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import org.weasis.core.api.gui.util.ActionW;
import org.weasis.core.api.gui.util.ComboItemListener;
import org.weasis.core.api.gui.util.MouseActionAdapter;
import org.weasis.core.api.gui.util.ToggleButtonListener;
import org.weasis.core.api.media.data.ImageElement;
import org.weasis.core.ui.editor.image.DefaultView2d.BulkDragSequence;
import org.weasis.core.ui.model.AbstractGraphicModel;
import org.weasis.core.ui.model.GraphicModel;
import org.weasis.core.ui.model.graphic.DragGraphic;
import org.weasis.core.ui.model.graphic.Graphic;
import org.weasis.core.ui.model.graphic.imp.area.SelectGraphic;
import org.weasis.core.ui.model.utils.Draggable;
import org.weasis.core.ui.model.utils.imp.DefaultDragSequence;
import org.weasis.core.ui.util.MouseEventDouble;
public class GraphicMouseHandler<E extends ImageElement> extends MouseActionAdapter {
private ViewCanvas<E> vImg;
private Draggable ds;
public GraphicMouseHandler(ViewCanvas<E> vImg) {
if (vImg == null) {
throw new IllegalArgumentException();
}
this.vImg = vImg;
}
public Draggable getDragSequence() {
return ds;
}
@Override
public void mousePressed(MouseEvent e) {
int buttonMask = getButtonMaskEx();
// Check if extended modifier of mouse event equals the current buttonMask
// Also asserts that Mouse adapter is not disable
if (e.isConsumed() || (e.getModifiersEx() & buttonMask) == 0) {
return;
}
// Convert mouse event point to real image coordinate point (without geometric transformation)
MouseEventDouble mouseEvt = new MouseEventDouble(e);
mouseEvt.setImageCoordinates(vImg.getImageCoordinatesFromMouse(e.getX(), e.getY()));
// Do nothing and return if current dragSequence is not completed
if (ds != null) {
Boolean c = ds.completeDrag(mouseEvt);
if (mouseEvt.isConsumed()) {
c = Boolean.FALSE;
ds = null;
}
if (!c) {
return;
}
}
Cursor newCursor = DefaultView2d.DEFAULT_CURSOR;
GraphicModel graphicList = vImg.getGraphicManager();
// Avoid any dragging on selection when Shift Button is Down
if (!mouseEvt.isShiftDown()) {
// Evaluates if mouse is on a dragging position, creates a DragSequence and changes cursor consequently
Optional<Graphic> firstGraphicIntersecting = graphicList.getFirstGraphicIntersecting(mouseEvt);
if (firstGraphicIntersecting.isPresent() && firstGraphicIntersecting.get() instanceof DragGraphic) {
DragGraphic dragGraph = (DragGraphic) firstGraphicIntersecting.get();
List<DragGraphic> selectedDragGraphList = graphicList.getSelectedDragableGraphics();
boolean locked = dragGraph.getLayer().getLocked();
if (!locked && selectedDragGraphList.contains(dragGraph)) {
if (selectedDragGraphList.size() > 1 && selectedDragGraphList.stream().allMatch(g -> !g.getLayer().getLocked())) {
ds = new BulkDragSequence(selectedDragGraphList, mouseEvt);
newCursor = DefaultView2d.MOVE_CURSOR;
} else if (selectedDragGraphList.size() == 1) {
if (dragGraph.isOnGraphicLabel(mouseEvt)) {
ds = dragGraph.createDragLabelSequence();
newCursor = DefaultView2d.HAND_CURSOR;
} else {
int handlePtIndex = dragGraph.getHandlePointIndex(mouseEvt);
if (handlePtIndex >= 0) {
dragGraph.moveMouseOverHandlePoint(handlePtIndex, mouseEvt);
ds = dragGraph.createResizeDrag(handlePtIndex);
newCursor = DefaultView2d.EDIT_CURSOR;
} else {
ds = dragGraph.createMoveDrag();
newCursor = DefaultView2d.MOVE_CURSOR;
}
}
}
} else {
if (!locked && dragGraph.isOnGraphicLabel(mouseEvt)) {
ds = dragGraph.createDragLabelSequence();
newCursor = DefaultView2d.HAND_CURSOR;
} else if (!locked) {
ds = dragGraph.createMoveDrag();
newCursor = DefaultView2d.MOVE_CURSOR;
}
vImg.getGraphicManager().setSelectedGraphic(Arrays.asList(dragGraph));
}
}
}
if (ds == null) {
ImageViewerEventManager<E> eventManager = vImg.getEventManager();
Optional<ActionW> action = eventManager.getMouseAction(e.getModifiersEx());
if (action.isPresent() && action.get().isDrawingAction()) {
Optional<ComboItemListener> items =
eventManager.getAction(ActionW.DRAW_CMD_PREFIX + action.get().cmd(), ComboItemListener.class);
if (items.isPresent()) {
Object item = items.get().getSelectedItem();
Graphic graph = AbstractGraphicModel.drawFromCurrentGraphic(vImg,
(Graphic) (item instanceof Graphic ? item : null));
if (graph instanceof DragGraphic) {
ds = ((DragGraphic) graph).createResizeDrag();
if (!(graph instanceof SelectGraphic)) {
vImg.getGraphicManager().setSelectedGraphic(Arrays.asList(graph));
}
}
}
}
}
vImg.getJComponent().setCursor(Optional.ofNullable(newCursor).orElse(DefaultView2d.DEFAULT_CURSOR));
if (ds != null) {
ds.startDrag(mouseEvt);
} else {
vImg.getGraphicManager().setSelectedGraphic(null);
}
// Throws to the tool listener the current graphic selection.
vImg.getGraphicManager().fireGraphicsSelectionChanged(vImg.getMeasurableLayer());
}
@Override
public void mouseReleased(MouseEvent e) {
int buttonMask = getButtonMask();
// Check if extended modifier of mouse event equals the current buttonMask
// Note that extended modifiers are not triggered in mouse released
// Also asserts that Mouse adapter is not disable
if ((e.getModifiers() & buttonMask) == 0) {
return;
}
// Do nothing and return if no dragSequence exist
if (ds == null) {
return;
}
// Convert mouse event point to real image coordinate point (without geometric transformation)
MouseEventDouble mouseEvt = new MouseEventDouble(e);
mouseEvt.setImageCoordinates(vImg.getImageCoordinatesFromMouse(e.getX(), e.getY()));
Optional<SelectGraphic> selection = vImg.getGraphicManager().getSelectGraphic();
if (selection.isPresent()) {
Graphic selectGraphic = selection.get();
AffineTransform transform = DefaultView2d.getAffineTransform(mouseEvt);
Rectangle selectionRect = selectGraphic.getBounds(transform);
// Little size rectangle in selection click is interpreted as a single clic
boolean isSelectionSingleClic =
selectionRect == null || (selectionRect.width < 5 && selectionRect.height < 5);
final List<Graphic> newSelectedGraphList = new ArrayList<>();
if (isSelectionSingleClic) {
vImg.getGraphicManager().getFirstGraphicIntersecting(mouseEvt).ifPresent(newSelectedGraphList::add);
} else {
newSelectedGraphList
.addAll(vImg.getGraphicManager().getSelectedAllGraphicsIntersecting(selectionRect, transform));
}
// Add all graphics inside selection rectangle at any level in layers instead in the case of single
// click where top level first graphic found is removed from list if already selected
if (mouseEvt.isShiftDown()) {
List<Graphic> selectedGraphList = vImg.getGraphicManager().getSelectedGraphics();
if (!selectedGraphList.isEmpty()) {
if (newSelectedGraphList.isEmpty()) {
newSelectedGraphList.addAll(selectedGraphList);
} else {
selectedGraphList.forEach(g -> {
if (!newSelectedGraphList.contains(g)) {
newSelectedGraphList.add(g);
} else if (isSelectionSingleClic) {
newSelectedGraphList.remove(g);
}
});
}
}
}
vImg.getGraphicManager().setSelectedGraphic(newSelectedGraphList);
}
if (ds.completeDrag(mouseEvt)) {
vImg.getEventManager().getAction(ActionW.DRAW_ONLY_ONCE, ToggleButtonListener.class)
.filter(ToggleButtonListener::isSelected).ifPresent(a -> {
vImg.getEventManager().getAction(ActionW.DRAW_MEASURE, ComboItemListener.class)
.ifPresent(c -> c.setSelectedItem(MeasureToolBar.selectionGraphic));
vImg.getEventManager().getAction(ActionW.DRAW_GRAPHICS, ComboItemListener.class)
.ifPresent(c -> c.setSelectedItem(MeasureToolBar.selectionGraphic));
});
ds = null;
}
// Throws to the tool listener the current graphic selection.
vImg.getGraphicManager().fireGraphicsSelectionChanged(vImg.getMeasurableLayer());
Cursor newCursor = DefaultView2d.DEFAULT_CURSOR;
// Evaluates if mouse is on a dragging position, and changes cursor image consequently
List<DragGraphic> selectedDragGraphList = vImg.getGraphicManager().getSelectedDragableGraphics();
Optional<Graphic> firstGraphicIntersecting = vImg.getGraphicManager().getFirstGraphicIntersecting(mouseEvt);
if (firstGraphicIntersecting.isPresent() && firstGraphicIntersecting.get() instanceof DragGraphic
&& !firstGraphicIntersecting.get().getLayer().getLocked()) {
DragGraphic dragGraph = (DragGraphic) firstGraphicIntersecting.get();
if (selectedDragGraphList.contains(dragGraph)) {
if (selectedDragGraphList.size() > 1) {
newCursor = DefaultView2d.MOVE_CURSOR;
} else if (selectedDragGraphList.size() == 1) {
if (dragGraph.isOnGraphicLabel(mouseEvt)) {
newCursor = DefaultView2d.HAND_CURSOR;
} else {
if (dragGraph.getHandlePointIndex(mouseEvt) >= 0) {
newCursor = DefaultView2d.EDIT_CURSOR;
} else {
newCursor = DefaultView2d.MOVE_CURSOR;
}
}
}
} else {
if (dragGraph.isOnGraphicLabel(mouseEvt)) {
newCursor = DefaultView2d.HAND_CURSOR;
} else {
newCursor = DefaultView2d.MOVE_CURSOR;
}
}
}
vImg.getJComponent().setCursor(Optional.ofNullable(newCursor).orElse(DefaultView2d.DEFAULT_CURSOR));
}
@Override
public void mouseDragged(MouseEvent e) {
int buttonMask = getButtonMaskEx();
// Check if extended modifier of mouse event equals the current buttonMask
// Also asserts that Mouse adapter is not disable
if (e.isConsumed() || (e.getModifiersEx() & buttonMask) == 0) {
return;
}
if (ds != null) {
// Convert mouse event point to real image coordinate point (without geometric transformation)
MouseEventDouble mouseEvt = new MouseEventDouble(e);
mouseEvt.setImageCoordinates(vImg.getImageCoordinatesFromMouse(e.getX(), e.getY()));
ds.drag(mouseEvt);
}
}
@Override
public void mouseMoved(MouseEvent e) {
if (e.isConsumed()) {
return;
}
// Convert mouse event point to real image coordinate point (without geometric transformation)
MouseEventDouble mouseEvt = new MouseEventDouble(e);
mouseEvt.setImageCoordinates(vImg.getImageCoordinatesFromMouse(e.getX(), e.getY()));
// Handle special case when drawing in mode [click > release > move/drag > release] instead of [click + drag >
// release]
if (ds instanceof DefaultDragSequence) {
ds.drag(mouseEvt);
} else {
Cursor newCursor = DefaultView2d.DEFAULT_CURSOR;
GraphicModel graphicList = vImg.getGraphicManager();
if (!mouseEvt.isShiftDown()) {
// Evaluates if mouse is on a dragging position, and changes cursor image consequently
Optional<Graphic> firstGraphicIntersecting = graphicList.getFirstGraphicIntersecting(mouseEvt);
if (firstGraphicIntersecting.isPresent() && firstGraphicIntersecting.get() instanceof DragGraphic
&& !firstGraphicIntersecting.get().getLayer().getLocked()) {
DragGraphic dragGraph = (DragGraphic) firstGraphicIntersecting.get();
List<DragGraphic> selectedDragGraphList = vImg.getGraphicManager().getSelectedDragableGraphics();
if (selectedDragGraphList.contains(dragGraph)) {
if (selectedDragGraphList.size() > 1) {
newCursor = DefaultView2d.MOVE_CURSOR;
} else if (selectedDragGraphList.size() == 1) {
if (dragGraph.isOnGraphicLabel(mouseEvt)) {
newCursor = DefaultView2d.HAND_CURSOR;
} else {
if (dragGraph.getHandlePointIndex(mouseEvt) >= 0) {
newCursor = DefaultView2d.EDIT_CURSOR;
} else {
newCursor = DefaultView2d.MOVE_CURSOR;
}
}
}
} else {
if (dragGraph.isOnGraphicLabel(mouseEvt)) {
newCursor = DefaultView2d.HAND_CURSOR;
} else {
newCursor = DefaultView2d.MOVE_CURSOR;
}
}
}
}
vImg.getJComponent().setCursor(Optional.ofNullable(newCursor).orElse(DefaultView2d.DEFAULT_CURSOR));
}
}
}