Commits

shemnon  committed 337088a

move config options to the menu bar

  • Participants
  • Parent commits b6869ce

Comments (0)

Files changed (11)

File flowdown-app/build.gradle

 javafx {
     mainClass = "FlowDown.Main"
     appName = "FlowDown"
-    appId = "com.bitbucket.shemnon.FlowDown"
+    appID = "com.bitbucket.shemnon.FlowDown"
 
 }

File flowdown-app/src/main/java/FlowDown/FLowDownModel.java

 package FlowDown;
 
 import javafx.beans.property.*;
+import org.pegdown.Extensions;
 
 import java.io.File;
 
 
     BooleanProperty dirty = new SimpleBooleanProperty(false);
 
+    ListProperty<String> cssURLs = new SimpleListProperty<>();
+
+    DoubleProperty splitpanePosition = new SimpleDoubleProperty(0.5);
+
+    // pegdown options
+
+    BooleanProperty optionHardLineWraps = new SimpleBooleanProperty(false);
+    BooleanProperty optionAutoLinks = new SimpleBooleanProperty(false);
+    BooleanProperty optionWikiLinks = new SimpleBooleanProperty(false);
+    BooleanProperty optionSmartDashesAndDots = new SimpleBooleanProperty(false);
+    BooleanProperty optionSmartQuotes = new SimpleBooleanProperty(false);
+    BooleanProperty optionAbbreviations = new SimpleBooleanProperty(false);
+    BooleanProperty optionDefinitions = new SimpleBooleanProperty(false);
+    BooleanProperty optionFencedCodeBlocks = new SimpleBooleanProperty(false);
+    BooleanProperty optionTables = new SimpleBooleanProperty(false);
+
+    public int getParserFlags() {
+        int flags = 0;
+        if (optionAbbreviations.get()) flags |= Extensions.ABBREVIATIONS;
+        if (optionAutoLinks.get()) flags |= Extensions.AUTOLINKS;
+        if (optionDefinitions.get()) flags |= Extensions.DEFINITIONS;
+        if (optionFencedCodeBlocks.get()) flags |= Extensions.DEFINITIONS;
+        if (optionHardLineWraps.get()) flags |= Extensions.HARDWRAPS;
+        if (optionSmartQuotes.get()) flags |= Extensions.QUOTES;
+        if (optionSmartDashesAndDots.get()) flags |= Extensions.SMARTS;
+        if (optionTables.get()) flags |= Extensions.TABLES;
+        if (optionWikiLinks.get()) flags |= Extensions.WIKILINKS;
+
+        return flags;
+    }
+
 }

File flowdown-app/src/main/java/FlowDown/FlowDownController.java

 import javafx.event.ActionEvent;
 import javafx.stage.FileChooser;
 import javafx.stage.WindowEvent;
+import org.bitbucket.shemnon.mdnode.MarkdownToNodeGenerator;
 
 import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URL;
 
 /**
  * Created with IntelliJ IDEA.
     }
 
     public void refreshCSS(ActionEvent e) {
+        if (view != null) {
+            String newStylesheet = model.cssFile.get();
+            String result = resolveStylesheet(newStylesheet);
+            view.setMarkDownStylesheets(result);
+        }
+    }
 
+    public void updateConfig(ActionEvent e) {
+        view.setParserFlags(model.getParserFlags());
     }
 
-    public void showSourceOnly(ActionEvent e) {
+    private String resolveStylesheet(String newStylesheet) {
+        String result = null;
+
+        try {
+            // first try as a URL
+            result = new URL(newStylesheet).toExternalForm();
+        } catch (MalformedURLException ignore) {
+        }
 
+        if (result == null) {
+            // next try as a file
+            File f = new File(newStylesheet);
+            if (f.exists() && f.isFile()) {
+                result = f.toURI().toString();
+            }
+        }
+
+        if (result == null) {
+            // next resolve against our classpath
+            try {
+                result = FlowDownView.class.getResource(newStylesheet).toExternalForm();
+            } catch (NullPointerException ignore) {
+            }
+        }
+
+        if (result == null) {
+            // finally resolve against the library classpath
+            try {
+                result = MarkdownToNodeGenerator.class.getResource(newStylesheet).toExternalForm();
+            } catch (NullPointerException ignore) {
+            }
+        }
+        return result;
     }
 
-    public void showSourceAndResult(ActionEvent e) {
 
+    public void showSourceOnly(ActionEvent e) {
+         model.splitpanePosition.set(1.0);
     }
 
-    public void showResultOnly(ActionEvent e) {
+    public void showSourceAndResult(ActionEvent e) {
+        model.splitpanePosition.set(0.5);
+    }
 
+    public void showResultOnly(ActionEvent e) {
+        model.splitpanePosition.set(0.0);
     }
 
     /**

File flowdown-app/src/main/java/FlowDown/FlowDownView.java

  */
 package FlowDown;
 
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ResourceBundle;
-
-import javafx.stage.Window;
-import org.bitbucket.shemnon.mdnode.MarkdownNode;
-import org.bitbucket.shemnon.mdnode.MarkdownToNodeGenerator;
-import com.sun.javafx.Utils;
-import javafx.event.ActionEvent;
-import javafx.event.Event;
 import javafx.fxml.FXML;
 import javafx.fxml.Initializable;
