Planet JFX

JFXPresentation is a facility that lets you easily create presentations. Here is a screenshot. The code has some HTML tags in it, so it renders oddly in this WIKI, but you can get the code by pressing the edit tab above.

Screenshot of JFXPresentation Program

Here is the source code. Simply edit and add slides to your presentation in the JFXPresentationModel class (look for the "//-------------------- This is where your presentation data goes --------------" comment).

Code[]


/*
 *  JFXPresentationMain.fx - A presentation facility that displays slides
 *                           placed in the JFXPresentationModel.fx file.
 *                           It serves as an example of several JavaFX concepts
 *                           and classes, including the BookPanel widget.
 *
 *  Developed 2007 by James L. Weaver (jim.weaver at lat-inc dot com)
 *  to serve as a JavaFX Script example.
 */

import javafx.ui.*;
import javafx.ui.canvas.*;
import java.awt.Rectangle;
//import edu.stanford.ejalbert.BrowserLauncher;

/**
 *  An image with an optional link 
 */
class ImageWithLink extends Image {
  attribute link:String?;
}

/**
 *  A bulleted item
 */
class Bullet {
  attribute text:String?;
  attribute link:String?;
  attribute code:String?;
  attribute image:ImageWithLink?;
  attribute bullets:Bullet*;
}


/**
 *  Used to create a table row for a table in a slide
 */
class TableEntry {
  attribute colData:String*;
}

/**
 *  Used to create a table in a slide
 */
class PresTable {
  attribute title:String;
  attribute header:TableEntry*;
  attribute entries:TableEntry*;
}


/**
 *  Represents a slide in a presentation, and contains code
 *  to render any html content in a slide.
 */
class Slide extends BorderPanel {
  attribute title:String;
  attribute bullets:Bullet*;

  // For tables in the presentation
  attribute table:PresTable*;
  attribute tableEntries:TableEntry*;

  attribute model:JFXPresentationModel;
  private attribute label:Label;
}

trigger on new Slide {
  label = new Label{};
  center = label;
  opaque = true;
  background = white;
}

trigger on Slide.model = model {
  border = 
    TitledBorder {
      title: title
    };
    
  label.text = 
    "<html>
       <h1 align = 'left'>{title}</h1>
       <font size = {model.titleFontSize}>
       <b>
       {if sizeof bullets <> 0
        then "<ul>"
        else ""}
       {
         foreach (bul in bullets)
           "<p><li>{if bul.link <> null 
                    then "<a href={bul.link}>{bul.text}</a>"
                    else "<font size = {model.bulletFontSize}>{bul.text}</font>"}
              {if sizeof bul.bullets > 0
               then "<ul>
                     {
                       foreach (b in bul.bullets)
                         "<p><li>{if b.link <> null 
                                  // TODO: Find out why this doesn't work (the operation gets a "not found: object:99999999"
                                  //then "<a href='{#(operation(){model.browserLauncher.openURLinBrowser(b.link);})}'>{b.text}</a>"
                                  then "<a href='{b.link})}'>{b.text}</a>"
                                  else "<font size = {model.bulletFontSize}>{b.text}</font>"}
                                 {if b.image <> null 
                                  then 
                                    if b.image.link <> null
                                    then "<a href={b.image.link}><p><img src={b.image.url}></img></a>"
                                    else "<p><img src={b.image.url}></img>"
                                  else ""}
                                 {if b.code <> null then "<font size={model.codeFontSize}><pre>{b.code}</pre></font>" else ""}
                              </li>"}
                     </ul>"
               else ""
              }
              {if bul.image <> null 
               then 
                 if bul.image.link <> null
                 then "<a href={bul.image.link}><p><img src={bul.image.url}></img></a>"
                 else "<p><img src={bul.image.url}></img>"
               else ""}
              {if bul.code <> null then "<font size={model.codeFontSize}><pre>{bul.code}</pre></font>" else ""}
            </li>"
       }
       {
         foreach (tab in table)
           "<h2 align='center'>{tab.title}</h2>
            <table border='0' cellspacing='2' cellpadding='5'>
            <font size={model.tableFontSize}>
              <tr bgcolor='#cccccc'>
                {
                  foreach (headData in tab.header.colData)
                    "<td><b>{headData}</b></td>"
                }
              </tr>
              {
                foreach (row in tab.entries)
                  "<tr bgcolor='#ccffff'>
                    {
                      foreach (data in row.colData)
                        "<td align='left'>{data}</td>"
                    }
                 </tr>"
              }
            </font>
            </table>"
       }
       {if sizeof bullets <> 0
        then "</ul>"
        else ""}
       </b>
       </font>
     </html>";
}

