1 /*
2  *  This file is part of Dune Legacy.
3  *
4  *  Dune Legacy is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  Dune Legacy is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with Dune Legacy.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef WINDOW_H
19 #define WINDOW_H
20 
21 #include "Widget.h"
22 
23 
24 #include <iostream>
25 #include <queue>
26 
27 #include <SDL.h>
28 
29 /// A class representing a window
30 class Window : public Widget {
31 public:
32     /**
33         Constructor for creating a window
34         \param  x   x position of this window
35         \param  y   y position of this window
36         \param  w   width of this window
37         \param  h   height of this window
38     */
39     Window(Uint32 x, Uint32 y, Uint32 w, Uint32 h);
40 
41     /// destructor
42     virtual ~Window();
43 
44     /**
45         This method is called if a child widget is destroyed (see Widget::~Widget).
46         If pChildWidget is the window widget (See setWindowWidget) then this widget
47         is removed. If pChildWidget is the child window then the child window is closed.
48         \param  pChildWidget    widget to remove
49     */
removeChildWidget(Widget * pChildWidget)50     virtual void removeChildWidget(Widget* pChildWidget) {
51         if(pChildWidget == pWindowWidget) {
52             pWindowWidget = nullptr;
53         } else if(pChildWidget == pChildWindow) {
54             pChildWindow = nullptr;
55         }
56     }
57 
58     /**
59         Opens a child window. The new window is drawn above this window.
60         \param  pChildWindow    new window
61     */
62     virtual void openWindow(Window* pChildWindow);
63 
64     /**
65         Closes the child window.
66     */
67     virtual void closeChildWindow();
68 
69     /**
70         This method is called, when the child window is about to be closed.
71         This child window will be closed after this method returns.
72         \param  pChildWindow    The child window that will be closed
73     */
onChildWindowClose(Window * pChildWindow)74     virtual void onChildWindowClose(Window* pChildWindow) { ; };
75 
76 
77     /**
78         This method checks whether this window has a child window.
79         \return true if child window present, false otherwise
80     */
hasChildWindow()81     bool hasChildWindow() const { return (pChildWindow != nullptr); };
82 
83     /**
84         Get the current position of this window.
85         \return current position of this window
86     */
getPosition()87     inline const Point& getPosition() { return position; };
88 
89     /**
90         Sets the current window position and size.
91         \param  x   x position of this window
92         \param  y   y position of this window
93         \param  w   width of this window
94         \param  h   height of this window
95     */
96     virtual void setCurrentPosition(Uint32 x, Uint32 y, Uint32 w, Uint32 h);
97 
98     /**
99         Sets the current window position and size.
100         \param  rect    position of this window
101     */
setCurrentPosition(const SDL_Rect & rect)102     virtual void setCurrentPosition(const SDL_Rect& rect) {
103         setCurrentPosition(rect.x, rect.y, rect.w, rect.h);
104     }
105 
106     /**
107         Handles the input recieved from SDL. Everytime a sdl event occures this method should
108         be called.
109         \param  event   SDL_Event that occures.
110     */
111     virtual void handleInput(SDL_Event& event);
112 
113     /**
114         Handles a mouse movement.
115         \param  x x-coordinate (relative to the left top corner of the window)
116         \param  y y-coordinate (relative to the left top corner of the window)
117         \param  insideOverlay   true, if (x,y) is inside an overlay and this widget may be behind it, false otherwise
118     */
119     virtual void handleMouseMovement(Sint32 x, Sint32 y, bool insideOverlay = false);
120 
121     /**
122         Handles a left mouse click.
123         \param  x x-coordinate (relative to the left top corner of the window)
124         \param  y y-coordinate (relative to the left top corner of the window)
125         \param  pressed true = mouse button pressed, false = mouse button released
126         \return true = click was processed by the window, false = click was not processed by the window
127     */
128     virtual bool handleMouseLeft(Sint32 x, Sint32 y, bool pressed);
129 
130     /**
131         Handles a right mouse click.
132         \param  x x-coordinate (relative to the left top corner of the window)
133         \param  y y-coordinate (relative to the left top corner of the window)
134         \param  pressed true = mouse button pressed, false = mouse button released
135         \return true = click was processed by the window, false = click was not processed by the window
136     */
137     virtual bool handleMouseRight(Sint32 x, Sint32 y, bool pressed);
138 
139     /**
140         Handles mouse wheel scrolling.
141         \param  x x-coordinate (relative to the left top corner of the widget)
142         \param  y y-coordinate (relative to the left top corner of the widget)
143         \param  up  true = mouse wheel up, false = mouse wheel down
144         \return true = the mouse wheel scrolling was processed by the widget, false = mouse wheel scrolling was not processed by the widget
145     */
146 
147     virtual bool handleMouseWheel(Sint32 x, Sint32 y, bool up);
148 
149     /**
150         Handles a key stroke.
151         \param  key the key that was pressed or released.
152         \return true = key stroke was processed by the window, false = key stroke was not processed by the window
153     */
154     virtual bool handleKeyPress(SDL_KeyboardEvent& key);
155 
156     /**
157         Handles a text input event.
158         \param  textInput the text input that was performed.
159         \return true = text input was processed by the window, false = text input was not processed by the window
160     */
161     virtual bool handleTextInput(SDL_TextInputEvent& textInput);
162 
163     /**
164         Draws this window to screen. This method should be called every frame.
165     */
draw()166     virtual void draw() { draw(Point(0,0)); };
167 
168     /**
169         Draws this window to screen. This method should be called every frame.
170         \param  position    Position to draw the window to. The position of the window is added to this.
171     */
172     virtual void draw(Point position);
173 
174     /**
175         This method draws the parts of this window that must be drawn after all the other
176         widgets are drawn (e.g. tooltips). This method is called after draw().
177     */
drawOverlay()178     virtual void drawOverlay() { drawOverlay(Point(0,0)); };
179 
180     /**
181         This method draws the parts of this window that must be drawn after all the other
182         widgets are drawn (e.g. tooltips). This method is called after draw().
183         \param  Position    Position to draw the window to. The position of the window is added to this.
184     */
185     virtual void drawOverlay(Point position);
186 
187     /**
188         That the current window widget. This is typically a container that hold all the widgets in this window.
189         The window itself can contain only one widget.
190         \param  pWindowWidget   The only widget that this window contains
191     */
setWindowWidget(Widget * pWindowWidget)192     virtual inline void setWindowWidget(Widget* pWindowWidget) {
193         this->pWindowWidget = pWindowWidget;
194         if(this->pWindowWidget != nullptr) {
195             this->pWindowWidget->setParent(this);
196             this->pWindowWidget->resize(getSize().x,getSize().y);
197             this->pWindowWidget->setActive();
198         }
199     };
200 
201     /**
202         Returns the current window widget.
203         \return the current window widget
204     */
getWindowWidget()205     virtual inline Widget* getWindowWidget() { return pWindowWidget; };
206 
207     /**
208         This method resizes the window.
209         \param  newSize the new size of this widget
210     */
resize(Point newSize)211     virtual inline void resize(Point newSize) {
212         resize(newSize.x, newSize.y);
213     };
214 
215     /**
216         This method resizes the window to width and height.
217         \param  width   the new width of this widget
218         \param  height  the new height of this widget
219     */
220     virtual void resize(Uint32 width, Uint32 height);
221 
222     /**
223         This method is typically called by the child widget when the child widget
224         requests to resizes its surrounding container. But windows do not resize if
225         it's content changes.
226     */
resizeAll()227     virtual void resizeAll() {
228         // Windows do not get bigger if content changes
229         resize(getSize().x,getSize().y);
230     };
231 
232     /**
233         Set the background of this window.
234         \param  pBackground the new background of this window. nullptr=default background
235         \param  bFreeBackground should this background be automatically be freed
236     */
237     virtual void setBackground(SDL_Surface* pBackground, bool bFreeBackground = true);
238 
239     /**
240         Set the background of this window.
241         \param  pBackground the new background of this window. nullptr=default background
242         \param  bFreeBackground should this background be automatically be freed
243     */
244     virtual void setBackground(SDL_Texture* pBackground, bool bFreeBackground = true);
245 
246     /**
247         This method sets a transparent background for this window.
248         \param bTransparent true = the background is transparent, false = the background is not transparent
249     */
250     virtual void setTransparentBackground(bool bTransparent);
251 
252 protected:
253 
254     bool processChildWindowOpenCloses();
255 
256     int    closeChildWindowCounter;             ///< Close the child window after processing all input?
257     Window* pChildWindow;                       ///< The current child window
258     bool pChildWindowAlreadyClosed;             /// Is the child window already closed?
259     std::queue<Window*> queuedChildWindows;     ///< We cannot close child windows while they are processed. Queue any newly opened windows here until we close the current child window
260     Widget* pWindowWidget;                      ///< The current window widget
261     Point position;                             ///< The left top corner of this window
262     bool bTransparentBackground;                ///< true = no background is drawn
263     bool bSelfGeneratedBackground;              ///< true = background is created by this window, false = created by someone else
264     bool bFreeBackground;                       ///< true = background should be automatically be freed
265     SDL_Texture* pBackground;                   ///< background texture
266 };
267 
268 #endif //WINDOW_H
269