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)(&currentWidth)}
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