]>
Commit | Line | Data |
---|---|---|
7c78e7c7 RR |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: window.cpp | |
3 | // Purpose: | |
4 | // Author: Robert Roebling | |
5 | // Created: 01/02/97 | |
6 | // Id: | |
7 | // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem | |
8 | // Licence: wxWindows licence | |
9 | ///////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | ||
12 | #ifdef __GNUG__ | |
13 | #pragma implementation "window.h" | |
14 | #endif | |
15 | ||
16 | #include "wx/defs.h" | |
17 | #include "wx/window.h" | |
18 | #include "wx/dc.h" | |
19 | #include "wx/frame.h" | |
20 | #include "wx/app.h" | |
21 | #include "wx/layout.h" | |
22 | #include "wx/utils.h" | |
23 | #include "wx/dialog.h" | |
24 | #include "wx/msgdlg.h" | |
25 | #include "wx/dcclient.h" | |
26 | #include "wx/dnd.h" | |
27 | #include "wx/mdi.h" | |
28 | #include "wx/notebook.h" | |
29 | #include "wx/statusbr.h" | |
30 | #include <math.h> | |
31 | ||
32 | //----------------------------------------------------------------------------- | |
33 | // data | |
34 | //----------------------------------------------------------------------------- | |
35 | ||
36 | extern wxList wxPendingDelete; | |
37 | extern wxList wxTopLevelWindows; | |
38 | ||
39 | //----------------------------------------------------------------------------- | |
40 | // wxWindow implementation | |
41 | //----------------------------------------------------------------------------- | |
42 | ||
43 | IMPLEMENT_DYNAMIC_CLASS(wxWindow,wxEvtHandler) | |
44 | ||
45 | BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler) | |
46 | EVT_SIZE(wxWindow::OnSize) | |
47 | EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged) | |
48 | EVT_INIT_DIALOG(wxWindow::OnInitDialog) | |
49 | EVT_IDLE(wxWindow::OnIdle) | |
50 | END_EVENT_TABLE() | |
51 | ||
52 | wxWindow::wxWindow() | |
53 | { | |
54 | m_parent = NULL; | |
55 | m_children.DeleteContents( FALSE ); | |
56 | m_x = 0; | |
57 | m_y = 0; | |
58 | m_width = 0; | |
59 | m_height = 0; | |
60 | m_retCode = 0; | |
61 | m_eventHandler = this; | |
62 | m_windowValidator = NULL; | |
63 | m_windowId = -1; | |
64 | m_cursor = new wxCursor( wxCURSOR_ARROW ); | |
65 | m_font = *wxSWISS_FONT; | |
66 | m_windowStyle = 0; | |
67 | m_windowName = "noname"; | |
68 | m_constraints = NULL; | |
69 | m_constraintsInvolvedIn = NULL; | |
70 | m_windowSizer = NULL; | |
71 | m_sizerParent = NULL; | |
72 | m_autoLayout = FALSE; | |
73 | m_pDropTarget = NULL; | |
74 | }; | |
75 | ||
76 | wxWindow::wxWindow( wxWindow *parent, wxWindowID id, | |
77 | const wxPoint &pos, const wxSize &size, | |
78 | long style, const wxString &name ) | |
79 | { | |
80 | Create( parent, id, pos, size, style, name ); | |
81 | }; | |
82 | ||
83 | bool wxWindow::Create( wxWindow *parent, wxWindowID id, | |
84 | const wxPoint &pos, const wxSize &size, | |
85 | long style, const wxString &name ) | |
86 | { | |
87 | return TRUE; | |
88 | }; | |
89 | ||
90 | wxWindow::~wxWindow(void) | |
91 | { | |
92 | DestroyChildren(); | |
93 | ||
94 | // delete m_cursor; | |
95 | ||
96 | DeleteRelatedConstraints(); | |
97 | if (m_constraints) | |
98 | { | |
99 | // This removes any dangling pointers to this window | |
100 | // in other windows' constraintsInvolvedIn lists. | |
101 | UnsetConstraints(m_constraints); | |
102 | delete m_constraints; | |
103 | m_constraints = NULL; | |
104 | } | |
105 | if (m_windowSizer) | |
106 | { | |
107 | delete m_windowSizer; | |
108 | m_windowSizer = NULL; | |
109 | } | |
110 | // If this is a child of a sizer, remove self from parent | |
111 | if (m_sizerParent) | |
112 | m_sizerParent->RemoveChild((wxWindow *)this); | |
113 | ||
114 | // Just in case the window has been Closed, but | |
115 | // we're then deleting immediately: don't leave | |
116 | // dangling pointers. | |
117 | wxPendingDelete.DeleteObject(this); | |
118 | ||
119 | // Just in case we've loaded a top-level window via | |
120 | // wxWindow::LoadNativeDialog but we weren't a dialog | |
121 | // class | |
122 | wxTopLevelWindows.DeleteObject(this); | |
123 | ||
124 | }; | |
125 | ||
126 | bool wxWindow::Close( bool force ) | |
127 | { | |
128 | wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId); | |
129 | event.SetEventObject(this); | |
130 | event.SetForce(force); | |
131 | ||
132 | return GetEventHandler()->ProcessEvent(event); | |
133 | }; | |
134 | ||
135 | bool wxWindow::Destroy(void) | |
136 | { | |
137 | m_hasVMT = FALSE; | |
138 | delete this; | |
139 | return TRUE; | |
140 | }; | |
141 | ||
142 | bool wxWindow::DestroyChildren(void) | |
143 | { | |
144 | if (GetChildren()) | |
145 | { | |
146 | wxNode *node; | |
147 | while ((node = GetChildren()->First()) != (wxNode *)NULL) | |
148 | { | |
149 | wxWindow *child; | |
150 | if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL) | |
151 | { | |
152 | delete child; | |
153 | if (GetChildren()->Member(child)) delete node; | |
154 | }; | |
155 | }; | |
156 | }; | |
157 | return TRUE; | |
158 | }; | |
159 | ||
160 | void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) ) | |
161 | { | |
162 | // are we to set fonts here ? | |
163 | }; | |
164 | ||
165 | void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags ) | |
166 | { | |
167 | ||
168 | int newX = x; | |
169 | int newY = y; | |
170 | int newW = width; | |
171 | int newH = height; | |
172 | ||
173 | if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING) | |
174 | { | |
175 | if (newX == -1) newX = m_x; | |
176 | if (newY == -1) newY = m_y; | |
177 | if (newW == -1) newW = m_width; | |
178 | if (newH == -1) newH = m_height; | |
179 | }; | |
180 | ||
181 | if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH) | |
182 | { | |
183 | if (newW == -1) newW = 80; | |
184 | }; | |
185 | ||
186 | if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT) | |
187 | { | |
188 | if (newH == -1) newH = 26; | |
189 | }; | |
190 | ||
191 | if ((m_x != newX) || (m_y != newY) || (!m_sizeSet)) | |
192 | { | |
193 | m_x = newX; | |
194 | m_y = newY; | |
195 | // | |
196 | }; | |
197 | if ((m_width != newW) || (m_height != newH) || (!m_sizeSet)) | |
198 | { | |
199 | m_width = newW; | |
200 | m_height = newH; | |
201 | // | |
202 | }; | |
203 | ||
204 | wxSizeEvent event( wxSize(m_width,m_height), GetId() ); | |
205 | event.SetEventObject( this ); | |
206 | ProcessEvent( event ); | |
207 | }; | |
208 | ||
209 | void wxWindow::SetSize( int width, int height ) | |
210 | { | |
211 | SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING ); | |
212 | }; | |
213 | ||
214 | void wxWindow::Move( int x, int y ) | |
215 | { | |
216 | SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING ); | |
217 | }; | |
218 | ||
219 | void wxWindow::GetSize( int *width, int *height ) const | |
220 | { | |
221 | if (width) (*width) = m_width; | |
222 | if (height) (*height) = m_height; | |
223 | }; | |
224 | ||
225 | void wxWindow::SetClientSize( int width, int height ) | |
226 | { | |
227 | }; | |
228 | ||
229 | void wxWindow::GetClientSize( int *width, int *height ) const | |
230 | { | |
231 | }; | |
232 | ||
233 | void wxWindow::GetPosition( int *x, int *y ) const | |
234 | { | |
235 | if (x) (*x) = m_x; | |
236 | if (y) (*y) = m_y; | |
237 | }; | |
238 | ||
239 | void wxWindow::ClientToScreen( int *x, int *y ) | |
240 | { | |
241 | }; | |
242 | ||
243 | void wxWindow::ScreenToClient( int *x, int *y ) | |
244 | { | |
245 | }; | |
246 | ||
247 | void wxWindow::Centre( int direction ) | |
248 | { | |
249 | }; | |
250 | ||
251 | void wxWindow::Fit(void) | |
252 | { | |
253 | int maxX = 0; | |
254 | int maxY = 0; | |
255 | wxNode *node = GetChildren()->First(); | |
256 | while ( node ) | |
257 | { | |
258 | wxWindow *win = (wxWindow *)node->Data(); | |
259 | int wx, wy, ww, wh; | |
260 | win->GetPosition(&wx, &wy); | |
261 | win->GetSize(&ww, &wh); | |
262 | if ( wx + ww > maxX ) | |
263 | maxX = wx + ww; | |
264 | if ( wy + wh > maxY ) | |
265 | maxY = wy + wh; | |
266 | ||
267 | node = node->Next(); | |
268 | } | |
269 | SetClientSize(maxX + 5, maxY + 10); | |
270 | }; | |
271 | ||
272 | void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) ) | |
273 | { | |
274 | //if (GetAutoLayout()) Layout(); | |
275 | }; | |
276 | ||
277 | bool wxWindow::Show( bool show ) | |
278 | { | |
279 | return TRUE; | |
280 | }; | |
281 | ||
282 | void wxWindow::Enable( bool enable ) | |
283 | { | |
284 | m_isEnabled = enable; | |
285 | }; | |
286 | ||
287 | void wxWindow::MakeModal( bool modal ) | |
288 | { | |
289 | } | |
290 | ||
291 | void wxWindow::SetFocus(void) | |
292 | { | |
293 | }; | |
294 | ||
295 | bool wxWindow::OnClose(void) | |
296 | { | |
297 | return TRUE; | |
298 | }; | |
299 | ||
300 | void wxWindow::AddChild( wxWindow *child ) | |
301 | { | |
302 | }; | |
303 | ||
304 | wxList *wxWindow::GetChildren(void) | |
305 | { | |
306 | return (&m_children); | |
307 | }; | |
308 | ||
309 | void wxWindow::RemoveChild( wxWindow *child ) | |
310 | { | |
311 | if (GetChildren()) | |
312 | GetChildren()->DeleteObject( child ); | |
313 | child->m_parent = NULL; | |
314 | }; | |
315 | ||
316 | void wxWindow::SetReturnCode( int retCode ) | |
317 | { | |
318 | m_retCode = retCode; | |
319 | }; | |
320 | ||
321 | int wxWindow::GetReturnCode(void) | |
322 | { | |
323 | return m_retCode; | |
324 | }; | |
325 | ||
326 | wxWindow *wxWindow::GetParent(void) | |
327 | { | |
328 | return m_parent; | |
329 | }; | |
330 | ||
331 | wxEvtHandler *wxWindow::GetEventHandler(void) | |
332 | { | |
333 | return m_eventHandler; | |
334 | }; | |
335 | ||
336 | void wxWindow::SetEventhandler( wxEvtHandler *handler ) | |
337 | { | |
338 | m_eventHandler = handler; | |
339 | }; | |
340 | ||
341 | wxValidator *wxWindow::GetValidator(void) | |
342 | { | |
343 | return m_windowValidator; | |
344 | }; | |
345 | ||
346 | void wxWindow::SetValidator( wxValidator *validator ) | |
347 | { | |
348 | m_windowValidator = validator; | |
349 | }; | |
350 | ||
351 | bool wxWindow::IsBeingDeleted(void) | |
352 | { | |
353 | return FALSE; | |
354 | }; | |
355 | ||
356 | void wxWindow::SetId( wxWindowID id ) | |
357 | { | |
358 | m_windowId = id; | |
359 | }; | |
360 | ||
361 | wxWindowID wxWindow::GetId(void) | |
362 | { | |
363 | return m_windowId; | |
364 | }; | |
365 | ||
366 | void wxWindow::SetCursor( const wxCursor &cursor ) | |
367 | { | |
368 | if (*m_cursor == cursor) return; | |
369 | (*m_cursor) = cursor; | |
370 | }; | |
371 | ||
372 | void wxWindow::Refresh( bool eraseBackground, const wxRect *rect ) | |
373 | { | |
374 | }; | |
375 | ||
376 | bool wxWindow::IsExposed( long x, long y ) | |
377 | { | |
378 | return (m_updateRegion.Contains( x, y ) != wxOutRegion ); | |
379 | }; | |
380 | ||
381 | bool wxWindow::IsExposed( long x, long y, long width, long height ) | |
382 | { | |
383 | return (m_updateRegion.Contains( x, y, width, height ) != wxOutRegion ); | |
384 | }; | |
385 | ||
386 | void wxWindow::Clear(void) | |
387 | { | |
388 | }; | |
389 | ||
390 | wxColour wxWindow::GetBackgroundColour(void) const | |
391 | { | |
392 | return m_backgroundColour; | |
393 | }; | |
394 | ||
395 | void wxWindow::SetBackgroundColour( const wxColour &colour ) | |
396 | { | |
397 | m_backgroundColour = colour; | |
398 | }; | |
399 | ||
400 | bool wxWindow::Validate(void) | |
401 | { | |
402 | wxNode *node = GetChildren()->First(); | |
403 | while (node) | |
404 | { | |
405 | wxWindow *child = (wxWindow *)node->Data(); | |
406 | if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this)) | |
407 | { return FALSE; } | |
408 | node = node->Next(); | |
409 | }; | |
410 | return TRUE; | |
411 | }; | |
412 | ||
413 | bool wxWindow::TransferDataToWindow(void) | |
414 | { | |
415 | wxNode *node = GetChildren()->First(); | |
416 | while (node) | |
417 | { | |
418 | wxWindow *child = (wxWindow *)node->Data(); | |
419 | if (child->GetValidator() && /* child->GetValidator()->Ok() && */ | |
420 | !child->GetValidator()->TransferToWindow() ) | |
421 | { | |
422 | wxMessageBox( "Application Error", "Could not transfer data to window", wxOK|wxICON_EXCLAMATION ); | |
423 | return FALSE; | |
424 | }; | |
425 | node = node->Next(); | |
426 | }; | |
427 | return TRUE; | |
428 | }; | |
429 | ||
430 | bool wxWindow::TransferDataFromWindow(void) | |
431 | { | |
432 | wxNode *node = GetChildren()->First(); | |
433 | while (node) | |
434 | { | |
435 | wxWindow *child = (wxWindow *)node->Data(); | |
436 | if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() ) | |
437 | { return FALSE; } | |
438 | node = node->Next(); | |
439 | } | |
440 | return TRUE; | |
441 | }; | |
442 | ||
443 | void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) ) | |
444 | { | |
445 | TransferDataToWindow(); | |
446 | }; | |
447 | ||
448 | void wxWindow::InitDialog(void) | |
449 | { | |
450 | wxInitDialogEvent event(GetId()); | |
451 | event.SetEventObject( this ); | |
452 | GetEventHandler()->ProcessEvent(event); | |
453 | }; | |
454 | ||
455 | void wxWindow::SetDropTarget( wxDropTarget *dropTarget ) | |
456 | { | |
457 | if (m_pDropTarget) | |
458 | { | |
459 | m_pDropTarget->UnregisterWidget( dnd_widget ); | |
460 | delete m_pDropTarget; | |
461 | }; | |
462 | m_pDropTarget = dropTarget; | |
463 | if (m_pDropTarget) | |
464 | { | |
465 | }; | |
466 | }; | |
467 | ||
468 | wxDropTarget *wxWindow::GetDropTarget() const | |
469 | { | |
470 | return m_pDropTarget; | |
471 | }; | |
472 | ||
473 | void wxWindow::SetFont( const wxFont &font ) | |
474 | { | |
475 | m_font = font; | |
476 | /* | |
477 | ... | |
478 | */ | |
479 | }; | |
480 | ||
481 | wxFont *wxWindow::GetFont(void) | |
482 | { | |
483 | return &m_font; | |
484 | }; | |
485 | ||
486 | void wxWindow::SetWindowStyleFlag( long flag ) | |
487 | { | |
488 | m_windowStyle = flag; | |
489 | }; | |
490 | ||
491 | long wxWindow::GetWindowStyleFlag(void) const | |
492 | { | |
493 | return m_windowStyle; | |
494 | }; | |
495 | ||
496 | void wxWindow::CaptureMouse(void) | |
497 | { | |
498 | }; | |
499 | ||
500 | void wxWindow::ReleaseMouse(void) | |
501 | { | |
502 | }; | |
503 | ||
504 | void wxWindow::SetTitle( const wxString &WXUNUSED(title) ) | |
505 | { | |
506 | }; | |
507 | ||
508 | wxString wxWindow::GetTitle(void) const | |
509 | { | |
510 | return (wxString&)m_windowName; | |
511 | }; | |
512 | ||
513 | wxString wxWindow::GetLabel(void) const | |
514 | { | |
515 | return GetTitle(); | |
516 | }; | |
517 | ||
518 | void wxWindow::SetName( const wxString &name ) | |
519 | { | |
520 | m_windowName = name; | |
521 | }; | |
522 | ||
523 | wxString wxWindow::GetName(void) const | |
524 | { | |
525 | return (wxString&)m_windowName; | |
526 | }; | |
527 | ||
528 | bool wxWindow::IsShown(void) const | |
529 | { | |
530 | return m_isShown; | |
531 | }; | |
532 | ||
533 | bool wxWindow::IsRetained(void) | |
534 | { | |
535 | return FALSE; | |
536 | }; | |
537 | ||
538 | wxWindow *wxWindow::FindWindow( long id ) | |
539 | { | |
540 | if (id == m_windowId) return this; | |
541 | wxNode *node = m_children.First(); | |
542 | while (node) | |
543 | { | |
544 | wxWindow *child = (wxWindow*)node->Data(); | |
545 | wxWindow *res = child->FindWindow( id ); | |
546 | if (res) return res; | |
547 | node = node->Next(); | |
548 | }; | |
549 | return NULL; | |
550 | }; | |
551 | ||
552 | wxWindow *wxWindow::FindWindow( const wxString& name ) | |
553 | { | |
554 | if (name == m_windowName) return this; | |
555 | wxNode *node = m_children.First(); | |
556 | while (node) | |
557 | { | |
558 | wxWindow *child = (wxWindow*)node->Data(); | |
559 | wxWindow *res = child->FindWindow( name ); | |
560 | if (res) return res; | |
561 | node = node->Next(); | |
562 | }; | |
563 | return NULL; | |
564 | }; | |
565 | ||
566 | void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible, | |
567 | int range, bool WXUNUSED(refresh) ) | |
568 | { | |
569 | }; | |
570 | ||
571 | void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) ) | |
572 | { | |
573 | }; | |
574 | ||
575 | int wxWindow::GetScrollThumb( int orient ) const | |
576 | { | |
577 | }; | |
578 | ||
579 | int wxWindow::GetScrollPos( int orient ) const | |
580 | { | |
581 | }; | |
582 | ||
583 | int wxWindow::GetScrollRange( int orient ) const | |
584 | { | |
585 | }; | |
586 | ||
587 | void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) ) | |
588 | { | |
589 | }; | |
590 | ||
591 | //------------------------------------------------------------------------------------- | |
592 | // Layout | |
593 | //------------------------------------------------------------------------------------- | |
594 | ||
595 | wxLayoutConstraints *wxWindow::GetConstraints(void) const | |
596 | { | |
597 | return m_constraints; | |
598 | }; | |
599 | ||
600 | void wxWindow::SetConstraints( wxLayoutConstraints *constraints ) | |
601 | { | |
602 | if (m_constraints) | |
603 | { | |
604 | UnsetConstraints(m_constraints); | |
605 | delete m_constraints; | |
606 | } | |
607 | m_constraints = constraints; | |
608 | if (m_constraints) | |
609 | { | |
610 | // Make sure other windows know they're part of a 'meaningful relationship' | |
611 | if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this)) | |
612 | m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this); | |
613 | if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this)) | |
614 | m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this); | |
615 | if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this)) | |
616 | m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this); | |
617 | if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this)) | |
618 | m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this); | |
619 | if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this)) | |
620 | m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this); | |
621 | if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this)) | |
622 | m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this); | |
623 | if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this)) | |
624 | m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this); | |
625 | if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this)) | |
626 | m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this); | |
627 | } | |
628 | ; | |
629 | } | |
630 | ; | |
631 | ||
632 | void wxWindow::SetAutoLayout( bool autoLayout ) | |
633 | { | |
634 | m_autoLayout = autoLayout; | |
635 | }; | |
636 | ||
637 | bool wxWindow::GetAutoLayout(void) const | |
638 | { | |
639 | return m_autoLayout; | |
640 | }; | |
641 | ||
642 | wxSizer *wxWindow::GetSizer(void) const | |
643 | { | |
644 | return m_windowSizer; | |
645 | }; | |
646 | ||
647 | void wxWindow::SetSizerParent( wxWindow *win ) | |
648 | { | |
649 | m_sizerParent = win; | |
650 | }; | |
651 | ||
652 | wxWindow *wxWindow::GetSizerParent(void) const | |
653 | { | |
654 | return m_sizerParent; | |
655 | }; | |
656 | ||
657 | // This removes any dangling pointers to this window | |
658 | // in other windows' constraintsInvolvedIn lists. | |
659 | void wxWindow::UnsetConstraints(wxLayoutConstraints *c) | |
660 | { | |
661 | if (c) | |
662 | { | |
663 | if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this)) | |
664 | c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this); | |
665 | if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this)) | |
666 | c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this); | |
667 | if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this)) | |
668 | c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this); | |
669 | if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this)) | |
670 | c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this); | |
671 | if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this)) | |
672 | c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this); | |
673 | if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this)) | |
674 | c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this); | |
675 | if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this)) | |
676 | c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this); | |
677 | if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this)) | |
678 | c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this); | |
679 | } | |
680 | } | |
681 | ||
682 | // Back-pointer to other windows we're involved with, so if we delete | |
683 | // this window, we must delete any constraints we're involved with. | |
684 | void wxWindow::AddConstraintReference(wxWindow *otherWin) | |
685 | { | |
686 | if (!m_constraintsInvolvedIn) | |
687 | m_constraintsInvolvedIn = new wxList; | |
688 | if (!m_constraintsInvolvedIn->Member(otherWin)) | |
689 | m_constraintsInvolvedIn->Append(otherWin); | |
690 | } | |
691 | ||
692 | // REMOVE back-pointer to other windows we're involved with. | |
693 | void wxWindow::RemoveConstraintReference(wxWindow *otherWin) | |
694 | { | |
695 | if (m_constraintsInvolvedIn) | |
696 | m_constraintsInvolvedIn->DeleteObject(otherWin); | |
697 | } | |
698 | ||
699 | // Reset any constraints that mention this window | |
700 | void wxWindow::DeleteRelatedConstraints(void) | |
701 | { | |
702 | if (m_constraintsInvolvedIn) | |
703 | { | |
704 | wxNode *node = m_constraintsInvolvedIn->First(); | |
705 | while (node) | |
706 | { | |
707 | wxWindow *win = (wxWindow *)node->Data(); | |
708 | wxNode *next = node->Next(); | |
709 | wxLayoutConstraints *constr = win->GetConstraints(); | |
710 | ||
711 | // Reset any constraints involving this window | |
712 | if (constr) | |
713 | { | |
714 | constr->left.ResetIfWin((wxWindow *)this); | |
715 | constr->top.ResetIfWin((wxWindow *)this); | |
716 | constr->right.ResetIfWin((wxWindow *)this); | |
717 | constr->bottom.ResetIfWin((wxWindow *)this); | |
718 | constr->width.ResetIfWin((wxWindow *)this); | |
719 | constr->height.ResetIfWin((wxWindow *)this); | |
720 | constr->centreX.ResetIfWin((wxWindow *)this); | |
721 | constr->centreY.ResetIfWin((wxWindow *)this); | |
722 | } | |
723 | delete node; | |
724 | node = next; | |
725 | } | |
726 | delete m_constraintsInvolvedIn; | |
727 | m_constraintsInvolvedIn = NULL; | |
728 | } | |
729 | } | |
730 | ||
731 | void wxWindow::SetSizer(wxSizer *sizer) | |
732 | { | |
733 | m_windowSizer = sizer; | |
734 | if (sizer) | |
735 | sizer->SetSizerParent((wxWindow *)this); | |
736 | } | |
737 | ||
738 | /* | |
739 | * New version | |
740 | */ | |
741 | ||
742 | bool wxWindow::Layout(void) | |
743 | { | |
744 | if (GetConstraints()) | |
745 | { | |
746 | int w, h; | |
747 | GetClientSize(&w, &h); | |
748 | GetConstraints()->width.SetValue(w); | |
749 | GetConstraints()->height.SetValue(h); | |
750 | } | |
751 | ||
752 | // If top level (one sizer), evaluate the sizer's constraints. | |
753 | if (GetSizer()) | |
754 | { | |
755 | int noChanges; | |
756 | GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated | |
757 | GetSizer()->LayoutPhase1(&noChanges); | |
758 | GetSizer()->LayoutPhase2(&noChanges); | |
759 | GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes | |
760 | return TRUE; | |
761 | } | |
762 | else | |
763 | { | |
764 | // Otherwise, evaluate child constraints | |
765 | ResetConstraints(); // Mark all constraints as unevaluated | |
766 | DoPhase(1); // Just one phase need if no sizers involved | |
767 | DoPhase(2); | |
768 | SetConstraintSizes(); // Recursively set the real window sizes | |
769 | } | |
770 | return TRUE; | |
771 | } | |
772 | ||
773 | ||
774 | // Do a phase of evaluating constraints: | |
775 | // the default behaviour. wxSizers may do a similar | |
776 | // thing, but also impose their own 'constraints' | |
777 | // and order the evaluation differently. | |
778 | bool wxWindow::LayoutPhase1(int *noChanges) | |
779 | { | |
780 | wxLayoutConstraints *constr = GetConstraints(); | |
781 | if (constr) | |
782 | { | |
783 | return constr->SatisfyConstraints((wxWindow *)this, noChanges); | |
784 | } | |
785 | else | |
786 | return TRUE; | |
787 | } | |
788 | ||
789 | bool wxWindow::LayoutPhase2(int *noChanges) | |
790 | { | |
791 | *noChanges = 0; | |
792 | ||
793 | // Layout children | |
794 | DoPhase(1); | |
795 | DoPhase(2); | |
796 | return TRUE; | |
797 | } | |
798 | ||
799 | // Do a phase of evaluating child constraints | |
800 | bool wxWindow::DoPhase(int phase) | |
801 | { | |
802 | int noIterations = 0; | |
803 | int maxIterations = 500; | |
804 | int noChanges = 1; | |
805 | int noFailures = 0; | |
806 | wxList succeeded; | |
807 | while ((noChanges > 0) && (noIterations < maxIterations)) | |
808 | { | |
809 | noChanges = 0; | |
810 | noFailures = 0; | |
811 | wxNode *node = GetChildren()->First(); | |
812 | while (node) | |
813 | { | |
814 | wxWindow *child = (wxWindow *)node->Data(); | |
815 | if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog))) | |
816 | { | |
817 | wxLayoutConstraints *constr = child->GetConstraints(); | |
818 | if (constr) | |
819 | { | |
820 | if (succeeded.Member(child)) | |
821 | { | |
822 | } | |
823 | else | |
824 | { | |
825 | int tempNoChanges = 0; | |
826 | bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ; | |
827 | noChanges += tempNoChanges; | |
828 | if (success) | |
829 | { | |
830 | succeeded.Append(child); | |
831 | } | |
832 | } | |
833 | } | |
834 | } | |
835 | node = node->Next(); | |
836 | } | |
837 | noIterations ++; | |
838 | } | |
839 | return TRUE; | |
840 | } | |
841 | ||
842 | void wxWindow::ResetConstraints(void) | |
843 | { | |
844 | wxLayoutConstraints *constr = GetConstraints(); | |
845 | if (constr) | |
846 | { | |
847 | constr->left.SetDone(FALSE); | |
848 | constr->top.SetDone(FALSE); | |
849 | constr->right.SetDone(FALSE); | |
850 | constr->bottom.SetDone(FALSE); | |
851 | constr->width.SetDone(FALSE); | |
852 | constr->height.SetDone(FALSE); | |
853 | constr->centreX.SetDone(FALSE); | |
854 | constr->centreY.SetDone(FALSE); | |
855 | } | |
856 | wxNode *node = GetChildren()->First(); | |
857 | while (node) | |
858 | { | |
859 | wxWindow *win = (wxWindow *)node->Data(); | |
860 | if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog))) | |
861 | win->ResetConstraints(); | |
862 | node = node->Next(); | |
863 | } | |
864 | } | |
865 | ||
866 | // Need to distinguish between setting the 'fake' size for | |
867 | // windows and sizers, and setting the real values. | |
868 | void wxWindow::SetConstraintSizes(bool recurse) | |
869 | { | |
870 | wxLayoutConstraints *constr = GetConstraints(); | |
871 | if (constr && constr->left.GetDone() && constr->right.GetDone() && | |
872 | constr->width.GetDone() && constr->height.GetDone()) | |
873 | { | |
874 | int x = constr->left.GetValue(); | |
875 | int y = constr->top.GetValue(); | |
876 | int w = constr->width.GetValue(); | |
877 | int h = constr->height.GetValue(); | |
878 | ||
879 | // If we don't want to resize this window, just move it... | |
880 | if ((constr->width.GetRelationship() != wxAsIs) || | |
881 | (constr->height.GetRelationship() != wxAsIs)) | |
882 | { | |
883 | // Calls Layout() recursively. AAAGH. How can we stop that. | |
884 | // Simply take Layout() out of non-top level OnSizes. | |
885 | SizerSetSize(x, y, w, h); | |
886 | } | |
887 | else | |
888 | { | |
889 | SizerMove(x, y); | |
890 | } | |
891 | } | |
892 | else if (constr) | |
893 | { | |
894 | char *windowClass = this->GetClassInfo()->GetClassName(); | |
895 | ||
896 | wxString winName; | |
897 | if (GetName() == "") | |
898 | winName = "unnamed"; | |
899 | else | |
900 | winName = GetName(); | |
901 | wxDebugMsg("Constraint(s) not satisfied for window of type %s, name %s:\n", (const char *)windowClass, (const char *)winName); | |
902 | if (!constr->left.GetDone()) | |
903 | wxDebugMsg(" unsatisfied 'left' constraint.\n"); | |
904 | if (!constr->right.GetDone()) | |
905 | wxDebugMsg(" unsatisfied 'right' constraint.\n"); | |
906 | if (!constr->width.GetDone()) | |
907 | wxDebugMsg(" unsatisfied 'width' constraint.\n"); | |
908 | if (!constr->height.GetDone()) | |
909 | wxDebugMsg(" unsatisfied 'height' constraint.\n"); | |
910 | wxDebugMsg("Please check constraints: try adding AsIs() constraints.\n"); | |
911 | } | |
912 | ||
913 | if (recurse) | |
914 | { | |
915 | wxNode *node = GetChildren()->First(); | |
916 | while (node) | |
917 | { | |
918 | wxWindow *win = (wxWindow *)node->Data(); | |
919 | if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog))) | |
920 | win->SetConstraintSizes(); | |
921 | node = node->Next(); | |
922 | } | |
923 | } | |
924 | } | |
925 | ||
926 | // This assumes that all sizers are 'on' the same | |
927 | // window, i.e. the parent of this window. | |
928 | void wxWindow::TransformSizerToActual(int *x, int *y) const | |
929 | { | |
930 | if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) || | |
931 | m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) ) | |
932 | return; | |
933 | ||
934 | int xp, yp; | |
935 | m_sizerParent->GetPosition(&xp, &yp); | |
936 | m_sizerParent->TransformSizerToActual(&xp, &yp); | |
937 | *x += xp; | |
938 | *y += yp; | |
939 | } | |
940 | ||
941 | void wxWindow::SizerSetSize(int x, int y, int w, int h) | |
942 | { | |
943 | int xx = x; | |
944 | int yy = y; | |
945 | TransformSizerToActual(&xx, &yy); | |
946 | SetSize(xx, yy, w, h); | |
947 | } | |
948 | ||
949 | void wxWindow::SizerMove(int x, int y) | |
950 | { | |
951 | int xx = x; | |
952 | int yy = y; | |
953 | TransformSizerToActual(&xx, &yy); | |
954 | Move(xx, yy); | |
955 | } | |
956 | ||
957 | // Only set the size/position of the constraint (if any) | |
958 | void wxWindow::SetSizeConstraint(int x, int y, int w, int h) | |
959 | { | |
960 | wxLayoutConstraints *constr = GetConstraints(); | |
961 | if (constr) | |
962 | { | |
963 | if (x != -1) | |
964 | { | |
965 | constr->left.SetValue(x); | |
966 | constr->left.SetDone(TRUE); | |
967 | } | |
968 | if (y != -1) | |
969 | { | |
970 | constr->top.SetValue(y); | |
971 | constr->top.SetDone(TRUE); | |
972 | } | |
973 | if (w != -1) | |
974 | { | |
975 | constr->width.SetValue(w); | |
976 | constr->width.SetDone(TRUE); | |
977 | } | |
978 | if (h != -1) | |
979 | { | |
980 | constr->height.SetValue(h); | |
981 | constr->height.SetDone(TRUE); | |
982 | } | |
983 | } | |
984 | } | |
985 | ||
986 | void wxWindow::MoveConstraint(int x, int y) | |
987 | { | |
988 | wxLayoutConstraints *constr = GetConstraints(); | |
989 | if (constr) | |
990 | { | |
991 | if (x != -1) | |
992 | { | |
993 | constr->left.SetValue(x); | |
994 | constr->left.SetDone(TRUE); | |
995 | } | |
996 | if (y != -1) | |
997 | { | |
998 | constr->top.SetValue(y); | |
999 | constr->top.SetDone(TRUE); | |
1000 | } | |
1001 | } | |
1002 | } | |
1003 | ||
1004 | void wxWindow::GetSizeConstraint(int *w, int *h) const | |
1005 | { | |
1006 | wxLayoutConstraints *constr = GetConstraints(); | |
1007 | if (constr) | |
1008 | { | |
1009 | *w = constr->width.GetValue(); | |
1010 | *h = constr->height.GetValue(); | |
1011 | } | |
1012 | else | |
1013 | GetSize(w, h); | |
1014 | } | |
1015 | ||
1016 | void wxWindow::GetClientSizeConstraint(int *w, int *h) const | |
1017 | { | |
1018 | wxLayoutConstraints *constr = GetConstraints(); | |
1019 | if (constr) | |
1020 | { | |
1021 | *w = constr->width.GetValue(); | |
1022 | *h = constr->height.GetValue(); | |
1023 | } | |
1024 | else | |
1025 | GetClientSize(w, h); | |
1026 | } | |
1027 | ||
1028 | void wxWindow::GetPositionConstraint(int *x, int *y) const | |
1029 | { | |
1030 | wxLayoutConstraints *constr = GetConstraints(); | |
1031 | if (constr) | |
1032 | { | |
1033 | *x = constr->left.GetValue(); | |
1034 | *y = constr->top.GetValue(); | |
1035 | } | |
1036 | else | |
1037 | GetPosition(x, y); | |
1038 | } | |
1039 | ||
1040 | bool wxWindow::AcceptsFocus() const | |
1041 | { | |
1042 | return IsEnabled() && IsShown(); | |
1043 | } | |
1044 | ||
1045 | void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event) ) | |
1046 | { | |
1047 | UpdateWindowUI(); | |
1048 | } |