1 // $Id: xxMultiChoice.cc 4502 2012-05-27 17:46:59Z flaterco $
2
3 /* xxMultiChoice Multiple-choice button widget.
4
5 Copyright (C) 1998 David Flater.
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "xtide.hh"
22 #include "xxReconfigurable.hh"
23 #include "xxLocationList.hh"
24 #include "xxMultiChoice.hh"
25
26
choice() const27 const unsigned xxMultiChoice::choice() const {
28 return currentChoice;
29 }
30
31
buttonCallback(Widget w,XtPointer client_data,XtPointer call_data unusedParameter)32 static void buttonCallback (Widget w,
33 XtPointer client_data,
34 XtPointer call_data unusedParameter) {
35 assert (client_data);
36 ((xxMultiChoice*)client_data)->callback (w);
37 }
38
39
callback(Widget choiceButton)40 void xxMultiChoice::callback (Widget choiceButton) {
41 currentChoice = buttonChoices[choiceButton];
42 Arg args[1] = {{XtNlabel, (XtArgVal)(_choices[currentChoice])}};
43 XtSetValues (button->widget(), args, 1);
44 if (_caller)
45 _caller->reconfigure();
46 }
47
48
construct(Widget containerWidget)49 void xxMultiChoice::construct (Widget containerWidget) {
50 Arg buttonArgs[4] = {
51 {XtNvisual, (XtArgVal)xxX::visual},
52 {XtNcolormap, (XtArgVal)xxX::colormap},
53 {XtNbackground, (XtArgVal)xxX::pixels[Colors::button]},
54 {XtNforeground, (XtArgVal)xxX::pixels[Colors::foreground]}
55 };
56
57 // The menu.
58 {
59 // 2012-02-04
60 // After the location list container was changed from box to form, the
61 // sort key button no longer resized itself, with the result that "Sort
62 // by Longitude" would no longer fit. Consequently, the button is now
63 // fixed at the width that is required for the longest string that it
64 // must contain.
65
66 Arg menuArgs[6] = {
67 {XtNvisual, (XtArgVal)xxX::visual},
68 {XtNcolormap, (XtArgVal)xxX::colormap},
69 {(char*)"menuName", (XtArgVal)"menu"},
70 {XtNbackground, (XtArgVal)xxX::pixels[Colors::button]},
71 {XtNforeground, (XtArgVal)xxX::pixels[Colors::foreground]},
72 {XtNresize, (XtArgVal)false}
73 };
74 Widget buttonWidget = xxX::createXtWidget (_choices[currentChoice],
75 menuButtonWidgetClass, containerWidget, menuArgs, 6);
76 button = xxX::wrap (buttonWidget);
77
78 // Only for genuine Athena Widgets is it the case that widget width =
79 // string width + 2 * internalWidth. Xaw3d and Xaw3dXft add different
80 // overheads. Infer the correct width based on what happened with the
81 // initial choice.
82 const unsigned firstStringWidth (xxX::stringWidth (xxX::defaultFontStruct, _choices[currentChoice]));
83 unsigned maxStringWidth = firstStringWidth;
84 for (unsigned y=0; _choices[y]; ++y)
85 maxStringWidth = std::max (maxStringWidth, xxX::stringWidth (xxX::defaultFontStruct, _choices[y]));
86 Dimension currentWidth;
87 Arg getWidthArgs[1] = {
88 {XtNwidth, (XtArgVal)(¤tWidth)}
89 };
90 XtGetValues (buttonWidget, getWidthArgs, 1);
91 const unsigned correctWidth (maxStringWidth + currentWidth - firstStringWidth);
92 if (currentWidth != correctWidth) {
93 Arg setWidthArgs[1] = {
94 {XtNwidth, (XtArgVal)correctWidth}
95 };
96 XtSetValues (buttonWidget, setWidthArgs, 1);
97 }
98 }{
99 Widget menushell = XtCreatePopupShell ("menu",
100 simpleMenuWidgetClass, button->widget(), buttonArgs, 4);
101 menu = xxX::wrap (menushell);
102 xxX::fixBorder (menushell);
103 }
104
105 // Buttons on the menu.
106 for (unsigned y=0; _choices[y]; ++y) {
107 Widget buttonWidget = xxX::createXtWidget (_choices[y],
108 smeBSBObjectClass,
109 menu->widget(),
110 buttonArgs,
111 4);
112 XtAddCallback (buttonWidget, XtNcallback, buttonCallback, (XtPointer)this);
113 choiceButtons.push_back (new xxWidget (buttonWidget));
114 buttonChoices[buttonWidget] = y;
115 }
116 }
117
118
construct(const xxWidget & parent,constString caption)119 void xxMultiChoice::construct (const xxWidget &parent, constString caption) {
120 {
121 Arg args[3] = {
122 {XtNbackground, (XtArgVal)xxX::pixels[Colors::background]},
123 {XtNforeground, (XtArgVal)xxX::pixels[Colors::foreground]},
124 {XtNorientation, (XtArgVal)XtorientHorizontal}
125 };
126 Widget boxWidget = xxX::createXtWidget ("", boxWidgetClass,
127 parent.widget(), args, 3);
128 _box = xxX::wrap (boxWidget);
129 }{
130 Arg args[3] = {
131 {XtNbackground, (XtArgVal)xxX::pixels[Colors::background]},
132 {XtNforeground, (XtArgVal)xxX::pixels[Colors::foreground]},
133 {XtNborderWidth, (XtArgVal)0}
134 };
135 Widget labelWidget = xxX::createXtWidget (caption,
136 labelWidgetClass, _box->widget(), args, 3);
137 label = xxX::wrap (labelWidget);
138 }
139 construct (_box->widget());
140 }
141
142
xxMultiChoice(const xxWidget & parent,constString caption,constStringArray choices,unsigned initialChoice,xxReconfigurable & caller)143 xxMultiChoice::xxMultiChoice (const xxWidget &parent,
144 constString caption,
145 constStringArray choices,
146 unsigned initialChoice,
147 xxReconfigurable &caller):
148 _caller(&caller),
149 _choices(choices),
150 currentChoice(initialChoice) {
151 construct (parent, caption);
152 }
153
154
xxMultiChoice(const xxWidget & parent,constString caption,constStringArray choices,unsigned initialChoice)155 xxMultiChoice::xxMultiChoice (const xxWidget &parent,
156 constString caption,
157 constStringArray choices,
158 unsigned initialChoice):
159 _caller(NULL),
160 _choices(choices),
161 currentChoice(initialChoice) {
162 construct (parent, caption);
163 }
164
165
xxMultiChoice(const xxWidget & box,constStringArray choices,unsigned initialChoice)166 xxMultiChoice::xxMultiChoice (const xxWidget &box,
167 constStringArray choices,
168 unsigned initialChoice):
169 _caller(NULL),
170 _choices(choices),
171 currentChoice(initialChoice) {
172 construct (box.widget());
173 }
174
175
xxMultiChoice(const xxWidget & box,constStringArray choices,unsigned initialChoice,xxReconfigurable & caller)176 xxMultiChoice::xxMultiChoice (const xxWidget &box,
177 constStringArray choices,
178 unsigned initialChoice,
179 xxReconfigurable &caller):
180 _caller(&caller),
181 _choices(choices),
182 currentChoice(initialChoice) {
183 construct (box.widget());
184 }
185
186
xxMultiChoice(const xxWidget & form,constStringArray choices,unsigned initialChoice,xxReconfigurable & caller,ArgList layoutArgs,Cardinal numLayoutArgs)187 xxMultiChoice::xxMultiChoice (const xxWidget &form,
188 constStringArray choices,
189 unsigned initialChoice,
190 xxReconfigurable &caller,
191 ArgList layoutArgs,
192 Cardinal numLayoutArgs):
193 _caller(&caller),
194 _choices(choices),
195 currentChoice(initialChoice) {
196 construct (form.widget());
197 if (layoutArgs != NULL && numLayoutArgs > 0)
198 XtSetValues (button->widget(), layoutArgs, numLayoutArgs);
199 }
200
201
~xxMultiChoice()202 xxMultiChoice::~xxMultiChoice () {
203 for (unsigned a=0; a<choiceButtons.size(); ++a)
204 delete choiceButtons[a];
205 }
206
207
widget() const208 const Widget xxMultiChoice::widget() const {
209 return button->widget();
210 }
211
212
globalRedraw()213 void xxMultiChoice::globalRedraw() {
214 Arg buttonArgs[4] = {
215 {XtNvisual, (XtArgVal)xxX::visual},
216 {XtNcolormap, (XtArgVal)xxX::colormap},
217 {XtNbackground, (XtArgVal)xxX::pixels[Colors::button]},
218 {XtNforeground, (XtArgVal)xxX::pixels[Colors::foreground]}
219 };
220 assert (button.get());
221 XtSetValues (button->widget(), buttonArgs, 4);
222 assert (menu.get());
223 XtSetValues (menu->widget(), buttonArgs, 4);
224 for (unsigned a=0; a<choiceButtons.size(); ++a)
225 XtSetValues (choiceButtons[a]->widget(), buttonArgs, 4);
226 if (_box.get()) {
227 Arg args[2] = {
228 {XtNbackground, (XtArgVal)xxX::pixels[Colors::background]},
229 {XtNforeground, (XtArgVal)xxX::pixels[Colors::foreground]}
230 };
231 assert (label.get());
232 XtSetValues (label->widget(), args, 2);
233 XtSetValues (_box->widget(), args, 2);
234 }
235 }
236
237 // Cleanup2006 Done
238