Kaynağa Gözat

allow resizing main window on all four corners
fixes #995

Sebastian Stenzel 5 yıl önce
ebeveyn
işleme
35d0ccfe89

+ 2 - 9
main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java

@@ -7,8 +7,7 @@ import javafx.fxml.FXML;
 import javafx.scene.input.DragEvent;
 import javafx.scene.input.TransferMode;
 import javafx.scene.layout.HBox;
-import javafx.scene.layout.Region;
-import javafx.scene.layout.VBox;
+import javafx.scene.layout.StackPane;
 import javafx.stage.Stage;
 import org.cryptomator.common.LicenseHolder;
 import org.cryptomator.common.vaults.VaultListManager;
@@ -46,8 +45,7 @@ public class MainWindowController implements FxController {
 	private final BooleanProperty draggingOver = new SimpleBooleanProperty();
 	private final BooleanProperty draggingVaultOver = new SimpleBooleanProperty();
 	public HBox titleBar;
-	public VBox root;
-	public Region resizer;
+	public StackPane root;
 	private double xOffset;
 	private double yOffset;
 
@@ -74,11 +72,6 @@ public class MainWindowController implements FxController {
 			window.setX(event.getScreenX() - xOffset);
 			window.setY(event.getScreenY() - yOffset);
 		});
-		resizer.setOnMouseDragged(event -> {
-			// we know for a fact that window is borderless. i.e. the scene starts at 0/0 of the window.
-			window.setWidth(event.getSceneX());
-			window.setHeight(event.getSceneY());
-		});
 		updateChecker.automaticallyCheckForUpdatesIfEnabled();
 		root.setOnDragEntered(this::handleDragEvent);
 		root.setOnDragOver(this::handleDragEvent);

+ 5 - 0
main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java

@@ -68,6 +68,11 @@ abstract class MainWindowModule {
 	@FxControllerKey(MainWindowController.class)
 	abstract FxController bindMainWindowController(MainWindowController controller);
 
+	@Binds
+	@IntoMap
+	@FxControllerKey(ResizeController.class)
+	abstract FxController bindResizeController(ResizeController controller);
+
 	@Binds
 	@IntoMap
 	@FxControllerKey(VaultListController.class)

+ 102 - 0
main/ui/src/main/java/org/cryptomator/ui/mainwindow/ResizeController.java

@@ -0,0 +1,102 @@
+package org.cryptomator.ui.mainwindow;
+
+import javafx.fxml.FXML;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.Region;
+import javafx.stage.Stage;
+import org.cryptomator.ui.common.FxController;
+
+import javax.inject.Inject;
+
+@MainWindow
+public class ResizeController implements FxController {
+
+	private final Stage window;
+
+	public Region tlResizer;
+	public Region trResizer;
+	public Region blResizer;
+	public Region brResizer;
+
+	private double origX, origY, origW, origH;
+
+	@Inject
+	ResizeController(@MainWindow Stage window) {
+		this.window = window;
+		// TODO inject settings and save current position and size
+	}
+
+	@FXML
+	public void initialize() {
+		tlResizer.setOnMousePressed(this::startResize);
+		trResizer.setOnMousePressed(this::startResize);
+		blResizer.setOnMousePressed(this::startResize);
+		brResizer.setOnMousePressed(this::startResize);
+		tlResizer.setOnMouseDragged(this::resizeTopLeft);
+		trResizer.setOnMouseDragged(this::resizeTopRight);
+		blResizer.setOnMouseDragged(this::resizeBottomLeft);
+		brResizer.setOnMouseDragged(this::resizeBottomRight);
+	}
+
+	private void startResize(MouseEvent evt) {
+		origX = window.getX();
+		origY = window.getY();
+		origW = window.getWidth();
+		origH = window.getHeight();
+	}
+
+	private void resizeTopLeft(MouseEvent evt) {
+		resizeTop(evt);
+		resizeLeft(evt);
+	}
+
+	private void resizeTopRight(MouseEvent evt) {
+		resizeTop(evt);
+		resizeRight(evt);
+	}
+
+	private void resizeBottomLeft(MouseEvent evt) {
+		resizeBottom(evt);
+		resizeLeft(evt);
+	}
+
+	private void resizeBottomRight(MouseEvent evt) {
+		resizeBottom(evt);
+		resizeRight(evt);
+	}
+
+	private void resizeTop(MouseEvent evt) {
+		double newY = evt.getScreenY();
+		double dy = newY - origY;
+		double newH = origH - dy;
+		if (newH < window.getMaxHeight() && newH > window.getMinHeight()) {
+			window.setY(newY);
+			window.setHeight(newH);
+		}
+	}
+
+	private void resizeLeft(MouseEvent evt) {
+		double newX = evt.getScreenX();
+		double dx = newX - origX;
+		double newW = origW - dx;
+		if (newW < window.getMaxWidth() && newW > window.getMinWidth()) {
+			window.setX(newX);
+			window.setWidth(newW);
+		}
+	}
+
+	private void resizeBottom(MouseEvent evt) {
+		double newH = evt.getSceneY();
+		if (newH < window.getMaxHeight() && newH > window.getMinHeight()) {
+			window.setHeight(newH);
+		}
+	}
+
+	private void resizeRight(MouseEvent evt) {
+		double newW = evt.getSceneX();
+		if (newW < window.getMaxWidth() && newW > window.getMinWidth()) {
+			window.setWidth(newW);
+		}
+	}
+
+}

+ 0 - 14
main/ui/src/main/resources/css/dark_theme.css

@@ -184,20 +184,6 @@
 	-fx-fill: CONTROL_WHITE_BG_ARMED;
 }
 
