Kendo TreeView: How to set Intermediate state Programmatically - angularjs

I am trying to use Kendo TreeView with other controls. Each of the leaf node on tree opens a detail pane. When I select all the elements from detail pane, I set the state of that node as Checked
myTree.dataItem(node).set("checked", true);
and when all the items are un-selected, I set the state of node as unchecked.
myTree.dataItem(node).set("checked", false);
but if some of the items are selected, I want to show the state of node as Intermediate
how can I do that. I cant find anything in the documentation that can help me. The closest thing I found is
myTree.updateIndeterminate()
however, it is not doing the job. Apparently, it sets the state based on the state of child nodes. but in my case, there are no child nodes. I am dealing with leaf nodes here. Can I set the state of a leaf node as Intermediate ? if yes, how?

Couldn't find any help on this.
Ended up using the following approach
I am now finding the checkbox associated with that particular node and setting it's indeterminate value using jQuery.
function SetTreeNodeIndeterminate(nodeId, set) {
var uid = $("#" + nodeId).parents('li').attr('data-uid');
var node = myTree.findByUid(uid);
if (node.length == 0) return;
var checkBox = $("#_" + uid);
if (checkBox.length == 0) return;
checkBox.prop('indeterminate', set);
updateParentNodeState(node);
}
the following line makes sure that all the parents of a node are also marked as indeterminate
function updateParentNodeState(node) {
myTree.updateIndeterminate(node);
let parentNode = myTree.parent(node);
if (parentNode.length > 0)
updateParentNodeState(parentNode);
}

Related

How to get data from an upstream node in maya?

I have a maya node myNode, which creates a shadeNode, which inMesh attribute is connected to shapeNode.outMesh and has an attribute distance.
myNode.outMesh -> shapeNode.inMesh
myNode.distance = 10
Then i have a command, which works on the shape node, but requires the distance argument, which it does by iterating over the inMesh connections:
MPlugArray meshConnections;
MPlug inMeshPlug = depNodeFn.findPlug("inMesh");
inMeshPlug.connectedTo(meshConnections, true, false); // in connections
bool node_found = false;
for(uint i = 0; i < numConnections; i++) {
MPlug remotePlug = meshConnections[i];
myNode = remotePlug.node();
if(MFnDependencyNode(myNode ).typeName() == "myNode") {
node_found = true;
break;
}
}
MFnDependencyNode myDepNode(myNode);
MPlug distancePlug = myDepNode.findPlug("distance");
Now i get a problem, when applying another node (of another type) to myShape, because the dependency graph now looks like this:
myNode.outMesh -> myOtherNode.inMesh
myOtherNode.outMesh -> shapeNode.inMesh
myNode.distance = 10
I tried to remove the check for typeName() == "myNode", because i understood the documentation like there should be recursion to the parent node, when the next node return Mstatus::kInvalidParameter for the unknown MPlug, but i cannot reach the distance plug without implementing further graph traversion.
What is the correct way to reliably find an attribute of a parent node, even when some other nodes were added in between?
The command itself should use the distance Plug to either connect to myNode or to some plug which gets the value recursively. If possible i do not want to change myOtherNode to have a distance plug and correspondig connections for forwarding the data.
The usual Maya workflow would be to make the node operate in isolation -- it should not require any knowledge of the graph structure which surrounds it, it just reacts to changes in inputs and emits new data from its outputs. The node needs to work properly if a user manually unhooks the inputs and then manually reconnects them to other objects -- you can't know, for example, that some tool won't insert a deformer upstream of your node changing the graph layout that was there when the node was first created.
You also don't want to pass data around outside the dag graph -- if the data needs to be updated you'll want to pass it as a connection. Otherwise you won't be able to reproduce the scene from the graph alone. You want to make sure that the graph can only ever produce an unambiguous result.
When you do have to do DAG manipulations -- like setting up a network of connectiosn -- put them into an MPXCommand or a mel/python script.
I found the answer in an answer (python code) to the question how to get all nodes in the graph. My code to find the node in the MPxCommand now looks like this:
MPlugArray meshConnections;
MPlug inMeshPlug = depNodeFn.findPlug("inMesh");
MItDependencyGraph depGraphIt(inMeshPlug, MFn::kInvalid, MItDependencyGraph::Direction::kUpstream);
bool offset_mesh_node_found = false;
while(!depGraphIt.isDone()) {
myNode = depGraphIt.currentItem();
if(MFnDependencyNode(myNode).typeName() == "myNode") {
offset_mesh_node_found = true;
break;
}
depGraphIt.next();
}
The MItDependencyGraph can traverse the graph in upstream or downstream direction either starting from an object or a plug. Here i just search for the first instance of myNode, as I assume there will only be one in my use case. It then connects the distance MPlug in the graph, which still works when more mesh transforms are inserted.
The MItDependencyGraph object allows to filter for node ids, but only the numeric node ids not node names. I probably add a filter later, when I have unique maya ids assigned in all plugins.

