diff --git a/ui/src/main/java/edu/wpi/grip/ui/Main.java b/ui/src/main/java/edu/wpi/grip/ui/Main.java index 9d6ecc0581..39a9558fba 100644 --- a/ui/src/main/java/edu/wpi/grip/ui/Main.java +++ b/ui/src/main/java/edu/wpi/grip/ui/Main.java @@ -145,7 +145,11 @@ public void start(Stage stage) throws IOException { stage.setTitle(MAIN_TITLE); stage.getIcons().add(new Image("/edu/wpi/grip/ui/icons/grip.png")); - stage.setScene(new Scene(root)); + Scene scene = new Scene(root); + root.getStylesheets().clear(); + scene.getStylesheets().clear(); + root.getStylesheets().setAll("/edu/wpi/grip/ui/GRIP.css"); + stage.setScene(scene); notifyPreloader(new Preloader.ProgressNotification(1.0)); notifyPreloader(new Preloader.StateChangeNotification( Preloader.StateChangeNotification.Type.BEFORE_START)); @@ -167,6 +171,8 @@ public void start(Stage stage) throws IOException { } catch (GripServerException e) { logger.log(Level.SEVERE, "The HTTP server could not be started", e); Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "", ButtonType.YES, ButtonType.NO); + alert.initOwner(root.getScene().getWindow()); + alert.getDialogPane().getStylesheets().setAll(root.getStylesheets()); alert.setTitle("The HTTP server could not be started"); alert.setHeaderText("The HTTP server could not be started"); alert.setContentText( @@ -203,6 +209,7 @@ public final void onUnexpectedThrowableEvent(UnexpectedThrowableEvent event) { // Don't create more than one exception dialog at the same time final ExceptionAlert exceptionAlert = new ExceptionAlert(root, throwable, message, isFatal, getHostServices()); + exceptionAlert.initOwner(root.getScene().getWindow()); exceptionAlert.setInitialFocus(); exceptionAlert.showAndWait(); } catch (Throwable e) { diff --git a/ui/src/main/java/edu/wpi/grip/ui/MainWindowController.java b/ui/src/main/java/edu/wpi/grip/ui/MainWindowController.java index cdf5bbde6a..25630a71dd 100644 --- a/ui/src/main/java/edu/wpi/grip/ui/MainWindowController.java +++ b/ui/src/main/java/edu/wpi/grip/ui/MainWindowController.java @@ -141,6 +141,7 @@ private boolean showConfirmationDialogAndWait() { dialog.setTitle("Save Project?"); dialog.setHeaderText("Save the current project first?"); dialog.getDialogPane().getButtonTypes().setAll(save, dontSave, cancel); + dialog.initOwner(root.getScene().getWindow()); if (!dialog.showAndWait().isPresent()) { // NOPMD return false; @@ -186,7 +187,11 @@ public void openProject() { new ExtensionFilter("GRIP File", "*.grip"), new ExtensionFilter("All Files", "*", "*.*")); - project.getFile().ifPresent(file -> fileChooser.setInitialDirectory(file.getParentFile())); + if (project.getFile().isPresent()) { + fileChooser.setInitialDirectory(project.getFile().get().getParentFile()); + } else { + fileChooser.setInitialDirectory(new File(System.getProperty("user.home") + "/GRIP")); + } final File file = fileChooser.showOpenDialog(root.getScene().getWindow()); if (file != null) { @@ -250,6 +255,7 @@ protected void showProjectSettingsEditor() { ProjectSettingsEditor projectSettingsEditor = new ProjectSettingsEditor(root, projectSettings, appSettings); + projectSettingsEditor.initOwner(root.getScene().getWindow()); projectSettingsEditor.showAndWait().ifPresent(buttonType -> { if (buttonType == ButtonType.OK) { eventBus.post(new ProjectSettingsChangedEvent(projectSettings)); @@ -262,8 +268,11 @@ protected void showProjectSettingsEditor() { protected void showProjectAboutDialog() throws IOException { if (aboutDialogStage == null) { aboutDialogStage = new Stage(); - aboutDialogStage.setScene(new Scene(aboutPane)); - aboutDialogStage.initStyle(StageStyle.UTILITY); + Scene scene = new Scene(aboutPane); + scene.getStylesheets().setAll(root.getStylesheets()); + aboutDialogStage.setScene(scene); + aboutDialogStage.initStyle(StageStyle.UNDECORATED); + aboutDialogStage.initOwner(root.getScene().getWindow()); aboutDialogStage.focusedProperty().addListener((observable, oldvalue, newvalue) -> { if (oldvalue) { aboutDialogStage.hide(); @@ -323,6 +332,8 @@ protected void generate() { return; } Dialog optionsDialog = new CodeGenerationSettingsDialog(codegenPane); + optionsDialog.getDialogPane().getStylesheets().setAll(root.getStylesheets()); + optionsDialog.initOwner(root.getScene().getWindow()); optionsDialog.showAndWait().ifPresent(settings -> { eventBus.post(new CodeGenerationSettingsChangedEvent(settings)); Exporter exporter = new Exporter(pipeline.getSteps(), settings); @@ -361,6 +372,7 @@ protected void deploy() { Dialog dialog = new Dialog<>(); dialog.setTitle("Deploy"); dialog.setHeaderText("Deploy"); + dialog.initOwner(root.getScene().getWindow()); dialog.setGraphic(graphic); dialog.getDialogPane().getButtonTypes().setAll(ButtonType.CLOSE); dialog.getDialogPane().styleProperty().bind(root.styleProperty()); @@ -381,6 +393,8 @@ public void onWarningEvent(WarningEvent e) { private void showWarningAlert(WarningEvent e) { Alert alert = new WarningAlert(e.getHeader(), e.getBody(), root.getScene().getWindow()); + alert.getDialogPane().getStylesheets().setAll(root.getStylesheets()); + alert.initOwner(root.getScene().getWindow()); alert.showAndWait(); } @@ -405,6 +419,7 @@ private void showAnalysis() { if (analysisStage == null) { analysisStage = new Stage(); analysisStage.setScene(new Scene(analysisPane)); + analysisPane.getStylesheets().setAll(root.getStylesheets()); analysisStage.initOwner(root.getScene().getWindow()); analysisStage.setTitle("Pipeline Analysis"); analysisStage.getIcons().add(new Image("/edu/wpi/grip/ui/icons/grip.png")); diff --git a/ui/src/main/java/edu/wpi/grip/ui/ProjectSettingsEditor.java b/ui/src/main/java/edu/wpi/grip/ui/ProjectSettingsEditor.java index 9e099079db..8f55e0a2d5 100644 --- a/ui/src/main/java/edu/wpi/grip/ui/ProjectSettingsEditor.java +++ b/ui/src/main/java/edu/wpi/grip/ui/ProjectSettingsEditor.java @@ -8,6 +8,7 @@ import org.controlsfx.property.BeanPropertyUtils; import javafx.collections.ObservableList; +import javafx.geometry.Insets; import javafx.scene.Parent; import javafx.scene.control.ButtonType; import javafx.scene.control.Dialog; @@ -43,6 +44,7 @@ public ProjectSettingsEditor(Parent root, new CustomPropertySheet(BeanPropertyUtils.getProperties(appSettings)) ); content.setSpacing(5.0); + content.setPadding(Insets.EMPTY); DialogPane pane = getDialogPane(); pane.getButtonTypes().setAll(ButtonType.OK, ButtonType.CANCEL); diff --git a/ui/src/main/java/edu/wpi/grip/ui/analysis/AnalysisController.java b/ui/src/main/java/edu/wpi/grip/ui/analysis/AnalysisController.java index 64b3e3f529..0639cc4fe4 100644 --- a/ui/src/main/java/edu/wpi/grip/ui/analysis/AnalysisController.java +++ b/ui/src/main/java/edu/wpi/grip/ui/analysis/AnalysisController.java @@ -42,6 +42,7 @@ import javafx.scene.control.TextArea; import javafx.scene.control.TextField; import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; import javafx.util.Callback; import javax.annotation.Nullable; @@ -49,8 +50,12 @@ /** * Controller for the analysis view. */ +@SuppressWarnings("PMD.TooManyFields") public class AnalysisController { + @FXML + private Pane root; + // Table @FXML private TableView table; @@ -191,6 +196,8 @@ private void exportCsv() { // Show benchmarking results Platform.runLater(() -> { Alert a = new Alert(Alert.AlertType.INFORMATION); + a.initOwner(root.getScene().getWindow()); + a.getDialogPane().getStylesheets().setAll(root.getStylesheets()); a.setHeaderText("Benchmarking results"); TextArea resultArea = new TextArea(csvReport); a.getDialogPane().setContent(resultArea); @@ -204,7 +211,6 @@ private void exportCsv() { * * @param m the map to stream * @param the type of the values in the map - * * @return a stream of the entries in the map, sorted by their key's index. */ private Stream> sortedStream(Map m) { diff --git a/ui/src/main/java/edu/wpi/grip/ui/pipeline/AddSourceButton.java b/ui/src/main/java/edu/wpi/grip/ui/pipeline/AddSourceButton.java index 9f6321638a..d212350298 100644 --- a/ui/src/main/java/edu/wpi/grip/ui/pipeline/AddSourceButton.java +++ b/ui/src/main/java/edu/wpi/grip/ui/pipeline/AddSourceButton.java @@ -84,6 +84,8 @@ public class AddSourceButton extends MenuButton { super("Add Source"); this.eventBus = eventBus; + getStyleClass().add("add-source-button"); + addMenuItem("Image(s)", getClass().getResource("/edu/wpi/grip/ui/icons/add-image.png"), mouseEvent -> { // Show a file picker so the user can open one or more images from disk @@ -392,6 +394,8 @@ private class SourceDialog extends Dialog { private SourceDialog(final Parent root, Node customField) { super(); + initOwner(root.getScene().getWindow()); + setOnShowing(event -> activeDialog = Optional.of(this)); setOnHidden(event -> activeDialog = Optional.empty()); diff --git a/ui/src/main/java/edu/wpi/grip/ui/util/DPIUtility.java b/ui/src/main/java/edu/wpi/grip/ui/util/DPIUtility.java index 037024a60e..fd85d1a55f 100644 --- a/ui/src/main/java/edu/wpi/grip/ui/util/DPIUtility.java +++ b/ui/src/main/java/edu/wpi/grip/ui/util/DPIUtility.java @@ -17,7 +17,7 @@ public class DPIUtility { public static final double SMALL_ICON_SIZE = 16.0 * (isManualHiDPI() ? HIDPI_SCALE : 1.0); public static final double LARGE_ICON_SIZE = 48.0 * (isManualHiDPI() ? HIDPI_SCALE : 1.0); public static final double STROKE_WIDTH = 2.0 * (isManualHiDPI() ? HIDPI_SCALE : 1.0); - public static final double SETTINGS_DIALOG_SIZE = 400.0 * (isManualHiDPI() ? HIDPI_SCALE : 1.0); + public static final double SETTINGS_DIALOG_SIZE = 425.0 * (isManualHiDPI() ? HIDPI_SCALE : 1.0); private static boolean isManualHiDPI() { // We need to do manual size adjustments for HiDPI on Linux. JavaFX automatically does this diff --git a/ui/src/main/resources/edu/wpi/grip/ui/AboutDialog.fxml b/ui/src/main/resources/edu/wpi/grip/ui/AboutDialog.fxml index 6db1c035d2..7b88e9c59f 100644 --- a/ui/src/main/resources/edu/wpi/grip/ui/AboutDialog.fxml +++ b/ui/src/main/resources/edu/wpi/grip/ui/AboutDialog.fxml @@ -10,7 +10,7 @@ - + @@ -43,9 +43,6 @@ - - - @@ -59,9 +56,6 @@ - - - @@ -86,7 +80,4 @@ - - - diff --git a/ui/src/main/resources/edu/wpi/grip/ui/GRIP.css b/ui/src/main/resources/edu/wpi/grip/ui/GRIP.css index 9af9fee96a..22d4181499 100644 --- a/ui/src/main/resources/edu/wpi/grip/ui/GRIP.css +++ b/ui/src/main/resources/edu/wpi/grip/ui/GRIP.css @@ -1,5 +1,15 @@ +@import "base.css"; + .root { -fx-font-family: "Roboto"; + + -swatch-100: hsb(180, 25%, 98%); + -swatch-200: hsb(180, 25%, 88%); + -swatch-300: hsb(180, 25%, 78%); + -swatch-400: hsb(180, 25%, 68%); + -swatch-500: hsb(180, 25%, 58%); + + -fx-mark-color: -swatch-400; } .main-window { @@ -13,30 +23,37 @@ } .pane-title { - -fx-background-color: -fx-control-inner-background; -fx-font-weight: bold; -fx-padding: 1.0em; -fx-border-width: 1px; + -fx-background-color: white; } .palette { -fx-min-width: 30em; } +.operation-list { + -fx-spacing: 0.5em; + -fx-padding: 0.5em; + -fx-background-color: #ddd; +} + .operation { -fx-cursor: hand; -fx-hgap: 1em; -fx-padding: 0.5em; -fx-alignment: center-left; - -fx-color: -fx-background; + -fx-color: white; -fx-background-color: -fx-color; + -fx-effect: dropshadow(gaussian, #aaa, 4, 0.1, 0, 2); } .operation:hover { - -fx-color: white; + -fx-color: #eee; } .operation:pressed { - -fx-color: -fx-pressed-base; + -fx-color: #d7d7d7; } Label.operation-name { @@ -62,14 +79,45 @@ Label.operation-description { -fx-pref-width: 40em; } +.previews > .scroll-pane { + -fx-padding: 0; +} + +.previews > .scroll-pane > .viewport { + -fx-background-color: #eee; + -fx-effect: innershadow(gaussian, #aaa, 8, 0.125, 2, 2); +} + .previews HBox { -fx-spacing: 1em; -fx-padding: 0.5em; } +.socket-preview { + -fx-effect: dropshadow(gaussian, #aaa, 16, 0.125, 0, 4); + -fx-background-color: white; + -fx-border-color: transparent; + -fx-padding: 0; +} + +.split-pane .split-pane-divider { + -fx-padding: 1pt; + -fx-background-color: white; +} + .socket-preview .title { -fx-font-weight: bold; -fx-padding: 0.5em; + -fx-background-color: transparent; +} + +.socket-preview > .content { + -fx-border-color: none; + -fx-padding: 0; +} + +.sources-pane { + -fx-background-color: white; } .addSource { @@ -81,6 +129,30 @@ Label.operation-description { -fx-max-width: Infinity; } +.add-source-button { + -fx-background-color: transparent; + -fx-border-color: -swatch-gray; + -fx-border-width: 0 0 2 0; + -fx-background-radius: 0; + -fx-border-radius: 0; +} + +.add-source-button:focused { + -fx-border-color: -swatch-500; +} + +.add-source-button > .arrow-button { + -fx-background-radius: 0.0 2.0 2.0 0.0; +} + +.add-source-button > .arrow-button > .arrow { + -fx-background-color: -swatch-200; +} + +.add-source-button:hover > .arrow-button > .arrow { + -fx-background-color: -swatch-400; +} + .sources { -fx-padding: 0.5em; -fx-spacing: 1em; @@ -91,7 +163,8 @@ Label.operation-description { -fx-spacing: 1em; -fx-border-width: 1px; -fx-border-color: -fx-box-border; - -fx-background-color: -fx-background; + -fx-background-color: white; + -fx-effect: dropshadow(gaussian, #aaa, 6, 0.125, 0, 4); } Label.source-name { @@ -103,6 +176,10 @@ Button.add-source { -fx-padding: 0.5em; } +.pipeline > .bottom { + -fx-background-color: hsb(0, 0%, 97%); +} + .steps { -fx-spacing: 1em; -fx-padding: 0.5em; @@ -111,11 +188,42 @@ Button.add-source { .step { -fx-pref-width: 15em; -fx-border-color: -fx-box-border; - -fx-background-color: -fx-background; + -fx-background-color: white; + -fx-effect: dropshadow(gaussian, #aaa, 6, 0.125, 0, 4); -fx-padding: 1.0em; -fx-spacing: 0.5em; } +.step .controls .button, +.source .source-header-box .button, +.source .source-header-box .toggle-button, +.small-icon-button { + -fx-background-color: transparent; + -fx-border-color: white; + -fx-effect: none; +} + +.step .controls .button:hover, +.source .source-header-box .button:hover, +.source .source-header-box .toggle-button:hover, +.small-icon-button:hover { + -fx-background-color: #eee; + -fx-border-color: -fx-box-border; +} + +.step .controls .button:pressed, +.source .button:pressed, +.source .source-header-box .toggle-button:selected, +.small-icon-button:selected, +.step .controls .button:pressed:focused, +.source .button:pressed:focused, +.source .source-header-box .toggle-button:selected:focused, +.small-icon-button:focused:selected { + -fx-background-color: #d7d7d7; + -fx-border-color: -fx-box-border; + -fx-effect: innershadow(gaussian, #777, 4, 0.25, 0, 0); +} + Button.delete, Button.move-left, Button.move-right, .start-stoppable-button, .exception-witness-responder-button { -fx-padding: 0.2em 0.8em; -fx-pref-height: 2em; @@ -151,6 +259,9 @@ VBox.sockets { -fx-max-width: 1em; -fx-max-height: 1em; -fx-cursor: hand; + -fx-border-width: 0; + -fx-background-color: -swatch-light-gray; + -fx-effect: innershadow(gaussian, -swatch-500, 2, 0.06, 1, 1); } .socket-handle:connecting { @@ -165,7 +276,8 @@ VBox.sockets { } .socket-handle:connected { - -fx-background-color: -fx-shadow-highlight-color, -fx-outer-border, -fx-inner-border, -fx-mark-color; + -fx-background-color: -fx-mark-color !important; + -fx-effect: innershadow(gaussian, -swatch-dark-gray, 2, 0.125, 1, 1); } .socket-handle:connected:focused { @@ -210,7 +322,6 @@ VBox.sockets { .property-sheet .property-pane { -fx-hgap: 4em; -fx-vgap: 1em; - -fx-padding: 0; } .exception-pane { @@ -251,13 +362,12 @@ VBox.sockets { .about-window Label { -fx-font-size: 14; } +.about-button { + -fx-padding: 3 3 3 3; +} .about-button:hover { - -fx-background-color: gray; + -fx-background-color: -swatch-light-gray; -fx-background-radius: 12; -fx-cursor: hand; } - -.about-button:hover Label { - -fx-text-fill: white; -} diff --git a/ui/src/main/resources/edu/wpi/grip/ui/MainWindow.fxml b/ui/src/main/resources/edu/wpi/grip/ui/MainWindow.fxml index 5e29d16b48..bb48160a7d 100644 --- a/ui/src/main/resources/edu/wpi/grip/ui/MainWindow.fxml +++ b/ui/src/main/resources/edu/wpi/grip/ui/MainWindow.fxml @@ -21,7 +21,8 @@ + fx:id="root" xmlns:fx="http://javafx.com/fxml/1" + stylesheets="/edu/wpi/grip/ui/GRIP.css"> @@ -215,8 +216,5 @@ - - - diff --git a/ui/src/main/resources/edu/wpi/grip/ui/OperationList.fxml b/ui/src/main/resources/edu/wpi/grip/ui/OperationList.fxml index 73d0806700..75d453837e 100644 --- a/ui/src/main/resources/edu/wpi/grip/ui/OperationList.fxml +++ b/ui/src/main/resources/edu/wpi/grip/ui/OperationList.fxml @@ -9,6 +9,6 @@ closable="false"> - + diff --git a/ui/src/main/resources/edu/wpi/grip/ui/analysis/Analysis.fxml b/ui/src/main/resources/edu/wpi/grip/ui/analysis/Analysis.fxml index 2508435d83..f86bdbdaeb 100644 --- a/ui/src/main/resources/edu/wpi/grip/ui/analysis/Analysis.fxml +++ b/ui/src/main/resources/edu/wpi/grip/ui/analysis/Analysis.fxml @@ -9,7 +9,7 @@ - + diff --git a/ui/src/main/resources/edu/wpi/grip/ui/base.css b/ui/src/main/resources/edu/wpi/grip/ui/base.css new file mode 100644 index 0000000000..b1069ffa87 --- /dev/null +++ b/ui/src/main/resources/edu/wpi/grip/ui/base.css @@ -0,0 +1,221 @@ +/******************************************************************************* + * * + * Base CSS for all themes. * + * This sets the styles for some app-specific types that are consistent * + * through all themes (like the tile highlight) or use CSS variables to make * + * them easy to reskin. * + ******************************************************************************/ +@import "material.css"; + +/******************************************************************************* + * * + * Root * + * * + ******************************************************************************/ +.root { + -fx-font-family: "Roboto"; +} + +/******************************************************************************* + * * + * Widget pane * + * * + ******************************************************************************/ +.widget-pane { + -fx-grid-line-color: -swatch-light-gray; +} + +/******************************************************************************* + * * + * Tab Pane * + * * + ******************************************************************************/ +.tab-pane { + -fx-border-color: white; + -fx-border-width: 0.025em; + -fx-open-tab-animation: NONE; + -fx-close-tab-animation: NONE; +} + +.tab-header-area .tab:selected .focus-indicator { + -fx-border-color: transparent; +} + +.tab-container { + /* Rotate the tab container to put the close button on the left-hand side */ + -fx-rotate: 180; +} + +.tab-container > * { + /* Re-rotate the contents to keep the text right-side up */ + -fx-rotate: 180; +} + +/******************************************************************************* + * * + * Tabs * + * * + ******************************************************************************/ + +.tab-header-area { + -fx-padding: 0; + -fx-background-color: white; +} + +.tab { + -fx-background-color: white; + -fx-align: center; + -fx-padding: 4; + -fx-border-radius: 0; + -fx-background-radius: 0; +} + +.tab .tab-close-button { + -fx-padding: 0 0 0 10px; +} + +.tab:hover { + -fx-cursor: hand; +} + +/******************************************************************************* + * * + * Property sheet * + * * + ******************************************************************************/ +.property-sheet .property-pane * { + -fx-font-size: 10pt; +} + +/******************************************************************************* + * * + * Slider, range slider * + * * + ******************************************************************************/ +.slider .track, .range-slider .track { + -fx-background-color: -swatch-gray; + -fx-background-insets: 1.5; +} + +.range-slider { + -fx-cursor: default; +} + +.range-slider:pressed .low-thumb, +.range-slider:pressed .high-thumb, +.range-slider:pressed .range-bar { + -fx-cursor: move; +} + +.range-slider .range-bar { + -fx-background-color: -swatch-500; + -fx-background-insets: 0.5; +} + +.range-slider .low-thumb, +.range-slider .high-thumb { + -fx-background-color: -swatch-500; + -fx-cursor: hand; +} + +.slider { + -fx-cursor: default; +} + +.slider .thumb { + -fx-cursor: hand; +} + +.slider:pressed .thumb { + -fx-cursor: move; +} + +.jfx-slider { + -jfx-default-thumb: -swatch-300; + -jfx-default-track: -swatch-gray; +} + +.jfx-slider .track { + -fx-pref-height: 4px; +} + +/******************************************************************************* + * * + * Dialog pane * + * * + ******************************************************************************/ +.dialog-pane .header-panel { + -fx-background-color: -swatch-500; +} + +.dialog-pane .header-panel .label { + -fx-text-fill: white; +} + +/******************************************************************************* + * * + * Settings dialogs * + * * + ******************************************************************************/ +.settings-pane { + -fx-border-width: 0 0 2px 0; + -fx-border-color: derive(-swatch-light-gray, 12%); +} + +.settings-pane > .split-pane-divider { + -fx-padding: 0 1 0 1; + -fx-background-color: -swatch-light-gray; + -fx-background-insets: 0; +} + +.settings-pane .settings-categories { + -fx-background-color: transparent; +} + +.settings-pane .settings-categories .tree-cell { + -fx-background-color: transparent; +} + +.settings-pane .settings-categories:focused .tree-cell:selected { + -fx-background-color: -swatch-100; + -fx-text-fill: -fx-text-base-color; +} + +.settings-pane .settings-categories .tree-cell:selected { + -fx-background-color: -swatch-500; + -fx-text-fill: -fx-text-base-color; +} + +.settings-pane .settings-categories .tree-cell > .tree-disclosure-node > .arrow { + -fx-background-color: -fx-text-base-color; +} + +/******************************************************************************* + * * + * Segmented Button * + * * + ******************************************************************************/ +.segmented-button { + -fx-border-width: 1; + -fx-border-color: -swatch-300; +} + +.segmented-button .toggle-button { + -fx-effect: none; +} + +.segmented-button .toggle-button:selected { + -fx-background-color: -swatch-500; +} + +.segmented-button .toggle-button.left-pill { + -fx-background-radius: 4 0 0 4; +} + +.segmented-button .toggle-button.right-pill { + -fx-background-radius: 0 4 4 0; +} + +.segmented-button .toggle-button.only-button { + -fx-background-radius: 4 4 4 4; +} diff --git a/ui/src/main/resources/edu/wpi/grip/ui/material.css b/ui/src/main/resources/edu/wpi/grip/ui/material.css new file mode 100644 index 0000000000..0550b0a128 --- /dev/null +++ b/ui/src/main/resources/edu/wpi/grip/ui/material.css @@ -0,0 +1,764 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 - AGIX | Innovative Engineering + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +/* + * This is a Material Design CSS for JavaFX + */ + +/******************************************************************************* + * * + * Root * + * * + ******************************************************************************/ +.root { + -fx-font-family: ""; + /* Swatch Colors - Blue*/ + -swatch-100: #BBDEFB; + -swatch-200: #90CAF9; + -swatch-300: #64BEF6; + -swatch-400: #42A5F5; + -swatch-500: #2196F3; + /*default text */ + -fx-text-base-color: rgb(100.0, 100.0, 100.0); + -fx-text-button-normal: -swatch-500; + -fx-text-button-colored: rgb(255.0, 255.0, 255.0); + -fx-text-button-text: rgb(100.0, 100.0, 100.0); + -fx-text-title-color: rgb(45.0, 45.0, 45.0); + -fx-text-subtitle-color: rgb(65.0, 65.0, 65.0); + -fx-text-control-title-color: rgb(130.0, 130.0, 130.0); + -fx-text-fill: -fx-text-base-color; + -dark: rgb(47.0, 52.0, 57.0); + -fx-disabled-opacity: 60%; + /*default colors */ + -swatch-gray: rgb(200.0, 200.0, 200.0); + -swatch-dark-gray: rgb(150.0, 150.0, 150.0); + -swatch-light-gray: rgb(230.0, 230.0, 230.0); + -swatch-toolbar: rgb(245.0, 245.0, 245.0); + -swatch-toolbar-selected: rgb(215.0, 215.0, 215.0); + /* + Modena colors + */ + -fx-dark-text-color: white; /* Text color when selected*/ + -fx-mid-text-color: -fx-text-base-color; + -fx-light-text-color: -swatch-light-gray; + -fx-body-color: white; + /* A bright blue for the focus indicator of objects. Typically used as the + * first color in -fx-background-color for the "focused" pseudo-class. Also + * typically used with insets of -1.4 to provide a glowing effect. + */ + -fx-focus-color: -swatch-400; + -fx-faint-focus-color: -swatch-200; + /* A bright blue for highlighting/accenting objects. For example: selected + * text; selected items in menus, lists, trees, and tables; progress bars */ + -fx-accent: -swatch-400; + -confirmation-color-confirmed: lightgreen; + -confirmation-color-warning: yellow; + -confirmation-color-error: darkred; +} + +/******************************************************************************* + * * + * Material Design - Cards * + * * + ******************************************************************************/ +.card { + -fx-background-color: rgb(255.0, 255.0, 255.0); + -fx-background-radius: 4.0; + -fx-effect: dropshadow(gaussian, rgba(0.0, 0.0, 0.0, 0.15), 6.0, 0.7, 0.0, 1.5); +} + +.card-title .text { + -fx-fill: -fx-text-title-color; +} + +.card-subtitle .text { + -fx-fill: -fx-text-subtitle-color; +} + +.control-label .text { + -fx-fill: -fx-text-control-title-color; +} + +.card-button { + -fx-effect: null; +} + +/******************************************************************************* + * * + * Button & ToggleButton * + * * + ******************************************************************************/ +.button-raised { + -fx-effect: dropshadow(gaussian, rgba(0.0, 0.0, 0.0, 0.30), 6.0, 0.3, 0, 1); + -fx-background-color: rgb(250, 250, 250); +} + +.button-flat { + -fx-effect: null; + -fx-background-color: transparent; +} + +.toggle-button, .button { + -fx-text-fill: -fx-text-button-normal; + -fx-font-weight: bold; + -fx-background-insets: 0.0; + -fx-background-radius: 0.0; + -fx-alignment: CENTER; + -fx-background-color: rgba(250, 250, 250); + -fx-effect: dropshadow(gaussian, rgba(0.0, 0.0, 0.0, 0.30), 6.0, 0.3, 0, 2); +} + +.toggle-button:selected, .button:selected { + -fx-background-color: -swatch-500; + -fx-text-fill: white; +} + +.button-raised .button .text, .button-flat .button .text { + -fx-text-weight: Bold; +} + +.button:default { + -fx-background-color: -swatch-500; + -fx-text-fill: white; +} + +.toggle-button:focused, .button:focused, .button:default:focused { + -fx-background-color: rgb(240, 240, 240); + -fx-text-fill: -swatch-500; +} + +.toggle-button:focused:selected { + -fx-background-color: derive(-swatch-500, -12%); + -fx-text-fill: white; +} + +.toggle-button:armed, .toggle-button:selected, .button:armed, .button:default:armed { + -fx-background-color: -swatch-500; + -fx-text-fill: white; +} + +.icon-button { + -fx-background-color: transparent; + -fx-padding: 0; +} + +.icon-button .text { + -fx-font-family: 'MaterialDesignIconicFont'; +} + +/******************************************************************************* + * * + * ComboBox, ChoiceBox COMMON * + * * + ******************************************************************************/ +.combo-box-base, .choice-box { + -fx-background-color: transparent; + -fx-border-color: -swatch-gray; + -fx-border-width: 0 0 2 0; + -fx-background-radius: 0; + -fx-border-radius: 0; +} + +.combo-box:focused, .choice-box:focused { + -fx-border-color: -swatch-500; +} + +.combo-box-base > .arrow-button, .choice-box > .open-button { + -fx-background-radius: 0.0 2.0 2.0 0.0; +} + +.combo-box-base > .arrow-button > .arrow, .choice-box > .open-button > .arrow { + -fx-background-color: -swatch-200; +} + +.combo-box-base .arrow-button:hover .arrow, .spinner .increment-arrow-button:hover .increment-arrow, +.spinner .decrement-arrow-button:hover .decrement-arrow { + -fx-background-color: -swatch-400; +} + +.menu-item:focused { + -fx-background-color: -swatch-light-gray; +} + +/******************************************************************************* + * * + * CheckBox * + * * + ******************************************************************************/ +.check-box .text { + -fx-fill: -fx-text-base-color; +} + +.check-box > .box, .check-box > .box.unfocused, .check-box:disabled > .box, +.check-box:indeterminate > .box { + -fx-border-radius: 4.0; + -fx-border-color: -swatch-gray; + -fx-border-width: 2; + -fx-background-radius: 4; + -fx-background-color: transparent; +} + +.check-box:selected > .box { + -fx-border-color: -swatch-500; + -fx-background-color: -swatch-500; +} + +.check-box:focused > .box { + -fx-effect: dropshadow(gaussian, rgba(0.0, 0.0, 0.0, 0.30), 6.0, 0.3, 0, 0); +} + +.check-box:selected > .box > .mark { + -fx-background-color: white; +} + +.check-box:indeterminate > .box > .mark { + -fx-background-color: -swatch-gray; +} + +/******************************************************************************* + * * + * ChoiceBox * + * * + ******************************************************************************/ +.context-menu { + -fx-background-color: rgba(255.0, 255.0, 255.0, 0.95); +} + +.radio-menu-item:checked .label, .check-menu-item:checked .label { + -fx-text-fill: -swatch-500; +} + +.radio-menu-item:checked > .left-container > .radio, .check-menu-item:checked > .left-container > .check { + -fx-background-color: -swatch-dark-gray; + -fx-effect: dropshadow(gaussian, rgba(0.0, 0.0, 0.0, 0.2), 0.0, 0.0, 0.0, 1.0); +} + +.radio-menu-item > .left-container > .radio, .check-menu-item > .left-container > .check { + -fx-background-color: transparent; +} + +/******************************************************************************* + * * + * ComboBox * + * * + ******************************************************************************/ +.popup-overlay { + -fx-background-color: white; + -fx-border-color: -swatch-gray; + -fx-border-width: 0 0 2 0; + -fx-background-radius: 0; + -fx-border-radius: 0; +} + +.title-bar .icon { + -fx-alignment: center-left; + -fx-effect: dropshadow(gaussian, rgba(0.0, 0.0, 0.0, 0.2), 0.0, 0.0, 0.0, 1.0); +} + +.title-bar .title-label { + -fx-alignment: center; + -fx-font-weight: bolder; +} + +.content-area { + -fx-background-color: -dark; +} + +.content-background { + -fx-background-color: white; + -fx-background-radius: 0.0 0.0 11.0 11.0; +} + +/******************************************************************************* + * * + * Date Picker * + * * + ******************************************************************************/ +.date-picker-popup .button { + -fx-background-color: -swatch-500; +} + +.date-picker-popup > .month-year-pane { + -fx-background-color: -swatch-500; +} + +.date-picker-popup > * > .spinner > .button > .left-arrow, .date-picker-popup > * > .spinner > .button > .right-arrow { + -fx-background-color: white; +} + +.date-picker-popup > * > .spinner { + -fx-border-width: 0; +} + +.date-picker-popup > * > .spinner > .label { + -fx-text-fill: white; + -fx-font-weight: bold; +} + +.date-picker-popup > * > .day-name-cell, .date-picker-popup > * > .week-number-cell { + -fx-font-weight: normal; + -fx-text-fill: -swatch-dark-gray; +} + +/******************************************************************************* + * * + * Date picker * + * * + ******************************************************************************/ +.date-picker .arrow-button { + -fx-background-color: transparent; +} + +.date-picker .arrow-button .arrow { + -fx-background-insets: -4; +} + +.date-picker .date-picker-display-node { + -fx-border-width: 0; +} + +/******************************************************************************* + * * + * HTML Editor * + * * + ******************************************************************************/ +.html-editor { + -fx-background-color: white; + -fx-border-width: 2 0 2 0; + -fx-border-color: -swatch-gray; +} + +.html-editor .web-view { + -fx-border-color: gray; + -fx-border-width: gray; +} + +.web-view { + -fx-font-smoothing-type: gray; +} + +/******************************************************************************* + * * + * Label * + * * + ******************************************************************************/ +.label { + -fx-text-fill: -fx-text-base-color; +} + +.label:disabled { + -fx-opacity: -fx-disabled-opacity; +} + +.label:show-mnemonics > .mnemonic-underline { + -fx-stroke: -fx-text-base-color; +} + +/******************************************************************************* + * * + * List, Tree, Table COMMON * + * * + ******************************************************************************/ +.list-view:focused .list-cell:filled:focused:selected { + -fx-background-color: -swatch-300; + -fx-text-fill: -fx-text-base-color; +} + +.list-view:hover .list-cell:filled:hover { + -fx-background-color: -swatch-light-gray; + -fx-text-fill: -fx-text-base-color; +} + +.list-view .list-cell:filled:selected { + -fx-background-color: -swatch-200; +} + +.list-view { + -fx-background-color: transparent; +} + +.list-view .list-cell { + -fx-background-color: derive(-fx-base, 26.4%); +} + +/******************************************************************************* + * * + * ProgressBar * + * * + ******************************************************************************/ +.progress-bar > .track { + -fx-background-color: derive(-swatch-gray, 50.0%); + -fx-background-radius: 2.0; + -fx-padding: 0.0; +} + +.progress-bar > .bar { + -fx-background-color: -swatch-500; + -fx-background-radius: 2.0; + -fx-background-insets: 0.0; + -fx-border-width: 0.0; + -fx-effect: null; +} + +.progress-bar:indeterminate > .bar { + -fx-background-color: derive(-swatch-500, 50.0%); + -fx-background-radius: 2.0; + -fx-background-insets: 0.0; + -fx-border-width: 0.0; + -fx-effect: null; +} + +/******************************************************************************* + * * + * ProgressIndicator * + * * + ******************************************************************************/ +.progress-indicator > .spinner { + -fx-border-width: 0; +} + +.progress-indicator > .determinate-indicator > .indicator { + -fx-background-color: rgba(255.0, 255.0, 255.0, 0.5); + -fx-padding: 0.0; +} + +.progress-indicator > .determinate-indicator > .progress { + -fx-background-color: -swatch-500; +} + +.progress-indicator > .determinate-indicator > .percentage { + -fx-fill: -fx-text-base-color; + -fx-translate-y: 0em; + -fx-padding: 0.0; +} + +/******************************************************************************* + * * + * RadioButton * + * * + ******************************************************************************/ +.radio-button .text { + -fx-fill: -fx-text-base-color; +} + +.radio-button > .radio, .radio-button > .radio.unfocused, .radio-button:disabled > .radio, +.radio-button:selected > .radio { + -fx-border-radius: 100.0; + -fx-border-color: -swatch-gray; + -fx-border-width: 2; + -fx-background-radius: 100; + -fx-background-color: transparent; +} + +.radio-button:focused > .radio { + -fx-background-color: -swatch-100; +} + +.radio-button:focused:armed > .radio { + -fx-background-color: -swatch-100; +} + +.radio-button:selected > .radio > .dot { + -fx-background-color: -swatch-500; + -fx-background-insets: 0; +} + +/******************************************************************************* + * * + * Separators * + * * + ******************************************************************************/ +.separator { +} + +/******************************************************************************* + * * + * Split panes * + * * + ******************************************************************************/ +.split-pane { +} + +.split-pane > .split-pane-divider { + -fx-background-color: -swatch-light-gray; +} + +/******************************************************************************* + * * + * Scroll Bar * + * * + ******************************************************************************/ +.scroll-bar:vertical > .track-background, .scroll-bar:horizontal > .track-background { + -fx-background-color: -swatch-light-gray; + -fx-background-insets: 0.0; +} + +.scroll-bar:vertical > .thumb, .scroll-bar:horizontal > .thumb { + -fx-background-color: -swatch-gray; + -fx-background-insets: 0.0; + -fx-background-radius: 4.0; +} + +.scroll-bar > .increment-button, .scroll-bar > .decrement-button, +.scroll-bar:hover > .increment-button, .scroll-bar:hover > .decrement-button { + -fx-background-color: transparent; +} + +.scroll-bar > .increment-button > .increment-arrow, .scroll-bar > .decrement-button > .decrement-arrow { + -fx-background-color: -swatch-dark-gray; +} + +.scroll-bar > .track-background { + -fx-background-color: transparent; +} + +/******************************************************************************* + * * + * Slider * + * * + ******************************************************************************/ + +.slider > .track { + -fx-background-color: -swatch-gray; + -fx-background-insets: 1.5; +} + +.slider > .thumb { + -fx-background-color: -swatch-500; +} + +/******************************************************************************* + * * + * Spinner * + * * + ******************************************************************************/ +.spinner { + -fx-background-color: transparent; + -fx-border-width: 0 0 2 0; + -fx-border-color: -swatch-gray; +} + +.spinner:focused { + -fx-border-color: -swatch-500; +} + +.spinner .text-field { + -fx-background-color: transparent; + -fx-background-radius: 0; + -fx-border-width: 0; + -fx-prompt-text-fill: derive(-dark, 50.0%); + -fx-highlight-fill: rgb(94.0, 203.0, 234.0); +} + +.spinner .increment-arrow-button, .spinner .decrement-arrow-button { + -fx-background-color: transparent; + -fx-fill: swatch-500; +} + +.spinner .increment-arrow-button .increment-arrow, .spinner .decrement-arrow-button .decrement-arrow { + -fx-background-color: -swatch-gray; +} + +.spinner .increment-arrow-button, .spinner .decrement-arrow-button { + -fx-background-color: transparent; + -fx-fill: swatch-500; +} + +/******************************************************************************* + * * + * Tables * + * * + ******************************************************************************/ +.table-view, .tree-table-view { + /* Constants used throughout the tableview. */ + -fx-table-header-border-color: transparent; + -fx-table-cell-border-color: -fx-box-border; /* Horizontal Lines*/ + -fx-background-color: transparent; +} + +/* The column header row is made up of a number of column-header, one for each + TableColumn, and a 'filler' area that extends from the right-most column + to the edge of the tableview, or up to the 'column control' button. */ +.table-view .filler, .tree-table-view .filler, .table-view .column-header, +.tree-table-view .column-header { + -fx-border-style: null; + -fx-border-color: -swatch-gray; + -fx-border-width: 0 0 2 0; + -fx-background-color: transparent; +} + +.table-view .show-hide-columns-button, .tree-table-view .show-hide-columns-button { + -fx-background-color: transparent; +} + +.table-view .column-header .label, .table-view .filler .label, +.table-view .column-drag-header .label, .tree-table-view .column-header .label, +.tree-table-view .filler .label, .tree-table-view .column-drag-header .label { + -fx-alignment: CENTER_LEFT; +} + +.table-view .column-header-background, .tree-table-view .column-header-background { + -fx-background-color: transparent; +} + +.table-cell { + -fx-border-color: transparent; /* Vertical Lines*/ + -fx-border-width: 1; +} + +/******************************************************************************* + * * + * Text, Text field & Text area * + * * + ******************************************************************************/ +.text { + -fx-font-smoothing-type: gray; +} + +.text-area, .text-field { + -underline-color: -swatch-gray; + -fx-background-color: transparent; + -fx-background-radius: 2.0; + -fx-border-color: -underline-color; + -fx-border-width: 0 0 2 0; + -fx-prompt-text-fill: derive(-dark, 50.0%); + -fx-highlight-fill: rgb(94.0, 203.0, 234.0); +} + +.text-area .text, .text-field > * > .text { + -fx-effect: null; + -fx-fill: -dark; +} + +.text-area .content { + -fx-border-width: 0.0; + -fx-background-color: transparent; +} + +.text-area:focused .content { + -fx-background-color: transparent; +} + +.text-area:focused, .text-field:focused { + -fx-border-color: -swatch-500; +} + +/******************************************************************************* + * * + * Tool bar & Menu bar * + * * + ******************************************************************************/ +.tool-bar, .menu-bar { /* top */ + -fx-background-color: -swatch-toolbar; + -fx-border-width: 0 0 2 0; + -fx-border-color: -swatch-gray; + -fx-alignment: CENTER_LEFT; +} + +.tool-bar .combo-box-base, .menu-bar .combo-base { + -fx-border-width: 0; +} + +.tool-bar .button, .tool-bar .toggle-button { + -fx-background-color: -swatch-toolbar; + -fx-text-fill: -fx-text-base-color; + -fx-padding: 0; + -fx-background-radius: 0; +} + +.tool-bar .button:pressed, .tool-bar .toggle-button:pressed, .tool-bar .toggle-button:selected { + -fx-background-color: -swatch-gray; +} + +.tool-bar .toggle-button { + -fx-background-color: -swatch-toolbar; +} + +.toolbar-colored { + -fx-background-color: -swatch-500; + -fx-border-width: 0 0 2 0; + -fx-border-color: -swatch-gray; +} + +.toolbar-colored .button, .toolbar-colored .toggle-button { + -fx-background-color: -swatch-500; + -fx-text-fill: white; +} + +.toolbar-colored .button:pressed, .toolbar-colored .toggle-button:pressed, +.toolbar-colored .toggle-button:selected { + -fx-background-color: -swatch-200; +} + +.toolbar-colored .text { + -fx-fill: white; +} + +/******************************************************************************* + * * + * Tabs * + * * + ******************************************************************************/ +.tab-pane { + -fx-border-color: black; +} + +.tab-header-background { + -fx-background-color: white; +} + +.tab { + -fx-background-color: transparent, white, -swatch-dark-gray; +} + +.tab:selected { + -fx-background-color: transparent; +} + +.tab .tab-close-button { + -fx-background-color: white; +} + +.tab .tab-label { + -fx-text-fill: white; +} + +.tab .tab-label { + /* + * Set a border to the same color as the background to keep the label text in the same position + * when the tab is selected. + */ + -fx-border-width: 0 0 0.125em 0; + -fx-border-color: white; +} + +.tab .tab-label { + -fx-text-fill: #333; +} + +.tab:selected .tab-label { + -fx-text-fill: black; + -fx-border-color: -fx-text-fill; +} diff --git a/ui/src/main/resources/edu/wpi/grip/ui/pipeline/OutputSocket.fxml b/ui/src/main/resources/edu/wpi/grip/ui/pipeline/OutputSocket.fxml index 314d85e6cb..ae411a3358 100644 --- a/ui/src/main/resources/edu/wpi/grip/ui/pipeline/OutputSocket.fxml +++ b/ui/src/main/resources/edu/wpi/grip/ui/pipeline/OutputSocket.fxml @@ -9,7 +9,7 @@ diff --git a/ui/src/main/resources/edu/wpi/grip/ui/pipeline/Pipeline.fxml b/ui/src/main/resources/edu/wpi/grip/ui/pipeline/Pipeline.fxml index 87377d1b3b..b299b0e4d6 100644 --- a/ui/src/main/resources/edu/wpi/grip/ui/pipeline/Pipeline.fxml +++ b/ui/src/main/resources/edu/wpi/grip/ui/pipeline/Pipeline.fxml @@ -1,6 +1,5 @@ - @@ -10,14 +9,8 @@ - - - - - - - - + +