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