-import javafx.geometry.HPos;
-import javafx.geometry.Point2D;
-import javafx.geometry.Side;
-import javafx.geometry.VPos;
-import javafx.scene.Node;
-import javafx.scene.Parent;
 import javafx.scene.control.*;
 import javafx.scene.layout.HBox;
 import javafx.scene.layout.Pane;
 import javafx.scene.layout.Priority;
-import javafx.stage.Popup;
-import org.pegdown.Extensions;
+import javafx.stage.Window;
+import org.bitbucket.shemnon.mdnode.MarkdownNode;
+import org.bitbucket.shemnon.mdnode.MarkdownToNodeGenerator;
+
+import java.net.URL;
+import java.util.ResourceBundle;
 
 
 public class FlowDownView
     implements Initializable {
 
     MarkdownNode mdNode;
-    private String stylesheet = resolveStylesheet(MarkdownToNodeGenerator.STYLESHEET_DEFAULT);
-
-    @FXML
-    private ScrollPane contentScrollPane;
-
-    @FXML
-    private CheckBox cbAbbreviations;
-
-    @FXML
-    private CheckBox cbAutoLinks;
-
-    @FXML
-    private CheckBox cbDefinisitons;
-
-    @FXML
-    private CheckBox cbFencedCodeBlocks;
 
     @FXML
-    private CheckBox cbHardWraps;
+    ScrollPane contentScrollPane;
 
     @FXML
-    private CheckBox cbQuotes;
+    SplitPane contentSplitPane;
 
     @FXML
-    private CheckBox cbSmarts;
+    CheckMenuItem micbOptionAutoLinks;
 
     @FXML
-    private CheckBox cbTables;
+    CheckMenuItem micbOptionHardLineWraps;
 
     @FXML
-    private CheckBox cbWikilinks;
+    CheckMenuItem micbOptionSmartDashesAndDots;
 
     @FXML
-    private Button configButton;
+    CheckMenuItem micbOptionSmartQuotes;
 
     @FXML
-    private Parent configGroup;
-    Popup configPopup = new Popup();
+    CheckMenuItem micbOptionWikiLinks;
 
     @FXML
     private Button refreshButton;
 
     @FXML
-    TextArea sourceTextArea;
+   TextArea sourceTextArea;
 
     @FXML
-    private ComboBox<String> styleCombo;
+    ComboBox<String> styleCombo;
 
     @FXML
     private Pane toolbarSpacer;
 
 
-    public void doConfig(ActionEvent event) {
-        show(configPopup, configButton, Side.BOTTOM, configButton.getWidth()/2 - 40, 0);
-    }
-
-    public void doReloadCSS(ActionEvent event) {
-        String newStylesheet = styleCombo.getValue();
-        String result = resolveStylesheet(newStylesheet);
-
-        if (result == null) {
-            System.out.println("Could not resolve '" + newStylesheet + "'");
-        } else if (contentScrollPane.getContent() instanceof Parent) {
-            // Sometimes it is fired before content is set, so guard against it
-            stylesheet = result;
-            ((Parent)contentScrollPane.getContent()).getStylesheets().setAll(stylesheet);
-        }
-    }
-
-
-    public void onChangeParserOptions(ActionEvent event) {
-        int flags = 0;
-        if (cbAbbreviations.isSelected()) flags |= Extensions.ABBREVIATIONS;
-        if (cbAutoLinks.isSelected()) flags |= Extensions.AUTOLINKS;
-        if (cbDefinisitons.isSelected()) flags |= Extensions.DEFINITIONS;
-        if (cbFencedCodeBlocks.isSelected()) flags |= Extensions.DEFINITIONS;
-        if (cbHardWraps.isSelected()) flags |= Extensions.HARDWRAPS;
-        if (cbQuotes.isSelected()) flags |= Extensions.QUOTES;
-        if (cbSmarts.isSelected()) flags |= Extensions.SMARTS;
-        if (cbTables.isSelected()) flags |= Extensions.TABLES;
-        if (cbWikilinks.isSelected()) flags |= Extensions.WIKILINKS;
-
+    public void setParserFlags(int flags) {
         mdNode.setParserFlags(flags);
-        mdNode.setValue(sourceTextArea.getText());
     }
 
     @Override
         mdNode.setValue(sourceTextArea.getText());
         contentScrollPane.setContent(mdNode);
 
-        if (configGroup != null) {
-            configPopup.getContent().setAll(configGroup);
-            configPopup.setAutoFix(true);
-            configPopup.setAutoHide(true);
-
-        }
-
         HBox.setHgrow(toolbarSpacer, Priority.ALWAYS);
     }
 
-    private String resolveStylesheet(String newStylesheet) {
-        String result = null;
-
-        try {
-            // first try as a URL
-            result = new URL(newStylesheet).toExternalForm();
-        } catch (MalformedURLException ignore) {
-        }
-
-        if (result == null) {
-            // next try as a file
-            File f = new File(newStylesheet);
-            if (f.exists() && f.isFile()) {
-                result = f.toURI().toString();
-            }
-        }
-
-        if (result == null) {
-            // next resolve against our classpath
-            try {
-                result = FlowDownView.class.getResource(newStylesheet).toExternalForm();
-            } catch (NullPointerException ignore) {
-            }
-        }
-
-        if (result == null) {
-            // finally resolve against the library classpath
-            try {
-                result = MarkdownToNodeGenerator.class.getResource(newStylesheet).toExternalForm();
-            } catch (NullPointerException ignore) {
-            }
-        }
-        return result;
-    }
 
     private void updateMarkdown(String newString) {
         mdNode.setValue(newString);
     }
 
-    // ripped from PopupControl
-    public void show(Popup popup, Node anchor, Side side, double dx, double dy) {
-        if (anchor == null) return;
-        Event.fireEvent(popup, new Event(Menu.ON_SHOWING));
-        if (popup.getScene().getRoot() == null) return;
-
-        HPos hpos = side == Side.LEFT ? HPos.LEFT : side == Side.RIGHT ? HPos.RIGHT : HPos.CENTER;
-        VPos vpos = side == Side.TOP ? VPos.TOP : side == Side.BOTTOM ? VPos.BOTTOM : VPos.CENTER;
-
-        // translate from anchor/hpos/vpos/dx/dy into screenX/screenY
-        Point2D point = Utils.pointRelativeTo(anchor,
-                popup.getWidth(), popup.getHeight(),
-                hpos, vpos, dx, dy, true);
-        popup.show(anchor, point.getX(), point.getY());
-    }
-
     public Window getWindow() {
         return contentScrollPane.getScene().getWindow();
     }
 
+
+    public void setMarkDownStylesheets(String... stylesheets) {
+       contentScrollPane.getStylesheets().setAll(stylesheets);
+    }
 }
 

