first commit
This commit is contained in:
parent
13125c415e
commit
601fad6433
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.idea*
|
||||||
|
*.iml
|
||||||
|
project/target
|
||||||
|
target
|
||||||
|
lib
|
||||||
|
out
|
||||||
|
.DS_Store
|
||||||
|
.gitconfig
|
||||||
|
.vscode
|
||||||
|
.bloop
|
||||||
|
.metals
|
1
.scalafmt.conf
Normal file
1
.scalafmt.conf
Normal file
@ -0,0 +1 @@
|
|||||||
|
version = "2.4.2"
|
7
CHANGES.md
Normal file
7
CHANGES.md
Normal file
@ -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)
|
||||||
|
84
build.sbt
Normal file
84
build.sbt
Normal file
@ -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
|
1
project/build.properties
Normal file
1
project/build.properties
Normal file
@ -0,0 +1 @@
|
|||||||
|
sbt.version=1.3.8
|
4
project/metals.sbt
Normal file
4
project/metals.sbt
Normal file
@ -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")
|
6
project/plugin.sbt
Normal file
6
project/plugin.sbt
Normal file
@ -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
src/main/resources/META-INF/beans.xml
Normal file
0
src/main/resources/META-INF/beans.xml
Normal file
8
src/main/resources/application.conf
Normal file
8
src/main/resources/application.conf
Normal file
@ -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
|
||||||
|
}
|
1
src/main/resources/bundles/application.properties
Normal file
1
src/main/resources/bundles/application.properties
Normal file
@ -0,0 +1 @@
|
|||||||
|
navigation.toggle=Toggle Workspace
|
1
src/main/resources/bundles/application_de.properties
Normal file
1
src/main/resources/bundles/application_de.properties
Normal file
@ -0,0 +1 @@
|
|||||||
|
navigation.toggle=Bereich wechseln
|
67
src/main/resources/fxml/Chat.fxml
Normal file
67
src/main/resources/fxml/Chat.fxml
Normal file
@ -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>
|
76
src/main/resources/fxml/Login.fxml
Normal file
76
src/main/resources/fxml/Login.fxml
Normal file
@ -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>
|
71
src/main/resources/fxml/MainView.fxml
Normal file
71
src/main/resources/fxml/MainView.fxml
Normal file
@ -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>
|
20
src/main/resources/fxml/Navigation.fxml
Normal file
20
src/main/resources/fxml/Navigation.fxml
Normal file
@ -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>
|
20
src/main/resources/fxml/UserBox.fxml
Normal file
20
src/main/resources/fxml/UserBox.fxml
Normal file
@ -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>
|
17
src/main/resources/fxml/Workspace.fxml
Normal file
17
src/main/resources/fxml/Workspace.fxml
Normal file
@ -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>
|
29
src/main/resources/fxml/default.css
Normal file
29
src/main/resources/fxml/default.css
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
src/main/resources/images/backgroung.jpg
Normal file
BIN
src/main/resources/images/backgroung.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 50 KiB |
14
src/main/resources/logback.xml
Normal file
14
src/main/resources/logback.xml
Normal file
@ -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
vendored
Normal file
1513
src/main/resources/styles/bootstrapfx.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
18
src/main/resources/styles/markdown.css
Normal file
18
src/main/resources/styles/markdown.css
Normal 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;
|
||||||
|
}
|
16
src/main/resources/styles/style2.css
Normal file
16
src/main/resources/styles/style2.css
Normal file
@ -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;
|
||||||
|
}
|
57
src/main/resources/styles/ui.css
Normal file
57
src/main/resources/styles/ui.css
Normal file
@ -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;
|
||||||
|
}*/
|
30
src/main/resources/styles/userbox.css
Normal file
30
src/main/resources/styles/userbox.css
Normal file
@ -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 ;
|
||||||
|
}
|
9
src/main/scala/wow/doge/chatto/Application.scala
Normal file
9
src/main/scala/wow/doge/chatto/Application.scala
Normal file
@ -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")
|
||||||
|
}
|
102
src/main/scala/wow/doge/chatto/ApplicationController.scala
Normal file
102
src/main/scala/wow/doge/chatto/ApplicationController.scala
Normal file
@ -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)
|
10
src/main/scala/wow/doge/chatto/config/Beans.scala
Normal file
10
src/main/scala/wow/doge/chatto/config/Beans.scala
Normal file
@ -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"
|
||||||
|
}
|
52
src/main/scala/wow/doge/chatto/control/UserBox.scala
Normal file
52
src/main/scala/wow/doge/chatto/control/UserBox.scala
Normal file
@ -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)
|
160
src/main/scala/wow/doge/chatto/controller/LoginController.scala
Normal file
160
src/main/scala/wow/doge/chatto/controller/LoginController.scala
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
81
src/main/scala/wow/doge/chatto/messagebubble/Bubble.java
Normal file
81
src/main/scala/wow/doge/chatto/messagebubble/Bubble.java
Normal file
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
src/main/scala/wow/doge/chatto/messagebubble/BubbleSpec.java
Normal file
23
src/main/scala/wow/doge/chatto/messagebubble/BubbleSpec.java
Normal file
@ -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;
|
||||||
|
|
||||||
|
}
|
178
src/main/scala/wow/doge/chatto/messagebubble/BubbledLabel.java
Normal file
178
src/main/scala/wow/doge/chatto/messagebubble/BubbledLabel.java
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
10
src/main/scala/wow/doge/chatto/model/ChatUser.scala
Normal file
10
src/main/scala/wow/doge/chatto/model/ChatUser.scala
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package wow.doge.chatto.model
|
||||||
|
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
case class ChatUser(
|
||||||
|
userId: Long,
|
||||||
|
userName: String,
|
||||||
|
password: String,
|
||||||
|
joinDate: Instant
|
||||||
|
)
|
46
src/main/scala/wow/doge/chatto/service/UserService.scala
Normal file
46
src/main/scala/wow/doge/chatto/service/UserService.scala
Normal file
@ -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]
|
||||||
|
)
|
14
src/main/scala/wow/doge/chatto/types/Types.scala
Normal file
14
src/main/scala/wow/doge/chatto/types/Types.scala
Normal file
@ -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]
|
||||||
|
}
|
2
version.sbt
Normal file
2
version.sbt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
version in ThisBuild := "0.1.0-SNAPSHOT"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user