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