You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
2.2 KiB

  1. package org.gerweck.scalafx.akka
  2. import language.implicitConversions
  3. import scala.collection.mutable.{ Clearable, Growable }
  4. import scala.concurrent._
  5. import scala.concurrent.duration._
  6. import scala.util._
  7. import akka.{ Done, NotUsed }
  8. import akka.stream.Materializer
  9. import akka.stream.scaladsl._
  10. import scalafx.application.Platform.runLater
  11. import scalafx.beans.Observable
  12. import scalafx.beans.property._
  13. import org.gerweck.scalafx.util.FutureObservable
  14. trait AkkaFXCollections extends Any {
  15. implicit def sourceToRichSource[A, B](source: Source[A, B]) = new AkkaFXCollections.RichSource(source)
  16. }
  17. object AkkaFXCollections {
  18. def collectionWriterSink[A]
  19. (buffer: Observable with Growable[A] with Clearable,
  20. clearFirst: Boolean,
  21. groupingSize: Int = 50, groupingTimeout: FiniteDuration = 100.milliseconds)
  22. : Sink[A, Future[Done]] = {
  23. sealed trait PopulateAction
  24. case class InsertRows(data: Seq[A]) extends PopulateAction
  25. case object ClearData extends PopulateAction
  26. val grouping = {
  27. Flow[A]
  28. .groupedWithin(groupingSize, groupingTimeout)
  29. .map(InsertRows)
  30. .named("GroupInsertActions")
  31. }
  32. val clearData = {
  33. if (clearFirst)
  34. Source.single(ClearData)
  35. else
  36. Source.empty
  37. }.named("OptionalClearAction")
  38. val combinedSource: Flow[A, PopulateAction, NotUsed] = grouping.prepend(clearData)
  39. combinedSource .toMat {
  40. Sink .foreach[PopulateAction] {
  41. case ClearData => runLater { buffer.clear() }
  42. case InsertRows(data) => runLater { buffer ++= data }
  43. } .named("BufferWriter")
  44. }(Keep.right)
  45. }
  46. class RichSource[A, B](val inner: Source[A, B]) extends AnyVal {
  47. def populateCollection[C >: A]
  48. (buffer: Observable with Growable[C] with Clearable,
  49. clearFirst: Boolean,
  50. groupingSize: Int = 50, groupingTimeout: FiniteDuration = 100.milliseconds)
  51. (implicit mat: Materializer, ec: ExecutionContext)
  52. : ReadOnlyObjectProperty[Option[Try[Done]]] = {
  53. val sink = collectionWriterSink(buffer, clearFirst, groupingSize, groupingTimeout)
  54. val graph = inner.toMat(sink)(Keep.right)
  55. FutureObservable.ofTryOption(graph.run())
  56. }
  57. }
  58. }