author | darkvater |
Mon, 16 Aug 2004 22:35:17 +0000 | |
changeset 70 | 60216d94f7c1 |
parent 69 | f8c29cdb388e |
child 77 | 855f2aaf816b |
permissions | -rw-r--r-- |
0 | 1 |
#include "stdafx.h" |
2 |
#include "ttd.h" |
|
3 |
#include "window.h" |
|
4 |
#include "gfx.h" |
|
5 |
#include "viewport.h" |
|
6 |
||
7 |
void HandleButtonClick(Window *w, byte widget) |
|
8 |
{ |
|
9 |
w->click_state |= (1 << widget); |
|
10 |
w->flags4 |= 5 << WF_TIMEOUT_SHL; |
|
11 |
InvalidateWidget(w, widget); |
|
12 |
} |
|
13 |
||
14 |
void DispatchLeftClickEvent(Window *w, int x, int y) { |
|
15 |
WindowEvent e; |
|
16 |
const Widget *wi; |
|
17 |
||
18 |
e.click.pt.x = x; |
|
19 |
e.click.pt.y = y; |
|
20 |
e.event = WE_CLICK; |
|
21 |
||
22 |
if (w->desc_flags & WDF_DEF_WIDGET) { |
|
23 |
e.click.widget = GetWidgetFromPos(w, x, y); |
|
24 |
if (e.click.widget < 0) return; /* exit if clicked outside of widgets */ |
|
25 |
||
26 |
wi = &w->widget[e.click.widget]; |
|
27 |
||
28 |
if (wi->type & 0xE0) { |
|
29 |
/* special widget handling */ |
|
30 |
switch(wi->type) { |
|
31 |
case WWT_IMGBTN | WWB_PUSHBUTTON: |
|
32 |
case WWT_TEXTBTN | WWB_PUSHBUTTON: |
|
33 |
if (HASBIT(w->disabled_state, e.click.widget)) |
|
34 |
return; /* don't allow click if disabled */ |
|
35 |
HandleButtonClick(w, e.click.widget); |
|
36 |
break; |
|
37 |
case WWT_NODISTXTBTN: |
|
38 |
if (HASBIT(w->disabled_state, e.click.widget)) |
|
39 |
return; /* don't allow click if disabled */ |
|
40 |
break; |
|
41 |
} |
|
42 |
} else if (wi->type == WWT_SCROLLBAR || wi->type == WWT_HSCROLLBAR) { |
|
43 |
ScrollbarClickHandler(w, wi, e.click.pt.x, e.click.pt.y); |
|
44 |
} |
|
45 |
||
46 |
w->wndproc(w, &e); |
|
47 |
||
48 |
if (w->desc_flags & WDF_STD_BTN) { |
|
49 |
if (e.click.widget == 0) DeleteWindow(w); |
|
50 |
else { |
|
51 |
if (e.click.widget == 1) { |
|
52 |
if (_ctrl_pressed) |
|
53 |
StartWindowSizing(w); |
|
54 |
else |
|
55 |
StartWindowDrag(w); |
|
56 |
} |
|
57 |
} |
|
58 |
} |
|
59 |
} else { |
|
60 |
w->wndproc(w, &e); |
|
61 |
} |
|
62 |
} |
|
63 |
||
64 |
void DispatchRightClickEvent(Window *w, int x, int y) { |
|
65 |
WindowEvent e; |
|
66 |
||
67 |
/* default tooltips handler? */ |
|
68 |
if (w->desc_flags & WDF_STD_TOOLTIPS) { |
|
69 |
e.click.widget = GetWidgetFromPos(w, x, y); |
|
70 |
if (e.click.widget < 0) |
|
71 |
return; /* exit if clicked outside of widgets */ |
|
72 |
||
73 |
if (w->widget[e.click.widget].tooltips != 0) { |
|
74 |
GuiShowTooltips(w->widget[e.click.widget].tooltips); |
|
75 |
return; |
|
76 |
} |
|
77 |
} |
|
78 |
||
79 |
e.event = WE_RCLICK; |
|
80 |
e.click.pt.x = x; |
|
81 |
e.click.pt.y = y; |
|
82 |
w->wndproc(w, &e); |
|
83 |
} |
|
84 |
||
85 |
||
86 |
void DispatchMouseWheelEvent(Window *w, int wheel) |
|
87 |
{ |
|
88 |
||
89 |
if (w->vscroll.count) { |
|
90 |
int pos = clamp(w->vscroll.pos + wheel, 0, w->vscroll.count - w->vscroll.cap); |
|
91 |
if (pos != w->vscroll.pos) { |
|
92 |
w->vscroll.pos = pos; |
|
93 |
SetWindowDirty(w); |
|
94 |
} |
|
95 |
} |
|
96 |
} |
|
97 |
||
98 |
||
99 |
void DrawOverlappedWindowForAll(int left, int top, int right, int bottom) |
|
100 |
{ |
|
101 |
Window *w; |
|
102 |
DrawPixelInfo bk; |
|
103 |
_cur_dpi = &bk; |
|
104 |
||
105 |
for(w=_windows; w!=_last_window; w++) { |
|
106 |
if (right > w->left && |
|
107 |
bottom > w->top && |
|
108 |
left < w->left + w->width && |
|
109 |
top < w->top + w->height) { |
|
110 |
DrawOverlappedWindow(w, left, top, right, bottom); |
|
111 |
} |
|
112 |
} |
|
113 |
} |
|
114 |
||
115 |
void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom) |
|
116 |
{ |
|
117 |
Window *v = w; |
|
118 |
int x; |
|
119 |
||
120 |
while (++v != _last_window) { |
|
121 |
if (right > v->left && |
|
122 |
bottom > v->top && |
|
123 |
left < v->left + v->width && |
|
124 |
top < v->top + v->height) { |
|
125 |
||
126 |
if (left < (x=v->left)) { |
|
127 |
DrawOverlappedWindow(w, left, top, x, bottom); |
|
128 |
DrawOverlappedWindow(w, x, top, right, bottom); |
|
129 |
return; |
|
130 |
} |
|
131 |
||
132 |
if (right > (x=v->left + v->width)) { |
|
133 |
DrawOverlappedWindow(w, left, top, x, bottom); |
|
134 |
DrawOverlappedWindow(w, x, top, right, bottom); |
|
135 |
return; |
|
136 |
} |
|
137 |
||
138 |
if (top < (x=v->top)) { |
|
139 |
DrawOverlappedWindow(w, left, top, right, x); |
|
140 |
DrawOverlappedWindow(w, left, x, right, bottom); |
|
141 |
return; |
|
142 |
} |
|
143 |
||
144 |
if (bottom > (x=v->top + v->height)) { |
|
145 |
DrawOverlappedWindow(w, left, top, right, x); |
|
146 |
DrawOverlappedWindow(w, left, x, right, bottom); |
|
147 |
return; |
|
148 |
} |
|
149 |
||
150 |
return; |
|
151 |
} |
|
152 |
} |
|
153 |
||
154 |
{ |
|
155 |
DrawPixelInfo *dp = _cur_dpi; |
|
156 |
dp->width = right - left; |
|
157 |
dp->height = bottom - top; |
|
158 |
dp->left = left - w->left; |
|
159 |
dp->top = top - w->top; |
|
160 |
dp->pitch = _screen.pitch; |
|
161 |
dp->dst_ptr = _screen.dst_ptr + top * _screen.pitch + left; |
|
162 |
dp->zoom = 0; |
|
163 |
CallWindowEventNP(w, WE_PAINT); |
|
164 |
} |
|
165 |
} |
|
166 |
||
167 |
void CallWindowEventNP(Window *w, int event) |
|
168 |
{ |
|
169 |
WindowEvent e; |
|
170 |
e.event = event; |
|
171 |
w->wndproc(w, &e); |
|
172 |
} |
|
173 |
||
174 |
void SetWindowDirty(Window *w) |
|
175 |
{ |
|
176 |
if (w == NULL) |
|
177 |
return; |
|
178 |
||
179 |
SetDirtyBlocks(w->left, w->top, w->left + w->width, w->top + w->height); |
|
180 |
} |
|
181 |
||
182 |
void DeleteWindow(Window *w) |
|
183 |
{ |
|
184 |
WindowClass wc; |
|
185 |
WindowNumber wn; |
|
186 |
ViewPort *vp; |
|
187 |
Window *v; |
|
188 |
int count; |
|
189 |
||
190 |
if (w == NULL) |
|
191 |
return; |
|
192 |
||
193 |
if (_thd.place_mode != 0 && _thd.window_class == w->window_class && _thd.window_number == w->window_number) { |
|
194 |
ResetObjectToPlace(); |
|
195 |
} |
|
196 |
||
197 |
wc = w->window_class; |
|
198 |
wn = w->window_number; |
|
199 |
||
200 |
CallWindowEventNP(w, WE_DESTROY); |
|
201 |
||
202 |
w = FindWindowById(wc, wn); |
|
203 |
||
204 |
vp = w->viewport; |
|
205 |
w->viewport = NULL; |
|
206 |
if (vp != NULL) { |
|
207 |
_active_viewports &= ~(1 << (vp - _viewports)); |
|
208 |
vp->width = 0; |
|
209 |
} |
|
210 |
||
211 |
SetWindowDirty(w); |
|
212 |
||
213 |
v = --_last_window; |
|
214 |
count = (byte*)v - (byte*)w; |
|
215 |
memcpy(w, w + 1, count); |
|
216 |
} |
|
217 |
||
218 |
Window *FindWindowById(WindowClass cls, WindowNumber number) |
|
219 |
{ |
|
220 |
Window *w; |
|
221 |
||
222 |
for(w=_windows; w!=_last_window; w++) { |
|
223 |
if (w->window_class == cls && |
|
224 |
w->window_number == number) { |
|
225 |
return w; |
|
226 |
} |
|
227 |
} |
|
228 |
||
229 |
return NULL; |
|
230 |
} |
|
231 |
||
232 |
void DeleteWindowById(WindowClass cls, WindowNumber number) |
|
233 |
{ |
|
234 |
DeleteWindow(FindWindowById(cls, number)); |
|
235 |
} |
|
236 |
||
237 |
Window *BringWindowToFrontById(WindowClass cls, WindowNumber number) |
|
238 |
{ |
|
239 |
Window *w = FindWindowById(cls, number); |
|
240 |
||
241 |
if (w != NULL) { |
|
242 |
w->flags4 |= WF_WHITE_BORDER_MASK; |
|
243 |
SetWindowDirty(w); |
|
244 |
BringWindowToFront(w); |
|
245 |
} |
|
246 |
||
247 |
return w; |
|
248 |
} |
|
249 |
||
250 |
Window *BringWindowToFront(Window *w) |
|
251 |
{ |
|
252 |
Window *v; |
|
253 |
||
254 |
v = _last_window; |
|
255 |
do { |
|
256 |
if (--v < _windows) |
|
257 |
return w; |
|
258 |
} while (v->window_class == WC_MAIN_TOOLBAR || v->window_class == WC_STATUS_BAR || v->window_class == WC_NEWS_WINDOW); |
|
259 |
||
260 |
if (w == v) |
|
261 |
return w; |
|
262 |
||
263 |
assert(w < v); |
|
264 |
||
265 |
do { |
|
266 |
memswap(w, w+1, sizeof(Window)); |
|
267 |
w++; |
|
268 |
} while (v != w); |
|
269 |
||
270 |
SetWindowDirty(w); |
|
271 |
||
272 |
return w; |
|
273 |
} |
|
274 |
||
275 |
Window *AllocateWindow( |
|
276 |
int x, |
|
277 |
int y, |
|
278 |
int width, |
|
279 |
int height, |
|
280 |
WindowProc *proc, |
|
281 |
WindowClass cls, |
|
282 |
const Widget *widget) |
|
283 |
{ |
|
284 |
Window *w; |
|
285 |
||
286 |
restart:; |
|
287 |
w = _last_window; |
|
288 |
||
289 |
if (w >= endof(_windows)) { |
|
290 |
for(w=_windows; ;w++) { |
|
291 |
assert(w < _last_window); |
|
292 |
||
293 |
if (w->window_class != WC_MAIN_WINDOW && w->window_class != WC_MAIN_TOOLBAR && |
|
294 |
w->window_class != WC_STATUS_BAR && w->window_class != WC_NEWS_WINDOW) { |
|
295 |
||
296 |
DeleteWindow(w); |
|
297 |
goto restart; |
|
298 |
} |
|
299 |
} |
|
300 |
} |
|
301 |
||
302 |
if (w != _windows && cls != WC_NEWS_WINDOW) { |
|
303 |
Window *v; |
|
304 |
||
305 |
v = FindWindowById(WC_MAIN_TOOLBAR, 0); |
|
306 |
if (v) { |
|
307 |
memmove(v+1, v, (byte*)w - (byte*)v); |
|
308 |
w = v; |
|
309 |
} |
|
310 |
||
311 |
v = FindWindowById(WC_STATUS_BAR, 0); |
|
312 |
if (v) { |
|
313 |
memmove(v+1, v, (byte*)w - (byte*)v); |
|
314 |
w = v; |
|
315 |
} |
|
316 |
} |
|
317 |
||
318 |
/* XXX: some more code here */ |
|
319 |
w->window_class = cls; |
|
320 |
w->flags4 = WF_WHITE_BORDER_MASK; |
|
321 |
w->caption_color = 0xFF; |
|
322 |
w->window_number = 0; |
|
323 |
w->left = x; |
|
324 |
w->top = y; |
|
325 |
w->width = width; |
|
326 |
w->height = height; |
|
327 |
w->viewport = NULL; |
|
328 |
w->desc_flags = 0; |
|
329 |
// w->landscape_assoc = 0xFFFF; |
|
330 |
w->wndproc = proc; |
|
331 |
w->click_state = 0; |
|
332 |
w->disabled_state = 0; |
|
333 |
w->hidden_state = 0; |
|
334 |
// w->unk22 = 0xFFFF; |
|
335 |
w->vscroll.pos = 0; |
|
336 |
w->vscroll.count = 0; |
|
337 |
w->hscroll.pos = 0; |
|
338 |
w->hscroll.count = 0; |
|
339 |
w->widget = widget; |
|
340 |
||
341 |
((uint32*)w->custom)[0] = 0; |
|
342 |
((uint32*)w->custom)[1] = 0; |
|
343 |
((uint32*)w->custom)[2] = 0; |
|
344 |
((uint32*)w->custom)[3] = 0; |
|
345 |
||
346 |
||
347 |
_last_window++; |
|
348 |
||
349 |
SetWindowDirty(w); |
|
350 |
||
351 |
return w; |
|
352 |
} |
|
353 |
||
354 |
Window *AllocateWindowAutoPlace2( |
|
355 |
WindowClass exist_class, |
|
356 |
WindowNumber exist_num, |
|
357 |
int width, |
|
358 |
int height, |
|
359 |
WindowProc *proc, |
|
360 |
WindowClass cls, |
|
361 |
const Widget *widget) |
|
362 |
{ |
|
363 |
Window *w; |
|
364 |
int x; |
|
365 |
||
366 |
w = FindWindowById(exist_class, exist_num); |
|
367 |
if (w == NULL || w->left >= (_screen.width-20) || w->left <= -60 || w->top >= (_screen.height-20)) { |
|
368 |
return AllocateWindowAutoPlace(width,height,proc,cls,widget); |
|
369 |
} |
|
370 |
||
371 |
x = w->left; |
|
372 |
if (x > _screen.width - width) |
|
373 |
x = (_screen.width - width) - 20; |
|
374 |
||
375 |
return AllocateWindow(x+10,w->top+10,width,height,proc,cls,widget); |
|
376 |
} |
|
377 |
||
378 |
||
379 |
typedef struct SizeRect { |
|
380 |
int left,top,width,height; |
|
381 |
} SizeRect; |
|
382 |
||
383 |
||
384 |
static SizeRect _awap_r; |
|
385 |
||
386 |
static bool IsGoodAutoPlace1(int left, int top) |
|
387 |
{ |
|
388 |
int right,bottom; |
|
389 |
Window *w; |
|
390 |
||
391 |
_awap_r.left= left; |
|
392 |
_awap_r.top = top; |
|
393 |
right = _awap_r.width + left; |
|
394 |
bottom = _awap_r.height + top; |
|
395 |
||
396 |
if (left < 0 || top < 22 || right > _screen.width || bottom > _screen.height) |
|
397 |
return false; |
|
398 |
||
399 |
// Make sure it is not obscured by any window. |
|
400 |
for(w=_windows; w!=_last_window; w++) { |
|
401 |
if (w->window_class == WC_MAIN_WINDOW) |
|
402 |
continue; |
|
403 |
||
404 |
if (right > w->left && |
|
405 |
w->left + w->width > left && |
|
406 |
bottom > w->top && |
|
407 |
w->top + w->height > top) |
|
408 |
return false; |
|
409 |
} |
|
410 |
||
411 |
return true; |
|
412 |
} |
|
413 |
||
414 |
static bool IsGoodAutoPlace2(int left, int top) |
|
415 |
{ |
|
416 |
int width,height; |
|
417 |
Window *w; |
|
418 |
||
419 |
_awap_r.left= left; |
|
420 |
_awap_r.top = top; |
|
421 |
width = _awap_r.width; |
|
422 |
height = _awap_r.height; |
|
423 |
||
424 |
if (left < -(width>>2) || left > _screen.width - (width>>1)) |
|
425 |
return false; |
|
426 |
if (top < 22 || top > _screen.height - (height>>2)) |
|
427 |
return false; |
|
428 |
||
429 |
// Make sure it is not obscured by any window. |
|
430 |
for(w=_windows; w!=_last_window; w++) { |
|
431 |
if (w->window_class == WC_MAIN_WINDOW) |
|
432 |
continue; |
|
433 |
||
434 |
if (left + width > w->left && |
|
435 |
w->left + w->width > left && |
|
436 |
top + height > w->top && |
|
437 |
w->top + w->height > top) |
|
438 |
return false; |
|
439 |
} |
|
440 |
||
441 |
return true; |
|
442 |
} |
|
443 |
||
444 |
Point GetAutoPlacePosition(int width, int height) { |
|
445 |
Window *w; |
|
446 |
Point pt; |
|
447 |
||
448 |
_awap_r.width = width; |
|
449 |
_awap_r.height = height; |
|
450 |
||
451 |
if (IsGoodAutoPlace1(0, 24)) goto ok_pos; |
|
452 |
||
453 |
for(w=_windows; w!=_last_window; w++) { |
|
454 |
if (w->window_class == WC_MAIN_WINDOW) |
|
455 |
continue; |
|
456 |
||
457 |
if (IsGoodAutoPlace1(w->left+w->width+2,w->top)) goto ok_pos; |
|
458 |
if (IsGoodAutoPlace1(w->left- width-2,w->top)) goto ok_pos; |
|
459 |
if (IsGoodAutoPlace1(w->left,w->top+w->height+2)) goto ok_pos; |
|
460 |
if (IsGoodAutoPlace1(w->left,w->top- height-2)) goto ok_pos; |
|
461 |
if (IsGoodAutoPlace1(w->left+w->width+2,w->top+w->height-height)) goto ok_pos; |
|
462 |
if (IsGoodAutoPlace1(w->left- width-2,w->top+w->height-height)) goto ok_pos; |
|
463 |
if (IsGoodAutoPlace1(w->left+w->width-width,w->top+w->height+2)) goto ok_pos; |
|
464 |
if (IsGoodAutoPlace1(w->left+w->width-width,w->top- height-2)) goto ok_pos; |
|
465 |
} |
|
466 |
||
467 |
for(w=_windows; w!=_last_window; w++) { |
|
468 |
if (w->window_class == WC_MAIN_WINDOW) |
|
469 |
continue; |
|
470 |
||
471 |
if (IsGoodAutoPlace2(w->left+w->width+2,w->top)) goto ok_pos; |
|
472 |
if (IsGoodAutoPlace2(w->left- width-2,w->top)) goto ok_pos; |
|
473 |
if (IsGoodAutoPlace2(w->left,w->top+w->height+2)) goto ok_pos; |
|
474 |
if (IsGoodAutoPlace2(w->left,w->top- height-2)) goto ok_pos; |
|
475 |
} |
|
476 |
||
477 |
{ |
|
478 |
int left=0,top=24; |
|
479 |
||
480 |
restart:; |
|
481 |
for(w=_windows; w!=_last_window; w++) { |
|
482 |
if (w->left == left && w->top == top) { |
|
483 |
left += 5; |
|
484 |
top += 5; |
|
485 |
goto restart; |
|
486 |
} |
|
487 |
} |
|
488 |
||
489 |
pt.x = left; |
|
490 |
pt.y = top; |
|
491 |
return pt; |
|
492 |
} |
|
493 |
||
494 |
ok_pos:; |
|
495 |
pt.x = _awap_r.left; |
|
496 |
pt.y = _awap_r.top; |
|
497 |
return pt; |
|
498 |
} |
|
499 |
||
500 |
Window *AllocateWindowAutoPlace( |
|
501 |
int width, |
|
502 |
int height, |
|
503 |
WindowProc *proc, |
|
504 |
WindowClass cls, |
|
505 |
const Widget *widget) { |
|
506 |
||
507 |
Point pt = GetAutoPlacePosition(width, height); |
|
508 |
return AllocateWindow(pt.x, pt.y, width, height, proc, cls, widget); |
|
509 |
} |
|
510 |
||
511 |
Window *AllocateWindowDescFront(const WindowDesc *desc, int value) |
|
512 |
{ |
|
513 |
Window *w; |
|
514 |
||
515 |
if (BringWindowToFrontById(desc->cls, value)) |
|
516 |
return NULL; |
|
517 |
w = AllocateWindowDesc(desc); |
|
518 |
w->window_number = value; |
|
519 |
return w; |
|
520 |
} |
|
521 |
||
522 |
Window *AllocateWindowDesc(const WindowDesc *desc) |
|
523 |
{ |
|
524 |
Point pt; |
|
525 |
Window *w; |
|
526 |
||
527 |
if (desc->parent_cls != WC_MAIN_WINDOW && |
|
528 |
(w = FindWindowById(desc->parent_cls, _alloc_wnd_parent_num), _alloc_wnd_parent_num=0, w) != NULL && |
|
529 |
w->left < _screen.width-20 && w->left > -60 && w->top < _screen.height-20) { |
|
530 |
pt.x = w->left + 10; |
|
531 |
if (pt.x > _screen.width + 10 - desc->width) |
|
532 |
pt.x = (_screen.width + 10 - desc->width) - 20; |
|
533 |
pt.y = w->top + 10; |
|
68
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
534 |
// open Build Toolbars and Terraforming Toolbar aligned |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
535 |
} else if (desc->cls == WC_BUILD_TOOLBAR || desc->cls == WC_SCEN_LAND_GEN) { |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
536 |
/* Override the position if a toolbar is opened according to the place of the maintoolbar |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
537 |
* The main toolbar (WC_MAIN_TOOLBAR) is 640px in width */ |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
538 |
switch (_patches.toolbar_pos) { |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
539 |
case 1: pt.x = ((_screen.width + 640) >> 1) - desc->width; break; |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
540 |
case 2: pt.x = _screen.width - desc->width; break; |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
541 |
default: pt.x = 640 - desc->width; |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
542 |
} |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
543 |
pt.y = desc->top; |
0 | 544 |
} else { |
545 |
pt.x = desc->left; |
|
546 |
pt.y = desc->top; |
|
547 |
if (pt.x == WDP_AUTO) { |
|
548 |
pt = GetAutoPlacePosition(desc->width, desc->height); |
|
549 |
} else { |
|
550 |
if (pt.x == WDP_CENTER) pt.x = (_screen.width - desc->width) >> 1; |
|
551 |
if (pt.y == WDP_CENTER) pt.y = (_screen.height - desc->height) >> 1; |
|
552 |
} |
|
553 |
} |
|
554 |
||
555 |
w = AllocateWindow(pt.x, pt.y, desc->width, desc->height, desc->proc, desc->cls, desc->widgets); |
|
556 |
w->desc_flags = desc->flags; |
|
557 |
return w; |
|
558 |
} |
|
559 |
||
560 |
Window *FindWindowFromPt(int x, int y) |
|
561 |
{ |
|
562 |
Window *w; |
|
563 |
||
564 |
for(w=_last_window; w != _windows;) { |
|
565 |
--w; |
|
566 |
if (IS_INSIDE_1D(x, w->left, w->width) && |
|
567 |
IS_INSIDE_1D(y, w->top, w->height)) |
|
568 |
return w; |
|
569 |
} |
|
570 |
||
571 |
return NULL; |
|
572 |
} |
|
573 |
||
574 |
||
575 |
void InitWindowSystem() |
|
576 |
{ |
|
577 |
memset(&_windows, 0, sizeof(_windows)); |
|
578 |
_last_window = _windows; |
|
579 |
memset(_viewports, 0, sizeof(_viewports)); |
|
580 |
_active_viewports = 0; |
|
581 |
} |
|
582 |
||
583 |
void DecreaseWindowCounters() |
|
584 |
{ |
|
585 |
Window *w; |
|
586 |
||
587 |
||
588 |
for(w=_last_window; w != _windows;) { |
|
589 |
--w; |
|
590 |
// Unclick scrollbar buttons if they are pressed. |
|
591 |
if (w->flags4 & (WF_SCROLL_DOWN | WF_SCROLL_UP)) { |
|
592 |
w->flags4 &= ~(WF_SCROLL_DOWN | WF_SCROLL_UP); |
|
593 |
SetWindowDirty(w); |
|
594 |
} |
|
595 |
CallWindowEventNP(w, WE_MOUSELOOP); |
|
596 |
} |
|
597 |
||
598 |
for(w=_last_window; w != _windows;) { |
|
599 |
--w; |
|
600 |
||
601 |
if (w->flags4&WF_TIMEOUT_MASK && !(--w->flags4&WF_TIMEOUT_MASK)) { |
|
602 |
CallWindowEventNP(w, WE_TIMEOUT); |
|
603 |
if (w->desc_flags & WDF_UNCLICK_BUTTONS) |
|
604 |
UnclickWindowButtons(w); |
|
605 |
} |
|
606 |
} |
|
607 |
} |
|
608 |
||
609 |
Window *GetCallbackWnd() |
|
610 |
{ |
|
611 |
return FindWindowById(_thd.window_class, _thd.window_number); |
|
612 |
} |
|
613 |
||
614 |
void HandlePlacePresize() |
|
615 |
{ |
|
616 |
Window *w; |
|
617 |
WindowEvent e; |
|
618 |
||
619 |
if (_special_mouse_mode != WSM_PRESIZE) |
|
620 |
return; |
|
621 |
||
622 |
if ((w = GetCallbackWnd()) == NULL) |
|
623 |
return; |
|
624 |
||
625 |
e.place.pt = GetTileBelowCursor(); |
|
626 |
if (e.place.pt.x == -1) { |
|
627 |
_thd.selend.x = -1; |
|
628 |
return; |
|
629 |
} |
|
630 |
e.place.tile = TILE_FROM_XY(e.place.pt.x, e.place.pt.y); |
|
631 |
e.event = WE_PLACE_PRESIZE; |
|
632 |
w->wndproc(w, &e); |
|
633 |
} |
|
634 |
||
635 |
bool HandleDragDrop() |
|
636 |
{ |
|
637 |
Window *w; |
|
638 |
WindowEvent e; |
|
639 |
||
640 |
if (_special_mouse_mode != WSM_DRAGDROP) |
|
641 |
return true; |
|
642 |
||
643 |
if (_left_button_down) |
|
644 |
return false; |
|
645 |
||
646 |
w = GetCallbackWnd(); |
|
647 |
||
648 |
ResetObjectToPlace(); |
|
649 |
||
650 |
if (w) { |
|
651 |
// send an event in client coordinates. |
|
652 |
e.event = WE_DRAGDROP; |
|
653 |
e.dragdrop.pt.x = _cursor.pos.x - w->left; |
|
654 |
e.dragdrop.pt.y = _cursor.pos.y - w->top; |
|
655 |
e.dragdrop.widget = GetWidgetFromPos(w, e.dragdrop.pt.x, e.dragdrop.pt.y); |
|
656 |
w->wndproc(w, &e); |
|
657 |
} |
|
658 |
return false; |
|
659 |
} |
|
660 |
||
661 |
bool HandlePopupMenu() |
|
662 |
{ |
|
663 |
Window *w; |
|
664 |
WindowEvent e; |
|
665 |
||
666 |
if (!_popup_menu_active) |
|
667 |
return true; |
|
668 |
||
669 |
w = FindWindowById(WC_TOOLBAR_MENU, 0); |
|
670 |
if (w == NULL) { |
|
671 |
_popup_menu_active = false; |
|
672 |
return false; |
|
673 |
} |
|
674 |
||
675 |
if (_left_button_down) { |
|
676 |
e.event = WE_POPUPMENU_OVER; |
|
677 |
e.popupmenu.pt = _cursor.pos; |
|
678 |
w->wndproc(w, &e); |
|
679 |
} else { |
|
680 |
_popup_menu_active = false; |
|
681 |
e.event = WE_POPUPMENU_SELECT; |
|
682 |
e.popupmenu.pt = _cursor.pos; |
|
683 |
w->wndproc(w, &e); |
|
684 |
} |
|
685 |
||
686 |
return false; |
|
687 |
} |
|
688 |
||
689 |
bool HandleWindowDragging() |
|
690 |
{ |
|
691 |
Window *w; |
|
692 |
int x, y, t; |
|
693 |
||
694 |
// Get out immediately if no window is being dragged at all. |
|
695 |
if (!_dragging_window) |
|
696 |
return true; |
|
697 |
||
698 |
// Otherwise find the window... |
|
699 |
for(w=_windows; w != _last_window; w++) { |
|
700 |
if (w->flags4&(WF_DRAGGING|WF_SIZING)) { |
|
701 |
||
702 |
// Stop the dragging if the left mouse button was released |
|
703 |
if (!_left_button_down) { |
|
704 |
w->flags4 &= ~(WF_DRAGGING | WF_SIZING); |
|
705 |
break; |
|
706 |
} |
|
707 |
||
708 |
// Otherwise calculate the delta position. |
|
709 |
x = _cursor.pos.x; |
|
710 |
y = clamp2(_cursor.pos.y, 23, _screen.height-12); |
|
711 |
t = _cursorpos_drag_start.x; _cursorpos_drag_start.x = x; x-=t; |
|
712 |
t = _cursorpos_drag_start.y; _cursorpos_drag_start.y = y; y-=t; |
|
713 |
||
714 |
// No movement? |
|
715 |
if (x == 0 && y == 0) |
|
716 |
return false; |
|
717 |
||
718 |
// Mark the old position dirty |
|
719 |
SetWindowDirty(w); |
|
720 |
||
721 |
if (w->flags4 & WF_SIZING) { |
|
722 |
// Size the window |
|
723 |
w->width += x; |
|
724 |
w->height += y; |
|
725 |
} else { |
|
726 |
// Move the window and viewport |
|
727 |
w->left += x; |
|
728 |
w->top += y; |
|
729 |
if (w->viewport) { |
|
730 |
w->viewport->left += x; |
|
731 |
w->viewport->top += y; |
|
732 |
} |
|
733 |
} |
|
734 |
||
735 |
// And also mark the new position dirty. |
|
736 |
SetWindowDirty(w); |
|
737 |
return false; |
|
738 |
} |
|
739 |
} |
|
740 |
||
741 |
_dragging_window = false; |
|
742 |
return false; |
|
743 |
} |
|
744 |
||
745 |
Window *StartWindowDrag(Window *w) |
|
746 |
{ |
|
747 |
w->flags4 |= WF_DRAGGING; |
|
748 |
_dragging_window = true; |
|
749 |
_cursorpos_drag_start = _cursor.pos; |
|
750 |
w = BringWindowToFront(w); |
|
751 |
DeleteWindowById(WC_DROPDOWN_MENU, 0); |
|
752 |
return w; |
|
753 |
} |
|
754 |
||
755 |
Window *StartWindowSizing(Window *w) |
|
756 |
{ |
|
757 |
w->flags4 |= WF_SIZING; |
|
758 |
_dragging_window = true; |
|
759 |
_cursorpos_drag_start = _cursor.pos; |
|
760 |
w = BringWindowToFront(w); |
|
761 |
DeleteWindowById(WC_DROPDOWN_MENU, 0); |
|
762 |
return w; |
|
763 |
} |
|
764 |
||
765 |
||
766 |
bool HandleScrollbarScrolling() |
|
767 |
{ |
|
768 |
Window *w; |
|
769 |
int i; |
|
770 |
int pos; |
|
771 |
Scrollbar *sb; |
|
772 |
||
773 |
// Get out quickly if no item is being scrolled |
|
774 |
if (!_scrolling_scrollbar) |
|
775 |
return true; |
|
776 |
||
777 |
// Find the scrolling window |
|
778 |
for(w=_windows; w != _last_window; w++) { |
|
779 |
if (w->flags4 & WF_SCROLL_MIDDLE) { |
|
780 |
// Abort if no button is clicked any more. |
|
781 |
if (!_left_button_down) { |
|
782 |
w->flags4 &= ~WF_SCROLL_MIDDLE; |
|
783 |
SetWindowDirty(w); |
|
784 |
break; |
|
785 |
} |
|
786 |
||
787 |
if (w->flags4 & WF_HSCROLL) { |
|
788 |
sb = &w->hscroll; |
|
789 |
i = _cursor.pos.x - _cursorpos_drag_start.x; |
|
790 |
} else { |
|
791 |
sb = &w->vscroll; |
|
792 |
i = _cursor.pos.y - _cursorpos_drag_start.y; |
|
793 |
} |
|
794 |
||
795 |
// Find the item we want to move to and make sure it's inside bounds. |
|
796 |
pos = min(max(0, i + _scrollbar_start_pos) * sb->count / _scrollbar_size, max(0, sb->count - sb->cap)); |
|
797 |
if (pos != sb->pos) { |
|
798 |
sb->pos = pos; |
|
799 |
SetWindowDirty(w); |
|
800 |
} |
|
801 |
return false; |
|
802 |
} |
|
803 |
} |
|
804 |
||
805 |
_scrolling_scrollbar = false; |
|
806 |
return false; |
|
807 |
} |
|
808 |
||
809 |
bool HandleViewportScroll() |
|
810 |
{ |
|
811 |
Window *w; |
|
812 |
ViewPort *vp; |
|
813 |
int dx,dy, x, y, sub; |
|
814 |
||
815 |
if (!_scrolling_viewport) |
|
816 |
return true; |
|
817 |
||
818 |
if (!_right_button_down) { |
|
819 |
stop_capt:; |
|
820 |
_cursor.fix_at = false; |
|
821 |
_scrolling_viewport = false; |
|
822 |
return true; |
|
823 |
} |
|
824 |
||
825 |
w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y); |
|
826 |
if (w == NULL) goto stop_capt; |
|
827 |
||
828 |
if (w->window_class != WC_SMALLMAP) { |
|
829 |
vp = IsPtInWindowViewport(w, _cursor.pos.x, _cursor.pos.y); |
|
830 |
if (vp == NULL) |
|
831 |
goto stop_capt; |
|
832 |
||
833 |
WP(w,vp_d).scrollpos_x += _cursor.delta.x << vp->zoom; |
|
834 |
WP(w,vp_d).scrollpos_y += _cursor.delta.y << vp->zoom; |
|
835 |
_cursor.delta.x = _cursor.delta.y = 0; |
|
836 |
return false; |
|
837 |
} else { |
|
838 |
// scroll the smallmap ? |
|
839 |
||
840 |
_cursor.fix_at = true; |
|
841 |
||
842 |
dx = _cursor.delta.x; |
|
843 |
dy = _cursor.delta.y; |
|
844 |
||
845 |
x = WP(w,smallmap_d).scroll_x; |
|
846 |
y = WP(w,smallmap_d).scroll_y; |
|
847 |
||
848 |
sub = WP(w,smallmap_d).subscroll + dx; |
|
849 |
||
850 |
x -= (sub >> 2) << 4; |
|
851 |
y += (sub >> 2) << 4; |
|
852 |
sub &= 3; |
|
853 |
||
854 |
x += (dy >> 1) << 4; |
|
855 |
y += (dy >> 1) << 4; |
|
856 |
||
857 |
if (dy & 1) { |
|
858 |
x += 16; |
|
859 |
sub += 2; |
|
860 |
if (sub > 3) { |
|
861 |
sub -= 4; |
|
862 |
x -= 16; |
|
863 |
y += 16; |
|
864 |
} |
|
865 |
} |
|
866 |
||
867 |
if (x < 16) { x = 16; sub = 0; } |
|
868 |
if (x > (TILES_X-2)*16) { x = (TILES_X-2)*16; sub = 0; } |
|
869 |
if (y < -1120) { y = -1120; sub = 0; } |
|
870 |
if (y > (TILE_X_MAX-40) * 16) { y = (TILE_X_MAX-40) * 16; sub = 0; } |
|
871 |
||
872 |
WP(w,smallmap_d).scroll_x = x; |
|
873 |
WP(w,smallmap_d).scroll_y = y; |
|
874 |
WP(w,smallmap_d).subscroll = sub; |
|
875 |
||
876 |
_cursor.delta.x = _cursor.delta.y = 0; |
|
877 |
||
878 |
SetWindowDirty(w); |
|
879 |
return false; |
|
880 |
} |
|
881 |
} |
|
882 |
||
883 |
static Window *MaybeBringWindowToFront(Window *w) |
|
884 |
{ |
|
885 |
Window *u; |
|
886 |
||
887 |
if (w->window_class == WC_MAIN_WINDOW || |
|
888 |
w->window_class == WC_MAIN_TOOLBAR || |
|
889 |
w->window_class == WC_STATUS_BAR || |
|
890 |
w->window_class == WC_NEWS_WINDOW || |
|
891 |
w->window_class == WC_TOOLTIPS || |
|
892 |
w->window_class == WC_DROPDOWN_MENU) |
|
893 |
return w; |
|
894 |
||
895 |
for(u=w; ++u != _last_window;) { |
|
896 |
if (u->window_class == WC_MAIN_WINDOW || u->window_class==WC_MAIN_TOOLBAR || u->window_class==WC_STATUS_BAR || |
|
897 |
u->window_class == WC_NEWS_WINDOW || u->window_class == WC_TOOLTIPS || u->window_class == WC_DROPDOWN_MENU) |
|
898 |
continue; |
|
899 |
||
900 |
if (w->left + w->width <= u->left || |
|
901 |
u->left + u->width <= w->left || |
|
902 |
w->top + w->height <= u->top || |
|
903 |
u->top + u->height <= w->top) |
|
904 |
continue; |
|
905 |
||
906 |
return BringWindowToFront(w); |
|
907 |
} |
|
908 |
||
909 |
return w; |
|
910 |
} |
|
911 |
||
912 |
static void HandleKeypress(uint32 key) |
|
913 |
{ |
|
914 |
Window *w; |
|
915 |
WindowEvent we; |
|
916 |
||
917 |
// Setup event |
|
918 |
we.keypress.event = WE_KEYPRESS; |
|
919 |
we.keypress.ascii = key & 0xFF; |
|
920 |
we.keypress.keycode = key >> 16; |
|
921 |
we.keypress.cont = true; |
|
922 |
||
923 |
// Call the event, start with the uppermost window. |
|
924 |
for(w=_last_window; w != _windows;) { |
|
925 |
--w; |
|
926 |
w->wndproc(w, &we); |
|
927 |
if (!we.keypress.cont) |
|
928 |
break; |
|
929 |
} |
|
930 |
} |
|
931 |
||
932 |
extern void UpdateTileSelection(); |
|
933 |
extern bool VpHandlePlaceSizingDrag(); |
|
934 |
||
935 |
void MouseLoop() |
|
936 |
{ |
|
937 |
int x,y; |
|
938 |
Window *w; |
|
939 |
ViewPort *vp; |
|
940 |
int click; |
|
941 |
int mousewheel; |
|
942 |
||
943 |
_current_player = _local_player; |
|
944 |
||
945 |
// Handle pressed keys |
|
946 |
if (_pressed_key) { |
|
947 |
uint32 key = _pressed_key; _pressed_key = 0; |
|
948 |
HandleKeypress(key); |
|
949 |
} |
|
950 |
||
951 |
// Mouse event? |
|
952 |
click = 0; |
|
953 |
if (_left_button_down && !_left_button_clicked) { |
|
954 |
_left_button_clicked = true; |
|
955 |
click = 1; |
|
956 |
} else if (_right_button_clicked) { |
|
957 |
_right_button_clicked = false; |
|
958 |
click = 2; |
|
959 |
} |
|
960 |
||
961 |
mousewheel = 0; |
|
962 |
if (_cursor.wheel) { |
|
963 |
mousewheel = _cursor.wheel; |
|
964 |
_cursor.wheel = 0; |
|
965 |
} |
|
966 |
||
967 |
DecreaseWindowCounters(); |
|
968 |
HandlePlacePresize(); |
|
969 |
UpdateTileSelection(); |
|
970 |
if (!VpHandlePlaceSizingDrag()) |
|
971 |
return; |
|
972 |
||
973 |
if (!HandleDragDrop()) |
|
974 |
return; |
|
975 |
||
976 |
if (!HandlePopupMenu()) |
|
977 |
return; |
|
978 |
||
979 |
if (!HandleWindowDragging()) |
|
980 |
return; |
|
981 |
||
982 |
if (!HandleScrollbarScrolling()) |
|
983 |
return; |
|
984 |
||
985 |
if (!HandleViewportScroll()) |
|
986 |
return; |
|
987 |
||
988 |
x = _cursor.pos.x; |
|
989 |
y = _cursor.pos.y; |
|
990 |
||
991 |
||
992 |
if (click == 0 && mousewheel == 0) { |
|
993 |
if (_patches.autoscroll && _game_mode != GM_MENU) { |
|
994 |
w = FindWindowFromPt(x, y); |
|
995 |
if (w == NULL || w->flags4 & WF_DISABLE_VP_SCROLL ) return; |
|
996 |
vp = IsPtInWindowViewport(w, x, y); |
|
997 |
if (vp) { |
|
998 |
x -= vp->left; |
|
999 |
y -= vp->top; |
|
1000 |
//here allows scrolling in both x and y axis |
|
1001 |
#define scrollspeed 3 |
|
1002 |
if (x-15<0) { WP(w,vp_d).scrollpos_x += (x-15) * scrollspeed << vp->zoom; } |
|
1003 |
else if (15-(vp->width-x) > 0) { WP(w,vp_d).scrollpos_x += (15-(vp->width-x))*scrollspeed << vp->zoom; } |
|
1004 |
if (y-15<0) { WP(w,vp_d).scrollpos_y += (y-15)*scrollspeed << vp->zoom; } |
|
1005 |
else if (15-(vp->height-y) > 0) { WP(w,vp_d).scrollpos_y += (15-(vp->height-y))*scrollspeed << vp->zoom; } |
|
1006 |
#undef scrollspeed |
|
1007 |
} |
|
1008 |
} |
|
1009 |
return; |
|
1010 |
} |
|
1011 |
||
1012 |
w = FindWindowFromPt(x, y); |
|
1013 |
if (w == NULL) |
|
1014 |
return; |
|
1015 |
w = MaybeBringWindowToFront(w); |
|
1016 |
vp = IsPtInWindowViewport(w, x, y); |
|
1017 |
if (vp != NULL) { |
|
1018 |
if (_game_mode == GM_MENU) |
|
1019 |
return; |
|
1020 |
||
1021 |
if (mousewheel && !(w->flags4 & WF_DISABLE_VP_SCROLL)) { |
|
1022 |
ZoomInOrOutToCursor(mousewheel < 0); |
|
1023 |
} |
|
1024 |
||
1025 |
if (click == 1) { |
|
70
60216d94f7c1
(svn r71) -Cheat: [976127] no extra frequent jet crash on small airports (truesatan)
darkvater
parents:
69
diff
changeset
|
1026 |
DEBUG(misc, 2) ("cursor: 0x%X (%d)", _cursor.sprite, _cursor.sprite); |
0 | 1027 |
if (_thd.place_mode != 0 && |
67
b2b551af3d9f
(svn r68) -Fix: [1009621] build in pause is now a cheat instead of a patch (truesatan)
darkvater
parents:
0
diff
changeset
|
1028 |
// query button and place sign button work in pause mode |
b2b551af3d9f
(svn r68) -Fix: [1009621] build in pause is now a cheat instead of a patch (truesatan)
darkvater
parents:
0
diff
changeset
|
1029 |
!(_cursor.sprite == 0x2CF || _cursor.sprite == 0x2D2) && |
0 | 1030 |
_pause != 0 && |
67
b2b551af3d9f
(svn r68) -Fix: [1009621] build in pause is now a cheat instead of a patch (truesatan)
darkvater
parents:
0
diff
changeset
|
1031 |
!_cheats.build_in_pause.value) |
0 | 1032 |
return; |
1033 |
||
1034 |
if (_thd.place_mode == 0) { |
|
1035 |
HandleViewportClicked(vp, x, y); |
|
1036 |
} else { |
|
1037 |
PlaceObject(); |
|
1038 |
} |
|
1039 |
} else if (click == 2) { |
|
1040 |
if (!(w->flags4 & WF_DISABLE_VP_SCROLL)) { |
|
1041 |
_scrolling_viewport = true; |
|
1042 |
_cursor.fix_at = true; |
|
1043 |
} |
|
1044 |
} |
|
1045 |
} else { |
|
1046 |
if (mousewheel) |
|
1047 |
DispatchMouseWheelEvent(w, mousewheel); |
|
1048 |
||
1049 |
if (click == 1) |
|
1050 |
DispatchLeftClickEvent(w, x - w->left, y - w->top); |
|
1051 |
else if (click == 2) |
|
1052 |
DispatchRightClickEvent(w, x - w->left, y - w->top); |
|
1053 |
} |
|
1054 |
} |
|
1055 |
||
1056 |
static int _we4_timer; |
|
1057 |
||
1058 |
extern uint32 _pixels_redrawn; |
|
1059 |
||
1060 |
void UpdateWindows() |
|
1061 |
{ |
|
1062 |
Window *w; |
|
1063 |
int t; |
|
1064 |
||
1065 |
||
1066 |
if ((t=_we4_timer+1) >= 100) { |
|
1067 |
for(w = _last_window; w != _windows;) { |
|
1068 |
w--; |
|
1069 |
CallWindowEventNP(w, WE_4); |
|
1070 |
} |
|
1071 |
t = 0; |
|
1072 |
} |
|
1073 |
_we4_timer = t; |
|
1074 |
||
1075 |
for(w = _last_window; w != _windows;) { |
|
1076 |
w--; |
|
1077 |
if (w->flags4 & WF_WHITE_BORDER_MASK) { |
|
1078 |
w->flags4 -= WF_WHITE_BORDER_ONE; |
|
1079 |
if (!(w->flags4 & WF_WHITE_BORDER_MASK)) { |
|
1080 |
SetWindowDirty(w); |
|
1081 |
} |
|
1082 |
} |
|
1083 |
} |
|
1084 |
||
1085 |
DrawDirtyBlocks(); |
|
1086 |
||
1087 |
for(w = _windows; w!=_last_window; w++) { |
|
1088 |
if (w->viewport != NULL) |
|
1089 |
UpdateViewportPosition(w); |
|
1090 |
} |
|
1091 |
// Redraw mouse cursor in case it was hidden |
|
1092 |
DrawMouseCursor(); |
|
1093 |
} |
|
1094 |
||
1095 |
||
1096 |
int GetMenuItemIndex(Window *w, int x, int y) |
|
1097 |
{ |
|
1098 |
if ((x -= w->left) >= 0 && x < w->width && (y -= w->top + 1) >= 0) { |
|
1099 |
y /= 10; |
|
1100 |
||
1101 |
if (y < WP(w,menu_d).item_count) |
|
1102 |
return y; |
|
1103 |
} |
|
1104 |
return -1; |
|
1105 |
} |
|
1106 |
||
1107 |
void InvalidateWindow(byte cls, WindowNumber number) |
|
1108 |
{ |
|
1109 |
Window *w; |
|
1110 |
||
1111 |
for(w=_windows; w!=_last_window; w++) { |
|
1112 |
if (w->window_class==cls && w->window_number==number) |
|
1113 |
SetWindowDirty(w); |
|
1114 |
} |
|
1115 |
} |
|
1116 |
||
1117 |
void InvalidateWidget(Window *w, byte widget_index) |
|
1118 |
{ |
|
1119 |
const Widget *wi = &w->widget[widget_index]; |
|
1120 |
// if (wi->left != -2) { |
|
1121 |
SetDirtyBlocks( |
|
1122 |
w->left + wi->left, |
|
1123 |
w->top + wi->top, |
|
1124 |
w->left + wi->right + 1, |
|
1125 |
w->top + wi->bottom + 1); |
|
1126 |
// } |
|
1127 |
} |
|
1128 |
||
1129 |
void InvalidateWindowWidget(byte cls, WindowNumber number, byte widget_index) |
|
1130 |
{ |
|
1131 |
Window *w; |
|
1132 |
||
1133 |
for(w=_windows; w!=_last_window; w++) { |
|
1134 |
if (w->window_class==cls && w->window_number==number) { |
|
1135 |
InvalidateWidget(w, widget_index); |
|
1136 |
} |
|
1137 |
} |
|
1138 |
} |
|
1139 |
||
1140 |
void InvalidateWindowClasses(byte cls) |
|
1141 |
{ |
|
1142 |
Window *w; |
|
1143 |
for(w=_windows; w!=_last_window; w++) { |
|
1144 |
if (w->window_class==cls) |
|
1145 |
SetWindowDirty(w); |
|
1146 |
} |
|
1147 |
} |
|
1148 |
||
1149 |
||
1150 |
void CallWindowTickEvent() |
|
1151 |
{ |
|
1152 |
Window *w; |
|
1153 |
for(w=_last_window; w != _windows;) { |
|
1154 |
--w; |
|
1155 |
CallWindowEventNP(w, WE_TICK); |
|
1156 |
} |
|
1157 |
} |
|
1158 |
||
1159 |
void DeleteNonVitalWindows() |
|
1160 |
{ |
|
1161 |
Window *w; |
|
1162 |
for(w=_windows; w!=_last_window;) { |
|
1163 |
if (w->window_class != WC_MAIN_WINDOW && |
|
1164 |
w->window_class != WC_SELECT_GAME && |
|
1165 |
w->window_class != WC_MAIN_TOOLBAR && |
|
1166 |
w->window_class != WC_STATUS_BAR && |
|
1167 |
w->window_class != WC_TOOLBAR_MENU && |
|
1168 |
w->window_class != WC_TOOLTIPS) { |
|
1169 |
DeleteWindow(w); |
|
1170 |
w = _windows; |
|
1171 |
} else { |
|
1172 |
w++; |
|
1173 |
} |
|
1174 |
} |
|
1175 |
} |
|
1176 |
||
68
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1177 |
int PositionMainToolbar(Window *w) |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1178 |
{ |
69 | 1179 |
DEBUG(misc, 1) ("Repositioning Main Toolbar..."); |
68
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1180 |
|
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1181 |
if (w == NULL || w->window_class != WC_MAIN_TOOLBAR) |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1182 |
w = FindWindowById(WC_MAIN_TOOLBAR, 0); |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1183 |
|
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1184 |
switch (_patches.toolbar_pos) { |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1185 |
case 1: w->left = (_screen.width - w->width) >> 1; break; |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1186 |
case 2: w->left = _screen.width - w->width; break; |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1187 |
default: w->left = 0; |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1188 |
} |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1189 |
SetDirtyBlocks(0, 0, _screen.width, w->height); // invalidate the whole top part |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1190 |
return w->left; |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1191 |
} |
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1192 |
|
0 | 1193 |
void RelocateAllWindows(int neww, int newh) |
1194 |
{ |
|
1195 |
Window *w; |
|
1196 |
||
1197 |
for(w=_windows; w!= _last_window ;w++) { |
|
1198 |
int left, top; |
|
1199 |
||
1200 |
if (w->window_class == WC_MAIN_WINDOW) { |
|
1201 |
ViewPort *vp = w->viewport; |
|
1202 |
vp->width = w->width = neww; |
|
1203 |
vp->height = w->height = newh; |
|
1204 |
vp->virtual_width = neww << vp->zoom; |
|
1205 |
vp->virtual_height = newh << vp->zoom; |
|
1206 |
continue; // don't modify top,left |
|
1207 |
} |
|
1208 |
||
1209 |
if (w->window_class == WC_MAIN_TOOLBAR) { |
|
1210 |
top = w->top; |
|
68
4051f3c8efa2
(svn r69) -Feature: align toolbar left/center/right patch (TrueLight)
darkvater
parents:
67
diff
changeset
|
1211 |
left = PositionMainToolbar(w); // changes toolbar orientation |
0 | 1212 |
} else if (w->window_class == WC_SELECT_GAME || w->window_class == WC_GAME_OPTIONS || w->window_class == WC_NETWORK_WINDOW){ |
1213 |
top = (newh - w->height) >> 1; |
|
1214 |
left = (neww - w->width) >> 1; |
|
1215 |
} else if (w->window_class == WC_NEWS_WINDOW) { |
|
1216 |
top = newh - w->height; |
|
1217 |
left = (neww - w->width) >> 1; |
|
1218 |
} else if (w->window_class == WC_STATUS_BAR) { |
|
1219 |
top = newh - w->height; |
|
1220 |
left = (neww - w->width) >> 1; |
|
1221 |
} else { |
|
1222 |
left = w->left; |
|
1223 |
if (left + (w->width>>1) >= neww) left = neww - w->width; |
|
1224 |
top = w->top; |
|
1225 |
if (top + (w->height>>1) >= newh) top = newh - w->height; |
|
1226 |
} |
|
1227 |
||
1228 |
if (w->viewport) { |
|
1229 |
w->viewport->left += left - w->left; |
|
1230 |
w->viewport->top += top - w->top; |
|
1231 |
} |
|
1232 |
||
1233 |
w->left = left; |
|
1234 |
w->top = top; |
|
1235 |
} |
|
1236 |
} |