Any way to get fine-grained control on treetable model updates, similar to AbstractTableModel.fireTableCellUpdated()

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Any way to get fine-grained control on treetable model updates, similar to AbstractTableModel.fireTableCellUpdated()

davide.cavestro
I have a treetable backed by an eventList (actually an ObservableElementList instance).
Every list element is an groovy.util.ObservableMap instance.
I noticed when I change a property (a map value) on the eventlist the TreeList.Format.getPath () method gets called. This seems a bit like the counterpart of a row change event.

So is there any way to get fine-grained control on treetable model updates? similar to AbstractTableModel.fireTableCellUpdated(int, int)

Running this snippet on groovyConsole you see that a change to a list element property triggers the TreeList.Format.getPath() method, printing 'getPath called' on the console.

@Grab(group='net.java.dev.glazedlists', module='glazedlists_java15', version='1.8.0')
import ca.odell.glazedlists.GlazedLists
import ca.odell.glazedlists.BasicEventList
import ca.odell.glazedlists.ObservableElementList
import ca.odell.glazedlists.DisposableMap
import ca.odell.glazedlists.FunctionList
import ca.odell.glazedlists.TreeList
import ca.odell.glazedlists.SortedList
import ca.odell.glazedlists.swing.EventTableModel
import ca.odell.glazedlists.gui.TableFormat
import ca.odell.glazedlists.swing.TreeTableSupport

import groovy.swing.SwingBuilder

class TaskKeyMaker implements FunctionList.Function<Map, Object> {

    Object evaluate(Map sourceValue) {
        return sourceValue.id
    }
}
//fake data 
Map data = [ 1: [ id: 1, name: 'elem 1', parentId: null], 
              2: [ id: 2, name: 'elem 1.1', parentId: 1], 
              3: [ id: 3, name: 'elem 1.2', parentId: 1]
            ] 

//holds path to the tree root for fake data 
Map paths = [ 1: [data[1]], 
               2: [data[1], data[2]], 
               3: [data[1], data[3]]
             ] 
             
             

BasicEventList myList = GlazedLists.threadSafeList(new BasicEventList (data.values ().collect {it as ObservableMap}))
ObservableElementList myObservableList = new ObservableElementList (myList, GlazedLists.beanConnector (ObservableMap.class))
DisposableMap myMap = GlazedLists.syncEventListToMap(myObservableList, new TaskKeyMaker ())

TreeList myTreeList = new TreeList( new SortedList (myObservableList, {a,b-> a.id <=> b.id} as Comparator), 
                   [ getPath: { path, elt ->
                       println 'getPath called'
                       path.addAll( paths[ elt.id])
                     }, 
                     allowsChildren: { true }, 
                     getComparator: { null } 
                   ] as TreeList.Format, TreeList.NODES_START_EXPANDED) 

new SwingBuilder().edt {
    frame (title:'Frame', size:[300,300], show: true) {
        vbox {
            scrollPane {
            def mycolumns = [[name: 'id', title: 'ID'], [name: 'name', title: 'Name']]
                table (
                    id:'myTable', 
                    model: new EventTableModel (myTreeList, new TableFormat () {
                        public int getColumnCount() {mycolumns.size ()}
                        public String getColumnName(int column){mycolumns[column].title}
                        public Object getColumnValue(Object baseObject, int column) {
                            baseObject.(mycolumns[column].name)
                        }
                    })
                )
                TreeTableSupport.install (myTable, myTreeList, 0i)
            } 
            button("Update cell", actionPerformed: { myMap[2].name+=' updated' })
        }
    }
}
Reply | Threaded
Open this post in threaded view
|

Re: Any way to get fine-grained control on treetable model updates, similar to AbstractTableModel.fireTableCellUpdated()

James Lemieux
I'm afraid not. All bindings from EventList into any form of a table model are row-based. (i.e. the entire row is said to be "changing"). Glazed Lists has no functionality for describing the fields which changed in a single item within an EventList, nor mapping those fields to a particular column in your table model.

James


On Tue, Feb 12, 2013 at 9:16 AM, davide.cavestro <[hidden email]> wrote:
I have a treetable backed by an eventList (actually an
/ObservableElementList/ instance).
Every list element is an /groovy.util.ObservableMap/ instance.
I noticed when I change a property (a map value) on the eventlist the
/TreeList.Format.getPath ()/ method gets called. This seems a bit like the
counterpart of a row change event.

So *is there any way to get fine-grained control on treetable model updates?
similar to AbstractTableModel.fireTableCellUpdated(int, int)*

Running this snippet on groovyConsole you see that a change to a list
element property triggers the TreeList.Format.getPath() method, printing
'getPath called' on the console.





--
View this message in context: http://glazedlists.1045722.n5.nabble.com/Any-way-to-get-fine-grained-control-on-treetable-model-updates-similar-to-AbstractTableModel-fireTab-tp5709850.html
Sent from the GlazedLists - User mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|

