How can I sort widgets in GWT? - gwt

I have a list of widgets which needs to be sorted. I want to create a container for these list of widgets to re-sort them each time new widget is added. How can I do it?
I can see the following ways:
a straightforward way is place them into arraylist and sort via Comparator, but after a new element is added we have to remove all list from container and add them again, in a new order.
use some sorting container. i have found only CellTable for this. But actually I dont need its rich functionality - I have only one column, dont need to sort on user events, only when new element added or removed, - so is there something else I can utilize in my use case?
GWT 2.4
PS
Actually, I am looking for something, that can be expressed like "widget container backed by widget collection", i.e. I change collection - container changes its contents, how can I implement this, or where can I find it?
PPS
The widgets can be different, thats why I dont think I can use CellTable easily.

There is no straightforward way of re-sorting the elements in the DOM after you add a new widget.
When the widgets are attached you cannot just move them (change their position in the document structure) without detaching and re-attaching.
Well, with absolute positioning you can just change the left-top coordinates to move the items, if it is what you need.
I had a similar problem to solve when I had to sort TreeItem elements (no built-in sort method available). As a workaround, I read all the children into the list and remove them from the parent widget at the same time, then sort these items using Comparator and add them back to parent from the sorted list. Everything is in a single sort() method, which encapsulates all required functionality and kind of simplifies understanding of this code.
"widget container backed by widget collection"
I would like to learn about one like that that also can do sorting and re-attaching on the fly. But it still will be backed by the same detaching-attaching I assume. I would recommend you to write one yourself, that will fit your particular needs. Either you need a Tree or a FlowPanel or anything else - you can extend that and add sort() logic according to context. And override add() method accordingly. So, your first option looks like a possible solution to me.

Related

How to build a tree in GTK4 (>= 4.10)

As the document said, TreeView in GTK4 has been deprecated since 4.10. The recommended replacement for it is ColumnView. However, I can't find clear documentation or example about how to build a treeView-like widget in GTK4 by ColumnView.
I found maybe TreeExpander related to it but I still don't know how to deal with it.
A very brief outline of what I did:
Familiarize yourself with how the new dynamic list widgets (Gtk.GridView and Gtk.ColumnView) work for a flat model (GLib.ListStore). There is example code in the Demo app.
Create a Gtk.TreeListModelCreateModelFunc function that takes a model item as a parameter and, if that item has children (e.g. is a folder in a filesystem model), creates and returns a Gtk.ListStore to hold the children. If the child items are already available then they can also be appended to the child model here. This means the child items are preloaded whether or not the row is expanded. For startup performance reasons, you might want to arrange to load them when the row is actually expanded which is more difficult - in this case you have to add a dummy child to the model else the expander will not be displayed.
Create a Gtk.SignalListItemFactory.
In the setup handler, create a display widget as usual then instead of using your display widget as child of the Gtk.ListItem, you create a Gtk.TreeExpander, and make that the child the Gtk.ListItem and make the display widget a child of the expander.
In the bind handler, get the display widget and model item from the supplied object. A complication here is that the object may be a Gtk.TreeListRow whose item might be another Gtk.TreeListRow so getting to the model item is harder. Bind the widget to the model item as usual. Then get the Gtk.TreeListRow from the Gtk.ListItem position and set the expander's list-row property to it.
If you delayed loading the child items then you would need to detect when the row is first expanded. You can connect to the notify signal for the Gtk.TreeListRow.expanded property to do this.
Use a Gtk.TreeListModel with a GLib.ListStore as its root_store as the model of a Gtk.ColumnView (after wrapping in Gtk.SelectionModel as usual). You must set the passthrough property to false else no expanders appear. If you are loading child items on demand then autoexpand should also be false.
If you are using a Gtk.ColumnView with multiple columns, you only need add the expander to the first column. Otherwise the factory signal handlers or similar to the flat model except the bind handler needs to be adapted for Gtk.TreeListRow parameter.
Simplifications and performance improvements may well be possible or later versions of Gtk4 may introduce some conveniences to make it less fiddly.
I am working on a file browser implementation using the above strategy, currently at https://github.com/elementary/files/tree/gtk4-treelistmodel but this may be merged into other branches (or abandoned!). Note that this branch is under development and contains unresolved bugs but the display of items works.

How do I find the next widget in a given direction in GTK+?

I want to find out which widget is in a given direction in GTK+, i.e. doing what the "move-focus" signal does, but without actually changing the focus. What I have in mind is a function that takes a GtkWidget * and a GtkDirectionType and returns the GtkWidget in the given direction (if any).
What I want this for is to ultimately enumerate the widgets inside a specific GtkFrame in my UI definition, in order from left to right. I.e. basically create a list of widgets from leftmost to rightmost, inside my GtkFrame (or in the general case, inside any container).
I've tried to search the GTK documentation but haven't found anything that doesn't also change focus.
Failing any other approach, the way I'm going forward with is to copy a selected set of static functions from the library implementation of GtkContainer and put them in a file in my own application, modifying them to suit my needs.
More specifically, the function gtk_container_focus_sort_left_right() and any local functions that it depends on. This includes the GCompareFunc left_right_compare() and get_allocation_coords().
Assuming the directions you care about are "Forward" and "Backward", it sounds like you want to use gtk_container_get_focus_chain() on the frame: it does pretty much what it says on the tin: you get a list of widgets in order of focus when tabbing.

