Gamedev Framework (gf)  0.3.0
A C++11 framework for 2D games
UI.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 #ifndef GF_UI_H
22 #define GF_UI_H
23 
24 #include <cstdint>
25 #include <memory>
26 
27 #include "ArrayRef.h"
28 #include "Drawable.h"
29 #include "Event.h"
30 #include "Flags.h"
31 #include "Font.h"
32 #include "Portability.h"
33 #include "StringRef.h"
34 #include "Types.h"
35 #include "Vector.h"
36 
37 namespace gf {
38 #ifndef DOXYGEN_SHOULD_SKIP_THIS
39 inline namespace v1 {
40 #endif
41 
42  /**
43  * @ingroup graphics
44  * @brief Properties for windows and window-like elements
45  *
46  * @sa gf::UIWindowFlags
47  */
48  enum class UIWindow : uint32_t {
49  Border = 0x0001, ///< The window has a border
50  Movable = 0x0002, ///< The window can be moved by the user
51  Scalable = 0x0004, ///< The window is scalable by the user
52  Closable = 0x0008, ///< The window can be closed with an icon in the header
53  Minimizable = 0x0010, ///< The window can be minimized with an icon in the header
54  NoScrollbar = 0x0020, ///< The window has no scrollbar
55  Title = 0x0040, ///< The window has a title in the header
56  ScrollAutoHide = 0x0080, ///< The window's scrollbar can hide automatically
57  Background = 0x0100, ///< The window is in the background
58  };
59 
60  /**
61  * @ingroup graphics
62  * @brief Flags composed of window properties
63  *
64  * @sa gf::UIWindow
65  */
66  using UIWindowFlags = Flags<UIWindow>;
67 
68  /**
69  * @ingroup graphics
70  * @brief Collapse property of a tree
71  */
72  enum class UICollapse : bool {
73  Minimized = false, ///< The tree is minimized
74  Maximized = true, ///< The tree is maximized
75  };
76 
77  /**
78  * @ingroup graphics
79  * @brief Layout property for rows
80  */
81  enum class UILayout {
82  Dynamic = 0, ///< The row has a dynamic layout
83  Static = 1, ///< The row has a static layout
84  };
85 
86  /**
87  * @ingroup graphics
88  * @brief The type of tree
89  */
90  enum class UITree {
91  Node = 0, ///< The tree is a node, generally an internal node of the tree
92  Tab = 1, ///< The tree is a tabulation, generally the root of the tree
93  };
94 
95  /**
96  * @ingroup graphics
97  * @brief The alignment of the text
98  *
99  * @sa gf::Alignment
100  */
101  enum class UIAlignment {
102  Left = 0x10 | 0x01, ///< Left alignment
103  Center = 0x10 | 0x02, ///< Centered alignment
104  Right = 0x10 | 0x04, ///< Right alignment
105  };
106 
107  /**
108  * @ingroup graphics
109  * @brief State for scrollbar in groups
110  */
111  using UIScroll = Vector<unsigned short, 2>;
112 
113  /**
114  * @ingroup graphics
115  * @brief Behavior for buttons
116  */
117  enum class UIButtonBehavior {
118  Default = 0, ///< The button is active once
119  Repeater = 1, ///< The button is active as long as it is pressed
120  };
121 
122  /**
123  * @ingroup graphics
124  * @brief State of the progress bar
125  */
126  enum class UIProgress : bool {
127  Fixed = false, ///< The progress bar is fixed
128  Modifyable = true, ///< The progress bar can be modified
129  };
130 
131  /**
132  * @ingroup graphics
133  * @brief A representative symbol
134  */
135  enum class UISymbol {
136  None, ///< No symbol
137  X, ///< X symbol
138  Underscore, ///< Underscore
139  CircleSolid, ///< Solid circle
140  CircleOutline, ///< Outline circle
141  RectSolid, ///< Solid rectangle
142  RectOutline, ///< Outline rectangle
143  TriangleUp, ///< Triangle up
144  TriangleDown, ///< Triangle down
145  TriangleLeft, ///< Triangle left
146  TriangleRight, ///< Triangle right
147  Plus, ///< Plus
148  Minus, ///< Minus
149  };
150 
151  /**
152  * @ingroup graphics
153  * @brief Type of popup
154  */
155  enum class UIPopup {
156  Static = 0, ///< The popup is static
157  Dynamic = 1, ///< The popup is dynamic
158  };
159 
160  /**
161  * @ingroup graphics
162  * @brief A predefined style
163  */
164  enum class UIPredefinedStyle {
165  Default, ///< The default style
166  White, ///< A light gray style
167  Red, ///< A red and gray style
168  Blue, ///< A blue and light gray style
169  Dark, ///< A dark gray and dark blue style
170  };
171 
172  /**
173  * @ingroup graphics
174  * @brief Context for an immediate mode graphical interface
175  *
176  * When building a graphical interfaces, you have basically two choices:
177  * either the retained mode where you build a hierarchy of widgets, or the
178  * immediate mode where widgets are built from function calls. Choosing the
179  * best mode between these two may be
180  * [controversial](http://gamedev.stackexchange.com/questions/24103/immediate-gui-yae-or-nay).
181  * gf offers an immediate mode graphical interface through this class.
182  *
183  * The immediate mode graphical interface (or imgui) of gf is based on
184  * [Nuklear](https://github.com/vurtun/nuklear), a C library with the same
185  * purpose. gf does not provide (yet?) all the features of Nuklear, but a
186  * fair amount of the main features. Nuklear is totally abstracted in gf so
187  * you won't see any interface from Nuklear and you won't be able to
188  * interact directly with Nuklear. If you need a feature that is not
189  * implemented yet, just ask.
190  *
191  * This imgui library can be used to create tools for the game developpers.
192  * It's easy and quick to build a functional interface with an imgui
193  * library. You can see some examples in gf itself. You can also use this
194  * library to build in-game interfaces, even if it's not its primary
195  * purpose. If your game is heavily based on a graphical interface, it
196  * may be a good option.
197  *
198  *
199  * # Creating a context
200  *
201  * An instance of gf::UI is a context for all the windows that will be
202  * created. You must provide a font and a character size that will be
203  * used in the interface. Generally, you create the instance of gf::UI
204  * at the beginning of your application and then you use this instance
205  * throughout your application.
206  *
207  * @snippet snippets/doc_ui.cc context
208  *
209  * By default, the character size is 13.
210  *
211  *
212  * # Managing events
213  *
214  * The imgui needs to know the input events that occurred in the frame time.
215  * So when polling the events in your main loop, you must pass the events
216  * to the context so that it can be updated and take the good decision. For
217  * example, if you press on a button, the mouse event will be transmitted
218  * and the library will know that you pressed a button and act accordingly.
219  *
220  * @snippet snippets/doc_ui.cc events
221  *
222  *
223  * # Creating a window
224  *
225  * Then, you have to create a window. The window has a title that may appear
226  * in the titlebar. It also identifies the window so two windows must have
227  * two different titles. The window also has bounds, i.e. a position and a
228  * size, that indicates where to put the window in the screen. There is no
229  * automatic placement of windows. Finally, the window can have many
230  * properties (see gf::UIWindow) that modify the interaction with the window.
231  * They are defined at the window creation.
232  *
233  * @snippet snippets/doc_ui.cc window
234  *
235  * For each begin(), you have to call end() to finish the window.
236  * You can create as many windows as you want as long as they have different
237  * titles.
238  *
239  *
240  * # Determining a layout
241  *
242  * Before drawing any widget, you have to define a layout. Think of it as a
243  * sort of specification for how to organize the following widgets. There
244  * are three types of layouts: rows, groups, trees.
245  *
246  * ## Rows
247  *
248  * Rows are the most common type of layout. The row layout is very flexible.
249  *
250  * A row can be either static (it does not adapt to the width of the window)
251  * of dynamic (it adapts to the width of the window). It can be fixed (all
252  * columns have the same width) or custom (columns' widths are specified,
253  * either relatively or absolutely), and in the latter case the
254  * specification can be global or in immediate mode. Here is a summary of
255  * the functions to use in each case:
256  *
257  * - dynamic row
258  * - fixed column layout: layoutRowDynamic()
259  * - custom column layout
260  * - array-based: layoutRow() with gf::UILayout::Dynamic
261  * - immediate-mode: layoutRowBegin() with gf::UILayout::Dynamic, layoutRowPush(), layoutRowEnd()
262  * - static row
263  * - fixed column layout: layoutRowStatic()
264  * - custom column layout
265  * - array-based: layoutRow() with gf::UILayout::Static
266  * - immediate-mode: layoutRowBegin() with gf::UILayout::Static, layoutRowPush(), layoutRowEnd()
267  *
268  * ## Trees
269  *
270  * A tree is a tree-like layout. It can be collapsed to hide its content
271  * except its title. There are two types of trees: tabs and nodes (see
272  * gf::UITree). A tab tree is generally put at the root of the tree, it is
273  * represented with a border around the title. A node tree is generally the
274  * son of a tab tree or another node tree. It is represented without any
275  * border.
276  *
277  * In both cases, you need a variable of type gf::UICollapse to handle the
278  * current state of the tree: minimized or maximized.
279  *
280  * @snippet snippets/doc_ui.cc tree
281  *
282  * ## Groups
283  *
284  * A group is a kind of window inside a window. It can have a title, a
285  * border and a scrollbar. However, a group needs to be put in a row.
286  * See groupBegin() and groupEnd().
287  *
288  * @snippet snippets/doc_ui.cc group
289  *
290  *
291  * # Adding widgets and more
292  *
293  * The library offers common kinds of widgets:
294  * - [labels](https://en.wikipedia.org/wiki/Label_%28control%29): label(), selectableLabel()
295  * - [buttons](https://en.wikipedia.org/wiki/Button_%28computing%29): buttonLabel(), buttonColor(), buttonSymbol(), buttonSymbolLabel()
296  * - [checkboxes](https://en.wikipedia.org/wiki/Checkbox): checkbox(), checkboxFlags()
297  * - [radio buttons](https://en.wikipedia.org/wiki/Radio_button): option(), radio()
298  * - [sliders](https://en.wikipedia.org/wiki/Slider_%28computing%29): sliderFloat(), sliderInt()
299  * - [progress bars](https://en.wikipedia.org/wiki/Progress_bar): progress()
300  * - [color pickers](https://en.wikipedia.org/wiki/Color_tool): colorPicker()
301  *
302  * Widgets often manipulate a reference to a user-provided variable that
303  * represents the state of the widget. This way, you can pass directly your
304  * model variables to the graphical interface without duplicating the data.
305  * Some widgets return a boolean that indicates a state change. For example,
306  * a button returns true if it has been pressed.
307  *
308  * The library also offers common graphical interface elements:
309  * - [popups](https://en.wikipedia.org/wiki/Popover_%28GUI%29): popupBegin(), popupEnd()
310  * - [combo boxes](https://en.wikipedia.org/wiki/Combo_box): combobox(), comboboxSeparator()
311  * - [contextuals](https://en.wikipedia.org/wiki/Context_menu): contextualBegin(), contextualEnd()
312  * - [tooltips](https://en.wikipedia.org/wiki/Tooltip): tooltip()
313  * - [menus](https://en.wikipedia.org/wiki/Menu_28computing%29): menubarBegin(), menubarEnd()
314  *
315  * Many of these elements have a begin/end API. The end part must be called
316  * if the begin part succeeded, i.e. returned true. Some elements offer a
317  * simplified version without begin/end for common cases.
318  *
319  */
320  class GF_API UI : public Drawable {
321  public:
322  /**
323  * @brief The default size for the font
324  */
325  static constexpr unsigned DefaultCharacterSize = 13;
326 
327  /**
328  * @brief Constructor
329  *
330  * @param font The font used in the interface
331  * @param characterSize The size of the font used in the interface
332  */
333  UI(Font& font, unsigned characterSize = DefaultCharacterSize);
334 
335  /**
336  * @brief Destructor
337  */
338  ~UI();
339 
340  /**
341  * @brief Deleted copy constructor
342  */
343  UI(const UI&) = delete;
344 
345  /**
346  * @brief Deleted copy assignment
347  */
348  UI& operator=(const UI&) = delete;
349 
350  /**
351  * @brief Move constructor
352  */
353  UI(UI&& other);
354 
355  /**
356  * @brief Move assignment
357  */
358  UI& operator=(UI&& other);
359 
360  /**
361  * @brief Update the internal state with an event
362  *
363  * This function must be called for every event that occur in a frame.
364  *
365  * @param event An event
366  */
367  void processEvent(const Event& event);
368 
369  /**
370  * @name Window
371  * @{
372  */
373 
374  /**
375  * @brief Create a window
376  *
377  * @snippet snippets/doc_ui.cc window
378  *
379  * @param title The title of the window
380  * @param bounds The area of the window
381  * @param flags The properties of the window
382  * @returns True is the content of the window is visible
383  *
384  * @sa end(), gf::UIWindow
385  */
386  bool begin(const std::string& title, const RectF& bounds, UIWindowFlags flags = None);
387 
388  /**
389  * @brief Finish a window
390  *
391  * @snippet snippets/doc_ui.cc window
392  *
393  * @sa begin()
394  */
395  void end();
396 
397  /**
398  * @}
399  */
400 
401  /**
402  * @name Layout
403  * @{
404  */
405 
406  /**
407  * @brief Dynamic row with fixed column layout
408  *
409  * @param height The height of the row
410  * @param cols The number of columns in the row
411  *
412  * @sa layoutRowStatic()
413  */
414  void layoutRowDynamic(float height, int cols);
415 
416  /**
417  * @brief Static row with fixed column layout
418  *
419  * @param height The height of the row
420  * @param itemWidth The width of each item in the row
421  * @param cols The number of columns in the row
422  *
423  * @sa layoutRowDynamic()
424  */
425  void layoutRowStatic(float height, int itemWidth, int cols);
426 
427  /**
428  * @brief Start an immediate mode custom column layout
429  *
430  * @param format The format of the row: static or dynamic
431  * @param height The height of the row
432  * @param cols The number of columns in the row
433  *
434  * @sa layoutRowPush(), layoutRowEnd()
435  */
436  void layoutRowBegin(UILayout format, float height, int cols);
437 
438  /**
439  * @brief Specify the width of the next column
440  *
441  * @param width The width of the next column
442  *
443  * @sa layoutRowBegin(), layoutRowEnd()
444  */
445  void layoutRowPush(float width);
446 
447  /**
448  * @brief Finish an immediate mode custom column layout
449  *
450  * @sa layoutRowBegin(), layoutRowPush()
451  */
452  void layoutRowEnd();
453 
454  /**
455  * @brief Array-based custom column layout
456  *
457  * @param format The format of the row: static or dynamic
458  * @param height The height of the row
459  * @param ratio A reference to an array of ratios for the columns
460  */
461  void layoutRow(UILayout format, float height, ArrayRef<float> ratio);
462 
463  /**
464  * @brief An empty separator
465  *
466  * This function creates an empty row so you have to specify a new row.
467  *
468  * @param height The height of the row
469  */
470  void separator(float height);
471 
472  /**
473  * @}
474  */
475 
476  /**
477  * @name Layout: Group
478  * @{
479  */
480 
481  /**
482  * @brief Start a group
483  *
484  * The only allowed flags are UIWindow::Title, UIWindow::Border,
485  * UIWindow::NoScrollbar.
486  *
487  * @snippet snippets/doc_ui.cc group
488  *
489  * @param title The title of the group
490  * @param flags The properties of the group
491  * @returns True if the group is visible
492  *
493  * @sa groupEnd()
494  */
495  bool groupBegin(const std::string& title, UIWindowFlags flags = None);
496 
497  /**
498  * @brief Finish a group
499  *
500  * @snippet snippets/doc_ui.cc group
501  *
502  * @sa groupBegin()
503  */
504  void groupEnd();
505 
506  /**
507  * @brief Start a scrolled group
508  *
509  * The only allowed flags are UIWindow::Title, UIWindow::Border,
510  * UIWindow::NoScrollbar.
511  *
512  * @param scroll A state for representing the scroll
513  * @param title The title of the group
514  * @param flags The properties of the group
515  * @returns True if the group is visible
516  *
517  * @sa groupScrolledEnd()
518  */
519  bool groupScrolledBegin(UIScroll& scroll, const std::string& title, UIWindowFlags flags = None);
520 
521  /**
522  * @brief Finish a scrolled group
523  *
524  * @sa groupScrolledBegin()
525  */
526  void groupScrolledEnd();
527 
528  /**
529  * @}
530  */
531 
532  /**
533  * @name Layout: Tree
534  * @{
535  */
536 
537  /**
538  * @brief Start a tree layout
539  *
540  * @snippet snippets/doc_ui.cc tree
541  *
542  * @param type The type of tree: tab or node
543  * @param title The title of the tree
544  * @param state The collapse state
545  * @returns True if the tree is maximized
546  *
547  * @sa treePop()
548  */
549  bool treePush(UITree type, const std::string& title, UICollapse& state);
550 
551  /**
552  * @brief Finish a tree layout
553  *
554  * @snippet snippets/doc_ui.cc tree
555  *
556  * @sa treePush()
557  */
558  void treePop();
559 
560  /**
561  * @}
562  */
563 
564  /**
565  * @name Widgets: Labels
566  * @{
567  */
568 
569  /**
570  * @brief A simple label with text
571  *
572  * @param title The title of the label
573  * @param align The alignment of the text in the label
574  *
575  * @sa labelColored()
576  */
577  void label(StringRef title, UIAlignment align = UIAlignment::Left);
578 
579  /**
580  * @brief A label with colored text
581  *
582  * @param color The color of the text
583  * @param title The title of the label
584  * @param align The alignment of the text in the label
585  *
586  * @sa label()
587  */
588  void labelColored(const Color4f& color, StringRef title, UIAlignment align = UIAlignment::Left);
589 
590  /**
591  * @brief A simple label that can wrap
592  *
593  * @param title The title of the label
594  *
595  * @sa labelWrapColored()
596  */
597  void labelWrap(StringRef title);
598 
599  /**
600  * @brief A label with colored text that can wrap
601  *
602  * @param color The color of the text
603  * @param title The title of the label
604  *
605  * @sa labelWrap()
606  */
607  void labelWrapColored(const Color4f& color, StringRef title);
608 
609  /**
610  * @}
611  */
612 
613  /**
614  * @name Widgets: Buttons
615  * @{
616  */
617 
618  /**
619  * @brief Change the behavior of buttons
620  *
621  * @param behavior The new behavior of buttons
622  *
623  * @sa buttonPushBehavior(), buttonPopBehavior()
624  */
625  void buttonSetBehavior(UIButtonBehavior behavior);
626 
627  /**
628  * @brief Push a new behavior of buttons
629  *
630  * @param behavior The new behavior of buttons
631  *
632  * @sa buttonSetBehavior(), buttonPopBehavior()
633  */
634  bool buttonPushBehavior(UIButtonBehavior behavior);
635 
636  /**
637  * @brief Pop the previous behavior of buttons
638  *
639  * @sa buttonSetBehavior(), buttonPushBehavior()
640  */
641  bool buttonPopBehavior();
642 
643  /**
644  * @brief A button with a centered label
645  *
646  * @param title The title of the button
647  * @returns True if the button was pressed
648  *
649  * @sa buttonColor(), buttonSymbol(), buttonSymbolLabel()
650  */
651  bool buttonLabel(StringRef title);
652 
653  /**
654  * @brief A button with a color
655  *
656  * @param color The color of the button
657  * @returns True if the button was pressed
658  *
659  * @sa buttonLabel(), buttonSymbol(), buttonSymbolLabel()
660  */
661  bool buttonColor(const Color4f& color);
662 
663  /**
664  * @brief A button with a symbol
665  *
666  * @param symbol A symbol
667  * @returns True if the button was pressed
668  *
669  * @sa buttonLabel(), buttonColor(), buttonSymbolLabel()
670  */
671  bool buttonSymbol(UISymbol symbol);
672 
673  /**
674  * @brief A button with a symbol and a centered label
675  *
676  * @param symbol A symbol
677  * @param title The title of the button
678  * @param align The alignment of the symbol
679  * @returns True if the button was pressed
680  *
681  * @sa buttonLabel(), buttonColor(), buttonSymbol()
682  */
684 
685  /**
686  * @}
687  */
688 
689  /**
690  * @name Widgets: Checkbox
691  * @{
692  */
693 
694  /**
695  * @brief A checkbox with a title
696  *
697  * @param title The title of the checkbox
698  * @param active A reference to a boolean that indicates the state of the checkbox
699  * @returns True if the checkbox has changed its state
700  *
701  * @sa checkboxFlags()
702  */
703  bool checkbox(StringRef title, bool& active);
704 
705  /**
706  * @brief A checkbox with a title for flags
707  *
708  * @param title The title of the checkbox
709  * @param flags A reference to the state of flags
710  * @param value The flag value for this checkbox
711  * @returns True if the checkbox has changed its state
712  *
713  * @sa checkbox()
714  */
715  bool checkboxFlags(StringRef title, unsigned& flags, unsigned value);
716 
717  /**
718  * @}
719  */
720 
721  /**
722  * @name Widgets: Radio
723  * @{
724  */
725 
726  /**
727  * @brief A radio button without state
728  *
729  * @param title The title of the radio button
730  * @param active A boolean that indicates if the radio is chosen
731  * @returns True if the radio is pressed
732  *
733  * @sa radio()
734  */
735  bool option(StringRef title, bool active);
736 
737  /**
738  * @brief A radio button with a reference state
739  *
740  * @param title The title of the radio button
741  * @param active A reference to the state of the radio
742  * @returns True if the radio is pressed
743  *
744  * @sa option()
745  */
746  bool radio(StringRef title, bool& active);
747 
748  /**
749  * @}
750  */
751 
752  /**
753  * @name Widgets: Selectable
754  * @{
755  */
756 
757  /**
758  * @brief A selectable label
759  *
760  * @param title The title of the label
761  * @param align The alignment of the text in the label
762  * @param value A reference to the state of the selection
763  * @returns True if the state has changed
764  *
765  * @sa label()
766  */
767  bool selectableLabel(StringRef title, UIAlignment align, bool& value);
768 
769  /**
770  * @}
771  */
772 
773  /**
774  * @name Widgets: Slider
775  * @{
776  */
777 
778  /**
779  * @brief A slider for a float value
780  *
781  * @param min The minimum for the value
782  * @param val A reference to the value
783  * @param max The maximum for the value
784  * @param step A step when changing the value
785  * @returns True if the slider has changed
786  *
787  * @sa sliderInt()
788  */
789  bool sliderFloat(float min, float& val, float max, float step);
790 
791  /**
792  * @brief A slider for an int value
793  *
794  * @param min The minimum for the value
795  * @param val A reference to the value
796  * @param max The maximum for the value
797  * @param step A step when changing the value
798  * @returns True if the slider has changed
799  *
800  * @sa sliderFloat()
801  */
802  bool sliderInt(int min, int& val, int max, int step);
803 
804  /**
805  * @}
806  */
807 
808  /**
809  * @name Widgets: Progressbar
810  * @{
811  */
812 
813  /**
814  * @brief A progress bar
815  *
816  * @param current A reference to the state of the progress bar
817  * @param max The maximum of the progress bar (the minimum is zero)
818  * @param modifyable A property to indicate if the progress bar can be modified by the user or not
819  * @returns True if the progress bar has changed
820  */
821  bool progress(std::size_t& current, std::size_t max, UIProgress modifyable = UIProgress::Modifyable);
822 
823  /**
824  * @}
825  */
826 
827  /**
828  * @name Widgets: Color picker
829  * @{
830  */
831 
832  /**
833  * @brief A color picker
834  *
835  * @param color A reference to the state of the color picker, i.e. the current color
836  * @returns True if the color has changed
837  */
838  bool colorPicker(Color4f& color);
839 
840  /**
841  * @}
842  */
843 
844  /**
845  * @name Widgets: Property
846  * @{
847  */
848 
849  /**
850  * @brief A property for an integer
851  *
852  * @param name The name of the property
853  * @param min The minimum for the value
854  * @param val A reference to the value
855  * @param max The maximum for the value
856  * @param step A step when changing the value
857  * @param incPerPixel A step when modifying the value with the mouse
858  *
859  * @sa propertyFloat(), propertyDouble()
860  */
861  void propertyInt(const std::string& name, int min, int& val, int max, int step, float incPerPixel);
862 
863  /**
864  * @brief A property for a float
865  *
866  * @param name The name of the property
867  * @param min The minimum for the value
868  * @param val A reference to the value
869  * @param max The maximum for the value
870  * @param step A step when changing the value
871  * @param incPerPixel A step when modifying the value with the mouse
872  *
873  * @sa propertyInt(), propertyDouble()
874  */
875  void propertyFloat(const std::string& name, float min, float& val, float max, float step, float incPerPixel);
876 
877  /**
878  * @brief A property for a double
879  *
880  * @param name The name of the property
881  * @param min The minimum for the value
882  * @param val A reference to the value
883  * @param max The maximum for the value
884  * @param step A step when changing the value
885  * @param incPerPixel A step when modifying the value with the mouse
886  *
887  * @sa propertyInt(), propertyFloat()
888  */
889  void propertyDouble(const std::string& name, double min, double& val, double max, double step, float incPerPixel);
890 
891  /**
892  * @}
893  */
894 
895  /**
896  * @name Popups
897  * @{
898  */
899 
900  /**
901  * @brief Start a popup window
902  *
903  * @param type The type of popup (static or dynamic)
904  * @param title The title of the popup
905  * @param flags The properties of the popup window
906  * @param bounds The area of the popup window
907  * @returns True if the popup is open
908  *
909  * @sa popupClose(), popupEnd()
910  */
911  bool popupBegin(UIPopup type, const std::string& title, UIWindowFlags flags, const RectF& bounds);
912 
913  /**
914  * @brief Close a popup window
915  *
916  * @sa popupBegin(), popupEnd()
917  */
918  void popupClose();
919 
920  /**
921  * @brief Finish a popup window
922  *
923  * @sa popupBegin(), popupClose()
924  */
925  void popupEnd();
926 
927  /**
928  * @}
929  */
930 
931  /**
932  * @name Combo box
933  * @{
934  */
935 
936  /**
937  * @brief A simple combo box with a list of item
938  *
939  * @param items The list of items in the combo box
940  * @param selected A reference to the selected item in the combo box
941  * @param itemHeight The height of the items in the list
942  * @param size The size of the combo box
943  *
944  * @sa comboboxSeparator()
945  */
946  void combobox(const std::vector<std::string>& items, int& selected, int itemHeight, Vector2f size);
947 
948  /**
949  * @brief A simple combo box with a string and a separator
950  *
951  * @param itemsSeparatedBySeparator A string with all the items separated by a separator
952  * @param separator The separator used in the string
953  * @param selected A reference to the selected item in the combo box
954  * @param itemHeight The height of the items in the list
955  * @param size The size of the combo box
956  *
957  * @sa combobox()
958  */
959  void comboboxSeparator(const std::string& itemsSeparatedBySeparator, char separator, int& selected, int itemHeight, Vector2f size);
960 
961  /**
962  * @brief Start a combo box with a label
963  *
964  * @param selected The selected item that appears in the combo box
965  * @param size The size of the combo box
966  * @returns True if the combo box is open
967  *
968  * @sa comboClose(), comboEnd()
969  */
970  bool comboBeginLabel(StringRef selected, Vector2f size);
971 
972  /**
973  * @brief Start a combo box with a color
974  *
975  * @param color The color that appears in the combo box
976  * @param size The size of the combo box
977  * @returns True if the combo box is open
978  *
979  * @sa comboClose(), comboEnd()
980  */
981  bool comboBeginColor(const Color4f& color, Vector2f size);
982 
983  /**
984  * @brief Start a combo box with a symbol
985  *
986  * @param symbol The symbol that appears in the combo box
987  * @param size The size of the combo box
988  * @returns True if the combo box is open
989  *
990  * @sa comboClose(), comboEnd()
991  */
992  bool comboBeginSymbol(UISymbol symbol, Vector2f size);
993 
994  /**
995  * @brief Start a combo box with a symbol and a label
996  *
997  * @param symbol The symbol that appears in the combo box
998  * @param selected The selected item that appears in the combo box
999  * @param size The size of the combo box
1000  * @returns True if the combo box is open
1001  *
1002  * @sa comboClose(), comboEnd()
1003  */
1004  bool comboBeginSymbolLabel(UISymbol symbol, StringRef selected, Vector2f size);
1005 
1006  /**
1007  * @brief A label inside the combo box
1008  *
1009  * @param title The title of the label
1010  * @param align The alignment of the text in the label
1011  * @returns True if the item is selected
1012  */
1014 
1015  /**
1016  * @brief A symbol and a label inside the combo box
1017  *
1018  * @param symbol The symbol of the item
1019  * @param title The title of the label
1020  * @param align The alignment of the text in the label
1021  * @returns True if the item is selected
1022  */
1024 
1025  /**
1026  * @brief Close a combo box
1027  *
1028  * @sa comboEnd()
1029  */
1030  void comboClose();
1031 
1032  /**
1033  * @brief Finish a combo box
1034  *
1035  * @sa comboBeginLabel(), comboBeginColor(), comboBeginSymbol(), comboBeginSymbolLabel()
1036  */
1037  void comboEnd();
1038 
1039  /**
1040  * @}
1041  */
1042 
1043  /**
1044  * @name Contextual
1045  * @{
1046  */
1047 
1048  /**
1049  * @brief Start a contextual window
1050  *
1051  * @param flags The properties of the contextual window
1052  * @param size The size of the contextual window
1053  * @param triggerBounds The bounds when the contextual should appear
1054  * @returns True if the contextual is open
1055  *
1056  * @sa contextualClose(), contextualEnd()
1057  */
1058  bool contextualBegin(UIWindowFlags flags, Vector2f size, const RectF& triggerBounds);
1059 
1060  /**
1061  * @brief A label inside the contextual window
1062  *
1063  * @param title The title of the label
1064  * @param align The alignment of the text in the label
1065  * @returns True if the item is selected
1066  */
1068 
1069  /**
1070  * @brief A symbol and a label inside the contextual window
1071  *
1072  * @param symbol The symbol of the item
1073  * @param title The title of the label
1074  * @param align The alignment of the text in the label
1075  * @returns True if the item is selected
1076  */
1078 
1079  /**
1080  * @brief Close the contextual window
1081  *
1082  * @sa contextualBegin(), contextualEnd()
1083  */
1084  void contextualClose();
1085 
1086  /**
1087  * @brief Finish the contextual window
1088  *
1089  * @sa contextualBegin(), contextualClose()
1090  */
1091  void contextualEnd();
1092 
1093  /**
1094  * @}
1095  */
1096 
1097  /**
1098  * @name Tooltip
1099  * @{
1100  */
1101 
1102  /**
1103  * @brief A simple tooltip with a text
1104  *
1105  * @param text The text of the tooltip
1106  */
1107  void tooltip(const std::string& text);
1108 
1109  /**
1110  * @brief Start a tooltip
1111  *
1112  * @param width The with of the tooltip
1113  * @returns True if the tooltip is open
1114  *
1115  * @sa tooltipEnd()
1116  */
1117  bool tooltipBegin(float width);
1118 
1119  /**
1120  * @brief Finish a tooltip
1121  *
1122  * @sa tooltipBegin()
1123  */
1124  void tooltipEnd();
1125 
1126  /**
1127  * @}
1128  */
1129 
1130  /**
1131  * @name Menu
1132  * @{
1133  */
1134 
1135  /**
1136  * @brief Start a menu bar
1137  *
1138  * @sa menubarEnd()
1139  */
1140  void menubarBegin();
1141 
1142  /**
1143  * @brief Finish a menu bar
1144  *
1145  * @sa menubarBegin()
1146  */
1147  void menubarEnd();
1148 
1149  /**
1150  * @brief Start a menu with a label
1151  *
1152  * @param title The title of the label
1153  * @param align The alignment of the text in the label
1154  * @param size The size of the menu
1155  * @returns True if the menu is open
1156  *
1157  * @sa menuClose(), menuEnd()
1158  */
1159  bool menuBeginLabel(StringRef title, UIAlignment align, Vector2f size);
1160 
1161  /**
1162  * @brief Start a menu with a symbol
1163  *
1164  * @param id A unique identifier for the menu
1165  * @param symbol A symbol for the menu
1166  * @param size The size of the menu
1167  * @returns True if the menu is open
1168  *
1169  * @sa menuClose(), menuEnd()
1170  */
1171  bool menuBeginSymbol(const std::string& id, UISymbol symbol, Vector2f size);
1172 
1173  /**
1174  * @brief Start a menu with a symbol and a label
1175  *
1176  * @param symbol A symbol for the menu
1177  * @param title The title of the label
1178  * @param align The alignment of the text in the label
1179  * @param size The size of the menu
1180  * @returns True if the menu is open
1181  *
1182  * @sa menuClose(), menuEnd()
1183  */
1184  bool menuBeginSymbolLabel(UISymbol symbol, StringRef title, UIAlignment align, Vector2f size);
1185 
1186  /**
1187  * @brief A label inside the menu
1188  *
1189  * @param title The title of the label
1190  * @param align The alignment of the text in the label
1191  * @returns True if the item is selected
1192  */
1194 
1195  /**
1196  * @brief A symbol and a label inside the menu
1197  *
1198  * @param symbol The symbol of the item
1199  * @param title The title of the label
1200  * @param align The alignment of the text in the label
1201  * @returns True if the item is selected
1202  */
1204 
1205  /**
1206  * @brief Close a menu
1207  *
1208  * @sa menuEnd()
1209  */
1210  void menuClose();
1211 
1212  /**
1213  * @brief Finish a menu
1214  *
1215  * @sa menuClose(), menuBeginLabel(), menuBeginSymbol(), menuBeginSymbolLabel()
1216  */
1217  void menuEnd();
1218 
1219  /**
1220  * @}
1221  */
1222 
1223  /**
1224  * @name Utilities
1225  * @{
1226  */
1227 
1228  /**
1229  * @brief Get the current widget bounds
1230  *
1231  * @returns The bounds of the widget
1232  */
1233  RectF getWidgetBounds();
1234 
1235  /**
1236  * @brief Check if the widget is hovered by the mouse
1237  *
1238  * You must do this check just after the layout specification
1239  *
1240  * @returns True if the mouse hovers the widget
1241  */
1242  bool isWidgetHovered();
1243 
1244  /**
1245  * @}
1246  */
1247 
1248  /**
1249  * @name Style
1250  * @{
1251  */
1252 
1253  /**
1254  * @brief Set a predefined style for all the windows and the widgets
1255  *
1256  * @param style The predefined style
1257  *
1258  * @sa gf::UIPredefinedStyle
1259  */
1261 
1262  /**
1263  * @}
1264  */
1265 
1266  virtual void draw(RenderTarget &target, RenderStates states) override;
1267 
1268  private:
1269  enum class State {
1270  Start,
1271  Input,
1272  Setup,
1273  Draw,
1274  };
1275 
1276  void setState(State state);
1277 
1278  private:
1279  struct UIImpl;
1280 
1281  std::unique_ptr<UIImpl> m_impl;
1282  };
1283 
1284 
1285 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1286 }
1287 #endif
1288 
1289 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1290 template<>
1291 struct EnableBitmaskOperators<UIWindow> {
1292  static constexpr bool value = true;
1293 };
1294 #endif
1295 
1296 }
1297 
1298 #endif // GF_UI_H
The window's scrollbar can hide automatically.
void setPredefinedStyle(UIPredefinedStyle style)
Set a predefined style for all the windows and the widgets.
void popupClose()
Close a popup window.
The window can be moved by the user.
The row has a dynamic layout.
UI(const UI &)=delete
Deleted copy constructor.
The tree is a node, generally an internal node of the tree.
The row has a static layout.
void labelColored(const Color4f &color, StringRef title, UIAlignment align=UIAlignment::Left)
A label with colored text.
bool isWidgetHovered()
Check if the widget is hovered by the mouse.
UILayout
Layout property for rows.
Definition: UI.h:81
void tooltipEnd()
Finish a tooltip.
void comboEnd()
Finish a combo box.
The button is active once.
bool groupScrolledBegin(UIScroll &scroll, const std::string &title, UIWindowFlags flags=None)
Start a scrolled group.
void label(StringRef title, UIAlignment align=UIAlignment::Left)
A simple label with text.
static constexpr unsigned DefaultCharacterSize
The default size for the font.
Definition: UI.h:325
bool menuBeginSymbolLabel(UISymbol symbol, StringRef title, UIAlignment align, Vector2f size)
Start a menu with a symbol and a label.
bool comboBeginSymbol(UISymbol symbol, Vector2f size)
Start a combo box with a symbol.
Base class for all render targets (window, texture, ...)
Definition: RenderTarget.h:65
~UI()
Destructor.
UIPopup
Type of popup.
Definition: UI.h:155
bool contextualBegin(UIWindowFlags flags, Vector2f size, const RectF &triggerBounds)
Start a contextual window.
Define the states used for drawing to a RenderTarget.
Definition: RenderStates.h:82
void menubarBegin()
Start a menu bar.
Bitfield relying on an enumeration.
Definition: Flags.h:68
UIProgress
State of the progress bar.
Definition: UI.h:126
bool buttonLabel(StringRef title)
A button with a centered label.
The button is active as long as it is pressed.
The tree is maximized.
The popup is static.
UI(Font &font, unsigned characterSize=DefaultCharacterSize)
Constructor.
UIPredefinedStyle
A predefined style.
Definition: UI.h:164
void menuEnd()
Finish a menu.
Context for an immediate mode graphical interface.
Definition: UI.h:320
bool buttonColor(const Color4f &color)
A button with a color.
void processEvent(const Event &event)
Update the internal state with an event.
void layoutRow(UILayout format, float height, ArrayRef< float > ratio)
Array-based custom column layout.
bool buttonSymbol(UISymbol symbol)
A button with a symbol.
bool checkbox(StringRef title, bool &active)
A checkbox with a title.
The window is scalable by the user.
bool menuItemLabel(StringRef title, UIAlignment align=UIAlignment::Left)
A label inside the menu.
bool popupBegin(UIPopup type, const std::string &title, UIWindowFlags flags, const RectF &bounds)
Start a popup window.
void combobox(const std::vector< std::string > &items, int &selected, int itemHeight, Vector2f size)
A simple combo box with a list of item.
void buttonSetBehavior(UIButtonBehavior behavior)
Change the behavior of buttons.
Centered alignment.
bool colorPicker(Color4f &color)
A color picker.
bool radio(StringRef title, bool &active)
A radio button with a reference state.
The popup is dynamic.
void layoutRowStatic(float height, int itemWidth, int cols)
Static row with fixed column layout.
bool comboBeginLabel(StringRef selected, Vector2f size)
Start a combo box with a label.
Abstract base class for objects that can be drawn to a render window.
Definition: Drawable.h:79
void groupEnd()
Finish a group.
bool contextualItemLabel(StringRef title, UIAlignment align=UIAlignment::Left)
A label inside the contextual window.
bool sliderInt(int min, int &val, int max, int step)
A slider for an int value.
void labelWrapColored(const Color4f &color, StringRef title)
A label with colored text that can wrap.
The tree is a tabulation, generally the root of the tree.
bool comboBeginColor(const Color4f &color, Vector2f size)
Start a combo box with a color.
The window has a border.
A red and gray style.
Solid rectangle.
void separator(float height)
An empty separator.
UIAlignment
The alignment of the text.
Definition: UI.h:101
void contextualEnd()
Finish the contextual window.
UI & operator=(const UI &)=delete
Deleted copy assignment.
void menubarEnd()
Finish a menu bar.
void comboClose()
Close a combo box.
bool progress(std::size_t &current, std::size_t max, UIProgress modifyable=UIProgress::Modifyable)
A progress bar.
UIButtonBehavior
Behavior for buttons.
Definition: UI.h:117
bool treePush(UITree type, const std::string &title, UICollapse &state)
Start a tree layout.
bool groupBegin(const std::string &title, UIWindowFlags flags=None)
Start a group.
bool buttonSymbolLabel(UISymbol symbol, StringRef title, UIAlignment align=UIAlignment::Left)
A button with a symbol and a centered label.
The window can be closed with an icon in the header.
void layoutRowBegin(UILayout format, float height, int cols)
Start an immediate mode custom column layout.
Definition: Action.h:34
void propertyFloat(const std::string &name, float min, float &val, float max, float step, float incPerPixel)
A property for a float.
A blue and light gray style.
X symbol.
A constant reference to an array and its size.
Definition: ArrayRef.h:41
bool menuBeginSymbol(const std::string &id, UISymbol symbol, Vector2f size)
Start a menu with a symbol.
A character font.
Definition: Font.h:130
virtual void draw(RenderTarget &target, RenderStates states) override
Draw the object to a render target.
Outline rectangle.
The progress bar can be modified.
Right alignment.
void menuClose()
Close a menu.
bool menuItemSymbolLabel(UISymbol symbol, StringRef title, UIAlignment align=UIAlignment::Left)
A symbol and a label inside the menu.
bool comboItemSymbolLabel(UISymbol symbol, StringRef title, UIAlignment align=UIAlignment::Left)
A symbol and a label inside the combo box.
UI & operator=(UI &&other)
Move assignment.
RectF getWidgetBounds()
Get the current widget bounds.
void labelWrap(StringRef title)
A simple label that can wrap.
void propertyDouble(const std::string &name, double min, double &val, double max, double step, float incPerPixel)
A property for a double.
void groupScrolledEnd()
Finish a scrolled group.
The tree is minimized.
UICollapse
Collapse property of a tree.
Definition: UI.h:72
void layoutRowPush(float width)
Specify the width of the next column.
void layoutRowEnd()
Finish an immediate mode custom column layout.
A light gray style.
UI(UI &&other)
Move constructor.
bool menuBeginLabel(StringRef title, UIAlignment align, Vector2f size)
Start a menu with a label.
bool sliderFloat(float min, float &val, float max, float step)
A slider for a float value.
The progress bar is fixed.
void comboboxSeparator(const std::string &itemsSeparatedBySeparator, char separator, int &selected, int itemHeight, Vector2f size)
A simple combo box with a string and a separator.
bool comboBeginSymbolLabel(UISymbol symbol, StringRef selected, Vector2f size)
Start a combo box with a symbol and a label.
bool buttonPushBehavior(UIButtonBehavior behavior)
Push a new behavior of buttons.
A constant reference to a string and its size.
Definition: StringRef.h:41
UISymbol
A representative symbol.
Definition: UI.h:135
Left alignment.
The window is in the background.
constexpr NoneType None
Constant to represent "none".
Definition: Types.h:45
The window has no scrollbar.
bool buttonPopBehavior()
Pop the previous behavior of buttons.
void popupEnd()
Finish a popup window.
void treePop()
Finish a tree layout.
UITree
The type of tree.
Definition: UI.h:90
bool tooltipBegin(float width)
Start a tooltip.
void layoutRowDynamic(float height, int cols)
Dynamic row with fixed column layout.
bool selectableLabel(StringRef title, UIAlignment align, bool &value)
A selectable label.
bool begin(const std::string &title, const RectF &bounds, UIWindowFlags flags=None)
Create a window.
void contextualClose()
Close the contextual window.
Defines a system event and its parameters.
Definition: Event.h:115
#define GF_API
Definition: Portability.h:35
General purpose math vector.
Definition: Vector.h:60
void tooltip(const std::string &text)
A simple tooltip with a text.
UIWindow
Properties for windows and window-like elements.
Definition: UI.h:48
A dark gray and dark blue style.
bool checkboxFlags(StringRef title, unsigned &flags, unsigned value)
A checkbox with a title for flags.
bool comboItemLabel(StringRef title, UIAlignment align=UIAlignment::Left)
A label inside the combo box.
The window can be minimized with an icon in the header.
void end()
Finish a window.
void propertyInt(const std::string &name, int min, int &val, int max, int step, float incPerPixel)
A property for an integer.
bool contextualItemSymbolLabel(UISymbol symbol, StringRef title, UIAlignment align=UIAlignment::Left)
A symbol and a label inside the contextual window.
The window has a title in the header.
bool option(StringRef title, bool active)
A radio button without state.