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-2025 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
110void
112 if (myCheck == TRUE) {
113 setCheck(FALSE);
114 } else if (myCheck == FALSE) {
115 setCheck(TRUE);
116 } else {
117 setCheck(MAYBE);
118 }
119}
120
121
122FXbool
124 return myCheck;
125}
126
127
128FXColor
130 return myBoxColor;
131}
132
133
134long
135MFXMenuCheckIcon::onCheck(FXObject*, FXSelector, void*) {
136 setCheck(TRUE);
137 return 1;
138}
139
140
141long
142MFXMenuCheckIcon::onUncheck(FXObject*, FXSelector, void*) {
143 setCheck(FALSE);
144 return 1;
145}
146
147
148long
149MFXMenuCheckIcon::onUnknown(FXObject*, FXSelector, void*) {
150 setCheck(MAYBE);
151 return 1;
152}
153
154
155long
156MFXMenuCheckIcon::onCmdSetValue(FXObject*, FXSelector, void* ptr) {
157 setCheck((FXbool)(FXuval)ptr);
158 return 1;
159}
160
161
162long
163MFXMenuCheckIcon::onCmdSetIntValue(FXObject*, FXSelector, void* ptr) {
164 setCheck((FXbool) * ((FXint*)ptr));
165 return 1;
166}
167
168
169long
170MFXMenuCheckIcon::onCmdGetIntValue(FXObject*, FXSelector, void* ptr) {
171 *((FXint*)ptr) = getCheck();
172 return 1;
173}
174
175
176long
177MFXMenuCheckIcon::onButtonPress(FXObject*, FXSelector, void*) {
178 if (!isEnabled()) {
179 return 0;
180 }
181 return 1;
182}
183
184
185long
186MFXMenuCheckIcon::onButtonRelease(FXObject*, FXSelector, void*) {
187 FXbool active = isActive();
188 if (!isEnabled()) {
189 return 0;
190 }
191 // keep menu open
192 //getParent()->handle(this, FXSEL(SEL_COMMAND, ID_UNPOST), NULL);
193 if (active) {
195 if (target) {
196 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)(FXuval)myCheck);
197 }
198 }
199 return 1;
200}
201
202
203long
204MFXMenuCheckIcon::onKeyPress(FXObject*, FXSelector, void* ptr) {
205 FXEvent* event = (FXEvent*)ptr;
206 if (isEnabled() && !(flags & FLAG_PRESSED)) {
207 FXTRACE((200, "%s::onKeyPress %p keysym = 0x%04x state = %04x\n", getClassName(), (void*)this, event->code, event->state));
208 if (event->code == FX::KEY_space || event->code == FX::KEY_KP_Space || event->code == FX::KEY_Return || event->code == FX::KEY_KP_Enter) {
209 flags |= FLAG_PRESSED;
210 return 1;
211 }
212 }
213 return 0;
214}
215
216
217long
218MFXMenuCheckIcon::onKeyRelease(FXObject*, FXSelector, void* ptr) {
219 FXEvent* event = (FXEvent*)ptr;
220 if (isEnabled() && (flags & FLAG_PRESSED)) {
221 FXTRACE((200, "%s::onKeyRelease %p keysym = 0x%04x state = %04x\n", getClassName(), (void*)this, event->code, event->state));
222 if (event->code == FX::KEY_space || event->code == FX::KEY_KP_Space || event->code == FX::KEY_Return || event->code == FX::KEY_KP_Enter) {
223 flags &= ~FLAG_PRESSED;
225 getParent()->handle(this, FXSEL(SEL_COMMAND, ID_UNPOST), NULL);
226 if (target) {
227 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)(FXuval)myCheck);
228 }
229 return 1;
230 }
231 }
232 return 0;
233}
234
235
236long
237MFXMenuCheckIcon::onHotKeyPress(FXObject*, FXSelector, void* ptr) {
238 FXTRACE((200, "%s::onHotKeyPress %p\n", getClassName(), (void*)this));
239 handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
240 if (isEnabled() && !(flags & FLAG_PRESSED)) {
241 flags |= FLAG_PRESSED;
242 }
243 return 1;
244}
245
246
247long
248MFXMenuCheckIcon::onHotKeyRelease(FXObject*, FXSelector, void*) {
249 FXTRACE((200, "%s::onHotKeyRelease %p\n", getClassName(), (void*)this));
250 if (isEnabled() && (flags & FLAG_PRESSED)) {
251 flags &= ~FLAG_PRESSED;
253 getParent()->handle(this, FXSEL(SEL_COMMAND, ID_UNPOST), NULL);
254 if (target) {
255 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)(FXuval)myCheck);
256 }
257 }
258 return 1;
259}
260
261
262long
263MFXMenuCheckIcon::onCmdAccel(FXObject*, FXSelector, void*) {
264 if (isEnabled()) {
266 if (target) {
267 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)(FXuval)myCheck);
268 }
269 return 1;
270 }
271 return 0;
272}
273
274
275long
276MFXMenuCheckIcon::onPaint(FXObject*, FXSelector, void* ptr) {
277 FXEvent* ev = (FXEvent*)ptr;
278 FXDCWindow dc(this, ev);
279 FXint xx, yy;
280 // set xx depending of myIcon
281 if (myIcon) {
282 xx = LEADSPACE + myIcon->getWidth() + 5;
283 } else {
284 xx = LEADSPACE;
285 }
286 // begin draw
287 if (!isEnabled()) {
288 // Grayed out
289 dc.setForeground(backColor);
290 dc.fillRectangle(0, 0, width, height);
291 if (!label.empty()) {
292 yy = font->getFontAscent() + (height - font->getFontHeight()) / 2;
293 dc.setFont(font);
294 dc.setForeground(hiliteColor);
295 dc.drawText(xx + 1, yy + 1, label);
296 if (!accel.empty()) {
297 dc.drawText(width - TRAILSPACE - font->getTextWidth(accel) + 1, yy + 1, accel);
298 }
299 if (0 <= hotoff) {
300 dc.fillRectangle(xx + font->getTextWidth(&label[0], hotoff) + 1, yy + 2, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
301 }
302 dc.setForeground(shadowColor);
303 dc.drawText(xx, yy, label);
304 if (!accel.empty()) {
305 dc.drawText(width - TRAILSPACE - font->getTextWidth(accel), yy, accel);
306 }
307 if (0 <= hotoff) {
308 dc.fillRectangle(xx + font->getTextWidth(&label[0], hotoff), yy + 1, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
309 }
310 }
311 } else if (isActive()) {
312 // Active
313 dc.setForeground(selbackColor);
314 dc.fillRectangle(0, 0, width, height);
315 if (!label.empty()) {
316 yy = font->getFontAscent() + (height - font->getFontHeight()) / 2;
317 dc.setFont(font);
318 dc.setForeground(isEnabled() ? seltextColor : shadowColor);
319 dc.drawText(xx, yy, label);
320 if (!accel.empty()) {
321 dc.drawText(width - TRAILSPACE - font->getTextWidth(accel), yy, accel);
322 }
323 if (0 <= hotoff) {
324 dc.fillRectangle(xx + font->getTextWidth(&label[0], hotoff), yy + 1, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
325 }
326 }
327 } else {
328 // Normal
329 dc.setForeground(backColor);
330 dc.fillRectangle(0, 0, width, height);
331 if (!label.empty()) {
332 yy = font->getFontAscent() + (height - font->getFontHeight()) / 2;
333 dc.setFont(font);
334 dc.setForeground(textColor);
335 dc.drawText(xx, yy, label);
336 if (!accel.empty()) {
337 dc.drawText(width - TRAILSPACE - font->getTextWidth(accel), yy, accel);
338 }
339 if (0 <= hotoff) {
340 dc.fillRectangle(xx + font->getTextWidth(&label[0], hotoff), yy + 1, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
341 }
342 }
343 }
344 // Draw the box
345 xx = 5;
346 yy = (height - 9) / 2;
347 if (!isEnabled()) {
348 dc.setForeground(backColor);
349 } else {
350 dc.setForeground(myBoxColor);
351 dc.fillRectangle(xx + 1, yy + 1, 8, 8);
352 dc.setForeground(shadowColor);
353 dc.drawRectangle(xx, yy, 9, 9);
354 }
355 // Draw the check (tick)
356 if (myCheck != FALSE) {
357 FXSegment seg[6];
358 seg[0].x1 = 2 + (FXshort)xx;
359 seg[0].y1 = 4 + (FXshort)yy;
360 seg[0].x2 = 4 + (FXshort)xx;
361 seg[0].y2 = 6 + (FXshort)yy;
362 seg[1].x1 = 2 + (FXshort)xx;
363 seg[1].y1 = 5 + (FXshort)yy;
364 seg[1].x2 = 4 + (FXshort)xx;
365 seg[1].y2 = 7 + (FXshort)yy;
366 seg[2].x1 = 2 + (FXshort)xx;
367 seg[2].y1 = 6 + (FXshort)yy;
368 seg[2].x2 = 4 + (FXshort)xx;
369 seg[2].y2 = 8 + (FXshort)yy;
370 seg[3].x1 = 4 + (FXshort)xx;
371 seg[3].y1 = 6 + (FXshort)yy;
372 seg[3].x2 = 8 + (FXshort)xx;
373 seg[3].y2 = 2 + (FXshort)yy;
374 seg[4].x1 = 4 + (FXshort)xx;
375 seg[4].y1 = 7 + (FXshort)yy;
376 seg[4].x2 = 8 + (FXshort)xx;
377 seg[4].y2 = 3 + (FXshort)yy;
378 seg[5].x1 = 4 + (FXshort)xx;
379 seg[5].y1 = 8 + (FXshort)yy;
380 seg[5].x2 = 8 + (FXshort)xx;
381 seg[5].y2 = 4 + (FXshort)yy;
382 if (isEnabled()) {
383 if (myCheck == MAYBE) {
384 dc.setForeground(shadowColor);
385 } else {
386 dc.setForeground(textColor);
387 }
388 } else {
389 dc.setForeground(shadowColor);
390 }
391 dc.drawLineSegments(seg, 6);
392 }
393 // draw icon
394 if (myIcon) {
395 if (isEnabled()) {
396 dc.drawIcon(myIcon, LEADSPACE, (height - myIcon->getHeight()) / 2);
397 xx += 5 + myIcon->getWidth();
398 } else {
399 dc.drawIconSunken(myIcon, LEADSPACE, (height - myIcon->getHeight()) / 2);
400 xx += 5 + myIcon->getWidth();
401 }
402 }
403 return 1;
404}
405
406
407void
409 if (clr != myBoxColor) {
410 myBoxColor = clr;
411 update();
412 }
413}
414
415
416void
417MFXMenuCheckIcon::save(FXStream& store) const {
418 FXMenuCommand::save(store);
419 store << myCheck;
420 store << myBoxColor;
421}
422
423
424void MFXMenuCheckIcon::load(FXStream& store) {
425 FXMenuCommand::load(store);
426 store >> myCheck;
427 store >> myBoxColor;
428}
429
430
432 myIcon(nullptr),
433 myCheck(FALSE),
434 myBoxColor(0) {
435}
#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.
void toggleCheck()
Toggle current check state.
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