package org.codemap.layers;
import static org.codemap.layers.CodemapVisualization.mapValues;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collection;
import org.codemap.CodemapCore;
import org.codemap.Location;
import org.codemap.MapInstance;
import org.codemap.MapSelection;
import org.codemap.internal.DEMAlgorithm;
import org.codemap.mapview.MapSelectionProvider;
import org.codemap.resources.MapValues;
import org.codemap.util.EclipseUtil;
import org.codemap.util.Resources;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DragDetectEvent;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.GC;
import ch.akuhn.util.List;
import ch.akuhn.values.Value;
public class CurrentSelectionOverlay extends SelectionOverlay {
protected final int POINT_STROKE = 2;
public static final String EVT_DOUBLE_CLICKED = "doubleClicked";
public static final String EVT_SELECTION_CHANGED = "selectionChanged";
private boolean isDragging = false;
private Point dragStart;
private Point dragStop;
@Override
public void dragDetected(DragDetectEvent e) {
isDragging = true;
dragStop = dragStart = new Point(e.x, e.y);
}
@Override
public void mouseDoubleClick(MouseEvent e) {
MapInstance map = CodemapVisualization.mapValues(e).mapInstance.getValue();
if (map == null) return;
Location neighbor = map.nearestNeighbor(e.x, e.y);
if (neighbor == null) return;
IResource resource = Resources.asResource(neighbor.getDocument());
if (!(resource instanceof IFile))
return;
EclipseUtil.openInEditor((IFile) resource);
}
@Override
public void mouseMove(MouseEvent e) {
if (!isDragging) return;
dragStop = new Point(e.x, e.y);
this.redraw(e);
}
@Override
public void mouseUp(MouseEvent e) {
if (isDragging) {
isDragging = false;
updateSelection(mapValues(e));
}
else if (e.count == 1) {
handleSingleClick(e);
}
this.redraw(e);
selectionChanged(getSelection(mapValues(e)));
}
public void selectionChanged(MapSelection mapSelection) {
final ArrayList<IJavaElement> selection = new ArrayList<IJavaElement>();
for (String each : mapSelection) {
IJavaElement javaElement = Resources.asJavaElement(each);
selection.add(javaElement);
}
StructuredSelection structuredSelection = new StructuredSelection(selection);
MapSelectionProvider selectionProvider = CodemapCore.getPlugin().getController().getSelectionProvider();
selectionProvider.setSelection(structuredSelection);
}
private void handleSingleClick(MouseEvent e) {
// only update selection for clicks with primary mouse button
if (e.button != 1) return;
Value<MapInstance> mapInstance = mapValues(e).mapInstance;
Location neighbor = mapInstance.getValueOrFail().nearestNeighbor(e.x, e.y);
if (neighbor == null) return;
if ((e.stateMask & SWT.SHIFT) != 0 || (e.stateMask & SWT.CTRL) != 0) {
handleMultipleSelect(neighbor, getSelection(mapValues(e)));
}
else {
handleSingleSelect(neighbor, getSelection(mapValues(e)));
}
}
private void handleMultipleSelect(Location neighbor, MapSelection mapSelection) {
mapSelection.add(neighbor.getDocument());
}
private void handleSingleSelect(Location neighbor, MapSelection mapSelection) {
mapSelection.replaceAll(List.of(neighbor.getDocument()));
}
@Override
public void paintBefore(MapValues map, GC gc) {
gc.setLineWidth(POINT_STROKE);
if (isDragging) {
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_LIST_SELECTION));
updateSelection(map);
int deltaX = dragStop.x - dragStart.x;
int deltaY = dragStop.y - dragStart.y;
gc.drawRectangle(dragStart.x, dragStart.y, deltaX, deltaY);
}
}
@Override
public void paintChild(MapValues map, GC gc, Location each) {
Device device = gc.getDevice();
int mapSize = map.mapSize.getValue();
int magic_r = (int) (each.getElevation() * 2 * mapSize / DEMAlgorithm.MAGIC_VALUE);
gc.setAlpha(128);
gc.setBackground(device.getSystemColor(SWT.COLOR_LIST_SELECTION));
gc.fillOval(each.px - magic_r, each.py - magic_r, magic_r * 2, magic_r * 2);
gc.setAlpha(255);
gc.setForeground(device.getSystemColor(SWT.COLOR_WHITE));
gc.drawOval(each.px-magic_r, each.py-magic_r, magic_r*2, magic_r*2);
}
private void updateSelection(MapValues map) {
MapInstance mapInstance = map.mapInstance.getValue();
if (mapInstance == null) return;
int minX = Math.min(dragStart.x, dragStop.x);
int minY = Math.min(dragStart.y, dragStop.y);
int maxX = Math.max(dragStart.x, dragStop.x);
int maxY = Math.max(dragStart.y, dragStop.y);
Collection<String> ids = new ArrayList<String>();
for (Location each : mapInstance.locations()) {
if (each.px < maxX && each.px > minX && each.py < maxY && each.py > minY) {
ids.add(each.getDocument());
}
}
getSelection(map).replaceAll(ids);
}
@Override
public MapSelection getSelection(MapValues map) {
return map.currentSelection;
}
@Override
public void keyReleased(KeyEvent e) {
if (!(e.keyCode == SWT.ESC)) return;
MapSelection selection = getSelection(CodemapCore.getPlugin().getActiveMap().getValues());
selection.clear();
selectionChanged(selection);
}
}