File flowdown-app/src/main/java/FlowDown/Main.java

 package FlowDown;
 
 import javafx.application.Application;
+import javafx.collections.ListChangeListener;
 import javafx.collections.ObservableMap;
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
         namespace.put("onShowSourceOnly", (EventHandler<ActionEvent>) controller::showSourceOnly);
         namespace.put("onShowSourceAndResult", (EventHandler<ActionEvent>) controller::showSourceAndResult);
         namespace.put("onShowResultOnly", (EventHandler<ActionEvent>) controller::showResultOnly);
+        namespace.put("onUpdateConfig", (EventHandler<ActionEvent>) controller::updateConfig);
 
 
         loader.load();
         controller.view = view;
 
         model.content.bindBidirectional(view.sourceTextArea.textProperty());
+        model.cssURLs.addListener((ListChangeListener<String>) change -> {
+            if (view.contentScrollPane.getContent() instanceof Parent) {
+                // Sometimes it is fired before content is set, so guard against it
+                ((Parent)view.contentScrollPane.getContent()).getStylesheets().setAll(change.getList());
+            }
+        });
+        model.cssFile.bind(view.styleCombo.getSelectionModel().selectedItemProperty());
+
+
+        model.splitpanePosition.addListener((observableValue, oldNumber, newNumber) ->
+                view.contentSplitPane.setDividerPosition(0, newNumber.doubleValue()));
 
         Parent p = loader.getRoot();
 