/**
 *  The model behind the JFXPresentationEngine 
 *  program.  This is where to put the content of your
 *  slides.  This content can be bulleted items with
 *  optional links, images, etc.  It can also be tables
 *  of information.  Slides can also
 *  contain any sublclass of Widget, as Slide is a
 *  subclass of BorderPanel.
 *  Note: Unless you use some sort of browser launcher
 *  (see the commented out BrowserLauncher import) then
 *  links won't actually open a browser.  If you do want
 *  this functionality, you'll have to modify the Slide
 *  class to render the correct JavaFX Script syntax for
 *  a hyperlink in a Label.
 */

class JFXPresentationModel {
  attribute title:String;
  attribute pages:Widget*;
  attribute links:String*;
  attribute selectedLink:Integer;
  attribute selectedPage:Integer;
//attribute browserLauncher:BrowserLauncher;
  attribute titleFontSize:String;
  attribute bulletFontSize:String;
  attribute codeFontSize:String;
  attribute tableFontSize:String;
  
  attribute defaultBookPageBounds:Rectangle;
}

attribute JFXPresentationModel.selectedPage = 0;
//attribute JFXPresentationModel.browserLauncher = new BrowserLauncher();
attribute JFXPresentationModel.titleFontSize = "'+1'";
attribute JFXPresentationModel.bulletFontSize = "'+1'";
attribute JFXPresentationModel.codeFontSize = "'-5'";
attribute JFXPresentationModel.defaultBookPageBounds = {x: 10, y: 10, width: 500, height: 650};
attribute JFXPresentationModel.tableFontSize = "'+2'";

trigger on new JFXPresentationModel {
//-------------------- This is where your presentation data goes --------------
  title = "Replace with Your Presentation Title";
  pages = [

    Slide {
      title: "Replace with the Title of this Slide"
      bullets: [
        {text: "A bullet:"},
        {text: "Another bullet:"},
        {text: "Yet another bullet:"}
      ]
      model: this
    },

    Slide {
      title: "Bullets may have sub-bullets"
      bullets: [
        {text: "A top-level bullet:"
          bullets: [
            {text: "A sub-bullet"},
            {text: "Another sub-bullet"}
          ]
        },
        {text: "Another top-level bullet:"}
      ]
      model: this
    },

    Slide {
      title: "Example of putting source code in a slide"
      bullets: [
        {text: "The Source Code:"
         code: 
"import javafx.ui.*;
import javafx.ui.canvas.*;

Frame \{
 title: \"Sample code snipppet\"
 height: 100
 width: 400
 content: ...
}
"
        }
      ]
      model: this
    },

    Slide {
      title: "Images and Text Formatting on Slides"
      bullets: [
        {text: "Bullets can contain HTML formatting like <i>italics</i>"},
        {text: "A bullet with an image"
          image:
            ImageWithLink {
              url: "http://jmentor.com/JavaFX/images/lat_logo.jpg"
            }
        },
        {text: "A bullet with sub-bullets"
          bullets: [
            {text: "Sub-bullet"},
            {text: "Sub-bullets can contain images as well"
              image:
                ImageWithLink {
                  url: "http://jmentor.com/JavaFX/images/super_duck_trans.gif"
                }
            }
          ]
        }
      ]
      model: this
    },

    Slide {
      title: "Example of putting source code in a slide"
      bullets: [
        {text: "The Source Code:"
         code: 
"import javafx.ui.*;
import javafx.ui.canvas.*;

Frame \{
 title: \"Sample code snipppet\"
 height: 100
 width: 400
 content: ...
}
"
        }
      ]
      model: this
    },

    Slide {
      var: self
      title: "Sample Table"
      table: 
        PresTable {
          header: 
            TableEntry {
              colData: [
                "Replace with a Heading",
                "Another Heading",
                "Yet Another Heading"
              ]
            }
          entries: [
            TableEntry {
              colData: [
                "Row 1 data",
                "More row 1 data",
                "Some more row 1 data"
              ]
            },
            TableEntry {
              colData: [
                "Row 1 data",
                "More row 1 data",
                "Some more row 1 data"

              ]
            }
          ]
        }
      model: this
    },

    Slide {
      title: "Example Putting a Widget (in this case a Canvas) on a Slide"
      center: 
        Canvas {
          content:
            Circle {
              cx: 200
              cy: 200
              radius: 100
              stroke: red
              fill: yellow
            }
        }
      model: this
    },

    Slide {
      title: "For Questions or Feature Enhancements, Please Email:"
      bullets: [
        {text: "James L. (Jim) Weaver"},
        {text: "jim.weaver@lat-inc.com"
          image:
            ImageWithLink {
              url: "http://jmentor.com/JavaFX/images/lat_logo.jpg"
            }
        },
      ]
      model: this
    }

  ];
}