-.main-window .resizer {
-	-fx-background-color: linear-gradient(to bottom right,
-		transparent 50%,
-		CONTROL_BORDER_NORMAL 51%,
-		CONTROL_BORDER_NORMAL 60%,
-		transparent 61%,
-		transparent 70%,
-		CONTROL_BORDER_NORMAL 71%,
-		CONTROL_BORDER_NORMAL 80%,
-		transparent 81%
-	);
-	-fx-cursor: nw_resize;
-}
-
 .main-window .update-indicator {
 	-fx-background-color: PRIMARY_BG, white, INDICATOR_BG;
 	-fx-background-insets: 0, 1px, 2px;

+ 0 - 14
main/ui/src/main/resources/css/light_theme.css

@@ -184,20 +184,6 @@
 	-fx-fill: CONTROL_WHITE_BG_ARMED;
 }
 
-.main-window .resizer {
-	-fx-background-color: linear-gradient(to bottom right,
-		transparent 50%,
-		CONTROL_BORDER_NORMAL 51%,
-		CONTROL_BORDER_NORMAL 60%,
-		transparent 61%,
-		transparent 70%,
-		CONTROL_BORDER_NORMAL 71%,
-		CONTROL_BORDER_NORMAL 80%,
-		transparent 81%
-	);
-	-fx-cursor: nw_resize;
-}
-
 .main-window .update-indicator {
 	-fx-background-color: PRIMARY_BG, white, INDICATOR_BG;
 	-fx-background-insets: 0, 1px, 2px;

+ 65 - 64
main/ui/src/main/resources/fxml/main_window.fxml

@@ -10,68 +10,69 @@
 <?import javafx.scene.layout.StackPane?>
 <?import javafx.scene.layout.VBox?>
 <?import org.cryptomator.ui.controls.FontAwesome5IconView?>
-<VBox xmlns="http://javafx.com/javafx"
-	  xmlns:fx="http://javafx.com/fxml"
-	  fx:id="root"
-	  fx:controller="org.cryptomator.ui.mainwindow.MainWindowController"
-	  styleClass="main-window">
-	<HBox styleClass="title" fx:id="titleBar" alignment="CENTER" minHeight="50" maxHeight="50" VBox.vgrow="NEVER" spacing="6">
-		<padding>
-			<Insets bottom="6" left="12" right="12" top="6"/>
-		</padding>
-		<children>
-			<Label text="Cryptomator"/>
-			<Region HBox.hgrow="ALWAYS"/>
-			<Button contentDisplay="GRAPHIC_ONLY" mnemonicParsing="false" onAction="#showDonationKeyPreferences" focusTraversable="false" visible="${!controller.licenseHolder.validLicense}">
-				<graphic>
-					<StackPane>
-						<FontAwesome5IconView glyph="EXCLAMATION_CIRCLE" glyphSize="16"/>
-						<Region styleClass="update-indicator" StackPane.alignment="TOP_RIGHT" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity"/>
-					</StackPane>
-				</graphic>
-				<tooltip>
-					<Tooltip text="%main.donationKeyMissing.tooltip"/>
-				</tooltip>
-			</Button>
-			<Button contentDisplay="GRAPHIC_ONLY" mnemonicParsing="false" onAction="#showPreferences" focusTraversable="false">
-				<graphic>
-					<StackPane>
-						<FontAwesome5IconView glyph="COGS" glyphSize="16"/>
-						<Region styleClass="update-indicator" visible="${controller.updateAvailable}" StackPane.alignment="TOP_RIGHT" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity"/>
-					</StackPane>
-				</graphic>
-				<tooltip>
-					<Tooltip text="%main.preferencesBtn.tooltip"/>
-				</tooltip>
-			</Button>
-			<Button contentDisplay="GRAPHIC_ONLY" mnemonicParsing="false" onAction="#close" focusTraversable="false">
-				<graphic>
-					<FontAwesome5IconView glyph="TIMES" glyphSize="16"/>
-				</graphic>
-				<tooltip>
-					<Tooltip text="%main.closeBtn.tooltip"/>
-				</tooltip>
-			</Button>
-		</children>
-	</HBox>
-	<StackPane VBox.vgrow="ALWAYS">
-		<SplitPane dividerPositions="0.33" orientation="HORIZONTAL">
-			<fx:include source="/fxml/vault_list.fxml" SplitPane.resizableWithParent="false"/>
-			<fx:include source="/fxml/vault_detail.fxml" SplitPane.resizableWithParent="true"/>
-		</SplitPane>
+<StackPane xmlns="http://javafx.com/javafx"
+		   xmlns:fx="http://javafx.com/fxml"
+		   fx:id="root"
+		   fx:controller="org.cryptomator.ui.mainwindow.MainWindowController"
+		   styleClass="main-window">
+	<VBox>
+		<HBox styleClass="title" fx:id="titleBar" alignment="CENTER" minHeight="50" maxHeight="50" VBox.vgrow="NEVER" spacing="6">
+			<padding>
+				<Insets bottom="6" left="12" right="12" top="6"/>
+			</padding>
+			<children>
+				<Label text="Cryptomator"/>
+				<Region HBox.hgrow="ALWAYS"/>
+				<Button contentDisplay="GRAPHIC_ONLY" mnemonicParsing="false" onAction="#showDonationKeyPreferences" focusTraversable="false" visible="${!controller.licenseHolder.validLicense}">
+					<graphic>
+						<StackPane>
+							<FontAwesome5IconView glyph="EXCLAMATION_CIRCLE" glyphSize="16"/>
+							<Region styleClass="update-indicator" StackPane.alignment="TOP_RIGHT" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity"/>
+						</StackPane>
+					</graphic>
+					<tooltip>
+						<Tooltip text="%main.donationKeyMissing.tooltip"/>
+					</tooltip>
+				</Button>
+				<Button contentDisplay="GRAPHIC_ONLY" mnemonicParsing="false" onAction="#showPreferences" focusTraversable="false">
+					<graphic>
+						<StackPane>
+							<FontAwesome5IconView glyph="COGS" glyphSize="16"/>
+							<Region styleClass="update-indicator" visible="${controller.updateAvailable}" StackPane.alignment="TOP_RIGHT" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity"/>
+						</StackPane>
+					</graphic>
+					<tooltip>
+						<Tooltip text="%main.preferencesBtn.tooltip"/>
+					</tooltip>
+				</Button>
+				<Button contentDisplay="GRAPHIC_ONLY" mnemonicParsing="false" onAction="#close" focusTraversable="false">
+					<graphic>
+						<FontAwesome5IconView glyph="TIMES" glyphSize="16"/>
+					</graphic>
+					<tooltip>
+						<Tooltip text="%main.closeBtn.tooltip"/>
+					</tooltip>
+				</Button>
+			</children>
+		</HBox>
+		<StackPane VBox.vgrow="ALWAYS">
+			<SplitPane dividerPositions="0.33" orientation="HORIZONTAL">
+				<fx:include source="/fxml/vault_list.fxml" SplitPane.resizableWithParent="false"/>
+				<fx:include source="/fxml/vault_detail.fxml" SplitPane.resizableWithParent="true"/>
+			</SplitPane>
 
-		<Region styleClass="resizer" StackPane.alignment="BOTTOM_RIGHT" fx:id="resizer" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity"/>
-
-		<VBox styleClass="drag-n-drop-indicator" visible="${controller.draggingOver}" alignment="TOP_CENTER">
-			<HBox visible="${!controller.draggingVaultOver}" managed="${!controller.draggingVaultOver}" spacing="6" styleClass="drag-n-drop-header" alignment="CENTER" VBox.vgrow="NEVER">
-				<FontAwesome5IconView glyph="EXCLAMATION_TRIANGLE"/>
-				<Label text="%main.dropZone.unknownDragboardContent"/>
-			</HBox>
-			<HBox visible="${controller.draggingVaultOver}" managed="${controller.draggingVaultOver}" spacing="6" styleClass="drag-n-drop-header" alignment="CENTER" VBox.vgrow="NEVER">
-				<FontAwesome5IconView glyph="CHECK"/>
-				<Label text="%main.dropZone.dropVault"/>
-			</HBox>
-			<Region VBox.vgrow="ALWAYS"/>
-		</VBox>
-	</StackPane>
-</VBox>
+			<VBox styleClass="drag-n-drop-indicator" visible="${controller.draggingOver}" alignment="TOP_CENTER">
+				<HBox visible="${!controller.draggingVaultOver}" managed="${!controller.draggingVaultOver}" spacing="6" styleClass="drag-n-drop-header" alignment="CENTER" VBox.vgrow="NEVER">
+					<FontAwesome5IconView glyph="EXCLAMATION_TRIANGLE"/>
+					<Label text="%main.dropZone.unknownDragboardContent"/>
+				</HBox>
+				<HBox visible="${controller.draggingVaultOver}" managed="${controller.draggingVaultOver}" spacing="6" styleClass="drag-n-drop-header" alignment="CENTER" VBox.vgrow="NEVER">
+					<FontAwesome5IconView glyph="CHECK"/>
+					<Label text="%main.dropZone.dropVault"/>
+				</HBox>
+				<Region VBox.vgrow="ALWAYS"/>
+			</VBox>
+		</StackPane>
+	</VBox>
+	<fx:include source="/fxml/main_window_resize.fxml"/>
+</StackPane>

+ 17 - 0
main/ui/src/main/resources/fxml/main_window_resize.fxml

@@ -0,0 +1,17 @@
+<?import javafx.scene.Cursor?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.Region?>
+<AnchorPane xmlns="http://javafx.com/javafx"
+			xmlns:fx="http://javafx.com/fxml"
+			fx:controller="org.cryptomator.ui.mainwindow.ResizeController"
+			nodeOrientation="LEFT_TO_RIGHT"
+			pickOnBounds="false">
+	<fx:define>
+		<Cursor fx:id="nwResize" fx:constant="NW_RESIZE"/>
+		<Cursor fx:id="neResize" fx:constant="NE_RESIZE"/>
+	</fx:define>
+	<Region fx:id="tlResizer" cursor="${nwResize}" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity" AnchorPane.topAnchor="0" AnchorPane.leftAnchor="0"/>
+	<Region fx:id="trResizer" cursor="${neResize}" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity" AnchorPane.topAnchor="0" AnchorPane.rightAnchor="0"/>
+	<Region fx:id="blResizer" cursor="${neResize}" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity" AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0"/>
+	<Region fx:id="brResizer" cursor="${nwResize}" prefWidth="10" prefHeight="10" maxWidth="-Infinity" maxHeight="-Infinity" AnchorPane.bottomAnchor="0" AnchorPane.rightAnchor="0"/>
+</AnchorPane>