-//        loader = new FXMLLoader(Main.class.getResource("ConfigPopup.fxml"));
-//        loader.setController(controller.view);
-//        loader.load();
+        model.optionAutoLinks.bindBidirectional(view.micbOptionAutoLinks.selectedProperty());
+        model.optionHardLineWraps.bindBidirectional(view.micbOptionHardLineWraps.selectedProperty());
+        model.optionSmartDashesAndDots.bindBidirectional(view.micbOptionSmartDashesAndDots.selectedProperty());
+        model.optionSmartQuotes.bindBidirectional(view.micbOptionSmartQuotes.selectedProperty());
+        model.optionWikiLinks.bindBidirectional(view.micbOptionWikiLinks.selectedProperty());
+
 
         Scene scene = new Scene(p);
 

File flowdown-app/src/main/resources/FlowDown/ConfigPopup.fxml

-<?xml version="1.0" encoding="UTF-8"?>
-
-<?import java.lang.*?>
-<?import java.util.*?>
-<?import javafx.geometry.*?>
-<?import javafx.scene.*?>
-<?import javafx.scene.control.*?>
-<?import javafx.scene.effect.*?>
-<?import javafx.scene.layout.*?>
-<?import javafx.scene.paint.*?>
-<?import javafx.scene.shape.*?>
-
-<AnchorPane fx:id="configGroup" visible="true" xmlns:fx="http://javafx.com/fxml">
-  <children>
-    <Polygon fill="SILVER" layoutX="40.0" layoutY="0.0" scaleX="1.0" scaleY="1.0" stroke="$null" strokeType="INSIDE">
-      <points>
-        <Double fx:value="-14.0" />
-        <Double fx:value="15.0" />
-        <Double fx:value="14.0" />
-        <Double fx:value="15.0" />
-        <Double fx:value="0.0" />
-        <Double fx:value="-0.0" />
-      </points>
-    </Polygon>
-    <HBox id="HBox" alignment="CENTER" layoutX="0.0" layoutY="13.0" prefHeight="-1.0" prefWidth="-1.0" spacing="20.0" style="-fx-background-color: silver;&#10;-fx-background-radius:6;&#10;">
-      <children>
-        <VBox prefHeight="-1.0" prefWidth="-1.0">
-          <children>
-            <VBox id="VBox" alignment="TOP_LEFT" prefHeight="-1.0" prefWidth="-1.0" spacing="5.0">
-              <children>
-                <Label text="Github Extensions" />
-                <CheckBox fx:id="cbHardWraps" mnemonicParsing="false" onAction="#onChangeParserOptions" text="Hard Line Wrap" />
-                <CheckBox fx:id="cbAutoLinks" mnemonicParsing="false" onAction="#onChangeParserOptions" text="Auto Links" />
-                <CheckBox fx:id="cbWikilinks" mnemonicParsing="false" onAction="#onChangeParserOptions" text="Wikilinks" />
-              </children>
-              <padding>
-                <Insets bottom="5.0" fx:id="x1" />
-              </padding>
-            </VBox>
-            <VBox id="VBox" alignment="TOP_LEFT" padding="$x1" prefHeight="-1.0" prefWidth="-1.0" spacing="5.0">
-              <children>
-                <Label text="Smarts" />
-                <CheckBox fx:id="cbSmarts" mnemonicParsing="false" onAction="#onChangeParserOptions" text="Dashes and Dots" />
-                <CheckBox fx:id="cbQuotes" mnemonicParsing="false" onAction="#onChangeParserOptions" text="Quotes" />
-              </children>
-            </VBox>
-          </children>
-        </VBox>
-        <VBox fillWidth="true" prefHeight="-1.0" prefWidth="-1.0" visible="true">
-          <children>
-            <VBox id="VBox" alignment="TOP_LEFT" padding="$x1" prefHeight="-1.0" prefWidth="-1.0" spacing="5.0" visible="true">
-              <children>
-                <Label text="PHP Extensions" />
-                <CheckBox fx:id="cbAbbreviations" disable="true" mnemonicParsing="false" onAction="#onChangeParserOptions" text="Abbreviations" />
-                <CheckBox fx:id="cbDefinisitons" allowIndeterminate="false" disable="true" indeterminate="false" mnemonicParsing="false" onAction="#onChangeParserOptions" text="Definitions" />
-                <CheckBox fx:id="cbFencedCodeBlocks" disable="true" mnemonicParsing="false" onAction="#onChangeParserOptions" text="Fenced Code Blocks" />
-              </children>
-            </VBox>
-            <VBox id="VBox" alignment="TOP_LEFT" padding="$x1" prefHeight="-1.0" prefWidth="-1.0" spacing="5.0">
-              <children>
-                <Label text="Multimarkdown" />
-                <CheckBox fx:id="cbTables" disable="true" mnemonicParsing="false" onAction="#onChangeParserOptions" text="Tables" />
-              </children>
-            </VBox>
-          </children>
-        </VBox>
-      </children>
-      <padding>
-        <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
-      </padding>
-    </HBox>
-  </children>
-  <effect>
-    <DropShadow height="43.0" offsetX="5.0" offsetY="5.0" radius="21.0" width="43.0">
-      <input>
-        <InnerShadow color="WHITE" />
-      </input>
-    </DropShadow>
-  </effect>
-</AnchorPane>

