1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2004-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    FXLCDLabel.cpp
11 /// @author  Mathew Robertson
12 /// @author  Daniel Krajzewicz
13 /// @author  Michael Behrisch
14 /// @date    2004-03-19
15 /// @version $Id$
16 ///
17 //
18 /****************************************************************************/
19 
20 
21 /* =========================================================================
22  * included modules
23  * ======================================================================= */
24 #include <config.h>
25 
26 #include <fxver.h>
27 #define NOMINMAX
28 #include <xincs.h>
29 #undef NOMINMAX
30 #include <fxdefs.h>
31 #include <fx.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 #include <FXLabel.h>
43 #include <FXFrame.h>
44 */
45 using namespace FX;
46 #include "FXSevenSegment.h"
47 #include "FXLCDLabel.h"
48 #include "FXBaseObject.h"
49 
50 using namespace FXEX;
51 namespace FXEX {
52 
53 FXDEFMAP(FXLCDLabel) FXLCDLabelMap[] = {
54     FXMAPFUNC(SEL_PAINT, 0, FXLCDLabel::onPaint),
55     FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETVALUE, FXLCDLabel::onCmdSetValue),
56     FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETINTVALUE, FXLCDLabel::onCmdSetIntValue),
57     FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETREALVALUE, FXLCDLabel::onCmdSetRealValue),
58     FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETSTRINGVALUE, FXLCDLabel::onCmdSetStringValue),
59     FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETINTVALUE, FXLCDLabel::onCmdGetIntValue),
60     FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETREALVALUE, FXLCDLabel::onCmdGetRealValue),
61     FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETSTRINGVALUE, FXLCDLabel::onCmdGetStringValue),
62     //  FXMAPFUNC(SEL_UPDATE,FXWindow::ID_QUERY_TIP,FXLCDLabel::onQueryTip),
63     //  FXMAPFUNC(SEL_UPDATE,FXWindow::ID_QUERY_HELP,FXLCDLabel::onQueryHelp),
64     FXMAPKEY(FXLCDLabel::ID_SEVENSEGMENT, FXLCDLabel::onRedirectEvent),
65 };
FXIMPLEMENT(FXLCDLabel,FXHorizontalFrame,FXLCDLabelMap,ARRAYNUMBER (FXLCDLabelMap))66 FXIMPLEMENT(FXLCDLabel, FXHorizontalFrame, FXLCDLabelMap, ARRAYNUMBER(FXLCDLabelMap))
67 
68 FXLCDLabel::FXLCDLabel(FXComposite* p, FXuint nfig, FXObject* tgt, FXSelector sel, FXuint opts, FXint pl, FXint pr, FXint pt, FXint pb, FXint hs) : FXHorizontalFrame(p, opts, 0, 0, 0, 0, pl, pr, pt, pb, hs, 0) {
69     if (nfig == 0) {
70         fxerror("%s: must have at least one figure.\n", getClassName());
71     }
72     nfigures = nfig;
73     setTarget(tgt);
74     setSelector(sel);
75     enable();
76     for (FXint i = 0; i < nfigures; i++) {
77         new FXSevenSegment(this, this, ID_SEVENSEGMENT, 0, 0, 0, 0);
78     }
79 }
80 
~FXLCDLabel()81 FXLCDLabel::~FXLCDLabel() {
82     /*
83       for (FXSevenSegment *child=(FXSevenSegment*)getFirst(); child; child=(FXSevenSegment*)child->getNext()){
84         delete child;
85         }
86     */
87 }
88 
89 // create resources
create()90 void FXLCDLabel::create() {
91     FXHorizontalFrame::create();
92     for (FXWindow* child = getFirst(); child; child = child->getNext()) {
93         child->create();
94     }
95 }
96 
97 // detach resources
detach()98 void FXLCDLabel::detach() {
99     for (FXWindow* child = getFirst(); child; child = child->getNext()) {
100         child->detach();
101     }
102     FXHorizontalFrame::detach();
103 }
104 
105 // destroy resources
destroy()106 void FXLCDLabel::destroy() {
107     for (FXWindow* child = getFirst(); child; child = child->getNext()) {
108         child->destroy();
109     }
110     FXHorizontalFrame::destroy();
111 }
112 
113 // get the foreground color
getFgColor() const114 FXColor FXLCDLabel::getFgColor() const {
115     FXSevenSegment* child = (FXSevenSegment*)getFirst();
116     return child->getFgColor();
117 }
118 
119 // set the foreground color
setFgColor(FXColor clr)120 void FXLCDLabel::setFgColor(FXColor clr) {
121     FXSevenSegment* child = (FXSevenSegment*)getFirst();
122     if (clr != child->getFgColor()) {
123         for (child = (FXSevenSegment*)getFirst(); child; child = (FXSevenSegment*)child->getNext()) {
124             child->setFgColor(clr);
125         }
126     }
127 }
128 
129 // get the background color
getBgColor() const130 FXColor FXLCDLabel::getBgColor() const {
131     FXSevenSegment* child = (FXSevenSegment*)getFirst();
132     return child->getBgColor();
133 }
134 
135 // set the background color
setBgColor(FXColor clr)136 void FXLCDLabel::setBgColor(FXColor clr) {
137     FXSevenSegment* child = (FXSevenSegment*)getFirst();
138     if (clr != child->getBgColor()) {
139         for (child = (FXSevenSegment*)getFirst(); child; child = (FXSevenSegment*)child->getNext()) {
140             child->setBgColor(clr);
141         }
142     }
143 }
144 
145 // set the text
setText(FXString lbl)146 void FXLCDLabel::setText(FXString lbl) {
147     if (lbl != label) {
148         label = lbl;
149         recalc();
150         update();
151     }
152 }
153 
154 // get the length of the horizontal segments
getHorizontal() const155 FXint FXLCDLabel::getHorizontal() const {
156     FXSevenSegment* child = (FXSevenSegment*)getFirst();
157     return child->getHorizontal();
158 }
159 
160 // set the length of the horizontal segments
setHorizontal(const FXint len)161 void FXLCDLabel::setHorizontal(const FXint len) {
162     FXSevenSegment* child = (FXSevenSegment*)getFirst();
163     if (len != child->getHorizontal()) {
164         for (child = (FXSevenSegment*)getFirst(); child; child = (FXSevenSegment*)child->getNext()) {
165             child->setHorizontal(len);
166         }
167         recalc();
168         update();
169     }
170 }
171 
172 // get the length of the vertical segments
getVertical() const173 FXint FXLCDLabel::getVertical() const {
174     FXSevenSegment* child = (FXSevenSegment*)getFirst();
175     return child->getVertical();
176 }
177 
178 // set the length of the vertical segments
setVertical(const FXint len)179 void FXLCDLabel::setVertical(const FXint len) {
180     FXSevenSegment* child = (FXSevenSegment*)getFirst();
181     if (len != child->getVertical()) {
182         for (child = (FXSevenSegment*)getFirst(); child; child = (FXSevenSegment*)child->getNext()) {
183             child->setVertical(len);
184         }
185         recalc();
186         update();
187     }
188 }
189 
190 // get the width of the segments
getThickness() const191 FXint FXLCDLabel::getThickness() const {
192     FXSevenSegment* child = (FXSevenSegment*)getFirst();
193     return child->getThickness();
194 }
195 
196 // set the width of the segments
setThickness(const FXint width)197 void FXLCDLabel::setThickness(const FXint width) {
198     FXSevenSegment* child = (FXSevenSegment*)getFirst();
199     if (width != child->getThickness()) {
200         for (child = (FXSevenSegment*)getFirst(); child; child = (FXSevenSegment*)child->getNext()) {
201             child->setThickness(width);
202         }
203         recalc();
204         update();
205     }
206 }
207 
208 // get the width of the segments
getGroove() const209 FXint FXLCDLabel::getGroove() const {
210     FXSevenSegment* child = (FXSevenSegment*)getFirst();
211     return child->getGroove();
212 }
213 
214 // set the groove width
setGroove(const FXint width)215 void FXLCDLabel::setGroove(const FXint width) {
216     FXSevenSegment* child = (FXSevenSegment*)getFirst();
217     if (width != child->getGroove()) {
218         for (child = (FXSevenSegment*)getFirst(); child; child = (FXSevenSegment*)child->getNext()) {
219             child->setGroove(width);
220         }
221         recalc();
222         update();
223     }
224 }
225 
226 // Update value from a message
onCmdSetValue(FXObject *,FXSelector,void * ptr)227 long FXLCDLabel::onCmdSetValue(FXObject*, FXSelector, void* ptr) {
228     setText((const FXchar*)ptr);
229     return 1;
230 }
231 
232 // Update value from a message
onCmdSetIntValue(FXObject *,FXSelector,void * ptr)233 long FXLCDLabel::onCmdSetIntValue(FXObject*, FXSelector, void* ptr) {
234     setText(FXStringVal(*((FXint*)ptr)));
235     return 1;
236 }
237 
238 // Update value from a message
onCmdSetRealValue(FXObject *,FXSelector,void * ptr)239 long FXLCDLabel::onCmdSetRealValue(FXObject*, FXSelector, void* ptr) {
240     setText(FXStringVal(*((FXdouble*)ptr)));
241     return 1;
242 }
243 
244 // Update value from a message
onCmdSetStringValue(FXObject *,FXSelector,void * ptr)245 long FXLCDLabel::onCmdSetStringValue(FXObject*, FXSelector, void* ptr) {
246     setText(*((FXString*)ptr));
247     return 1;
248 }
249 
250 // Obtain value from text field
onCmdGetIntValue(FXObject *,FXSelector,void * ptr)251 long FXLCDLabel::onCmdGetIntValue(FXObject*, FXSelector, void* ptr) {
252     *((FXint*)ptr) = FXIntVal(getText());
253     return 1;
254 }
255 
256 // Obtain value from text field
onCmdGetRealValue(FXObject *,FXSelector,void * ptr)257 long FXLCDLabel::onCmdGetRealValue(FXObject*, FXSelector, void* ptr) {
258     *((FXdouble*)ptr) = FXDoubleVal(getText());
259     return 1;
260 }
261 
262 // Obtain value from text field
onCmdGetStringValue(FXObject *,FXSelector,void * ptr)263 long FXLCDLabel::onCmdGetStringValue(FXObject*, FXSelector, void* ptr) {
264     *((FXString*)ptr) = getText();
265     return 1;
266 }
267 
268 // handle paint event
onPaint(FXObject *,FXSelector,void * ptr)269 long FXLCDLabel::onPaint(FXObject*, FXSelector, void* ptr) {
270     FXEvent* event = (FXEvent*) ptr;
271     FXDCWindow dc(this, event);
272     drawFrame(dc, 0, 0, width, height);
273     FXSevenSegment* child = (FXSevenSegment*)getFirst();
274     // Fill the background
275     dc.setForeground(child->getBgColor());
276     dc.fillRectangle(border, border, width - (border << 1), height - (border << 1));
277     // Draw the current string
278     dc.setForeground(child->getFgColor());
279     drawString(label);
280     return 1;
281 }
282 
283 // draw a specified string/label
drawString(const FXString & lbl)284 void FXLCDLabel::drawString(const FXString& lbl) {
285     FXint i = 0;
286     FXString displayString(' ', nfigures);
287     if (options & LCDLABEL_LEADING_ZEROS && (FXIntVal(lbl) || lbl == "0")) {
288         FXString txt = lbl;
289         if (txt[0] == '-') {
290             displayString.replace(0, '-');
291             txt.erase(0);
292             i = 1;
293         }
294         for (; (i + txt.length()) < nfigures; i++) {
295             displayString.replace(i, '0');
296         }
297         displayString.insert(i, txt);
298     } else if (options & JUSTIFY_RIGHT) {
299         for (; (i + lbl.length()) < nfigures; i++) {}
300         displayString.insert(i, lbl);
301     } else {
302         displayString.insert(0, lbl);
303     }
304     displayString.trunc(nfigures);
305     i = 0;
306 
307     // FIXME: at the moment, if we resize the parent widget, we must use integer multiples
308     //        of the SevenSegment width.  The problem is that it makes the padding on the
309     //        RHS look wrong.  What we need to do is to extend the horizontal segment width
310     //        for the last sevensegment, so as to fill the remaining space.
311     FXSevenSegment* child = (FXSevenSegment*)getFirst();
312     if (options & LAYOUT_FILL) {
313         FXint width = this->width - padleft - padright - (border << 1);
314         FXint height = this->height - padtop - padbottom - (border << 1);
315         hspacing = FXMAX(width, height) / 50;
316         if (hspacing < 1) {
317             hspacing = 1;
318         }
319         FXint hsl = (width - (nfigures - 1) * hspacing) / nfigures;
320         if (hsl < 5) {
321             hsl = 5;
322         }
323         FXint vsl = height >> 1;
324         if (vsl < 5) {
325             vsl = 5;
326         }
327         FXint st = FXMIN(hsl, vsl) / 4;
328         if (st < 1) {
329             st = 1;
330         }
331         FXint groove = st / 4;
332         if (groove < 1) {
333             groove = 1;
334         }
335         if (options & LAYOUT_FILL_X) {
336             hsl -= groove << 1;
337             for (; child; child = (FXSevenSegment*)child->getNext()) {
338                 child->setHorizontal(hsl);
339             }
340             child = (FXSevenSegment*)getFirst();
341         }
342         if (options & LAYOUT_FILL_Y) {
343             vsl -= groove << 1;
344             for (; child; child = (FXSevenSegment*)child->getNext()) {
345                 child->setVertical(vsl);
346             }
347             child = (FXSevenSegment*)getFirst();
348         }
349         for (; child; child = (FXSevenSegment*)child->getNext()) {
350             child->setText(displayString[i++]);
351             child->setGroove(groove);
352             child->setThickness(st);
353         }
354     } else {
355         for (; child; child = (FXSevenSegment*)child->getNext()) {
356             child->setText(displayString[i++]);
357         }
358     }
359 }
360 
361 // redirect events to main window
onRedirectEvent(FXObject *,FXSelector sel,void * ptr)362 long FXLCDLabel::onRedirectEvent(FXObject*, FXSelector sel, void* ptr) {
363     FXuint seltype = FXSELTYPE(sel);
364     if (isEnabled()) {
365         if (target) {
366             target->handle(this, FXSEL(seltype, message), ptr);
367         }
368     }
369     return 1;
370 }
371 
372 // return minimum width
getDefaultWidth()373 FXint FXLCDLabel::getDefaultWidth() {
374     return padleft + getFirst()->getDefaultWidth() * nfigures + hspacing * (nfigures - 1) + padright + (border << 1);
375 }
376 
377 // return minimum height
getDefaultHeight()378 FXint FXLCDLabel::getDefaultHeight() {
379     return padtop + getFirst()->getDefaultHeight() + padbottom + (border << 1);
380 }
381 
382 // save resources
save(FXStream & store) const383 void FXLCDLabel::save(FXStream& store) const {
384     FXHorizontalFrame::save(store);
385     store << label;
386     store << nfigures;
387 }
388 
389 // load resources
load(FXStream & store)390 void FXLCDLabel::load(FXStream& store) {
391     FXHorizontalFrame::load(store);
392     store >> label;
393     store >> nfigures;
394 }
395 
396 // let parent show tip if appropriate
onQueryTip(FXObject * sender,FXSelector sel,void * ptr)397 long FXLCDLabel::onQueryTip(FXObject* sender, FXSelector sel, void* ptr) {
398     if (getParent()) {
399         return getParent()->handle(sender, sel, ptr);
400     }
401     return 0;
402 }
403 
404 // let parent show help if appropriate
onQueryHelp(FXObject * sender,FXSelector sel,void * ptr)405 long FXLCDLabel::onQueryHelp(FXObject* sender, FXSelector sel, void* ptr) {
406     if (getParent()) {
407         return getParent()->handle(sender, sel, ptr);
408     }
409     return 0;
410 }
411 
412 }
413 
414