How to capture which treeview node is clicked

I created a tree view controls using WinApi. I want to capture mouse click on checkboxes. The notification message NM_CLICK contains NMHDR, which has no information about the node being clicked. since the clicked node may be different from the selected node, there should be a way to find which node has been checked or unchecked, It could be HTREEITEM, or lParam Inserted when adding items to tree view. I want to capture the checking/unchecking in real time. How can I specify which Node being checked/unchecked? any help or link appreciated.
mr.abzadeh
I want to capture the checking/unchecking in real time. How can I
specify which Node being checked/unchecked?
for this exist notification TVN_ITEMCHANGING and TVN_ITEMCHANGED - look for uStateNew and uStateOld members of NMTVITEMCHANGE - when tree view have checkboxes (TVS_CHECKBOXES style) it used as state image list with 2 images - unchecked and checked.
so state & TVIS_STATEIMAGEMASK will be 0 when no checkbox, INDEXTOSTATEIMAGEMASK(1) for unchecked and INDEXTOSTATEIMAGEMASK(2) for checked. based on this info we can and capture mouse click on checkboxes
by using TVN_ITEMCHANGING you can also prevent the change when you return TRUE for this notification. if you need only notify - use TVN_ITEMCHANGED
case WM_NOTIFY:
{
union {
LPARAM lp;
NMTVITEMCHANGE *pnm;
NMHDR* phdr;
};
lp = lParam;
switch (phdr->code)
{
case TVN_ITEMCHANGING:
{
UINT CheckStateOld = pnm->uStateOld & TVIS_STATEIMAGEMASK;
UINT CheckStateNew = pnm->uStateNew & TVIS_STATEIMAGEMASK;
if (CheckStateNew != CheckStateOld)
{
PCSTR szstate = "??";
switch (CheckStateNew)
{
case INDEXTOSTATEIMAGEMASK(1):
szstate = "uncheck";
break;
case INDEXTOSTATEIMAGEMASK(2):
szstate = "check";
break;
}
DbgPrint("%p>%s\n", pnm->lParam, szstate);
}
}
return FALSE;
}
}
also read How to Work With State Image Indexes
// Image 1 in the tree-view check box image list is the unchecked box.
// Image 2 is the checked box.
tvItem.state = INDEXTOSTATEIMAGEMASK((fCheck ? 2 : 1));
notification TVN_ITEMCHANGING and TVN_ITEMCHANGED is available begin from Windows Vista. if you need XP support too - on xp only option use #IInspectable solution
You can send a TVM_HITTEST message (or use the TreeView_HitTest macro) to find the tree view item, given a client-relative coordinate.
To get the cursor position at the time the NM_CLICK message was generated, use the GetMessagePos API.
This allows you do monitor any mouse click in the client area of the control. If you are interested in the state changes as the result of the standard tree view control implementation, you can handle the TVN_ITEMCHANGING or TVN_ITEMCHANGED notifications instead. Both supply an NMTVITEMCHANGE structure, where the hItem identifies the item being changed, and lParam carries application specific data.

Get Current value of a Firebase Node? (Using AngularJS)

Trying to update the information in a node by adding an amount to the current value. I can't find a way to reference the current value so I can add my value. How can you call the current value?
.update({total: "current-value?" + $scope.user.amount}).then(function() {
});
As it looks like you might not be able to pull the current value of a node without using a function, that is what I did:
snap.ref().child('gold/total').transaction(function(currentVal) {
return (currentVal || 0) + $scope.user.amount;
});
The current value of the node is captured with "currentVal", and then it can be passed along so that the addition can be performed.

