Rework gui for small sizes

This commit is contained in:
crschnick
2026-06-01 11:21:16 +00:00
parent c4811625e5
commit 351dbea6c2
15 changed files with 84 additions and 29 deletions
@@ -8,7 +8,7 @@ import io.xpipe.app.comp.SimpleRegionBuilder;
import io.xpipe.app.comp.base.*;
import io.xpipe.app.core.AppFontSizes;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.core.window.AppMainWindow;
import io.xpipe.app.core.AppSizeBreakpoints;
import io.xpipe.app.ext.ShellStore;
import io.xpipe.app.hub.comp.StoreEntryWrapper;
import io.xpipe.app.hub.comp.StoreFilter;
@@ -80,7 +80,7 @@ public class BrowserFullSessionComp extends SimpleRegionBuilder {
loadingStack.apply(struc -> struc.setPickOnBounds(false));
var delayedStack = new DelayedInitComp(
left, () -> StoreViewState.get() != null && StoreViewState.get().isInitialized());
delayedStack.hide(AppMainWindow.get().getStage().widthProperty().lessThan(1000));
delayedStack.hide(AppSizeBreakpoints.compactMode());
var splitPane = new LeftSplitPaneComp(delayedStack, loadingStack)
.withInitialWidth(AppLayoutModel.get().getSavedState().getBrowserConnectionsWidth())
.withOnDividerChange(d -> {
@@ -6,9 +6,9 @@ import io.xpipe.app.comp.SimpleRegionBuilder;
import io.xpipe.app.comp.base.LoadingIconComp;
import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.app.comp.base.StackComp;
import io.xpipe.app.core.App;
import io.xpipe.app.core.AppFontSizes;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppSizeBreakpoints;
import io.xpipe.app.platform.LabelGraphic;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.PlatformThread;
@@ -269,26 +269,24 @@ public class BrowserSessionTabsComp extends SimpleRegionBuilder {
.paddingProperty()
.bind(Bindings.createObjectBinding(
() -> {
var w = App.getApp().getStage().getWidth();
if (w >= 1000) {
if (!AppSizeBreakpoints.compactMode().get()) {
return new Insets(2, 0, 4, -leftPadding.get() + 3);
} else {
return new Insets(2, 0, 4, -leftPadding.get() - 4);
}
},
App.getApp().getStage().widthProperty(),
AppSizeBreakpoints.compactMode(),
leftPadding));
tabs.paddingProperty()
.bind(Bindings.createObjectBinding(
() -> {
var w = App.getApp().getStage().getWidth();
if (w >= 1000) {
if (!AppSizeBreakpoints.compactMode().get()) {
return new Insets(0, 0, 0, -5);
} else {
return new Insets(0, 0, 0, 5);
}
},
App.getApp().getStage().widthProperty()));
AppSizeBreakpoints.compactMode()));
headerHeight.bind(headerArea.heightProperty());
});
}
@@ -5,6 +5,7 @@ import io.xpipe.app.comp.RegionDescriptor;
import io.xpipe.app.comp.SimpleRegionBuilder;
import io.xpipe.app.core.AppFontSizes;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppSizeBreakpoints;
import io.xpipe.app.ext.FileEntry;
import io.xpipe.app.ext.FileInfo;
import io.xpipe.app.ext.FileKind;
@@ -193,7 +194,7 @@ public final class BrowserFileListComp extends SimpleRegionBuilder {
TableColumn<BrowserEntry, String> sizeCol) {
table.widthProperty().subscribe((newValue) -> {
if (fileList.getFileSystemModel().getFileSystem().supportsOwnerColumn()) {
ownerCol.setVisible(newValue.doubleValue() > 1000);
ownerCol.setVisible(!AppSizeBreakpoints.compactMode().get());
}
if (fileList.getFileSystemModel().getFileSystem().supportsModeColumn()) {
@@ -5,14 +5,13 @@ import io.xpipe.app.core.AppFontSizes;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.platform.LabelGraphic;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.layout.*;
import atlantafx.base.theme.Styles;
import javafx.scene.paint.Color;
import lombok.Setter;
import org.kordamp.ikonli.javafx.FontIcon;
@@ -69,13 +68,12 @@ public class IntroComp extends SimpleRegionBuilder {
v.getChildren().add(buttonPane);
}
v.setMinWidth(Region.USE_PREF_SIZE);
v.setMaxWidth(Region.USE_PREF_SIZE);
v.setMinHeight(Region.USE_PREF_SIZE);
v.setMaxHeight(Region.USE_PREF_SIZE);
v.setMinWidth(0);
v.setMinHeight(0);
v.setSpacing(20);
v.getStyleClass().add("intro");
v.setPadding(new Insets(40, 20, 40, 20));
return v;
}
}
@@ -4,8 +4,10 @@ import io.xpipe.app.comp.SimpleRegionBuilder;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.layout.Background;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import java.util.List;
@@ -20,12 +22,7 @@ public class IntroListComp extends SimpleRegionBuilder {
@Override
public Region createSimple() {
var v = new VerticalComp(intros).build();
v.setSpacing(80);
v.setMinWidth(Region.USE_PREF_SIZE);
v.setMaxWidth(Region.USE_PREF_SIZE);
v.setMinHeight(Region.USE_PREF_SIZE);
v.setMaxHeight(Region.USE_PREF_SIZE);
var sp = new StackPane(v);
sp.setPadding(new Insets(40, 0, 0, 0));
sp.setAlignment(Pos.CENTER);
@@ -0,0 +1,31 @@
package io.xpipe.app.core;
import io.xpipe.app.core.window.AppMainWindow;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableBooleanValue;
public class AppSizeBreakpoints {
private static final BooleanProperty compactMode = new SimpleBooleanProperty();
private static final BooleanProperty portraitMode = new SimpleBooleanProperty();
public static ObservableBooleanValue compactMode() {
return compactMode;
}
public static ObservableBooleanValue portraitMode() {
return portraitMode;
}
public static void init() {
compactMode.bind(Bindings.createBooleanBinding(() -> {
return AppMainWindow.get().getStage().getWidth() <= 1000;
}, AppMainWindow.get().getStage().widthProperty()));
portraitMode.bind(Bindings.createBooleanBinding(() -> {
return AppMainWindow.get().getStage().getWidth() <= 700 &&
AppMainWindow.get().getStage().getHeight() > AppMainWindow.get().getStage().getWidth();
}, AppMainWindow.get().getStage().widthProperty(), AppMainWindow.get().getStage().heightProperty()));
}
}
@@ -144,6 +144,7 @@ public abstract class AppOperationMode {
ThreadHelper.runAsync(() -> {
PlatformInit.init(true);
AppMainWindow.init(AppOperationMode.getStartupMode() == XPipeDaemonMode.GUI);
AppSizeBreakpoints.init();
});
TrackEvent.info("Finished initial setup");
} catch (Throwable ex) {
@@ -88,8 +88,8 @@ public class AppMainWindow {
}
var stage = App.getApp().getStage();
stage.setMinWidth(500);
stage.setMinHeight(400);
stage.setMinWidth(300);
stage.setMinHeight(300);
INSTANCE = new AppMainWindow(stage);
AppModifiedStage.prepareStage(stage);
@@ -116,6 +116,7 @@ public class AppMainWindow {
AppWindowStyle.addStylesheets(stage.getScene());
AppWindowStyle.addClickShield(stage);
AppWindowStyle.addMaximizedPseudoClass(stage);
AppWindowStyle.addSizePseudoClasses(stage);
AppWindowStyle.addFontSize(scene);
AppTheme.initThemeHandlers(stage);
@@ -38,6 +38,17 @@ public class AppWindowStyle {
AppPrefs.get().theme()));
}
public static void addSizePseudoClasses(Stage stage) {
stage.getScene().rootProperty().subscribe(root -> {
AppSizeBreakpoints.compactMode().subscribe(v -> {
root.pseudoClassStateChanged(PseudoClass.getPseudoClass("compact"), v);
});
AppSizeBreakpoints.portraitMode().subscribe(v -> {
root.pseudoClassStateChanged(PseudoClass.getPseudoClass("portrait"), v);
});
});
}
public static void addMaximizedPseudoClass(Stage stage) {
stage.getScene().rootProperty().subscribe(root -> {
stage.maximizedProperty().subscribe(v -> {
@@ -4,6 +4,7 @@ import io.xpipe.app.comp.BaseRegionBuilder;
import io.xpipe.app.comp.RegionBuilder;
import io.xpipe.app.core.AppFontSizes;
import io.xpipe.app.core.AppSizeBreakpoints;
import javafx.beans.binding.Bindings;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
@@ -68,7 +69,9 @@ public class DenseStoreEntryComp extends StoreEntryComp {
protected Region createContent() {
var grid = new GridPane();
grid.setHgap(8);
grid.hgapProperty().bind(Bindings.createDoubleBinding(() -> {
return AppSizeBreakpoints.portraitMode().get() ? 2.0 : 6.0;
}, AppSizeBreakpoints.portraitMode()));
var tags = createTags().build();
var index = createOrderIndex().build();
@@ -3,8 +3,10 @@ package io.xpipe.app.hub.comp;
import io.xpipe.app.comp.BaseRegionBuilder;
import io.xpipe.app.comp.RegionBuilder;
import io.xpipe.app.core.AppFontSizes;
import io.xpipe.app.core.AppSizeBreakpoints;
import io.xpipe.app.util.OsType;
import javafx.beans.binding.Bindings;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
@@ -36,7 +38,9 @@ public class StandardStoreEntryComp extends StoreEntryComp {
var pinIcon = createPinIcon().build();
var grid = new GridPane();
grid.setHgap(6);
grid.hgapProperty().bind(Bindings.createDoubleBinding(() -> {
return AppSizeBreakpoints.portraitMode().get() ? 2.0 : 6.0;
}, AppSizeBreakpoints.portraitMode()));
grid.setVgap(OsType.ofLocal() == OsType.MACOS ? 2 : 0);
var selection = createBatchSelection();
@@ -5,7 +5,7 @@ import io.xpipe.app.comp.SimpleRegionBuilder;
import io.xpipe.app.comp.base.DelayedInitComp;
import io.xpipe.app.comp.base.LeftSplitPaneComp;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.core.window.AppMainWindow;
import io.xpipe.app.core.AppSizeBreakpoints;
import io.xpipe.app.platform.InputHelper;
import io.xpipe.app.terminal.TerminalDockHubComp;
import io.xpipe.app.terminal.TerminalDockHubManager;
@@ -30,7 +30,7 @@ public class StoreLayoutComp extends SimpleRegionBuilder {
private Region createContent() {
var filterTrigger = new ObservableSubscriber();
var left = new StoreSidebarComp(filterTrigger);
left.hide(AppMainWindow.get().getStage().widthProperty().lessThan(1000));
left.hide(AppSizeBreakpoints.compactMode());
left.minWidth(285);
left.maxWidth(500);
left.minHeight(0);
@@ -112,6 +112,7 @@ public class RemoteDesktopWindow {
AppWindowStyle.addStylesheets(stage.getScene());
AppWindowStyle.addClickShield(stage);
AppWindowStyle.addMaximizedPseudoClass(stage);
AppWindowStyle.addSizePseudoClasses(stage);
AppWindowStyle.addFontSize(scene);
AppWindowStyle.addNavigationPseudoClasses(scene);
AppTheme.initThemeHandlers(stage);
@@ -2,6 +2,10 @@
-fx-padding: 0 40 0 80;
}
.root:portrait .prefs-box {
-fx-padding: 0 30 0 10;
}
.prefs-container .options-comp .name {
-fx-padding: 1.8em 0 0 0;
-fx-font-weight: BOLD;
@@ -153,6 +153,11 @@
-fx-padding: 5px 0 0 17px;
}
.root:portrait .store-entry-section-comp > .children-content {
-fx-padding: 5px 0 0 8;
}
.store-entry-section-comp > .separator .line {
-fx-padding: 0;
-fx-border-insets: 0px;