Skip to content

Commit a09fd86

Browse files
committed
Merge branch 'issue38-property-popover'
2 parents 86e2227 + fef57ad commit a09fd86

File tree

4 files changed

+55
-11
lines changed

4 files changed

+55
-11
lines changed

src/main/java/net/sourceforge/pmd/util/fxdesigner/model/PropertyDescriptorSpec.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ public Var<String> valueProperty() {
147147
* @return An xml string
148148
*/
149149
public String toXml() {
150-
return String.format("<property name=\"%s\" type=\"%s\" value=\"%s\" />",
151-
getName(), getTypeId().getStringId(), getValue());
150+
return String.format("<property name=\"%s\" type=\"%s\" value=\"%s\" description=\"%s\"/>",
151+
getName(), getTypeId().getStringId(), getValue(), getDescription());
152152
}
153153

154154

src/main/java/net/sourceforge/pmd/util/fxdesigner/popups/ExportXPathWizardController.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import static com.github.oowekyala.rxstring.ItemRenderer.indented;
99
import static com.github.oowekyala.rxstring.ItemRenderer.surrounded;
1010
import static com.github.oowekyala.rxstring.ItemRenderer.wrapped;
11-
import static net.sourceforge.pmd.util.fxdesigner.util.AuxLanguageRegistry.getSupportedLanguageVersions;
1211
import static net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil.stringConverter;
1312
import static net.sourceforge.pmd.util.fxdesigner.util.reactfx.ReactfxUtil.rewireInit;
1413

@@ -173,10 +172,7 @@ public Subscription bindToRuleBuilder(ObservableXPathRuleBuilder ruleBuilder) {
173172

174173

175174
private void initialiseLanguageChoiceBox() {
176-
languageChoiceBox.getItems().addAll(getSupportedLanguageVersions().stream()
177-
.map(LanguageVersion::getLanguage)
178-
.distinct()
179-
.collect(Collectors.toList()));
175+
languageChoiceBox.getItems().setAll(AuxLanguageRegistry.getSupportedLanguages().collect(Collectors.toList()));
180176

181177
languageChoiceBox.setConverter(stringConverter(Language::getShortName, AuxLanguageRegistry::findLanguageByShortName));
182178
}
@@ -286,6 +282,7 @@ private static LiveTemplateBuilder<ObservableXPathRuleBuilder> liveTemplateBuild
286282
.append("<property name=\"").bind(PropertyDescriptorSpec::nameProperty)
287283
.append("\" type=\"").bind(PropertyDescriptorSpec::typeIdProperty, PropertyTypeId::getStringId)
288284
.append("\" value=\"").bind(PropertyDescriptorSpec::valueProperty)
285+
.append("\" description=\"").bind(PropertyDescriptorSpec::descriptionProperty)
289286
.appendLine("\"/>")
290287
)
291288
.appendIndent(2).append("<property name=\"version\" value=\"").bind(ObservableXPathRuleBuilder::xpathVersionProperty).appendLine("\"/>")

src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/PopOverWrapper.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil;
2020

2121
import javafx.application.Platform;
22+
import javafx.event.EventHandler;
2223
import javafx.stage.Stage;
2324
import javafx.stage.Window;
2425
import javafx.stage.WindowEvent;
@@ -34,6 +35,7 @@ public final class PopOverWrapper<T> {
3435
private final Var<PopOver> myPopover = Var.newSimpleVar(null);
3536
private BiFunction<T, PopOver, PopOver> rebinder;
3637
private T identity;
38+
private EventHandler<WindowEvent> userOnHiding = we -> {};
3739

3840
public PopOverWrapper(BiFunction<T, @Nullable PopOver, @Nullable PopOver> rebinder) {
3941
this.identity = null;
@@ -56,7 +58,12 @@ public void showOrFocus(Consumer<@NonNull PopOver> showMethod) {
5658
}
5759

5860
public void rebind(T identity) {
59-
preload(() -> rebinder.apply(identity, myPopover.getValue()));
61+
if (identity != this.identity) {
62+
this.identity = identity;
63+
this.userOnHiding.handle(null);
64+
this.userOnHiding = we -> {};
65+
preload(() -> rebinder.apply(identity, myPopover.getValue()));
66+
}
6067
}
6168

6269
private void preload(Supplier<PopOver> supplier) {
@@ -68,6 +75,14 @@ private void preload(Supplier<PopOver> supplier) {
6875
myPopover.setValue(null);
6976
return;
7077
}
78+
79+
this.userOnHiding = popOver.getOnHiding();
80+
81+
popOver.setOnHiding(we -> {
82+
this.identity = null;
83+
this.userOnHiding.handle(we);
84+
});
85+
7186
popOver.getRoot().getStylesheets().addAll(DesignerUtil.getCss("popover").toString());
7287
popOver.getRoot().applyCss();
7388
myPopover.setValue(popOver);

src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/PropertyCollectionView.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import java.io.IOException;
88
import java.util.Comparator;
99
import java.util.Objects;
10-
import java.util.Optional;
1110

1211
import org.apache.commons.lang3.StringUtils;
1312
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -62,6 +61,35 @@ public class PropertyCollectionView extends VBox implements ApplicationComponent
6261
ValueExtractor.addObservableValueExtractor(c -> c instanceof ListCell, c -> ((ListCell) c).itemProperty());
6362
}
6463

64+
/*
65+
Note: nesting a popover within a popover is error-prone: JavaFX
66+
doesn't support a proper focus model for PopupWindows (used by PopOver)
67+
68+
This means, multiple open popovers maintain independent focus models
69+
and react to every event of the stage. Ie there's no stage that has
70+
primary focus. Eg if you focus a textfield in a popover and carry
71+
on editing somewhere else in the main stage, both places will see
72+
the update.
73+
74+
This also means that when eg here, you click the "add property" button,
75+
the button doesn't lose focus in its popover. When editing something in
76+
the new popover, this will send an event to the edited text field AND
77+
to the "add property" button.
78+
79+
This is why the action handlers explicitly request focus on some
80+
innocuous control (eg listview) after they're done processing.
81+
82+
This is also why we can't let the edit popover hover around in
83+
detached mode.
84+
85+
86+
See:
87+
88+
https://github.com/openjdk/jfx/blob/be22e8535cb3f98069c0a0216b056cfe8ef037e8/modules/javafx.graphics/src/main/java/javafx/stage/PopupWindow.java#L531-L535
89+
90+
91+
*/
92+
6593

6694
// for scenebuilder
6795
@SuppressWarnings("ConstantConditions") // suppress nullability issue
@@ -90,7 +118,10 @@ public PropertyCollectionView(@NamedArg("designerRoot") DesignerRoot root) {
90118

91119
ControlUtil.anchorFirmly(addProperty);
92120

93-
addProperty.setOnAction(e -> addNewProperty(getUniqueNewName()));
121+
addProperty.setOnAction(e -> {
122+
addNewProperty(getUniqueNewName());
123+
view.requestFocus();
124+
});
94125
footer.getChildren().addAll(addProperty);
95126
this.getChildren().addAll(view, footer);
96127

@@ -175,7 +206,6 @@ private PopOver rebindPopover(PropertyDescriptorSpec newSpec, PopOver pop) {
175206
// create it
176207
return detailsPopOver(newSpec);
177208
}
178-
Optional.ofNullable(pop.getOnHiding()).ifPresent(it -> it.handle(null));
179209

180210
pop.titleProperty().bind(newSpec.nameProperty()
181211
.filter(StringUtils::isNotBlank)
@@ -279,6 +309,7 @@ protected Pair<Node, Subscription> getNonEditingGraphic(PropertyDescriptorSpec s
279309
edit.setOnAction(e -> {
280310
myEditPopover.rebind(spec);
281311
myEditPopover.showOrFocus(p -> PopOverUtil.showAt(p, owner, this));
312+
view.requestFocus();
282313
});
283314

284315
sub = sub.and(() -> edit.setOnAction(null));
@@ -293,6 +324,7 @@ protected Pair<Node, Subscription> getNonEditingGraphic(PropertyDescriptorSpec s
293324
myEditPopover.rebind(null);
294325
myEditPopover.hide();
295326
}
327+
view.requestFocus();
296328
});
297329

298330
sub = sub.and(() -> delete.setOnAction(null));

0 commit comments

Comments
 (0)