GXT re-arrange data array index in TreeStore - gxt

Currently, I'm using gxt 3.0.6
I have a TreeStore let's called it "treeStore", with model data "ParentDto".
private TreeStore<ParentDto> treeStore;
treeStore = new TreeStore<ParentDto>(new ModelKeyProvider<ParentDto>(){
#Override
public String getKey(ParentDto item){
return String.valueOf(item.getParentId());
}
});
Inside ParentDto there is a list of ChildDto. If there is ParentDto data which has list of ChildDto, I want to show it in a tree grid. I use basic tree grid from this link
https://www.sencha.com/examples/#ExamplePlace:basictreegrid
Using that reference, if I try to add 1 ParentDto everything works fine, but when the problem is when I add many Parent Dto.
Here is my code for adding data into the treeStore
public void fillTreeStore(List<ParentDto) listParent){
treeStore.clear();
for(ParentDto parentDto : listParent){
treeStore.add(parentDto);
if(parentDto.getListChild().size() > 0){
for(ChildDto childDto : parent.getListChild()){
treeStore.add(parentDto,childDto);
}
}
}
In my case, I only need 1 level parent and child tree so this code is enough.
I try to debug my code use this expression
treeStore.getAll().get(index);
When I add 1 ParentDto (parentA) which has 1 Child (childA). The result will be
treeStore.getAll().get(0) -> contain parentA
treeStore.getAll().get(1) -> contain childA
But if I add 2 ParentDto (parentA, parentB) and each of them have 1 child (childA,childB). The result will be
treeStore.getAll().get(0) -> contain parentA
treeStore.getAll().get(1) -> contain parentB
treeStore.getAll().get(2) -> contain childA
treeStore.getAll().get(3) -> contain childB
But in the grid, those data will be shown perfectly fine :
row 1 : parentA (this row can expand)
row 2 : childA (the expanded row form parentA)
row 3 : parentB (this row can expand)
row 4 : childB (the expanded row form parentB)
I need to render icon if the data is "parent" so I use this code :
(icon_variable).addBeforeRenderIconCellEventHandler(new BeforeRenderIconCellEventHandler() {
#Override
public void onBeforeRenderIconCell(BeforeRenderIconCellEvent event) {
if(treeStore.getParent(treeStore.get(event.getSelectedRowIndex())) == null){
//#render icon here
}
}
});
The problem is at this code
treeStore.get(event.getSelectedRowIndex())
When parentB is added it will trigger addBeforeRenderIconCellEventHandler method. event.getSelectedRowIndex() will get the row index based on "grid's perspective". At the second row, from grid's perspective (childA), event.getSelectedRowIndex() will return 1. But from "treeStore's perspective", index 1 is "parentB", so my icon render is messed up.
That's why, the result I need in treeStore is like this
treeStore.getAll().get(0) -> contain parentA
treeStore.getAll().get(1) -> contain childA
treeStore.getAll().get(2) -> contain parentB
treeStore.getAll().get(3) -> contain childB
My solution :
To solve this problem, for now, I use 2 Stores, the first one is TreeStore, and the second one is ListStore. Each time parent and child are added, I insert them at TreeStore and ListStore. In the ListStore, I keep parent's and child's index to always match with grid's perspective, so that whenever addBeforeRenderIconCellEventHandler is triggered, I use ListStore to get the data.
In my opinion, this solution is not good enough but because in my case, the maximum data can be added into the store less than 50, it's enough.

It looks like this is default behavior. You didn't say what it is you are trying to do but my guess is you can do it with the methods they provide. I'm guessing you are trying to traverse the tree by looking at the parent and then all of it's children before moving on to the next parent. Something like this would do it.
for (ParentDto parent : treeStore.getRootItems()){
for (ChildDto child : treeStore.getChildren(parent)){
}
}

Related

How do I add map markers to a separate class file?

In android studio I've created a map with hundreds of markers on it. I want to separate these into individual classes and put them in a separate package, so that there isn't one massive list of markers in my main code. Is there a way of doing this? I'm using Kotlin.
so what I think you are trying to say is.
There is an Activity let's say MainActivity and it has maps in it and has let's say some 200 markers on it.
and all are individually initialized and assigned and you want to club them all together so that you'll be able to use them just by searching for one.
if that's the case, what I would suggest is.
make a separate Data Class that stores Marker and other data related to it.
data class MarkerInfo(
//marker ID
val id:Int,
//marker Data
val markerData:Marker,
//other Data
var otherData:String
)
now coming to storing and accessing data.
class MainActivity(){
//at the top level, inside Activity
// This will create an empty list of Marker Info
var markerData = mutableListOf<MarkerInfo>()
//Now take any function, let's say x
private fun x(){
//Mark a Marker on Map and assign it to a variable.
val markerA : Marker = map.addMarker( MarkerOptions.position(somePosition))
//we assign a function with id and other relevant data
val x= markerData.size
//store data in list
markerData.add(MarkerInfo(x, markerA, "This is a very useful marker"))
}
}
//now to access that marker.
//let's say there is a function named y.
private fun y(){
//say we want to access the first marker
//there are two ways to do so.
//first method: you know some data which is already in there let's say we know id
for(i in markerData){
if(i.id == 1){
Log.d("TAG", i.toString())
}
}
//second method: directly
Log.d("TAG",markerData[0].toString())
}

JOOQ: fetchGroups() always returns list with only one element

I'm new to JOOQ and currently fail to map a joined query to Map<K, List<V>>: the list always only contains one element.
Here's my code:
DSL.using(...)
.select(ORDER.fields())
.select(ORDER_ITEM_ARTICLE.fields())
.from(ORDER)
.leftOuterJoin(ORDER_ITEM_ARTICLE).on(ORDER.ID.eq(ORDER_ITEM_ARTICLE.ORDER_ID))
// to Map<InOutOrder, List<OrderItemArticle>>
.fetchGroups(
r -> r.into(ORDER).into(InOutOrder.class),
r -> r.into(ORDER_ITEM_ARTICLE).into(OrderItemArticle.class)
)
// map to InOutOrder
.entrySet().stream().map( e -> {
// e.getValue() always returns list with only 1 element?!
e.getKey().articles = e.getValue();
return e.getKey();
})
.collect(Collectors.toList())
;
Say I have 1 row in ORDER and 2 corresponding rows in ORDER_ITEM_ARTICLE. Running the SQL returned by .getSQL() (after .fetchGroups()), returns me 2 rows as expected, so I assumed the fetchGroups() call will populate my list with two entries as well?!
What am I missing?
Thanks!
Update:
As requested, the InOutOrder class:
public class InOutOrder extends Order {
public List<OrderItemArticle> articles;
public List<OrderItemOther> others;
public List<OrderItemCost> costs;
public List<OrderContact> contacts;
public List<EmailJob> emailJobs;
}
So this is just an extension of the JOOQ POJO class and is used for JSON communication with the API clients...
fetchGroups() simply puts objects in a LinkedHashMap. You have to adhere to the usual Map contract, which means implementing equals() and hashCode(). Without it, each object you're creating (or which jOOQ is creating for you) will use identity comparison, so you get every "value" only once in the result.

Is it possible to use multiple NIBs mixed in a UICollectionView?

I have to create a view such as the iTunes Appstore with 3 different types of blocks: one for an image (ImageBlock), another for a list of object1 (Type1List) and a third for a list of object2 (Type2List).
I have functional MvxCollectionViewCells for all of the three, but I'd need to make an UICollectionView out of these three. I have an list of these lists (Items). A single list (Item) has a value called "type", which is an integer value 1, 2 or 3. I'd have to get this integer value for each Item and determine the NIB I want to use for this specific cell.
//Collection = UICollectionView
//ViewModel.Items = MvxObservableCollection<Item>
public override void ViewDidLoad()
{
base.ViewDidLoad();
var set = this.CreateBindingSet<View, ViewModel>();
// NIBs for types 1, 2 and 3 respectively
Collection.RegisterNibForCell(Type1List.Nib, Type1List.Key);
Collection.RegisterNibForCell(Type2List.Nib, Type2List.Key);
Collection.RegisterNibForCell(ImageBlock.Nib, ImageBlock.Key);
// This shows all items of type 1 correctly, and others using type 1 XIB with no contents
Source = new MvxCollectionViewSource(Collection, Type1List.Key);
// This gives a Null Reference Exception if used in place of the previous one
//Source = new MvxCollectionViewSource(Collection);
set.Bind(Source)
.To(vm => vm.Items);
// This takes the items and calculates the height for Collection in this View
// All types will differ in size
set.Bind(CollectionHeight)
.For(v => v.Constant)
.To(vm => vm.Items)
.WithConversion("IosCollectionHeight", Collection);
Collection.Source = Source;
// Set to 200 for now to see the cells
// TODO: set a working variable size
(Collection.CollectionViewLayout as UICollectionViewFlowLayout).ItemSize = new CoreGraphics.CGSize(UIScreen.MainScreen.Bounds.Width, 200);
//(Collection.CollectionViewLayout as UICollectionViewFlowLayout).EstimatedItemSize = new CoreGraphics.CGSize(UIScreen.MainScreen.Bounds.Width, 100);
set.Apply();
Collection.ReloadData();
}
So I have currently 2 problems:
I don't know how to use different NIBs by type for my UICollectionView
I don't know how to resize cells by type
All three cell NIBs are tested and working as intended, but this CollectionView is problematic.
-Pasketi

Un-nesting nested tuples to single terms

I have written an udf (extends EvalFunc<Tuple>) which has as output tuples with inner tuples (nested).
For example the dump looks like:
(((photo,photos,photo)))
(((wedg,wedge),(audusd,audusd)))
(((quantum,quantum),(mind,mind)))
(((cassi,cassie),(cancion,canciones)))
(((calda,caldas),(nova,novas),(rodada,rodada)))
(((fingerprint,fingerprint),(craft,craft),(easter,easter)))
Now I want to process each of this terms, distinct it and give it an id (RANK). To do this, i need to get rid of the brackets. A simple FLATTENdoes not help in this case.
The final output should be like:
1 photo
2 photos
3 wedg
4 wedge
5 audusd
6 quantum
7 mind
....
My code (not the udf part and not the raw parsing):
tags = FOREACH raw GENERATE FLATTEN(tags) AS tag;
tags_distinct = DISTINCT tags;
tags_sorted = RANK tags_distinct BY tag;
DUMP tags_sorted;
I think your UDF is return is not optimal for your workflow. Instead of returning a tuple with variable number of fields (which are tuples), it would be a lot more convenient to return a bag of tuples.
Instead of
(((wedg,wedge),(audusd,audusd)))
you will have
({(wedg,wedge),(audusd,audusd)})
and you will be able to FLATTEN that bag to:
1. make the DISTINCT
2. RANK the tags
To do so, update your UDF like this :
class MyUDF extends EvalFunc <DataBag> {
#Override
public DataBag exec(Tuple input) throws IOException {
// create DataBag
}
}

Styling NSOutlineView Rows

I have a Document based Core Data app with an NSTreeController supplying the content to a view based NSOutlineView. I am "styling" (setting text colour, background colour etc.) the rows based on persistent "transformable" NSColor and NSFont attributes in my data model which the end use can modify. When a new row is popped up, it displays things with the colours/fonts set in the data model. Here is the delegate/datasource code that sets the row background colour:
- (void) outlineView:(NSOutlineView *)outlineView
didAddRowView:(NSTableRowView *)rowView
forRow:(NSInteger)row
{
// Get the relevant nodeType which contains the attributes
QVItem *aNode = [[outlineView itemAtRow:row] representedObject];
if (aNode.backColor)
{
rowView.backgroundColor = aNode.backColor;
}
}
However when the style attributes change I want the associated visible rows to be redrawn with the new style values. Each time a "style" attribute is changed, I am using NSNotificationCenter to send a notification to the Outline view delegate, with the model object whose row needs to be redrawn with the changed style. This is the code in the delegate that receives the notification.
-(void) styleHasChanged: (NSNotification *)aNotification
{
NSTreeNode *aTreeNode = [myTreeController treeNodeForModelObject:aNotification.object];
[myOutlineView reloadItem:aTreeNode];
}
My assumption here is that I can navigate the tree controller to find the tree node which is representing my model object and then ask the outline view to redraw the row for that tree node. This is the "additions" code in the tree controller which walks the tree to find the object - not super efficient, but I don't think there is another way.
#implementation NSTreeController (QVAdditions)
- (NSTreeNode *)treeNodeForModelObject:(id)aModelObject
{
return [self treeNodeForModelObject:aModelObject inNodes:[[self arrangedObjects] childNodes]];
}
- (NSTreeNode *)treeNodeForModelObject:(id)aModelObject inNodes:(NSArray*)nodes
{
for(NSTreeNode* node in nodes)
{
if([node representedObject] == aModelObject)
return node;
if([[node childNodes] count])
{
NSTreeNode * treeNode = [self treeNodeForModelObject:aModelObject inNodes:[node childNodes]];
return treeNode;
}
}
return nil;
}
So sometimes this works and the row redraws, and sometimes it doesn't. The delegate method "styleHasChanged:" is always called, and the tree controller always returns a corresponding tree node (Actually of a subclass of NSTreeNode). But more often than not the outline view does not recognise the tree node, and the row is not redrawn. Its like the tree controller has given back a different tree node object to the one it gave the outline view in the past. But weirdly sometimes it does work and the right row is redrawn with the new background colour. If I collapse the row out of view and pop it open again, it is redrawn correctly.
Anyone any idea why it works sometimes and not other times?
It would be nice to be able to bind the colour/font attributes to the row and columns in some way, so that the outline view did this styling automatically with KVO, but I don't think that is possible - is it?
You spend hours/days trying to work out what you've done wrong; You write the question out; Post it; Sleep on it; and think how stupid can you be.
So I asked the NSTableRowView to redraw itself, but I had not set the new background colour. So here is the new improved (and works) version of styleHasChanged:
-(void) styleHasChanged: (NSNotification *)aNotification
{
QVItem *modelItem = aNotification.object;
NSTreeNode *aTreeNode = [myTreeController treeNodeForModelObject:modelItem];
NSInteger rowIndex = [myOutlineView rowForItem:aTreeNode];
if !(rowIndex == -1)
{
NSTableRowView *rowViewToBeUpdated = [myOutlineView rowViewAtRow:rowIndex makeIfNecessary:YES];
rowViewToBeUpdated.backgroundColor = modelItem.backColor;
}
}
Duh!

Resources