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.
24 #include "Interface.h"
25 #include "MapControl.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
;
38 this->Height
= Height
;
39 this->BackGround
= NULL
;
42 lastMouseFocus
= NULL
;
44 Visible
= WINDOW_INVISIBLE
;
46 Cursor
= IE_CURSOR_NORMAL
;
47 DefaultControl
[0] = -1;
48 DefaultControl
[1] = -1;
54 std::vector
< Control
*>::iterator m
= Controls
.begin();
55 while (Controls
.size() != 0) {
56 Control
* ctrl
= ( *m
);
61 core
->GetVideoDriver()->FreeSprite( BackGround
);
64 /** Add a Control in the Window */
65 void Window::AddControl(Control
* ctrl
)
71 for (size_t i
= 0; i
< Controls
.size(); i
++) {
72 if (Controls
[i
]->ControlID
== ctrl
->ControlID
) {
73 delete( Controls
[i
] );
79 Controls
.push_back( ctrl
);
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
);
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
);
97 if ( (Flags
& (WF_FRAME
|WF_CHANGED
) )== (WF_FRAME
|WF_CHANGED
) ) {
98 Region
screen( 0, 0, core
->Width
, core
->Height
);
99 video
->SetClipRect( NULL
);
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
];
117 video
->SetClipRect(&to_clip
);
119 video
->BlitSprite( BackGround
, XPos
, YPos
, true );
123 clip_regions
.clear();
124 video
->SetClipRect( &clip
);
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
) ) {
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
166 std::vector
< Control
*>::const_iterator m
;
167 for (m
= Controls
.begin(); m
!= Controls
.end(); m
++) {
168 if (ignore
&& (*m
)->ControlID
&IGNORE_CONTROL
) {
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
)) {
184 Control
* Window::GetOver() const
189 Control
* Window::GetFocus() const
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;
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
;
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()) {
238 bool Window::IsValidControl(unsigned short ID
, Control
*ctrl
) const
240 size_t i
= Controls
.size();
242 if (Controls
[i
]==ctrl
) {
243 return ctrl
->ControlID
==ID
;
249 void Window::DelControl(unsigned short i
)
251 if (i
< Controls
.size() ) {
252 Control
*ctrl
= Controls
[i
];
256 if (ctrl
==lastOver
) {
259 if (ctrl
==lastFocus
) {
262 if (ctrl
==lastMouseFocus
) {
266 Controls
.erase(Controls
.begin()+i
);
271 Control
* Window::GetDefaultControl(unsigned int ctrltype
) const
273 if (!Controls
.size()) {
279 return GetControl( (ieWord
) DefaultControl
[ctrltype
] );
282 Control
* Window::GetScrollControl() const
284 if (!Controls
.size()) {
287 return GetControl( (ieWord
) ScrollControl
);
290 void Window::release(void)
292 Visible
= WINDOW_INVALID
;
295 lastMouseFocus
= NULL
;
299 /** Redraw all the Window */
300 void Window::Invalidate()
302 DefaultControl
[0] = -1;
303 DefaultControl
[1] = -1;
305 for (unsigned int i
= 0; i
< Controls
.size(); i
++) {
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
))
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
;
324 case IE_GUI_GAMECONTROL
:
325 DefaultControl
[0] = i
;
326 DefaultControl
[1] = i
;
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
) {
348 MapControl
*mc
= ( MapControl
* ) (Controls
[i
]);
349 mc
->RedrawMapControl( VarName
, Sum
);
354 Button
* bt
= ( Button
* ) ( Controls
[i
] );
355 bt
->RedrawButton( VarName
, Sum
);
358 case IE_GUI_TEXTAREA
:
360 TextArea
* pb
= ( TextArea
* ) ( Controls
[i
] );
361 pb
->RedrawTextArea( VarName
, Sum
);
364 case IE_GUI_PROGRESSBAR
:
366 Progressbar
* pb
= ( Progressbar
* ) ( Controls
[i
] );
367 pb
->RedrawProgressbar( VarName
, Sum
);
372 Slider
* sl
= ( Slider
* ) ( Controls
[i
] );
373 sl
->RedrawSlider( VarName
, Sum
);
376 case IE_GUI_SCROLLBAR
:
378 ScrollBar
* sb
= ( ScrollBar
* ) ( Controls
[i
] );
379 sb
->RedrawScrollBar( VarName
, Sum
);
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
;
391 std::vector
< Control
*>::iterator m
;
392 for (m
= Controls
.begin(); m
!= Controls
.end(); m
++) {
393 if (( *m
)->Owner
!= this)
395 if (( *m
)->ControlType
== IE_GUI_SCROLLBAR
) {
396 if (( *m
)->ControlID
== SBID
) {
397 sb
= ( ScrollBar
* ) ( *m
);
401 } else if (( *m
)->ControlType
== IE_GUI_TEXTAREA
) {
402 if (( *m
)->ControlID
== TAID
) {
403 ta
= ( TextArea
* ) ( *m
);
411 ta
->SetScrollBar( sb
);
415 void Window::OnMouseEnter(unsigned short x
, unsigned short y
, Control
*ctrl
)
421 lastOver
->OnMouseEnter( x
- XPos
- lastOver
->XPos
, y
- YPos
- lastOver
->YPos
);
424 void Window::OnMouseLeave(unsigned short x
, unsigned short y
)
429 lastOver
->OnMouseLeave( x
- XPos
- lastOver
->XPos
, y
- YPos
- lastOver
->YPos
);
433 void Window::OnMouseOver(unsigned short x
, unsigned short y
)
438 lastOver
->OnMouseOver( x
- XPos
- lastOver
->XPos
, y
- YPos
- lastOver
->YPos
);