Skip to content

Commit

Permalink
Declaration alignment FIX (#137)
Browse files Browse the repository at this point in the history
* Declaration resizing and alignment fixed for both single and split canvas (and minor refactoring)

* Zoom keyboard shortcuts on split canvas FIXED

* NullPointerException when opening existing project FIXED

* WIP: Exceptions are thrown on project open and split canvas

* WIP: Exceptions FIXED (Refactoring might be needed before merge)

* Review suggestions

* Dangling engines FIX (#140)

* WIP: Potential fix for dangling engines by keeping track of started connections in one place and removing this responsibility from the QueryHandler

* Method rename to better follow new logic

* Add started backend connections immediately and use them to find used ports

---------

Co-authored-by: Sebastian Lund <[email protected]>

* Declaration resizing and alignment fixed for both single and split canvas (and minor refactoring)

* Zoom keyboard shortcuts on split canvas FIXED

* NullPointerException when opening existing project FIXED

* WIP: Exceptions are thrown on project open and split canvas

* WIP: Exceptions FIXED (Refactoring might be needed before merge)

* Review suggestions

---------

Co-authored-by: Sebastian Lund <[email protected]>
  • Loading branch information
Nielswps and seblund authored Mar 2, 2023
1 parent 66c5fd4 commit 052b620
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 116 deletions.
12 changes: 6 additions & 6 deletions src/main/java/ecdar/Ecdar.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class Ecdar extends Application {
private static EcdarPresentation presentation;
private static BooleanProperty isUICached = new SimpleBooleanProperty();
public static BooleanProperty shouldRunBackgroundQueries = new SimpleBooleanProperty(true);
private static final BooleanProperty isSplit = new SimpleBooleanProperty(true); //Set to true to ensure correct behaviour at first toggle.
private static final BooleanProperty isSplit = new SimpleBooleanProperty(false);
private static BackendDriver backendDriver = new BackendDriver();
private static QueryHandler queryHandler = new QueryHandler(backendDriver);
private Stage debugStage;
Expand Down Expand Up @@ -168,15 +168,15 @@ public static BooleanProperty toggleQueryPane() {
return presentation.toggleQueryPane();
}

public static BooleanProperty isSplitProperty() {
return isSplit;
}

/**
* Toggles whether to canvas is split or single.
*
* @return the property specifying whether the canvas is split
*/
public static BooleanProperty toggleCanvasSplit() {
public static void toggleCanvasSplit() {
isSplit.set(!isSplit.get());

return isSplit;
}

/**
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/ecdar/controllers/CanvasController.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,18 @@ private void onActiveModelChanged(final HighLevelModelPresentation oldObject, fi
modelPane.getChildren().add(activeComponentPresentation);

// To avoid NullPointerException on initial model
if (oldObject != null) zoomHelper.resetZoom();
Platform.runLater(zoomHelper::resetZoom);

} else if (newObject instanceof DeclarationsPresentation) {
activeComponentPresentation = null;
modelPane.getChildren().add(newObject);

// Bind size of Declaration to size of the model pane to ensure alignment and avoid drag
DeclarationsController declarationsController = (DeclarationsController) newObject.getController();
declarationsController.root.minWidthProperty().bind(modelPane.minWidthProperty());
declarationsController.root.maxWidthProperty().bind(modelPane.maxWidthProperty());
declarationsController.root.minHeightProperty().bind(modelPane.minHeightProperty());
declarationsController.root.maxHeightProperty().bind(modelPane.maxHeightProperty());
} else if (newObject instanceof SystemPresentation) {
activeComponentPresentation = null;
modelPane.getChildren().add(newObject);
Expand Down
16 changes: 1 addition & 15 deletions src/main/java/ecdar/controllers/DeclarationsController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package ecdar.controllers;

import ecdar.Ecdar;
import ecdar.abstractions.Declarations;
import ecdar.abstractions.HighLevelModel;
import ecdar.utility.helpers.UPPAALSyntaxHighlighter;
Expand All @@ -19,9 +18,9 @@
* Controller for overall declarations.
*/
public class DeclarationsController extends HighLevelModelController implements Initializable {
public StyleClassedTextArea textArea;
public StackPane root;
public BorderPane frame;
public StyleClassedTextArea textArea;

private final ObjectProperty<Declarations> declarations;

Expand All @@ -35,22 +34,9 @@ public void setDeclarations(final Declarations declarations) {

@Override
public void initialize(final URL location, final ResourceBundle resources) {
initializeWidthAndHeight();
initializeText();
}

/**
* Initializes width and height of the text editor field, such that it fills up the whole canvas
*/
private void initializeWidthAndHeight() {
// Fetch width and height of canvas and update
root.minWidthProperty().bind(Ecdar.getPresentation().getController().canvasPane.minWidthProperty());
root.maxWidthProperty().bind(Ecdar.getPresentation().getController().canvasPane.maxWidthProperty());
root.minHeightProperty().bind(Ecdar.getPresentation().getController().canvasPane.minHeightProperty());
root.maxHeightProperty().bind(Ecdar.getPresentation().getController().canvasPane.maxHeightProperty());
textArea.setTranslateY(20);
}

/**
* Sets up the linenumbers and binds the text in the text area to the declaration object
*/
Expand Down
80 changes: 60 additions & 20 deletions src/main/java/ecdar/controllers/EcdarController.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import ecdar.utility.colors.Color;
import ecdar.utility.colors.EnabledColor;
import ecdar.utility.helpers.SelectHelper;
import ecdar.utility.helpers.ZoomHelper;
import ecdar.utility.keyboard.Keybind;
import ecdar.utility.keyboard.KeyboardTracker;
import ecdar.utility.keyboard.NudgeDirection;
Expand Down Expand Up @@ -522,10 +523,21 @@ public static void setActiveCanvasPresentation(CanvasPresentation newActiveCanva
activeCanvasPresentation.get().setOpacity(0.75);
newActiveCanvasPresentation.setOpacity(1);
activeCanvasPresentation.set(newActiveCanvasPresentation);
rebindZoomShortcutBindings(newActiveCanvasPresentation.getController().zoomHelper);
}

/**
* Binds the zoom shortcuts to the provided zoom helper (consequently unbinds the previously bound zoom helper)
*/
private static void rebindZoomShortcutBindings(ZoomHelper zoomHelper) {
KeyboardTracker.registerKeybind(KeyboardTracker.ZOOM_IN, new Keybind(new KeyCodeCombination(KeyCode.PLUS, KeyCombination.SHORTCUT_DOWN), zoomHelper::zoomIn));
KeyboardTracker.registerKeybind(KeyboardTracker.ZOOM_OUT, new Keybind(new KeyCodeCombination(KeyCode.MINUS, KeyCombination.SHORTCUT_DOWN), zoomHelper::zoomOut));
KeyboardTracker.registerKeybind(KeyboardTracker.ZOOM_TO_FIT, new Keybind(new KeyCodeCombination(KeyCode.EQUALS, KeyCombination.SHORTCUT_DOWN), zoomHelper::zoomToFit));
KeyboardTracker.registerKeybind(KeyboardTracker.RESET_ZOOM, new Keybind(new KeyCodeCombination(KeyCode.DIGIT0, KeyCombination.SHORTCUT_DOWN), zoomHelper::resetZoom));
}

public void setActiveModelPresentationForActiveCanvas(HighLevelModelPresentation newActiveModelPresentation) {
projectPane.getController().changeOneActiveModelPresentationForAnother(EcdarController.getActiveCanvasPresentation().getController().getActiveModelPresentation(), newActiveModelPresentation);
projectPane.getController().swapHighlightBetweenTwoModelFiles(EcdarController.getActiveCanvasPresentation().getController().getActiveModelPresentation(), newActiveModelPresentation);
EcdarController.getActiveCanvasPresentation().getController().setActiveModelPresentation(newActiveModelPresentation);
}

Expand Down Expand Up @@ -642,13 +654,14 @@ private void initializeViewMenu() {

menuBarViewCanvasSplit.getGraphic().setOpacity(1);
menuBarViewCanvasSplit.setOnAction(event -> {
final BooleanProperty isSplit = Ecdar.toggleCanvasSplit();
if (isSplit.get()) {
Platform.runLater(this::setCanvasModeToSingular);
menuBarViewCanvasSplit.setText("Split canvas");
} else {
Ecdar.toggleCanvasSplit();
});

Ecdar.isSplitProperty().addListener((observable, oldValue, newValue) -> {
if (newValue) {
Platform.runLater(this::setCanvasModeToSplit);
menuBarViewCanvasSplit.setText("Merge canvases");
} else {
Platform.runLater(this::setCanvasModeToSingular);
}
});

Expand Down Expand Up @@ -709,8 +722,7 @@ private void initializeOpenProjectMenuItem() {
final File file = projectPicker.showDialog(root.getScene().getWindow());
if (file != null) {
try {
Ecdar.projectDirectory.set(file.getAbsolutePath());
Ecdar.initializeProjectFolder();
setProjectDirectory(file.getAbsolutePath());
UndoRedoStack.clear();
addProjectToRecentProjects(file.getAbsolutePath());
} catch (final IOException e) {
Expand All @@ -730,8 +742,7 @@ private void initializeRecentProjectsMenu() {

item.setOnAction(event -> {
try {
Ecdar.projectDirectory.set(path);
Ecdar.initializeProjectFolder();
setProjectDirectory(path);
} catch (IOException ex) {
Ecdar.showToast("Unable to load project: \"" + path + "\"");
}
Expand All @@ -757,6 +768,12 @@ private void initializeRecentProjectsMenu() {
menuBarFileRecentProjects.getItems().add(item);
}

private static void setProjectDirectory(String path) throws IOException {
Ecdar.projectDirectory.set(path);
Ecdar.initializeProjectFolder();
Ecdar.isSplitProperty().set(false);
}

/**
* Saves the project to the {@link Ecdar#projectDirectory} path.
* This include making directories, converting project files (components and queries)
Expand Down Expand Up @@ -887,9 +904,11 @@ private void createNewProject() {

CodeAnalysis.clearErrorsAndWarnings();

Ecdar.projectDirectory.set(null);

projectPane.getController().resetProject();
try {
setProjectDirectory(null);
} catch (IOException ex) {
Ecdar.showToast("Unable to initialize new project directory");
}

UndoRedoStack.clear();

Expand Down Expand Up @@ -974,7 +993,9 @@ private void setCanvasModeToSingular() {
canvasPresentation.getController().zoomablePane.minHeightProperty().bind(canvasPane.heightProperty());
canvasPresentation.getController().zoomablePane.maxHeightProperty().bind(canvasPane.heightProperty());

projectPane.getController().setActiveModelPresentations(canvasPresentation.getController().getActiveModelPresentation());
projectPane.getController().setHighlightedForModelFiles(getActiveModelPresentations());

menuBarViewCanvasSplit.setText("Split canvas");
}

/**
Expand Down Expand Up @@ -1039,13 +1060,32 @@ private void setCanvasModeToSplit() {
canvasGrid.add(canvasPresentation, 1, 1);

canvasPane.getChildren().add(canvasGrid);
projectPane.getController().setActiveModelPresentations(getActiveModelPresentations(canvasGrid));
projectPane.getController().setHighlightedForModelFiles(getActiveModelPresentations());

menuBarViewCanvasSplit.setText("Merge canvases");
}

private static List<HighLevelModelPresentation> getActiveModelPresentations(GridPane canvasGrid) {
return canvasGrid.getChildren()
.stream().map(canvas -> ((CanvasPresentation) canvas)
.getController().getActiveModelPresentation()).collect(Collectors.toList());
/**
* Get list of shown HighLevelModelPresentations
*
* @return a list of all the HighLevelModelPresentations currently being shown
*/
private List<HighLevelModelPresentation> getActiveModelPresentations() {
Pane canvasChild = (Pane) canvasPane.getChildren().get(0);

if (canvasChild instanceof GridPane) {
return canvasChild.getChildren()
.stream().map(canvas -> ((CanvasPresentation) canvas)
.getController().getActiveModelPresentation()).filter(Objects::nonNull).collect(Collectors.toList());
} else if (canvasChild instanceof CanvasPresentation) {
return new ArrayList<>() {
{
((CanvasPresentation) canvasChild).getController().getActiveModelPresentation();
}
};
}

return new ArrayList<>();
}

/**
Expand Down
48 changes: 20 additions & 28 deletions src/main/java/ecdar/controllers/ProjectPaneController.java
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,26 @@ private HashSet<String> getSystemNames() {
return names;
}

public ObservableList<ComponentPresentation> getComponentPresentations() {
return componentPresentations;
}

public void setHighlightedForModelFiles(List<HighLevelModelPresentation> currentlyActiveModelPresentations) {
modelPresentationMap.values().forEach(fp -> fp.getController().setIsActive(false));

for (HighLevelModelPresentation modelPresentation : currentlyActiveModelPresentations) {
if (modelPresentationMap.containsKey(modelPresentation)) modelPresentationMap.get(modelPresentation).getController().setIsActive(true);
}
}

public void swapHighlightBetweenTwoModelFiles(final HighLevelModelPresentation oldActive, final HighLevelModelPresentation newActive) {
if (modelPresentationMap.containsKey(oldActive)) modelPresentationMap.get(oldActive)
.getController()
.setIsActive(false);

if (modelPresentationMap.containsKey(newActive)) modelPresentationMap.get(newActive).getController().setIsActive(true); // newActive is not in the map when opening an existing project
}

/**
* Method for creating a new component
*/
Expand Down Expand Up @@ -494,32 +514,4 @@ private void setGeneratedComponentsVisibilityButtonClicked() {
this.tempFilesList.setManaged(false);
}
}

public ObservableList<ComponentPresentation> getComponentPresentations() {
return componentPresentations;
}

public void setActiveModelPresentations(HighLevelModelPresentation activeModelPresentation) {
Platform.runLater(() -> {
modelPresentationMap.values().forEach(fp -> fp.getController().setIsActive(false));
modelPresentationMap.get(activeModelPresentation).getController().setIsActive(true);
});
}

public void setActiveModelPresentations(List<HighLevelModelPresentation> currentlyActiveModelPresentations) {
Platform.runLater(() -> {
modelPresentationMap.values().forEach(fp -> fp.getController().setIsActive(false));

for (HighLevelModelPresentation modelPresentation : currentlyActiveModelPresentations) {
modelPresentationMap.get(modelPresentation).getController().setIsActive(true);
}
});
}

public void changeOneActiveModelPresentationForAnother(final HighLevelModelPresentation oldActive, final HighLevelModelPresentation newActive) {
if (modelPresentationMap.get(oldActive) != null) modelPresentationMap.get(oldActive)
.getController()
.setIsActive(false);
modelPresentationMap.get(newActive).getController().setIsActive(true);
}
}
4 changes: 0 additions & 4 deletions src/main/java/ecdar/presentations/EcdarPresentation.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,6 @@ public EcdarPresentation() {
});

initializeHelpImages();
KeyboardTracker.registerKeybind(KeyboardTracker.ZOOM_IN, new Keybind(new KeyCodeCombination(KeyCode.PLUS, KeyCombination.SHORTCUT_DOWN), () -> EcdarController.getActiveCanvasPresentation().getController().zoomHelper.zoomIn()));
KeyboardTracker.registerKeybind(KeyboardTracker.ZOOM_OUT, new Keybind(new KeyCodeCombination(KeyCode.MINUS, KeyCombination.SHORTCUT_DOWN), () -> EcdarController.getActiveCanvasPresentation().getController().zoomHelper.zoomOut()));
KeyboardTracker.registerKeybind(KeyboardTracker.ZOOM_TO_FIT, new Keybind(new KeyCodeCombination(KeyCode.EQUALS, KeyCombination.SHORTCUT_DOWN), () -> EcdarController.getActiveCanvasPresentation().getController().zoomHelper.zoomToFit()));
KeyboardTracker.registerKeybind(KeyboardTracker.RESET_ZOOM, new Keybind(new KeyCodeCombination(KeyCode.DIGIT0, KeyCombination.SHORTCUT_DOWN), () -> EcdarController.getActiveCanvasPresentation().getController().zoomHelper.resetZoom()));
KeyboardTracker.registerKeybind(KeyboardTracker.UNDO, new Keybind(new KeyCodeCombination(KeyCode.Z, KeyCombination.SHORTCUT_DOWN), UndoRedoStack::undo));
KeyboardTracker.registerKeybind(KeyboardTracker.REDO, new Keybind(new KeyCodeCombination(KeyCode.Z, KeyCombination.SHORTCUT_DOWN, KeyCombination.SHIFT_DOWN), UndoRedoStack::redo));

Expand Down
Loading

0 comments on commit 052b620

Please sign in to comment.