How to properly populate/navigate this tree structure using path strings? - c++

Update:
Turns out I was needlessly complicating things. For the purposes of a context menu, you really only need an arbitrary tree (with a Parent, FirstChild and NextSibling). The best way to visualize a tree for a context menu is just like any other tree, but branching out horizontally instead of vertically. There's never really any need to be able to walk the tree in 4 different directions (Up, Down, Left and Right), because all of the information you need is already there with Parent, FirstChild and NextSibling (all of which is fairly easy to determine if you already have a list of path strings).
This thread can safely be closed.
I'm not using XPath or any web or DOM-related libraries, but I would like to utilize an XPath-style means of populating the contents of a context menu widget:
struct ContextMenuNode
{
ContextMenuNode* Left; // Parent Menu
ContextMenuNode* Right; // Sub Menu
ContextMenuNode* Up; // Previous Sibling
ContextMenuNode* Down; // Next Sibling
FString Path; // An XPath-like string
FString Caption; // Display text of this menu item
}
What I would like to do is something like this:
// Defined in a class declaration:
TArray<ContextMenuNode*> MenuNodes;
// ...
/* This should create 2 unique nodes ("/File" doesn't exist yet within MenuNodes),
establish Left & Right relationships between them, and
return the newly created "/File/Open" node,
adding both nodes into MenuNodes
*/
auto openFileNode = AddNode("/File/Open");
/* Much like the previous line, this should
create 1 unique node (since "/File" should already exist from the previous call),
Left should be "/File", Up should be "/File/Open".
But also, we need to update THOSE nodes in relation to this node now...
Both "/File/Open" and "/File/Save" are Up/Down siblings with the same Left ("/File")
*/
auto saveFileNode = AddNode("/File/Save");
How can this be achieved, or is there simply a better way of going about this?
Useful links for those who are unfamiliar with UE4:
FString: https://api.unrealengine.com/INT/API/Runtime/Core/Containers/FString/index.html
TArray: http://api.unrealengine.com/INT/API/Runtime/Core/Containers/TArray/index.html

Related

MFC How to make ctreectrl virtual?

