Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MFXMenuCheckIcon.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2004-2023 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
18//
19/****************************************************************************/
20
21#include <fxkeys.h>
22
23#include "MFXMenuCheckIcon.h"
24
25
26#define LEADSPACE 22
27#define TRAILSPACE 16
28
29// ===========================================================================
30// FOX callback mapping
31// ===========================================================================
32
33FXDEFMAP(MFXMenuCheckIcon) MFXMenuCheckIconMap[] = {
34 FXMAPFUNC(SEL_PAINT, 0, MFXMenuCheckIcon::onPaint),
35 FXMAPFUNC(SEL_LEFTBUTTONPRESS, 0, MFXMenuCheckIcon::onButtonPress),
36 FXMAPFUNC(SEL_LEFTBUTTONRELEASE, 0, MFXMenuCheckIcon::onButtonRelease),
37 FXMAPFUNC(SEL_MIDDLEBUTTONPRESS, 0, MFXMenuCheckIcon::onButtonPress),
38 FXMAPFUNC(SEL_MIDDLEBUTTONRELEASE, 0, MFXMenuCheckIcon::onButtonRelease),
39 FXMAPFUNC(SEL_RIGHTBUTTONPRESS, 0, MFXMenuCheckIcon::onButtonPress),
40 FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, 0, MFXMenuCheckIcon::onButtonRelease),
41 FXMAPFUNC(SEL_KEYPRESS, 0, MFXMenuCheckIcon::onKeyPress),
42 FXMAPFUNC(SEL_KEYRELEASE, 0, MFXMenuCheckIcon::onKeyRelease),
43 FXMAPFUNC(SEL_KEYPRESS, FXWindow::ID_HOTKEY, MFXMenuCheckIcon::onHotKeyPress),
44 FXMAPFUNC(SEL_KEYRELEASE, FXWindow::ID_HOTKEY, MFXMenuCheckIcon::onHotKeyRelease),
45 FXMAPFUNC(SEL_COMMAND, FXWindow::ID_CHECK, MFXMenuCheckIcon::onCheck),
46 FXMAPFUNC(SEL_COMMAND, FXWindow::ID_UNCHECK, MFXMenuCheckIcon::onUncheck),
47 FXMAPFUNC(SEL_COMMAND, FXWindow::ID_UNKNOWN, MFXMenuCheckIcon::onUnknown),
48 FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETVALUE, MFXMenuCheckIcon::onCmdSetValue),
49 FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETINTVALUE, MFXMenuCheckIcon::onCmdSetIntValue),
50 FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETINTVALUE, MFXMenuCheckIcon::onCmdGetIntValue),
51 FXMAPFUNC(SEL_COMMAND, FXWindow::ID_ACCEL, MFXMenuCheckIcon::onCmdAccel),
52};
53
54// Object implementation
55FXIMPLEMENT(MFXMenuCheckIcon, FXMenuCommand, MFXMenuCheckIconMap, ARRAYNUMBER(MFXMenuCheckIconMap))
56
57// ===========================================================================
58// member method definitions
59// ===========================================================================
60
61MFXMenuCheckIcon::MFXMenuCheckIcon(FXComposite* p, const std::string& text, const std::string& shortcut, const std::string& info, const FXIcon* icon, FXObject* tgt, FXSelector sel, FXuint opts) :
62 FXMenuCommand(p, (text + "\t" + shortcut + "\t" + info).c_str(), NULL, tgt, sel, opts),
63 myIcon(icon),
64 myCheck(FALSE),
65 myBoxColor(getApp()->getBackColor()) {
66}
67
68
69FXint
71 FXint tw, aw;
72 tw = aw = 0;
73 if (!label.empty()) {
74 tw = font->getTextWidth(label.text(), label.length());
75 }
76 if (!accel.empty()) {
77 aw = font->getTextWidth(accel.text(), accel.length());
78 }
79 if (aw && tw) {
80 aw += 5;
81 }
82 // return width depending of icon
83 if (myIcon) {
84 return LEADSPACE + (myIcon->getWidth() + 5) + tw + aw + TRAILSPACE;
85 } else {
86 return LEADSPACE + tw + aw + TRAILSPACE;
87 }
88}
89
90
91FXint
93 FXint th = 0;
94 if (!label.empty() || !accel.empty()) {
95 th = font->getFontHeight() + 5;
96 }
97 return FXMAX(th, 20);
98}
99
100
101void
103 if (myCheck != s) {
104 myCheck = s;
105 update();
106 }
107}
108
109
110FXbool
112 return myCheck;
113}
114
115
116FXColor
118 return myBoxColor;
119}
120
121
122long
123MFXMenuCheckIcon::onCheck(FXObject*, FXSelector, void*) {
124 setCheck(TRUE);
125 return 1;
126}
127
128
129long
130MFXMenuCheckIcon::onUncheck(FXObject*, FXSelector, void*) {
131 setCheck(FALSE);
132 return 1;
133}
134
135
136long
137MFXMenuCheckIcon::onUnknown(FXObject*, FXSelector, void*) {
138 setCheck(MAYBE);
139 return 1;
140}
141
142
143long
144MFXMenuCheckIcon::onCmdSetValue(FXObject*, FXSelector, void* ptr) {
145 setCheck((FXbool)(FXuval)ptr);
146 return 1;
147}
148
149
150long
151MFXMenuCheckIcon::onCmdSetIntValue(FXObject*, FXSelector, void* ptr) {
152 setCheck((FXbool) * ((FXint*)ptr));
153 return 1;
154}
155
156
157long
158MFXMenuCheckIcon::onCmdGetIntValue(FXObject*, FXSelector, void* ptr) {
159 *((FXint*)ptr) = getCheck();
160 return 1;
161}
162
163
164long
165MFXMenuCheckIcon::onButtonPress(FXObject*, FXSelector, void*) {
166 if (!isEnabled()) {
167 return 0;
168 }
169 return 1;
170}
171
172
173long
174MFXMenuCheckIcon::onButtonRelease(FXObject*, FXSelector, void*) {
175 FXbool active = isActive();
176 if (!isEnabled()) {
177 return 0;
178 }
179 getParent()->handle(this, FXSEL(SEL_COMMAND, ID_UNPOST), NULL);
180 if (active) {
182 if (target) {
183 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)(FXuval)myCheck);
184 }
185 }
186 return 1;
187}
188
189
190long
191MFXMenuCheckIcon::onKeyPress(FXObject*, FXSelector, void* ptr) {
192 FXEvent* event = (FXEvent*)ptr;
193 if (isEnabled() && !(flags & FLAG_PRESSED)) {
194 FXTRACE((200, "%s::onKeyPress %p keysym = 0x%04x state = %04x\n", getClassName(), (void*)this, event->code, event->state));
195 if (event->code == FX::KEY_space || event->code == FX::KEY_KP_Space || event->code == FX::KEY_Return || event->code == FX::KEY_KP_Enter) {
196 flags |= FLAG_PRESSED;
197 return 1;
198 }
199 }
200 return 0;
201}
202
203
204long
205MFXMenuCheckIcon::onKeyRelease(FXObject*, FXSelector, void* ptr) {
206 FXEvent* event = (FXEvent*)ptr;
207 if (isEnabled() && (flags & FLAG_PRESSED)) {
208 FXTRACE((200, "%s::onKeyRelease %p keysym = 0x%04x state = %04x\n", getClassName(), (void*)this, event->code, event->state));
209 if (event->code == FX::KEY_space || event->code == FX::KEY_KP_Space || event->code == FX::KEY_Return || event->code == FX::KEY_KP_Enter) {
210 flags &= ~FLAG_PRESSED;
212 getParent()->handle(this, FXSEL(SEL_COMMAND, ID_UNPOST), NULL);
213 if (target) {
214 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)(FXuval)myCheck);
215 }
216 return 1;
217 }
218 }
219 return 0;
220}
221
222
223long
224MFXMenuCheckIcon::onHotKeyPress(FXObject*, FXSelector, void* ptr) {
225 FXTRACE((200, "%s::onHotKeyPress %p\n", getClassName(), (void*)this));
226 handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
227 if (isEnabled() && !(flags & FLAG_PRESSED)) {
228 flags |= FLAG_PRESSED;
229 }
230 return 1;
231}
232
233
234long
235MFXMenuCheckIcon::onHotKeyRelease(FXObject*, FXSelector, void*) {
236 FXTRACE((200, "%s::onHotKeyRelease %p\n", getClassName(), (void*)this));
237 if (isEnabled() && (flags & FLAG_PRESSED)) {
238 flags &= ~FLAG_PRESSED;
240 getParent()->handle(this, FXSEL(SEL_COMMAND, ID_UNPOST), NULL);
241 if (target) {
242 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)(FXuval)myCheck);
243 }
244 }
245 return 1;
246}
247
248
249long
250MFXMenuCheckIcon::onCmdAccel(FXObject*, FXSelector, void*) {
251 if (isEnabled()) {
253 if (target) {
254 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)(FXuval)myCheck);
255 }
256 return 1;
257 }
258 return 0;
259}
260
261
262long
263MFXMenuCheckIcon::onPaint(FXObject*, FXSelector, void* ptr) {
264 FXEvent* ev = (FXEvent*)ptr;
265 FXDCWindow dc(this, ev);
266 FXint xx, yy;
267 // set xx depending of myIcon
268 if (myIcon) {
269 xx = LEADSPACE + myIcon->getWidth() + 5;
270 } else {
271 xx = LEADSPACE;
272 }
273 // begin draw
274 if (!isEnabled()) {
275 // Grayed out
276 dc.setForeground(backColor);
277 dc.fillRectangle(0, 0, width, height);
278 if (!label.empty()) {
279 yy = font->getFontAscent() + (height - font->getFontHeight()) / 2;
280 dc.setFont(font);
281 dc.setForeground(hiliteColor);
282 dc.drawText(xx + 1, yy + 1, label);
283 if (!accel.empty()) {
284 dc.drawText(width - TRAILSPACE - font->getTextWidth(accel) + 1, yy + 1, accel);
285 }
286 if (0 <= hotoff) {
287 dc.fillRectangle(xx + font->getTextWidth(&label[0], hotoff) + 1, yy + 2, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
288 }
289 dc.setForeground(shadowColor);
290 dc.drawText(xx, yy, label);
291 if (!accel.empty()) {
292 dc.drawText(width - TRAILSPACE - font->getTextWidth(accel), yy, accel);
293 }
294 if (0 <= hotoff) {
295 dc.fillRectangle(xx + font->getTextWidth(&label[0], hotoff), yy + 1, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
296 }
297 }
298 } else if (isActive()) {
299 // Active
300 dc.setForeground(selbackColor);
301 dc.fillRectangle(0, 0, width, height);
302 if (!label.empty()) {
303 yy = font->getFontAscent() + (height - font->getFontHeight()) / 2;
304 dc.setFont(font);
305 dc.setForeground(isEnabled() ? seltextColor : shadowColor);
306 dc.drawText(xx, yy, label);
307 if (!accel.empty()) {
308 dc.drawText(width - TRAILSPACE - font->getTextWidth(accel), yy, accel);
309 }
310 if (0 <= hotoff) {
311 dc.fillRectangle(xx + font->getTextWidth(&label[0], hotoff), yy + 1, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
312 }
313 }
314 } else {
315 // Normal
316 dc.setForeground(backColor);
317 dc.fillRectangle(0, 0, width, height);
318 if (!label.empty()) {
319 yy = font->getFontAscent() + (height - font->getFontHeight()) / 2;
320 dc.setFont(font);
321 dc.setForeground(textColor);
322 dc.drawText(xx, yy, label);
323 if (!accel.empty()) {
324 dc.drawText(width - TRAILSPACE - font->getTextWidth(accel), yy, accel);
325 }
326 if (0 <= hotoff) {
327 dc.fillRectangle(xx + font->getTextWidth(&label[0], hotoff), yy + 1, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
328 }
329 }
330 }
331 // Draw the box
332 xx = 5;
333 yy = (height - 9) / 2;
334 if (!isEnabled()) {
335 dc.setForeground(backColor);
336 } else {
337 dc.setForeground(myBoxColor);
338 dc.fillRectangle(xx + 1, yy + 1, 8, 8);
339 dc.setForeground(shadowColor);
340 dc.drawRectangle(xx, yy, 9, 9);
341 }
342 // Draw the check (tick)
343 if (myCheck != FALSE) {
344 FXSegment seg[6];
345 seg[0].x1 = 2 + (FXshort)xx;
346 seg[0].y1 = 4 + (FXshort)yy;
347 seg[0].x2 = 4 + (FXshort)xx;
348 seg[0].y2 = 6 + (FXshort)yy;
349 seg[1].x1 = 2 + (FXshort)xx;
350 seg[1].y1 = 5 + (FXshort)yy;
351 seg[1].x2 = 4 + (FXshort)xx;
352 seg[1].y2 = 7 + (FXshort)yy;
353 seg[2].x1 = 2 + (FXshort)xx;
354 seg[2].y1 = 6 + (FXshort)yy;
355 seg[2].x2 = 4 + (FXshort)xx;
356 seg[2].y2 = 8 + (FXshort)yy;
357 seg[3].x1 = 4 + (FXshort)xx;
358 seg[3].y1 = 6 + (FXshort)yy;
359 seg[3].x2 = 8 + (FXshort)xx;
360 seg[3].y2 = 2 + (FXshort)yy;
361 seg[4].x1 = 4 + (FXshort)xx;
362 seg[4].y1 = 7 + (FXshort)yy;
363 seg[4].x2 = 8 + (FXshort)xx;
364 seg[4].y2 = 3 + (FXshort)yy;
365 seg[5].x1 = 4 + (FXshort)xx;
366 seg[5].y1 = 8 + (FXshort)yy;
367 seg[5].x2 = 8 + (FXshort)xx;
368 seg[5].y2 = 4 + (FXshort)yy;
369 if (isEnabled()) {
370 if (myCheck == MAYBE) {
371 dc.setForeground(shadowColor);
372 } else {
373 dc.setForeground(textColor);
374 }
375 } else {
376 dc.setForeground(shadowColor);
377 }
378 dc.drawLineSegments(seg, 6);
379 }
380 // draw icon
381 if (myIcon) {
382 if (isEnabled()) {
383 dc.drawIcon(myIcon, LEADSPACE, (height - myIcon->getHeight()) / 2);
384 xx += 5 + myIcon->getWidth();
385 } else {
386 dc.drawIconSunken(myIcon, LEADSPACE, (height - myIcon->getHeight()) / 2);
387 xx += 5 + myIcon->getWidth();
388 }
389 }
390 return 1;
391}
392
393
394void
396 if (clr != myBoxColor) {
397 myBoxColor = clr;
398 update();
399 }
400}
401
402
403void
404MFXMenuCheckIcon::save(FXStream& store) const {
405 FXMenuCommand::save(store);
406 store << myCheck;
407 store << myBoxColor;
408}
409
410
411void MFXMenuCheckIcon::load(FXStream& store) {
412 FXMenuCommand::load(store);
413 store >> myCheck;
414 store >> myBoxColor;
415}
416
417
419 myIcon(nullptr),
420 myCheck(FALSE),
421 myBoxColor(0) {
422}
#define LEADSPACE
#define TRAILSPACE
FXDEFMAP(MFXMenuCheckIcon) MFXMenuCheckIconMap[]
long onHotKeyPress(FXObject *, FXSelector, void *)
long onUnknown(FXObject *, FXSelector, void *)
long onKeyRelease(FXObject *, FXSelector, void *)
void setBoxColor(FXColor clr)
Set the box background color.
virtual void load(FXStream &store)
Load menu from a stream.
MFXMenuCheckIcon()
default constructor
long onCheck(FXObject *, FXSelector, void *)
long onCmdSetIntValue(FXObject *, FXSelector, void *)
virtual FXint getDefaultWidth()
Return default width.
long onHotKeyRelease(FXObject *, FXSelector, void *)
FXColor myBoxColor
Box color.
long onCmdAccel(FXObject *, FXSelector, void *)
long onButtonPress(FXObject *, FXSelector, void *)
const FXIcon * myIcon
Icon.
long onCmdSetValue(FXObject *, FXSelector, void *)
FXColor getBoxColor() const
Get the box background color.
FXuchar myCheck
State of menu.
long onUncheck(FXObject *, FXSelector, void *)
long onKeyPress(FXObject *, FXSelector, void *)
long onPaint(FXObject *, FXSelector, void *)
virtual void save(FXStream &store) const
Save menu to a stream.
FXbool getCheck() const
Get check state (TRUE, FALSE or MAYBE)
long onCmdGetIntValue(FXObject *, FXSelector, void *)
virtual FXint getDefaultHeight()
Return default height.
long onButtonRelease(FXObject *, FXSelector, void *)
void setCheck(FXbool s=TRUE)
Set check state (TRUE, FALSE or MAYBE)
Definition json.hpp:4471