|SAS/AF Software: Class Dictionary|
|About the Data|
In an organizational chart, each piece of information and its relation to every other piece of information is graphically represented. Every piece of information is a node that has a single parent node (except the root node, which is the top or first node in the tree), and zero or more subordinate nodes or children. A node and all the nodes below it are called a tree.
An organizational chart must be created from a data set or SCL list. Each observation in a data set or sublist in a list represents a node in the tree. The data for the chart tell the organizational chart object where to place each node in the tree. To do this, the data must define a node's position in the tree by providing either
Note: Because the
Organizational Chart class is a legacy class (that
is, one based on Version 6), it does not support table specifications that
exceed 32 characters. This limitation includes both name and associated options.
Include the level number in a data set variable and map that variable to the node variable, LEVEL. For example, the data set in Data Set with Level Number contains the variables NODE and LEVEL. The shaded portion of the output includes notes that explain how the value of LEVEL determines the node's position in the tree:
Data Set with Level Number
NODE LEVEL Node Position USA 1 at the tree root EAST 2 below USA Pat Watson 3 below EAST Miguel Aguero 4 below Pat Watson Fred Wong 3 next to Pat Watson and below EAST WEST 2 below USA and next to EAST Dana Josephs 3 below WEST Brenda Kratka 3 below WEST and next to Dana Josephs
Notice that a child node such as Pat Watson is listed directly after its parent (EAST). Miguel Aguero is a child node of Pat Watson and is listed directly after its parent and before any siblings of the parent, such as Fred Wong.
The mapping list for this data set is
|Node Information||Data Set Variable|
Data set variable that identifies current node. It is not a node variable but a list item that determines hierarchy.
Assigning a level number is the fastest way to build a chart because
the chart does not need to search to find a node's parent.
Include a data set variable that describes the node's parent and map that variable to PARENT_NODE. The data set in Data Set Specifying Parent Node includes the same node data as before (and creates the same chart), but instead of the LEVEL variable the data set contains a variable called FROM that contains the value of the node just above it in the tree (its parent). The exception is the root node, which has no parent so none is specified.
Data Set Specifying Parent Node
TEXT FROM USA EAST USA Pat Watson EAST Miguel Aguero Pat Watson Fred Wong EAST WEST USA Dana Josephs WEST Brenda Kratka WEST
The mapping list for this data set is
|Node Information||Data Set Variable|
Data set variable that identifies parent node. Like CURRENT_NODE it is not a node variable but a list item that determines hierarchy.
The data set in Data Set Specifying Two Text Variables also determines the chart hierarchy by defining the parent node, in this case the manager's employee number. In the data set, each observation represents an employee and includes the employee's number as well as the number of the employee's manager.
Unlike the previous examples, the variables that are displayed as text (TITLE and NAME) are not the same as the variable specifying the current node (EMPNO). It is not necessary to display either PARENT_NODE or CURRENT_NODE.
Data Set Specifying Two Text Variables
TITLE NAME EMPNO MNGRNO President Jean DuBois 0001 . Eastern VP Laura Stoyavich 0002 0001 Western VP Roy Hodges 0005 0001 Publisher Pat Watson 0100 0002 Sales Manager Fred Wong 0200 0002 MIS Manager Dana Josephs 0300 0005 Security Brenda Kratka 0400 0005
The mapping list for this data set is
|Node Information||Data Set Variable|
Assigning the two text items displays the employee's name above the title in each node.
Specifying the parent node is less efficient because the chart searches
the entire tree every time it processes an observation and positions a node.
When populating from a data set, use either the LEVEL node variable or the Parent node and Current node fields in the Mapping List window to indicate the chart hierarchy. (These fields correspond to the PARENT_NODE and CURRENT_NODE mapping list items).
When using a parent-child specification for the data used by the organizational chart, every child node must have a uniquely identified parent. If a child node does not have a unique parent, the resulting organizational chart may not render as intended. In such a situation, there may be more than one possible tree, which requires the organizational chart to select one.
When populating from an SCL list that specifies node variables, use the CHILDREN sublist to specify all the children of a node. This creates the chart hierarchy. For example, this is the contents of an SCL list that produces the same tree as the previous examples:
<listid>(TEXT = "USA" CHILDREN = ((TEXT = "EAST" CHILDREN = ((TEXT = "Pat Watson" CHILDREN = ((TEXT = "Miguel Aguero"))) (TEXT = "Fred Wong"))) (TEXT = "WEST" CHILDREN = ((TEXT = "Dana Josephs") (TEXT = "Brenda Kratka"))))
For an example of populating an organizational chart from an SCL list, see the _repopulate method in this class.
Each node in an organizational chart is a widget that can display text
or an image, or both. In addition, each node can perform actions or run sections
of SCL code when selected.
Every node in an organizational chart has a predefined set of node variables that stores information about the node data it represents and about the node's appearance. Each node in the tree stores information in the variables described in the following table.
|Node Variable Name||Type||Description|
|BACKGROUND_COLOR||C||the node's background color|
|BORDER_COLOR||C||the node's border color|
|CHILDREN||N||a list of the children of a node. Used only by the _repopulate method. The _getChildren method conditionally returns the value of this variable. See the description of these methods for details.|
|CLASS||C||the three- or four-level name of the widget class associated with the node type assigned to the current observation or list item. Used only by the _repopulate method. No Organizational Chart methods return the value of this variable.|
|CVALUE||C||an internal character value assigned to the node. Use the Mapping List window to assign a character data set variable to the CVALUE variable. You can store any text string here.|
|FOREGROUND_COLOR||C||the node's foreground color|
|ID||N||a numeric identification number assigned to the node by the user. Use the Mapping List window to assign a numeric data set variable value to the ID variable.|
|IMAGE||C||the name of an image:
|LEVEL||N||a number indicating the level of the node in the tree|
|LINE_COLOR||C||the color of the line connecting the node to its parent|
|NODEID||N||a unique identification number assigned to the node by the organizational chart object. The user cannot set NODEID.|
|NVALUE||N||an internal numeric value assigned to the node. Use the Mapping List window to assign a numeric data set variable to the NVALUE variable. You can store any number here.|
|OBS||N||the number of the SAS data set observation from which the node was created. The OBS value may not match the true observation number if a WHERE clause was active when the organizational chart read in the data set, or if the node variable OBS is mapped to a different data set variable (not OBS) in the SAS data set.|
|OWNER||N||the numeric identifier of the organizational chart that is automatically passed to the node's _init, _postinit, and _select methods. You can also set this value by calling the _getOwner method after calling CALL SUPER (_SELF_, '_init'). This value cannot be retrieved by any other method.|
|TEXT||C||the text of the node; each line of text is a separate TEXT item|
|TYPE||N||the number of the node type (see Node Types). If not given, the node uses the default node type unless you specify CLASS.|
|WIDGETID||N||the temporary identification number assigned to the node by the frame. WIDGETID cannot be set by the user. Because each node is a widget, it has an object identifier as well as a node identifier. This value changes when you scroll the chart. Do not store this value.|
Organizational Chart methods identify nodes by the numeric node identifier (NODEID) instead of the object identifier (WIDGETID) because during scrolling, the nodes are removed from the frame when they are not visible, rendering the object identifier invalid. However, the organizational chart node identifier is always valid. Therefore, it is best to use only Organizational Chart methods to modify the appearance of a node so that you can scroll a widget off and back onto the display and the widget retains its appearance.
As an alternative, you may subclass a node widget and run other methods
in the node's _init or _postinit method. Then if a node is scrolled out of
viewing area and removed, when it is scrolled back into view, its _init and
_postinit methods run and cause it to reappear.
Nodes are separated into types. Each type has general region and object settings such as region borders, colors, fonts, line widths, and action upon selection. The following table describes the predefined node types.
|Node Type Index||Description||Widget Subclass|
|1||graphics text only (subclass of the Extended Text Entry class)||SASHELP.FSP.ORGTEXT.CLASS|
|2||images only (subclass of the Image class)||SASHELP.FSP.ORGIMAG.CLASS|
|3||images with text (subclass of the Image Icon class)||SASHELP.FSP.ORGIMGI.CLASS|
The general settings of these types can be changed, but the widget class, node type number, and description cannot be changed. You can create new node types with different colors, fonts, region borders, and so on. from the same widget class. Specify new node types in the Attributes window.
Because general node characteristics are specified in the Attributes window, several different node types can be of the same class, but you can change the default images, fonts, colors, and so forth by the numeric node type without creating more classes. To create a new node widget class, subclass one of the three predefined widget classes mentioned in the Node Types or create an entirely new widget class. For more information on subclassing, see Creating a New Node Type.
The three predefined organizational chart widget classes only override the _init and _binit methods of the base SASHELP.FSP.WIDGET classes they were derived from. In addition, they each define a _setFcolor method the Organizational Chart class calls to set the foreground color of a widget. For graphics text objects (node type 1) and image icons (node type 3), this method sets text color. For image objects (node type 2), _setFcolor has no effect.
The nodes in a chart can be different types, and nodes can be created from any of the following:
|Creating a Sample Organizational Chart|
Two sample data sets are provided with the class and can be selected from the Data set field of the Attributes window. To create and test an organizational chart from one of the sample data sets, follow these steps:
Selected instance variables that can be used with an organizational chart widget are described here. Instance variables are typically modified with methods or through the Attributes window. For more information on instance variables, see SAS/AF online help.
You can use the appropriate GETNITEMx() function to retrieve these values from the organizational chart widget identifier. If you set these instance variables with the appropriate SETNITEMx() function, you should make this method call:
call send (orgid, '_set_option_', 'iv_changed');
This statement notifies the organizational chart that one or more instance variables were set directly by the user.
For an example of using instance variables to control the run-time menu, see Controlling the Pop-up Menu with Instance Variables.
The character values for the mapping list items are the data set variable names that specify that particular attribute. For example, an item named TEXT with a value of OFFICE means the values in the data set variable OFFICE specify the text to display for each node.
If PARENT_NODE is not in the list, or is blank, you must map the CURRENT_NODE variable to the node level number as well as the LEVEL variable.
You do not have to specify all mapping list variables. The simplest mapping lists would specify TEXT and CURRENT_NODE if level numbers are used, or TEXT, CURRENT_NODE, and PARENT_NODE if level numbers are not used. For examples, see About the Data.
The PARENT_NODE and the CURRENT_NODE must map to the same variable type. That is, both must be numeric, or both must be character.
For example, specify "Print..." to gray that menu item. Set this list during the PREPOP label/method. An item that does not exist in the menu is ignored. See also the PREPOP instance variable.
You may add selections onto the end of the menu by defining an SCL list of options and assigning the instance variable POPMENU_LIST to that list.
|Specifying Images for Nodes|
When you use a node type that includes an image, you can choose whether the nodes display a standard image (the same image for every node of that type) or a custom image (the image depends on the content of the node).
If you want every node of a particular type to display the same image, assign the image in the Text and Image window. In this case you explicitly name the image using either the path name of an external file or the name of an IMAGE catalog entry.
If you want every node of a particular type to display a different image whose name is specified in a variable in the data set that populates the chart, you can do it in two ways:
If you want to assign a default image to display if the image in the data set is missing, specify that image in the Text and Image window and set Node Image Names to Override Name.
For example, suppose you are populating a chart using both a data set of employee information and a catalog of employee photographs. The data set includes the employee identification number which is also used as the name of the catalog entry containing the employee's photograph.
To use a prefix, in the Name field of the Text and Image window, specify the library and catalog containing the photographs and set Node Image Names to Append to Name. In the Mapping List window map the data set variable, for example EMPNUM, to the node variable IMAGE.
Using a mask is similar except that instead of specifying a prefix,
you specify the complete location using an asterisk (*) where the value of
the data set variable should be substituted. For example, if the employee
photographs are stored in a UNIX environment in a directory with filenames
using the pattern
xxxx is the employee number, you could specify a pathname such as
Node Image Names to
Override Name, and map EMPNUM to IMAGE. When the chart is populated,
the employee number is inserted into the mask to build the correct pathname.
|Creating a New Node Type|
If you subclass one of the predefined node types to create a new widget class, you need to override the default _init and _binit methods and initialize the widget yourself from information passed to you from the organizational chart object. You may also override the default _select method to have whatever you want happen upon node selection.
In the _init method for your own defined class, the instance variable NODEDATA is passed to you from the _SELF_ list. NODEDATA is a list containing the information the organizational chart object has about the node it received at population time. This list is only valid during the _init and _binit methods. The format of the list is the same as the format of the returned list in the _getChildren method. The only difference is that the list items WIDGETID and CHILDREN are omitted.
It is up to you to set the proper instance variables for that widget class and perform a CALL SUPER method call if needed. If you subclass an Organizational Chart class and you do not wish the organizational chart to override your initialization settings during the CALL SUPER, you can set the numeric instance variable INITED to 1 on the NODEDATA list before calling CALL SUPER.
This is an example of the _init method for a user-defined widget class that will be used as a node. This code performs self initialization before CALL SUPER:
INIT: METHOD; ndinfo = getniteml(_self_,'_nodedata'); text = getnitemc(ndinfo,'text'); value = getnitemn(ndinfo,'nvalue'); rc = setnitemc(_self_,text, 'mytext'); rc = setnitemn(_self_,value,'myvalue'); rc = setnitemn(ndinfo,1,'inited'); call super(_self_,_method_); ENDMETHOD;
The instance variable named _nodeid can be accessed in the SELECT label or SELECT METHOD for that widget and used for any appropriate Organizational Chart class methods you wish to call. This is true no matter what widget class you are using.
|Controlling the Pop-up Menu with Instance Variables|
This example shows how you can customize the run-time pop-up menu by adding items or graying items. It shows how to do this without having to subclass the organizational chart or node classes, and without having to create additional SCL programs to handle pop-up menu methods.
In addition, it shows how to use the _snapshot method (Widget class) to take a "picture" of the organizational chart and save it as an IMAGE catalog entry (see the POSTPOPL label in the example). The saved image can then be displayed with the Image or Image Icon class in any Frame. You can also change the size of the image when it is displayed with these classes.
Other features of the program include
This is how the program works. When the user opens the run-time
menu, the organizational chart object first looks to see if the application
specifies a PREPOP label or method. If so, the object runs that label to see
if the application wants to gray or add anything to the menu. In this case,
it adds two items:
Then it tests to see if the user clicked on a node. If so, it grays
out the application-defined item
Edit by making it INACTIVE.
It also grays out the default menu
Attribute by putting it
on a 'graylist'.
If the user makes a menu selection that is defined by the application,
the POSTPOPL section runs. In this program POSTPOPL defines the action to
take when the user selects either
Take snapshot. If the selection is not an application defined item, the POSTPOPL
section does not run.
/* Get the widget ID for the chart and tell */ /* the object to run PREPOP and POSTPOP sections. */ /* Create the lists. */ INIT: call send(_frame_,"_getWidget", "ORGCHART",orgid); rc = setnitemc(orgid,"PREPOPL, "PREPOP"); rc = setnitemc(orgid,"POSTPOPL, "POSTPOP"); graylist = makelist(0); popmlist = makelist(0); return; /* After the program has run, free the lists. */ TERM: rc = dellist(graylist,"Y"); rc = dellist(popmlist,"Y"); rc = setniteml(orgid,0, "POPMENU_GRAYLIST"); rc = setniteml(orgid,0, "POPMENU_LIST"); return; /* When the menu is opened, add two items to the menu. */ PREPOPL: rc = clearlist(graylist,"Y"); rc = clearlist(popmlist,"Y"); rc = insertc(popmlist,"Take snapshot",-1); rc = insertc(popmlist,"Edit...",-1); /* Test if the cursor was over a node when */ /* the user clicked to open the menu. */ popid = getnitemn(orgid,"_popid",1,1,0); /* If not on a node, gray the application-defined 'Edit...' */ /* menu item and the default 'Attributes' menu item. */ if (popid eq 0) then rc = setlattr(popmlist,"INACTIVE", -1); rc = insertc(graylist,"Attributes...", -1); rc = setniteml(orgid,graylist, "POPMENU_GRAYLIST"); rc = setniteml(orgid,popmlist, "POPMENU_LIST"); return; /* If the user selected one of the items defined */ /* in PREPOPL, this section runs. */ POSTPOPL: item = getnitemn(orgid,"POPMENU_ITEM"); select (item); when (1); /* SNAPSHOT */ fname = "WORK.A.SNAPSHOT.IMAGE"; imgdatid = instance(loadclass("SASHELP. FSP.IMGDAT.CLASS")); call send(orgid,"_snapshot",imgdatid, rc,"MAIN"); call send(imgdatid,"_writeCatalog", fname); call send(imgdatid,"_term"); _msg = "NOTE: Snapshot saved as " || fname; when (2); /* EDIT */ call display("MYEDITOR.FRAME", orgid,popid); end; /* select */ return;
Top of Page
Copyright 1999 by SAS Institute Inc., Cary, NC, USA. All rights reserved.