]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/panel.hxx
e3e5f04e15d7c19c9b6ad7fcdc2d5a87e3345c2d
[flightgear.git] / src / Cockpit / panel.hxx
1 //  panel.hxx - generic support classes for a 2D panel.
2 //
3 //  Written by David Megginson, started January 2000.
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License as
7 //  published by the Free Software Foundation; either version 2 of the
8 //  License, or (at your option) any later version.
9 // 
10 //  This program is distributed in the hope that it will be useful, but
11 //  WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 //  General Public License for more details.
14 // 
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //
19 //  $Id$
20
21 #ifndef __PANEL_HXX
22 #define __PANEL_HXX
23
24 #ifndef __cplusplus                                                          
25 # error This library requires C++
26 #endif                                   
27
28
29 #ifdef HAVE_CONFIG_H
30 #  include <config.h>
31 #endif
32
33 #ifdef HAVE_WINDOWS_H          
34 #  include <windows.h>
35 #endif
36
37 #include <GL/glut.h>
38 #include <plib/ssg.h>
39
40 #include <simgear/misc/props.hxx>
41
42 #include <vector>
43 #include <map>
44 #include <plib/fnt.h>
45
46 FG_USING_STD(vector);
47 FG_USING_STD(map);
48
49 class FGPanelInstrument;
50
51
52 \f
53 ////////////////////////////////////////////////////////////////////////
54 // Texture manager (should migrate out into FGFS).
55 //
56 // This class ensures that no texture is loaded more than once.
57 ////////////////////////////////////////////////////////////////////////
58
59 class FGTextureManager
60 {
61 public:
62   static ssgTexture * createTexture(const string &relativePath);
63 private:
64   static map<string,ssgTexture *> _textureMap;
65 };
66
67
68 \f
69 ////////////////////////////////////////////////////////////////////////
70 // Cropped texture (should migrate out into FGFS).
71 //
72 // This structure wraps an SSG texture with cropping information.
73 ////////////////////////////////////////////////////////////////////////
74
75 struct CroppedTexture
76 {
77   CroppedTexture () {}
78   CroppedTexture (const string &path,
79                   float _minX = 0.0, float _minY = 0.0,
80                   float _maxX = 1.0, float _maxY = 1.0)
81     : texture(FGTextureManager::createTexture(path)),
82       minX(_minX), minY(_minY), maxX(_maxX), maxY(_maxY) {}
83
84   ssgTexture * texture;
85   float minX, minY, maxX, maxY;
86 };
87
88
89 \f
90 ////////////////////////////////////////////////////////////////////////
91 // Instrument panel class.
92 //
93 // The panel is a container that has a background texture and holds
94 // zero or more instruments.  The panel will order the instruments to
95 // redraw themselves when necessary, and will pass mouse clicks on to
96 // the appropriate instruments for processing.
97 ////////////////////////////////////////////////////////////////////////
98
99 class FGPanel
100 {
101 public:
102
103   FGPanel (int x, int y, int w, int h);
104   virtual ~FGPanel ();
105
106                                 // transfer pointer ownership!!!
107   virtual void addInstrument (FGPanelInstrument * instrument);
108
109                                 // Update the panel (every frame).
110   virtual void update () const;
111
112                                 // Background texture.
113   virtual void setBackground (ssgTexture * texture);
114
115                                 // Make the panel visible or invisible.
116   virtual bool getVisibility () const;
117   virtual void setVisibility (bool visibility);
118
119                                 // Handle a mouse click.
120   virtual bool doMouseAction (int button, int updown, int x, int y);
121
122 private:
123   mutable bool _visibility;
124   mutable bool _mouseDown;
125   mutable int _mouseButton, _mouseX, _mouseY;
126   mutable int _mouseDelay;
127   mutable FGPanelInstrument * _mouseInstrument;
128   typedef vector<FGPanelInstrument *> instrument_list_type;
129   int _x, _y, _w, _h;
130   int _panel_h;
131   ssgTexture * _bg;
132                                 // List of instruments in panel.
133   instrument_list_type _instruments;
134 };
135
136
137 \f
138 ////////////////////////////////////////////////////////////////////////
139 // Base class for user action types.
140 //
141 // Individual instruments can have actions associated with a mouse
142 // click in a rectangular area.  Current concrete classes include
143 // FGAdjustAction, FGSwapAction, and FGToggleAction.
144 ////////////////////////////////////////////////////////////////////////
145
146 class FGPanelAction
147 {
148 public:
149   FGPanelAction ();
150   FGPanelAction (int button, int x, int y, int w, int h);
151   virtual ~FGPanelAction ();
152
153                                 // Getters.
154   virtual int getButton () const { return _button; }
155   virtual int getX () const { return _x; }
156   virtual int getY () const { return _y; }
157   virtual int getWidth () const { return _w; }
158   virtual int getHeight () const { return _h; }
159
160                                 // Setters.
161   virtual void setButton (int button) { _button = button; }
162   virtual void setX (int x) { _x = x; }
163   virtual void setY (int y) { _y = y; }
164   virtual void setWidth (int w) { _w = w; }
165   virtual void setHeight (int h) { _h = h; }
166
167                                 // Check whether we're in the area.
168   virtual bool inArea (int button, int x, int y)
169   {
170     return (button == _button &&
171             x >= _x &&
172             x < _x + _w &&
173             y >= _y &&
174             y < _y + _h);
175   }
176
177                                 // Perform the action.
178   virtual void doAction () = 0;
179
180 private:
181   int _button;
182   int _x;
183   int _y;
184   int _w;
185   int _h;
186 };
187
188
189 \f
190 ////////////////////////////////////////////////////////////////////////
191 // Adjustment action.
192 //
193 // This is an action to increase or decrease an FGFS value by a certain
194 // increment within a certain range.  If the wrap flag is true, the
195 // value will wrap around if it goes below min or above max; otherwise,
196 // it will simply stop at min or max.
197 ////////////////////////////////////////////////////////////////////////
198
199 class FGAdjustAction : public FGPanelAction
200 {
201 public:
202   FGAdjustAction (int button, int x, int y, int w, int h,
203                   SGValue * value, float increment,
204                   float min, float max, bool wrap=false);
205   virtual ~FGAdjustAction ();
206   virtual void doAction ();
207
208 private:
209   SGValue * _value;
210   float _increment;
211   float _min;
212   float _max;
213   bool _wrap;
214 };
215
216
217 \f
218 ////////////////////////////////////////////////////////////////////////
219 // Swap action.
220 //
221 // This is an action to swap two values.  It's currently used in the
222 // navigation radios.
223 ////////////////////////////////////////////////////////////////////////
224
225 class FGSwapAction : public FGPanelAction
226 {
227 public:
228   FGSwapAction (int button, int x, int y, int w, int h,
229                 SGValue * value1, SGValue * value2);
230   virtual ~FGSwapAction ();
231   virtual void doAction ();
232
233 private:
234   SGValue * _value1;
235   SGValue * _value2;
236 };
237
238
239 \f
240 ////////////////////////////////////////////////////////////////////////
241 // Toggle action.
242 //
243 // This is an action to toggle a boolean value.
244 ////////////////////////////////////////////////////////////////////////
245
246 class FGToggleAction : public FGPanelAction
247 {
248 public:
249   FGToggleAction (int button, int x, int y, int w, int h,
250                   SGValue * value);
251   virtual ~FGToggleAction ();
252   virtual void doAction ();
253
254 private:
255   SGValue * _value;
256 };
257
258
259 \f
260 ////////////////////////////////////////////////////////////////////////
261 // Abstract base class for a panel instrument.
262 //
263 // A panel instrument consists of zero or more actions, associated
264 // with mouse clicks in rectangular areas.  Currently, the only
265 // concrete class derived from this is FGLayeredInstrument, but others
266 // may show up in the future (some complex instruments could be 
267 // entirely hand-coded, for example).
268 ////////////////////////////////////////////////////////////////////////
269
270 class FGPanelInstrument
271 {
272 public:
273   FGPanelInstrument ();
274   FGPanelInstrument (int x, int y, int w, int h);
275   virtual ~FGPanelInstrument ();
276
277   virtual void draw () = 0;
278
279   virtual void setPosition(int x, int y);
280   virtual void setSize(int w, int h);
281
282   virtual int getXPos () const;
283   virtual int getYPos () const;
284   virtual int getWidth () const;
285   virtual int getHeight () const;
286
287                                 // Coordinates relative to centre.
288                                 // Transfer pointer ownership!!
289   virtual void addAction (FGPanelAction * action);
290
291                                 // Coordinates relative to centre.
292   virtual bool doMouseAction (int button, int x, int y);
293
294 protected:
295   int _x, _y, _w, _h;
296   typedef vector<FGPanelAction *> action_list_type;
297   action_list_type _actions;
298 };
299
300
301 \f
302 ////////////////////////////////////////////////////////////////////////
303 // Abstract base class for an instrument layer.
304 //
305 // The FGLayeredInstrument class builds up instruments by using layers
306 // of textures or text.  Each layer can have zero or more
307 // transformations applied to it: for example, a needle layer can
308 // rotate to show the altitude or airspeed.
309 ////////////////////////////////////////////////////////////////////////
310
311
312 /**
313  * A transformation for a layer.
314  */
315 class FGPanelTransformation {
316 public:
317
318   enum Type {
319     XSHIFT,
320     YSHIFT,
321     ROTATION
322   };
323
324   FGPanelTransformation ();
325   FGPanelTransformation (Type type, const SGValue * value,
326                          float min, float max,
327                          float factor, float offset);
328   virtual ~FGPanelTransformation ();
329
330   Type type;
331   const SGValue * value;
332   float min;
333   float max;
334   float factor;
335   float offset;
336 };
337
338
339
340 /**
341  * A single layer of a multi-layered instrument.
342  *
343  * Each layer can be subject to a series of transformations based
344  * on current FGFS instrument readings: for example, a texture
345  * representing a needle can rotate to show the airspeed.
346  */
347 class FGInstrumentLayer
348 {
349 public:
350
351   FGInstrumentLayer (int w = -1, int h = -1);
352   virtual ~FGInstrumentLayer ();
353
354   virtual void draw () = 0;
355   virtual void transform () const;
356
357   virtual int getWidth () const { return _w; }
358   virtual int getHeight () const { return _h; }
359   virtual void setWidth (int w) { _w = w; }
360   virtual void setHeight (int h) { _h = h; }
361
362                                 // Transfer pointer ownership!!
363                                 // DEPRECATED
364   virtual void addTransformation (FGPanelTransformation * transformation);
365
366 protected:
367   int _w, _h;
368
369   typedef vector<FGPanelTransformation *> transformation_list;
370   transformation_list _transformations;
371 };
372
373
374 \f
375 ////////////////////////////////////////////////////////////////////////
376 // An instrument composed of layers.
377 //
378 // This class represents an instrument which is simply a series of
379 // layers piled one on top of the other, each one undergoing its own
380 // set of transformations.  For example, one layer can represent
381 // the instrument's face (which doesn't move), while the next layer
382 // can represent a needle that rotates depending on an FGFS variable.
383 ////////////////////////////////////////////////////////////////////////
384
385
386 /**
387  * An instrument constructed of multiple layers.
388  *
389  * Each individual layer can be rotated or shifted to correspond
390  * to internal FGFS instrument readings.
391  */
392 class FGLayeredInstrument : public FGPanelInstrument
393 {
394 public:
395   typedef vector<FGInstrumentLayer *> layer_list;
396   FGLayeredInstrument (int x, int y, int w, int h);
397   virtual ~FGLayeredInstrument ();
398
399   virtual void draw ();
400
401                                 // Transfer pointer ownership!!
402   virtual int addLayer (FGInstrumentLayer *layer);
403   virtual int addLayer (CroppedTexture &texture, int w = -1, int h = -1);
404
405                                 // Transfer pointer ownership!!
406   virtual void addTransformation (FGPanelTransformation * transformation);
407
408 protected:
409   layer_list _layers;
410 };
411
412
413 \f
414 ////////////////////////////////////////////////////////////////////////
415 // A textured layer of an instrument.
416 //
417 // This is a layer holding a single texture.  Normally, the texture's
418 // backgound should be transparent so that lower layers and the panel
419 // background can show through.
420 ////////////////////////////////////////////////////////////////////////
421
422 class FGTexturedLayer : public FGInstrumentLayer
423 {
424 public:
425   FGTexturedLayer (int w = -1, int h = -1) : FGInstrumentLayer(w, h) {}
426   FGTexturedLayer (const CroppedTexture &texture, int w = -1, int h = -1);
427   virtual ~FGTexturedLayer ();
428
429   virtual void draw ();
430
431   virtual void setTexture (const CroppedTexture &texture) {
432     _texture = texture;
433   }
434   virtual CroppedTexture &getTexture () { return _texture; }
435   virtual const CroppedTexture &getTexture () const { return _texture; }
436
437 private:
438   mutable CroppedTexture _texture;
439 };
440
441
442 \f
443 ////////////////////////////////////////////////////////////////////////
444 // A moving window on a texture.
445 //
446 // This layer automatically recrops a cropped texture based on
447 // property values, creating a moving window over the texture.
448 ////////////////////////////////////////////////////////////////////////
449
450 class FGWindowLayer : public FGTexturedLayer
451 {
452 public:
453   FGWindowLayer (int w = -1, int h = -1);
454   FGWindowLayer (const CroppedTexture &texture, int w = -1, int h = -1);
455   virtual ~FGWindowLayer ();
456
457   virtual void draw ();
458
459   virtual const SGValue * getXValue () const { return _xValue; }
460   virtual void setXValue (const SGValue * value) { _xValue = value; }
461   virtual const SGValue * getYValue () const { return _yValue; }
462   virtual void setYValue (const SGValue * value) { _yValue = value; }
463
464 private:
465   const SGValue * _xValue;
466   const SGValue * _yValue;
467 };
468
469
470 \f
471 ////////////////////////////////////////////////////////////////////////
472 // A text layer of an instrument.
473 //
474 // This is a layer holding a string of static and/or generated text.
475 // It is useful for instruments that have text displays, such as
476 // a chronometer, GPS, or NavCom radio.
477 ////////////////////////////////////////////////////////////////////////
478
479 class FGTextLayer : public FGInstrumentLayer
480 {
481 public:
482   typedef enum ChunkType {
483     TEXT,
484     TEXT_VALUE,
485     DOUBLE_VALUE
486   };
487
488   class Chunk {
489   public:
490     Chunk (const string &text, const string &fmt = "%s");
491     Chunk (ChunkType type, const SGValue * value,
492            const string &fmt = "", float mult = 1.0);
493
494     const char * getValue () const;
495   private:
496     ChunkType _type;
497     string _text;
498     const SGValue * _value;
499     string _fmt;
500     float _mult;
501     mutable char _buf[1024];
502   };
503
504   FGTextLayer (int w = -1, int h = -1, Chunk * chunk1 = 0, Chunk * chunk2 = 0,
505                Chunk * chunk3 = 0);
506   virtual ~FGTextLayer ();
507
508   virtual void draw ();
509
510                                 // Transfer pointer!!
511   virtual void addChunk (Chunk * chunk);
512   virtual void setColor (float r, float g, float b);
513   virtual void setPointSize (float size);
514   virtual void setFont (fntFont * font);
515
516 private:
517   typedef vector<Chunk *> chunk_list;
518   chunk_list _chunks;
519   float _color[4];
520
521   float _pointSize;
522                                 // FIXME: need only one globally
523   mutable fntRenderer _renderer;
524 };
525
526
527 \f
528 ////////////////////////////////////////////////////////////////////////
529 // A layer that switches between two other layers.
530 ////////////////////////////////////////////////////////////////////////
531
532 class FGSwitchLayer : public FGInstrumentLayer
533 {
534 public:
535                                 // Transfer pointers!!
536   FGSwitchLayer (int w, int h, const SGValue * value,
537                  FGInstrumentLayer * layer1,
538                  FGInstrumentLayer * layer2);
539   virtual ~FGSwitchLayer ();
540
541   virtual void draw ();
542
543 private:
544   const SGValue * _value;
545   FGInstrumentLayer * _layer1, * _layer2;
546 };
547
548
549 \f
550 ////////////////////////////////////////////////////////////////////////
551 // The current panel, if any.
552 ////////////////////////////////////////////////////////////////////////
553
554 extern FGPanel * current_panel;
555
556
557 \f
558 #endif // __PANEL_HXX
559
560 // end of panel.hxx
561
562