1 // -*- C++ -*-
2 /* GG is a GUI for OpenGL.
3    Copyright (C) 2003-2008 T. Zachary Laine
4 
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public License
7    as published by the Free Software Foundation; either version 2.1
8    of the License, or (at your option) any later version.
9 
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA
19 
20    If you do not wish to comply with the terms of the LGPL please
21    contact the author as other terms are available for a fee.
22 
23    Zach Laine
24    whatwasthataddress@gmail.com */
25 
26 /** \file GUI.h \brief Contains GUI class, which encapsulates the state and
27     behavior of the entire GG GUI. */
28 
29 #ifndef _GG_GUI_h_
30 #define _GG_GUI_h_
31 
32 #include <GG/Font.h>
33 #include <GG/WndEvent.h>
34 
35 #include <boost/signals2/signal.hpp>
36 
37 #include <chrono>
38 
39 
40 namespace boost { namespace archive {
41     class xml_oarchive;
42     class xml_iarchive;
43 } }
44 
45 namespace GG {
46 
47 class Cursor;
48 class Wnd;
49 class StyleFactory;
50 class Texture;
51 class Timer;
52 struct GUIImpl;
53 
54 template <typename T>
LockAndResetIfExpired(std::weak_ptr<T> & ptr)55 std::shared_ptr<T> LockAndResetIfExpired(std::weak_ptr<T>& ptr) {
56     auto locked = ptr.lock();
57     if (!locked)
58         ptr.reset();
59     return locked;
60 }
61 
62 /** \brief An abstract base for an GUI framework class to drive the GG GUI.
63 
64     This class has all the essential services that GG requires:
65     - GUI initialization and emergency exit
66     - GG event handling
67     - rendering of GUI windows
68     - entry into and cleanup after a "2D" mode, in case the app also uses non-orthographic 3D projections
69     - registration into, removal from, and movement within a z-ordering of windows, including handling of "always-on-top" windows
70     - handling of modal windows
71     - drag-and-drop support
72     - inter-frame time updates and FPS calculations
73     - limits on FPS speed
74     - access to the dimensions of the application window or screen
75     - mouse state information
76     - keyboard accelerators
77     - management of fonts and textures
78 
79     <p>The user is required to provide several functions.  The most vital
80     functions the user is required to provide are: Enter2DMode(),
81     Exit2DMode() and Run()[virtual private].  Without these, GUI is pretty
82     useless.  In addition, HandleEvent() must be driven from Run().  The
83     code driving HandleEvent() must interact with the hardware and/or operating
84     system, and supply the appropriate EventType's, key presses, and mouse
85     position info to HandleEvent().
86 
87     <p>Keyboard accelerators may be defined, as mentioned above.  Each defined
88     accelerator has its own signal which is emitted each time the accelerator
89     is detected.  Client code should listen to the appropriate signal to act
90     on an accelerator invocation.  Each slot that is signalled with a keyboard
91     accelerator should return true if it processed the accelerator, or false
92     otherwise.  This lets GUI know whether or not it should create a keystroke
93     event and process it normally, sending it to the Wnd that currently has
94     focus.  Note that since signals can be connected to multiple slots, if
95     even one slot returns true, no kestroke event is created.  It is perfectly
96     legal to return false even if an accelerator is processed, as long as you
97     also then want the focus Wnd to receive a keystroke event.  Also, note
98     that all accelerators are processed before, and possbily instead of, any
99     key events.  So setting a plain "h" as a keyboard accelerator can (if it
100     is processed normally by a slot) prevent any Wnd anywhere in your
101     application from receiving "h" keystrokes.  To avoid this:
102     - Define accelerators with modifier keys like CTRL and ALT, or
103     - Have slots that process these accelerators return false, or
104     - Do not connect anything to such an accelerator, in which case it will return false.
105 
106     <p>A GUI-wide StyleFactory can be set; this controls the actual types of
107     controls and dialogs that are created when a control or dialog creates one
108     (e.g. when FileDlg encounters an error and creates a ThreeButtonDlg).
109     This is overridden by any StyleFactory that may be installed in an
110     individual Wnd.
111 
112     <p>A note about "button-down-repeat".  When you click on the down-button
113     on a scroll-bar, you probably expect the the button's action (scrolling
114     down one increment) to repeat when you hold down the button, much like the
115     way kestrokes are repeated when you hold down a keyboard key.  This is in
116     fact what happens, and it is accomplished by having the scroll and its
117     buttons respond to extra LButtonDown events generated by the GUI.  These
118     extra messages, occur ButtonDownRepeatDelay() milliseconds after the
119     button is first depressed, repeating every ButtonDownRepeatInterval()
120     milliseconds thereafter.  Only Wnds created with the REPEAT_BUTTON_DOWN
121     flag receive such extra messages.
122 */
123 class GG_API GUI
124 {
125 private:
126     struct OrCombiner
127     {
128         typedef bool result_type;
129         template <typename InIt> bool operator()(InIt first, InIt last) const;
130     };
131 
132 public:
133     /** \name Signal Types */ ///@{
134     /** Emitted when a keyboard accelerator is invoked. A return value of true
135         indicates that the accelerator was processed by some slot; otherwise,
136         a keystroke event is processed instead. */
137     typedef boost::signals2::signal<bool (), OrCombiner> AcceleratorSignalType;
138     //@}
139 
140     /// These are the only events absolutely necessary for GG to function
141     /// properly
142     enum EventType : int {
143         IDLE,        ///< nothing has changed since the last message, but the GUI might want to update some things anyway
144         KEYPRESS,    ///< a down key press or key repeat, with or without modifiers like Alt, Ctrl, Meta, etc.
145         KEYRELEASE,  ///< a key release, with or without modifiers like Alt, Ctrl, Meta, etc.
146         TEXTINPUT,   ///< user inputted unicode text using some method
147         LPRESS,      ///< a left mouse button press
148         MPRESS,      ///< a middle mouse button press
149         RPRESS,      ///< a right mouse button press
150         LRELEASE,    ///< a left mouse button release
151         MRELEASE,    ///< a middle mouse button release
152         RRELEASE,    ///< a right mouse button release
153         MOUSEMOVE,   ///< movement of the mouse; may include relative motion in addition to absolute position
154         MOUSEWHEEL   ///< rolling of the mouse wheel; this event is accompanied by the amount of roll in the y-component of the mouse's relative position (+ is up, - is down)
155     };
156 
157     /** The type of iterator returned by non-const accel_begin() and
158         accel_end(). */
159     typedef std::set<std::pair<Key, Flags<ModKey>>>::iterator accel_iterator;
160 
161     /** The type of iterator returned by const accel_begin() and
162         accel_end(). */
163     typedef std::set<std::pair<Key, Flags<ModKey>>>::const_iterator const_accel_iterator;
164 
165     /** \name Structors */ ///@{
166     virtual ~GUI();
167     //@}
168 
169     /** \name Accessors */ ///@{
170     const std::string&          AppName() const;                    ///< returns the user-defined name of the application
171     std::shared_ptr<Wnd>        FocusWnd() const;                   ///< returns the GG::Wnd that currently has the input focus
172     bool                        FocusWndAcceptsTypingInput() const; ///< returns true iff the current focus GG::Wnd accepts typing input
173     std::shared_ptr<Wnd>        PrevFocusInteractiveWnd() const;    ///< returns the previous Wnd to the current FocusWnd. Cycles through INTERACTIVE Wnds, in order determined by parent-child relationships
174     std::shared_ptr<Wnd>        NextFocusInteractiveWnd() const;    ///< returns the next Wnd to the current FocusWnd.
175     std::shared_ptr<Wnd>        GetWindowUnder(const Pt& pt) const; ///< returns the GG::Wnd under the point pt
176     virtual unsigned int        Ticks() const = 0;                  ///< returns milliseconds since the app started running
177     bool                        RenderingDragDropWnds() const;      ///< returns true iff drag-and-drop Wnds are currently being rendered
178     bool                        FPSEnabled() const;                 ///< returns true iff FPS calulations are turned on
179     double                      FPS() const;                        ///< returns the frames per second at which the GUI is rendering
180     std::string                 FPSString() const;                  ///< returns a string of the form "[m_FPS] frames per second"
181     double                      MaxFPS() const;                     ///< returns the maximum allowed frames per second of rendering speed.  0 indicates no limit.
182     virtual X                   AppWidth() const = 0;               ///< returns the width of the application window/screen
183     virtual Y                   AppHeight() const = 0;              ///< returns the height of the application window/screen
184     unsigned int                KeyPressRepeatDelay() const;        ///< returns the \a delay value set by EnableKeyPressRepeat()
185     unsigned int                KeyPressRepeatInterval() const;     ///< returns the \a interval value set by EnableKeyPressRepeat()
186     unsigned int                ButtonDownRepeatDelay() const;      ///< returns the \a delay value set by EnableMouseButtonDownRepeat()
187     unsigned int                ButtonDownRepeatInterval() const;   ///< returns the \a interval value set by EnableMouseButtonDownRepeat()
188     unsigned int                DoubleClickInterval() const;        ///< returns the maximum interval allowed between clicks that is still considered a double-click, in ms
189     unsigned int                MinDragTime() const;                ///< returns the minimum time (in ms) an item must be dragged before it is a valid drag
190     unsigned int                MinDragDistance() const;            ///< returns the minimum distance an item must be dragged before it is a valid drag
191     bool                        DragWnd(const Wnd* wnd, unsigned int mouse_button) const;   ///< returns true if \a wnd is currently being dragged with button \a mouse_button
192     bool                        DragDropWnd(const Wnd* wnd) const;  ///< returns true if \a wnd is currently begin dragged as part of a drag-and-drop operation
193     bool                        AcceptedDragDropWnd(const Wnd* wnd) const;  ///< returns true if \a wnd is currently begin dragged as part of a drag-and-drop operation, and it is over a drop target that will accept it
194     bool                        MouseButtonDown(unsigned int bn) const;     ///< returns the up/down states of the mouse buttons
195     Pt                          MousePosition() const;              ///< returns the absolute position of mouse, based on the last mouse motion event
196     Pt                          MouseMovement() const;              ///< returns the relative position of mouse, based on the last mouse motion event
197     Flags<ModKey>               ModKeys() const;                    ///< returns the set of modifier keys that are currently depressed, based on the last event
198     bool                        MouseLRSwapped() const;             ///< returns true if the left and right mouse button press events are set to be swapped before event handling. This is to facilitate left-handed mouse users semi-automatically.
199     virtual std::string         ClipboardText() const;              ///< returns text stored in a clipboard
200 
201     /** Returns the (begin, end) indices of the code points of all the
202         word-tokens in the given string.  This is perhaps an odd place for
203         this function to exist, but the notion of what a "word" is is so
204         application-specific that it was placed here so that users can
205         customize this behavior. */
206     virtual std::set<std::pair<CPSize, CPSize>>     FindWords(const std::string& str) const;
207     virtual std::set<std::pair<StrSize, StrSize>>   FindWordsStringIndices(const std::string& str) const;
208     /** Returns true if \a word is a word that appears in \a str */
209     virtual bool                                    ContainsWord(const std::string& str, const std::string& word) const;
210 
211     /** Returns the currently-installed style factory. */
212     const std::shared_ptr<StyleFactory>&    GetStyleFactory() const;
213 
214     bool                                    RenderCursor() const; ///< returns true iff the GUI is responsible for rendering the cursor
215 
216     /* Returns the currently-installed cursor. */
217     const std::shared_ptr<Cursor>&          GetCursor() const;
218 
219     /** Returns an iterator to one past the first defined keyboard accelerator. */
220     const_accel_iterator                    accel_begin() const;
221 
222     /** Returns an iterator to one past the last defined keyboard accelerator. */
223     const_accel_iterator                    accel_end() const;
224 
225     /** Returns the signal that is emitted when the requested keyboard accelerator is invoked. */
226     AcceleratorSignalType&                  AcceleratorSignal(Key key, Flags<ModKey> mod_keys = MOD_KEY_NONE) const;
227 
228     /** Returns true iff keyboard accelerator signals fire while modal windows are open. */
229     bool                                    ModalAcceleratorSignalsEnabled() const;
230 
231     /** Returns true iff any modal Wnds are open. */
232     bool                                    ModalWndsOpen() const;
233 
234     /** Saves \a wnd to file \a filename during the next render cycle.  If \a
235         wnd is not rendered during the render cycle, or PNG support is not
236         enabled, this is a no-op. */
237     void                                    SaveWndAsPNG(const Wnd* wnd, const std::string& filename) const;
238     //@}
239 
240     /** \name Mutators */ ///@{
241     //! Executes main event handler/render loop
242     virtual void    Run() = 0;
243 
244     virtual void    ExitApp(int code = 0) = 0;           ///< does basic clean-up, then calls exit(); callable from anywhere in user code via GetGUI()
245 
246     /** Handles all waiting system events (from SDL, DirectInput, etc.).  This
247         function should only be called from custom RunModal event
248         handlers. */
249     virtual void    HandleSystemEvents() = 0;
250 
251     /** Event handler for GG events. */
252     void            HandleGGEvent(EventType event, Key key, std::uint32_t key_code_point, Flags<ModKey> mod_keys, const Pt& pos, const Pt& rel, const std::string* text = nullptr);
253 
254     void            ClearEventState();
255 
256     void            SetFocusWnd(const std::shared_ptr<Wnd>& wnd);          ///< sets the input focus window to \a wnd
257     /** Suspend the GUI thread for \p us microseconds.  Singlethreaded GUI subclasses may do
258         nothing here, or may pause for \p us microseconds. */
259     virtual void    Wait(std::chrono::microseconds us);
260     virtual void    Wait(unsigned int ms);          ///< suspends the GUI thread for \a ms milliseconds.  Singlethreaded GUI subclasses may do nothing here, or may pause for \a ms milliseconds.
261 
262     /** Adds \p wnd into the z-list.  A registered window is owned by the GUI as a top level
263         window. Registering a null pointer or registering the same window multiple times is a no-op. */
264     void            Register(std::shared_ptr<Wnd> wnd);
265     /** Adds \p wnd onto the modal windows "stack".  Modal windows are owned by the GUI as a
266         top-level window. */
267     void            RegisterModal(std::shared_ptr<Wnd> wnd);
268     void            RunModal(std::shared_ptr<Wnd> wnd, bool& done);
269     void            Remove(const std::shared_ptr<Wnd>& wnd);               ///< removes \a wnd from the z-list.  Removing a null pointer or removing the same window multiple times is a no-op.
270     void            MoveUp(const std::shared_ptr<Wnd>& wnd);               ///< moves \a wnd to the top of the z-list
271     void            MoveDown(const std::shared_ptr<Wnd>& wnd);             ///< moves \a wnd to the bottom of the z-list
272 
273     /** Adds \a wnd to the set of current drag-and-drop Wnds, to be rendered
274         \a offset pixels from the cursor position. \a originating_wnd
275         indicates the original owner of \a wnd before the drag-and-drop.
276         \throw std::runtime_error May throw std::runtime_error if there are
277         already other Wnds registered that belong to a window other than \a
278         originating_wnd. */
279     void           RegisterDragDropWnd(std::shared_ptr<Wnd> wnd, const Pt& offset, std::shared_ptr<Wnd> originating_wnd);
280     void           CancelDragDrop();             ///< clears the set of current drag-and-drop Wnds
281 
282     void           RegisterTimer(Timer& timer);  ///< adds \a timer to the list of active timers
283     void           RemoveTimer(Timer& timer);    ///< removes \a timer from the list of active timers
284 
285     virtual void   Enter2DMode() = 0;            ///< saves any current GL state, sets up GG-friendly 2D drawing mode.  GG expects an orthographic projection, with the origin in the upper left corner, and with one unit of GL space equal to one pixel on the screen.
286     virtual void   Exit2DMode() = 0;             ///< restores GL to its condition prior to Enter2DMode() call
287     void           EnableFPS(bool b = true);     ///< turns FPS calulations on or off
288     void           SetMaxFPS(double max);        ///< sets the maximum allowed FPS, so the render loop does not act as a spinlock when it runs very quickly.  0 indicates no limit.
289     void           EnableKeyPressRepeat(unsigned int delay, unsigned int interval);         ///< delay and interval are in ms; Setting delay to 0 disables key press repeating completely.
290     void           EnableMouseButtonDownRepeat(unsigned int delay, unsigned int interval);  ///< delay and interval are in ms; Setting delay to 0 disables mouse button-down repeating completely.
291     void           SetDoubleClickInterval(unsigned int interval); ///< sets the maximum interval allowed between clicks that is still considered a double-click, in ms
292     void           SetMinDragTime(unsigned int time);     ///< sets the minimum time (in ms) an item must be dragged before it is a valid drag
293     void           SetMinDragDistance(unsigned int distance); ///< sets the minimum distance an item must be dragged before it is a valid drag
294 
295     /** Returns an iterator to the first defined keyboard accelerator. */
296     accel_iterator accel_begin();
297 
298     /** Returns an iterator to one past the last defined keyboard accelerator. */
299     accel_iterator accel_end();
300 
301     /** Establishes a keyboard accelerator.  Any key modifiers may be
302         specified, or none at all. */
303     void           SetAccelerator(Key key, Flags<ModKey> mod_keys = MOD_KEY_NONE);
304 
305     /** Removes a keyboard accelerator.  Any key modifiers may be specified,
306         or none at all. */
307     void           RemoveAccelerator(Key key, Flags<ModKey> mod_keys = MOD_KEY_NONE);
308 
309     /** Removes a keyboard accelerator. */
310     void           RemoveAccelerator(accel_iterator it);
311 
312     /** Sets whether to emit keyboard accelerator signals while modal windows are open. */
313     void           EnableModalAcceleratorSignals(bool allow = true);
314 
315     /** Sets whether to swap left and right mouse button events. */
316     void           SetMouseLRSwapped(bool swapped = true);
317 
318     /** Returns a shared_ptr to the desired font, supporting all printable
319         ASCII characters. */
320     std::shared_ptr<Font> GetFont(const std::string& font_filename, unsigned int pts);
321 
322     /** Returns a shared_ptr to the desired font, supporting all printable
323         ASCII characters, from the in-memory contents \a file_contents. */
324     std::shared_ptr<Font> GetFont(const std::string& font_filename, unsigned int pts,
325                                   const std::vector<unsigned char>& file_contents);
326 
327     /** Returns a shared_ptr to the desired font, supporting all the
328         characters in the UnicodeCharsets in the range [first, last). */
329     template <typename CharSetIter>
330     std::shared_ptr<Font> GetFont(const std::string& font_filename, unsigned int pts,
331                                   CharSetIter first, CharSetIter last);
332 
333     /** Returns a shared_ptr to the desired font, supporting all the
334         characters in the UnicodeCharsets in the range [first, last), from the
335         in-memory contents \a file_contents. */
336     template <typename CharSetIter>
337     std::shared_ptr<Font> GetFont(const std::string& font_filename, unsigned int pts,
338                                   const std::vector<unsigned char>& file_contents,
339                                   CharSetIter first, CharSetIter last);
340 
341     /** Returns a shared_ptr to existing font \a font in a new size, \a pts. */
342     std::shared_ptr<Font> GetFont(const std::shared_ptr<Font>& font, unsigned int pts);
343 
344     /** Removes the desired font from the managed pool; since shared_ptr's are
345         used, the font may be deleted much later. */
346     void                       FreeFont(const std::string& font_filename, unsigned int pts);
347 
348     /** Adds an already-constructed texture to the managed pool \warning
349         calling code <b>must not</b> delete \a texture; the texture pool will
350         do that. */
351     std::shared_ptr<Texture> StoreTexture(Texture* texture, const std::string& texture_name);
352 
353     /** Adds an already-constructed texture to the managed pool. */
354     std::shared_ptr<Texture> StoreTexture(const std::shared_ptr<Texture> &texture, const std::string& texture_name);
355 
356     /** Loads the requested texture from file \a name; mipmap textures are
357       * generated if \a mipmap is true. */
358     std::shared_ptr<Texture> GetTexture(const std::string& name, bool mipmap = false);
359 
360     /** Loads the requested texture from file \a name; mipmap textures are
361       * generated if \a mipmap is true. */
362     std::shared_ptr<Texture> GetTexture(const boost::filesystem::path& path, bool mipmap = false);
363 
364     /** Removes the desired texture from the managed pool; since shared_ptr's
365       * are used, the texture may be deleted much later. */
366     void                       FreeTexture(const std::string& name);
367 
368     /** Removes the desired texture from the managed pool; since shared_ptr's
369       * are used, the texture may be deleted much later. */
370     void                       FreeTexture(const boost::filesystem::path& path);
371 
372     /** Sets the currently-installed style factory. */
373     void SetStyleFactory(const std::shared_ptr<StyleFactory>& factory);
374 
375     void RenderCursor(bool render); ///< set this to true iff the GUI should render the cursor
376 
377     /** Sets the currently-installed cursor. */
378     void SetCursor(const std::shared_ptr<Cursor>& cursor);
379 
380     virtual bool SetClipboardText(const std::string& text); ///< sets text stored in clipboard
381     bool CopyFocusWndText();                                ///< copies current focus Wnd as text to clipboard
382     bool CopyWndText(const Wnd* wnd);                       ///< copies \a wnd as text to clipboard
383     bool PasteFocusWndText(const std::string& text);        ///< attempts to paste \a text into the current focus Wnd
384     bool PasteWndText(Wnd* wnd, const std::string& text);   ///< attempts to paste \a text into the Wnd \a wnd
385     bool PasteFocusWndClipboardText();                      ///< attempts to paste clipboard contents into the current focus Wnd
386     bool CutFocusWndText();                                 ///< copies current focus Wnd as text to clipboard, then pastes an empty string into that Wnd
387     bool CutWndText(Wnd* wnd);                              ///< copies \a wnd as text to clipboard, then pastes an empty string to that Wnd
388     bool FocusWndSelectAll();                               ///< selects all of anything selectable in the current focus Wnd
389     bool WndSelectAll(Wnd* wnd);                            ///< selects all of anything selectable in the Wnd \a wnd
390     bool FocusWndDeselect();                                ///< deselects anything selected in the current focus Wnd
391     bool WndDeselect(Wnd* wnd);                             ///< deselects all of anything selectable in the Wnd \a wnd
392 
393     bool SetPrevFocusWndInCycle();                          ///< sets the focus Wnd to the next INTERACTIVE Wnd in a cycle determined by Wnd parent-child relationships
394     bool SetNextFocusWndInCycle();                          ///< sets the focus Wnd to the next in the cycle.
395     //@}
396 
397     static GUI*  GetGUI();                  ///< allows any GG code access to GUI framework by calling GUI::GetGUI()
398 
399     /** If \p wnd is visible recursively call PreRenderWindow() on all \p wnd's children and then
400         call \p wnd->PreRender().  The order guarantees that when wnd->PreRender() is called all
401         of \p wnd's children have already been prerendered.*/
402     static void  PreRenderWindow(const std::shared_ptr<Wnd>& wnd);
403     static void  PreRenderWindow(Wnd* wnd);
404     static void  RenderWindow(const std::shared_ptr<Wnd>& wnd);    ///< renders a window (if it is visible) and all its visible descendents recursively
405     static void  RenderWindow(Wnd* wnd);    ///< renders a window (if it is visible) and all its visible descendents recursively
406     virtual void RenderDragDropWnds();      ///< renders Wnds currently being drag-dropped
407 
408 
409     /** Emitted whenever the GUI's AppWidth() and/or AppHeight() change. */
410     boost::signals2::signal<void (X, Y)>    WindowResizedSignal;
411 
412     /** Emitted whenever the GUI's window's left and top positions change. */
413     boost::signals2::signal<void (X, Y)>    WindowMovedSignal;
414 
415     /** Emitted when the Window in which the GUI is operating gains or loses
416       * focus. bool parameter is true when gaining focus, and false otherwise.*/
417      boost::signals2::signal<void (bool)>   FocusChangedSignal;
418 
419     /** Emitted whenever the window manager requests the window close. */
420     boost::signals2::signal<void ()>    WindowClosingSignal;
421 
422     /** Emitted whenever the app is requested to close. */
423     boost::signals2::signal<void ()>    AppQuittingSignal;
424 
425     /** \name Exceptions */ ///@{
426     /** The base class for GUI exceptions. */
427     GG_ABSTRACT_EXCEPTION(Exception);
428 
429     /** Thrown when an attempt is made to invoke either of the save- or
430         load-window functions before they have been set. */
431     GG_CONCRETE_EXCEPTION(BadFunctionPointer, GG::GUI, Exception);
432     //@}
433 
434     /** Returns a list of resolutions that are supported for full-screen.
435      * The format is [width]x[height] @ [bits per pixel].
436      * This is not a conceptually ideal place for this function, but it needs to be
437      * implemented using the underlying graphics system,
438      * and deriving GUI is the way to connect GiGi to a graphics system, so here it is.
439      */
440     virtual std::vector<std::string> GetSupportedResolutions() const = 0;
441 
442     /** Returns the default resolution of the display */
443     virtual Pt GetDefaultResolution(int display_id) const = 0;
444 
445 protected:
446     /** \name Structors */ ///@{
447     GUI(const std::string& app_name); ///< protected ctor, called by derived classes
448     //@}
449 
450     /** \name Mutators */ ///@{
451     void            ProcessBrowseInfo();    ///< determines the current browse info mode, if any
452     /** Allow all windows in the z-list to update data before rendering. */
453     virtual void    PreRender();
454     virtual void    RenderBegin() = 0;      ///< clears the backbuffer, etc.
455     virtual void    Render();               ///< renders the windows in the z-list
456     virtual void    RenderEnd() = 0;        ///< swaps buffers, etc.
457     //@}
458 
459     /** Determine if the app has the mouse focus. */
AppHasMouseFocus()460     virtual bool    AppHasMouseFocus() const { return true; };
461 
462 private:
463     bool                 ProcessBrowseInfoImpl(Wnd* wnd);
464     std::shared_ptr<Wnd> ModalWindow() const;   ///< returns the current modal window, if any
465 
466     // Returns the window under \a pt, sending Mouse{Enter|Leave} or
467     // DragDrop{Enter|Leave} as appropriate
468     std::shared_ptr<Wnd> CheckedGetWindowUnder(const Pt& pt, Flags<ModKey> mod_keys);
469 
470     static GUI*              s_gui;
471     std::unique_ptr<GUIImpl> m_impl;
472 
473     friend struct GUIImpl;
474 };
475 
476 /** Returns true if lwnd == rwnd or if lwnd contains rwnd */
477 GG_API bool MatchesOrContains(const Wnd* lwnd, const Wnd* rwnd);
478 GG_API bool MatchesOrContains(const std::shared_ptr<Wnd>& lwnd, const Wnd* rwnd);
479 GG_API bool MatchesOrContains(const Wnd* lwnd, const std::shared_ptr<Wnd>& rwnd);
480 GG_API bool MatchesOrContains(const std::shared_ptr<Wnd>& lwnd, const std::shared_ptr<Wnd>& rwnd);
481 
482 /* returns the storage value of mod_keys that should be used with keyboard
483     accelerators the accelerators don't care which side of the keyboard you
484     use for CTRL, SHIFT, etc., and whether or not the numlock or capslock are
485     engaged.*/
486 GG_API Flags<ModKey> MassagedAccelModKeys(Flags<ModKey> mod_keys);
487 
488 
489 // template implementations
490 template <typename InIt>
operator()491 bool GUI::OrCombiner::operator()(InIt first, InIt last) const
492 {
493     bool retval = false;
494     while (first != last)
495         retval |= static_cast<bool>(*first++);
496     return retval;
497 }
498 
499 template <typename CharSetIter>
GetFont(const std::string & font_filename,unsigned int pts,CharSetIter first,CharSetIter last)500 std::shared_ptr<Font> GUI::GetFont(const std::string& font_filename, unsigned int pts,
501                                    CharSetIter first, CharSetIter last)
502 { return GetFontManager().GetFont(font_filename, pts, first, last); }
503 
504 template <typename CharSetIter>
GetFont(const std::string & font_filename,unsigned int pts,const std::vector<unsigned char> & file_contents,CharSetIter first,CharSetIter last)505 std::shared_ptr<Font> GUI::GetFont(const std::string& font_filename, unsigned int pts,
506                                    const std::vector<unsigned char>& file_contents,
507                                    CharSetIter first, CharSetIter last)
508 { return GetFontManager().GetFont(font_filename, pts, file_contents, first, last); }
509 
510 } // namespace GG
511 
512 #endif
513