Browse Source

Started doing some work on the GUI.

Added a markdown processor.
Change the about file to be a markdown file.
Got the about button to implement a parser and display a dialog.
Included an example of a utility dialog that loads a remote website.
master
Drew Short 10 years ago
parent
commit
a225f267cf
  1. 27
      pom.xml
  2. 85
      src/main/java/com/sothr/imagetools/App.java
  3. 12
      src/main/java/com/sothr/imagetools/AppConfig.java
  4. 2
      src/main/resources/documents/about.md
  5. 45
      src/main/resources/fxml/mainapp/MainApp.fxml
  6. 2
      src/main/scala/com/sothr/imagetools/Engine.scala
  7. 137
      src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala

27
pom.xml

@ -45,6 +45,7 @@
<lib.h2database.version>1.3.175</lib.h2database.version>
<lib.hibernate.version>4.3.0.Final</lib.hibernate.version>
<lib.hibernate.ehcache.version>2.6.6</lib.hibernate.ehcache.version>
<lib.markdown4j.version>2.2-cj-1.0</lib.markdown4j.version>
</properties>
<dependencies>
@ -160,6 +161,11 @@
<artifactId>hibernate-c3p0</artifactId>
<version>${lib.hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.commonjava.googlecode.markdown4j</groupId>
<artifactId>markdown4j</artifactId>
<version>${lib.markdown4j.version}</version>
</dependency>
</dependencies>
<build>
@ -171,6 +177,7 @@
<include>**/*.conf</include>
<include>**/*.properties</include>
<include>**/*.info</include>
<include>**/*.md</include>
</includes>
</resource>
<resource>
@ -180,6 +187,7 @@
<exclude>**/*.conf</exclude>
<exclude>**/*.properties</exclude>
<exclude>**/*.info</exclude>
<exclude>**/*.md</exclude>
</excludes>
</resource>
</resources>
@ -191,6 +199,7 @@
<include>**/*.conf</include>
<include>**/*.properties</include>
<include>**/*.info</include>
<include>**/*.md</include>
</includes>
</testResource>
<testResource>
@ -200,6 +209,7 @@
<exclude>**/*.conf</exclude>
<exclude>**/*.properties</exclude>
<exclude>**/*.info</exclude>
<exclude>**/*.md</exclude>
</excludes>
</testResource>
</testResources>
@ -403,7 +413,8 @@
<artifactId>maven-antrun-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<execution>
<id>prepare</id>
<phase>process-resources</phase>
<configuration>
<tasks>
@ -423,6 +434,20 @@
<goal>run</goal>
</goals>
</execution>
<execution>
<id>package</id>
<phase>package</phase>
<configuration>
<tasks>
<!-- set permissions on run files -->
<chmod file="${project.build.directory}/release/startCLI.sh" perm="755"/>
<chmod file="${project.build.directory}/release/startGUI.sh" perm="755"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>

85
src/main/java/com/sothr/imagetools/App.java

@ -25,57 +25,62 @@ public class App extends Application
public static void main( String[] args )
{
AppConfig.configureApp();
try {
//try to run the UI
launch(args);
} catch (Exception ex) {
logger.error("A fatal error has occurred: ", ex);
//show popup about the error to the user then exit
}
AppConfig.configureApp();
try {
//try to run the UI
launch(args);
} catch (Exception ex) {
logger.error("A fatal error has occurred: ", ex);
//show popup about the error to the user then exit
}
}
@Override
public void init() throws Exception{
AppConfig.configureApp();
logger = LoggerFactory.getLogger(this.getClass());
logger.info("Initializing Image Tools");
List<String> parameters = this.getParameters().getRaw();
logger.info(String.format("Application was called with '%s' parameters", parameters.toString()));
super.init();
AppConfig.configureApp();
logger = LoggerFactory.getLogger(this.getClass());
logger.info("Initializing Image Tools");
List<String> parameters = this.getParameters().getRaw();
logger.info(String.format("Application was called with '%s' parameters", parameters.toString()));
super.init();
}
@Override
public void start(Stage primaryStage) throws Exception {
logger.info("Image-Tools is starting");
logger.info(String.format("Launching GUI with FXML file %s", MAINGUI_FXML));
try {
Parent root = FXMLLoader.load(ResourceLoader.get().getResource(MAINGUI_FXML));
primaryStage.setScene(new Scene(root));
//config main scene
primaryStage.setTitle("Image Tools");
primaryStage.setMinHeight(600.0);
primaryStage.setMinWidth(800.0);
primaryStage.setResizable(true);
//show main scene
primaryStage.show();
} catch (IOException ioe) {
String message = String.format("Unable to load FXML file: %s", MAINGUI_FXML);
ImageToolsException ite = new ImageToolsException(message, ioe);
logger.error(message, ioe);
throw ite;
} catch (Exception ex) {
String message = "An unhandled exception was thrown by the GUI";
ImageToolsException ite = new ImageToolsException(message, ex);
logger.error(message, ex);
throw ite;
}
logger.info("Image-Tools is starting");
logger.info(String.format("Launching GUI with FXML file %s", MAINGUI_FXML));
//store the primary stage globally for reference in popups and the like
AppConfig.setPrimaryStage(primaryStage);
try {
Parent root = FXMLLoader.load(ResourceLoader.get().getResource(MAINGUI_FXML));
primaryStage.setScene(new Scene(root));
//config main scene
primaryStage.setTitle("Image Tools");
primaryStage.setMinHeight(600.0);
primaryStage.setMinWidth(800.0);
primaryStage.setResizable(true);
//show main scene
primaryStage.show();
} catch (IOException ioe) {
String message = String.format("Unable to load FXML file: %s", MAINGUI_FXML);
ImageToolsException ite = new ImageToolsException(message, ioe);
logger.error(message, ioe);
throw ite;
} catch (Exception ex) {
String message = "An unhandled exception was thrown by the GUI";
ImageToolsException ite = new ImageToolsException(message, ex);
logger.error(message, ex);
throw ite;
}
}
@Override
public void stop() throws Exception {
logger.info("Image-Tools is shutting down");
AppConfig.shutdown();
super.stop();
logger.info("Image-Tools is shutting down");
AppConfig.shutdown();
super.stop();
//force the JVM to close
System.exit(0);
}
}

