Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Checkbox states - Java

Options
  • 03-12-2016 11:06pm
    #1
    Registered Users Posts: 8,197 ✭✭✭


    Hi,

    I'm looking at a bit of Java cade which has a tree of checkboxes.

    The observed issue is that when a minority of child checkboxes are selected, its immediate parent checkbox becomes checked instead of block filled - indicating partial checked. This occurs at all levels - not just at a certain level.

    Is it a big fix to correct this so that the parent checkboxes transition from block filled to checked as its child checkboxes become selected?

    Any pointers as to whereabouts in the code I should be looking? The listener is implementing the ICheckStateListener class.

    Edit: I've found the code responsible. What it is doing is listening for a CheckStateChangedEvent and if the checkbox is checked, then it sets the parent as selected. I now need to figure out how to tell the class that if any (but not all) of the child nodes are selected then it should redraw the checkbox with the solid fill.
    I;ve looked at the options available for use in the class and there seems to be no neat way of doing this.

    What I'm currently trying to do is that I've obtained the parent node and from it I've obtained a list of all its children as a List. However, the class does not have an accessor to obtain the state of the children - which seems rellly odd to me.

    I can see that I need to call the CheckboxTreeViewer class with the parent node. However, I'm struggling to tease out if the parent requires to be grayed or checked.


    Thanks.


Comments

  • Registered Users Posts: 403 ✭✭counterpointaud


    I've actually done something similar in a JavaScript app recently. Will post the code in case it helps. Quite possiblly it won't, as it sounds like your problem is that you don't have access to the properties you need, but maybe the logic will be helpful in some way.
    /*
     * Get state for select-all box based on flattened values
     */
    export function getSelectAllState(activeFilters, flattenedValues = [], includedFilters = []) {
      const { isUnfiltered, empty } = activeFilters;
      const isChecked = { checked: true, indeterminate: false };
      const isIndeterminate = { checked: false, indeterminate: true };
      const isUnchecked = { checked: false, indeterminate: false };
    
      if (isUnfiltered) {
        return isChecked;
      }
    
      if (empty) {
        return isUnchecked;
      }
    
      if (!includedFilters.length && !Object.keys(activeFilters).length) {
        return isChecked;
      }
    
      if (flattenedValues.every(v => includedFilters.values.includes(v))) {
        return isChecked;
      }
    
      if (flattenedValues.some(v => includedFilters.values.includes(v))) {
        return isIndeterminate;
      }
    
      return isUnchecked;
    }
    

    Note: Before someone calls me out, I am aware that that using .every and .includes together is not the greatest idea, perf wise. Don't do this (or the Java equivalent) if you don't have a guarantee that both arrays will be small. The main purpose of the example is the logic, not the implementation.


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    Okay - thanks for that.

    I've made some progress and got it 'kind of' working.

    There appears to be an issue in that it is holding the number of grayed boxes even after I have deselected it.

    I can see from debug output to the console that things are mostly working - there just seems to be an anomaly in the grayed. I'm using a counter which is in scope within a method so should be garbage collected by the time it comes around again. I'm not sure where it is picking up the value from.

    The top level node has only one child node. However, I can see it showing the checked counter as 1 and the grayed counter as 1. I've no idea as to why this as becuase I've already catered for the checked method returning anything selected (as opposed to checked).

    What I'm doing is get the parent node. Find its children. Interrogate them to find if they are checked (selected) or grayed. Using this info I can then decide how to build up the parent node. If the child nodes have no checked or grayed, then parent = clear. If all children = checked then set parent to checked, otherwise set parent to grayed.

    However, the graying is not working for me and I really can't see why. :(

    Frustrated and quitting for the night!


  • Registered Users Posts: 403 ✭✭counterpointaud


    So are you sure that the state calculation is called whenever there is a change in any checkbox?

    It's sounds like you have a tree / hierarchy or checkboxes (i.e. each child can also have children), how many levels deep is it / can it get?

    Do you have a flattened collection of all the descendants of the root node in some sort of list, or do you have to recursively traverse some tree-like data structure?

    I'm know how this sort of UI is typically rendered in the Java framework you are using, so don't have any more specific ideas on what could be going wrong there.


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    So are you sure that the state calculation is called whenever there is a change in any checkbox?
    Yes, I've stepped through it using debug and it is going all the way up to the method which does the update - I'll check it's name when I log in.
    It's sounds like you have a tree / hierarchy or checkboxes (i.e. each child can also have children), how many levels deep is it / can it get?
    Yes - that is what it is. It only goes 4 levels deep.
    Do you have a flattened collection of all the descendants of the root node in some sort of list, or do you have to recursively traverse some tree-like data structure?
    This code is legacy. The implementation recursively traverses up the tree from the checked node/checkbox.
    I'm know how this sort of UI is typically rendered in the Java framework you are using, so don't have any more specific ideas on what could be going wrong there.
    I've no clue either. :(


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    Okay - I've got it working apart from one problem.

    If I open the dialog and click on a checkbox it will redraw as checked. The children correctly get redrawn as checked and the parents get grayed or checked as appropriate.
    However, if I then clear this checkbox and individually check each of its children code will correctly gray this box for the first number of checked children, but when all children are checked it does not refresh this box to checked.

    Going back to this checkbox and checking/unchecking it will correctly check the children but itself remains grayed and similar with any other parents which were previously grayed.

    I can trace the code up to correctly calling CheckboxTreeViewer.setChecked with the expected node and a value of true. I think therefore that any code I've added is correct. I just can't see why this is not working. It works downwards, but when tracing back up through the tree, I cannot get the code to switch from gray to checked.


    Any suggestions?


  • Advertisement
  • Registered Users Posts: 403 ✭✭counterpointaud


    Any suggestions?

    Not really... sounds like you are on the right track, it sounds like a bug that will reveal itself in time.

    That sort of UI logic can get really complex, quickly. In my case I am not calculating things up and down the tree from a node, I am calculating from the entire tree, flattened into a list. You may be dealing with a different implementation though, sounds like you have a common method for all checkboxes which is supposed to figure out checkbox state for each instance, no matter where in the tree it is? Sounds like a bit of a headache to implement that way.


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    It is similar in approach to what is used elsewhere in the system.
    Unfortunately it does not appear to be generic for anyone to pick up. Everyone has gone and done their own thing.


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    Got it fixed. Checkboxes when grayed are still marked as checked - it is not a tri-state enum. Therefore when handling checkboxes you need to consider what setting to use for the grayed indication and the checked indication.

    I was missing clearing the grayed indication when inside the functionality to set a checkbox. When setting/clearing a grayed indication the provided method was able to handle both. This was using org.eclipse.jface.viewers.CheckboxTreeViewer.


Advertisement