Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/keenwrite.git

Removed dependency on observable path. Updated CREDITS with links to software. Moved state restore out of file editor tab pane and into the main window to ensure that *all* new tabs are associated with the text processors.

Authordjarvis <email>
Date2016-12-05 17:18:52 GMT-0800
Commite12e320a34064381992d481115bec30a2f6d847c
Parentc722d7e
CHANGES.md
-Change Log
-==========
+# Change Log
+
+## 0.5
+
+- Added document processors for Markdown and Variables
+- Simplified code base
+- Added `Ctrl+Space` hot key for quick variable injection
+- Replaced commonmark-java with flexmark
## 0.4
- Initial release
-
CREDITS.md
Credits
-=======
-
- * Karl Tauber for [Markdown Writer FX]
- * Tomas Mikula for [RichTextFX], [ReactFX], [WellBehavedFX], [Flowless] and [UndoFX]
- * Mikael Grev for [MigLayout] and Tom Eugelink for MigPane
- * sirthias for [pegdown] Markdown parser
- * Jens Deters for [FontAwesomeFX]
+===
+ * Dave Jarvis: [Scrivenvar](https://github.com/DaveJarvis/scrivenvar/)
+ * Karl Tauber: [Markdown Writer FX](https://github.com/JFormDesigner/markdown-writer-fx)
+ * Tomas Mikula: [RichTextFX](https://github.com/TomasMikula/RichTextFX), [ReactFX](https://github.com/TomasMikula/ReactFX), [WellBehavedFX](https://github.com/TomasMikula/WellBehavedFX), [Flowless](https://github.com/TomasMikula/Flowless), and [UndoFX](https://github.com/TomasMikula/UndoFX)
+ * Mikael Grev: [MigLayout](http://www.miglayout.com/)
+ * Tom Eugelink: [MigPane](https://github.com/mikaelgrev/miglayout/blob/master/javafx/src/main/java/org/tbee/javafx/scene/layout/fxml/MigPane.java)
+ * Vladimir Schneider: [flexmark](https://website.com)
+ * Jens Deters: [FontAwesomeFX](https://bitbucket.org/Jerady/fontawesomefx)
src/main/java/com/scrivenvar/FileEditorTabPane.java
};
- tabs.addListener( (ListChangeListener<Tab>)c -> {
- while( c.next() ) {
- if( c.wasAdded() ) {
- c.getAddedSubList().stream().forEach( (tab) -> {
- ((FileEditorTab)tab.getUserData()).modifiedProperty().addListener( modifiedListener );
- } );
- } else if( c.wasRemoved() ) {
- c.getRemoved().stream().forEach( (tab) -> {
- ((FileEditorTab)tab.getUserData()).modifiedProperty().removeListener( modifiedListener );
- } );
- }
- }
-
- // Changes in the tabs may also change anyFileEditorModified property
- // (e.g. closed modified file)
- modifiedListener.changed( null, null, null );
- } );
-
- // re-open files
- restoreState();
- }
-
- public <T extends Event, U extends T> void addEventListener(
- final EventPattern<? super T, ? extends U> event,
- final Consumer<? super U> consumer ) {
- getActiveFileEditor().addEventListener( event, consumer );
- }
-
- /**
- * Delegates to the active file editor pane, and, ultimately, to its text
- * area.
- *
- * @param map The map of methods to events.
- */
- public void addEventListener( final InputMap<InputEvent> map ) {
- getActiveFileEditor().addEventListener( map );
- }
-
- public void removeEventListener( final InputMap<InputEvent> map ) {
- getActiveFileEditor().removeEventListener( map );
- }
-
- @Override
- public void changed(
- final ObservableValue<? extends Tab> observable,
- final Tab oldTab,
- final Tab newTab ) {
-
- if( newTab != null ) {
- final FileEditorTab tab = (FileEditorTab)newTab;
-
- this.activeFileEditor.set( (FileEditorTab)newTab.getUserData() );
- }
- }
-
- Node getNode() {
- return this;
- }
-
- /**
- * Allows clients to manipulate the editor content directly.
- *
- * @return The text area for the active file editor.
- */
- public StyledTextArea getEditor() {
- return getActiveFileEditor().getEditorPane().getEditor();
- }
-
- public FileEditorTab getActiveFileEditor() {
- return this.activeFileEditor.get();
- }
-
- ReadOnlyObjectProperty<FileEditorTab> activeFileEditorProperty() {
- return this.activeFileEditor.getReadOnlyProperty();
- }
-
- ReadOnlyBooleanProperty anyFileEditorModifiedProperty() {
- return this.anyFileEditorModified.getReadOnlyProperty();
- }
-
- private FileEditorTab createFileEditor( Path path ) {
- final FileEditorTab fileEditor = new FileEditorTab( path );
-
- fileEditor.setOnCloseRequest( e -> {
- if( !canCloseEditor( fileEditor ) ) {
- e.consume();
- }
- } );
-
- return fileEditor;
- }
-
- FileEditorTab newEditor() {
- final FileEditorTab tab = createFileEditor( null );
-
- getTabs().add( tab );
- getSelectionModel().select( tab );
- return tab;
- }
-
- List<FileEditorTab> openFileDialog() {
- final FileChooser dialog
- = createFileChooser( get( "Dialog.file.choose.open.title" ) );
- final List<File> files = dialog.showOpenMultipleDialog( getWindow() );
-
- return (files != null && !files.isEmpty())
- ? openFiles( files )
- : new ArrayList<>();
- }
-
- /**
- * Opens the files into new editors, unless one of those files was a
- * definition file. The definition file is loaded into the definition pane,
- * but only the first one selected (multiple definition files will result in a
- * warning).
- *
- * @param files The list of non-definition files that the were requested to
- * open.
- *
- * @return A list of files that can be opened in text editors.
- */
- private List<FileEditorTab> openFiles( final List<File> files ) {
- final List<FileEditorTab> openedEditors = new ArrayList<>();
-
- final FileTypePredicate predicate
- = new FileTypePredicate( createExtensionFilter( "definition" ).getExtensions() );
-
- // The user might have opened muliple definitions files. These will
- // be discarded from the text editable files.
- final List<File> definitions
- = files.stream().filter( predicate ).collect( Collectors.toList() );
-
- // Create a modifiable list to remove any definition files that were
- // opened.
- final List<File> editors = new ArrayList<>( files );
- editors.removeAll( definitions );
-
- // If there are any editor-friendly files opened (e.g,. Markdown, XML), then
- // open them up in new tabs.
- if( editors.size() > 0 ) {
- saveLastDirectory( editors.get( 0 ) );
- openedEditors.addAll( openEditors( editors, 0 ) );
- }
-
- if( definitions.size() > 0 ) {
- openDefinition( definitions.get( 0 ) );
- }
-
- return openedEditors;
- }
-
- private List<FileEditorTab> openEditors( final List<File> files, final int activeIndex ) {
- final List<FileEditorTab> editors = new ArrayList<>();
- final List<Tab> tabs = getTabs();
-
- // Close single unmodified "Untitled" tab.
- if( tabs.size() == 1 ) {
- final FileEditorTab fileEditor = (FileEditorTab)(tabs.get( 0 ).getUserData());
-
- if( fileEditor.getPath() == null && !fileEditor.isModified() ) {
- closeEditor( fileEditor, false );
- }
- }
-
- for( int i = 0; i < files.size(); i++ ) {
- Path path = files.get( i ).toPath();
-
- // Check whether file is already opened.
- FileEditorTab fileEditor = findEditor( path );
-
- if( fileEditor == null ) {
- fileEditor = createFileEditor( path );
- getTabs().add( fileEditor );
- editors.add( fileEditor );
- }
-
- // Select first file.
- if( i == activeIndex ) {
- getSelectionModel().select( fileEditor );
- }
- }
-
- return editors;
- }
-
- /**
- * Called when the user has opened a definition file (using the file open
- * dialog box). This will replace the current set of definitions for the
- * active tab.
- *
- * @param definition The file to open.
- */
- private void openDefinition( final File definition ) {
- System.out.println( "open definition file: " + definition.toString() );
- }
-
- boolean saveEditor( final FileEditorTab fileEditor ) {
- if( fileEditor == null || !fileEditor.isModified() ) {
- return true;
- }
-
- if( fileEditor.getPath() == null ) {
- getSelectionModel().select( fileEditor );
-
- final FileChooser fileChooser = createFileChooser( Messages.get( "Dialog.file.choose.save.title" ) );
- final File file = fileChooser.showSaveDialog( getWindow() );
- if( file == null ) {
- return false;
- }
-
- saveLastDirectory( file );
- fileEditor.setPath( file.toPath() );
- }
-
- return fileEditor.save();
- }
-
- boolean saveAllEditors() {
- FileEditorTab[] allEditors = getAllEditors();
-
- boolean success = true;
- for( FileEditorTab fileEditor : allEditors ) {
- if( !saveEditor( fileEditor ) ) {
- success = false;
- }
- }
-
- return success;
- }
-
- boolean canCloseEditor( final FileEditorTab fileEditor ) {
- if( !fileEditor.isModified() ) {
- return true;
- }
-
- final AlertMessage message = getAlertService().createAlertMessage(
- Messages.get( "Alert.file.close.title" ),
- Messages.get( "Alert.file.close.text" ),
- fileEditor.getText()
- );
-
- final Alert alert = getAlertService().createAlertConfirmation( message );
- final ButtonType response = alert.showAndWait().get();
-
- return response == YES ? saveEditor( fileEditor ) : response == NO;
- }
-
- private AlertService getAlertService() {
- return this.alertService;
- }
-
- boolean closeEditor( FileEditorTab fileEditor, boolean save ) {
- if( fileEditor == null ) {
- return true;
- }
-
- final Tab tab = fileEditor;
-
- if( save ) {
- Event event = new Event( tab, tab, Tab.TAB_CLOSE_REQUEST_EVENT );
- Event.fireEvent( tab, event );
- if( event.isConsumed() ) {
- return false;
- }
- }
-
- getTabs().remove( tab );
- if( tab.getOnClosed() != null ) {
- Event.fireEvent( tab, new Event( Tab.CLOSED_EVENT ) );
- }
-
- return true;
- }
-
- boolean closeAllEditors() {
- FileEditorTab[] allEditors = getAllEditors();
- FileEditorTab activeEditor = activeFileEditor.get();
-
- // try to save active tab first because in case the user decides to cancel,
- // then it stays active
- if( activeEditor != null && !canCloseEditor( activeEditor ) ) {
- return false;
- }
-
- // save modified tabs
- for( int i = 0; i < allEditors.length; i++ ) {
- FileEditorTab fileEditor = allEditors[ i ];
- if( fileEditor == activeEditor ) {
- continue;
- }
-
- if( fileEditor.isModified() ) {
- // activate the modified tab to make its modified content visible to the user
- getSelectionModel().select( i );
-
- if( !canCloseEditor( fileEditor ) ) {
- return false;
- }
- }
- }
-
- // Close all tabs.
- for( final FileEditorTab fileEditor : allEditors ) {
- if( !closeEditor( fileEditor, false ) ) {
- return false;
- }
- }
-
- saveState( allEditors, activeEditor );
-
- return getTabs().isEmpty();
- }
-
- private FileEditorTab[] getAllEditors() {
- final ObservableList<Tab> tabs = getTabs();
- final FileEditorTab[] allEditors = new FileEditorTab[ tabs.size() ];
- final int length = tabs.size();
-
- for( int i = 0; i < length; i++ ) {
- allEditors[ i ] = (FileEditorTab)tabs.get( i ).getUserData();
- }
-
- return allEditors;
- }
-
- private FileEditorTab findEditor( Path path ) {
- for( final Tab tab : getTabs() ) {
- final FileEditorTab fileEditor = (FileEditorTab)tab.getUserData();
-
- if( path.equals( fileEditor.getPath() ) ) {
- return fileEditor;
- }
- }
-
- return null;
- }
-
- private Settings getSettings() {
- return this.settings;
- }
-
- private FileChooser createFileChooser( String title ) {
- final FileChooser fileChooser = new FileChooser();
-
- fileChooser.setTitle( title );
- fileChooser.getExtensionFilters().addAll(
- createExtensionFilters() );
-
- final String lastDirectory = getState().get( "lastDirectory", null );
- File file = new File( (lastDirectory != null) ? lastDirectory : "." );
-
- if( !file.isDirectory() ) {
- file = new File( "." );
- }
-
- fileChooser.setInitialDirectory( file );
- return fileChooser;
- }
-
- private List<ExtensionFilter> createExtensionFilters() {
- final List<ExtensionFilter> list = new ArrayList<>();
-
- // TODO: Return a list of all properties that match the filter prefix.
- // This will allow dynamic filters to be added and removed just by
- // updating the properties file.
- list.add( createExtensionFilter( "markdown" ) );
- list.add( createExtensionFilter( "definition" ) );
- list.add( createExtensionFilter( "xml" ) );
- list.add( createExtensionFilter( "all" ) );
- return list;
- }
-
- private ExtensionFilter createExtensionFilter( final String filetype ) {
- final String tKey = String.format( "%s.title.%s", FILTER_PREFIX, filetype );
- final String eKey = String.format( "%s.ext.%s", FILTER_PREFIX, filetype );
-
- return new ExtensionFilter( Messages.get( tKey ), getExtensions( eKey ) );
- }
-
- private List<String> getExtensions( final String key ) {
- return getStringSettingList( key );
- }
-
- private List<String> getStringSettingList( String key ) {
- return getStringSettingList( key, null );
- }
-
- private List<String> getStringSettingList( String key, List<String> values ) {
- return getSettings().getStringSettingList( key, values );
- }
-
- private void saveLastDirectory( File file ) {
- getState().put( "lastDirectory", file.getParent() );
- }
-
- private void restoreState() {
+ tabs.addListener( (ListChangeListener<Tab>)change -> {
+ while( change.next() ) {
+ if( change.wasAdded() ) {
+ change.getAddedSubList().stream().forEach( (tab) -> {
+ ((FileEditorTab)tab.getUserData()).modifiedProperty().addListener( modifiedListener );
+ } );
+ } else if( change.wasRemoved() ) {
+ change.getRemoved().stream().forEach( (tab) -> {
+ ((FileEditorTab)tab.getUserData()).modifiedProperty().removeListener( modifiedListener );
+ } );
+ }
+ }
+
+ // Changes in the tabs may also change anyFileEditorModified property
+ // (e.g. closed modified file)
+ modifiedListener.changed( null, null, null );
+ } );
+ }
+
+ public <T extends Event, U extends T> void addEventListener(
+ final EventPattern<? super T, ? extends U> event,
+ final Consumer<? super U> consumer ) {
+ getActiveFileEditor().addEventListener( event, consumer );
+ }
+
+ /**
+ * Delegates to the active file editor pane, and, ultimately, to its text
+ * area.
+ *
+ * @param map The map of methods to events.
+ */
+ public void addEventListener( final InputMap<InputEvent> map ) {
+ getActiveFileEditor().addEventListener( map );
+ }
+
+ public void removeEventListener( final InputMap<InputEvent> map ) {
+ getActiveFileEditor().removeEventListener( map );
+ }
+
+ @Override
+ public void changed(
+ final ObservableValue<? extends Tab> observable,
+ final Tab oldTab,
+ final Tab newTab ) {
+
+ if( newTab != null ) {
+ this.activeFileEditor.set( (FileEditorTab)newTab.getUserData() );
+ }
+ }
+
+ Node getNode() {
+ return this;
+ }
+
+ /**
+ * Allows clients to manipulate the editor content directly.
+ *
+ * @return The text area for the active file editor.
+ */
+ public StyledTextArea getEditor() {
+ return getActiveFileEditor().getEditorPane().getEditor();
+ }
+
+ public FileEditorTab getActiveFileEditor() {
+ return this.activeFileEditor.get();
+ }
+
+ ReadOnlyObjectProperty<FileEditorTab> activeFileEditorProperty() {
+ return this.activeFileEditor.getReadOnlyProperty();
+ }
+
+ ReadOnlyBooleanProperty anyFileEditorModifiedProperty() {
+ return this.anyFileEditorModified.getReadOnlyProperty();
+ }
+
+ private FileEditorTab createFileEditor( final Path path ) {
+ final FileEditorTab tab = new FileEditorTab( path );
+
+ tab.setOnCloseRequest( e -> {
+ if( !canCloseEditor( tab ) ) {
+ e.consume();
+ }
+ } );
+
+ return tab;
+ }
+
+ /**
+ * Called when the user selects New from the File menu.
+ *
+ * @return The newly added tab.
+ */
+ FileEditorTab newEditor() {
+ final FileEditorTab tab = createFileEditor( null );
+
+ getTabs().add( tab );
+ getSelectionModel().select( tab );
+ return tab;
+ }
+
+ List<FileEditorTab> openFileDialog() {
+ final FileChooser dialog
+ = createFileChooser( get( "Dialog.file.choose.open.title" ) );
+ final List<File> files = dialog.showOpenMultipleDialog( getWindow() );
+
+ return (files != null && !files.isEmpty())
+ ? openFiles( files )
+ : new ArrayList<>();
+ }
+
+ /**
+ * Opens the files into new editors, unless one of those files was a
+ * definition file. The definition file is loaded into the definition pane,
+ * but only the first one selected (multiple definition files will result in a
+ * warning).
+ *
+ * @param files The list of non-definition files that the were requested to
+ * open.
+ *
+ * @return A list of files that can be opened in text editors.
+ */
+ private List<FileEditorTab> openFiles( final List<File> files ) {
+ final List<FileEditorTab> openedEditors = new ArrayList<>();
+
+ final FileTypePredicate predicate
+ = new FileTypePredicate( createExtensionFilter( "definition" ).getExtensions() );
+
+ // The user might have opened muliple definitions files. These will
+ // be discarded from the text editable files.
+ final List<File> definitions
+ = files.stream().filter( predicate ).collect( Collectors.toList() );
+
+ // Create a modifiable list to remove any definition files that were
+ // opened.
+ final List<File> editors = new ArrayList<>( files );
+ editors.removeAll( definitions );
+
+ // If there are any editor-friendly files opened (e.g,. Markdown, XML), then
+ // open them up in new tabs.
+ if( editors.size() > 0 ) {
+ saveLastDirectory( editors.get( 0 ) );
+ openedEditors.addAll( openEditors( editors, 0 ) );
+ }
+
+ if( definitions.size() > 0 ) {
+ openDefinition( definitions.get( 0 ) );
+ }
+
+ return openedEditors;
+ }
+
+ private List<FileEditorTab> openEditors( final List<File> files, final int activeIndex ) {
+ final List<FileEditorTab> editors = new ArrayList<>();
+ final List<Tab> tabs = getTabs();
+
+ // Close single unmodified "Untitled" tab.
+ if( tabs.size() == 1 ) {
+ final FileEditorTab fileEditor = (FileEditorTab)(tabs.get( 0 ).getUserData());
+
+ if( fileEditor.getPath() == null && !fileEditor.isModified() ) {
+ closeEditor( fileEditor, false );
+ }
+ }
+
+ for( int i = 0; i < files.size(); i++ ) {
+ Path path = files.get( i ).toPath();
+
+ // Check whether file is already opened.
+ FileEditorTab fileEditor = findEditor( path );
+
+ if( fileEditor == null ) {
+ fileEditor = createFileEditor( path );
+ getTabs().add( fileEditor );
+ editors.add( fileEditor );
+ }
+
+ // Select first file.
+ if( i == activeIndex ) {
+ getSelectionModel().select( fileEditor );
+ }
+ }
+
+ return editors;
+ }
+
+ /**
+ * Called when the user has opened a definition file (using the file open
+ * dialog box). This will replace the current set of definitions for the
+ * active tab.
+ *
+ * @param definition The file to open.
+ */
+ private void openDefinition( final File definition ) {
+ System.out.println( "open definition file: " + definition.toString() );
+ }
+
+ boolean saveEditor( final FileEditorTab fileEditor ) {
+ if( fileEditor == null || !fileEditor.isModified() ) {
+ return true;
+ }
+
+ if( fileEditor.getPath() == null ) {
+ getSelectionModel().select( fileEditor );
+
+ final FileChooser fileChooser = createFileChooser( Messages.get( "Dialog.file.choose.save.title" ) );
+ final File file = fileChooser.showSaveDialog( getWindow() );
+ if( file == null ) {
+ return false;
+ }
+
+ saveLastDirectory( file );
+ fileEditor.setPath( file.toPath() );
+ }
+
+ return fileEditor.save();
+ }
+
+ boolean saveAllEditors() {
+ final FileEditorTab[] allEditors = getAllEditors();
+
+ boolean success = true;
+ for( FileEditorTab fileEditor : allEditors ) {
+ if( !saveEditor( fileEditor ) ) {
+ success = false;
+ }
+ }
+
+ return success;
+ }
+
+ boolean canCloseEditor( final FileEditorTab tab ) {
+ if( !tab.isModified() ) {
+ return true;
+ }
+
+ final AlertMessage message = getAlertService().createAlertMessage(
+ Messages.get( "Alert.file.close.title" ),
+ Messages.get( "Alert.file.close.text" ),
+ tab.getText()
+ );
+
+ final Alert alert = getAlertService().createAlertConfirmation( message );
+ final ButtonType response = alert.showAndWait().get();
+
+ return response == YES ? saveEditor( tab ) : response == NO;
+ }
+
+ private AlertService getAlertService() {
+ return this.alertService;
+ }
+
+ boolean closeEditor( FileEditorTab fileEditor, boolean save ) {
+ if( fileEditor == null ) {
+ return true;
+ }
+
+ final Tab tab = fileEditor;
+
+ if( save ) {
+ Event event = new Event( tab, tab, Tab.TAB_CLOSE_REQUEST_EVENT );
+ Event.fireEvent( tab, event );
+ if( event.isConsumed() ) {
+ return false;
+ }
+ }
+
+ getTabs().remove( tab );
+ if( tab.getOnClosed() != null ) {
+ Event.fireEvent( tab, new Event( Tab.CLOSED_EVENT ) );
+ }
+
+ return true;
+ }
+
+ boolean closeAllEditors() {
+ FileEditorTab[] allEditors = getAllEditors();
+ FileEditorTab activeEditor = activeFileEditor.get();
+
+ // try to save active tab first because in case the user decides to cancel,
+ // then it stays active
+ if( activeEditor != null && !canCloseEditor( activeEditor ) ) {
+ return false;
+ }
+
+ // save modified tabs
+ for( int i = 0; i < allEditors.length; i++ ) {
+ FileEditorTab fileEditor = allEditors[ i ];
+ if( fileEditor == activeEditor ) {
+ continue;
+ }
+
+ if( fileEditor.isModified() ) {
+ // activate the modified tab to make its modified content visible to the user
+ getSelectionModel().select( i );
+
+ if( !canCloseEditor( fileEditor ) ) {
+ return false;
+ }
+ }
+ }
+
+ // Close all tabs.
+ for( final FileEditorTab fileEditor : allEditors ) {
+ if( !closeEditor( fileEditor, false ) ) {
+ return false;
+ }
+ }
+
+ saveState( allEditors, activeEditor );
+
+ return getTabs().isEmpty();
+ }
+
+ private FileEditorTab[] getAllEditors() {
+ final ObservableList<Tab> tabs = getTabs();
+ final FileEditorTab[] allEditors = new FileEditorTab[ tabs.size() ];
+ final int length = tabs.size();
+
+ for( int i = 0; i < length; i++ ) {
+ allEditors[ i ] = (FileEditorTab)tabs.get( i ).getUserData();
+ }
+
+ return allEditors;
+ }
+
+ private FileEditorTab findEditor( Path path ) {
+ for( final Tab tab : getTabs() ) {
+ final FileEditorTab fileEditor = (FileEditorTab)tab.getUserData();
+
+ if( path.equals( fileEditor.getPath() ) ) {
+ return fileEditor;
+ }
+ }
+
+ return null;
+ }
+
+ private Settings getSettings() {
+ return this.settings;
+ }
+
+ private FileChooser createFileChooser( String title ) {
+ final FileChooser fileChooser = new FileChooser();
+
+ fileChooser.setTitle( title );
+ fileChooser.getExtensionFilters().addAll(
+ createExtensionFilters() );
+
+ final String lastDirectory = getState().get( "lastDirectory", null );
+ File file = new File( (lastDirectory != null) ? lastDirectory : "." );
+
+ if( !file.isDirectory() ) {
+ file = new File( "." );
+ }
+
+ fileChooser.setInitialDirectory( file );
+ return fileChooser;
+ }
+
+ private List<ExtensionFilter> createExtensionFilters() {
+ final List<ExtensionFilter> list = new ArrayList<>();
+
+ // TODO: Return a list of all properties that match the filter prefix.
+ // This will allow dynamic filters to be added and removed just by
+ // updating the properties file.
+ list.add( createExtensionFilter( "markdown" ) );
+ list.add( createExtensionFilter( "definition" ) );
+ list.add( createExtensionFilter( "xml" ) );
+ list.add( createExtensionFilter( "all" ) );
+ return list;
+ }
+
+ private ExtensionFilter createExtensionFilter( final String filetype ) {
+ final String tKey = String.format( "%s.title.%s", FILTER_PREFIX, filetype );
+ final String eKey = String.format( "%s.ext.%s", FILTER_PREFIX, filetype );
+
+ return new ExtensionFilter( Messages.get( tKey ), getExtensions( eKey ) );
+ }
+
+ private List<String> getExtensions( final String key ) {
+ return getStringSettingList( key );
+ }
+
+ private List<String> getStringSettingList( String key ) {
+ return getStringSettingList( key, null );
+ }
+
+ private List<String> getStringSettingList( String key, List<String> values ) {
+ return getSettings().getStringSettingList( key, values );
+ }
+
+ private void saveLastDirectory( File file ) {
+ getState().put( "lastDirectory", file.getParent() );
+ }
+
+ public void restoreState() {
int activeIndex = 0;
src/main/java/com/scrivenvar/MainWindow.java
import static com.scrivenvar.Messages.get;
import com.scrivenvar.definition.DefinitionPane;
+import com.scrivenvar.editor.EditorPane;
import com.scrivenvar.editor.MarkdownEditorPane;
import com.scrivenvar.editor.VariableNameInjector;
final ObservableList<Tab> tabs = editorPane.getTabs();
- tabs.addListener( (Change<? extends Tab> change) -> {
+ tabs.addListener((Change<? extends Tab> change) -> {
while( change.next() ) {
if( change.wasAdded() ) {
+ // Multiple tabs can be added simultaneously.
for( final Tab tab : change.getAddedSubList() ) {
final FileEditorTab feTab = (FileEditorTab)tab;
+ final HTMLPreviewPane previewPane = feTab.getPreviewPane();
+ final EditorPane editorPane1 = feTab.getEditorPane();
// Load file and create UI when the tab becomes visible the first time.
- final HTMLPreviewPane previewPane = feTab.getPreviewPane();
-
// TODO: Change this to use a factory based on the filename extension.
// See: https://github.com/DaveJarvis/scrivenvar/issues/17
// See: https://github.com/DaveJarvis/scrivenvar/issues/18
final Processor<String> hpp = new HTMLPreviewProcessor( previewPane );
final Processor<String> mp = new MarkdownProcessor( hpp );
final Processor<String> vnp = new VariableProcessor( mp, getResolvedMap() );
final TextChangeProcessor tp = new TextChangeProcessor( vnp );
-
- feTab.getEditorPane().addChangeListener( tp );
- System.out.println( "TAB WAS ADDED" );
+
+ editorPane1.addChangeListener( tp );
}
- } else if( change.wasRemoved() ) {
- System.out.println( "TAB WAS REMOVED" );
}
}
- } );
-
- /*
- editorPane.getActiveFileEditor().getEditorPane().getEditor().focusedProperty().addListener(
- (ObservableValue<? extends Boolean> b, Boolean oldB, Boolean newB) -> {
+ });
+
+ // After the processors are in place, restore the previously closed
+ // tabs. Adding them will trigger the change event, above.
+ editorPane.restoreState();
- if( newB ) {
- System.out.println( "Textfield on focus" );
- } else {
- System.out.println( "Textfield out focus" );
- }
- }
- );
- */
-// editorPane.getActiveFileEditor().addChangeListener( tp );
return editorPane;
}
src/main/java/com/scrivenvar/dialogs/LinkDialog.java
import com.scrivenvar.Messages;
-import com.scrivenvar.controls.BrowseDirectoryButton;
-import com.scrivenvar.controls.BrowseFileButton;
import com.scrivenvar.controls.EscapeTextField;
import com.scrivenvar.editor.HyperlinkModel;
initComponents();
-
- linkBrowseDirectoyButton.setBasePath( basePath );
- linkBrowseDirectoyButton.urlProperty().bindBidirectional( urlField.escapedTextProperty() );
-
- linkBrowseFileButton.setBasePath( basePath );
- linkBrowseFileButton.urlProperty().bindBidirectional( urlField.escapedTextProperty() );
setDialogPane( new ButtonOrderPane() );
final DialogPane dialog = getDialogPane();
- dialog.setContent( dialog );
+ dialog.setContent( pane );
dialog.getButtonTypes().addAll( ButtonType.OK, ButtonType.CANCEL );
Label urlLabel = new Label();
urlField = new EscapeTextField();
- linkBrowseDirectoyButton = new BrowseDirectoryButton();
- linkBrowseFileButton = new BrowseFileButton();
Label textLabel = new Label();
textField = new EscapeTextField();
urlField.setEscapeCharacters( "()" );
pane.add( urlField, "cell 1 0" );
- pane.add( linkBrowseDirectoyButton, "cell 2 0" );
- pane.add( linkBrowseFileButton, "cell 3 0" );
//---- textLabel ----
private MigPane pane;
private EscapeTextField urlField;
- private BrowseDirectoryButton linkBrowseDirectoyButton;
- private BrowseFileButton linkBrowseFileButton;
private EscapeTextField textField;
private EscapeTextField titleField;
src/main/java/com/scrivenvar/preview/HTMLPreviewPane.java
private void scrollY( final double value ) {
- System.out.println( "Scroll to: " + value );
execute(
"window.scrollTo(0, (document.body.scrollHeight - window.innerHeight) * "
Delta425 lines added, 444 lines removed, 19-line decrease