diff options
| author | Kostya <mail@sartin.in> | 2026-09-09 10:05:12 +0300 |
|---|---|---|
| committer | Kostya <mail@sartin.in> | 2026-09-09 10:05:12 +0300 |
| commit | f23c20c1c66b39fb1f49307e08e8593fa708e026 (patch) | |
| tree | 35cf625f5bbb1acf079b6abd2e239fcd446cd2a5 /ui-desktop/src/main/resources/market/guess | |
| parent | 8d7cecd9cf9fb2b0b45607b8efd7ca8f19a89fc6 (diff) | |
| download | guess-market-f23c20c1c66b39fb1f49307e08e8593fa708e026.tar.gz guess-market-f23c20c1c66b39fb1f49307e08e8593fa708e026.tar.xz guess-market-f23c20c1c66b39fb1f49307e08e8593fa708e026.zip | |
ui-desktop: build the JavaFX market UI on top of the service
Replace the placeholder hello-world window with a working desktop
client for the guess market.
ServiceEngine wires the in-memory repositories, XML loader, risk,
matching, fulfillment and settlement contexts together, and AppState
exposes their results as observable JavaFX state for the views to bind
to. The FXML views have an events tab and a users tab. The events tab
lists events with mechanism and commission filters, and shows each
event's price chart, order book ladder, trade history and participants.
The users tab shows each user's ledger and positions, and lets them
place buy and sell orders. Dialogs cover loading an XML file (in a
background task), creating an event and resolving one.
Bundle a CSS theme and Nerd Font faces so the UI looks the same on
every machine. Teach build.sh to copy each module's src/main/resources
into its class output, since FXML, CSS and fonts are loaded from the
classpath at runtime.
Diffstat (limited to 'ui-desktop/src/main/resources/market/guess')
20 files changed, 2143 insertions, 0 deletions
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/app_view.fxml b/ui-desktop/src/main/resources/market/guess/ui/desktop/app_view.fxml new file mode 100644 index 0000000..855b787 --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/app_view.fxml | |||
| @@ -0,0 +1,158 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | |||
| 3 | <?import javafx.geometry.Insets?> | ||
| 4 | <?import javafx.scene.control.Button?> | ||
| 5 | <?import javafx.scene.control.ComboBox?> | ||
| 6 | <?import javafx.scene.control.Label?> | ||
| 7 | <?import javafx.scene.control.ScrollPane?> | ||
| 8 | <?import javafx.scene.control.Tab?> | ||
| 9 | <?import javafx.scene.control.TabPane?> | ||
| 10 | <?import javafx.scene.control.Tooltip?> | ||
| 11 | <?import javafx.scene.layout.BorderPane?> | ||
| 12 | <?import javafx.scene.layout.HBox?> | ||
| 13 | <?import javafx.scene.layout.Region?> | ||
| 14 | <?import javafx.scene.layout.StackPane?> | ||
| 15 | <?import javafx.scene.layout.VBox?> | ||
| 16 | <?import javafx.scene.shape.SVGPath?> | ||
| 17 | |||
| 18 | <StackPane fx:id="rootStack" styleClass="gm-root" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="market.guess.ui.desktop.controllers.AppController"> | ||
| 19 | <children> | ||
| 20 | <!-- Safety net: scrolls only if the viewport gets smaller than AppView.MIN_WIDTH x MIN_HEIGHT. --> | ||
| 21 | <ScrollPane fitToHeight="true" fitToWidth="true" styleClass="gm-app-scroll"> | ||
| 22 | <content> | ||
| 23 | <BorderPane fx:id="chrome" styleClass="gm-chrome"> | ||
| 24 | <top> | ||
| 25 | <VBox> | ||
| 26 | <children> | ||
| 27 | <!-- Window Bar --> | ||
| 28 | <HBox fx:id="windowBar" alignment="CENTER_LEFT" prefHeight="32.0" spacing="10.0" styleClass="gm-bg-panel2, gm-divider-bottom"> | ||
| 29 | <padding> | ||
| 30 | <Insets left="14.0" right="14.0" /> | ||
| 31 | </padding> | ||
| 32 | <children> | ||
| 33 | <HBox alignment="CENTER_LEFT" spacing="8.0" styleClass="gm-traffic-lights"> | ||
| 34 | <children> | ||
| 35 | <StackPane maxHeight="12.0" maxWidth="12.0" minHeight="12.0" minWidth="12.0" onMouseClicked="#handleClose" prefHeight="12.0" prefWidth="12.0" styleClass="gm-traffic-dot, gm-traffic-dot-no"> | ||
| 36 | <children> | ||
| 37 | <SVGPath content="M 0 0 L 5 5 M 5 0 L 0 5" styleClass="gm-traffic-icon" /> | ||
| 38 | </children> | ||
| 39 | </StackPane> | ||
| 40 | <StackPane maxHeight="12.0" maxWidth="12.0" minHeight="12.0" minWidth="12.0" onMouseClicked="#handleMinimize" prefHeight="12.0" prefWidth="12.0" styleClass="gm-traffic-dot, gm-traffic-dot-accent"> | ||
| 41 | <children> | ||
| 42 | <SVGPath content="M 0 2.5 L 6 2.5" styleClass="gm-traffic-icon" /> | ||
| 43 | </children> | ||
| 44 | </StackPane> | ||
| 45 | <StackPane maxHeight="12.0" maxWidth="12.0" minHeight="12.0" minWidth="12.0" onMouseClicked="#handleMaximize" prefHeight="12.0" prefWidth="12.0" styleClass="gm-traffic-dot, gm-traffic-dot-yes"> | ||
| 46 | <children> | ||
| 47 | <SVGPath content="M 0 2.5 L 5 2.5 M 2.5 0 L 2.5 5" styleClass="gm-traffic-icon" /> | ||
| 48 | </children> | ||
| 49 | </StackPane> | ||
| 50 | </children> | ||
| 51 | </HBox> | ||
| 52 | <Label styleClass="gm-text-base, gm-font-semibold, gm-text-ink2" text="Guess Market" /> | ||
| 53 | </children> | ||
| 54 | </HBox> | ||
| 55 | <!-- Toolbar --> | ||
| 56 | <HBox alignment="CENTER_LEFT" spacing="12.0" styleClass="gm-bg-panel, gm-divider-bottom"> | ||
| 57 | <padding> | ||
| 58 | <Insets bottom="12.0" left="16.0" right="16.0" top="12.0" /> | ||
| 59 | </padding> | ||
| 60 | <children> | ||
| 61 | <Button minWidth="-Infinity" onAction="#handleLoadFile" styleClass="gm-btn, gm-btn-primary" text="Load File…" /> | ||
| 62 | <HBox alignment="CENTER_LEFT" spacing="10.0" styleClass="gm-card-panel2" HBox.hgrow="ALWAYS"> | ||
| 63 | <padding> | ||
| 64 | <Insets bottom="8.0" left="12.0" right="12.0" top="8.0" /> | ||
| 65 | </padding> | ||
| 66 | <children> | ||
| 67 | <Label minWidth="-Infinity" styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="" /> | ||
| 68 | <Label fx:id="loadedFilePathLabel" maxWidth="1.7976931348623157E308" minWidth="0.0" styleClass="gm-text-base, gm-font-mono, gm-font-medium, gm-text-ink" textOverrun="ELLIPSIS" HBox.hgrow="ALWAYS" /> | ||
| 69 | </children> | ||
| 70 | </HBox> | ||
| 71 | <HBox alignment="CENTER_RIGHT" minWidth="-Infinity" spacing="12.0"> | ||
| 72 | <children> | ||
| 73 | <Button fx:id="animationsButton" onAction="#handleAnimationsToggled" styleClass="gm-btn, gm-btn-secondary, gm-btn-icon"> | ||
| 74 | <tooltip> | ||
| 75 | <Tooltip text="Toggle animations" /> | ||
| 76 | </tooltip> | ||
| 77 | </Button> | ||
| 78 | <HBox alignment="CENTER_LEFT" spacing="8.0"> | ||
| 79 | <children> | ||
| 80 | <ComboBox fx:id="skinComboBox" onAction="#handleSkinChanged" styleClass="gm-select-base, gm-select-btn-bg" /> | ||
| 81 | </children> | ||
| 82 | </HBox> | ||
| 83 | </children> | ||
| 84 | </HBox> | ||
| 85 | </children> | ||
| 86 | </HBox> | ||
| 87 | </children> | ||
| 88 | </VBox> | ||
| 89 | </top> | ||
| 90 | <center> | ||
| 91 | <StackPane fx:id="centerContainer"> | ||
| 92 | <children> | ||
| 93 | <fx:include fx:id="emptyState" source="controllers/empty_state.fxml" /> | ||
| 94 | <TabPane fx:id="tabPane" managed="false" styleClass="gm-tabs" tabClosingPolicy="UNAVAILABLE" visible="false"> | ||
| 95 | <tabs> | ||
| 96 | <Tab text="Events"> | ||
| 97 | <content> | ||
| 98 | <fx:include fx:id="eventsTab" source="controllers/events_tab.fxml" /> | ||
| 99 | </content> | ||
| 100 | </Tab> | ||
| 101 | <Tab text="Users"> | ||
| 102 | <content> | ||
| 103 | <fx:include fx:id="usersTab" source="controllers/users_tab.fxml" /> | ||
| 104 | </content> | ||
| 105 | </Tab> | ||
| 106 | </tabs> | ||
| 107 | </TabPane> | ||
| 108 | <!-- Overlaid on the right of the tab header; height is bound to the header in AppController --> | ||
| 109 | <HBox fx:id="tabInfo" alignment="CENTER_RIGHT" maxHeight="-Infinity" pickOnBounds="false" spacing="8.0" visible="false" StackPane.alignment="TOP_RIGHT"> | ||
| 110 | <padding> | ||
| 111 | <Insets left="4.0" right="20.0" /> | ||
| 112 | </padding> | ||
| 113 | <children> | ||
| 114 | <Label fx:id="actingAsLabel" styleClass="gm-text-base, gm-font-medium, gm-text-ink2"> | ||
| 115 | <padding> | ||
| 116 | <Insets right="12.0" /> | ||
| 117 | </padding> | ||
| 118 | </Label> | ||
| 119 | <Label styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="ACCOUNT BALANCE" /> | ||
| 120 | <Label fx:id="balanceValueLabel" styleClass="gm-font-mono, gm-text-lg, gm-font-semibold, gm-text-accent" /> | ||
| 121 | </children> | ||
| 122 | </HBox> | ||
| 123 | </children> | ||
| 124 | </StackPane> | ||
| 125 | </center> | ||
| 126 | <bottom> | ||
| 127 | <HBox alignment="CENTER_LEFT" prefHeight="30.0" spacing="12.0" styleClass="gm-bg-panel2, gm-divider-top"> | ||
| 128 | <padding> | ||
| 129 | <Insets left="14.0" right="14.0" /> | ||
| 130 | </padding> | ||
| 131 | <children> | ||
| 132 | <Label fx:id="statusBarLabel" styleClass="gm-text-sm, gm-font-mono, gm-text-ink2" /> | ||
| 133 | <Region HBox.hgrow="ALWAYS" /> | ||
| 134 | <Button fx:id="ejectButton" onAction="#handleEjectFile" styleClass="gm-link-button" text="" visible="false" /> | ||
| 135 | </children> | ||
| 136 | </HBox> | ||
| 137 | </bottom> | ||
| 138 | </BorderPane> | ||
| 139 | </content> | ||
| 140 | </ScrollPane> | ||
| 141 | <StackPane fx:id="dialogContainer" mouseTransparent="true" visible="false"> | ||
| 142 | <children> | ||
| 143 | <fx:include fx:id="loadDialog" managed="false" source="controllers/dialog_load.fxml" visible="false" /> | ||
| 144 | <fx:include fx:id="createEventDialog" managed="false" source="controllers/dialog_create_event.fxml" visible="false" /> | ||
| 145 | <fx:include fx:id="resolveDialog" managed="false" source="controllers/dialog_resolve.fxml" visible="false" /> | ||
| 146 | </children> | ||
| 147 | </StackPane> | ||
| 148 | <StackPane fx:id="toastContainer" mouseTransparent="true" pickOnBounds="false"> | ||
| 149 | <children> | ||
| 150 | <Label fx:id="toastLabel" styleClass="gm-toast" visible="false" StackPane.alignment="BOTTOM_CENTER"> | ||
| 151 | <StackPane.margin> | ||
| 152 | <Insets bottom="44.0" /> | ||
| 153 | </StackPane.margin> | ||
| 154 | </Label> | ||
| 155 | </children> | ||
| 156 | </StackPane> | ||
| 157 | </children> | ||
| 158 | </StackPane> | ||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/dialog_create_event.fxml b/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/dialog_create_event.fxml new file mode 100644 index 0000000..c8f092f --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/dialog_create_event.fxml | |||
| @@ -0,0 +1,137 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | |||
| 3 | <?import javafx.geometry.Insets?> | ||
| 4 | <?import javafx.scene.control.Button?> | ||
| 5 | <?import javafx.scene.control.CheckBox?> | ||
| 6 | <?import javafx.scene.control.ComboBox?> | ||
| 7 | <?import javafx.scene.control.Label?> | ||
| 8 | <?import javafx.scene.control.ScrollPane?> | ||
| 9 | <?import javafx.scene.control.TextArea?> | ||
| 10 | <?import javafx.scene.control.TextField?> | ||
| 11 | <?import javafx.scene.layout.HBox?> | ||
| 12 | <?import javafx.scene.layout.Region?> | ||
| 13 | <?import javafx.scene.layout.StackPane?> | ||
| 14 | <?import javafx.scene.layout.VBox?> | ||
| 15 | |||
| 16 | <StackPane styleClass="gm-modal-scrim" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="market.guess.ui.desktop.controllers.CreateEventDialogController"> | ||
| 17 | <children> | ||
| 18 | <ScrollPane fitToWidth="true" maxHeight="640.0" maxWidth="620.0" prefWidth="620.0" styleClass="gm-modal-card" StackPane.alignment="CENTER"> | ||
| 19 | <content> | ||
| 20 | <VBox> | ||
| 21 | <children> | ||
| 22 | <!-- Header --> | ||
| 23 | <HBox alignment="BASELINE_LEFT" styleClass="gm-divider-bottom"> | ||
| 24 | <padding> | ||
| 25 | <Insets bottom="16.0" left="20.0" right="20.0" top="16.0" /> | ||
| 26 | </padding> | ||
| 27 | <children> | ||
| 28 | <Label styleClass="gm-text-xl, gm-font-bold, gm-text-ink" text="Create new event" /> | ||
| 29 | <Region HBox.hgrow="ALWAYS" /> | ||
| 30 | </children> | ||
| 31 | </HBox> | ||
| 32 | <!-- Body Form --> | ||
| 33 | <VBox spacing="14.0"> | ||
| 34 | <padding> | ||
| 35 | <Insets bottom="18.0" left="20.0" right="20.0" top="18.0" /> | ||
| 36 | </padding> | ||
| 37 | <children> | ||
| 38 | <!-- Name Field --> | ||
| 39 | <VBox spacing="5.0"> | ||
| 40 | <children> | ||
| 41 | <Label styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Event name" /> | ||
| 42 | <TextField fx:id="nameField" maxWidth="1.7976931348623157E308" promptText="Will the summit happen before Q4?" styleClass="gm-textfield" /> | ||
| 43 | </children> | ||
| 44 | </VBox> | ||
| 45 | <!-- Description Field --> | ||
| 46 | <VBox spacing="5.0"> | ||
| 47 | <children> | ||
| 48 | <Label styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Description & termination condition" /> | ||
| 49 | <TextArea fx:id="descArea" prefRowCount="2" promptText="Resolves YES if a joint summit is publicly confirmed and held before October 1st." styleClass="gm-textarea" wrapText="true" /> | ||
| 50 | </children> | ||
| 51 | </VBox> | ||
| 52 | <!-- Row 1: Trading Method & Fee Collection --> | ||
| 53 | <HBox spacing="12.0"> | ||
| 54 | <children> | ||
| 55 | <VBox spacing="5.0" HBox.hgrow="ALWAYS"> | ||
| 56 | <children> | ||
| 57 | <Label styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Trading method" /> | ||
| 58 | <HBox> | ||
| 59 | <children> | ||
| 60 | <Button fx:id="lmsrBtn" maxWidth="1.7976931348623157E308" onAction="#handleSelectLmsr" styleClass="gm-seg, gm-seg-left, gm-seg-pad-tight" text="LMSR" HBox.hgrow="ALWAYS" /> | ||
| 61 | <Button fx:id="orderBookBtn" maxWidth="1.7976931348623157E308" onAction="#handleSelectOrderBook" styleClass="gm-seg, gm-seg-right, gm-seg-pad-tight" text="Order Book" HBox.hgrow="ALWAYS" /> | ||
| 62 | </children> | ||
| 63 | </HBox> | ||
| 64 | </children> | ||
| 65 | </VBox> | ||
| 66 | <VBox spacing="5.0" HBox.hgrow="ALWAYS"> | ||
| 67 | <children> | ||
| 68 | <Label styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Fee collection" /> | ||
| 69 | <ComboBox fx:id="feeCollectionCombo" maxWidth="1.7976931348623157E308" styleClass="gm-select-base, gm-select-panel2-bg" /> | ||
| 70 | </children> | ||
| 71 | </VBox> | ||
| 72 | </children> | ||
| 73 | </HBox> | ||
| 74 | <!-- Row 2: Fee Percent & Parameter --> | ||
| 75 | <HBox spacing="12.0"> | ||
| 76 | <children> | ||
| 77 | <VBox spacing="5.0" HBox.hgrow="ALWAYS"> | ||
| 78 | <children> | ||
| 79 | <Label styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Fee percent (0–90)" /> | ||
| 80 | <TextField fx:id="feePercentField" maxWidth="1.7976931348623157E308" promptText="5" styleClass="gm-textfield, gm-textfield-mono" /> | ||
| 81 | </children> | ||
| 82 | </VBox> | ||
| 83 | <VBox spacing="5.0" HBox.hgrow="ALWAYS"> | ||
| 84 | <children> | ||
| 85 | <Label fx:id="paramLabel" styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Liquidity b (integer)" /> | ||
| 86 | <TextField fx:id="paramField" maxWidth="1.7976931348623157E308" promptText="100" styleClass="gm-textfield, gm-textfield-mono" /> | ||
| 87 | </children> | ||
| 88 | </VBox> | ||
| 89 | </children> | ||
| 90 | </HBox> | ||
| 91 | <!-- Option Names --> | ||
| 92 | <HBox spacing="12.0"> | ||
| 93 | <children> | ||
| 94 | <VBox spacing="5.0" HBox.hgrow="ALWAYS"> | ||
| 95 | <children> | ||
| 96 | <Label styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Option 1" /> | ||
| 97 | <TextField fx:id="opt1Field" maxWidth="1.7976931348623157E308" promptText="YES" styleClass="gm-textfield" /> | ||
| 98 | </children> | ||
| 99 | </VBox> | ||
| 100 | <VBox spacing="5.0" HBox.hgrow="ALWAYS"> | ||
| 101 | <children> | ||
| 102 | <Label styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Option 2" /> | ||
| 103 | <TextField fx:id="opt2Field" maxWidth="1.7976931348623157E308" promptText="NO" styleClass="gm-textfield" /> | ||
| 104 | </children> | ||
| 105 | </VBox> | ||
| 106 | </children> | ||
| 107 | </HBox> | ||
| 108 | <!-- Minting CheckBox (Order Book only) --> | ||
| 109 | <CheckBox fx:id="mintingCheckBox" selected="true" styleClass="gm-checkbox-strong" text="Allow minting new share pairs when bid + ask exceeds d" visible="false" /> | ||
| 110 | <!-- Info Box --> | ||
| 111 | <HBox styleClass="gm-card-panel2"> | ||
| 112 | <padding> | ||
| 113 | <Insets bottom="11.0" left="13.0" right="13.0" top="11.0" /> | ||
| 114 | </padding> | ||
| 115 | <children> | ||
| 116 | <Label fx:id="infoNoteLabel" styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" wrapText="true" /> | ||
| 117 | </children> | ||
| 118 | </HBox> | ||
| 119 | </children> | ||
| 120 | </VBox> | ||
| 121 | <!-- Footer --> | ||
| 122 | <HBox alignment="CENTER_LEFT" spacing="9.0" styleClass="gm-divider-top"> | ||
| 123 | <padding> | ||
| 124 | <Insets bottom="14.0" left="20.0" right="20.0" top="14.0" /> | ||
| 125 | </padding> | ||
| 126 | <children> | ||
| 127 | <Region HBox.hgrow="ALWAYS" /> | ||
| 128 | <Button onAction="#handleCancel" styleClass="gm-btn, gm-btn-secondary" text="Cancel" /> | ||
| 129 | <Button onAction="#handleCreate" styleClass="gm-btn, gm-btn-primary" text="Create event" /> | ||
| 130 | </children> | ||
| 131 | </HBox> | ||
| 132 | </children> | ||
| 133 | </VBox> | ||
| 134 | </content> | ||
| 135 | </ScrollPane> | ||
| 136 | </children> | ||
| 137 | </StackPane> | ||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/dialog_load.fxml b/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/dialog_load.fxml new file mode 100644 index 0000000..d93ac9e --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/dialog_load.fxml | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | |||
| 3 | <?import javafx.geometry.Insets?> | ||
| 4 | <?import javafx.scene.control.Button?> | ||
| 5 | <?import javafx.scene.control.Label?> | ||
| 6 | <?import javafx.scene.control.ProgressBar?> | ||
| 7 | <?import javafx.scene.layout.HBox?> | ||
| 8 | <?import javafx.scene.layout.Region?> | ||
| 9 | <?import javafx.scene.layout.StackPane?> | ||
| 10 | <?import javafx.scene.layout.VBox?> | ||
| 11 | |||
| 12 | <StackPane styleClass="gm-modal-scrim" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="market.guess.ui.desktop.controllers.LoadDialogController"> | ||
| 13 | <children> | ||
| 14 | <VBox maxHeight="-Infinity" maxWidth="-Infinity" prefWidth="430.0" spacing="12.0" styleClass="gm-card" StackPane.alignment="CENTER"> | ||
| 15 | <padding> | ||
| 16 | <Insets bottom="20.0" left="22.0" right="22.0" top="20.0" /> | ||
| 17 | </padding> | ||
| 18 | <children> | ||
| 19 | <Label styleClass="gm-text-lg, gm-font-bold, gm-text-ink" text="Loading events file…" /> | ||
| 20 | <Label fx:id="pathLabel" maxWidth="1.7976931348623157E308" minWidth="0.0" styleClass="gm-text-sm, gm-font-mono, gm-font-medium, gm-text-ink2" textOverrun="ELLIPSIS" /> | ||
| 21 | <ProgressBar fx:id="progressBar" maxWidth="1.7976931348623157E308" prefHeight="9.0" progress="0.06" styleClass="gm-progress, gm-progress-accent" /> | ||
| 22 | <HBox alignment="CENTER_LEFT"> | ||
| 23 | <children> | ||
| 24 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Validating users, market makers and fees…" /> | ||
| 25 | <Region HBox.hgrow="ALWAYS" /> | ||
| 26 | <Button onAction="#handleCancel" styleClass="gm-btn, gm-btn-secondary" text="Cancel" /> | ||
| 27 | </children> | ||
| 28 | </HBox> | ||
| 29 | </children> | ||
| 30 | </VBox> | ||
| 31 | </children> | ||
| 32 | </StackPane> | ||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/dialog_resolve.fxml b/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/dialog_resolve.fxml new file mode 100644 index 0000000..b5a9634 --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/dialog_resolve.fxml | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | |||
| 3 | <?import javafx.geometry.Insets?> | ||
| 4 | <?import javafx.scene.control.Button?> | ||
| 5 | <?import javafx.scene.control.Label?> | ||
| 6 | <?import javafx.scene.layout.HBox?> | ||
| 7 | <?import javafx.scene.layout.Priority?> | ||
| 8 | <?import javafx.scene.layout.Region?> | ||
| 9 | <?import javafx.scene.layout.StackPane?> | ||
| 10 | <?import javafx.scene.layout.VBox?> | ||
| 11 | |||
| 12 | <StackPane styleClass="gm-modal-scrim" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="market.guess.ui.desktop.controllers.ResolveDialogController"> | ||
| 13 | <children> | ||
| 14 | <VBox maxHeight="-Infinity" maxWidth="-Infinity" prefWidth="470.0" styleClass="gm-card" StackPane.alignment="CENTER"> | ||
| 15 | <children> | ||
| 16 | <!-- Title --> | ||
| 17 | <HBox alignment="CENTER_LEFT" styleClass="gm-divider-bottom"> | ||
| 18 | <padding> | ||
| 19 | <Insets bottom="16.0" left="20.0" right="20.0" top="16.0" /> | ||
| 20 | </padding> | ||
| 21 | <children> | ||
| 22 | <Label styleClass="gm-text-lg, gm-font-bold, gm-text-ink" text="Close & resolve event" /> | ||
| 23 | </children> | ||
| 24 | </HBox> | ||
| 25 | <!-- Body --> | ||
| 26 | <VBox spacing="13.0"> | ||
| 27 | <padding> | ||
| 28 | <Insets bottom="18.0" left="20.0" right="20.0" top="18.0" /> | ||
| 29 | </padding> | ||
| 30 | <children> | ||
| 31 | <Label styleClass="gm-text-base, gm-font-regular, gm-text-ink2" text="Pick the option the event ended with. The contract account is emptied to holders of the winning option; a close-time fee is moved to the market maker. This cannot be undone." wrapText="true" /> | ||
| 32 | <HBox spacing="10.0"> | ||
| 33 | <children> | ||
| 34 | <Button fx:id="resolveYesBtn" maxWidth="1.7976931348623157E308" onAction="#handleSelectYes" styleClass="gm-resolve-option, gm-resolve-option-yes" text="YES" HBox.hgrow="ALWAYS" /> | ||
| 35 | <Button fx:id="resolveNoBtn" maxWidth="1.7976931348623157E308" onAction="#handleSelectNo" styleClass="gm-resolve-option, gm-resolve-option-no" text="NO" HBox.hgrow="ALWAYS" /> | ||
| 36 | </children> | ||
| 37 | </HBox> | ||
| 38 | </children> | ||
| 39 | </VBox> | ||
| 40 | <!-- Footer --> | ||
| 41 | <HBox alignment="CENTER_LEFT" spacing="9.0" styleClass="gm-divider-top"> | ||
| 42 | <padding> | ||
| 43 | <Insets bottom="14.0" left="20.0" right="20.0" top="14.0" /> | ||
| 44 | </padding> | ||
| 45 | <children> | ||
| 46 | <Region HBox.hgrow="ALWAYS" /> | ||
| 47 | <Button onAction="#handleCancel" styleClass="gm-btn, gm-btn-secondary" text="Cancel" /> | ||
| 48 | <Button fx:id="confirmBtn" disable="true" onAction="#handleConfirm" styleClass="gm-btn, gm-btn-destructive" text="Resolve as …" /> | ||
| 49 | </children> | ||
| 50 | </HBox> | ||
| 51 | </children> | ||
| 52 | </VBox> | ||
| 53 | </children> | ||
| 54 | </StackPane> | ||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/empty_state.fxml b/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/empty_state.fxml new file mode 100644 index 0000000..0385759 --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/empty_state.fxml | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | |||
| 3 | <?import javafx.scene.control.Button?> | ||
| 4 | <?import javafx.scene.control.Label?> | ||
| 5 | <?import javafx.scene.layout.StackPane?> | ||
| 6 | <?import javafx.scene.layout.VBox?> | ||
| 7 | <?import market.guess.ui.desktop.components.graphic.MarketChart?> | ||
| 8 | |||
| 9 | <StackPane styleClass="gm-chrome" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="market.guess.ui.desktop.controllers.EmptyStateController"> | ||
| 10 | <children> | ||
| 11 | <VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" spacing="14.0"> | ||
| 12 | <children> | ||
| 13 | <MarketChart fx:id="marketChart" /> | ||
| 14 | <Label styleClass="gm-text-xl, gm-font-semibold, gm-text-ink" text="No file loaded" /> | ||
| 15 | <Label alignment="CENTER" maxWidth="420.0" styleClass="gm-text-md, gm-font-regular, gm-text-ink2" text="Load an XML file to populate events and users" textAlignment="CENTER" wrapText="true" /> | ||
| 16 | </children> | ||
| 17 | </VBox> | ||
| 18 | </children> | ||
| 19 | </StackPane> | ||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/events_tab.fxml b/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/events_tab.fxml new file mode 100644 index 0000000..4e2c1d4 --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/events_tab.fxml | |||
| @@ -0,0 +1,448 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | |||
| 3 | <?import javafx.geometry.Insets?> | ||
| 4 | <?import javafx.scene.layout.FlowPane?> | ||
| 5 | <?import javafx.scene.chart.LineChart?> | ||
| 6 | <?import javafx.scene.chart.NumberAxis?> | ||
| 7 | <?import javafx.scene.control.Button?> | ||
| 8 | <?import javafx.scene.control.Label?> | ||
| 9 | <?import javafx.scene.control.ListView?> | ||
| 10 | <?import javafx.scene.control.ProgressBar?> | ||
| 11 | <?import javafx.scene.control.ScrollPane?> | ||
| 12 | <?import javafx.scene.layout.HBox?> | ||
| 13 | <?import javafx.scene.layout.Priority?> | ||
| 14 | <?import javafx.scene.layout.Region?> | ||
| 15 | <?import javafx.scene.layout.StackPane?> | ||
| 16 | <?import javafx.scene.layout.VBox?> | ||
| 17 | |||
| 18 | <HBox spacing="12.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="market.guess.ui.desktop.controllers.EventsTabController"> | ||
| 19 | <padding> | ||
| 20 | <Insets bottom="12.0" left="16.0" right="16.0" top="12.0" /> | ||
| 21 | </padding> | ||
| 22 | <children> | ||
| 23 | <!-- Left Card: Filters + List --> | ||
| 24 | <VBox maxWidth="498.0" minWidth="498.0" prefWidth="498.0" spacing="10.0" styleClass="gm-card"> | ||
| 25 | <padding> | ||
| 26 | <Insets bottom="12.0" left="12.0" right="12.0" top="12.0" /> | ||
| 27 | </padding> | ||
| 28 | <children> | ||
| 29 | <!-- Method Filter --> | ||
| 30 | <HBox alignment="CENTER_LEFT" spacing="8.0"> | ||
| 31 | <children> | ||
| 32 | <Label minWidth="74.0" prefWidth="74.0" styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Method" /> | ||
| 33 | <Button fx:id="methodFilterAllBtn" onAction="#handleMethodAll" styleClass="gm-toggle" text="All" /> | ||
| 34 | <Button fx:id="methodFilterLmsrBtn" onAction="#handleMethodLmsr" styleClass="gm-toggle" text="LMSR" /> | ||
| 35 | <Button fx:id="methodFilterObBtn" onAction="#handleMethodOb" styleClass="gm-toggle" text="Order Book" /> | ||
| 36 | </children> | ||
| 37 | </HBox> | ||
| 38 | <!-- Status Filter --> | ||
| 39 | <HBox alignment="CENTER_LEFT" spacing="8.0"> | ||
| 40 | <children> | ||
| 41 | <Label minWidth="74.0" prefWidth="74.0" styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Status" /> | ||
| 42 | <Button fx:id="statusFilterAllBtn" onAction="#handleStatusAll" styleClass="gm-toggle" text="All" /> | ||
| 43 | <Button fx:id="statusFilterNotStartedBtn" onAction="#handleStatusNotStarted" styleClass="gm-toggle" text="Not started" /> | ||
| 44 | <Button fx:id="statusFilterActiveBtn" onAction="#handleStatusActive" styleClass="gm-toggle" text="Active" /> | ||
| 45 | <Button fx:id="statusFilterClosedBtn" onAction="#handleStatusClosed" styleClass="gm-toggle" text="Closed" /> | ||
| 46 | </children> | ||
| 47 | </HBox> | ||
| 48 | <!-- Fee Filter --> | ||
| 49 | <HBox alignment="CENTER_LEFT" spacing="8.0"> | ||
| 50 | <children> | ||
| 51 | <Label minWidth="74.0" prefWidth="74.0" styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Fee" /> | ||
| 52 | <Button fx:id="feeFilterAllBtn" onAction="#handleFeeAll" styleClass="gm-toggle" text="All" /> | ||
| 53 | <Button fx:id="feeFilterPurchaseBtn" onAction="#handleFeePurchase" styleClass="gm-toggle" text="On purchase" /> | ||
| 54 | <Button fx:id="feeFilterCloseBtn" onAction="#handleFeeClose" styleClass="gm-toggle" text="On close" /> | ||
| 55 | </children> | ||
| 56 | </HBox> | ||
| 57 | <!-- Virtualized Event List --> | ||
| 58 | <ListView fx:id="eventListContainer" styleClass="gm-scroll-transparent, gm-list-view" VBox.vgrow="ALWAYS" /> | ||
| 59 | <!-- Footer --> | ||
| 60 | <HBox alignment="CENTER_LEFT"> | ||
| 61 | <children> | ||
| 62 | <Label fx:id="eventCountLabel" styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="0 of 0 events shown" /> | ||
| 63 | <Region HBox.hgrow="ALWAYS" /> | ||
| 64 | <Button onAction="#handleNewEvent" styleClass="gm-btn, gm-btn-secondary" text="+ New Event" /> | ||
| 65 | </children> | ||
| 66 | </HBox> | ||
| 67 | </children> | ||
| 68 | </VBox> | ||
| 69 | <!-- Right Card: Event Details --> | ||
| 70 | <VBox fx:id="eventDetailCard" styleClass="gm-card" HBox.hgrow="ALWAYS"> | ||
| 71 | <children> | ||
| 72 | <!-- Detail Header --> | ||
| 73 | <VBox fx:id="detailHeaderBox" spacing="9.0" styleClass="gm-divider-bottom"> | ||
| 74 | <padding> | ||
| 75 | <Insets bottom="14.0" left="16.0" right="16.0" top="14.0" /> | ||
| 76 | </padding> | ||
| 77 | <children> | ||
| 78 | <HBox alignment="TOP_LEFT" spacing="12.0"> | ||
| 79 | <children> | ||
| 80 | <VBox spacing="5.0" HBox.hgrow="ALWAYS"> | ||
| 81 | <children> | ||
| 82 | <Label fx:id="eventNameLabel" styleClass="gm-text-xl, gm-font-bold, gm-text-ink" /> | ||
| 83 | <Label fx:id="eventDescLabel" styleClass="gm-text-base, gm-font-regular, gm-text-ink2" wrapText="true" /> | ||
| 84 | </children> | ||
| 85 | </VBox> | ||
| 86 | <HBox spacing="7.0"> | ||
| 87 | <children> | ||
| 88 | <Button fx:id="openEventBtn" onAction="#handleOpenEvent" styleClass="gm-btn, gm-btn-primary" text="Open Event" /> | ||
| 89 | <Button fx:id="closeEventBtn" onAction="#handleCloseEvent" styleClass="gm-btn, gm-btn-secondary" text="Close & Resolve…" /> | ||
| 90 | </children> | ||
| 91 | </HBox> | ||
| 92 | </children> | ||
| 93 | </HBox> | ||
| 94 | <HBox fx:id="metaFieldsBox" alignment="CENTER_LEFT" spacing="16.0"> | ||
| 95 | <children> | ||
| 96 | <HBox fx:id="livePill" alignment="CENTER_LEFT" spacing="7.0" styleClass="gm-pill, gm-live-pill"> | ||
| 97 | <children> | ||
| 98 | <StackPane fx:id="liveBarsBox" /> | ||
| 99 | <Label fx:id="liveLabel" styleClass="gm-live-label" /> | ||
| 100 | </children> | ||
| 101 | </HBox> | ||
| 102 | <HBox alignment="CENTER_LEFT" spacing="4.0"> | ||
| 103 | <children> | ||
| 104 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Method" /> | ||
| 105 | <Label fx:id="metaMethodLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 106 | </children> | ||
| 107 | </HBox> | ||
| 108 | <HBox alignment="CENTER_LEFT" spacing="4.0"> | ||
| 109 | <children> | ||
| 110 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Status" /> | ||
| 111 | <Label fx:id="metaStatusLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 112 | </children> | ||
| 113 | </HBox> | ||
| 114 | <HBox alignment="CENTER_LEFT" spacing="4.0"> | ||
| 115 | <children> | ||
| 116 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Market Maker" /> | ||
| 117 | <Label fx:id="metaMmLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 118 | </children> | ||
| 119 | </HBox> | ||
| 120 | <HBox alignment="CENTER_LEFT" spacing="4.0"> | ||
| 121 | <children> | ||
| 122 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Fee" /> | ||
| 123 | <Label fx:id="metaFeeLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 124 | </children> | ||
| 125 | </HBox> | ||
| 126 | <HBox alignment="CENTER_LEFT" spacing="4.0"> | ||
| 127 | <children> | ||
| 128 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Contract" /> | ||
| 129 | <Label fx:id="metaContractLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 130 | </children> | ||
| 131 | </HBox> | ||
| 132 | </children> | ||
| 133 | </HBox> | ||
| 134 | </children> | ||
| 135 | </VBox> | ||
| 136 | <!-- Detail Scrollable Body --> | ||
| 137 | <ScrollPane fitToWidth="true" styleClass="gm-scroll-transparent" VBox.vgrow="ALWAYS"> | ||
| 138 | <content> | ||
| 139 | <VBox spacing="14.0"> | ||
| 140 | <padding> | ||
| 141 | <Insets bottom="14.0" left="16.0" right="16.0" top="14.0" /> | ||
| 142 | </padding> | ||
| 143 | <children> | ||
| 144 | <!-- LMSR Section --> | ||
| 145 | <VBox fx:id="lmsrSection" spacing="14.0"> | ||
| 146 | <children> | ||
| 147 | <!-- YES / NO Option Cards --> | ||
| 148 | <HBox spacing="10.0"> | ||
| 149 | <children> | ||
| 150 | <VBox spacing="9.0" styleClass="gm-card-soft-yes" HBox.hgrow="ALWAYS"> | ||
| 151 | <padding> | ||
| 152 | <Insets bottom="12.0" left="13.0" right="13.0" top="12.0" /> | ||
| 153 | </padding> | ||
| 154 | <children> | ||
| 155 | <HBox alignment="BASELINE_LEFT"> | ||
| 156 | <children> | ||
| 157 | <Label styleClass="gm-text-lg, gm-font-bold, gm-text-yes" text="YES" /> | ||
| 158 | <Region HBox.hgrow="ALWAYS" /> | ||
| 159 | <Label fx:id="lmsrYesPriceLabel" styleClass="gm-text-2xl, gm-font-semibold, gm-font-mono, gm-text-yes" /> | ||
| 160 | </children> | ||
| 161 | </HBox> | ||
| 162 | <ProgressBar fx:id="lmsrYesProgressBar" maxHeight="6.0" maxWidth="1.7976931348623157E308" minHeight="6.0" prefHeight="6.0" styleClass="gm-progress, gm-progress-yes" /> | ||
| 163 | <Label fx:id="lmsrYesSharesLabel" styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" /> | ||
| 164 | </children> | ||
| 165 | </VBox> | ||
| 166 | <VBox spacing="9.0" styleClass="gm-card-soft-no" HBox.hgrow="ALWAYS"> | ||
| 167 | <padding> | ||
| 168 | <Insets bottom="12.0" left="13.0" right="13.0" top="12.0" /> | ||
| 169 | </padding> | ||
| 170 | <children> | ||
| 171 | <HBox alignment="BASELINE_LEFT"> | ||
| 172 | <children> | ||
| 173 | <Label styleClass="gm-text-lg, gm-font-bold, gm-text-no" text="NO" /> | ||
| 174 | <Region HBox.hgrow="ALWAYS" /> | ||
| 175 | <Label fx:id="lmsrNoPriceLabel" styleClass="gm-text-2xl, gm-font-semibold, gm-font-mono, gm-text-no" /> | ||
| 176 | </children> | ||
| 177 | </HBox> | ||
| 178 | <ProgressBar fx:id="lmsrNoProgressBar" maxHeight="6.0" maxWidth="1.7976931348623157E308" minHeight="6.0" prefHeight="6.0" styleClass="gm-progress, gm-progress-no" /> | ||
| 179 | <Label fx:id="lmsrNoSharesLabel" styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" /> | ||
| 180 | </children> | ||
| 181 | </VBox> | ||
| 182 | </children> | ||
| 183 | </HBox> | ||
| 184 | <!-- LMSR Chart Block --> | ||
| 185 | <VBox spacing="8.0"> | ||
| 186 | <children> | ||
| 187 | <HBox alignment="CENTER_LEFT"> | ||
| 188 | <children> | ||
| 189 | <Label styleClass="gm-text-base, gm-font-semibold, gm-text-ink" text="Share price over time" /> | ||
| 190 | <Region HBox.hgrow="ALWAYS" /> | ||
| 191 | <Label fx:id="lmsrChartSubLabel" styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" /> | ||
| 192 | </children> | ||
| 193 | </HBox> | ||
| 194 | <VBox styleClass="gm-card-panel2"> | ||
| 195 | <padding> | ||
| 196 | <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> | ||
| 197 | </padding> | ||
| 198 | <children> | ||
| 199 | <LineChart fx:id="lmsrChart" animated="false" createSymbols="false" horizontalGridLinesVisible="true" legendVisible="false" prefHeight="170.0" styleClass="gm-chart, gm-chart-dual" verticalGridLinesVisible="false"> | ||
| 200 | <xAxis> | ||
| 201 | <NumberAxis autoRanging="false" forceZeroInRange="false" minorTickVisible="false" styleClass="gm-chart-axis" tickLabelsVisible="true" tickMarkVisible="true" /> | ||
| 202 | </xAxis> | ||
| 203 | <yAxis> | ||
| 204 | <NumberAxis autoRanging="false" lowerBound="0.0" minorTickVisible="false" styleClass="gm-chart-axis" tickUnit="0.25" upperBound="1.0" /> | ||
| 205 | </yAxis> | ||
| 206 | </LineChart> | ||
| 207 | </children> | ||
| 208 | </VBox> | ||
| 209 | </children> | ||
| 210 | </VBox> | ||
| 211 | </children> | ||
| 212 | </VBox> | ||
| 213 | <!-- Order Book Section --> | ||
| 214 | <VBox fx:id="orderBookSection" spacing="14.0"> | ||
| 215 | <children> | ||
| 216 | <HBox spacing="12.0"> | ||
| 217 | <children> | ||
| 218 | <!-- YES Order Book --> | ||
| 219 | <VBox styleClass="gm-card-panel2" HBox.hgrow="ALWAYS"> | ||
| 220 | <children> | ||
| 221 | <HBox alignment="CENTER_LEFT" styleClass="gm-card-soft-yes"> | ||
| 222 | <padding> | ||
| 223 | <Insets bottom="10.0" left="12.0" right="12.0" top="10.0" /> | ||
| 224 | </padding> | ||
| 225 | <children> | ||
| 226 | <Label styleClass="gm-text-base, gm-font-bold, gm-text-yes" text="YES Order Book" /> | ||
| 227 | <Region HBox.hgrow="ALWAYS" /> | ||
| 228 | <Label fx:id="yesBookCountLabel" styleClass="gm-text-xs, gm-font-regular, gm-text-ink2" /> | ||
| 229 | </children> | ||
| 230 | </HBox> | ||
| 231 | <FlowPane hgap="12.0" vgap="4.0" styleClass="gm-divider-bottom"> | ||
| 232 | <padding> | ||
| 233 | <Insets bottom="8.0" left="12.0" right="12.0" top="8.0" /> | ||
| 234 | </padding> | ||
| 235 | <children> | ||
| 236 | <HBox spacing="4.0"> | ||
| 237 | <children> | ||
| 238 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Last" /> | ||
| 239 | <Label fx:id="yesLastLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 240 | </children> | ||
| 241 | </HBox> | ||
| 242 | <HBox spacing="4.0"> | ||
| 243 | <children> | ||
| 244 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Best bid" /> | ||
| 245 | <Label fx:id="yesBestBidLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 246 | </children> | ||
| 247 | </HBox> | ||
| 248 | <HBox spacing="4.0"> | ||
| 249 | <children> | ||
| 250 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Best ask" /> | ||
| 251 | <Label fx:id="yesBestAskLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 252 | </children> | ||
| 253 | </HBox> | ||
| 254 | <HBox spacing="4.0"> | ||
| 255 | <children> | ||
| 256 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Mid" /> | ||
| 257 | <Label fx:id="yesMidLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 258 | </children> | ||
| 259 | </HBox> | ||
| 260 | <HBox spacing="4.0"> | ||
| 261 | <children> | ||
| 262 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Spread" /> | ||
| 263 | <Label fx:id="yesSpreadLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 264 | </children> | ||
| 265 | </HBox> | ||
| 266 | </children> | ||
| 267 | </FlowPane> | ||
| 268 | <HBox spacing="8.0" styleClass="gm-bg-panel3"> | ||
| 269 | <padding> | ||
| 270 | <Insets bottom="6.0" left="12.0" right="12.0" top="6.0" /> | ||
| 271 | </padding> | ||
| 272 | <children> | ||
| 273 | <Label alignment="CENTER_RIGHT" minWidth="54.0" prefWidth="54.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Price" /> | ||
| 274 | <Label alignment="CENTER_RIGHT" minWidth="50.0" prefWidth="50.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Side" /> | ||
| 275 | <Label alignment="CENTER_RIGHT" minWidth="50.0" prefWidth="50.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Qty" /> | ||
| 276 | <Label maxWidth="1.7976931348623157E308" minWidth="0.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="User" textOverrun="ELLIPSIS" HBox.hgrow="ALWAYS" /> | ||
| 277 | </children> | ||
| 278 | </HBox> | ||
| 279 | <VBox fx:id="yesBookLadderList" /> | ||
| 280 | </children> | ||
| 281 | </VBox> | ||
| 282 | <!-- NO Order Book --> | ||
| 283 | <VBox styleClass="gm-card-panel2" HBox.hgrow="ALWAYS"> | ||
| 284 | <children> | ||
| 285 | <HBox alignment="CENTER_LEFT" styleClass="gm-card-soft-no"> | ||
| 286 | <padding> | ||
| 287 | <Insets bottom="10.0" left="12.0" right="12.0" top="10.0" /> | ||
| 288 | </padding> | ||
| 289 | <children> | ||
| 290 | <Label styleClass="gm-text-base, gm-font-bold, gm-text-no" text="NO Order Book" /> | ||
| 291 | <Region HBox.hgrow="ALWAYS" /> | ||
| 292 | <Label fx:id="noBookCountLabel" styleClass="gm-text-xs, gm-font-regular, gm-text-ink2" /> | ||
| 293 | </children> | ||
| 294 | </HBox> | ||
| 295 | <FlowPane hgap="12.0" vgap="4.0" styleClass="gm-divider-bottom"> | ||
| 296 | <padding> | ||
| 297 | <Insets bottom="8.0" left="12.0" right="12.0" top="8.0" /> | ||
| 298 | </padding> | ||
| 299 | <children> | ||
| 300 | <HBox spacing="4.0"> | ||
| 301 | <children> | ||
| 302 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Last" /> | ||
| 303 | <Label fx:id="noLastLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 304 | </children> | ||
| 305 | </HBox> | ||
| 306 | <HBox spacing="4.0"> | ||
| 307 | <children> | ||
| 308 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Best bid" /> | ||
| 309 | <Label fx:id="noBestBidLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 310 | </children> | ||
| 311 | </HBox> | ||
| 312 | <HBox spacing="4.0"> | ||
| 313 | <children> | ||
| 314 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Best ask" /> | ||
| 315 | <Label fx:id="noBestAskLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 316 | </children> | ||
| 317 | </HBox> | ||
| 318 | <HBox spacing="4.0"> | ||
| 319 | <children> | ||
| 320 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Mid" /> | ||
| 321 | <Label fx:id="noMidLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 322 | </children> | ||
| 323 | </HBox> | ||
| 324 | <HBox spacing="4.0"> | ||
| 325 | <children> | ||
| 326 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="Spread" /> | ||
| 327 | <Label fx:id="noSpreadLabel" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink" /> | ||
| 328 | </children> | ||
| 329 | </HBox> | ||
| 330 | </children> | ||
| 331 | </FlowPane> | ||
| 332 | <HBox spacing="8.0" styleClass="gm-bg-panel3"> | ||
| 333 | <padding> | ||
| 334 | <Insets bottom="6.0" left="12.0" right="12.0" top="6.0" /> | ||
| 335 | </padding> | ||
| 336 | <children> | ||
| 337 | <Label alignment="CENTER_RIGHT" minWidth="54.0" prefWidth="54.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Price" /> | ||
| 338 | <Label alignment="CENTER_RIGHT" minWidth="50.0" prefWidth="50.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Side" /> | ||
| 339 | <Label alignment="CENTER_RIGHT" minWidth="50.0" prefWidth="50.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Qty" /> | ||
| 340 | <Label maxWidth="1.7976931348623157E308" minWidth="0.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="User" textOverrun="ELLIPSIS" HBox.hgrow="ALWAYS" /> | ||
| 341 | </children> | ||
| 342 | </HBox> | ||
| 343 | <VBox fx:id="noBookLadderList" /> | ||
| 344 | </children> | ||
| 345 | </VBox> | ||
| 346 | </children> | ||
| 347 | </HBox> | ||
| 348 | <VBox spacing="8.0"> | ||
| 349 | <children> | ||
| 350 | <HBox alignment="CENTER_LEFT"> | ||
| 351 | <children> | ||
| 352 | <Label styleClass="gm-text-base, gm-font-semibold, gm-text-ink" text="Last trade price over time" /> | ||
| 353 | <Region HBox.hgrow="ALWAYS" /> | ||
| 354 | <Label fx:id="obChartSubLabel" styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" /> | ||
| 355 | </children> | ||
| 356 | </HBox> | ||
| 357 | <VBox styleClass="gm-card-panel2"> | ||
| 358 | <padding> | ||
| 359 | <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> | ||
| 360 | </padding> | ||
| 361 | <children> | ||
| 362 | <LineChart fx:id="obChart" animated="false" createSymbols="false" horizontalGridLinesVisible="true" legendVisible="false" prefHeight="160.0" styleClass="gm-chart, gm-chart-single" verticalGridLinesVisible="false"> | ||
| 363 | <xAxis> | ||
| 364 | <NumberAxis autoRanging="false" forceZeroInRange="false" minorTickVisible="false" styleClass="gm-chart-axis" tickLabelsVisible="true" tickMarkVisible="true" /> | ||
| 365 | </xAxis> | ||
| 366 | <yAxis> | ||
| 367 | <NumberAxis autoRanging="false" lowerBound="0.0" minorTickVisible="false" styleClass="gm-chart-axis" tickUnit="0.25" upperBound="1.0" /> | ||
| 368 | </yAxis> | ||
| 369 | </LineChart> | ||
| 370 | </children> | ||
| 371 | </VBox> | ||
| 372 | </children> | ||
| 373 | </VBox> | ||
| 374 | </children> | ||
| 375 | </VBox> | ||
| 376 | <!-- Trade History Block --> | ||
| 377 | <VBox spacing="7.0"> | ||
| 378 | <children> | ||
| 379 | <HBox alignment="CENTER_LEFT" spacing="6.0"> | ||
| 380 | <children> | ||
| 381 | <Label styleClass="gm-text-base, gm-font-semibold, gm-text-ink" text="Trade history" /> | ||
| 382 | <Label styleClass="gm-text-base, gm-font-regular, gm-text-ink2" text="newest first" /> | ||
| 383 | </children> | ||
| 384 | </HBox> | ||
| 385 | <VBox styleClass="gm-card-panel"> | ||
| 386 | <children> | ||
| 387 | <HBox alignment="CENTER_LEFT" spacing="8.0" styleClass="gm-bg-panel3"> | ||
| 388 | <padding> | ||
| 389 | <Insets bottom="8.0" left="11.0" right="11.0" top="8.0" /> | ||
| 390 | </padding> | ||
| 391 | <children> | ||
| 392 | <Label minWidth="66.0" prefWidth="66.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="#" /> | ||
| 393 | <Label maxWidth="1.7976931348623157E308" minWidth="0.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="User" textOverrun="ELLIPSIS" HBox.hgrow="ALWAYS" /> | ||
| 394 | <Label minWidth="76.0" prefWidth="76.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Option" /> | ||
| 395 | <Label minWidth="92.0" prefWidth="92.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Shares" /> | ||
| 396 | <Label minWidth="88.0" prefWidth="88.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Paid" /> | ||
| 397 | </children> | ||
| 398 | </HBox> | ||
| 399 | <VBox fx:id="tradeHistoryRowsContainer" /> | ||
| 400 | </children> | ||
| 401 | </VBox> | ||
| 402 | </children> | ||
| 403 | </VBox> | ||
| 404 | <!-- Participants Section --> | ||
| 405 | <VBox spacing="7.0"> | ||
| 406 | <children> | ||
| 407 | <VBox styleClass="gm-card-panel"> | ||
| 408 | <children> | ||
| 409 | <Label styleClass="gm-text-base, gm-font-semibold, gm-text-ink" text="Participants"> | ||
| 410 | <padding> | ||
| 411 | <Insets bottom="4.0" /> | ||
| 412 | </padding> | ||
| 413 | </Label> | ||
| 414 | <HBox alignment="CENTER_LEFT" spacing="8.0" styleClass="gm-bg-panel3"> | ||
| 415 | <padding> | ||
| 416 | <Insets bottom="8.0" left="11.0" right="11.0" top="8.0" /> | ||
| 417 | </padding> | ||
| 418 | <children> | ||
| 419 | <Label maxWidth="1.7976931348623157E308" minWidth="0.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="User" textOverrun="ELLIPSIS" HBox.hgrow="ALWAYS" /> | ||
| 420 | <Label alignment="CENTER_RIGHT" minWidth="84.0" prefWidth="84.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="YES" /> | ||
| 421 | <Label alignment="CENTER_RIGHT" minWidth="84.0" prefWidth="84.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="NO" /> | ||
| 422 | <Label alignment="CENTER_RIGHT" minWidth="96.0" prefWidth="96.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Value" /> | ||
| 423 | <Label alignment="CENTER_RIGHT" minWidth="96.0" prefWidth="96.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Fees paid" /> | ||
| 424 | </children> | ||
| 425 | </HBox> | ||
| 426 | <VBox fx:id="participantsRowsContainer" /> | ||
| 427 | </children> | ||
| 428 | </VBox> | ||
| 429 | </children> | ||
| 430 | </VBox> | ||
| 431 | <!-- Resolved Banner Section --> | ||
| 432 | <HBox fx:id="resolvedBanner" alignment="CENTER_LEFT" spacing="12.0" styleClass="gm-banner-resolved"> | ||
| 433 | <padding> | ||
| 434 | <Insets bottom="12.0" left="14.0" right="14.0" top="12.0" /> | ||
| 435 | </padding> | ||
| 436 | <children> | ||
| 437 | <Label styleClass="gm-pill, gm-pill-resolved" text="RESOLVED" /> | ||
| 438 | <Label fx:id="resolvedBannerText" maxWidth="1.7976931348623157E308" styleClass="gm-text-md, gm-font-medium, gm-text-ink" wrapText="true" HBox.hgrow="ALWAYS" /> | ||
| 439 | </children> | ||
| 440 | </HBox> | ||
| 441 | </children> | ||
| 442 | </VBox> | ||
| 443 | </content> | ||
| 444 | </ScrollPane> | ||
| 445 | </children> | ||
| 446 | </VBox> | ||
| 447 | </children> | ||
| 448 | </HBox> | ||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/users_tab.fxml b/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/users_tab.fxml new file mode 100644 index 0000000..0a8ee3b --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/controllers/users_tab.fxml | |||
| @@ -0,0 +1,240 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | |||
| 3 | <?import javafx.geometry.Insets?> | ||
| 4 | <?import javafx.scene.chart.LineChart?> | ||
| 5 | <?import javafx.scene.chart.NumberAxis?> | ||
| 6 | <?import javafx.scene.control.Button?> | ||
| 7 | <?import javafx.scene.control.Label?> | ||
| 8 | <?import javafx.scene.control.ListView?> | ||
| 9 | <?import javafx.scene.control.ScrollPane?> | ||
| 10 | <?import javafx.scene.control.TextField?> | ||
| 11 | <?import javafx.scene.layout.FlowPane?> | ||
| 12 | <?import javafx.scene.layout.HBox?> | ||
| 13 | <?import javafx.scene.layout.Priority?> | ||
| 14 | <?import javafx.scene.layout.Region?> | ||
| 15 | <?import javafx.scene.layout.StackPane?> | ||
| 16 | <?import javafx.scene.layout.VBox?> | ||
| 17 | |||
| 18 | <HBox spacing="12.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="market.guess.ui.desktop.controllers.UsersTabController"> | ||
| 19 | <padding> | ||
| 20 | <Insets bottom="12.0" left="16.0" right="16.0" top="12.0" /> | ||
| 21 | </padding> | ||
| 22 | <children> | ||
| 23 | <!-- Left Card: Users List --> | ||
| 24 | <VBox maxWidth="274.0" minWidth="274.0" prefWidth="274.0" spacing="6.0" styleClass="gm-card"> | ||
| 25 | <padding> | ||
| 26 | <Insets bottom="12.0" left="12.0" right="12.0" top="12.0" /> | ||
| 27 | </padding> | ||
| 28 | <children> | ||
| 29 | <!-- Header --> | ||
| 30 | <HBox alignment="CENTER_LEFT" spacing="8.0"> | ||
| 31 | <children> | ||
| 32 | <Label maxWidth="1.7976931348623157E308" minWidth="0.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="User" textOverrun="ELLIPSIS" HBox.hgrow="ALWAYS" /> | ||
| 33 | <Label alignment="CENTER_RIGHT" minWidth="84.0" prefWidth="84.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Balance" /> | ||
| 34 | </children> | ||
| 35 | </HBox> | ||
| 36 | <!-- Virtualized Users List --> | ||
| 37 | <ListView fx:id="userListContainer" styleClass="gm-scroll-transparent, gm-list-view" VBox.vgrow="ALWAYS" /> | ||
| 38 | <!-- Create Event Button --> | ||
| 39 | <Button maxWidth="1.7976931348623157E308" onAction="#handleCreateNewEvent" styleClass="gm-btn, gm-btn-primary" text="+ Create New Event" /> | ||
| 40 | </children> | ||
| 41 | </VBox> | ||
| 42 | <!-- Right Card: User Details --> | ||
| 43 | <VBox fx:id="userDetailCard" styleClass="gm-card" HBox.hgrow="ALWAYS"> | ||
| 44 | <children> | ||
| 45 | <!-- Header Section --> | ||
| 46 | <HBox alignment="CENTER_LEFT" spacing="14.0" styleClass="gm-divider-bottom"> | ||
| 47 | <padding> | ||
| 48 | <Insets bottom="14.0" left="16.0" right="16.0" top="14.0" /> | ||
| 49 | </padding> | ||
| 50 | <children> | ||
| 51 | <VBox spacing="5.0" HBox.hgrow="ALWAYS"> | ||
| 52 | <children> | ||
| 53 | <HBox alignment="CENTER_LEFT" spacing="9.0"> | ||
| 54 | <children> | ||
| 55 | <Label fx:id="userNameLabel" styleClass="gm-text-xl, gm-font-bold, gm-text-ink" /> | ||
| 56 | <Label fx:id="userRolePill" styleClass="gm-pill" /> | ||
| 57 | </children> | ||
| 58 | </HBox> | ||
| 59 | <Label fx:id="userSubLabel" styleClass="gm-text-base, gm-font-regular, gm-text-ink2" /> | ||
| 60 | </children> | ||
| 61 | </VBox> | ||
| 62 | <HBox alignment="CENTER_RIGHT" spacing="12.0"> | ||
| 63 | <children> | ||
| 64 | <StackPane fx:id="sparklineBox" /> | ||
| 65 | <VBox alignment="CENTER_RIGHT" spacing="4.0"> | ||
| 66 | <children> | ||
| 67 | <Label styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Balance" /> | ||
| 68 | <Label fx:id="userBalanceLabel" styleClass="gm-user-balance" /> | ||
| 69 | </children> | ||
| 70 | </VBox> | ||
| 71 | </children> | ||
| 72 | </HBox> | ||
| 73 | </children> | ||
| 74 | </HBox> | ||
| 75 | <!-- Body Content (Scrollable) --> | ||
| 76 | <ScrollPane fitToWidth="true" styleClass="gm-scroll-transparent" VBox.vgrow="ALWAYS"> | ||
| 77 | <content> | ||
| 78 | <VBox spacing="14.0"> | ||
| 79 | <padding> | ||
| 80 | <Insets bottom="14.0" left="16.0" right="16.0" top="14.0" /> | ||
| 81 | </padding> | ||
| 82 | <children> | ||
| 83 | <!-- Blocked Banner --> | ||
| 84 | <HBox fx:id="blockedBanner" alignment="CENTER_LEFT" spacing="11.0" styleClass="gm-banner-blocked"> | ||
| 85 | <padding> | ||
| 86 | <Insets bottom="11.0" left="13.0" right="13.0" top="11.0" /> | ||
| 87 | </padding> | ||
| 88 | <children> | ||
| 89 | <Label styleClass="gm-pill, gm-pill-blocked" text="BLOCKED" /> | ||
| 90 | <Label maxWidth="1.7976931348623157E308" styleClass="gm-text-base, gm-font-medium, gm-text-ink" text="This account reached a negative balance. All trading actions are disabled and cannot be re-enabled — accounts cannot be topped up in Ex 2." wrapText="true" HBox.hgrow="ALWAYS" /> | ||
| 91 | </children> | ||
| 92 | </HBox> | ||
| 93 | <!-- Balance Chart Block --> | ||
| 94 | <VBox spacing="8.0"> | ||
| 95 | <children> | ||
| 96 | <HBox alignment="CENTER_LEFT"> | ||
| 97 | <children> | ||
| 98 | <Label styleClass="gm-text-base, gm-font-semibold, gm-text-ink" text="Account balance over time" /> | ||
| 99 | <Region HBox.hgrow="ALWAYS" /> | ||
| 100 | <Label styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" text="every trade, fee and payout" /> | ||
| 101 | </children> | ||
| 102 | </HBox> | ||
| 103 | <VBox styleClass="gm-card-panel2"> | ||
| 104 | <padding> | ||
| 105 | <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> | ||
| 106 | </padding> | ||
| 107 | <children> | ||
| 108 | <LineChart fx:id="balanceChart" animated="false" createSymbols="false" horizontalGridLinesVisible="true" legendVisible="false" prefHeight="170.0" styleClass="gm-chart, gm-chart-single" verticalGridLinesVisible="false"> | ||
| 109 | <xAxis> | ||
| 110 | <NumberAxis autoRanging="false" forceZeroInRange="false" minorTickVisible="false" styleClass="gm-chart-axis" tickLabelsVisible="true" tickMarkVisible="true" /> | ||
| 111 | </xAxis> | ||
| 112 | <yAxis> | ||
| 113 | <NumberAxis autoRanging="true" minorTickVisible="false" styleClass="gm-chart-axis" /> | ||
| 114 | </yAxis> | ||
| 115 | </LineChart> | ||
| 116 | </children> | ||
| 117 | </VBox> | ||
| 118 | </children> | ||
| 119 | </VBox> | ||
| 120 | <!-- Participation Table Block --> | ||
| 121 | <VBox spacing="7.0"> | ||
| 122 | <children> | ||
| 123 | <Label styleClass="gm-text-base, gm-font-semibold, gm-text-ink" text="Events participation / owner" /> | ||
| 124 | <VBox styleClass="gm-card-panel"> | ||
| 125 | <children> | ||
| 126 | <HBox alignment="CENTER_LEFT" spacing="8.0" styleClass="gm-bg-panel3"> | ||
| 127 | <padding> | ||
| 128 | <Insets bottom="8.0" left="11.0" right="11.0" top="8.0" /> | ||
| 129 | </padding> | ||
| 130 | <children> | ||
| 131 | <Label maxWidth="1.7976931348623157E308" minWidth="0.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Event" textOverrun="ELLIPSIS" HBox.hgrow="ALWAYS" /> | ||
| 132 | <Label minWidth="-Infinity" prefWidth="92.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Role" /> | ||
| 133 | <Label minWidth="-Infinity" prefWidth="78.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="Type" /> | ||
| 134 | <Label alignment="CENTER_RIGHT" minWidth="78.0" prefWidth="78.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="YES" /> | ||
| 135 | <Label alignment="CENTER_RIGHT" minWidth="78.0" prefWidth="78.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="NO" /> | ||
| 136 | <Label alignment="CENTER_RIGHT" minWidth="90.0" prefWidth="90.0" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" text="P/L" /> | ||
| 137 | </children> | ||
| 138 | </HBox> | ||
| 139 | <VBox fx:id="participationRowsContainer" /> | ||
| 140 | </children> | ||
| 141 | </VBox> | ||
| 142 | </children> | ||
| 143 | </VBox> | ||
| 144 | <!-- Trade Panel Block --> | ||
| 145 | <VBox fx:id="tradePanel" spacing="9.0" styleClass="gm-card-panel2"> | ||
| 146 | <padding> | ||
| 147 | <Insets bottom="13.0" left="14.0" right="14.0" top="13.0" /> | ||
| 148 | </padding> | ||
| 149 | <children> | ||
| 150 | <Label fx:id="noTradeEventLabel" styleClass="gm-text-base, gm-font-regular, gm-text-ink2" text="Select an event above to trade." visible="false" /> | ||
| 151 | <VBox fx:id="tradeContentBox" spacing="9.0"> | ||
| 152 | <children> | ||
| 153 | <HBox alignment="BASELINE_LEFT"> | ||
| 154 | <children> | ||
| 155 | <Label fx:id="tradeEventTitle" styleClass="gm-text-lg, gm-font-bold, gm-text-ink" /> | ||
| 156 | <Region HBox.hgrow="ALWAYS" /> | ||
| 157 | <Label fx:id="tradeEventSub" styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" /> | ||
| 158 | </children> | ||
| 159 | </HBox> | ||
| 160 | <HBox spacing="10.0"> | ||
| 161 | <children> | ||
| 162 | <VBox fx:id="tradeYesOptCard" onMouseClicked="#handleSelectTradeYes" spacing="6.0" styleClass="gm-option-card, gm-option-card-yes" HBox.hgrow="ALWAYS"> | ||
| 163 | <padding> | ||
| 164 | <Insets bottom="10.0" left="12.0" right="12.0" top="10.0" /> | ||
| 165 | </padding> | ||
| 166 | <children> | ||
| 167 | <HBox alignment="CENTER_LEFT"> | ||
| 168 | <children> | ||
| 169 | <Label styleClass="gm-text-md, gm-font-bold, gm-text-yes" text="YES" /> | ||
| 170 | <Region HBox.hgrow="ALWAYS" /> | ||
| 171 | <Label fx:id="tradeYesPriceLabel" styleClass="gm-text-xl, gm-font-semibold, gm-font-mono, gm-text-yes" /> | ||
| 172 | </children> | ||
| 173 | </HBox> | ||
| 174 | <Label fx:id="tradeYesHeldLabel" styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" /> | ||
| 175 | </children> | ||
| 176 | </VBox> | ||
| 177 | <VBox fx:id="tradeNoOptCard" onMouseClicked="#handleSelectTradeNo" spacing="6.0" styleClass="gm-option-card, gm-option-card-no" HBox.hgrow="ALWAYS"> | ||
| 178 | <padding> | ||
| 179 | <Insets bottom="10.0" left="12.0" right="12.0" top="10.0" /> | ||
| 180 | </padding> | ||
| 181 | <children> | ||
| 182 | <HBox alignment="CENTER_LEFT"> | ||
| 183 | <children> | ||
| 184 | <Label styleClass="gm-text-md, gm-font-bold, gm-text-no" text="NO" /> | ||
| 185 | <Region HBox.hgrow="ALWAYS" /> | ||
| 186 | <Label fx:id="tradeNoPriceLabel" styleClass="gm-text-xl, gm-font-semibold, gm-font-mono, gm-text-no" /> | ||
| 187 | </children> | ||
| 188 | </HBox> | ||
| 189 | <Label fx:id="tradeNoHeldLabel" styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" /> | ||
| 190 | </children> | ||
| 191 | </VBox> | ||
| 192 | </children> | ||
| 193 | </HBox> | ||
| 194 | <FlowPane alignment="BOTTOM_LEFT" hgap="10.0" vgap="10.0"> | ||
| 195 | <children> | ||
| 196 | <VBox spacing="5.0"> | ||
| 197 | <children> | ||
| 198 | <Label styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Action" /> | ||
| 199 | <HBox> | ||
| 200 | <children> | ||
| 201 | <Button fx:id="tradeBuyBtn" onAction="#handleTradeBuy" styleClass="gm-seg, gm-seg-left, gm-seg-pad-wide" text="Buy" /> | ||
| 202 | <Button fx:id="tradeSellBtn" onAction="#handleTradeSell" styleClass="gm-seg, gm-seg-right, gm-seg-pad-wide" text="Sell" /> | ||
| 203 | </children> | ||
| 204 | </HBox> | ||
| 205 | </children> | ||
| 206 | </VBox> | ||
| 207 | <VBox spacing="5.0"> | ||
| 208 | <children> | ||
| 209 | <Label styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Shares" /> | ||
| 210 | <TextField fx:id="tradeQtyField" prefWidth="96.0" styleClass="gm-textfield, gm-textfield-mono" /> | ||
| 211 | </children> | ||
| 212 | </VBox> | ||
| 213 | <VBox spacing="5.0"> | ||
| 214 | <children> | ||
| 215 | <Label styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Price / share" /> | ||
| 216 | <TextField fx:id="tradePriceField" prefWidth="96.0" styleClass="gm-textfield, gm-textfield-mono" /> | ||
| 217 | </children> | ||
| 218 | </VBox> | ||
| 219 | <VBox spacing="5.0"> | ||
| 220 | <children> | ||
| 221 | <Label styleClass="gm-text-base, gm-font-medium, gm-text-ink2" text="Estimated cost" /> | ||
| 222 | <Label fx:id="tradeCostLabel" styleClass="gm-text-lg, gm-font-semibold, gm-font-mono, gm-text-ink" /> | ||
| 223 | </children> | ||
| 224 | </VBox> | ||
| 225 | <Button fx:id="tradeSubmitBtn" onAction="#handleTradeSubmit" styleClass="gm-btn, gm-btn-primary" /> | ||
| 226 | </children> | ||
| 227 | </FlowPane> | ||
| 228 | <Label fx:id="tradeHintLabel" styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" wrapText="true" /> | ||
| 229 | </children> | ||
| 230 | </VBox> | ||
| 231 | </children> | ||
| 232 | </VBox> | ||
| 233 | </children> | ||
| 234 | </VBox> | ||
| 235 | </content> | ||
| 236 | </ScrollPane> | ||
| 237 | </children> | ||
| 238 | </VBox> | ||
| 239 | </children> | ||
| 240 | </HBox> | ||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/event_list_item.fxml b/ui-desktop/src/main/resources/market/guess/ui/desktop/event_list_item.fxml new file mode 100644 index 0000000..9d82c4a --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/event_list_item.fxml | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | |||
| 3 | <?import javafx.geometry.Insets?> | ||
| 4 | <?import javafx.scene.control.Label?> | ||
| 5 | <?import javafx.scene.layout.HBox?> | ||
| 6 | <?import javafx.scene.layout.Region?> | ||
| 7 | <?import javafx.scene.layout.VBox?> | ||
| 8 | |||
| 9 | <fx:root type="javafx.scene.layout.VBox" spacing="5.0" styleClass="gm-list-row" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1"> | ||
| 10 | <padding> | ||
| 11 | <Insets bottom="9.0" left="11.0" right="11.0" top="9.0" /> | ||
| 12 | </padding> | ||
| 13 | <children> | ||
| 14 | <HBox alignment="CENTER_LEFT" spacing="6.0"> | ||
| 15 | <children> | ||
| 16 | <Label fx:id="numLabel" styleClass="gm-text-xs, gm-font-semibold, gm-text-ink2, gm-font-mono" /> | ||
| 17 | <Label fx:id="titleLabel" maxWidth="1.7976931348623157E308" styleClass="gm-text-md, gm-font-semibold, gm-text-ink" textOverrun="ELLIPSIS" HBox.hgrow="ALWAYS" /> | ||
| 18 | </children> | ||
| 19 | </HBox> | ||
| 20 | <HBox alignment="CENTER_LEFT" spacing="8.0"> | ||
| 21 | <children> | ||
| 22 | <Label fx:id="typeLabel" styleClass="gm-text-xs, gm-font-medium, gm-text-ink2" /> | ||
| 23 | <Label fx:id="statusLabel" styleClass="gm-pill" /> | ||
| 24 | <Label fx:id="feeLabel" minWidth="0.0" styleClass="gm-text-xs, gm-font-medium, gm-text-ink2" textOverrun="ELLIPSIS" /> | ||
| 25 | <Region HBox.hgrow="ALWAYS" /> | ||
| 26 | <Label fx:id="contractLabel" alignment="CENTER_RIGHT" styleClass="gm-text-xs, gm-font-semibold, gm-font-mono, gm-text-accent" /> | ||
| 27 | </children> | ||
| 28 | </HBox> | ||
| 29 | </children> | ||
| 30 | </fx:root> | ||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/CaskaydiaCoveNerdFont-Bold.ttf b/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/CaskaydiaCoveNerdFont-Bold.ttf new file mode 100644 index 0000000..be823bf --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/CaskaydiaCoveNerdFont-Bold.ttf | |||
| Binary files differ | |||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/CaskaydiaCoveNerdFont-Regular.ttf b/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/CaskaydiaCoveNerdFont-Regular.ttf new file mode 100644 index 0000000..013a15b --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/CaskaydiaCoveNerdFont-Regular.ttf | |||
| Binary files differ | |||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/FiraCodeNerdFont-Bold.ttf b/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/FiraCodeNerdFont-Bold.ttf new file mode 100644 index 0000000..ed37330 --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/FiraCodeNerdFont-Bold.ttf | |||
| Binary files differ | |||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/FiraCodeNerdFont-Regular.ttf b/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/FiraCodeNerdFont-Regular.ttf new file mode 100644 index 0000000..3fd04ba --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/FiraCodeNerdFont-Regular.ttf | |||
| Binary files differ | |||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/JetBrainsMonoNerdFont-Bold.ttf b/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/JetBrainsMonoNerdFont-Bold.ttf new file mode 100644 index 0000000..de2d3b3 --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/JetBrainsMonoNerdFont-Bold.ttf | |||
| Binary files differ | |||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/JetBrainsMonoNerdFont-Regular.ttf b/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/JetBrainsMonoNerdFont-Regular.ttf new file mode 100644 index 0000000..235a07a --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/fonts/JetBrainsMonoNerdFont-Regular.ttf | |||
| Binary files differ | |||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/ladder_item.fxml b/ui-desktop/src/main/resources/market/guess/ui/desktop/ladder_item.fxml new file mode 100644 index 0000000..7516d5b --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/ladder_item.fxml | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | |||
| 3 | <?import javafx.geometry.Insets?> | ||
| 4 | <?import javafx.scene.control.Label?> | ||
| 5 | <?import javafx.scene.layout.HBox?> | ||
| 6 | <?import javafx.scene.layout.Priority?> | ||
| 7 | |||
| 8 | <fx:root type="javafx.scene.layout.HBox" alignment="CENTER_LEFT" spacing="8.0" styleClass="gm-ladder-row" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1"> | ||
| 9 | <padding> | ||
| 10 | <Insets bottom="3.0" left="12.0" right="12.0" top="3.0" /> | ||
| 11 | </padding> | ||
| 12 | <children> | ||
| 13 | <Label fx:id="priceLabel" alignment="CENTER_RIGHT" minWidth="54.0" prefWidth="54.0" styleClass="gm-text-xs, gm-font-mono, gm-text-ink2" /> | ||
| 14 | <Label fx:id="sideLabel" alignment="CENTER_RIGHT" minWidth="50.0" prefWidth="50.0" styleClass="gm-text-xs, gm-font-mono, gm-text-ink2" /> | ||
| 15 | <Label fx:id="qtyLabel" alignment="CENTER_RIGHT" minWidth="50.0" prefWidth="50.0" styleClass="gm-text-xs, gm-font-mono, gm-text-ink2" /> | ||
| 16 | <Label fx:id="userLabel" maxWidth="1.7976931348623157E308" minWidth="0.0" styleClass="gm-text-xs, gm-font-medium, gm-text-ink2" textOverrun="ELLIPSIS" HBox.hgrow="ALWAYS" /> | ||
| 17 | </children> | ||
| 18 | </fx:root> | ||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/participant_item.fxml b/ui-desktop/src/main/resources/market/guess/ui/desktop/participant_item.fxml new file mode 100644 index 0000000..840bacb --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/participant_item.fxml | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | |||
| 3 | <?import javafx.geometry.Insets?> | ||
| 4 | <?import javafx.scene.control.Label?> | ||
| 5 | <?import javafx.scene.layout.HBox?> | ||
| 6 | <?import javafx.scene.layout.Priority?> | ||
| 7 | |||
| 8 | <fx:root type="javafx.scene.layout.HBox" alignment="CENTER_LEFT" spacing="8.0" styleClass="gm-divider-top" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1"> | ||
| 9 | <padding> | ||
| 10 | <Insets bottom="7.0" left="11.0" right="11.0" top="7.0" /> | ||
| 11 | </padding> | ||
| 12 | <children> | ||
| 13 | <Label fx:id="userLabel" maxWidth="1.7976931348623157E308" minWidth="0.0" styleClass="gm-text-sm, gm-font-medium, gm-text-ink" textOverrun="ELLIPSIS" HBox.hgrow="ALWAYS" /> | ||
| 14 | <Label fx:id="yesLabel" alignment="CENTER_RIGHT" minWidth="84.0" prefWidth="84.0" styleClass="gm-text-sm, gm-font-mono, gm-text-ink2" /> | ||
| 15 | <Label fx:id="noLabel" alignment="CENTER_RIGHT" minWidth="84.0" prefWidth="84.0" styleClass="gm-text-sm, gm-font-mono, gm-text-ink2" /> | ||
| 16 | <Label fx:id="valueLabel" alignment="CENTER_RIGHT" minWidth="96.0" prefWidth="96.0" styleClass="gm-text-sm, gm-font-mono, gm-text-ink2" /> | ||
| 17 | <Label fx:id="feesLabel" alignment="CENTER_RIGHT" minWidth="96.0" prefWidth="96.0" styleClass="gm-text-sm, gm-font-mono, gm-text-ink2" /> | ||
| 18 | </children> | ||
| 19 | </fx:root> | ||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/theme.css b/ui-desktop/src/main/resources/market/guess/ui/desktop/theme.css new file mode 100644 index 0000000..f2616a3 --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/theme.css | |||
| @@ -0,0 +1,926 @@ | |||
| 1 | /* Guess Market desktop UI stylesheet. | ||
| 2 | * | ||
| 3 | * PALETTES & TYPOGRAPHY: | ||
| 4 | * Each skin class (.gm-skin-*) defines its own looked-up color variables (-gm-*) | ||
| 5 | * and root font-family. AppView puts exactly one skin class on the scene root, | ||
| 6 | * allowing all child rules to automatically cascade and re-resolve without | ||
| 7 | * requiring any inline CSS or manual style-string construction in Java. | ||
| 8 | * | ||
| 9 | * BUNDLED NERD FONTS: | ||
| 10 | * - Rosé Pine Dawn -> CaskaydiaCove Nerd Font (CaskaydiaCove NF) | ||
| 11 | * - Catppuccin -> JetBrainsMono Nerd Font (JetBrainsMono NF) | ||
| 12 | * - Gruvbox -> FiraCode Nerd Font (FiraCode Nerd Font) | ||
| 13 | */ | ||
| 14 | |||
| 15 | @font-face { | ||
| 16 | font-family: 'CaskaydiaCove NF'; | ||
| 17 | src: url('fonts/CaskaydiaCoveNerdFont-Regular.ttf'); | ||
| 18 | } | ||
| 19 | @font-face { | ||
| 20 | font-family: 'CaskaydiaCove NF'; | ||
| 21 | font-weight: bold; | ||
| 22 | src: url('fonts/CaskaydiaCoveNerdFont-Bold.ttf'); | ||
| 23 | } | ||
| 24 | |||
| 25 | @font-face { | ||
| 26 | font-family: 'JetBrainsMono NF'; | ||
| 27 | src: url('fonts/JetBrainsMonoNerdFont-Regular.ttf'); | ||
| 28 | } | ||
| 29 | @font-face { | ||
| 30 | font-family: 'JetBrainsMono NF'; | ||
| 31 | font-weight: bold; | ||
| 32 | src: url('fonts/JetBrainsMonoNerdFont-Bold.ttf'); | ||
| 33 | } | ||
| 34 | |||
| 35 | @font-face { | ||
| 36 | font-family: 'FiraCode Nerd Font'; | ||
| 37 | src: url('fonts/FiraCodeNerdFont-Regular.ttf'); | ||
| 38 | } | ||
| 39 | @font-face { | ||
| 40 | font-family: 'FiraCode Nerd Font'; | ||
| 41 | font-weight: bold; | ||
| 42 | src: url('fonts/FiraCodeNerdFont-Bold.ttf'); | ||
| 43 | } | ||
| 44 | |||
| 45 | /* rose-pine.dev/palette/#dawn — base/surface/overlay/highlight, iris accent, pine/love for yes/no */ | ||
| 46 | .gm-root, | ||
| 47 | .gm-root:skin-rose-pine-dawn, | ||
| 48 | .gm-skin-rose-pine-dawn { | ||
| 49 | -fx-font-family: "CaskaydiaCove NF", "CaskaydiaCove Nerd Font", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; | ||
| 50 | -fx-font-size: 13px; | ||
| 51 | -gm-bg: #faf4ed; | ||
| 52 | -gm-panel: #fffaf3; | ||
| 53 | -gm-panel2: #f2e9e1; | ||
| 54 | -gm-panel3: #dfdad9; | ||
| 55 | -gm-line: #cecacd; | ||
| 56 | -gm-ink: #575279; | ||
| 57 | -gm-ink2: #797593; | ||
| 58 | -gm-accent: #907aa9; | ||
| 59 | -gm-accent-fg: #fffaf3; | ||
| 60 | -gm-btn: #f2e9e1; | ||
| 61 | -gm-btn-line: #cecacd; | ||
| 62 | -gm-yes: #286983; | ||
| 63 | -gm-no: #b4637a; | ||
| 64 | -gm-yes-soft: #e3edf0; | ||
| 65 | -gm-no-soft: #f5e6ea; | ||
| 66 | } | ||
| 67 | |||
| 68 | /* catppuccin.com Mocha — mantle/base/surface, mauve accent, green/red for yes/no */ | ||
| 69 | .gm-root:skin-catppuccin, | ||
| 70 | .gm-skin-catppuccin { | ||
| 71 | -fx-font-family: "JetBrainsMono NF", "JetBrainsMono Nerd Font", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; | ||
| 72 | -fx-font-size: 13px; | ||
| 73 | -gm-bg: #181825; | ||
| 74 | -gm-panel: #1e1e2e; | ||
| 75 | -gm-panel2: #313244; | ||
| 76 | -gm-panel3: #45475a; | ||
| 77 | -gm-line: #585b70; | ||
| 78 | -gm-ink: #cdd6f4; | ||
| 79 | -gm-ink2: #a6adc8; | ||
| 80 | -gm-accent: #cba6f7; | ||
| 81 | -gm-accent-fg: #1e1e2e; | ||
| 82 | -gm-btn: #313244; | ||
| 83 | -gm-btn-line: #585b70; | ||
| 84 | -gm-yes: #a6e3a1; | ||
| 85 | -gm-no: #f38ba8; | ||
| 86 | -gm-yes-soft: #23312a; | ||
| 87 | -gm-no-soft: #34232c; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* gruvbox dark (hard) — bg0_h/bg0/bg1/bg2, bright orange accent, bright green/red */ | ||
| 91 | .gm-root:skin-gruvbox, | ||
| 92 | .gm-skin-gruvbox { | ||
| 93 | -fx-font-family: "FiraCode Nerd Font", "FiraCode NF", Consolas, "Liberation Mono", Menlo, monospace; | ||
| 94 | -fx-font-size: 13.5px; | ||
| 95 | -gm-bg: #1d2021; | ||
| 96 | -gm-panel: #282828; | ||
| 97 | -gm-panel2: #3c3836; | ||
| 98 | -gm-panel3: #504945; | ||
| 99 | -gm-line: #665c54; | ||
| 100 | -gm-ink: #ebdbb2; | ||
| 101 | -gm-ink2: #a89984; | ||
| 102 | -gm-accent: #fe8019; | ||
| 103 | -gm-accent-fg: #1d2021; | ||
| 104 | -gm-btn: #3c3836; | ||
| 105 | -gm-btn-line: #665c54; | ||
| 106 | -gm-yes: #b8bb26; | ||
| 107 | -gm-no: #fb4934; | ||
| 108 | -gm-yes-soft: #2b3021; | ||
| 109 | -gm-no-soft: #3b2320; | ||
| 110 | } | ||
| 111 | |||
| 112 | /* ---- typography & text fills ------------------------------------------ */ | ||
| 113 | |||
| 114 | .root { | ||
| 115 | -fx-text-fill: -gm-ink; | ||
| 116 | } | ||
| 117 | |||
| 118 | .gm-text-ink { -fx-text-fill: -gm-ink; } | ||
| 119 | .gm-text-ink2 { -fx-text-fill: -gm-ink2; } | ||
| 120 | .gm-text-accent { -fx-text-fill: -gm-accent; } | ||
| 121 | .gm-text-accent-fg { -fx-text-fill: -gm-accent-fg; } | ||
| 122 | .gm-text-yes { -fx-text-fill: -gm-yes; } | ||
| 123 | .gm-text-no { -fx-text-fill: -gm-no; } | ||
| 124 | |||
| 125 | .gm-font-mono, | ||
| 126 | .gm-textfield-mono, | ||
| 127 | .gm-pill, | ||
| 128 | .gm-user-balance, | ||
| 129 | .gm-balance-cell, | ||
| 130 | .gm-pnl-cell, | ||
| 131 | .gm-chart-axis, | ||
| 132 | .gm-anim-tick { | ||
| 133 | -fx-font-family: "CaskaydiaCove NF", "JetBrainsMono NF", "FiraCode Nerd Font", monospace; | ||
| 134 | } | ||
| 135 | |||
| 136 | .gm-root:skin-rose-pine-dawn .gm-font-mono, | ||
| 137 | .gm-skin-rose-pine-dawn .gm-font-mono, | ||
| 138 | .gm-root:skin-rose-pine-dawn .gm-textfield-mono, | ||
| 139 | .gm-skin-rose-pine-dawn .gm-textfield-mono, | ||
| 140 | .gm-root:skin-rose-pine-dawn .gm-pill, | ||
| 141 | .gm-skin-rose-pine-dawn .gm-pill, | ||
| 142 | .gm-root:skin-rose-pine-dawn .gm-user-balance, | ||
| 143 | .gm-skin-rose-pine-dawn .gm-user-balance, | ||
| 144 | .gm-root:skin-rose-pine-dawn .gm-balance-cell, | ||
| 145 | .gm-skin-rose-pine-dawn .gm-balance-cell, | ||
| 146 | .gm-root:skin-rose-pine-dawn .gm-pnl-cell, | ||
| 147 | .gm-skin-rose-pine-dawn .gm-pnl-cell, | ||
| 148 | .gm-root:skin-rose-pine-dawn .gm-chart-axis, | ||
| 149 | .gm-skin-rose-pine-dawn .gm-chart-axis, | ||
| 150 | .gm-root:skin-rose-pine-dawn .gm-anim-tick, | ||
| 151 | .gm-skin-rose-pine-dawn .gm-anim-tick { | ||
| 152 | -fx-font-family: "CaskaydiaCove NF", "CaskaydiaCove Nerd Font", monospace; | ||
| 153 | } | ||
| 154 | |||
| 155 | .gm-root:skin-catppuccin .gm-font-mono, | ||
| 156 | .gm-skin-catppuccin .gm-font-mono, | ||
| 157 | .gm-root:skin-catppuccin .gm-textfield-mono, | ||
| 158 | .gm-skin-catppuccin .gm-textfield-mono, | ||
| 159 | .gm-root:skin-catppuccin .gm-pill, | ||
| 160 | .gm-skin-catppuccin .gm-pill, | ||
| 161 | .gm-root:skin-catppuccin .gm-user-balance, | ||
| 162 | .gm-skin-catppuccin .gm-user-balance, | ||
| 163 | .gm-root:skin-catppuccin .gm-balance-cell, | ||
| 164 | .gm-skin-catppuccin .gm-balance-cell, | ||
| 165 | .gm-root:skin-catppuccin .gm-pnl-cell, | ||
| 166 | .gm-skin-catppuccin .gm-pnl-cell, | ||
| 167 | .gm-root:skin-catppuccin .gm-chart-axis, | ||
| 168 | .gm-skin-catppuccin .gm-chart-axis, | ||
| 169 | .gm-root:skin-catppuccin .gm-anim-tick, | ||
| 170 | .gm-skin-catppuccin .gm-anim-tick { | ||
| 171 | -fx-font-family: "JetBrainsMono NF", "JetBrainsMono Nerd Font", monospace; | ||
| 172 | } | ||
| 173 | |||
| 174 | .gm-root:skin-gruvbox .gm-font-mono, | ||
| 175 | .gm-skin-gruvbox .gm-font-mono, | ||
| 176 | .gm-root:skin-gruvbox .gm-textfield-mono, | ||
| 177 | .gm-skin-gruvbox .gm-textfield-mono, | ||
| 178 | .gm-root:skin-gruvbox .gm-pill, | ||
| 179 | .gm-skin-gruvbox .gm-pill, | ||
| 180 | .gm-root:skin-gruvbox .gm-user-balance, | ||
| 181 | .gm-skin-gruvbox .gm-user-balance, | ||
| 182 | .gm-root:skin-gruvbox .gm-balance-cell, | ||
| 183 | .gm-skin-gruvbox .gm-balance-cell, | ||
| 184 | .gm-root:skin-gruvbox .gm-pnl-cell, | ||
| 185 | .gm-skin-gruvbox .gm-pnl-cell, | ||
| 186 | .gm-root:skin-gruvbox .gm-chart-axis, | ||
| 187 | .gm-skin-gruvbox .gm-chart-axis, | ||
| 188 | .gm-root:skin-gruvbox .gm-anim-tick, | ||
| 189 | .gm-skin-gruvbox .gm-anim-tick { | ||
| 190 | -fx-font-family: "FiraCode Nerd Font", "FiraCode NF", monospace; | ||
| 191 | } | ||
| 192 | .gm-font-bold { -fx-font-weight: 700; } | ||
| 193 | .gm-font-semibold { -fx-font-weight: 600; } | ||
| 194 | .gm-font-medium { -fx-font-weight: 500; } | ||
| 195 | .gm-font-regular { -fx-font-weight: 400; } | ||
| 196 | |||
| 197 | .gm-text-xs { -fx-font-size: 10.5px; } | ||
| 198 | .gm-text-sm { -fx-font-size: 11.5px; } | ||
| 199 | .gm-text-base { -fx-font-size: 12.5px; } | ||
| 200 | .gm-text-md { -fx-font-size: 13px; } | ||
| 201 | .gm-text-lg { -fx-font-size: 14px; } | ||
| 202 | .gm-text-xl { -fx-font-size: 17px; } | ||
| 203 | .gm-text-2xl { -fx-font-size: 22px; } | ||
| 204 | |||
| 205 | /* ---- window chrome & containers --------------------------------------- */ | ||
| 206 | |||
| 207 | .gm-chrome { | ||
| 208 | -fx-background-color: -gm-bg; | ||
| 209 | } | ||
| 210 | |||
| 211 | .gm-bg-panel { | ||
| 212 | -fx-background-color: -gm-panel; | ||
| 213 | } | ||
| 214 | |||
| 215 | .gm-bg-panel2 { | ||
| 216 | -fx-background-color: -gm-panel2; | ||
| 217 | } | ||
| 218 | |||
| 219 | .gm-bg-panel3 { | ||
| 220 | -fx-background-color: -gm-panel3; | ||
| 221 | } | ||
| 222 | |||
| 223 | .gm-card { | ||
| 224 | -fx-background-color: -gm-panel; | ||
| 225 | -fx-border-color: -gm-line; | ||
| 226 | -fx-border-width: 1; | ||
| 227 | -fx-background-radius: 7; | ||
| 228 | -fx-border-radius: 7; | ||
| 229 | } | ||
| 230 | |||
| 231 | .gm-card-panel2 { | ||
| 232 | -fx-background-color: -gm-panel2; | ||
| 233 | -fx-border-color: -gm-line; | ||
| 234 | -fx-border-width: 1; | ||
| 235 | -fx-background-radius: 6; | ||
| 236 | -fx-border-radius: 6; | ||
| 237 | } | ||
| 238 | |||
| 239 | .gm-card-panel { | ||
| 240 | -fx-background-color: -gm-panel; | ||
| 241 | -fx-border-color: -gm-line; | ||
| 242 | -fx-border-width: 1; | ||
| 243 | -fx-background-radius: 6; | ||
| 244 | -fx-border-radius: 6; | ||
| 245 | } | ||
| 246 | |||
| 247 | .gm-card-soft-yes { | ||
| 248 | -fx-background-color: -gm-yes-soft; | ||
| 249 | -fx-border-color: -gm-line; | ||
| 250 | -fx-border-width: 1; | ||
| 251 | -fx-background-radius: 6; | ||
| 252 | -fx-border-radius: 6; | ||
| 253 | } | ||
| 254 | |||
| 255 | .gm-card-soft-no { | ||
| 256 | -fx-background-color: -gm-no-soft; | ||
| 257 | -fx-border-color: -gm-line; | ||
| 258 | -fx-border-width: 1; | ||
| 259 | -fx-background-radius: 6; | ||
| 260 | -fx-border-radius: 6; | ||
| 261 | } | ||
| 262 | |||
| 263 | .gm-banner-blocked { | ||
| 264 | -fx-background-color: -gm-no-soft; | ||
| 265 | -fx-border-color: -gm-no; | ||
| 266 | -fx-border-width: 1; | ||
| 267 | -fx-background-radius: 6; | ||
| 268 | -fx-border-radius: 6; | ||
| 269 | } | ||
| 270 | |||
| 271 | .gm-banner-resolved { | ||
| 272 | -fx-background-color: -gm-yes-soft; | ||
| 273 | -fx-border-color: -gm-line; | ||
| 274 | -fx-border-width: 1; | ||
| 275 | -fx-background-radius: 6; | ||
| 276 | -fx-border-radius: 6; | ||
| 277 | } | ||
| 278 | |||
| 279 | .gm-divider-bottom { | ||
| 280 | -fx-border-color: transparent transparent -gm-line transparent; | ||
| 281 | -fx-border-width: 0 0 1 0; | ||
| 282 | } | ||
| 283 | |||
| 284 | .gm-divider-top { | ||
| 285 | -fx-border-color: -gm-line transparent transparent transparent; | ||
| 286 | -fx-border-width: 1 0 0 0; | ||
| 287 | } | ||
| 288 | |||
| 289 | .gm-hline { | ||
| 290 | -fx-background-color: -gm-line; | ||
| 291 | -fx-pref-height: 1; | ||
| 292 | -fx-min-height: 1; | ||
| 293 | } | ||
| 294 | |||
| 295 | /* ---- buttons & interactive controls ----------------------------------- */ | ||
| 296 | |||
| 297 | .gm-btn { | ||
| 298 | -fx-border-width: 1; | ||
| 299 | -fx-background-radius: 5; | ||
| 300 | -fx-border-radius: 5; | ||
| 301 | -fx-font-size: 13px; | ||
| 302 | -fx-font-weight: 600; | ||
| 303 | -fx-padding: 8 15; | ||
| 304 | -fx-cursor: hand; | ||
| 305 | } | ||
| 306 | |||
| 307 | .gm-btn:hover { | ||
| 308 | -fx-opacity: 0.92; | ||
| 309 | } | ||
| 310 | |||
| 311 | .gm-btn:disabled { | ||
| 312 | -fx-opacity: 0.45; | ||
| 313 | -fx-cursor: default; | ||
| 314 | } | ||
| 315 | |||
| 316 | .gm-btn-primary { | ||
| 317 | -fx-background-color: -gm-accent; | ||
| 318 | -fx-text-fill: -gm-accent-fg; | ||
| 319 | -fx-border-color: -gm-accent; | ||
| 320 | } | ||
| 321 | |||
| 322 | .gm-btn-secondary { | ||
| 323 | -fx-background-color: -gm-btn; | ||
| 324 | -fx-text-fill: -gm-ink; | ||
| 325 | -fx-border-color: -gm-btn-line; | ||
| 326 | } | ||
| 327 | |||
| 328 | .gm-btn-destructive { | ||
| 329 | -fx-background-color: -gm-no; | ||
| 330 | -fx-text-fill: -gm-accent-fg; | ||
| 331 | -fx-border-color: -gm-no; | ||
| 332 | -fx-border-width: 1; | ||
| 333 | -fx-background-radius: 5; | ||
| 334 | -fx-border-radius: 5; | ||
| 335 | -fx-font-size: 12.5px; | ||
| 336 | -fx-font-weight: 600; | ||
| 337 | -fx-padding: 9 17; | ||
| 338 | -fx-cursor: hand; | ||
| 339 | } | ||
| 340 | |||
| 341 | .gm-btn-destructive:disabled { | ||
| 342 | -fx-opacity: 0.5; | ||
| 343 | -fx-cursor: default; | ||
| 344 | } | ||
| 345 | |||
| 346 | .gm-app-scroll, | ||
| 347 | .gm-app-scroll > .viewport { | ||
| 348 | -fx-background-color: transparent; | ||
| 349 | -fx-background-insets: 0; | ||
| 350 | -fx-padding: 0; | ||
| 351 | } | ||
| 352 | |||
| 353 | .gm-tabs > .tab-header-area { | ||
| 354 | -fx-padding: 6 16 0 16; | ||
| 355 | } | ||
| 356 | |||
| 357 | .gm-tabs > .tab-header-area > .tab-header-background { | ||
| 358 | -fx-background-color: -gm-line, -gm-panel; | ||
| 359 | -fx-background-insets: 0, 0 0 1 0; | ||
| 360 | } | ||
| 361 | |||
| 362 | .gm-tabs > .tab-content-area { | ||
| 363 | -fx-background-color: transparent; | ||
| 364 | } | ||
| 365 | |||
| 366 | .gm-tabs > .tab-header-area > .headers-region > .tab { | ||
| 367 | -fx-background-color: -gm-panel2; | ||
| 368 | -fx-background-insets: 0 1 0 1; | ||
| 369 | -fx-border-color: -gm-line; | ||
| 370 | -fx-border-width: 1 1 0 1; | ||
| 371 | -fx-border-insets: 0 1 0 1; | ||
| 372 | -fx-background-radius: 6 6 0 0; | ||
| 373 | -fx-border-radius: 6 6 0 0; | ||
| 374 | -fx-padding: 9 20; | ||
| 375 | -fx-cursor: hand; | ||
| 376 | } | ||
| 377 | |||
| 378 | .gm-tabs > .tab-header-area > .headers-region > .tab:selected { | ||
| 379 | -fx-background-color: -gm-bg; | ||
| 380 | } | ||
| 381 | |||
| 382 | .gm-tabs > .tab-header-area > .headers-region > .tab .tab-label { | ||
| 383 | -fx-text-fill: -gm-ink2; | ||
| 384 | -fx-font-size: 13px; | ||
| 385 | -fx-font-weight: 600; | ||
| 386 | } | ||
| 387 | |||
| 388 | .gm-tabs > .tab-header-area > .headers-region > .tab:selected .tab-label { | ||
| 389 | -fx-text-fill: -gm-ink; | ||
| 390 | } | ||
| 391 | |||
| 392 | .gm-tabs > .tab-header-area > .headers-region > .tab:selected .focus-indicator { | ||
| 393 | -fx-border-color: transparent; | ||
| 394 | } | ||
| 395 | |||
| 396 | .gm-toggle { | ||
| 397 | -fx-background-color: -gm-btn; | ||
| 398 | -fx-text-fill: -gm-ink2; | ||
| 399 | -fx-border-color: -gm-btn-line; | ||
| 400 | -fx-border-width: 1; | ||
| 401 | -fx-background-radius: 4; | ||
| 402 | -fx-border-radius: 4; | ||
| 403 | -fx-font-size: 12px; | ||
| 404 | -fx-font-weight: 500; | ||
| 405 | -fx-padding: 5 11; | ||
| 406 | -fx-cursor: hand; | ||
| 407 | } | ||
| 408 | |||
| 409 | .gm-toggle:selected { | ||
| 410 | -fx-background-color: -gm-accent; | ||
| 411 | -fx-text-fill: -gm-accent-fg; | ||
| 412 | -fx-border-color: -gm-accent; | ||
| 413 | } | ||
| 414 | |||
| 415 | .gm-seg { | ||
| 416 | -fx-background-color: -gm-btn; | ||
| 417 | -fx-text-fill: -gm-ink; | ||
| 418 | -fx-border-color: -gm-btn-line; | ||
| 419 | -fx-border-width: 1; | ||
| 420 | -fx-font-size: 12px; | ||
| 421 | -fx-font-weight: 600; | ||
| 422 | -fx-cursor: hand; | ||
| 423 | } | ||
| 424 | |||
| 425 | .gm-seg:selected { | ||
| 426 | -fx-background-color: -gm-accent; | ||
| 427 | -fx-text-fill: -gm-accent-fg; | ||
| 428 | } | ||
| 429 | |||
| 430 | .gm-seg:disabled { | ||
| 431 | -fx-opacity: 0.45; | ||
| 432 | -fx-cursor: default; | ||
| 433 | } | ||
| 434 | |||
| 435 | .gm-seg-left { | ||
| 436 | -fx-background-radius: 5 0 0 5; | ||
| 437 | -fx-border-radius: 5 0 0 5; | ||
| 438 | } | ||
| 439 | |||
| 440 | .gm-seg-right { | ||
| 441 | -fx-background-radius: 0 5 5 0; | ||
| 442 | -fx-border-radius: 0 5 5 0; | ||
| 443 | } | ||
| 444 | |||
| 445 | .gm-seg-pad-tight { | ||
| 446 | -fx-padding: 8 0; | ||
| 447 | } | ||
| 448 | |||
| 449 | .gm-seg-pad-wide { | ||
| 450 | -fx-padding: 8 15; | ||
| 451 | } | ||
| 452 | |||
| 453 | .gm-textfield { | ||
| 454 | -fx-background-color: -gm-panel2; | ||
| 455 | -fx-border-color: -gm-btn-line; | ||
| 456 | -fx-border-width: 1; | ||
| 457 | -fx-background-radius: 5; | ||
| 458 | -fx-border-radius: 5; | ||
| 459 | -fx-font-size: 13px; | ||
| 460 | -fx-text-fill: -gm-ink; | ||
| 461 | -fx-padding: 8 10; | ||
| 462 | } | ||
| 463 | |||
| 464 | .gm-textfield:disabled { | ||
| 465 | -fx-opacity: 0.45; | ||
| 466 | } | ||
| 467 | |||
| 468 | .gm-textfield:error, | ||
| 469 | .gm-textfield.error { | ||
| 470 | -fx-border-color: -gm-no; | ||
| 471 | -fx-border-width: 1.5; | ||
| 472 | } | ||
| 473 | |||
| 474 | .gm-textfield-mono { | ||
| 475 | -fx-font-family: "CaskaydiaCove NF", "JetBrainsMono NF", "FiraCode Nerd Font", monospace; | ||
| 476 | } | ||
| 477 | |||
| 478 | .gm-textarea { | ||
| 479 | -fx-control-inner-background: -gm-panel2; | ||
| 480 | -fx-border-color: -gm-btn-line; | ||
| 481 | -fx-border-radius: 5; | ||
| 482 | -fx-background-radius: 5; | ||
| 483 | -fx-font-size: 13px; | ||
| 484 | -fx-text-fill: -gm-ink; | ||
| 485 | } | ||
| 486 | |||
| 487 | .gm-select-base { | ||
| 488 | -fx-border-color: -gm-btn-line; | ||
| 489 | -fx-border-radius: 5; | ||
| 490 | -fx-background-radius: 5; | ||
| 491 | -fx-font-size: 12.5px; | ||
| 492 | -fx-text-base-color: -gm-ink; | ||
| 493 | } | ||
| 494 | |||
| 495 | .gm-select-btn-bg { | ||
| 496 | -fx-background-color: -gm-btn; | ||
| 497 | } | ||
| 498 | |||
| 499 | .gm-select-panel2-bg { | ||
| 500 | -fx-background-color: -gm-panel2; | ||
| 501 | } | ||
| 502 | |||
| 503 | .gm-checkbox { | ||
| 504 | -fx-text-fill: -gm-ink2; | ||
| 505 | -fx-font-size: 12.5px; | ||
| 506 | } | ||
| 507 | |||
| 508 | .gm-checkbox-strong { | ||
| 509 | -fx-text-fill: -gm-ink; | ||
| 510 | -fx-font-size: 12.5px; | ||
| 511 | } | ||
| 512 | |||
| 513 | .gm-link-button { | ||
| 514 | -fx-background-color: transparent; | ||
| 515 | -fx-text-fill: -gm-ink2; | ||
| 516 | -fx-font-size: 14.5px; | ||
| 517 | -fx-underline: false; | ||
| 518 | -fx-cursor: hand; | ||
| 519 | -fx-border-width: 0; | ||
| 520 | } | ||
| 521 | |||
| 522 | .gm-toast { | ||
| 523 | -fx-background-color: -gm-ink; | ||
| 524 | -fx-text-fill: -gm-bg; | ||
| 525 | -fx-background-radius: 6; | ||
| 526 | -fx-padding: 10 16; | ||
| 527 | -fx-font-size: 12.5px; | ||
| 528 | -fx-font-weight: 600; | ||
| 529 | } | ||
| 530 | |||
| 531 | .gm-scroll-transparent { | ||
| 532 | -fx-background-color: transparent; | ||
| 533 | -fx-background: transparent; | ||
| 534 | } | ||
| 535 | |||
| 536 | .gm-scroll-transparent > .viewport { | ||
| 537 | -fx-background-color: transparent; | ||
| 538 | } | ||
| 539 | |||
| 540 | /* ---- badges, pills, traffic lights ------------------------------------ */ | ||
| 541 | |||
| 542 | .gm-pill { | ||
| 543 | -fx-background-radius: 3; | ||
| 544 | -fx-padding: 3 6; | ||
| 545 | -fx-font-family: "CaskaydiaCove NF", "JetBrainsMono NF", "FiraCode Nerd Font", monospace; | ||
| 546 | -fx-font-size: 10px; | ||
| 547 | -fx-font-weight: 600; | ||
| 548 | -fx-background-color: -gm-panel3; | ||
| 549 | -fx-text-fill: -gm-ink2; | ||
| 550 | } | ||
| 551 | |||
| 552 | /* Pseudo-class states for pills */ | ||
| 553 | .gm-pill:active { -fx-background-color: -gm-yes-soft; -fx-text-fill: -gm-yes; } | ||
| 554 | .gm-pill:closed { -fx-background-color: -gm-no-soft; -fx-text-fill: -gm-no; } | ||
| 555 | .gm-pill:idle { -fx-background-color: -gm-panel3; -fx-text-fill: -gm-ink2; } | ||
| 556 | .gm-pill:blocked { -fx-background-color: -gm-no; -fx-text-fill: -gm-accent-fg; } | ||
| 557 | .gm-pill:mm { -fx-background-color: -gm-accent; -fx-text-fill: -gm-accent-fg; } | ||
| 558 | .gm-pill:trader { -fx-background-color: -gm-panel3; -fx-text-fill: -gm-ink2; } | ||
| 559 | .gm-pill:resolved { -fx-background-color: -gm-yes; -fx-text-fill: -gm-accent-fg; } | ||
| 560 | |||
| 561 | .gm-pill-active { -fx-background-color: -gm-yes-soft; -fx-text-fill: -gm-yes; } | ||
| 562 | .gm-pill-closed { -fx-background-color: -gm-no-soft; -fx-text-fill: -gm-no; } | ||
| 563 | .gm-pill-idle { -fx-background-color: -gm-panel3; -fx-text-fill: -gm-ink2; } | ||
| 564 | .gm-pill-blocked { -fx-background-color: -gm-no; -fx-text-fill: -gm-accent-fg; } | ||
| 565 | .gm-pill-mm { -fx-background-color: -gm-accent; -fx-text-fill: -gm-accent-fg; } | ||
| 566 | .gm-pill-trader { -fx-background-color: -gm-panel3; -fx-text-fill: -gm-ink2; } | ||
| 567 | .gm-pill-resolved { -fx-background-color: -gm-yes; -fx-text-fill: -gm-accent-fg; } | ||
| 568 | |||
| 569 | /* ---- user balance ---------------------------------------------------- */ | ||
| 570 | .gm-user-balance { | ||
| 571 | -fx-font-family: "CaskaydiaCove NF", "JetBrainsMono NF", "FiraCode Nerd Font", monospace; | ||
| 572 | -fx-font-size: 22px; | ||
| 573 | -fx-font-weight: 600; | ||
| 574 | -fx-text-fill: -gm-accent; | ||
| 575 | } | ||
| 576 | |||
| 577 | .gm-user-balance:negative { | ||
| 578 | -fx-text-fill: -gm-no; | ||
| 579 | } | ||
| 580 | |||
| 581 | /* ---- traffic lights with macOS on-hover symbols ---------------------- */ | ||
| 582 | |||
| 583 | .gm-traffic-lights { | ||
| 584 | -fx-alignment: center-left; | ||
| 585 | } | ||
| 586 | |||
| 587 | .gm-traffic-dot { | ||
| 588 | -fx-min-width: 12px; | ||
| 589 | -fx-min-height: 12px; | ||
| 590 | -fx-pref-width: 12px; | ||
| 591 | -fx-pref-height: 12px; | ||
| 592 | -fx-max-width: 12px; | ||
| 593 | -fx-max-height: 12px; | ||
| 594 | -fx-background-radius: 999px; | ||
| 595 | -fx-alignment: center; | ||
| 596 | -fx-cursor: hand; | ||
| 597 | } | ||
| 598 | |||
| 599 | .gm-traffic-icon { | ||
| 600 | -fx-fill: transparent; | ||
| 601 | -fx-stroke: transparent; | ||
| 602 | -fx-stroke-width: 1.1; | ||
| 603 | -fx-stroke-line-cap: round; | ||
| 604 | } | ||
| 605 | |||
| 606 | /* Reveal glyphs on traffic lights cluster hover */ | ||
| 607 | .gm-traffic-lights:hover .gm-traffic-icon { | ||
| 608 | -fx-stroke: rgba(0, 0, 0, 0.68); | ||
| 609 | } | ||
| 610 | |||
| 611 | .gm-traffic-dot:hover { -fx-opacity: 0.85; } | ||
| 612 | .gm-traffic-dot:pressed { -fx-opacity: 0.70; } | ||
| 613 | |||
| 614 | .gm-traffic-dot-no { -fx-background-color: -gm-no; } | ||
| 615 | .gm-traffic-dot-accent { -fx-background-color: -gm-accent; } | ||
| 616 | .gm-traffic-dot-yes { -fx-background-color: -gm-yes; } | ||
| 617 | |||
| 618 | /* ---- list rows, tables & option cards --------------------------------- */ | ||
| 619 | |||
| 620 | .gm-balance-cell { | ||
| 621 | -fx-font-family: "CaskaydiaCove NF", "JetBrainsMono NF", "FiraCode Nerd Font", monospace; | ||
| 622 | -fx-font-size: 13px; | ||
| 623 | -fx-font-weight: 600; | ||
| 624 | -fx-text-fill: -gm-accent; | ||
| 625 | } | ||
| 626 | .gm-balance-cell:negative { | ||
| 627 | -fx-text-fill: -gm-no; | ||
| 628 | } | ||
| 629 | |||
| 630 | .gm-pnl-cell { | ||
| 631 | -fx-font-family: "CaskaydiaCove NF", "JetBrainsMono NF", "FiraCode Nerd Font", monospace; | ||
| 632 | -fx-font-size: 12px; | ||
| 633 | -fx-font-weight: 600; | ||
| 634 | -fx-text-fill: -gm-yes; | ||
| 635 | } | ||
| 636 | .gm-pnl-cell:negative { | ||
| 637 | -fx-text-fill: -gm-no; | ||
| 638 | } | ||
| 639 | |||
| 640 | .gm-list-view { | ||
| 641 | -fx-background-color: transparent; | ||
| 642 | -fx-background-insets: 0; | ||
| 643 | -fx-padding: 0; | ||
| 644 | -fx-border-color: transparent; | ||
| 645 | -fx-border-width: 0; | ||
| 646 | } | ||
| 647 | |||
| 648 | .gm-list-view .list-cell { | ||
| 649 | -fx-background-color: transparent; | ||
| 650 | -fx-background-insets: 0; | ||
| 651 | -fx-padding: 1 0; | ||
| 652 | } | ||
| 653 | |||
| 654 | .gm-list-view .list-cell:empty { | ||
| 655 | -fx-background-color: transparent; | ||
| 656 | } | ||
| 657 | |||
| 658 | .gm-list-view .list-cell:filled:selected { | ||
| 659 | -fx-background-color: transparent; | ||
| 660 | } | ||
| 661 | |||
| 662 | .gm-list-view:focused .list-cell:filled:focused:selected { | ||
| 663 | -fx-background-color: transparent; | ||
| 664 | } | ||
| 665 | |||
| 666 | .gm-list-row { | ||
| 667 | -fx-background-color: transparent; | ||
| 668 | -fx-border-color: transparent; | ||
| 669 | -fx-border-width: 0 0 0 3; | ||
| 670 | -fx-background-radius: 5; | ||
| 671 | -fx-cursor: hand; | ||
| 672 | } | ||
| 673 | |||
| 674 | .gm-list-row:hover { | ||
| 675 | -fx-background-color: -gm-panel2; | ||
| 676 | } | ||
| 677 | |||
| 678 | .gm-list-row:selected { | ||
| 679 | -fx-background-color: -gm-panel3; | ||
| 680 | -fx-border-color: -gm-accent; | ||
| 681 | } | ||
| 682 | |||
| 683 | .gm-ladder-row { | ||
| 684 | -fx-border-color: -gm-line transparent transparent transparent; | ||
| 685 | -fx-border-width: 1 0 0 0; | ||
| 686 | } | ||
| 687 | |||
| 688 | .gm-ladder-row:bid, | ||
| 689 | .gm-ladder-row-bid { | ||
| 690 | -fx-background-color: -gm-yes-soft; | ||
| 691 | } | ||
| 692 | |||
| 693 | .gm-ladder-row:ask, | ||
| 694 | .gm-ladder-row-ask { | ||
| 695 | -fx-background-color: -gm-no-soft; | ||
| 696 | } | ||
| 697 | |||
| 698 | .gm-participation-row { | ||
| 699 | -fx-border-color: -gm-line transparent transparent transparent; | ||
| 700 | -fx-border-width: 1 0 0 0; | ||
| 701 | -fx-cursor: hand; | ||
| 702 | } | ||
| 703 | |||
| 704 | .gm-participation-row:hover { | ||
| 705 | -fx-background-color: -gm-panel2; | ||
| 706 | } | ||
| 707 | |||
| 708 | .gm-participation-row:selected { | ||
| 709 | -fx-background-color: -gm-panel3; | ||
| 710 | } | ||
| 711 | |||
| 712 | .gm-option-card { | ||
| 713 | -fx-background-radius: 6; | ||
| 714 | -fx-border-radius: 6; | ||
| 715 | -fx-cursor: hand; | ||
| 716 | -fx-background-color: -gm-panel; | ||
| 717 | -fx-border-color: -gm-line; | ||
| 718 | -fx-border-width: 1; | ||
| 719 | } | ||
| 720 | |||
| 721 | .gm-option-card-yes:selected { | ||
| 722 | -fx-background-color: -gm-yes-soft; | ||
| 723 | -fx-border-color: -gm-yes; | ||
| 724 | -fx-border-width: 1.5; | ||
| 725 | } | ||
| 726 | |||
| 727 | .gm-option-card-no:selected { | ||
| 728 | -fx-background-color: -gm-no-soft; | ||
| 729 | -fx-border-color: -gm-no; | ||
| 730 | -fx-border-width: 1.5; | ||
| 731 | } | ||
| 732 | |||
| 733 | /* ---- modals & dialogs ------------------------------------------------- */ | ||
| 734 | |||
| 735 | .gm-modal-scrim { | ||
| 736 | -fx-background-color: rgba(10, 10, 10, 0.42); | ||
| 737 | } | ||
| 738 | |||
| 739 | .gm-modal-card { | ||
| 740 | -fx-background-color: -gm-panel; | ||
| 741 | -fx-background: -gm-panel; | ||
| 742 | -fx-background-radius: 8; | ||
| 743 | -fx-border-radius: 8; | ||
| 744 | -fx-border-color: -gm-line; | ||
| 745 | } | ||
| 746 | |||
| 747 | .gm-resolve-option { | ||
| 748 | -fx-border-width: 1; | ||
| 749 | -fx-background-radius: 6; | ||
| 750 | -fx-border-radius: 6; | ||
| 751 | -fx-font-size: 14px; | ||
| 752 | -fx-font-weight: 700; | ||
| 753 | -fx-padding: 14 0; | ||
| 754 | -fx-cursor: hand; | ||
| 755 | -fx-background-color: -gm-panel2; | ||
| 756 | -fx-border-color: -gm-line; | ||
| 757 | } | ||
| 758 | |||
| 759 | .gm-resolve-option-yes { | ||
| 760 | -fx-text-fill: -gm-yes; | ||
| 761 | } | ||
| 762 | |||
| 763 | .gm-resolve-option-yes:selected { | ||
| 764 | -fx-background-color: -gm-yes-soft; | ||
| 765 | -fx-border-color: -gm-yes; | ||
| 766 | -fx-border-width: 1.5; | ||
| 767 | } | ||
| 768 | |||
| 769 | .gm-resolve-option-no { | ||
| 770 | -fx-text-fill: -gm-no; | ||
| 771 | } | ||
| 772 | |||
| 773 | .gm-resolve-option-no:selected { | ||
| 774 | -fx-background-color: -gm-no-soft; | ||
| 775 | -fx-border-color: -gm-no; | ||
| 776 | -fx-border-width: 1.5; | ||
| 777 | } | ||
| 778 | |||
| 779 | /* ---- progress bars ---------------------------------------------------- */ | ||
| 780 | |||
| 781 | .gm-progress { | ||
| 782 | -fx-control-inner-background: -gm-panel3; | ||
| 783 | } | ||
| 784 | |||
| 785 | .gm-progress > .track { | ||
| 786 | -fx-background-color: -gm-panel3; | ||
| 787 | -fx-background-insets: 0; | ||
| 788 | -fx-background-radius: 3px; | ||
| 789 | -fx-padding: 0; | ||
| 790 | } | ||
| 791 | |||
| 792 | .gm-progress > .bar { | ||
| 793 | -fx-background-insets: 0; | ||
| 794 | -fx-background-radius: 3px; | ||
| 795 | -fx-padding: 0; | ||
| 796 | } | ||
| 797 | |||
| 798 | .gm-progress-accent > .bar { | ||
| 799 | -fx-background-color: -gm-accent; | ||
| 800 | } | ||
| 801 | |||
| 802 | .gm-progress-yes > .bar { | ||
| 803 | -fx-background-color: -gm-yes; | ||
| 804 | } | ||
| 805 | |||
| 806 | .gm-progress-no > .bar { | ||
| 807 | -fx-background-color: -gm-no; | ||
| 808 | } | ||
| 809 | |||
| 810 | /* ---- charts ----------------------------------------------------------- */ | ||
| 811 | |||
| 812 | .gm-chart { | ||
| 813 | -fx-background-color: transparent; | ||
| 814 | } | ||
| 815 | |||
| 816 | .gm-chart-axis { | ||
| 817 | -fx-tick-label-fill: -gm-ink2; | ||
| 818 | -fx-tick-mark-stroke: -gm-ink2; | ||
| 819 | -fx-font-family: "CaskaydiaCove NF", "JetBrainsMono NF", "FiraCode Nerd Font", monospace; | ||
| 820 | -fx-font-size: 10px; | ||
| 821 | } | ||
| 822 | |||
| 823 | .gm-chart-axis .axis-tick-mark, | ||
| 824 | .gm-chart-axis .axis-minor-tick-mark { | ||
| 825 | -fx-fill: null; | ||
| 826 | -fx-stroke: -gm-ink2; | ||
| 827 | } | ||
| 828 | |||
| 829 | .gm-chart-axis:bottom { | ||
| 830 | -fx-border-color: -gm-line transparent transparent transparent; | ||
| 831 | } | ||
| 832 | |||
| 833 | .gm-chart-axis:left { | ||
| 834 | -fx-border-color: transparent -gm-line transparent transparent; | ||
| 835 | } | ||
| 836 | |||
| 837 | .gm-chart .chart-line-symbol { | ||
| 838 | -fx-background-color: transparent, transparent; | ||
| 839 | -fx-background-radius: 0; | ||
| 840 | -fx-padding: 0; | ||
| 841 | } | ||
| 842 | |||
| 843 | .gm-chart .chart-series-line { | ||
| 844 | -fx-stroke-width: 2.5px; | ||
| 845 | } | ||
| 846 | |||
| 847 | .gm-chart-single .series0.chart-series-line { | ||
| 848 | -fx-stroke: -gm-accent; | ||
| 849 | } | ||
| 850 | |||
| 851 | .gm-chart-dual .series0.chart-series-line { | ||
| 852 | -fx-stroke: -gm-yes; | ||
| 853 | } | ||
| 854 | |||
| 855 | .gm-chart-dual .series1.chart-series-line { | ||
| 856 | -fx-stroke: -gm-no; | ||
| 857 | } | ||
| 858 | |||
| 859 | |||
| 860 | /* ---- decorative animations (see Anim.java) ---------------------------- */ | ||
| 861 | |||
| 862 | .gm-anim-rule { -fx-stroke: -gm-line; } | ||
| 863 | |||
| 864 | .gm-anim-tick { | ||
| 865 | -fx-fill: -gm-ink2; | ||
| 866 | -fx-font-family: "CaskaydiaCove NF", "JetBrainsMono NF", "FiraCode Nerd Font", monospace; | ||
| 867 | -fx-font-size: 9px; | ||
| 868 | } | ||
| 869 | |||
| 870 | .gm-anim-curve-yes { -fx-stroke: -gm-yes; } | ||
| 871 | .gm-anim-curve-no { -fx-stroke: -gm-no; } | ||
| 872 | .gm-anim-dot-yes { -fx-fill: -gm-yes; } | ||
| 873 | .gm-anim-dot-no { -fx-fill: -gm-no; } | ||
| 874 | |||
| 875 | /* LIVE pill: bars and label take the pill's status colour */ | ||
| 876 | .gm-live-pill { -fx-padding: 3 7; } | ||
| 877 | |||
| 878 | .gm-anim-bar { -fx-fill: -gm-ink2; } | ||
| 879 | .gm-live-label { -fx-text-fill: -gm-ink2; } | ||
| 880 | |||
| 881 | .gm-pill:active .gm-anim-bar { -fx-fill: -gm-yes; } | ||
| 882 | .gm-pill:active .gm-live-label { -fx-text-fill: -gm-yes; } | ||
| 883 | .gm-pill:closed .gm-anim-bar { -fx-fill: -gm-no; } | ||
| 884 | .gm-pill:closed .gm-live-label { -fx-text-fill: -gm-no; } | ||
| 885 | |||
| 886 | /* Balance sparkline: stroke follows the sign of the balance */ | ||
| 887 | .gm-anim-spark { -fx-stroke: -gm-accent; } | ||
| 888 | .gm-anim-spark-dot { -fx-fill: -gm-accent; } | ||
| 889 | |||
| 890 | .gm-anim-sparkline:negative .gm-anim-spark { -fx-stroke: -gm-no; } | ||
| 891 | .gm-anim-sparkline:negative .gm-anim-spark-dot { -fx-fill: -gm-no; } | ||
| 892 | |||
| 893 | /* Animation toggle button & spinner */ | ||
| 894 | .gm-btn-icon { | ||
| 895 | -fx-padding: 4 8; | ||
| 896 | -fx-min-width: 34px; | ||
| 897 | -fx-min-height: 30px; | ||
| 898 | -fx-pref-height: 30px; | ||
| 899 | -fx-alignment: center; | ||
| 900 | } | ||
| 901 | |||
| 902 | .gm-btn-icon:selected { | ||
| 903 | -fx-background-color: -gm-panel3; | ||
| 904 | -fx-border-color: -gm-accent; | ||
| 905 | } | ||
| 906 | |||
| 907 | .gm-anim-spinner { | ||
| 908 | -fx-fill: -gm-ink2; | ||
| 909 | } | ||
| 910 | |||
| 911 | .gm-anim-spinner-hub { | ||
| 912 | -fx-fill: -gm-panel; | ||
| 913 | -fx-stroke: -gm-ink2; | ||
| 914 | -fx-stroke-width: 1; | ||
| 915 | } | ||
| 916 | |||
| 917 | .gm-btn-icon:selected .gm-anim-spinner { | ||
| 918 | -fx-fill: -gm-accent; | ||
| 919 | } | ||
| 920 | |||
| 921 | .gm-btn-icon:selected .gm-anim-spinner-hub { | ||
| 922 | -fx-fill: -gm-panel; | ||
| 923 | -fx-stroke: -gm-accent; | ||
| 924 | -fx-stroke-width: 1; | ||
| 925 | } | ||
| 926 | |||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/trade_history_item.fxml b/ui-desktop/src/main/resources/market/guess/ui/desktop/trade_history_item.fxml new file mode 100644 index 0000000..2a2bf92 --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/trade_history_item.fxml | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | |||
| 3 | <?import javafx.geometry.Insets?> | ||
| 4 | <?import javafx.scene.control.Label?> | ||
| 5 | <?import javafx.scene.layout.HBox?> | ||
| 6 | <?import javafx.scene.layout.Priority?> | ||
| 7 | |||
| 8 | <fx:root type="javafx.scene.layout.HBox" alignment="CENTER_LEFT" spacing="8.0" styleClass="gm-divider-top" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1"> | ||
| 9 | <padding> | ||
| 10 | <Insets bottom="7.0" left="11.0" right="11.0" top="7.0" /> | ||
| 11 | </padding> | ||
| 12 | <children> | ||
| 13 | <Label fx:id="numLabel" minWidth="66.0" prefWidth="66.0" styleClass="gm-text-sm, gm-font-semibold, gm-text-ink2, gm-font-mono" /> | ||
| 14 | <Label fx:id="userLabel" maxWidth="1.7976931348623157E308" minWidth="0.0" styleClass="gm-text-sm, gm-font-medium, gm-text-ink" textOverrun="ELLIPSIS" HBox.hgrow="ALWAYS" /> | ||
| 15 | <Label fx:id="optionLabel" minWidth="76.0" prefWidth="76.0" styleClass="gm-text-sm, gm-font-bold" /> | ||
| 16 | <Label fx:id="sharesLabel" alignment="CENTER_RIGHT" minWidth="92.0" prefWidth="92.0" styleClass="gm-text-sm, gm-font-mono" /> | ||
| 17 | <Label fx:id="paidLabel" alignment="CENTER_RIGHT" minWidth="88.0" prefWidth="88.0" styleClass="gm-text-sm, gm-font-semibold, gm-font-mono, gm-text-accent" /> | ||
| 18 | </children> | ||
| 19 | </fx:root> | ||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/user_event_item.fxml b/ui-desktop/src/main/resources/market/guess/ui/desktop/user_event_item.fxml new file mode 100644 index 0000000..93631a1 --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/user_event_item.fxml | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | |||
| 3 | <?import javafx.geometry.Insets?> | ||
| 4 | <?import javafx.scene.control.Label?> | ||
| 5 | <?import javafx.scene.layout.HBox?> | ||
| 6 | <?import javafx.scene.layout.Priority?> | ||
| 7 | |||
| 8 | <fx:root type="javafx.scene.layout.HBox" alignment="CENTER_LEFT" spacing="8.0" styleClass="gm-participation-row" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1"> | ||
| 9 | <padding> | ||
| 10 | <Insets bottom="8.0" left="11.0" right="11.0" top="8.0" /> | ||
| 11 | </padding> | ||
| 12 | <children> | ||
| 13 | <Label fx:id="nameLabel" maxWidth="1.7976931348623157E308" minWidth="0.0" styleClass="gm-text-sm, gm-font-medium, gm-text-ink" textOverrun="ELLIPSIS" HBox.hgrow="ALWAYS" /> | ||
| 14 | <!-- Sized for the longest values ("Market Maker", "Order Book") in every skin's mono font; never shrinks. --> | ||
| 15 | <Label fx:id="roleLabel" minWidth="-Infinity" prefWidth="92.0" styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" /> | ||
| 16 | <Label fx:id="typeLabel" minWidth="-Infinity" prefWidth="78.0" styleClass="gm-text-sm, gm-font-regular, gm-text-ink2" /> | ||
| 17 | <Label fx:id="yesLabel" alignment="CENTER_RIGHT" minWidth="78.0" prefWidth="78.0" styleClass="gm-text-sm, gm-font-mono" /> | ||
| 18 | <Label fx:id="noLabel" alignment="CENTER_RIGHT" minWidth="78.0" prefWidth="78.0" styleClass="gm-text-sm, gm-font-mono" /> | ||
| 19 | <Label fx:id="plLabel" alignment="CENTER_RIGHT" minWidth="90.0" prefWidth="90.0" styleClass="gm-pnl-cell" /> | ||
| 20 | </children> | ||
| 21 | </fx:root> | ||
diff --git a/ui-desktop/src/main/resources/market/guess/ui/desktop/user_list_item.fxml b/ui-desktop/src/main/resources/market/guess/ui/desktop/user_list_item.fxml new file mode 100644 index 0000000..dec7706 --- /dev/null +++ b/ui-desktop/src/main/resources/market/guess/ui/desktop/user_list_item.fxml | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | |||
| 3 | <?import javafx.geometry.Insets?> | ||
| 4 | <?import javafx.scene.control.Label?> | ||
| 5 | <?import javafx.scene.layout.HBox?> | ||
| 6 | <?import javafx.scene.layout.Priority?> | ||
| 7 | <?import javafx.scene.layout.VBox?> | ||
| 8 | |||
| 9 | <fx:root type="javafx.scene.layout.HBox" alignment="CENTER_LEFT" spacing="8.0" styleClass="gm-list-row" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1"> | ||
| 10 | <padding> | ||
| 11 | <Insets bottom="9.0" left="11.0" right="11.0" top="9.0" /> | ||
| 12 | </padding> | ||
| 13 | <children> | ||
| 14 | <VBox maxWidth="1.7976931348623157E308" minWidth="0.0" spacing="3.0" HBox.hgrow="ALWAYS"> | ||
| 15 | <children> | ||
| 16 | <Label fx:id="nameLabel" styleClass="gm-text-md, gm-font-semibold, gm-text-ink" /> | ||
| 17 | <Label fx:id="roleLabel" styleClass="gm-text-xs, gm-font-regular, gm-text-ink2" /> | ||
| 18 | </children> | ||
| 19 | </VBox> | ||
| 20 | <Label fx:id="balanceLabel" alignment="CENTER_RIGHT" minWidth="84.0" prefWidth="84.0" styleClass="gm-balance-cell" /> | ||
| 21 | </children> | ||
| 22 | </fx:root> | ||