diff --git a/app/bundle/src/main/scala/org/bitcoins/bundle/gui/BundleGUI.scala b/app/bundle/src/main/scala/org/bitcoins/bundle/gui/BundleGUI.scala index 94079bf3f3..3dfb76164f 100644 --- a/app/bundle/src/main/scala/org/bitcoins/bundle/gui/BundleGUI.scala +++ b/app/bundle/src/main/scala/org/bitcoins/bundle/gui/BundleGUI.scala @@ -72,6 +72,7 @@ object BundleGUI extends WalletGUI with JFXApp { scene = guiScene icons.add(GUIUtil.logo) } + taskRunner def changeToWalletGUIScene(): Unit = { Platform.runLater( diff --git a/app/gui/src/main/scala/org/bitcoins/gui/GUI.scala b/app/gui/src/main/scala/org/bitcoins/gui/GUI.scala index 0d8871b3fa..2c69f7df31 100644 --- a/app/gui/src/main/scala/org/bitcoins/gui/GUI.scala +++ b/app/gui/src/main/scala/org/bitcoins/gui/GUI.scala @@ -95,4 +95,5 @@ object GUI extends WalletGUI with JFXApp { } fetchStartingData() + taskRunner } diff --git a/app/gui/src/main/scala/org/bitcoins/gui/WalletGUIModel.scala b/app/gui/src/main/scala/org/bitcoins/gui/WalletGUIModel.scala index 7a25973c09..5e48b435cb 100644 --- a/app/gui/src/main/scala/org/bitcoins/gui/WalletGUIModel.scala +++ b/app/gui/src/main/scala/org/bitcoins/gui/WalletGUIModel.scala @@ -9,16 +9,18 @@ import org.bitcoins.core.wallet.fee.FeeUnit import org.bitcoins.gui.dialog._ import org.bitcoins.gui.util.GUIUtil import scalafx.application.Platform -import scalafx.beans.property.{ObjectProperty, StringProperty} +import scalafx.beans.property._ import scalafx.scene.control.Alert import scalafx.scene.control.Alert.AlertType import scalafx.stage.Window import scala.concurrent.duration.DurationInt +import scala.concurrent.{Await, Promise} import scala.util.{Failure, Success, Try} class WalletGUIModel()(implicit system: ActorSystem) { var taskRunner: TaskRunner = _ + import system.dispatcher // Sadly, it is a Java "pattern" to pass null into // constructors to signal that you want some default @@ -35,7 +37,6 @@ class WalletGUIModel()(implicit system: ActorSystem) { } def startWalletInfoScheduler(): Cancellable = { - import system.dispatcher system.scheduler.scheduleAtFixedRate(0.seconds, 10.seconds)( UpdateWalletInfoRunnable) } @@ -49,19 +50,22 @@ class WalletGUIModel()(implicit system: ActorSystem) { } def onGetNewAddress(): Unit = { - val address = StringProperty("") + val addressP = Promise[String]() taskRunner.run( caption = "Get New Address", op = { ConsoleCli.exec(GetNewAddress(None), GlobalData.consoleCliConfig) match { - case Success(commandReturn) => address.value = commandReturn - case Failure(err) => throw err + case Success(commandReturn) => addressP.success(commandReturn) + case Failure(err) => + addressP.failure(err) + throw err } } ) + val address = Await.result(addressP.future, 15.seconds) GetNewAddressDialog.showAndWait(parentWindow.value, address) } diff --git a/app/gui/src/main/scala/org/bitcoins/gui/dialog/GetNewAddressDialog.scala b/app/gui/src/main/scala/org/bitcoins/gui/dialog/GetNewAddressDialog.scala index da9716af0f..21a7af200d 100644 --- a/app/gui/src/main/scala/org/bitcoins/gui/dialog/GetNewAddressDialog.scala +++ b/app/gui/src/main/scala/org/bitcoins/gui/dialog/GetNewAddressDialog.scala @@ -1,9 +1,16 @@ package org.bitcoins.gui.dialog +import com.google.zxing.BarcodeFormat +import com.google.zxing.common.BitMatrix +import com.google.zxing.qrcode.QRCodeWriter +import javafx.scene.image.WritableImage +import javafx.scene.paint.Color +import org.bitcoins.core.protocol.BitcoinAddress import org.bitcoins.gui.GlobalData import scalafx.Includes._ import scalafx.beans.property.StringProperty import scalafx.scene.control.{ButtonType, Dialog, TextArea} +import scalafx.scene.image.{Image, ImageView} import scalafx.stage.Window object GetNewAddressDialog { @@ -27,7 +34,33 @@ object GetNewAddressDialog { text <== address editable = false } + val image: Image = + generateQRCode(address = BitcoinAddress.fromString(address.getValue)) + + val qrView = new ImageView(image) + dialog.graphic = qrView val _ = dialog.showAndWait() } + + private def generateQRCode(address: BitcoinAddress): Image = { + val width = 250 + val height = 250 + val qrCodeWriter = new QRCodeWriter + val bitMatrix: BitMatrix = + qrCodeWriter.encode(s"bitcoin:$address", + BarcodeFormat.QR_CODE, + width, + height) + + val writableImage = new WritableImage(width, height) + val pixelWriter = writableImage.getPixelWriter + 0.until(height).map { x => + 0.until(width).map { y => + val color = if (bitMatrix.get(x, y)) Color.BLACK else Color.WHITE + pixelWriter.setColor(x, y, color) + } + } + writableImage + } } diff --git a/project/Deps.scala b/project/Deps.scala index 35170158af..12f8a7df07 100644 --- a/project/Deps.scala +++ b/project/Deps.scala @@ -62,6 +62,8 @@ object Deps { val sttpV = "1.7.2" val codehausV = "3.1.4" val scalaJsTimeV = "2.3.0" + val zxingV = "3.4.1" + } object Compile { @@ -216,6 +218,12 @@ object Deps { val dropwizardMetrics = "io.dropwizard.metrics" % "metrics-core" % V.dropwizardMetricsV withSources () withJavadoc () + + val zxingCore = + "com.google.zxing" % "core" % V.zxingV withSources () withJavadoc () + + val zxingJ2SE = + "com.google.zxing" % "javase" % V.zxingV withSources () withJavadoc () } object Test { @@ -410,7 +418,9 @@ object Deps { val gui = List(Compile.akkaActor, Compile.breezeViz, - Compile.scalaFx) ++ Compile.javaFxDeps + Compile.scalaFx, + Compile.zxingCore, + Compile.zxingJ2SE) ++ Compile.javaFxDeps val server = Def.setting { List(