Switch to using -I to find includes, rather than relative paths.
[gemrb.git] / gemrb / plugins / Core / Window.cpp
blobe0c153a42aa9bbccb2c32cbff478f27218a6729d
1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program 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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "win32def.h"
22 #include "Window.h"
23 #include "Control.h"
24 #include "Interface.h"
25 #include "MapControl.h"
26 #include "Video.h"
27 #include "Button.h"
28 #include "Slider.h"
29 #include "Progressbar.h"
31 Window::Window(unsigned short WindowID, unsigned short XPos,
32 unsigned short YPos, unsigned short Width, unsigned short Height)
34 this->WindowID = WindowID;
35 this->XPos = XPos;
36 this->YPos = YPos;
37 this->Width = Width;
38 this->Height = Height;
39 this->BackGround = NULL;
40 lastC = NULL;
41 lastFocus = NULL;
42 lastMouseFocus = NULL;
43 lastOver = NULL;
44 Visible = WINDOW_INVISIBLE;
45 Flags = WF_CHANGED;
46 Cursor = IE_CURSOR_NORMAL;
47 DefaultControl[0] = -1;
48 DefaultControl[1] = -1;
49 ScrollControl = -1;
52 Window::~Window()
54 std::vector< Control*>::iterator m = Controls.begin();
55 while (Controls.size() != 0) {
56 Control* ctrl = ( *m );
57 delete ctrl;
58 Controls.erase( m );
59 m = Controls.begin();
61 core->GetVideoDriver()->FreeSprite( BackGround );
62 BackGround = NULL;
64 /** Add a Control in the Window */
65 void Window::AddControl(Control* ctrl)
67 if (ctrl == NULL) {
68 return;
70 ctrl->Owner = this;
71 for (size_t i = 0; i < Controls.size(); i++) {
72 if (Controls[i]->ControlID == ctrl->ControlID) {
73 delete( Controls[i] );
74 Controls[i] = ctrl;
75 Invalidate();
76 return;
79 Controls.push_back( ctrl );
80 Invalidate();
82 /** Set the Window's BackGround Image. If 'img' is NULL, no background will be set. If the 'clean' parameter is true (default is false) the old background image will be deleted. */
83 void Window::SetBackGround(Sprite2D* img, bool clean)
85 if (clean && BackGround) {
86 core->GetVideoDriver()->FreeSprite( this->BackGround );
88 BackGround = img;
89 Invalidate();
91 /** This function Draws the Window on the Output Screen */
92 void Window::DrawWindow()
94 Video* video = core->GetVideoDriver();
95 Region clip( XPos, YPos, Width, Height );
96 //Frame && Changed
97 if ( (Flags & (WF_FRAME|WF_CHANGED) )== (WF_FRAME|WF_CHANGED) ) {
98 Region screen( 0, 0, core->Width, core->Height );
99 video->SetClipRect( NULL );
100 //removed this?
101 Color black = { 0, 0, 0, 255 };
102 video->DrawRect( screen, black );
103 if (core->WindowFrames[0])
104 video->BlitSprite( core->WindowFrames[0], 0, 0, true );
105 if (core->WindowFrames[1])
106 video->BlitSprite( core->WindowFrames[1], core->Width - core->WindowFrames[1]->Width, 0, true );
107 if (core->WindowFrames[2])
108 video->BlitSprite( core->WindowFrames[2], (core->Width - core->WindowFrames[2]->Width) / 2, 0, true );
109 if (core->WindowFrames[3])
110 video->BlitSprite( core->WindowFrames[3], (core->Width - core->WindowFrames[3]->Width) / 2, core->Height - core->WindowFrames[3]->Height, true );
111 } else if (clip_regions.size()) {
112 // clip drawing (we only do Background right now) for InvalidateForControl
113 for (unsigned int i = 0; i < clip_regions.size(); i++) {
114 Region to_clip = clip_regions[i];
115 to_clip.x += XPos;
116 to_clip.y += YPos;
117 video->SetClipRect(&to_clip);
118 if (BackGround) {
119 video->BlitSprite( BackGround, XPos, YPos, true );
123 clip_regions.clear();
124 video->SetClipRect( &clip );
125 //Float || Changed
126 if (BackGround && (Flags & (WF_FLOAT|WF_CHANGED) ) ) {
127 video->BlitSprite( BackGround, XPos, YPos, true );
129 std::vector< Control*>::iterator m;
130 for (m = Controls.begin(); m != Controls.end(); ++m) {
131 ( *m )->Draw( XPos, YPos );
133 if ( (Flags&WF_CHANGED) && (Visible == WINDOW_GRAYED) ) {
134 Color black = { 0, 0, 0, 128 };
135 video->DrawRect(clip, black);
137 video->SetClipRect( NULL );
138 Flags &= ~WF_CHANGED;
141 /** Set window frame used to fill screen on higher resolutions*/
142 void Window::SetFrame()
144 if ( (Width < core->Width) || (Height < core->Height) ) {
145 Flags|=WF_FRAME;
147 Invalidate();
150 /** Returns the Control at X,Y Coordinates */
151 Control* Window::GetControl(unsigned short x, unsigned short y, bool ignore)
153 Control* ctrl = NULL;
155 //Check if we are still on the last control
156 if (( lastC != NULL )) {
157 if (( XPos + lastC->XPos <= x )
158 && ( YPos + lastC->YPos <= y )
159 && ( XPos + lastC->XPos + lastC->Width >= x )
160 && ( YPos + lastC->YPos + lastC->Height >= y )
161 && ! lastC->IsPixelTransparent (x - XPos - lastC->XPos, y - YPos - lastC->YPos)) {
162 //Yes, we are on the last returned Control
163 return lastC;
166 std::vector< Control*>::const_iterator m;
167 for (m = Controls.begin(); m != Controls.end(); m++) {
168 if (ignore && (*m)->ControlID&IGNORE_CONTROL) {
169 continue;
171 if (( XPos + ( *m )->XPos <= x )
172 && ( YPos + ( *m )->YPos <= y )
173 && ( XPos + ( *m )->XPos + ( *m )->Width >= x )
174 && ( YPos + ( *m )->YPos + ( *m )->Height >= y )
175 && ! ( *m )->IsPixelTransparent (x - XPos - ( *m )->XPos, y - YPos - ( *m )->YPos)) {
176 ctrl = *m;
177 break;
180 lastC = ctrl;
181 return ctrl;
184 Control* Window::GetOver() const
186 return lastOver;
189 Control* Window::GetFocus() const
191 return lastFocus;
194 Control* Window::GetMouseFocus() const
196 return lastMouseFocus;
199 /** Sets 'ctrl' as Focused */
200 void Window::SetFocused(Control* ctrl)
202 if (lastFocus != NULL) {
203 lastFocus->hasFocus = false;
204 lastFocus->Changed = true;
206 lastFocus = ctrl;
207 if (ctrl != NULL) {
208 lastFocus->hasFocus = true;
209 lastFocus->Changed = true;
213 /** Sets 'ctrl' as Mouse Focused */
214 void Window::SetMouseFocused(Control* ctrl)
216 if (lastMouseFocus != NULL) {
217 lastMouseFocus->Changed = true;
219 lastMouseFocus = ctrl;
220 if (ctrl != NULL) {
221 lastMouseFocus->Changed = true;
225 unsigned int Window::GetControlCount() const
227 return Controls.size();
230 Control* Window::GetControl(unsigned short i) const
232 if (i < Controls.size()) {
233 return Controls[i];
235 return NULL;
238 bool Window::IsValidControl(unsigned short ID, Control *ctrl) const
240 size_t i = Controls.size();
241 while (i--) {
242 if (Controls[i]==ctrl) {
243 return ctrl->ControlID==ID;
246 return false;
249 void Window::DelControl(unsigned short i)
251 if (i < Controls.size() ) {
252 Control *ctrl = Controls[i];
253 if (ctrl==lastC) {
254 lastC=NULL;
256 if (ctrl==lastOver) {
257 lastOver=NULL;
259 if (ctrl==lastFocus) {
260 lastFocus=NULL;
262 if (ctrl==lastMouseFocus) {
263 lastMouseFocus=NULL;
265 delete ctrl;
266 Controls.erase(Controls.begin()+i);
268 Invalidate();
271 Control* Window::GetDefaultControl(unsigned int ctrltype) const
273 if (!Controls.size()) {
274 return NULL;
276 if (ctrltype>=2) {
277 return NULL;
279 return GetControl( (ieWord) DefaultControl[ctrltype] );
282 Control* Window::GetScrollControl() const
284 if (!Controls.size()) {
285 return NULL;
287 return GetControl( (ieWord) ScrollControl );
290 void Window::release(void)
292 Visible = WINDOW_INVALID;
293 lastC = NULL;
294 lastFocus = NULL;
295 lastMouseFocus = NULL;
296 lastOver = NULL;
299 /** Redraw all the Window */
300 void Window::Invalidate()
302 DefaultControl[0] = -1;
303 DefaultControl[1] = -1;
304 ScrollControl = -1;
305 for (unsigned int i = 0; i < Controls.size(); i++) {
306 if (!Controls[i]) {
307 continue;
309 Controls[i]->Changed = true;
310 switch (Controls[i]->ControlType) {
311 case IE_GUI_SCROLLBAR:
312 if ((ScrollControl == -1) || (Controls[i]->Flags & IE_GUI_SCROLLBAR_DEFAULT))
313 ScrollControl = i;
314 break;
315 case IE_GUI_BUTTON:
316 if (( Controls[i]->Flags & IE_GUI_BUTTON_DEFAULT )) {
317 DefaultControl[0] = i;
319 if (( Controls[i]->Flags & IE_GUI_BUTTON_CANCEL )) {
320 DefaultControl[1] = i;
322 break;
323 //falling through
324 case IE_GUI_GAMECONTROL:
325 DefaultControl[0] = i;
326 DefaultControl[1] = i;
327 break;
328 default: ;
331 Flags |= WF_CHANGED;
334 /** Redraw enough to update the specified Control */
335 void Window::InvalidateForControl(Control *ctrl) {
336 // TODO: for this to be general-purpose, we should mark anything inside this
337 // region with Changed, and also do mass Invalidate() if we overlap with
338 // another window, but for now this just clips the *background*, see DrawWindow()
339 clip_regions.push_back( Region(ctrl->XPos, ctrl->YPos, ctrl->Width, ctrl->Height) );
342 void Window::RedrawControls(const char* VarName, unsigned int Sum)
344 for (unsigned int i = 0; i < Controls.size(); i++) {
345 switch (Controls[i]->ControlType) {
346 case IE_GUI_MAP:
348 MapControl *mc = ( MapControl* ) (Controls[i]);
349 mc->RedrawMapControl( VarName, Sum );
350 break;
352 case IE_GUI_BUTTON:
354 Button* bt = ( Button* ) ( Controls[i] );
355 bt->RedrawButton( VarName, Sum );
356 break;
358 case IE_GUI_TEXTAREA:
360 TextArea* pb = ( TextArea* ) ( Controls[i] );
361 pb->RedrawTextArea( VarName, Sum );
362 break;
364 case IE_GUI_PROGRESSBAR:
366 Progressbar* pb = ( Progressbar* ) ( Controls[i] );
367 pb->RedrawProgressbar( VarName, Sum );
368 break;
370 case IE_GUI_SLIDER:
372 Slider* sl = ( Slider* ) ( Controls[i] );
373 sl->RedrawSlider( VarName, Sum );
374 break;
376 case IE_GUI_SCROLLBAR:
378 ScrollBar* sb = ( ScrollBar* ) ( Controls[i] );
379 sb->RedrawScrollBar( VarName, Sum );
380 break;
386 /** Searches for a ScrollBar and a TextArea to link them */
387 void Window::Link(unsigned short SBID, unsigned short TAID)
389 ScrollBar* sb = NULL;
390 TextArea* ta = NULL;
391 std::vector< Control*>::iterator m;
392 for (m = Controls.begin(); m != Controls.end(); m++) {
393 if (( *m )->Owner != this)
394 continue;
395 if (( *m )->ControlType == IE_GUI_SCROLLBAR) {
396 if (( *m )->ControlID == SBID) {
397 sb = ( ScrollBar * ) ( *m );
398 if (ta != NULL)
399 break;
401 } else if (( *m )->ControlType == IE_GUI_TEXTAREA) {
402 if (( *m )->ControlID == TAID) {
403 ta = ( TextArea * ) ( *m );
404 if (sb != NULL)
405 break;
409 if (sb && ta) {
410 sb->ta = ta;
411 ta->SetScrollBar( sb );
415 void Window::OnMouseEnter(unsigned short x, unsigned short y, Control *ctrl)
417 lastOver = ctrl;
418 if (!lastOver) {
419 return;
421 lastOver->OnMouseEnter( x - XPos - lastOver->XPos, y - YPos - lastOver->YPos );
424 void Window::OnMouseLeave(unsigned short x, unsigned short y)
426 if (!lastOver) {
427 return;
429 lastOver->OnMouseLeave( x - XPos - lastOver->XPos, y - YPos - lastOver->YPos );
430 lastOver = NULL;
433 void Window::OnMouseOver(unsigned short x, unsigned short y)
435 if (!lastOver) {
436 return;
438 lastOver->OnMouseOver( x - XPos - lastOver->XPos, y - YPos - lastOver->YPos );