Skip to content

Commit

Permalink
Refactor Travel Planner to use MVVM instead of MVC
Browse files Browse the repository at this point in the history
  • Loading branch information
ckuessner committed Jul 5, 2024
1 parent b887e31 commit f1790e6
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 57 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package lofi_acl.example.monotonic_acl

import scalafx.geometry.Pos
import scalafx.scene.Scene
import scalafx.scene.control.{Button, TextField}
import scalafx.scene.layout.{BorderPane, HBox, VBox}

class MainScene extends Scene {
private val viewModel = new MainSceneViewModel()
private val rootPane = new BorderPane()

private val createNewDocumentButton: Button = new Button("Create new Travel Plan Document")
createNewDocumentButton.alignment = Pos.Center
createNewDocumentButton.onAction = _ => viewModel.createNewDocumentButtonPressed()
createNewDocumentButton.disable <== viewModel.documentIsOpen

private val joinDocumentButton: Button = new Button("Join")
joinDocumentButton.alignment = Pos.Center
joinDocumentButton.onAction = _ => viewModel.joinDocumentButtonPressed()
joinDocumentButton.disable <== viewModel.documentIsOpen

private val remoteDocumentUriTextField = new TextField {
promptText = "user@host:port"
// hgrow = Priority.Always
}
remoteDocumentUriTextField.disable <== viewModel.documentIsOpen
remoteDocumentUriTextField.text <==> viewModel.joinDocumentUri

rootPane.center = VBox(
createNewDocumentButton,
HBox(
remoteDocumentUriTextField,
joinDocumentButton
)
)

content = rootPane

// TODO: Hook in the document view on document open
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package lofi_acl.example.monotonic_acl

import scalafx.beans.property.{BooleanProperty, StringProperty}
import scalafx.scene.layout.StackPane

import scala.concurrent.ExecutionContext.global

class MainSceneViewModel {
private var model: Option[TravelPlanModel] = None

val bucketListViewContainer: StackPane = new StackPane()
bucketListViewContainer.minWidth = 400
bucketListViewContainer.minHeight = 800

val expenseViewContainer: StackPane = new StackPane()
expenseViewContainer.minWidth = 400
expenseViewContainer.minHeight = 800

val documentIsOpen: BooleanProperty = new BooleanProperty()
documentIsOpen.value = false

val joinDocumentUri: StringProperty = new StringProperty()

def createNewDocumentButtonPressed(): Unit = {
require(model.isEmpty)
documentIsOpen.value = true
global.execute { () =>
model = Some(TravelPlanModel(None))
}
}

def joinDocumentButtonPressed(): Unit = {
documentIsOpen.value = true
global.execute { () =>
model = Some(TravelPlanModel(Some(joinDocumentUri.value)))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,22 @@ import lofi_acl.sync.acl.monotonic.SyncWithMonotonicAcl

import java.util.concurrent.atomic.AtomicReference

class TravelPlannerController private (isNewDocument: Boolean) {
class TravelPlanModel(joinedDocument: Option[String]) {
private val privateId: PrivateIdentity = IdentityFactory.createNewIdentity

private val crdt = AtomicReference[TravelPlan]()

private val sync: SyncWithMonotonicAcl[TravelPlan] = SyncWithMonotonicAcl[TravelPlan](
privateId,
List.empty,
DeltaMapWithPrefix.empty
)
sync.start()
joinedDocument.foreach(sync.connect)

println(sync.connectionString)

def connect(connectionString: String): Unit = {
sync.connect(connectionString)
}
def connectionString: Option[String] = Some(sync.connectionString)

def shutdown(): Unit = {
sync.stop()
}

private val crdt = AtomicReference[TravelPlan]()
}

object TravelPlannerController {
def forNewDocument: TravelPlannerController = TravelPlannerController(true)

def forExistingDocument(connectionString: String): TravelPlannerController =
val controller = TravelPlannerController(false)
controller.connect(connectionString)
controller
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package lofi_acl.example.monotonic_acl

class TravelPlanView {

}
Original file line number Diff line number Diff line change
@@ -1,50 +1,15 @@
package lofi_acl.example.monotonic_acl

import scalafx.application.JFXApp3
import scalafx.scene.Scene
import scalafx.scene.control.{Button, TextField}
import scalafx.scene.layout.VBox

object TravelPlannerAppMonotonic extends TravelPlannerApp

class TravelPlannerApp extends JFXApp3 {
var controller: Option[TravelPlannerController] = None

object TravelPlannerApp extends JFXApp3 {
override def start(): Unit = {
val createNewDocumentButton = new Button {
text = "Create new travel plan"
onAction = ev => {
controller = Some(TravelPlannerController.forNewDocument)
}
}

val remoteDocumentUriTextField = new TextField {
promptText = "user@host:port"
// hgrow = Priority.Always
}

val joinDocumentButton = new Button {
text = "Join travel document"
onAction = ev => {
controller = Some(TravelPlannerController.forExistingDocument(remoteDocumentUriTextField.getText))
}
}

stage = new JFXApp3.PrimaryStage {
title.value = s"App with replicaId: ???"
scene = new Scene {
content = new VBox {
children = Seq(
createNewDocumentButton,
remoteDocumentUriTextField,
joinDocumentButton
)
}
}
title = s"Travel Planner"
scene = new MainScene()
resizable = true
}
}

override def stopApp(): Unit = {
controller.foreach(_.shutdown())
}
override def stopApp(): Unit = {}
}

0 comments on commit f1790e6

Please sign in to comment.