Project

General

Profile

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:
  1. Microsoft's TreeView 6.0 from the Windows Common Control library
  2. dxTreeList by DevExpress

Use the following XML attributes in your *.ext-hints file:

  1. target-widget="treeview" at xpath /extension/ocx for MS TreeView 6.0
  2. target-widget="treelist" at xpath /extension/ocx for dxTreeList 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.

treeview-complex-example.png (27 KB) Hynek Cihlar, 01/04/2019 05:49 PM

treeview-sample-icon4.png (901 Bytes) Hynek Cihlar, 01/07/2019 09:18 AM

treeview-sample-icon3.png (983 Bytes) Hynek Cihlar, 01/07/2019 09:18 AM

treeview-sample-icon2.png (808 Bytes) Hynek Cihlar, 01/07/2019 09:18 AM

treeview-sample-icon1.png (667 Bytes) Hynek Cihlar, 01/07/2019 09:18 AM