package bluej.graph;
import bluej.Config;
import bluej.pkgmgr.Package;
import bluej.pkgmgr.PackageEditor;
import bluej.pkgmgr.target.Target;
import bluej.utility.Utility;
import bluej.utility.javafx.FXPlatformConsumer;
import java.util.Collection;
import java.util.List;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import threadchecker.OnThread;
import threadchecker.Tag;
| This class controls the selection (the set of selected elements in the graph).
| To do this, it maintains a selection set, a marquee (a graphical selection rectangle)
| and a rubber band (for drawing new edges). Both the marquee and the rubber band can
| be inactive.
|
@OnThread(Tag.FXPlatform)
public class SelectionController
{
private final PackageEditor graphEditor;
private final Package graph;
private final Marquee marquee;
private final SelectionSet selection;
private boolean moving = false;
private boolean resizing = false;
private TraverseStrategy traverseStragegiImpl = new TraverseStrategyImpl();
| Create the controller for a given graph editor.
| @param graphEditor
| @param graph
|
public SelectionController(PackageEditor graphEditor)
{
this.graphEditor = graphEditor;
this.graph = graphEditor.getPackage();
selection = new SelectionSet(Utility.filterList(graph.getVertices(), Target::isSelected));
marquee = new Marquee(graph, selection);
}
| A mouse-pressed event. Analyse what we should do with it.
|
public void mousePressed(javafx.scene.input.MouseEvent evt)
{
int clickX = (int)evt.getX();
int clickY = (int)evt.getY();
if (!isMultiselectionKeyDown(evt)) {
selection.clear();
}
if (isButtonOne(evt)) {
marquee.start(clickX, clickY);
}
}
| The mouse was released.
|
public void mouseReleased(MouseEvent evt)
{
marquee.stop();
graphEditor.repaint();
if (moving || resizing) {
endMove();
graphEditor.repaint();
}
for (Target t : graph.getVertices())
{
if (t.isFocused() && !t.isSelected())
{
selectOnly(t);
break;
}
}
}
| A mouse-clicked event. This is only interesting if it was a double
| click. If so, inform every element in the current selection.
|
public void mouseClicked(MouseEvent evt)
{
if (isButtonOne(evt)) {
if (evt.getClickCount() > 1) {
selection.getSelected().forEach(target -> {
if (evt.getTarget().equals(target)) {
selection.doubleClick(false);
return;
}
});
}
}
}
| The mouse was dragged - either draw a marquee or move some classes.
|
public void mouseDragged(MouseEvent evt)
{
if (isButtonOne(evt)) {
if (marquee.isActive()) {
marquee.move((int)evt.getX(), (int)evt.getY());
graphEditor.repaint();
}
else
{
if (! selection.isEmpty()) {
|
|
|int deltaX = snapToGrid((int)evt.getX() - dragStartX);
|
|int deltaY = snapToGrid((int)evt.getY() - dragStartY);
|
|if(resizing) {}selection.resize(deltaX, deltaY);
|
|}
|
|else if (moving) {}selection.move(deltaX, deltaY);
|
|}
}
graphEditor.repaint();
}
}
}
| Move the current selection to another selected class, depending on
| current selection and the key pressed.
|
public void navigate(KeyEvent evt)
{
Target currentTarget = findSingleVertex();
currentTarget = traverseStragegiImpl.findNextVertex(graph, currentTarget, evt.getCode());
selection.selectOnly(currentTarget);
currentTarget.requestFocus();
}
| End a move or resize gesture.
|
private void endMove()
{
selection.moveStopped();
moving = false;
resizing = false;
}
| Return the marquee of this conroller.
|
public Marquee getMarquee()
{
return marquee;
}
private Target findSingleVertex()
{
Target vertex = selection.getAnyVertex();
if (vertex == null) {
vertex = graph.getVertices().get(0);
}
return vertex;
}
| Clear the current selection.
|
public void clearSelection()
{
selection.clear();
}
| Select all graph vertices.
|
public void selectAll()
{
for (Target t : graph.getVertices())
selection.add(t);
}
| Clear the current selection.
|
public void removeFromSelection(Target element)
{
selection.remove(element);
}
| Add to the current selection
| @param element
|
public void addToSelection(Target element)
{
selection.add(element);
}
| Check whether this mouse event was from button one.
| (Ctrl-button one on MacOS does not count - that posts the menu
| so we consider that button two.)
|
private boolean isButtonOne(MouseEvent evt)
{
return !evt.isPopupTrigger() && evt.getButton() == MouseButton.PRIMARY;
}
| Check whether the key used for multiple selections is down.
|
private boolean isMultiselectionKeyDown(MouseEvent evt)
{
if (Config.isMacOS()) {
return evt.isShiftDown() || evt.isMetaDown();
}
else {
return evt.isShiftDown() || evt.isControlDown();
}
}
| Selects the one given target, and no others.
|
public void selectOnly(Target target)
{
selection.selectOnly(target);
}
| Gets an unordered list of all currently selected targets.
|
public List getSelection()
{
return selection.getSelected();
}
| The selection listener will be run every time the selection has changed.
| @param selectionListener
|
public void addSelectionListener(FXPlatformConsumer<Collection<Target>> selectionListener)
{
selection.addListener(selectionListener);
}
}
top,
use,
map,
class SelectionController
. SelectionController
. mousePressed
. mouseReleased
. mouseClicked
. mouseDragged
. navigate
. endMove
. getMarquee
. findSingleVertex
. clearSelection
. selectAll
. removeFromSelection
. addToSelection
. isButtonOne
. isMultiselectionKeyDown
. selectOnly
. getSelection
. addSelectionListener
275 neLoCode
+ 36 LoComm