Rohan Sircar
4 years ago
19 changed files with 748 additions and 381 deletions
-
12build.sbt
-
61src/main/resources/fxml/Chat.fxml
-
13src/main/resources/fxml/Login.fxml
-
54src/main/resources/fxml/MainView.fxml
-
29src/main/resources/fxml/default.css
-
173src/main/resources/styles/chat.css
-
85src/main/resources/styles/default.css
-
5src/main/resources/styles/login.css
-
57src/main/scala/wow/doge/chatto/ApplicationController.scala
-
114src/main/scala/wow/doge/chatto/control/JFXSmoothScroll.java
-
10src/main/scala/wow/doge/chatto/control/MessageBox.scala
-
5src/main/scala/wow/doge/chatto/control/UserBox2.scala
-
388src/main/scala/wow/doge/chatto/controller/ChatController.scala
-
15src/main/scala/wow/doge/chatto/controller/LoginController.scala
-
19src/main/scala/wow/doge/chatto/controller/MainViewController.scala
-
4src/main/scala/wow/doge/chatto/controller/NavigationController.scala
-
2src/main/scala/wow/doge/chatto/controller/WorkspaceController.scala
-
69src/main/scala/wow/doge/chatto/service/CustomSerializer.scala
-
14src/main/scala/wow/doge/chatto/service/UserService.scala
@ -1,29 +0,0 @@ |
|||
.navigation { |
|||
-fx-background-color: derive(cadetblue, 60%); |
|||
-fx-font-size: 14px; |
|||
} |
|||
|
|||
.status { |
|||
-fx-background-color: derive(lightgray, 30%); |
|||
-fx-font-size: 12px; |
|||
} |
|||
|
|||
.workspace2 { |
|||
-fx-background-color: azure; |
|||
-fx-font-size: 16px; |
|||
} |
|||
|
|||
.workspace { |
|||
-fx-background-color: beige; |
|||
-fx-font-size: 13px; |
|||
} |
|||
|
|||
.personPane { |
|||
-fx-font-size: 11px; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,173 @@ |
|||
/* .ikonli-font-icon { |
|||
-fx-icon-size: 100px; |
|||
-fx-icon-color: blue; |
|||
} */ |
|||
|
|||
.ikonli-font-icon:hover { |
|||
-fx-icon-color: #1976a8; |
|||
} |
|||
|
|||
#chatMainPane { |
|||
-fx-padding: 5px; |
|||
} |
|||
|
|||
.my-list-view .scroll-bar:horizontal .track, |
|||
.my-list-view .scroll-bar:vertical .track { |
|||
-fx-background-color: transparent; |
|||
-fx-border-color: transparent; |
|||
-fx-background-radius: 0em; |
|||
-fx-border-radius: 2em; |
|||
} |
|||
|
|||
.my-list-view .scroll-bar:horizontal .increment-button, |
|||
.my-list-view .scroll-bar:horizontal .decrement-button { |
|||
-fx-background-color: transparent; |
|||
-fx-background-radius: 0em; |
|||
-fx-padding: 0 0 10 0; |
|||
} |
|||
|
|||
.my-list-view .scroll-bar:vertical .increment-button, |
|||
.my-list-view .scroll-bar:vertical .decrement-button { |
|||
-fx-background-color: transparent; |
|||
-fx-background-radius: 0em; |
|||
-fx-padding: 0 10 0 0; |
|||
} |
|||
.my-list-view .scroll-bar .increment-arrow, |
|||
.my-list-view .scroll-bar .decrement-arrow { |
|||
-fx-shape: " "; |
|||
-fx-padding: 0; |
|||
} |
|||
|
|||
.my-list-view .scroll-bar:horizontal .thumb, |
|||
.my-list-view .scroll-bar:vertical .thumb { |
|||
-fx-background-color: derive(black, 90%); |
|||
-fx-background-insets: 2, 0, 0; |
|||
-fx-background-radius: 2em; |
|||
} |
|||
|
|||
.scroll-pane .scroll-bar:horizontal .track, |
|||
.scroll-pane .scroll-bar:vertical .track { |
|||
-fx-background-color: transparent; |
|||
-fx-border-color: transparent; |
|||
-fx-background-radius: 0em; |
|||
-fx-border-radius: 2em; |
|||
} |
|||
|
|||
.scroll-pane .scroll-bar:horizontal .increment-button, |
|||
.scroll-pane .scroll-bar:horizontal .decrement-button { |
|||
-fx-background-color: transparent; |
|||
-fx-background-radius: 0em; |
|||
-fx-padding: 0 0 10 0; |
|||
} |
|||
|
|||
.scroll-pane .scroll-bar:vertical .increment-button, |
|||
.scroll-pane .scroll-bar:vertical .decrement-button { |
|||
-fx-background-color: transparent; |
|||
-fx-background-radius: 0em; |
|||
-fx-padding: 0 10 0 0; |
|||
} |
|||
.scroll-pane .scroll-bar .increment-arrow, |
|||
.scroll-pane .scroll-bar .decrement-arrow { |
|||
-fx-shape: " "; |
|||
-fx-padding: 0; |
|||
} |
|||
|
|||
.scroll-pane .scroll-bar:horizontal .thumb, |
|||
.scroll-pane .scroll-bar:vertical .thumb { |
|||
-fx-background-color: derive(black, 90%); |
|||
-fx-background-insets: 2, 0, 0; |
|||
-fx-background-radius: 2em; |
|||
} |
|||
|
|||
.scroll-pane { |
|||
-fx-background-color: transparent; |
|||
} |
|||
|
|||
.scroll-pane > .viewport { |
|||
-fx-background-color: transparent; |
|||
} |
|||
|
|||
.chat-message-box { |
|||
-fx-text-fill: white; |
|||
/* -fx-background-color: LIGHTGREEN; */ |
|||
-fx-background-color: #82ccdd; |
|||
-fx-background-radius: 30px; |
|||
-fx-padding: 20px; |
|||
} |
|||
|
|||
.chat-background { |
|||
-fx-background-color: rgba(0, 0, 0, 0.4); |
|||
/* -fx-selection-bar: rgba(0, 0, 0, 0.5); */ |
|||
-fx-text-fill: white; |
|||
-fx-background-radius: 20px; |
|||
-fx-padding: 5px 10px; |
|||
} |
|||
|
|||
.my-list-view { |
|||
-fx-background-color: rgba(0, 0, 0, 0.4); |
|||
/* -fx-selection-bar: rgba(0, 0, 0, 0.5); */ |
|||
-fx-text-fill: white; |
|||
-fx-background-radius: 20px; |
|||
-fx-padding: 5px 10px; |
|||
} |
|||
|
|||
.list-cell { |
|||
-fx-background-color: transparent; |
|||
-fx-text-fill: white; |
|||
} |
|||
|
|||
.list-cell:selected { |
|||
-fx-background-color: rgba(0, 0, 0, 0.2); |
|||
-fx-text-fill: white; |
|||
-fx-background-radius: 20px; |
|||
} |
|||
|
|||
.list-cell:hover { |
|||
-fx-background-color: rgba(0, 0, 0, 0.1); |
|||
-fx-text-fill: white; |
|||
-fx-background-radius: 20px; |
|||
} |
|||
|
|||
.list-cell:selected:hover { |
|||
-fx-background-color: rgba(0, 0, 0, 0.3); |
|||
-fx-text-fill: white; |
|||
-fx-background-radius: 20px; |
|||
} |
|||
|
|||
.list-view:focused .list-cell:selected { |
|||
-fx-background-color: rgba(0, 0, 0, 0.3); |
|||
-fx-text-fill: white; |
|||
-fx-background-radius: 20px; |
|||
} |
|||
|
|||
.text-area { |
|||
-fx-text-fill: white; |
|||
-fx-border-radius: 20px; |
|||
} |
|||
|
|||
.text-area .content { |
|||
-fx-background-color: rgb(116, 116, 116); |
|||
-fx-background-radius: 20px; |
|||
} |
|||
|
|||
.text-area { |
|||
-fx-background-color: rgba(53, 89, 119, 0.4); |
|||
} |
|||
|
|||
.text-area .scroll-pane { |
|||
-fx-background-color: transparent; |
|||
} |
|||
|
|||
.text-area .scroll-pane .viewport { |
|||
-fx-background-color: transparent; |
|||
} |
|||
|
|||
.text-area .scroll-pane .content { |
|||
-fx-background-color: transparent; |
|||
} |
|||
|
|||
#chatInput { |
|||
-fx-text-fill: white; |
|||
-fx-background-radius: 20px; |
|||
-fx-padding: 5px 10px; |
|||
} |
@ -0,0 +1,85 @@ |
|||
.navigation { |
|||
-fx-background-color: derive(cadetblue, 60%); |
|||
-fx-font-size: 14px; |
|||
} |
|||
|
|||
.status { |
|||
-fx-background-color: derive(lightgray, 30%); |
|||
-fx-font-size: 12px; |
|||
} |
|||
|
|||
.workspace2 { |
|||
-fx-background-color: azure; |
|||
-fx-font-size: 16px; |
|||
} |
|||
|
|||
.workspace { |
|||
-fx-background-color: beige; |
|||
-fx-font-size: 13px; |
|||
} |
|||
|
|||
.personPane { |
|||
-fx-font-size: 11px; |
|||
} |
|||
|
|||
.root { |
|||
-fx-padding: 5 5 5 5; |
|||
} |
|||
|
|||
.scroll-bar:horizontal .track, |
|||
.scroll-bar:vertical .track { |
|||
-fx-background-color: transparent; |
|||
-fx-border-color: transparent; |
|||
-fx-background-radius: 0em; |
|||
-fx-border-radius: 2em; |
|||
} |
|||
|
|||
.scroll-bar:horizontal .increment-button, |
|||
.scroll-bar:horizontal .decrement-button { |
|||
-fx-background-color: transparent; |
|||
-fx-background-radius: 0em; |
|||
-fx-padding: 0 0 10 0; |
|||
} |
|||
|
|||
.scroll-bar:vertical .increment-button, |
|||
.scroll-bar:vertical .decrement-button { |
|||
-fx-background-color: transparent; |
|||
-fx-background-radius: 0em; |
|||
-fx-padding: 0 10 0 0; |
|||
} |
|||
|
|||
.scroll-bar .increment-arrow, |
|||
.scroll-bar .decrement-arrow { |
|||
-fx-shape: " "; |
|||
-fx-padding: 0.15em 0; |
|||
} |
|||
|
|||
.scroll-bar:vertical .increment-arrow, |
|||
.scroll-bar:vertical .decrement-arrow { |
|||
-fx-shape: " "; |
|||
-fx-padding: 0 0.15em; |
|||
} |
|||
|
|||
.scroll-bar:horizontal .thumb, |
|||
.scroll-bar:vertical .thumb { |
|||
-fx-background-color: derive(black, 90%); |
|||
-fx-background-insets: 2, 0, 0; |
|||
-fx-background-radius: 2em; |
|||
} |
|||
|
|||
.scroll-bar:horizontal .thumb:hover, |
|||
.scroll-bar:vertical .thumb:hover { |
|||
-fx-background-color: derive(#4d4c4f, 10%); |
|||
-fx-background-insets: 2, 0, 0; |
|||
-fx-background-radius: 2em; |
|||
} |
|||
|
|||
.root { |
|||
-fx-background-color: linear-gradient(to right, #91eae4, #86a8e7, #7f7fd5); |
|||
} |
|||
/* linear-gradient(to right, #91EAE4, #86A8E7, #7F7FD5); */ |
|||
/* linear-gradient(from 25% 25% to 100% 100%, #dc143c, #661a33)"); */ |
|||
|
|||
.text-white { |
|||
-fx-text-fill: white; |
|||
} |
@ -0,0 +1,5 @@ |
|||
#rootPane { |
|||
-fx-background-image: url("../images/backgroung.jpg"); |
|||
-fx-background-size: 1920 1080; |
|||
-fx-background-position: center center; |
|||
} |
@ -0,0 +1,114 @@ |
|||
|
|||
package wow.doge.chatto.control; |
|||
|
|||
import javafx.animation.Animation; |
|||
import javafx.animation.KeyFrame; |
|||
import javafx.animation.Timeline; |
|||
import javafx.beans.DefaultProperty; |
|||
import javafx.beans.property.DoubleProperty; |
|||
import javafx.event.EventHandler; |
|||
import javafx.geometry.Bounds; |
|||
import javafx.geometry.Insets; |
|||
import javafx.geometry.Pos; |
|||
import javafx.scene.Node; |
|||
import javafx.scene.control.ScrollPane; |
|||
import javafx.scene.control.ListView; |
|||
import javafx.geometry.Orientation; |
|||
import javafx.scene.control.ScrollBar; |
|||
import javafx.scene.input.MouseEvent; |
|||
import javafx.scene.input.ScrollEvent; |
|||
import javafx.scene.layout.*; |
|||
import javafx.scene.paint.Color; |
|||
import javafx.scene.shape.Rectangle; |
|||
import javafx.scene.transform.Scale; |
|||
import javafx.scene.transform.Transform; |
|||
import javafx.util.Duration; |
|||
|
|||
import java.util.function.Function; |
|||
|
|||
public class JFXSmoothScroll { |
|||
|
|||
private static ScrollBar getScrollbarComponent(ListView<?> control, Orientation orientation) { |
|||
Node n = control.lookup(".scroll-bar"); |
|||
if (n instanceof ScrollBar) { |
|||
final ScrollBar bar = (ScrollBar) n; |
|||
if (bar.getOrientation().equals(orientation)) { |
|||
return bar; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
public static void smoothScrollingListView(ListView<?> listView, double speed) { |
|||
smoothScrollingListView(listView, speed, Orientation.VERTICAL, bounds -> bounds.getHeight()); |
|||
} |
|||
|
|||
public static void smoothHScrollingListView(ListView<?> listView, double speed) { |
|||
smoothScrollingListView(listView, speed, Orientation.HORIZONTAL, bounds -> bounds.getHeight()); |
|||
} |
|||
|
|||
private static void smoothScrollingListView(ListView<?> listView, double speed, Orientation orientation, |
|||
Function<Bounds, Double> sizeFunc) { |
|||
ScrollBar scrollBar = getScrollbarComponent(listView, orientation); |
|||
if (scrollBar == null) { |
|||
return; |
|||
} |
|||
scrollBar.setUnitIncrement(5); |
|||
final double[] frictions = { 0.99, 0.1, 0.05, 0.04, 0.03, 0.02, 0.01, 0.04, 0.01, 0.008, 0.008, 0.008, 0.008, |
|||
0.0006, 0.0005, 0.00003, 0.00001 }; |
|||
final double[] pushes = { speed }; |
|||
final double[] derivatives = new double[frictions.length]; |
|||
final double[] lastVPos = { 0 }; |
|||
Timeline timeline = new Timeline(); |
|||
final EventHandler<MouseEvent> dragHandler = event -> timeline.stop(); |
|||
final EventHandler<ScrollEvent> scrollHandler = event -> { |
|||
scrollBar.valueProperty().set(lastVPos[0]); |
|||
if (event.getEventType() == ScrollEvent.SCROLL) { |
|||
double direction = event.getDeltaY() > 0 ? -1 : 1; |
|||
for (int i = 0; i < pushes.length; i++) { |
|||
derivatives[i] += direction * pushes[i]; |
|||
} |
|||
if (timeline.getStatus() == Animation.Status.STOPPED) { |
|||
timeline.play(); |
|||
} |
|||
|
|||
} |
|||
event.consume(); |
|||
}; |
|||
if (scrollBar.getParent() != null) { |
|||
scrollBar.getParent().addEventHandler(MouseEvent.DRAG_DETECTED, dragHandler); |
|||
scrollBar.getParent().addEventHandler(ScrollEvent.ANY, scrollHandler); |
|||
} |
|||
scrollBar.parentProperty().addListener((o, oldVal, newVal) -> { |
|||
if (oldVal != null) { |
|||
oldVal.removeEventHandler(MouseEvent.DRAG_DETECTED, dragHandler); |
|||
oldVal.removeEventHandler(ScrollEvent.ANY, scrollHandler); |
|||
} |
|||
if (newVal != null) { |
|||
newVal.addEventHandler(MouseEvent.DRAG_DETECTED, dragHandler); |
|||
newVal.addEventHandler(ScrollEvent.ANY, scrollHandler); |
|||
} |
|||
}); |
|||
|
|||
timeline.getKeyFrames().add(new KeyFrame(Duration.millis(3), (event) -> { |
|||
for (int i = 0; i < derivatives.length; i++) { |
|||
derivatives[i] *= frictions[i]; |
|||
} |
|||
for (int i = 1; i < derivatives.length; i++) { |
|||
derivatives[i] += derivatives[i - 1]; |
|||
} |
|||
double dy = derivatives[derivatives.length - 1]; |
|||
double size = sizeFunc.apply(scrollBar.getLayoutBounds()); |
|||
scrollBar.valueProperty().set(Math.min(Math.max(scrollBar.getValue() + dy / size, 0), 1)); |
|||
lastVPos[0] = scrollBar.getValue(); |
|||
if (Math.abs(dy) < 1) { |
|||
if (Math.abs(dy) < 0.001) { |
|||
timeline.stop(); |
|||
} |
|||
} |
|||
})); |
|||
timeline.setCycleCount(Animation.INDEFINITE); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,10 @@ |
|||
package wow.doge.chatto.control |
|||
|
|||
import javafx.scene.layout.HBox |
|||
import javafx.scene.control.Label |
|||
import scalafx.Includes._ |
|||
import wow.doge.chatto.controller.ChatData |
|||
import com.sfxcode.sapphire.core.value.FXBean |
|||
|
|||
class MessageBox(val sender: String, val receiver: String, val message: String) |
|||
extends HBox() {} |
@ -1,69 +0,0 @@ |
|||
package wow.doge.chatto.service |
|||
|
|||
import org.json4s.CustomSerializer |
|||
import org.json4s._ |
|||
import java.time.Instant |
|||
// import org.json4s.JsonAST._ |
|||
import org.json4s.JsonDSL._ |
|||
// class ParentSerializer extends Serializer[Parent] { |
|||
// private val ParentClass = classOf[Parent] |
|||
// implicit val formats = DefaultFormats |
|||
|
|||
// def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), Parent] = { |
|||
// case (TypeInfo(ParentClass, _), json) => json match { |
|||
// case JObject(JField("kind", JString(kind)) :: _) => kind match { |
|||
// case "first_type" => json.extract[ChildClassOne] |
|||
// case "second_type" => json.extract[ChildClassTwo] |
|||
// } |
|||
|
|||
// case _ => throw new MappingException("Invalid kind") |
|||
// } |
|||
// } |
|||
|
|||
// def serialize(implicit format: Formats): PartialFunction[Any, JValue] = Map() |
|||
// } |
|||
|
|||
// class MyJInstantSerializer extends Serializer[Instant] { |
|||
// implicit val formats = DefaultFormats |
|||
|
|||
// def deserialize( |
|||
// implicit format: Formats |
|||
// ): PartialFunction[(TypeInfo, JValue), Instant] = { |
|||
// case (_, JString(d)) => Instant.parse(d) |
|||
// case (_, JNull) => null |
|||
// } |
|||
|
|||
// def serialize(implicit format: Formats): PartialFunction[Any, JValue] = { |
|||
// case d: Instant => JString(d.toString()) |
|||
// } |
|||
// } |
|||
|
|||
// class MyJInstantSerializer |
|||
// extends CustomSerializer[Instant](implicit format => |
|||
// ( |
|||
// { |
|||
// // case JInt(d) => Instant.ofEpochMilli(d.toLong) |
|||
// case JString(d) => Instant.parse(d) |
|||
// case JNull => null |
|||
// }, { |
|||
// // case d: Instant => JInt(d.toEpochMilli) |
|||
// case d: Instant => JString(d.toString()) |
|||
// } |
|||
// ) |
|||
// ) |
|||
// import java.time.ZonedDateTime |
|||
// import java.time.format.DateTimeFormatter |
|||
|
|||
// a custom serializer has two partial functions, one |
|||
// for serializing and one for deserializing |
|||
// case object ZDTSerializer |
|||
// extends CustomSerializer[ZonedDateTime](format => |
|||
// ({ |
|||
// case JString(s) => ZonedDateTime.parse(s) |
|||
// }, { |
|||
// case zdt: ZonedDateTime => |
|||
// JString( |
|||
// zdt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX")) |
|||
// ) |
|||
// }) |
|||
// ) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue