| 29 | 29 | |
| 30 | 30 | import com.scrivenvar.service.Settings; |
| 31 | import org.fxmisc.flowless.VirtualizedScrollPane; | |
| 32 | 31 | |
| 33 | 32 | /** |
| ... | ||
| 117 | 116 | public static final String PARAGRAPH_ID_PREFIX = "p-"; |
| 118 | 117 | |
| 119 | /** | |
| 120 | * The {@link VirtualizedScrollPane} does not provide a way to differentiate | |
| 121 | * between keyboard entry triggering a scroll event and a mouse event that | |
| 122 | * triggers scrolling. This value ensures that if a user has "just" pressed | |
| 123 | * a key that no synchronized scrolling will be attempted, despite a | |
| 124 | * scrolling event being fired. | |
| 125 | */ | |
| 126 | public static final int KEYBOARD_SCROLL_DELAY = 750; | |
| 118 | public static final String FONT_DIRECTORY = "/fonts"; | |
| 127 | 119 | } |
| 128 | 120 | |
| 51 | 51 | import static java.awt.font.TextAttribute.LIGATURES; |
| 52 | 52 | import static java.awt.font.TextAttribute.LIGATURES_ON; |
| 53 | import static javafx.scene.input.KeyCode.F11; | |
| 54 | import static javafx.scene.input.KeyEvent.KEY_PRESSED; | |
| 53 | 55 | |
| 54 | 56 | /** |
| 55 | 57 | * Application entry point. The application allows users to edit Markdown |
| 56 | 58 | * files and see a real-time preview of the edits. |
| 57 | 59 | * |
| 58 | 60 | * @author Karl Tauber and White Magic Software, Ltd. |
| 59 | 61 | */ |
| 60 | 62 | public final class Main extends Application { |
| 61 | 63 | |
| 62 | // Suppress logging errors to standard output. | |
| 64 | // Suppress standard output logging; the Launcher suppresses stderr output. | |
| 63 | 65 | static { |
| 64 | 66 | LogManager.getLogManager().reset(); |
| ... | ||
| 109 | 111 | try { |
| 110 | 112 | ResourceWalker.walk( |
| 111 | "/fonts", path -> { | |
| 113 | FONT_DIRECTORY, path -> { | |
| 112 | 114 | final var uri = path.toUri(); |
| 113 | 115 | final var filename = path.toString(); |
| ... | ||
| 158 | 160 | stage.setTitle( getApplicationTitle() ); |
| 159 | 161 | stage.setScene( getScene() ); |
| 162 | ||
| 163 | stage.addEventHandler( KEY_PRESSED, event -> { | |
| 164 | if( F11.equals( event.getCode() ) ) { | |
| 165 | stage.setFullScreen( !stage.isFullScreen() ); | |
| 166 | } | |
| 167 | } ); | |
| 160 | 168 | } |
| 161 | 169 | |
| ... | ||
| 179 | 187 | thread.interrupt(); |
| 180 | 188 | thread.join(); |
| 189 | } | |
| 190 | ||
| 191 | private static Notifier getNotifier() { | |
| 192 | return sNotifier; | |
| 181 | 193 | } |
| 182 | 194 | |
| ... | ||
| 191 | 203 | private Options getOptions() { |
| 192 | 204 | return mOptions; |
| 193 | } | |
| 194 | ||
| 195 | private static Notifier getNotifier() { | |
| 196 | return sNotifier; | |
| 197 | 205 | } |
| 198 | 206 | |
| 46 | 46 | import com.scrivenvar.util.ActionBuilder; |
| 47 | 47 | import com.scrivenvar.util.ActionUtils; |
| 48 | import com.scrivenvar.util.ResourceWalker; | |
| 49 | 48 | import javafx.application.Platform; |
| 50 | 49 | import javafx.beans.binding.Bindings; |
| ... | ||
| 63 | 62 | import javafx.scene.Scene; |
| 64 | 63 | import javafx.scene.control.*; |
| 65 | import javafx.scene.control.Menu; | |
| 66 | import javafx.scene.control.MenuBar; | |
| 67 | import javafx.scene.control.TextField; | |
| 68 | 64 | import javafx.scene.control.Alert.AlertType; |
| 69 | 65 | import javafx.scene.image.Image; |
| ... | ||
| 82 | 78 | import org.xhtmlrenderer.util.XRLog; |
| 83 | 79 | |
| 84 | import java.awt.*; | |
| 85 | import java.awt.font.TextAttribute; | |
| 86 | import java.io.FileInputStream; | |
| 87 | import java.io.IOException; | |
| 88 | import java.io.InputStream; | |
| 89 | import java.net.URI; | |
| 90 | 80 | import java.nio.file.Path; |
| 91 | 81 | import java.util.HashMap; |
| ... | ||
| 100 | 90 | import static com.scrivenvar.util.StageState.*; |
| 101 | 91 | import static de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon.*; |
| 102 | import static java.awt.font.TextAttribute.LIGATURES; | |
| 103 | import static java.awt.font.TextAttribute.LIGATURES_ON; | |
| 104 | 92 | import static javafx.event.Event.fireEvent; |
| 105 | 93 | import static javafx.scene.input.KeyCode.ENTER; |
| 1 | /* | |
| 2 | * Copyright (c) 2015 Karl Tauber <karl at jformdesigner dot com> | |
| 3 | * All rights reserved. | |
| 4 | * | |
| 5 | * Redistribution and use in source and binary forms, with or without | |
| 6 | * modification, are permitted provided that the following conditions are met: | |
| 7 | * | |
| 8 | * o Redistributions of source code must retain the above copyright | |
| 9 | * notice, this list of conditions and the following disclaimer. | |
| 10 | * | |
| 11 | * o Redistributions in binary form must reproduce the above copyright | |
| 12 | * notice, this list of conditions and the following disclaimer in the | |
| 13 | * documentation and/or other materials provided with the distribution. | |
| 14 | * | |
| 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 18 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 19 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 21 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 26 | */ | |
| 27 | ||
| 28 | package com.scrivenvar.controls; | |
| 29 | ||
| 30 | import com.scrivenvar.Messages; | |
| 31 | import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon; | |
| 32 | import de.jensd.fx.glyphs.fontawesome.utils.FontAwesomeIconFactory; | |
| 33 | import javafx.event.ActionEvent; | |
| 34 | import javafx.scene.control.Tooltip; | |
| 35 | import javafx.stage.DirectoryChooser; | |
| 36 | ||
| 37 | import java.io.File; | |
| 38 | ||
| 39 | /** | |
| 40 | * Button that opens a directory chooser to select a local directory for a | |
| 41 | * URL in markdown. | |
| 42 | * | |
| 43 | * @author Karl Tauber | |
| 44 | */ | |
| 45 | public class BrowseDirectoryButton | |
| 46 | extends BrowseFileButton { | |
| 47 | public BrowseDirectoryButton() { | |
| 48 | setGraphic( FontAwesomeIconFactory.get() | |
| 49 | .createIcon( FontAwesomeIcon.FOLDER_ALT, | |
| 50 | "1.2em" ) ); | |
| 51 | setTooltip( new Tooltip( Messages.get( "BrowseDirectoryButton.tooltip" ) ) ); | |
| 52 | } | |
| 53 | ||
| 54 | @Override | |
| 55 | protected void browse( ActionEvent e ) { | |
| 56 | DirectoryChooser directoryChooser = new DirectoryChooser(); | |
| 57 | directoryChooser.setTitle( Messages.get( | |
| 58 | "BrowseDirectoryButton.chooser.title" ) ); | |
| 59 | directoryChooser.setInitialDirectory( getInitialDirectory() ); | |
| 60 | File result = directoryChooser.showDialog( getScene().getWindow() ); | |
| 61 | if( result != null ) { | |
| 62 | updateUrl( result ); | |
| 63 | } | |
| 64 | } | |
| 65 | } | |
| 66 | 1 |
| 28 | 28 | package com.scrivenvar.controls; |
| 29 | 29 | |
| 30 | import java.io.File; | |
| 31 | import java.nio.file.Path; | |
| 32 | import java.util.ArrayList; | |
| 33 | import java.util.List; | |
| 30 | import com.scrivenvar.Messages; | |
| 31 | import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon; | |
| 32 | import de.jensd.fx.glyphs.fontawesome.utils.FontAwesomeIconFactory; | |
| 34 | 33 | import javafx.beans.property.ObjectProperty; |
| 35 | 34 | import javafx.beans.property.SimpleObjectProperty; |
| 36 | 35 | import javafx.event.ActionEvent; |
| 37 | 36 | import javafx.scene.control.Button; |
| 38 | 37 | import javafx.scene.control.Tooltip; |
| 39 | 38 | import javafx.scene.input.KeyCode; |
| 40 | 39 | import javafx.scene.input.KeyEvent; |
| 41 | 40 | import javafx.stage.FileChooser; |
| 42 | 41 | import javafx.stage.FileChooser.ExtensionFilter; |
| 43 | import com.scrivenvar.Messages; | |
| 44 | import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon; | |
| 45 | import de.jensd.fx.glyphs.fontawesome.utils.FontAwesomeIconFactory; | |
| 42 | ||
| 43 | import java.io.File; | |
| 44 | import java.nio.file.Path; | |
| 45 | import java.util.ArrayList; | |
| 46 | import java.util.List; | |
| 46 | 47 | |
| 47 | 48 | /** |
| 48 | * Button that opens a file chooser to select a local file for a URL in markdown. | |
| 49 | * Button that opens a file chooser to select a local file for a URL in | |
| 50 | * markdown. | |
| 49 | 51 | * |
| 50 | 52 | * @author Karl Tauber |
| 51 | 53 | */ |
| 52 | public class BrowseFileButton | |
| 53 | extends Button | |
| 54 | { | |
| 55 | private final List<ExtensionFilter> extensionFilters = new ArrayList<>(); | |
| 54 | public class BrowseFileButton extends Button { | |
| 55 | private final List<ExtensionFilter> extensionFilters = new ArrayList<>(); | |
| 56 | 56 | |
| 57 | public BrowseFileButton() { | |
| 58 | setGraphic(FontAwesomeIconFactory.get().createIcon(FontAwesomeIcon.FILE_ALT, "1.2em")); | |
| 59 | setTooltip(new Tooltip(Messages.get("BrowseFileButton.tooltip"))); | |
| 60 | setOnAction(this::browse); | |
| 57 | public BrowseFileButton() { | |
| 58 | setGraphic( | |
| 59 | FontAwesomeIconFactory.get().createIcon( FontAwesomeIcon.FILE_ALT ) | |
| 60 | ); | |
| 61 | setTooltip( new Tooltip( Messages.get( "BrowseFileButton.tooltip" ) ) ); | |
| 62 | setOnAction( this::browse ); | |
| 61 | 63 | |
| 62 | disableProperty().bind(basePath.isNull()); | |
| 64 | disableProperty().bind( basePath.isNull() ); | |
| 63 | 65 | |
| 64 | // workaround for a JavaFX bug: | |
| 65 | // avoid closing the dialog that contains this control when the user | |
| 66 | // closes the FileChooser or DirectoryChooser using the ESC key | |
| 67 | addEventHandler(KeyEvent.KEY_RELEASED, e-> { | |
| 68 | if (e.getCode() == KeyCode.ESCAPE) | |
| 69 | e.consume(); | |
| 70 | }); | |
| 71 | } | |
| 66 | // workaround for a JavaFX bug: | |
| 67 | // avoid closing the dialog that contains this control when the user | |
| 68 | // closes the FileChooser or DirectoryChooser using the ESC key | |
| 69 | addEventHandler( KeyEvent.KEY_RELEASED, e -> { | |
| 70 | if( e.getCode() == KeyCode.ESCAPE ) { | |
| 71 | e.consume(); | |
| 72 | } | |
| 73 | } ); | |
| 74 | } | |
| 72 | 75 | |
| 73 | public void addExtensionFilter(ExtensionFilter extensionFilter) { | |
| 74 | extensionFilters.add(extensionFilter); | |
| 75 | } | |
| 76 | public void addExtensionFilter( ExtensionFilter extensionFilter ) { | |
| 77 | extensionFilters.add( extensionFilter ); | |
| 78 | } | |
| 76 | 79 | |
| 77 | // 'basePath' property | |
| 78 | private final ObjectProperty<Path> basePath = new SimpleObjectProperty<>(); | |
| 79 | public Path getBasePath() { return basePath.get(); } | |
| 80 | public void setBasePath(Path basePath) { this.basePath.set(basePath); } | |
| 81 | public ObjectProperty<Path> basePathProperty() { return basePath; } | |
| 80 | // 'basePath' property | |
| 81 | private final ObjectProperty<Path> basePath = new SimpleObjectProperty<>(); | |
| 82 | 82 | |
| 83 | // 'url' property | |
| 84 | private final ObjectProperty<String> url = new SimpleObjectProperty<>(); | |
| 85 | public String getUrl() { return url.get(); } | |
| 86 | public void setUrl(String url) { this.url.set(url); } | |
| 87 | public ObjectProperty<String> urlProperty() { return url; } | |
| 83 | public Path getBasePath() { | |
| 84 | return basePath.get(); | |
| 85 | } | |
| 88 | 86 | |
| 89 | protected void browse(ActionEvent e) { | |
| 90 | FileChooser fileChooser = new FileChooser(); | |
| 91 | fileChooser.setTitle(Messages.get("BrowseFileButton.chooser.title")); | |
| 92 | fileChooser.getExtensionFilters().addAll(extensionFilters); | |
| 93 | fileChooser.getExtensionFilters().add(new ExtensionFilter(Messages.get("BrowseFileButton.chooser.allFilesFilter"), "*.*")); | |
| 94 | fileChooser.setInitialDirectory(getInitialDirectory()); | |
| 95 | File result = fileChooser.showOpenDialog(getScene().getWindow()); | |
| 96 | if (result != null) | |
| 97 | updateUrl(result); | |
| 98 | } | |
| 87 | public void setBasePath( Path basePath ) { | |
| 88 | this.basePath.set( basePath ); | |
| 89 | } | |
| 99 | 90 | |
| 100 | protected File getInitialDirectory() { | |
| 101 | //TODO build initial directory based on current value of 'url' property | |
| 102 | return getBasePath().toFile(); | |
| 103 | } | |
| 91 | // 'url' property | |
| 92 | private final ObjectProperty<String> url = new SimpleObjectProperty<>(); | |
| 104 | 93 | |
| 105 | protected void updateUrl(File file) { | |
| 106 | String newUrl; | |
| 107 | try { | |
| 108 | newUrl = getBasePath().relativize(file.toPath()).toString(); | |
| 109 | } catch (IllegalArgumentException ex) { | |
| 110 | newUrl = file.toString(); | |
| 111 | } | |
| 112 | url.set(newUrl.replace('\\', '/')); | |
| 113 | } | |
| 94 | public ObjectProperty<String> urlProperty() { | |
| 95 | return url; | |
| 96 | } | |
| 97 | ||
| 98 | protected void browse( ActionEvent e ) { | |
| 99 | FileChooser fileChooser = new FileChooser(); | |
| 100 | fileChooser.setTitle( Messages.get( "BrowseFileButton.chooser.title" ) ); | |
| 101 | fileChooser.getExtensionFilters().addAll( extensionFilters ); | |
| 102 | fileChooser.getExtensionFilters() | |
| 103 | .add( new ExtensionFilter( Messages.get( | |
| 104 | "BrowseFileButton.chooser.allFilesFilter" ), "*.*" ) ); | |
| 105 | fileChooser.setInitialDirectory( getInitialDirectory() ); | |
| 106 | File result = fileChooser.showOpenDialog( getScene().getWindow() ); | |
| 107 | if( result != null ) { | |
| 108 | updateUrl( result ); | |
| 109 | } | |
| 110 | } | |
| 111 | ||
| 112 | protected File getInitialDirectory() { | |
| 113 | //TODO build initial directory based on current value of 'url' property | |
| 114 | return getBasePath().toFile(); | |
| 115 | } | |
| 116 | ||
| 117 | protected void updateUrl( File file ) { | |
| 118 | String newUrl; | |
| 119 | try { | |
| 120 | newUrl = getBasePath().relativize( file.toPath() ).toString(); | |
| 121 | } catch( IllegalArgumentException ex ) { | |
| 122 | newUrl = file.toString(); | |
| 123 | } | |
| 124 | url.set( newUrl.replace( '\\', '/' ) ); | |
| 125 | } | |
| 114 | 126 | } |
| 115 | 127 |
| 1 | /* | |
| 2 | * Copyright (c) 2015 Karl Tauber <karl at jformdesigner dot com> | |
| 3 | * All rights reserved. | |
| 4 | * | |
| 5 | * Redistribution and use in source and binary forms, with or without | |
| 6 | * modification, are permitted provided that the following conditions are met: | |
| 7 | * | |
| 8 | * o Redistributions of source code must retain the above copyright | |
| 9 | * notice, this list of conditions and the following disclaimer. | |
| 10 | * | |
| 11 | * o Redistributions in binary form must reproduce the above copyright | |
| 12 | * notice, this list of conditions and the following disclaimer in the | |
| 13 | * documentation and/or other materials provided with the distribution. | |
| 14 | * | |
| 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 18 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 19 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 21 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 26 | */ | |
| 27 | package com.scrivenvar.controls; | |
| 28 | ||
| 29 | import javafx.beans.property.IntegerProperty; | |
| 30 | import javafx.beans.property.SimpleIntegerProperty; | |
| 31 | import javafx.scene.control.CheckBox; | |
| 32 | ||
| 33 | /** | |
| 34 | * CheckBox that toggles a bit in an integer. | |
| 35 | * | |
| 36 | * @author Karl Tauber | |
| 37 | */ | |
| 38 | public class FlagCheckBox extends CheckBox { | |
| 39 | ||
| 40 | public FlagCheckBox() { | |
| 41 | setOnAction( e -> { | |
| 42 | if( isSelected() ) { | |
| 43 | setFlags( getFlags() | getFlag() ); | |
| 44 | } else { | |
| 45 | setFlags( getFlags() & ~getFlag() ); | |
| 46 | } | |
| 47 | } ); | |
| 48 | ||
| 49 | flags.addListener( (obs, oldFlags, newFlags) -> { | |
| 50 | setSelected( (newFlags.intValue() & getFlag()) != 0 ); | |
| 51 | } ); | |
| 52 | } | |
| 53 | ||
| 54 | // 'flag' property | |
| 55 | private final IntegerProperty flag = new SimpleIntegerProperty(); | |
| 56 | ||
| 57 | public int getFlag() { | |
| 58 | return flag.get(); | |
| 59 | } | |
| 60 | ||
| 61 | public void setFlag( int flag ) { | |
| 62 | this.flag.set( flag ); | |
| 63 | } | |
| 64 | ||
| 65 | public IntegerProperty flagProperty() { | |
| 66 | return flag; | |
| 67 | } | |
| 68 | ||
| 69 | // 'flags' property | |
| 70 | private final IntegerProperty flags = new SimpleIntegerProperty(); | |
| 71 | ||
| 72 | public int getFlags() { | |
| 73 | return flags.get(); | |
| 74 | } | |
| 75 | ||
| 76 | public void setFlags( int flags ) { | |
| 77 | this.flags.set( flags ); | |
| 78 | } | |
| 79 | ||
| 80 | public IntegerProperty flagsProperty() { | |
| 81 | return flags; | |
| 82 | } | |
| 83 | } | |
| 84 | 1 |
| 28 | 28 | package com.scrivenvar.definition; |
| 29 | 29 | |
| 30 | import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon; | |
| 31 | import de.jensd.fx.glyphs.fontawesome.utils.FontAwesomeIconFactory; | |
| 30 | 32 | import javafx.beans.property.SimpleStringProperty; |
| 31 | 33 | import javafx.beans.property.StringProperty; |
| 32 | 34 | import javafx.collections.ObservableList; |
| 35 | import javafx.event.ActionEvent; | |
| 33 | 36 | import javafx.event.Event; |
| 34 | 37 | import javafx.event.EventHandler; |
| 38 | import javafx.geometry.Insets; | |
| 35 | 39 | import javafx.scene.Node; |
| 36 | 40 | import javafx.scene.control.*; |
| 37 | 41 | import javafx.scene.control.cell.TextFieldTreeCell; |
| 38 | 42 | import javafx.scene.input.KeyEvent; |
| 43 | import javafx.scene.layout.BorderPane; | |
| 44 | import javafx.scene.layout.HBox; | |
| 39 | 45 | import javafx.util.StringConverter; |
| 40 | 46 | |
| 41 | 47 | import java.util.*; |
| 42 | 48 | |
| 43 | 49 | import static com.scrivenvar.Messages.get; |
| 50 | import static de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon.*; | |
| 51 | import static javafx.geometry.Pos.CENTER; | |
| 44 | 52 | import static javafx.scene.input.KeyEvent.KEY_PRESSED; |
| 45 | 53 | |
| ... | ||
| 85 | 93 | treeView.setShowRoot( false ); |
| 86 | 94 | getSelectionModel().setSelectionMode( SelectionMode.MULTIPLE ); |
| 95 | ||
| 96 | final var bCreate = createButton( | |
| 97 | "create", TREE, e -> addItem() ); | |
| 98 | final var bRename = createButton( | |
| 99 | "rename", EDIT, e -> editSelectedItem() ); | |
| 100 | final var bDelete = createButton( | |
| 101 | "delete", TRASH, e -> deleteSelectedItems() ); | |
| 102 | ||
| 103 | final var buttonBar = new HBox(); | |
| 104 | buttonBar.getChildren().addAll( bCreate, bRename, bDelete ); | |
| 105 | buttonBar.setAlignment( CENTER ); | |
| 106 | buttonBar.setSpacing( 10 ); | |
| 107 | ||
| 108 | final var borderPane = new BorderPane(); | |
| 109 | borderPane.setPadding( new Insets( 0, 0, 0, 0 ) ); | |
| 110 | borderPane.setCenter( treeView ); | |
| 111 | borderPane.setBottom( buttonBar ); | |
| 87 | 112 | |
| 88 | 113 | textProperty().bind( mFilename ); |
| 89 | 114 | |
| 90 | setContent( treeView ); | |
| 115 | setContent( borderPane ); | |
| 91 | 116 | setCollapsible( false ); |
| 117 | } | |
| 118 | ||
| 119 | private Button createButton( | |
| 120 | final String msgKey, | |
| 121 | final FontAwesomeIcon icon, | |
| 122 | final EventHandler<ActionEvent> eventHandler ) { | |
| 123 | final var keyPrefix = "Pane.definition.button." + msgKey; | |
| 124 | final var button = new Button( get( keyPrefix + ".label" ) ); | |
| 125 | button.setOnAction( eventHandler ); | |
| 126 | ||
| 127 | button.setGraphic( | |
| 128 | FontAwesomeIconFactory.get().createIcon( icon ) | |
| 129 | ); | |
| 130 | button.setTooltip( new Tooltip( get( keyPrefix + ".tooltip" ) ) ); | |
| 131 | ||
| 132 | return button; | |
| 92 | 133 | } |
| 93 | 134 | |
| 130 | 130 | |
| 131 | 131 | Pane.definition.node.root.title=Definitions |
| 132 | Pane.definition.button.create.label=_Create | |
| 133 | Pane.definition.button.rename.label=_Rename | |
| 134 | Pane.definition.button.delete.label=_Delete | |
| 135 | Pane.definition.button.create.tooltip=Add new item (Insert) | |
| 136 | Pane.definition.button.rename.tooltip=Rename selected item (F2) | |
| 137 | Pane.definition.button.delete.tooltip=Delete selected items (Delete) | |
| 132 | 138 | |
| 133 | 139 | # Controls ############################################################### |
| 40 | 40 | =============================================================================*/ |
| 41 | 41 | body { |
| 42 | /* Must be bundled in JAR file. */ | |
| 42 | 43 | font-family: "Vollkorn", serif; |
| 43 | 44 | font-size: 16px; |
| ... | ||
| 146 | 147 | =============================================================================*/ |
| 147 | 148 | dl { |
| 148 | /** Horizontal scroll bar from appears if set to 100%. */ | |
| 149 | /** Horizontal scroll bar will appear if set to 100%. */ | |
| 149 | 150 | width: 99%; |
| 150 | 151 | overflow: hidden; |
| ... | ||
| 177 | 178 | pre, code, tt { |
| 178 | 179 | font-size: 14px; |
| 180 | /* Must be bundled in JAR file. */ | |
| 179 | 181 | font-family: "Fira Code", monospace; |
| 180 | 182 | } |
| ... | ||
| 209 | 211 | kbd { |
| 210 | 212 | background-color: #ccc; |
| 211 | background-image: linear-gradient(#F1F1F1, #DDDDDD); | |
| 213 | background-image: linear-gradient(#f8f8f8, #DDDDDD); | |
| 212 | 214 | background-repeat: repeat-x; |
| 213 | 215 | border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD; |
| 214 | 216 | border-image: none; |
| 215 | 217 | border-radius: 2px; |
| 216 | 218 | border-style: solid; |
| 217 | 219 | border-width: 1px; |
| 218 | font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; | |
| 219 | line-height: 10px; | |
| 220 | font-family: sans-serif; | |
| 221 | line-height: 1.25; | |
| 220 | 222 | padding: 1px 4px; |
| 221 | 223 | } |