[2] | 1 | ; $Id$ |
---|
| 2 | ; |
---|
[69] | 3 | ; Copyright (c) 1992-2005, Research Systems, Inc. All rights reserved. |
---|
| 4 | ; Unauthorized reproduction prohibited. |
---|
[2] | 5 | ;+ |
---|
| 6 | ; NAME: |
---|
[69] | 7 | ; CW_BGROUP |
---|
[2] | 8 | ; |
---|
| 9 | ; PURPOSE: |
---|
[69] | 10 | ; CW_BGROUP is a compound widget that simplifies creating |
---|
| 11 | ; a base of buttons. It handles the details of creating the |
---|
| 12 | ; proper base (standard, exclusive, or non-exclusive) and filling |
---|
| 13 | ; in the desired buttons. Events for the individual buttons are |
---|
| 14 | ; handled transparently, and a CW_BGROUP event returned. This |
---|
| 15 | ; event can return any one of the following: |
---|
| 16 | ; - The Index of the button within the base. |
---|
| 17 | ; - The widget ID of the button. |
---|
| 18 | ; - The name of the button. |
---|
| 19 | ; - An arbitrary value taken from an array of User values. |
---|
[2] | 20 | ; |
---|
| 21 | ; CATEGORY: |
---|
[69] | 22 | ; Compound widgets. |
---|
[2] | 23 | ; |
---|
| 24 | ; CALLING SEQUENCE: |
---|
[69] | 25 | ; Widget = CW_BGROUP(Parent, Names) |
---|
[2] | 26 | ; |
---|
[69] | 27 | ; To get or set the value of a CW_BGROUP, use the GET_VALUE and |
---|
| 28 | ; SET_VALUE keywords to WIDGET_CONTROL. The value of a CW_BGROUP |
---|
| 29 | ; is: |
---|
[2] | 30 | ; |
---|
[69] | 31 | ; ----------------------------------------------- |
---|
| 32 | ; Type Value |
---|
| 33 | ; ----------------------------------------------- |
---|
| 34 | ; normal None |
---|
| 35 | ; exclusive Index of currently set button |
---|
| 36 | ; non-exclusive Vector indicating the position |
---|
| 37 | ; of each button (1-set, 0-unset) |
---|
| 38 | ; ----------------------------------------------- |
---|
[2] | 39 | ; |
---|
| 40 | ; |
---|
| 41 | ; INPUTS: |
---|
[69] | 42 | ; Parent: The ID of the parent widget. |
---|
| 43 | ; Names: A string array, containing one string per button, |
---|
| 44 | ; giving the name of each button. |
---|
[2] | 45 | ; |
---|
| 46 | ; KEYWORD PARAMETERS: |
---|
| 47 | ; |
---|
[69] | 48 | ; BUTTON_UVALUE: An array of user values to be associated with |
---|
| 49 | ; each button and returned in the event structure. |
---|
| 50 | ; COLUMN: Buttons will be arranged in the number of columns |
---|
| 51 | ; specified by this keyword. |
---|
| 52 | ; EVENT_FUNCT: The name of an optional user-supplied event function |
---|
| 53 | ; for buttons. This function is called with the return |
---|
| 54 | ; value structure whenever a button is pressed, and |
---|
| 55 | ; follows the conventions for user-written event |
---|
| 56 | ; functions. |
---|
| 57 | ; EXCLUSIVE: Buttons will be placed in an exclusive base, with |
---|
| 58 | ; only one button allowed to be selected at a time. |
---|
| 59 | ; FONT: The name of the font to be used for the button |
---|
| 60 | ; titles. If this keyword is not specified, the default |
---|
| 61 | ; font is used. |
---|
| 62 | ; FRAME: Specifies the width of the frame to be drawn around |
---|
| 63 | ; the base. |
---|
| 64 | ; IDS: A named variable into which the button IDs will be |
---|
| 65 | ; stored, as a longword vector. |
---|
| 66 | ; LABEL_LEFT: Creates a text label to the left of the buttons. |
---|
| 67 | ; LABEL_TOP: Creates a text label above the buttons. |
---|
| 68 | ; MAP: If set, the base will be mapped when the widget |
---|
| 69 | ; is realized (the default). |
---|
| 70 | ; NONEXCLUSIVE: Buttons will be placed in an non-exclusive base. |
---|
| 71 | ; The buttons will be independent. |
---|
| 72 | ; NO_RELEASE: If set, button release events will not be returned. |
---|
| 73 | ; RETURN_ID: If set, the VALUE field of returned events will be |
---|
| 74 | ; the widget ID of the button. |
---|
| 75 | ; RETURN_INDEX: If set, the VALUE field of returned events will be |
---|
| 76 | ; the zero-based index of the button within the base. |
---|
| 77 | ; THIS IS THE DEFAULT. |
---|
| 78 | ; RETURN_NAME: If set, the VALUE field of returned events will be |
---|
| 79 | ; the name of the button within the base. |
---|
| 80 | ; ROW: Buttons will be arranged in the number of rows |
---|
| 81 | ; specified by this keyword. |
---|
| 82 | ; SCROLL: If set, the base will include scroll bars to allow |
---|
| 83 | ; viewing a large base through a smaller viewport. |
---|
| 84 | ; SET_VALUE: The initial value of the buttons. This is equivalent |
---|
| 85 | ; to the later statement: |
---|
[2] | 86 | ; |
---|
[69] | 87 | ; WIDGET_CONTROL, widget, set_value=value |
---|
[2] | 88 | ; |
---|
[69] | 89 | ; SPACE: The space, in pixels, to be left around the edges |
---|
| 90 | ; of a row or column major base. This keyword is |
---|
| 91 | ; ignored if EXCLUSIVE or NONEXCLUSIVE are specified. |
---|
| 92 | ; UVALUE: The user value to be associated with the widget. |
---|
| 93 | ; UNAME: The user name to be associated with the widget. |
---|
| 94 | ; XOFFSET: The X offset of the widget relative to its parent. |
---|
| 95 | ; XPAD: The horizontal space, in pixels, between children |
---|
| 96 | ; of a row or column major base. Ignored if EXCLUSIVE |
---|
| 97 | ; or NONEXCLUSIVE are specified. |
---|
| 98 | ; XSIZE: The width of the base. |
---|
| 99 | ; X_SCROLL_SIZE: The width of the viewport if SCROLL is specified. |
---|
| 100 | ; YOFFSET: The Y offset of the widget relative to its parent. |
---|
| 101 | ; YPAD: The vertical space, in pixels, between children of |
---|
| 102 | ; a row or column major base. Ignored if EXCLUSIVE |
---|
| 103 | ; or NONEXCLUSIVE are specified. |
---|
| 104 | ; YSIZE: The height of the base. |
---|
| 105 | ; Y_SCROLL_SIZE: The height of the viewport if SCROLL is specified. |
---|
[2] | 106 | ; |
---|
| 107 | ; OUTPUTS: |
---|
| 108 | ; The ID of the created widget is returned. |
---|
| 109 | ; |
---|
| 110 | ; SIDE EFFECTS: |
---|
[69] | 111 | ; This widget generates event structures with the following definition: |
---|
[2] | 112 | ; |
---|
[69] | 113 | ; event = { ID:0L, TOP:0L, HANDLER:0L, SELECT:0, VALUE:0 } |
---|
[2] | 114 | ; |
---|
[69] | 115 | ; The SELECT field is passed through from the button event. VALUE is |
---|
| 116 | ; either the INDEX, ID, NAME, or BUTTON_UVALUE of the button, |
---|
| 117 | ; depending on how the widget was created. |
---|
[2] | 118 | ; |
---|
| 119 | ; RESTRICTIONS: |
---|
[69] | 120 | ; Only buttons with textual names are handled by this widget. |
---|
| 121 | ; Bitmaps are not understood. |
---|
[2] | 122 | ; |
---|
| 123 | ; MODIFICATION HISTORY: |
---|
[69] | 124 | ; 15 June 1992, AB |
---|
| 125 | ; 7 April 1993, AB, Removed state caching. |
---|
| 126 | ; 6 Oct. 1994, KDB, Font keyword is not applied to the label. |
---|
[2] | 127 | ; 10 FEB 1995, DJC fixed bad bug in event procedure, getting |
---|
| 128 | ; id of stash widget. |
---|
[69] | 129 | ; 11 April 1995, AB Removed Motif special cases. |
---|
[2] | 130 | ;- |
---|
| 131 | |
---|
| 132 | |
---|
| 133 | pro CW_BGROUP_SETV, id, value |
---|
[114] | 134 | compile_opt hidden, idl2, strictarrsubs |
---|
[2] | 135 | |
---|
[69] | 136 | ON_ERROR, 2 ;return to caller |
---|
[2] | 137 | |
---|
| 138 | stash = WIDGET_INFO(id, /CHILD) |
---|
| 139 | WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY |
---|
| 140 | |
---|
| 141 | case state.type of |
---|
| 142 | 0: message,'unable to set plain button group value' |
---|
| 143 | 1: begin |
---|
[69] | 144 | WIDGET_CONTROL, SET_BUTTON=0, state.ids[state.excl_pos] |
---|
| 145 | state.excl_pos = value |
---|
| 146 | WIDGET_CONTROL, /SET_BUTTON, state.ids[value] |
---|
| 147 | end |
---|
[2] | 148 | 2: begin |
---|
[69] | 149 | n = n_elements(value)-1 |
---|
| 150 | for i = 0, n do begin |
---|
| 151 | state.nonexcl_curpos[i] = value[i] |
---|
| 152 | WIDGET_CONTROL, state.ids[i], SET_BUTTON=value[i] |
---|
| 153 | endfor |
---|
| 154 | end |
---|
[2] | 155 | endcase |
---|
| 156 | |
---|
| 157 | WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY |
---|
| 158 | end |
---|
| 159 | |
---|
| 160 | |
---|
| 161 | |
---|
| 162 | function CW_BGROUP_GETV, id, value |
---|
| 163 | |
---|
[114] | 164 | compile_opt hidden, idl2, strictarrsubs |
---|
[69] | 165 | ON_ERROR, 2 ;return to caller |
---|
[2] | 166 | |
---|
[69] | 167 | stash = WIDGET_INFO(id, /CHILD) |
---|
| 168 | WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY |
---|
[2] | 169 | |
---|
[69] | 170 | case state.type of |
---|
| 171 | 0: message, 'unable to get plain button group value' |
---|
[2] | 172 | ; 1: ret = state.excl_pos |
---|
[69] | 173 | 1: ret = state.ret_arr[state.excl_pos] |
---|
[2] | 174 | ; 2: ret = state.nonexcl_curpos |
---|
[69] | 175 | 2: BEGIN |
---|
| 176 | index = where(state.nonexcl_curpos NE 0) |
---|
| 177 | if index[0] EQ -1 then begin |
---|
| 178 | if size(state.ret_arr, /type) EQ 7 then ret = '' ELSE ret = -1 |
---|
| 179 | ENDIF ELSE ret = state.ret_arr[index] |
---|
| 180 | END |
---|
| 181 | endcase |
---|
| 182 | |
---|
| 183 | WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY |
---|
[2] | 184 | |
---|
[69] | 185 | return, ret |
---|
[2] | 186 | |
---|
| 187 | end |
---|
| 188 | |
---|
| 189 | |
---|
| 190 | |
---|
| 191 | function CW_BGROUP_EVENT, ev |
---|
[114] | 192 | compile_opt hidden, idl2, strictarrsubs |
---|
[2] | 193 | WIDGET_CONTROL, ev.handler, GET_UVALUE=stash |
---|
| 194 | WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY |
---|
| 195 | WIDGET_CONTROL, ev.id, get_uvalue=uvalue |
---|
| 196 | |
---|
[69] | 197 | ret = 1 ;Assume we return a struct |
---|
[2] | 198 | case state.type of |
---|
| 199 | 0: |
---|
| 200 | 1: if (ev.select eq 1) then begin |
---|
[69] | 201 | state.excl_pos = uvalue |
---|
| 202 | ENDIF else begin |
---|
| 203 | if (state.no_release ne 0) then ret = 0 |
---|
| 204 | ENDELSE |
---|
[2] | 205 | 2: begin |
---|
[69] | 206 | ; Keep track of the current state |
---|
| 207 | state.nonexcl_curpos[uvalue] = ev.select |
---|
[2] | 208 | if (state.no_release ne 0) and (ev.select eq 0) then ret = 0 |
---|
[69] | 209 | end |
---|
[2] | 210 | endcase |
---|
| 211 | |
---|
[69] | 212 | if ret then begin ;Return a struct? |
---|
[2] | 213 | ret = { ID:state.base, TOP:ev.top, HANDLER:0L, SELECT:ev.select, $ |
---|
[69] | 214 | VALUE:state.ret_arr[uvalue] } |
---|
[2] | 215 | efun = state.efun |
---|
| 216 | WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY |
---|
| 217 | if efun ne '' then return, CALL_FUNCTION(efun, ret) $ |
---|
| 218 | else return, ret |
---|
[69] | 219 | endif else begin ;Trash the event |
---|
[2] | 220 | WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY |
---|
| 221 | return, 0 |
---|
| 222 | endelse |
---|
| 223 | end |
---|
| 224 | |
---|
| 225 | |
---|
| 226 | |
---|
| 227 | |
---|
| 228 | |
---|
| 229 | |
---|
| 230 | |
---|
| 231 | function CW_BGROUP, parent, names, $ |
---|
[69] | 232 | BUTTON_UVALUE = button_uvalue, COLUMN=column, EVENT_FUNCT = efun, $ |
---|
| 233 | EXCLUSIVE=excl, FONT=font, FRAME=frame, IDS=ids, LABEL_TOP=label_top, $ |
---|
| 234 | LABEL_LEFT=label_left, MAP=map, $ |
---|
| 235 | NONEXCLUSIVE=nonexcl, NO_RELEASE=no_release, RETURN_ID=return_id, $ |
---|
| 236 | RETURN_INDEX=return_index, RETURN_NAME=return_name, $ |
---|
| 237 | ROW=row, SCROLL=scroll, SET_VALUE=sval, SPACE=space, $ |
---|
| 238 | TAB_MODE=tab_mode, UVALUE=uvalue, $ |
---|
| 239 | XOFFSET=xoffset, XPAD=xpad, XSIZE=xsize, X_SCROLL_SIZE=x_scroll_size,$ |
---|
| 240 | YOFFSET=yoffset, YPAD=ypad, YSIZE=ysize, Y_SCROLL_SIZE=y_scroll_size, $ |
---|
| 241 | UNAME=uname |
---|
[2] | 242 | |
---|
| 243 | |
---|
| 244 | IF (N_PARAMS() ne 2) THEN MESSAGE, 'Incorrect number of arguments' |
---|
| 245 | |
---|
[69] | 246 | ON_ERROR, 2 ;return to caller |
---|
[2] | 247 | |
---|
| 248 | ; Set default values for the keywords |
---|
| 249 | version = WIDGET_INFO(/version) |
---|
| 250 | if (version.toolkit eq 'OLIT') then def_space_pad = 4 else def_space_pad = 3 |
---|
[69] | 251 | IF (N_ELEMENTS(column) eq 0) then column = 0 |
---|
| 252 | IF (N_ELEMENTS(excl) eq 0) then excl = 0 |
---|
| 253 | IF (N_ELEMENTS(frame) eq 0) then frame = 0 |
---|
| 254 | IF (N_ELEMENTS(map) eq 0) then map=1 |
---|
| 255 | IF (N_ELEMENTS(nonexcl) eq 0) then nonexcl = 0 |
---|
| 256 | IF (N_ELEMENTS(no_release) eq 0) then no_release = 0 |
---|
| 257 | IF (N_ELEMENTS(row) eq 0) then row = 0 |
---|
| 258 | IF (N_ELEMENTS(scroll) eq 0) then scroll = 0 |
---|
| 259 | IF (N_ELEMENTS(space) eq 0) then space = def_space_pad |
---|
| 260 | IF (N_ELEMENTS(uname) eq 0) then uname = 'CW_BGROUP_UNAME' |
---|
| 261 | IF (N_ELEMENTS(uvalue) eq 0) then uvalue = 0 |
---|
| 262 | IF (N_ELEMENTS(xoffset) eq 0) then xoffset=0 |
---|
| 263 | IF (N_ELEMENTS(xpad) eq 0) then xpad = def_space_pad |
---|
| 264 | IF (N_ELEMENTS(xsize) eq 0) then xsize = 0 |
---|
| 265 | IF (N_ELEMENTS(x_scroll_size) eq 0) then x_scroll_size = 0 |
---|
| 266 | IF (N_ELEMENTS(yoffset) eq 0) then yoffset=0 |
---|
| 267 | IF (N_ELEMENTS(ypad) eq 0) then ypad = def_space_pad |
---|
| 268 | IF (N_ELEMENTS(ysize) eq 0) then ysize = 0 |
---|
| 269 | IF (N_ELEMENTS(y_scroll_size) eq 0) then y_scroll_size = 0 |
---|
[2] | 270 | |
---|
| 271 | |
---|
| 272 | |
---|
[69] | 273 | |
---|
[2] | 274 | top_base = 0L |
---|
| 275 | if (n_elements(label_top) ne 0) then begin |
---|
[69] | 276 | next_base = WIDGET_BASE(parent, XOFFSET=xoffset, YOFFSET=yoffset, /COLUMN) |
---|
[2] | 277 | if(keyword_set(font))then $ |
---|
| 278 | junk = WIDGET_LABEL(next_base, value=label_top,font=font) $ |
---|
| 279 | else junk = WIDGET_LABEL(next_base, value=label_top) |
---|
| 280 | top_base = next_base |
---|
| 281 | endif else next_base = parent |
---|
[69] | 282 | |
---|
[2] | 283 | if (n_elements(label_left) ne 0) then begin |
---|
[69] | 284 | next_base = WIDGET_BASE(next_base, XOFFSET=xoffset, YOFFSET=yoffset, /ROW) |
---|
[2] | 285 | if(keyword_set(font))then $ |
---|
| 286 | junk = WIDGET_LABEL(next_base, value=label_left, font=font) $ |
---|
| 287 | else junk = WIDGET_LABEL(next_base, value=label_left) |
---|
| 288 | if (top_base eq 0L) then top_base = next_base |
---|
| 289 | endif |
---|
| 290 | ; We need some kind of outer base to hold the users UVALUE |
---|
| 291 | if (top_base eq 0L) then begin |
---|
[69] | 292 | top_base = WIDGET_BASE(parent, XOFFSET=xoffset, YOFFSET=yoffset) |
---|
[2] | 293 | next_base = top_base |
---|
| 294 | endif |
---|
| 295 | If (top_base EQ next_base) THEN $ |
---|
[69] | 296 | next_base = WIDGET_BASE(top_base, Xpad=1, Ypad=1, Space=1) |
---|
[2] | 297 | |
---|
| 298 | ; Set top level base attributes |
---|
| 299 | WIDGET_CONTROL, top_base, MAP=map, $ |
---|
[69] | 300 | FUNC_GET_VALUE='CW_BGROUP_GETV', PRO_SET_VALUE='CW_BGROUP_SETV', $ |
---|
| 301 | SET_UVALUE=uvalue, SET_UNAME=uname |
---|
[2] | 302 | |
---|
[69] | 303 | ; Tabbing |
---|
| 304 | if (n_elements(tab_mode) ne 0) then begin |
---|
| 305 | WIDGET_CONTROL, top_base, TAB_MODE=tab_mode |
---|
| 306 | WIDGET_CONTROL, next_base, TAB_MODE=tab_mode |
---|
| 307 | end |
---|
| 308 | |
---|
[2] | 309 | ; The actual button holding base |
---|
| 310 | base = WIDGET_BASE(next_base, COLUMN=column, EXCLUSIVE=excl, FRAME=frame, $ |
---|
[69] | 311 | NONEXCLUSIVE=nonexcl, ROW=row, SCROLL=scroll, SPACE=space, $ |
---|
| 312 | XPAD=xpad, XSIZE=xsize, X_SCROLL_SIZE=x_scroll_size, $ |
---|
| 313 | YPAD=ypad, YSIZE=ysize, Y_SCROLL_SIZE=y_scroll_size, $ |
---|
| 314 | EVENT_FUNC='CW_BGROUP_EVENT', $ |
---|
| 315 | UVALUE=WIDGET_INFO(top_base, /child)) |
---|
[2] | 316 | |
---|
| 317 | |
---|
| 318 | n = n_elements(names) |
---|
| 319 | ids = lonarr(n) |
---|
| 320 | for i = 0, n-1 do begin |
---|
| 321 | if (n_elements(font) eq 0) then begin |
---|
[69] | 322 | ids[i] = WIDGET_BUTTON(base, value=names[i], UVALUE=i, $ |
---|
| 323 | UNAME=uname+'_BUTTON'+STRTRIM(i,2)) |
---|
[2] | 324 | endif else begin |
---|
[69] | 325 | ids[i] = WIDGET_BUTTON(base, value=names[i], FONT=font, $ |
---|
| 326 | UVALUE=i, UNAME=uname+'_BUTTON'+STRTRIM(i,2)) |
---|
[2] | 327 | endelse |
---|
| 328 | endfor |
---|
| 329 | |
---|
| 330 | ; Keep the state info in the real (inner) base UVALUE. |
---|
| 331 | ; Pick an event value type: |
---|
[69] | 332 | ; 0 - Return ID |
---|
| 333 | ; 1 - Return INDEX |
---|
| 334 | ; 2 - Return NAME |
---|
[2] | 335 | ret_type = 1 |
---|
| 336 | if KEYWORD_SET(RETURN_ID) then ret_type = 0 |
---|
| 337 | if KEYWORD_SET(RETURN_NAME) then ret_type = 2 |
---|
| 338 | if KEYWORD_SET(BUTTON_UVALUE) then ret_type = 3 |
---|
| 339 | case ret_type of |
---|
| 340 | 0: ret_arr = ids |
---|
| 341 | 1: ret_arr = indgen(n) |
---|
| 342 | 2: ret_arr = names |
---|
| 343 | 3: ret_arr = button_uvalue |
---|
| 344 | endcase |
---|
| 345 | type = 0 |
---|
| 346 | if (excl ne 0) then type = 1 |
---|
| 347 | |
---|
| 348 | if (nonexcl ne 0) then type = 2 |
---|
| 349 | if n_elements(efun) le 0 then efun = '' |
---|
[69] | 350 | state = { type:type, $ ; 0-Standard, 1-Exclusive, 2-Non-exclusive |
---|
| 351 | base: top_base, $ ; cw_bgroup base... |
---|
| 352 | ret_arr:ret_arr, $ ; Vector of event values |
---|
| 353 | efun : efun, $ ; Name of event fcn |
---|
| 354 | nonexcl_curpos:intarr(n), $ ; If non-exclus, tracks state |
---|
| 355 | excl_pos:0, $ ; If exclusive, current button |
---|
| 356 | ids:ids, $ ; Ids of buttons |
---|
| 357 | no_release:no_release } |
---|
[2] | 358 | WIDGET_CONTROL, WIDGET_INFO(top_base, /CHILD), SET_UVALUE=state, /NO_COPY |
---|
| 359 | |
---|
| 360 | if (n_elements(sval) ne 0) then CW_BGROUP_SETV, top_base, sval |
---|
| 361 | |
---|
| 362 | return, top_base |
---|
| 363 | END |
---|