My application is displaying a Hugh amount of files system entries held in memory using a ctreectrl , adding all the items takes ~20seconds even when using SetRedraw(False) , so how to make a completely virtual(breadth,depth) ctreectrl & how to populate it ?
Edit#1
I want to display the displayed portion items expanded from the beginning , but I don't want to store them in the tree, for example
Root-->
Child1-->
SubChile1
Child2
Child3
you must not add all items at once. you must add only top level items with cChildren = I_CHILDRENCALLBACK
and handle WM_NOTIFY
with code == TVN_GETDISPINFO if mask & TVIF_CHILDREN set
cChildren (TRUE or FALSE)
with code == TVN_ITEMEXPANDING, action == TVE_EXPAND - expand
node - add only direct child items (one level) again with
cChildren = I_CHILDRENCALLBACK
and possible
with code == TVN_ITEMEXPANDED, action == TVE_COLLAPSE - collapse
node - remove all childs
sense of cChildren = I_CHILDRENCALLBACK - if you add folder to list, you not need at once initialize it (open handle, enum childs) - only when you first time got I_CHILDRENCALLBACK (this when your item become visible, but if containing folder large enough(like system32) - it have too many items, but visible only several top at begin, new begin visible when user scroll down)- open folder, determinate are it have subitems (and based on this set cChildren) but not full enumerate it (do this only on <TVN_ITEMEXPANDING, TVE_EXPAND>
I have no advice to make it virtual.
I use for large tree structures the possibility of collecting a child branch only when it is need. I trap TVN_ITEMEXPANDING
So how to do it: First read the first level (root), than keep all root node collapsed and read all child nodes of the root (just 1 level deep) and populate them.
When a node expands, you already have the nodes, now read the next level below the childs of the expanding node.
So you see only the expanded nodes plus one invisible level.
I do this in this way to show all nodes that are expandable with the + sign. All nodes without children nodes are shown without it as leafs.
The second way is not to fill the string data and let the tree load it via callback. But the impact is small. The real problem with the speed are the number of nodes.

Forcing QGraphicsItem to use z value and ignore the parent child relationship

I have problem using QGraphicsItem class.
There is a base_parent, base_part, part_1, part_2. The base_parent is the parent of the base_part. part_1 and part_2 are children of the base_part. What I want to do is to set the Z value of this items in a way that part_1 and part_2 stack behind the base_parent and the base_part stacks in front of the base_parent. So what I've implemented is something like this:
base_part->setParentItem(base_parent);
part_1->setParentItem(base_part);
part_2->setParentItem(base_part);
At first the tried setting the z value using setZValue() but obviously it didn't work.
base_parent->setZValue(0);
base_part->setZValue(1);
part_1->setZValue(-1);
part_2->setZValue(-2);
In the documentation it is said that:
An item's children are stacked on top of the parent
I was giving up but then I saw another parameter.
You can call setZValue() on an item to explicitly stack it on top of,
or under, other sibling items. The default Z value for an item is 0.
Items with the same Z value are stacked by insertion order.
You can call stackBefore() to reorder the list of children. This will
directly modify the insertion order.
You can set the ItemStacksBehindParent flag to stack a child item
behind its parent.
So I tried setting the ItemStacksBehindParent flag but it moved the stacked the whole child behind, meaning the base_part, part_1 and part_2 were stacked behind the base_parent.
Afterwards I found another flag, ItemNegativeZStacksBehindParent.
The item automatically stacks behind it's parent if it's z-value is negative. This flag enables setZValue() to toggle ItemStacksBehindParent. This flag was introduced in Qt 4.6.
So I tried again:
base_part->setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent);
part_1->setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent);
part_2->setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent);
Using this flag stacks part_1 and part_2 behind the base_part but they are still stack in front of the base_parent.
I want to know if there's a way to force items to use only Z value and ignore the parent child relationship.
The main reason for insisting on hierarchical structure is that I want to animate the base_part and the part_1 and part_2 must move along the base_part, Of course I know my way around this problem, If only I set parent of the part_1 and part_2 to base_parent, I'll be able to get the result I wanted, but then I have to animate part_1 and part_2 as well which is a little nasty.

How to change the selection from one item to the selected item in tree control?

I had a tree control which is being populated some values.And In this few tree nodes consists of
check boxes whereas few doesn't. My problem is Initially when the tree is enumerated the default
selection is on the first root node and this root node consists of three children where each child
consists of check box. Here is my problem exactly is,
Now when I expand the tree and tried to click on the child item which consist of check box(clicking on the check box)
Until the mouse left button down the focus comes to the item we are checking and when the left button click up then
the selection is reverting back to the root item (or to the item which is previously selected).
In order to resolve this this is something I tried,
//TVN_ITEMCHANGED
void CDriverSetupView::OnTvnItemChangedTree(NMHDR *pNMHDR, LRESULT *pResult)
{
NM_TREEVIEW* pNewTreeView = (NM_TREEVIEW*)pNMHDR;
if(NULL != pNewTreeView->itemNew.hItem)
{
m_TreeCtrl.Select(pNewTreeView->itemNew.hItem,TVGN_CARET | TVGN_FIRSTVISIBLE | TVGN_DROPHILITE);
m_TreeCtrl.SelectItem(pNewTreeView->itemNew.hItem);
m_TreeCtrl.SelectDropTarget(pNewTreeView->itemNew.hItem);
}
}
If I am doing like this then I am able to get the selection to whatever the child I am checking everything is cool.
But Initially when launch my application then the tree is is getting expanded and the selection is not on the root item
,it is moving on to the last item .
Please find the below images for better understanding,
When the tree is enumerated without the piece of code in OnTvnItemChangedTree,the tree looks like this,
Now when mouse left button down on the first checkbox the selection seems that it changed to checkbox
item ,
Now when mouse left button up on the checkbox the selection again revert back to the previous node,
Now when I use the piece of code within OnTvnItemChangedTree then I am able to get the selection to the checked node but initially when I launch my application then the tree is getting expanded and the selection is on to the last child item which is as follows,
In the above image I am able to get what I want but the tree is getting expanded and the selection is on to the last item,I know this is because in the pNewTreeView->itemNew.hItem at last after the initialization that item consists handle to the last item ,but how can we make such that initially the tree should not get expanded and selection should properly work when I check on any node then the selection should get changed to the checked item.
Can anyone please let me know how can make the selection to be remained on to the root item and the tree Initial status should
be as not expanded.
I'm probably misunderstanding the question because the solution seems so obvious, but why don't you just collapse the tree and set the focus to the first item when you create it? So after you've added all children?
Finally I solved it .In order to avoid that expand while at the time Initialization and moving the focus from one item to the checked item can be achieved as follows,
For NM_CLICK notification add this piece of code ,which works like charm.
void CMyTreeCtrl::OnNMClickTree(NMHDR *pNMHDR, LRESULT *pResult)
{
if(NULL != pNewTreeView->itemNew.hItem)
{
m_TreeCtrl.Select(pNewTreeView->itemNew.hItem,TVGN_CARET | TVGN_FIRSTVISIBLE | TVGN_DROPHILITE);
m_TreeCtrl.SelectItem(pNewTreeView->itemNew.hItem);
}
}
The only mistake I had done was added this code in OnTvItemChanged Instead I added in OnNMClickTree ,Now finally I achieved what exactly I want.