how to write a recursive function to create a treeview from data in datawindow?

I have a parent-child data in a datawindow from a table mytab(id, pid....)
Then I want to use to data to create a tree in treeview.
I try to use recursive function, but have problem with datawindow as I use filter to change the data in datawindow.
here is my code:
of_addnode(treeviewitem node, rootrow):
int li_rows,li_newitem, i
treeviewitem li_tvitem
dw_1.SetFilter("pid = " + string(node.data))
dw_1.Filter( )
li_rows = dw_1.RowCount()
if li_rows = 0 then
return
end if
for i = 1 to li_rows
li_tvitem.level = node.level +1
li_tvitem.data = dw_1.GetItemNumber(i,"id")
li_tvitem.label = dw_1.GetItemString(i,"description")
li_tvitem.pictureindex = 1
li_tvitem.selectedpictureindex = 2
li_newitem = tv_1.insertitemsort (rootrow, li_tvitem) // insert a new node
of_addnode(li_tvitem,li_newitem)
dw_1.SetFilter("pid = " + string(node.data)) //restore data back to filter, problem here. tree will have duplicate item
dw_1.Filter( )
next
how to create a recursive function from one datasource datawindow for this case?
Here are some ideas... it sounds like you want to use the treeview control and I don't blame you as the treeview dataobject is not very refined because it shows the expand button even if there aren't any children and I haven't found an elegant way to deal with this.
One thing to consider, will manipulating the data on back-end help you? This works for using the treeview dataobject type or might help in making the recursion logic more simple.
This database view is in MySQL but could be developed for other databases. I snipped it at three levels of recursion and yes it was hard coded for six levels of recursion the max supported by this application. This works great if using a treeview dataobject control but you are stuck with the expand button problems when there are no children. This can also be useful for making recursion logic simpler by effectively giving you "path" to the item.
**DATABASE VIEW TO FLATTEN PARENT AND CHILD (HIERARCHY) RELATIONSHIPS **
CREATE
ALGORITHM = UNDEFINED
DEFINER = `root`#`%`
SQL SECURITY DEFINER
VIEW `v_category` AS
select
`t1`.`parent_id` AS `parent1`,
`t1`.`id` AS `id1`,
`t1`.`title` AS `title1`,
`t1`.`sort_order` AS `sort1`,
`t2`.`parent_id` AS `parent2`,
`t2`.`id` AS `id2`,
`t2`.`title` AS `title2`,
`t2`.`sort_order` AS `sort2`,
`t3`.`parent_id` AS `parent3`,
`t3`.`id` AS `id3`,
`t3`.`title` AS `title3`,
`t3`.`sort_order` AS `sort3`
from
(((((`ld_category` `t1`
left join `ld_category` `t2` ON ((`t2`.`parent_id` = `t1`.`id`)))
left join `ld_category` `t3` ON ((`t3`.`parent_id` = `t2`.`id`)))
left join `ld_category` `t4` ON ((`t4`.`parent_id` = `t3`.`id`)))
BUILDING TREEVIEW USING RECURSION
You are on the right track for populating the treeview control but without seeing your dataobject it is impossible to know if your setfilter and filter are working properly and what is going on. The key is to get the level from the insertitemXXX function and pass that into the first argument of the next insertitemXXX function. This simple example of the PB help always gets me on the right track. I see you are using treeviewitems but that doesn't really change things. Hope this helps.
long ll_lev1, ll_lev2, ll_lev3, ll_lev4
int index
ll_lev1 = tv_list.InsertItemLast(0,"Composers",1)
ll_lev2 = tv_list.InsertItemLast(ll_lev1, "Beethoven",2)
ll_lev3 = tv_list.InsertItemLast(ll_lev2, "Symphonies",3)
FOR index = 1 to 9
ll_lev4 = tv_list.InsertItemSort(ll_lev3, "Symphony # " + String(index), 4)
NEXT

Extjs 4.0.7 How do I re render my treepanel to see changes

I am creating an item selector with two boxes that move things back and forth within an extjs application. On the right box, I am creating buttons that serve to move items up and down. Essentially I am swapping the item with one above or below it. So, my code is straight forward in that regard
MoveUp: function(button, event, eOpts){
var theChosen = Ext.getStore('storeId').getRootNode().findChild('text', 'Chosen folder');
var chosenPanel = Ext.ComponenetQuery.query('#chosenTreePanel')[0];
var selected = chosenPanel.getSelectionModel().getSelection();
for( var i = 1; i < theChosen.childNodes.length; i++){
if(Ext.Array.contains(selected, theChosen.childNodes[i]) && (!Ext.Array.contains(selected, theChosen.childNodes[i-1]){
var temp = theChosen.childNodes[i];
theChosen.childNodes[i] = theChosen.childNodes[i-1];
theChosen.childNodes[i-1] = temp;
}
}
}
All of this code seems to work fine, because after clicking my button, and checking the DOM in firebug, I can see that the selected nodes have moved in the array correctly, however, this effect is never shown within my treepanel. ???How do I make the treepanel update when it's elements change. ???
TreePanel heirarchy looks like this just to clarify
Root Node
'Chosen Folder Node'
Array of items I am moving up and down within the 'folder'
I am USING VERSION 4.0.7
Attempting to use replaceChild() to fire an event to rerender does not behave as I expected
Changing:
var temp = theChosen.childNodes[i];
theChosen.childNodes[i] = theChosen.childNodes[i-1];
theChosen.childNodes[i-1] = temp;
To:
var temp = theChosen.childNodes[i];
theChosen.replaceChild(theChosen.childNodes[i-1], theChosen.childNodes[i]);
theChosen.replaceChild(temp, theChosen.childNodes[i-1]);
Results in odd behavior in which some nodes go missing. Certaintly not what I was looking for. Where am I going wrong here?
Tried the following code using the datachanged and (undocumented)refresh event:
Ext.getStore('storeId').fireEvent('datachanged', Ext.getStore('chosen') );
Ext.getStore('storeId').fireEvent('datachanged', Ext.getStore('chosen') );
This does not reload anything...
SOLUTION:
Use the insertChild method of nodeInterface....
I have noticed something strange in how insertChild works in that I need to change my index more based on moving up or down will explain with code below.
To move Up:
theChosen.insertChild( (i-1), theChosen.childNodes[i]);
To move down:
theChosen.insertChild( (i+2), theChosen.childNodes[i]);
Although the -1 vs +2 they both effectively move the item by one in the appropriate direction.
If you want to update the view of the nodes, I recommend using yourTree.getView().refresh();
But you can avoid that by using parentNode.insertChild(index, childNode); where index is where you want the node to show up and parentNode is the parent to the nodes you are reordering. ChildNode can be a config for a new node or any other nodeinterface that already exists. If the node does already exist and you use the insertChild method to insert it, it will automatically remove that node from whereever else it is.
So as you provided in your question in response to my answer, your code will work with something like (this is probably how I'd do it, but this is untested):
MoveUp: function(button, event, eOpts){
var chosenPanel = Ext.ComponenetQuery.query('#chosenTreePanel')[0];
var selectedNodes = chosenPanel.getSelectionModel().getSelection();
for( var i = 0; i < selectedNodes.length; i++){
var currentNode = selectedNodes[i];
if(!currentNode.isFirst())
{
var parentNode = currentNode.parentNode;
var newIndex = parentNode.indexOf(currentNode) - 1;
parentNode.insertChild(newIndex, currentNode);
}
}
}
Edit:
Back to the the responsible event question...
You need to fire the
'datachanged'
'refresh'
Events on the store with the store as only param. That should cause a UI update. But please note that I just had a glimpse into the sourcecode and I am sure this can all be done much smarter. At least a DD solution for this exists already.
If I find some time I my look into this again, but I guess you should be fine with these events for the first.
You never see anything cause you just do it without the appropriate methods that then fire the responsible events that cause rerender. Take a look at
appendChild()
removeChild()
replaceChild()
There may also be more methods that can help on the Ext.data.NodeInterface. I recommend you to use these instead of doing it under hood without any responsible event fired.
In addition to my second comment (just a wild guess without knowing if that is exactly what you want):
MoveUp: function(button, event, eOpts){
var target = Ext.getStore('storeId').getRootNode().findChild('text', 'Chosen folder');
var selected = chosenPanel.getSelectionModel().getSelection();
target.appendChild(selected);
}

Resources