Skip to content

Commit

Permalink
Setup uncaught exception handling
Browse files Browse the repository at this point in the history
  • Loading branch information
jpsacha committed May 30, 2020
1 parent 9a72dd3 commit dec552f
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 152 deletions.
4 changes: 3 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ scalaVersion := "2.13.1"

libraryDependencies ++= Seq(
"org.scalafx" %% "scalafx" % "14-R19",
"org.scala-lang.modules" %% "scala-xml" % "1.3.0"
"org.scala-lang.modules" %% "scala-xml" % "1.3.0",
"org.scalafx" %% "scalafx-extras" % "0.3.4",
"org.scalatest" %% "scalatest" % "3.1.2"
)

// Add OS specific JavaFX dependencies
Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
sbt.version=1.3.10
sbt.version=1.3.11

277 changes: 150 additions & 127 deletions src/main/scala/scalafx/ensemble/Ensemble.scala
Original file line number Diff line number Diff line change
@@ -1,128 +1,151 @@
/*
* Copyright (c) 2012-2015, ScalaFX Ensemble Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the ScalaFX Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE SCALAFX PROJECT OR ITS CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package scalafx.ensemble

import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.ensemble.commons.PageDisplayer
import scalafx.geometry.Insets
import scalafx.scene.Scene
import scalafx.scene.control._
import scalafx.scene.image.{Image, ImageView}
import scalafx.scene.layout._
import scalafx.stage.Screen

/** The main ScalaFX Ensemble application object. */
object Ensemble extends JFXApp {

//
// Example selection tree
//
var centerPane = PageDisplayer.choosePage("dashBoard")
val rootTreeItem = new TreeItem[String]("ScalaFX Ensemble") {
expanded = true
children = EnsembleTree.create().getTree
}

val screen = Screen.primary
val controlsView = new TreeView[String]() {
minWidth = 200
maxWidth = 200
editable = true
root = rootTreeItem
id = "page-tree"
}
controlsView.selectionModel().selectionMode = SelectionMode.Single
controlsView.selectionModel().selectedItem.onChange {
(_, _, newItem) => {
val pageCode = (newItem.isLeaf, Option(newItem.getParent)) match {
case (true, Some(parent)) => parent.getValue.toLowerCase + " > " + newItem.getValue
case (false, Some(_)) => "dashBoard - " + newItem.getValue
case (_, _) => "dashBoard"
}
centerPane = PageDisplayer.choosePage(pageCode)
splitPane.items.remove(1)
splitPane.items.add(1, centerPane)
}
}

val scrollPane = new ScrollPane {
minWidth = 200
maxWidth = 200
fitToWidth = true
fitToHeight = true
id = "page-tree"
content = controlsView
}
lazy val splitPane = new SplitPane {
dividerPositions = 0
id = "page-splitpane"
items.addAll(scrollPane, centerPane)
}

//
// Layout the main stage
//
stage = new PrimaryStage {
title = "ScalaFX Ensemble"
icons += new Image("/scalafx/ensemble/images/ScalaFX-icon-64x64.png")
scene = new Scene(1020, 700) {
stylesheets += this.getClass.getResource("/scalafx/ensemble/css/ensemble.css").toExternalForm
root = new BorderPane {
top = new VBox {
vgrow = Priority.Always
hgrow = Priority.Always
children = new ToolBar {
prefHeight = 76
maxHeight = 76
id = "mainToolBar"
content = List(
new ImageView {
image = new Image(
this.getClass.getResourceAsStream("/scalafx/ensemble/images/logo.png"))
margin = Insets(0, 0, 0, 10)
},
new Region {
minWidth = 300
},
new Button {
minWidth = 120
minHeight = 66
id = "newButton"
})
}
}
center = new BorderPane {
center = splitPane
}
styleClass += "application"
}
}
}
/*
* Copyright (c) 2012-2015, ScalaFX Ensemble Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the ScalaFX Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE SCALAFX PROJECT OR ITS CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package scalafx.ensemble

import org.scalafx.extras.{onFXAndWait, showException}
import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.ensemble.commons.PageDisplayer
import scalafx.geometry.Insets
import scalafx.scene.control._
import scalafx.scene.image.{Image, ImageView}
import scalafx.scene.layout._
import scalafx.scene.{Node, Scene}
import scalafx.stage.Screen

/** The main ScalaFX Ensemble application object. */
object Ensemble extends JFXApp {

private val Title = "ScalaFX Ensemble"

setupUncaughtExceptionHandling()

//
// Example selection tree
//
private var centerPane: Node = PageDisplayer.choosePage("dashBoard")
private val rootTreeItem: TreeItem[String] = new TreeItem[String](Title) {
expanded = true
children = EnsembleTree.create().getTree
}

private val screen = Screen.primary
private val controlsView: TreeView[String] = new TreeView[String]() {
minWidth = 200
maxWidth = 200
editable = true
root = rootTreeItem
id = "page-tree"
}
controlsView.selectionModel().selectionMode = SelectionMode.Single
controlsView.selectionModel().selectedItem.onChange {
(_, _, newItem) => {
val pageCode = (newItem.isLeaf, Option(newItem.getParent)) match {
case (true, Some(parent)) => parent.getValue.toLowerCase + " > " + newItem.getValue
case (false, Some(_)) => "dashBoard - " + newItem.getValue
case (_, _) => "dashBoard"
}
centerPane = PageDisplayer.choosePage(pageCode)
splitPane.items.remove(1)
splitPane.items.add(1, centerPane)
}
}

private val scrollPane: ScrollPane = new ScrollPane {
minWidth = 200
maxWidth = 200
fitToWidth = true
fitToHeight = true
id = "page-tree"
content = controlsView
}

lazy val splitPane: SplitPane = new SplitPane {
dividerPositions = 0
id = "page-splitpane"
items.addAll(scrollPane, centerPane)
}

//
// Layout the main stage
//
stage = new PrimaryStage {
title = "ScalaFX Ensemble"
icons += new Image("/scalafx/ensemble/images/ScalaFX-icon-64x64.png")
scene = new Scene(1020, 700) {
stylesheets += this.getClass.getResource("/scalafx/ensemble/css/ensemble.css").toExternalForm
root = new BorderPane {
top = new VBox {
vgrow = Priority.Always
hgrow = Priority.Always
children = new ToolBar {
prefHeight = 76
maxHeight = 76
id = "mainToolBar"
content = List(
new ImageView {
image = new Image(
this.getClass.getResourceAsStream("/scalafx/ensemble/images/logo.png"))
margin = Insets(0, 0, 0, 10)
},
new Region {
minWidth = 300
},
new Button {
minWidth = 120
minHeight = 66
id = "newButton"
})
}
}
center = new BorderPane {
center = splitPane
}
styleClass += "application"
}
}
}

def setupUncaughtExceptionHandling(): Unit = {
Thread.setDefaultUncaughtExceptionHandler(
(t: Thread, e: Throwable) => {
showException(Title, s"Unhandled exception on thread ${t.getName}.", e, stage)
}
)


onFXAndWait {
Thread.currentThread().setUncaughtExceptionHandler(
(t: Thread, e: Throwable) => {
showException(Title, s"Unhandled exception on thread ${t.getName}.", e, stage)
}
)
}
}
}
42 changes: 19 additions & 23 deletions src/main/scala/scalafx/ensemble/commons/ContentFactory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ package scalafx.ensemble.commons

import java.util.Locale

import javafx.scene.control.Alert
import javafx.scene.control.Alert.AlertType
import javafx.stage.Stage
import org.scalafx.extras.showException
import scalafx.Includes._
import scalafx.ensemble.commons.IOUtils._
import scalafx.ensemble.sbt.SBTProjectBuilder
Expand All @@ -43,16 +41,16 @@ import scalafx.scene.web.WebView
import scalafx.stage.DirectoryChooser

/**
* populates the tabbed content by loading
* EnsembleExample instance
*/
* populates the tabbed content by loading
* EnsembleExample instance
*/
object ContentFactory {
def createContent(exampleName: String, groupName: String) = {
def createContent(exampleName: String, groupName: String): ScrollPane = {

// Construct content of the samples dynamically
val fullClassName = ExampleInfo.className(exampleName, groupName)
var cache = Map[String, EnsembleExample]()
val sampleNode = if (cache.get(fullClassName).isDefined) {
val sampleNode = if (cache.contains(fullClassName)) {
cache(fullClassName).getContent
} else {
val inst = Class.forName(fullClassName).getDeclaredConstructor().newInstance().asInstanceOf[EnsembleExample]
Expand Down Expand Up @@ -152,10 +150,14 @@ object ContentFactory {
}
} catch {
case t: Throwable =>
// FIXME: test casting
t.printStackTrace()
val stage = thisButton.scene().window().asInstanceOf[Stage]
showError(stage, title = thisButton.text(), header = "Error saving sample SBT project",
message = t.getClass.getName + ": " + t.getMessage, t)
val window = thisButton.scene().window()
showException(
title = thisButton.text(),
message = "Error saving sample SBT project.",
t = t,
ownerWindow = window)
}
},
new Button {
Expand All @@ -169,9 +171,12 @@ object ContentFactory {
Clipboard.systemClipboard.setContent(content)
} catch {
case t: Throwable =>
val stage = thisButton.scene().window().asInstanceOf[Stage]
showError(stage, title = thisButton.text(),
header = "Error copying source to clipboard", message = t.getClass.getName + ": " + t.getMessage, t)
val window = thisButton.scene().window()
showException(
title = thisButton.text(),
message = "Error copying source to clipboard",
t = t,
ownerWindow = window)
}
}
)
Expand All @@ -192,13 +197,4 @@ object ContentFactory {
os.indexOf("mac") >= 0
}

private def showError(stage: Stage, title: String, header: String, message: String, t: Throwable): Unit = {
t.printStackTrace()
val alert = new Alert(AlertType.ERROR)
alert.initOwner(stage)
alert.setContentText(message)
alert.setHeaderText(header)
alert.setTitle(title)
alert.showAndWait()
}
}

0 comments on commit dec552f

Please sign in to comment.