Rohan Sircar
4 years ago
45 changed files with 3155 additions and 1 deletions
-
11.gitignore
-
1.scalafmt.conf
-
7CHANGES.md
-
6README.md
-
84build.sbt
-
1project/build.properties
-
4project/metals.sbt
-
6project/plugin.sbt
-
0src/main/resources/META-INF/beans.xml
-
8src/main/resources/application.conf
-
1src/main/resources/bundles/application.properties
-
1src/main/resources/bundles/application_de.properties
-
67src/main/resources/fxml/Chat.fxml
-
76src/main/resources/fxml/Login.fxml
-
71src/main/resources/fxml/MainView.fxml
-
20src/main/resources/fxml/Navigation.fxml
-
20src/main/resources/fxml/UserBox.fxml
-
17src/main/resources/fxml/Workspace.fxml
-
29src/main/resources/fxml/default.css
-
BINsrc/main/resources/images/backgroung.jpg
-
14src/main/resources/logback.xml
-
1513src/main/resources/styles/bootstrapfx.css
-
18src/main/resources/styles/markdown.css
-
16src/main/resources/styles/style2.css
-
57src/main/resources/styles/ui.css
-
30src/main/resources/styles/userbox.css
-
9src/main/scala/wow/doge/chatto/Application.scala
-
102src/main/scala/wow/doge/chatto/ApplicationController.scala
-
10src/main/scala/wow/doge/chatto/config/Beans.scala
-
52src/main/scala/wow/doge/chatto/control/UserBox.scala
-
37src/main/scala/wow/doge/chatto/controller/AbstractViewController.scala
-
80src/main/scala/wow/doge/chatto/controller/ChatController.scala
-
160src/main/scala/wow/doge/chatto/controller/LoginController.scala
-
54src/main/scala/wow/doge/chatto/controller/MainViewController.scala
-
18src/main/scala/wow/doge/chatto/controller/NavigationController.scala
-
46src/main/scala/wow/doge/chatto/controller/StatusBarController.scala
-
21src/main/scala/wow/doge/chatto/controller/WorkspaceController.scala
-
81src/main/scala/wow/doge/chatto/messagebubble/Bubble.java
-
23src/main/scala/wow/doge/chatto/messagebubble/BubbleSpec.java
-
178src/main/scala/wow/doge/chatto/messagebubble/BubbledLabel.java
-
135src/main/scala/wow/doge/chatto/messagebubble/BubbledMDFXNode.java
-
10src/main/scala/wow/doge/chatto/model/ChatUser.scala
-
46src/main/scala/wow/doge/chatto/service/UserService.scala
-
14src/main/scala/wow/doge/chatto/types/Types.scala
-
2version.sbt
@ -0,0 +1,11 @@ |
|||||
|
.idea* |
||||
|
*.iml |
||||
|
project/target |
||||
|
target |
||||
|
lib |
||||
|
out |
||||
|
.DS_Store |
||||
|
.gitconfig |
||||
|
.vscode |
||||
|
.bloop |
||||
|
.metals |
@ -0,0 +1 @@ |
|||||
|
version = "2.4.2" |
@ -0,0 +1,7 @@ |
|||||
|
# Changes # |
||||
|
|
||||
|
## Versions |
||||
|
|
||||
|
### 0.1.0-SNAPSHOT |
||||
|
|
||||
|
* initial Version |
@ -1,3 +1,7 @@ |
|||||
# Chatto-Desktop-ScalaFX |
# Chatto-Desktop-ScalaFX |
||||
|
|
||||
WIP desktop client for Chatto reimplemented in ScalaFX and Sapphire Framework |
|
||||
|
WIP desktop client for Chatto reimplemented in ScalaFX and Sapphire Framework |
||||
|
|
||||
|
## Based on Sapphire |
||||
|
|
||||
|
A JavaFX Application Framework for Scala User. [https://sfxcode.github.io/sapphire-core](https://sfxcode.github.io/sapphire-core) |
@ -0,0 +1,84 @@ |
|||||
|
name := "chatto-sapphire" |
||||
|
|
||||
|
organization := "wow.doge" |
||||
|
|
||||
|
scalaVersion := "2.13.1" |
||||
|
|
||||
|
mainClass := Some("wow.doge.chatto.Application") |
||||
|
|
||||
|
resolvers += "sfxcode-maven" at "https://bintray.com/sfxcode/maven/" |
||||
|
resolvers += "javafx-markdown-renderer" at "https://sandec.bintray.com/repo" |
||||
|
|
||||
|
libraryDependencies += "org.specs2" %% "specs2-core" % "4.7.1" % Test |
||||
|
|
||||
|
val JavaFXVersion = "11.0.2" |
||||
|
|
||||
|
val osName = System.getProperty("os.name") match { |
||||
|
case n if n.startsWith("Linux") => "linux" |
||||
|
case n if n.startsWith("Mac") => "mac" |
||||
|
case n if n.startsWith("Windows") => "win" |
||||
|
case _ => throw new Exception("Unknown platform!") |
||||
|
} |
||||
|
|
||||
|
fork := true |
||||
|
|
||||
|
libraryDependencies ++= Seq( |
||||
|
"base", |
||||
|
"controls", |
||||
|
"fxml", |
||||
|
"graphics", |
||||
|
"media", |
||||
|
"swing", |
||||
|
"web" |
||||
|
).map(m => "org.openjfx" % s"javafx-$m" % JavaFXVersion classifier osName) |
||||
|
|
||||
|
libraryDependencies += "com.sfxcode.sapphire" %% "sapphire-core" % "1.7.3" |
||||
|
|
||||
|
libraryDependencies += "com.sfxcode.sapphire" %% "sapphire-extension" % "1.0.6" |
||||
|
|
||||
|
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3" |
||||
|
|
||||
|
libraryDependencies ++= Seq( |
||||
|
"org.scalafx" %% "scalafx" % "12.0.2-R18", |
||||
|
"org.scalafx" %% "scalafx-extras" % "0.3.4", |
||||
|
"com.softwaremill.sttp.client" %% "json4s" % "2.1.1", |
||||
|
"org.json4s" %% "json4s-native" % "3.6.7", |
||||
|
"org.scala-lang.modules" %% "scala-async" % "0.10.0", |
||||
|
"org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided, |
||||
|
// "org.kordamp.ikonli" %% "ikonli-javafx" % "11.4.0", |
||||
|
// "org.kordamp.ikonli" %% "ikonli-fontawesome-pack" % "11.4.0", |
||||
|
// "org.kordamp.ikonli" %% "ikonli-fontawesome5-pack" % "11.4.0", |
||||
|
"org.jsoup" % "jsoup" % "1.13.1", |
||||
|
"com.sandec" % "mdfx" % "0.1.6", |
||||
|
"com.softwaremill.sttp.client" %% "async-http-client-backend-future" % "2.1.1", |
||||
|
"com.softwaremill.quicklens" %% "quicklens" % "1.5.0" |
||||
|
) |
||||
|
libraryDependencies += "org.asynchttpclient" % "async-http-client" % "2.12.1" |
||||
|
libraryDependencies += "com.softwaremill.macwire" %% "macros" % "2.3.3" |
||||
|
scalacOptions ++= Seq("-Ymacro-annotations", "-deprecation") |
||||
|
|
||||
|
libraryDependencies += "org.scalafx" %% "scalafxml-core-sfx8" % "0.5" |
||||
|
// https://mvnrepository.com/artifact/com.jfoenix/jfoenix |
||||
|
libraryDependencies += "com.jfoenix" % "jfoenix" % "9.0.9" |
||||
|
// https://mvnrepository.com/artifact/org.kordamp.bootstrapfx/bootstrapfx-core |
||||
|
libraryDependencies += "org.kordamp.bootstrapfx" % "bootstrapfx-core" % "0.2.4" |
||||
|
|
||||
|
enablePlugins(BuildInfoPlugin) |
||||
|
|
||||
|
buildInfoPackage := "wow.doge.chatto" |
||||
|
|
||||
|
buildInfoOptions += BuildInfoOption.BuildTime |
||||
|
|
||||
|
enablePlugins(JavaFxPlugin) |
||||
|
|
||||
|
javaFxMainClass := "wow.doge.chatto.Application" |
||||
|
|
||||
|
javaFxJvmargs := Seq("-Xms512m", "-Xmx1024m", "-XX:ReservedCodeCacheSize=128m") |
||||
|
|
||||
|
javaFxTitle := "chatto-sapphire" |
||||
|
|
||||
|
javaFxCategory := "Aplication" |
||||
|
|
||||
|
javaFxNativeBundles := "image" |
||||
|
|
||||
|
javaFxVerbose := true |
@ -0,0 +1 @@ |
|||||
|
sbt.version=1.3.8 |
@ -0,0 +1,4 @@ |
|||||
|
// DO NOT EDIT! This file is auto-generated. |
||||
|
// This file enables sbt-bloop to create bloop config files. |
||||
|
|
||||
|
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.4.0-RC1-229-b7c15aa9") |
@ -0,0 +1,6 @@ |
|||||
|
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.5.0") |
||||
|
|
||||
|
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.9.0") |
||||
|
|
||||
|
addSbtPlugin("com.quadstingray" % "sbt-javafx" % "1.5.2") |
||||
|
|
@ -0,0 +1,8 @@ |
|||||
|
sapphire.core.fxml.basePath="/fxml/" |
||||
|
application.name = "Application" |
||||
|
project.name = "chatto-sapphire" |
||||
|
project.version = "0.1.0-SNAPSHOT" |
||||
|
stage.default { |
||||
|
height = 600 |
||||
|
width = 800 |
||||
|
} |
@ -0,0 +1 @@ |
|||||
|
navigation.toggle=Toggle Workspace |
@ -0,0 +1 @@ |
|||||
|
navigation.toggle=Bereich wechseln |
@ -0,0 +1,67 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
|
||||
|
<?import java.net.URL ?> |
||||
|
<?import javafx.geometry.Insets ?> |
||||
|
<?import javafx.scene.control.Button ?> |
||||
|
<?import javafx.scene.control.Label ?> |
||||
|
<?import javafx.scene.control.ListView ?> |
||||
|
<?import javafx.scene.control.TextArea ?> |
||||
|
<?import javafx.scene.layout.BorderPane ?> |
||||
|
<?import javafx.scene.layout.FlowPane ?> |
||||
|
<?import javafx.scene.layout.HBox ?> |
||||
|
<?import javafx.scene.layout.VBox ?> |
||||
|
|
||||
|
<!-- <?import com.example.javafx.control.UserBox?> --> |
||||
|
<!-- 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"> |
||||
|
<left> |
||||
|
<VBox fx:id="usersVBox" alignment="TOP_CENTER" prefHeight="200.0" prefWidth="175.0" BorderPane.alignment="CENTER"> |
||||
|
<children> |
||||
|
<Button mnemonicParsing="false" styleClass="userButton" text="User1" VBox.vgrow="ALWAYS"> |
||||
|
<VBox.margin> |
||||
|
<Insets /> |
||||
|
</VBox.margin> |
||||
|
</Button> |
||||
|
<Button mnemonicParsing="false" styleClass="userButton" text="User2"> |
||||
|
<VBox.margin> |
||||
|
<Insets /> |
||||
|
</VBox.margin> |
||||
|
</Button> |
||||
|
</children> |
||||
|
</VBox> |
||||
|
</left> |
||||
|
<center> |
||||
|
<VBox prefHeight="200.0" prefWidth="100.0" spacing="5.0" BorderPane.alignment="CENTER"> |
||||
|
<children> |
||||
|
<ListView fx:id="chatListView" prefHeight="792.0" prefWidth="610.0" /> |
||||
|
<TextArea id="chatTextArea" fx:id="chatTextArea" editable="false" prefHeight="474.0" prefWidth="690.0" styleClass="lead" visible="false" VBox.vgrow="ALWAYS"> |
||||
|
<VBox.margin> |
||||
|
<Insets /> |
||||
|
</VBox.margin> |
||||
|
</TextArea> |
||||
|
<HBox prefHeight="50.0" prefWidth="790.0" spacing="2.0"> |
||||
|
<children> |
||||
|
<Label fx:id="label" contentDisplay="CENTER" maxWidth="100.0" prefHeight="30.0" prefWidth="52.0" text="Label" /> |
||||
|
<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"> |
||||
|
<children> |
||||
|
|
||||
|
<Button fx:id="logoutButton" styleClass="btn, btn-primary" text="Logout" /> |
||||
|
<Button fx:id="submitButton" styleClass="btn, btn-primary" text="Submit" /> |
||||
|
|
||||
|
</children> |
||||
|
</FlowPane> |
||||
|
</children> |
||||
|
</HBox> |
||||
|
</children> |
||||
|
<BorderPane.margin> |
||||
|
<Insets left="5.0" /> |
||||
|
</BorderPane.margin> |
||||
|
</VBox> |
||||
|
</center> |
||||
|
<stylesheets> |
||||
|
<URL value="@../styles/ui.css" /> |
||||
|
<URL value="@../styles/bootstrapfx.css" /> |
||||
|
</stylesheets> |
||||
|
</BorderPane> |
@ -0,0 +1,76 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
|
||||
|
<?import com.jfoenix.controls.JFXButton ?> |
||||
|
<?import com.jfoenix.controls.JFXPasswordField ?> |
||||
|
<?import com.jfoenix.controls.JFXTextField ?> |
||||
|
<?import java.net.URL ?> |
||||
|
<?import javafx.scene.control.Label ?> |
||||
|
<?import javafx.scene.effect.DropShadow ?> |
||||
|
<?import javafx.scene.layout.ColumnConstraints ?> |
||||
|
<?import javafx.scene.layout.GridPane ?> |
||||
|
<?import javafx.scene.layout.RowConstraints ?> |
||||
|
<?import javafx.scene.layout.VBox ?> |
||||
|
<?import javafx.scene.text.Font ?> |
||||
|
|
||||
|
<!-- minHeight="533.0" minWidth="800" maxHeight="533.0" maxWidth="800" --> |
||||
|
<!-- fx:controller="com.example.javafx.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 hgrow="SOMETIMES" maxWidth="257.0" minWidth="10.0" prefWidth="122.0" /> |
||||
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="667.0" /> |
||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="121.0" minWidth="10.0" prefWidth="119.0" /> |
||||
|
</columnConstraints> |
||||
|
<rowConstraints> |
||||
|
<RowConstraints maxHeight="170.0" minHeight="0.0" prefHeight="54.0" vgrow="SOMETIMES" /> |
||||
|
<RowConstraints minHeight="10.0" prefHeight="429.0" vgrow="SOMETIMES" /> |
||||
|
<RowConstraints maxHeight="63.0" minHeight="0.0" prefHeight="48.0" vgrow="SOMETIMES" /> |
||||
|
</rowConstraints> |
||||
|
<children> |
||||
|
<VBox alignment="CENTER" fillWidth="false" prefHeight="431.0" prefWidth="283.0" spacing="20.0" style="-fx-background-color: #fff; -fx-background-radius: 40px;" GridPane.columnIndex="1" GridPane.rowIndex="1"> |
||||
|
<effect> |
||||
|
<DropShadow color="#9e9e9e" /> |
||||
|
</effect> |
||||
|
<children> |
||||
|
<Label lineSpacing="10.0" text="Sign In" textFill="#004ecd"> |
||||
|
<font> |
||||
|
<Font name="Microsoft JhengHei UI Light" size="28.0" /> |
||||
|
</font> |
||||
|
</Label> |
||||
|
<Label alignment="CENTER" prefHeight="37.0" prefWidth="324.0" text="Hi, please login to view your messages" textAlignment="CENTER" textFill="#727070" wrapText="true"> |
||||
|
<font> |
||||
|
<Font size="14.0" /> |
||||
|
</font> |
||||
|
</Label> |
||||
|
<JFXTextField 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" 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" styleClass="btn, btn-primary" text="Submit" /> |
||||
|
|
||||
|
<!-- 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"> |
||||
|
<font> |
||||
|
<Font size="14.0" /> |
||||
|
</font> |
||||
|
</Label> |
||||
|
|
||||
|
<Label alignment="CENTER" prefHeight="31.0" prefWidth="263.0" text="Forgot password" textAlignment="CENTER" textFill="#727070" wrapText="true"> |
||||
|
<font> |
||||
|
<Font size="14.0" /> |
||||
|
</font> |
||||
|
</Label> |
||||
|
<Label alignment="CENTER" prefHeight="31.0" prefWidth="221.0" text="Create a new account " textAlignment="CENTER" textFill="#727070" wrapText="true"> |
||||
|
<font> |
||||
|
<Font size="14.0" /> |
||||
|
</font> |
||||
|
</Label> |
||||
|
</children> |
||||
|
</VBox> |
||||
|
</children> |
||||
|
<stylesheets> |
||||
|
<URL value="@../styles/style2.css" /> |
||||
|
<URL value="@../styles/bootstrapfx.css" /> |
||||
|
</stylesheets> |
||||
|
</GridPane> |
@ -0,0 +1,71 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
|
||||
|
<?import java.net.* ?> |
||||
|
<?import javafx.scene.layout.* ?> |
||||
|
<?import javafx.scene.control.* ?> |
||||
|
|
||||
|
<AnchorPane 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> |
||||
|
<MenuBar VBox.vgrow="NEVER" fx:id="menuBar"> |
||||
|
<menus> |
||||
|
<Menu mnemonicParsing="false" text="File"> |
||||
|
<items> |
||||
|
<MenuItem mnemonicParsing="false" text="New" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Open…" /> |
||||
|
<Menu mnemonicParsing="false" text="Open Recent" /> |
||||
|
<SeparatorMenuItem mnemonicParsing="false" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Close" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Save" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Save As…" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Revert" /> |
||||
|
<SeparatorMenuItem mnemonicParsing="false" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Preferences…" /> |
||||
|
<SeparatorMenuItem mnemonicParsing="false" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Quit" /> |
||||
|
</items> |
||||
|
</Menu> |
||||
|
<Menu mnemonicParsing="false" text="Edit"> |
||||
|
<items> |
||||
|
<MenuItem mnemonicParsing="false" text="Undo" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Redo" /> |
||||
|
<SeparatorMenuItem mnemonicParsing="false" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Cut" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Copy" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Paste" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Delete" /> |
||||
|
<SeparatorMenuItem mnemonicParsing="false" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Select All" /> |
||||
|
<MenuItem mnemonicParsing="false" text="Unselect All" /> |
||||
|
</items> |
||||
|
</Menu> |
||||
|
<Menu mnemonicParsing="false" text="Help"> |
||||
|
<items> |
||||
|
<MenuItem mnemonicParsing="false" text="About MyHelloApp" /> |
||||
|
</items> |
||||
|
</Menu> |
||||
|
</menus> |
||||
|
</MenuBar> |
||||
|
|
||||
|
<!-- <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="loginPane"></AnchorPane> |
||||
|
<AnchorPane fx:id="chatPane"></AnchorPane> |
||||
|
</children> |
||||
|
<stylesheets> |
||||
|
<URL value="@default.css" /> |
||||
|
<URL value="@../styles/ui.css" /> |
||||
|
</stylesheets> |
||||
|
</AnchorPane> |
@ -0,0 +1,20 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
|
||||
|
<?import javafx.geometry.Insets?> |
||||
|
<?import javafx.scene.control.Button?> |
||||
|
<?import javafx.scene.layout.AnchorPane?> |
||||
|
<?import javafx.scene.layout.HBox?> |
||||
|
|
||||
|
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="40.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wow.doge.chatto.controller.NavigationController"> |
||||
|
<children> |
||||
|
<HBox layoutY="-10.0" prefHeight="40.0" prefWidth="600.0" spacing="10.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> |
||||
|
<children> |
||||
|
<Button mnemonicParsing="false" onAction="#actionClickButton" text="Navigation Button" /> |
||||
|
<Button mnemonicParsing="false" onAction="#actionHotReload" text="Hot Reload FXML" textFill="RED" /> |
||||
|
</children> |
||||
|
<padding> |
||||
|
<Insets left="10.0" top="5.0" /> |
||||
|
</padding> |
||||
|
</HBox> |
||||
|
</children> |
||||
|
</AnchorPane> |
@ -0,0 +1,20 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
|
||||
|
<?import java.net.URL ?> |
||||
|
<?import javafx.scene.control.Label ?> |
||||
|
<?import javafx.scene.control.RadioButton ?> |
||||
|
<?import javafx.scene.layout.VBox ?> |
||||
|
|
||||
|
<!-- fx:controller="com.example.javafx.control.UserBox" --> |
||||
|
|
||||
|
<fx:root prefHeight="65.0" styleClass="btn, btn-primary, user-box" type="VBox" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1"> |
||||
|
<children> |
||||
|
<!-- <Label fx:id="nameLabel" id="nameLabel" text="John Doe" /> --> |
||||
|
<RadioButton fx:id="_userRadioButton" mnemonicParsing="false" styleClass="h1, user-radio, lead" text="John Doe Radio" /> |
||||
|
<Label fx:id="_messageLabel" styleClass="messageLabel, lbl" text="Hey there, how are you?" /> |
||||
|
</children> |
||||
|
<stylesheets> |
||||
|
<URL value="@../styles/userbox.css" /> |
||||
|
<URL value="@../styles/bootstrapfx.css" /> |
||||
|
</stylesheets> |
||||
|
</fx:root> |
@ -0,0 +1,17 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
|
||||
|
<?import javafx.scene.control.Label?> |
||||
|
<?import javafx.scene.layout.*?> |
||||
|
<?import java.net.URL?> |
||||
|
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" |
||||
|
styleClass="workspace" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" |
||||
|
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/null" |
||||
|
xmlns:fx="http://javafx.com/fxml/1" |
||||
|
fx:controller="wow.doge.chatto.controller.WorkspaceController"> |
||||
|
<children> |
||||
|
<Label fx:id="infoLabel" layoutX="79.0" layoutY="126.0" text="Workspace"/> |
||||
|
</children> |
||||
|
<stylesheets> |
||||
|
<URL value="@default.css"/> |
||||
|
</stylesheets> |
||||
|
</AnchorPane> |
@ -0,0 +1,29 @@ |
|||||
|
.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; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
After Width: 800 | Height: 533 | Size: 50 KiB |
@ -0,0 +1,14 @@ |
|||||
|
<configuration> |
||||
|
|
||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> |
||||
|
<!-- encoders are assigned the type |
||||
|
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> |
||||
|
<encoder> |
||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> |
||||
|
</encoder> |
||||
|
</appender> |
||||
|
|
||||
|
<root level="info"> |
||||
|
<appender-ref ref="STDOUT" /> |
||||
|
</root> |
||||
|
</configuration> |
1513
src/main/resources/styles/bootstrapfx.css
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,18 @@ |
|||||
|
* { |
||||
|
-mdfx-font-color: white; |
||||
|
-mdfx-border-color-1: #888; |
||||
|
|
||||
|
-mdfx-bg-color-1: #ccc; |
||||
|
-mdfx-bg-color-2: #ddd; |
||||
|
-mdfx-bg-color-3: #eee; |
||||
|
} |
||||
|
|
||||
|
.markdown-text { |
||||
|
-fx-font-family: ARIAL; |
||||
|
} |
||||
|
.markdown-italic { |
||||
|
-fx-font-style: italic; |
||||
|
} |
||||
|
.markdown-bold { |
||||
|
-fx-font-weight: bold; |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
#rootPane{ |
||||
|
-fx-background-image: url("../images/backgroung.jpg"); |
||||
|
-fx-background-size: 1920.0 1080.0; |
||||
|
-fx-background-position: center center; |
||||
|
} |
||||
|
|
||||
|
.ikonli-font-icon{ |
||||
|
-fx-icon-size: 100px; |
||||
|
-fx-icon-color: blue; |
||||
|
} |
||||
|
|
||||
|
.user-radio .radio { |
||||
|
visibility: hidden; |
||||
|
-fx-pref-width: 0px; |
||||
|
-fx-max-width: 0px; |
||||
|
} |
@ -0,0 +1,57 @@ |
|||||
|
/* .button { |
||||
|
-fx-background-color: #009688; |
||||
|
-fx-background-radius: 0.0; |
||||
|
-fx-text-fill: #FFFFFF; |
||||
|
-fx-margin: 0.0; |
||||
|
-fx-background-radius: 21.0px; |
||||
|
} */ |
||||
|
|
||||
|
/* .userButton{ |
||||
|
-fx-background-color: #ff9688; |
||||
|
-fx-background-radius: 0.0px; |
||||
|
-fx-pref-width: 100px; |
||||
|
-fx-pref-height: 40px; |
||||
|
-fx-background-insets: 5px; |
||||
|
} */ |
||||
|
.root{ |
||||
|
-fx-padding: 5.0 5.0 5.0 5.0; |
||||
|
-fx-background-image: url("../images/backgroung.jpg"); |
||||
|
-fx-background-size: 1920.0 1080.0; |
||||
|
-fx-background-position: center center; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#flowPane { |
||||
|
-fx-hgap: 5.0px; |
||||
|
-fx-vgap: 5.0px; |
||||
|
} |
||||
|
|
||||
|
.userVbox { |
||||
|
-fx-padding: 5.0 5.0 5.0 5.0; |
||||
|
-fx-background-insets: 5px; |
||||
|
-fx-background-size: 1920.0 1080.0; |
||||
|
-fx-background-position: center center; |
||||
|
-fx-background-color: #ff0055; |
||||
|
-fx-background-radius: 10px; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#chatTextArea{ |
||||
|
-fx-font-size: 1.4em; |
||||
|
} |
||||
|
|
||||
|
.my-list-cell { |
||||
|
-fx-background-color: null; |
||||
|
} |
||||
|
|
||||
|
.my-list-view { |
||||
|
-fx-background-color: null; |
||||
|
} |
||||
|
|
||||
|
.my-list-view > .list-cell { |
||||
|
-fx-background-color: null; |
||||
|
} |
||||
|
|
||||
|
/*.myButton { |
||||
|
-fx-background-radius: 21.0px; |
||||
|
}*/ |
@ -0,0 +1,30 @@ |
|||||
|
.user-box { |
||||
|
-fx-padding: 0.0 2.5 0.0 0.0; |
||||
|
-fx-background-radius: 0px; |
||||
|
-fx-border-color: #337ab7; |
||||
|
} |
||||
|
.user-box:selected { |
||||
|
-fx-background-color: red; |
||||
|
} |
||||
|
.user-radio .radio { |
||||
|
visibility: hidden; |
||||
|
-fx-pref-width: 0.0px; |
||||
|
-fx-max-width: 0.0px; |
||||
|
-fx-padding: 0.0 0.0 0.0 0.0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.user-radio { |
||||
|
-fx-font-size: 20px ; |
||||
|
} |
||||
|
#nameLabel { |
||||
|
-fx-text-fill: #fff; |
||||
|
} |
||||
|
.user-radio { |
||||
|
-fx-text-fill: #fff; |
||||
|
} |
||||
|
.messageLabel { |
||||
|
-fx-padding: 0.0 0.0 0.0 5.0; |
||||
|
-fx-text-fill: #fff; |
||||
|
-fx-font-size: 15px ; |
||||
|
} |
@ -0,0 +1,9 @@ |
|||||
|
package wow.doge.chatto |
||||
|
|
||||
|
import com.sfxcode.sapphire.core.ConfigValues |
||||
|
import com.sfxcode.sapphire.core.application.FXApp |
||||
|
|
||||
|
object Application extends FXApp with ConfigValues { |
||||
|
|
||||
|
override def title: String = configStringValue("project.name") |
||||
|
} |
@ -0,0 +1,102 @@ |
|||||
|
package wow.doge.chatto |
||||
|
|
||||
|
import javax.enterprise.context.ApplicationScoped |
||||
|
import javax.enterprise.inject.Produces |
||||
|
import javax.inject.Named |
||||
|
import com.typesafe.config.ConfigFactory |
||||
|
import com.sfxcode.sapphire.core.controller.DefaultWindowController |
||||
|
// import org.asynchttpclient.Dsl._ |
||||
|
import wow.doge.chatto.controller.MainViewController |
||||
|
import sttp.client.asynchttpclient.future.AsyncHttpClientFutureBackend |
||||
|
import sttp.client._ |
||||
|
import scala.concurrent.ExecutionContext.Implicits.global |
||||
|
import scala.async.Async.{async, await} |
||||
|
import sttp.client.json4s._ |
||||
|
import org.json4s._ |
||||
|
import org.json4s.native.JsonMethods._ |
||||
|
import org.json4s.JsonDSL._ |
||||
|
import scala.util.Success |
||||
|
import scala.util.Failure |
||||
|
import com.softwaremill.quicklens._ |
||||
|
@Named |
||||
|
@ApplicationScoped |
||||
|
class ApplicationController extends DefaultWindowController { |
||||
|
// import ApplicationController._ |
||||
|
|
||||
|
lazy val mainViewController = getController[MainViewController]() |
||||
|
private implicit lazy val serialization = org.json4s.native.Serialization |
||||
|
private implicit lazy val backend = AsyncHttpClientFutureBackend() |
||||
|
|
||||
|
// override def width: Int = 400 |
||||
|
|
||||
|
def applicationDidLaunch() = { |
||||
|
logger.info("start " + this) |
||||
|
applicationEnvironment.loadResourceBundle("bundles/application") |
||||
|
replaceSceneContent(mainViewController) |
||||
|
} |
||||
|
|
||||
|
@Produces |
||||
|
def applicationName: ApplicationName = { |
||||
|
ApplicationName(configStringValue("application.name")) |
||||
|
} |
||||
|
|
||||
|
@Produces var appData: AppData = synchronized { |
||||
|
AppData(User.empty, "") |
||||
|
} |
||||
|
|
||||
|
@Produces |
||||
|
def httpBackend = backend |
||||
|
|
||||
|
def replacePrimarySceneContent(): Unit = { |
||||
|
// Styling |
||||
|
reloadStyles() |
||||
|
// Resources |
||||
|
applicationEnvironment.clearResourceBundleCache() |
||||
|
applicationEnvironment.loadResourceBundle("bundles/application") |
||||
|
// FXML |
||||
|
val newMainViewController = getController[MainViewController]() |
||||
|
replaceSceneContent(newMainViewController) |
||||
|
} |
||||
|
|
||||
|
override def applicationWillStop(): Unit = async { |
||||
|
super.applicationWillStop() |
||||
|
println("stopping") |
||||
|
await(httpBackend.close()) |
||||
|
System.exit(0) |
||||
|
} |
||||
|
|
||||
|
def showLoginPane() = { |
||||
|
appData = appData.copy(user = User.empty) |
||||
|
appData = appData.modify(_.user).using(_ => User.empty) |
||||
|
appData = appData.modify(_.user.username).using(_ => "") |
||||
|
replaceSceneContent(mainViewController.loginController) |
||||
|
} |
||||
|
|
||||
|
def showChatPane(): Unit = { |
||||
|
// import org.scalafx.extras._ |
||||
|
replaceSceneContent(mainViewController.chatController, true) |
||||
|
// 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) |
||||
|
} |
||||
|
} |
||||
|
final case class ApplicationName(name: String) |
||||
|
final case class User(username: String, password: String, token: String) |
||||
|
object User { |
||||
|
def empty = User("", "", "") |
||||
|
} |
||||
|
final case class AppData(user: User, sumth: String) |
@ -0,0 +1,10 @@ |
|||||
|
package wow.doge.chatto.config |
||||
|
|
||||
|
import javax.enterprise.context.ApplicationScoped |
||||
|
import javax.enterprise.inject.Produces |
||||
|
|
||||
|
@ApplicationScoped |
||||
|
class AppBeans { |
||||
|
@Produces |
||||
|
def something: String = "Hello" |
||||
|
} |
@ -0,0 +1,52 @@ |
|||||
|
package wow.doge.chatto.control |
||||
|
|
||||
|
import javafx.scene.layout.VBox |
||||
|
import javafx.fxml.FXML |
||||
|
import javafx.scene.control.RadioButton |
||||
|
import javafx.scene.control.Label |
||||
|
import javafx.fxml.FXMLLoader |
||||
|
import scalafx.Includes._ |
||||
|
|
||||
|
class UserBox() extends VBox() { |
||||
|
@FXML private var _userRadioButton: RadioButton = _ |
||||
|
@FXML private var _messageLabel: Label = _ |
||||
|
|
||||
|
def userRadioButton = this._userRadioButton |
||||
|
def messageLabel = this._messageLabel |
||||
|
|
||||
|
init() |
||||
|
|
||||
|
def init() = { |
||||
|
val fxmlLoader = new FXMLLoader( |
||||
|
getClass().getResource("/fxml/UserBox.fxml") |
||||
|
) |
||||
|
fxmlLoader.setRoot(this); |
||||
|
fxmlLoader.setController(this); |
||||
|
|
||||
|
fxmlLoader.load(); |
||||
|
|
||||
|
// userRadioButton |
||||
|
// .selectedProperty() |
||||
|
// .addListener(changeListener => { |
||||
|
// if (userRadioButton.isSelected()) { |
||||
|
// getStyleClass().clear(); |
||||
|
// getStyleClass().addAll("btn", "btn-primary", "user-box"); |
||||
|
// } else { |
||||
|
// getStyleClass().clear(); |
||||
|
// getStyleClass().addAll("btn", "btn-primary", "user-box"); |
||||
|
// } |
||||
|
// }); |
||||
|
|
||||
|
userRadioButton.selected.onChange { (_, _, _) => |
||||
|
{ |
||||
|
getStyleClass().clear(); |
||||
|
getStyleClass().addAll("btn", "btn-primary", "user-box"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
object UserBox { |
||||
|
// val ub = new UserBox() |
||||
|
} |
@ -0,0 +1,37 @@ |
|||||
|
package wow.doge.chatto.controller |
||||
|
|
||||
|
import com.sfxcode.sapphire.core.controller.ViewController |
||||
|
import com.typesafe.scalalogging.LazyLogging |
||||
|
import wow.doge.chatto.ApplicationController |
||||
|
|
||||
|
abstract class AbstractViewController extends ViewController with LazyLogging { |
||||
|
|
||||
|
override def didGainVisibility(): Unit = { |
||||
|
statusBarController.statusLabel.setText( |
||||
|
"%s loaded".format(getClass.getSimpleName) |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
def applicationController: ApplicationController = { |
||||
|
getBean[ApplicationController]() |
||||
|
|
||||
|
} |
||||
|
|
||||
|
def mainViewController: MainViewController = |
||||
|
applicationController.mainViewController |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @return |
||||
|
*/ |
||||
|
def statusBarController = getBean[StatusBarController]() |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @return workspace manager resolved by parent |
||||
|
*/ |
||||
|
def workspaceManager = mainViewController.workspaceManager |
||||
|
|
||||
|
// def loginManager = mainViewController.loginManager |
||||
|
|
||||
|
} |
@ -0,0 +1,80 @@ |
|||||
|
package wow.doge.chatto.controller |
||||
|
|
||||
|
import javafx.fxml.FXML |
||||
|
import javafx.scene.control.Label |
||||
|
import javafx.scene.control.Button |
||||
|
import javafx.scene.layout.FlowPane |
||||
|
import javafx.scene.control.TextArea |
||||
|
import javafx.scene.control.ListView |
||||
|
import javafx.scene.layout.HBox |
||||
|
import javafx.scene.layout.VBox |
||||
|
import scalafx.Includes._ |
||||
|
import wow.doge.chatto.control.UserBox |
||||
|
import javafx.application.Platform |
||||
|
import javax.inject.Inject |
||||
|
import org.scalafx.extras._ |
||||
|
import wow.doge.chatto.messagebuble.BubbledMDFXNode |
||||
|
import wow.doge.chatto.service.UserService |
||||
|
import scala.concurrent.ExecutionContext |
||||
|
import scala.concurrent.ExecutionContext.Implicits.global |
||||
|
import com.typesafe.scalalogging.LazyLogging |
||||
|
// import wow.doge.chatto.controller.LoginController.Person |
||||
|
import com.sfxcode.sapphire.core.value.FXBean |
||||
|
|
||||
|
class ChatController @Inject() (userService: UserService) |
||||
|
extends AbstractViewController |
||||
|
with LazyLogging { |
||||
|
|
||||
|
@FXML private var label: Label = _ |
||||
|
@FXML private var flowPane: FlowPane = _ |
||||
|
@FXML private var submitButton: Button = _ |
||||
|
@FXML private var loginButton: Button = _ |
||||
|
@FXML private var chatTextArea: TextArea = _ |
||||
|
@FXML private var chatInput: TextArea = _ |
||||
|
@FXML private var usersVBox: VBox = _ |
||||
|
@FXML private var chatListView: ListView[HBox] = _ |
||||
|
// applicationController.show |
||||
|
|
||||
|
override def didGainVisibilityFirstTime(): Unit = { |
||||
|
super.didGainVisibilityFirstTime() |
||||
|
val ub = new UserBox() |
||||
|
this.stage.resizable = true |
||||
|
ub.messageLabel.text = "Hi there" |
||||
|
// ub.messageLabel.id = |
||||
|
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}")) |
||||
|
|
||||
|
val person = Person(0, 10, "Billy") |
||||
|
val bean = FXBean[Person](person) |
||||
|
ub.messageLabel.text <== bean.getStringProperty("name") |
||||
|
// bean.getStringProperty("name") <== chatInput.text |
||||
|
|
||||
|
// bean.getStringProperty("name")() = "Lester" |
||||
|
println(bean.getValue("name")) |
||||
|
println(bean.getStringProperty("name")()) |
||||
|
// bean. |
||||
|
bean.updateValue("name", "Lester") |
||||
|
println(bean.bean) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
override def didGainVisibility(): Unit = { |
||||
|
super.didGainVisibility() |
||||
|
} |
||||
|
def func() = { |
||||
|
val x = offFXAndWait { |
||||
|
2 + 3 |
||||
|
} |
||||
|
x |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
final case class Person(id: Int, age: Int, name: String) |
@ -0,0 +1,160 @@ |
|||||
|
package wow.doge.chatto.controller |
||||
|
|
||||
|
import com.typesafe.scalalogging.LazyLogging |
||||
|
import com.sfxcode.sapphire.core.controller.ViewController |
||||
|
import javafx.fxml.FXML |
||||
|
import com.jfoenix.controls.JFXButton |
||||
|
import com.jfoenix.controls.JFXTextField |
||||
|
import com.jfoenix.controls.JFXPasswordField |
||||
|
import scalafx.Includes._ |
||||
|
// import scalafx.application.Platform |
||||
|
import scalafx.event.ActionEvent |
||||
|
import com.sfxcode.sapphire.core.value.KeyBindings |
||||
|
import scalafx.scene.layout.VBox |
||||
|
import com.sfxcode.sapphire.core.value.FXBean |
||||
|
import javax.inject.Inject |
||||
|
import com.sfxcode.sapphire.core.value.FXBeanAdapter |
||||
|
import wow.doge.chatto.service.UserService |
||||
|
import scala.concurrent.ExecutionContext.Implicits.global |
||||
|
import scala.util.Success |
||||
|
import scala.util.Failure |
||||
|
import javafx.scene.control.Label |
||||
|
import javafx.scene.input.KeyCode |
||||
|
import scala.async.Async.{async, await} |
||||
|
import wow.doge.chatto.AppData |
||||
|
import wow.doge.chatto.User |
||||
|
import sttp.client._ |
||||
|
import scala.concurrent.Future |
||||
|
import sttp.client.asynchttpclient.WebSocketHandler |
||||
|
import wow.doge.chatto.types.AppTypes.HttpBackend |
||||
|
import wow.doge.chatto.types.AppTypes |
||||
|
|
||||
|
class LoginController @Inject() (userService: UserService, var appData: AppData)( |
||||
|
implicit backend: HttpBackend |
||||
|
) extends AbstractViewController |
||||
|
with LazyLogging |
||||
|
with AppTypes { |
||||
|
@FXML private var submitButton: JFXButton = _ |
||||
|
|
||||
|
@FXML private var usernameTextField: JFXTextField = _ |
||||
|
|
||||
|
@FXML private var passwordTextField: JFXPasswordField = _ |
||||
|
|
||||
|
@FXML private var errorLabel: Label = _ |
||||
|
|
||||
|
override def didGainVisibilityFirstTime(): Unit = { |
||||
|
super.didGainVisibilityFirstTime() |
||||
|
this.stage.resizable = false |
||||
|
usernameTextField.requestFocus() |
||||
|
submitButton.setOnAction(actionLogin) |
||||
|
|
||||
|
// println(something) |
||||
|
|
||||
|
val bindings = KeyBindings("usernameTextField", "passwordTextField") |
||||
|
// Expression Binding Example |
||||
|
// bindings.add( |
||||
|
// "usernameTextField", |
||||
|
// "${sf:i18n('personText', _self.usernameTextField(), _self.passwordTextField())})" |
||||
|
// ) |
||||
|
|
||||
|
val box = new VBox() |
||||
|
val adapter = FXBeanAdapter[Person](this) |
||||
|
// adapter. |
||||
|
val bean = FXBean[Person](Person("twar", "username", "password")) |
||||
|
// bean. |
||||
|
// bean.get |
||||
|
adapter.addBindings(bindings) |
||||
|
adapter.set(bean) |
||||
|
// adapter.addIntConverter("age") |
||||
|
// adapter.hasBeanProperty |
||||
|
// adapter.revert() |
||||
|
|
||||
|
// usernameTextField.onKeyPressed = (keyEvent) => { |
||||
|
// if (keyEvent.getCode() == KeyCode.ENTER) submitButton.fire() |
||||
|
// } |
||||
|
// submitButton.onKeyPressed = (keyEvent) => { |
||||
|
// if (keyEvent.getCode() == KeyCode.ENTER) submitButton.fire() |
||||
|
// } |
||||
|
// passwordTextField.onKeyPressed = (keyEvent) => { |
||||
|
// if (keyEvent.getCode() == KeyCode.ENTER) submitButton.fire() |
||||
|
// } |
||||
|
|
||||
|
Array(usernameTextField, passwordTextField, submitButton) |
||||
|
.foreach(_.onKeyPressed = (keyEvent) => { |
||||
|
if (keyEvent.getCode() == KeyCode.ENTER) submitButton.fire() |
||||
|
}) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
override def didGainVisibility(): Unit = { |
||||
|
usernameTextField.requestFocus() |
||||
|
} |
||||
|
|
||||
|
def actionLogin(e: ActionEvent) = { |
||||
|
import org.scalafx.extras._ |
||||
|
val inputUserName = usernameTextField.text() |
||||
|
val inputPassword = passwordTextField.text() |
||||
|
|
||||
|
// val authenticated = |
||||
|
// inputPassword.equals("password") && inputUserName.equals("hmm") |
||||
|
login(inputUserName, inputPassword) onComplete { |
||||
|
case Success(value) => { |
||||
|
value.foreach(println) |
||||
|
value match { |
||||
|
case Some(token) => { |
||||
|
appData = |
||||
|
appData.copy(user = User(inputUserName, inputPassword, token)) |
||||
|
} |
||||
|
case None => { |
||||
|
onFX(errorLabel.text = |
||||
|
"Error logging in - please check your password" |
||||
|
) |
||||
|
logger.warn("Login unsuccessful wrong password") |
||||
|
} |
||||
|
} |
||||
|
// Platform.runLater(() => applicationController.showChatPane()) |
||||
|
onFX(applicationController.showChatPane()) |
||||
|
} |
||||
|
case Failure(exception) => { |
||||
|
logger.error(s"${exception.getMessage()}") |
||||
|
logger.warn("Login unsuccessful network problem") |
||||
|
onFX { |
||||
|
errorLabel.text = "Error logging in - Please check your network" |
||||
|
applicationController.showChatPane() |
||||
|
} |
||||
|
// onFX(applicationController.showChatPane()) |
||||
|
} |
||||
|
} |
||||
|
// if (authenticated) { |
||||
|
// passwordTextField.clear() |
||||
|
// val res = Result(username = inputUserName, password = inputPassword) |
||||
|
// println(res) |
||||
|
// // loginManager. |
||||
|
|
||||
|
// applicationController.showChatPane() |
||||
|
// } else { |
||||
|
// logger.error("Login Error") |
||||
|
// } |
||||
|
} |
||||
|
|
||||
|
def login(username: String, password: String) = async { |
||||
|
val resp = await(initLogin(username, password)) |
||||
|
resp.header("X-AUTH-TOKEN") |
||||
|
} |
||||
|
|
||||
|
def initLogin(username: String, password: String) = { |
||||
|
basicRequest.auth |
||||
|
.basic(username, password) |
||||
|
.get(uri"http://localhost:8080/api/chat/get/token") |
||||
|
.send() |
||||
|
} |
||||
|
|
||||
|
final case class Result(username: String, password: String) |
||||
|
|
||||
|
final case class Person( |
||||
|
id: String, |
||||
|
usernameTextField: String, |
||||
|
passwordTextField: String |
||||
|
) |
||||
|
|
||||
|
} |
@ -0,0 +1,54 @@ |
|||||
|
package wow.doge.chatto.controller |
||||
|
|
||||
|
import javafx.fxml.FXML |
||||
|
import javafx.scene.control.MenuBar |
||||
|
import javafx.scene.layout.Pane |
||||
|
import javax.enterprise.event.Observes |
||||
|
|
||||
|
import com.sfxcode.sapphire.core.controller.ViewController |
||||
|
import com.sfxcode.sapphire.core.scene.{ContentDidChangeEvent, ContentManager} |
||||
|
import com.typesafe.scalalogging.LazyLogging |
||||
|
import wow.doge.chatto.messagebuble.BubbledMDFXNode |
||||
|
import scalafx.scene.layout.GridPane |
||||
|
import scalafx.Includes._ |
||||
|
// import wow.doge.chatto. |
||||
|
|
||||
|
class MainViewController extends ViewController with LazyLogging { |
||||
|
|
||||
|
@FXML var menuBar: MenuBar = _ |
||||
|
// @FXML |
||||
|
// var workspacePane: Pane = _ |
||||
|
// @FXML |
||||
|
// var statusPane: Pane = _ |
||||
|
// @FXML |
||||
|
// var navigationPane: Pane = _ |
||||
|
|
||||
|
@FXML var loginPane: Pane = _ |
||||
|
|
||||
|
@FXML var chatPane: Pane = _ |
||||
|
|
||||
|
lazy val workspaceController = getController[WorkspaceController]() |
||||
|
lazy val navigationController = getController[NavigationController]() |
||||
|
lazy val statusBarController = getBean[StatusBarController]() |
||||
|
lazy val loginController = getController[LoginController]() |
||||
|
lazy val chatController = getController[ChatController]() |
||||
|
|
||||
|
// val bubbleNode = new BubbledMDFXNode("Wow") |
||||
|
|
||||
|
var workspaceManager: ContentManager = _ |
||||
|
var navigationManager: ContentManager = _ |
||||
|
var statusBarManager: ContentManager = _ |
||||
|
var mainManager: ContentManager = _ |
||||
|
|
||||
|
override def didGainVisibilityFirstTime() { |
||||
|
// menuBar.setUseSystemMenuBar(true) |
||||
|
menuBar.setVisible(false) |
||||
|
|
||||
|
// navigationManager = |
||||
|
// ContentManager(navigationPane, this, navigationController) |
||||
|
// statusBarManager = ContentManager(statusPane, this, statusBarController) |
||||
|
// workspaceManager = ContentManager(workspacePane, this, workspaceController) |
||||
|
mainManager = ContentManager(loginPane, this, loginController) |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,18 @@ |
|||||
|
package wow.doge.chatto.controller |
||||
|
|
||||
|
import javafx.event.ActionEvent |
||||
|
import javafx.scene.control.Button |
||||
|
|
||||
|
class NavigationController extends AbstractViewController { |
||||
|
|
||||
|
def actionClickButton(event: ActionEvent) { |
||||
|
logger.debug(event.toString) |
||||
|
statusBarController.updateLabel(event.getSource.asInstanceOf[Button]) |
||||
|
} |
||||
|
|
||||
|
def actionHotReload(event: ActionEvent) { |
||||
|
applicationController.replacePrimarySceneContent() |
||||
|
logger.debug("Hot Reload Succeeded") |
||||
|
statusBarController.updateLabel(event.getSource.asInstanceOf[Button]) |
||||
|
} |
||||
|
} |
@ -0,0 +1,46 @@ |
|||||
|
package wow.doge.chatto.controller |
||||
|
|
||||
|
import com.typesafe.scalalogging.LazyLogging |
||||
|
import javafx.geometry.Insets |
||||
|
import javafx.scene.control.{Button, Label} |
||||
|
import javafx.scene.layout.HBox |
||||
|
import javax.enterprise.context.ApplicationScoped |
||||
|
import javax.inject.Named |
||||
|
|
||||
|
@Named |
||||
|
@ApplicationScoped |
||||
|
class StatusBarController extends AbstractViewController with LazyLogging { |
||||
|
|
||||
|
rootPane = new HBox() |
||||
|
|
||||
|
val actionLabel: Label = new Label("Status Bar Action Label ...") |
||||
|
actionLabel.setPadding(new Insets(5)) |
||||
|
|
||||
|
val statusLabel: Label = new Label("Status Bar Status Label ...") |
||||
|
statusLabel.setPadding(new Insets(5)) |
||||
|
|
||||
|
val statusButton = new Button("Status Button 1") |
||||
|
statusButton.setOnAction(_ => { |
||||
|
logger.debug("%s".format(statusButton.getText)) |
||||
|
updateLabel(statusButton) |
||||
|
}) |
||||
|
|
||||
|
val statusButton2 = new Button("Status Button 2") |
||||
|
statusButton2.setOnAction(_ => { |
||||
|
logger.debug("%s".format(statusButton2.getText)) |
||||
|
updateLabel(statusButton2) |
||||
|
}) |
||||
|
|
||||
|
val box = new HBox() |
||||
|
box.setId("statusBar") |
||||
|
box.setPadding(new Insets(10)) |
||||
|
box.setSpacing(10.0) |
||||
|
|
||||
|
box.getChildren.addAll(statusButton, statusButton2, statusLabel, actionLabel) |
||||
|
|
||||
|
rootPane = box |
||||
|
|
||||
|
def updateLabel(button: Button): Unit = { |
||||
|
actionLabel.setText("%s clicked".format(button.getText)) |
||||
|
} |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
package wow.doge.chatto.controller |
||||
|
|
||||
|
import javafx.fxml.FXML |
||||
|
import javafx.scene.control.Label |
||||
|
import javax.inject.Inject |
||||
|
|
||||
|
import wow.doge.chatto.ApplicationName |
||||
|
|
||||
|
class WorkspaceController @Inject() (applicationName: ApplicationName) |
||||
|
extends AbstractViewController { |
||||
|
|
||||
|
// @Inject |
||||
|
// var applicationName: ApplicationName = _ |
||||
|
|
||||
|
@FXML |
||||
|
var infoLabel: Label = _ |
||||
|
|
||||
|
override def didGainVisibilityFirstTime() { |
||||
|
infoLabel.setText(applicationName.name) |
||||
|
} |
||||
|
} |
@ -0,0 +1,81 @@ |
|||||
|
package wow.doge.chatto.messagebuble; |
||||
|
|
||||
|
import javafx.scene.shape.HLineTo; |
||||
|
import javafx.scene.shape.LineTo; |
||||
|
import javafx.scene.shape.MoveTo; |
||||
|
import javafx.scene.shape.Path; |
||||
|
import javafx.scene.shape.VLineTo; |
||||
|
|
||||
|
public class Bubble extends Path { |
||||
|
|
||||
|
/* |
||||
|
* Copyright {2015} {Terah Laweh} |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not |
||||
|
* use this file except in compliance with the License. You may obtain a copy of |
||||
|
* the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
||||
|
* License for the specific language governing permissions and limitations under |
||||
|
* the License. |
||||
|
*/ |
||||
|
|
||||
|
public Bubble(BubbleSpec bubbleSpec) { |
||||
|
super(); |
||||
|
switch (bubbleSpec) { |
||||
|
case FACE_BOTTOM: |
||||
|
break; |
||||
|
case FACE_LEFT_BOTTOM: |
||||
|
drawRectBubbleLeftBaselineIndicator(); |
||||
|
break; |
||||
|
case FACE_LEFT_CENTER: |
||||
|
drawRectBubbleLeftCenterIndicator(); |
||||
|
break; |
||||
|
case FACE_RIGHT_BOTTOM: |
||||
|
drawRectBubbleRightBaselineIndicator(); |
||||
|
break; |
||||
|
case FACE_RIGHT_CENTER: |
||||
|
drawRectBubbleRightCenterIndicator(); |
||||
|
break; |
||||
|
case FACE_TOP: |
||||
|
drawRectBubbleToplineIndicator(); |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
private void drawRectBubbleToplineIndicator() { |
||||
|
getElements().addAll(new MoveTo(1.0f, 1.2f), new HLineTo(2.5f), new LineTo(2.7f, 1.0f), new LineTo(2.9f, 1.2f), |
||||
|
new HLineTo(4.4f), new VLineTo(4f), new HLineTo(1.0f), new VLineTo(1.2f)); |
||||
|
} |
||||
|
|
||||
|
private void drawRectBubbleRightBaselineIndicator() { |
||||
|
getElements().addAll(new MoveTo(3.0f, 1.0f), new HLineTo(0f), new VLineTo(4f), new HLineTo(3.0f), |
||||
|
new LineTo(2.8f, 3.8f), new VLineTo(1f)); |
||||
|
} |
||||
|
|
||||
|
private void drawRectBubbleLeftBaselineIndicator() { |
||||
|
getElements().addAll(new MoveTo(1.2f, 1.0f), new HLineTo(3f), new VLineTo(4f), new HLineTo(1.0f), |
||||
|
new LineTo(1.2f, 3.8f), new VLineTo(1f)); |
||||
|
} |
||||
|
|
||||
|
private void drawRectBubbleRightCenterIndicator() { |
||||
|
getElements().addAll(new MoveTo(3.0f, 2.5f), new LineTo(2.8f, 2.4f), new VLineTo(1f), new HLineTo(0f), |
||||
|
new VLineTo(4f), new HLineTo(2.8f), new VLineTo(2.7f), new LineTo(3.0f, 2.5f)); |
||||
|
} |
||||
|
|
||||
|
protected double drawRectBubbleIndicatorRule = 0.2; |
||||
|
|
||||
|
private void drawRectBubbleLeftCenterIndicator() { |
||||
|
getElements().addAll(new MoveTo(1.0f, 2.5f), new LineTo(1.2f, 2.4f), new VLineTo(1f), new HLineTo(2.9f), |
||||
|
new VLineTo(4f), new HLineTo(1.2f), new VLineTo(2.7f), new LineTo(1.0f, 2.5f)); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
package wow.doge.chatto.messagebuble; |
||||
|
|
||||
|
public enum BubbleSpec { |
||||
|
|
||||
|
/* |
||||
|
* Copyright {2015} {Terah Laweh} |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not |
||||
|
* use this file except in compliance with the License. You may obtain a copy of |
||||
|
* the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
||||
|
* License for the specific language governing permissions and limitations under |
||||
|
* the License. |
||||
|
*/ |
||||
|
|
||||
|
FACE_TOP, FACE_BOTTOM, FACE_LEFT_BOTTOM, FACE_LEFT_CENTER, FACE_RIGHT_BOTTOM, FACE_RIGHT_CENTER; |
||||
|
|
||||
|
} |
@ -0,0 +1,178 @@ |
|||||
|
package wow.doge.chatto.messagebuble; |
||||
|
|
||||
|
import javafx.beans.InvalidationListener; |
||||
|
import javafx.beans.Observable; |
||||
|
import javafx.beans.value.ChangeListener; |
||||
|
import javafx.beans.value.ObservableValue; |
||||
|
import javafx.geometry.Insets; |
||||
|
import javafx.scene.Node; |
||||
|
import javafx.scene.control.Label; |
||||
|
import javafx.scene.effect.DropShadow; |
||||
|
import javafx.scene.paint.Color; |
||||
|
import javafx.scene.shape.Shape; |
||||
|
|
||||
|
public class BubbledLabel extends Label { |
||||
|
|
||||
|
/* |
||||
|
* Copyright {2015} {Terah Laweh} |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not |
||||
|
* use this file except in compliance with the License. You may obtain a copy of |
||||
|
* the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
||||
|
* License for the specific language governing permissions and limitations under |
||||
|
* the License. |
||||
|
*/ |
||||
|
|
||||
|
private BubbleSpec bs = BubbleSpec.FACE_LEFT_CENTER; |
||||
|
private double pading = 5.0; |
||||
|
private boolean systemCall = false; |
||||
|
|
||||
|
public BubbledLabel() { |
||||
|
super(); |
||||
|
init(); |
||||
|
} |
||||
|
|
||||
|
public BubbledLabel(String arg0, Node arg1) { |
||||
|
super(arg0, arg1); |
||||
|
init(); |
||||
|
} |
||||
|
|
||||
|
public BubbledLabel(String arg0) { |
||||
|
super(arg0); |
||||
|
init(); |
||||
|
} |
||||
|
|
||||
|
public BubbledLabel(BubbleSpec bubbleSpec) { |
||||
|
super(); |
||||
|
this.bs = bubbleSpec; |
||||
|
init(); |
||||
|
} |
||||
|
|
||||
|
public BubbledLabel(String arg0, Node arg1, BubbleSpec bubbleSpec) { |
||||
|
super(arg0, arg1); |
||||
|
this.bs = bubbleSpec; |
||||
|
init(); |
||||
|
} |
||||
|
|
||||
|
public BubbledLabel(String arg0, BubbleSpec bubbleSpec) { |
||||
|
super(arg0); |
||||
|
this.bs = bubbleSpec; |
||||
|
init(); |
||||
|
} |
||||
|
|
||||
|
private void init() { |
||||
|
DropShadow ds = new DropShadow(); |
||||
|
ds.setOffsetX(1.3); |
||||
|
ds.setOffsetY(1.3); |
||||
|
ds.setColor(Color.DARKGRAY); |
||||
|
setPrefSize(Label.USE_COMPUTED_SIZE, Label.USE_COMPUTED_SIZE); |
||||
|
shapeProperty().addListener(new ChangeListener<Shape>() { |
||||
|
@Override |
||||
|
public void changed(ObservableValue<? extends Shape> arg0, Shape arg1, Shape arg2) { |
||||
|
if (systemCall) { |
||||
|
systemCall = false; |
||||
|
} else { |
||||
|
shapeIt(); |
||||
|
} |
||||
|
/* |
||||
|
* if(arg2.getClass().isAssignableFrom(Bubble.class)){ // i do no need to check |
||||
|
* for this actuall is waste of time systemCall = false; return; }else{ // not |
||||
|
* the required shape systemCall = true; setShape(new Bubble(bs)); System.gc(); |
||||
|
* } |
||||
|
*/ |
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
heightProperty().addListener(new InvalidationListener() { |
||||
|
|
||||
|
@Override |
||||
|
public void invalidated(Observable arg0) { |
||||
|
if (!systemCall) |
||||
|
setPrefHeight(Label.USE_COMPUTED_SIZE); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
widthProperty().addListener(new InvalidationListener() { |
||||
|
|
||||
|
@Override |
||||
|
public void invalidated(Observable observable) { |
||||
|
if (!systemCall) |
||||
|
setPrefHeight(Label.USE_COMPUTED_SIZE); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
shapeIt(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void updateBounds() { |
||||
|
super.updateBounds(); |
||||
|
// top right bottom left |
||||
|
switch (bs) { |
||||
|
case FACE_LEFT_BOTTOM: |
||||
|
setPadding(new Insets(pading, pading, |
||||
|
(this.getBoundsInLocal().getWidth() * ((Bubble) getShape()).drawRectBubbleIndicatorRule) / 2 |
||||
|
+ pading, |
||||
|
pading)); |
||||
|
break; |
||||
|
case FACE_LEFT_CENTER: |
||||
|
setPadding(new Insets(pading, pading, pading, |
||||
|
(this.getBoundsInLocal().getWidth() * ((Bubble) getShape()).drawRectBubbleIndicatorRule) / 2 |
||||
|
+ pading)); |
||||
|
break; |
||||
|
case FACE_RIGHT_BOTTOM: |
||||
|
setPadding(new Insets(pading, |
||||
|
(this.getBoundsInLocal().getWidth() * ((Bubble) getShape()).drawRectBubbleIndicatorRule) / 2 |
||||
|
+ pading, |
||||
|
pading, pading)); |
||||
|
break; |
||||
|
case FACE_RIGHT_CENTER: |
||||
|
setPadding(new Insets(pading, |
||||
|
(this.getBoundsInLocal().getWidth() * ((Bubble) getShape()).drawRectBubbleIndicatorRule) / 2 |
||||
|
+ pading, |
||||
|
pading, pading)); |
||||
|
break; |
||||
|
case FACE_TOP: |
||||
|
setPadding(new Insets( |
||||
|
(this.getBoundsInLocal().getWidth() * ((Bubble) getShape()).drawRectBubbleIndicatorRule) / 2 |
||||
|
+ pading, |
||||
|
pading, pading, pading)); |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public final double getPading() { |
||||
|
return pading; |
||||
|
} |
||||
|
|
||||
|
public void setPading(double pading) { |
||||
|
if (pading > 25.0) |
||||
|
return; |
||||
|
this.pading = pading; |
||||
|
} |
||||
|
|
||||
|
public BubbleSpec getBubbleSpec() { |
||||
|
return bs; |
||||
|
} |
||||
|
|
||||
|
public void setBubbleSpec(BubbleSpec bubbleSpec) { |
||||
|
this.bs = bubbleSpec; |
||||
|
shapeIt(); |
||||
|
} |
||||
|
|
||||
|
private final void shapeIt() { |
||||
|
systemCall = true; |
||||
|
setShape(new Bubble(bs)); |
||||
|
System.gc(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,135 @@ |
|||||
|
package wow.doge.chatto.messagebuble; |
||||
|
|
||||
|
import com.sandec.mdfx.MDFXNode; |
||||
|
|
||||
|
import javafx.beans.InvalidationListener; |
||||
|
import javafx.beans.Observable; |
||||
|
import javafx.beans.value.ChangeListener; |
||||
|
import javafx.beans.value.ObservableValue; |
||||
|
import javafx.geometry.Insets; |
||||
|
import javafx.scene.Node; |
||||
|
import javafx.scene.control.Label; |
||||
|
import javafx.scene.effect.DropShadow; |
||||
|
import javafx.scene.paint.Color; |
||||
|
import javafx.scene.shape.Shape; |
||||
|
|
||||
|
public class BubbledMDFXNode extends MDFXNode { |
||||
|
public BubbledMDFXNode(String s) { |
||||
|
super(s); |
||||
|
init(); |
||||
|
} |
||||
|
|
||||
|
private BubbleSpec bs = BubbleSpec.FACE_LEFT_CENTER; |
||||
|
private double pading = 5.0; |
||||
|
private boolean systemCall = false; |
||||
|
|
||||
|
private void init() { |
||||
|
DropShadow ds = new DropShadow(); |
||||
|
ds.setOffsetX(1.3); |
||||
|
ds.setOffsetY(1.3); |
||||
|
ds.setColor(Color.DARKGRAY); |
||||
|
setPrefSize(Label.USE_COMPUTED_SIZE, Label.USE_COMPUTED_SIZE); |
||||
|
shapeProperty().addListener(new ChangeListener<Shape>() { |
||||
|
@Override |
||||
|
public void changed(ObservableValue<? extends Shape> arg0, Shape arg1, Shape arg2) { |
||||
|
if (systemCall) { |
||||
|
systemCall = false; |
||||
|
} else { |
||||
|
shapeIt(); |
||||
|
} |
||||
|
/* |
||||
|
* if(arg2.getClass().isAssignableFrom(Bubble.class)){ // i do no need to check |
||||
|
* for this actuall is waste of time systemCall = false; return; }else{ // not |
||||
|
* the required shape systemCall = true; setShape(new Bubble(bs)); System.gc(); |
||||
|
* } |
||||
|
*/ |
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
heightProperty().addListener(new InvalidationListener() { |
||||
|
|
||||
|
@Override |
||||
|
public void invalidated(Observable arg0) { |
||||
|
if (!systemCall) |
||||
|
setPrefHeight(Label.USE_COMPUTED_SIZE); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
widthProperty().addListener(new InvalidationListener() { |
||||
|
|
||||
|
@Override |
||||
|
public void invalidated(Observable observable) { |
||||
|
if (!systemCall) |
||||
|
setPrefHeight(Label.USE_COMPUTED_SIZE); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
shapeIt(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void updateBounds() { |
||||
|
super.updateBounds(); |
||||
|
// top right bottom left |
||||
|
switch (bs) { |
||||
|
case FACE_LEFT_BOTTOM: |
||||
|
setPadding(new Insets(pading, pading, |
||||
|
(this.getBoundsInLocal().getWidth() * ((Bubble) getShape()).drawRectBubbleIndicatorRule) / 2 |
||||
|
+ pading, |
||||
|
pading)); |
||||
|
break; |
||||
|
case FACE_LEFT_CENTER: |
||||
|
setPadding(new Insets(pading, pading, pading, |
||||
|
(this.getBoundsInLocal().getWidth() * ((Bubble) getShape()).drawRectBubbleIndicatorRule) / 2 |
||||
|
+ pading)); |
||||
|
break; |
||||
|
case FACE_RIGHT_BOTTOM: |
||||
|
setPadding(new Insets(pading, |
||||
|
(this.getBoundsInLocal().getWidth() * ((Bubble) getShape()).drawRectBubbleIndicatorRule) / 2 |
||||
|
+ pading, |
||||
|
pading, pading)); |
||||
|
break; |
||||
|
case FACE_RIGHT_CENTER: |
||||
|
setPadding(new Insets(pading, |
||||
|
(this.getBoundsInLocal().getWidth() * ((Bubble) getShape()).drawRectBubbleIndicatorRule) / 2 |
||||
|
+ pading, |
||||
|
pading, pading)); |
||||
|
break; |
||||
|
case FACE_TOP: |
||||
|
setPadding(new Insets( |
||||
|
(this.getBoundsInLocal().getWidth() * ((Bubble) getShape()).drawRectBubbleIndicatorRule) / 2 |
||||
|
+ pading, |
||||
|
pading, pading, pading)); |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public final double getPading() { |
||||
|
return pading; |
||||
|
} |
||||
|
|
||||
|
public void setPading(double pading) { |
||||
|
if (pading > 25.0) |
||||
|
return; |
||||
|
this.pading = pading; |
||||
|
} |
||||
|
|
||||
|
public BubbleSpec getBubbleSpec() { |
||||
|
return bs; |
||||
|
} |
||||
|
|
||||
|
public void setBubbleSpec(BubbleSpec bubbleSpec) { |
||||
|
this.bs = bubbleSpec; |
||||
|
shapeIt(); |
||||
|
} |
||||
|
|
||||
|
private final void shapeIt() { |
||||
|
systemCall = true; |
||||
|
setShape(new Bubble(bs)); |
||||
|
System.gc(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,10 @@ |
|||||
|
package wow.doge.chatto.model |
||||
|
|
||||
|
import java.time.Instant |
||||
|
|
||||
|
case class ChatUser( |
||||
|
userId: Long, |
||||
|
userName: String, |
||||
|
password: String, |
||||
|
joinDate: Instant |
||||
|
) |
@ -0,0 +1,46 @@ |
|||||
|
package wow.doge.chatto.service |
||||
|
|
||||
|
import scala.concurrent.ExecutionContext |
||||
|
import scala.concurrent.ExecutionContext.Implicits.global |
||||
|
import scala.async.Async.{async, await} |
||||
|
import sttp.client.json4s._ |
||||
|
import org.json4s._ |
||||
|
import sttp.client._ |
||||
|
import scala.concurrent.Future |
||||
|
import sttp.client.asynchttpclient.WebSocketHandler |
||||
|
import javax.inject.Inject |
||||
|
import scala.async.Async.{async, await} |
||||
|
import scala.util.Success |
||||
|
import scala.util.Failure |
||||
|
import wow.doge.chatto.AppData |
||||
|
import wow.doge.chatto.types.AppTypes.HttpBackend |
||||
|
|
||||
|
class UserService @Inject() (appData: AppData)( |
||||
|
implicit backend: HttpBackend |
||||
|
) { |
||||
|
private implicit lazy val serialization = org.json4s.native.Serialization |
||||
|
|
||||
|
def func1() = { |
||||
|
val willBeResponse = basicRequest |
||||
|
.get(uri"https://httpbin.org/get") |
||||
|
.response(asJson[HttpBinResponse]) |
||||
|
.send() |
||||
|
async { |
||||
|
val r = await { willBeResponse } |
||||
|
r.body.map(println) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
def func2() = |
||||
|
basicRequest |
||||
|
.get(uri"https://httpbin.org/get") |
||||
|
.response(asJson[HttpBinResponse]) |
||||
|
.send() |
||||
|
|
||||
|
} |
||||
|
|
||||
|
case class HttpBinResponse( |
||||
|
url: String, |
||||
|
origin: String, |
||||
|
headers: Map[String, String] |
||||
|
) |
@ -0,0 +1,14 @@ |
|||||
|
package wow.doge.chatto.types |
||||
|
|
||||
|
import sttp.client.SttpBackend |
||||
|
import scala.concurrent.Future |
||||
|
import sttp.client.asynchttpclient.WebSocketHandler |
||||
|
|
||||
|
trait AppTypes { |
||||
|
// import AppTypes._ |
||||
|
type HttpBackend = SttpBackend[Future, Nothing, WebSocketHandler] |
||||
|
} |
||||
|
|
||||
|
object AppTypes extends AppTypes { |
||||
|
// type HttpBackend = SttpBackend[Future, Nothing, WebSocketHandler] |
||||
|
} |
@ -0,0 +1,2 @@ |
|||||
|
version in ThisBuild := "0.1.0-SNAPSHOT" |
||||
|
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue