David Elliott wrote:
>Thanks to James Hassell, I have made significant progress in my dialog
>programming. However, I am not clear on what can and cannot be done
>in a "heavyweight i-action," it being very much a trial and error
>undertaking. Once can change labels and hide/disable controls. Using
>James's example above once can populate lists in the PREINIT stage of
>dialog creation. What I would like to do is populate a second list
>following user selection of a variable. That list would be populated
>with the results of a levelsof. I have tried to extend James's
>example with a second ado, but I don't seem to be able to change the
>contents of a list class once the dialog box has been created. Am I
>correct in thinking that once a dialog box has been initialized that
>the only changes that can be made are to the interaction with the
>controls themselves, not to the *contents* of the controls?
>
>I see a way around this by creating a new dialog box to create and do
>the picking of levels. This would be similar in function to the ifin
>expression builder dialog. Am I correct in assuming that this would
>be a viable alternative? Are there any caveats?
>
>Many thanks. Although I have thoroughly read the dialog and class
>sections, it is not always obvious how to use them to accomplish
>specific tasks.
Heavyweight i-action's can be used to do many things. Heavyweight means
that the dialog program calls out to Stata's ado engine to perform some
task. That task might be typical ado programming, class system programming
which interacts with a dialog box, or both. For your purposes you will need
an ado program that does both. All objects (controls or properties) that
belong to a dialog have built-in member programs. These member programs
are documented in -help dialog_programming-. These member programs can be
called in dialog programs or scripts (the typical way), or externally by
through the class system using the fully qualified object name and member
program.
Examples:
.mydialog_dlg.mytab.mycontrol.memberProgram
.mydialog_dlg.myStringProperty.setstring "somestring"
Most dialog controls have the following member programs...
hide, show, disable, enable, and setposition.
Some controls allow you to set their label and value using the
setlabel and setvalue member programs respectively. Unfortunately there
is not a built-in member program for the COMBOBOX or LISTBOX controls which
would allow for managing its contents. There are implementation details
which are preventing us from providing such functionally at this time.
However, all is not lost. There is a utility that is part of Stata 9 that
will help David do just what he wants. dynamic_list_control.class is a
helper routine for some of the -irf graph- commands that was built for
managing LISTBOXes and COMBOXBOXes from ado code. I have written an
example which I believe does what David has requested...
/////////////////////// BEGIN d1.dlg //////////////////////////
/*
*! VERSION 1.0.0 14nov2006
*/
VERSION 9
SYNCHRONOUS_ONLY
POSITION . . 400 300
OK ok1, label("OK")
CANCEL can1, label("Cancel")
SUBMIT sub1, label("Submit")
RESET res1
SCRIPT PREINIT
BEGIN
create BOOLEAN isLoading
isLoading.settrue
/* Set true when dialog is loading to block events that
* might be triggered by the initial populating of the
* variable combobox.
*/
program initialize
END
SCRIPT POSTINIT
BEGIN
.isLoading.setfalse
program getLevels
END
DIALOG main, label("Test COMBOBOX control as varlist")
BEGIN
TEXT tx_var 10 10 100 ., ///
label("Variable:") right
COMBOBOX cb_var +105 @ 240 ., ///
dropdownlist contents(variables) ///
onselchange(program getLevels)
TEXT tx_level 10 50 100 ., ///
label("Levels:") right
LISTBOX lb_level +105 @ 100 ., ///
contents(levels)
END
LIST variables
BEGIN
// intentionally empty
// this list will be populated by d1_work.ado
END
LIST levels
BEGIN
// intentionally empty
// this list will be populated by d1_work.ado
END
PROGRAM initialize
BEGIN
put "d1_work Init"
stata hidden
END
PROGRAM getLevels
BEGIN
if main.cb_var & ! isLoading {
put "d1_work GetLevels " main.cb_var
stata hidden
}
END
/////////////////////// END d1.dlg //////////////////////////
////////////////// BEGIN d1_work.ado ////////////////////////
program d1_work
version 9
gettoken subcmd 0 : 0
`subcmd' `0'
end
program Init
syntax [varlist]
unab varlist : `varlist'
if "`varlist'" != "" {
.d1_dlg.variables.Arrdropall
}
foreach v of local varlist {
capture confirm numeric variable `v'
if ! _rc {
.d1_dlg.variables.Arrpush "`v'"
}
}
end
program GetLevels
syntax [varlist]
quietly levelsof `varlist'
local levels `r(levels)'
capture {
/* dynamic_list_control is a helper class
* for managing dynamic list conrols.
*/
.dlist = .dynamic_list_control.new , ///
dialogname(d1) controlname(main.lb_level)
.dlist.setList, newlist(`levels')
}
capture classutil drop .dlist
end
/////////////////// END d1_work.ado /////////////////////////
-- James
*
* For searches and help try:
* http://www.stata.com/support/faqs/res/findit.html
* http://www.stata.com/support/statalist/faq
* http://www.ats.ucla.edu/stat/stata/