]> git.mxchange.org Git - flightgear.git/blob - src/Instrumentation/HUD/HUD_label.cxx
new HUD (work in progress)
[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 #include <simgear/props/condition.hxx>
23 #include "HUD.hxx"
24
25
26 HUD::Label::Label(HUD *hud, const SGPropertyNode *n, float x, float y) :
27     Item(hud, n, x, y),
28     _input(n->getNode("input", false)),
29     _fontsize(fgGetInt("/sim/startup/xsize") > 1000 ? FONT_LARGE : FONT_SMALL),         // FIXME
30     _box(n->getBoolValue("box", false)),
31     _blink_condition(0),
32     _blink_interval(n->getFloatValue("blinking/interval", -1.0f)),
33     _blink_target(0.0),
34     _blink_state(true)
35 {
36     const SGPropertyNode *node = n->getNode("blinking/condition");
37     if (node)
38        _blink_condition = sgReadCondition(globals->get_props(), node);
39
40     const char *halign = n->getStringValue("halign", "center");
41     if (!strcmp(halign, "left"))
42         _halign = LEFT_ALIGN;
43     else if (!strcmp(halign, "right"))
44         _halign = RIGHT_ALIGN;
45     else
46         _halign = CENTER_ALIGN;
47
48     const char *pre = n->getStringValue("prefix", 0);
49     const char *post = n->getStringValue("postfix", 0);
50     const char *fmt = n->getStringValue("format", 0);
51
52     if (pre)
53         _format = pre;
54     if (fmt)
55         _format += fmt;
56     else
57         _format += "%s";
58     if (post)
59         _format += post;
60
61     _mode = check_format(_format.c_str());
62     if (_mode == INVALID) {
63         SG_LOG(SG_INPUT, SG_ALERT, "HUD: invalid format '" << _format.c_str() << '\'');
64         _format = "INVALID";
65         _mode = NONE;
66     }
67
68     blink();
69 }
70
71
72 void HUD::Label::draw(void)
73 {
74     if (!(_mode == NONE || _input.isValid() && blink()))
75         return;
76
77     Rect scrn_rect = get_location();
78
79     if (_box) {
80         float x = scrn_rect.left;
81         float y = scrn_rect.top;
82         float w = scrn_rect.right;
83         float h = _hud->_font_size;                     // FIXME
84
85         glPushMatrix();
86         glLoadIdentity();
87
88         glBegin(GL_LINES);
89         glVertex2f(x - 2.0,  y - 2.0);
90         glVertex2f(x + w + 2.0, y - 2.0);
91         glVertex2f(x + w + 2.0, y + h + 2.0);
92         glVertex2f(x - 2.0,  y + h + 2.0);
93         glEnd();
94
95         glEnable(GL_LINE_STIPPLE);
96         glLineStipple(1, 0xAAAA);
97
98         glBegin(GL_LINES);
99         glVertex2f(x + w + 2.0, y - 2.0);
100         glVertex2f(x + w + 2.0, y + h + 2.0);
101         glVertex2f(x - 2.0, y + h + 2.0);
102         glVertex2f(x - 2.0, y - 2.0);
103         glEnd();
104
105         glDisable(GL_LINE_STIPPLE);
106         glPopMatrix();
107     }
108
109     const int BUFSIZE = 256;
110     char buf[BUFSIZE];
111     if (_mode == NONE)
112         snprintf(buf, BUFSIZE, _format.c_str());
113     else if (_mode == STRING)
114         snprintf(buf, BUFSIZE, _format.c_str(), _input.getStringValue());
115     else if (_mode == INT)
116         snprintf(buf, BUFSIZE, _format.c_str(), int(_input.getFloatValue()));
117     else if (_mode == LONG)
118         snprintf(buf, BUFSIZE, _format.c_str(), long(_input.getFloatValue()));
119     else if (_mode == FLOAT)
120         snprintf(buf, BUFSIZE, _format.c_str(), float(_input.getFloatValue()));
121     else if (_mode == DOUBLE) // not really supported yet
122         snprintf(buf, BUFSIZE, _format.c_str(), double(_input.getFloatValue()));
123
124     float posincr;
125     float lenstr = text_width(buf);
126
127     if (_halign == RIGHT_ALIGN)
128         posincr = scrn_rect.right - lenstr;
129     else if (_halign == CENTER_ALIGN)
130         posincr = get_span() - (lenstr / 2);            // FIXME get_span() ? really?
131     else // LEFT_ALIGN
132         posincr = 0;
133
134     if (_fontsize == FONT_SMALL)
135         draw_text(scrn_rect.left + posincr, scrn_rect.top, buf, get_digits());
136     else if (_fontsize == FONT_LARGE)
137         draw_text(scrn_rect.left + posincr, scrn_rect.top, buf, get_digits());
138 }
139
140
141 // make sure the format matches '[ -+#]?\d*(\.\d*)?(l?[df]|s)'
142 //
143 HUD::Label::Format HUD::Label::check_format(const char *f) const
144 {
145     bool l = false;
146     Format fmt = STRING;
147
148     for (; *f; f++) {
149         if (*f == '%') {
150             if (f[1] == '%')
151                 f++;
152             else
153                 break;
154         }
155     }
156     if (*f++ != '%')
157         return NONE;
158     if (*f == ' ' || *f == '+' || *f == '-' || *f == '#')
159         f++;
160     while (*f && isdigit(*f))
161         f++;
162     if (*f == '.') {
163         f++;
164         while (*f && isdigit(*f))
165             f++;
166     }
167     if (*f == 'l')
168         l = true, f++;
169
170     if (*f == 'd')
171         fmt = l ? LONG : INT;
172     if (*f == 'f')
173         fmt = l ? DOUBLE : FLOAT;
174     else if (*f == 's') {
175         if (l)
176             return INVALID;
177         fmt = STRING;
178     } else
179         return INVALID;
180
181     for (++f; *f; f++) {
182         if (*f == '%') {
183             if (f[1] == '%')
184                 f++;
185             else
186                 return INVALID;
187         }
188     }
189     return fmt;
190 }
191
192
193 bool HUD::Label::blink()
194 {
195     if (_blink_interval < 0.0f)
196         return true;
197
198     if (_blink_condition && !_blink_condition->test())
199         return true;
200
201     if (_hud->timer() < _blink_target)
202         return _blink_state;
203
204     _blink_target = _hud->timer() + _blink_interval;
205     return _blink_state = !_blink_state;
206 }
207
208