1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
|
/* Interface.h
Copyright (c) 2014 by Michael Zahniser
Endless Sky 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 3 of the License, or (at your option) any later version.
Endless Sky 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, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "text/Alignment.h"
#include "Color.h"
#include "Point.h"
#include "Rectangle.h"
#include "text/Truncate.h"
#include "text/WrappedText.h"
#include <map>
#include <memory>
#include <string>
#include <vector>
class DataNode;
class Information;
class Panel;
class Sprite;
// Class representing a user interface, specified in a data file and filled with
// the contents of an Information object.
class Interface {
public:
void Load(const DataNode &node);
// Draw this interface. If the given panel is not null, also register any
// buttons in this interface with the panel's list of clickable zones.
void Draw(const Information &info, Panel *panel = nullptr) const;
// Get the location of a named point or box.
bool HasPoint(const std::string &name) const;
Point GetPoint(const std::string &name) const;
Rectangle GetBox(const std::string &name) const;
// Get a named value.
double GetValue(const std::string &name) const;
// Get a named list.
const std::vector<double> &GetList(const std::string &name) const;
private:
class AnchoredPoint {
public:
// Get the point's location, given the current screen dimensions.
Point Get() const;
// Get the point's location, treating the Region within the Information as the screen area.
Point Get(const Information &info) const;
void Set(const Point &position, const Point &anchor);
private:
Point position;
Point anchor;
};
class Element {
public:
// State enumeration:
static const int INACTIVE = 0;
static const int ACTIVE = 1;
static const int HOVER = 2;
public:
// Make sure the destructor is virtual, because classes derived from
// this one will be used in a polymorphic list.
Element() = default;
virtual ~Element() = default;
// Create a new element. The alignment of the interface that contains
// this element is used to calculate the element's position.
void Load(const DataNode &node, const Point &globalAnchor);
// Draw this element, relative to the given anchor point. If this is a
// button, it will add a clickable zone to the given panel.
void Draw(const Information &info, Panel *panel) const;
// Set the conditions that control when this element is visible and active.
// An empty string means it is always visible or active.
void SetConditions(const std::string &visible, const std::string &active);
// Get the bounding rectangle, given the current screen dimensions.
Rectangle Bounds() const;
// Get the bounding rectangle, treating the Region within the Information as the screen area.
Rectangle Bounds(const Information &info) const;
protected:
// Parse the given data line: one that is not recognized by Element
// itself. This returns false if it does not recognize the line, either.
virtual bool ParseLine(const DataNode &node);
// Report the actual dimensions of the object that will be drawn.
virtual Point NativeDimensions(const Information &info, int state) const;
// Draw this element in the given rectangle.
virtual void Draw(const Rectangle &rect, const Information &info, int state) const;
// Add any click handlers needed for this element. This will only be
// called if the element is visible and active.
virtual void Place(const Rectangle &bounds, Panel *panel) const;
protected:
AnchoredPoint from;
AnchoredPoint to;
Point alignment;
Point padding;
std::string visibleIf;
std::string activeIf;
};
// This class handles "sprite", "image", and "outline" elements.
class ImageElement : public Element {
public:
ImageElement(const DataNode &node, const Point &globalAnchor);
protected:
// Parse the given data line: one that is not recognized by Element
// itself. This returns false if it does not recognize the line, either.
virtual bool ParseLine(const DataNode &node) override;
// Report the actual dimensions of the object that will be drawn.
virtual Point NativeDimensions(const Information &info, int state) const override;
// Draw this element in the given rectangle.
virtual void Draw(const Rectangle &rect, const Information &info, int state) const override;
private:
const Sprite *GetSprite(const Information &info, int state) const;
private:
// If a name is given, look up the sprite with that name and draw it.
std::string name;
// Otherwise, draw a sprite. Which sprite is drawn depends on the current
// state of this element: inactive, active, or hover.
const Sprite *sprite[3] = {nullptr, nullptr, nullptr};
// If this flag is set, draw the sprite as an outline:
bool isOutline = false;
// Store whether the outline should be colored.
bool isColored = false;
};
// This class contains common members of both text element categories.
class TextElement : public Element {
public:
TextElement(const DataNode &node, const Point &globalAnchor);
protected:
// Parse the given data line: one that is not recognized by Element
// itself. This returns false if it does not recognize the line, either.
virtual bool ParseLine(const DataNode &node) override;
// Add any click handlers needed for this element. This will only be
// called if the element is visible and active.
virtual void Place(const Rectangle &bounds, Panel *panel) const override;
// Fill in any undefined state colors.
void FinishLoadingColors();
// Get text contents of this element.
std::string GetString(const Information &info) const;
protected:
// The string may either be a name of a dynamic string, or static text.
std::string str;
// Color for inactive, active, and hover states.
const Color *color[3] = {nullptr, nullptr, nullptr};
int fontSize = 14;
char buttonKey = '\0';
bool isDynamic = false;
Truncate truncate = Truncate::NONE;
};
// This class handles "label", "string", "button", and "dynamic button" elements.
class BasicTextElement : public TextElement {
public:
BasicTextElement(const DataNode &node, const Point &globalAnchor);
protected:
// Report the actual dimensions of the object that will be drawn.
virtual Point NativeDimensions(const Information &info, int state) const override;
// Draw this element in the given rectangle.
virtual void Draw(const Rectangle &rect, const Information &info, int state) const override;
};
// This class handles "wrapped label", "wrapped string",
// "wrapped button", and "wrapped dynamic button" elements.
class WrappedTextElement : public TextElement {
public:
WrappedTextElement(const DataNode &node, const Point &globalAnchor);
protected:
// Parse the given data line: one that is not recognized by Element
// itself. This returns false if it does not recognize the line, either.
virtual bool ParseLine(const DataNode &node) override;
// Report the actual dimensions of the object that will be drawn.
virtual Point NativeDimensions(const Information &info, int state) const override;
// Draw this element in the given rectangle.
virtual void Draw(const Rectangle &rect, const Information &info, int state) const override;
private:
mutable WrappedText text;
Alignment textAlignment = Alignment::LEFT;
};
// This class handles "bar" and "ring" elements.
class BarElement : public Element {
public:
BarElement(const DataNode &node, const Point &globalAnchor);
protected:
// Parse the given data line: one that is not recognized by Element
// itself. This returns false if it does not recognize the line, either.
virtual bool ParseLine(const DataNode &node) override;
// Draw this element in the given rectangle.
virtual void Draw(const Rectangle &rect, const Information &info, int state) const override;
private:
std::string name;
const Color *fromColor = nullptr;
const Color *toColor = nullptr;
float width = 2.f;
bool reversed = false;
bool isRing = false;
double spanAngle = 360.;
double startAngle = 0.;
};
// This class handles "pointer" elements.
class PointerElement : public Element {
public:
PointerElement(const DataNode &node, const Point &globalAnchor);
protected:
// Parse the given data line: one that is not recognized by Element
// itself. This returns false if it does not recognize the line, either.
virtual bool ParseLine(const DataNode &node) override;
// Draw this element in the given rectangle.
virtual void Draw(const Rectangle &rect, const Information &info, int state) const override;
private:
const Color *color = nullptr;
Point orientation;
};
// This class handles "line" elements.
class LineElement : public Element {
public:
LineElement(const DataNode &node, const Point &globalAnchor);
protected:
// Parse the given data line: one that is not recognized by Element
// itself. This returns false if it does not recognize the line, either.
virtual bool ParseLine(const DataNode &node) override;
// Draw this element in the given rectangle.
virtual void Draw(const Rectangle &rect, const Information &info, int state) const override;
private:
const Color *color = nullptr;
};
private:
std::vector<std::unique_ptr<Element>> elements;
std::map<std::string, Element> points;
std::map<std::string, double> values;
std::map<std::string, std::vector<double>> lists;
};
|