]> git.mxchange.org Git - flightgear.git/blob - src/Instrumentation/HUD/HUD_label.cxx
4b79d4bdd62f6fde2316265d2127eb666eb78fe7
[flightgear.git] / src / Instrumentation / HUD / HUD_label.cxx
1 // HUD_label.cxx -- HUD Label
2 //
3 // Written by Michele America, started September 1997.
4 //
5 // Copyright (C) 1997  Michele F. America  [micheleamerica#geocities:com]
6 // Copyright (C) 2006  Melchior FRANZ  [mfranz#aon:at]
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21
22 #ifdef HAVE_CONFIG_H
23 #  include <config.h>
24 #endif
25
26 #include <simgear/props/condition.hxx>
27 #include "HUD.hxx"
28
29
30 HUD::Label::Label(HUD *hud, const SGPropertyNode *n, float x, float y) :
31     Item(hud, n, x, y),
32     _input(n->getNode("input", false)),
33     _fontsize(fgGetInt("/sim/startup/xsize") > 1000 ? FONT_LARGE : FONT_SMALL),         // FIXME
34     _box(n->getBoolValue("box", false)),
35     _marker_offset(n->getFloatValue("marker-offset", 5)),
36     _blink_condition(0),
37     _blink_interval(n->getFloatValue("blinking/interval", -1.0f)),
38     _blink_target(0.0),
39     _blink_state(true)
40 {
41     const SGPropertyNode *node = n->getNode("blinking/condition");
42     if (node)
43        _blink_condition = sgReadCondition(globals->get_props(), node);
44
45     const char *halign = n->getStringValue("halign", "center");
46     if (!strcmp(halign, "left"))
47         _halign = LEFT_ALIGN;
48     else if (!strcmp(halign, "right"))
49         _halign = RIGHT_ALIGN;
50     else
51         _halign = CENTER_ALIGN;
52
53     const char *pre = n->getStringValue("prefix", 0);
54     const char *post = n->getStringValue("postfix", 0);
55     const char *fmt = n->getStringValue("format", 0);
56
57     if (pre)
58         _format = pre;
59
60     if (fmt)
61         _format += fmt;
62     else
63         _format += "%s";
64
65     if (post)
66         _format += post;
67
68     _mode = check_format(_format.c_str());
69     if (_mode == INVALID) {
70         SG_LOG(SG_INPUT, SG_ALERT, "HUD: invalid format '" << _format.c_str() << '\'');
71         _format = "INVALID";
72         _mode = NONE;
73     }
74
75     float top;
76     _hud->_font->getBBox("0", _hud->_font_size, 0.0, 0, 0, 0, &top);
77     _text_y = _y + (_h - top) / 2.0;
78     blink();
79 }
80
81
82 void HUD::Label::draw(void)
83 {
84     if (!(_mode == NONE || _input.isValid() && blink()))
85         return;
86
87     if (_box) {
88         const float tan30 = 0.57735;
89         float base = _marker_offset * tan30;
90         float l, r, p;
91
92         l = _center_x - base;
93         r = _center_x + base;
94
95         if (option_bottom()) {
96             p = _y - _marker_offset;
97             draw_line(_x, _y, l, _y);
98             draw_line(l, _y, _center_x, p);
99             draw_line(_center_x, p, r, _y);
100             draw_line(r, _y, _x + _w, _y);
101         } else
102             draw_line(_x, _y, _x + _w, _y);
103
104         if (option_top()) {
105             p = _y + _h + _marker_offset;
106             draw_line(_x, _y + _h, l, _y + _h);
107             draw_line(l, _y + _h, _center_x, p);
108             draw_line(_center_x, p, r, _y + _h);
109             draw_line(r, _y + _h, _x + _w, _y + _h);
110         } else
111             draw_line(_x + _w, _y + _h, _x, _y + _h);
112
113         l = _center_y - base;
114         r = _center_y + base;
115
116         if (option_left()) {
117             p = _x - _marker_offset;
118             draw_line(_x, _y, _x, l);
119             draw_line(_x, l, p, _center_y);
120             draw_line(p, _center_y, _x, r);
121             draw_line(_x, r, _x, _y + _h);
122         } else
123             draw_line(_x, _y + _h, _x, _y);
124
125         if (option_right()) {
126             p = _x + _w + _marker_offset;
127             draw_line(_x + _w, _y, _x + _w, l);
128             draw_line(_x + _w, l, p, _center_y);
129             draw_line(p, _center_y, _x + _w, r);
130             draw_line(_x + _w, r, _x + _w, _y + _h);
131         } else
132             draw_line(_x + _w, _y, _x + _w, _y + _h);
133     }
134
135     const int BUFSIZE = 256;
136     char buf[BUFSIZE];
137     if (_mode == NONE)
138         snprintf(buf, BUFSIZE, _format.c_str());
139     else if (_mode == STRING)
140         snprintf(buf, BUFSIZE, _format.c_str(), _input.getStringValue());
141     else if (_mode == INT)
142         snprintf(buf, BUFSIZE, _format.c_str(), int(_input.getFloatValue()));
143     else if (_mode == LONG)
144         snprintf(buf, BUFSIZE, _format.c_str(), long(_input.getFloatValue()));
145     else if (_mode == FLOAT)
146         snprintf(buf, BUFSIZE, _format.c_str(), float(_input.getFloatValue()));
147     else if (_mode == DOUBLE) // not really supported yet
148         snprintf(buf, BUFSIZE, _format.c_str(), double(_input.getFloatValue()));
149
150     float posincr;
151     float lenstr = text_width(buf);
152
153     if (_halign == RIGHT_ALIGN)
154         posincr = _w - lenstr;
155     else if (_halign == CENTER_ALIGN)
156         posincr = (_w - lenstr) / 2.0;
157     else // LEFT_ALIGN
158         posincr = 0;
159
160     if (_fontsize == FONT_SMALL)
161         draw_text(_x + posincr, _text_y, buf, get_digits());
162     else if (_fontsize == FONT_LARGE)
163         draw_text(_x + posincr, _text_y, buf, get_digits());
164 }
165
166
167 // make sure the format matches '[ -+#]?\d*(\.\d*)?(l?[df]|s)'
168 //
169 HUD::Label::Format HUD::Label::check_format(const char *f) const
170 {
171     bool l = false;
172     Format fmt = STRING;
173
174     for (; *f; f++) {
175         if (*f == '%') {
176             if (f[1] == '%')
177                 f++;
178             else
179                 break;
180         }
181     }
182     if (*f++ != '%')
183         return NONE;
184     if (*f == ' ' || *f == '+' || *f == '-' || *f == '#')
185         f++;
186     while (*f && isdigit(*f))
187         f++;
188     if (*f == '.') {
189         f++;
190         while (*f && isdigit(*f))
191             f++;
192     }
193     if (*f == 'l')
194         l = true, f++;
195
196     if (*f == 'd')
197         fmt = l ? LONG : INT;
198     else if (*f == 'f')
199         fmt = l ? DOUBLE : FLOAT;
200     else if (*f == 's') {
201         if (l)
202             return INVALID;
203         fmt = STRING;
204     } else
205         return INVALID;
206
207     for (++f; *f; f++) {
208         if (*f == '%') {
209             if (f[1] == '%')
210                 f++;
211             else
212                 return INVALID;
213         }
214     }
215     return fmt;
216 }
217
218
219 bool HUD::Label::blink()
220 {
221     if (_blink_interval < 0.0f)
222         return true;
223
224     if (_blink_condition && !_blink_condition->test())
225         return true;
226
227     if (_hud->timer() < _blink_target)
228         return _blink_state;
229
230     _blink_target = _hud->timer() + _blink_interval;
231     return _blink_state = !_blink_state;
232 }
233
234