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-2024 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 // keep menu open
180 //getParent()->handle(this, FXSEL(SEL_COMMAND, ID_UNPOST), NULL);
181 if (active) {
183 if (target) {
184 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)(FXuval)myCheck);
185 }
186 }
187 return 1;
188}
189
190
191long
192MFXMenuCheckIcon::onKeyPress(FXObject*, FXSelector, void* ptr) {
193 FXEvent* event = (FXEvent*)ptr;
194 if (isEnabled() && !(flags & FLAG_PRESSED)) {
195 FXTRACE((200, "%s::onKeyPress %p keysym = 0x%04x state = %04x\n", getClassName(), (void*)this, event->code, event->state));
196 if (event->code == FX::KEY_space || event->code == FX::KEY_KP_Space || event->code == FX::KEY_Return || event->code == FX::KEY_KP_Enter) {
197 flags |= FLAG_PRESSED;
198 return 1;
199 }
200 }
201 return 0;
202}
203
204
205long
206MFXMenuCheckIcon::onKeyRelease(FXObject*, FXSelector, void* ptr) {
207 FXEvent* event = (FXEvent*)ptr;
208 if (isEnabled() && (flags & FLAG_PRESSED)) {
209 FXTRACE((200, "%s::onKeyRelease %p keysym = 0x%04x state = %04x\n", getClassName(), (void*)this, event->code, event->state));
210 if (event->code == FX::KEY_space || event->code == FX::KEY_KP_Space || event->code == FX::KEY_Return || event->code == FX::KEY_KP_Enter) {
211 flags &= ~FLAG_PRESSED;
213 getParent()->handle(this, FXSEL(SEL_COMMAND, ID_UNPOST), NULL);
214 if (target) {
215 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)(FXuval)myCheck);
216 }
217 return 1;
218 }
219 }
220 return 0;
221}
222
223
224long
225MFXMenuCheckIcon::onHotKeyPress(FXObject*, FXSelector, void* ptr) {
226 FXTRACE((200, "%s::onHotKeyPress %p\n", getClassName(), (void*)this));
227 handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
228 if (isEnabled() && !(flags & FLAG_PRESSED)) {
229 flags |= FLAG_PRESSED;
230 }
231 return 1;
232}
233
234
235long
236MFXMenuCheckIcon::onHotKeyRelease(FXObject*, FXSelector, void*) {
237 FXTRACE((200, "%s::onHotKeyRelease %p\n", getClassName(), (void*)this));
238 if (isEnabled() && (flags & FLAG_PRESSED)) {
239 flags &= ~FLAG_PRESSED;
241 getParent()->handle(this, FXSEL(SEL_COMMAND, ID_UNPOST), NULL);
242 if (target) {
243 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)(FXuval)myCheck);
244 }
245 }
246 return 1;
247}
248
249
250long
251MFXMenuCheckIcon::onCmdAccel(FXObject*, FXSelector, void*) {
252 if (isEnabled()) {
254 if (target) {
255 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)(FXuval)myCheck);
256 }
257 return 1;
258 }
259 return 0;
260}
261
262
263long
264MFXMenuCheckIcon::onPaint(FXObject*, FXSelector, void* ptr) {
265 FXEvent* ev = (FXEvent*)ptr;
266 FXDCWindow dc(this, ev);
267 FXint xx, yy;
268 // set xx depending of myIcon
269 if (myIcon) {
270 xx = LEADSPACE + myIcon->getWidth() + 5;
271 } else {
272 xx = LEADSPACE;
273 }
274 // begin draw
275 if (!isEnabled()) {
276 // Grayed out
277 dc.setForeground(backColor);
278 dc.fillRectangle(0, 0, width, height);
279 if (!label.empty()) {
280 yy = font->getFontAscent() + (height - font->getFontHeight()) / 2;
281 dc.setFont(font);
282 dc.setForeground(hiliteColor);
283 dc.drawText(xx + 1, yy + 1, label);
284 if (!accel.empty()) {
285 dc.drawText(width - TRAILSPACE - font->getTextWidth(accel) + 1, yy + 1, accel);
286 }
287 if (0 <= hotoff) {
288 dc.fillRectangle(xx + font->getTextWidth(&label[0], hotoff) + 1, yy + 2, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
289 }
290 dc.setForeground(shadowColor);
291 dc.drawText(xx, yy, label);
292 if (!accel.empty()) {
293 dc.drawText(width - TRAILSPACE - font->getTextWidth(accel), yy, accel);
294 }
295 if (0 <= hotoff) {
296 dc.fillRectangle(xx + font->getTextWidth(&label[0], hotoff), yy + 1, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
297 }
298 }
299 } else if (isActive()) {
300 // Active
301 dc.setForeground(selbackColor);
302 dc.fillRectangle(0, 0, width, height);
303 if (!label.empty()) {
304 yy = font->getFontAscent() + (height - font->getFontHeight()) / 2;
305 dc.setFont(font);
306 dc.setForeground(isEnabled() ? seltextColor : shadowColor);
307 dc.drawText(xx, yy, label);
308 if (!accel.empty()) {
309 dc.drawText(width - TRAILSPACE - font->getTextWidth(accel), yy, accel);
310 }
311 if (0 <= hotoff) {
312 dc.fillRectangle(xx + font->getTextWidth(&label[0], hotoff), yy + 1, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
313 }
314 }
315 } else {
316 // Normal
317 dc.setForeground(backColor);
318 dc.fillRectangle(0, 0, width, height);
319 if (!label.empty()) {
320 yy = font->getFontAscent() + (height - font->getFontHeight()) / 2;
321 dc.setFont(font);
322 dc.setForeground(textColor);
323 dc.drawText(xx, yy, label);
324 if (!accel.empty()) {
325 dc.drawText(width - TRAILSPACE - font->getTextWidth(accel), yy, accel);
326 }
327 if (0 <= hotoff) {
328 dc.fillRectangle(xx + font->getTextWidth(&label[0], hotoff), yy + 1, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
329 }
330 }
331 }
332 // Draw the box
333 xx = 5;
334 yy = (height - 9) / 2;
335 if (!isEnabled()) {
336 dc.setForeground(backColor);
337 } else {
338 dc.setForeground(myBoxColor);
339 dc.fillRectangle(xx + 1, yy + 1, 8, 8);
340 dc.setForeground(shadowColor);
341 dc.drawRectangle(xx, yy, 9, 9);
342 }
343 // Draw the check (tick)
344 if (myCheck != FALSE) {
345 FXSegment seg[6];
346 seg[0].x1 = 2 + (FXshort)xx;
347 seg[0].y1 = 4 + (FXshort)yy;
348 seg[0].x2 = 4 + (FXshort)xx;
349 seg[0].y2 = 6 + (FXshort)yy;
350 seg[1].x1 = 2 + (FXshort)xx;
351 seg[1].y1 = 5 + (FXshort)yy;
352 seg[1].x2 = 4 + (FXshort)xx;
353 seg[1].y2 = 7 + (FXshort)yy;
354 seg[2].x1 = 2 + (FXshort)xx;
355 seg[2].y1 = 6 + (FXshort)yy;
356 seg[2].x2 = 4 + (FXshort)xx;
357 seg[2].y2 = 8 + (FXshort)yy;
358 seg[3].x1 = 4 + (FXshort)xx;
359 seg[3].y1 = 6 + (FXshort)yy;
360 seg[3].x2 = 8 + (FXshort)xx;
361 seg[3].y2 = 2 + (FXshort)yy;
362 seg[4].x1 = 4 + (FXshort)xx;
363 seg[4].y1 = 7 + (FXshort)yy;
364 seg[4].x2 = 8 + (FXshort)xx;
365 seg[4].y2 = 3 + (FXshort)yy;
366 seg[5].x1 = 4 + (FXshort)xx;
367 seg[5].y1 = 8 + (FXshort)yy;
368 seg[5].x2 = 8 + (FXshort)xx;
369 seg[5].y2 = 4 + (FXshort)yy;
370 if (isEnabled()) {
371 if (myCheck == MAYBE) {
372 dc.setForeground(shadowColor);
373 } else {
374 dc.setForeground(textColor);
375 }
376 } else {
377 dc.setForeground(shadowColor);
378 }
379 dc.drawLineSegments(seg, 6);
380 }
381 // draw icon
382 if (myIcon) {
383 if (isEnabled()) {
384 dc.drawIcon(myIcon, LEADSPACE, (height - myIcon->getHeight()) / 2);
385 xx += 5 + myIcon->getWidth();
386 } else {
387 dc.drawIconSunken(myIcon, LEADSPACE, (height - myIcon->getHeight()) / 2);
388 xx += 5 + myIcon->getWidth();
389 }
390 }
391 return 1;
392}
393
394
395void
397 if (clr != myBoxColor) {
398 myBoxColor = clr;
399 update();
400 }
401}
402
403
404void
405MFXMenuCheckIcon::save(FXStream& store) const {
406 FXMenuCommand::save(store);
407 store << myCheck;
408 store << myBoxColor;
409}
410
411
412void MFXMenuCheckIcon::load(FXStream& store) {
413 FXMenuCommand::load(store);
414 store >> myCheck;
415 store >> myBoxColor;
416}
417
418
420 myIcon(nullptr),
421 myCheck(FALSE),
422 myBoxColor(0) {
423}
#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