File flowdown-app/src/main/resources/FlowDown/FlowDownView.fxml

 <?import javafx.scene.shape.*?>
 <?import javafx.scene.text.*?>
 
-<VBox id="VBox" alignment="CENTER" prefHeight="500.0" prefWidth="700.0" spacing="0.0" xmlns:fx="http://javafx.com/fxml" fx:controller="FlowDown.FlowDownView">
+<VBox id="VBox" alignment="CENTER" prefHeight="500.0" prefWidth="800.0" spacing="0.0" xmlns:fx="http://javafx.com/fxml" fx:controller="FlowDown.FlowDownView">
   <children>
     <MenuBar useSystemMenuBar="true" VBox.vgrow="NEVER">
       <menus>
             <MenuItem mnemonicParsing="true" onAction="$onQuit" text="_Quit" />
           </items>
         </Menu>
-        <Menu mnemonicParsing="false" text="Edit">
+        <Menu mnemonicParsing="false" text="View">
           <items>
-            <MenuItem mnemonicParsing="false" text="Delete" />
+            <MenuItem mnemonicParsing="false" onAction="$onShowSourceOnly" text="Show Source Only" />
+            <MenuItem mnemonicParsing="false" onAction="$onShowResultOnly" text="Show Content Only" />
+            <MenuItem mnemonicParsing="false" onAction="$onShowSourceAndResult" text="Show Source and Content" />
           </items>
         </Menu>
-        <Menu mnemonicParsing="false" text="Help">
+        <Menu mnemonicParsing="false" text="Options">
           <items>
-            <MenuItem mnemonicParsing="false" text="About" />
+            <CheckMenuItem mnemonicParsing="false" onAction="$onUpdateConfig" text="Hard Line Wraps" fx:id="micbOptionHardLineWraps" />
+            <CheckMenuItem mnemonicParsing="false" onAction="$onUpdateConfig" text="Auto Links" fx:id="micbOptionAutoLinks" />
+            <CheckMenuItem mnemonicParsing="false" onAction="$onUpdateConfig" text="WikiLinks" fx:id="micbOptionWikiLinks" />
+            <SeparatorMenuItem mnemonicParsing="false" />
+            <CheckMenuItem mnemonicParsing="false" onAction="$onUpdateConfig" text="Smart Dashes and Dots" fx:id="micbOptionSmartDashesAndDots" />
+            <CheckMenuItem mnemonicParsing="false" onAction="$onUpdateConfig" text="Smart Quotes" fx:id="micbOptionSmartQuotes" />
           </items>
         </Menu>
       </menus>
     </MenuBar>
     <ToolBar orientation="HORIZONTAL" VBox.vgrow="NEVER">
       <items>
