1717import javafx .application .Application ;
1818import javafx .beans .binding .Bindings ;
1919import javafx .beans .binding .BooleanBinding ;
20+ import javafx .beans .property .BooleanProperty ;
21+ import javafx .beans .property .SimpleBooleanProperty ;
2022import javafx .collections .FXCollections ;
2123import javafx .scene .Scene ;
2224import javafx .scene .control .Button ;
3335
3436import org .fxmisc .richtext .Codec ;
3537import org .fxmisc .richtext .InlineStyleTextArea ;
38+ import org .fxmisc .richtext .Paragraph ;
39+ import org .fxmisc .richtext .StyleSpan ;
3640import org .fxmisc .richtext .StyleSpans ;
3741import org .reactfx .SuspendableNo ;
3842
@@ -180,14 +184,16 @@ private static String cssColor(Color color) {
180184 final Optional <Color > backgroundColor ;
181185
182186 public StyleInfo () {
183- bold = Optional .empty ();
184- italic = Optional .empty ();
185- underline = Optional .empty ();
186- strikethrough = Optional .empty ();
187- fontSize = Optional .empty ();
188- fontFamily = Optional .empty ();
189- textColor = Optional .empty ();
190- backgroundColor = Optional .empty ();
187+ this (
188+ Optional .empty (),
189+ Optional .empty (),
190+ Optional .empty (),
191+ Optional .empty (),
192+ Optional .empty (),
193+ Optional .empty (),
194+ Optional .empty (),
195+ Optional .empty ()
196+ );
191197 }
192198
193199 public StyleInfo (
@@ -338,31 +344,34 @@ public static void main(String[] args) {
338344 launch (args );
339345 }
340346
341- private final InlineStyleTextArea <StyleInfo > area =
342- new InlineStyleTextArea <StyleInfo >(
347+ private final InlineStyleTextArea <StyleInfo , StyleInfo > area =
348+ new InlineStyleTextArea <>(
343349 StyleInfo .EMPTY .updateFontSize (12 ).updateFontFamily ("Serif" ).updateTextColor (Color .BLACK ),
344- style -> style .toCss ());
350+ StyleInfo ::toCss ,
351+ StyleInfo .EMPTY ,
352+ StyleInfo ::toCss );
345353 {
346354 area .setWrapText (true );
347355 area .setStyleCodec (StyleInfo .CODEC );
348356 }
349357
350358 private final SuspendableNo updatingToolbar = new SuspendableNo ();
359+ private final BooleanProperty applyToParagraph = new SimpleBooleanProperty (false );
351360
352361 @ Override
353362 public void start (Stage primaryStage ) {
354363 CheckBox wrapToggle = new CheckBox ("Wrap" );
355364 wrapToggle .setSelected (true );
356365 area .wrapTextProperty ().bind (wrapToggle .selectedProperty ());
357- Button undoBtn = createButton ("undo" , () -> area . undo () );
358- Button redoBtn = createButton ("redo" , () -> area . redo () );
359- Button cutBtn = createButton ("cut" , () -> area . cut () );
360- Button copyBtn = createButton ("copy" , () -> area . copy () );
361- Button pasteBtn = createButton ("paste" , () -> area . paste () );
362- Button boldBtn = createButton ("bold" , () -> toggleBold () );
363- Button italicBtn = createButton ("italic" , () -> toggleItalic () );
364- Button underlineBtn = createButton ("underline" , () -> toggleUnderline () );
365- Button strikeBtn = createButton ("strikethrough" , () -> toggleStrikethrough () );
366+ Button undoBtn = createButton ("undo" , area :: undo );
367+ Button redoBtn = createButton ("redo" , area :: redo );
368+ Button cutBtn = createButton ("cut" , area :: cut );
369+ Button copyBtn = createButton ("copy" , area :: copy );
370+ Button pasteBtn = createButton ("paste" , area :: paste );
371+ Button boldBtn = createButton ("bold" , this :: toggleBold );
372+ Button italicBtn = createButton ("italic" , this :: toggleItalic );
373+ Button underlineBtn = createButton ("underline" , this :: toggleUnderline );
374+ Button strikeBtn = createButton ("strikethrough" , this :: toggleStrikethrough );
366375 ComboBox <Integer > sizeCombo = new ComboBox <>(FXCollections .observableArrayList (5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 16 , 18 , 20 , 22 , 24 , 28 , 32 , 36 , 40 , 48 , 56 , 64 , 72 ));
367376 sizeCombo .getSelectionModel ().select (Integer .valueOf (12 ));
368377 ComboBox <String > familyCombo = new ComboBox <>(FXCollections .observableList (Font .getFamilies ()));
@@ -407,9 +416,9 @@ protected boolean computeValue() {
407416 strike = styles .styleStream ().anyMatch (s -> s .strikethrough .orElse (false ));
408417 int [] sizes = styles .styleStream ().mapToInt (s -> s .fontSize .orElse (-1 )).distinct ().toArray ();
409418 fontSize = sizes .length == 1 ? sizes [0 ] : -1 ;
410- String [] families = styles .styleStream ().map (s -> s .fontFamily .orElse (null )).distinct ().toArray (i -> new String [i ] );
419+ String [] families = styles .styleStream ().map (s -> s .fontFamily .orElse (null )).distinct ().toArray (String []:: new );
411420 fontFamily = families .length == 1 ? families [0 ] : null ;
412- Color [] colors = styles .styleStream ().map (s -> s .textColor .orElse (null )).distinct ().toArray (i -> new Color [i ] );
421+ Color [] colors = styles .styleStream ().map (s -> s .textColor .orElse (null )).distinct ().toArray (Color []:: new );
413422 textColor = colors .length == 1 ? colors [0 ] : null ;
414423 Color [] backgrounds = styles .styleStream ().map (s -> s .backgroundColor .orElse (null )).distinct ().toArray (i -> new Color [i ]);
415424 backgroundColor = backgrounds .length == 1 ? backgrounds [0 ] : null ;
@@ -511,19 +520,35 @@ private Button createButton(String styleClass, Runnable action) {
511520 }
512521
513522 private void toggleBold () {
514- updateStyleInSelection (spans -> StyleInfo .EMPTY .updateBold (!spans .styleStream ().allMatch (style -> style .bold .orElse (false ))));
523+ if (!applyToParagraph .get ()) {
524+ updateStyleInSelection (spans -> StyleInfo .EMPTY .updateBold (!spans .styleStream ().allMatch (style -> style .bold .orElse (false ))));
525+ } else {
526+ updateParagraphStyleInSelection (styleInfo -> styleInfo .updateBold (!styleInfo .bold .orElse (false )));
527+ }
515528 }
516529
517530 private void toggleItalic () {
518- updateStyleInSelection (spans -> StyleInfo .EMPTY .updateItalic (!spans .styleStream ().allMatch (style -> style .italic .orElse (false ))));
531+ if (!applyToParagraph .get ()) {
532+ updateStyleInSelection (spans -> StyleInfo .EMPTY .updateItalic (!spans .styleStream ().allMatch (style -> style .italic .orElse (false ))));
533+ } else {
534+ updateParagraphStyleInSelection (styleInfo -> styleInfo .updateItalic (!styleInfo .italic .orElse (false )));
535+ }
519536 }
520537
521538 private void toggleUnderline () {
522- updateStyleInSelection (spans -> StyleInfo .EMPTY .updateUnderline (!spans .styleStream ().allMatch (style -> style .underline .orElse (false ))));
539+ if (!applyToParagraph .get ()) {
540+ updateStyleInSelection (spans -> StyleInfo .EMPTY .updateUnderline (!spans .styleStream ().allMatch (style -> style .underline .orElse (false ))));
541+ } else {
542+ updateParagraphStyleInSelection (styleInfo -> styleInfo .updateUnderline (!styleInfo .underline .orElse (false )));
543+ }
523544 }
524545
525546 private void toggleStrikethrough () {
526- updateStyleInSelection (spans -> StyleInfo .EMPTY .updateStrikethrough (!spans .styleStream ().allMatch (style -> style .strikethrough .orElse (false ))));
547+ if (!applyToParagraph .get ()) {
548+ updateStyleInSelection (spans -> StyleInfo .EMPTY .updateStrikethrough (!spans .styleStream ().allMatch (style -> style .strikethrough .orElse (false ))));
549+ } else {
550+ updateParagraphStyleInSelection (styleInfo -> styleInfo .updateStrikethrough (!styleInfo .strikethrough .orElse (false )));
551+ }
527552 }
528553
529554 private void updateStyleInSelection (Function <StyleSpans <StyleInfo >, StyleInfo > mixinGetter ) {
@@ -538,34 +563,55 @@ private void updateStyleInSelection(Function<StyleSpans<StyleInfo>, StyleInfo> m
538563
539564 private void updateStyleInSelection (StyleInfo mixin ) {
540565 IndexRange selection = area .getSelection ();
541- if (selection .getLength () != 0 ) {
566+ if (selection .getLength () != 0 ) {
542567 StyleSpans <StyleInfo > styles = area .getStyleSpans (selection );
543568 StyleSpans <StyleInfo > newStyles = styles .mapStyles (style -> style .updateWith (mixin ));
544569 area .setStyleSpans (selection .getStart (), newStyles );
545570 }
546571 }
547572
573+ private void updateParagraphStyleInSelection (Function <StyleInfo , StyleInfo > updater ) {
574+ Paragraph <StyleInfo , StyleInfo > paragraph = area .getParagraph (area .getCurrentParagraph ());
575+ paragraph .setParagraphStyle (updater .apply (paragraph .getParagraphStyle ()));
576+ }
577+
548578 private void updateFontSize (Integer size ) {
549579 if (!updatingToolbar .get ()) {
550- updateStyleInSelection (StyleInfo .fontSize (size ));
580+ if (!applyToParagraph .get ()) {
581+ updateStyleInSelection (StyleInfo .fontSize (size ));
582+ } else {
583+ updateParagraphStyleInSelection (styleInfo -> styleInfo .updateFontSize (size ));
584+ }
551585 }
552586 }
553587
554588 private void updateFontFamily (String family ) {
555589 if (!updatingToolbar .get ()) {
556- updateStyleInSelection (StyleInfo .fontFamily (family ));
590+ if (!applyToParagraph .get ()) {
591+ updateStyleInSelection (StyleInfo .fontFamily (family ));
592+ } else {
593+ updateParagraphStyleInSelection (styleInfo -> styleInfo .updateFontFamily (family ));
594+ }
557595 }
558596 }
559597
560598 private void updateTextColor (Color color ) {
561599 if (!updatingToolbar .get ()) {
562- updateStyleInSelection (StyleInfo .textColor (color ));
600+ if (!applyToParagraph .get ()) {
601+ updateStyleInSelection (StyleInfo .textColor (color ));
602+ } else {
603+ updateParagraphStyleInSelection (styleInfo -> styleInfo .updateTextColor (color ));
604+ }
563605 }
564606 }
565607
566608 private void updateBackgroundColor (Color color ) {
567609 if (!updatingToolbar .get ()) {
568- updateStyleInSelection (StyleInfo .backgroundColor (color ));
610+ if (!applyToParagraph .get ()) {
611+ updateStyleInSelection (StyleInfo .backgroundColor (color ));
612+ } else {
613+ updateParagraphStyleInSelection (styleInfo -> styleInfo .updateBackgroundColor (color ));
614+ }
569615 }
570616 }
571617}
0 commit comments