Saturday, December 12, 2015

Get Me Outta Here!

Happy Holidays! 

For today's post I want to share something I have been working on for the last few days. For quite some time I have wanted to build a small application which would generate a maze of sorts. The program would produce a user who would try to escape out of the box by trying multiple directions to get around the obstacles. I decided to use JavaFX as my platform to produce this application as it has the functions necessary (like intersects for collision detection) to build out my idea and I know the Java language very well.


Challenges

Collision Detection

During the development process I ran into many challenges. One of the largest of those was attempting to build the collision detection math from scratch. After many failed attempts I came across the built in functionality to assign intersection binding to nodes which is built into JavaFX. After each move I took the new user coordinates and used the Shape class getBoundsInLocal().getWidth() method to determine if the collision had occurred. In that case I would reset the current direction of the user.

for (Line border : borders) {
            Shape intersect = Shape.intersect(border, user);
            if (intersect.getBoundsInLocal().getWidth() != -1) {
                System.out.println("Hit a border");
                hitPlayer.play();
                user.setCenterX(currentX);
                user.setCenterY(currentY);
                currentDirection = -1;
                break;
            }
}


UI Updates / JFX Application Thread

Due to the implementation of JavaFX and threading it is necessary execute updates to the scene graph on the JavaFX application thread. In order to update this thread and graph from your application you must choose one of the methods provided by the platform. The one that I choose was using the Task object. Overriding the call method I execute the platform.runLater method to move the user. After each move the status bar is updated along with the position of the user in the application. This task is started with Thread t = new Thread(task), t.setDaemon(true), then t.start().

