TREEVIEW Widget and OCX Replacement¶
The 4GL doesn't offer a tree control out of the box. There are workarounds employed to overcome this limitation. One solution is to implement a tree view with the primitives native 4GL offers. One of the FWD's customers implemented tree control with pure 4GL and made the code freely available, see Pure 4GL Tree Control. Another solution we have seen at our customers was the use of OCX controls. The commonly used ones are:- Microsoft's TreeView 6.0 from the Windows Common Control library
- dxTreeList by DevExpress
Use the following XML attributes in your *.ext-hints
file:
target-widget="treeview"
at xpath/extension/ocx
forMS TreeView 6.0
target-widget="treelist"
at xpath/extension/ocx
fordxTreeList by DevExpress
TREEVIEW¶
To simplify the modernization of applications that use tree OCX components, which are bound to the Windows OS and can't be easily moved in the web, we implemented a TREEVIEW widget as an extension to the 4GL language. The widget can be used as any other 4GL widget, see below for an example.
DEFINE VAR h AS HANDLE. DEFINE VAR hNode AS HANDLE. DEFINE FRAME f. CREATE TREEVIEW h ASSIGN FRAME = FRAME f:HANDLE WIDTH = 20 HEIGHT = 10 VISIBLE = TRUE. hNode = h:NODES:ADD-LAST-NODE("node 1", "This is a root node"). hNode:NODES:ADD-LAST-NODE("node 2", "This is a child node").
The extension only exists in FWD, it doesn't work in OpenEdge. The API of the TREEVIEW widget was influenced by the Microsoft's TreeView from the Windows Common Control and dxTreeList by DevExpress. This is to make the conversion process more straightforward.
Attributes¶
Attribute Name | Handle Type | Type | Read Only | Default | Description |
---|---|---|---|---|---|
BUILDING-TREE | TREEVIEW | LOGICAL | N | FALSE | When set to TRUE any model changes (nodes added or removed) won't be reflected until the attribute is set back to FALSE. VALUE-CHANGED events won't be triggered until the attribute is set back to FALSE. |
DBL-CLICK-EXPANDING | TREEVIEW | LOGICAL | Y | TRUE | The attribute returns negated value of the EXPAND-ON-SINGLE-CLICK attribute. |
DRAG-DROP | TREEVIEW | LOGICAL | N | FALSE | When set to TRUE the tree nodes can be dragged by the end user. Note that currently this feature is not supported. |
EXPAND-ON-SINGLE-CLICK | TREEVIEW | LOGICAL | N | FALSE | When set to TRUE nodes will be expanded/collapsed on single-click, when FALSE nodes will be expanded/collapsed on double-click. |
FIRST-NODE | TREEVIEW | TREEVIEW-NODE | Y | UNKNOWN | The first node displayed in the tree, or unknown when the there are no nodes in the widget. |
FIRST-VISIBLE-NODE | TREEVIEW | TREEVIEW-NODE | Y | UNKNOWN | The node that is fully displayed as the first node in the current viewport, or unknown when the there are no nodes in the view. |
FOCUSED-AND-SELECTED-NODE | TREEVIEW | TREEVIEW-NODE | Y | UNKNOWN | Returns a handle of the currently focused node or unknown handle when no node is currently focused. The handle will wrap an instance of TREE-VIEW-NODE. Note that the runtime behavior is the same as for the SELECTED-NODE attribute. |
FOCUSED-NODE | TREEVIEW | TREEVIEW-NODE | Y | UNKNOWN | Returns a handle of the currently focused node or unknown handle when no node is currently focused. The handle will wrap an instance of TREE-VIEW-NODE. Note that the runtime behavior is the same as for the SELECTED-NODE attribute. |
FONT-NAME | TREEVIEW | CHARACTER | N | (empty string) | Face name of the optional custom font to use to draw the node texts. |
FONT-SIZE | TREEVIEW | INTEGER | N | 0 | Size of the optional custom font to use to draw the node texts. |
INDENTATION | TREEVIEW | INTEGER | N | 0 | Tree node horizontal indentation size in pixels. The attribute defines the horizontal shift for every node level in respect to the parent level. The returned value is 0 until the widget is realized. |
MULTI-SELECT | TREEVIEW | LOGICAL | N | FALSE | When set to TRUE multiple nodes can be selected at a time. Note that multi-selection is currently not supported. |
NODE-HEIGHT | TREEVIEW | INTEGER | N | 0 | Tree node vertical size in pixels. The returned value is 0 until the widget is realized. Note that currently this feature is not supported. |
NODES | TREEVIEW | TREEVIEW-NODE-COLLECTION | Y | TREEVIEW-NODE-COLLECTION | The root nodes of this TREEVIEW. |
SELECTED-NODE | TREEVIEW | TREEVIEW-NODE | N | UNKNOWN | The tree node to be selected. |
SHOW-BUTTONS | TREEVIEW | LOGICAL | N | TRUE | Set to TRUE to make the node expand icons (+-) visible, FALSE to make the expand icons invisible. |
TEXT-EDIT | TREEVIEW | LOGICAL | N | FALSE | When set to true node text can be edited by the end-user. Note that this feature is currently not supported. |
VISIBLE-NODE-COUNT | TREEVIEW | INTEGER | Y | 0 | This is the total number of expanded nodes in the widget. |
Attribute Name | Handle Type | Type | Read Only | Default | Description |
---|---|---|---|---|---|
EXPAND-NODE-ICON | TREEVIEW-NODE | INTEGER | N | -1 | The attribute holds the id of the image displayed as the expanded icon. The image must be first registered with the call to CREATE-IMAGE or built-in image ids can be used. For more details see CREATE-SUB-NODE. |
NODE-EXPANDED | TREEVIEW-NODE | LOGICAL | N | FALSE | Holds the node's expanded state. |
NODE-ICON | TREEVIEW-NODE | INTEGER | N | -1 | The attribute holds the id of the image displayed as the collapsed (for node with children) or leaf icon (for leaf node). The image must be first registered with the call to CREATE-IMAGE or built-in image ids can be used. For more details see CREATE-SUB-NODE. |
NODE-ID | TREEVIEW-NODE | INTEGER | Y | (unique integer) | Every node is identified with a numeric node id. The id is unique in the scope of the TREEVIEW widget. The id is assigned automatically during node creation. |
NODE-INDEX | TREEVIEW-NODE | INTEGER | Y | (current index) | The attribute holds the index position of the node in its owning node collection (i.e. nodes at one tree level). |
NODE-KEY | TREEVIEW-NODE | CHARACTER | Y | (assigned key) | Every node can also be identified with a textual key. The key is assigned by the caller when node is created. The caller must ensure its uniqueness in the scope of the TREEVIEW widget. |
NODE-PARENT | TREEVIEW-NODE | TREEVIEW-NODE | Y | TREEVIEW-NODE | Every node has an owning parent node. The nodes at the highest tree level have a technical parent, never visible, with NODE-ID equal to 0. |
NODE-TEXT | TREEVIEW-NODE | CHARACTER | N | (assigned text) | The attribute holds the text displayed on the node in the widget. The attribute TREEVIEW:SCREEN-VALUE is assigned to the value of this attribute, when assigned, or to the value of NODE-KEY. |
NODES | TREEVIEW-NODE | TREEVIEW-NODE-COLLECTION | Y | TREEVIEW-NODE-COLLECTION | Child nodes of this node. |
TREE-NODE-VALUE | TREEVIEW-NODE | (poly) | N | UNKNOWN | This attribute can hold an arbitrary value assigned by the application. It has no special meaning to the widget implementation. |
Attribute Name | Handle Type | Type | Read Only | Default | Description |
---|---|---|---|---|---|
NODE-COUNT | TREEVIEW-NODE-COLLECTION | INTEGER | Y | 0 | The number of nodes in the collection. |
Methods¶
Method Name | Handle Type | Return Type | Parameters | Description |
---|---|---|---|---|
CLEAR-ALL | TREEVIEW | VOID | N/A | Unconditionally removes all the nodes from the tree. |
COLLAPSE-NODE | TREEVIEW | VOID | nodeId:INTEGER Id of the node to be collapsed | Collapses a node |
CREATE-IMAGE | TREEVIEW | INTEGER | path:CHARACTER The image file path. Can be an absolute name or relative. When relative the Propath entries will be searched. | Creates an image that can be later used in SET-TREE-NODE-ICONS and CREATE-SUB-NODE. |
CREATE-SUB-NODE | TREEVIEW | INTEGER | parentNodeId:INTEGER Id of the parent node for the newly created node. Use 0 to create a root node. nodeText:CHARACTER The node text. nodeKey:CHARACTER The unique node key for the new node. hasChildren:LOGICAL When set to FALSE the node will be created as a leaf node without any children, use TRUE for nodes that may hold child nodes. collapseIcon:INTEGER Optional collapse image. expandIcon:INTEGER Optional expand image. |
Creates a new node for the supplied parent node. To create a node at the root level set parentNodeId to 0. For the arguments collapseIcon and expandIcon use one of the built-in image ids or an id returned by CREATE-IMAGE. For no image pass unknown or -1. The built-in images are: Id Image 0 Default expanded icon. 1 Default collapsed icon. 2 Default leaf-node icon. |
ENSURE-NODE-VISIBLE | TREEVIEW | VOID | nodeKey:CHARACTER The node to make the top visible. | Makes the supplied node the first visible node (at the top of the view if possible). |
EXPAND-NODE | TREEVIEW | VOID | nodeId:INTEGER Id of the node to be expanded. | Expands a node. |
GET-FIRST-CHILD-NODE | TREEVIEW | VOID | nodeId:INTEGER Id of the parent node. outChildId:INTEGER Upon return will hold id of the found node, unknown if no such node found. outChildKey:CHARACTER Upon return will hold key of the found node, unknown if no such node found. |
Returns the first child node of the specified parent node. |
GET-NEXT-NODE | TREEVIEW | INTEGER | nodeId:INTEGER Id of the node for to start the search. | Returns the next visible node from the specified node. The method recursively traverses the visible and expanded nodes and returns the first node after the specified one or unknown if no such node is found. |
GET-NEXT-SIBLING-NODE | TREEVIEW | VOID | nodeId:INTEGER Id of the node where the search should start. outSiblingId:INTEGER Upon return will hold id of the found node, unknown if no such node found. outSiblingKey:INTEGER Upon return will hold key of the found node, unknown if no such node found. |
Returns the next sibling node of the specified node. |
GET-NODE-AT | TREEVIEW | CHARACTER | x:INTEGER The x pixel coordinate. y:INTEGER The y pixel coordinate. |
Returns key of the node at the specified location relative to the tree's top-left corner. Returns unknown when no node is found. This feature is currently not supported. |
GET-NODE-BGCOLOR | TREEVIEW | INTEGER | nodeId:CHARACTER A valid node id. | Returns background color of the supplied node. Until the widget is realized the method returns undefined value. The returned color value is compatible with the P4GL color binary format, i.e. BGR encoding. |
GET-NODE-LEVEL | TREEVIEW | INTEGER | nodeKey:CHARACTER Node key. | Returns tree level of the specified node. The root nodes are at level 0, children at level 1, etc. When the supplied node key doesn't resolve a valid node the method will return unknown. |
GET-NODE-VISIBLE-IN-VIEWPORT | TREEVIEW | LOGICAL | nodeKey:CHARACTER Node key of the node to check. | The method returns TRUE if the specified node is visible in the current view port. |
GET-PARENT-NODE | TREEVIEW | VOID | nodeId:INTEGER Id of the node where the search should start. outParentId:INTEGER Upon return will hold id of the found node, unknown if no such node found. outParentKey:CHARACTER Upon return will hold key of the found node, unknown if no such node found. |
Returns the parent node of the specified node. |
GET-PREV-SIBLING-NODE | TREEVIEW | VOID | nodeId:INTEGER Id of the node where the search should start. outSiblingId:INTEGER Upon return will hold id of the found node, unknown if no such node found. outSiblingKey:INTEGER Upon return will hold key of the found node, unknown if no such node found. |
Returns the previous sibling node of the specified node. |
GET-SELECTED-NODE-COLORS | TREEVIEW | VOID | outBg:INTEGER The out parameter that will be assigned the background color for selected nodes. outFg:INTEGER The out parameter that will be assigned the foreground color for selected nodes. |
Returns background and foreground colors for selected nodes. Until the widget is realized the method returns undefined value. The returned color value is compatible with the P4GL color binary format, i.e. BGR (blue red green) encoding. |
IS-NODE-EXPANDED | TREEVIEW | LOGICAL | nodeId:INTEGER Id of the node to be checked. | Returns TRUE when the node of the supplied id is expanded. |
REMOVE-NODE | TREEVIEW | VOID | nodeId:INTEGER A node id of the node to be removed. | Removes an existing node from the tree. |
SCROLL-NODE-TO-TOP | TREEVIEW | VOID | nodeKey:CHARACTER The node to make the top visible. | Makes the supplied node the first visible (at the top of the view if possible) node. |
SCROLL-VERTICAL | TREEVIEW | VOID | lines:INTEGER The number of lines to scroll. | Scrolls the tree view the specified number of lines. This feature is currently not implemented. |
SELECT-SET-FIRST-VISIBLE-NODE | TREEVIEW | VOID | nodeId:INTEGER The node to make the top visible. | Makes the supplied node the first visible node (at the top of the view if possible). |
SET-NODE-BGCOLOR | TREEVIEW | VOID | nodeId:INTEGER A valid node id. bgrValue:INTEGER The new color. |
Sets background color for the supplied node. |
SET-SELECTED-NODE-COLORS | TREEVIEW | VOID | bg:INTEGER The new background color. fg:INTEGER The new foreground color. |
Sets background and foreground colors for selected nodes. The expected color format is the P4GL compatible BRG (blue red green) encoding. |
SET-TREE-NODE-ICONS | TREEVIEW | VOID | nodeId:INTEGER Id of the node to modify. icon:INTEGER Id of the image resource to be used as leaf icon (when the node has no children) or collapse icon (when the node has children). The image must be first created with the call to CREATE-IMAGE. expandIcon:INTEGER Id of the image resource to be used as expand icon. The image must be first created with the call to CREATE-IMAGE |
Sets leaf, collapse and expand icons for the specified node. |
Method Name | Handle Type | Return Type | Parameters | Description |
---|---|---|---|---|
ADD-CHILD-NODE | TREEVIEW-NODE-COLLECTION | TREEVIEW-NODE | relativeNode:TREEVIEW-NODE The relative node. key:CHARACTER The key of the new node. text:CHARACTER The text of the new node. |
Creates a new node and inserts it as the last child item relative to the supplied node. |
ADD-FIRST-NODE | TREEVIEW-NODE-COLLECTION | TREEVIEW-NODE | key:CHARACTER The key of the new node. text:CHARACTER The text of the new node. |
Creates a new node and inserts it as the first item in the collection. |
ADD-LAST-NODE | TREEVIEW-NODE-COLLECTION | TREEVIEW-NODE | key:CHARACTER The key of the new node. text:CHARACTER The text of the new node. |
Creates a new node and inserts it as the last item in the collection. |
ADD-NEXT-NODE | TREEVIEW-NODE-COLLECTION | TREEVIEW-NODE | relativeNode:TREEVIEW-NODE The relative node. key:CHARACTER The key of the new node. text:CHARACTER The text of the new node. |
Creates a new node and inserts it as the next item relative to the supplied node. |
CLEAR-NODES | TREEVIEW-NODE-COLLECTION | VOID | N/A | Removes all the nodes from the collections and all the child nodes recursively. |
GET-TREE-NODE | TREEVIEW-NODE-COLLECTION | TREEVIEW-NODE | index:INTEGER A valid index. | Returns the node at the specified index. |
GET-TREE-NODE | TREEVIEW-NODE-COLLECTION | TREEVIEW-NODE | key:CHARACTER A valid node key. | Returns the node of the specified key. |
REMOVE-NODE | TREEVIEW-NODE-COLLECTION | VOID | index:INTEGER A valid index. | Removes the node at the specified index. |
REMOVE-NODE | TREEVIEW-NODE-COLLECTION | VOID | key:CHARACTER A valid node key. | Removes the node of the specified key. |
Events¶
Event Name | Affected Widget | Description |
---|---|---|
DEFAULT-ACTION | TREEVIEW | Triggered when ENTER key is pressed or mouse is double-clicked (or clicked when EXPAND-ON-SINGLE-CLICK set to TRUE) on a leaf node. |
VALUE-CHANGED | TREEVIEW | Triggered when node selection changes. |
Standard 4GL members¶
Besides the members introduced in FWD, the widget also supports the following standard 4GL members. Please consult the official OpenEdge documentation.
BGCOLOR COLUMN FGCOLOR FONT FRAME FRAME-COL FRAME-ROW FRAME-X FRAME-Y HEIGHT-CHARS HEIGHT-PIXELS HELP HIDDEN INSTANTIATING-PROCEDURE LABEL LABEL-FONT LOAD-MOUSE-POINTER MENU-KEY MENU-MOUSE MOUSE-POINTER MOVE-AFTER-TAB MOVE-TO-BOTTOM MOVE-TO-TOP NAME NEXT-SIBLING NEXT-TAB-ITEM PARENT POPUP-MENU PREV-SIBLING PREV-TAB-ITEM PRIVATE-DATA ROW SCREEN-VALUE SENSITIVE SIDE-LABEL-HANDLE TAB-POSITION TAB-STOP TYPE VISIBLE WIDGET-ID WIDTH WIDTH-CHARS WIDTH-PIXELS WINDOW X Y
Examples¶
Create TREEVIEW widget¶
CREATE TREEVIEW hTree ASSIGN FRAME = FRAME f:HANDLE WIDTH = 20 HEIGHT = 10 VISIBLE = TRUE.
Add new nodes¶
hNode = hTree:NODES:ADD-LAST-NODE("node 1", "This is a root node"). hNode:NODES:ADD-LAST-NODE("node 2", "This is a child node"). iNode = hTree:CREATE-SUB-NODE(hNode:NODE-ID, "node 3", "Leaf node at third level", FALSE, ?, ?).
Find a node¶
hNode = hTree:FIND-NODE(iNode).
Remove a node¶
hTree:REMOVE-NODE(hNode:NODE-ID).
Complex example¶
Conversion¶
FWD is capable to automatically convert the usages of DevExpress dxTreeList and Microsoft's Treeview from the Windows Common Controls library. Note that only subset of the dxTreeList and Treeview API is currently supported.
To enable the conversion create the file <procedurefile.p>.ext-hints with the following structure.
<extension> <ocx control-frame="CtrlFrame" control-frame-handle="chCtrlFrame" com-handle="chCtrlFrame:tree" target-handle="hTree" target-widget="treeview" /> </extension>
The xml element ocx defines the CONTROL-FRAME hosting the treeview control (control-frame), the com handle (control-frame-handle) of the control frame,
com handle property (com-handle) for referencing the treeview in the control frame and the handle (target-handle) for the converted treeview widget.
To give an example, the following code sample will convert with the xml configuration given above.
define variable CtrlFrame as widget-handle no-undo. define variable chCtrlFrame as component-handle no-undo. procedure control_load : define variable UIB_S as logical no-undo. define variable OCXFile as character no-undo. OCXFile = search( "tree.wrx":U ). assign chCtrlFrame = CtrlFrame:com-handle UIB_S = chCtrlFrame:LoadControls( OCXFile, "CtrlFrame":U) . end procedure. run control_load. chCtrlFrame:tree:CreateSubNode (...). procedure CtrlFrame.tree.OnClick. ... end procedure.
Pure 4GL Tree Control¶
DON'T USE THIS. This documentation is just being kept around for historical purposes. Trying this approach will be harder to implement/integrate than the FWD TreeView control AND it will be SLOWER.
There is a 4GL-only (no OCX) implementation of tree control written by one of our customers using ADM2 and SDO. It was implemented before we made the TREEVIEW widget available as an 4GL extension. The customer made that code available as a sample and we have integrated it into the Hotel GUI Demo Application. Download the code and use the notes below as a guide to reusing the tree control.
The core tree code can be seen in abl/common/ftreefr0.w
. It relies upon multiple Possenet include files and super procedures.
The expand/collapse icons, the dotted lines for the tree and the tree nodes are drawn using images. The graphics for these can be found in abl/common/graphics/treeview/
.
There is no documentation for this code. The only way to use it is to examine a program where it is used. Please see abl/add-rooms-dialog.w
. In particular, look at PROCEDURE adm-create-objects
and PROCEDURE createObjects
. These handle the initialization. From there you must look deeper in the SDO (abl/roomtypedo.w
) and the ADM2 implementation of ftreefr0.w
itself.
© 2018-2019 Golden Code Development Corporation. ALL RIGHTS RESERVED.