rexx-things/modules/windows/oodialog/controls/TreeView/treeViewCustomDraw.rex
2025-03-12 20:50:48 +00:00

851 lines
30 KiB
Rexx
Executable File

/*----------------------------------------------------------------------------*/
/* */
/* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
/* Copyright (c) 2005-2014 Rexx Language Association. All rights reserved. */
/* */
/* This program and the accompanying materials are made available under */
/* the terms of the Common Public License v1.0 which accompanies this */
/* distribution. A copy is also available at the following address: */
/* https://www.oorexx.org/license.html */
/* */
/* Redistribution and use in source and binary forms, with or */
/* without modification, are permitted provided that the following */
/* conditions are met: */
/* */
/* Redistributions of source code must retain the above copyright */
/* notice, this list of conditions and the following disclaimer. */
/* Redistributions in binary form must reproduce the above copyright */
/* notice, this list of conditions and the following disclaimer in */
/* the documentation and/or other materials provided with the distribution. */
/* */
/* Neither the name of Rexx Language Association nor the names */
/* of its contributors may be used to endorse or promote products */
/* derived from this software without specific prior written permission. */
/* */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* */
/*----------------------------------------------------------------------------*/
/**
* treeViewCustomDraw.rex
*
* This example demonstrates many of the features of a tree-view control.
* Including, but not limited to: label editing of items, custom draw, using
* image lists to supply the icons for tree-view items, using a custom compare
* function in the Rexx dialog to sort the tree-view items, displaying info
* tips, etc..
*
* Note: this program uses the public routine, locate(), to get the full path
* name to the directory this source code file is located. In places, the
* variable holding this value has been callously abbreviated to 'sd' which
* stands for source directory.
*
*/
-- Get our source code file location.
srcDir = locate()
-- Use the global .constDir for symbolic IDs and turn automatic data
-- detection off.
.application~setDefaults('O', srcDir'rc\treeViewCustomDraw.h', .false)
dlg = .InventoryDlg~new(srcDir"rc\treeViewCustomDraw.rc", IDD_TREE_DLG)
if dlg~initCode = 0 then do
ret = dlg~execute("SHOWTOP")
end
return 0
::requires "ooDialog.cls" -- Require the ooDialog framework.
/*- TreeViewConstants - Class - - - - - - - - - - - - - - - - - - - - - - - - *\
This mixin class defines some constant values and is inherited by the two
dialog classes in this example.
\*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
::class 'TreeViewConstants' mixinclass Object
::attribute BMP_FILE get
sd = locate()
return sd"rc\treeViewCustomDraw.bmp" -- Icons for selected/not-selected items.
::attribute TREE_FILE get
sd = locate()
return sd"treeViewCustomDraw.inp" -- Input file with the items to build the tree.
::attribute ITEM_FILE get
sd = locate()
return sd"treeViewCustomDrawi.inp" -- Input file with dynamically added items.
::constant APPLICATION_TITLE "Crazy Sam's Emporium - Inventory"
::constant UNSELECTED_FOLDER 0 -- Index for the icon of an unselected folder item
::constant SELECTED_FOLDER 1 -- Index for the icon of a selected folder item
::constant UNSELECTED_LEAF 2 -- Index for the icon of an unselected leaf item
::constant SELECTED_LEAF 3 -- Index for the icon of a selected leaf item
/*- InventoryDlg - Class- - - - - - - - - - - - - - - - - - - - - - - - - - - *\
This is the main dialog class for this example. It contains the tree-view
control that the example is all about.
\*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
::class 'InventoryDlg' subclass RcDialog inherit CustomDraw TreeViewConstants
/** isLeafItem() [class method]
*
* The isLeafItem() method provides a convenient way to test if any tree-view
* item is a leaf item rather than a folder item. Leaf items and folder items
* in this example use different icon images, so we just test which icon is set
* for the item.
*/
::method isLeafItem class
use strict arg treeView, item
info. = treeView~itemInfo(item)
return info.!Image == self~UNSELECTED_LEAF
/** init()
*
* Initialization of the Rexx dialog object. We do several things here.
*
* 1.) Initialize the super class. Never invoke any method on a dialog class
* before the super class is initialized.
*
* 2.) So a sanity check to ensure the data files needed can be found.
*
* 3.) Connect the event handlers for the tree-view.
*
* 4.) Create custom colors to draw the individual items in the tree-view.
*
* 5.) Initialize the custom draw interface and register the tree-view control
* to use custom draw.
*/
::method init
expose bkClr oddLevelClr evenLevelClr selectedClr leafClr
use arg rcFile, idDlg
self~init:super(rcFile, idDlg)
if self~initCode <> 0 then return self~initCode
if self~checkForRequiredFiles == .false then do
self~initCode = 17
return self~initCode
end
-- Connect dialog control events to methods in the Rexx dialog.
self~connectTreeViewEvent(IDC_TREE, "EXPANDING", "onExpanding", .true)
self~connectTreeViewEvent(IDC_TREE, "DEFAULTEDIT")
self~connectTreeViewEvent(IDC_TREE, "KEYDOWN", "onKeyDown")
self~connectTreeViewEvent(IDC_TREE, "GETINFOTIP", "onGetInfoTip")
self~connectButtonEvent(IDC_PB_NEW, "CLICKED", "onNewItem")
self~connectButtonEvent(IDC_PB_DELETE, "CLICKED", "onDeleteItem")
self~connectButtonEvent(IDC_PB_SORT, "CLICKED", "onSortChildren")
self~connectButtonEvent(IDC_PB_EXP_ALL, "CLICKED", "onExpandAll")
self~connectButtonEvent(IDC_PB_COL_ALL, "CLICKED", "onCollapseAll")
self~connectButtonEvent(IDC_PB_INFO, "CLICKED", "onItemInfo")
-- Create the custom colors use to draw the tree-view items
bkClr = self~RGB(250, 250, 250)
oddLevelClr = self~RGB( 82, 61, 0)
evenLevelClr = self~RGB( 0, 20, 82)
selectedClr = self~RGB( 82, 0, 20)
leafClr = self~RGB( 0, 82, 20)
-- Initialize the custom draw interface and register the tree-view control
-- to use custom draw.
self~customDraw
self~customDrawControl(IDC_TREE, 'TreeView')
return 0
/** initDialog()
*
* Just as the init() method is for initializing the Rexx dialog object, the
* initDialog() method is used to initialize the underlying Windows dialog.
* Some things, like inserting the items into a tree-view, can only be done
* after the Windows dialog exists. Those types of things are done here.
*/
::method initDialog
expose tv
tv = self~newTreeView("IDC_TREE")
-- Set the image list for the tree-vies
image = .Image~getImage(self~BMP_FILE)
imageList = .ImageList~create(.Size~new(16, 12), 'COLOR8', 5, 2)
if \image~isNull, \imageList~isNull then do
imageList~add(image)
tv~setImageList(imageList, 'NORMAL')
image~release
end
-- Read the file containing the tree input data and build the tree.
do while lines(self~TREE_FILE)
args = self~makeArgs(linein(self~TREE_FILE))
tv~sendWith('add', args)
end
-- Select the item with the text of Computers.
hItem = tv~find('Computers')
if hItem \== 0 then tv~select(hItem)
return 0
/*- - - - - - - - - - Event handler(s) - - - - - - - - - - - - - - - - - - - -*/
/** onCustomDraw()
*
* This is the event handler for the custom draw event. Certain of the dialog
* controls in Windows support custom draw. Those controls send custom draw
* event notifications through out the paint cycle when the control is drawing
* or redrawing itself
*
* Please read the custom draw documentation in the ooDialog reference manual to
* fully understand the details.
*
* We take advantage of custom draw here to paint each individual tree-view item
* a custom color depending on exactly which item is about to be drawn.
*
* Our scheme is relatively simple. Every other level of the tree is painted an
* alternating color. If an item is selected, it is painted a reddish color to
* match the reddish selected icon. If not selected and a leaf node, we paint
* it a greenish color to match the non-folder, non-selected greenish icon.
*/
::method onCustomDraw unguarded
expose tv bkClr oddLevelClr evenLevelClr selectedClr leafClr
use arg tvcds
if tvcds~drawStage == self~CDDS_ITEMPREPAINT then do
tvcds~reply = self~CDRF_NEWFONT
selected = tv~selected
isLeaf = .InventoryDlg~isLeafItem(tv, tvcds~item)
if selected == tvcds~item then do
tvcds~clrText = selectedClr
tvcds~clrTextBk = bkClr
end
else if isLeaf then do
tvcds~clrText = leafClr
tvcds~clrTextBk = bkClr
end
else if tvcds~level // 2 == 1 then do
tvcds~clrText = oddLevelClr
tvcds~clrTextBk = bkClr
end
else do
tvcds~clrText = evenLevelClr
tvcds~clrTextBk = bkClr
end
return .true
end
return .false
/** onExpanding()
*
* This is the event handler for the EXPANDING event. The method is invoked
* when a tree-view item is about to be expanded or collapsed. The method is
* invoked before the item is expanded or collapsed.
*
* This method demonstrates dynamically adding items to the tree. The node,
* 'Special Offers' is initially added to the tree during initDialog with no
* children.
*
* When the user expands the node, the child items for the node are dynamically
* added here. The items are loaded from a file in the same manner as the
* original items are loaded from a file to build the tree.
*
* Note that the fourth argument to connectTreeViewEvent() was used for the
* EXPANDING event and set to true. This causes the interpreter to wait for the
* reply from this event handler, before it replies to the operating system. If
* the interpreter were to not wait for the reply, the tree-view control would
* immediately expand the item before the children were added.
*
* When the user collapses the node, all its children items are removed. This
* is done through the collapseAndReset method, which collapse the item and also
* tells the tree-view control to deallocate the children.
*/
::method onExpanding unguarded
expose tv
use arg tree, item, what, extra
itemInfo. = tv~itemInfo(item)
if itemInfo.!TEXT = "Special Offers" then do
if what == "EXPANDED", tv~child(item) == 0 then do
do while lines(self~ITEM_FILE)
args = self~makeArgs(item, , linein(self~ITEM_FILE))
newItem = tv~sendWith('insert', args)
end
end
else if what == "COLLAPSED", tv~child(item) \== 0 then do
tv~collapseAndReset(item)
end
end
return .true
/** onKeyDown()
*
* This is the event handler for the key down event. It is invoked each time
* the user presses a key when the tree-view has the focus.
*
* We examime the key pressed to see if it is the insert or delete key.
*
* On the insert key we simulate pushing the 'New Item' push button by invoking
* the event handler for that button. This allows the user to add a new tree-
* view item.
*
* On the delete key, we delete the selected item.
*/
::method onKeyDown unguarded
expose tv
use arg treeId, key
if key == .VK~DELETE then
tv~delete(tv~Selected)
else if key == .VK~INSERT then
self~onNewItem
return 0
/** onNewItem()
*
* This is the event handler for the 'New Item' push button. It is invoked when
* the user clicks that button.
*
* We put up a dialog that allows the user to fill out the details for a new
* tree-view item and insert it into the tree-view.
*/
::method onNewItem unguarded
expose tv
sd = locate()
dlg = .NewTreeItemDlg~new(sd"rc\treeViewCustomDraw.rc", IDD_ADD_TREE_ITEM, tv)
dlg~execute
return 0
/** onDeleteItem()
*
* This is the event handler for the 'Delete Item' push button. This method is
* invoked when the user clicks that button.
*
* We expand the selected item and all its children recursively.
*/
::method onDeleteItem unguarded
expose tv
selected = tv~selected
if selected == 0 then do
title = self~APPLICATION_TITLE~subword(1, 3) '- Warning'
msg = "There is no tree-view item selected. If you" || .endOfLine ||-
"continue, all items will be deleted." || .endOfLine~copies(2) ||-
"Do you want to continue and delete all items?"
ret = MessageDialog(msg, self~hwnd, title, 'YESNO', 'WARNING', 'DEFBUTTON2')
if ret == self~IDNO then return 0
end
tv~delete(selected)
return 0
/** onGetInfoTip()
*
* This is the event handler for the INFOTIP event. It is invoked when the
* tree-view wants the text to display in the info tip.
*
* If we return the empty string, then no info tip is displayed. Otherwise, the
* text returned is displayed. Here, we only return text when the itemData is
* the string: '...' In that case we return some text. In all other cases we
* return the empty string and no info tip is displayed.
*/
::method onGetInfoTip unguarded
expose tv
use arg id, hItem, text, maxLen, itemData
if itemData == '...' then return 'There are too many books to list'
else return ''
/** onSortChildre()
*
* This is the event handler for the 'Reverse Sort' push button. This method is
* invoked when the user pushes that button.
*
* Note that the tree-view provides a function to sort the children of an item,
* but it only sorts in ascending alphabetical order of the item text. The
* ooDialog TreeView class provides that function in the sortChildren() method.
*
* To sort in any other order requires using the sortChildrenCB() method. With
* this method, the programmer names a 'call back' method in the Rexx dialog.
* This method is then invoked by the tree-view for each item it needs to
* determine the order of.
*
* This is what we do here, we use the sortChildrenCB method and provide on own
* comparsion method, rexxSort().
*
* We sort the children of the selected item. If no item is selected we sort
* the children of the root item. Note that only the direct children of the
* parent item are sorted. To sort all items, the programmer would need to
* implement a recursive function, similar to the expandAll() or collapseAll()
* functions.
*/
::method onSortChildren unguarded
expose tv
selectedItem = tv~selected
if selectedItem == 0 then selectedItem = tv~root
ret = tv~sortChildrenCB(selectedItem, rexxSort)
/** rexxSort()
*
* This is our comparison callback function. We are passed the user item data
* for the first tree-view item and the user item data for the second tree-view
* item. The method needs to return a positive number if the first item is
* greater than the second, a negative number if the first item is less than the
* second, and 0 if the two items are equivalent.
*
* In this program, for every tree-view item inserted, we set the item data for
* that item to be the text of the item. Then, in our comparison function here,
* we just do a reverse comparison of that text. This orders the items in
* descending order rather than ascending order. The userParam argument is
* ignored here.
*/
::method rexxSort unguarded
use arg itemData1, itemData2, userParam
-- Reverse sort:
return itemData2~compareTo(itemData1)
/** onExpandAll()
*
* This is the event handler for the 'Expand All' push button. This method is
* invoked when the user clicks that button.
*
* We expand the selected item and all its children recursively.
*/
::method onExpandAll unguarded
expose tv
if tv~selected == 0 then do
title = self~APPLICATION_TITLE~subword(1, 3) '- Error'
msg = "There is no tree-view item selected. Before" || .endOfLine ||-
"you can expand all items you must first" || .endOfLine ||-
"select an item"
ret = MessageDialog(msg, self~hwnd, title, 'OK', 'WARNING')
return 0
end
if self~isFullyExpanded(tv~selected) then do
title = self~APPLICATION_TITLE~subword(1, 3) '- Information'
msg = "The selected tree-view item is already fully" || .endOfLine ||-
"expanded. Expanding will take place, but it" || .endOfLine ||-
"have no visile effect."
ret = MessageDialog(msg, self~hwnd, title, 'OK', 'WARNING')
end
self~expandAll(tv~selected)
return 0
/** onCollapseAll()
*
* This is the event handler for the 'Collapse All' push button. This method is
* invoked when the user clicks that button.
*
* We collapse the selected item and all its children recursively.
*/
::method onCollapseAll unguarded
expose tv
if tv~selected == 0 then do
title = self~APPLICATION_TITLE~subword(1, 3) '- Error'
msg = "There is no tree-view item selected. Before" || .endOfLine ||-
"you can collapse all items you must first" || .endOfLine ||-
"select an item"
ret = MessageDialog(msg, self~hwnd, title, 'OK', 'WARNING')
return 0
end
itemInfo. = tv~itemInfo(tv~selected)
if itemInfo.!State~wordPos('EXPANDED') == 0 then do
title = self~APPLICATION_TITLE~subword(1, 3) '- Information'
msg = "The selected tree-view item is already collapsed. You" || .endOfLine || -
"may not see anything, but all children of the selected" || .endOfLine || -
"item will be collapsed."
ret = MessageDialog(msg, self~hwnd, title, 'OK', 'INFORMATION')
end
self~collapseAll(tv~selected)
return 0
/** onItemInfo
*
* This is the event handler for the 'Item Info' push button. It iw invoked
* when the button is clicked.
*
* We get the selected tree-view item and display information about it.
*/
::method onItemInfo unguarded
expose tv
selected = tv~selected
if selected == 0 then do
title = self~APPLICATION_TITLE~subword(1, 3) '- Error'
msg = "There is no tree-view item selected. Before" || .endOfLine ||-
"you can display information on an item you" || .endOfLine ||-
"must first select an item"
ret = MessageDialog(msg, self~hwnd, title, 'OK', 'WARNING')
return 0
end
itemInfo. = tv~itemInfo(selected)
tab1 = '09'x
tab2 = tab1~copies(2)
hasChildren = self~logicalToString(itemInfo.!Children)
title = self~APPLICATION_TITLE~changeStr('-', '') '- Item Information'
msg = 'The Selected Item is:' || tab1 || '"'itemInfo.!Text'"' || .endOfLine~copies(2) || -
' Contains children:' || tab2 || hasChildren || .endOfLine || -
' Unselected icon index:' || tab1 || itemInfo.!Image || .endOfLine || -
' Selected icon index:' || tab2 || itemInfo.!SelectedImage || .endOfLine || -
' Item state:' || tab2 || itemInfo.!State || .endOfLine || -
' Is leaf node:' || tab2 || self~logicalToString(.InventoryDlg~isLeafItem(tv, selected))
ret = MessageDialog(msg, self~hwnd, title 'OK', 'INFORMATION')
return 0
/** help()
*
* The help command event handler is connected automatically by the ooDialog
* framework to the command with ID of 9. The default help event handler
* provided by ooDialog does nothing.
*
* In this example, the Help push button is given the resource ID of 9, and
* therefore the help event handler is invoked when the user clicks on the Help
* button. Rather than do noting when the button is clicked, we over-ride the
* help method here. We still do not do much, just inform the user that there
* is no help.
*/
::method help unguarded
title = self~APPLICATION_TITLE
msg = "There is no help available for this example program."
ret = MessageDialog(msg, self~hwnd, title, "OK", "INFORMATION")
return 0
/*- - - - - - - - - - Helper Methods - - - - - - - - - - - - - - - - - - - - -*/
/** expandAll()
*
* This helper method recursively expands all children nodes of the specified
* tree-view item.
*/
::method expandAll private unguarded
expose tv
use strict arg item
if item == 0 then return 0
tv~expand(item)
nextItem = tv~child(item)
do while nextItem \== 0
self~expandAll(nextItem)
nextItem = tv~next(nextItem)
end
return 0
/** collapseAll()
*
* This helper method recursively collapse the specified tree-view item and all
* its children.
*/
::method collapseAll private unguarded
expose tv
use strict arg item
if item == 0 then return 0
nextItem = tv~child(item)
do while nextItem \== 0
self~collapseAll(nextItem)
nextItem = tv~next(nextItem)
end
tv~collapse(item)
return 0
/** isFullyExpanded()
*
* This helper method checks if the specified item is fully expanded by
* recursively descending though the children of the item and checking that each
* item is expanded.
*
* Returns .true if the item is fully expanded, otherwise .false.
*/
::method isFullyExpanded private unguarded
expose tv
use strict arg item
if item == 0 then return .true
if .InventoryDlg~isLeafItem(tv, item) then return .true
itemInfo. = tv~itemInfo(item)
if itemInfo.!State~wordPos('EXPANDED') == 0 then return .false
nextItem = tv~child(item)
do while nextItem \== 0
if \ self~isFullyExpanded(nextItem) then return .false
nextItem = tv~next(nextItem)
end
return .true
/** checkForRequiredFiles()
*
* This helper method is used to check that the bitmap and input files are
* available. It returns .true if they are found and .false if they are not
* found.
*/
::method checkForRequiredFiles private
haveError = .false
file = ''
if stream(self~BMP_FILE, "C", "QUERY EXISTS") = "" then do
haveError = .true
file = self~BMP_FILE
end
else if stream(self~TREE_FILE, "C", "QUERY EXISTS") = "" then do
haveError = .true
file = self~TREE_FILE
end
else if stream(self~ITEM_FILE, "C", "QUERY EXISTS") = "" then do
haveError = .true
file = self~ITEM_FILE
end
if haveError then do
title = self~APPLICATION_TITLE~subword(1, 3) '- File Error'
msg = "The required data file" file || .endOfLine || -
"does not exist. Without that file, this progam" || .endOfLine || -
"will not run." || .endOfLine~copies(2) || -
"The program will abort."
ret = MessageDialog(msg, 0, title, 'OK', 'ERROR')
end
return \haveError
/** makeArgs()
*
* This helper method turns a line of comma separted values into an argument
* array with empty values turned into empty indexes in the array.
*/
::method makeArgs private unguarded
if arg() == 1 then line = arg(1)
else line = arg(3)
args = line~makeArray(',')
if arg() == 1 then do
newArgs = .array~new(args~items)
do i = 1 to args~items
if args[i]~strip \== "" then newArgs[i] = args[i]~strip('B', '"')
end
end
else do
newArgs = .array~new(args~items + 2)
newArgs[1] = arg(1)
newArgs[2] = 'LAST'
j = 2
do i = 1 to args~items
j += 1
if args[i]~strip \== "" then newArgs[j] = args[i]~strip('B', '"')
end
end
return newArgs
/** logicalToString()
*
* This helper method converts and returns a value to true or false if value is
* a logical, otherwise it returns the empty string.
*/
::method logicalToString private
use strict arg logical
if logical == .true then return 'True'
else if logical == .false then return 'False'
else return ''
/** print()
*
* This helper function is useful in debugging. It prints the label of the
* specified tree-view item to the screen.
*/
::method print private unguarded
expose tv
use strict arg item, indent
itemInfo. = tv~itemInfo(item);
say indent || itemInfo.!Text
return 0
/*- NewTreeItemDlg - Class- - - - - - - - - - - - - - - - - - - - - - - - - - *\
This dialog class allows the user to add a new item to the tree-view
\*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
::class 'NewTreeItemDlg' subclass RcDialog inherit TreeViewConstants
/** init()
*
* The initialization of the Rexx dialog object. We just use this to grab a
* reference to the tree-view control in the parent dialog.
*/
::method init
expose treeControl
use arg scriptFile, dlgID, treeControl
-- Initialize the super class.
self~init:super(scriptFile, dlgID)
/** initDialog()
*
* The initialization of the Windows dialog. We use this to set the state of
* the various controls in the dialog.
*/
::method initDialog
expose treeControl editControl childRB folderChk selected
-- Save a reference to the current selected item
selected = treeControl~selected
editControl = self~newEdit(IDC_EDIT_NAME)
childRB = self~newRadioButton(IDC_RB_CHILD)
siblingRB = self~newRadioButton(IDC_RB_SIBLING)
folderChk = self~newCheckBox(IDC_CHK_FOLDER)
-- If the selected is the root of the tree, a new item has to be inserted as
-- a child. So disable the radio buttons that allow the user to choose to
-- insert as a child or sibling. And, pre-check the add as a folder check
-- box.
if selected == treeControl~root then do
childRB~~check~disable
siblingRB~disable
folderChk~check
end
else if .InventoryDlg~isLeafItem(treeControl, selected) then do
siblingRB~~check~disable
childRB~disable
end
else do
siblingRB~check
end
-- Set a visual cue for the edit control. This will only show when the edit
-- control has no text in it, and does not have the focus.
editControl~setCue("Enter name of new item")
return 0
/** ok()
*
* The is the event handler for the Ok button. It is invoked when the user
* clicks that button.
*
* The ooDialog framework provides a default implementation for this event. It
* is important to always close a dialog, once the underlying Windows dialog has
* been created, through the Ok or Cancel event handlers. This ensures that the
* dialog is ended correctly and that the needed clean up.
*
* Here we over-ride the superclass ok method so that we can check that the user
* entered the correct data for the new item and then insert it into the tree-
* view. If the user did not enter the data correctly, we giver her a chance to
* correct it. We give her a chance to cancel and if she does, we end the
* dialog cancel instead of ok.
*
* Note that we end the dialog by either calling the superclass ok or cancel
* method. We prevent the dialog from closing by *not* invoking one of those
* methods and simply returning.
*/
::method ok
expose treeControl editControl childRB folderChk selected
-- Make sure the user has given the item a name.
text = editControl~getText~strip
if text == "" then do
msg = "You must enter the name of the new item"
title = self~APPLICATION_TITLE~changestr('-', '') '- Add Item'
ret = MessageDialog(msg, self~hwnd, title, 'WARNING', 'OKCANCEL')
if ret == self~IDCANCEL then return self~cancel:super
editControl~assignFocus
return 0
end
-- See if the user wants to add this as a folder item, or a regular item.
-- This will determine the image IDs we use when we insert the item
addAsFolder = folderChk~checked
-- Now insert the item either as a child or a sibling depending on what the
-- user requested. Note that we set the item data on each insert to the text
-- of the inserted item.
if childRB~checked then do
if addAsFolder then newItem = treeControl~insert(selected, , text, self~UNSELECTED_FOLDER, self~SELECTED_FOLDER, , , text)
else newItem = treeControl~insert(selected, , text, self~UNSELECTED_LEAF, self~SELECTED_LEAF, , , text)
treeControl~expand(treeControl~parent(newItem))
end
else do
if addAsFolder then treeControl~insert(treeControl~Parent(selected), , text, self~UNSELECTED_FOLDER, self~SELECTED_FOLDER, , , text)
else treeControl~insert(treeControl~Parent(selected), , text, self~UNSELECTED_LEAF, self~SELECTED_LEAF, , , text)
end
-- Finally, quit by invoking the super class ok() method.
return self~ok:super