Task task = new Task<Void>() {
                    @Override
                    protected Void call() throws Exception {
                        for (int i = 1; i <= TASK_MAX; i++) {
                            updateProgress(i, TASK_MAX);
                            Platform.runLater(new Runnable() {

                                @Override
                                public void run() {
                                    autoMove();
                                }

Movement

Another issue which I had to solve was giving the user some sort of intelligence. If you were stuck in this box and you moved forward one space you most likely wouldn’t change your mind and go backwards. To provide for this I implemented logic to continue the user in their current direction until you hit something. When a collision ccurred the user would randomly decide a new direction and continue that way until they hit another block. I used a random number generator to provide an integer between 0 and 7, one for up, down, left, right, up right, up left, down right, down left. Then I update the position :

private void autoMove() {
        int dir = getDirection();
        if (dir < 0) {
            return;
        }
        switch (dir) {
            case 0:
                updateUser(null, user.getCenterY(), 0, JUMP);
                break;

The get direction method is used to return your current direction or get you a new one since you hit a block. A block collision sets direction
to -1.

private int getDirection() {
        if (currentDirection == -1) {
            Random rand = new Random();
            currentDirection = rand.nextInt(8);
        }
        return currentDirection;
}

I hope everyone has a safe and happy holiday with family and friends! Enjoy! 

The code for this project can be found on my github site here: https://github.com/dtbell99/GetMeOuttaHere


Wednesday, November 18, 2015

Handy Diff Utility (aka Differ)

How many times has someone asked you to tell them the difference between two files and that person would be upset if you handed them the output of a unix diff command? For developers who have access to IDE's or fancy difference tools you can see the changes easily but do any of them output those nice views into something useful you can hand over?

Due to this issue and not finding anything useful on the web I decided to create such a utility. I call this program Differ.

The command to run the application is: "java -jar Differ.jar changes.txt original.txt"

Pass into the application the newly changed file first and the existing or original version as the second parameter. The system will run through and generate an html report which can be passed around and viewed by everyone in an easily readable format.

Sample Report:

The source code will be available on my github page at the following: https://github.com/dtbell99/differ

Easy Bash Git Scripts

While enjoying all the benefits of git source control on my local development machine I thought I would share a few of my favorite shortcut scripts I've created for you to enjoy.

gitstat
This script is used to display the stat diff version between master and the current branch I'm working on. Save the script below in an executable path named gitstat.

#!/bin/bash
clear
echo ""
echo "Command: git diff --stat master..$1"
echo "----------------------------------------------------"
git diff --stat master..$1
echo ""

Run it with the command: gitstat branch_name


githelp
This is a simple echo of commonly used command line options for git to give me a quick reminder when I may forget something. Save the script in a executable path and name it githelp.

#!/bin/bash
clear
echo "Useful git commands"
echo "---------------------------------------------------------------------------"
echo "Create Branch              :   git branch nameofbranch"
echo "Switch to Branch           :   git checkout nameofbranch" 
echo "Update master              :   git checkout master | git merge nameofbranch"
echo "Remove branch              :   git branch -D nameofbranch"
echo "Add all files to staging   :   git add -all"
echo "Add staged files to branch :   git commit -m \"message\""
echo "Show diff between branches :   git diff branchone..branchtwo"
echo "Show all branches          :   git branch"

echo ""

Run it with the command: githelp

Thursday, November 12, 2015

ScanMyCode : A Code Count Generator

Recently I was sitting around wondering just how much code I had in a project I've been working on single handedly for the last couple years. Since there are programs out there that do this today I thought the best approach would be to write one myself.

The main aspects I wanted to gather were total files of each type and their line count minus blank lines. I also thought I would write a few lines of code to capture the method count as well.. why not... :)

So in order to complete the task I had to create a Java application which takes the base directory and a report name. I would then generate both a HTML and a CSV file after the code was finished. I used maps for files, lines, and methods. Then I used a collection of type Extension (custom class) and used a comparable to sort it by lines of code.

The output of the HTML report looks like the following screenshot.


The code can be found at my github account: https://github.com/dtbell99/ScanMyCode

Friday, May 8, 2015

Tombstone Idea

I came up with the perfect idea for my tombstone message for when the final day eventually comes and thought I'd post it. Enjoy!


Tuesday, April 14, 2015

JavaFX : Using Shapes To Create Your Own Icons

If you are like me you are always on the lookout for great icons for your applications. I always seem to find options that are very close but not quite right. If the design looks good then the color is wrong, or if the color and design are great the icon isn't available in the size I need. As a general rule I do not go into Photoshop or any other graphics tools and create or modify items like icons as I do not have an eye for good design. That brings us to JavaFX shapes and how you can leverage built in objects to generate great looking sharp icons or images to use in your applications that are generated from code so no external resources are required.

Below is an example of a play, pause, stop, and checkmark icon I created for a JavaFX application which I will be releasing later this year!


The code for this project can be found on github: https://github.com/dtbell99/JavaFXShapeIcons

FXML Markup:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import javafx.scene.shape.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>


<AnchorPane id="AnchorPane" prefHeight="328.0" prefWidth="395.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.40" fx:controller="com.broadlyapplicable.javafxexamples.shapes.icons.CustomController">
   <children>
      <VBox fx:id="vbox" layoutX="70.0" layoutY="51.0" prefHeight="328.0" prefWidth="395.0" spacing="75.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="25.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="25.0" />
   </children>
</AnchorPane>


Controller:

package com.broadlyapplicable.javafxexamples.shapes.icons;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Polyline;
import javafx.scene.shape.Rectangle;

public class CustomController implements Initializable {
    
    @FXML
    private VBox vbox;
    
    private static final String GREEN = "#68C953";
    private static final String RED = "#CF3E3E";
    private static final String YELLOW = "#EDAD18";
    private static final String BLUEGREEN = "#22BDBD";
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        vbox.getChildren().add(getPlayIcon());
        HBox hbox = new HBox(5);
        hbox.getChildren().add(getHalfPause());
        hbox.getChildren().add(getHalfPause());
        vbox.getChildren().add(hbox);
        vbox.getChildren().add(getStopIcon());
        vbox.getChildren().add(getCompletedIcon());
    }    
    
    private Polyline getCompletedIcon() {
        Polyline polygon = new Polyline();
        polygon.getPoints().addAll(new Double[]{
            0.0, 100.0, 40.0, 150.0, 80.0, 0.0
        });        
        polygon.setStroke(Paint.valueOf(BLUEGREEN));
        polygon.setStrokeWidth(15.0);
        return polygon;
    }
    
    private Polygon getPlayIcon() {
        Polygon polygon = new Polygon();
        polygon.getPoints().addAll(new Double[]{
            0.0, 0.0,
            0.0, 100.0,
            75.0, 50.0});
        
        polygon.setFill(Paint.valueOf(GREEN));
        return polygon;
    }
    
    private Rectangle getHalfPause() {
        Rectangle rectangle = new Rectangle();
        rectangle.setHeight(75);
        rectangle.setWidth(30);
        rectangle.setFill(Paint.valueOf(YELLOW));
        return rectangle;
    }
    
    private Rectangle getStopIcon() {
        Rectangle rectangle = new Rectangle();
        rectangle.setHeight(65);
        rectangle.setWidth(65);
        rectangle.setFill(Paint.valueOf(RED));
        return rectangle;
    }
    
}




Wednesday, March 18, 2015

JavaFX Toolbar Button Layout

For this simple post I will show how to layout your buttons on a JavaFX toolbar. There are many scenarios in which you would want to move these buttons around on the toolbar.  Therefore I will provide you a very simple example to accomplish left, right, center, and multiple alignments for your buttons.



The key to accomplishing this is using a <Pane HBox.hgrow="ALWAYS" /> between the edges to create space (see code below). Enjoy!!

This project has been uploaded to github. For the most recent updates please visit : https://github.com/dtbell99/JavaFXToolbar




FXML Code:
------------------


<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="364.0" prefWidth="727.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.broadlyapplicable.javafxexamples.toolbar.ToolbarExampleController">
   <children>
      <VBox prefHeight="577.0" prefWidth="727.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <children>
            <Pane>
               <children>
                  <Label prefHeight="24.0" prefWidth="356.0" text="Left Aligned Buttons (Default)">
                     <font>
                        <Font size="19.0" />
                     </font>
                     <padding>
                        <Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
                     </padding>
                  </Label>
               </children>
            </Pane>
             <ToolBar>
              <items>
                <Button mnemonicParsing="false" text="Left Button 1" />
                  <Button mnemonicParsing="false" text="Left Button 2" />
              </items>
            </ToolBar>
            <Pane>
               <children>
                  <Label prefHeight="24.0" prefWidth="356.0" text="Center Aligned Buttons">
                     <font>
                        <Font size="19.0" />
                     </font>
                     <padding>
                        <Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
                     </padding>
                  </Label>
               </children>
            </Pane>
            <ToolBar>
              <items>
                  <Pane HBox.hgrow="ALWAYS" />
                <Button mnemonicParsing="false" text="Center Button 1" />
                  <Button mnemonicParsing="false" text="Center Button 2" />
                  <Pane HBox.hgrow="ALWAYS" />
              </items>
            </ToolBar>
            <Pane>
               <children>
                  <Label prefHeight="24.0" prefWidth="356.0" text="Right Aligned Buttons">
                     <font>
                        <Font size="19.0" />
                     </font>
                     <padding>
                        <Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
                     </padding>
                  </Label>
               </children>
            </Pane>
            <ToolBar>
              <items>
                  <Pane HBox.hgrow="ALWAYS" />
                <Button mnemonicParsing="false" text="Right Button 1" />
                  <Button mnemonicParsing="false" text="Right Button 2" />
              </items>
            </ToolBar>
            <Pane>
               <children>
                  <Label prefHeight="24.0" prefWidth="356.0" text="Left Center Right Align Buttons">
                     <font>
                        <Font size="19.0" />
                     </font>
                     <padding>
                        <Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
                     </padding>
                  </Label>
               </children>
            </Pane>
            <ToolBar>
               <items>
                  <Button mnemonicParsing="false" text="Left Button 1" />
                  <Button mnemonicParsing="false" text="Left Button 2" />
                  <Pane HBox.hgrow="ALWAYS" />
                  <Button mnemonicParsing="false" text="Left Button 1" />
                  <Button mnemonicParsing="false" text="Left Button 2" />
                  <Pane HBox.hgrow="ALWAYS" />
                  <Button mnemonicParsing="false" text="Left Button 1" />
                  <Button mnemonicParsing="false" text="Left Button 2" />
               </items>
            </ToolBar>
         </children>
      </VBox>
   </children>
</AnchorPane>

Thursday, March 5, 2015

JavaFX Capture & Restore Splitpane Divider Position

Here is another simple code example on how to capture, store, and recover the divider position of a JavaFX splitpane. Implementing this approach allows your splitpane divider to be persisted when you close your application and restored as you left it when you closed the window.

Once the application is built and run you can drag the divider and see the current value of the position. Upon closing the program and restarting the divider should return to its last position.


Concepts: This example demonstrates the following:

1) How to access the PositionProperty field on the splitpane divider and add a listener to capture change events using a lambda function in Java 8.

2) How to use the javafx.application.Platform.runLater method to set the divider position when your application launches. (This technique is necessary due to how the application starts up and initializes)

3) How to store and retrieve simple application preferences using java.util.prefs.Preferences.


Requirements: Java SE 8







package com.broadlyapplicable.javafxexamples;

import java.net.URL;
import java.util.ResourceBundle;
import java.util.prefs.Preferences;
import javafx.beans.property.DoubleProperty;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;

public class FXMLDocumentController implements Initializable {
 
    private static final String SPLIT_PANE_DIVIDER = "SplitPaneDivider";
    private static final String NODE = "FXMLDocumentController";
 
    @FXML
    private SplitPane splitPane;
 
    @FXML
    private Label dividerLabel;
 
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        javafx.application.Platform.runLater(new Runnable() {
            @Override
            public void run() {
                Preferences pref = Preferences.userRoot().node(NODE);
                double splitPaneDivider = pref.getDouble(SPLIT_PANE_DIVIDER, .25);
                splitPane.setDividerPositions(splitPaneDivider);
            }
        });
     
        DoubleProperty dividerPositionProperty = splitPane.getDividers().get(0).positionProperty();
        dividerPositionProperty.addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
            dividerLabel.setText(newValue.toString());
            Preferences pref = Preferences.userRoot().node(NODE);
            pref.putDouble(SPLIT_PANE_DIVIDER, newValue.doubleValue());
        });
    }  
 
}




