]> git.saurik.com Git - wxWidgets.git/blob - src/mgl/window.cpp
added new text event macros description
[wxWidgets.git] / src / mgl / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mgl/window.cpp
3 // Purpose: wxWindow
4 // Author: Vaclav Slavik
5 // (based on GTK & MSW implementations)
6 // RCS-ID: $Id$
7 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
8 // Licence: wxWindows license
9 /////////////////////////////////////////////////////////////////////////////
10
11 // ===========================================================================
12 // declarations
13 // ===========================================================================
14
15 // ---------------------------------------------------------------------------
16 // headers
17 // ---------------------------------------------------------------------------
18
19 #ifdef __GNUG__
20 #pragma implementation "window.h"
21 #endif
22
23 // For compilers that support precompilation, includes "wx.h".
24 #include "wx/wxprec.h"
25
26 #ifdef __BORLANDC__
27 #pragma hdrstop
28 #endif
29
30 #ifndef WX_PRECOMP
31 #include "wx/window.h"
32 #include "wx/accel.h"
33 #include "wx/setup.h"
34 #include "wx/dc.h"
35 #include "wx/dcclient.h"
36 #include "wx/utils.h"
37 #include "wx/app.h"
38 #include "wx/panel.h"
39 #include "wx/caret.h"
40 #endif
41
42 #if wxUSE_DRAG_AND_DROP
43 #include "wx/dnd.h"
44 #endif
45
46 #include "wx/log.h"
47 #include "wx/sysopt.h"
48 #include "wx/mgl/private.h"
49 #include "wx/intl.h"
50 #include "wx/dcscreen.h"
51
52 #include <mgraph.hpp>
53
54 #if wxUSE_TOOLTIPS
55 #include "wx/tooltip.h"
56 #endif
57
58 // ---------------------------------------------------------------------------
59 // global variables
60 // ---------------------------------------------------------------------------
61
62 // MGL window manager and associated DC.
63 winmng_t *g_winMng = NULL;
64 MGLDevCtx *g_displayDC = NULL;
65
66 extern wxList WXDLLEXPORT wxPendingDelete;
67 // FIXME_MGL -- ???
68
69 // the window that has keyboard+joystick focus:
70 static wxWindowMGL *g_focusedWindow = NULL;
71 // the window that is currently under mouse cursor:
72 static wxWindowMGL *g_windowUnderMouse = NULL;
73
74 // ---------------------------------------------------------------------------
75 // constants
76 // ---------------------------------------------------------------------------
77
78 // Custom identifiers used to distinguish between various event handlers
79 // and capture handlers passed to MGL_wm
80 enum
81 {
82 wxMGL_CAPTURE_MOUSE = 1,
83 wxMGL_CAPTURE_KEYB = 2
84 };
85
86
87 // ---------------------------------------------------------------------------
88 // private functions
89 // ---------------------------------------------------------------------------
90
91 // wxCreateMGL_WM creates MGL display DC and associates it with winmng_t
92 // structure. Dimensions and depth of the DC are fetched from wxSystemOptions
93 // object.
94 // This function is *not* called from wxApp's initialization but rather at
95 // the time when WM is needed, i.e. when first wxWindow is created. This
96 // has two important effects:
97 // a) it is possible to write windowless wxMGL apps
98 // b) the app has plenty of time in wxApp::OnInit to feed wxSystemOptions
99 // with desired settings
100
101 // FIXME_MGL -- move to app.cpp??
102 static void wxDesktopPainter(window_t *wnd, MGLDC *dc)
103 {
104 // FIXME_MGL - for now...
105 MGL_setColorRGB(0x63, 0x63, 0x96);
106 MGL_fillRectCoord(0, 0, wnd->width, wnd->height);
107 }
108
109
110 bool wxCreateMGL_WM()
111 {
112 int mode;
113 int width = 640, height = 480, depth = 16;
114 int refresh = MGL_DEFAULT_REFRESH;
115
116 #if wxUSE_SYSTEM_OPTIONS
117 // FIXME_MGL -- so what is The Proper Way?
118 if ( wxSystemOptions::HasOption(wxT("mgl.screen-width") )
119 width = wxSystemOptions::GetOptionInt(wxT("mgl.screen-width"));
120 if ( wxSystemOptions::HasOption(wxT("mgl.screen-height") )
121 height = wxSystemOptions::GetOptionInt(wxT("mgl.screen-height"));
122 if ( wxSystemOptions::HasOption(wxT("mgl.screen-depth") )
123 depth = wxSystemOptions::GetOptionInt(wxT("mgl.screen-depth"));
124 if ( wxSystemOptions::HasOption(wxT("mgl.screen-refresh") )
125 refresh = wxSystemOptions::GetOptionInt(wxT("mgl.screen-refresh"));
126 #endif
127
128 mode = MGL_findMode(width, height, depth);
129 if ( mode == -1 )
130 {
131 wxLogWarning(_("Mode %ix%i-%i not available, falling back to default mode."), width, height, depth);
132 mode = 0; // always available
133 }
134 g_displayDC = new MGLDisplayDC(mode, 1, refresh);
135 if ( !g_displayDC->isValid() )
136 {
137 delete g_displayDC;
138 g_displayDC = NULL;
139 return FALSE;
140 }
141
142 g_winMng = MGL_wmCreate(g_displayDC->getDC());
143 if (!g_winMng)
144 return FALSE;
145
146 MGL_wmSetWindowPainter(MGL_wmGetRootWindow(g_winMng), wxDesktopPainter);
147
148 return TRUE;
149 }
150
151 void wxDestroyMGL_WM()
152 {
153 if ( g_winMng )
154 {
155 MGL_wmDestroy(g_winMng);
156 g_winMng = NULL;
157 }
158 if ( g_displayDC )
159 {
160 delete g_displayDC;
161 g_displayDC = NULL;
162 }
163 }
164
165 // ---------------------------------------------------------------------------
166 // MGL_WM hooks:
167 // ---------------------------------------------------------------------------
168
169 static void wxWindowPainter(window_t *wnd, MGLDC *dc)
170 {
171 wxWindowMGL *w = (wxWindow*) wnd->userData;
172 if (w)
173 {
174 MGLDevCtx ctx(dc);
175 w->HandlePaint(&ctx);
176 }
177 // FIXME_MGL -- root window should be a regular window so that
178 // enter/leave and activate/deactivate events work correctly
179 }
180
181 static ibool wxWindowMouseHandler(window_t *wnd, event_t *e)
182 {
183 wxWindowMGL *win = (wxWindowMGL*)MGL_wmGetWindowUserData(wnd);
184 wxPoint where = win->ScreenToClient(wxPoint(e->where_x, e->where_y));
185
186 wxEventType type = wxEVT_NULL;
187 wxMouseEvent event;
188 event.SetEventObject(win);
189 event.SetTimestamp(e->when);
190 event.m_x = where.x;
191 event.m_y = where.y;
192 event.m_shiftDown = e->modifiers & EVT_SHIFTKEY;
193 event.m_controlDown = e->modifiers & EVT_CTRLSTATE;
194 event.m_altDown = e->modifiers & EVT_LEFTALT;
195 event.m_metaDown = e->modifiers & EVT_RIGHTALT;
196 event.m_leftDown = e->modifiers & EVT_LEFTBUT;
197 event.m_middleDown = e->modifiers & EVT_MIDDLEBUT;
198 event.m_rightDown = e->modifiers & EVT_RIGHTBUT;
199
200 switch (e->what)
201 {
202 case EVT_MOUSEDOWN:
203 if ( e->message & EVT_LEFTBMASK )
204 type = (e->message & EVT_DBLCLICK) ?
205 wxEVT_LEFT_DCLICK : wxEVT_LEFT_DOWN;
206 else if ( e->message & EVT_MIDDLEBMASK )
207 type = (e->message & EVT_DBLCLICK) ?
208 wxEVT_MIDDLE_DCLICK : wxEVT_MIDDLE_DOWN;
209 else if ( e->message & EVT_RIGHTBMASK )
210 type = (e->message & EVT_DBLCLICK) ?
211 wxEVT_RIGHT_DCLICK : wxEVT_RIGHT_DOWN;
212 break;
213
214 case EVT_MOUSEUP:
215 if ( e->message & EVT_LEFTBMASK )
216 type = wxEVT_LEFT_UP;
217 else if ( e->message & EVT_MIDDLEBMASK )
218 type = wxEVT_MIDDLE_UP;
219 else if ( e->message & EVT_RIGHTBMASK )
220 type = wxEVT_RIGHT_UP;
221 break;
222
223 case EVT_MOUSEMOVE:
224 if ( win != g_windowUnderMouse )
225 {
226 if ( g_windowUnderMouse )
227 {
228 wxMouseEvent event2(event);
229 wxPoint where2 = g_windowUnderMouse->ScreenToClient(
230 wxPoint(e->where_x, e->where_y));
231 event2.m_x = where2.x;
232 event2.m_y = where2.y;
233 event2.SetEventObject(g_windowUnderMouse);
234 event2.SetEventType(wxEVT_LEAVE_WINDOW);
235 g_windowUnderMouse->GetEventHandler()->ProcessEvent(event2);
236 }
237
238 wxMouseEvent event3(event);
239 event3.SetEventType(wxEVT_ENTER_WINDOW);
240 win->GetEventHandler()->ProcessEvent(event3);
241
242 g_windowUnderMouse = win;
243 }
244
245 type = wxEVT_MOTION;
246 break;
247
248 default:
249 break;
250 }
251
252 if ( type == wxEVT_NULL )
253 {
254 return FALSE;
255 }
256 else
257 {
258 event.SetEventType(type);
259 return win->GetEventHandler()->ProcessEvent(event);
260 }
261 }
262
263 static ibool wxWindowKeybHandler(window_t *wnd, event_t *e)
264 {
265 // FIXME_MGL
266 return FALSE;
267 }
268
269 static ibool wxWindowJoyHandler(window_t *wnd, event_t *e)
270 {
271 // FIXME_MGL
272 return FALSE;
273 }
274
275 // ---------------------------------------------------------------------------
276 // event tables
277 // ---------------------------------------------------------------------------
278
279 // in wxUniv this class is abstract because it doesn't have DoPopupMenu()
280 IMPLEMENT_ABSTRACT_CLASS(wxWindowMGL, wxWindowBase)
281
282 BEGIN_EVENT_TABLE(wxWindowMGL, wxWindowBase)
283 END_EVENT_TABLE()
284
285 // ===========================================================================
286 // implementation
287 // ===========================================================================
288
289 // ----------------------------------------------------------------------------
290 // constructors and such
291 // ----------------------------------------------------------------------------
292
293 void wxWindowMGL::Init()
294 {
295 // generic:
296 InitBase();
297
298 // mgl specific:
299 m_wnd = NULL;
300 m_isShown = TRUE;
301 m_isBeingDeleted = FALSE;
302 m_isEnabled = TRUE;
303 m_frozen = FALSE;
304 m_paintMGLDC = NULL;
305 }
306
307 // Destructor
308 wxWindowMGL::~wxWindowMGL()
309 {
310 m_isBeingDeleted = TRUE;
311
312 if ( g_focusedWindow == this )
313 KillFocus();
314 if ( g_windowUnderMouse == this )
315 g_windowUnderMouse = NULL;
316
317 // VS: destroy children first and _then_ detach *this from its parent.
318 // If we'd do it the other way around, children wouldn't be able
319 // find their parent frame (see above).
320 DestroyChildren();
321
322 if ( m_parent )
323 m_parent->RemoveChild(this);
324
325 if ( m_wnd )
326 MGL_wmDestroyWindow(m_wnd);
327 }
328
329 // real construction (Init() must have been called before!)
330 bool wxWindowMGL::Create(wxWindow *parent,
331 wxWindowID id,
332 const wxPoint& pos,
333 const wxSize& size,
334 long style,
335 const wxString& name)
336 {
337 // FIXME_MGL -- temporary!
338 //wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") );
339
340 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
341 return FALSE;
342
343 if ( parent ) // FIXME_MGL temporary
344 parent->AddChild(this);
345 else
346 m_isShown=FALSE;// FIXME_MGL -- temporary, simulates wxTLW/wxFrame
347
348 if ( style & wxPOPUP_WINDOW )
349 {
350 // it is created hidden as other top level windows
351 m_isShown = FALSE;
352 }
353
354 int x, y, w, h;
355 x = pos.x, y = pos.y;
356 if ( x == -1 )
357 x = 0; // FIXME_MGL, something better, see GTK+
358 if ( y == -1 )
359 y = 0; // FIXME_MGL, something better, see GTK+
360 w = WidthDefault(size.x);
361 h = HeightDefault(size.y);
362
363 m_wnd = MGL_wmCreateWindow(g_winMng,
364 parent ? parent->GetHandle() : NULL,
365 x, y, w, h);
366
367 MGL_wmSetWindowUserData(m_wnd, (void*) this);
368 MGL_wmSetWindowPainter(m_wnd, wxWindowPainter);
369 MGL_wmShowWindow(m_wnd, m_isShown);
370 MGL_wmSetWindowCursor(m_wnd, *wxSTANDARD_CURSOR->GetMGLCursor());
371
372 MGL_wmPushWindowEventHandler(m_wnd, wxWindowMouseHandler, EVT_MOUSEEVT, 0);
373 MGL_wmPushWindowEventHandler(m_wnd, wxWindowKeybHandler, EVT_KEYEVT, 0);
374 MGL_wmPushWindowEventHandler(m_wnd, wxWindowJoyHandler, EVT_JOYEVT, 0);
375
376 return TRUE;
377 }
378
379 // ---------------------------------------------------------------------------
380 // basic operations
381 // ---------------------------------------------------------------------------
382
383 void wxWindowMGL::SetFocus()
384 {
385 if (g_focusedWindow)
386 g_focusedWindow->KillFocus();
387
388 g_focusedWindow = this;
389
390 MGL_wmCaptureEvents(GetHandle(), EVT_KEYEVT|EVT_JOYEVT, wxMGL_CAPTURE_KEYB);
391
392 #if wxUSE_CARET
393 // caret needs to be informed about focus change
394 wxCaret *caret = GetCaret();
395 if (caret)
396 caret->OnSetFocus();
397 #endif // wxUSE_CARET
398
399 if ( IsTopLevel() )
400 {
401 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, GetId());
402 event.SetEventObject(this);
403 GetEventHandler()->ProcessEvent(event);
404 }
405
406 wxFocusEvent event(wxEVT_SET_FOCUS, GetId());
407 event.SetEventObject(this);
408 GetEventHandler()->ProcessEvent(event);
409 }
410
411 void wxWindowMGL::KillFocus()
412 {
413 if ( g_focusedWindow != this ) return;
414 g_focusedWindow = NULL;
415
416 if ( m_isBeingDeleted ) return;
417
418 MGL_wmUncaptureEvents(GetHandle(), wxMGL_CAPTURE_KEYB);
419
420 #if wxUSE_CARET
421 // caret needs to be informed about focus change
422 wxCaret *caret = GetCaret();
423 if ( caret )
424 caret->OnKillFocus();
425 #endif // wxUSE_CARET
426
427 if ( IsTopLevel() )
428 {
429 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId());
430 event.SetEventObject(this);
431 GetEventHandler()->ProcessEvent(event);
432 }
433
434 wxFocusEvent event(wxEVT_KILL_FOCUS, GetId());
435 event.SetEventObject(this);
436 GetEventHandler()->ProcessEvent(event);
437 }
438
439 // ----------------------------------------------------------------------------
440 // this wxWindowBase function is implemented here (in platform-specific file)
441 // because it is static and so couldn't be made virtual
442 // ----------------------------------------------------------------------------
443 wxWindow *wxWindowBase::FindFocus()
444 {
445 return (wxWindow*)g_focusedWindow;
446 }
447
448 bool wxWindowMGL::Show(bool show)
449 {
450 if ( !wxWindowBase::Show(show) )
451 return FALSE;
452
453 MGL_wmShowWindow(m_wnd, show);
454 return TRUE;
455 }
456
457 // Raise the window to the top of the Z order
458 void wxWindowMGL::Raise()
459 {
460 MGL_wmRaiseWindow(m_wnd);
461 }
462
463 // Lower the window to the bottom of the Z order
464 void wxWindowMGL::Lower()
465 {
466 MGL_wmLowerWindow(m_wnd);
467 }
468
469 void wxWindowMGL::CaptureMouse()
470 {
471 MGL_wmCaptureEvents(m_wnd, EVT_MOUSEEVT, wxMGL_CAPTURE_MOUSE);
472 }
473
474 void wxWindowMGL::ReleaseMouse()
475 {
476 MGL_wmUncaptureEvents(m_wnd, wxMGL_CAPTURE_MOUSE);
477 }
478
479 /* static */ wxWindow *wxWindowBase::GetCapture()
480 {
481 for (captureentry_t *c = g_winMng->capturedEvents; c; c = c->next)
482 {
483 if ( c->id == wxMGL_CAPTURE_MOUSE )
484 return (wxWindow*)c->wnd->userData;
485 }
486 return NULL;
487 }
488
489 bool wxWindowMGL::SetCursor(const wxCursor& cursor)
490 {
491 if ( !wxWindowBase::SetCursor(cursor) )
492 {
493 // no change
494 return FALSE;
495 }
496
497 if ( m_cursor.Ok() )
498 MGL_wmSetWindowCursor(m_wnd, *m_cursor.GetMGLCursor());
499 else
500 MGL_wmSetWindowCursor(m_wnd, *wxSTANDARD_CURSOR->GetMGLCursor());
501
502 // FIXME_MGL -- should it set children's cursor or not?!
503
504 return TRUE;
505 }
506
507 void wxWindowMGL::WarpPointer(int x, int y)
508 {
509 ClientToScreen(&x, &y);
510 EVT_setMousePos(x, y);
511 }
512
513 #if WXWIN_COMPATIBILITY
514 // If nothing defined for this, try the parent.
515 // E.g. we may be a button loaded from a resource, with no callback function
516 // defined.
517 void wxWindowMGL::OnCommand(wxWindow& win, wxCommandEvent& event)
518 {
519 if ( GetEventHandler()->ProcessEvent(event) )
520 return;
521 if ( m_parent )
522 m_parent->GetEventHandler()->OnCommand(win, event);
523 }
524 #endif // WXWIN_COMPATIBILITY_2
525
526 #if WXWIN_COMPATIBILITY
527 wxObject* wxWindowMGL::GetChild(int number) const
528 {
529 // Return a pointer to the Nth object in the Panel
530 wxNode *node = GetChildren().First();
531 int n = number;
532 while (node && n--)
533 node = node->Next();
534 if ( node )
535 {
536 wxObject *obj = (wxObject *)node->Data();
537 return(obj);
538 }
539 else
540 return NULL;
541 }
542 #endif // WXWIN_COMPATIBILITY
543
544 // Set this window to be the child of 'parent'.
545 bool wxWindowMGL::Reparent(wxWindowBase *parent)
546 {
547 if ( !wxWindowBase::Reparent(parent) )
548 return FALSE;
549
550 MGL_wmReparentWindow(m_wnd, parent->GetHandle());
551
552 return TRUE;
553 }
554
555
556 // ---------------------------------------------------------------------------
557 // drag and drop
558 // ---------------------------------------------------------------------------
559
560 #if wxUSE_DRAG_AND_DROP
561
562 void wxWindowMGL::SetDropTarget(wxDropTarget *pDropTarget)
563 {
564 if ( m_dropTarget != 0 ) {
565 m_dropTarget->Revoke(m_hWnd);
566 delete m_dropTarget;
567 }
568
569 m_dropTarget = pDropTarget;
570 if ( m_dropTarget != 0 )
571 m_dropTarget->Register(m_hWnd);
572 }
573 // FIXME_MGL
574 #endif // wxUSE_DRAG_AND_DROP
575
576 // old style file-manager drag&drop support: we retain the old-style
577 // DragAcceptFiles in parallel with SetDropTarget.
578 void wxWindowMGL::DragAcceptFiles(bool accept)
579 {
580 #if 0 // FIXME_MGL
581 HWND hWnd = GetHwnd();
582 if ( hWnd )
583 ::DragAcceptFiles(hWnd, (BOOL)accept);
584 #endif
585 }
586
587 // ---------------------------------------------------------------------------
588 // moving and resizing
589 // ---------------------------------------------------------------------------
590
591 // Get total size
592 void wxWindowMGL::DoGetSize(int *x, int *y) const
593 {
594 if (x) *x = m_wnd->width;
595 if (y) *y = m_wnd->height;
596 }
597
598 void wxWindowMGL::DoGetPosition(int *x, int *y) const
599 {
600 if (x) *x = m_wnd->x;
601 if (y) *y = m_wnd->y;
602 }
603
604 void wxWindowMGL::DoScreenToClient(int *x, int *y) const
605 {
606 int ax, ay;
607 wxPoint co = GetClientAreaOrigin();
608
609 MGL_wmCoordGlobalToLocal(m_wnd, m_wnd->x, m_wnd->y, &ax, &ay);
610 ax -= co.x;
611 ay -= co.y;
612 if (x)
613 *x = ax;
614 if (y)
615 *y = ay;
616 }
617
618 void wxWindowMGL::DoClientToScreen(int *x, int *y) const
619 {
620 int ax, ay;
621 wxPoint co = GetClientAreaOrigin();
622
623 MGL_wmCoordGlobalToLocal(m_wnd, m_wnd->x+co.x, m_wnd->y+co.y, &ax, &ay);
624 if (x)
625 *x = ax;
626 if (y)
627 *y = ay;
628 }
629
630 // Get size *available for subwindows* i.e. excluding menu bar etc.
631 void wxWindowMGL::DoGetClientSize(int *x, int *y) const
632 {
633 DoGetSize(x, y);
634 }
635
636 void wxWindowMGL::DoMoveWindow(int x, int y, int width, int height)
637 {
638 MGL_wmSetWindowPosition(GetHandle(), x, y, width, height);
639 }
640
641 // set the size of the window: if the dimensions are positive, just use them,
642 // but if any of them is equal to -1, it means that we must find the value for
643 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
644 // which case -1 is a valid value for x and y)
645 //
646 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
647 // the width/height to best suit our contents, otherwise we reuse the current
648 // width/height
649 void wxWindowMGL::DoSetSize(int x, int y, int width, int height, int sizeFlags)
650 {
651 // get the current size and position...
652 int currentX, currentY;
653 GetPosition(&currentX, &currentY);
654 int currentW,currentH;
655 GetSize(&currentW, &currentH);
656
657 // ... and don't do anything (avoiding flicker) if it's already ok
658 if ( x == currentX && y == currentY &&
659 width == currentW && height == currentH )
660 {
661 return;
662 }
663
664 if ( x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
665 x = currentX;
666 if ( y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
667 y = currentY;
668
669 #if 0 // FIXME_MGL -- what's this good for?
670 AdjustForParentClientOrigin(x, y, sizeFlags);
671 #endif
672
673 wxSize size(-1, -1);
674 if ( width == -1 )
675 {
676 if ( sizeFlags & wxSIZE_AUTO_WIDTH )
677 {
678 size = DoGetBestSize();
679 width = size.x;
680 }
681 else
682 {
683 // just take the current one
684 width = currentW;
685 }
686 }
687
688 if ( height == -1 )
689 {
690 if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
691 {
692 if ( size.x == -1 )
693 {
694 size = DoGetBestSize();
695 }
696 //else: already called DoGetBestSize() above
697
698 height = size.y;
699 }
700 else
701 {
702 // just take the current one
703 height = currentH;
704 }
705 }
706
707 DoMoveWindow(x, y, width, height);
708
709 wxSizeEvent event(wxSize(width, height), GetId());
710 event.SetEventObject(this);
711 GetEventHandler()->ProcessEvent(event);
712 }
713
714 void wxWindowMGL::DoSetClientSize(int width, int height)
715 {
716 SetSize(width, height);
717 }
718
719 // ---------------------------------------------------------------------------
720 // text metrics
721 // ---------------------------------------------------------------------------
722
723 int wxWindowMGL::GetCharHeight() const
724 {
725 wxScreenDC dc;
726 dc.SetFont(m_font);
727 return dc.GetCharHeight();
728 }
729
730 int wxWindowMGL::GetCharWidth() const
731 {
732 wxScreenDC dc;
733 dc.SetFont(m_font);
734 return dc.GetCharWidth();
735 }
736
737 void wxWindowMGL::GetTextExtent(const wxString& string,
738 int *x, int *y,
739 int *descent, int *externalLeading,
740 const wxFont *theFont) const
741 {
742 wxScreenDC dc;
743 if (!theFont)
744 theFont = &m_font;
745 dc.GetTextExtent(string, x, y, descent, externalLeading, (wxFont*)theFont);
746 }
747
748 #if wxUSE_CARET && WXWIN_COMPATIBILITY
749 // ---------------------------------------------------------------------------
750 // Caret manipulation
751 // ---------------------------------------------------------------------------
752
753 void wxWindowMGL::CreateCaret(int w, int h)
754 {
755 SetCaret(new wxCaret(this, w, h));
756 }
757
758 void wxWindowMGL::CreateCaret(const wxBitmap *WXUNUSED(bitmap))
759 {
760 wxFAIL_MSG("not implemented");
761 }
762
763 void wxWindowMGL::ShowCaret(bool show)
764 {
765 wxCHECK_RET( m_caret, "no caret to show" );
766
767 m_caret->Show(show);
768 }
769
770 void wxWindowMGL::DestroyCaret()
771 {
772 SetCaret(NULL);
773 }
774
775 void wxWindowMGL::SetCaretPos(int x, int y)
776 {
777 wxCHECK_RET( m_caret, "no caret to move" );
778
779 m_caret->Move(x, y);
780 }
781
782 void wxWindowMGL::GetCaretPos(int *x, int *y) const
783 {
784 wxCHECK_RET( m_caret, "no caret to get position of" );
785
786 m_caret->GetPosition(x, y);
787 }
788 #endif // wxUSE_CARET
789
790
791 // ---------------------------------------------------------------------------
792 // painting
793 // ---------------------------------------------------------------------------
794
795 void wxWindowMGL::Clear()
796 {
797 wxClientDC dc((wxWindow *)this);
798 wxBrush brush(GetBackgroundColour(), wxSOLID);
799 dc.SetBackground(brush);
800 dc.Clear();
801 }
802
803 void wxWindowMGL::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect)
804 {
805 if ( rect )
806 {
807 rect_t r;
808 r.left = rect->GetLeft(), r.right = rect->GetRight();
809 r.top = rect->GetTop(), r.bottom = rect->GetBottom();
810 MGL_wmInvalidateWindowRect(GetHandle(), &r);
811 }
812 else
813 MGL_wmInvalidateWindow(GetHandle());
814 }
815
816 void wxWindowMGL::Update()
817 {
818 if ( !m_frozen )
819 MGL_wmUpdateDC(g_winMng);
820 }
821
822 void wxWindowMGL::Freeze()
823 {
824 m_frozen = TRUE;
825 m_refreshAfterThaw = FALSE;
826 }
827
828 void wxWindowMGL::Thaw()
829 {
830 m_frozen = FALSE;
831 if ( m_refreshAfterThaw )
832 Refresh();
833 }
834
835 void wxWindowMGL::HandlePaint(MGLDevCtx *dc)
836 {
837 if ( m_frozen )
838 {
839 // Don't paint anything if the window is frozen.
840 m_refreshAfterThaw = TRUE;
841 return;
842 }
843
844 MGLRegion clip;
845 dc->getClipRegion(clip);
846 m_updateRegion = wxRegion(clip);
847 m_paintMGLDC = dc;
848
849 {
850 wxWindowDC dc((wxWindow*)this);
851 wxEraseEvent eventEr(m_windowId, &dc);
852 eventEr.SetEventObject(this);
853 GetEventHandler()->ProcessEvent(eventEr);
854 }
855
856 wxNcPaintEvent eventNc(GetId());
857 eventNc.SetEventObject(this);
858 GetEventHandler()->ProcessEvent(eventNc);
859
860 wxPaintEvent eventPt(GetId());
861 eventPt.SetEventObject(this);
862 GetEventHandler()->ProcessEvent(eventPt);
863
864 m_paintMGLDC = NULL;
865 m_updateRegion.Clear();
866 }
867
868
869 // Find the wxWindow at the current mouse position, returning the mouse
870 // position.
871 wxWindow* wxFindWindowAtPointer(wxPoint& pt)
872 {
873 return wxFindWindowAtPoint(pt = wxGetMousePosition());
874 }
875
876 wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
877 {
878 window_t *wnd = MGL_wmGetWindowAtPosition(g_winMng, pt.x, pt.y);
879 return (wxWindow*)wnd->userData;
880 }