source: trunk/SRC/ToBeReviewed/WIDGET/COMPOUND_WIDGET/cw_bgroup.pro @ 114

Last change on this file since 114 was 114, checked in by smasson, 18 years ago

new compilation options (compile_opt idl2, strictarrsubs) in each routine

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 13.0 KB
Line 
1; $Id$
2;
3; Copyright (c) 1992-2005, Research Systems, Inc.  All rights reserved.
4;   Unauthorized reproduction prohibited.
5;+
6; NAME:
7;   CW_BGROUP
8;
9; PURPOSE:
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.
20;
21; CATEGORY:
22;   Compound widgets.
23;
24; CALLING SEQUENCE:
25;       Widget = CW_BGROUP(Parent, Names)
26;
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:
30;
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;       -----------------------------------------------
39;
40;
41; INPUTS:
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.
45;
46; KEYWORD PARAMETERS:
47;
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:
86;
87;           WIDGET_CONTROL, widget, set_value=value
88;
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.
106;
107; OUTPUTS:
108;       The ID of the created widget is returned.
109;
110; SIDE EFFECTS:
111;   This widget generates event structures with the following definition:
112;
113;       event = { ID:0L, TOP:0L, HANDLER:0L, SELECT:0, VALUE:0 }
114;
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.
118;
119; RESTRICTIONS:
120;   Only buttons with textual names are handled by this widget.
121;   Bitmaps are not understood.
122;
123; MODIFICATION HISTORY:
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.
127;       10 FEB 1995, DJC  fixed bad bug in event procedure, getting
128;                         id of stash widget.
129;   11 April 1995, AB Removed Motif special cases.
130;-
131
132
133pro CW_BGROUP_SETV, id, value
134  compile_opt hidden, idl2, strictarrsubs
135
136  ON_ERROR, 2                       ;return to caller
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
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
148    2: begin
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
155  endcase
156
157  WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
158end
159
160
161
162function CW_BGROUP_GETV, id, value
163
164  compile_opt hidden, idl2, strictarrsubs
165  ON_ERROR, 2                       ;return to caller
166
167  stash = WIDGET_INFO(id, /CHILD)
168  WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY
169
170  case state.type of
171    0: message, 'unable to get plain button group value'
172;    1: ret = state.excl_pos
173    1: ret = state.ret_arr[state.excl_pos]
174;    2: ret = state.nonexcl_curpos
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
184
185  return, ret
186
187end
188
189
190
191function CW_BGROUP_EVENT, ev
192  compile_opt hidden, idl2, strictarrsubs
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
197  ret = 1           ;Assume we return a struct
198  case state.type of
199    0:
200    1: if (ev.select eq 1) then begin
201      state.excl_pos = uvalue
202    ENDIF else begin
203      if (state.no_release ne 0) then ret = 0
204    ENDELSE
205    2: begin
206      ; Keep track of the current state
207      state.nonexcl_curpos[uvalue] = ev.select
208          if (state.no_release ne 0) and (ev.select eq 0) then ret = 0
209    end
210  endcase
211
212  if ret then begin     ;Return a struct?
213      ret = { ID:state.base, TOP:ev.top, HANDLER:0L, SELECT:ev.select, $
214           VALUE:state.ret_arr[uvalue] }
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
219  endif else begin      ;Trash the event
220      WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
221      return, 0
222  endelse
223end
224
225
226
227
228
229
230
231function CW_BGROUP, parent, names, $
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
242
243
244  IF (N_PARAMS() ne 2) THEN MESSAGE, 'Incorrect number of arguments'
245
246  ON_ERROR, 2                       ;return to caller
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
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
270
271
272
273
274  top_base = 0L
275  if (n_elements(label_top) ne 0) then begin
276    next_base = WIDGET_BASE(parent, XOFFSET=xoffset, YOFFSET=yoffset, /COLUMN)
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
282
283  if (n_elements(label_left) ne 0) then begin
284    next_base = WIDGET_BASE(next_base, XOFFSET=xoffset, YOFFSET=yoffset, /ROW)
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
292    top_base = WIDGET_BASE(parent, XOFFSET=xoffset, YOFFSET=yoffset)
293    next_base = top_base
294  endif
295  If (top_base EQ next_base) THEN $
296     next_base = WIDGET_BASE(top_base, Xpad=1, Ypad=1, Space=1)
297
298  ; Set top level base attributes
299  WIDGET_CONTROL, top_base, MAP=map, $
300    FUNC_GET_VALUE='CW_BGROUP_GETV', PRO_SET_VALUE='CW_BGROUP_SETV', $
301    SET_UVALUE=uvalue, SET_UNAME=uname
302
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
309  ; The actual button holding base
310  base = WIDGET_BASE(next_base, COLUMN=column, EXCLUSIVE=excl, FRAME=frame, $
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))
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
322      ids[i] = WIDGET_BUTTON(base, value=names[i], UVALUE=i, $
323      UNAME=uname+'_BUTTON'+STRTRIM(i,2))
324    endif else begin
325      ids[i] = WIDGET_BUTTON(base, value=names[i], FONT=font, $
326      UVALUE=i, UNAME=uname+'_BUTTON'+STRTRIM(i,2))
327    endelse
328  endfor
329
330  ; Keep the state info in the real (inner) base UVALUE.
331  ; Pick an event value type:
332  ; 0 - Return ID
333  ; 1 - Return INDEX
334  ; 2 - Return NAME
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 = ''
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 }
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
363END
Note: See TracBrowser for help on using the repository browser.