-        <Pane fx:id="toolbarSpacer" prefHeight="0.0" prefWidth="0.0" />
-        <Button fx:id="configButton" alignment="CENTER" contentDisplay="GRAPHIC_ONLY" graphicTextGap="4.0" maxHeight="-1.0" minHeight="-1.0" mnemonicParsing="false" onAction="#doConfig" prefHeight="-1.0" scaleX="1.0" scaleY="1.0" text="">
-          <graphic>
-            <ImageView id="emblem-system" fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" scaleX="1.0" scaleY="1.0">
-              <image>
-                <Image url="@preferences-system.png" preserveRatio="true" smooth="true" />
-              </image>
-            </ImageView>
-          </graphic>
-        </Button>
-        <Label alignment="BASELINE_RIGHT" text="Stylesheet:" />
-        <ComboBox fx:id="styleCombo" editable="true" onAction="#doReloadCSS" prefHeight="-1.0" prefWidth="150.0" promptText="FlowDown.css">
+        <Pane fx:id="toolbarSpacer" prefHeight="0.0" prefWidth="-1.0" />
+        <Label alignment="BASELINE_RIGHT" minHeight="-Infinity" minWidth="-Infinity" text="Stylesheet:" />
+        <ComboBox fx:id="styleCombo" editable="true" minHeight="-Infinity" minWidth="-Infinity" onAction="$onRefreshCSS" prefHeight="-1.0" prefWidth="150.0" promptText="FlowDown.css">
           <items>
             <FXCollections fx:factory="observableArrayList">
               <String fx:value="Item 1" />
             </FXCollections>
           </items>
         </ComboBox>
-        <Button fx:id="refreshButton" mnemonicParsing="false" onAction="#doReloadCSS" text="Reload CSS" />
+        <Button fx:id="refreshButton" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="$onRefreshCSS" text="Reload CSS" />
       </items>
     </ToolBar>
-    <SplitPane dividerPositions="0.5" focusTraversable="true" orientation="HORIZONTAL" prefHeight="513.0" prefWidth="600.0" VBox.vgrow="ALWAYS">
+    <SplitPane id="contentSlider" fx:id="contentSplitPane" dividerPositions="0.5" focusTraversable="true" orientation="HORIZONTAL" prefHeight="445.0" prefWidth="800.0" VBox.vgrow="ALWAYS">
       <items>
