Eclipse SUMO - Simulation of Urban MObility
FXSevenSegment.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2004-2022 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 /****************************************************************************/
20 //
21 /****************************************************************************/
22 
23 
24 /* =========================================================================
25  * included modules
26  * ======================================================================= */
27 #include <config.h>
28 
29 #define NOMINMAX
30 #undef NOMINMAX
31 #include "fxheader.h"
32 /*
33 #include <FXStream.h>
34 #include <FXString.h>
35 #include <FXSize.h>
36 #include <FXPoint.h>
37 #include <FXRectangle.h>
38 #include <FXRegistry.h>
39 #include <FXHash.h>
40 #include <FXApp.h>
41 #include <FXDCWindow.h>
42 */
43 using namespace FX;
44 #include "FXSevenSegment.h"
45 
46 using namespace FXEX;
47 namespace FXEX {
48 
49 /* note: this class may change into FXLCDsegment, so as to support 7 or 14 segment display */
50 #define ASCII_ZERO 48
51 
52 // map
53 FXDEFMAP(FXSevenSegment) FXSevenSegmentMap[] = {
54  FXMAPFUNC(SEL_PAINT, 0, FXSevenSegment::onPaint),
55  FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETVALUE, FXSevenSegment::onCmdSetValue),
56  FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETINTVALUE, FXSevenSegment::onCmdSetIntValue),
57  FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETINTVALUE, FXSevenSegment::onCmdGetIntValue),
58  FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETSTRINGVALUE, FXSevenSegment::onCmdSetStringValue),
59  FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETSTRINGVALUE, FXSevenSegment::onCmdGetStringValue),
60  // FXMAPFUNC(SEL_UPDATE,FXWindow::ID_QUERY_TIP,FXSevenSegment::onQueryTip),
61  // FXMAPFUNC(SEL_UPDATE,FXWindow::ID_QUERY_HELP,FXSevenSegment::onQueryHelp),
62 };
63 FXIMPLEMENT(FXSevenSegment, FXFrame, FXSevenSegmentMap, ARRAYNUMBER(FXSevenSegmentMap))
64 
65 // ctor
66 FXSevenSegment::FXSevenSegment(FXComposite* p, FXObject* tgt, FXSelector sel, FXuint opts, FXint pl, FXint pr, FXint pt, FXint pb) : FXFrame(p, opts, 0, 0, 0, 0, pl, pr, pt, pb), value(' '), fgcolor(FXRGB(0, 255, 0)), bgcolor(FXRGB(0, 0, 0)), hsl(8), vsl(8), st(3), groove(1) {
67  setTarget(tgt);
68  setSelector(sel);
69  enable();
70 }
71 
72 // minimum width
73 FXint FXSevenSegment::getDefaultWidth() {
74  return padleft + (groove << 1) + hsl + padright + (border << 1);
75 }
76 
77 // minimum height
78 FXint FXSevenSegment::getDefaultHeight() {
79  return padtop + (groove << 2) + (vsl << 1) + padbottom + (border << 1);
80 }
81 
82 // set value on widget
83 void FXSevenSegment::setText(FXchar val) {
84  if (FXString(val, 1).upper() != FXString(value, 1).upper()) {
85  value = val;
86  recalc();
87  update();
88  }
89 }
90 
91 // set foreground color
92 void FXSevenSegment::setFgColor(const FXColor clr) {
93  if (fgcolor != clr) {
94  fgcolor = clr;
95  recalc();
96  update();
97  }
98 }
99 
100 // set backgound color
101 void FXSevenSegment::setBgColor(const FXColor clr) {
102  if (bgcolor != clr) {
103  bgcolor = clr;
104  recalc();
105  update();
106  }
107 }
108 
109 // set horizontal segment length
110 void FXSevenSegment::setHorizontal(const FXint len) {
111  if (len != hsl) {
112  hsl = (FXshort)len;
113  checkSize();
114  recalc();
115  update();
116  }
117 }
118 
119 // set vertical segment length
120 void FXSevenSegment::setVertical(const FXint len) {
121  if (len != vsl) {
122  vsl = (FXshort)len;
123  checkSize();
124  recalc();
125  update();
126  }
127 }
128 
129 // set segment thickness
130 void FXSevenSegment::setThickness(const FXint w) {
131  if (w != st) {
132  st = (FXshort)w;
133  checkSize();
134  recalc();
135  update();
136  }
137 }
138 
139 // set groove thickness
140 void FXSevenSegment::setGroove(const FXint w) {
141  if (w != groove) {
142  groove = (FXshort)w;
143  checkSize();
144  recalc();
145  update();
146  }
147 }
148 
149 // draw/redraw object
150 long FXSevenSegment::onPaint(FXObject*, FXSelector, void* ptr) {
151  FXEvent* event = (FXEvent*) ptr;
152  FXDCWindow dc(this, event);
153  drawFrame(dc, 0, 0, width, height);
154  dc.setForeground(bgcolor);
155  dc.fillRectangle(border, border, width - (border << 1), height - (border << 1));
156  dc.setForeground(fgcolor);
157  drawFigure(dc, value);
158  return 1;
159 }
160 
161 // set from value
162 long FXSevenSegment::onCmdSetValue(FXObject*, FXSelector, void* ptr) {
163  FXchar* c = (FXchar*)ptr;
164  if (c[0] != '\0') {
165  setText(c[0]);
166  }
167  return 1;
168 }
169 
170 // get value from int
171 long FXSevenSegment::onCmdGetIntValue(FXObject* sender, FXSelector, void*) {
172  FXint i = value - ASCII_ZERO;
173  if (i < 0) {
174  i = 0;
175  }
176  if (i > 9) {
177  i = 9;
178  }
179  sender->handle(this, FXSEL(SEL_COMMAND, ID_SETINTVALUE), (void*)&i);
180  return 1;
181 }
182 
183 // set from int value
184 long FXSevenSegment::onCmdSetIntValue(FXObject*, FXSelector, void* ptr) {
185  FXint i = *((FXint*)ptr);
186  if (i < 0) {
187  i = 0;
188  }
189  if (i > 9) {
190  i = 9;
191  }
192  setText((FXchar)(i + ASCII_ZERO));
193  return 1;
194 }
195 
196 // get value from string
197 long FXSevenSegment::onCmdGetStringValue(FXObject* sender, FXSelector, void*) {
198  FXString s(value, 1);
199  sender->handle(this, FXSEL(SEL_COMMAND, ID_SETSTRINGVALUE), (void*)&s);
200  return 1;
201 }
202 
203 // set from string value
204 long FXSevenSegment::onCmdSetStringValue(FXObject*, FXSelector, void* ptr) {
205  FXString* s = (FXString*)ptr;
206  if ((*s).length()) {
207  setText((*s)[0]);
208  }
209  return 1;
210 }
211 
212 // draw the specific character - figure out which segments to draw
213 void FXSevenSegment::drawFigure(FXDCWindow& dc, FXchar figure) {
214  switch (figure) {
215  case ' ' :
216  drawSegments(dc, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE);
217  break;
218  case '(' :
219  drawSegments(dc, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE);
220  break;
221  case ')' :
222  drawSegments(dc, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE);
223  break;
224  case '[' :
225  drawSegments(dc, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE);
226  break;
227  case ']' :
228  drawSegments(dc, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE);
229  break;
230  case '=' :
231  drawSegments(dc, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE);
232  break;
233 // case '+' : drawSegments (dc, FALSE,FALSE,FALSE,TRUE ,FALSE,FALSE,FALSE); break;
234  case '-' :
235  case ':' :
236  drawSegments(dc, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE);
237  break;
238  case '_' :
239  case '.' :
240  case ',' :
241  drawSegments(dc, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE);
242  break;
243  case '0' :
244  drawSegments(dc, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE);
245  break;
246  case '1' :
247  drawSegments(dc, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE);
248  break;
249  case '2' :
250  drawSegments(dc, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE);
251  break;
252  case '3' :
253  drawSegments(dc, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE);
254  break;
255  case '4' :
256  drawSegments(dc, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE);
257  break;
258  case '5' :
259  drawSegments(dc, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE);
260  break;
261  case '6' :
262  drawSegments(dc, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE);
263  break;
264  case '7' :
265  drawSegments(dc, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE);
266  break;
267  case '8' :
268  drawSegments(dc, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
269  break;
270  case '9' :
271  drawSegments(dc, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE);
272  break;
273  case 'a' :
274  case 'A' :
275  drawSegments(dc, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE);
276  break;
277  case 'b' :
278  case 'B' :
279  drawSegments(dc, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE);
280  break;
281  case 'c' :
282  case 'C' :
283  drawSegments(dc, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE);
284  break;
285  case 'd' :
286  case 'D' :
287  drawSegments(dc, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE);
288  break;
289  case 'e' :
290  case 'E' :
291  drawSegments(dc, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE);
292  break;
293  case 'f' :
294  case 'F' :
295  drawSegments(dc, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE);
296  break;
297  case 'g' :
298  case 'G' :
299  drawSegments(dc, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE);
300  break;
301  case 'h' :
302  case 'H' :
303  drawSegments(dc, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE);
304  break;
305  case 'i' :
306  case 'I' :
307  drawSegments(dc, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
308  break;
309  case 'j' :
310  case 'J' :
311  drawSegments(dc, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE);
312  break;
313 // case 'k' :
314 // case 'k' : drawSegments (dc, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE); break;
315  case 'l' :
316  case 'L' :
317  drawSegments(dc, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE);
318  break;
319 // case 'm' :
320 // case 'M' : drawSegments (dc, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE); break;
321  case 'n' :
322  case 'N' :
323  drawSegments(dc, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE);
324  break;
325  case 'o' :
326  case 'O' :
327  drawSegments(dc, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE);
328  break;
329  case 'p' :
330  case 'P' :
331  drawSegments(dc, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE);
332  break;
333  case 'q' :
334  case 'Q' :
335  drawSegments(dc, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE);
336  break;
337  case 'r' :
338  case 'R' :
339  drawSegments(dc, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE);
340  break;
341  case 's' :
342  case 'S' :
343  drawSegments(dc, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE);
344  break;
345  case 't' :
346  case 'T' :
347  drawSegments(dc, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE);
348  break;
349  case 'u' :
350  case 'U' :
351  drawSegments(dc, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE);
352  break;
353 // case 'v' :
354 // case 'V' : drawSegments (dc, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE); break;
355 // case 'w' :
356 // case 'W' : drawSegments (dc, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE); break;
357  case 'x' :
358  case 'X' :
359  drawSegments(dc, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE);
360  break;
361  case 'y' :
362  case 'Y' :
363  drawSegments(dc, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE);
364  break;
365 // case 'z' :
366 // case 'Z' :
367  default :
368  fxerror("FXSevenSegment doesnt support: %c\n", figure);
369  }
370 }
371 
372 // validates the sizes of the segment dimensions
373 void FXSevenSegment::checkSize() {
374  if (hsl < 3) {
375  hsl = 3;
376  st = 1;
377  }
378  if (vsl < 3) {
379  vsl = 3;
380  st = 1;
381  }
382  if (st < 1) {
383  st = 1;
384  }
385  if (hsl < (st << 1)) {
386  hsl = (st << 1) + 1;
387  }
388  if (vsl < (st << 1)) {
389  vsl = (st << 1) + 1;
390  }
391  if (hsl < 8 || vsl < 8) {
392  groove = 2;
393  }
394  if (hsl < 1 || vsl < 3 || st < 3) {
395  groove = 1;
396  }
397  if (groove >= st) {
398  groove = st - 1;
399  }
400 }
401 
402 // draw each segment, into the available drawing space
403 // if widget is resizeable, caculate new sizes for length/width/grove of each segment
404 void FXSevenSegment::drawSegments(FXDCWindow& dc, FXbool s1, FXbool s2, FXbool s3, FXbool s4, FXbool s5, FXbool s6, FXbool s7) {
405  FXshort sx = (FXshort)(border + padleft), sy = (FXshort)(border + padtop);
406  FXshort x, y;
407  if (options & LAYOUT_FILL) {
408  if (options & LAYOUT_FILL_X) {
409  hsl = (FXshort)(width - padleft - padright - (border << 1));
410  if (hsl < 4) {
411  hsl = 4;
412  }
413  }
414  if (options & LAYOUT_FILL_Y) {
415  vsl = (FXshort)(height - padtop - padbottom - (border << 1)) >> 1;
416  if (vsl < 4) {
417  vsl = 4;
418  }
419  }
420  st = FXMIN(hsl, vsl) / 4;
421  groove = st / 4;
422  if (st < 1) {
423  st = 1;
424  }
425  if (groove < 1) {
426  groove = 1;
427  }
428  if (options & LAYOUT_FILL_X) {
429  hsl -= groove << 1;
430  }
431  if (options & LAYOUT_FILL_Y) {
432  vsl -= groove << 1;
433  }
434  }
435  if (s1) {
436  x = sx + groove;
437  y = sy;
438  drawTopSegment(dc, x, y);
439  }
440  if (s2) {
441  x = sx;
442  y = sy + groove;
443  drawLeftTopSegment(dc, x, y);
444  }
445  if (s3) {
446  x = sx + groove + hsl - st + groove;
447  y = sy + groove;
448  drawRightTopSegment(dc, x, y);
449  }
450  if (s4) {
451  x = sx + groove;
452  y = sy + groove + vsl - (st >> 1) + groove;
453  drawMiddleSegment(dc, x, y);
454  }
455  if (s5) {
456  x = sx;
457  y = sy + (groove << 1) + vsl + groove;
458  drawLeftBottomSegment(dc, x, y);
459  }
460  if (s6) {
461  x = sx + groove + hsl - st + groove;
462  y = sy + (groove << 1) + vsl + groove;
463  drawRightBottomSegment(dc, x, y);
464  }
465  if (s7) {
466  x = sx + groove;
467  y = sy + (groove << 1) + vsl + groove + vsl + groove - st;
468  drawBottomSegment(dc, x, y);
469  }
470 }
471 
472 void FXSevenSegment::drawTopSegment(FXDCWindow& dc, FXshort x, FXshort y) {
473  FXPoint points[4];
474  points[0].x = x;
475  points[0].y = y;
476  points[1].x = x + hsl;
477  points[1].y = y;
478  points[2].x = x + hsl - st;
479  points[2].y = y + st;
480  points[3].x = x + st;
481  points[3].y = y + st;
482  dc.fillPolygon(points, 4);
483 }
484 
485 void FXSevenSegment::drawLeftTopSegment(FXDCWindow& dc, FXshort x, FXshort y) {
486  FXPoint points[4];
487  points[0].x = x;
488  points[0].y = y;
489  points[1].x = x + st;
490  points[1].y = y + st;
491  points[2].x = x + st;
492  points[2].y = y + vsl - (st >> 1);
493  points[3].x = x;
494  points[3].y = y + vsl;
495  dc.fillPolygon(points, 4);
496 }
497 
498 void FXSevenSegment::drawRightTopSegment(FXDCWindow& dc, FXshort x, FXshort y) {
499  FXPoint points[4];
500  points[0].x = x + st;
501  points[0].y = y;
502  points[1].x = x + st;
503  points[1].y = y + vsl;
504  points[2].x = x;
505  points[2].y = y + vsl - (st >> 1);
506  points[3].x = x;
507  points[3].y = y + st;
508  dc.fillPolygon(points, 4);
509 }
510 
511 void FXSevenSegment::drawMiddleSegment(FXDCWindow& dc, FXshort x, FXshort y) {
512  FXPoint points[6];
513  points[0].x = x + st;
514  points[0].y = y;
515  points[1].x = x + hsl - st;
516  points[1].y = y;
517  points[2].x = x + hsl;
518  points[2].y = y + (st >> 1);
519  points[3].x = x + hsl - st;
520  points[3].y = y + st;
521  points[4].x = x + st;
522  points[4].y = y + st;
523  points[5].x = x;
524  points[5].y = y + (st >> 1);
525  dc.fillPolygon(points, 6);
526 }
527 
528 void FXSevenSegment::drawLeftBottomSegment(FXDCWindow& dc, FXshort x, FXshort y) {
529  FXPoint points[4];
530  points[0].x = x;
531  points[0].y = y;
532  points[1].x = x + st;
533  points[1].y = y + (st >> 1);
534  points[2].x = x + st;
535  points[2].y = y + vsl - st;
536  points[3].x = x;
537  points[3].y = y + vsl;
538  dc.fillPolygon(points, 4);
539 }
540 
541 void FXSevenSegment::drawRightBottomSegment(FXDCWindow& dc, FXshort x, FXshort y) {
542  FXPoint points[4];
543  points[0].x = x + st;
544  points[0].y = y;
545  points[1].x = x + st;
546  points[1].y = y + vsl;
547  points[2].x = x;
548  points[2].y = y + vsl - st;
549  points[3].x = x;
550  points[3].y = y + (st >> 1);
551  dc.fillPolygon(points, 4);
552 }
553 
554 void FXSevenSegment::drawBottomSegment(FXDCWindow& dc, FXshort x, FXshort y) {
555  FXPoint points[4];
556  points[0].x = x + st;
557  points[0].y = y;
558  points[1].x = x + hsl - st;
559  points[1].y = y;
560  points[2].x = x + hsl;
561  points[2].y = y + st;
562  points[3].x = x;
563  points[3].y = y + st;
564  dc.fillPolygon(points, 4);
565 }
566 
567 void FXSevenSegment::save(FXStream& store) const {
568  FXFrame::save(store);
569  store << value;
570  store << fgcolor;
571  store << bgcolor;
572  store << hsl;
573  store << vsl;
574  store << st;
575  store << groove;
576 }
577 
578 void FXSevenSegment::load(FXStream& store) {
579  FXFrame::load(store);
580  store >> value;
581  store >> fgcolor;
582  store >> bgcolor;
583  store >> hsl;
584  store >> vsl;
585  store >> st;
586  store >> groove;
587 }
588 
589 // let parent show tip if appropriate
590 long FXSevenSegment::onQueryTip(FXObject* sender, FXSelector sel, void* ptr) {
591  if (getParent()) {
592  return getParent()->handle(sender, sel, ptr);
593  }
594  return 0;
595 }
596 
597 // let parent show help if appropriate
598 long FXSevenSegment::onQueryHelp(FXObject* sender, FXSelector sel, void* ptr) {
599  if (getParent()) {
600  return getParent()->handle(sender, sel, ptr);
601  }
602  return 0;
603 }
604 
605 }
606 
#define ASCII_ZERO
FXDEFMAP(FXSevenSegment) FXSevenSegmentMap[]