<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="427.0" prefWidth="570.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.broadlyapplicable.javafxexamples.FXMLDocumentController">
    <children>
      <VBox prefHeight="427.0" prefWidth="570.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <children>
            <SplitPane fx:id="splitPane" dividerPositions="0.33098591549295775">
              <items>
                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" style="-fx-background-color: #dddddd;" />
                <AnchorPane prefHeight="425.0" prefWidth="86.0" style="-fx-background-color: #aaaaaa;" />
              </items>
            </SplitPane>
            <Label fx:id="dividerLabel" alignment="CENTER" text="0.0">
               <font>
                  <Font size="31.0" />
               </font>
               <padding>
                  <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
               </padding>
            </Label>
         </children>
      </VBox>
    </children>
</AnchorPane>


Monday, February 23, 2015

JavaFX Restore Window Size & Position

So this evening I decided to figure out how to make my new JavaFX application remember the screen size and location so my wonderful users won't get mad at me when the app doesn't remember how they positioned it. I started to research how to do this in JavaFX and learned two things I did not know so I thought I'd share them with the world.

1) How to get the location and size of a JavaFX stage at the close of the application.
2) How to use java.util.prefs.Preferences to store simple key/value application settings.

package javafxexamples;

import java.io.IOException;
import java.util.ResourceBundle;
import java.util.prefs.Preferences;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