Add droppable element with Mootools' drag&drop

here's my problem, I'm using mootools' Drag&Drop functionalities, it works great but i can't find a way to add new droppable element on the fly since the droppable element are defined when the draggables are.
Their is a method makedraggable that you can use to add draggable element but it has no equivalent for the droppables.
With jQuery, you set the draggable elements on one side and the droppable on the other, so you can do pretty much what you want.
Do you know a way to solve my problem?
in theory, you should be able to push elements to the instance.droppables collection.
var foo = new Drag.Move({
droppables: document.getElements('div.dropHere'),
...
});
foo.droppables.push(document.id('newDropHere'));
// or...
foo.droppables.include(element); // etc. all array/Elements methods.
read https://github.com/mootools/mootools-more/blob/master/Source/Drag/Drag.Move.js
if you want actual help, build an example on tinker.io or jsfiddle.net. if memory serves, this has been asked here before and there had to be some extra work around parsing possible droppables in addition to adding to the Collection.

Using i18n .properties-defined maps in a UiBinder template

Suppose I have a <String,String> map defined in my i18n .properties files, e.g.:
userGroupMap = 0, 1, 2, 3
0=Factory
1=Administrators
2=Superusers
3=Operators
The dev guide explains that introducing a corresponding Map<String,String> userGroupMap() method in MyConstants implements Constants interface will result in calls such as MyConstants.userGroupMap().get("1") returning the localized "Administrators". So far so good.
What about UiBinder? How do I use one of the mapped values in a UiBinder template? Is there a syntax I'm missing, e.g. <ui:msg key="userGroupMap:1">Administrators</ui:msg> (doesn't actually work)?
One way you could do this would be a non-xml solution, but you could use a #UiFactory to help with the creation of the specific fields or labels that you need I18N'd. But to me, this particular problems seems like it begs the solution below, since you seem to be looking to decouple your widgets from your screen or panel layouts.
I struggled with this, and for my implementation, I ended up making core widgets with UiBinder backing for their internals(for instance a label and a text field with a help button), and then passing in a 'fieldKey' that was used as a prepender for all the I18N keys in the various maps.
For instance, for the PartNumber field, I had a key in the following maps: labelTexts(), helpTexts(), tooltipTexts(), defaultFieldValues(). Then in the constructor for that widget, I would pass in the string key 'partNumber', and that would be used to build up all the keys needed, so I would call labelTexts().get('partNumberLabelText'), helpTexts().get('partNumberHelpText'), etc.
I didn't want to do this directly in UiBinder, since I wanted the widget key to map back to it's display information, so I could create a widget with as little input information as possible, in many cases just the key and then the widget (provided it was configured in the I18N setup correctly) would just populate everything from the maps based on that.
From a design standpoint, for me it didn't make sense to have separate UiBinders for the screen sets, they were composited from objects that defined the screen layout and relation of all the widgets (meaning that you could define screen content at runtime).

CellTree suggestion - AsyncDataProvider add/remove/update

I have issues with GWT CellTree and at this point, I'm wondering if it's really ready for prime time. Maybe I'm not getting the default use-cases??
Most questions that have seen over the Web so far are related to CRUD operations with a CellTree but using a simple ListDataProvider such as GWT - Add and remove nodes in celltree.
In my case, I'm populating the nodes of a CellTree using an AsyncDataProvider.
The nodes are fetched on-demand using a RequestFactory service.
Given a selection, I would like to add child nodes, remove/update the current selection. The GWT TreeViewModel interface is way too basic in my opinion.
From my current understanding, the way to go would be to use a map of DataProviders, keep a reference of the underlying list returned by the remote call and likely a reference to the parent NodeInfo object.
For example to delete the current selection I'd probably do the following:
TreeViewModel model = cellTree.getTreeViewModel();
TreeViewModel.NodeInfo nodeInfo = model.getNodeInfo(selectionFromChangeListener);
CustomNodeInfo parent = ((CustomNodeInfo) nodeInfo).getParent();
parent.getUnderLyingNodeListFromDataProvider().remove(selectionFromChangeListener);
// maybe force refresh using dataProvider???
parent.getDataProvider().refreshDisplayAsInRepopulateData()
Any better suggestion? It looks like it's going to be a challenging task, unless I'm mistaken... It seems a bit overkill though. In Swing it would be very easy to achieve or even in most other Web Frameworks providing Tree widgets.
Would using the default Tree widget and replacing myself the icons with the "loading" image be a more straightforward thing? It looks like the basic Tree allows way more manipulations of nodes as TreeItems.
The CellTree widget seems to be based on the original code of FastTree.
The FastTree already have more or less what I need, without some kind of setUserObject method as in a Swing DefaultMutableTreeNode
For spinning icons, someone already investigated it in the past.
I guess that for now, I'll switch from CellTree to a customized version of FastTree and FastTreeItem.
Out of the box ability to have methods such as getParentItem, remove(current node or specific child node)?? Thank you very much sir...