//----------------------- End of presentation data  ---------------------

/**
 * The main script for JFXPresentationMain.fx 
 */
 
var presModel = 
  JFXPresentationModel {};
var bookPanel =
  BookPanel {
    pages: presModel.pages
    pageBounds: bind presModel.defaultBookPageBounds
  };
  
var nextButton:Button;
var prevButton:Button;

prevButton = 
  Button {
    icon: 
      Image {
        url: "http://jmentor.com/JavaFX/images/left.gif"
      }
    enabled: bind bookPanel.leftPageIndex > 0
    action:
      operation() {
        bookPanel.previousPage();
      }
  };
nextButton = 
  Button {
    icon: 
      Image {
        url: "http://jmentor.com/JavaFX/images/right.gif"
      }
    enabled: bind bookPanel.leftPageIndex < sizeof presModel.pages - 2
    action:
      operation() {
        bookPanel.nextPage();
      }
  };

Frame {
  title: bind presModel.title
  visible: true
  content:
    BorderPanel {
      bottom:
        FlowPanel {
          alignment: CENTER
          content:
            ToolBar {
              buttons: [
                Button {
                  border:
                    BevelBorder {}
                  text: "Expand left page"
                  action:
                    operation() {
                      Dialog {
                        var:self
                        modal: true
                        visible: true
                        width: 1000
                        height: 700
                        content:
                          BorderPanel {
                            center:
                              ScrollPane {
                                horizontalScrollBarPolicy: AS_NEEDED
                                view: bookPanel.pages[bookPanel.leftPageIndex]
                              }
                          }
                      }
                    }
                },
                prevButton,
                ComboBox {
                  selection: bind bookPanel.leftPageIndex
                  cells: bind
                    foreach (page in bookPanel.pages)
                      ComboBoxCell {
                        text: "{indexof page} - {((Slide)page).title}" 
                      }
                  action:
                    operation() {
                      bookPanel.visible = false;
                      bookPanel.visible = true; 
                    }
                },
                nextButton,
                Button {
                  border:
                    BevelBorder {}
                  text: "Expand right page"
                  action:
                    operation() {
                      Dialog {
                        var: self
                        modal: true
                        visible: true
                        width: 1000
                        height: 700
                        content:
                          BorderPanel {
                            center:
                              ScrollPane {
                                horizontalScrollBarPolicy: AS_NEEDED
                                view: bookPanel.pages[bookPanel.leftPageIndex + 1]
                              }
                          }
                      }
                    }
                }
              ]
            }
        }
      center: bookPanel
    }
  onOpen: 
    operation() {
      bookPanel.leftPageIndex = 0;
    }
};