public class ViewSwitcher {

    private static final String WINDOW_POSITION_X = "Window_Position_X";
    private static final String WINDOW_POSITION_Y = "Window_Position_Y";
    private static final String WINDOW_WIDTH = "Window_Width";
    private static final String WINDOW_HEIGHT = "Window_Height";
    private static final double DEFAULT_X = 10;
    private static final double DEFAULT_Y = 10;
    private static final double DEFAULT_WIDTH = 800;
    private static final double DEFAULT_HEIGHT = 600;
    private static final String NODE_NAME = "ViewSwitcher";
    private static final String BUNDLE = "Bundle";

    public void switchView(String fxmlView, Stage stage, String title) throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource(fxmlView),
            ResourceBundle.getBundle(BUNDLE));
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.setTitle(title);
        stage.show();

     
        // Pull the saved preferences and set the stage size and start location
     
        Preferences pref = Preferences.userRoot().node(NODE_NAME);
        double x = pref.getDouble(WINDOW_POSITION_X, DEFAULT_X);
        double y = pref.getDouble(WINDOW_POSITION_Y, DEFAULT_Y);
        double width = pref.getDouble(WINDOW_WIDTH, DEFAULT_WIDTH);
        double height = pref.getDouble(WINDOW_HEIGHT, DEFAULT_HEIGHT);
        stage.setX(x);
        stage.setY(y);
        stage.setWidth(width);
        stage.setHeight(height);
     
     
        // When the stage closes store the current size and window location.
     
        stage.setOnCloseRequest((final WindowEvent event) -> {
            Preferences preferences = Preferences.userRoot().node(NODE_NAME);
            preferences.putDouble(WINDOW_POSITION_X, stage.getX());
            preferences.putDouble(WINDOW_POSITION_Y, stage.getY());
            preferences.putDouble(WINDOW_WIDTH, stage.getWidth());
            preferences.putDouble(WINDOW_HEIGHT, stage.getHeight());
        });
    }
}