The purpose of a property sheet is to enable the user to view and edit the properties of an object subclassed from the IDLitComponent class. (All IDLgr* and IDLit* objects subclass from the IDLitComponent class.)
For example, a user may have rendered data as a surface. Using IDL's iSurface tool, the user can select the surface and bring up a property sheet that lists all of the surface's properties, including color, shading method, etc. To change the color, the user can go to the property sheet, select the color property, bring up the color picker, and select a new color. The name of the changed property is placed into an IDL event. It is in the processing of this event that the object is updated. An existing property sheet can be assigned a new component, which causes it to reload with the new list of properties and their values.
The following topics show how to use the property sheet widget with the iTool's paradigm:
In order for a property associated with a component object to be included in the property sheet for that component, the property must be registered. The property registration mechanism accomplishes several things:
Groups of properties of graphical atomic objects can be registered by setting their REGISTER_PROPERTIES properties to True when the object is initialized. See the property tables for each graphical atomic object in the IDL Reference Guide.
A property sheet consists of rows and columns. The left-most column identifies the properties, and the other column or columns identify the property values of one or more objects (also known as components). A select event is generated whenever a cell containing a property name or a property value is selected by left-clicking on it using the mouse. When a single property value is clicked on, the associated property name appears indented. Only a single property value can be selected at one time. However, when the MULTIPLE_PROPERTIES keyword is set, multiple properties can be selected in a property sheet using the Ctrl key to make nonadjacent selections or using the Shift key to make adjacent selections.
| Note |
When the property sheet is initially realized, no properties are selected by default. However a single property or multiple properties can be selected programmatically using the PROPERTYSHEET_SETSELECTED keyword to the WIDGET_CONTROL procedure.
Set the PROPERTYSHEET_SETSELECTED keyword to a string or an array of strings identifying the properties to appear selected. The strings should match valid property identifiers. When this keyword is set to an empty string or an array that contains only an empty sting, it clears all property selections. For example, the following code pre-selects two properties in a property sheet:
; Create the property sheet.
oComp = OBJ_NEW('IDLitVisAxis')
wPropAxis = WIDGET_PROPERTYSHEET(base, VALUE = oComp, $
EVENT_PRO = 'PropertyEvent', UNAME = 'PropSheet', $
/MULTIPLE_PROPERTIES)
; Pre-select the color and transparency properties of
; axis component.
WIDGET_CONTROL, wPropAxis,
PROPERTYSHEET_SETSELECTED=['Color', 'Transparency']
The event structure (WIDGET_PROPSHEET_SELECT) provided when selection occurs contains a COMPONENT tag, an IDENTIFIER tag, and a NSELECTED tag.
{WIDGET_PROPSHEET_SELECT, ID:0L, TOP:0L, HANDLER:0L, TYPE:0L,
COMPONENT:OBJREF, IDENTIFIER:"", NSELECTED:0L }
The COMPONENT tag is a reference to the object associated with the selected property value. When multiple objects (also known as components) are associated with the property sheet, this member indicates which one object had one of its property values selected. If a property (instead of a property value) is selected, the COMPONENT tag always contains an object reference to the first object, even if there are multiple objects in the property sheet. The IDENTIFIER tag uniquely identifies the property. This identifier is unique among all of the component's properties. The component and identifier can be used to obtain the value of the selected property:
isDefined = event.component-> $ GetPropertyByIdentifier(event.identifier, value)
where event is the event structure, isDefined is a 1 if the value is defined (0, otherwise), and value receives the property's value.
The NSELECTED tag returns the number of currently selected properties. When more than a single property is selected, the IDENTIFIER field holds the identifier of the first item selected. This is not the first item selected with the mouse, but the first item encountered in the property sheet definition among those which are selected. The NSELECTED tag is equivalent to calling WIDGET_INFO with the /PROPERTYSHEET_NSELECTED keyword.
Using WIDGET_INFO, it is also possible to return the identifiers of all selected properties using the /PROPERTYSHEET_SELECTED keyword. This returns a string or string array containing the identifiers of the selected properties.
; Return information about single or multiple property ; selections. vNumSelected = WIDGET_INFO(event.ID, /PROPERTYSHEET_NSELECTED) vSelected = WIDGET_INFO(event.ID, /PROPERTYSHEET_SELECTED) PRINT, 'Number properties selected: ' + STRING(vNumSelected) PRINT, 'Selected properties: ' PRINT, vSelected
Three things that determine the appearance of a property sheet data cells. They are, in order of greatest to least precedence:
A change event is generated whenever a new value is entered for a property. It is also used to signal that a user-defined property needs changing. The event structure (WIDGET_PROPSHEET_CHANGE) provided when a change occurs contains a COMPONENT, an IDENTIFIER, a PROPTYPE, and a SET_DEFINED tag. The COMPONENT tag contains a reference to the object associated with the property sheet. When multiple objects are associated with the property sheet, this member indicates which object is to change. The IDENTIFIER tag specifies the value of the property's identifier attribute. This identifier is unique among all of the component's properties. The PROPTYPE tag indicates the type of the property (integer, string, etc.). Integer values for these types can be found in the documentation for components. The SET_DEFINED tag indicates whether or not an undefined property is having its value set. In most circumstances, along with its new value, the property should have its 'UNDEFINED' attribute set to zero. If a property is never marked as undefined, this field can be ignored.
Although the component's object reference is included in the event structure, it can also be retrieved via the following call:
WIDGET_CONTROL, event.id, GET_VALUE = obj
where event is the event structure and obj is the object reference of the component.
The PROPTYPE field is provided for convenience. The property type should be known implicitly based on IDENTIFIER, but can be retrieved (in integer form) by:
obj->GetPropertyAttribute, event.identifier, TYPE = type
where obj is the object reference of the component, event is the event structure, and type represents the data type of the property. Here, the value returned in by the TYPE keyword is the same as the value of the PROPTYPE field of the widget event structure.
Properties can use their UNDEFINED attribute to show an indeterminate state (set attribute UNDEFINED = 1). This might arise after the aggregation of two or more properties. One could imagine a COLOR property representing both the border and the interior color of a polygon so that just one color property is displayed in the property sheet. When set, the chosen color would be applied to both, and then the following code could be used to mark the property as defined:
IF (event.set_defined) THEN $ event.component->SetPropertyAttribute, $ event.identifier, UNDEFINED = 0 WIDGET_CONTROL, event.id, REFRESH_PROPERTY = event.identifier
where event is the event structure.
| Note |
Properties can also be hidden (removing them from the property sheet entirely) or desensitized (displaying the property in the property sheet, but not allowing the user to change its value). See Property Attributes for additional details.
When a value has been changed in the property sheet, you can access this resulting value through the WIDGET_INFO function:
value = WIDGET_INFO(event.id, PROPERTY_VALUE = event.identifier)
where event is the event structure. This value can then be used to update the changed property in the component object by calling its SetPropertyByIdentifier method:
event.component->SetPropertyByIdentifier, event.identifier, $ value
where event is the event structure and value is the modified property value.
User-defined properties allow IDL programmers to provide their own custom means for editing a property. One significant difference from other types of properties is that user-defined properties must have a string version of their value. This string value is stored in the USERDEF attribute of the property and must be explicitly updated. The string value is the value displayed in the property sheet. See Property Management for further discussion of user-defined properties.
Like other property types, user-defined properties generate IDL property sheet change events. The difference is that the IDL event handler cannot query the property sheet for the new value. It must use some other means to determine a new value. Typically this is done through widget code, in which the user is asked to set a value, but virtually any other technique is valid.
When handling change events, determine the property's type using the PROPTYPE field of the widget event structure. Once a value has been acquired, update the component using its SetProperty method. In addition, the string version of the user-defined property's value should be updated. This is done by executing a statement similar to the following example:
eventBase.component->SetPropertyAttribute, $ eventBase.identifier, USERDEF = userDefValue
where eventBase is the event structure of the top-level-base and userDefValue is the string representing the user-defined value when the property sheet is refreshed.
Once the underlying component has been updated, the property sheet is ready to be refreshed. Execute a call to update a given property with the current value:
widget_control, propsheet, refresh_property = eventBase.identifier
where propsheet is the widget ID of the property sheet widget and eventBase is the event structure of the top-level-base.
Property sheets without a size definition (lacking a specified SCR_XSIZE or XSIZE keyword value) are naturally sized. Column widths are dependent upon the cell contents of the components. Naturally sized property sheets allow the full contents of the longest cell to be visible in a column as shown in the left-hand image in the following figure. When a size definition is provided, selecting the cell displays the list contents in a drop-down box that is wide enough for the longest item as shown in the right-hand image in the following figure.
| Note |
The following elements are considered when determining column width in a naturally sized property sheet:
When a property sheet size is explicitly defined, the column width may crop the display of the full cell contents. However, when you select the cell, the full contents will be visible as follows:
The following example provides a property sheet containing all the available controls, including user-defined properties of a custom component.
Enter the following text into the IDL Editor:
; Property Sheet Demo
;
; This program contains these sections of code:
;
; (1) Definition of the IDLitTester class.
; (2) Methods for handling the user-defined data type.
; (3) Event handlers and main widget program.
;================================================
; (1) Definition of the IDLitTester class.
;------------------------------------------------
; IDLitTester
;
; Superclasses:
; IDLitComponent
;
; Subclasses:
; none
;
; Interfaces:
; IIDLProperty
;
; Intrinsic Methods:
; none (because it contains no objects)
;------------------------------------------------
; IDLitTester::Init
FUNCTION IDLitTester::Init, _REF_EXTRA = _extra
compile_opt idl2
; Initialize the superclass.
IF (self->IDLitComponent::Init() ne 1) THEN $
RETURN, 0
; Create IDLitTester.
; Nothing to do, for now.
; Register properties.
;
; * Only registered properties will show up in the property sheet.
; * <identifier> must match self.<identifier>.
self->RegisterProperty, 'BOOLEAN', /BOOLEAN , $
NAME = 'Boolean', DESCRIPTION = 'TRUE or FALSE'
self->RegisterProperty, 'COLOR', /COLOR, $
NAME = 'Color', DESCRIPTION = 'Color (RGB)'
self->RegisterProperty, 'USERDEF', USERDEF = '', $
NAME = 'User Defined', DESCRIPTION = 'User defined property'
self->RegisterProperty, 'NUMBER1', /INTEGER , $
NAME = 'Integer', DESCRIPTION = 'Integer in [-100, 100]', $
valid_range = [-100, 100]
self->RegisterProperty, 'NUMBER2', /FLOAT, $
NAME = 'Floating Point', DESCRIPTION = 'Number trackbar', $
valid_range = [-19.0D, 6.0D, 0.33333333333333D]
self->RegisterProperty, 'NUMBER3', /FLOAT, $
NAME = 'Floating Point', $
DESCRIPTION = 'Double in [-1.0, 1.0]', $
valid_range = [-1.0D, 1.0D]
self->RegisterProperty, 'LINESTYLE', /LINESTYLE, $
NAME = 'Line Style', DESCRIPTION = 'Line style'
self->RegisterProperty, 'LINETHICKNESS', /THICKNESS , $
NAME = 'Line Thickness', $
DESCRIPTION = 'Line thickness (pixels)'
self->RegisterProperty, 'STRINGOLA', /STRING , $
NAME = 'String', DESCRIPTION = 'Just some text'
self->RegisterProperty, 'SYMBOL', /SYMBOL , $
NAME = 'Symbol', DESCRIPTION = 'Symbol of some sort'
self->RegisterProperty, 'STRINGLIST', $
NAME = 'String List', DESCRIPTION = 'Enumerated list', $
enumlist = ['dog', 'cat', 'bat', 'rat', 'nat', $
'emu', 'owl', 'pig', 'hog', 'ant']
; Set any property values.
self->SetProperty, _EXTRA = _extra
RETURN, 1
END
;------------------------------------------------
; IDLitTester::Cleanup
PRO IDLitTester::Cleanup
compile_opt idl2
self->IDLitComponent::Cleanup
END
;------------------------------------------------
; IDLitTester::GetProperty
;
; Implemention for IIDLProperty interface
PRO IDLitTester::GetProperty, $
boolean = boolean, $
color = color, $
userdef = userdef, $
font = font, $
number1 = number1, $
number2 = number2, $
number3 = number3, $
linestyle = linestyle, $
linethickness = linethickness, $
stringola = stringola, $
stringlist = stringlist, $
symbol = symbol, $
_REF_EXTRA = _extra
compile_opt idl2
IF (arg_present(boolean)) THEN boolean = self.boolean
IF (arg_present(color)) THEN color = self.color
IF (arg_present(userdef)) THEN userdef = self.userdef
IF (arg_present(font)) THEN font = self.font
IF (arg_present(number1)) THEN number1 = self.number1
IF (arg_present(number2)) THEN number2 = self.number2
IF (arg_present(number3)) THEN number3 = self.number3
IF (arg_present(linestyle)) THEN linestyle = self.linestyle
IF (arg_present(linethickness)) $
THEN linethickness = self.linethickness
IF (arg_present(stringola)) THEN stringola = self.stringola
IF (arg_present(stringlist)) THEN stringlist = self.stringlist
IF (arg_present(symbol)) THEN symbol = self.symbol
; Superclass' properties:
IF (n_elements(_extra) gt 0) THEN $
self->IDLitComponent::GetProperty, _EXTRA = _extra
END
;------------------------------------------------
; IDLitTester::SetProperty
;
; Implementation for IIDLProperty interface
PRO IDLitTester::SetProperty, $
boolean = boolean, $
color = color, $
userdef = userdef, $
font = font, $
number1 = number1, $
number2 = number2, $
number3 = number3, $
linestyle = linestyle, $
linethickness = linethickness, $
stringola = stringola, $
stringlist = stringlist, $
symbol = symbol, $
_REF_EXTRA = _extra
compile_opt idl2
IF (n_elements(boolean) ne 0) THEN self.boolean = boolean
IF (n_elements(color) ne 0) THEN self.color = color
IF (n_elements(userdef) ne 0) THEN self.userdef = userdef
IF (n_elements(font) ne 0) THEN self.font = font
IF (n_elements(number1) ne 0) THEN self.number1 = number1
IF (n_elements(number2) ne 0) THEN self.number2 = number2
IF (n_elements(number3) ne 0) THEN self.number3 = number3
IF (n_elements(linestyle) ne 0) THEN self.linestyle = linestyle
IF (n_elements(linethickness) ne 0) THEN $
self.linethickness = linethickness
IF (n_elements(stringola) ne 0) THEN self.stringola = stringola
IF (n_elements(stringlist) ne 0) THEN self.stringlist = stringlist
IF (n_elements(symbol) ne 0) THEN self.symbol = symbol
self->IDLitComponent::SetProperty, _EXTRA = _extra
END
;------------------------------------------------
; IDLitTester__Define
PRO IDLitTester__Define
compile_opt idl2, hidden
struct = {$
IDLitTester, $
inherits IDLitComponent, $
boolean:0L, $
color:[0B,0B,0B], $
userdef:"", $
number1:0L, $
number2:0D, $
number3:0D, $
linestyle:0L, $
linethickness:0L, $
stringola:"", $
stringlist:0L, $
symbol:0L $
}
END
;================================================
; (2) Methods for handling the user-defined data type.
;------------------------------------------------
; UserDefEvent
;
; This procedure is just part of the widget code for
; the user defined property.
PRO UserDefEvent, e
IF (tag_names(e, /structure_name) eq 'WIDGET_BUTTON') $
THEN BEGIN
widget_control, e.top, get_uvalue = uvalue
widget_control, e.id, get_uvalue = numb_ness
propsheet = uvalue.propsheet
component = uvalue.component
identifier = uvalue.identifier
; Set the human readable value.
component->SetPropertyAttribute, $
identifier, userdef = numb_ness
; Set the real value of the component.
component->SetPropertyByIdentifier, identifier, numb_ness
widget_control, propsheet, refresh_property = identifier
print, 'Changed: ', uvalue.identifier, ': ', numb_ness
widget_control, e.top, /destroy
ENDIF
END
;------------------------------------------------
; GetUserDefValue
;
; Creates widgets used to modify the user defined property's
; value. The value is actually set in UserDefEvent.
PRO GetUserDefValue, e
base = widget_base(/row, title = 'Pick a Number', $
/modal, group_leader = e.top)
one = widget_button(base, value = 'one', uvalue = 'oneness')
two = widget_button(base, value = 'two', uvalue = 'twoness')
six = widget_button(base, value = 'six', uvalue = 'sixness')
ten = widget_button(base, value = 'ten', uvalue = 'tenness')
; We will need this info when we set the value
widget_control, base, $
set_uvalue = {propsheet:e.id, $
component:e.component, $
identifier:e.identifier}
widget_control, base, /realize
xmanager, 'UserDefEvent', base, event_handler = 'UserDefEvent'
END
;================================================
; (3) Event handlers and main widget program.
;------------------------------------------------
;
; Event handling code for the main widget program and
; the main widget program.
;------------------------------------------------
; prop_event
;
; The property sheet generates an event whenever the user changes
; a value. The event holds the property's identifier and type, and
; an object reference to the component.
;
; Note: widget_control, e.id, get_value = objref also retrieves an
; object reference to the component.
PRO prop_event, e
IF (e.type eq 0) THEN BEGIN ; Value changed
; Get the value of the property identified by e.identifier.
IF (e.proptype ne 0) THEN BEGIN
; Get the value from the property sheet.
value = widget_info(e.id, property_value = e.identifier)
; Set the component's property's value.
e.component->SetPropertyByIdentifier, e.identifier, $
value
; Print the change in the component's property value.
PRINT, 'Changed', e.identifier, ': ', value
ENDIF ELSE BEGIN
; Use alternative means to get the value.
GetUserDefValue, e
ENDELSE
ENDIF ELSE BEGIN ; selection changed
print, 'Selected: ' + e.identifier
r = e.component->GetPropertyByIdentifier(e.identifier, value)
PRINT, ' Current Value: ', value
ENDELSE
END
;------------------------------------------------
; refresh_event
PRO refresh_event, e
widget_control, e.id, get_uvalue = uvalue
uvalue.o->SetProperty, boolean = 0L
uvalue.o->SetProperty, color = [255, 0, 46]
uvalue.o->SetPropertyAttribute, 'userdef', userdef = "Yeehaw!"
uvalue.o->SetProperty, number1 = 99L
uvalue.o->SetProperty, number2 = -13.1
uvalue.o->SetProperty, number3 = 6.5
uvalue.o->SetProperty, linestyle = 6L
uvalue.o->SetProperty, stringola = 'It worked!'
uvalue.o->SetProperty, stringlist = 6L
uvalue.o->SetProperty, symbol = 6L
uvalue.o->SetPropertyAttribute, 'Number1', sensitive = 1
uvalue.o->SetPropertyAttribute, 'Number2', sensitive = 1
widget_control, uvalue.prop, $
refresh_property = ['boolean', 'color', 'userdef', $
'number1', 'number2', 'number3', 'linestyle', $
'stringola', 'stringlist', 'symbol']
END
;------------------------------------------------
; reload_event
PRO reload_event, e
widget_control, e.id, get_uvalue = uvalue
LoadValues, uvalue.o
widget_control, uvalue.prop, set_value = uvalue.o
update_state, e.top, 1
END
;------------------------------------------------
; hide_event
PRO hide_event, e
widget_control, e.id, get_uvalue = uvalue
uvalue.o->SetPropertyAttribute, 'color', /hide
widget_control, uvalue.prop, refresh_property = 'color'
END
;------------------------------------------------
; show_event
PRO show_event, e
widget_control, e.id, get_uvalue = uvalue
uvalue.o->SetPropertyAttribute, 'color', hide = 0
widget_control, uvalue.prop, refresh_property = 'color'
END
;------------------------------------------------
; clear_event
PRO clear_event, e
update_state, e.top, 0
widget_control, e.id, get_uvalue = uvalue
widget_control, uvalue.prop, set_value = obj_new()
END
;------------------------------------------------
; psdemo_large_event
;
; Handles resize events for the property sheet demo program.
PRO psdemo_large_event, e
WIDGET_CONTROL, e.id, GET_UVALUE = base
geo_tlb = WIDGET_INFO(e.id, /GEOMETRY)
WIDGET_CONTROL, base.prop, $
SCR_XSIZE = geo_tlb.xsize - (2*geo_tlb.xpad), $
SCR_YSIZE = geo_tlb.ysize - (2*geo_tlb.ypad)
END
;------------------------------------------------
; sensitivity_event
;
; Procedure to test sensitizing and desensitizing
PRO sensitivity_event, e
widget_control, e.id, get_uvalue = uvalue, get_value = value
IF (value eq 'Desensitize') THEN b = 0 $
ELSE b = 1
uvalue.o->SetPropertyAttribute, 'Boolean', sensitive = b
uvalue.o->SetPropertyAttribute, 'Color', sensitive = b
uvalue.o->SetPropertyAttribute, 'UserDef', sensitive = b
uvalue.o->SetPropertyAttribute, 'Number1', sensitive = b
uvalue.o->SetPropertyAttribute, 'Number2', sensitive = b
uvalue.o->SetPropertyAttribute, 'Number3', sensitive = b
uvalue.o->SetPropertyAttribute, 'LineStyle', sensitive = b
uvalue.o->SetPropertyAttribute, 'LineThickness', sensitive = b
uvalue.o->SetPropertyAttribute, 'Stringola', sensitive = b
uvalue.o->SetPropertyAttribute, 'Symbol', sensitive = b
uvalue.o->SetPropertyAttribute, 'StringList', sensitive = b
widget_control, uvalue.prop, $
refresh_property = ['Boolean', 'Color', 'UserDef', $
'Number1', 'Number2', 'Number3', 'LineStyle', $
'LineThickness', 'Stringola', 'Symbol', 'StringList']
END
;------------------------------------------------
; LoadValues
PRO LoadValues, o
o->SetProperty, boolean = 1L ; 0 or 1
o->SetProperty, color = [200, 100, 50] ; RGB
o->SetPropertyAttribute, 'userdef', userdef = ""
; to be set later
o->SetProperty, number1 = 42L ; integer
o->SetProperty, number2 = 0.0 ; double
o->SetProperty, number3 = 0.1 ; double
o->SetProperty, linestyle = 4L ; 5th item (zero based)
o->SetProperty, linethickness = 4L ; pixels
o->SetProperty, stringola = "This is a silly string."
o->SetProperty, stringlist = 3L ; 4th item in list
o->SetProperty, symbol = 4L ; 5th symbol in list
END
;------------------------------------------------
; quit_event
PRO quit_event, e
widget_control, e.top, /destroy
END
;------------------------------------------------
; update_state
PRO update_state, top, sensitive
widget_control, top, get_uvalue = uvalue
for i = 0, n_elements(uvalue.b) - 1 do $
widget_control, uvalue.b[i], sensitive = sensitive
END
;------------------------------------------------
; psdemo_large
PRO psdemo_large
; Create and initialize the component.
o = obj_new('IDLitTester')
LoadValues, o
; Create some widgets.
base = widget_base(/column, /tlb_size_event, $
title = 'Property Sheet Demo (Large)')
prop = widget_propertysheet(base, value = o, $
ysize = 13, /frame, event_pro = 'prop_event')
b1 = widget_button(base, value = 'Refresh', $
uvalue = {o:o, prop:prop}, $
event_pro = 'refresh_event')
b2 = widget_button(base, value = 'Reload', $
uvalue = {o:o, prop:prop}, $
event_pro = 'reload_event')
b3 = widget_button(base, value = 'Hide Color', $
uvalue = {o:o, prop:prop}, $
event_pro = 'hide_event')
b4 = widget_button(base, value = 'Show Color', $
uvalue = {o:o, prop:prop}, $
event_pro = 'show_event')
b5 = widget_button(base, value = 'Clear', $
uvalue = {o:o, prop:prop}, $
event_pro = 'clear_event')
b6 = widget_button(base, value = 'Desensitize', $
uvalue = {o:o, prop:prop}, $
event_pro = 'sensitivity_event')
b7 = widget_button(base, value = 'Sensitize', $
uvalue = {o:o, prop:prop}, $
event_pro = 'sensitivity_event')
b8 = widget_button(base, value = 'Quit', $
event_pro = 'quit_event')
; Buttons that can't be pushed after clearing:
b = [b1, b3, b4, b5, b6, b7]
; Activate the widgets.
widget_control, base, set_uvalue = {prop:prop, b:b}, /realize
xmanager, 'psdemo_large', base, /no_block
END
The following figure displays the output of this example:
To demonstrate the controls available from the WIDGET_PROPERTYSHEET, do the following and note the Selected and Changed messages in the IDL Output Log:
Click the eight buttons at the bottom of the property sheet to initiate the following events:
refresh_event into the property sheet, using the REFRESH_PROPERTY keyword to WIDGET_CONTROL.LoadValues into the property sheet, using the SET_VALUE keyword to WIDGET_CONTROL.hide_event, which sets the HIDE attribute for the color property to one.show_event, which sets the HIDE attribute for the color property to zero.clear_event, which creates a new set of empty objects, deactivating all but the Reload button.sensitivity_event, which deactivates the displayed fields.sensitivity_event, which reactivates the displayed fields.quit_event, which destroys the top-level base and ends the program.The following example shows how to create a property sheet for multiple components.
Enter the following text in the IDL Editor:
; ExMultiSheet.pro
;
; Provides an example of a property sheet that is
; associated with more than one object. In this case,
; multiple IDLitVisAxis objects are used, with random
; colors and hidden cells, just for fun.
PRO PropertyEvent, event
IF (event.type EQ 0) THEN BEGIN ; Value changed.
PRINT, 'Changed: ', event.component
PRINT, ' ', event.identifier, ': ', $
WIDGET_INFO(event.id, COMPONENT = event.component, $
PROPERTY_VALUE = event.identifier)
ENDIF ELSE BEGIN ; Selection changed.
PRINT, 'Selected: ' + event.identifier
ENDELSE
END
PRO CleanupEvent, baseID
WIDGET_CONTROL, baseID, GET_UVALUE = objects
FOR i = 0, (N_ELEMENTS(objects) - 1) DO $
OBJ_DESTROY, objects[i]
END
PRO ExMultiSheet_event, event
ps = WIDGET_INFO(event.id, $
FIND_BY_UNAME = 'PropSheet')
geo_tlb = WIDGET_INFO(event.id, /GEOMETRY)
WIDGET_CONTROL, ps, $
SCR_XSIZE = geo_tlb.xsize - (2*geo_tlb.xpad), $
SCR_YSIZE = geo_tlb.ysize - (2*geo_tlb.ypad)
END
PRO ExMultiSheet
tlb = WIDGET_BASE(/COLUMN, /TLB_SIZE_EVENTS, $
KILL_NOTIFY = 'CleanupEvent')
; Create some columns.
oComp1 = OBJ_NEW('IDLitVisAxis', $
COLOR = RANDOMU(s1, 3)*256, $
TEXT_COLOR = RANDOMU(s7, 3)*256)
oComp2 = OBJ_NEW('IDLitVisAxis', $
COLOR = RANDOMU(s2, 3)*256, $
TEXT_COLOR = RANDOMU(s8, 3)*256)
oComp3 = OBJ_NEW('IDLitVisAxis', $
COLOR = RANDOMU(s3, 3)*256, $
TEXT_COLOR = RANDOMU(s9, 3)*256)
oComp4 = OBJ_NEW('IDLitVisAxis', $
COLOR = RANDOMU(s4, 3)*256, $
TEXT_COLOR = RANDOMU(s10, 3)*256)
oComp5 = OBJ_NEW('IDLitVisAxis', $
COLOR = RANDOMU(s5, 3)*256, $
TEXT_COLOR = RANDOMU(s11, 3)*256)
oComp6 = OBJ_NEW('IDLitVisAxis', $
COLOR = RANDOMU(s6, 3)*256, $
TEXT_COLOR = RANDOMU(s12, 3)*256)
oComps = [oComp1, oComp2, oComp3, $
oComp4, oComp5, oComp6]
WIDGET_CONTROL, tlb, SET_UVALUE = oComps
; Hide some properties.
oComp2->SetPropertyAttribute, 'color', /HIDE
oComp2->SetPropertyAttribute, 'ticklen', /HIDE
oComp5->SetPropertyAttribute, 'ticklen', /HIDE
; Create the property sheet.
prop = WIDGET_PROPERTYSHEET(tlb, $
UNAME = 'PropSheet', $
VALUE = oComps, $
FONT = 'Courier New*16', $
XSIZE = 100, YSIZE = 24, $
/FRAME, EVENT_PRO = 'PropertyEvent')
; Activate the widgets.
WIDGET_CONTROL, tlb, /REALIZE
XMANAGER, 'ExMultiSheet', tlb, /NO_BLOCK
END
Save the program as ExMultiSheet.pro, then compile and run it. A property sheet displaying the properties of six axes is displayed:
The gray boxes indicate properties that have been hidden. To remove the gray boxes, comment out the code after the following comment:
; Hide some properties.
The text is displayed at 16 points in the Courier New font. To view the property sheet with the text displayed in the default size and font, comment out the following segment of the property sheet creation code:
FONT = "Courier New*16", $
To see the text displayed in a font and size of your choosing, edit the same segment to include a different font name and size.