-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow CheckBoxTreeCell CellFactory #1
Comments
Hi Jordan, you are in control of creating your |
Right, but in the documentation, it says,
If I do set the cell factory as you mentioned, I get the desired view, but the functionality doesn't work. Checking a parent directory will not also check its subdirectories and files. |
Ah, I see, that's unfortunate. This is another example of how most JavaFX controls are not very reusable beyond a very limited use case that someone had in mind when designing them. The implementation of the checkbox functionality must use Now, I will not go down the path of duplicating code for the special case of |
Lol... no kidding...
Have you see my PR #3? |
Lol... I just reread my own comment about the documentation, I guess my recent work in my PR actually shouldn't be done: the root also needs to be |
I've submitted another PR to account for the above realization (#4) |
I saw the PR and by
I mean that adding |
Right, just realized that. I went the route I did because I wasn't sure how to account for that, but I see how to do it now. |
On second thought, this code doesn't work: abstract class PathItem<GenericTreeItem extends TreeItem<Path>> extends GenericTreeItem {
} |
I'm guessing we'll need to convert the |
Nah, even that doesn't work out well due to |
Here's an idea. Currently we have PathItem extends TreeItem<Path> Let's keep PathItem parameterized, i.e. PathItem<T> extends TreeItem<T> The idea is that This additional type parameter will also have to be added all the way to I haven't worked out all the details, but it seems promising. Maybe another desired tweak will be to provide versions of |
Correct me if I'm wrong, but the only way to make this scalable isn't much different than the poorly-scalable idea that my PR uses because one cannot write: class PathItem<T extends TreeItem<Path>> extends T {}
This is essentially what my approach does. However, this approach could be further refined. If each If Java supported |
I'm trying out another way. I'm using default methods in interfaces to make things more generic (public methods are named the same but private methods are now prefixed with an underscore). To get around the problem of accessing the trees, I'm using a hack: interface PathItem<T extends TreeItem<Path> & PathItem<T>, /* other generics */> {
T getTree();
} Whenever a new |
I've finished the implementation of this new way. See #5. |
Lol... Just now saw your latest comment. |
I'm looking at your comment again. In some ways, I feel like the ideas you are proposing there would be useful in resolving #2. |
So, you are proposing something like this: PathItem<T> extends TreeItem<T> {
PathItem( /* args */, Function<T, Path> project) {}
}
FileItem<T> extends PathItem<T> { /* no changes */ }
DirItem<T> extends PathItem<T> {
DirItem( /* args */, Function<Path, T> inject) {}
}
TopLevelDirItem<T> extends DirItem<T> { /* no changes */ } The regular // For regular TreeItems
PathItem<Path> pathItem = new PathItem<>(/* args */, Function.identity());
TreeView<Path> view = new TreeView<>(root); But the // For CheckBoxTreeItems
PathItem<Tuple2<Path, Var<Boolean>>> checkBoxItem = new PathItem<>(/* args */, Tuple2::get1);
TreeView<Tuple2<Path, Var<Boolean>>> view = new TreeView<>(root);
view.setCellFactory(customCheckBoxFactory); where If so, yes, I do believe that would work. |
Yes, that's a pretty accurate description of what I meant. |
I wish I would have read that and understood it before writing #5 because that got really complex really fast 😃 |
I'm sure it was a great learning experience :) |
Lol... It was. |
Ran into a problem in my attempt to implement the The reason why |
TreeCell.getTreeItem() gives you the tree item, right? |
I looked at OpenJDK and looked through how they wrote the code for the initial The issue I'm running into is how to update the parent/children's selected/intermediate properties efficiently. |
In your custom |
Btw, if I needed to represent 3 values (selected, intermediate, unselected), I would define an |
Let me explain. Since every TreeCell has added a listener to its TreeItem's Using pseduo code: // ACTUAL CODE
checkbox.selectedProperty.bindbidirectional(selectedProperty());
// where state property is
// "Val.combine(selectedProperty, intermediateProperty, null);"
stateProperty.addListener(obs -> updateCheckBoxItems());
public void updateCheckBoxItems() {
// no need to handle leaf/node's checkbox update
// because it's bound bidirectionally...
// update going upwards
TreeItem parent = getTreeItem().getParent();
if (parent != null) { updateParent(parent) }
// now that upwards is done, do downwards update
if (newstate == checked) {
force check all children and their children recursively
} else if (newstate == unchecked) {
force uncheck all children and their children recursively
}
// don't do anything for intermediate state.
}
public void updateParent(TreeItem parentItem) {
if (parents children are all checked) {
make parent checked also
} else if (at least one child is checked) {
make parent undefined [indeterminate == true]
} else ( /* no children checked */ ) {
make parent unchecked
}
// now that parent is figured out, continue the recursion on its parent
updateParent(parentItem.getParent())
} I realized that when I run the code So, I would get a crazy chain of updates that looked like this:
I get that some sort of That's about how far I got before something else needed my attention. |
You don't need to call |
I guess now that I see that my original code does work (see below), yeah you're right. If I update the parent, then allow the parent listener to continue that process, I don't need to make it recursive.
Turns out it does work. I assumed that, in the downward update, it would set its child to a new value. However, that doesn't occur when a parent's new state is an intermediate state and when it's checked or unchecked and it tries to force check/uncheck its children, those children will already be up-to-date because of the upwards update (and thus a no-op). In the one case where that isn't already true, that's the case I want it to work that way.... |
I've been thinking this issue over and I think it's not needed.... I realized that the Commit dialog or Revert dialog that would be used in JGitFX is static. The dialog that displays the Beyond that, if I implement my own |
Another update: Although I won't be using the CheckBox-pseudo-code workaround you suggested in the manner I initially thought I would, I still think generalizing the code is better. For example, I want to include a directory watcher in a JGitFX demo, but I want to update the text color of the file to represent the status of that file in the git repo (added, modified, untracked, etc.). With the generic-approach and the inject/project functions, I would be able to implement that. |
Eliminate some type casts and warnings.
Closing via #7 |
I was hoping to use this library in JGitFX. However,
LiveDirs
does not allow the option of using theCheckBoxTreeCell
factory, which is essential for designing a commit or revert dialog where the user can check which files they want to stage and commit or revert.The text was updated successfully, but these errors were encountered: