diff --git a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/BulletFactory.java b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/BulletFactory.java new file mode 100644 index 000000000..14e341da5 --- /dev/null +++ b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/BulletFactory.java @@ -0,0 +1,77 @@ +package org.fxmisc.richtext.demo.richtext; + +import java.util.function.IntFunction; + +import org.fxmisc.richtext.GenericStyledArea; + +import javafx.geometry.Insets; +import javafx.scene.Node; +import javafx.scene.control.ContentDisplay; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import javafx.scene.shape.Circle; +import javafx.scene.shape.Rectangle; + +public class BulletFactory implements IntFunction +{ + private GenericStyledArea area; + + public BulletFactory( GenericStyledArea area ) + { + this.area = area; + } + + @Override + public Node apply( int value ) + { + if ( value < 0 ) return null; + + ParStyle ps = area.getParagraph( value ).getParagraphStyle(); + if ( ! ps.indent.isPresent() ) return null; + + return createBullet( ps.indent.get() ); + } + + private Node createBullet(Indent in) { + Node result; + switch( in.level ) { + case 1 : { + Circle c = new Circle(2.5); + c.setFill(Color.BLACK); + c.setStroke(Color.BLACK); + result = c; + } + break; + + case 2 : { + Circle c = new Circle(2.5); + c.setFill(Color.WHITE); + c.setStroke(Color.BLACK); + result = c; + } + break; + + case 3 : { + Rectangle r = new Rectangle(5, 5); + r.setFill(Color.BLACK); + r.setStroke(Color.BLACK); + result = r; + } + break; + + default : { + Rectangle r = new Rectangle(5, 5); + r.setFill(Color.WHITE); + r.setStroke(Color.BLACK); + result = r; + } + break; + } + + Label l = new Label( " ", result ); + l.setPadding( new Insets( 0, 0, 0, in.level*in.width ) ); + l.setContentDisplay( ContentDisplay.LEFT ); + return new VBox( 0, l ); + } +} diff --git a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/Indent.java b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/Indent.java new file mode 100644 index 000000000..0dbf20aba --- /dev/null +++ b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/Indent.java @@ -0,0 +1,7 @@ +package org.fxmisc.richtext.demo.richtext; + +public class Indent +{ + double width = 15; + int level = 1; +} diff --git a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/ParStyle.java b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/ParStyle.java index 6057bd639..5a696d2c6 100644 --- a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/ParStyle.java +++ b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/ParStyle.java @@ -55,14 +55,20 @@ public ParStyle decode(DataInputStream is) throws IOException { final Optional alignment; final Optional backgroundColor; + final Optional indent; public ParStyle() { - this(Optional.empty(), Optional.empty()); + this(Optional.empty(), Optional.empty(), Optional.empty()); } public ParStyle(Optional alignment, Optional backgroundColor) { + this(alignment, backgroundColor, Optional.empty()); + } + + public ParStyle(Optional alignment, Optional backgroundColor, Optional indent) { this.alignment = alignment; this.backgroundColor = backgroundColor; + this.indent = indent; } @Override @@ -111,15 +117,33 @@ public String toCss() { public ParStyle updateWith(ParStyle mixin) { return new ParStyle( mixin.alignment.isPresent() ? mixin.alignment : alignment, - mixin.backgroundColor.isPresent() ? mixin.backgroundColor : backgroundColor); + mixin.backgroundColor.isPresent() ? mixin.backgroundColor : backgroundColor, + mixin.indent.isPresent() ? mixin.indent : indent ); } public ParStyle updateAlignment(TextAlignment alignment) { - return new ParStyle(Optional.of(alignment), backgroundColor); + return new ParStyle(Optional.of(alignment), backgroundColor, indent); } public ParStyle updateBackgroundColor(Color backgroundColor) { - return new ParStyle(alignment, Optional.of(backgroundColor)); + return new ParStyle(alignment, Optional.of(backgroundColor), indent); + } + + public ParStyle updateIndent(Indent indent) { + return new ParStyle(alignment, backgroundColor, Optional.ofNullable(indent)); + } + + public ParStyle increaseIndent() { + if ( indent.isPresent() ) indent.get().level++; + else return updateIndent( new Indent() ); + return this; + } + + public ParStyle decreaseIndent() { + if ( indent.isPresent() && --indent.get().level == 0 ) { + return updateIndent( null ); + } + return this; } } diff --git a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/RichTextDemo.java b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/RichTextDemo.java index 349c32f60..fc7b2dcf6 100644 --- a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/RichTextDemo.java +++ b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/RichTextDemo.java @@ -87,6 +87,7 @@ public static void main(String[] args) { area.setStyleCodecs( ParStyle.CODEC, Codec.styledSegmentCodec(Codec.eitherCodec(Codec.STRING_CODEC, LinkedImage.codec()), TextStyle.CODEC)); + area.setParagraphGraphicFactory( new BulletFactory( area ) ); } private Stage mainStage; @@ -118,6 +119,8 @@ public void start(Stage primaryStage) { Button underlineBtn = createButton("underline", this::toggleUnderline, "Underline"); Button strikeBtn = createButton("strikethrough", this::toggleStrikethrough, "Strike Trough"); Button insertImageBtn = createButton("insertimage", this::insertImage, "Insert Image"); + Button increaseIndentBtn = createButton("increaseIndent", this::increaseIndent, "Increase indent"); + Button decreaseIndentBtn = createButton("decreaseIndent", this::decreaseIndent, "Decrease indent"); ToggleGroup alignmentGrp = new ToggleGroup(); ToggleButton alignLeftBtn = createToggleButton(alignmentGrp, "align-left", this::alignLeft, "Align left"); ToggleButton alignCenterBtn = createToggleButton(alignmentGrp, "align-center", this::alignCenter, "Align center"); @@ -282,6 +285,7 @@ undoBtn, redoBtn, new Separator(Orientation.VERTICAL), cutBtn, copyBtn, pasteBtn, new Separator(Orientation.VERTICAL), boldBtn, italicBtn, underlineBtn, strikeBtn, new Separator(Orientation.VERTICAL), alignLeftBtn, alignCenterBtn, alignRightBtn, alignJustifyBtn, new Separator(Orientation.VERTICAL), + increaseIndentBtn, decreaseIndentBtn, new Separator(Orientation.VERTICAL), insertImageBtn, new Separator(Orientation.VERTICAL), paragraphBackgroundPicker); @@ -309,11 +313,6 @@ private Node createNode(StyledSegment, TextStyle> se ); } - @Deprecated - private Button createButton(String styleClass, Runnable action) { - return createButton(styleClass, action, null); - } - private Button createButton(String styleClass, Runnable action, String toolTip) { Button button = new Button(); button.getStyleClass().add(styleClass); @@ -465,6 +464,14 @@ private void insertImage() { } } + private void increaseIndent() { + updateParagraphStyleInSelection( ps -> ps.increaseIndent() ); + } + + private void decreaseIndent() { + updateParagraphStyleInSelection( ps -> ps.decreaseIndent() ); + } + private void updateStyleInSelection(Function, TextStyle> mixinGetter) { IndexRange selection = area.getSelection(); if(selection.getLength() != 0) { diff --git a/richtextfx-demos/src/main/resources/org/fxmisc/richtext/demo/richtext/decreaseIndent.png b/richtextfx-demos/src/main/resources/org/fxmisc/richtext/demo/richtext/decreaseIndent.png new file mode 100644 index 000000000..4c67f82e9 Binary files /dev/null and b/richtextfx-demos/src/main/resources/org/fxmisc/richtext/demo/richtext/decreaseIndent.png differ diff --git a/richtextfx-demos/src/main/resources/org/fxmisc/richtext/demo/richtext/increaseIndent.png b/richtextfx-demos/src/main/resources/org/fxmisc/richtext/demo/richtext/increaseIndent.png new file mode 100644 index 000000000..af845bc52 Binary files /dev/null and b/richtextfx-demos/src/main/resources/org/fxmisc/richtext/demo/richtext/increaseIndent.png differ diff --git a/richtextfx-demos/src/main/resources/org/fxmisc/richtext/demo/richtext/rich-text.css b/richtextfx-demos/src/main/resources/org/fxmisc/richtext/demo/richtext/rich-text.css index 66efd31c8..4ddff1656 100644 --- a/richtextfx-demos/src/main/resources/org/fxmisc/richtext/demo/richtext/rich-text.css +++ b/richtextfx-demos/src/main/resources/org/fxmisc/richtext/demo/richtext/rich-text.css @@ -17,8 +17,10 @@ .button.underline { -fx-background-image: url(underline.png); } .button.strikethrough { -fx-background-image: url(strikethrough.png); } .button.insertimage { -fx-background-image: url(insertimage.png); } +.button.increaseIndent { -fx-background-image: url(increaseIndent.png); } +.button.decreaseIndent { -fx-background-image: url(decreaseIndent.png); } .toggle-button.align-left { -fx-background-image: url(align-left.png); } .toggle-button.align-center { -fx-background-image: url(align-center.png); } .toggle-button.align-right { -fx-background-image: url(align-right.png); } -.toggle-button.align-justify { -fx-background-image: url(align-justify.png); } \ No newline at end of file +.toggle-button.align-justify { -fx-background-image: url(align-justify.png); }