-        <TextArea fx:id="sourceTextArea" minHeight="20.0" minWidth="20.0" prefWidth="-1.0" text="A First Level Header&#10;====================&#10;&#10;A Second Level Header&#10;--------------------&#10;&#10;Now is the time for all good men to come to&#10;the aid of their country. This is just a&#10;regular paragraph.&#10;&#10;The quick brown fox jumped over the lazy&#10;dog's back.&#10;&#10;### Header 3&#10;&#10;&gt; This is a blockquote.&#10;&gt;&#10;&gt; This is the second paragraph in the blockquote.&#10;&gt;&#10;&gt; ## This is an H2 in a blockquote&#10;&#10;Some of these words *are emphasized*.&#10;Some of these words _are emphasized also_.&#10;&#10;Use two asterisks for **strong emphasis**.&#10;Or, if you prefer, __use two underscores instead__.&#10;&#10;star&#10;&#10;*   Candy.&#10;*   Gum&#10;*   Booze.&#10;&#10;plus&#10;&#10;+   Candy.&#10;+   Gum.&#10;+   Booze.&#10;&#10;minus&#10;&#10;-   Candy.&#10;-   Gum.&#10;-   Booze.&#10;&#10;number&#10;&#10;1.  Red&#10;2.  Green&#10;3.  Blue&#10;&#10;&#10;*   A list item.&#10;&#10;    With multiple paragraphs.&#10;&#10;*   Another item in the list.&#10;&#10;&#10;&#10;This is an [example link](http://example.com/).&#10;&#10;&#10;This is an [example link](http://example.com/ &quot;With a Title&quot;).&#10;&#10;&#10;I get 10 times more traffic from [Google][1] than from&#10;[Yahoo][2] or [MSN][3].&#10;&#10;[1]: http://google.com/        &quot;Google&quot;&#10;[2]: http://search.yahoo.com/  &quot;Yahoo Search&quot;&#10;[3]: http://search.msn.com/    &quot;MSN Search&quot;&#10;&#10;&#10;I start my morning with a cup of coffee and&#10;[The New York Times][NY Times].&#10;&#10;[ny times]: http://www.nytimes.com/&#10;&#10;![alt text](/path/to/img.jpg &quot;Title&quot;)&#10;&#10;&#10;![alt text][id]&#10;&#10;[id]: /path/to/img.jpg &quot;Title&quot;&#10;&#10;I strongly recommend against using any `&lt;blink&gt;` tags.&#10;&#10;I wish SmartyPants used named entities like `&amp;mdash;`&#10;instead of decimal-encoded entites like `&amp;#8212;`.&#10;&#10;&#10;    If you want your page to validate under XHTML 1.0 Strict,&#10;    you've got to put paragraph tags in your blockquotes:&#10;&#10;        &lt;blockquote&gt;&#10;            &lt;p&gt;For example.&lt;/p&gt;&#10;        &lt;/blockquote&gt;&#10;" wrapText="true" />
-        <ScrollPane id="ScrollPane" fx:id="contentScrollPane" content="$null" fitToWidth="true" hbarPolicy="AS_NEEDED" style="-fx-background-color: white;" vbarPolicy="ALWAYS" />
+        <TextArea fx:id="sourceTextArea" minHeight="0.0" minWidth="0.0" prefWidth="-1.0" style="-fx-font: 10pt monospace;" text="#FlowDown&#10;&#10;Flowdown started as a tech demo for the new&#10;TextFlow node in JavaFX.  It renders&#10;[MarkDown](http://markdown.org) but instead&#10;of using HTML it uses JavaFX. The name was&#10;origianlly picked as a portmadou (sp) of &#10;TextFlow and MarkDown, but it is actually a&#10;real word in the US Legal system:&#10;&#10;&gt; A flow down clause is a contract provision&#10;&gt; by which  the parties incorporate the terms&#10;&gt; of the general contract between the owner&#10;&gt; and the general contractor into the lower&#10;&gt; tier agreement. It may also be referred to&#10;&gt; as a pass-through or conduit clause. They&#10;&gt; are most common in construction contracts.&#10;&gt; Such provisions state that the&#10;&gt; subcontractor is bound to the contractor&#10;&gt; in the same manner as the contractor is&#10;&gt; bound to the owner in the prime contract.&#10;&gt; Flow-down provisions help to ensure that&#10;&gt; the subcontractor's obligations to the&#10;&gt; contractor mirror the contractor's&#10;&gt; obligations to the owner.&#10;&gt; \[ [USLegal](http://definitions.uslegal.com/f/flow-down-clause/) \]&#10;&#10;&#10;So rather than HTML being the subcontractor&#10;JavaFX is the subcontractor." wrapText="true" />
+        <ScrollPane id="ScrollPane" fx:id="contentScrollPane" content="$null" fitToWidth="true" hbarPolicy="AS_NEEDED" minHeight="0.0" minWidth="0.0" style="-fx-background-color: white;" vbarPolicy="ALWAYS" />
       </items>
     </SplitPane>
   </children>

File flowdown-app/src/main/resources/FlowDown/applications-system.png

Removed
Old image

File flowdown-app/src/main/resources/FlowDown/preferences-system.png

Removed
Old image

File markdown-node/src/main/java/org/bitbucket/shemnon/TransformingPane.java

 
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.SimpleObjectProperty;
-import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
-import javafx.scene.Group;
 import javafx.scene.Node;
-import javafx.scene.layout.Pane;
 import javafx.scene.layout.VBox;
 
 import java.util.function.Function;
         valueProp.addListener(this::sourceValueChanged);
     }
 
+    public void recalculateTransform() {
+        sourceValueChanged(valueProp, valueProp.get(), valueProp.get());
+    }
+
     public void sourceValueChanged(ObservableValue<? extends T> prop, T oldValue, T newValue) {
         getChildren().setAll(transformation.apply(newValue));
     }

File markdown-node/src/main/java/org/bitbucket/shemnon/mdnode/MarkdownNode.java

 
 import org.bitbucket.shemnon.OffThreadTransformingPane;
 
-import java.util.function.Function;
-
 /**
  * Created with IntelliJ IDEA.
  * User: shemnon
 
     public MarkdownNode() {
         generator = new MarkdownToNodeGenerator();
-        setTransformation(markdown -> generator.createMarkdownNode(markdown));
+        setTransformation(generator::createMarkdownNode);
     }
 
     public void setParserFlags(int flags) {
-        generator.setParserFlags(flags);
+        int oldFlags = generator.getParserFlags();
+        if (oldFlags != flags) {
+            generator.setParserFlags(flags);
+            recalculateTransform();
+        }
     }
 
     public int getParserFlags() {