updated UI
This commit is contained in:
parent
8402c2f59e
commit
640b2507eb
12
build.sbt
12
build.sbt
@ -45,13 +45,14 @@ libraryDependencies ++= Seq(
|
|||||||
"org.json4s" %% "json4s-jackson" % "3.6.8",
|
"org.json4s" %% "json4s-jackson" % "3.6.8",
|
||||||
"org.scala-lang.modules" %% "scala-async" % "0.10.0",
|
"org.scala-lang.modules" %% "scala-async" % "0.10.0",
|
||||||
"org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided,
|
"org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided,
|
||||||
// "org.kordamp.ikonli" %% "ikonli-javafx" % "11.4.0",
|
"org.kordamp.ikonli" % "ikonli-javafx" % "11.4.0",
|
||||||
// "org.kordamp.ikonli" %% "ikonli-fontawesome-pack" % "11.4.0",
|
"org.kordamp.ikonli" % "ikonli-fontawesome-pack" % "11.4.0",
|
||||||
// "org.kordamp.ikonli" %% "ikonli-fontawesome5-pack" % "11.4.0",
|
"org.kordamp.ikonli" % "ikonli-fontawesome5-pack" % "11.4.0",
|
||||||
"org.jsoup" % "jsoup" % "1.13.1",
|
"org.jsoup" % "jsoup" % "1.13.1",
|
||||||
"com.sandec" % "mdfx" % "0.1.6",
|
"com.sandec" % "mdfx" % "0.1.6",
|
||||||
"com.softwaremill.sttp.client" %% "async-http-client-backend-future" % "2.1.1",
|
"com.softwaremill.sttp.client" %% "async-http-client-backend-future" % "2.1.1",
|
||||||
"com.softwaremill.quicklens" %% "quicklens" % "1.5.0"
|
"com.softwaremill.quicklens" %% "quicklens" % "1.5.0",
|
||||||
|
"net.synedra" % "validatorfx" % "0.1.11"
|
||||||
)
|
)
|
||||||
libraryDependencies += "org.asynchttpclient" % "async-http-client" % "2.12.1"
|
libraryDependencies += "org.asynchttpclient" % "async-http-client" % "2.12.1"
|
||||||
libraryDependencies += "com.softwaremill.macwire" %% "macros" % "2.3.3"
|
libraryDependencies += "com.softwaremill.macwire" %% "macros" % "2.3.3"
|
||||||
@ -66,6 +67,9 @@ libraryDependencies += "org.kordamp.bootstrapfx" % "bootstrapfx-core" % "0.2.4"
|
|||||||
// https://mvnrepository.com/artifact/org.json4s/json4s-ext
|
// https://mvnrepository.com/artifact/org.json4s/json4s-ext
|
||||||
libraryDependencies += "org.json4s" %% "json4s-ext" % "3.6.8"
|
libraryDependencies += "org.json4s" %% "json4s-ext" % "3.6.8"
|
||||||
|
|
||||||
|
// https://mvnrepository.com/artifact/org.jsoup/jsoup
|
||||||
|
libraryDependencies += "org.jsoup" % "jsoup" % "1.13.1"
|
||||||
|
|
||||||
enablePlugins(BuildInfoPlugin)
|
enablePlugins(BuildInfoPlugin)
|
||||||
|
|
||||||
buildInfoPackage := "wow.doge.chatto"
|
buildInfoPackage := "wow.doge.chatto"
|
||||||
|
@ -1,49 +1,54 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import com.jfoenix.controls.JFXListView ?>
|
<?import com.jfoenix.controls.JFXListView?>
|
||||||
<?import javafx.geometry.Insets ?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.Button ?>
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.Label ?>
|
<?import javafx.scene.control.Label?>
|
||||||
<?import javafx.scene.control.TextArea ?>
|
<?import javafx.scene.control.TextArea?>
|
||||||
<?import javafx.scene.layout.BorderPane ?>
|
<?import javafx.scene.layout.BorderPane?>
|
||||||
<?import javafx.scene.layout.FlowPane ?>
|
<?import javafx.scene.layout.FlowPane?>
|
||||||
<?import javafx.scene.layout.HBox ?>
|
<?import javafx.scene.layout.HBox?>
|
||||||
<?import javafx.scene.layout.VBox ?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
|
<?import org.kordamp.ikonli.javafx.FontIcon?>
|
||||||
|
|
||||||
<!-- <?import com.example.javafx.control.UserBox?> -->
|
<!-- <?import com.example.javafx.control.UserBox?> -->
|
||||||
<!-- fx:controller="com.example.javafx.controller.SimpleUiController" -->
|
<!-- fx:controller="com.example.javafx.controller.SimpleUiController" -->
|
||||||
|
|
||||||
<BorderPane minHeight="533.0" minWidth="800.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wow.doge.chatto.controller.ChatController">
|
<BorderPane fx:id="chatMainPane" minWidth="800.0" prefHeight="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wow.doge.chatto.controller.ChatController">
|
||||||
<left>
|
<left>
|
||||||
<VBox fx:id="usersVBox" alignment="TOP_CENTER" prefHeight="200.0" prefWidth="175.0" BorderPane.alignment="CENTER">
|
<VBox fx:id="usersVBox" alignment="CENTER" prefHeight="200.0" prefWidth="175.0" BorderPane.alignment="CENTER">
|
||||||
<children>
|
<children>
|
||||||
<JFXListView fx:id="usersListView" prefHeight="554.0" prefWidth="175.0" styleClass="my-list-view" />
|
<JFXListView fx:id="usersListView" prefHeight="561.0" prefWidth="175.0" styleClass="my-list-view" VBox.vgrow="ALWAYS" />
|
||||||
</children>
|
</children>
|
||||||
</VBox>
|
</VBox>
|
||||||
</left>
|
</left>
|
||||||
<center>
|
<center>
|
||||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="5.0" BorderPane.alignment="CENTER">
|
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" spacing="5.0" BorderPane.alignment="CENTER">
|
||||||
<children>
|
<children>
|
||||||
<BorderPane prefHeight="41.0" prefWidth="620.0">
|
<BorderPane prefHeight="41.0" prefWidth="620.0">
|
||||||
<center>
|
<center>
|
||||||
<HBox alignment="CENTER" spacing="5.0">
|
<HBox fx:id="selectedUserBox" alignment="CENTER" spacing="5.0" styleClass="chat-background">
|
||||||
<children>
|
<children>
|
||||||
<Label id="currentUser" fx:id="curUsr" text="User1" />
|
<Label id="currentUser" fx:id="curUsr" styleClass="text-white" text="User1" />
|
||||||
<Label id="lastActive" fx:id="dataContent" text="User2" />
|
<Label id="lastActive" fx:id="lastActiveLabel" styleClass="text-white" text="User2" />
|
||||||
<Label id="online" text="User2" />
|
<Label id="online" fx:id="isOnlineLabel" styleClass="text-white" text="User2" />
|
||||||
</children>
|
</children>
|
||||||
</HBox>
|
</HBox>
|
||||||
</center>
|
</center>
|
||||||
</BorderPane>
|
</BorderPane>
|
||||||
<JFXListView fx:id="chatListView" prefHeight="463.0" prefWidth="610.0" />
|
<JFXListView fx:id="chatListView" minWidth="100.0" prefHeight="477.0" prefWidth="608.0" styleClass="my-list-view" VBox.vgrow="ALWAYS" />
|
||||||
<HBox prefHeight="50.0" prefWidth="790.0" spacing="2.0">
|
<HBox prefHeight="50.0" prefWidth="790.0" spacing="2.0" styleClass="chat-background">
|
||||||
<children>
|
<children>
|
||||||
<TextArea fx:id="chatInput" prefHeight="15.0" prefWidth="250.0" HBox.hgrow="ALWAYS" />
|
<TextArea fx:id="chatInput" prefHeight="15.0" prefWidth="250.0" HBox.hgrow="ALWAYS" />
|
||||||
<FlowPane alignment="CENTER" hgap="2.0" prefHeight="47.0" prefWidth="221.0">
|
<FlowPane alignment="CENTER" hgap="2.0" prefHeight="50.0" prefWidth="181.0">
|
||||||
<children>
|
<children>
|
||||||
|
|
||||||
<Button fx:id="logoutButton" styleClass="btn, btn-primary" text="Logout" onAction="#actionLogout" />
|
<Button fx:id="logoutButton" onAction="#actionLogout" styleClass="btn, btn-primary" text="Logout" />
|
||||||
<Button fx:id="submitButton" styleClass="btn, btn-primary" text="Submit" />
|
<Button fx:id="submitButton" style="-fx-background-color: transparent;">
|
||||||
|
<graphic>
|
||||||
|
<FontIcon accessibleText="Submit" fill="#2f91c9" iconLiteral="fa-chevron-circle-right" iconSize="40" />
|
||||||
|
</graphic>
|
||||||
|
</Button>
|
||||||
|
|
||||||
</children>
|
</children>
|
||||||
</FlowPane>
|
</FlowPane>
|
||||||
@ -55,8 +60,8 @@
|
|||||||
</BorderPane.margin>
|
</BorderPane.margin>
|
||||||
</VBox>
|
</VBox>
|
||||||
</center>
|
</center>
|
||||||
<stylesheets>
|
<!-- <stylesheets>
|
||||||
<!-- <URL value="@../styles/ui.css" />
|
<URL value="@../styles/chat.css" />
|
||||||
<URL value="@../styles/bootstrapfx.css" /> -->
|
<URL value="@../styles/bootstrapfx.css" />
|
||||||
</stylesheets>
|
</stylesheets> -->
|
||||||
</BorderPane>
|
</BorderPane>
|
||||||
|
@ -15,8 +15,7 @@
|
|||||||
<!-- minHeight="533.0" minWidth="800" maxHeight="533.0" maxWidth="800" -->
|
<!-- minHeight="533.0" minWidth="800" maxHeight="533.0" maxWidth="800" -->
|
||||||
<!-- fx:controller="com.example.javafx.controller.LoginController" -->
|
<!-- fx:controller="com.example.javafx.controller.LoginController" -->
|
||||||
|
|
||||||
|
<GridPane id="rootPane" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wow.doge.chatto.controller.LoginController">
|
||||||
<GridPane prefHeight="533.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wow.doge.chatto.controller.LoginController">
|
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="257.0" minWidth="10.0" prefWidth="122.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="257.0" minWidth="10.0" prefWidth="122.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="667.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="667.0" />
|
||||||
@ -43,14 +42,14 @@
|
|||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<JFXTextField fx:id="usernameTextField" focusColor="#d30699" labelFloat="true" minWidth="196.0" prefHeight="31.0" prefWidth="215.0" id="username" promptText="Username" />
|
<JFXTextField id="username" fx:id="usernameTextField" focusColor="#d30699" labelFloat="true" minWidth="196.0" prefHeight="31.0" prefWidth="215.0" promptText="Username" />
|
||||||
<JFXPasswordField fx:id="passwordTextField" focusColor="#fb06d2" labelFloat="true" minWidth="196.0" prefHeight="31.0" prefWidth="215.0" id="password" promptText="Password" />
|
<JFXPasswordField id="password" fx:id="passwordTextField" focusColor="#fb06d2" labelFloat="true" minWidth="196.0" prefHeight="31.0" prefWidth="215.0" promptText="Password" />
|
||||||
<!-- <JFXButton fx:id="submitButton" buttonType="RAISED" prefHeight="37.0" prefWidth="110.0" ripplerFill="WHITE" style="-fx-background-color: #fb06d2; -fx-background-radius: 50px;" text="Get started" textFill="WHITE" /> -->
|
<!-- <JFXButton fx:id="submitButton" buttonType="RAISED" prefHeight="37.0" prefWidth="110.0" ripplerFill="WHITE" style="-fx-background-color: #fb06d2; -fx-background-radius: 50px;" text="Get started" textFill="WHITE" /> -->
|
||||||
<JFXButton fx:id="submitButton" styleClass="btn, btn-primary" text="Submit" onAction="#actionLogin" />
|
<JFXButton fx:id="submitButton" onAction="#actionLogin" styleClass="btn, btn-primary" text="Submit" />
|
||||||
|
|
||||||
<!-- style="-fx-background-radius: 50px;-fx-background-color: #fb06d2" -->
|
<!-- style="-fx-background-radius: 50px;-fx-background-color: #fb06d2" -->
|
||||||
|
|
||||||
<Label fx:id="errorLabel" alignment="CENTER" prefHeight="37.0" prefWidth="324.0" text="" textAlignment="CENTER" textFill="#727070" wrapText="true">
|
<Label fx:id="errorLabel" alignment="CENTER" prefHeight="37.0" prefWidth="324.0" style="-fx-text-fill: RED;" textAlignment="CENTER" wrapText="true">
|
||||||
<font>
|
<font>
|
||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
@ -70,7 +69,7 @@
|
|||||||
</VBox>
|
</VBox>
|
||||||
</children>
|
</children>
|
||||||
<stylesheets>
|
<stylesheets>
|
||||||
<!-- <URL value="@../styles/style2.css" /> -->
|
<URL value="@../styles/login.css" />
|
||||||
<URL value="@../styles/bootstrapfx.css" />
|
<URL value="@../styles/bootstrapfx.css" />
|
||||||
</stylesheets>
|
</stylesheets>
|
||||||
</GridPane>
|
</GridPane>
|
@ -4,8 +4,27 @@
|
|||||||
<?import javafx.scene.layout.* ?>
|
<?import javafx.scene.layout.* ?>
|
||||||
<?import javafx.scene.control.* ?>
|
<?import javafx.scene.control.* ?>
|
||||||
|
|
||||||
<AnchorPane id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="400" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wow.doge.chatto.controller.MainViewController">
|
<BorderPane id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="400" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wow.doge.chatto.controller.MainViewController">
|
||||||
<children>
|
<!-- <children>
|
||||||
|
<BorderPane prefHeight="600.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
||||||
|
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
|
<top>
|
||||||
|
<AnchorPane fx:id="navigationPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
|
||||||
|
prefHeight="40.0" styleClass="navigation"/>
|
||||||
|
</top>
|
||||||
|
<center>
|
||||||
|
<AnchorPane fx:id="workspacePane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
|
||||||
|
prefHeight="200.0"/>
|
||||||
|
</center>
|
||||||
|
<bottom>
|
||||||
|
<AnchorPane fx:id="statusPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
|
||||||
|
prefHeight="30.0" styleClass="status"/>
|
||||||
|
</bottom>
|
||||||
|
</BorderPane>
|
||||||
|
<AnchorPane fx:id="mainPane"></AnchorPane>
|
||||||
|
<AnchorPane fx:id="chatPane"></AnchorPane>
|
||||||
|
</children> -->
|
||||||
|
<top>
|
||||||
<MenuBar VBox.vgrow="NEVER" fx:id="menuBar">
|
<MenuBar VBox.vgrow="NEVER" fx:id="menuBar">
|
||||||
<menus>
|
<menus>
|
||||||
<Menu mnemonicParsing="false" text="File">
|
<Menu mnemonicParsing="false" text="File">
|
||||||
@ -45,28 +64,13 @@
|
|||||||
</Menu>
|
</Menu>
|
||||||
</menus>
|
</menus>
|
||||||
</MenuBar>
|
</MenuBar>
|
||||||
|
</top>
|
||||||
<!-- <BorderPane prefHeight="600.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
<center>
|
||||||
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
<HBox fx:id="mainPane"></HBox>
|
||||||
<top>
|
</center>
|
||||||
<AnchorPane fx:id="navigationPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
|
|
||||||
prefHeight="40.0" styleClass="navigation"/>
|
|
||||||
</top>
|
|
||||||
<center>
|
|
||||||
<AnchorPane fx:id="workspacePane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
|
|
||||||
prefHeight="200.0"/>
|
|
||||||
</center>
|
|
||||||
<bottom>
|
|
||||||
<AnchorPane fx:id="statusPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
|
|
||||||
prefHeight="30.0" styleClass="status"/>
|
|
||||||
</bottom>
|
|
||||||
</BorderPane> -->
|
|
||||||
<AnchorPane fx:id="mainPane"></AnchorPane>
|
|
||||||
<!-- <AnchorPane fx:id="chatPane"></AnchorPane> -->
|
|
||||||
</children>
|
|
||||||
<stylesheets>
|
<stylesheets>
|
||||||
<!-- <URL value="@default.css" />
|
<URL value="@../styles/default.css" />
|
||||||
<URL value="@../styles/ui.css" />
|
<URL value="@../styles/bootstrapfx.css" />
|
||||||
<URL value="@../styles/style2.css" /> -->
|
<URL value="@../styles/chat.css" />
|
||||||
</stylesheets>
|
</stylesheets>
|
||||||
</AnchorPane>
|
</BorderPane>
|
@ -1,29 +0,0 @@
|
|||||||
.navigation {
|
|
||||||
-fx-background-color: derive(cadetblue, 60%);
|
|
||||||
-fx-font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status {
|
|
||||||
-fx-background-color: derive(lightgray, 30%);
|
|
||||||
-fx-font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace2 {
|
|
||||||
-fx-background-color: azure;
|
|
||||||
-fx-font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace {
|
|
||||||
-fx-background-color: beige;
|
|
||||||
-fx-font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.personPane {
|
|
||||||
-fx-font-size: 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
173
src/main/resources/styles/chat.css
Normal file
173
src/main/resources/styles/chat.css
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/* .ikonli-font-icon {
|
||||||
|
-fx-icon-size: 100px;
|
||||||
|
-fx-icon-color: blue;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.ikonli-font-icon:hover {
|
||||||
|
-fx-icon-color: #1976a8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chatMainPane {
|
||||||
|
-fx-padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-list-view .scroll-bar:horizontal .track,
|
||||||
|
.my-list-view .scroll-bar:vertical .track {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-border-color: transparent;
|
||||||
|
-fx-background-radius: 0em;
|
||||||
|
-fx-border-radius: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-list-view .scroll-bar:horizontal .increment-button,
|
||||||
|
.my-list-view .scroll-bar:horizontal .decrement-button {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-background-radius: 0em;
|
||||||
|
-fx-padding: 0 0 10 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-list-view .scroll-bar:vertical .increment-button,
|
||||||
|
.my-list-view .scroll-bar:vertical .decrement-button {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-background-radius: 0em;
|
||||||
|
-fx-padding: 0 10 0 0;
|
||||||
|
}
|
||||||
|
.my-list-view .scroll-bar .increment-arrow,
|
||||||
|
.my-list-view .scroll-bar .decrement-arrow {
|
||||||
|
-fx-shape: " ";
|
||||||
|
-fx-padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-list-view .scroll-bar:horizontal .thumb,
|
||||||
|
.my-list-view .scroll-bar:vertical .thumb {
|
||||||
|
-fx-background-color: derive(black, 90%);
|
||||||
|
-fx-background-insets: 2, 0, 0;
|
||||||
|
-fx-background-radius: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-pane .scroll-bar:horizontal .track,
|
||||||
|
.scroll-pane .scroll-bar:vertical .track {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-border-color: transparent;
|
||||||
|
-fx-background-radius: 0em;
|
||||||
|
-fx-border-radius: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-pane .scroll-bar:horizontal .increment-button,
|
||||||
|
.scroll-pane .scroll-bar:horizontal .decrement-button {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-background-radius: 0em;
|
||||||
|
-fx-padding: 0 0 10 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-pane .scroll-bar:vertical .increment-button,
|
||||||
|
.scroll-pane .scroll-bar:vertical .decrement-button {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-background-radius: 0em;
|
||||||
|
-fx-padding: 0 10 0 0;
|
||||||
|
}
|
||||||
|
.scroll-pane .scroll-bar .increment-arrow,
|
||||||
|
.scroll-pane .scroll-bar .decrement-arrow {
|
||||||
|
-fx-shape: " ";
|
||||||
|
-fx-padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-pane .scroll-bar:horizontal .thumb,
|
||||||
|
.scroll-pane .scroll-bar:vertical .thumb {
|
||||||
|
-fx-background-color: derive(black, 90%);
|
||||||
|
-fx-background-insets: 2, 0, 0;
|
||||||
|
-fx-background-radius: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-pane {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-pane > .viewport {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-message-box {
|
||||||
|
-fx-text-fill: white;
|
||||||
|
/* -fx-background-color: LIGHTGREEN; */
|
||||||
|
-fx-background-color: #82ccdd;
|
||||||
|
-fx-background-radius: 30px;
|
||||||
|
-fx-padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-background {
|
||||||
|
-fx-background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
/* -fx-selection-bar: rgba(0, 0, 0, 0.5); */
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-background-radius: 20px;
|
||||||
|
-fx-padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-list-view {
|
||||||
|
-fx-background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
/* -fx-selection-bar: rgba(0, 0, 0, 0.5); */
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-background-radius: 20px;
|
||||||
|
-fx-padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-cell {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-text-fill: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-cell:selected {
|
||||||
|
-fx-background-color: rgba(0, 0, 0, 0.2);
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-background-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-cell:hover {
|
||||||
|
-fx-background-color: rgba(0, 0, 0, 0.1);
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-background-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-cell:selected:hover {
|
||||||
|
-fx-background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-background-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-view:focused .list-cell:selected {
|
||||||
|
-fx-background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-background-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-area {
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-area .content {
|
||||||
|
-fx-background-color: rgb(116, 116, 116);
|
||||||
|
-fx-background-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-area {
|
||||||
|
-fx-background-color: rgba(53, 89, 119, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-area .scroll-pane {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-area .scroll-pane .viewport {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-area .scroll-pane .content {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chatInput {
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-background-radius: 20px;
|
||||||
|
-fx-padding: 5px 10px;
|
||||||
|
}
|
85
src/main/resources/styles/default.css
Normal file
85
src/main/resources/styles/default.css
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
.navigation {
|
||||||
|
-fx-background-color: derive(cadetblue, 60%);
|
||||||
|
-fx-font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
-fx-background-color: derive(lightgray, 30%);
|
||||||
|
-fx-font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace2 {
|
||||||
|
-fx-background-color: azure;
|
||||||
|
-fx-font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace {
|
||||||
|
-fx-background-color: beige;
|
||||||
|
-fx-font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.personPane {
|
||||||
|
-fx-font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root {
|
||||||
|
-fx-padding: 5 5 5 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-bar:horizontal .track,
|
||||||
|
.scroll-bar:vertical .track {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-border-color: transparent;
|
||||||
|
-fx-background-radius: 0em;
|
||||||
|
-fx-border-radius: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-bar:horizontal .increment-button,
|
||||||
|
.scroll-bar:horizontal .decrement-button {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-background-radius: 0em;
|
||||||
|
-fx-padding: 0 0 10 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-bar:vertical .increment-button,
|
||||||
|
.scroll-bar:vertical .decrement-button {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
-fx-background-radius: 0em;
|
||||||
|
-fx-padding: 0 10 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-bar .increment-arrow,
|
||||||
|
.scroll-bar .decrement-arrow {
|
||||||
|
-fx-shape: " ";
|
||||||
|
-fx-padding: 0.15em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-bar:vertical .increment-arrow,
|
||||||
|
.scroll-bar:vertical .decrement-arrow {
|
||||||
|
-fx-shape: " ";
|
||||||
|
-fx-padding: 0 0.15em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-bar:horizontal .thumb,
|
||||||
|
.scroll-bar:vertical .thumb {
|
||||||
|
-fx-background-color: derive(black, 90%);
|
||||||
|
-fx-background-insets: 2, 0, 0;
|
||||||
|
-fx-background-radius: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-bar:horizontal .thumb:hover,
|
||||||
|
.scroll-bar:vertical .thumb:hover {
|
||||||
|
-fx-background-color: derive(#4d4c4f, 10%);
|
||||||
|
-fx-background-insets: 2, 0, 0;
|
||||||
|
-fx-background-radius: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root {
|
||||||
|
-fx-background-color: linear-gradient(to right, #91eae4, #86a8e7, #7f7fd5);
|
||||||
|
}
|
||||||
|
/* linear-gradient(to right, #91EAE4, #86A8E7, #7F7FD5); */
|
||||||
|
/* linear-gradient(from 25% 25% to 100% 100%, #dc143c, #661a33)"); */
|
||||||
|
|
||||||
|
.text-white {
|
||||||
|
-fx-text-fill: white;
|
||||||
|
}
|
5
src/main/resources/styles/login.css
Normal file
5
src/main/resources/styles/login.css
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#rootPane {
|
||||||
|
-fx-background-image: url("../images/backgroung.jpg");
|
||||||
|
-fx-background-size: 1920 1080;
|
||||||
|
-fx-background-position: center center;
|
||||||
|
}
|
@ -38,19 +38,20 @@ class ApplicationController extends DefaultWindowController {
|
|||||||
|
|
||||||
// override def width: Int = 400
|
// override def width: Int = 400
|
||||||
|
|
||||||
@Inject
|
// @Inject
|
||||||
private var appDataHandler: AppDataHandler = _
|
// private var appDataHandler: AppDataHandler = _
|
||||||
|
|
||||||
def applicationDidLaunch() = {
|
def applicationDidLaunch() = {
|
||||||
logger.info("start " + this)
|
logger.info("start " + this)
|
||||||
applicationEnvironment.loadResourceBundle("bundles/application")
|
applicationEnvironment.loadResourceBundle("bundles/application")
|
||||||
replaceSceneContent(mainViewController)
|
replaceSceneContent(mainViewController.loginController)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Produces
|
@Produces
|
||||||
def applicationName: ApplicationName = {
|
def applicationName: ApplicationName = {
|
||||||
ApplicationName(configStringValue("application.name"))
|
ApplicationName(configStringValue("application.name"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Produces
|
@Produces
|
||||||
def httpBackend = backend
|
def httpBackend = backend
|
||||||
|
|
||||||
@ -65,15 +66,15 @@ class ApplicationController extends DefaultWindowController {
|
|||||||
replaceSceneContent(newMainViewController)
|
replaceSceneContent(newMainViewController)
|
||||||
}
|
}
|
||||||
|
|
||||||
def testListener(@Observes event: SceneControllerWillChangeEvent) = {
|
// def testListener(@Observes event: SceneControllerWillChangeEvent) = {
|
||||||
logger.info("test success 1")
|
// logger.info("test success 1")
|
||||||
// logger.info(s"${event.newController}")
|
// // logger.info(s"${event.newController}")
|
||||||
}
|
// }
|
||||||
|
|
||||||
def testListener2(@Observes event: SceneControllerDidChangeEvent) = {
|
// def testListener2(@Observes event: SceneControllerDidChangeEvent) = {
|
||||||
logger.info("test success 2")
|
// logger.info("test success 2")
|
||||||
// logger.info(s"${event.newController}")
|
// // logger.info(s"${event.newController}")
|
||||||
}
|
// }
|
||||||
|
|
||||||
override def applicationWillStop(): Unit = async {
|
override def applicationWillStop(): Unit = async {
|
||||||
super.applicationWillStop()
|
super.applicationWillStop()
|
||||||
@ -84,42 +85,17 @@ class ApplicationController extends DefaultWindowController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def showLoginPane() = onFX {
|
def showLoginPane() = onFX {
|
||||||
offFX { appDataHandler.clearCredentials() }
|
// offFX { appDataHandler.clearCredentials() }
|
||||||
// replaceSceneContent(mainViewController.loginController)
|
|
||||||
// mainViewController.mainManager.updatePaneContent(
|
|
||||||
// mainViewController.loginController
|
|
||||||
// )
|
|
||||||
replaceSceneContent(mainViewController.loginController)
|
replaceSceneContent(mainViewController.loginController)
|
||||||
}
|
}
|
||||||
|
|
||||||
def logout() = {
|
def logout() = onFX {
|
||||||
val newMainViewController = getController[MainViewController]()
|
val newMainViewController = getController[MainViewController]()
|
||||||
replaceSceneContent(newMainViewController)
|
replaceSceneContent(mainViewController.loginController)
|
||||||
}
|
}
|
||||||
|
|
||||||
def showChatPane(): Unit = onFX {
|
def showChatPane(): Unit = onFX {
|
||||||
// import org.scalafx.extras._
|
replaceSceneContent(mainViewController, true)
|
||||||
replaceSceneContent(mainViewController.chatController, true)
|
|
||||||
// mainViewController.mainManager.updatePaneContent(
|
|
||||||
// mainViewController.chatController
|
|
||||||
// )
|
|
||||||
// httpBackend.send(basicRequest.get(uri""))
|
|
||||||
// val willBeResponse = basicRequest
|
|
||||||
// .get(uri"https://httpbin.org/get")
|
|
||||||
// .response(asJson[HttpBinResponse])
|
|
||||||
// .send()
|
|
||||||
// async {
|
|
||||||
// val r = await { willBeResponse }
|
|
||||||
// r.body.map(println)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// willBeResponse onComplete {
|
|
||||||
// case Success(x) => { x.body }
|
|
||||||
// case Failure(x) => {}
|
|
||||||
// }
|
|
||||||
// val body = for {
|
|
||||||
// r <- willBeResponse
|
|
||||||
// } yield (r.body)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +118,6 @@ class AppDataHandler {
|
|||||||
def appData = _appData
|
def appData = _appData
|
||||||
|
|
||||||
def updateCredentials(credentials: UserCredentials): Unit = offFX {
|
def updateCredentials(credentials: UserCredentials): Unit = offFX {
|
||||||
println(credentials)
|
|
||||||
appData = appData.copy(credentials = credentials)
|
appData = appData.copy(credentials = credentials)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
114
src/main/scala/wow/doge/chatto/control/JFXSmoothScroll.java
Normal file
114
src/main/scala/wow/doge/chatto/control/JFXSmoothScroll.java
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
|
||||||
|
package wow.doge.chatto.control;
|
||||||
|
|
||||||
|
import javafx.animation.Animation;
|
||||||
|
import javafx.animation.KeyFrame;
|
||||||
|
import javafx.animation.Timeline;
|
||||||
|
import javafx.beans.DefaultProperty;
|
||||||
|
import javafx.beans.property.DoubleProperty;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.geometry.Bounds;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.ScrollPane;
|
||||||
|
import javafx.scene.control.ListView;
|
||||||
|
import javafx.geometry.Orientation;
|
||||||
|
import javafx.scene.control.ScrollBar;
|
||||||
|
import javafx.scene.input.MouseEvent;
|
||||||
|
import javafx.scene.input.ScrollEvent;
|
||||||
|
import javafx.scene.layout.*;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.shape.Rectangle;
|
||||||
|
import javafx.scene.transform.Scale;
|
||||||
|
import javafx.scene.transform.Transform;
|
||||||
|
import javafx.util.Duration;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class JFXSmoothScroll {
|
||||||
|
|
||||||
|
private static ScrollBar getScrollbarComponent(ListView<?> control, Orientation orientation) {
|
||||||
|
Node n = control.lookup(".scroll-bar");
|
||||||
|
if (n instanceof ScrollBar) {
|
||||||
|
final ScrollBar bar = (ScrollBar) n;
|
||||||
|
if (bar.getOrientation().equals(orientation)) {
|
||||||
|
return bar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void smoothScrollingListView(ListView<?> listView, double speed) {
|
||||||
|
smoothScrollingListView(listView, speed, Orientation.VERTICAL, bounds -> bounds.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void smoothHScrollingListView(ListView<?> listView, double speed) {
|
||||||
|
smoothScrollingListView(listView, speed, Orientation.HORIZONTAL, bounds -> bounds.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void smoothScrollingListView(ListView<?> listView, double speed, Orientation orientation,
|
||||||
|
Function<Bounds, Double> sizeFunc) {
|
||||||
|
ScrollBar scrollBar = getScrollbarComponent(listView, orientation);
|
||||||
|
if (scrollBar == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
scrollBar.setUnitIncrement(5);
|
||||||
|
final double[] frictions = { 0.99, 0.1, 0.05, 0.04, 0.03, 0.02, 0.01, 0.04, 0.01, 0.008, 0.008, 0.008, 0.008,
|
||||||
|
0.0006, 0.0005, 0.00003, 0.00001 };
|
||||||
|
final double[] pushes = { speed };
|
||||||
|
final double[] derivatives = new double[frictions.length];
|
||||||
|
final double[] lastVPos = { 0 };
|
||||||
|
Timeline timeline = new Timeline();
|
||||||
|
final EventHandler<MouseEvent> dragHandler = event -> timeline.stop();
|
||||||
|
final EventHandler<ScrollEvent> scrollHandler = event -> {
|
||||||
|
scrollBar.valueProperty().set(lastVPos[0]);
|
||||||
|
if (event.getEventType() == ScrollEvent.SCROLL) {
|
||||||
|
double direction = event.getDeltaY() > 0 ? -1 : 1;
|
||||||
|
for (int i = 0; i < pushes.length; i++) {
|
||||||
|
derivatives[i] += direction * pushes[i];
|
||||||
|
}
|
||||||
|
if (timeline.getStatus() == Animation.Status.STOPPED) {
|
||||||
|
timeline.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
event.consume();
|
||||||
|
};
|
||||||
|
if (scrollBar.getParent() != null) {
|
||||||
|
scrollBar.getParent().addEventHandler(MouseEvent.DRAG_DETECTED, dragHandler);
|
||||||
|
scrollBar.getParent().addEventHandler(ScrollEvent.ANY, scrollHandler);
|
||||||
|
}
|
||||||
|
scrollBar.parentProperty().addListener((o, oldVal, newVal) -> {
|
||||||
|
if (oldVal != null) {
|
||||||
|
oldVal.removeEventHandler(MouseEvent.DRAG_DETECTED, dragHandler);
|
||||||
|
oldVal.removeEventHandler(ScrollEvent.ANY, scrollHandler);
|
||||||
|
}
|
||||||
|
if (newVal != null) {
|
||||||
|
newVal.addEventHandler(MouseEvent.DRAG_DETECTED, dragHandler);
|
||||||
|
newVal.addEventHandler(ScrollEvent.ANY, scrollHandler);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
timeline.getKeyFrames().add(new KeyFrame(Duration.millis(3), (event) -> {
|
||||||
|
for (int i = 0; i < derivatives.length; i++) {
|
||||||
|
derivatives[i] *= frictions[i];
|
||||||
|
}
|
||||||
|
for (int i = 1; i < derivatives.length; i++) {
|
||||||
|
derivatives[i] += derivatives[i - 1];
|
||||||
|
}
|
||||||
|
double dy = derivatives[derivatives.length - 1];
|
||||||
|
double size = sizeFunc.apply(scrollBar.getLayoutBounds());
|
||||||
|
scrollBar.valueProperty().set(Math.min(Math.max(scrollBar.getValue() + dy / size, 0), 1));
|
||||||
|
lastVPos[0] = scrollBar.getValue();
|
||||||
|
if (Math.abs(dy) < 1) {
|
||||||
|
if (Math.abs(dy) < 0.001) {
|
||||||
|
timeline.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
timeline.setCycleCount(Animation.INDEFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
src/main/scala/wow/doge/chatto/control/MessageBox.scala
Normal file
10
src/main/scala/wow/doge/chatto/control/MessageBox.scala
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package wow.doge.chatto.control
|
||||||
|
|
||||||
|
import javafx.scene.layout.HBox
|
||||||
|
import javafx.scene.control.Label
|
||||||
|
import scalafx.Includes._
|
||||||
|
import wow.doge.chatto.controller.ChatData
|
||||||
|
import com.sfxcode.sapphire.core.value.FXBean
|
||||||
|
|
||||||
|
class MessageBox(val sender: String, val receiver: String, val message: String)
|
||||||
|
extends HBox() {}
|
@ -7,7 +7,10 @@ import wow.doge.chatto.controller.ChatData
|
|||||||
import com.sfxcode.sapphire.core.value.FXBean
|
import com.sfxcode.sapphire.core.value.FXBean
|
||||||
|
|
||||||
class UserBox2(val username: String, val chatData: ChatData) extends HBox() {
|
class UserBox2(val username: String, val chatData: ChatData) extends HBox() {
|
||||||
val usernameLabel = new Label(username)
|
val usernameLabel = new Label(username) {
|
||||||
|
// this.style = "-fx-text-fill: white"
|
||||||
|
this.styleClass ++= Seq("text-white")
|
||||||
|
}
|
||||||
// lazy val chatDataBean = FXBean[ChatData](chatData)
|
// lazy val chatDataBean = FXBean[ChatData](chatData)
|
||||||
this.children ++= Seq {
|
this.children ++= Seq {
|
||||||
usernameLabel
|
usernameLabel
|
||||||
|
@ -18,7 +18,6 @@ import wow.doge.chatto.service.UserService
|
|||||||
import scala.concurrent.ExecutionContext
|
import scala.concurrent.ExecutionContext
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
import com.typesafe.scalalogging.LazyLogging
|
import com.typesafe.scalalogging.LazyLogging
|
||||||
// import wow.doge.chatto.controller.LoginController.Person
|
|
||||||
import com.sfxcode.sapphire.core.value.FXBean
|
import com.sfxcode.sapphire.core.value.FXBean
|
||||||
import wow.doge.chatto.AppDataHandler
|
import wow.doge.chatto.AppDataHandler
|
||||||
import com.jfoenix.controls.JFXListView
|
import com.jfoenix.controls.JFXListView
|
||||||
@ -41,6 +40,27 @@ import wow.doge.chatto.messagebuble.BubbleSpec
|
|||||||
import javafx.scene.layout.Background
|
import javafx.scene.layout.Background
|
||||||
import javafx.scene.layout.BackgroundFill
|
import javafx.scene.layout.BackgroundFill
|
||||||
import javafx.geometry.Pos
|
import javafx.geometry.Pos
|
||||||
|
import scalafx.beans.property.ReadOnlyBufferProperty
|
||||||
|
import scalafx.beans.property.ReadOnlyBufferWrapper
|
||||||
|
import javafx.beans.property.ReadOnlyListProperty
|
||||||
|
import scalafx.beans.property.BufferProperty
|
||||||
|
import javafx.collections.FXCollections
|
||||||
|
import com.sandec.mdfx.MDFXNode
|
||||||
|
import javafx.scene.layout.BorderPane
|
||||||
|
import javafx.scene.layout.Priority
|
||||||
|
import net.synedra.validatorfx.Validator
|
||||||
|
import wow.doge.chatto.control.JFXSmoothScroll
|
||||||
|
import javafx.scene.control.ContextMenu
|
||||||
|
import javafx.scene.control.MenuItem
|
||||||
|
import javafx.scene.input.Clipboard
|
||||||
|
import javafx.scene.input.ClipboardContent
|
||||||
|
import scalafx.scene.input.KeyCodeCombination
|
||||||
|
import scalafx.scene.input.KeyCode
|
||||||
|
import scalafx.scene.input.KeyCombination
|
||||||
|
import javafx.scene.input.DataFormat
|
||||||
|
import wow.doge.chatto.control.MessageBox
|
||||||
|
import javafx.scene.control.SelectionMode
|
||||||
|
import scalafx.beans.property.BooleanProperty
|
||||||
|
|
||||||
class ChatController @Inject() (
|
class ChatController @Inject() (
|
||||||
userService: UserService,
|
userService: UserService,
|
||||||
@ -49,71 +69,54 @@ class ChatController @Inject() (
|
|||||||
with LazyLogging {
|
with LazyLogging {
|
||||||
|
|
||||||
// @FXML private var label: Label = _
|
// @FXML private var label: Label = _
|
||||||
@FXML private var flowPane: FlowPane = _
|
@FXML var chatMainPane: BorderPane = _
|
||||||
|
// @FXML private var flowPane: FlowPane = _
|
||||||
@FXML private var submitButton: Button = _
|
@FXML private var submitButton: Button = _
|
||||||
@FXML private var logoutButton: Button = _
|
@FXML private var logoutButton: Button = _
|
||||||
// @FXML private var chatTextArea: TextArea = _
|
// @FXML private var chatTextArea: TextArea = _
|
||||||
@FXML private var chatInput: TextArea = _
|
@FXML private var chatInput: TextArea = _
|
||||||
@FXML private var usersVBox: VBox = _
|
@FXML private var usersVBox: VBox = _
|
||||||
@FXML var usersListView: JFXListView[UserBox2] = _
|
@FXML var usersListView: JFXListView[UserBox2] = _
|
||||||
@FXML var chatListView: JFXListView[HBox] = _
|
@FXML var chatListView: JFXListView[MessageBox] = _
|
||||||
@FXML private var curUsr: Label = _
|
@FXML private var curUsr: Label = _
|
||||||
@FXML private var dataContent: Label = _
|
@FXML private var lastActiveLabel: Label = _
|
||||||
// applicationController.show
|
@FXML private var isOnlineLabel: Label = _
|
||||||
private val usersListProperty = new SimpleListProperty(
|
@FXML private var selectedUserBox: HBox = _
|
||||||
ObservableBuffer[UserBox2]()
|
|
||||||
)
|
private val usersBuffer = ObservableBuffer.empty[UserBox2]
|
||||||
private val chatDataBuffer = ObservableBuffer[UserBox2]()
|
private val usersListProperty = BufferProperty(usersBuffer)
|
||||||
private val chatDataStore: mutable.Map[String, ChatDataProperty] =
|
|
||||||
TrieMap()
|
/**
|
||||||
|
* Readonly property wrapping an unmodifiable list.
|
||||||
|
* Synchronized with the internal users list property.
|
||||||
|
* Attemping to modify the internal list will throw an exception
|
||||||
|
*/
|
||||||
|
val usersListROProp: ReadOnlyListProperty[UserBox2] = BufferProperty(
|
||||||
|
FXCollections.unmodifiableObservableList(usersListProperty())
|
||||||
|
)
|
||||||
|
|
||||||
|
private val chatDataStore = TrieMap.empty[String, ChatDataProperty]
|
||||||
|
|
||||||
// private lazy val curUserKeys = KeyBindings("curUser")
|
|
||||||
// bindings.add("person", "Person ${_self.name()} with age of ${_self.age()} is active: ${_self.isActive()}")
|
|
||||||
// private lazy val curUserAdapter = FXBeanAdapter[User](this)
|
|
||||||
private lazy val chatDataAdapter = FXBeanAdapter[ChatData](this)
|
private lazy val chatDataAdapter = FXBeanAdapter[ChatData](this)
|
||||||
|
|
||||||
override def didGainVisibilityFirstTime(): Unit = {
|
override def didGainVisibilityFirstTime(): Unit = {
|
||||||
super.didGainVisibilityFirstTime()
|
super.didGainVisibilityFirstTime()
|
||||||
// val ub = new UserBox()
|
|
||||||
this.stage.resizable = true
|
this.stage.resizable = true
|
||||||
// ub.messageLabel.text = "Hi there"
|
chatMainPane.hgrow = Priority.ALWAYS
|
||||||
// ub.messageLabel.id =
|
chatListView.selectionModel().selectionMode = SelectionMode.MULTIPLE
|
||||||
// ub.userRadioButton.text = "User 1"
|
|
||||||
// usersVBox.children.clear()
|
|
||||||
// usersVBox.children += ub
|
|
||||||
// println("test")
|
|
||||||
// println(s"Result = ${func()}")
|
|
||||||
// offFX(println("hello from new thread"))
|
|
||||||
// chatTextArea.visible <== !chatInput.text.isEmpty
|
|
||||||
// chatTextArea.text <== chatInput.text
|
|
||||||
|
|
||||||
// for (r <- userService.func2()) yield (logger.info(s"${r.body}"))
|
chatDataAdapter.set(FXBean(ChatData.empty))
|
||||||
|
|
||||||
// val person = Person(0, 10, "Billy")
|
Array(submitButton, chatInput).foreach(n => {
|
||||||
// val bean = FXBean[Person](person)
|
n.disableProperty() <== usersListView
|
||||||
// ub.messageLabel.text <== bean.getStringProperty("name")
|
.selectionModel()
|
||||||
// bean.getStringProperty("name") <== chatInput.text
|
.selectedItemProperty()
|
||||||
|
.isNull()
|
||||||
|
})
|
||||||
|
|
||||||
// bean.getStringProperty("name")() = "Lester"
|
|
||||||
// println(bean.getValue("name"))
|
|
||||||
// println(bean.getStringProperty("name")())
|
|
||||||
// bean.
|
|
||||||
// bean.updateValue("name", "Lester")
|
|
||||||
// println(bean.bean)
|
|
||||||
|
|
||||||
// val curUserBean = FXBean[User](User("None"))
|
|
||||||
|
|
||||||
// logoutButton.onAction = (e) =>
|
|
||||||
|
|
||||||
// usersListView
|
|
||||||
// .getSelectionModel()
|
|
||||||
// .selectedItemProperty()
|
|
||||||
// .addListener((_, _, newValue) => {
|
|
||||||
// curUsr.text() = newValue.usernameLabel.text()
|
|
||||||
// })
|
|
||||||
// curUserKeys.add("content", "${_self.data().content()}")
|
// curUserKeys.add("content", "${_self.data().content()}")
|
||||||
val chatDataAdapterKeys = KeyBindings()
|
val chatDataAdapterKeys = KeyBindings()
|
||||||
// chatDataAdapterKeys.add("currentUser", "${_self.userName()}")
|
chatDataAdapterKeys.add("currentUser", "${_self.userName()}")
|
||||||
// chatDataAdapterKeys.add(
|
// chatDataAdapterKeys.add(
|
||||||
// "lastActive",
|
// "lastActive",
|
||||||
// "${_self.lastActiveString()}"
|
// "${_self.lastActiveString()}"
|
||||||
@ -125,39 +128,97 @@ class ChatController @Inject() (
|
|||||||
// curUserAdapter.addDateConverter()
|
// curUserAdapter.addDateConverter()
|
||||||
// curUserAdapter.addBindings(curUserKeys)
|
// curUserAdapter.addBindings(curUserKeys)
|
||||||
chatDataAdapter.addBindings(chatDataAdapterKeys)
|
chatDataAdapter.addBindings(chatDataAdapterKeys)
|
||||||
// curUsr.text <== chatDataAdapter.beanProperty
|
|
||||||
// .getOrElse(FXBean(ChatData.empty))
|
|
||||||
// .getStringProperty("lastActiveString")
|
|
||||||
usersListView
|
usersListView
|
||||||
.getSelectionModel()
|
.selectionModel()
|
||||||
.selectedItemProperty()
|
.selectedItemProperty()
|
||||||
.addListener((_, _, newValue) => {
|
.addListener((_, _, newValue) => {
|
||||||
if (newValue != null) {
|
Option(newValue).foreach(nv => {
|
||||||
// val dataBean =
|
val maybeCDP = chatDataStore
|
||||||
// FXBean(User(newValue.usernameLabel.text(), Data("test data")))
|
.get(nv.username)
|
||||||
// curUserAdapter
|
val chatDataBean = maybeCDP
|
||||||
// .set(dataBean)
|
|
||||||
// chatDataAdapter.set(newValue.chatDataBean)
|
|
||||||
val y = chatDataStore
|
|
||||||
.get(newValue.username)
|
|
||||||
val x = y
|
|
||||||
.map(_.bean)
|
.map(_.bean)
|
||||||
.getOrElse {
|
.getOrElse {
|
||||||
logger.error("Error null")
|
logger.error("Error null")
|
||||||
FXBean(ChatData.empty)
|
FXBean(ChatData.empty)
|
||||||
}
|
}
|
||||||
chatDataAdapter.set(x)
|
chatDataAdapter.set(chatDataBean)
|
||||||
y.map(z => chatListView.items <== z.prop)
|
maybeCDP.foreach(cdp => {
|
||||||
}
|
// lastActiveLabel.text <== cdp.lastActive
|
||||||
|
isOnlineLabel.text <== cdp.isActive.asString()
|
||||||
|
chatListView.items <== cdp.messageBubbles
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// curUsr.text <== usersListView
|
val copyMessageMenuItem = new MenuItem("Copy Message")
|
||||||
// .getSelectionModel()
|
copyMessageMenuItem.accelerator =
|
||||||
// .getSelectedItem()
|
new KeyCodeCombination(KeyCode.C, KeyCombination.ControlDown)
|
||||||
// .usernameLabel
|
copyMessageMenuItem.onAction = _ => {
|
||||||
// .text
|
val content = new ClipboardContent()
|
||||||
|
val x = chatListView.getSelectionModel().getSelectedItems().map(_.message)
|
||||||
|
// chatListView.selectionModel().selectedItem().message
|
||||||
|
Option(x).foreach(message => {
|
||||||
|
content.putString(message.mkString("\n"))
|
||||||
|
Clipboard.getSystemClipboard().setContent(content)
|
||||||
|
})
|
||||||
|
// val message = cdp.messageList(selectedIndex)
|
||||||
|
|
||||||
|
// val maybeCDP = chatDataStore.get(chatDataAdapter.get.bean.userName)
|
||||||
|
// maybeCDP.foreach(cdp => {
|
||||||
|
// // val message = Option(cdp.messageList().get(selectedIndex)).toRight {
|
||||||
|
// // "Unexpected error - message not found"
|
||||||
|
// // }
|
||||||
|
// // message.map(msg => {
|
||||||
|
// // // content.putString(msg)
|
||||||
|
// // // clipboard.setContent(content)
|
||||||
|
// // // val content = clipboard.content
|
||||||
|
// // // content.putString(msg)
|
||||||
|
// // // clipboard.content = content
|
||||||
|
// // clipboard.putString(msg)
|
||||||
|
// // })
|
||||||
|
// // message.left.map(err => logger.error(err))
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
val chatListMenu = new ContextMenu()
|
||||||
|
|
||||||
|
chatListMenu.items += copyMessageMenuItem
|
||||||
|
chatListView.contextMenu = chatListMenu
|
||||||
|
|
||||||
usersListView.items <== usersListProperty
|
usersListView.items <== usersListProperty
|
||||||
|
|
||||||
|
val validator = new Validator()
|
||||||
|
|
||||||
|
submitButton.disable <== validator.containsErrorsProperty()
|
||||||
|
|
||||||
|
submitButton.onAction = (e) => {
|
||||||
|
// val msgBox = ChatDataProperty.createMdMessageBox2(chatInput.text())
|
||||||
|
// chatListView.items() += msgBox
|
||||||
|
if (!chatInput.text().equals("") &&
|
||||||
|
!chatInput.text().equals(" ") &&
|
||||||
|
!chatInput.text().equals("\n")) {
|
||||||
|
val maybeCDP = chatDataStore.get(chatDataAdapter.get.bean.userName)
|
||||||
|
|
||||||
|
maybeCDP.foreach(cdp => {
|
||||||
|
cdp.messageBubbles += ChatDataProperty.createMdMessageBox3(
|
||||||
|
appDataHandler.appData.credentials.username,
|
||||||
|
cdp.username(),
|
||||||
|
chatInput.text()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
validator
|
||||||
|
.createCheck()
|
||||||
|
.withMethod(c => {
|
||||||
|
val userName = chatInput.text()
|
||||||
|
if (!userName.toLowerCase().equals(userName)) {
|
||||||
|
c.error("Please use only lowercase letters.")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.dependsOn("chatInput", chatInput.text)
|
||||||
|
.decorates(chatInput)
|
||||||
|
.immediate()
|
||||||
}
|
}
|
||||||
|
|
||||||
override def didGainVisibility(): Unit = {
|
override def didGainVisibility(): Unit = {
|
||||||
@ -165,70 +226,60 @@ class ChatController @Inject() (
|
|||||||
chatInput.requestFocus()
|
chatInput.requestFocus()
|
||||||
|
|
||||||
async {
|
async {
|
||||||
val willBeUsers = userService
|
|
||||||
.getUsers(appDataHandler.appData.credentials)
|
|
||||||
.map(_.body)
|
|
||||||
val willBeActiveUsers = userService
|
val willBeActiveUsers = userService
|
||||||
.getActiveUsers(appDataHandler.appData.credentials)
|
.getActiveUsers(appDataHandler.appData.credentials)
|
||||||
.map(_.body)
|
.map(_.body)
|
||||||
val maybeUsers = await(willBeUsers)
|
|
||||||
val maybeActiveUsers = await(willBeActiveUsers)
|
val maybeActiveUsers = await(willBeActiveUsers)
|
||||||
|
|
||||||
// maybeActiveUsers.foreach(println)
|
logger.debug(s"Received Users: $maybeActiveUsers")
|
||||||
logger.debug(s"$maybeActiveUsers")
|
|
||||||
|
|
||||||
val maybeUserBoxes = maybeActiveUsers.map(users => {
|
val maybeUserBoxes = maybeActiveUsers.map(users => {
|
||||||
// usersBuffer ++= users
|
|
||||||
users.map(user => {
|
users.map(user => {
|
||||||
// usersBuffer += FXBean(User(user))
|
|
||||||
// val ub = new UserBox()
|
|
||||||
// ub.messageLabel.text = "Hi there"
|
|
||||||
// ub.userRadioButton.text = user
|
|
||||||
// ub
|
|
||||||
// new Rectangle {
|
|
||||||
// fill <== when(hover) choose (Color.Red)
|
|
||||||
// }
|
|
||||||
// val hb = new HBox
|
|
||||||
val chatData =
|
val chatData =
|
||||||
ChatData(user.userName, user, ObservableBuffer.empty[String])
|
ChatData(user.userName, user, ObservableBuffer.empty[String])
|
||||||
// chatDataStore.updateWith(user.userName)(maybeCD =>
|
|
||||||
// maybeCD.map(cd => {
|
|
||||||
// cd.messagesStringProperty +=
|
|
||||||
// })
|
|
||||||
// )
|
|
||||||
chatDataStore.put(user.userName, new ChatDataProperty(chatData))
|
chatDataStore.put(user.userName, new ChatDataProperty(chatData))
|
||||||
chatDataStore
|
|
||||||
.get(user.userName)
|
|
||||||
.map(cdp => {
|
|
||||||
cdp.prop ++= Seq("hi", "hello", "bye")
|
|
||||||
.map(s => ChatDataProperty.createMdMessageBox(s))
|
|
||||||
})
|
|
||||||
new UserBox2(user.userName, chatData) {
|
new UserBox2(user.userName, chatData) {
|
||||||
// this.children += new Label {
|
this.styleClass ++= Seq("text-white")
|
||||||
// textProperty() = user
|
|
||||||
// // textFillProperty <== when(this.hover) choose (Color.RED) otherwise (Color.BLUE)
|
|
||||||
// }
|
|
||||||
// fill <== when(this.hover) choose (Color.RED) otherwise (Color.BLUE)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
// maybeUserBoxes.map(userBoxes => {
|
val messageBox = ChatDataProperty.createMdMessageBox2(
|
||||||
// // chatDataBuffer ++= userBoxes
|
"""**Hello world qefwew yeeehay bwergqwevqcqe**
|
||||||
// usersListProperty ++= userBoxes
|
|**Hello world qefwew yeeehay bwergqwevqcqe**
|
||||||
// })
|
|
|
||||||
val messageBox = ChatDataProperty.createMdMessageBox("*hello!*")
|
| Hello World
|
||||||
|
""".stripMargin
|
||||||
|
)
|
||||||
onFX {
|
onFX {
|
||||||
// maybeUserBoxes.map(userBoxes => {
|
maybeUserBoxes.foreach(userBoxes => {
|
||||||
// chatDataBuffer ++= userBoxes
|
usersBuffer ++= userBoxes
|
||||||
// // usersListView.items() ++= userBoxes
|
|
||||||
// // val x = new SimpleListProperty(ObservableBuffer(userBoxes))
|
|
||||||
// // usersListView.items <== x
|
|
||||||
// })
|
|
||||||
maybeUserBoxes.map(userBoxes => {
|
|
||||||
usersListProperty ++= userBoxes
|
|
||||||
})
|
})
|
||||||
chatListView.items() += messageBox
|
chatListView.items() ++= Seq(
|
||||||
|
messageBox,
|
||||||
|
ChatDataProperty.createMdMessageBox2("hello"),
|
||||||
|
ChatDataProperty.createMdMessageBox2(
|
||||||
|
""" 1. Hello world qefwew yeeehay bwergqwevqcqe
|
||||||
|
|1. Hello world qefwew yeeehay bwergqwevqcqe
|
||||||
|
|1. Hello world qefwew yeeehay bwergqwevqcqe
|
||||||
|
|1. Hello world qefwew yeeehay bwergqwevqcqe""".stripMargin
|
||||||
|
)
|
||||||
|
)
|
||||||
|
// .map(node => {
|
||||||
|
// node.prefWidthProperty <== (chatListView.prefWidthProperty - 200)
|
||||||
|
// node
|
||||||
|
// })
|
||||||
|
// JFXSmoothScroll.smoothScrollingListView(chatListView, 0.1)
|
||||||
}
|
}
|
||||||
|
chatDataStore
|
||||||
|
.map { case (key, value) => value }
|
||||||
|
.foreach(cdp => {
|
||||||
|
cdp.messageBubbles ++= Seq(
|
||||||
|
ChatDataProperty.createMdMessageBox2("hi"),
|
||||||
|
ChatDataProperty.createMdMessageBox2("hello"),
|
||||||
|
ChatDataProperty.createMdMessageBox2("bye")
|
||||||
|
)
|
||||||
|
// .map(ChatDataProperty.createMdMessageBox)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def func() = {
|
def func() = {
|
||||||
@ -241,40 +292,29 @@ class ChatController @Inject() (
|
|||||||
def actionLogout = onFX {
|
def actionLogout = onFX {
|
||||||
offFXAndWait {
|
offFXAndWait {
|
||||||
appDataHandler.clearCredentials()
|
appDataHandler.clearCredentials()
|
||||||
println(appDataHandler.appData)
|
|
||||||
}
|
}
|
||||||
// curUserAdapter.set(User.empty)
|
// curUserAdapter.set(User.empty)
|
||||||
|
logger.debug(s"Logout - clearing credentials - ${appDataHandler.appData}")
|
||||||
chatDataAdapter.set(FXBean(ChatData.empty))
|
chatDataAdapter.set(FXBean(ChatData.empty))
|
||||||
usersListView.items().clear()
|
usersListView.items().clear()
|
||||||
chatListView.items().clear()
|
chatListView.items().clear()
|
||||||
chatDataBuffer.clear()
|
|
||||||
chatDataStore.clear()
|
chatDataStore.clear()
|
||||||
usersListProperty.clear()
|
usersBuffer.clear()
|
||||||
|
chatInput.clear()
|
||||||
|
this.stage.maximized = false
|
||||||
applicationController.logout()
|
applicationController.logout()
|
||||||
println(appDataHandler.appData)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
implicit class MyClipboardExtension(clipboard: Clipboard) {
|
||||||
object ChatController {
|
def putString(string: String) = {
|
||||||
lazy val markdownStyleSheet =
|
// val content = Option(clipboard.getContent(DataFormat.PLAIN_TEXT))
|
||||||
getClass().getResource("/styles/markdown.css").toExternalForm()
|
// .getOrElse(new ClipboardContent())
|
||||||
|
// content.putString(string)
|
||||||
|
// clipboard.setContent(content)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final case class Person(id: Int, age: Int, name: String)
|
|
||||||
final case class Data(content: String)
|
|
||||||
final case class User(curUser: String, data: Data)
|
|
||||||
object User {
|
|
||||||
def empty = User("", Data(""))
|
|
||||||
// Bindings.createObjectBinding()
|
|
||||||
}
|
|
||||||
// final case class ActiveUser(
|
|
||||||
// userName: String,
|
|
||||||
// online: Boolean,
|
|
||||||
// lastActive: String
|
|
||||||
// )
|
|
||||||
// object ActiveUser {
|
|
||||||
// def empty = ActiveUser("empty", false, "empty")
|
|
||||||
// }
|
|
||||||
final case class ChatData(
|
final case class ChatData(
|
||||||
userName: String,
|
userName: String,
|
||||||
activeUser: ActiveUser,
|
activeUser: ActiveUser,
|
||||||
@ -294,21 +334,26 @@ object ChatData {
|
|||||||
class ChatDataProperty(chatData: ChatData) {
|
class ChatDataProperty(chatData: ChatData) {
|
||||||
import ChatDataProperty._
|
import ChatDataProperty._
|
||||||
val bean = FXBean(chatData)
|
val bean = FXBean(chatData)
|
||||||
val usernameProperty = bean.getStringProperty("userName")
|
val username = bean.getStringProperty("userName")
|
||||||
val isActiveProperty = bean.getBooleanProperty("activeUser.online")
|
val isActive = bean.getBooleanProperty("activeUser.online")
|
||||||
val lastActiveProperty = bean.getStringProperty("lastActiveString")
|
val lastActive = bean.getStringProperty("lastActiveString")
|
||||||
val messagesStringProperty = new SimpleListProperty(chatData.messages)
|
lazy val messageBubbles = BufferProperty(
|
||||||
val prop = new SimpleListProperty(ObservableBuffer.empty[HBox])
|
chatData.messages.map(ChatDataProperty.createMdMessageBox2)
|
||||||
// val x = messagesStringProperty.map(message => createMdMessageBox(message))
|
)
|
||||||
// prop <== messagesStringProperty.map(message => createMdMessageBox(message))
|
def messageList = messageBubbles().map(_.message)
|
||||||
// prop <== new SimpleListProperty(x)
|
// lazy val messages = messagesBubbleProperty
|
||||||
|
// .get()
|
||||||
|
// .map(_.messageText)
|
||||||
}
|
}
|
||||||
object ChatDataProperty {
|
object ChatDataProperty {
|
||||||
|
lazy val markdownStyleSheet =
|
||||||
|
getClass().getResource("/styles/markdown.css").toExternalForm()
|
||||||
|
|
||||||
def createMdMessageBox(mdfxText: String) = {
|
def createMdMessageBox(mdfxText: String) = {
|
||||||
val mdfxNode = new BubbledMDFXNode(mdfxText);
|
val mdfxNode = new BubbledMDFXNode(mdfxText);
|
||||||
mdfxNode
|
mdfxNode
|
||||||
.getStylesheets()
|
.getStylesheets()
|
||||||
.add(ChatController.markdownStyleSheet);
|
.add(markdownStyleSheet);
|
||||||
mdfxNode.setBubbleSpec(BubbleSpec.FACE_RIGHT_CENTER);
|
mdfxNode.setBubbleSpec(BubbleSpec.FACE_RIGHT_CENTER);
|
||||||
mdfxNode.setBackground(
|
mdfxNode.setBackground(
|
||||||
new Background(new BackgroundFill(Color.LIGHTSTEELBLUE, null, null))
|
new Background(new BackgroundFill(Color.LIGHTSTEELBLUE, null, null))
|
||||||
@ -319,4 +364,49 @@ object ChatDataProperty {
|
|||||||
box.children += mdfxNode;
|
box.children += mdfxNode;
|
||||||
box
|
box
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def createMdMessageBox2(mdfxText: String) = {
|
||||||
|
val mdfxNode = new MDFXNode(mdfxText);
|
||||||
|
mdfxNode
|
||||||
|
.getStylesheets()
|
||||||
|
.add(markdownStyleSheet)
|
||||||
|
mdfxNode.setMaxWidth(500)
|
||||||
|
mdfxNode.vgrow = Priority.ALWAYS
|
||||||
|
mdfxNode.setAlignment(Pos.CENTER)
|
||||||
|
mdfxNode.styleClass = Seq("chat-message-box")
|
||||||
|
|
||||||
|
val box = new MessageBox("", "", mdfxText)
|
||||||
|
box.setAlignment(Pos.CENTER_RIGHT)
|
||||||
|
// box.maxWidth(500)
|
||||||
|
box.hgrow = Priority.ALWAYS
|
||||||
|
box.vgrow = Priority.ALWAYS
|
||||||
|
box.children ++= Seq(mdfxNode)
|
||||||
|
box.fillHeight = true
|
||||||
|
box
|
||||||
|
}
|
||||||
|
|
||||||
|
def createMdMessageBox3(
|
||||||
|
sender: String,
|
||||||
|
receiver: String,
|
||||||
|
mdfxText: String
|
||||||
|
) = {
|
||||||
|
val mdfxNode = new MDFXNode(mdfxText);
|
||||||
|
mdfxNode
|
||||||
|
.getStylesheets()
|
||||||
|
.add(markdownStyleSheet)
|
||||||
|
mdfxNode.setMaxWidth(500)
|
||||||
|
mdfxNode.vgrow = Priority.ALWAYS
|
||||||
|
mdfxNode.setAlignment(Pos.CENTER)
|
||||||
|
mdfxNode.styleClass = Seq("chat-message-box")
|
||||||
|
|
||||||
|
val box = new MessageBox(sender, receiver, mdfxText)
|
||||||
|
box.setAlignment(Pos.CENTER_RIGHT)
|
||||||
|
// box.maxWidth(500)
|
||||||
|
box.hgrow = Priority.ALWAYS
|
||||||
|
box.vgrow = Priority.ALWAYS
|
||||||
|
box.children ++= Seq(mdfxNode)
|
||||||
|
box.fillHeight = true
|
||||||
|
box
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@ import wow.doge.chatto.types.AppTypes
|
|||||||
import org.scalafx.extras._
|
import org.scalafx.extras._
|
||||||
import wow.doge.chatto.AppDataHandler
|
import wow.doge.chatto.AppDataHandler
|
||||||
import com.sfxcode.sapphire.core.value.BeanConversions
|
import com.sfxcode.sapphire.core.value.BeanConversions
|
||||||
|
import javafx.scene.layout.StackPane
|
||||||
|
import com.jfoenix.controls.JFXSpinner
|
||||||
|
|
||||||
class LoginController @Inject() (
|
class LoginController @Inject() (
|
||||||
userService: UserService,
|
userService: UserService,
|
||||||
@ -87,33 +89,31 @@ class LoginController @Inject() (
|
|||||||
val inputUserName = usernameTextField.text()
|
val inputUserName = usernameTextField.text()
|
||||||
val inputPassword = passwordTextField.text()
|
val inputPassword = passwordTextField.text()
|
||||||
|
|
||||||
|
submitButton.disable = true
|
||||||
login(inputUserName, inputPassword) onComplete {
|
login(inputUserName, inputPassword) onComplete {
|
||||||
case Success(maybeToken) => {
|
case Success(maybeToken) => {
|
||||||
maybeToken.foreach(println)
|
|
||||||
maybeToken match {
|
maybeToken match {
|
||||||
case Some(token) =>
|
case Some(token) =>
|
||||||
async {
|
async {
|
||||||
val credentials =
|
val credentials =
|
||||||
UserCredentials(inputUserName, inputPassword, token)
|
UserCredentials(inputUserName, inputPassword, token)
|
||||||
appDataHandler.updateCredentials(credentials)
|
appDataHandler.updateCredentials(credentials)
|
||||||
// await {
|
updateErrorLabel("")
|
||||||
// userService.getUsers(credentials).map(_.body.foreach(println))
|
|
||||||
// }
|
|
||||||
applicationController.showChatPane()
|
applicationController.showChatPane()
|
||||||
|
onFX { submitButton.disable = false }
|
||||||
}
|
}
|
||||||
case None => {
|
case None => {
|
||||||
updateErrorLabel("Error logging in - please check your password")
|
updateErrorLabel("Error logging in - please check your password")
|
||||||
logger.warn("Login unsuccessful wrong password")
|
logger.warn("Login unsuccessful wrong password")
|
||||||
|
onFX { submitButton.disable = false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// applicationController.showChatPane()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
case Failure(exception) => {
|
case Failure(exception) => {
|
||||||
logger.error(s"${exception.getMessage()}")
|
logger.error(s"${exception.getMessage()}")
|
||||||
logger.warn("Login unsuccessful network problem")
|
logger.warn("Login unsuccessful network problem")
|
||||||
updateErrorLabel("Error logging in - Please check your network")
|
updateErrorLabel("Error logging in - Please check your network")
|
||||||
// applicationController.showChatPane()
|
onFX { submitButton.disable = false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,5 +141,4 @@ class LoginController @Inject() (
|
|||||||
username: String,
|
username: String,
|
||||||
password: String
|
password: String
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,13 @@ import com.typesafe.scalalogging.LazyLogging
|
|||||||
import wow.doge.chatto.messagebuble.BubbledMDFXNode
|
import wow.doge.chatto.messagebuble.BubbledMDFXNode
|
||||||
import scalafx.scene.layout.GridPane
|
import scalafx.scene.layout.GridPane
|
||||||
import scalafx.Includes._
|
import scalafx.Includes._
|
||||||
// import wow.doge.chatto.
|
import javafx.scene.layout.HBox
|
||||||
|
import javafx.scene.layout.Priority
|
||||||
|
import wow.doge.chatto.control.UserBox
|
||||||
|
|
||||||
class MainViewController extends ViewController with LazyLogging {
|
class MainViewController extends ViewController with LazyLogging {
|
||||||
|
|
||||||
@FXML var menuBar: MenuBar = _
|
@FXML private var menuBar: MenuBar = _
|
||||||
// @FXML
|
// @FXML
|
||||||
// var workspacePane: Pane = _
|
// var workspacePane: Pane = _
|
||||||
// @FXML
|
// @FXML
|
||||||
@ -23,9 +25,7 @@ class MainViewController extends ViewController with LazyLogging {
|
|||||||
// @FXML
|
// @FXML
|
||||||
// var navigationPane: Pane = _
|
// var navigationPane: Pane = _
|
||||||
|
|
||||||
@FXML var mainPane: Pane = _
|
@FXML private var mainPane: HBox = _
|
||||||
|
|
||||||
// @FXML var chatPane: Pane = _
|
|
||||||
|
|
||||||
lazy val workspaceController = getController[WorkspaceController]()
|
lazy val workspaceController = getController[WorkspaceController]()
|
||||||
lazy val navigationController = getController[NavigationController]()
|
lazy val navigationController = getController[NavigationController]()
|
||||||
@ -33,22 +33,21 @@ class MainViewController extends ViewController with LazyLogging {
|
|||||||
lazy val loginController = getController[LoginController]()
|
lazy val loginController = getController[LoginController]()
|
||||||
lazy val chatController = getController[ChatController]()
|
lazy val chatController = getController[ChatController]()
|
||||||
|
|
||||||
// val bubbleNode = new BubbledMDFXNode("Wow")
|
|
||||||
|
|
||||||
var workspaceManager: ContentManager = _
|
var workspaceManager: ContentManager = _
|
||||||
var navigationManager: ContentManager = _
|
var navigationManager: ContentManager = _
|
||||||
var statusBarManager: ContentManager = _
|
var statusBarManager: ContentManager = _
|
||||||
var mainManager: ContentManager = _
|
var mainManager: ContentManager = _
|
||||||
|
|
||||||
override def didGainVisibilityFirstTime() {
|
override def didGainVisibilityFirstTime() = {
|
||||||
// menuBar.setUseSystemMenuBar(true)
|
menuBar.setUseSystemMenuBar(true)
|
||||||
// menuBar.setVisible(false)
|
// menuBar.setVisible(false)
|
||||||
|
|
||||||
// navigationManager =
|
// navigationManager =
|
||||||
// ContentManager(navigationPane, this, navigationController)
|
// ContentManager(navigationPane, this, navigationController)
|
||||||
// statusBarManager = ContentManager(statusPane, this, statusBarController)
|
// statusBarManager = ContentManager(statusPane, this, statusBarController)
|
||||||
// workspaceManager = ContentManager(workspacePane, this, workspaceController)
|
// workspaceManager = ContentManager(workspacePane, this, workspaceController)
|
||||||
mainManager = ContentManager(mainPane, this, loginController)
|
mainManager = ContentManager(mainPane, this, chatController)
|
||||||
|
chatController.chatMainPane.hgrow = Priority.ALWAYS
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,12 @@ import javafx.scene.control.Button
|
|||||||
|
|
||||||
class NavigationController extends AbstractViewController {
|
class NavigationController extends AbstractViewController {
|
||||||
|
|
||||||
def actionClickButton(event: ActionEvent) {
|
def actionClickButton(event: ActionEvent) = {
|
||||||
logger.debug(event.toString)
|
logger.debug(event.toString)
|
||||||
statusBarController.updateLabel(event.getSource.asInstanceOf[Button])
|
statusBarController.updateLabel(event.getSource.asInstanceOf[Button])
|
||||||
}
|
}
|
||||||
|
|
||||||
def actionHotReload(event: ActionEvent) {
|
def actionHotReload(event: ActionEvent) = {
|
||||||
applicationController.replacePrimarySceneContent()
|
applicationController.replacePrimarySceneContent()
|
||||||
logger.debug("Hot Reload Succeeded")
|
logger.debug("Hot Reload Succeeded")
|
||||||
statusBarController.updateLabel(event.getSource.asInstanceOf[Button])
|
statusBarController.updateLabel(event.getSource.asInstanceOf[Button])
|
||||||
|
@ -15,7 +15,7 @@ class WorkspaceController @Inject() (applicationName: ApplicationName)
|
|||||||
@FXML
|
@FXML
|
||||||
var infoLabel: Label = _
|
var infoLabel: Label = _
|
||||||
|
|
||||||
override def didGainVisibilityFirstTime() {
|
override def didGainVisibilityFirstTime() = {
|
||||||
infoLabel.setText(applicationName.name)
|
infoLabel.setText(applicationName.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
package wow.doge.chatto.service
|
|
||||||
|
|
||||||
import org.json4s.CustomSerializer
|
|
||||||
import org.json4s._
|
|
||||||
import java.time.Instant
|
|
||||||
// import org.json4s.JsonAST._
|
|
||||||
import org.json4s.JsonDSL._
|
|
||||||
// class ParentSerializer extends Serializer[Parent] {
|
|
||||||
// private val ParentClass = classOf[Parent]
|
|
||||||
// implicit val formats = DefaultFormats
|
|
||||||
|
|
||||||
// def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), Parent] = {
|
|
||||||
// case (TypeInfo(ParentClass, _), json) => json match {
|
|
||||||
// case JObject(JField("kind", JString(kind)) :: _) => kind match {
|
|
||||||
// case "first_type" => json.extract[ChildClassOne]
|
|
||||||
// case "second_type" => json.extract[ChildClassTwo]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// case _ => throw new MappingException("Invalid kind")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// def serialize(implicit format: Formats): PartialFunction[Any, JValue] = Map()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// class MyJInstantSerializer extends Serializer[Instant] {
|
|
||||||
// implicit val formats = DefaultFormats
|
|
||||||
|
|
||||||
// def deserialize(
|
|
||||||
// implicit format: Formats
|
|
||||||
// ): PartialFunction[(TypeInfo, JValue), Instant] = {
|
|
||||||
// case (_, JString(d)) => Instant.parse(d)
|
|
||||||
// case (_, JNull) => null
|
|
||||||
// }
|
|
||||||
|
|
||||||
// def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
|
|
||||||
// case d: Instant => JString(d.toString())
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// class MyJInstantSerializer
|
|
||||||
// extends CustomSerializer[Instant](implicit format =>
|
|
||||||
// (
|
|
||||||
// {
|
|
||||||
// // case JInt(d) => Instant.ofEpochMilli(d.toLong)
|
|
||||||
// case JString(d) => Instant.parse(d)
|
|
||||||
// case JNull => null
|
|
||||||
// }, {
|
|
||||||
// // case d: Instant => JInt(d.toEpochMilli)
|
|
||||||
// case d: Instant => JString(d.toString())
|
|
||||||
// }
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
// import java.time.ZonedDateTime
|
|
||||||
// import java.time.format.DateTimeFormatter
|
|
||||||
|
|
||||||
// a custom serializer has two partial functions, one
|
|
||||||
// for serializing and one for deserializing
|
|
||||||
// case object ZDTSerializer
|
|
||||||
// extends CustomSerializer[ZonedDateTime](format =>
|
|
||||||
// ({
|
|
||||||
// case JString(s) => ZonedDateTime.parse(s)
|
|
||||||
// }, {
|
|
||||||
// case zdt: ZonedDateTime =>
|
|
||||||
// JString(
|
|
||||||
// zdt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX"))
|
|
||||||
// )
|
|
||||||
// })
|
|
||||||
// )
|
|
@ -52,12 +52,12 @@ class UserService @Inject() (appDataHandler: AppDataHandler)(
|
|||||||
private def endpoint(uri: String) = uri"$baseUrl/$uri"
|
private def endpoint(uri: String) = uri"$baseUrl/$uri"
|
||||||
|
|
||||||
def getUsers(credentials: UserCredentials) = async {
|
def getUsers(credentials: UserCredentials) = async {
|
||||||
logger.debug(s"${appDataHandler.appData}")
|
// logger.debug(s"${appDataHandler.appData}")
|
||||||
println(
|
// println(
|
||||||
write[ActiveUser](
|
// write[ActiveUser](
|
||||||
ActiveUser("hmm what is it", true, Some(ZonedDateTime.now()))
|
// ActiveUser("hmm what is it", true, Some(ZonedDateTime.now()))
|
||||||
)
|
// )
|
||||||
)
|
// )
|
||||||
await {
|
await {
|
||||||
authBasicRequest(credentials)
|
authBasicRequest(credentials)
|
||||||
.get(uri"http://localhost:8080/api/chat/get/users")
|
.get(uri"http://localhost:8080/api/chat/get/users")
|
||||||
@ -67,7 +67,7 @@ class UserService @Inject() (appDataHandler: AppDataHandler)(
|
|||||||
}
|
}
|
||||||
|
|
||||||
def getMessages(credentials: UserCredentials) = async {
|
def getMessages(credentials: UserCredentials) = async {
|
||||||
logger.debug(s"${appDataHandler.appData}")
|
// logger.debug(s"${appDataHandler.appData}")
|
||||||
await {
|
await {
|
||||||
authBasicRequest(credentials)
|
authBasicRequest(credentials)
|
||||||
.get(uri"http://localhost:8080/api/chat/get/users")
|
.get(uri"http://localhost:8080/api/chat/get/users")
|
||||||
|
Loading…
Reference in New Issue
Block a user