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 "GUI/Window.h"
23 #include "GUI/Button.h"
24 #include "GUI/Control.h"
25 #include "GUI/MapControl.h"
26 #include "GUI/Progressbar.h"
27 #include "GUI/Slider.h"
31 #include "Interface.h"
34 Window::Window(unsigned short WindowID
, unsigned short XPos
,
35 unsigned short YPos
, unsigned short Width
, unsigned short Height
)
37 this->WindowID
= WindowID
;
41 this->Height
= Height
;
42 this->BackGround
= NULL
;
45 lastMouseFocus
= NULL
;
47 Visible
= WINDOW_INVISIBLE
;
49 Cursor
= IE_CURSOR_NORMAL
;
50 DefaultControl
[0] = -1;
51 DefaultControl
[1] = -1;
57 std::vector
< Control
*>::iterator m
= Controls
.begin();
58 while (Controls
.size() != 0) {
59 Control
* ctrl
= ( *m
);
64 core
->GetVideoDriver()->FreeSprite( BackGround
);
67 /** Add a Control in the Window */
68 void Window::AddControl(Control
* ctrl
)
74 for (size_t i
= 0; i
< Controls
.size(); i
++) {
75 if (Controls
[i
]->ControlID
== ctrl
->ControlID
) {
76 delete( Controls
[i
] );
82 Controls
.push_back( ctrl
);
85 /** 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. */
86 void Window::SetBackGround(Sprite2D
* img
, bool clean
)
88 if (clean
&& BackGround
) {
89 core
->GetVideoDriver()->FreeSprite( this->BackGround
);
94 /** This function Draws the Window on the Output Screen */
95 void Window::DrawWindow()
97 Video
* video
= core
->GetVideoDriver();
98 Region
clip( XPos
, YPos
, Width
, Height
);
100 if ( (Flags
& (WF_FRAME
|WF_CHANGED
) )== (WF_FRAME
|WF_CHANGED
) ) {
101 Region
screen( 0, 0, core
->Width
, core
->Height
);
102 video
->SetClipRect( NULL
);
104 Color black
= { 0, 0, 0, 255 };
105 video
->DrawRect( screen
, black
);
106 if (core
->WindowFrames
[0])
107 video
->BlitSprite( core
->WindowFrames
[0], 0, 0, true );
108 if (core
->WindowFrames
[1])
109 video
->BlitSprite( core
->WindowFrames
[1], core
->Width
- core
->WindowFrames
[1]->Width
, 0, true );
110 if (core
->WindowFrames
[2])
111 video
->BlitSprite( core
->WindowFrames
[2], (core
->Width
- core
->WindowFrames
[2]->Width
) / 2, 0, true );
112 if (core
->WindowFrames
[3])
113 video
->BlitSprite( core
->WindowFrames
[3], (core
->Width
- core
->WindowFrames
[3]->Width
) / 2, core
->Height
- core
->WindowFrames
[3]->Height
, true );
114 } else if (clip_regions
.size()) {
115 // clip drawing (we only do Background right now) for InvalidateForControl
116 for (unsigned int i
= 0; i
< clip_regions
.size(); i
++) {
117 Region to_clip
= clip_regions
[i
];
120 video
->SetClipRect(&to_clip
);
122 video
->BlitSprite( BackGround
, XPos
, YPos
, true );
126 clip_regions
.clear();
127 video
->SetClipRect( &clip
);
129 if (BackGround
&& (Flags
& (WF_FLOAT
|WF_CHANGED
) ) ) {
130 video
->BlitSprite( BackGround
, XPos
, YPos
, true );
132 std::vector
< Control
*>::iterator m
;
133 for (m
= Controls
.begin(); m
!= Controls
.end(); ++m
) {
134 ( *m
)->Draw( XPos
, YPos
);
136 if ( (Flags
&WF_CHANGED
) && (Visible
== WINDOW_GRAYED
) ) {
137 Color black
= { 0, 0, 0, 128 };
138 video
->DrawRect(clip
, black
);
140 video
->SetClipRect( NULL
);
141 Flags
&= ~WF_CHANGED
;
144 /** Set window frame used to fill screen on higher resolutions*/
145 void Window::SetFrame()
147 if ( (Width
< core
->Width
) || (Height
< core
->Height
) ) {
153 /** Returns the Control at X,Y Coordinates */
154 Control
* Window::GetControl(unsigned short x
, unsigned short y
, bool ignore
)
156 Control
* ctrl
= NULL
;
158 //Check if we are still on the last control
159 if (( lastC
!= NULL
)) {
160 if (( XPos
+ lastC
->XPos
<= x
)
161 && ( YPos
+ lastC
->YPos
<= y
)
162 && ( XPos
+ lastC
->XPos
+ lastC
->Width
>= x
)
163 && ( YPos
+ lastC
->YPos
+ lastC
->Height
>= y
)
164 && ! lastC
->IsPixelTransparent (x
- XPos
- lastC
->XPos
, y
- YPos
- lastC
->YPos
)) {
165 //Yes, we are on the last returned Control
169 std::vector
< Control
*>::const_iterator m
;
170 for (m
= Controls
.begin(); m
!= Controls
.end(); m
++) {
171 if (ignore
&& (*m
)->ControlID
&IGNORE_CONTROL
) {
174 if (( XPos
+ ( *m
)->XPos
<= x
)
175 && ( YPos
+ ( *m
)->YPos
<= y
)
176 && ( XPos
+ ( *m
)->XPos
+ ( *m
)->Width
>= x
)
177 && ( YPos
+ ( *m
)->YPos
+ ( *m
)->Height
>= y
)
178 && ! ( *m
)->IsPixelTransparent (x
- XPos
- ( *m
)->XPos
, y
- YPos
- ( *m
)->YPos
)) {
187 Control
* Window::GetOver() const
192 Control
* Window::GetFocus() const
197 Control
* Window::GetMouseFocus() const
199 return lastMouseFocus
;
202 /** Sets 'ctrl' as Focused */
203 void Window::SetFocused(Control
* ctrl
)
205 if (lastFocus
!= NULL
) {
206 lastFocus
->hasFocus
= false;
207 lastFocus
->Changed
= true;
211 lastFocus
->hasFocus
= true;
212 lastFocus
->Changed
= true;
216 /** Sets 'ctrl' as Mouse Focused */
217 void Window::SetMouseFocused(Control
* ctrl
)
219 if (lastMouseFocus
!= NULL
) {
220 lastMouseFocus
->Changed
= true;
222 lastMouseFocus
= ctrl
;
224 lastMouseFocus
->Changed
= true;
228 unsigned int Window::GetControlCount() const
230 return Controls
.size();
233 Control
* Window::GetControl(unsigned short i
) const
235 if (i
< Controls
.size()) {
241 bool Window::IsValidControl(unsigned short ID
, Control
*ctrl
) const
243 size_t i
= Controls
.size();
245 if (Controls
[i
]==ctrl
) {
246 return ctrl
->ControlID
==ID
;
252 void Window::DelControl(unsigned short i
)
254 if (i
< Controls
.size() ) {
255 Control
*ctrl
= Controls
[i
];
259 if (ctrl
==lastOver
) {
262 if (ctrl
==lastFocus
) {
265 if (ctrl
==lastMouseFocus
) {
269 Controls
.erase(Controls
.begin()+i
);
274 Control
* Window::GetDefaultControl(unsigned int ctrltype
) const
276 if (!Controls
.size()) {
282 return GetControl( (ieWord
) DefaultControl
[ctrltype
] );
285 Control
* Window::GetScrollControl() const
287 if (!Controls
.size()) {
290 return GetControl( (ieWord
) ScrollControl
);
293 void Window::release(void)
295 Visible
= WINDOW_INVALID
;
298 lastMouseFocus
= NULL
;
302 /** Redraw all the Window */
303 void Window::Invalidate()
305 DefaultControl
[0] = -1;
306 DefaultControl
[1] = -1;
308 for (unsigned int i
= 0; i
< Controls
.size(); i
++) {
312 Controls
[i
]->Changed
= true;
313 switch (Controls
[i
]->ControlType
) {
314 case IE_GUI_SCROLLBAR
:
315 if ((ScrollControl
== -1) || (Controls
[i
]->Flags
& IE_GUI_SCROLLBAR_DEFAULT
))
319 if (( Controls
[i
]->Flags
& IE_GUI_BUTTON_DEFAULT
)) {
320 DefaultControl
[0] = i
;
322 if (( Controls
[i
]->Flags
& IE_GUI_BUTTON_CANCEL
)) {
323 DefaultControl
[1] = i
;
327 case IE_GUI_GAMECONTROL
:
328 DefaultControl
[0] = i
;
329 DefaultControl
[1] = i
;
337 /** Redraw enough to update the specified Control */
338 void Window::InvalidateForControl(Control
*ctrl
) {
339 // TODO: for this to be general-purpose, we should mark anything inside this
340 // region with Changed, and also do mass Invalidate() if we overlap with
341 // another window, but for now this just clips the *background*, see DrawWindow()
342 clip_regions
.push_back( Region(ctrl
->XPos
, ctrl
->YPos
, ctrl
->Width
, ctrl
->Height
) );
345 void Window::RedrawControls(const char* VarName
, unsigned int Sum
)
347 for (unsigned int i
= 0; i
< Controls
.size(); i
++) {
348 switch (Controls
[i
]->ControlType
) {
351 MapControl
*mc
= ( MapControl
* ) (Controls
[i
]);
352 mc
->RedrawMapControl( VarName
, Sum
);
357 Button
* bt
= ( Button
* ) ( Controls
[i
] );
358 bt
->RedrawButton( VarName
, Sum
);
361 case IE_GUI_TEXTAREA
:
363 TextArea
* pb
= ( TextArea
* ) ( Controls
[i
] );
364 pb
->RedrawTextArea( VarName
, Sum
);
367 case IE_GUI_PROGRESSBAR
:
369 Progressbar
* pb
= ( Progressbar
* ) ( Controls
[i
] );
370 pb
->RedrawProgressbar( VarName
, Sum
);
375 Slider
* sl
= ( Slider
* ) ( Controls
[i
] );
376 sl
->RedrawSlider( VarName
, Sum
);
379 case IE_GUI_SCROLLBAR
:
381 ScrollBar
* sb
= ( ScrollBar
* ) ( Controls
[i
] );
382 sb
->RedrawScrollBar( VarName
, Sum
);
389 /** Searches for a ScrollBar and a TextArea to link them */
390 void Window::Link(unsigned short SBID
, unsigned short TAID
)
392 ScrollBar
* sb
= NULL
;
394 std::vector
< Control
*>::iterator m
;
395 for (m
= Controls
.begin(); m
!= Controls
.end(); m
++) {
396 if (( *m
)->Owner
!= this)
398 if (( *m
)->ControlType
== IE_GUI_SCROLLBAR
) {
399 if (( *m
)->ControlID
== SBID
) {
400 sb
= ( ScrollBar
* ) ( *m
);
404 } else if (( *m
)->ControlType
== IE_GUI_TEXTAREA
) {
405 if (( *m
)->ControlID
== TAID
) {
406 ta
= ( TextArea
* ) ( *m
);
414 ta
->SetScrollBar( sb
);
418 void Window::OnMouseEnter(unsigned short x
, unsigned short y
, Control
*ctrl
)
424 lastOver
->OnMouseEnter( x
- XPos
- lastOver
->XPos
, y
- YPos
- lastOver
->YPos
);
427 void Window::OnMouseLeave(unsigned short x
, unsigned short y
)
432 lastOver
->OnMouseLeave( x
- XPos
- lastOver
->XPos
, y
- YPos
- lastOver
->YPos
);
436 void Window::OnMouseOver(unsigned short x
, unsigned short y
)
441 lastOver
->OnMouseOver( x
- XPos
- lastOver
->XPos
, y
- YPos
- lastOver
->YPos
);