├── fx8-swingempire ├── src │ ├── .gitignore │ ├── demo │ │ └── de │ │ │ └── swingempire │ │ │ └── fx │ │ │ ├── control │ │ │ ├── backups │ │ │ │ ├── commitonfocuslost.css~0 │ │ │ │ └── focusedtablecell.css~0 │ │ │ ├── commitonfocuslost.css │ │ │ ├── focusedtablecell.css │ │ │ ├── comboboxsize.css │ │ │ ├── choiceitems.fxml │ │ │ ├── choicecomboitems.fxml │ │ │ ├── treetextonly.css │ │ │ ├── ChoiceItemsMain.java │ │ │ ├── ChoiceComboItemsMain.java │ │ │ ├── CommitOnFocusLostComboSkin.java │ │ │ ├── ImmutableObservableList.java │ │ │ ├── ComboBoxSize.java │ │ │ ├── treetextonlyso.css │ │ │ ├── BaselineInHBox.java │ │ │ ├── DynamicTooltipRT_40080.java │ │ │ ├── ComboWithConverter.java │ │ │ ├── SliderBug_8089730.java │ │ │ ├── SliderSnapToTickBug.java │ │ │ ├── TableVisibleRowCountEckig.java │ │ │ ├── layout │ │ │ │ └── ChatBubbleDriver.java │ │ │ ├── TreeEllipsisNoScrollRT_19468.java │ │ │ ├── ChoiceItemsView.java │ │ │ ├── ChoiceComboItemsView.java │ │ │ ├── CommitOnFocusLostWithStyleSheet.java │ │ │ ├── SynchScrollBars.java │ │ │ └── DynamicTooltipMouseLocation.java │ │ │ ├── chart │ │ │ ├── chartstyles.css │ │ │ ├── ChartColorCSS.java │ │ │ └── HorizontalBarExample.java │ │ │ ├── scene │ │ │ └── control │ │ │ │ ├── et │ │ │ │ ├── focusedlistcell.css │ │ │ │ ├── ContextMenuKeyboard.java │ │ │ │ └── LabeledFocus.java │ │ │ │ ├── table │ │ │ │ └── toggle │ │ │ │ │ ├── Person.java │ │ │ │ │ ├── People.fxml │ │ │ │ │ ├── PeopleX.fxml │ │ │ │ │ ├── MainApp.java │ │ │ │ │ ├── MainAppX.java │ │ │ │ │ └── PeopleController.java │ │ │ │ ├── tree │ │ │ │ ├── TreeItemStreamSupport.java │ │ │ │ ├── TreeItemIterator.java │ │ │ │ └── TableEdit.java │ │ │ │ ├── comboboxx │ │ │ │ ├── EditableComboActionHandlerRT_35586.java │ │ │ │ ├── Combo15793Regression.java │ │ │ │ ├── ComboBoxStringConverter.java │ │ │ │ ├── ComboBoxStringConverterRT_32919.java │ │ │ │ ├── CanNotRenderPromptTextInComboBoxRT_22930.java │ │ │ │ └── ComboSelectBugRT_38886.java │ │ │ │ ├── selection │ │ │ │ ├── NullComboBoxApp.java │ │ │ │ ├── TableViewSelectionBugMinimal_38884.java │ │ │ │ ├── ListViewSelectionBugMinimal_38884.java │ │ │ │ ├── TableSortNPEIfNullItems.java │ │ │ │ ├── TreeViewSelection_16068.java │ │ │ │ ├── ListViewSelection_37632.java │ │ │ │ ├── TreeTableReorderNullPointerException.java │ │ │ │ ├── TreeViewSample_RT_38334.java │ │ │ │ ├── ListViewItemBug_37632.java │ │ │ │ ├── MultipleSelectionModelBase_RT_40185.java │ │ │ │ ├── TableSortNPEIfNullSelectionModel.java │ │ │ │ ├── ListFocusedCellDefault_38517.java │ │ │ │ ├── ListSelectedItemRT_28637.java │ │ │ │ ├── LookupApp_35039.java │ │ │ │ └── TreeViewSelectionRT_38341.java │ │ │ │ ├── cell │ │ │ │ ├── Person22463.java │ │ │ │ └── chartcell.css │ │ │ │ └── text │ │ │ │ ├── TextFlowExample.java │ │ │ │ └── ThousandSeparatorFormatter.java │ │ │ ├── property │ │ │ ├── albumdemo │ │ │ │ ├── AlbumFxManagerModel.java │ │ │ │ └── AlbumFxDriver.java │ │ │ └── BindingDemo.java │ │ │ ├── graphic │ │ │ └── DragTest.java │ │ │ ├── swing │ │ │ └── FXApplet.java │ │ │ └── concurrency │ │ │ └── ProgressTask.java │ ├── java │ │ └── de │ │ │ └── swingempire │ │ │ └── fx │ │ │ ├── collection │ │ │ ├── .gitignore │ │ │ └── Filters.java │ │ │ ├── scene │ │ │ └── control │ │ │ │ ├── slider │ │ │ │ └── XSliderBehavior.java │ │ │ │ ├── skin │ │ │ │ ├── patch8 │ │ │ │ │ ├── VirtualFlow.java │ │ │ │ │ └── BehaviorBase.java │ │ │ │ └── patch │ │ │ │ │ ├── VirtualFlow.java │ │ │ │ │ ├── BehaviorBase.java │ │ │ │ │ └── VirtualContainerBase.java │ │ │ │ ├── tree │ │ │ │ ├── TreeItemPredicate.java │ │ │ │ └── Leafness.java │ │ │ │ ├── choiceboxx │ │ │ │ ├── SeparatorMarker.java │ │ │ │ ├── ChoiceBoxSkinRT38724.java │ │ │ │ └── ChoiceBoxRT38724.java │ │ │ │ ├── et │ │ │ │ ├── TableRowET.java │ │ │ │ ├── TableViewET.java │ │ │ │ ├── TableViewETSkin.java │ │ │ │ └── TableRowETSkin.java │ │ │ │ ├── cell │ │ │ │ ├── XTableCellSkin.java │ │ │ │ └── TableRowSkinX.java │ │ │ │ ├── selection │ │ │ │ ├── SimpleTreeSelectionModel.java │ │ │ │ ├── FocusModelSlave.java │ │ │ │ ├── DefaultSelectionModelJ.java │ │ │ │ ├── SimpleListSelectionModel.java │ │ │ │ ├── IndexedItemsController.java │ │ │ │ ├── MultipleSelectionController.java │ │ │ │ ├── TreeSelectionController.java │ │ │ │ └── ListViewAnchored.java │ │ │ │ ├── ControlUtils.java │ │ │ │ └── pagination │ │ │ │ └── NavigationModel.java │ │ │ └── property │ │ │ ├── BooleanChangeMarker.java │ │ │ ├── Trigger.java │ │ │ ├── DynamicBooleanBinding.java │ │ │ └── BidirectionalBinding.java │ ├── test │ │ ├── de │ │ │ └── swingempire │ │ │ │ └── fx │ │ │ │ ├── property │ │ │ │ ├── ObservableListTest.java │ │ │ │ ├── PropertyIgnores.java │ │ │ │ └── TriggerTest.java │ │ │ │ ├── scene │ │ │ │ └── control │ │ │ │ │ ├── TreeIgnores.java │ │ │ │ │ ├── selection │ │ │ │ │ ├── TableCoreMultipleSelectionIssues.java │ │ │ │ │ ├── ComboBoxSelectionIssues.java │ │ │ │ │ ├── SelectionUtils.java │ │ │ │ │ └── TreeSimpleMultipleSelectionIssues.java │ │ │ │ │ ├── pagination │ │ │ │ │ └── DirectPaginationTest.java │ │ │ │ │ └── CheckBoxTreeCell_32620Plain.java │ │ │ │ ├── junit │ │ │ │ ├── DummyExtended.java │ │ │ │ ├── DummyTestWithPlatformRunner.java │ │ │ │ ├── DummyTestWithRules.java │ │ │ │ └── DummyTestConditionalIgnore.java │ │ │ │ └── util │ │ │ │ └── FXUtilsTest.java │ │ └── fx │ │ │ └── collection │ │ │ └── SimpleTest.java │ └── testsupport │ │ └── de │ │ └── swingempire │ │ └── fx │ │ ├── junit │ │ └── FXThreadingRule.java │ │ └── util │ │ ├── InvalidationReport.java │ │ ├── StageLoader.java │ │ ├── ChangeReport.java │ │ └── ListChangeReport.java ├── .gitignore ├── lib │ └── reactfx-1.4.jar └── .classpath └── README.md /fx8-swingempire/src/.gitignore: -------------------------------------------------------------------------------- 1 | /corecopy 2 | /local 3 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/backups/commitonfocuslost.css~0: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fx8-swingempire/.gitignore: -------------------------------------------------------------------------------- 1 | /classes 2 | /.classpath 3 | /.project 4 | /.settings 5 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/collection/.gitignore: -------------------------------------------------------------------------------- 1 | /TestDiagram.jpg 2 | /TestDiagram.png 3 | /TestDiagram.xml 4 | -------------------------------------------------------------------------------- /fx8-swingempire/lib/reactfx-1.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kleopatra/swingempire-fx/HEAD/fx8-swingempire/lib/reactfx-1.4.jar -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/commitonfocuslost.css: -------------------------------------------------------------------------------- 1 | .combo-box { 2 | -fx-skin: "de.swingempire.fx.control.CommitOnFocusLostComboSkin"; 3 | } 4 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/chart/chartstyles.css: -------------------------------------------------------------------------------- 1 | .default-color3.chart-bar { 2 | -fx-bar-fill: black; 3 | } 4 | 5 | .default-color0.chart-pie { 6 | -fx-pie-color: black; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/property/ObservableListTest.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kleopatra/swingempire-fx/HEAD/fx8-swingempire/src/test/de/swingempire/fx/property/ObservableListTest.java -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/slider/XSliderBehavior.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kleopatra/swingempire-fx/HEAD/fx8-swingempire/src/java/de/swingempire/fx/scene/control/slider/XSliderBehavior.java -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/focusedtablecell.css: -------------------------------------------------------------------------------- 1 | .table-view:focused:row-selection > .virtual-flow > .clipped-container > .sheet > .table-cell:focused, 2 | .table-cell:focused 3 | { 4 | -fx-border-color: yellow; 5 | -fx-border-insets: 2; 6 | } 7 | 8 | 9 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/comboboxsize.css: -------------------------------------------------------------------------------- 1 | .combo-box-base > *.arrow-button { 2 | -fx-padding: 0 0 0 0; 3 | -fx-background-color: pink, pink, pink, pink; 4 | } 5 | 6 | #.combo-box > .list-cell { 7 | # -fx-padding: 0 0 0 0; 8 | # -fx-border-insets: 0 0 0 0; 9 | #} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # swingempire-fx 2 | Bits and pieces for javafx 3 | 4 | Nothing more than my public notebook ;) 5 | 6 | The latest code is in branch master9 (note-to-self: make it the real master), current work centers around TextField and EventDispatch 7 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/et/focusedlistcell.css: -------------------------------------------------------------------------------- 1 | .list-cell:filled:selected { 2 | -fx-background: -fx-selection-bar; 3 | -fx-table-cell-border-color: derive(-fx-selection-bar, 20%); 4 | } 5 | 6 | .list-cell:focused { 7 | -fx-background-color: -fx-background, -fx-cell-focus-inner-border, -fx-background; 8 | -fx-background-insets: 0, 1, 2; 9 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/skin/patch8/VirtualFlow.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 15.03.2016 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.skin.patch8; 6 | 7 | import javafx.scene.control.IndexedCell; 8 | 9 | 10 | /** 11 | * @author Jeanette Winzenburg, Berlin 12 | */ 13 | public class VirtualFlow 14 | extends com.sun.javafx.scene.control.skin.VirtualFlow { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/skin/patch/VirtualFlow.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 15.03.2016 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.skin.patch; 6 | 7 | import javafx.scene.control.IndexedCell; 8 | 9 | 10 | /** 11 | * @author Jeanette Winzenburg, Berlin 12 | */ 13 | public class VirtualFlow 14 | extends de.swingempire.fx.scene.control.skin.patch8.VirtualFlow { 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /fx8-swingempire/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/skin/patch/BehaviorBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 15.03.2016 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.skin.patch; 6 | 7 | import javafx.scene.control.Control; 8 | 9 | 10 | /** 11 | * @author Jeanette Winzenburg, Berlin 12 | */ 13 | public abstract class BehaviorBase 14 | extends de.swingempire.fx.scene.control.skin.patch8.BehaviorBase { 15 | 16 | public BehaviorBase(C control, String bindingsKey) { 17 | super(control, bindingsKey); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/scene/control/TreeIgnores.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 08.01.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control; 6 | 7 | import com.codeaffine.test.ConditionalIgnoreRule.IgnoreCondition; 8 | 9 | 10 | /** 11 | * @author Jeanette Winzenburg, Berlin 12 | */ 13 | public class TreeIgnores { 14 | 15 | public static class IgnoreLog implements IgnoreCondition { 16 | 17 | @Override 18 | public boolean isSatisfied() { 19 | return true; 20 | } 21 | 22 | } 23 | 24 | private TreeIgnores() {}; 25 | } 26 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/tree/TreeItemPredicate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 16.06.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.tree; 6 | 7 | import java.util.function.Predicate; 8 | 9 | import javafx.scene.control.TreeItem; 10 | 11 | /** 12 | * Filtering Tree: all related classes copied from 13 | * http://www.kware.net/?p=204 14 | */ 15 | @FunctionalInterface 16 | public interface TreeItemPredicate { 17 | 18 | boolean test(TreeItem parent, T value); 19 | 20 | static TreeItemPredicate create(Predicate predicate) { 21 | return (parent, value) -> predicate.test(value); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/choiceitems.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/choicecomboitems.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/treetextonly.css: -------------------------------------------------------------------------------- 1 | /* remove the highligh from cell as a whole, c&p from modena */ 2 | .tree-text-only:filled:selected { 3 | -fx-background: -fx-control-inner-background; 4 | /* -fx-background-color: -fx-background; */ 5 | } 6 | 7 | .tree-text-only:filled:selected > .label { 8 | /* following is the selection color from themes, doesn't show */ 9 | -fx-background: -fx-selection-bar; 10 | -fx-background-color: -fx-background; 11 | /* hard-coded color does show */ 12 | /* -fx-background-color: -fx-accent ; */ 13 | -fx-background-color: CHART_COLOR_2 ; 14 | /* auto-adjust text fill */ 15 | /* no effect for hard-coded color, showing nothing for selection bar */ 16 | /*-fx-text-fill: -fx-text-background-color;*/ 17 | } 18 | 19 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/table/toggle/Person.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 11.08.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.table.toggle; 6 | 7 | import javafx.beans.property.SimpleStringProperty; 8 | import javafx.beans.property.StringProperty; 9 | 10 | public class Person { 11 | private final StringProperty name; 12 | 13 | public Person() { 14 | this(null); 15 | } 16 | 17 | public Person(String name) { 18 | this.name = new SimpleStringProperty(name); 19 | } 20 | 21 | public String getName() { 22 | return name.get(); 23 | } 24 | 25 | public void setName(String name) { 26 | this.name.set(name); 27 | } 28 | 29 | public StringProperty nameProperty() { 30 | return name; 31 | } 32 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/junit/DummyExtended.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 30.09.2014 3 | * 4 | */ 5 | package de.swingempire.fx.junit; 6 | 7 | import org.junit.Rule; 8 | import org.junit.runner.RunWith; 9 | import org.junit.runners.JUnit4; 10 | 11 | import com.codeaffine.test.ConditionalIgnoreRule; 12 | 13 | /** 14 | * @author Jeanette Winzenburg, Berlin 15 | */ 16 | @SuppressWarnings({ "rawtypes", "unchecked" }) 17 | @RunWith(JUnit4.class) 18 | public class DummyExtended extends DummyTestConditionalIgnore { 19 | // repeating the role from super doesn't help 20 | // @Rule 21 | // public ConditionalIgnoreRule rule = new ConditionalIgnoreRule(); 22 | 23 | /** 24 | * @return 25 | */ 26 | @Override 27 | public boolean supportsSeparators() { 28 | return false; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/choiceboxx/SeparatorMarker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 28.09.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.choiceboxx; 6 | 7 | /** 8 | * A tagging interface used to denote a separator. 9 | * 10 | * Note: this is not really nice because 11 | *
  • needs cooperation of both 12 | * ChoiceBoxSelectionModel and ChoiceBoxSkin. The latter 13 | * is deeply buried in private code 14 | *
  • needs a dummy extension of the custom type 15 | * that implements it 16 | *
  • isn't applicable for primitive types, in particular String 17 | * 18 | *

    19 | * 20 | * PENDING JW: 21 | * let choiceBox support a list of separators independent of the actual data 22 | * 23 | * @author Jeanette Winzenburg, Berlin 24 | */ 25 | public interface SeparatorMarker { 26 | 27 | } 28 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/skin/patch/VirtualContainerBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 15.03.2016 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.skin.patch; 6 | 7 | import javafx.scene.control.Control; 8 | import javafx.scene.control.IndexedCell; 9 | 10 | /** 11 | * The glue layer: must talk to either patch8 or patch9. 12 | * 13 | * @author Jeanette Winzenburg, Berlin 14 | */ 15 | public abstract class VirtualContainerBase 16 | extends de.swingempire.fx.scene.control.skin.patch8.VirtualContainerBase { 17 | 18 | public VirtualContainerBase(C control, Object behavior) { 19 | super(control, behavior); 20 | } 21 | 22 | @Override 23 | protected VirtualFlow createVirtualFlow() { 24 | return new VirtualFlow<>(); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/collection/Filters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 12.02.2015 3 | * 4 | */ 5 | package de.swingempire.fx.collection; 6 | 7 | import java.util.Objects; 8 | import java.util.function.Predicate; 9 | 10 | /** 11 | * @author Jeanette Winzenburg, Berlin 12 | */ 13 | public class Filters { 14 | 15 | public static class EqualsPredicate implements Predicate { 16 | 17 | private T matchValue; 18 | 19 | public EqualsPredicate(T matchValue) { 20 | this.matchValue = Objects.requireNonNull(matchValue); 21 | } 22 | @Override 23 | public boolean test(T t) { 24 | return matchValue.equals(t); 25 | } 26 | 27 | protected boolean areEquals() { 28 | return false; 29 | } 30 | } 31 | 32 | private Filters() {}; 33 | } 34 | -------------------------------------------------------------------------------- /fx8-swingempire/src/testsupport/de/swingempire/fx/junit/FXThreadingRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 23.06.2014 3 | * 4 | */ 5 | package de.swingempire.fx.junit; 6 | 7 | 8 | import javafx.application.Platform; 9 | import org.junit.rules.TestRule; 10 | import org.junit.runner.Description; 11 | import org.junit.runners.model.Statement; 12 | 13 | /** 14 | * Method rule as precondition for all fx-tests. 15 | * @author kleopatra 16 | */ 17 | public class FXThreadingRule implements TestRule { 18 | 19 | @Override 20 | public Statement apply(Statement base, Description description) { 21 | System.out.println("threading rule: on fx-at " + Platform.isFxApplicationThread()); 22 | if (!Platform.isFxApplicationThread()) 23 | throw new IllegalStateException("test must be run on fx-at " + description ); 24 | return base; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/table/toggle/People.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/table/toggle/PeopleX.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/tree/TreeItemStreamSupport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 17.12.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.tree; 6 | 7 | import java.util.stream.Stream; 8 | import java.util.stream.StreamSupport; 9 | 10 | import javafx.scene.control.TreeItem; 11 | 12 | /** 13 | * Answer by jewelsea 14 | * http://stackoverflow.com/a/26810381/203657 15 | * Provide a stream of tree items from a root tree item. 16 | */ 17 | public class TreeItemStreamSupport { 18 | public static Stream> stream(TreeItem rootItem) { 19 | return asStream(new TreeItemIterator<>(rootItem)); 20 | } 21 | 22 | private static Stream> asStream(TreeItemIterator iterator) { 23 | Iterable> iterable = () -> iterator; 24 | 25 | return StreamSupport.stream( 26 | iterable.spliterator(), 27 | false 28 | ); 29 | } 30 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/ChoiceItemsMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 31.08.2014 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import javafx.application.Application; 8 | import javafx.fxml.FXMLLoader; 9 | import javafx.scene.Parent; 10 | import javafx.scene.Scene; 11 | import javafx.stage.Stage; 12 | 13 | import com.sun.glass.ui.View; 14 | 15 | public class ChoiceItemsMain extends Application { 16 | private Parent rootPane; 17 | @Override 18 | public void start(Stage arg0) throws Exception { 19 | Scene scene = new Scene(rootPane); 20 | arg0.setScene(scene); 21 | arg0.show(); 22 | } 23 | @Override 24 | public void init() throws Exception { 25 | FXMLLoader loader = new FXMLLoader(getClass().getResource("choiceitems.fxml")); 26 | rootPane = loader.load(); 27 | loader.getController().init(); 28 | } 29 | public static void main(String[] args) { 30 | launch(args); 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/ChoiceComboItemsMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 31.08.2014 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import javafx.application.Application; 8 | import javafx.fxml.FXMLLoader; 9 | import javafx.scene.Parent; 10 | import javafx.scene.Scene; 11 | import javafx.stage.Stage; 12 | 13 | import com.sun.glass.ui.View; 14 | 15 | public class ChoiceComboItemsMain extends Application { 16 | private Parent rootPane; 17 | @Override 18 | public void start(Stage arg0) throws Exception { 19 | Scene scene = new Scene(rootPane); 20 | arg0.setScene(scene); 21 | arg0.show(); 22 | } 23 | @Override 24 | public void init() throws Exception { 25 | FXMLLoader loader = new FXMLLoader(getClass().getResource("choicecomboitems.fxml")); 26 | rootPane = loader.load(); 27 | loader.getController().init(); 28 | } 29 | public static void main(String[] args) { 30 | launch(args); 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/CommitOnFocusLostComboSkin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 23.09.2015 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import javafx.scene.control.ComboBox; 8 | 9 | import com.sun.javafx.scene.control.skin.ComboBoxListViewSkin; 10 | 11 | /** 12 | * Subclass of ComboBoxListViewSkin that forces commit-on-focusLost. Implemented in 13 | * a listener to focusedProperty to call the appropriate protected method of super. 14 | * 15 | * @author Jeanette Winzenburg, Berlin 16 | */ 17 | public class CommitOnFocusLostComboSkin extends ComboBoxListViewSkin { 18 | 19 | public CommitOnFocusLostComboSkin(ComboBox comboBox) { 20 | super(comboBox); 21 | getSkinnable().focusedProperty().addListener((source, ov, nv) -> { 22 | if (!nv) { 23 | // this method is exposed post-jdk845 24 | setTextFromTextFieldIntoComboBoxValue(); 25 | } 26 | }); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/property/BooleanChangeMarker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 30.05.2014 3 | * 4 | */ 5 | package de.swingempire.fx.property; 6 | 7 | import javafx.beans.property.ReadOnlyBooleanPropertyBase; 8 | 9 | /** 10 | * Marker property: always same value (false) but allows to manually fire an invalidation event. 11 | * 12 | * Trying to implement a dynamic boolean or binding. 13 | * 14 | * @author Jeanette Winzenburg, Berlin 15 | */ 16 | public class BooleanChangeMarker extends ReadOnlyBooleanPropertyBase { 17 | 18 | 19 | /** 20 | * Overridden to allow external access. 21 | */ 22 | @Override 23 | public void fireValueChangedEvent() { 24 | super.fireValueChangedEvent(); 25 | } 26 | 27 | @Override 28 | public Object getBean() { 29 | return null; 30 | } 31 | 32 | @Override 33 | public String getName() { 34 | return null; 35 | } 36 | 37 | @Override 38 | public boolean get() { 39 | return false; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/tree/TreeItemIterator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 17.12.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.tree; 6 | 7 | import java.util.Iterator; 8 | import java.util.Stack; 9 | 10 | import javafx.scene.control.TreeItem; 11 | 12 | /** 13 | * Answer by jewelsea 14 | * http://stackoverflow.com/a/26810381/203657 15 | * Iterate over items in a tree. 16 | * The tree should not be modified while this iterator is being used. 17 | * 18 | * @param the type of items stored in the tree. 19 | */ 20 | public class TreeItemIterator implements Iterator> { 21 | private Stack> stack = new Stack<>(); 22 | 23 | public TreeItemIterator(TreeItem root) { 24 | stack.push(root); 25 | } 26 | 27 | @Override 28 | public boolean hasNext() { 29 | return !stack.isEmpty(); 30 | } 31 | 32 | @Override 33 | public TreeItem next() { 34 | TreeItem nextItem = stack.pop(); 35 | nextItem.getChildren().forEach(stack::push); 36 | 37 | return nextItem; 38 | } 39 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/property/Trigger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 24.05.2014 3 | * 4 | */ 5 | package de.swingempire.fx.property; 6 | 7 | import javafx.beans.value.ObservableValueBase; 8 | 9 | /** 10 | * @author Jeanette Winzenburg, Berlin 11 | */ 12 | public class Trigger extends ObservableValueBase { 13 | private static final Boolean COMMIT = Boolean.TRUE; 14 | private static final Boolean FLUSH = Boolean.FALSE; 15 | private static final Boolean NEUTRAL = null; 16 | 17 | private Boolean state; 18 | 19 | @Override 20 | public Boolean getValue() { 21 | return state; 22 | } 23 | 24 | public void triggerCommit() { 25 | setState(COMMIT); 26 | } 27 | 28 | /** 29 | * @param commit2 30 | */ 31 | private void setState(Boolean state) { 32 | Boolean old = getValue(); 33 | if (old != null && old == state) { 34 | setState(null); 35 | } 36 | this.state = state; 37 | fireValueChangedEvent(); 38 | } 39 | 40 | public void triggerFlush() { 41 | setState(FLUSH); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/ImmutableObservableList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 14.04.2015 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import java.util.List; 8 | 9 | import javafx.collections.ObservableListBase; 10 | 11 | public class ImmutableObservableList extends ObservableListBase { 12 | 13 | private List backing; 14 | 15 | public ImmutableObservableList(List backingList) { 16 | this.backing = backingList; 17 | } 18 | 19 | public void setBackingList(List backingList) { 20 | beginChange(); 21 | if (this.backing != null) { 22 | nextRemove(0, this.backing); 23 | } 24 | this.backing = backingList; 25 | if (backingList != null) { 26 | nextAdd(0, backingList.size()); 27 | } 28 | endChange(); 29 | } 30 | @Override 31 | public E get(int index) { 32 | if (backing == null) throw new IndexOutOfBoundsException(); 33 | return backing.get(index); 34 | } 35 | 36 | @Override 37 | public int size() { 38 | return backing != null ? backing.size() : 0; 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/property/DynamicBooleanBinding.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 30.05.2014 3 | * 4 | */ 5 | package de.swingempire.fx.property; 6 | 7 | import javafx.beans.Observable; 8 | import javafx.beans.binding.BooleanBinding; 9 | 10 | /** 11 | * A boolean binding that supports adding observables. 12 | * 13 | * This is a trick: Bindings are designed for static dependencies, 14 | * there's no way to make it invalid except indirectly through 15 | * a change in a dependency. 16 | * 17 | * @author Jeanette Winzenburg, Berlin 18 | */ 19 | public abstract class DynamicBooleanBinding extends BooleanBinding { 20 | 21 | BooleanChangeMarker marker; 22 | 23 | public DynamicBooleanBinding() { 24 | marker = new BooleanChangeMarker(); 25 | bind(marker); 26 | } 27 | 28 | public void addDependencies(Observable... dependencies) { 29 | if (dependencies != null && dependencies.length > 0) { 30 | bind(dependencies); 31 | marker.fireValueChangedEvent(); 32 | } 33 | } 34 | // @Override 35 | // protected boolean computeValue() { 36 | // return false; 37 | // } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/property/albumdemo/AlbumFxManagerModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 01.06.2014 3 | * 4 | */ 5 | package de.swingempire.fx.property.albumdemo; 6 | 7 | import javafx.beans.property.ObjectProperty; 8 | import javafx.beans.property.SimpleObjectProperty; 9 | import javafx.collections.ObservableList; 10 | 11 | /** 12 | * @author Jeanette Winzenburg, Berlin 13 | */ 14 | public class AlbumFxManagerModel { 15 | 16 | private AlbumFxManager manager; 17 | private ObjectProperty current; 18 | 19 | public AlbumFxManagerModel(AlbumFxManager manager) { 20 | this.manager = manager; 21 | current = new SimpleObjectProperty(this, "currentAlbum", new AlbumFxModel()); 22 | } 23 | 24 | public ObservableList getManagedAlbums() { 25 | return manager.getManagedAlbums(); 26 | } 27 | 28 | /** 29 | * @return 30 | */ 31 | public AlbumFxModel getAlbumFxModel() { 32 | return current.get(); 33 | } 34 | 35 | /** 36 | * @param item 37 | * @return 38 | */ 39 | public String getText(AlbumFx item) { 40 | return item.getTitle(); 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/et/TableRowET.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 20.02.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.et; 6 | 7 | import javafx.event.EventDispatchChain; 8 | import javafx.event.EventTarget; 9 | import javafx.scene.control.Skin; 10 | import javafx.scene.control.TableRow; 11 | 12 | /** 13 | * TableRow with extended event dispatch. 14 | * 15 | * @author Jeanette Winzenburg, Berlin 16 | */ 17 | public class TableRowET extends TableRow { 18 | 19 | /** 20 | * Overridden to allow the skin to hook into the event dispatch chain, 21 | * before calling super. 22 | */ 23 | @Override 24 | public EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) { 25 | if (getSkin() instanceof EventTarget) { 26 | ((EventTarget) getSkin()).buildEventDispatchChain(tail); 27 | } 28 | return super.buildEventDispatchChain(tail); 29 | } 30 | 31 | /** 32 | * Overridden to return a skin that implements EventTarget. 33 | */ 34 | @Override 35 | protected Skin createDefaultSkin() { 36 | return new TableRowETSkin<>(this); 37 | } 38 | 39 | 40 | 41 | public TableRowET() { 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/comboboxx/EditableComboActionHandlerRT_35586.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 02.10.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.comboboxx; 6 | 7 | import javafx.application.Application; 8 | import javafx.event.ActionEvent; 9 | import javafx.event.EventHandler; 10 | import javafx.scene.Scene; 11 | import javafx.scene.control.ComboBox; 12 | import javafx.stage.Stage; 13 | 14 | /** 15 | * https://javafx-jira.kenai.com/browse/RT-35586 16 | * actionHandler notified twice 17 | * 18 | * fixed in 8u20 19 | */ 20 | public class EditableComboActionHandlerRT_35586 extends Application { 21 | public static void main(String[] args) { 22 | launch(args); 23 | } 24 | 25 | @Override 26 | public void start(Stage primaryStage) throws Exception { 27 | final ComboBox cb = new ComboBox(); 28 | cb.setEditable(true); 29 | cb.setOnAction(new EventHandler() { 30 | int counter = 0; 31 | 32 | @Override 33 | public void handle(ActionEvent event) { 34 | System.out.println(counter++); 35 | } 36 | }); 37 | primaryStage.setScene(new Scene(cb)); 38 | primaryStage.show(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/graphic/DragTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 01.10.2015 3 | * 4 | */ 5 | package de.swingempire.fx.graphic; 6 | 7 | import javafx.application.Application; 8 | import javafx.scene.Scene; 9 | import javafx.scene.layout.FlowPane; 10 | import javafx.scene.shape.Circle; 11 | import javafx.stage.Stage; 12 | 13 | /** 14 | * Performance 15 | * https://bugs.openjdk.java.net/browse/JDK-8087922 16 | * 17 | * Drag circle around and see cursor moving ahead (outside) 18 | * of the circle 19 | */ 20 | public class DragTest extends Application { 21 | @Override 22 | public void start(Stage stage) throws Exception { 23 | FlowPane flowPane = new FlowPane(); 24 | Scene scene = new Scene(flowPane, 500, 500); 25 | stage.setScene(scene); 26 | double circleRadius = 20; 27 | Circle circle = new Circle(circleRadius); 28 | circle.setOnMouseDragged(mouseEvent -> { 29 | circle.setTranslateX(mouseEvent.getSceneX() - circleRadius); 30 | circle.setTranslateY(mouseEvent.getSceneY() - circleRadius); 31 | }); 32 | flowPane.getChildren().add(circle); 33 | stage.show(); 34 | } 35 | 36 | public static void main(String[] args) { 37 | Application.launch(args); 38 | } 39 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/scene/control/selection/TableCoreMultipleSelectionIssues.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 02.06.2013 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.collections.ObservableList; 8 | import javafx.scene.control.SelectionMode; 9 | import javafx.scene.control.TableColumn; 10 | import javafx.scene.control.TableView; 11 | import javafx.scene.control.TableView.TableViewSelectionModel; 12 | 13 | import org.junit.runner.RunWith; 14 | import org.junit.runners.Parameterized; 15 | 16 | import static org.junit.Assert.*; 17 | 18 | /** 19 | * @author Jeanette Winzenburg, Berlin 20 | */ 21 | @SuppressWarnings({ "rawtypes", "unchecked" }) 22 | @RunWith(Parameterized.class) 23 | public class TableCoreMultipleSelectionIssues 24 | extends AbstractTableMultipleSelectionIssues { 25 | 26 | 27 | 28 | public TableCoreMultipleSelectionIssues(boolean multiple, boolean cellSelection) { 29 | super(multiple, cellSelection); 30 | } 31 | 32 | @Override 33 | protected TableView createEmptyView() { 34 | TableView table = new TableView(); 35 | TableColumn column = new TableColumn("numberedItems"); 36 | table.getColumns().add(column); 37 | return table; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /fx8-swingempire/src/testsupport/de/swingempire/fx/util/InvalidationReport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 24.05.2014 3 | * 4 | */ 5 | package de.swingempire.fx.util; 6 | 7 | import java.util.LinkedList; 8 | import java.util.List; 9 | 10 | import javafx.beans.InvalidationListener; 11 | import javafx.beans.Observable; 12 | import javafx.beans.value.ObservableValue; 13 | 14 | /** 15 | * @author Jeanette Winzenburg, Berlin 16 | */ 17 | public class InvalidationReport implements InvalidationListener { 18 | 19 | List sources = new LinkedList<>(); 20 | 21 | Observable source; 22 | 23 | public InvalidationReport() { 24 | this(null); 25 | } 26 | 27 | /** 28 | * @param object 29 | */ 30 | public InvalidationReport(Observable object) { 31 | source = object; 32 | source.addListener(this); 33 | } 34 | 35 | @Override 36 | public void invalidated(Observable observable) { 37 | sources.add(0, observable); 38 | } 39 | 40 | public int getEventCount() { 41 | return sources.size(); 42 | } 43 | 44 | public Object getLastSource() { 45 | return sources.size() > 0 ? sources.get(0) : null; 46 | } 47 | 48 | public void clear() { 49 | sources.clear(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/NullComboBoxApp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 18.09.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.application.Application; 8 | import javafx.collections.FXCollections; 9 | import javafx.scene.Scene; 10 | import javafx.scene.control.ComboBox; 11 | import javafx.scene.layout.StackPane; 12 | import javafx.stage.Stage; 13 | /** 14 | * http://stackoverflow.com/q/25877323/203657 15 | * add null to items throws in 8u20 16 | * it's a non-sensical requirement, though. 17 | */ 18 | public class NullComboBoxApp extends Application { 19 | 20 | @Override 21 | public void start(Stage primaryStage) { 22 | 23 | ComboBox cb = new ComboBox<>(FXCollections.observableArrayList( 24 | "Option 1", 25 | "Option 2", 26 | "Option 3" 27 | )); 28 | 29 | cb.getItems().add(null); 30 | 31 | StackPane root = new StackPane(); 32 | root.getChildren().add(cb); 33 | 34 | Scene scene = new Scene(root, 300, 250); 35 | 36 | primaryStage.setTitle("Null ComboBox Example"); 37 | primaryStage.setScene(scene); 38 | primaryStage.show(); 39 | } 40 | 41 | public static void main(String[] args) { 42 | launch(args); 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/cell/XTableCellSkin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 12.08.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.cell; 6 | 7 | import javafx.beans.property.BooleanProperty; 8 | import javafx.beans.property.ReadOnlyDoubleProperty; 9 | import javafx.scene.control.TableCell; 10 | import javafx.scene.control.TableColumn; 11 | 12 | import com.sun.javafx.scene.control.behavior.TableCellBehavior; 13 | import com.sun.javafx.scene.control.skin.TableCellSkinBase; 14 | 15 | /** 16 | * @author Jeanette Winzenburg, Berlin 17 | */ 18 | public class XTableCellSkin extends TableCellSkinBase, TableCellBehavior> { 19 | 20 | private final TableCell tableCell; 21 | private final TableColumn tableColumn; 22 | 23 | public XTableCellSkin(TableCell tableCell) { 24 | super(tableCell, new XTableCellBehavior(tableCell)); 25 | 26 | this.tableCell = tableCell; 27 | this.tableColumn = tableCell.getTableColumn(); 28 | 29 | super.init(tableCell); 30 | } 31 | 32 | @Override protected BooleanProperty columnVisibleProperty() { 33 | return tableColumn.visibleProperty(); 34 | } 35 | 36 | @Override protected ReadOnlyDoubleProperty columnWidthProperty() { 37 | return tableColumn.widthProperty(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/ComboBoxSize.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 31.08.2014 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import javafx.application.Application; 8 | import javafx.collections.FXCollections; 9 | import javafx.collections.ObservableList; 10 | import javafx.scene.Parent; 11 | import javafx.scene.Scene; 12 | import javafx.scene.control.ComboBox; 13 | import javafx.stage.Stage; 14 | 15 | /** 16 | * combo sizing not fully configurable 17 | * http://stackoverflow.com/q/24852429/203657 18 | * @author Jeanette Winzenburg, Berlin 19 | */ 20 | public class ComboBoxSize extends Application { 21 | 22 | /** 23 | * @return 24 | */ 25 | private Parent getContent() { 26 | ObservableList items = FXCollections.observableArrayList("Some longish item that is the only one"); 27 | ComboBox box = new ComboBox<>(items); 28 | box.setValue(items.get(0)); 29 | return box; 30 | } 31 | 32 | @Override 33 | public void start(Stage primaryStage) throws Exception { 34 | Scene scene = new Scene(getContent()); 35 | scene.getStylesheets().add(getClass().getResource("comboboxsize.css").toExternalForm()); 36 | primaryStage.setScene(scene); 37 | primaryStage.show(); 38 | 39 | } 40 | 41 | public static void main(String[] args) { 42 | launch(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/treetextonlyso.css: -------------------------------------------------------------------------------- 1 | /* 2 | * remove the highlight from cell as a whole 3 | */ 4 | 5 | /* Selected rows */ 6 | .tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-text-only:filled:selected { 7 | -fx-background: -fx-control-inner-background; 8 | } 9 | /* Selected when control is not focused */ 10 | .tree-text-only:filled:selected { 11 | -fx-background: -fx-control-inner-background; 12 | } 13 | /* focused cell (keyboard navigation) */ 14 | .tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-text-only:focused { 15 | -fx-cell-focus-inner-border: -fx-control-inner-background; 16 | } 17 | 18 | /* 19 | * highlight only the label 20 | */ 21 | 22 | // Add background color rule 23 | .tree-text-only > .label { 24 | -fx-background-color: -fx-background; 25 | } 26 | /* Selected rows */ 27 | .tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-text-only:filled:selected > .label { 28 | -fx-background: -fx-selection-bar; 29 | } 30 | /* Selected when control is not focused */ 31 | .tree-text-only:filled:selected > .label { 32 | -fx-background: -fx-selection-bar-non-focused; 33 | } 34 | /* focused cell (keyboard navigation) */ 35 | .tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-text-only:focused > .label { 36 | -fx-background: -fx-selection-bar; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/chart/ChartColorCSS.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 27.01.2015 3 | * 4 | */ 5 | package de.swingempire.fx.chart; 6 | 7 | import javafx.application.Application; 8 | import javafx.scene.Scene; 9 | import javafx.scene.control.Button; 10 | import javafx.scene.layout.HBox; 11 | import javafx.scene.shape.Rectangle; 12 | import javafx.stage.Stage; 13 | 14 | /** 15 | * Regression: CHART_COLOR_XX not accessible in 8u40b20, 16 | * works fine in 8u20 17 | * 18 | * Reported: https://javafx-jira.kenai.com/browse/RT-39899 19 | * Might be intentional, as CHART_COLOR_XX isn't specified. 20 | * 21 | * Evaluated as bug, marked as fixed for 8u60 22 | * 23 | * @author Jeanette Winzenburg, Berlin 24 | */ 25 | public class ChartColorCSS extends Application { 26 | 27 | public static void main(String[] args) { 28 | launch(args); 29 | } 30 | 31 | @Override 32 | public void start(Stage primaryStage) throws Exception { 33 | Rectangle r = new Rectangle(300, 400); 34 | Button button = new Button("style"); 35 | button.setOnAction(e -> 36 | r.setStyle("-fx-fill:CHART_COLOR_1;")); 37 | HBox root = new HBox(r, button); 38 | Scene scene = new Scene(root); 39 | primaryStage.setScene(scene); 40 | primaryStage.setTitle(System.getProperty("java.version")); 41 | primaryStage.show(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/selection/SimpleTreeSelectionModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 18.12.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.scene.control.FocusModel; 8 | import javafx.scene.control.TreeItem; 9 | import javafx.scene.control.TreeView; 10 | 11 | /** 12 | * @author Jeanette Winzenburg, Berlin 13 | */ 14 | public class SimpleTreeSelectionModel extends AbstractSelectionModelBase> { 15 | 16 | private TreeView treeView; 17 | private TreeBasedSelectionHelper helper; 18 | 19 | /** 20 | * 21 | */ 22 | public SimpleTreeSelectionModel(TreeView treeView) { 23 | this.treeView = treeView; 24 | controller = new TreeSelectionController<>(treeView); 25 | // PENDING JW: this is brittle: need to register _after_ controller! 26 | helper = new TreeBasedSelectionHelper(this, treeView); 27 | } 28 | 29 | @Override 30 | protected FocusModel> getFocusModel() { 31 | return treeView.getFocusModel(); 32 | } 33 | 34 | @Override 35 | protected void focus(int index) { 36 | if (getFocusModel() == null) return; 37 | getFocusModel().focus(index); 38 | } 39 | 40 | @Override 41 | protected int getFocusedIndex() { 42 | if (getFocusModel() == null) return -1; 43 | return getFocusModel().getFocusedIndex(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/TableViewSelectionBugMinimal_38884.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 18.11.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.application.Application; 8 | import javafx.application.Platform; 9 | import javafx.collections.FXCollections; 10 | import javafx.collections.ListChangeListener.Change; 11 | import javafx.collections.ObservableList; 12 | import javafx.scene.control.TableView; 13 | import javafx.stage.Stage; 14 | 15 | /** 16 | * not yet in 8u40b12 - could use for regression testing in custom ListViewSelection 17 | */ 18 | public class TableViewSelectionBugMinimal_38884 extends Application { 19 | @Override 20 | public void start(Stage primaryStage) throws Exception { 21 | ObservableList items = FXCollections.observableArrayList(); 22 | TableView table = new TableView<>(items); 23 | table.getSelectionModel().getSelectedItems().addListener((Change c) -> { 24 | while (c.next()) { 25 | if (c.wasRemoved()) { 26 | System.out.println(c.getRemoved()); 27 | } 28 | } 29 | }); 30 | 31 | items.add("foo"); 32 | table.getSelectionModel().select(0); 33 | items.clear(); 34 | Platform.exit(); 35 | } 36 | 37 | public static void main(String[] args) { 38 | launch(args); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /fx8-swingempire/src/testsupport/de/swingempire/fx/util/StageLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 02.09.2014 3 | * 4 | */ 5 | package de.swingempire.fx.util; 6 | 7 | import javafx.scene.Group; 8 | import javafx.scene.Node; 9 | import javafx.scene.Scene; 10 | import javafx.stage.Stage; 11 | 12 | /** 13 | * copy of openfx infrastructure 14 | * http://hg.openjdk.java.net/openjfx/8/master/rt/file/773008dbb998/modules/controls/src/test/java/com/sun/javafx/scene/control/infrastructure/StageLoader.java 15 | */ 16 | public class StageLoader { 17 | 18 | private Group group; 19 | private Scene scene; 20 | private Stage stage; 21 | 22 | public StageLoader(Node... content) { 23 | if (content == null || content.length == 0) { 24 | throw new IllegalArgumentException("Null / empty content not allowed"); 25 | } 26 | group = new Group(); 27 | group.getChildren().setAll(content); 28 | scene = new Scene(group); 29 | stage = new Stage(); 30 | stage.setScene(scene); 31 | stage.show(); 32 | } 33 | 34 | public StageLoader(Scene scene) { 35 | stage = new Stage(); 36 | stage.setScene(scene); 37 | stage.show(); 38 | } 39 | 40 | public Stage getStage() { 41 | return stage; 42 | } 43 | 44 | public void dispose() { 45 | stage.hide(); 46 | group.getChildren().clear(); 47 | group = null; 48 | scene = null; 49 | stage = null; 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/comboboxx/Combo15793Regression.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 18.10.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.comboboxx; 6 | 7 | import javafx.application.Application; 8 | import javafx.collections.FXCollections; 9 | import javafx.scene.Parent; 10 | import javafx.scene.Scene; 11 | import javafx.scene.control.Button; 12 | import javafx.scene.control.ComboBox; 13 | import javafx.scene.layout.VBox; 14 | import javafx.stage.Stage; 15 | 16 | /** 17 | * Reported: https://javafx-jira.kenai.com/browse/RT-39030 18 | * 19 | * - sanity: open popup and see it's empty (expected) 20 | * - press button 21 | * - open popup 22 | * - expected: see added item 23 | * - actual: empty 24 | */ 25 | public class Combo15793Regression extends Application { 26 | 27 | @Override 28 | public void start(Stage primaryStage) throws Exception { 29 | ComboBox box = new ComboBox(); 30 | Button button = new Button("set empty list and add item"); 31 | button.setOnAction(e -> { 32 | box.setItems(FXCollections.observableArrayList()); 33 | box.getItems().add("Toto"); 34 | }); 35 | Parent root = new VBox(box, button); 36 | primaryStage.setScene(new Scene(root)); 37 | primaryStage.setTitle(System.getProperty("java.version")); 38 | primaryStage.show(); 39 | } 40 | 41 | public static void main(String[] args) { 42 | launch(args); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/cell/Person22463.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 21.10.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.cell; 6 | 7 | 8 | 9 | /** 10 | * @author dosiennik 11 | */ 12 | public class Person22463 { 13 | 14 | private Long id; 15 | private String name; 16 | 17 | public Long getId() { 18 | return id; 19 | } 20 | 21 | public void setId(Long id) { 22 | this.id = id; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | @Override 34 | public boolean equals(Object obj) { 35 | if (obj == null) { 36 | return false; 37 | } 38 | if (getClass() != obj.getClass()) { 39 | return false; 40 | } 41 | final Person22463 other = (Person22463) obj; 42 | if (this.id != other.id) { 43 | return false; 44 | } 45 | return true; 46 | } 47 | 48 | @Override 49 | public int hashCode() { 50 | int hash = 7; 51 | hash = 89 * hash + (int) (this.id ^ (this.id >>> 32)); 52 | return hash; 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | return name + id; 58 | } 59 | 60 | 61 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/junit/DummyTestWithPlatformRunner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 23.06.2014 3 | * 4 | */ 5 | package de.swingempire.fx.junit; 6 | 7 | 8 | import java.util.logging.Logger; 9 | 10 | import javafx.application.Platform; 11 | import static junit.framework.TestCase.fail; 12 | 13 | import org.junit.Before; 14 | 15 | 16 | import org.junit.Rule; 17 | import org.junit.Test; 18 | import org.junit.runner.RunWith; 19 | import org.junit.rules.TestRule; 20 | 21 | import de.swingempire.fx.junit.FXThreadingRule; 22 | import de.swingempire.fx.junit.PlatformRunner; 23 | 24 | /** 25 | * Example of how-to enforce fx-app thread in testing: 26 | * 27 | * use the Platformrunner w/out additional rule (double safety net). 28 | * 29 | * @author Jeanette Winzenburg, Berlin 30 | */ 31 | @RunWith(PlatformRunner.class) 32 | public class DummyTestWithPlatformRunner { //extends TestCase { 33 | 34 | @Rule 35 | public TestRule mRule = new FXThreadingRule(); 36 | 37 | @Test 38 | public void passingTest() { 39 | LOG.info("nothing done, trivial passt ..."); 40 | } 41 | 42 | @Test 43 | public void failingTest() { 44 | fail("just saying ...."); 45 | } 46 | 47 | @Before 48 | public void init() { 49 | LOG.info("fx-at? " + Platform.isFxApplicationThread()); 50 | } 51 | 52 | @SuppressWarnings("unused") 53 | private static final Logger LOG = Logger.getLogger(DummyTestWithPlatformRunner.class 54 | .getName()); 55 | } 56 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/ListViewSelectionBugMinimal_38884.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 18.11.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.application.Application; 8 | import javafx.application.Platform; 9 | import javafx.collections.FXCollections; 10 | import javafx.collections.ListChangeListener.Change; 11 | import javafx.collections.ObservableList; 12 | import javafx.scene.control.ListView; 13 | import javafx.stage.Stage; 14 | 15 | /** 16 | * not yet in 8u40b12 - could use for regression testing in custom ListViewSelection 17 | */ 18 | public class ListViewSelectionBugMinimal_38884 extends Application { 19 | @Override 20 | public void start(Stage primaryStage) throws Exception { 21 | ObservableList items = FXCollections.observableArrayList(); 22 | // ListView table = new ListView<>(items); 23 | ListViewAnchored table = new ListViewAnchored<>(items); 24 | table.getSelectionModel().getSelectedItems().addListener((Change c) -> { 25 | while (c.next()) { 26 | if (c.wasRemoved()) { 27 | System.out.println(c.getRemoved()); 28 | } 29 | } 30 | }); 31 | 32 | items.add("foo"); 33 | table.getSelectionModel().select(0); 34 | items.clear(); 35 | Platform.exit(); 36 | } 37 | 38 | public static void main(String[] args) { 39 | launch(args); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/text/TextFlowExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 05.05.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.text; 6 | 7 | import javafx.application.Application; 8 | import javafx.beans.binding.Bindings; 9 | import javafx.collections.FXCollections; 10 | import javafx.collections.ObservableList; 11 | import javafx.scene.Parent; 12 | import javafx.scene.Scene; 13 | import javafx.scene.control.Button; 14 | import javafx.scene.layout.BorderPane; 15 | import javafx.scene.text.Text; 16 | import javafx.scene.text.TextFlow; 17 | import javafx.stage.Stage; 18 | 19 | /** 20 | * @author Jeanette Winzenburg, Berlin 21 | */ 22 | public class TextFlowExample extends Application { 23 | 24 | int count = 0; 25 | private Parent getContent() { 26 | ObservableList bullets = FXCollections.observableArrayList( 27 | new Text("dummy1"), new Text("other")); 28 | TextFlow flow = new TextFlow(); 29 | Bindings.bindContent(flow.getChildren(), bullets); 30 | BorderPane pane = new BorderPane(flow); 31 | Button add = new Button("Add"); 32 | add.setOnAction(e -> bullets.add(new Text("added " + count++))); 33 | pane.setBottom(add); 34 | return pane; 35 | } 36 | @Override 37 | public void start(Stage primaryStage) throws Exception { 38 | primaryStage.setScene(new Scene(getContent())); 39 | primaryStage.show(); 40 | } 41 | 42 | public static void main(String[] args) { 43 | launch(args); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/comboboxx/ComboBoxStringConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 02.10.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.comboboxx; 6 | 7 | import javafx.application.Application; 8 | import javafx.scene.Scene; 9 | import javafx.scene.control.ComboBox; 10 | import javafx.scene.layout.VBox; 11 | import javafx.stage.Stage; 12 | import javafx.util.StringConverter; 13 | 14 | /** 15 | * Converter must be used always (if available) 16 | * 17 | * Run: 18 | * - expected: display value "none" 19 | * - actual: empty 20 | */ 21 | public class ComboBoxStringConverter extends Application 22 | { 23 | public static void main(String[] args) 24 | { 25 | Application.launch(args); 26 | } 27 | 28 | @Override 29 | public void start(Stage stage) throws Exception 30 | { 31 | final ComboBox cb = new ComboBox(); 32 | cb.getItems().setAll(1, 2, 3); 33 | StringConverter converter = new StringConverter() { 34 | @Override public String toString(Object arg0) { 35 | if (arg0 == null) return "none"; 36 | return "item " + arg0; } 37 | @Override public Integer fromString(String arg0) { throw new UnsupportedOperationException(); } 38 | }; 39 | cb.setConverter(converter); 40 | VBox c = new VBox(cb); 41 | stage.setScene(new Scene(c, 500, 400)); 42 | stage.setTitle(System.getProperty("java.version")); 43 | stage.show(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/cell/chartcell.css: -------------------------------------------------------------------------------- 1 | .root { 2 | -fx-chart-color-1: #f3622d; 3 | -fx-chart-color-2: #fba71b; 4 | -fx-chart-color-3: #57b757 5 | } 6 | 7 | /* cell with chart */ 8 | .chart-cell { 9 | } 10 | 11 | .chart-cell .chart-content { 12 | -fx-padding: 0; 13 | } 14 | 15 | .chart-cell .chart { 16 | -fx-legend-visible: false; 17 | -fx-padding: 2; 18 | /* makes chart fit into cell with fixedCellSize 19 | */ 20 | -fx-min-height: 0; 21 | } 22 | 23 | /* 24 | .default-color0.chart-bar { -fx-bar-fill: -fx-chart-color-1; } 25 | .default-color1.chart-bar { -fx-bar-fill: -fx-chart-color-3; } 26 | */ 27 | .chart-cell .stacked-bar-chart { 28 | -fx-horizontal-grid-lines-visible: false; 29 | -fx-vertical-grid-lines-visible: false; 30 | -fx-legend-visible: false; 31 | -fx-category-gap: 0; 32 | } 33 | 34 | .chart-cell .axis { 35 | -fx-horizontal-zero-line-visible: false; 36 | -fx-vertical-zero-line-visible: false; 37 | -fx-tick-mark-visible: false; 38 | -fx-minor-tick-visible: false; 39 | -fx-tick-labels-visible: false; 40 | -fx-start-margin: 0; 41 | -fx-end-margin: 0; 42 | 43 | /* following three are for hiding the line between content and axis 44 | * for valueAxis that is drawn by the border, setting to transparent 45 | * does make it invisible but still leaves the area. Also doesn't 46 | * work for catagory at all. Setting prefwidth/height to zero does 47 | * the trick - but is an implementation detail of axis/chart layout! 48 | */ 49 | -fx-pref-height: 0; 50 | -fx-pref-width: 0; 51 | 52 | 53 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/swing/FXApplet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 15.04.2015 3 | * 4 | */ 5 | package de.swingempire.fx.swing; 6 | 7 | import javafx.application.Platform; 8 | import javafx.embed.swing.JFXPanel; 9 | import javafx.scene.Group; 10 | import javafx.scene.Parent; 11 | import javafx.scene.Scene; 12 | import javafx.scene.control.Button; 13 | import javafx.scene.control.TextField; 14 | import javafx.scene.layout.HBox; 15 | import javafx.stage.Popup; 16 | 17 | import javax.swing.JApplet; 18 | import javax.swing.SwingUtilities; 19 | 20 | /** 21 | * Focus problem with popup in swing/fx intermix 22 | * http://stackoverflow.com/q/29646127/203657 23 | */ 24 | public class FXApplet extends JApplet { 25 | protected Scene scene; 26 | protected Parent root; 27 | 28 | @Override 29 | public final void init() { 30 | SwingUtilities.invokeLater(() -> initSwing()); 31 | } 32 | 33 | private void initSwing() { 34 | JFXPanel fxPanel = new JFXPanel(); 35 | add(fxPanel); 36 | 37 | Platform.runLater(() -> { 38 | initFX(fxPanel); 39 | initApplet(); 40 | }); 41 | } 42 | 43 | private void initFX(JFXPanel fxPanel) { 44 | Button button = new Button("dummy"); 45 | root = new HBox(button); 46 | scene = new Scene(root); 47 | fxPanel.setScene(scene); 48 | } 49 | 50 | public void initApplet() { 51 | Popup popup = new Popup(); 52 | 53 | popup.setAutoHide(false); 54 | popup.getContent().add(new TextField()); 55 | popup.show(scene.getWindow()); 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/scene/control/pagination/DirectPaginationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 29.07.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.pagination; 6 | 7 | import org.junit.runner.RunWith; 8 | import org.junit.runners.JUnit4; 9 | 10 | import javafx.beans.property.IntegerProperty; 11 | import javafx.scene.control.Pagination; 12 | 13 | /** 14 | * @author Jeanette Winzenburg, Berlin 15 | */ 16 | @RunWith(JUnit4.class) 17 | public class DirectPaginationTest extends NavigationTest { 18 | 19 | 20 | private Pagination pagination; 21 | 22 | @Override 23 | public void setup() { 24 | pagination = new Pagination(1); 25 | super.setup(); 26 | } 27 | 28 | @Override 29 | protected NavigationModel createNavigation() { 30 | return new PaginationDrivenNavigationModel(pagination); 31 | } 32 | 33 | /** 34 | * NavigationModel that delegates its current/size properties directly to 35 | * the pagination's properties 36 | */ 37 | public static class PaginationDrivenNavigationModel implements NavigationModel { 38 | 39 | private Pagination pagination; 40 | 41 | public PaginationDrivenNavigationModel(Pagination pagination) { 42 | this.pagination = pagination; 43 | } 44 | @Override 45 | public IntegerProperty currentProperty() { 46 | return pagination.currentPageIndexProperty(); 47 | } 48 | 49 | @Override 50 | public IntegerProperty sizeProperty() { 51 | return pagination.pageCountProperty(); 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/junit/DummyTestWithRules.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 23.06.2014 3 | * 4 | */ 5 | package de.swingempire.fx.junit; 6 | 7 | import java.util.logging.Logger; 8 | 9 | import javafx.application.Platform; 10 | 11 | import org.junit.Before; 12 | import org.junit.ClassRule; 13 | import org.junit.Rule; 14 | import org.junit.Test; 15 | import org.junit.rules.TestRule; 16 | import org.junit.runner.RunWith; 17 | import org.junit.runners.JUnit4; 18 | 19 | import de.swingempire.fx.junit.FXThreadingRule; 20 | import de.swingempire.fx.junit.JavaFXThreadingRule; 21 | import static junit.framework.TestCase.*; 22 | 23 | /** 24 | * Example of enforcing fx-app thread: 25 | * 26 | * use arbitrary runner combined with classRule for thread 27 | * enforcing. 28 | * 29 | * @author Jeanette Winzenburg, Berlin 30 | */ 31 | @RunWith(JUnit4.class) 32 | public class DummyTestWithRules { //extends TestCase { 33 | 34 | @ClassRule 35 | public static TestRule classRule = new JavaFXThreadingRule(); 36 | 37 | @Rule 38 | public TestRule mRule = new FXThreadingRule(); 39 | 40 | @Test 41 | public void passingTest() { 42 | LOG.info("nothing done, trivial passt ..."); 43 | } 44 | 45 | @Test 46 | public void failingTest() { 47 | fail("just saying ...."); 48 | } 49 | 50 | @Before 51 | public void init() { 52 | LOG.info("fx-at? " + Platform.isFxApplicationThread()); 53 | } 54 | 55 | @SuppressWarnings("unused") 56 | private static final Logger LOG = Logger.getLogger(DummyTestWithPlatformRunner.class 57 | .getName()); 58 | } 59 | -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/scene/control/selection/ComboBoxSelectionIssues.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 02.06.2013 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.collections.ObservableList; 8 | import javafx.scene.control.ComboBox; 9 | import javafx.scene.control.FocusModel; 10 | import javafx.scene.control.SingleSelectionModel; 11 | 12 | import org.junit.runner.RunWith; 13 | import org.junit.runners.JUnit4; 14 | 15 | /** 16 | * PENDING: what is this? looks like a left-over 17 | * before introducing the AbstractChoice layer? 18 | * 19 | * @author Jeanette Winzenburg, Berlin 20 | */ 21 | @SuppressWarnings({ "rawtypes", "unchecked" }) 22 | @RunWith(JUnit4.class) 23 | public class ComboBoxSelectionIssues extends SelectionIssues { 24 | 25 | 26 | @Override 27 | protected SingleSelectionModel getSelectionModel() { 28 | return getView().getSelectionModel(); 29 | } 30 | 31 | @Override 32 | protected ComboBox createView(ObservableList items) { 33 | return new ComboBox(items); 34 | } 35 | 36 | @Override 37 | protected FocusModel getFocusModel() { 38 | return null; 39 | } 40 | 41 | @Override 42 | protected int getAnchorIndex(int index) { 43 | return index; 44 | } 45 | 46 | @Override 47 | protected void setSelectionModel(SingleSelectionModel model) { 48 | getView().setSelectionModel(model); 49 | } 50 | 51 | @Override 52 | protected void resetItems(ObservableList other) { 53 | getView().setItems(other); 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/BaselineInHBox.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 12.12.2014 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import java.util.logging.Logger; 8 | 9 | import javafx.application.Application; 10 | import javafx.geometry.Pos; 11 | import javafx.scene.Parent; 12 | import javafx.scene.Scene; 13 | import javafx.scene.control.Button; 14 | import javafx.scene.control.CheckBox; 15 | import javafx.scene.control.TextField; 16 | import javafx.scene.layout.FlowPane; 17 | import javafx.scene.layout.GridPane; 18 | import javafx.scene.layout.HBox; 19 | import javafx.stage.Stage; 20 | 21 | /** 22 | * Alignment problems: http://stackoverflow.com/q/27435805/203657 23 | * @author Jeanette Winzenburg, Berlin 24 | */ 25 | public class BaselineInHBox extends Application { 26 | 27 | // FlowPane box = new FlowPane(new TextField("something"), 28 | // new CheckBox("soso"), new Button("hello")); 29 | /** 30 | * @return 31 | */ 32 | private Parent getContent() { 33 | HBox box = new HBox(new TextField("something"), 34 | new CheckBox("soso"), new Button("hello")); 35 | box.setAlignment(Pos.BASELINE_CENTER); 36 | return box; 37 | } 38 | 39 | @Override 40 | public void start(Stage primaryStage) throws Exception { 41 | Scene scene = new Scene(getContent()); 42 | primaryStage.setScene(scene); 43 | primaryStage.show(); 44 | } 45 | 46 | public static void main(String[] args) { 47 | launch(args); 48 | } 49 | 50 | @SuppressWarnings("unused") 51 | private static final Logger LOG = Logger.getLogger(BaselineInHBox.class 52 | .getName()); 53 | } 54 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/DynamicTooltipRT_40080.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 17.02.2015 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import de.swingempire.fx.util.FXUtils; 8 | import javafx.application.Application; 9 | import javafx.scene.Parent; 10 | import javafx.scene.Scene; 11 | import javafx.scene.control.Button; 12 | import javafx.scene.control.ContextMenu; 13 | import javafx.scene.control.MenuItem; 14 | import javafx.scene.control.Tooltip; 15 | import javafx.scene.layout.VBox; 16 | import javafx.stage.Stage; 17 | 18 | /** 19 | * Tooltip flickering (showing/hiding) when setting text in onShowing. 20 | * 21 | * Reported: https://javafx-jira.kenai.com/browse/RT-40080 22 | * 23 | * @author Jeanette Winzenburg, Berlin 24 | */ 25 | public class DynamicTooltipRT_40080 extends Application { 26 | 27 | @Override 28 | public void start(Stage stage) throws Exception { 29 | Button button = new Button(FXUtils.version()); 30 | Tooltip t = new Tooltip("button"); 31 | button.setTooltip(t); 32 | t.setOnShowing(e -> { 33 | // side-effect: tooltip hidden/shown 34 | // t.setText("x/y: " + t.getX() + "/" + t.getY()); 35 | // here we get a stable tooltip 36 | t.textProperty().set("x/y: " + t.getX() + "/" + t.getY() + "\n" + 37 | "ax/y: " + t.getAnchorX() + "/" + t.getAnchorY()); 38 | }); 39 | VBox pane = new VBox(button); 40 | Scene scene = new Scene(pane); 41 | stage.setScene(scene); 42 | stage.show(); 43 | stage.setTitle(FXUtils.version()); 44 | } 45 | 46 | public static void main(String[] args) { 47 | launch(args); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/choiceboxx/ChoiceBoxSkinRT38724.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 23.09.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.choiceboxx; 6 | 7 | import java.lang.reflect.InvocationTargetException; 8 | import java.lang.reflect.Method; 9 | 10 | import javafx.scene.control.ChoiceBox; 11 | 12 | import com.sun.javafx.scene.control.skin.ChoiceBoxSkin; 13 | 14 | /** 15 | * Fix for RT-38724: update value on change of selectionModel. 16 | * 17 | * @author Jeanette Winzenburg, Berlin 18 | */ 19 | public class ChoiceBoxSkinRT38724 extends ChoiceBoxSkin { 20 | 21 | public ChoiceBoxSkinRT38724(ChoiceBox control) { 22 | super(control); 23 | } 24 | 25 | @Override 26 | protected void handleControlPropertyChanged(String p) { 27 | super.handleControlPropertyChanged(p); 28 | if ("SELECTION_MODEL".equals(p)) { 29 | // super called updateSelectionModel 30 | // super forgot to call updateSelection 31 | // invoking the latter here 32 | invokeUpdateSelection(); 33 | } 34 | } 35 | 36 | /** 37 | * Reflective method access of private super method 38 | */ 39 | private void invokeUpdateSelection() { 40 | Class clazz = ChoiceBoxSkin.class; 41 | try { 42 | Method method = clazz.getDeclaredMethod("updateSelection"); 43 | method.setAccessible(true); 44 | method.invoke(this); 45 | } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 46 | // TODO Auto-generated catch block 47 | e.printStackTrace(); 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/et/TableViewET.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 20.02.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.et; 6 | 7 | import javafx.collections.ObservableList; 8 | import javafx.event.EventDispatchChain; 9 | import javafx.event.EventTarget; 10 | import javafx.scene.control.Skin; 11 | import javafx.scene.control.TableView; 12 | 13 | /** 14 | * A TableView with extended event dispatching.

    15 | * 16 | * Allows the skin to hook into the event dispatch chain, provided 17 | * it is of type EventTarget (which is created by default for this view). 18 | * 19 | * @author Jeanette Winzenburg, Berlin 20 | */ 21 | public class TableViewET extends TableView { 22 | 23 | /** 24 | * Overridden to allow the skin hook into the dispatch chain before 25 | * calling super, if the skin is of type EventTarget. 26 | */ 27 | @Override 28 | public EventDispatchChain buildEventDispatchChain( 29 | EventDispatchChain tail) { 30 | if (getSkin() instanceof EventTarget) { 31 | ((EventTarget) getSkin()).buildEventDispatchChain(tail); 32 | } 33 | return super.buildEventDispatchChain(tail); 34 | } 35 | 36 | 37 | /** 38 | * Overridden to create and return a TableViewSkin 39 | * which implements EventTarget. 40 | */ 41 | @Override 42 | protected Skin createDefaultSkin() { 43 | return new TableViewETSkin<>(this); 44 | } 45 | 46 | //---------- boiler-plate: super's constructors 47 | public TableViewET() { 48 | this(null); 49 | } 50 | 51 | public TableViewET(ObservableList items) { 52 | super(items); 53 | setRowFactory(p -> new TableRowET<>()); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/choiceboxx/ChoiceBoxRT38724.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 23.09.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.choiceboxx; 6 | 7 | import javafx.beans.value.ChangeListener; 8 | import javafx.collections.ObservableList; 9 | import javafx.scene.control.ChoiceBox; 10 | import javafx.scene.control.SingleSelectionModel; 11 | import javafx.scene.control.Skin; 12 | 13 | /** 14 | * Quick fix for RT-38724: update value on change of selectionModel. 15 | * 16 | * Has two parts: 17 | *

      18 | *
    • install a ChangeListener on selectionModelProperty and let it update the value 19 | *
    • install a custom skin that (reflectively) calls updateSelection in addition 20 | * to super calling updateSelectionModel 21 | *
    22 | * 23 | * @author Jeanette Winzenburg, Berlin 24 | */ 25 | public class ChoiceBoxRT38724 extends ChoiceBox { 26 | 27 | public ChoiceBoxRT38724(ObservableList items) { 28 | super(items); 29 | installListenerFix(); 30 | } 31 | 32 | /** 33 | * Fix for RT38724: listening to selectionModel property and update value. 34 | */ 35 | private void installListenerFix() { 36 | ChangeListener> modelListener = (p, old, value) -> { 37 | updateValueFromSelectionModel(value != null ? value.getSelectedItem() : null); 38 | }; 39 | selectionModelProperty().addListener(modelListener); 40 | } 41 | 42 | protected void updateValueFromSelectionModel(T t1) { 43 | if (! valueProperty().isBound()) { 44 | setValue(t1); 45 | } 46 | } 47 | 48 | @Override 49 | protected Skin createDefaultSkin() { 50 | return new ChoiceBoxSkinRT38724<>(this); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/selection/FocusModelSlave.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 11.11.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | 8 | /** 9 | * Hack around competing responsibilities of MultipleSelectionModel and 10 | * FocusModel. Semantically, both must update themselves on changes to the items, 11 | * often the SelectionModel does so on behalf of the FocusModel: happens 12 | * whenever it calls select(index) during its own update. 13 | * FocusModel can't know whether or not that had happened, so the net effect 14 | * occasionally is doubling of the update.

    15 | * 16 | * Simply removing the responsibility of updating from FocusModel blows if 17 | * focus != selectedIndex.

    18 | * 19 | * With this tagging interface, we move the responsibility completely 20 | * to the SelectionModel (aka: primary 21 | * controller): it has to update the focus internally. 22 | *

    23 | * 24 | * Note: refactored to tagging (vs. providing a hook for rooting) looks fine so far. 25 | * PENDING JW: handle default focus 26 | * 27 | * 28 | * @author Jeanette Winzenburg, Berlin 29 | */ 30 | public interface FocusModelSlave { 31 | 32 | // /** 33 | // * Must be called by primary controller of list changes if it didn't 34 | // * update the focus itself. Must be called after the controller 35 | // * handled any partial change, that is implementations can assume 36 | // * that the state of the controller is stable. 37 | // * 38 | // * Note that implementors must cope with a Change that is dirty, that 39 | // * is they must call c.reset before evaluating the change. 40 | // * 41 | // * @param c 42 | // */ 43 | // void listChanged(Change c); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/comboboxx/ComboBoxStringConverterRT_32919.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 02.10.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.comboboxx; 6 | 7 | import javafx.application.Application; 8 | import javafx.event.ActionEvent; 9 | import javafx.event.EventHandler; 10 | import javafx.scene.Scene; 11 | import javafx.scene.control.Button; 12 | import javafx.scene.control.ComboBox; 13 | import javafx.scene.layout.VBox; 14 | import javafx.stage.Stage; 15 | import javafx.util.StringConverter; 16 | 17 | /** 18 | * https://javafx-jira.kenai.com/browse/RT-32919 19 | * setConverter must not clear selection 20 | * 21 | * seems to be fixed in 8u40 22 | */ 23 | public class ComboBoxStringConverterRT_32919 extends Application 24 | { 25 | public static void main(String[] args) 26 | { 27 | Application.launch(args); 28 | } 29 | 30 | @Override 31 | public void start(Stage stage) throws Exception 32 | { 33 | final ComboBox cb = new ComboBox(); 34 | cb.getItems().setAll(1, 2, 3); 35 | cb.getSelectionModel().select(0); 36 | 37 | Button b = new Button("set string converter"); 38 | b.setOnAction(new EventHandler() { 39 | @Override 40 | public void handle(ActionEvent arg0) 41 | { 42 | // this should not clear the selection but it does... 43 | cb.setConverter(new StringConverter() { 44 | @Override public String toString(Integer arg0) { return "item " + arg0; } 45 | @Override public Integer fromString(String arg0) { throw new UnsupportedOperationException(); } 46 | }); 47 | } 48 | }); 49 | 50 | VBox c = new VBox(); 51 | c.getChildren().addAll(cb, b); 52 | stage.setScene(new Scene(c, 500, 400)); 53 | stage.show(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/TableSortNPEIfNullItems.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 09.12.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.application.Application; 8 | import javafx.geometry.Insets; 9 | import javafx.scene.Parent; 10 | import javafx.scene.Scene; 11 | import javafx.scene.control.TableColumn; 12 | import javafx.scene.control.TableView; 13 | import javafx.scene.layout.HBox; 14 | import javafx.scene.layout.Pane; 15 | import javafx.stage.Stage; 16 | 17 | /** 18 | * Issue TableView throws NPE on sorting column if items property value is null. 19 | * Reported as https://javafx-jira.kenai.com/browse/RT-37674 20 | * 21 | * 22 | * @author Jeanette Winzenburg, Berlin 23 | */ 24 | public class TableSortNPEIfNullItems extends Application { 25 | 26 | private Parent getContent() { 27 | // instantiate the table with null items 28 | TableView view = new TableView(null); 29 | TableColumn column = new TableColumn<>("Items"); 30 | // either click on header for sorting 31 | view.getColumns().addAll(column); 32 | // or add column to sort order immediately 33 | //view.getSortOrder().add(column); 34 | Pane parent = new HBox(100); 35 | parent.getChildren().addAll(view); 36 | parent.setPadding(new Insets(20)); 37 | return parent; 38 | } 39 | 40 | @Override 41 | public void start(Stage primaryStage) throws Exception { 42 | Scene scene = new Scene(getContent()); 43 | primaryStage.setTitle(System.getProperty("java.version")); 44 | primaryStage.setScene(scene); 45 | primaryStage.show(); 46 | } 47 | 48 | public static void main(String[] args) { 49 | launch(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/et/TableViewETSkin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 20.02.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.et; 6 | 7 | import javafx.event.EventDispatchChain; 8 | import javafx.event.EventTarget; 9 | import javafx.scene.control.IndexedCell; 10 | import javafx.scene.control.TableColumn; 11 | import javafx.scene.control.TablePosition; 12 | import javafx.scene.control.TableRow; 13 | import javafx.scene.control.TableView; 14 | 15 | import com.sun.javafx.event.EventHandlerManager; 16 | import com.sun.javafx.scene.control.skin.TableRowSkin; 17 | import com.sun.javafx.scene.control.skin.TableViewSkin; 18 | 19 | /** 20 | * @author Jeanette Winzenburg, Berlin 21 | */ 22 | public class TableViewETSkin extends TableViewSkin implements EventTarget { 23 | 24 | EventHandlerManager eventHandlerManager = new EventHandlerManager(this); 25 | @Override 26 | public EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) { 27 | TablePosition focused = getFocusedCell(); 28 | if (focused != null) { 29 | TableColumn column = focused.getTableColumn(); 30 | if (column != null) { 31 | column.buildEventDispatchChain(tail); 32 | // PENDING delegate without nesting 33 | int row = focused.getRow(); 34 | if (row > -1) { 35 | IndexedCell rowCell = flow.getCell(row); 36 | rowCell.buildEventDispatchChain(tail); 37 | } 38 | } 39 | } 40 | // return tail.prepend(eventHandlerManager); 41 | return tail; 42 | } 43 | 44 | //---------------- boiler-plate constructor 45 | 46 | public TableViewETSkin(TableView tableView) { 47 | super(tableView); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/et/ContextMenuKeyboard.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 03.03.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.et; 6 | 7 | 8 | import javafx.application.Application; 9 | import javafx.scene.Parent; 10 | import javafx.scene.Scene; 11 | import javafx.scene.control.Button; 12 | import javafx.scene.control.ContextMenu; 13 | import javafx.scene.control.MenuItem; 14 | import javafx.scene.layout.HBox; 15 | import javafx.stage.Stage; 16 | 17 | /** 18 | * ContextMenu: 19 | * user interaction broken when activated by keyboard. 20 | * https://javafx-jira.kenai.com/browse/RT-40175 21 | * 22 | * To reproduce, compile, run and activate contextMenu by keyboard (shift-f10 on win) 23 | * 24 | * variant A: 25 | * - press DOWN 26 | * - expected: next menu item highlighted 27 | * - actual: system menu of window opens 28 | * 29 | * variant B: 30 | * - press ESC 31 | * - expected: contextMenu hidden 32 | * - actual: nothing happens (needs a second ESC to hide) 33 | * 34 | * variant C 35 | * - move mouse over menu 36 | * - expected: menu item below mouse is highlighted 37 | * - actual: no visual change 38 | */ 39 | public class ContextMenuKeyboard extends Application { 40 | 41 | private Parent getContent() { 42 | Button button = new Button("simple button with contextMenu"); 43 | button.setContextMenu(new ContextMenu(new MenuItem("one"), new MenuItem("two"))); 44 | Parent pane = new HBox(button); 45 | return pane; 46 | } 47 | 48 | @Override 49 | public void start(Stage primaryStage) throws Exception { 50 | Scene scene = new Scene(getContent()); 51 | primaryStage.setScene(scene); 52 | primaryStage.show(); 53 | } 54 | 55 | public static void main(String[] args) { 56 | launch(args); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/et/TableRowETSkin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 20.02.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.et; 6 | 7 | import java.lang.ref.Reference; 8 | 9 | import javafx.event.EventDispatchChain; 10 | import javafx.event.EventTarget; 11 | import javafx.scene.control.Cell; 12 | import javafx.scene.control.TableCell; 13 | import javafx.scene.control.TableColumn; 14 | import javafx.scene.control.TablePosition; 15 | import javafx.scene.control.TableRow; 16 | import javafx.scene.control.TableView; 17 | 18 | import com.sun.javafx.event.EventHandlerManager; 19 | import com.sun.javafx.scene.control.skin.TableRowSkin; 20 | 21 | /** 22 | * @author Jeanette Winzenburg, Berlin 23 | */ 24 | public class TableRowETSkin extends TableRowSkin implements EventTarget { 25 | 26 | EventHandlerManager eventHandlerManager = new EventHandlerManager(this); 27 | 28 | @Override 29 | public EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) { 30 | TableView tableView = getSkinnable().getTableView(); 31 | TablePosition focused = tableView.getFocusModel().getFocusedCell(); 32 | if (focused != null && focused.getTableColumn() != null) { 33 | TableColumn column = focused.getTableColumn(); 34 | Reference> cellReference = cellsMap.get(column); 35 | Cell cell = cellReference != null ? cellReference.get() : null; 36 | if (cell != null) { 37 | cell.buildEventDispatchChain(tail); 38 | } 39 | } 40 | // return tail.prepend(eventHandlerManager); 41 | return tail; 42 | } 43 | 44 | //-------------------- boiler-plate constructor 45 | 46 | public TableRowETSkin(TableRow tableRow) { 47 | super(tableRow); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/ComboWithConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 14.09.2015 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import javafx.application.Application; 8 | import javafx.collections.FXCollections; 9 | import javafx.collections.ObservableList; 10 | import javafx.scene.Scene; 11 | import javafx.scene.control.ComboBox; 12 | import javafx.scene.layout.BorderPane; 13 | import javafx.stage.Stage; 14 | import javafx.util.StringConverter; 15 | 16 | public class ComboWithConverter extends Application 17 | { 18 | @Override 19 | public void start(Stage stage) throws Exception 20 | { 21 | int state = 0; 22 | 23 | // ObservableList options = FXCollections.observableArrayList( 24 | // "Active", 25 | // "Blocked" 26 | // ); 27 | ObservableList options = FXCollections.observableArrayList( 28 | 0, 29 | 1 30 | ); 31 | 32 | ComboBox comboBox = new ComboBox(options); 33 | StringConverter converter = new StringConverter() { 34 | 35 | @Override 36 | public String toString(Integer object) { 37 | if (object == null) return ""; 38 | return object.intValue() == 0 ? "Blocked" : "Active"; 39 | } 40 | 41 | @Override 42 | public Integer fromString(String string) { 43 | return null; 44 | } 45 | 46 | }; 47 | comboBox.setConverter(converter); 48 | BorderPane bp = new BorderPane(comboBox); 49 | bp.setPrefSize(800, 800); 50 | Scene scene = new Scene(bp); 51 | stage.setScene(scene); 52 | stage.show(); 53 | } 54 | 55 | public static void main(String[] args) 56 | { 57 | launch(args); 58 | } 59 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/comboboxx/CanNotRenderPromptTextInComboBoxRT_22930.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 03.10.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.comboboxx; 6 | 7 | import javafx.application.Application; 8 | import javafx.collections.FXCollections; 9 | import javafx.scene.Scene; 10 | import javafx.scene.control.ComboBox; 11 | import javafx.scene.control.ListCell; 12 | import javafx.scene.layout.FlowPane; 13 | import javafx.stage.Stage; 14 | 15 | /** 16 | * https://javafx-jira.kenai.com/browse/RT-22930 17 | * Respect "prompt text" in buttonCell. Was rejected as usage error: 18 | * should use prompt text property of combo 19 | * 20 | * Technically, cannot work as skin.updateDisplayNode changes the cell's 21 | * text/graphic under its feet (not much else to do for uncontained 22 | * selectedItem) 23 | */ 24 | public class CanNotRenderPromptTextInComboBoxRT_22930 extends Application { 25 | 26 | public static void main(String[] args) { 27 | launch(args); 28 | } 29 | 30 | @Override 31 | public void start(Stage stage) { 32 | FlowPane pane = new FlowPane(); 33 | ComboBox comboBox = new ComboBox<>(); 34 | comboBox.setPrefWidth(500); 35 | pane.getChildren().add(comboBox); 36 | comboBox.buttonCellProperty().set(new ListCell() { 37 | @Override 38 | protected void updateItem(String item, boolean isEmpty) { 39 | super.updateItem(item, isEmpty); 40 | if (isEmpty) { 41 | setText("Prompt Text"); 42 | return; 43 | } 44 | setText(item); 45 | } 46 | }); 47 | 48 | comboBox.setItems(FXCollections.observableArrayList("one", "two")); 49 | 50 | stage.setScene(new Scene(pane)); 51 | stage.show(); 52 | } 53 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/table/toggle/MainApp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 11.08.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.table.toggle; 6 | 7 | import java.io.IOException; 8 | 9 | import javafx.application.Application; 10 | import javafx.collections.FXCollections; 11 | import javafx.collections.ObservableList; 12 | import javafx.fxml.FXMLLoader; 13 | import javafx.scene.Scene; 14 | import javafx.scene.layout.AnchorPane; 15 | import javafx.stage.Stage; 16 | 17 | public class MainApp extends Application { 18 | 19 | private Stage primaryStage; 20 | 21 | private AnchorPane rootLayout; 22 | 23 | private ObservableList personData = FXCollections 24 | .observableArrayList(); 25 | 26 | public MainApp() { 27 | for (int i = 0; i < 40; i++) { 28 | personData.add(new Person("person " + i)); 29 | } 30 | } 31 | 32 | public ObservableList getPersonData() { 33 | return personData; 34 | } 35 | 36 | @Override 37 | public void start(Stage primaryStage) throws Exception { 38 | this.primaryStage = primaryStage; 39 | try { 40 | FXMLLoader loader = new FXMLLoader(); 41 | loader.setLocation(MainApp.class.getResource("People.fxml")); 42 | rootLayout = (AnchorPane) loader.load(); 43 | Scene scene = new Scene(rootLayout); 44 | primaryStage.setScene(scene); 45 | primaryStage.show(); 46 | PeopleController controller = loader.getController(); 47 | controller.setMainApp(this); 48 | } catch (IOException e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | 53 | public Stage getPrimaryStage() { 54 | return primaryStage; 55 | } 56 | 57 | public static void main(String[] args) { 58 | launch(args); 59 | } 60 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/table/toggle/MainAppX.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 11.08.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.table.toggle; 6 | 7 | import java.io.IOException; 8 | 9 | import javafx.application.Application; 10 | import javafx.collections.FXCollections; 11 | import javafx.collections.ObservableList; 12 | import javafx.fxml.FXMLLoader; 13 | import javafx.scene.Scene; 14 | import javafx.scene.layout.AnchorPane; 15 | import javafx.stage.Stage; 16 | 17 | public class MainAppX extends Application { 18 | 19 | private Stage primaryStage; 20 | 21 | private AnchorPane rootLayout; 22 | 23 | private ObservableList personData = FXCollections 24 | .observableArrayList(); 25 | 26 | public MainAppX() { 27 | for (int i = 0; i < 40; i++) { 28 | personData.add(new Person("person " + i)); 29 | } 30 | } 31 | 32 | public ObservableList getPersonData() { 33 | return personData; 34 | } 35 | 36 | @Override 37 | public void start(Stage primaryStage) throws Exception { 38 | this.primaryStage = primaryStage; 39 | try { 40 | FXMLLoader loader = new FXMLLoader(); 41 | loader.setLocation(MainAppX.class.getResource("PeopleX.fxml")); 42 | rootLayout = (AnchorPane) loader.load(); 43 | Scene scene = new Scene(rootLayout); 44 | primaryStage.setScene(scene); 45 | primaryStage.show(); 46 | PeopleControllerX controller = loader.getController(); 47 | controller.setMainApp(this); 48 | } catch (IOException e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | 53 | public Stage getPrimaryStage() { 54 | return primaryStage; 55 | } 56 | 57 | public static void main(String[] args) { 58 | launch(args); 59 | } 60 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/SliderBug_8089730.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 04.12.2015 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import javafx.application.Application; 8 | import javafx.scene.Scene; 9 | import javafx.scene.control.Label; 10 | import javafx.scene.control.Slider; 11 | import javafx.scene.layout.BorderPane; 12 | import javafx.scene.layout.HBox; 13 | import javafx.stage.Stage; 14 | import de.swingempire.fx.control.TooltipOnSlider.MySliderSkin; 15 | import de.swingempire.fx.scene.control.slider.XSliderSkin; 16 | 17 | /** 18 | * Slider: slider value differs from selected real value 19 | * https://bugs.openjdk.java.net/browse/JDK-8089730 20 | * 21 | * MySliderSkin is better, but not optimal - rounding error? 22 | */ 23 | public class SliderBug_8089730 extends Application { 24 | 25 | @Override 26 | public void start(Stage stage) throws Exception { 27 | 28 | Slider s = new Slider(); 29 | // s.setSkin(new MySliderSkin(s)); 30 | s.setSkin(new XSliderSkin(s)); 31 | s.setMinWidth(500.0); 32 | s.setPrefWidth(500.0); 33 | s.setMax(200.0); 34 | s.setMin(-50.0); 35 | s.setShowTickMarks(true); 36 | s.setShowTickLabels(true); 37 | Label lbl = new Label(); 38 | lbl.textProperty().bind(s.valueProperty().asString()); 39 | 40 | // HBox root = new HBox(20d); 41 | // root.getChildren().addAll(s, lbl); 42 | BorderPane root = new BorderPane(s); 43 | root.setBottom(lbl); 44 | Scene scene = new Scene(root); //, 300, 500); 45 | 46 | stage.setScene(scene); 47 | stage.setTitle(System.getProperty("java.runtime.version") + "; " 48 | + System.getProperty("javafx.runtime.version")); 49 | stage.show(); 50 | } 51 | 52 | public static void main(String[] args) { 53 | launch(args); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /fx8-swingempire/src/testsupport/de/swingempire/fx/util/ChangeReport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 24.05.2014 3 | * 4 | */ 5 | package de.swingempire.fx.util; 6 | 7 | import java.util.LinkedList; 8 | import java.util.List; 9 | 10 | import javafx.beans.value.ChangeListener; 11 | import javafx.beans.value.ObservableValue; 12 | 13 | /** 14 | * @author Jeanette Winzenburg, Berlin 15 | */ 16 | public class ChangeReport implements ChangeListener { 17 | 18 | List sources = new LinkedList<>(); 19 | List oldValues = new LinkedList<>(); 20 | List newValues = new LinkedList<>(); 21 | 22 | ObservableValue source; 23 | 24 | public ChangeReport() { 25 | this(null); 26 | } 27 | 28 | /** 29 | * @param object 30 | */ 31 | public ChangeReport(ObservableValue object) { 32 | source = object; 33 | source.addListener(this); 34 | } 35 | 36 | @Override 37 | public void changed(ObservableValue observable, Object oldValue, 38 | Object newValue) { 39 | sources.add(0, observable); 40 | oldValues.add(0, oldValue); 41 | newValues.add(0, newValue); 42 | } 43 | 44 | public int getEventCount() { 45 | return sources.size(); 46 | } 47 | 48 | public Object getLastSource() { 49 | return sources.size() > 0 ? sources.get(0) : null; 50 | } 51 | public Object getLastOldValue() { 52 | return oldValues.size() > 0 ? oldValues.get(0) : null; 53 | } 54 | public Object getLastNewValue() { 55 | return newValues.size() > 0 ? newValues.get(0) : null; 56 | } 57 | 58 | public Object getNewValueAt(int index) { 59 | return index < newValues.size() ? newValues.get(index) : null; 60 | } 61 | public void clear() { 62 | sources.clear(); 63 | newValues.clear(); 64 | oldValues.clear(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/TreeViewSelection_16068.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 19.03.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.application.Application; 8 | import javafx.event.ActionEvent; 9 | import javafx.event.EventHandler; 10 | import javafx.scene.Scene; 11 | import javafx.scene.control.Button; 12 | import javafx.scene.control.TreeItem; 13 | import javafx.scene.control.TreeView; 14 | import javafx.scene.layout.VBox; 15 | import javafx.stage.Stage; 16 | 17 | /** 18 | * Was: selection moved up if item below was removed. 19 | * Fixed for 8u40/8u60 - check u20! 20 | */ 21 | public class TreeViewSelection_16068 extends Application { 22 | 23 | 24 | @Override 25 | public void start(Stage stage) { 26 | VBox content = new VBox(); 27 | final TreeView tree_view = new TreeView(); 28 | TreeItem tree_model = new TreeItem("Root"); 29 | for (int i = 0; i < 3; i++) { 30 | TreeItem node = new TreeItem("Node " + i); 31 | tree_model.getChildren().add(node); 32 | } 33 | tree_view.setRoot(tree_model); 34 | tree_view.setShowRoot(true); 35 | tree_model.setExpanded(true); 36 | Button removeBelow = new Button("Remove \"Node 2\""); 37 | removeBelow.setOnAction(new EventHandler() { 38 | public void handle(ActionEvent t) { 39 | tree_view.getRoot().getChildren().remove(2); 40 | } 41 | }); 42 | content.getChildren().add(tree_view); 43 | content.getChildren().add(removeBelow); 44 | stage.setScene(new Scene(content, 200, 200)); 45 | stage.setTitle(System.getProperty("java.version")); 46 | stage.show(); 47 | tree_view.getSelectionModel().select(2); 48 | } 49 | 50 | public static void main(String[] args) { 51 | launch(TreeViewSelection_16068.class, args); 52 | } 53 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/property/PropertyIgnores.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 31.10.2014 3 | * 4 | */ 5 | package de.swingempire.fx.property; 6 | 7 | import com.codeaffine.test.ConditionalIgnoreRule.IgnoreCondition; 8 | 9 | /** 10 | * Ignores for Property/Observable related tests 11 | * @author Jeanette Winzenburg, Berlin 12 | */ 13 | public class PropertyIgnores { 14 | 15 | /** 16 | * Ignore tests around TreeView.getRow() 17 | * Reported as https://javafx-jira.kenai.com/browse/RT-39661 18 | * 19 | * Tests still failing? Dig! 20 | */ 21 | public static class IgnoreTreeGetRow implements IgnoreCondition { 22 | 23 | @Override 24 | public boolean isSatisfied() { 25 | return true; 26 | } 27 | 28 | } 29 | /** 30 | * Administrative: ignore not yet implemented. 31 | * 32 | * - sorting of tree 33 | */ 34 | public static class IgnoreNotYetImplemented implements IgnoreCondition { 35 | 36 | @Override 37 | public boolean isSatisfied() { 38 | return true; 39 | } 40 | 41 | } 42 | 43 | /** 44 | * Object property doesn't fire change if newVale.equals(oldValue), 45 | * That's by design (impl?), nothing we can do about 46 | *

    47 | * Any test failing due to this is incorrect! Remove 48 | * 49 | */ 50 | public static class IgnoreEqualsNotFire implements IgnoreCondition { 51 | 52 | @Override 53 | public boolean isSatisfied() { 54 | return false; 55 | } 56 | 57 | } 58 | 59 | /** 60 | * Used for reported bugs that are still open. 61 | * 62 | */ 63 | public static class IgnoreReported implements IgnoreCondition { 64 | 65 | @Override 66 | public boolean isSatisfied() { 67 | return true; 68 | } 69 | 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/property/BindingDemo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 30.10.2014 3 | * 4 | */ 5 | package de.swingempire.fx.property; 6 | 7 | import java.util.logging.Logger; 8 | 9 | import javafx.beans.property.SimpleStringProperty; 10 | import javafx.beans.property.StringProperty; 11 | import javafx.beans.value.ChangeListener; 12 | import javafx.beans.value.ObservableValue; 13 | import javafx.scene.control.CheckBox; 14 | 15 | /** 16 | * @author Jeanette Winzenburg, Berlin 17 | */ 18 | public class BindingDemo { 19 | 20 | public static class Demo1 { 21 | 22 | private ChangeListener l = (source, old, value) -> valueChanged(source, old, value); 23 | 24 | /** 25 | * @param source 26 | * @param old 27 | * @param value 28 | * @return 29 | */ 30 | protected void valueChanged(ObservableValue source, T old, 31 | T value) { 32 | LOG.info("" + getClass().getSimpleName()); 33 | } 34 | 35 | public Demo1(ObservableValue source) { 36 | source.addListener(l); 37 | } 38 | } 39 | 40 | public static class Demo2 extends Demo1{ 41 | 42 | public Demo2(ObservableValue source) { 43 | super(source); 44 | } 45 | 46 | @Override 47 | protected void valueChanged(ObservableValue source, T old, 48 | T value) { 49 | LOG.info("I'm the constant"); 50 | } 51 | 52 | 53 | } 54 | 55 | public static void main(String[] args) { 56 | StringProperty p = new SimpleStringProperty("my-my"); 57 | Demo1 first = new Demo1(p); 58 | Demo2 second = new Demo2(p); 59 | p.set("newValue?"); 60 | } 61 | 62 | @SuppressWarnings("unused") 63 | private static final Logger LOG = Logger.getLogger(BindingDemo.class 64 | .getName()); 65 | } 66 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/SliderSnapToTickBug.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 03.12.2015 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import javafx.application.Application; 8 | import javafx.scene.Scene; 9 | import javafx.scene.control.Button; 10 | import javafx.scene.control.Label; 11 | import javafx.scene.control.Slider; 12 | import javafx.scene.layout.VBox; 13 | import javafx.stage.Stage; 14 | 15 | /** 16 | * http://stackoverflow.com/a/34057532/203657 17 | * convert mouse location to value - not really easy! 18 | * 19 | * This is the solution by James_D, very good! Except not working 20 | * without one of ticks/labels. 21 | * 22 | * Both using axis/thumb have a slight offset against value. 23 | * For axis, that's caused by a bug in core 24 | *

  • not adjusting for offset (aka: radius) in mouseHandler. 25 | * 26 | * Using track (instead of axis) can't work because we don't know the 27 | * internal layout. 28 | */ 29 | public class SliderSnapToTickBug extends Application { 30 | 31 | double lowerBound = 5; 32 | double upperBound = 25; 33 | double initialValue = 15; 34 | @Override 35 | public void start(Stage primaryStage) { 36 | Slider slider = new Slider(5, 25, 15); 37 | // show ticks 38 | slider.setShowTickMarks(true); 39 | slider.setShowTickLabels(true); 40 | slider.setMajorTickUnit(10); 41 | 42 | Label valueLabel = new Label(); 43 | valueLabel.textProperty().bind(slider.valueProperty().asString()); 44 | 45 | Button snapTicks = new Button("snap to ticks"); 46 | snapTicks.setOnAction(e -> { 47 | slider.setSnapToTicks(!slider.isSnapToTicks()); 48 | }); 49 | VBox root = new VBox(10, slider, valueLabel, snapTicks); 50 | primaryStage.setScene(new Scene(root, 500, 400)); 51 | primaryStage.show(); 52 | } 53 | 54 | 55 | public static void main(String[] args) { 56 | launch(args); 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/TableVisibleRowCountEckig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 30.01.2015 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import java.util.stream.IntStream; 8 | 9 | import javafx.application.Application; 10 | import javafx.beans.binding.Bindings; 11 | import javafx.beans.property.SimpleStringProperty; 12 | import javafx.geometry.Insets; 13 | import javafx.scene.Scene; 14 | import javafx.scene.control.TableColumn; 15 | import javafx.scene.control.TableView; 16 | import javafx.scene.layout.BorderPane; 17 | import javafx.stage.Stage; 18 | 19 | /** 20 | * "Remove" empty rows: http://stackoverflow.com/a/27949038/203657 21 | * suggestion by Eckig - doesn't work 22 | */ 23 | public class TableVisibleRowCountEckig extends Application { 24 | 25 | @Override 26 | public void start(Stage primaryStage) { 27 | 28 | TableView tableView = new TableView<>(); 29 | tableView.setFixedCellSize(25); 30 | tableView.prefHeightProperty().bind(tableView.fixedCellSizeProperty().multiply(Bindings.size(tableView.getItems()).add(1.01))); 31 | tableView.minHeightProperty().bind(tableView.prefHeightProperty()); 32 | tableView.maxHeightProperty().bind(tableView.prefHeightProperty()); 33 | // testing the extended TableView - works fine 34 | // TableView tableView = new TableViewWithVisibleRowCount<>(); 35 | TableColumn col1 = new TableColumn<>(); 36 | col1.setCellValueFactory(cb -> new SimpleStringProperty(cb.getValue())); 37 | tableView.getColumns().add(col1); 38 | IntStream.range(0, 10).mapToObj(Integer::toString).forEach(tableView.getItems()::add); 39 | 40 | 41 | BorderPane root = new BorderPane(tableView); 42 | root.setPadding(new Insets(10)); 43 | Scene scene = new Scene(root); 44 | primaryStage.setScene(scene); 45 | primaryStage.show(); 46 | } 47 | 48 | public static void main(String[] args) { 49 | launch(args); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/comboboxx/ComboSelectBugRT_38886.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 05.10.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.comboboxx; 6 | 7 | import javafx.application.Application; 8 | import javafx.collections.FXCollections; 9 | import javafx.collections.ObservableList; 10 | import javafx.scene.Scene; 11 | import javafx.scene.control.Button; 12 | import javafx.scene.control.ComboBox; 13 | import javafx.scene.layout.Pane; 14 | import javafx.scene.layout.VBox; 15 | import javafx.stage.Stage; 16 | 17 | /** 18 | * same as 19 | */ 20 | public class ComboSelectBugRT_38886 extends Application { 21 | 22 | @Override 23 | public void start(Stage primaryStage) throws Exception { 24 | ObservableList list = FXCollections.observableArrayList(); 25 | list.add(new StringBuilder("0")); 26 | list.add(new StringBuilder("1")); 27 | list.add(new StringBuilder("2")); 28 | list.add(new StringBuilder("3")); 29 | list.add(new StringBuilder("4")); 30 | list.add(new StringBuilder("5")); 31 | list.add(new StringBuilder("6")); 32 | list.add(new StringBuilder("7")); 33 | list.add(new StringBuilder("8")); 34 | list.add(new StringBuilder("9")); 35 | 36 | ComboBox combo = new ComboBox<>(list); 37 | Button change = new Button("change"); 38 | change.setOnAction((event) -> { 39 | list.set(5, new StringBuilder("-")); 40 | }); 41 | 42 | Button remove = new Button("remove"); 43 | remove.setOnAction(e -> { 44 | Object item = combo.getValue(); 45 | list.remove(item); 46 | 47 | }); 48 | Pane borderPane = new VBox(combo, change, remove); 49 | Scene scene = new Scene(borderPane); 50 | primaryStage.setScene(scene); 51 | primaryStage.show(); 52 | 53 | } 54 | 55 | public static void main(String[] args) { 56 | launch(args); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/property/BidirectionalBinding.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 23.04.2015 3 | * 4 | */ 5 | package de.swingempire.fx.property; 6 | 7 | import javafx.beans.value.ChangeListener; 8 | import javafx.beans.value.ObservableValue; 9 | /** 10 | * Custom bidi-binding that guards against loops. 11 | * from: 12 | * http://wittcarl.deneb.uberspace.de/wordpress/customized-bidirectional-bindings-in-javafx/ 13 | */ 14 | public class BidirectionalBinding { 15 | 16 | /** Executes updateB when propertyA is changed. Executes updateA when propertyB is changed. 17 | * Makes sure that no update loops are caused by mutual updates. 18 | */ 19 | public static void bindBidirectional(ObservableValue propertyA, ObservableValue propertyB, ChangeListener updateB, ChangeListener updateA){ 20 | 21 | addFlaggedChangeListener(propertyA, updateB); 22 | addFlaggedChangeListener(propertyB, updateA); 23 | 24 | } 25 | 26 | /** 27 | * Adds a change listener to a property that will not react to changes caused (transitively) by itself (i.e. from an update call in the call tree that is a descendant of itself.) 28 | * @param property the property to add a change listener to 29 | * @param updateProperty the logic to execute when the property changes 30 | * @param the type of the observable value 31 | */ 32 | private static void addFlaggedChangeListener(ObservableValue property, ChangeListener updateProperty){ 33 | property.addListener(new ChangeListener() { 34 | 35 | private boolean alreadyCalled = false; 36 | 37 | @Override public void changed(ObservableValue observable, T oldValue, T newValue) { 38 | if(alreadyCalled) return; 39 | try { 40 | alreadyCalled = true; 41 | updateProperty.changed(observable,oldValue,newValue); 42 | } 43 | finally { alreadyCalled = false; } 44 | } 45 | }); 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/layout/ChatBubbleDriver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 27.07.2015 3 | * 4 | */ 5 | package de.swingempire.fx.control.layout; 6 | 7 | import javafx.application.Application; 8 | import javafx.geometry.Insets; 9 | import javafx.scene.Group; 10 | import javafx.scene.Scene; 11 | import javafx.scene.control.Label; 12 | import javafx.scene.layout.Background; 13 | import javafx.scene.layout.BackgroundFill; 14 | import javafx.scene.layout.Pane; 15 | import javafx.scene.paint.Color; 16 | import javafx.stage.Stage; 17 | import de.swingempire.fx.control.layout.ChatBubble.BubbleSpec; 18 | 19 | /** 20 | * @author Jeanette Winzenburg, Berlin 21 | */ 22 | public class ChatBubbleDriver extends Application { 23 | 24 | public void start(Stage primaryStage) { 25 | try { 26 | Group root = new Group(); 27 | Scene scene = new Scene(root,400,400); 28 | // scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); 29 | Pane p = new Pane(); 30 | p.setShape(new ChatBubble(BubbleSpec.FACE_TOP)); 31 | p.setPrefSize(400, 400); 32 | p.setBackground(new Background(new BackgroundFill(Color.GOLD, 33 | null, null))); 34 | root.getChildren().add(p); 35 | Label label = new Label("Madam Kleopatra this is it"); 36 | label.setShape(new ChatBubble(BubbleSpec.FACE_LEFT_CENTER)); 37 | p.getChildren().add(label); 38 | label.setBackground(new Background(new BackgroundFill(Color.YELLOW, 39 | null, null))); 40 | label.setPrefSize(200, 100); 41 | // label.setPadding(new Insets(20)); 42 | label.relocate(100, 100); 43 | primaryStage.setScene(scene); 44 | primaryStage.show(); 45 | } catch(Exception e) { 46 | e.printStackTrace(); 47 | } 48 | } 49 | public static void main(String[] args) { 50 | launch(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /fx8-swingempire/src/test/fx/collection/SimpleTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package fx.collection; 7 | 8 | import java.util.logging.Logger; 9 | 10 | import javafx.application.Platform; 11 | import javafx.collections.FXCollections; 12 | import javafx.collections.ObservableList; 13 | import javafx.scene.control.ListView; 14 | import javafx.scene.control.SelectionModel; 15 | 16 | import org.junit.Before; 17 | import org.junit.BeforeClass; 18 | import org.junit.ClassRule; 19 | import org.junit.Rule; 20 | import org.junit.Test; 21 | import org.junit.runner.RunWith; 22 | import org.junit.runners.JUnit4; 23 | 24 | import de.swingempire.fx.junit.JavaFXThreadingRule; 25 | 26 | /** 27 | * 28 | * @author kleopatra 29 | */ 30 | @RunWith(JUnit4.class) 31 | public class SimpleTest { //extends TestCase{ 32 | @ClassRule public static JavaFXThreadingRule classfxRule = new JavaFXThreadingRule(); 33 | // @Rule public JavaFXThreadingRule javafxRule = new JavaFXThreadingRule(); 34 | 35 | protected ObservableList items; 36 | protected SelectionModel selectionModel; 37 | 38 | @Test 39 | public void testMe() { 40 | 41 | LOG.info("testMe " + Platform.isFxApplicationThread()); 42 | } 43 | 44 | @BeforeClass 45 | public static void init() { 46 | // JFXPanel panel = new JFXPanel(); 47 | 48 | } 49 | 50 | @Before 51 | // @Override 52 | public void setUp() { 53 | items = FXCollections.observableArrayList( 54 | "5-item", "4-item", "3-item", "2-item", "1-item"); 55 | 56 | LOG.info("setup ..."); 57 | ListView view = new ListView(items); 58 | selectionModel = view.getSelectionModel(); 59 | } 60 | 61 | @SuppressWarnings("unused") 62 | private static final Logger LOG = Logger.getLogger(SimpleTest.class 63 | .getName()); 64 | } 65 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/ListViewSelection_37632.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 19.03.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.application.Application; 8 | import javafx.collections.FXCollections; 9 | import javafx.collections.ObservableList; 10 | import javafx.scene.Scene; 11 | import javafx.scene.control.Label; 12 | import javafx.scene.control.ListView; 13 | import javafx.scene.control.TextField; 14 | import javafx.scene.layout.VBox; 15 | import javafx.stage.Stage; 16 | 17 | /** 18 | * selectedIndex out of sync with selected indices 19 | * 20 | * fixed 8u60b5 21 | */ 22 | public class ListViewSelection_37632 extends Application { 23 | 24 | @Override 25 | public void start(Stage stage) 26 | { 27 | final ObservableList listOne = FXCollections.observableArrayList("A", "B", "C"); 28 | final ObservableList listTwo = FXCollections.observableArrayList("C"); 29 | 30 | final ListView listView = new ListView<>(); 31 | listView.setItems(listOne); 32 | listView.onMouseClickedProperty().setValue(e -> { 33 | System.err.println("selectedIndex = " + listView.getSelectionModel().getSelectedIndex()); 34 | System.err.println("selectedIndices = " + listView.getSelectionModel().getSelectedIndices()); 35 | }); 36 | listView.getSelectionModel().selectFirst(); 37 | 38 | TextField textField = new TextField(); 39 | textField.onKeyReleasedProperty().setValue(e -> listView.setItems(listTwo)); 40 | 41 | final Label label = new Label(); 42 | label.textProperty().bind(listView.selectionModelProperty().getValue().selectedItemProperty()); 43 | 44 | VBox root = new VBox(10, label, textField, listView); 45 | Scene scene = new Scene(root, 800, 600); 46 | 47 | stage.setScene(scene); 48 | stage.show(); 49 | } 50 | 51 | public static void main(String[] args) { 52 | launch(args); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/concurrency/ProgressTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 24.09.2015 3 | * 4 | */ 5 | package de.swingempire.fx.concurrency; 6 | 7 | import javafx.application.Application; 8 | import javafx.concurrent.Task; 9 | import javafx.scene.Parent; 10 | import javafx.scene.Scene; 11 | import javafx.scene.control.Button; 12 | import javafx.scene.control.ProgressBar; 13 | import javafx.scene.layout.VBox; 14 | import javafx.stage.Stage; 15 | import de.swingempire.fx.util.FXUtils; 16 | 17 | /** 18 | * Minimal example to bind to a Task's progress. 19 | * http://stackoverflow.com/q/32757069/203657 20 | * @author Jeanette Winzenburg, Berlin 21 | */ 22 | public class ProgressTask extends Application { 23 | 24 | @Override 25 | public void start(Stage primaryStage) throws Exception { 26 | primaryStage.setScene(new Scene(getContent())); 27 | primaryStage.setTitle(FXUtils.version()); 28 | primaryStage.show(); 29 | } 30 | 31 | /** 32 | * @return 33 | */ 34 | private Parent getContent() { 35 | ProgressBar bar = new ProgressBar(0); 36 | Button button = new Button("Start"); 37 | Task task = new Task() { 38 | 39 | @Override 40 | protected Void call() throws Exception { 41 | long max = 137; 42 | for (int i = 0; i <= max; i++) { 43 | updateProgress(i, max); 44 | Thread.sleep(100); 45 | } 46 | return null; 47 | } 48 | 49 | }; 50 | button.setOnAction(e -> { 51 | // a task is not reusable, disable 52 | button.setDisable(true); 53 | // bind "late" to not get an initial indeterminate PB 54 | bar.progressProperty().bind(task.progressProperty()); 55 | new Thread(task).start(); 56 | }); 57 | VBox pane = new VBox(10, bar, button); 58 | return pane; 59 | } 60 | 61 | public static void main(String[] args) { 62 | launch(args); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/selection/DefaultSelectionModelJ.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 29.10.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.beans.property.ListProperty; 8 | import javafx.beans.property.ReadOnlyIntegerProperty; 9 | import javafx.beans.property.ReadOnlyIntegerWrapper; 10 | import javafx.beans.property.SimpleListProperty; 11 | import javafx.collections.ObservableList; 12 | 13 | /** 14 | * @author Jeanette Winzenburg, Berlin 15 | */ 16 | public class DefaultSelectionModelJ implements SelectionModelJ { 17 | 18 | private ListProperty itemsList = new SimpleListProperty<>(this, "itemsList", null); 19 | private ReadOnlyIntegerWrapper selectedIndex = new ReadOnlyIntegerWrapper(this, "selectedIndex", -1); 20 | 21 | public DefaultSelectionModelJ() { 22 | this(null); 23 | } 24 | 25 | /** 26 | * @param items 27 | */ 28 | public DefaultSelectionModelJ(ListProperty items) { 29 | if (items != null) { 30 | itemsList.bind(items); 31 | } 32 | } 33 | 34 | public DefaultSelectionModelJ(ObservableList items) { 35 | itemsList.set(items); 36 | } 37 | 38 | protected ListProperty itemsListProperty() { 39 | return itemsList; 40 | } 41 | 42 | 43 | @Override 44 | public int getItemCount() { 45 | return itemsListProperty().size(); 46 | } 47 | 48 | protected void setSelectedIndex(int value) { selectedIndex.set(value); } 49 | 50 | @Override 51 | public final ReadOnlyIntegerProperty selectedIndexProperty() { 52 | return selectedIndex.getReadOnlyProperty(); 53 | } 54 | 55 | @Override 56 | public void clearAndSelect(int index) { 57 | if (!isSelectable(index)) return; 58 | setSelectedIndex(index); 59 | } 60 | 61 | @Override 62 | public void clearSelection(int index) { 63 | if (!isSelected(index)) return; 64 | clearSelection(); 65 | } 66 | 67 | @Override 68 | public void clearSelection() { 69 | setSelectedIndex(-1); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/TreeTableReorderNullPointerException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 08.04.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.application.Application; 8 | import javafx.scene.Scene; 9 | import javafx.scene.control.TreeItem; 10 | import javafx.scene.control.TreeTableColumn; 11 | import javafx.scene.control.TreeTableView; 12 | import javafx.scene.control.cell.TreeItemPropertyValueFactory; 13 | import javafx.stage.Stage; 14 | import de.swingempire.fx.demobean.Person; 15 | 16 | /** 17 | * https://javafx-jira.kenai.com/browse/RT-38888 18 | */ 19 | public class TreeTableReorderNullPointerException extends Application { 20 | @Override 21 | public void start(Stage primaryStage) throws Exception { 22 | TreeTableView treeTable = new TreeTableView<>(); 23 | treeTable.setShowRoot(false); 24 | 25 | TreeTableColumn column = new TreeTableColumn<>("Name"); 26 | column.setCellValueFactory(new TreeItemPropertyValueFactory<>("lastName")); 27 | treeTable.getColumns().add(column); 28 | 29 | TreeItem root = new TreeItem<>(new Person(null,"root", null)); 30 | treeTable.setRoot(root); 31 | 32 | TreeItem one = new TreeItem<>(new Person(null,"one", null)); 33 | root.getChildren().add(one); 34 | 35 | TreeItem two = new TreeItem<>(new Person(null,"two", null)); 36 | root.getChildren().add(two); 37 | 38 | // Select two, then move two from root to one. 39 | treeTable.getSelectionModel().select(two); 40 | root.getChildren().remove(two); 41 | System.out.println("selected after remove: " 42 | + treeTable.getSelectionModel().getSelectedItem() 43 | + treeTable.getSelectionModel().getSelectedIndex() 44 | ); 45 | one.getChildren().add(two); 46 | one.setExpanded(true); 47 | 48 | primaryStage.setScene(new Scene(treeTable)); 49 | primaryStage.show(); 50 | } 51 | 52 | public static void main(String[] args) { 53 | launch(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/et/LabeledFocus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 03.03.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.et; 6 | 7 | import java.util.logging.Logger; 8 | 9 | import javafx.application.Application; 10 | import javafx.scene.Parent; 11 | import javafx.scene.Scene; 12 | import javafx.scene.control.ContextMenu; 13 | import javafx.scene.control.Label; 14 | import javafx.scene.control.Labeled; 15 | import javafx.scene.control.MenuItem; 16 | import javafx.scene.input.MouseEvent; 17 | import javafx.scene.layout.HBox; 18 | import javafx.stage.Stage; 19 | 20 | /** 21 | * @author Jeanette Winzenburg, Berlin 22 | */ 23 | public class LabeledFocus extends Application { 24 | 25 | private Labeled createLabel(String text) { 26 | Labeled label = new Label(text); 27 | label.setFocusTraversable(true); 28 | label.setContextMenu(new ContextMenu(new MenuItem(text))); 29 | label.addEventHandler(MouseEvent.MOUSE_PRESSED, e -> { 30 | label.requestFocus(); 31 | }); 32 | return label; 33 | } 34 | private Parent getContent() { 35 | HBox pane = new HBox(10, createLabel("first label"), createLabel("secondLabel")); 36 | return pane; 37 | } 38 | 39 | @Override 40 | public void start(Stage primaryStage) throws Exception { 41 | Scene scene = new Scene(getContent()); 42 | // scene.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, e -> e.consume()); 43 | // scene.addEventFilter(ContextMenuEvent.CONTEXT_MENU_REQUESTED, e -> e.consume()); 44 | scene.focusOwnerProperty().addListener((source, old, value) -> { 45 | String change = "focusOwner old/new: " 46 | + "\n old: " + old 47 | + "\n new: " + value; 48 | LOG.info(change); 49 | }); 50 | primaryStage.setScene(scene); 51 | primaryStage.show(); 52 | } 53 | 54 | public static void main(String[] args) { 55 | launch(args); 56 | } 57 | 58 | @SuppressWarnings("unused") 59 | private static final Logger LOG = Logger.getLogger(LabeledFocus.class 60 | .getName()); 61 | } 62 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/ControlUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 10.11.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control; 6 | 7 | import java.util.Objects; 8 | import java.util.function.Function; 9 | 10 | import javafx.beans.property.ReadOnlyObjectWrapper; 11 | import javafx.beans.value.ObservableValue; 12 | import javafx.scene.control.TableColumn.CellDataFeatures; 13 | import javafx.util.Callback; 14 | 15 | /** 16 | * PENDING JW: unused, still favoring property access by name, old habits :-) 17 | */ 18 | public class ControlUtils { 19 | 20 | /** 21 | * Type-safe replacement of PropertyValueFactory. 22 | * 23 | */ 24 | public static class PropertyFactory implements 25 | Callback, ObservableValue>{ 26 | 27 | private final Function> function; 28 | public PropertyFactory(Function> function) { 29 | this.function = Objects.requireNonNull(function, "function must not be null"); 30 | } 31 | @Override 32 | public ObservableValue call(CellDataFeatures data) { 33 | if (data == null || data.getValue() == null) return null; 34 | return function.apply(data.getValue()); 35 | } 36 | 37 | } 38 | 39 | /** 40 | * Type-safe replacement of PropertyValueFactory. 41 | * 42 | */ 43 | public static class ObservableFactory implements 44 | Callback, ObservableValue>{ 45 | 46 | private final Function function; 47 | public ObservableFactory(Function method) { 48 | this.function = Objects.requireNonNull(method, "function must not be null"); 49 | } 50 | 51 | @Override 52 | public ObservableValue call(CellDataFeatures data) { 53 | if (data == null || data.getValue() == null) return null; 54 | T result = function.apply(data.getValue()); 55 | return new ReadOnlyObjectWrapper(result); 56 | } 57 | } 58 | 59 | private ControlUtils() {} 60 | 61 | } 62 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/property/albumdemo/AlbumFxDriver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 21.05.2014 3 | * 4 | */ 5 | package de.swingempire.fx.property.albumdemo; 6 | 7 | import javafx.application.Application; 8 | import javafx.scene.Parent; 9 | import javafx.scene.Scene; 10 | import javafx.scene.control.CheckBox; 11 | import javafx.scene.control.Label; 12 | import javafx.scene.control.TextField; 13 | import javafx.scene.layout.Pane; 14 | import javafx.scene.layout.VBox; 15 | import javafx.stage.Stage; 16 | 17 | /** 18 | * @author Jeanette Winzenburg, Berlin 19 | */ 20 | public class AlbumFxDriver extends Application { 21 | 22 | private CheckBox checkBox; 23 | private TextField textField; 24 | private AlbumFx album; 25 | private Label label; 26 | 27 | public AlbumFxDriver() { 28 | album = new AlbumFx(); 29 | // album.setClassical(true); 30 | initComponents(); 31 | bindComponents(); 32 | } 33 | /** 34 | * 35 | */ 36 | private void bindComponents() { 37 | checkBox.selectedProperty().bindBidirectional(album.classicalProperty()); 38 | textField.textProperty().bindBidirectional(album.composerProperty()); 39 | // following line to see self-protection fail with IllegalStateExcetpion 40 | // album.composerProperty().bind(textField.textProperty()); 41 | label.textProperty().bind(album.composerProperty()); 42 | } 43 | /** 44 | * @return 45 | */ 46 | private Parent createContent() { 47 | Pane root = new VBox(); 48 | root.getChildren().addAll(checkBox, textField, label); 49 | return root; 50 | } 51 | protected void initComponents() { 52 | checkBox = new CheckBox("classical"); 53 | textField = new TextField(); 54 | label = new Label(); 55 | } 56 | 57 | @Override 58 | public void start(Stage primaryStage) throws Exception { 59 | Parent root = createContent(); 60 | Scene scene = new Scene(root); 61 | primaryStage.setScene(scene); 62 | primaryStage.show(); 63 | } 64 | 65 | public static void main(String[] args) { 66 | launch(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/chart/HorizontalBarExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 07.10.2015 3 | * 4 | */ 5 | package de.swingempire.fx.chart; 6 | 7 | import javafx.application.Application; 8 | import javafx.collections.FXCollections; 9 | import javafx.collections.ObservableList; 10 | import javafx.scene.Scene; 11 | import javafx.scene.chart.BarChart; 12 | import javafx.scene.chart.CategoryAxis; 13 | import javafx.scene.chart.NumberAxis; 14 | import javafx.scene.chart.XYChart; 15 | import javafx.stage.Stage; 16 | 17 | /** 18 | * Category axis rotates on getting smaller, such that the labels are no longer 19 | * visible 20 | * 21 | * http://stackoverflow.com/q/32979001/203657 22 | */ 23 | public class HorizontalBarExample extends Application { 24 | @Override 25 | public void start(Stage stage) { 26 | NumberAxis xAxis = new NumberAxis(); 27 | CategoryAxis yAxis = new CategoryAxis(); 28 | BarChart bc = new BarChart(xAxis, yAxis); 29 | bc.setBarGap(0d); 30 | bc.setCategoryGap(0); 31 | 32 | xAxis.setTickLabelRotation(90); 33 | yAxis.tickLabelRotationProperty().set(0d); 34 | 35 | XYChart.Series series1 = new XYChart.Series<>(); 36 | series1.setName("example"); 37 | ObservableList categories = FXCollections.observableArrayList(); 38 | for (int i = 0; i < 10; i++) { 39 | String yValue = "long data label number" + i; 40 | series1.getData().add(new XYChart.Data(Math.random() * 5000, yValue)); 41 | categories.add(yValue); 42 | } 43 | 44 | bc.getData().add(series1); 45 | 46 | // without auto-ranging, the labels are not rotated 47 | // requires manual setting of categories 48 | // layout suboptimal! 49 | // yAxis.setAutoRanging(false); 50 | // yAxis.setCategories(categories); 51 | 52 | series1.getData(); 53 | Scene scene = new Scene(bc, 800, 600); 54 | stage.setScene(scene); 55 | stage.show(); 56 | } 57 | 58 | public static void main(String[] args) { 59 | launch(args); 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/skin/patch8/BehaviorBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 15.03.2016 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.skin.patch8; 6 | 7 | import java.util.Map; 8 | import java.util.function.Predicate; 9 | 10 | import javafx.event.EventHandler; 11 | import javafx.event.EventType; 12 | import javafx.scene.control.Control; 13 | import javafx.scene.input.KeyCode; 14 | import javafx.scene.input.KeyCodeCombination; 15 | import javafx.scene.input.KeyEvent; 16 | import javafx.scene.input.MouseEvent; 17 | 18 | 19 | /** 20 | * @author Jeanette Winzenburg, Berlin 21 | */ 22 | public abstract class BehaviorBase 23 | extends com.sun.javafx.scene.control.behavior.BehaviorBase { 24 | 25 | /** 26 | * Super constructor expects a list of KeyBindings. Note that its 27 | * bindings field is final (no injection!) and it creates a 28 | * unmodifiable List from the given list. So here the parameter 29 | * must be some kind of factory again, that produces the list for 30 | * super. 31 | * 32 | * @param control 33 | * @param bindings 34 | */ 35 | public BehaviorBase(C control, String bindingsKey) { 36 | super(control, KeyBindingsFactory.createKeyBindings(bindingsKey)); 37 | } 38 | 39 | //---------- compatibility API, no-ops 40 | 41 | /** 42 | * Compatibility API: no-op in fx-8, mainly because super's keyBindings 43 | * are final and immutatble in super. Nothing we can do about it ... 44 | * 45 | * @param key 46 | * @param c 47 | */ 48 | protected void addDefaultKeyBinding(KeyCode key, EventHandler handler) { 49 | } 50 | 51 | protected void addDefaultKeyBinding(KeyCodeCombination key, EventHandler c) { 52 | } 53 | 54 | protected void addDefaultFocusTraversalMapping() { 55 | } 56 | 57 | protected void addDefaultMouseBinding(EventType type, EventHandler handler) { 58 | } 59 | 60 | protected void createAndAddDefaultChildKeyBindings( 61 | Map> keyBindings, Predicate interceptor) { 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/TreeViewSample_RT_38334.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 05.01.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.application.Application; 8 | import javafx.scene.Scene; 9 | import javafx.scene.control.TreeItem; 10 | import javafx.scene.control.TreeView; 11 | import javafx.scene.layout.StackPane; 12 | import javafx.stage.Stage; 13 | 14 | /** 15 | * SelectedItems contains null if unselected 16 | * grand-parent of selected item is removed 17 | * 18 | * https://javafx-jira.kenai.com/browse/RT-38334 19 | */ 20 | public class TreeViewSample_RT_38334 extends Application { 21 | 22 | public static void main(String[] args) { 23 | launch(args); 24 | } 25 | 26 | @Override 27 | public void start(Stage primaryStage) { 28 | 29 | // Construct and display a TreeView. 30 | primaryStage.setTitle("Tree View Sample"); 31 | TreeItem rootItem = new TreeItem ("Root"); 32 | TreeView tree = new TreeView (rootItem); 33 | rootItem.setExpanded(true); 34 | TreeItem lastItem=rootItem; 35 | for (int i = 1; i < 4; i++) { 36 | TreeItem item = new TreeItem ("Level" + i); 37 | item.setExpanded(true); 38 | lastItem.getChildren().add(item); 39 | lastItem=item; 40 | } 41 | StackPane root = new StackPane(); 42 | root.getChildren().add(tree); 43 | primaryStage.setScene(new Scene(root, 300, 250)); 44 | primaryStage.show(); 45 | 46 | // Select the Level 3 item. 47 | tree.getSelectionModel().selectLast(); 48 | 49 | // Remove the (unselected) Level 2 item, including its selected Level 3 child. 50 | rootItem.getChildren().get(0).getChildren().remove(0); 51 | 52 | // Dump the selected items list to stdout. With Java 8 update 11, I see one "null" item in this output. I'd expect a zero-length list. 53 | for (TreeItem item : tree.getSelectionModel().getSelectedItems()) 54 | System.out.println("getSelectedItems() element = "+((item==null) ? "null" : item.toString())); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/tree/Leafness.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 06.01.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.tree; 6 | 7 | import javafx.collections.ObservableList; 8 | import javafx.scene.control.TreeItem; 9 | 10 | /** 11 | * Experiment: defining leafness such that subclasses of TreeItem can 12 | * customize state depending on either children list state or value state 13 | * (or anything in between?) 14 | * 15 | * @author Jeanette Winzenburg, Berlin 16 | */ 17 | public interface Leafness { 18 | 19 | /** 20 | * The semantic leaf property. Base implementations will implement 21 | * it as low-level leaf (== !hasChildren), extending implmentations 22 | * can take allowsChildren/askAllowsChildren into account to 23 | * differentiate f.i. an empty folder node from a file.

    24 | * 25 | * In Swing, isLeaf == !hasChildren and defined in TreeNode. 26 | * @return 27 | * 28 | * @see javafx.scene.control.TreeItem#isLeaf() 29 | * @see javafx.scene.control.TreeItem#leafProperty() 30 | */ 31 | boolean isLeaf(); 32 | 33 | /** 34 | * Returns true if leaf should depend on allowsChildren. 35 | * The default value is false. 36 | * 37 | * In Swing, this is a mutable property of DefaultTreeModel. 38 | * @return 39 | */ 40 | default boolean isAskAllowsChildren() { 41 | return false; 42 | } 43 | 44 | /** 45 | * Returns true if this can have children, false if not. 46 | * The default implementation returns true. 47 | * 48 | * In Swing, this is a mutable property of TreeNode. 49 | * @return 50 | */ 51 | default boolean isAllowsChildren() { 52 | return true; 53 | } 54 | 55 | /** 56 | * Returns true if the children list is not empty. 57 | * @return 58 | */ 59 | default boolean hasChildren() { 60 | return !getChildren().isEmpty(); 61 | } 62 | 63 | /** 64 | * Returns the list of children. Guaranteed to be not null, but may be 65 | * empty or not modifiable. 66 | * 67 | * @return 68 | */ 69 | ObservableList> getChildren(); 70 | 71 | } 72 | -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/scene/control/selection/SelectionUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 04.12.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.collections.FXCollections; 8 | import javafx.collections.ObservableList; 9 | import javafx.scene.control.MultipleSelectionModel; 10 | 11 | /** 12 | * Mainly no-op. Just used to replace any old model 13 | * @author Jeanette Winzenburg, Berlin 14 | */ 15 | public class SelectionUtils { 16 | 17 | public static class TestMultipleSelectionModel extends MultipleSelectionModel { 18 | 19 | @Override 20 | public ObservableList getSelectedIndices() { 21 | return FXCollections.emptyObservableList(); 22 | } 23 | 24 | @Override 25 | public ObservableList getSelectedItems() { 26 | return FXCollections.emptyObservableList(); 27 | } 28 | 29 | @Override 30 | public void selectIndices(int index, int... indices) { 31 | } 32 | 33 | @Override 34 | public void selectAll() { 35 | } 36 | 37 | @Override 38 | public void selectFirst() { 39 | } 40 | 41 | @Override 42 | public void selectLast() { 43 | } 44 | 45 | @Override 46 | public void clearAndSelect(int index) { 47 | } 48 | 49 | @Override 50 | public void select(int index) { 51 | } 52 | 53 | @Override 54 | public void select(T obj) { 55 | } 56 | 57 | @Override 58 | public void clearSelection(int index) { 59 | } 60 | 61 | @Override 62 | public void clearSelection() { 63 | } 64 | 65 | @Override 66 | public boolean isSelected(int index) { 67 | return false; 68 | } 69 | 70 | @Override 71 | public boolean isEmpty() { 72 | return false; 73 | } 74 | 75 | @Override 76 | public void selectPrevious() { 77 | } 78 | 79 | @Override 80 | public void selectNext() { 81 | } 82 | 83 | } 84 | 85 | private SelectionUtils() { 86 | 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/TreeEllipsisNoScrollRT_19468.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 22.01.2015 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import javafx.application.Application; 8 | import javafx.scene.Parent; 9 | import javafx.scene.Scene; 10 | import javafx.scene.control.TreeItem; 11 | import javafx.scene.control.TreeView; 12 | import javafx.scene.layout.HBox; 13 | import javafx.scene.layout.Pane; 14 | import javafx.scene.paint.Color; 15 | import javafx.scene.shape.Rectangle; 16 | import javafx.stage.Stage; 17 | 18 | /** 19 | * TreeCell showing ellipsis instead of scrollbars. 20 | * 21 | * https://javafx-jira.kenai.com/browse/RT-19468 22 | * 23 | * Hmm ... can't reproduce in 8u40b20 24 | */ 25 | public class TreeEllipsisNoScrollRT_19468 extends Application { 26 | 27 | public static void main(String[] args) { 28 | Application.launch(args); 29 | } 30 | 31 | private Parent getContent() { 32 | Pane pane = new HBox(); 33 | TreeItem root = new TreeItem("ROOT", new Rectangle(20, 20, Color.CHOCOLATE)); 34 | root.setExpanded(true); 35 | TreeItem firstBrunch = new TreeItem("brunch 1"); 36 | firstBrunch.setExpanded(true); 37 | firstBrunch.getChildren().addAll(new TreeItem("first item"), new TreeItem("second item", new Rectangle(20, 20, Color.DARKGREY))); 38 | root.getChildren().addAll(firstBrunch); 39 | TreeItem secondBrunch = new TreeItem("brunch 2"); 40 | secondBrunch.getChildren().addAll(new TreeItem("first item"), new TreeItem("second item", new Rectangle(20, 20, Color.DARKGREY))); 41 | root.getChildren().addAll(secondBrunch); 42 | TreeView tree = new TreeView(root); 43 | tree.setFocusTraversable(false); 44 | tree.setMaxSize(130,140); 45 | pane.getChildren().add(tree); 46 | return pane; 47 | } 48 | 49 | public void start(Stage stage) { 50 | stage.setX(100); 51 | stage.setY(100); 52 | stage.setWidth(700); 53 | stage.setHeight(700); 54 | Scene scene = new Scene(getContent()); 55 | stage.setScene(scene); 56 | stage.show(); 57 | } 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/ListViewItemBug_37632.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 04.09.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.application.Application; 8 | import javafx.collections.FXCollections; 9 | import javafx.collections.ObservableList; 10 | import javafx.scene.Scene; 11 | import javafx.scene.control.Label; 12 | import javafx.scene.control.ListView; 13 | import javafx.scene.control.TextField; 14 | import javafx.scene.layout.VBox; 15 | import javafx.stage.Stage; 16 | 17 | /** 18 | * https://javafx-jira.kenai.com/browse/RT-37632 19 | * listView may not return selected item 20 | * 21 | * Type a character in the TextField then click on "C" in the resulting list. 22 | * Notice that getSelectedIndex() and getSelectedIndices() do not return the same value 23 | * 24 | * reported as fixed in 8u40 25 | */ 26 | public class ListViewItemBug_37632 extends Application { 27 | 28 | @Override 29 | public void start(Stage stage) 30 | { 31 | final ObservableList listOne = FXCollections.observableArrayList("A", "B", "C"); 32 | final ObservableList listTwo = FXCollections.observableArrayList("C"); 33 | 34 | final ListView listView = new ListView<>(); 35 | listView.setItems(listOne); 36 | listView.onMouseClickedProperty().setValue(e -> { 37 | System.err.println("selectedIndex = " + listView.getSelectionModel().getSelectedIndex()); 38 | System.err.println("selectedIndices = " + listView.getSelectionModel().getSelectedIndices()); 39 | }); 40 | listView.getSelectionModel().selectFirst(); 41 | 42 | TextField textField = new TextField(); 43 | textField.onKeyReleasedProperty().setValue(e -> listView.setItems(listTwo)); 44 | 45 | final Label label = new Label(); 46 | label.textProperty().bind(listView.selectionModelProperty().getValue().selectedItemProperty()); 47 | 48 | VBox root = new VBox(10, label, textField, listView); 49 | Scene scene = new Scene(root, 800, 600); 50 | 51 | stage.setScene(scene); 52 | stage.show(); 53 | } 54 | 55 | public static void main(String[] args) { 56 | launch(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/MultipleSelectionModelBase_RT_40185.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 04.03.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Collections; 9 | 10 | import javafx.application.Application; 11 | import javafx.collections.ListChangeListener; 12 | import javafx.scene.control.ListView; 13 | import javafx.scene.control.SelectionMode; 14 | import javafx.stage.Stage; 15 | 16 | 17 | /** 18 | * ClearSelection in MultipleSelectionModelBase is incorrect. 19 | * https://javafx-jira.kenai.com/browse/RT-40185 20 | */ 21 | public class MultipleSelectionModelBase_RT_40185 extends Application { 22 | 23 | public static void main(String[] args) { 24 | launch(); 25 | } 26 | 27 | @Override 28 | public void start(Stage stage) { 29 | final ListView lv = new ListView<>(); 30 | // lv.setSelectionModel(new SimpleListSelectionModel<>(lv)); 31 | final ArrayList expected = new ArrayList<>(); 32 | Collections.addAll(expected, 1, 2); 33 | 34 | lv.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); 35 | lv.getSelectionModel() 36 | .getSelectedIndices() 37 | .addListener( 38 | (ListChangeListener) change -> { 39 | while (change.next()) { 40 | if (change.wasRemoved()) { 41 | System.out.println(change.getRemoved() 42 | .toString() 43 | + " <-> " 44 | + expected.toString()); 45 | if (!change.getRemoved().equals(expected)) 46 | throw new IllegalStateException("expected/actual: " + expected + "/" + change.getRemoved()); 47 | } 48 | } 49 | }); 50 | 51 | lv.getItems().addAll("-0-", "-1-", "-2-"); 52 | lv.getSelectionModel().selectIndices(1, 2); 53 | lv.getSelectionModel().clearSelection(); 54 | System.exit(-1); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/property/TriggerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 24.05.2014 3 | * 4 | */ 5 | package de.swingempire.fx.property; 6 | 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.junit.runners.JUnit4; 11 | 12 | import de.swingempire.fx.util.ChangeReport; 13 | import static org.junit.Assert.*; 14 | 15 | /** 16 | * @author Jeanette Winzenburg, Berlin 17 | */ 18 | @RunWith(JUnit4.class) 19 | public class TriggerTest { 20 | 21 | private Trigger triggerValue; 22 | private ChangeReport report; 23 | 24 | @Test 25 | public void testTriggerCommitTwice() { 26 | triggerValue.triggerCommit(); 27 | report.clear(); 28 | triggerValue.triggerCommit(); 29 | assertEquals("value must be true after commit", Boolean.TRUE, triggerValue.getValue()); 30 | // JW: it's 3 including the first change from null to true 31 | assertEquals("change event count", 2, report.getEventCount()); 32 | } 33 | 34 | @Test 35 | public void testTriggerFlushTwice() { 36 | triggerValue.triggerFlush(); 37 | report.clear(); 38 | triggerValue.triggerFlush(); 39 | assertEquals("value must be true after flush", Boolean.FALSE, triggerValue.getValue()); 40 | // JW: it's 3 including the first change from null to true 41 | assertEquals("change event count", 2, report.getEventCount()); 42 | } 43 | @Test 44 | public void testTriggerCommit() { 45 | triggerValue.triggerCommit(); 46 | assertEquals("value must be true after commit", Boolean.TRUE, triggerValue.getValue()); 47 | assertEquals("change event count", 1, report.getEventCount()); 48 | } 49 | 50 | @Test 51 | public void testTriggerFlush() { 52 | triggerValue.triggerFlush(); 53 | assertEquals("value must be true after flush", Boolean.FALSE, triggerValue.getValue()); 54 | assertEquals("change event count", 1, report.getEventCount()); 55 | 56 | } 57 | 58 | @Test 59 | public void testTriggerValueInitial() { 60 | assertNull(triggerValue.getValue()); 61 | } 62 | 63 | @Before 64 | public void setup() { 65 | triggerValue = new Trigger(); 66 | report = new ChangeReport(triggerValue); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/TableSortNPEIfNullSelectionModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 09.12.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import java.util.Locale; 8 | 9 | import javafx.application.Application; 10 | import javafx.collections.FXCollections; 11 | import javafx.collections.ObservableList; 12 | import javafx.geometry.Insets; 13 | import javafx.scene.Parent; 14 | import javafx.scene.Scene; 15 | import javafx.scene.control.TableColumn; 16 | import javafx.scene.control.TableView; 17 | import javafx.scene.control.cell.PropertyValueFactory; 18 | import javafx.scene.layout.HBox; 19 | import javafx.scene.layout.Pane; 20 | import javafx.stage.Stage; 21 | 22 | /** 23 | * Issue TableView throws NPE on sorting column if selectionModel property value is null. 24 | * reported https://javafx-jira.kenai.com/browse/RT-39624 25 | * 26 | * @author Jeanette Winzenburg, Berlin 27 | */ 28 | public class TableSortNPEIfNullSelectionModel extends Application { 29 | private final ObservableList data = 30 | FXCollections.observableArrayList(Locale.getAvailableLocales() 31 | ); 32 | 33 | private Parent getContent() { 34 | // instantiate the table with null items 35 | TableView view = new TableView(data); 36 | TableColumn column = new TableColumn<>( 37 | "Language"); 38 | column.setCellValueFactory(new PropertyValueFactory<>("displayLanguage")); 39 | // either click on header for sorting 40 | view.getColumns().addAll(column); 41 | view.setSelectionModel(null); 42 | // or add column to sort order immediately 43 | //view.getSortOrder().add(column); 44 | Pane parent = new HBox(100); 45 | parent.getChildren().addAll(view); 46 | parent.setPadding(new Insets(20)); 47 | return parent; 48 | } 49 | 50 | @Override 51 | public void start(Stage primaryStage) throws Exception { 52 | Scene scene = new Scene(getContent()); 53 | primaryStage.setTitle(System.getProperty("java.version")); 54 | primaryStage.setScene(scene); 55 | primaryStage.show(); 56 | } 57 | 58 | public static void main(String[] args) { 59 | launch(); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/ListFocusedCellDefault_38517.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 14.07.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import java.util.Locale; 8 | import java.util.logging.Logger; 9 | 10 | import de.swingempire.fx.util.FXUtils; 11 | import javafx.application.Application; 12 | import javafx.collections.FXCollections; 13 | import javafx.collections.ObservableList; 14 | import javafx.scene.Scene; 15 | import javafx.scene.control.Button; 16 | import javafx.scene.control.ListView; 17 | import javafx.scene.control.SelectionMode; 18 | import javafx.scene.control.TableColumn; 19 | import javafx.scene.control.cell.PropertyValueFactory; 20 | import javafx.scene.input.KeyCode; 21 | import javafx.scene.input.KeyEvent; 22 | import javafx.scene.layout.BorderPane; 23 | import javafx.stage.Stage; 24 | 25 | /** 26 | * Reported: https://javafx-jira.kenai.com/browse/RT-38517 27 | * Regression: no way to unselect a list 28 | * 29 | * To reproduce: 30 | * 31 | * - run: first item selected 32 | * - click button: selection cleared 33 | * - tab in list: first item selected again 34 | * 35 | * Hack around: set clientProperty 36 | * 37 | */ 38 | public class ListFocusedCellDefault_38517 extends Application { 39 | private final ObservableList data = 40 | FXCollections.observableArrayList(Locale.getAvailableLocales()); 41 | 42 | private final ListView list = new ListView<>(data); 43 | 44 | @Override 45 | public void start(Stage stage) { 46 | stage.setTitle("List Focus/Anchor Bug"); 47 | // hack for ListView, not available for TableView 48 | list.getProperties().put("selectOnFocusGain", Boolean.FALSE); 49 | Button clear = new Button("Clear Selection"); 50 | clear.setOnAction(ev -> { 51 | list.getSelectionModel().clearSelection();; 52 | }); 53 | BorderPane root = new BorderPane(list); 54 | root.setTop(clear); 55 | Scene scene = new Scene(root); 56 | stage.setScene(scene); 57 | stage.show(); 58 | } 59 | 60 | public static void main(String[] args) { 61 | launch(args); 62 | } 63 | @SuppressWarnings("unused") 64 | private static final Logger LOG = Logger.getLogger(ListFocusedCellDefault_38517.class 65 | .getName()); 66 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/selection/SimpleListSelectionModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 18.11.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import java.util.logging.Logger; 8 | 9 | import javafx.beans.property.ListProperty; 10 | import javafx.beans.property.SimpleListProperty; 11 | import javafx.scene.control.FocusModel; 12 | import javafx.scene.control.ListView; 13 | import de.swingempire.fx.collection.IndexMappedList; 14 | import de.swingempire.fx.collection.IndicesList; 15 | 16 | /** 17 | * Concrete SelectionModel using indicesList/indexedItems for ListView. 18 | * 19 | * Note: this can extend AbstractSelectionModelBase/-React as needed - functionally 20 | * equivalent except for handling correlated selectedIndex/Item in the latter. 21 | * 22 | * @author Jeanette Winzenburg, Berlin 23 | */ 24 | public class SimpleListSelectionModel 25 | extends AbstractSelectionModelBase { 26 | // extends AbstractSelectionModelReact { 27 | 28 | private ListView listView; 29 | private ListProperty itemsList; 30 | private ListBasedSelectionHelper helper; 31 | 32 | /** 33 | * Live with coupling to view for now, will be removed! 34 | * @param listView 35 | */ 36 | public SimpleListSelectionModel(ListView listView) { 37 | this.listView = listView; 38 | itemsList = new SimpleListProperty<>(); 39 | itemsList.bind(listView.itemsProperty()); 40 | controller = new MultipleSelectionController<>(itemsList); 41 | // PENDING JW: this is brittle: need to register _after_ controller! 42 | helper = new ListBasedSelectionHelper<>(this, itemsList); 43 | } 44 | 45 | @Override 46 | protected void focus(int index) { 47 | if (getFocusModel() == null) return; 48 | getFocusModel().focus(index); 49 | } 50 | 51 | @Override 52 | protected int getFocusedIndex() { 53 | if (getFocusModel() == null) return -1; 54 | return getFocusModel().getFocusedIndex(); 55 | } 56 | 57 | @Override 58 | protected FocusModel getFocusModel() { 59 | return listView.getFocusModel(); 60 | } 61 | 62 | @SuppressWarnings("unused") 63 | private static final Logger LOG = Logger 64 | .getLogger(SimpleListSelectionModel.class.getName()); 65 | } 66 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/ListSelectedItemRT_28637.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 12.11.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.application.Application; 8 | import javafx.collections.FXCollections; 9 | import javafx.collections.ObservableList; 10 | import javafx.event.ActionEvent; 11 | import javafx.event.EventHandler; 12 | import javafx.scene.Scene; 13 | import javafx.scene.control.Button; 14 | import javafx.scene.control.ListView; 15 | import javafx.scene.layout.VBoxBuilder; 16 | import javafx.stage.Stage; 17 | 18 | /** 19 | * Regression guard against 28637 20 | * Please run the code. 21 | * Select the first item. 22 | * Click the Remove button, which removes the first item. 23 | * Click the Show button, which says, that the selected item is "String1", 24 | * although it is no longer in the list and cannot be the selected item. (The real selected item is in fact "String2") 25 | * 26 | * This only works, if you removed the first item in the list. 27 | * 28 | * 29 | */ 30 | public class ListSelectedItemRT_28637 extends Application { 31 | public static void main(String[] args) { 32 | Application.launch(); 33 | } 34 | 35 | private ObservableList items = FXCollections.observableArrayList("String1", "String2", "String3", "String4"); 36 | 37 | @Override 38 | public void start(Stage stage) throws Exception { 39 | 40 | final ListViewAnchored listView = new ListViewAnchored(); 41 | listView.setItems(items); 42 | 43 | Button button = new Button("Remove"); 44 | button.setOnAction(new EventHandler() { 45 | @Override 46 | public void handle(ActionEvent actionEvent) { 47 | items.remove(listView.getSelectionModel().getSelectedItem()); 48 | } 49 | }); 50 | 51 | Button btnShow = new Button("Show"); 52 | btnShow.setOnAction(new EventHandler() { 53 | @Override 54 | public void handle(ActionEvent actionEvent) { 55 | System.out.println(listView.getSelectionModel().getSelectedItem()); 56 | } 57 | }); 58 | 59 | Scene scene = new Scene(VBoxBuilder.create().children(listView, button, btnShow).build()); 60 | stage.setScene(scene); 61 | stage.show(); 62 | } 63 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/text/ThousandSeparatorFormatter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 05.05.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.text; 6 | 7 | import java.text.DecimalFormat; 8 | import java.text.DecimalFormatSymbols; 9 | import java.text.NumberFormat; 10 | import java.util.logging.Logger; 11 | 12 | import javafx.application.Application; 13 | import javafx.scene.Parent; 14 | import javafx.scene.Scene; 15 | import javafx.scene.control.TextField; 16 | import javafx.scene.control.TextFormatter; 17 | import javafx.scene.layout.VBox; 18 | import javafx.stage.Stage; 19 | import javafx.util.converter.NumberStringConverter; 20 | 21 | /** 22 | */ 23 | public class ThousandSeparatorFormatter extends Application { 24 | 25 | TextField textfield; 26 | 27 | 28 | public void initialize() { 29 | textfield = new TextField(); 30 | DecimalFormat numberFormat = (DecimalFormat) NumberFormat.getInstance(); 31 | LOG.info("format? " + numberFormat.getClass()); 32 | numberFormat.setMaximumIntegerDigits(6); 33 | numberFormat.setParseIntegerOnly(true); 34 | numberFormat.setGroupingUsed(true); 35 | DecimalFormatSymbols symbols = numberFormat.getDecimalFormatSymbols(); 36 | symbols.setGroupingSeparator(' '); 37 | numberFormat.setDecimalFormatSymbols(symbols); 38 | 39 | TextFormatter form = new TextFormatter(new NumberStringConverter( numberFormat)); 40 | //why dont this work? 41 | textfield.setTextFormatter(form); 42 | 43 | //this thing "works" 44 | // textfield.onKeyReleasedProperty().setValue(event -> { 45 | // textfield.setText( String.valueOf( form.getValueConverter().fromString( textfield.getText()))); 46 | // }); 47 | } 48 | 49 | private Parent getContent() { 50 | initialize(); 51 | VBox pane = new VBox(textfield); 52 | return pane; 53 | } 54 | 55 | @Override 56 | public void start(Stage primaryStage) throws Exception { 57 | primaryStage.setScene(new Scene(getContent())); 58 | primaryStage.show(); 59 | } 60 | 61 | public static void main(String[] args) { 62 | launch(args); 63 | } 64 | 65 | @SuppressWarnings("unused") 66 | private static final Logger LOG = Logger 67 | .getLogger(ThousandSeparatorFormatter.class.getName()); 68 | } 69 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/pagination/NavigationModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 29.07.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.pagination; 6 | 7 | import javafx.beans.property.IntegerProperty; 8 | 9 | /** 10 | * Model to encapsulate the navigation across a pagination control. 11 | * 12 | * This is a model for the sake of the navigation ui, which is 13 | * under the control of the pagination skin. Design goal is to encapsulate 14 | * the control such that the navigation control is pluggable. 15 | * 16 | * This is similar to the index-related part of a SelectionModel: 17 | * it has a current (aka: selected) 18 | * index and navigation services next/prev/first/last. It also 19 | * (similar to some implementations of SelectionModel) has the notion of 20 | * size which might be INDETERMINATE if unknown. 21 | * 22 | * It differs from SelectionModel in 23 | *

  • not having an item corresponding to the index 24 | *
  • cannot be empty: minimum size is 1 25 | * 26 | * The default implementation assumes that the properties enforce the 27 | * constraints 0 <= current < size 28 | * 29 | * @author Jeanette Winzenburg, Berlin 30 | */ 31 | public interface NavigationModel { 32 | /** 33 | * Value for indicating that the page count is indeterminate. 34 | */ 35 | public static final int INDETERMINATE = Integer.MAX_VALUE; 36 | 37 | IntegerProperty currentProperty(); 38 | 39 | default int getCurrent() { 40 | return currentProperty().get(); 41 | } 42 | 43 | default void setCurrent(int current) { 44 | currentProperty().set(current); 45 | } 46 | 47 | IntegerProperty sizeProperty(); 48 | 49 | /** 50 | * 51 | * @return 52 | */ 53 | default int getSize() { 54 | return sizeProperty().get(); 55 | } 56 | 57 | default void next() { 58 | int current = getCurrent(); 59 | if (current < getSize() -1) { 60 | setCurrent(current + 1); 61 | } 62 | } 63 | 64 | default void previous() { 65 | int current = getCurrent(); 66 | if (current > 0) { 67 | setCurrent(current - 1); 68 | } 69 | } 70 | 71 | default void last() { 72 | setCurrent(getSize() - 1); 73 | } 74 | 75 | default void first() { 76 | setCurrent(0); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/selection/IndexedItemsController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 04.12.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.collections.ObservableList; 8 | 9 | /** 10 | * Encapsulates control of the pair selectedIndices/selectedItems, that is 11 | * multiple selection state. 12 | * 13 | * @author Jeanette Winzenburg, Berlin 14 | */ 15 | public interface IndexedItemsController { 16 | 17 | /** 18 | * Returns the list of indices. 19 | * 20 | * @return 21 | */ 22 | ObservableList getIndices(); 23 | 24 | /** 25 | * Returns the indexed items. 26 | * 27 | * @return 28 | */ 29 | ObservableList getIndexedItems(); 30 | 31 | /** 32 | * Sets the given indices. All previously set indices are 33 | * cleared. 34 | * 35 | * Does nothing if null or empty. 36 | * 37 | * @param indices positions in source list 38 | */ 39 | void setIndices(int... indices); 40 | 41 | /** 42 | * Adds the given indices. Does nothing if null or empty. 43 | * 44 | * @param indices 45 | */ 46 | void addIndices(int... indices); 47 | 48 | /** 49 | * Clears the given indices. Does nothing if null or empty. 50 | * @param indices position in sourceList 51 | */ 52 | void clearIndices(int... indices); 53 | 54 | /** 55 | * Sets all indices. 56 | * 57 | * PENDING JW: notification on already set? 58 | */ 59 | void setAllIndices(); 60 | 61 | /** 62 | * Clears all indices. 63 | */ 64 | void clearAllIndices(); 65 | 66 | /** 67 | * Returns the index of the item in the backing data structure. 68 | * 69 | * @param item 70 | * @return 71 | */ 72 | int sourceIndexOf(T item); 73 | 74 | /** 75 | * Returns the size of the backing data structure. 76 | * @return 77 | */ 78 | int getSourceSize(); 79 | 80 | /** 81 | * Returns the item at sourceIndex. 82 | * 83 | * @param sourceIndex in coordinates of the backing structure, 84 | * must be valid 85 | * @return 86 | */ 87 | T getSourceItem(int sourceIndex); 88 | 89 | // PENDING JW: really want to expose backing properties? 90 | // ObservableList getSource(); 91 | 92 | } 93 | -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/junit/DummyTestConditionalIgnore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 30.09.2014 3 | * 4 | */ 5 | package de.swingempire.fx.junit; 6 | 7 | import org.junit.Before; 8 | import org.junit.Rule; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.junit.runners.JUnit4; 12 | 13 | import com.codeaffine.test.ConditionalIgnoreRule; 14 | import com.codeaffine.test.ConditionalIgnoreRule.ConditionalIgnore; 15 | import com.codeaffine.test.ConditionalIgnoreRule.IgnoreCondition; 16 | 17 | import static org.junit.Assert.*; 18 | 19 | /** 20 | * Try to dig why conditionalIgnor makes test hang. 21 | * 22 | * Does not work with subclassing the test. Decision for now: 23 | * defer to future, add code inside tests. 24 | * 25 | * @author Jeanette Winzenburg, Berlin 26 | */ 27 | @SuppressWarnings({ "rawtypes", "unchecked" }) 28 | @RunWith(JUnit4.class) 29 | public class DummyTestConditionalIgnore { 30 | 31 | // @ClassRule 32 | // public static TestRule classRule = new JavaFXThreadingRule(); 33 | 34 | @Rule 35 | public ConditionalIgnoreRule rule = new ConditionalIgnoreRule(); 36 | protected int passing; 37 | protected int failing; 38 | public /*static*/ class NoSeparatorSupport implements IgnoreCondition { 39 | 40 | // private DummyTestConditionalIgnore target; 41 | // public NoSeparatorSupport(DummyTestConditionalIgnore target) { 42 | // this.target = target; 43 | // } 44 | @Override 45 | public boolean isSatisfied() { 46 | return /*!target.*/supportsSeparators(); 47 | } 48 | 49 | } 50 | 51 | @Test 52 | public void testWithoutIgnore() { 53 | assertEquals("failing test", failing, 1); 54 | } 55 | 56 | @Test 57 | @ConditionalIgnore(condition = NoSeparatorSupport.class) 58 | public void testWithIgnore() { 59 | assertEquals("failing test", failing, 1); 60 | } 61 | 62 | 63 | @Test 64 | public void testAnotherTest() { 65 | assertEquals("passing", passing, 1); 66 | } 67 | @Test 68 | public void testYetAnotherTest() { 69 | assertEquals("failing", failing, 1); 70 | } 71 | 72 | @Before 73 | public void setUp() { 74 | passing = 1; 75 | failing = 5; 76 | } 77 | /** 78 | * @return 79 | */ 80 | public boolean supportsSeparators() { 81 | return false; 82 | } 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/ChoiceItemsView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 31.08.2014 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import java.nio.charset.Charset; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Set; 11 | import java.util.logging.Logger; 12 | 13 | import javafx.fxml.FXML; 14 | import javafx.scene.control.ChoiceBox; 15 | 16 | /** 17 | * http://stackoverflow.com/q/25583707/203657 18 | * app freezing after exchanging items from one choicebox to another. 19 | * 20 | * Might be user error: from choicebox api doc "ChoiceBox is used for 21 | * presenting the user with a relatively small set of 22 | * predefined choices" 23 | */ 24 | public class ChoiceItemsView { 25 | @FXML 26 | private ChoiceBox firstCB; 27 | @FXML 28 | private ChoiceBox secondCB; 29 | public void init() { 30 | Set keySet = Charset.availableCharsets().keySet(); 31 | List list = new ArrayList<>(keySet); 32 | // smaller subset is just fine 33 | // list = list.subList(0, 10); 34 | firstCB.getItems().addAll(list); 35 | secondCB.getItems().addAll(list); 36 | LOG.info("item count: " + secondCB.getItems().size()); 37 | firstCB.getSelectionModel().selectedItemProperty() 38 | .addListener((observable, oldVal, newVal) -> { 39 | System.out.printf("[%s]firstCB selection changed%n", Thread.currentThread().getName()); 40 | if (newVal != null) 41 | secondCB.getItems().remove(newVal); 42 | if (oldVal != null) 43 | secondCB.getItems().add(oldVal); 44 | LOG.info("old/new " + oldVal + "/" + newVal + "/" + secondCB.getItems().size()); 45 | }); 46 | // removing one of the event listeners doesn't help 47 | secondCB.getSelectionModel().selectedItemProperty() 48 | .addListener((observable, oldVal, newVal) -> { 49 | System.out.printf("[%s]secondCB selection changed%n", Thread.currentThread().getName()); 50 | if (newVal != null) 51 | firstCB.getItems().remove(newVal); 52 | if (oldVal != null) 53 | firstCB.getItems().add(oldVal); 54 | LOG.info("old/new " + oldVal + "/" + newVal + "/" + firstCB.getItems().size()); 55 | }); 56 | } 57 | 58 | @SuppressWarnings("unused") 59 | private static final Logger LOG = Logger.getLogger(ChoiceItemsView.class 60 | .getName()); 61 | } 62 | 63 | -------------------------------------------------------------------------------- /fx8-swingempire/src/testsupport/de/swingempire/fx/util/ListChangeReport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 26.09.2014 3 | * 4 | */ 5 | package de.swingempire.fx.util; 6 | 7 | import java.util.LinkedList; 8 | import java.util.List; 9 | 10 | import javafx.beans.value.ObservableListValue; 11 | import javafx.collections.ListChangeListener; 12 | import javafx.collections.ObservableList; 13 | 14 | /** 15 | * @author Jeanette Winzenburg, Berlin 16 | */ 17 | @SuppressWarnings({ "rawtypes", "unchecked" }) 18 | public class ListChangeReport implements ListChangeListener { 19 | 20 | List changes = new LinkedList<>(); 21 | 22 | ObservableList source; 23 | 24 | public ListChangeReport() { 25 | this(null); 26 | } 27 | public ListChangeReport(ObservableList source) { 28 | this.source = source; 29 | if (source != null) source.addListener(this); 30 | } 31 | 32 | @Override 33 | public void onChanged(Change c) { 34 | changes.add(0, c); 35 | } 36 | 37 | public int getEventCount() { 38 | return changes.size(); 39 | } 40 | 41 | public void prettyPrint() { 42 | Change c = getLastChange(); 43 | if (c == null) return; 44 | FXUtils.prettyPrint(c); 45 | c.reset(); 46 | } 47 | 48 | public void prettyPrintAll() { 49 | changes.stream().forEach(c -> { 50 | System.out.println("--- change at: " + changes.indexOf(c)); 51 | FXUtils.prettyPrint(c); 52 | c.reset(); 53 | }); 54 | } 55 | /** 56 | * @return the last change, reset if available 57 | */ 58 | public Change getLastChange() { 59 | return getLastChange(true); 60 | } 61 | 62 | /** 63 | * Returns the last change that was received. Resets the change if reset == true, 64 | * returns it unchanged otherwise. 65 | * 66 | * @param reset 67 | * @return 68 | */ 69 | public Change getLastChange(boolean reset) { 70 | Change c = hasChanges() ? changes.get(0) : null; 71 | if (c != null && reset) { 72 | c.reset(); 73 | } 74 | return c; 75 | } 76 | public ObservableList getLastValue() { 77 | return hasChanges() ? getLastChange().getList() : null; 78 | } 79 | 80 | public boolean hasChanges() { 81 | return getEventCount() > 0; 82 | } 83 | 84 | public void clear() { 85 | changes.clear(); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/ChoiceComboItemsView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 31.08.2014 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import java.nio.charset.Charset; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Set; 11 | import java.util.logging.Logger; 12 | 13 | import javafx.fxml.FXML; 14 | import javafx.scene.control.ComboBox; 15 | 16 | /** 17 | * http://stackoverflow.com/q/25583707/203657 18 | * app freezing after exchanging items from one choicebox to another. 19 | * 20 | * Might be user error: from choicebox api doc "ChoiceBox is used for 21 | * presenting the user with a relatively small set of 22 | * predefined choices" 23 | */ 24 | public class ChoiceComboItemsView { 25 | @FXML 26 | private ComboBox firstCB; 27 | @FXML 28 | private ComboBox secondCB; 29 | public void init() { 30 | Set keySet = Charset.availableCharsets().keySet(); 31 | List list = new ArrayList<>(keySet); 32 | // list = list.subList(0, 10); 33 | firstCB.getItems().addAll(list); //list.subList(0, 10)); 34 | secondCB.getItems().addAll(list); //list.subList(10, 20)); 35 | LOG.info("item count: " + secondCB.getItems().size()); 36 | firstCB.getSelectionModel().selectedItemProperty() 37 | .addListener((observable, oldVal, newVal) -> { 38 | System.out.printf("[%s]firstCB selection changed%n", Thread.currentThread().getName()); 39 | if (newVal != null) 40 | secondCB.getItems().remove(newVal); 41 | if (oldVal != null) 42 | secondCB.getItems().add(oldVal); 43 | LOG.info("old/new " + oldVal + "/" + newVal + "/" + secondCB.getItems().size()); 44 | }); 45 | // removing one of the event listeners doesn't help 46 | secondCB.getSelectionModel().selectedItemProperty() 47 | .addListener((observable, oldVal, newVal) -> { 48 | System.out.printf("[%s]secondCB selection changed%n", Thread.currentThread().getName()); 49 | if (newVal != null) 50 | firstCB.getItems().remove(newVal); 51 | if (oldVal != null) 52 | firstCB.getItems().add(oldVal); 53 | LOG.info("old/new " + oldVal + "/" + newVal + "/" + firstCB.getItems().size()); 54 | }); 55 | } 56 | 57 | @SuppressWarnings("unused") 58 | private static final Logger LOG = Logger.getLogger(ChoiceComboItemsView.class 59 | .getName()); 60 | } 61 | 62 | -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/util/FXUtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 22.01.2015 3 | * 4 | */ 5 | package de.swingempire.fx.util; 6 | 7 | import java.util.List; 8 | 9 | import javafx.beans.Observable; 10 | import javafx.collections.FXCollections; 11 | import javafx.collections.ObservableList; 12 | 13 | import org.junit.Before; 14 | import org.junit.Rule; 15 | import org.junit.Test; 16 | import org.junit.runner.RunWith; 17 | import org.junit.runners.JUnit4; 18 | 19 | import com.codeaffine.test.ConditionalIgnoreRule; 20 | 21 | import de.swingempire.fx.demobean.Person; 22 | 23 | import static de.swingempire.fx.util.FXUtils.*; 24 | import static org.junit.Assert.*; 25 | 26 | /** 27 | * @author Jeanette Winzenburg, Berlin 28 | */ 29 | //@SuppressWarnings({ "rawtypes", "unchecked" }) 30 | @RunWith(JUnit4.class) 31 | public class FXUtilsTest { 32 | @Rule 33 | public ConditionalIgnoreRule rule = new ConditionalIgnoreRule(); 34 | private ObservableList rawItems; 35 | 36 | @Test 37 | public void testCollectToObservableListExtractor() { 38 | List persons = Person.persons(); 39 | ObservableList result = persons.stream().map(e -> e) 40 | .collect(toObservableList(person -> { 41 | return new Observable[]{person.firstNameProperty()}; 42 | })); 43 | assertEquals("sanity", persons, result); 44 | ListChangeReport report = new ListChangeReport(result); 45 | persons.get(0).setFirstName("newName"); 46 | assertEquals(1, report.getEventCount()); 47 | } 48 | 49 | @Test 50 | public void testCollectToObservableListParam() { 51 | ObservableList list = FXCollections.observableArrayList(); 52 | List result = rawItems.stream().map(e -> e) 53 | .collect(toObservableList(list)); 54 | assertSame(list, result); 55 | assertEquals(rawItems, result); 56 | } 57 | 58 | @Test 59 | public void testCollectToObservableList() { 60 | List result = rawItems.stream().map(e -> e).collect(toObservableList()); 61 | assertTrue(result instanceof ObservableList); 62 | assertEquals(rawItems, result); 63 | } 64 | 65 | @Before 66 | public void setup() { 67 | rawItems = FXCollections.observableArrayList( 68 | "9-item", "8-item", "7-item", "6-item", 69 | "5-item", "4-item", "3-item", "2-item", "1-item"); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/selection/MultipleSelectionController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 04.12.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.collections.ObservableList; 8 | import de.swingempire.fx.collection.IndexMappedList; 9 | import de.swingempire.fx.collection.IndicesList; 10 | 11 | /** 12 | * Implementation of IndexedItemsController that handles a list of items. 13 | *

    14 | * PENDING JW: 15 | * - should take a property of items (vs. the raw items) 16 | * 17 | * @author Jeanette Winzenburg, Berlin 18 | */ 19 | public class MultipleSelectionController implements IndexedItemsController{ 20 | 21 | protected IndicesList indicesList; 22 | protected IndexMappedList indexedItems; 23 | 24 | public MultipleSelectionController(ObservableList items) { 25 | indicesList = new IndicesList<>(items); 26 | indexedItems = new IndexMappedList<>(indicesList); 27 | } 28 | 29 | @Override 30 | public ObservableList getIndices() { 31 | return indicesList; 32 | } 33 | 34 | @Override 35 | public ObservableList getIndexedItems() { 36 | return indexedItems; 37 | } 38 | 39 | @Override 40 | public void setIndices(int... indices) { 41 | indicesList.setIndices(indices); 42 | } 43 | 44 | @Override 45 | public void addIndices(int... indices) { 46 | indicesList.addIndices(indices); 47 | } 48 | 49 | @Override 50 | public void clearIndices(int... indices) { 51 | indicesList.clearIndices(indices); 52 | } 53 | 54 | @Override 55 | public void setAllIndices() { 56 | indicesList.setAllIndices(); 57 | } 58 | 59 | @Override 60 | public void clearAllIndices() { 61 | indicesList.clearAllIndices(); 62 | } 63 | 64 | @Override 65 | public int sourceIndexOf(T item) { 66 | // int index = indexedItems.indexOf(item); 67 | // return index < 0 ? -1 : indicesList.getSourceIndex(index); 68 | return getSource().indexOf(item); 69 | } 70 | 71 | @Override 72 | public int getSourceSize() { 73 | return getSource().size(); 74 | } 75 | 76 | 77 | @Override 78 | public T getSourceItem(int index) { 79 | return getSource().get(index); 80 | } 81 | 82 | // @Override 83 | private ObservableList getSource() { 84 | return indicesList.getSource(); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/scene/control/selection/TreeSimpleMultipleSelectionIssues.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 02.06.2013 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import java.util.logging.Logger; 8 | 9 | import javafx.collections.ObservableList; 10 | import javafx.scene.control.MultipleSelectionModel; 11 | import javafx.scene.control.SelectionMode; 12 | import javafx.scene.control.TreeItem; 13 | import javafx.scene.control.TreeView; 14 | 15 | import org.junit.runner.RunWith; 16 | import org.junit.runners.Parameterized; 17 | 18 | import de.swingempire.fx.scene.control.tree.TreeItemX; 19 | import static org.junit.Assert.*; 20 | 21 | /** 22 | * @author Jeanette Winzenburg, Berlin 23 | */ 24 | @SuppressWarnings({ "rawtypes", "unchecked" }) 25 | @RunWith(Parameterized.class) 26 | public class TreeSimpleMultipleSelectionIssues extends AbstractTreeMultipleSelectionIssues { 27 | 28 | 29 | public TreeSimpleMultipleSelectionIssues(boolean multiple) { 30 | super(multiple); 31 | } 32 | 33 | @Override 34 | protected TreeView createView(ObservableList items) { 35 | TreeItem root = createItem("root"); 36 | root.getChildren().setAll(items); 37 | TreeView table = new TreeView(root); 38 | table.setSelectionModel(new SimpleTreeSelectionModel<>(table)); 39 | root.setExpanded(true); 40 | table.setShowRoot(false); 41 | MultipleSelectionModel model = table.getSelectionModel(); 42 | assertEquals("sanity: test setup assumes that initial mode is single", 43 | SelectionMode.SINGLE, model.getSelectionMode()); 44 | checkMode(model); 45 | // PENDING JW: this is crude ... think of doing it elsewhere 46 | // the problem is to keep super blissfully unaware of possible modes 47 | assertEquals(multipleMode, model.getSelectionMode() == SelectionMode.MULTIPLE); 48 | return table; 49 | } 50 | 51 | @Override 52 | protected TreeItemX createItem(Object item) { 53 | return new TreeItemX(item); 54 | } 55 | 56 | @SuppressWarnings("unused") 57 | private static final Logger LOG = Logger 58 | .getLogger(TreeSimpleMultipleSelectionIssues.class.getName()); 59 | 60 | @Override 61 | protected TreeView createEmptyView() { 62 | TreeView tree = new TreeView(); 63 | tree.setSelectionModel(new SimpleTreeSelectionModel<>(tree)); 64 | tree.setShowRoot(false); 65 | return tree; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/CommitOnFocusLostWithStyleSheet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 23.09.2015 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import com.sun.javafx.css.StyleManager; 8 | 9 | import javafx.application.Application; 10 | import javafx.collections.FXCollections; 11 | import javafx.scene.Parent; 12 | import javafx.scene.Scene; 13 | import javafx.scene.control.Button; 14 | import javafx.scene.control.ComboBox; 15 | import javafx.scene.control.Dialog; 16 | import javafx.scene.control.Label; 17 | import javafx.scene.layout.HBox; 18 | import javafx.stage.Stage; 19 | import de.swingempire.fx.util.FXUtils; 20 | 21 | /** 22 | * Use custom stylesheet to 23 | * @author Jeanette Winzenburg, Berlin 24 | */ 25 | public class CommitOnFocusLostWithStyleSheet extends Application { 26 | 27 | @Override 28 | public void start(Stage primaryStage) throws Exception { 29 | Scene scene = new Scene(getContent()); 30 | String commitCSS = getClass().getResource("commitonfocuslost.css").toExternalForm(); 31 | // 1. this adds the style for all stylable nodes of the types in the css 32 | // but only per-scene, needs to be duplicated for each subscene (popups as well!) 33 | // scene.getStylesheets().add(commitCSS); 34 | // 2. next two looses all default styles! 35 | // scene.setUserAgentStylesheet(getClass().getResource("commitonfocuslost.css").toExternalForm()); 36 | // Application.setUserAgentStylesheet(commitCSS); 37 | // 3. using StyleManager we can add the sheet application-wide 38 | // but it is internal api, won't make it into jdk9 39 | StyleManager s = StyleManager.getInstance(); 40 | s.addUserAgentStylesheet(commitCSS); 41 | primaryStage.setScene(scene); 42 | primaryStage.setTitle(FXUtils.version()); 43 | primaryStage.show(); 44 | } 45 | 46 | /** 47 | * @return 48 | */ 49 | private Parent getContent() { 50 | ComboBox box = new ComboBox(FXCollections.observableArrayList("one", "two", "threee")); 51 | box.setEditable(true); 52 | box.setValue("initial"); 53 | Label label = new Label(); 54 | label.textProperty().bind(box.valueProperty()); 55 | Button button = new Button("dummy to focus - and open dialog"); 56 | Dialog d; 57 | HBox grid = new HBox(10, box, label, button); 58 | return grid; 59 | } 60 | 61 | public static void main(String[] args) { 62 | launch(args); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/SynchScrollBars.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 14.07.2014 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import java.util.Locale; 8 | import java.util.logging.Logger; 9 | 10 | import javafx.application.Application; 11 | import javafx.collections.FXCollections; 12 | import javafx.collections.ObservableList; 13 | import javafx.scene.Scene; 14 | import javafx.scene.control.ScrollBar; 15 | import javafx.scene.control.TableColumn; 16 | import javafx.scene.control.TableView; 17 | import javafx.scene.control.cell.PropertyValueFactory; 18 | import javafx.scene.layout.HBox; 19 | import javafx.stage.Stage; 20 | 21 | /** 22 | * http://stackoverflow.com/a/25742558/203657 23 | * 24 | * force 2 scrollbars to same value 25 | * 26 | * OP's self-solution was a listener - why not bind? 27 | */ 28 | public class SynchScrollBars extends Application { 29 | private final ObservableList data = 30 | FXCollections.observableArrayList(Locale.getAvailableLocales() 31 | ); 32 | 33 | private final TableView table = new TableView<>(data); 34 | private final TableView table2 = new TableView<>(data); 35 | 36 | 37 | @Override 38 | public void start(Stage stage) { 39 | stage.setTitle("Table FocusedCell Bug"); 40 | configureTable(table); 41 | configureTable(table2); 42 | HBox root = new HBox(table, table2); 43 | Scene scene = new Scene(root); 44 | stage.setScene(scene); 45 | stage.show(); 46 | ScrollBar one = (ScrollBar) table.lookup(".scroll-bar"); 47 | ScrollBar other = (ScrollBar) table2.lookup(".scroll-bar"); 48 | other.valueProperty().bindBidirectional(one.valueProperty()); 49 | } 50 | 51 | protected void configureTable(TableView table) { 52 | TableColumn language = new TableColumn<>( 53 | "Language"); 54 | language.setCellValueFactory(new PropertyValueFactory<>("displayLanguage")); 55 | TableColumn country = new TableColumn<>("Country"); 56 | country.setCellValueFactory(new PropertyValueFactory<>("country")); 57 | table.setItems(data); 58 | table.getColumns().addAll(language, country); 59 | } 60 | 61 | public static void main(String[] args) { 62 | launch(args); 63 | } 64 | @SuppressWarnings("unused") 65 | private static final Logger LOG = Logger.getLogger(SynchScrollBars.class 66 | .getName()); 67 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/LookupApp_35039.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 09.03.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import javafx.application.Application; 11 | import javafx.collections.FXCollections; 12 | import javafx.event.ActionEvent; 13 | import javafx.event.EventHandler; 14 | import javafx.scene.Scene; 15 | import javafx.scene.control.Button; 16 | import javafx.scene.control.ComboBox; 17 | import javafx.scene.layout.VBox; 18 | import javafx.stage.Stage; 19 | import javafx.util.StringConverter; 20 | 21 | /** 22 | * SelectedItem was cleared on replacing the items. 23 | * 24 | */ 25 | public class LookupApp_35039 extends Application { 26 | 27 | public static void main(String... args) { 28 | launch(args); 29 | } 30 | 31 | @Override 32 | public void start(Stage primaryStage) throws Exception { 33 | final Map map = new HashMap<>(); 34 | map.put("aabbaa", new SomeBean("aabbaa")); 35 | map.put("bbc", new SomeBean("bbc")); 36 | final ComboBox combo = new ComboBox<>(); 37 | combo.setEditable(true); 38 | combo.setItems(FXCollections.observableArrayList(map.values())); 39 | combo.setConverter(new StringConverter() { 40 | 41 | @Override 42 | public String toString(SomeBean bean) { 43 | if(bean != null) { 44 | return bean.getId(); 45 | } else { 46 | return ""; 47 | } 48 | } 49 | 50 | @Override 51 | public SomeBean fromString(String text) { 52 | return map.get(text); 53 | } 54 | }); 55 | Button button = new Button("Refresh items"); 56 | button.setOnAction(new EventHandler() { 57 | 58 | @Override 59 | public void handle(ActionEvent arg0) { 60 | combo.setItems(FXCollections.observableArrayList(map.values())); 61 | } 62 | }); 63 | primaryStage.setScene(new Scene(new VBox(combo, button))); 64 | primaryStage.show(); 65 | } 66 | 67 | public class SomeBean { 68 | 69 | private String id; 70 | 71 | public SomeBean(String id) { 72 | this.id = id; 73 | } 74 | 75 | public String getId() { 76 | return id; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/DynamicTooltipMouseLocation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 17.02.2015 3 | * 4 | */ 5 | package de.swingempire.fx.control; 6 | 7 | import java.util.logging.Logger; 8 | 9 | import javafx.application.Application; 10 | import javafx.geometry.Point2D; 11 | import javafx.scene.Scene; 12 | import javafx.scene.control.Button; 13 | import javafx.scene.control.Tooltip; 14 | import javafx.scene.layout.VBox; 15 | import javafx.stage.PopupWindow.AnchorLocation; 16 | import javafx.stage.Stage; 17 | 18 | public class DynamicTooltipMouseLocation extends Application { 19 | 20 | private static final Object MOUSE_TRIGGER_LOCATION = "tooltip-last-location"; 21 | 22 | protected Button createButton(AnchorLocation location) { 23 | Tooltip t = new Tooltip(""); 24 | String text = location != null ? location.toString() 25 | : t.getAnchorLocation().toString() + " (default)"; 26 | if (location != null) { 27 | t.setAnchorLocation(location); 28 | } 29 | t.setOnShown(e -> { 30 | // here we get a stable tooltip 31 | t.textProperty().set("x/y: " + t.getX() + "/" + t.getY() + "\n" + 32 | "stored: " + t.getProperties().get(MOUSE_TRIGGER_LOCATION) + "\n" + 33 | "ax/y: " + t.getAnchorX() + "/" + t.getAnchorY()); 34 | }); 35 | Button button = new Button(text); 36 | button.setTooltip(t); 37 | button.setOnContextMenuRequested(e -> { 38 | LOG.info("context: " + text + "\n " + 39 | "scene/screen/source " + e.getSceneX() + " / " + e.getScreenX() + " / " + e.getX()); 40 | }); 41 | button.setOnMouseMoved(e -> { 42 | Point2D screen = new Point2D(e.getScreenX(), e.getScreenY()); 43 | t.getProperties().put(MOUSE_TRIGGER_LOCATION, screen); 44 | LOG.info("moved: " + text + "\n " + 45 | "scene/screen/source " + e.getSceneX() + " / " + e.getScreenX() + " / " + e.getX()); 46 | }); 47 | return button; 48 | } 49 | 50 | @Override 51 | public void start(Stage stage) throws Exception { 52 | VBox pane = new VBox(createButton(AnchorLocation.CONTENT_TOP_LEFT)); 53 | Scene scene = new Scene(pane); 54 | stage.setScene(scene); 55 | stage.show(); 56 | } 57 | public static void main(String[] args) { 58 | launch(args); 59 | } 60 | 61 | @SuppressWarnings("unused") 62 | private static final Logger LOG = Logger 63 | .getLogger(DynamicTooltipMouseLocation.class.getName()); 64 | } 65 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/cell/TableRowSkinX.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 07.11.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.cell; 6 | 7 | import java.lang.ref.WeakReference; 8 | 9 | import javafx.beans.InvalidationListener; 10 | import javafx.beans.WeakInvalidationListener; 11 | import javafx.beans.value.ObservableValue; 12 | import javafx.scene.control.TableRow; 13 | 14 | import com.sun.javafx.scene.control.skin.TableRowSkin; 15 | 16 | /** 17 | * Skin that updates child cells in an InvalidationListener if 18 | * super's changeListener can't (that is if oldItem.equals(newItem)). 19 | * 20 | * @author Jeanette Winzenburg, Berlin 21 | */ 22 | public class TableRowSkinX extends TableRowSkin { 23 | 24 | private WeakReference oldItemRef; 25 | private InvalidationListener itemInvalidationListener; 26 | private WeakInvalidationListener weakItemInvalidationListener; 27 | /** 28 | * @param tableRow 29 | */ 30 | public TableRowSkinX(TableRow tableRow) { 31 | super(tableRow); 32 | oldItemRef = new WeakReference<>(tableRow.getItem()); 33 | itemInvalidationListener = o -> { 34 | T newItem = ((ObservableValue) o).getValue(); 35 | T oldItem = oldItemRef != null ? oldItemRef.get() : null; 36 | oldItemRef = new WeakReference<>(newItem); 37 | if (oldItem != null && newItem != null && oldItem.equals(newItem)) { 38 | forceCellUpdate(); 39 | } 40 | }; 41 | weakItemInvalidationListener = new WeakInvalidationListener(itemInvalidationListener); 42 | tableRow.itemProperty().addListener(weakItemInvalidationListener); 43 | } 44 | 45 | /** 46 | * Try to force cell update for equal (but not same) items. 47 | * C&P'ed code from TableRowSkinBase. 48 | */ 49 | private void forceCellUpdate() { 50 | updateCells = true; 51 | getSkinnable().requestLayout(); 52 | 53 | // update the index of all children cells (RT-29849). 54 | // Note that we do this after the TableRow item has been updated, 55 | // rather than when the TableRow index has changed (as this will be 56 | // before the row has updated its item). This will result in the 57 | // issue highlighted in RT-33602, where the table cell had the correct 58 | // item whilst the row had the old item. 59 | final int newIndex = getSkinnable().getIndex(); 60 | for (int i = 0, max = cells.size(); i < max; i++) { 61 | cells.get(i).updateIndex(newIndex); 62 | } 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/control/backups/focusedtablecell.css~0: -------------------------------------------------------------------------------- 1 | .table-view:focused:row-selection > .virtual-flow > .clipped-container > .sheet > .table-cell:focused, 2 | .table-cell:focused 3 | { 4 | -fx-border-color: yellow; 5 | -fx-border-insets: 2; 6 | } 7 | 8 | .tab-pane { 9 | # -fx-table-cell-border-color: #derive(-fx-selection-bar, 20%) 10 | -fx-background-color: -fx-background, -fx-cell-focus-inner-border, -fx-background; 11 | -fx-background-insets: 0, 1, 10; 12 | -fx-background-color: white; 13 | -fx-background-insets:0; 14 | -fx-padding: 0; 15 | } 16 | 17 | *.tab-header-background { 18 | -fx-padding:0; 19 | -fx-background-insets:0; 20 | } 21 | 22 | .tab-pane *.tab-header-background { 23 | -fx-padding:0; 24 | -fx-background-insets:0; 25 | } 26 | 27 | .tab:selected { 28 | -fx-background-color: white; 29 | -fx-background-insets: 0; 30 | -fx-background-radius: 0; 31 | } 32 | 33 | .tab { 34 | -fx-background-color: white; 35 | -fx-padding: 0; 36 | -fx-background-insets: 0; 37 | } 38 | 39 | .tab:top { 40 | -fx-padding: 0; 41 | -fx-background-insets: 0; 42 | } 43 | 44 | .tab:right { 45 | -fx-padding: 0; 46 | -fx-background-insets: 0; 47 | } 48 | 49 | .tab:bottom { 50 | -fx-padding: 0; 51 | -fx-background-insets: 0; 52 | } 53 | 54 | .tab:left { 55 | -fx-padding: 0; 56 | -fx-background-insets: 0; 57 | } 58 | 59 | .tab:hover { 60 | -fx-padding: 0; 61 | -fx-background-insets: 0; 62 | } 63 | 64 | .tab-header-area { 65 | -fx-padding: 0; 66 | -fx-background-insets: 0; 67 | } 68 | 69 | .tab-pane:top *.tab-header-area { 70 | -fx-background-insets: 0; 71 | -fx-padding: 0; 72 | } 73 | 74 | .tab-pane:bottom *.tab-header-area { 75 | -fx-background-insets: 0; 76 | -fx-padding: 0; 77 | } 78 | 79 | .tab-pane:left *.tab-header-area { 80 | -fx-background-insets: 0; 81 | -fx-padding: 0; 82 | } 83 | 84 | .tab-pane:right *.tab-header-area { 85 | -fx-background-insets: 0; 86 | -fx-padding: 0; 87 | } 88 | 89 | .control-buttons-tab { 90 | -fx-background-insets: 0; 91 | -fx-background-radius: 0; 92 | -fx-padding: 0; 93 | } 94 | 95 | .tab-down-button { 96 | -fx-background-color: green; 97 | -fx-padding: 0; 98 | } 99 | 100 | .tab-down-button .arrow { 101 | -fx-background-insets: 0; 102 | -fx-background:black; 103 | -fx-width:0; 104 | -fx-padding: 0; 105 | -fx-shape: " "; 106 | } 107 | 108 | .arrow { 109 | -fx-background-insets: 0; 110 | -fx-background:black; 111 | -fx-width:0; 112 | -fx-padding: 0; 113 | -fx-shape: " "; 114 | } 115 | 116 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/selection/TreeViewSelectionRT_38341.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 22.09.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.application.Application; 8 | import javafx.collections.ListChangeListener.Change; 9 | import javafx.scene.Scene; 10 | import javafx.scene.control.TreeItem; 11 | import javafx.scene.control.TreeView; 12 | import javafx.scene.input.KeyCode; 13 | import javafx.scene.layout.StackPane; 14 | import javafx.stage.Stage; 15 | 16 | /** 17 | * https://javafx-jira.kenai.com/browse/RT-38341 18 | * 19 | * no notification of change of selectedItem if selected iem 20 | * is removed. 21 | * 22 | * To reproduce: 23 | * - expand root1 24 | * - select child 1 25 | * - press delete: selection is moved to root1 26 | * - expected: notification of selectedItem change 27 | * - actual: no notification 28 | */ 29 | public class TreeViewSelectionRT_38341 extends Application { 30 | 31 | public static void main(final String[] args) { 32 | launch(args); 33 | } 34 | 35 | @Override 36 | public void start(final Stage primaryStage) throws Exception { 37 | final StackPane stackPane = new StackPane(); 38 | 39 | final TreeItem root = new TreeItem<>(); 40 | root.setExpanded(true); 41 | root.getChildren().addAll(createItem(1), createItem(2)); 42 | 43 | final TreeView treeView = new TreeView<>(root); 44 | treeView.setShowRoot(false); 45 | treeView.getSelectionModel().getSelectedItems().addListener(this::handleChange); 46 | treeView.setOnKeyPressed(event -> { 47 | if (event.getCode() == KeyCode.DELETE) { 48 | final TreeItem selectedItem = treeView.getSelectionModel().getSelectedItem(); 49 | selectedItem.getParent().getChildren().remove(selectedItem); 50 | } 51 | }); 52 | 53 | stackPane.getChildren().add(treeView); 54 | 55 | final Scene scene = new Scene(stackPane, 400, 400); 56 | primaryStage.setScene(scene); 57 | primaryStage.show(); 58 | } 59 | 60 | private TreeItem createItem(final int number) { 61 | final TreeItem root = new TreeItem<>("Root " + number); 62 | final TreeItem child = new TreeItem<>("Child " + number); 63 | 64 | root.getChildren().add(child); 65 | return root; 66 | } 67 | 68 | private void handleChange(final Change> change) { 69 | System.out.println(change); 70 | System.out.println(change.getList()); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/selection/TreeSelectionController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 18.12.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.collections.ObservableList; 8 | import javafx.scene.control.TreeItem; 9 | import javafx.scene.control.TreeView; 10 | import de.swingempire.fx.collection.TreeIndexMappedList; 11 | import de.swingempire.fx.collection.TreeIndicesList; 12 | 13 | 14 | /** 15 | * Implementation of IndexedItemsController that handles a TreeView. Unfortunately, 16 | * a treeView doesn't have a model and is needed for flattening the hierarchical 17 | * structure of its TreeItems into a sequential, indexable data 18 | * structure. 19 | *

    20 | * PENDING JW: 21 | *

  • root changes 22 | *
  • changes to showRoot property not handled 23 | * 24 | *

    25 | * @author Jeanette Winzenburg, Berlin 26 | */ 27 | public class TreeSelectionController implements IndexedItemsController> { 28 | 29 | protected TreeIndicesList indicesList; 30 | protected TreeIndexMappedList indexedItems; 31 | 32 | public TreeSelectionController(TreeView tree) { 33 | indicesList = new TreeIndicesList<>(tree); 34 | indexedItems = new TreeIndexMappedList<>(indicesList); 35 | } 36 | 37 | @Override 38 | public ObservableList getIndices() { 39 | return indicesList; 40 | } 41 | 42 | @Override 43 | public ObservableList> getIndexedItems() { 44 | return indexedItems; 45 | } 46 | 47 | @Override 48 | public void setIndices(int... indices) { 49 | indicesList.setIndices(indices); 50 | } 51 | 52 | @Override 53 | public void addIndices(int... indices) { 54 | indicesList.addIndices(indices); 55 | } 56 | 57 | @Override 58 | public void clearIndices(int... indices) { 59 | indicesList.clearIndices(indices); 60 | } 61 | 62 | @Override 63 | public void setAllIndices() { 64 | indicesList.setAllIndices(); 65 | } 66 | 67 | @Override 68 | public void clearAllIndices() { 69 | indicesList.clearAllIndices(); 70 | } 71 | 72 | @Override 73 | public int sourceIndexOf(TreeItem item) { 74 | return indicesList.getSource().getRow(item); 75 | } 76 | 77 | @Override 78 | public int getSourceSize() { 79 | return indicesList.getSource().getExpandedItemCount(); 80 | } 81 | 82 | @Override 83 | public TreeItem getSourceItem(int index) { 84 | return indicesList.getSource().getTreeItem(index); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/table/toggle/PeopleController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 11.08.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.table.toggle; 6 | 7 | import javafx.application.Platform; 8 | import javafx.fxml.FXML; 9 | import javafx.geometry.Pos; 10 | import javafx.scene.control.TableCell; 11 | import javafx.scene.control.TableColumn; 12 | import javafx.scene.control.TableView; 13 | import javafx.scene.control.ToggleButton; 14 | import javafx.scene.control.ToggleGroup; 15 | import javafx.util.Callback; 16 | 17 | import com.sun.prism.impl.Disposer; 18 | 19 | /** 20 | * Have a toggleButton as cell. 21 | * http://stackoverflow.com/q/31893394/203657 22 | * 23 | * Problem: selected sticks to button, not to row. 24 | */ 25 | public class PeopleController { 26 | 27 | @FXML 28 | private TableView personTable; 29 | 30 | @FXML 31 | private TableColumn nameColumn; 32 | 33 | @FXML 34 | private TableColumn previewColumn; 35 | 36 | private MainApp mainApp; 37 | 38 | final ToggleGroup group = new ToggleGroup(); 39 | 40 | @SuppressWarnings("unchecked") 41 | @FXML 42 | public void initialize() { 43 | System.out.println("on fx? " + Platform.isFxApplicationThread()); 44 | nameColumn.setCellValueFactory(cellData -> cellData.getValue() 45 | .nameProperty()); 46 | previewColumn 47 | .setCellFactory(new Callback, TableCell>() { 48 | 49 | @Override 50 | public TableCell call( 51 | TableColumn p) { 52 | ButtonCell cell = new ButtonCell(group); 53 | cell.setAlignment(Pos.CENTER); 54 | return cell; 55 | } 56 | }); 57 | } 58 | 59 | public void setMainApp(MainApp mainApp) { 60 | this.mainApp = mainApp; 61 | personTable.setItems(mainApp.getPersonData()); 62 | } 63 | 64 | public class ButtonCell extends TableCell { 65 | 66 | final ToggleButton cellButton = new ToggleButton("click"); 67 | 68 | public ButtonCell(ToggleGroup group) { 69 | cellButton.setToggleGroup(group); 70 | } 71 | 72 | @Override 73 | protected void updateItem(Boolean t, boolean empty) { 74 | super.updateItem(t, empty); 75 | if (!empty) { 76 | setGraphic(cellButton); 77 | } 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/test/de/swingempire/fx/scene/control/CheckBoxTreeCell_32620Plain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 25.03.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import javafx.application.Application; 11 | import javafx.scene.Scene; 12 | import javafx.scene.control.Button; 13 | import javafx.scene.control.CheckBoxTreeItem; 14 | import javafx.scene.control.TreeItem; 15 | import javafx.scene.control.TreeView; 16 | import javafx.scene.control.cell.CheckBoxTreeCell; 17 | import javafx.scene.layout.BorderPane; 18 | import javafx.scene.layout.HBox; 19 | import javafx.stage.Stage; 20 | 21 | import com.sun.javafx.runtime.VersionInfo; 22 | 23 | /** 24 | * https://javafx-jira.kenai.com/browse/RT-32620 25 | * 26 | * The example in the bug report doesn't behave as described in api doc of 27 | * CheckBoxTreeCell, so trying to simplify. CheckBoxTreeCell needs 28 | * a tree with CheckBoxTreeItems, then working as expected. But: 29 | * not updating parent state on modifications to the children list. 30 | * 31 | */ 32 | public class CheckBoxTreeCell_32620Plain extends Application { 33 | 34 | public static void main(String[] args) { 35 | launch(args); 36 | } 37 | 38 | @Override 39 | public void start(Stage stage) throws Exception { 40 | stage.setTitle(VersionInfo.getRuntimeVersion()); 41 | stage.setScene(getScene()); 42 | stage.show(); 43 | } 44 | 45 | private Scene getScene() { 46 | 47 | List> ls = new ArrayList>(10); 48 | for (int i = 0; i < 10; i++) { 49 | ls.add(new CheckBoxTreeItem("Test " + i)); 50 | } 51 | 52 | TreeView tv = new TreeView(); 53 | tv.setRoot(new CheckBoxTreeItem("Root")); 54 | 55 | tv.getRoot().getChildren().addAll(ls); 56 | tv.getRoot().setExpanded(true); 57 | tv.setEditable(true); 58 | 59 | tv.setCellFactory(CheckBoxTreeCell.forTreeView()); 60 | BorderPane root = new BorderPane(); 61 | root.setCenter(tv); 62 | 63 | Button removeSelected = new Button("removeSelected"); 64 | removeSelected.setOnAction(e -> { 65 | TreeItem item = tv.getSelectionModel().getSelectedItem(); 66 | if (item == null || item == tv.getRoot()) return; 67 | tv.getRoot().getChildren().remove(item); 68 | }); 69 | HBox buttonPane = new HBox(removeSelected); 70 | root.setBottom(buttonPane); 71 | 72 | return new Scene(root, 600, 400); 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /fx8-swingempire/src/demo/de/swingempire/fx/scene/control/tree/TableEdit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 28.04.2015 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.tree; 6 | 7 | import javafx.application.Application; 8 | import javafx.scene.Parent; 9 | import javafx.scene.Scene; 10 | import javafx.scene.control.Button; 11 | import javafx.scene.control.TableColumn; 12 | import javafx.scene.control.TableView; 13 | import javafx.scene.control.cell.PropertyValueFactory; 14 | import javafx.scene.control.cell.TextFieldTableCell; 15 | import javafx.scene.layout.VBox; 16 | import javafx.stage.Stage; 17 | import de.swingempire.fx.demobean.Person; 18 | 19 | /** 20 | * Impossible to reliably start editing after 21 | * inserting an item. 22 | * 23 | * http://stackoverflow.com/q/29863095/203657 24 | * 25 | * In TableView, only showing if calling scrollTo(row) before 26 | * starting the edit, hack same (call tableView.laoyut()). 27 | * 28 | * http://stackoverflow.com/q/30060978/203657 29 | * 30 | * 31 | * @author Jeanette Winzenburg, Berlin 32 | * @see TreeEdit 33 | */ 34 | public class TableEdit extends Application { 35 | 36 | private Parent getContent() { 37 | TableView table = new TableView<>(Person.persons()); 38 | table.setEditable(true); 39 | TableColumn lastName = new TableColumn<>("lastName"); 40 | lastName.setCellValueFactory(new PropertyValueFactory("lastName")); 41 | lastName.setCellFactory(TextFieldTableCell.forTableColumn()); 42 | TableColumn firstName = new TableColumn<>("FirstName"); 43 | firstName.setCellValueFactory(new PropertyValueFactory("firstName")); 44 | firstName.setCellFactory(TextFieldTableCell.forTableColumn()); 45 | table.getColumns().addAll(firstName, lastName); 46 | 47 | Button button = new Button("add Person"); 48 | button.setOnAction(e -> { 49 | Person person = new Person(null, null, null); 50 | table.getItems().add(person); 51 | table.getSelectionModel().select(person); 52 | table.requestFocus(); 53 | int row = table.getItems().size() - 1; 54 | table.scrollTo(row); 55 | table.layout(); 56 | table.edit(row, table.getColumns().get(0)); 57 | }); 58 | VBox box = new VBox(table, button); 59 | return box; 60 | } 61 | @Override 62 | public void start(Stage primaryStage) throws Exception { 63 | primaryStage.setScene(new Scene(getContent())); 64 | primaryStage.show(); 65 | } 66 | 67 | public static void main(String[] args) { 68 | launch(args); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /fx8-swingempire/src/java/de/swingempire/fx/scene/control/selection/ListViewAnchored.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 03.09.2014 3 | * 4 | */ 5 | package de.swingempire.fx.scene.control.selection; 6 | 7 | import javafx.collections.FXCollections; 8 | import javafx.collections.ObservableList; 9 | import javafx.scene.control.ListView; 10 | import javafx.scene.control.Skin; 11 | 12 | /** 13 | * All anchored** are based on 8u20. 14 | * 15 | * Changes in 8u40b9: 16 | * 17 | * ListView.ListBitSelectionModel 18 | * - selectFirstRowByDefault: listening to properties changes of key 19 | * "selectFirstRowByDefault" and updates private field accordingly 20 | 21 | * ListBitSelectionModel 22 | * - updateDefaultSelection/setAnchor in constructor of ListViewSelectionModel 23 | * - overridden clearAndSelect to set anchor 24 | * - extracted end of updateItems into updateDefaultSelection (which clears selection!) and 25 | * calls select(newIndex) 26 | * 27 | * ListViewBehavior 28 | * - new: checks for replaced in selectedIndices to update anchor 29 | * - new ListCellBehavior.setAnchor has third parameter 30 | * - new ListCellBehavior.hasNonDefaultAnchor called from behavior 31 | * 32 | * ListViewSkin 33 | * - nothing except accessibility 34 | * 35 | * ListCellBehavior 36 | * - no change 37 | * 38 | * CellBehaviorBase 39 | * - added notion of defaultAnchor (whatever that is), key "isDefaultAnchor" 40 | * - default somehow used in set/get/removeAnchor 41 | * 42 | * ControlUtils 43 | * - unchanged 44 | * 45 | * MultipleSelectionModelBase 46 | * - select(T): added setSelectedIndex(-1) if item not in list 47 | * 48 | * ListViewFocusModel 49 | * - focus(0) in constructor 50 | * - note: NO change in itemsContentListener, just changed to lambda 51 | * 52 | * @author Jeanette Winzenburg, Berlin 53 | */ 54 | public class ListViewAnchored extends ListView { 55 | 56 | /** 57 | * 58 | */ 59 | public ListViewAnchored() { 60 | this(FXCollections.observableArrayList()); 61 | } 62 | 63 | /** 64 | * @param items 65 | */ 66 | public ListViewAnchored(ObservableList items) { 67 | super(items); 68 | setSelectionModel(new AnchoredListViewSelectionModel<>(this)); 69 | setFocusModel(new ListViewAFocusModel<>(this)); 70 | // getProperties().put("selectOnFocusGain", Boolean.FALSE); 71 | // getProperties().put("selectFirstRowByDefault", Boolean.FALSE); 72 | } 73 | 74 | @Override 75 | protected Skin createDefaultSkin() { 76 | return new de.swingempire.fx.scene.control.skin.ListViewASkin<>(this); 77 | // return new ListViewASkin<>(this); 78 | } 79 | 80 | } 81 | --------------------------------------------------------------------------------