Eclipse SUMO - Simulation of Urban MObility
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 
33 FXDEFMAP(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
55 FXIMPLEMENT(MFXMenuCheckIcon, FXMenuCommand, MFXMenuCheckIconMap, ARRAYNUMBER(MFXMenuCheckIconMap))
56 
57 // ===========================================================================
58 // member method definitions
59 // ===========================================================================
60 
61 MFXMenuCheckIcon::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 
69 FXint
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 
91 FXint
93  FXint th = 0;
94  if (!label.empty() || !accel.empty()) {
95  th = font->getFontHeight() + 5;
96  }
97  return FXMAX(th, 20);
98 }
99 
100 
101 void
103  if (myCheck != s) {
104  myCheck = s;
105  update();
106  }
107 }
108 
109 
110 FXbool
112  return myCheck;
113 }
114 
115 
116 FXColor
118  return myBoxColor;
119 }
120 
121 
122 long
123 MFXMenuCheckIcon::onCheck(FXObject*, FXSelector, void*) {
124  setCheck(TRUE);
125  return 1;
126 }
127 
128 
129 long
130 MFXMenuCheckIcon::onUncheck(FXObject*, FXSelector, void*) {
131  setCheck(FALSE);
132  return 1;
133 }
134 
135 
136 long
137 MFXMenuCheckIcon::onUnknown(FXObject*, FXSelector, void*) {
138  setCheck(MAYBE);
139  return 1;
140 }
141 
142 
143 long
144 MFXMenuCheckIcon::onCmdSetValue(FXObject*, FXSelector, void* ptr) {
145  setCheck((FXbool)(FXuval)ptr);
146  return 1;
147 }
148 
149 
150 long
151 MFXMenuCheckIcon::onCmdSetIntValue(FXObject*, FXSelector, void* ptr) {
152  setCheck((FXbool) * ((FXint*)ptr));
153  return 1;
154 }
155 
156 
157 long
158 MFXMenuCheckIcon::onCmdGetIntValue(FXObject*, FXSelector, void* ptr) {
159  *((FXint*)ptr) = getCheck();
160  return 1;
161 }
162 
163 
164 long
165 MFXMenuCheckIcon::onButtonPress(FXObject*, FXSelector, void*) {
166  if (!isEnabled()) {
167  return 0;
168  }
169  return 1;
170 }
171 
172 
173 long
174 MFXMenuCheckIcon::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) {
181  setCheck(!myCheck);
182  if (target) {
183  target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)(FXuval)myCheck);
184  }
185  }
186  return 1;
187 }
188 
189 
190 long
191 MFXMenuCheckIcon::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 
204 long
205 MFXMenuCheckIcon::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;
211  setCheck(!myCheck);
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 
223 long
224 MFXMenuCheckIcon::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 
234 long
235 MFXMenuCheckIcon::onHotKeyRelease(FXObject*, FXSelector, void*) {
236  FXTRACE((200, "%s::onHotKeyRelease %p\n", getClassName(), (void*)this));
237  if (isEnabled() && (flags & FLAG_PRESSED)) {
238  flags &= ~FLAG_PRESSED;
239  setCheck(!myCheck);
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 
249 long
250 MFXMenuCheckIcon::onCmdAccel(FXObject*, FXSelector, void*) {
251  if (isEnabled()) {
252  setCheck(!myCheck);
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 
262 long
263 MFXMenuCheckIcon::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 
394 void
396  if (clr != myBoxColor) {
397  myBoxColor = clr;
398  update();
399  }
400 }
401 
402 
403 void
404 MFXMenuCheckIcon::save(FXStream& store) const {
405  FXMenuCommand::save(store);
406  store << myCheck;
407  store << myBoxColor;
408 }
409 
410 
411 void 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