source: trunk/WIDGET/COMPOUND_WIDGET/cw_bgroup.pro @ 2

Last change on this file since 2 was 2, checked in by opalod, 22 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 11.9 KB
Line 
1; $Id$
2;
3; Copyright (c) 1992-1998, 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;       XOFFSET:        The X offset of the widget relative to its parent.
94;       XPAD:           The horizontal space, in pixels, between children
95;                       of a row or column major base. Ignored if EXCLUSIVE
96;                       or NONEXCLUSIVE are specified.
97;       XSIZE:          The width of the base.
98;       X_SCROLL_SIZE:  The width of the viewport if SCROLL is specified.
99;       YOFFSET:        The Y offset of the widget relative to its parent.
100;       YPAD:           The vertical space, in pixels, between children of
101;                       a row or column major base. Ignored if EXCLUSIVE
102;                       or NONEXCLUSIVE are specified.
103;       YSIZE:          The height of the base.
104;       Y_SCROLL_SIZE:  The height of the viewport if SCROLL is specified.
105;
106; OUTPUTS:
107;       The ID of the created widget is returned.
108;
109; SIDE EFFECTS:
110;       This widget generates event structures with the following definition:
111;
112;               event = { ID:0L, TOP:0L, HANDLER:0L, SELECT:0, VALUE:0 }
113;
114;       The SELECT field is passed through from the button event. VALUE is
115;       either the INDEX, ID, NAME, or BUTTON_UVALUE of the button,
116;       depending on how the widget was created.
117;
118; RESTRICTIONS:
119;       Only buttons with textual names are handled by this widget.
120;       Bitmaps are not understood.
121;
122; MODIFICATION HISTORY:
123;       15 June 1992, AB
124;       7 April 1993, AB, Removed state caching.
125;       6 Oct. 1994, KDB, Font keyword is not applied to the label.
126;       10 FEB 1995, DJC  fixed bad bug in event procedure, getting
127;                         id of stash widget.
128;       11 April 1995, AB Removed Motif special cases.
129;-
130
131
132pro CW_BGROUP_SETV, id, value
133
134  ON_ERROR, 2                                           ;return to caller
135
136  stash = WIDGET_INFO(id, /CHILD)
137  WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY
138
139  case state.type of
140    0: message,'unable to set plain button group value'
141    1: begin
142          WIDGET_CONTROL, SET_BUTTON=0, state.ids[state.excl_pos]
143          state.excl_pos = value
144          WIDGET_CONTROL, /SET_BUTTON, state.ids[value]
145        end
146    2: begin
147          n = n_elements(value)-1
148          for i = 0, n do begin
149            state.nonexcl_curpos[i] = value[i]
150            WIDGET_CONTROL, state.ids[i], SET_BUTTON=value[i]
151          endfor
152        end
153  endcase
154
155  WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
156end
157
158
159
160function CW_BGROUP_GETV, id, value
161
162   ON_ERROR, 2                  ;return to caller
163
164   stash = WIDGET_INFO(id, /CHILD)
165   WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY
166
167   case state.type of
168      0: message,'unable to get plain button group value'
169;    1: ret = state.excl_pos
170      1: ret = state.ret_arr[state.excl_pos]
171;    2: ret = state.nonexcl_curpos
172      2: BEGIN
173         index = where(state.nonexcl_curpos NE 0)
174         if index[0] EQ -1 then begin
175            if size(state.ret_arr, /type) EQ 7 then ret = '' ELSE ret = -1
176         ENDIF ELSE ret = state.ret_arr[index]
177      END
178   endcase
179
180   WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
181
182   return, ret
183
184end
185
186
187
188function CW_BGROUP_EVENT, ev
189  WIDGET_CONTROL, ev.handler, GET_UVALUE=stash
190  WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY
191  WIDGET_CONTROL, ev.id, get_uvalue=uvalue
192
193  ret = 1                       ;Assume we return a struct
194  case state.type of
195    0:
196    1: if (ev.select eq 1) then begin
197          state.excl_pos = uvalue
198        ENDIF else begin
199          if (state.no_release ne 0) then ret = 0
200        ENDELSE
201    2: begin
202          ; Keep track of the current state
203          state.nonexcl_curpos[uvalue] = ev.select
204          if (state.no_release ne 0) and (ev.select eq 0) then ret = 0
205        end
206  endcase
207
208  if ret then begin             ;Return a struct?
209      ret = { ID:state.base, TOP:ev.top, HANDLER:0L, SELECT:ev.select, $
210               VALUE:state.ret_arr[uvalue] }
211      efun = state.efun
212      WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
213      if efun ne '' then return, CALL_FUNCTION(efun, ret) $
214      else return, ret
215  endif else begin              ;Trash the event
216      WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
217      return, 0
218  endelse
219end
220
221
222
223
224
225
226
227function CW_BGROUP, parent, names, $
228        BUTTON_UVALUE = button_uvalue, COLUMN=column, EVENT_FUNCT = efun, $
229        EXCLUSIVE=excl, FONT=font, FRAME=frame, IDS=ids, LABEL_TOP=label_top, $
230        LABEL_LEFT=label_left, MAP=map, $
231        NONEXCLUSIVE=nonexcl, NO_RELEASE=no_release, RETURN_ID=return_id, $
232        RETURN_INDEX=return_index, RETURN_NAME=return_name, $
233        ROW=row, SCROLL=scroll, SET_VALUE=sval, SPACE=space, UVALUE=uvalue, UNAME = uname, $
234        XOFFSET=xoffset, XPAD=xpad, XSIZE=xsize, X_SCROLL_SIZE=x_scroll_size,$
235        YOFFSET=yoffset, YPAD=ypad, YSIZE=ysize, Y_SCROLL_SIZE=y_scroll_size, $
236           _EXTRA = ex
237
238
239  IF (N_PARAMS() ne 2) THEN MESSAGE, 'Incorrect number of arguments'
240
241  ON_ERROR, 2                                           ;return to caller
242
243  ; Set default values for the keywords
244  version = WIDGET_INFO(/version)
245  if (version.toolkit eq 'OLIT') then def_space_pad = 4 else def_space_pad = 3
246  IF (N_ELEMENTS(column) eq 0)          then column = 0
247  IF (N_ELEMENTS(excl) eq 0)            then excl = 0
248  IF (N_ELEMENTS(frame) eq 0)           then frame = 0
249  IF (N_ELEMENTS(map) eq 0)             then map=1
250  IF (N_ELEMENTS(nonexcl) eq 0)         then nonexcl = 0
251  IF (N_ELEMENTS(no_release) eq 0)      then no_release = 0
252  IF (N_ELEMENTS(row) eq 0)             then row = 0
253  IF (N_ELEMENTS(scroll) eq 0)          then scroll = 0
254  IF (N_ELEMENTS(space) eq 0)           then space = def_space_pad
255  IF (N_ELEMENTS(uvalue) eq 0)          then uvalue = 0
256  IF (N_ELEMENTS(uname) eq 0)           then uname = ' '
257  IF (N_ELEMENTS(xoffset) eq 0)         then xoffset=0
258  IF (N_ELEMENTS(xpad) eq 0)            then xpad = def_space_pad
259  IF (N_ELEMENTS(xsize) eq 0)           then xsize = 0
260  IF (N_ELEMENTS(x_scroll_size) eq 0)   then x_scroll_size = 0
261  IF (N_ELEMENTS(yoffset) eq 0)         then yoffset=0
262  IF (N_ELEMENTS(ypad) eq 0)            then ypad = def_space_pad
263  IF (N_ELEMENTS(ysize) eq 0)           then ysize = 0
264  IF (N_ELEMENTS(y_scroll_size) eq 0)   then y_scroll_size = 0
265 
266
267
268
269  top_base = 0L
270  if (n_elements(label_top) ne 0) then begin
271    next_base = WIDGET_BASE(parent, XOFFSET=xoffset, YOFFSET=yoffset, /COLUMN, _EXTRA = ex)
272    if(keyword_set(font))then $
273       junk = WIDGET_LABEL(next_base, value=label_top,font=font) $
274    else    junk = WIDGET_LABEL(next_base, value=label_top)
275    top_base = next_base
276  endif else next_base = parent
277  if (n_elements(label_left) ne 0) then begin
278    next_base = WIDGET_BASE(next_base, XOFFSET=xoffset, YOFFSET=yoffset, /ROW, _EXTRA = ex)
279    if(keyword_set(font))then $
280       junk = WIDGET_LABEL(next_base, value=label_left, font=font) $
281    else junk = WIDGET_LABEL(next_base, value=label_left)
282    if (top_base eq 0L) then top_base = next_base
283  endif
284  ; We need some kind of outer base to hold the users UVALUE
285  if (top_base eq 0L) then begin
286    top_base = WIDGET_BASE(parent, XOFFSET=xoffset, YOFFSET=yoffset, _EXTRA = ex)
287    next_base = top_base
288  endif
289  If (top_base EQ next_base) THEN $
290     next_base = WIDGET_BASE(top_base, Xpad=1, Ypad=1, Space=1, _EXTRA = ex)
291
292  ; Set top level base attributes
293  WIDGET_CONTROL, top_base, MAP=map, $
294        FUNC_GET_VALUE='CW_BGROUP_GETV', PRO_SET_VALUE='CW_BGROUP_SETV', $
295        SET_UVALUE=uvalue, SET_UNAME = uname
296
297  ; The actual button holding base
298  base = WIDGET_BASE(next_base, COLUMN=column, EXCLUSIVE=excl, FRAME=frame, $
299        NONEXCLUSIVE=nonexcl, ROW=row, SCROLL=scroll, SPACE=space, $
300        XPAD=xpad, XSIZE=xsize, X_SCROLL_SIZE=x_scroll_size, $
301        YPAD=ypad, YSIZE=ysize, Y_SCROLL_SIZE=y_scroll_size, $
302        EVENT_FUNC='CW_BGROUP_EVENT', _EXTRA = ex, $
303        UVALUE=WIDGET_INFO(top_base, /child))
304
305
306  n = n_elements(names)
307  ids = lonarr(n)
308  for i = 0, n-1 do begin
309    if (n_elements(font) eq 0) then begin
310      ids[i] = WIDGET_BUTTON(base, value=names[i], UVALUE=i)
311    endif else begin
312      ids[i] = WIDGET_BUTTON(base, value=names[i], FONT=font, UVALUE=i)
313    endelse
314  endfor
315
316  ; Keep the state info in the real (inner) base UVALUE.
317  ; Pick an event value type:
318  ;     0 - Return ID
319  ;     1 - Return INDEX
320  ;     2 - Return NAME
321  ret_type = 1
322  if KEYWORD_SET(RETURN_ID) then ret_type = 0
323  if KEYWORD_SET(RETURN_NAME) then ret_type = 2
324  if KEYWORD_SET(BUTTON_UVALUE) then ret_type = 3
325    case ret_type of
326      0: ret_arr = ids
327      1: ret_arr = indgen(n)
328      2: ret_arr = names
329      3: ret_arr = button_uvalue
330    endcase
331  type = 0
332  if (excl ne 0) then type = 1
333
334  if (nonexcl ne 0) then type = 2
335  if n_elements(efun) le 0 then efun = ''
336  state = { type:type, $        ; 0-Standard, 1-Exclusive, 2-Non-exclusive
337            base: top_base, $   ; cw_bgroup base...
338            ret_arr:ret_arr, $  ; Vector of event values
339            efun : efun, $      ; Name of event fcn
340            nonexcl_curpos:intarr(n), $ ; If non-exclus, tracks state
341            excl_pos:0, $                       ; If exclusive, current button
342            ids:ids, $                  ; Ids of buttons
343            no_release:no_release }
344  WIDGET_CONTROL, WIDGET_INFO(top_base, /CHILD), SET_UVALUE=state, /NO_COPY
345
346  if (n_elements(sval) ne 0) then CW_BGROUP_SETV, top_base, sval
347
348  return, top_base
349END
Note: See TracBrowser for help on using the repository browser.