12
src/main/java/com/sothr/imagetools/AppConfig.java

@ -5,6 +5,7 @@ import com.sothr.imagetools.dao.HibernateUtil;
import com.sothr.imagetools.util.ResourceLoader;
import com.sothr.imagetools.util.PropertiesService;
import com.sothr.imagetools.util.PropertiesEnum;
import javafx.stage.Stage;
import net.sf.ehcache.CacheManager;
import org.slf4j.LoggerFactory;
@ -23,21 +24,26 @@ public class AppConfig {
private static Logger logger;
public static CacheManager cacheManager;
//Logging defaults
// Logging defaults
private static final String LOGSETTINGSFILE = "./logback.xml";
private static Boolean configuredLogging = false;
//Properties defaults
// Properties defaults
private static final String DEFAULTPROPERTIESFILE = "application.conf";
private static final String USERPROPERTIESFILE = "user.conf";
private static Boolean loadedProperties = false;
//Cache defaults
// Cache defaults
private static Boolean configuredCache = false;
// General Akka Actor System
private static ActorSystem appSystem = ActorSystem.create("ITActorSystem");
// The Main App
private static Stage primaryStage = null;
public static Stage getPrimaryStage() { return primaryStage; }
public static void setPrimaryStage(Stage newPrimaryStage) { primaryStage = newPrimaryStage; }
public static ActorSystem getAppActorSystem() {
return appSystem;
}

2
src/main/resources/documents/about.info → src/main/resources/documents/about.md

@ -1,4 +1,4 @@
Image Tools Version: ${project.version}
**Image Tools Version: ${project.version}**
This is a simple about script. It demonstrates loading the about text from a file.

45
src/main/resources/fxml/mainapp/MainApp.fxml

@ -4,24 +4,27 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane minHeight="400.0" minWidth="600.0" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sothr.imagetools.ui.controller.AppController">
<children><MenuBar fx:id="rootMenuBar" minWidth="-Infinity" prefHeight="29.0" prefWidth="600.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns:fx="http://javafx.com/fxml">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem fx:id="" mnemonicParsing="false" onAction="#closeAction" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" onAction="#aboutAction" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</children></AnchorPane>
<AnchorPane minHeight="400.0" minWidth="600.0" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.sothr.imagetools.ui.controller.AppController">
<children>
<MenuBar fx:id="rootMenuBar" minWidth="-Infinity" prefHeight="29.0" prefWidth="600.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" onAction="#closeAction" text="Close" fx:id="" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" onAction="#aboutAction" text="About" />
<MenuItem mnemonicParsing="false" onAction="#helpAction" text="Help Site" />
</items>
</Menu>
</menus>
</MenuBar>
</children>
</AnchorPane>

2
src/main/scala/com/sothr/imagetools/Engine.scala

@ -10,7 +10,7 @@ import akka.actor.{ActorRef, ActorSystem, ActorLogging, Actor}
/**
* Created by drew on 1/26/14.
*/
abstract class Engine extends Logging{
abstract class Engine extends Logging {
val system = ActorSystem("EngineActorSystem")
val imageFilter:ImageFilter = new ImageFilter()
val imageCache = AppConfig.cacheManager.getCache("images")

137
src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala

@ -2,60 +2,157 @@ package com.sothr.imagetools.ui.controller
import javafx.fxml.FXML
import javafx.event.ActionEvent
import org.slf4j.LoggerFactory
import org.slf4j.Logger
import javafx.stage.{StageStyle, Stage}
import javafx.scene.Scene
import javafx.scene.Group
import javafx.scene.text.Text
import java.io.{IOException, File}
import javafx.scene.text.{TextAlignment, Text}
import java.io.IOException
import java.util.Scanner
import com.sothr.imagetools.util.ResourceLoader
import java.net.URL
import grizzled.slf4j.Logging
import javafx.scene.web.WebView
import org.markdown4j.Markdown4jProcessor
/**
* Created by drew on 12/31/13.
*/
class AppController {
class AppController extends Logging {
val logger:Logger = LoggerFactory.getLogger(this.getClass)
//val logger:Logger = LoggerFactory.getLogger(this.getClass)
//Define controls
@FXML var rootMenuBar : javafx.scene.control.MenuBar = null
//region MenuItem Actions
@FXML
def helpAction(event:ActionEvent) = {
showExternalHTMLUtilityDialog("http://www.sothr.com")
}
@FXML
def aboutAction(event:ActionEvent) = {
logger.debug("Displaying about screen")
debug("Displaying about screen")
var aboutMessage = "Simple About Message"
try {
aboutMessage = new Scanner(ResourceLoader.get().getResourceStream("documents/about")).useDelimiter("\\A").next()
val scanner = new Scanner(ResourceLoader.get().getResourceStream("documents/about.md"))
aboutMessage = ""
while (scanner.hasNextLine) {
aboutMessage += scanner.nextLine().trim() + "\n"
}
debug(s"Parsed About Message: '$aboutMessage'")
} catch {
case ioe:IOException =>
logger.error("Unable to read about file")
error("Unable to read about file")
}
showMarkdownUtilityDialog("About", aboutMessage, 400.0, 300.0)
debug("Showing About Dialog")
}
@FXML
def closeAction(event:ActionEvent ) = {
debug("Closing application from the menu bar")
val stage:Stage = this.rootMenuBar.getScene.getWindow.asInstanceOf[Stage]
stage.close()
}
//endregion
//todo: include a templating engine for rendering information
//todo: show a dialog that is rendered from markdown content
def showMarkdownUtilityDialog(title:String, markdown:String, width:Double = 800.0, height:Double = 600.0) = {
val htmlBody = new Markdown4jProcessor().process(markdown)
showHTMLUtilityDialog(title, htmlBody, width, height)
}
/**
* Render HTML content to a utility dialog. No input or output, just raw rendered content through a webkit engine.
*
* @param title
* @param htmlBody
* @param width
* @param height
*/
def showHTMLUtilityDialog(title:String, htmlBody:String, width:Double = 800.0, height:Double = 600.0) = {
val dialog:Stage = new Stage()
dialog.initStyle(StageStyle.UTILITY)
val parent:Group = new Group();
parent.getChildren.add(new Text(25, 25, aboutMessage))
val parent:Group = new Group()
//setup the HTML view
val htmlView = new WebView
htmlView.getEngine.loadContent(htmlBody)
htmlView.setMinWidth(width)
htmlView.setMinHeight(height)
htmlView.setPrefWidth(width)
htmlView.setPrefHeight(height)
parent.getChildren.add(htmlView)
val scene:Scene = new Scene(parent)
dialog.setScene(scene)
dialog.setResizable(false)
dialog.setMinHeight(400.0)
dialog.setMinWidth(400.0)
dialog.setTitle(title)
dialog.show()
}
@FXML
def closeAction(event:ActionEvent ) = {
logger.debug("Closing application from the menu bar")
val stage:Stage = this.rootMenuBar.getScene.getWindow.asInstanceOf[Stage]
stage.close()
def showExternalHTMLUtilityDialog(url:String) = {
val dialog:Stage = new Stage()
dialog.initStyle(StageStyle.UTILITY)
val parent:Group = new Group()
//setup the HTML view
val htmlView = new WebView
htmlView.getEngine.load(url)
//htmlView.setMinWidth(width)
//htmlView.setMinHeight(height)
//htmlView.setPrefWidth(width)
//htmlView.setPrefHeight(height)
parent.getChildren.add(htmlView)
val scene:Scene = new Scene(parent)
dialog.setScene(scene)
dialog.setResizable(false)
dialog.setTitle(htmlView.getEngine.getTitle)
dialog.show()
}
//endregion
/**
* Show a plain text utility dialog
*
* @param message
* @param wrapWidth
* @param alignment
*/
def showUtilityDialog(title:String,
message:String,
wrapWidth:Double=300.0,
xOffset:Double = 25.0,
yOffset:Double = 25.0,
alignment:TextAlignment=TextAlignment.JUSTIFY) = {
val dialog:Stage = new Stage()
dialog.initStyle(StageStyle.UTILITY)
val parent:Group = new Group()
// fill the text box
val messageText = new Text()
messageText.setText(message)
messageText.setWrappingWidth(wrapWidth)
messageText.setX(xOffset)
messageText.setY(yOffset)
messageText.setTextAlignment(TextAlignment.JUSTIFY)
parent.getChildren.add(messageText)
val scene:Scene = new Scene(parent)
dialog.setScene(scene)
dialog.setResizable(false)
dialog.setMinWidth(wrapWidth+xOffset*2)
dialog.setTitle(title)
dialog.show()
}
def print():String = {
return "This method works"

Loading…
Cancel
Save