JavaFX getChildren() List behaviour

Look at the following code:
public static void main(String[] args) {
Group group1 = new Group();
Group group2 = new Group();
Label label = new Label("test");
group1.getChildren().add(label);
group2.getChildren().add(label);
System.out.println("Size group1: " +group1.getChildren().size());
System.out.println("Size group2: " +group2.getChildren().size());
}
If the label gets added to group2 it automatically gets removed from group1. Does anyone know why this is intended?
Until now, I do not need the extra functionality e.g. bounds from the group class and use a simple ArrayList to store the references to the label objects.
From the Node documentation:
A node may occur at most once anywhere in the scene graph.
Specifically, a node must appear no more than once in all of the
following: as the root node of a Scene, the children ObservableList of
a Parent, or as the clip of a Node.
...
If a program adds a child node to a Parent (including Group, Region,
etc) and that node is already a child of a different Parent or the
root of a Scene, the node is automatically (and silently) removed from
its former parent.
...
It is possible to rearrange the structure of the scene graph, for
example, to move a subtree from one location in the scene graph to
another. In order to do this, one would normally remove the subtree
from its old location before inserting it at the new location.
However, the subtree will be automatically removed as described above
if the application doesn't explicitly remove it.
When a Node is added to a Scene, the JavaFX system sets and manages attributes specific to that node at that location in the Scene Graph. One example is the location of the node as determined by a parent layout manager and it's constraints. Another is the css style set inherited from parent nodes. Both of these kinds of data may vary depending on the Node's location in the Scene Graph.
If the system allowed you to also place the same Node at another location in the Scene Graph, it would overwrite system calculated attributes determined for the first location. Everything would become very confused - resulting in programs that are difficult to reason about and possessing subtle bugs.

Need Help writing an undo/redo function for text editor program

