// panel.hxx - generic support classes for a 2D panel. // // Written by David Megginson, started January 2000. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // $Id$ #ifndef __PANEL_HXX #define __PANEL_HXX #ifndef __cplusplus # error This library requires C++ #endif #ifdef HAVE_CONFIG_H # include #endif #include #ifdef HAVE_WINDOWS_H # include #endif #include #include #include #include #include #include FG_USING_STD(vector); FG_USING_STD(map); class FGPanelInstrument; //////////////////////////////////////////////////////////////////////// // Texture manager (should migrate out into FGFS). // // This class ensures that no texture is loaded more than once. //////////////////////////////////////////////////////////////////////// class FGTextureManager { public: static ssgTexture * createTexture(const string &relativePath); private: static map _textureMap; }; //////////////////////////////////////////////////////////////////////// // Cropped texture (should migrate out into FGFS). // // This structure wraps an SSG texture with cropping information. //////////////////////////////////////////////////////////////////////// class FGCroppedTexture { public: FGCroppedTexture (); FGCroppedTexture (const string &path, float _minX = 0.0, float _minY = 0.0, float _maxX = 1.0, float _maxY = 1.0); virtual ~FGCroppedTexture (); virtual void setPath (const string &path) { _path = path; } virtual const string &getPath () const { return _path; } virtual ssgTexture * getTexture (); virtual void setCrop (float minX, float minY, float maxX, float maxY) { _minX = minX; _minY = minY; _maxX = maxX; _maxY = maxY; } virtual float getMinX () const { return _minX; } virtual float getMinY () const { return _minY; } virtual float getMaxX () const { return _maxX; } virtual float getMaxY () const { return _maxY; } private: string _path; ssgTexture * _texture; float _minX, _minY, _maxX, _maxY; }; //////////////////////////////////////////////////////////////////////// // Instrument panel class. // // The panel is a container that has a background texture and holds // zero or more instruments. The panel will order the instruments to // redraw themselves when necessary, and will pass mouse clicks on to // the appropriate instruments for processing. //////////////////////////////////////////////////////////////////////// class FGPanel { public: FGPanel (int x, int y, int w, int h); virtual ~FGPanel (); // transfer pointer ownership!!! virtual void addInstrument (FGPanelInstrument * instrument); // Update the panel (every frame). virtual void update () const; // Background texture. virtual void setBackground (ssgTexture * texture); // Make the panel visible or invisible. virtual bool getVisibility () const; virtual void setVisibility (bool visibility); // Handle a mouse click. virtual bool doMouseAction (int button, int updown, int x, int y); private: mutable bool _visibility; mutable bool _mouseDown; mutable int _mouseButton, _mouseX, _mouseY; mutable int _mouseDelay; mutable FGPanelInstrument * _mouseInstrument; typedef vector instrument_list_type; int _x, _y, _w, _h; int _panel_h; ssgTexture * _bg; // List of instruments in panel. instrument_list_type _instruments; }; //////////////////////////////////////////////////////////////////////// // Base class for user action types. // // Individual instruments can have actions associated with a mouse // click in a rectangular area. Current concrete classes include // FGAdjustAction, FGSwapAction, and FGToggleAction. //////////////////////////////////////////////////////////////////////// class FGPanelAction { public: FGPanelAction (); FGPanelAction (int button, int x, int y, int w, int h); virtual ~FGPanelAction (); // Getters. virtual int getButton () const { return _button; } virtual int getX () const { return _x; } virtual int getY () const { return _y; } virtual int getWidth () const { return _w; } virtual int getHeight () const { return _h; } // Setters. virtual void setButton (int button) { _button = button; } virtual void setX (int x) { _x = x; } virtual void setY (int y) { _y = y; } virtual void setWidth (int w) { _w = w; } virtual void setHeight (int h) { _h = h; } // Check whether we're in the area. virtual bool inArea (int button, int x, int y) { return (button == _button && x >= _x && x < _x + _w && y >= _y && y < _y + _h); } // Perform the action. virtual void doAction () = 0; private: int _button; int _x; int _y; int _w; int _h; }; //////////////////////////////////////////////////////////////////////// // Adjustment action. // // This is an action to increase or decrease an FGFS value by a certain // increment within a certain range. If the wrap flag is true, the // value will wrap around if it goes below min or above max; otherwise, // it will simply stop at min or max. //////////////////////////////////////////////////////////////////////// class FGAdjustAction : public FGPanelAction { public: FGAdjustAction (int button, int x, int y, int w, int h, SGValue * value, float increment, float min, float max, bool wrap=false); virtual ~FGAdjustAction (); virtual void doAction (); private: SGValue * _value; float _increment; float _min; float _max; bool _wrap; }; //////////////////////////////////////////////////////////////////////// // Swap action. // // This is an action to swap two values. It's currently used in the // navigation radios. //////////////////////////////////////////////////////////////////////// class FGSwapAction : public FGPanelAction { public: FGSwapAction (int button, int x, int y, int w, int h, SGValue * value1, SGValue * value2); virtual ~FGSwapAction (); virtual void doAction (); private: SGValue * _value1; SGValue * _value2; }; //////////////////////////////////////////////////////////////////////// // Toggle action. // // This is an action to toggle a boolean value. //////////////////////////////////////////////////////////////////////// class FGToggleAction : public FGPanelAction { public: FGToggleAction (int button, int x, int y, int w, int h, SGValue * value); virtual ~FGToggleAction (); virtual void doAction (); private: SGValue * _value; }; //////////////////////////////////////////////////////////////////////// // Abstract base class for a panel instrument. // // A panel instrument consists of zero or more actions, associated // with mouse clicks in rectangular areas. Currently, the only // concrete class derived from this is FGLayeredInstrument, but others // may show up in the future (some complex instruments could be // entirely hand-coded, for example). //////////////////////////////////////////////////////////////////////// class FGPanelInstrument { public: FGPanelInstrument (); FGPanelInstrument (int x, int y, int w, int h); virtual ~FGPanelInstrument (); virtual void draw () = 0; virtual void setPosition(int x, int y); virtual void setSize(int w, int h); virtual int getXPos () const; virtual int getYPos () const; virtual int getWidth () const; virtual int getHeight () const; // Coordinates relative to centre. // Transfer pointer ownership!! virtual void addAction (FGPanelAction * action); // Coordinates relative to centre. virtual bool doMouseAction (int button, int x, int y); protected: int _x, _y, _w, _h; typedef vector action_list_type; action_list_type _actions; }; //////////////////////////////////////////////////////////////////////// // Abstract base class for an instrument layer. // // The FGLayeredInstrument class builds up instruments by using layers // of textures or text. Each layer can have zero or more // transformations applied to it: for example, a needle layer can // rotate to show the altitude or airspeed. //////////////////////////////////////////////////////////////////////// /** * A transformation for a layer. */ class FGPanelTransformation { public: enum Type { XSHIFT, YSHIFT, ROTATION }; FGPanelTransformation (); FGPanelTransformation (Type type, const SGValue * value, float min, float max, float factor, float offset); virtual ~FGPanelTransformation (); Type type; const SGValue * value; float min; float max; float factor; float offset; }; /** * A single layer of a multi-layered instrument. * * Each layer can be subject to a series of transformations based * on current FGFS instrument readings: for example, a texture * representing a needle can rotate to show the airspeed. */ class FGInstrumentLayer { public: FGInstrumentLayer (int w = -1, int h = -1); virtual ~FGInstrumentLayer (); virtual void draw () = 0; virtual void transform () const; virtual int getWidth () const { return _w; } virtual int getHeight () const { return _h; } virtual void setWidth (int w) { _w = w; } virtual void setHeight (int h) { _h = h; } // Transfer pointer ownership!! // DEPRECATED virtual void addTransformation (FGPanelTransformation * transformation); protected: int _w, _h; typedef vector transformation_list; transformation_list _transformations; }; //////////////////////////////////////////////////////////////////////// // An instrument composed of layers. // // This class represents an instrument which is simply a series of // layers piled one on top of the other, each one undergoing its own // set of transformations. For example, one layer can represent // the instrument's face (which doesn't move), while the next layer // can represent a needle that rotates depending on an FGFS variable. //////////////////////////////////////////////////////////////////////// /** * An instrument constructed of multiple layers. * * Each individual layer can be rotated or shifted to correspond * to internal FGFS instrument readings. */ class FGLayeredInstrument : public FGPanelInstrument { public: typedef vector layer_list; FGLayeredInstrument (int x, int y, int w, int h); virtual ~FGLayeredInstrument (); virtual void draw (); // Transfer pointer ownership!! virtual int addLayer (FGInstrumentLayer *layer); virtual int addLayer (FGCroppedTexture &texture, int w = -1, int h = -1); // Transfer pointer ownership!! virtual void addTransformation (FGPanelTransformation * transformation); protected: layer_list _layers; }; //////////////////////////////////////////////////////////////////////// // A textured layer of an instrument. // // This is a layer holding a single texture. Normally, the texture's // backgound should be transparent so that lower layers and the panel // background can show through. //////////////////////////////////////////////////////////////////////// class FGTexturedLayer : public FGInstrumentLayer { public: FGTexturedLayer (int w = -1, int h = -1) : FGInstrumentLayer(w, h) {} FGTexturedLayer (const FGCroppedTexture &texture, int w = -1, int h = -1); virtual ~FGTexturedLayer (); virtual void draw (); virtual void setTexture (const FGCroppedTexture &texture) { _texture = texture; } virtual FGCroppedTexture &getTexture () { return _texture; } virtual const FGCroppedTexture &getTexture () const { return _texture; } private: mutable FGCroppedTexture _texture; }; //////////////////////////////////////////////////////////////////////// // A moving window on a texture. // // This layer automatically recrops a cropped texture based on // property values, creating a moving window over the texture. //////////////////////////////////////////////////////////////////////// class FGWindowLayer : public FGTexturedLayer { public: FGWindowLayer (int w = -1, int h = -1); FGWindowLayer (const FGCroppedTexture &texture, int w = -1, int h = -1); virtual ~FGWindowLayer (); virtual void draw (); virtual const SGValue * getXValue () const { return _xValue; } virtual void setXValue (const SGValue * value) { _xValue = value; } virtual const SGValue * getYValue () const { return _yValue; } virtual void setYValue (const SGValue * value) { _yValue = value; } private: const SGValue * _xValue; const SGValue * _yValue; }; //////////////////////////////////////////////////////////////////////// // A text layer of an instrument. // // This is a layer holding a string of static and/or generated text. // It is useful for instruments that have text displays, such as // a chronometer, GPS, or NavCom radio. //////////////////////////////////////////////////////////////////////// class FGTextLayer : public FGInstrumentLayer { public: typedef enum ChunkType { TEXT, TEXT_VALUE, DOUBLE_VALUE }; class Chunk { public: Chunk (const string &text, const string &fmt = "%s"); Chunk (ChunkType type, const SGValue * value, const string &fmt = "", float mult = 1.0); const char * getValue () const; private: ChunkType _type; string _text; const SGValue * _value; string _fmt; float _mult; mutable char _buf[1024]; }; FGTextLayer (int w = -1, int h = -1, Chunk * chunk1 = 0, Chunk * chunk2 = 0, Chunk * chunk3 = 0); virtual ~FGTextLayer (); virtual void draw (); // Transfer pointer!! virtual void addChunk (Chunk * chunk); virtual void setColor (float r, float g, float b); virtual void setPointSize (float size); virtual void setFont (fntFont * font); private: typedef vector chunk_list; chunk_list _chunks; float _color[4]; float _pointSize; // FIXME: need only one globally mutable fntRenderer _renderer; }; //////////////////////////////////////////////////////////////////////// // A layer that switches between two other layers. //////////////////////////////////////////////////////////////////////// class FGSwitchLayer : public FGInstrumentLayer { public: // Transfer pointers!! FGSwitchLayer (int w, int h, const SGValue * value, FGInstrumentLayer * layer1, FGInstrumentLayer * layer2); virtual ~FGSwitchLayer (); virtual void draw (); private: const SGValue * _value; FGInstrumentLayer * _layer1, * _layer2; }; //////////////////////////////////////////////////////////////////////// // The current panel, if any. //////////////////////////////////////////////////////////////////////// extern FGPanel * current_panel; #endif // __PANEL_HXX // end of panel.hxx