Re: Any way to get fine-grained control on treetable model updates, similar to AbstractTableModel.fireTableCellUpdated()

davide.cavestro
James Lemieux wrote
I'm afraid not. All bindings from EventList into any form of a table model
are row-based. (i.e. the entire row is said to be "changing"). Glazed Lists
has no functionality for describing the fields which changed in a single
item within an EventList, nor mapping those fields to a particular column
in your table model.
Ok, that makes sense.
So - in order to prevent too much database accesses - I could fall back on caching the path into an in-memory structure: hence the getPath implementation will use that in-memory structure instead of the database-backed service... or better I could introduce caching for the relevant service method (using spring @cacheable annotation).
That said, I guess I'll never need finer control on model changes.
One last not-so-related thing: is there any workaround or plan to fix the loose of selection updating leaf nodes? If needed I could easily produce a groovy test case script.
Reply | Threaded
Open this post in threaded view
|

Re: Any way to get fine-grained control on treetable model updates, similar to AbstractTableModel.fireTableCellUpdated()

James Lemieux
I wish I could give you better news, but if I'm being truthful, it has been many moons since work has been done on TreeList. I'd only say TreeList is about 80% complete at this point. It should do the basic job ok (readonly treetable with expand/collapse and a selection model), but there are bugs like the one you point out, and large missing features (people ask for the ability to sort their TreeList in meaningful ways pretty often... something we really don't have an elegant solution for right now).

So, I guess my advice would be cautionary: if you have significant needs for this treetable component (i.e. it needs bells and whistles), I'd probably say you should roll your own. (which isn't that easy... I'm sympathetic to your plight).

James


On Thu, Feb 14, 2013 at 1:47 AM, davide.cavestro <[hidden email]> wrote:
James Lemieux wrote
> I'm afraid not. All bindings from EventList into any form of a table model
> are row-based. (i.e. the entire row is said to be "changing"). Glazed
> Lists
> has no functionality for describing the fields which changed in a single
> item within an EventList, nor mapping those fields to a particular column
> in your table model.

Ok, that makes sense.
So - in order to prevent too much database accesses - I could fall back on
caching the path into an in-memory structure: hence the /getPath/
implementation will use that in-memory structure instead of the
database-backed service... or better I could introduce caching for the
relevant service method (using spring @cacheable annotation).
That said, I guess I'll never need finer control on model changes.
One last not-so-related thing: is there any workaround or plan to fix the
loose of selection updating leaf nodes
<http://java.net/jira/browse/GLAZEDLISTS-462?focusedCommentId=354466&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_354466>
? If needed I could easily produce a groovy test case script.



--
View this message in context: http://glazedlists.1045722.n5.nabble.com/Any-way-to-get-fine-grained-control-on-treetable-model-updates-similar-to-AbstractTableModel-fireTab-tp5709850p5709865.html
Sent from the GlazedLists - User mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|

Re: Any way to get fine-grained control on treetable model updates, similar to AbstractTableModel.fireTableCellUpdated()

davide.cavestro
James Lemieux wrote
...if you have significant needs
for this treetable component (i.e. it needs bells and whistles), I'd
probably say you should roll your own. (which isn't that easy... I'm
sympathetic to your plight).
Since I just want to reduce the effects of changes to leaf attributes, I shamelessly tried to produce a patch for the original model. I noticed TreeList discriminates changes to leafs from other nodes this way:
    private void deleteAndDetachNode(int sourceIndex, List<Node<E>> nodesToVerify) {
        Node<E> node = data.get(sourceIndex, REAL_NODES).get();

        // if it has children, replace it with a virtual copy and schedule that for verification
        if(!node.isLeaf()) {
            Node<E> replacement = new Node<E>(node.virtual, new ArrayList<E>(node.path()));
            replaceNode(node, replacement, true);

            nodesToVerify.add(replacement);

        // otherwise delete it directly
        } else {
            Node<E> follower = node.next();

            deleteNode(node);

            // remove the parent if necessary in the next iteration
            nodesToVerify.add(node.parent);

            // also remove the follower - it may have become redundant as well
            if(follower != null && follower.virtual) nodesToVerify.add(follower);
        }
    }
Since this method is called even for UPDATE changes from listChanged method, I guess it produces removals for updates on leafs, hence leading to the loose of selection.
I just wonder if that special treatment for leafs is really needed to somewhat maintain the internal structure integrity (I must confess I didn't go deeper into the matter) or it is simply some sort of expendable optimization.
Any idea?
Reply | Threaded
Open this post in threaded view
|

Re: Any way to get fine-grained control on treetable model updates, similar to AbstractTableModel.fireTableCellUpdated()

davide.cavestro
In reply to this post by James Lemieux
Removing the special treatment for leafs, hence handling them as every other node seems to fix the problem. I've not seen any side effect so far.