I have written a text editor program in C++ that has simple commands: LEFT, RIGHT, HOME, END, BACKSPACE, DELETE, INSERT, and now I need to perform the UNDO and REDO functions. In my program the user must be able to undo no more than the last ten commands. I would like to use a vector implementation to accomplish this, but I have no idea how to set this up. I'm not sure how to store the cursor position and the character into a vector. Can someone offer some help?
#ifndef CURSOR_H
#define CURSOR_H
#include <stdlib.h>
#include <iostream>
template <class Object>
class Cursor;
// Incomplete Declaration
template <class Object>
class CNode
{
public:
CNode( const Object & theElement = Object( ), CNode * n = NULL ) : element( theElement ), next( n ) { }
Object element;
CNode *next;
friend class Cursor<Object>;
};
template <class Object>
class Cursor
{
public:
Cursor( );
bool isEmpty( ) const;
void makeEmpty( );
void left ( );
void right ( );
void del ( ); //This is the delete operation. I named it del instead of delete as delete conflicts with a C++ keyword.
void back ( );
void insert( const Object & x );
void home ( );
void end ( );
void undo ( );
private:
void printText ( ) ;
CNode<Object> *header;
CNode<Object> *cursorPosition;
};
//#include "Cursor.cpp"
#endif
You want to use a deque so that you can add and remove from the front or the back; when adding a command, add it to the back, when undoing remove it from the back, and when you reach 11 commands remove one from the front.
Look at the Memento Design Pattern and also in GOF
It exists for this very specific requirement. You may have to use it in combination with other Design patterns (e.g. Command, Iterator, FlyWeight etc)
Memento Intent
Without violating encapsulation,
capture and externalize an object's
internal state so that the object can
be restored to this state later.
Command Intent
Encapsulate a request
as an object, thereby letting you
parameterize clients with different
requests, queue or log requests, and
support undoable operations.
Some other things to consider:
In general, you do not want to apply undo/redo to cursor movements (i.e. they would have no affect on the limit of ten commands limit). When undoing/redoing a deletion or insertion of text, of course you have to place the cursor in the proper place before performing the operation. If the user is typing a number of characters without performing any cursor movements or corrections (backspace), generally these are treated as a single unit when applying undo/redo.
Congrats on including undo/redo. It's a great feature in any sort of editor. It can get tricky, still. Here are some thoughts for you (all hand-waving, no code).
I recommend learning about the Command Design Pattern. What you want to do is design a 'Command' class, an instance of which can "Do" a single command (like insert the letter 'A'), as well as "Undo" itself.
When the user invokes some command (like to add the letter 'A') you 'new' a Command, define its "Do" to insert 'A', also define its "Undo" to remove A, then add it to the top of your undo list, and then "Do" it.
Don't limit your undos to only 10. Why not make it infinite?
Whatever structure you use to make a list of undoable Commands, the usual behavior is that if you have undo'd to some level, and then begin to edit at that point, then all the redos above the current level should be discarded.
For each operation you want to be able to undo (i.e. presumably insert, backspace and del, but not the cursor movements), we can list the "undo" procedure:
insert -> position the cursor at that character and issue a del
del -> position the cursor at the following character and issue an insert
backspace -> position the cursor at the following character and issue an insert
Unfortunately, your cursors use pointers, and when you undo a delete/backspace the newly allocated CNode may not be at the same address as previously, which could invalidate an earlier undo step trying to use that pointer address. Options include:
some additional data structures to track which pointers have been invalidated in this way, and repopulate them with new values if the corresponding elements are recreated (painful)
find a more deterministic way to find the correct index in the CNode list
an absolute index into the document (but that may be difficult to calculate and slow to move to)
save your cursor movement in your undo history
mixing 10 substantive edits (del, backspace, insert) with an arbitrary number of interspersed cursor movements requires a dynamically sized container, and you'd be carrying quite a bit of "verbose baggage"
you could hang a dynamic list of cursor movements off each element in a fixed-sized list of each substantive edit (not much better though)
(As is, your Cnode list doesn't appear double-linked, so I don't see how you can move left without a very painful reiteration through the "document" from the header element...?)
After sorting out this indexing/cursor-movement issue, you must decide between:
after each operation, use a deque to save the undo information:
struct History
{
an indicator of which operation to undo (e.g. enum Op { left, right, insert, del... })
only for insert operations: an object value
}
then have some on-undo processing function that reads these History records and coordinates the operations they describe, or
when an operation is performed, push a function object onto your deque that encodes the undo and redo operations (in terms of calls to the Cursor object methods), so that actually doing an undo or redo operation just involves executing that object (i.e. the undo/redo operation is a "black box" parcelled up at edit time) / this is more elegant and flexible, but probably less familiar to beginning/intermediate programmers so may be harder to get right. The boost library has good supporting functions for this.
I agree with the others about capturing undoable commands as the "do" command is executed.
I'd also suggest working through the list periodically and combining undo commands.
For example, if your undo commands are:
Delete A, Delete B, Delete C, Left-Cursor, Left-Cursor, Right-Cursor, Left-Cursor.
Convert that to merely,
Delete "ABC", Left-Cursor(2).
That way, when the user does undo actions, they don't see every single keystroke hit. Instead, the undo happens in logical groups.