]> git.saurik.com Git - wxWidgets.git/commitdiff
wxMGL wxWindow and wxApp mostly complete, now hunting bugs
authorVáclav Slavík <vslavik@fastmail.fm>
Thu, 9 Aug 2001 22:40:39 +0000 (22:40 +0000)
committerVáclav Slavík <vslavik@fastmail.fm>
Thu, 9 Aug 2001 22:40:39 +0000 (22:40 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@11341 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

13 files changed:
include/wx/mgl/app.h
include/wx/mgl/dc.h
include/wx/mgl/dcclient.h
include/wx/mgl/settings.h
include/wx/mgl/window.h
src/mgl/app.cpp
src/mgl/cursor.cpp
src/mgl/dc.cpp
src/mgl/dcclient.cpp
src/mgl/evtloop.cpp [new file with mode: 0644]
src/mgl/settings.cpp
src/mgl/utils.cpp
src/mgl/window.cpp

index 1b2506c2b0a7d58496312bb4859f9e0676883299..8cb604c6a13879d74274d1141083ed41e8e45e24 100644 (file)
@@ -21,8 +21,8 @@
 // classes
 //-----------------------------------------------------------------------------
 
-class wxApp;
-class wxLog;
+class WXDLLEXPORT wxApp;
+class WXDLLEXPORT wxLog;
 
 //-----------------------------------------------------------------------------
 // wxApp
@@ -31,59 +31,40 @@ class wxLog;
 class WXDLLEXPORT wxApp: public wxAppBase
 {
 public:
-    wxApp() {}
-    ~wxApp() {}
+    wxApp();
+    ~wxApp();
 
     /* override for altering the way wxGTK intializes the GUI
      * (palette/visual/colorcube). under wxMSW, OnInitGui() does nothing by
      * default. when overriding this method, the code in it is likely to be
      * platform dependent, otherwise use OnInit(). */
-    virtual bool OnInitGui() {return 0;}
+    virtual bool OnInitGui();
 
     // override base class (pure) virtuals
-    virtual int MainLoop() {return 0;}
-    virtual void ExitMainLoop() {}
-    virtual bool Initialized() {return 0;}
-    virtual bool Pending() {return 0;}
-    virtual void Dispatch() {}
+    virtual int MainLoop();
+    virtual void ExitMainLoop();
+    virtual bool Initialized();
+    virtual bool Pending();
+    virtual void Dispatch();
 
-    virtual wxIcon GetStdIcon(int which) const {return wxNullIcon;}
+    virtual wxIcon GetStdIcon(int which) const;
 
     // implementation only from now on
-    void OnIdle( wxIdleEvent &event ) {}
-    bool SendIdleEvents() {return 0;}
-    bool SendIdleEvents( wxWindow* win ) {return 0;}
+    void OnIdle(wxIdleEvent &event);
+    bool SendIdleEvents();
+    bool SendIdleEvents(wxWindow* win);
 
-    static bool Initialize() {return 0;}
-    static bool InitialzeVisual() {return 0;}
-    static void CleanUp() {}
+    static bool Initialize();
+    static void CleanUp();
 
-    bool ProcessIdle() {return 0;}
-    void DeletePendingObjects() {}
-
-    // This can be used to suppress the generation of Idle events.
-    void SuppressIdleEvents(bool arg = TRUE) { m_suppressIdleEvents = arg; }
-    bool GetSuppressIdleEvents() const { return m_suppressIdleEvents; }
-
-#if 0 //FIXME MGL
-    bool            m_initialized;
-
-    gint            m_idleTag;
-#if wxUSE_THREADS
-    gint            m_wakeUpTimerTag;
-#endif
-    unsigned char  *m_colorCube;
-#endif
-
-private:
-    /// Set to TRUE while we are in wxYield().
-    bool m_suppressIdleEvents;
+    bool ProcessIdle();
+    void DeletePendingObjects();
 
 private:
     DECLARE_DYNAMIC_CLASS(wxApp)
     DECLARE_EVENT_TABLE()
 };
 
-int WXDLLEXPORT wxEntry( int argc, char *argv[] );
+int WXDLLEXPORT wxEntry(int argc, char *argv[]);
 
 #endif // __WX_APP_H__
index 5d4b1c1be11d3869886178d1cadddbbfdcce2656..d59cec8a7bfc733bb2ed079b1f17c0c139b884cd 100644 (file)
@@ -45,6 +45,7 @@ class WXDLLEXPORT wxDC;
 
 // MGL fwd declarations:
 class MGLDevCtx;
+class MGLRegion;
 struct font_t;
 
 class WXDLLEXPORT wxDC : public wxDCBase
@@ -268,6 +269,8 @@ protected:
     wxPalette         m_oldPalette;
     
     wxRegion          m_currentClippingRegion;
+    // clipping region m_MGLDC had when it was attached:
+    MGLRegion        *m_globalClippingRegion;
 
     // wxDC::Blit handles memoryDCs as special cases :(
     bool              m_isMemDC;
index f062e9d5e72110fb77729efe7025e1d2e69f4f14..37f8ea423e4c33ab3855a67c0b60186941644f61 100644 (file)
@@ -16,8 +16,6 @@
 
 #include "wx/dc.h"
 
-class WXDLLEXPORT wxWindowMGL;
-
 //-----------------------------------------------------------------------------
 // classes
 //-----------------------------------------------------------------------------
@@ -25,6 +23,7 @@ class WXDLLEXPORT wxWindowMGL;
 class WXDLLEXPORT wxWindowDC;
 class WXDLLEXPORT wxPaintDC;
 class WXDLLEXPORT wxClientDC;
+class WXDLLEXPORT wxWindowMGL;
 
 //-----------------------------------------------------------------------------
 // wxWindowDC
@@ -39,6 +38,7 @@ public:
 
 protected:
     wxWindow *m_wnd;
+    bool      m_inPaintHandler;
 
 private:
     DECLARE_DYNAMIC_CLASS(wxWindowDC)
@@ -55,7 +55,6 @@ public:
     wxClientDC(wxWindow *win);
 
 private:
-    wxWindowMGL *m_wnd;
     DECLARE_DYNAMIC_CLASS(wxClientDC)
 };
 
@@ -63,12 +62,11 @@ private:
 // wxPaintDC
 //-----------------------------------------------------------------------------
 
-// FIXME_MGL
 class WXDLLEXPORT wxPaintDC : public wxClientDC
 {
 public:
-    wxPaintDC() }
-    wxPaintDC( wxWindow *win ) {}
+    wxPaintDC() : wxClientDC() {}
+    wxPaintDC(wxWindow *win) : wxClientDC(win) {}
 
 private:
     DECLARE_DYNAMIC_CLASS(wxPaintDC)
index 78204b3f0730b1217af033112ab48258383ed007..5ecfa01f8e615b4853b048930aff17af5b3b1967 100644 (file)
@@ -1,9 +1,8 @@
 /////////////////////////////////////////////////////////////////////////////
 // Name:        settings.h
-// Purpose:
-// Author:      Robert Roebling
+// Author:      Vaclav Slavik
 // Id:          $Id$
-// Copyright:   (c) 1998 Robert Roebling
+// Copyright:   (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
 // Licence:    wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 class wxSystemSettings: public wxObject
 {
 public:
-    inline wxSystemSettings() {}
+    wxSystemSettings() {}
 
-    inline static void Init() {}
+    static void Init() {}
     static void Done() {}
 
     // Get a system colour
-    static wxColour    GetSystemColour(int index) {}
+    static wxColour GetSystemColour(int index);
 
     // Get a system font
-    static wxFont      GetSystemFont(int index) {}
+    static wxFont GetSystemFont(int index);
 
     // Get a system metric, e.g. scrollbar size
-    static int         GetSystemMetric(int index) {}
+    static int GetSystemMetric(int index);
 };
 
 #endif
index 4cd53c3d278c75ec0e34703265f4071c63772384..9735d47aba96963ffaf0b6dd603c06e0c100d3b7 100644 (file)
@@ -113,7 +113,6 @@ protected:
     // (see wxWindow::Refresh)
     bool                  m_frozen;
     bool                  m_refreshAfterThaw;
-    wxFont                m_font;
 
     // implement the base class pure virtuals
     virtual void DoClientToScreen( int *x, int *y ) const;
@@ -141,9 +140,6 @@ private:
     MGLDevCtx *m_paintMGLDC;
     friend class wxPaintDC;
 
-    void OnEraseBackground(wxEraseEvent& event);
-    void OnSetFocus(wxFocusEvent& event);
-
     DECLARE_DYNAMIC_CLASS(wxWindowMGL);
     DECLARE_NO_COPY_CLASS(wxWindowMGL);
     DECLARE_EVENT_TABLE()
@@ -151,6 +147,7 @@ private:
 public:
     void HandlePaint(MGLDevCtx *dc);
     // needed by wxWindowPainter
+    MGLDevCtx *GetPaintMGLDC() const { return m_paintMGLDC; }
 };
 
 
index f1c96de5284e8e0d478676ae6e498aad76ec7ccf..d8b012870ebf195eb614bcea584cb1783e8758dd 100644 (file)
@@ -1,7 +1,7 @@
 /////////////////////////////////////////////////////////////////////////////
 // Name:        app.cpp
-// Purpose:
 // Author:      Vaclav Slavik
+//              based on GTK and MSW implementations
 // Id:          $Id$
 // Copyright:   (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
 // Licence:     wxWindows licence
     #pragma implementation "app.h"
 #endif
 
-#include "wx/app.h"
-#include "wx/settings.h"
-#include "wx/module.h"
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+    #include "wx/settings.h"
+    #include "wx/module.h"
+    #include "wx/evtloop.h"
+    #include "wx/frame.h"
+    #include "wx/dialog.h"
+    #include "wx/intl.h"
+#endif
 
-#include <mgraph.hpp>
+#include "wx/app.h"
+#include "wx/mgl/private.h"
 
 //-----------------------------------------------------------------------------
 // Global data
 //-----------------------------------------------------------------------------
 
-wxApp *wxTheApp = (wxApp *)  NULL;
+wxApp *wxTheApp = NULL;
 wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
 
-// FIXME_MGL - whole file
-
+static wxEventLoop *gs_mainEventLoop = NULL;
 
-extern bool g_isIdle;
 
-bool g_mainThreadLocked = FALSE;
+//-----------------------------------------------------------------------------
+// wxExit
+//-----------------------------------------------------------------------------
 
 void wxExit()
 {
+    MGL_exit();
     exit(0);
 }
 
@@ -40,17 +54,63 @@ void wxExit()
 // wxYield
 //-----------------------------------------------------------------------------
 
+static bool gs_inYield = FALSE;
+
 bool wxYield()
 {
+#if wxUSE_THREADS
+    if ( !wxThread::IsMain() )
+    {
+        // can't process events from other threads, MGL is thread-unsafe
+        return TRUE;
+    }
+#endif // wxUSE_THREADS
+
+    gs_inYield = TRUE;
+
+    wxLog::Suspend();
+
+    while (gs_mainEventLoop->Pending())
+        gs_mainEventLoop->Dispatch();
+        
+    /* it's necessary to call ProcessIdle() to update the frames sizes which
+       might have been changed (it also will update other things set from
+       OnUpdateUI() which is a nice (and desired) side effect) */
+    while (wxTheApp->ProcessIdle()) { }
+
+    wxLog::Resume();
+
+    gs_inYield = FALSE;
+
     return TRUE;
 }
 
+bool wxYieldIfNeeded()
+{
+    if (gs_inYield)
+        return FALSE;
+
+    return wxYield();
+}
+
+
 //-----------------------------------------------------------------------------
 // wxWakeUpIdle
 //-----------------------------------------------------------------------------
 
 void wxWakeUpIdle()
 {
+#if wxUSE_THREADS
+    if (!wxThread::IsMain())
+        wxMutexGuiEnter();
+#endif
+
+    while (wxTheApp->ProcessIdle()) {} 
+
+#if wxUSE_THREADS
+    if (!wxThread::IsMain())
+        wxMutexGuiLeave();
+#endif
 }
 
 //-----------------------------------------------------------------------------
@@ -64,26 +124,390 @@ BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
 END_EVENT_TABLE()
 
 
-int wxEntry( int argc, char *argv[] )
+wxApp::wxApp()
+{
+}
+
+wxApp::~wxApp()
+{
+}
+
+bool wxApp::OnInitGui()
+{
+    if ( MGL_init(".", NULL) == 0 )
+        return FALSE;
+    if ( !wxCreateMGL_WM() )
+        return FALSE;
+
+    // This has to be done *after* wxCreateMGL_WM() because it initializes 
+    // wxUniv's themes
+    if ( !wxAppBase::OnInitGui() )
+        return FALSE;
+
+    return TRUE;
+}
+
+bool wxApp::ProcessIdle()
+{
+    wxIdleEvent event;
+    event.SetEventObject(this);
+    ProcessEvent(event);
+
+    return event.MoreRequested();
+}
+
+void wxApp::OnIdle(wxIdleEvent &event)
+{
+    static bool s_inOnIdle = FALSE;
+
+    /* Avoid recursion (via ProcessEvent default case) */
+    if (s_inOnIdle)
+        return;
+
+    s_inOnIdle = TRUE;
+
+    /* Resend in the main thread events which have been prepared in other
+       threads */
+    ProcessPendingEvents();
+
+    // 'Garbage' collection of windows deleted with Close().
+    DeletePendingObjects();
+
+    // Send OnIdle events to all windows
+    if ( SendIdleEvents() )
+        event.RequestMore(TRUE);
+
+    s_inOnIdle = FALSE;
+}
+
+bool wxApp::SendIdleEvents()
+{
+    bool needMore = FALSE;
+
+    wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
+    while (node)
+    {
+        wxWindow* win = node->GetData();
+        if ( SendIdleEvents(win) )
+            needMore = TRUE;
+        node = node->GetNext();
+    }
+
+    return needMore;
+}
+
+bool wxApp::SendIdleEvents(wxWindow* win)
+{
+    bool needMore = FALSE;
+
+    wxIdleEvent event;
+    event.SetEventObject(win);
+
+    win->GetEventHandler()->ProcessEvent(event);
+
+#if 0 // FIXME_MGL - what the hell it is?
+    win->OnInternalIdle();
+
+    if ( event.MoreRequested() )
+        needMore = TRUE;
+#endif
+
+    wxNode* node = win->GetChildren().First();
+    while (node)
+    {
+        wxWindow* win = (wxWindow*) node->Data();
+        if ( SendIdleEvents(win) )
+            needMore = TRUE;
+
+        node = node->Next();
+    }
+    return needMore;
+}
+
+int wxApp::MainLoop()
+{
+    gs_mainEventLoop = new wxEventLoop;
+    return gs_mainEventLoop->Run();
+    delete gs_mainEventLoop;
+    gs_mainEventLoop = NULL;
+}
+
+void wxApp::ExitMainLoop()
+{
+    gs_mainEventLoop->Exit(0);
+}
+
+bool wxApp::Initialized()
+{
+    return (GetTopWindow() != NULL);
+}
+
+bool wxApp::Pending()
+{
+    return gs_mainEventLoop->Pending();
+}
+
+void wxApp::Dispatch()
 {
-    return 0;
+    gs_mainEventLoop->Dispatch();
 }
 
+void wxApp::DeletePendingObjects()
+{
+    wxNode *node = wxPendingDelete.First();
+    while (node)
+    {
+        wxObject *obj = (wxObject *)node->Data();
+
+        delete obj;
+
+        if ( wxPendingDelete.Find(obj) )
+            delete node;
 
-// FIXME_MGL - this is temporary solution, will be removed
-// once I have wxApp up and running
-bool wxMGL_Initialize()
+        node = wxPendingDelete.First();
+    }
+}
+
+bool wxApp::Initialize()
 {
     wxBuffer = new wxChar[BUFSIZ + 512];
 
     wxClassInfo::InitializeClasses();
+
     wxSystemSettings::Init();
-    wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
+    
+#if wxUSE_INTL
+    wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
+#endif
+
+    // GL: I'm annoyed ... I don't know where to put this and I don't want to
+    // create a module for that as it's part of the core.
+#if wxUSE_THREADS
+    wxPendingEvents = new wxList;
+    wxPendingEventsLocker = new wxCriticalSection;
+#endif
+
+    wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
     wxTheColourDatabase->Initialize();
+
     wxInitializeStockLists();
     wxInitializeStockObjects();
+
+#if wxUSE_WX_RESOURCES
+    wxInitializeResourceSystem();
+#endif
+
     wxModule::RegisterModules();
     if (!wxModule::InitializeModules()) return FALSE;
+
     return TRUE;
 }
 
+#include "info.xpm"
+#include "error.xpm"
+#include "question.xpm"
+#include "warning.xpm"
+
+wxIcon wxApp::GetStdIcon(int which) const
+{
+    switch(which)
+    {
+        case wxICON_INFORMATION:
+            return wxIcon(info_xpm);
+        case wxICON_QUESTION:
+            return wxIcon(question_xpm);
+        case wxICON_EXCLAMATION:
+            return wxIcon(warning_xpm);
+        default:
+            wxFAIL_MSG(wxT("requested non existent standard icon"));
+            // still fall through
+        case wxICON_HAND:
+            return wxIcon(error_xpm);
+    }
+}
+
+void wxApp::CleanUp()
+{
+#if wxUSE_LOG
+    // flush the logged messages if any
+    wxLog *log = wxLog::GetActiveTarget();
+    if (log != NULL && log->HasPendingMessages())
+        log->Flush();
+
+    // continuing to use user defined log target is unsafe from now on because
+    // some resources may be already unavailable, so replace it by something
+    // more safe
+    wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
+    if ( oldlog )
+        delete oldlog;
+#endif // wxUSE_LOG
+
+    wxModule::CleanUpModules();
+
+#if wxUSE_WX_RESOURCES
+    wxCleanUpResourceSystem();
+#endif
+
+    if (wxTheColourDatabase)
+        delete wxTheColourDatabase;
+
+    wxTheColourDatabase = (wxColourDatabase*) NULL;
+
+    wxDeleteStockObjects();
+
+    wxDeleteStockLists();
+
+    delete wxTheApp;
+    wxTheApp = (wxApp*) NULL;
+
+    // GL: I'm annoyed ... I don't know where to put this and I don't want to
+    // create a module for that as it's part of the core.
+#if wxUSE_THREADS
+    delete wxPendingEvents;
+    delete wxPendingEventsLocker;
+#endif
+
+    wxSystemSettings::Done();
+
+    delete[] wxBuffer;
+
+    wxClassInfo::CleanUpClasses();
+
+    // check for memory leaks
+#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
+    if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
+    {
+        wxLogDebug(wxT("There were memory leaks.\n"));
+        wxDebugContext::Dump();
+        wxDebugContext::PrintStatistics();
+    }
+#endif // Debug
+
+#if wxUSE_LOG
+    // do this as the very last thing because everything else can log messages
+    wxLog::DontCreateOnDemand();
+
+    wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
+    if (oldLog)
+        delete oldLog;
+#endif // wxUSE_LOG
+
+    wxDestroyMGL_WM();
+    MGL_exit();
+}
+
+
+int wxEntryStart(int argc, char *argv[])
+{
+    return wxApp::Initialize() ? 0 : -1;
+}
+
+
+int wxEntryInitGui()
+{
+    return wxTheApp->OnInitGui() ? 0 : -1;
+}
+
+
+void wxEntryCleanup()
+{
+    wxApp::CleanUp();
+}
+
+
+
+int wxEntry(int argc, char *argv[])
+{
+#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
+    // This seems to be necessary since there are 'rogue'
+    // objects present at this point (perhaps global objects?)
+    // Setting a checkpoint will ignore them as far as the
+    // memory checking facility is concerned.
+    // Of course you may argue that memory allocated in globals should be
+    // checked, but this is a reasonable compromise.
+    wxDebugContext::SetCheckpoint();
+#endif
+    int err = wxEntryStart(argc, argv);
+    if ( err )
+        return err;
+
+    if ( !wxTheApp )
+    {
+        wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
+                     wxT("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
+
+        wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
+
+        wxObject *test_app = app_ini();
+
+        wxTheApp = (wxApp*) test_app;
+    }
+
+    wxCHECK_MSG( wxTheApp, -1, wxT("wxWindows error: no application object") );
+
+    wxTheApp->argc = argc;
+#if wxUSE_UNICODE
+    wxTheApp->argv = new wxChar*[argc+1];
+    int mb_argc = 0;
+    while (mb_argc < argc)
+    {
+        wxTheApp->argv[mb_argc] = wxStrdup(wxConvLibc.cMB2WX(argv[mb_argc]));
+        mb_argc++;
+    }
+    wxTheApp->argv[mb_argc] = (wxChar *)NULL;
+#else
+    wxTheApp->argv = argv;
+#endif
+
+    wxString name(wxFileNameFromPath(argv[0]));
+    wxStripExtension(name);
+    wxTheApp->SetAppName(name);
+
+    int retValue;
+    retValue = wxEntryInitGui();
+
+    // Here frames insert themselves automatically into wxTopLevelWindows by
+    // getting created in OnInit().
+    if ( retValue == 0 )
+    {
+        if ( !wxTheApp->OnInit() )
+            retValue = -1;
+    }
+
+    if ( retValue == 0 )
+    {
+        /* delete pending toplevel windows (typically a single
+           dialog) so that, if there isn't any left, we don't
+           call OnRun() */
+        wxTheApp->DeletePendingObjects();
+
+        if ( wxTheApp->Initialized() &&
+             wxTopLevelWindows.GetCount() != 0 )
+        {
+            wxTheApp->OnRun();
+
+            wxWindow *topWindow = wxTheApp->GetTopWindow();
+            if ( topWindow )
+            {
+                /* Forcibly delete the window. */
+                if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
+                    topWindow->IsKindOf(CLASSINFO(wxDialog)) )
+                {
+                    topWindow->Close(TRUE);
+                    wxTheApp->DeletePendingObjects();
+                }
+                else
+                {
+                    delete topWindow;
+                    wxTheApp->SetTopWindow((wxWindow*) NULL);
+                }
+            }
+
+            retValue = wxTheApp->OnExit();
+        }
+    }
+
+    wxEntryCleanup();
+
+    return retValue;
+}
index 0764b9351943f9f254fc99f9e2ecb7450cfabf1d..1e4867ae705e74d2f025491b84e8876656924f71 100644 (file)
@@ -68,6 +68,9 @@ wxCursor::wxCursor(int cursorId)
 
     switch (cursorId)
     {
+        // FIXME_MGL -- what about storing these default cursors in executable
+        //              as XPMs so that wxMGL binary wouldn't depend on 
+        //              tons of files in $MGL_ROOT/cursors? I don't know yet...
         case wxCURSOR_ARROW:           cursorname = "arrow.cur"; break;
         case wxCURSOR_BULLSEYE:        cursorname = "bullseye.cur"; break;
         case wxCURSOR_CHAR:            cursorname = "char.cur"; break;
index bc91b0e75e4c9a0840095a64611f86dddaa106e3..a2d932bd5a861b22cd1522db7977658f9c2493ea 100644 (file)
@@ -172,6 +172,7 @@ wxDC::wxDC()
     m_downloadedPatterns[0] = m_downloadedPatterns[1] = FALSE;
     
     m_mglFont = NULL;
+    m_globalClippingRegion = NULL;
 }
 
 
@@ -179,6 +180,7 @@ wxDC::~wxDC()
 {
     if (m_OwnsMGLDC) 
         delete m_MGLDC;
+    delete m_globalClippingRegion;
 }
 
 void wxDC::SetMGLDC(MGLDevCtx *mgldc, bool OwnsMGLDC)
@@ -188,6 +190,15 @@ void wxDC::SetMGLDC(MGLDevCtx *mgldc, bool OwnsMGLDC)
     m_MGLDC = mgldc;
     m_OwnsMGLDC = OwnsMGLDC;
        m_ok = TRUE;
+    
+    if ( mgldc->getDC()->a.clipRegion )
+    {
+        m_globalClippingRegion = new MGLRegion;
+        mgldc->getClipRegion(*m_globalClippingRegion);
+    }
+    else
+        m_globalClippingRegion = NULL;
+    
     InitializeMGLDC();
 }
 
@@ -226,7 +237,13 @@ void wxDC::DoSetClippingRegion(wxCoord cx, wxCoord cy, wxCoord cw, wxCoord ch)
     else
         m_currentClippingRegion.Union(rect);
 
-    m_MGLDC->setClipRegion(m_currentClippingRegion.GetMGLRegion());
+    if ( m_globalClippingRegion )
+    {
+        m_MGLDC->setClipRegion(m_currentClippingRegion.GetMGLRegion() 
+                               & *m_globalClippingRegion);
+    }
+    else
+        m_MGLDC->setClipRegion(m_currentClippingRegion.GetMGLRegion());
 
     m_clipping = TRUE;
     DO_SET_CLIPPING_BOX(m_currentClippingRegion)
@@ -265,7 +282,13 @@ void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
     else
         m_currentClippingRegion.Union(rg);
 
-    m_MGLDC->setClipRegion(m_currentClippingRegion.GetMGLRegion());
+    if ( m_globalClippingRegion )
+    {
+        m_MGLDC->setClipRegion(m_currentClippingRegion.GetMGLRegion() 
+                               & *m_globalClippingRegion);
+    }
+    else
+        m_MGLDC->setClipRegion(m_currentClippingRegion.GetMGLRegion());
 
     m_clipping = TRUE;
     DO_SET_CLIPPING_BOX(m_currentClippingRegion)
@@ -275,7 +298,10 @@ void wxDC::DestroyClippingRegion()
 {
     wxCHECK_RET( Ok(), wxT("invalid dc") );
     
-    m_MGLDC->setClipRect(MGLRect(0, 0, m_MGLDC->sizex(), m_MGLDC->sizey()));
+    if ( m_globalClippingRegion )
+        m_MGLDC->setClipRegion(*m_globalClippingRegion);
+    else
+        m_MGLDC->setClipRect(MGLRect(0, 0, m_MGLDC->sizex(), m_MGLDC->sizey()));
     m_clipping = FALSE;
     m_currentClippingRegion.Clear();    
 }
index f3bef5fbd7648c6995f80e8592242149a5a8e0f0..8edae04c3b05fecff9dd1ab4ae01a8d0cad90f73 100644 (file)
 #include <mgraph.hpp>
 
 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
-IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
 IMPLEMENT_DYNAMIC_CLASS(wxClientDC,wxWindowDC)
+IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
 
 wxWindowDC::wxWindowDC(wxWindow *win) : m_wnd(win)
 {
-    MGLDC *dc = MGL_wmBeginPaint(m_wnd->GetHandle());
-    SetMGLDC(new MGLDevCtx(dc), FALSE);
-    // FIXME_MGL -- correctly handle setting device origin and
-    //              clipping regions
+    MGLDevCtx *dc = win->GetPaintMGLDC();
+    if ( dc )
+    {
+        m_inPaintHandler = TRUE;
+        SetMGLDC(dc, FALSE);
+    }
+    else
+    {
+        m_inPaintHandler = FALSE;
+        SetMGLDC(new MGLDevCtx(MGL_wmBeginPaint(m_wnd->GetHandle())), TRUE);
+        // TRUE means that dtor will delete MGLDevCtx object
+        // but it won't destroy MGLDC returned by MGL_wmBeginPaint because
+        // ~MGLDevCtx() doesn't call destroy()
+    }
 }
 
 wxWindowDC::~wxWindowDC()
 {
-    MGL_wmEndPaint(m_wnd->GetHandle());
+    if ( m_inPaintHandler )
+    {
+        // This is neccessary so that subsequently created wxPaintDCs won't get
+        // confused about clipping. Another reason is that the same MGL dc is reused
+        // for wxEraseEvent, wxNcPaintEvent and wxPaintEvent
+        DestroyClippingRegion();
+    }
+    else
+    {
+        GetMGLDC()->setDC(NULL);
+        MGL_wmEndPaint(m_wnd->GetHandle());
+    }
 }
 
 wxClientDC::wxClientDC(wxWindow *win) : wxWindowDC(win)
diff --git a/src/mgl/evtloop.cpp b/src/mgl/evtloop.cpp
new file mode 100644 (file)
index 0000000..9f8161d
--- /dev/null
@@ -0,0 +1,176 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        mgl/evtloop.cpp
+// Purpose:     implements wxEventLoop for MGL
+// Author:      Vaclav Slavik
+// RCS-ID:      $Id$
+// Copyright:   (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
+// License:     wxWindows license
+///////////////////////////////////////////////////////////////////////////////
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+#ifdef __GNUG__
+    #pragma implementation "evtloop.h"
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+    #include "wx/window.h"
+    #include "wx/app.h"
+    #include "wx/thread.h"
+#endif //WX_PRECOMP
+
+#include "wx/evtloop.h"
+
+#include "wx/mgl/private.h"
+
+// ----------------------------------------------------------------------------
+// wxEventLoopImpl
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxEventLoopImpl
+{
+public:
+    // ctor
+    wxEventLoopImpl()
+        {
+            SetExitCode(0);
+            SetKeepLooping(TRUE);
+        }
+
+    // process a message
+    void ProcessEvent(event_t *evt);
+
+    // generate an idle message, return TRUE if more idle time requested
+    bool SendIdleMessage();
+
+    // set/get the exit code
+    void SetExitCode(int exitcode) { m_exitcode = exitcode; }
+    int GetExitCode() const { return m_exitcode; }
+    
+    void SetKeepLooping(bool k) { m_keepLooping = k; }
+    bool GetKeepLooping() const { return m_keepLooping; }
+
+private:
+
+    // the exit code of the event loop
+    int m_exitcode;
+    // FALSE if the loop should end
+    bool m_keepLooping;
+};
+
+// ============================================================================
+// wxEventLoopImpl implementation
+// ============================================================================
+
+void wxEventLoopImpl::ProcessEvent(event_t *evt)
+{
+    MGL_wmProcessEvent(g_winMng, evt);
+}
+
+bool wxEventLoopImpl::SendIdleMessage()
+{
+    wxIdleEvent event;
+
+    return wxTheApp->ProcessEvent(event) && event.MoreRequested();
+}
+
+// ============================================================================
+// wxEventLoop implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxEventLoop running and exiting
+// ----------------------------------------------------------------------------
+
+wxEventLoop::~wxEventLoop()
+{
+    wxASSERT_MSG( !m_impl, _T("should have been deleted in Run()") );
+}
+
+bool wxEventLoop::IsRunning() const
+{
+    return m_impl != NULL;
+}
+
+int wxEventLoop::Run()
+{
+    // event loops are not recursive, you need to create another loop!
+    wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") );
+
+    m_impl = new wxEventLoopImpl;
+
+    for ( ;; )
+    {
+#if wxUSE_THREADS
+        //wxMutexGuiLeaveOrEnter(); // FIXME_MGL - huh?
+#endif // wxUSE_THREADS
+
+        // generate and process idle events for as long as we don't have
+        // anything else to do
+        while ( !Pending() && m_impl->SendIdleMessage() ) {}
+
+        // a message came or no more idle processing to do, sit in Dispatch()
+        // waiting for the next message
+        if ( !Dispatch() )
+        {
+            // app terminated
+            break;
+        }
+    }
+
+    int exitcode = m_impl->GetExitCode();
+    delete m_impl;
+    m_impl = NULL;
+
+    return exitcode;
+}
+
+void wxEventLoop::Exit(int rc)
+{
+    wxCHECK_RET( IsRunning(), _T("can't call Exit() if not running") );
+
+    m_impl->SetExitCode(rc);
+    m_impl->SetKeepLooping(FALSE);
+}
+
+// ----------------------------------------------------------------------------
+// wxEventLoop message processing dispatching
+// ----------------------------------------------------------------------------
+
+bool wxEventLoop::Pending() const
+{
+    event_t evt;
+    return EVT_peekNext(&evt, EVT_EVERYEVT);
+}
+
+bool wxEventLoop::Dispatch()
+{
+    wxCHECK_MSG( IsRunning(), FALSE, _T("can't call Dispatch() if not running") );
+
+    event_t evt;
+    ibool rc = EVT_getNext(&evt, EVT_EVERYEVT);
+
+    if ( !rc )
+    {
+        wxLogError(_T("events queue empty even though Pending() returned true"));
+        return FALSE;
+    }
+    
+    // FIXME_MGL -- there must be some way to programatically exit
+    // the loop, like WM_QUIT under Windows -- perhaps we need custom
+    // event to indicate this??
+
+    m_impl->ProcessEvent(&evt);
+
+    return m_impl->GetKeepLooping();
+}
+
index 19427c69a50385d85e857b94935e9e012b69332c..fab6801169e0c9a4aeb7a1148046f94cace1489d 100644 (file)
@@ -1,9 +1,8 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        settings.cpp
-// Purpose:
-// Author:      Robert Roebling
+// Name:        settings.h
+// Author:      Vaclav Slavik
 // Id:          $Id$
-// Copyright:   (c) 1998 Robert Roebling
+// Copyright:   (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
 // Licence:    wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 #endif
 
 #include "wx/settings.h"
+#include "wx/colour.h"
+#include "wx/font.h"
 
+wxColour wxSystemSettings::GetSystemColour(int WXUNUSED(index))
+{
+    // FIXME_MGL
+    return wxColour(255,255,0);
+}
+
+wxFont wxSystemSettings::GetSystemFont(int WXUNUSED(index))
+{
+    // FIXME_MGL
+    return wxFont(12, wxMODERN, wxNORMAL, wxNORMAL);
+}
+
+int wxSystemSettings::GetSystemMetric(int WXUNUSED(index))
+{
+    // FIXME_MGL
+    return 1;
+}
index 7ad8f8af4f2277f8febdb5b208a1d5a8e5717f83..5e5409772da363d91934163543cceffb742390b9 100644 (file)
@@ -47,16 +47,23 @@ void wxDisplaySize(int *width, int *height)
     if (height) *height = g_displayDC->sizey();
 }
 
-void wxGetMousePosition(int* x, int* y)
+void wxDisplaySizeMM(int *width, int *height)
 {
-    MS_getPos(x, y);
+    wxASSERT_MSG( g_displayDC, wxT("MGL display DC not created yet.") );
+    if (width) *width = g_displayDC->sizex() * 25/72;
+    if (height) *height = g_displayDC->sizey() * 25/72;
+    // FIXME_MGL -- what about returning *real* monitor dimensions?
 }
 
-wxPoint wxGetMousePosition()
+void wxClientDisplayRect(int *x, int *y, int *width, int *height)
 {
-    wxPoint pt;
-    wxGetMousePosition(&pt.x, &pt.y);
-    return pt;
+    // This is supposed to return desktop dimensions minus any window
+    // manager panels, menus, taskbars, etc.  If there is a way to do that
+    // for this platform please fix this function, otherwise it defaults
+    // to the entire desktop.
+    if (x) *x = 0;
+    if (y) *y = 0;
+    wxDisplaySize(width, height);
 }
 
 bool wxColourDisplay()
@@ -85,6 +92,20 @@ int wxGetOsVersion(int *majorVsn, int *minorVsn)
 }
 
 
+void wxGetMousePosition(int* x, int* y)
+{
+    MS_getPos(x, y);
+}
+
+wxPoint wxGetMousePosition()
+{
+    wxPoint pt;
+    wxGetMousePosition(&pt.x, &pt.y);
+    return pt;
+}
+
+
+
 #ifdef __UNIX__
 
 int wxAddProcessCallback(wxEndProcessData *proc_data, int fd)
index 2b65c36f0d810c6bdd9db7de51511bde321b6b42..1ac85be6fa4268c6474338f5fe7d013fdc1a6268 100644 (file)
@@ -65,8 +65,11 @@ MGLDevCtx *g_displayDC = NULL;
 
 extern wxList WXDLLEXPORT wxPendingDelete;
  // FIXME_MGL -- ???
-static wxWindowMGL *g_focusedWindow;
+
+// the window that has keyboard+joystick focus: 
+static wxWindowMGL *g_focusedWindow = NULL;
+// the window that is currently under mouse cursor:
+static wxWindowMGL *g_windowUnderMouse = NULL;
 
 // ---------------------------------------------------------------------------
 // constants
@@ -85,8 +88,6 @@ enum
 // private functions
 // ---------------------------------------------------------------------------
 
-static void wxWindowPainter(window_t *wnd, MGLDC *dc);
-
 // wxCreateMGL_WM creates MGL display DC and associates it with winmng_t
 // structure. Dimensions and depth of the DC are fetched from wxSystemOptions
 // object. 
@@ -137,15 +138,31 @@ bool wxCreateMGL_WM()
 
 void wxDestroyMGL_WM()
 {
-    if (g_winMng)
+    if ( g_winMng )
     {
         MGL_wmDestroy(g_winMng);
         g_winMng = NULL;
     }
-    delete g_displayDC;
-    g_displayDC = NULL;
+    if ( g_displayDC )
+    {
+        delete g_displayDC;
+        g_displayDC = NULL;
+    }
 }
 
+// ---------------------------------------------------------------------------
+// MGL_WM hooks:
+// ---------------------------------------------------------------------------
+
+static void wxWindowPainter(window_t *wnd, MGLDC *dc)
+{
+    wxWindowMGL *w = (wxWindow*) wnd->userData;
+    if (w)
+    {
+        MGLDevCtx ctx(dc);
+        w->HandlePaint(&ctx);
+    }
+}
 
 // ---------------------------------------------------------------------------
 // event tables
@@ -156,8 +173,6 @@ void wxDestroyMGL_WM()
 IMPLEMENT_ABSTRACT_CLASS(wxWindowMGL, wxWindowBase)
 
 BEGIN_EVENT_TABLE(wxWindowMGL, wxWindowBase)
-    EVT_ERASE_BACKGROUND(wxWindowMGL::OnEraseBackground)
-    EVT_SET_FOCUS(wxWindowMGL::OnSetFocus)
 END_EVENT_TABLE()
 
 // ===========================================================================
@@ -191,7 +206,8 @@ wxWindowMGL::~wxWindowMGL()
     m_isBeingDeleted = TRUE;
 
     if ( g_focusedWindow == this )
-        g_focusedWindow = NULL;
+        KillFocus();
+
 #if 0 // -- fixme - do we need this?
     // VS: make sure there's no wxFrame with last focus set to us:
     for (wxWindow *win = GetParent(); win; win = win->GetParent())
@@ -226,12 +242,16 @@ bool wxWindowMGL::Create(wxWindow *parent,
                          long style,
                          const wxString& name)
 {
-    wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") );
+    // FIXME_MGL -- temporary!
+    //wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") );
 
     if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
         return FALSE;
 
-    parent->AddChild(this);
+    if ( parent ) // FIXME_MGL temporary
+        parent->AddChild(this);
+    else
+        m_isShown=FALSE;// FIXME_MGL -- temporary, simulates wxTLW/wxFrame
 
     if ( style & wxPOPUP_WINDOW )
     {
@@ -260,10 +280,6 @@ void wxWindowMGL::SetFocus()
     
     MGL_wmCaptureEvents(GetHandle(), EVT_KEYEVT | EVT_JOYEVT, wxMGL_CAPTURE_KEYB);
 
-    wxPanel *panel = wxDynamicCast(GetParent(), wxPanel);
-    if (panel)
-        panel->SetLastFocus((wxWindow*)this);
-
 #if wxUSE_CARET
     // caret needs to be informed about focus change
     wxCaret *caret = GetCaret();
@@ -288,16 +304,18 @@ void wxWindowMGL::KillFocus()
     if ( g_focusedWindow != this ) return;
     g_focusedWindow = NULL;
 
+    if ( m_isBeingDeleted ) return;
+    
     MGL_wmUncaptureEvents(GetHandle(), wxMGL_CAPTURE_KEYB);
 
 #if wxUSE_CARET
     // caret needs to be informed about focus change
     wxCaret *caret = GetCaret();
-    if (caret)
+    if ( caret )
         caret->OnKillFocus();
 #endif // wxUSE_CARET
 
-    if (IsTopLevel())
+    if ( IsTopLevel() )
     {
         wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId());
         event.SetEventObject(this);
@@ -657,35 +675,6 @@ void wxWindowMGL::GetCaretPos(int *x, int *y) const
 #endif // wxUSE_CARET
 
 
-// ---------------------------------------------------------------------------
-// activation/focus
-// ---------------------------------------------------------------------------
-
-void wxWindowMGL::OnSetFocus(wxFocusEvent& event)
-{
-    // panel wants to track the window which was the last to have focus in it,
-    // so we want to set ourselves as the window which last had focus
-    //
-    // notice that it's also important to do it upwards the tree becaus
-    // otherwise when the top level panel gets focus, it won't set it back to
-    // us, but to some other sibling
-    wxWindow *win = (wxWindow *)this;
-    while ( win )
-    {
-        wxWindow *parent = win->GetParent();
-        wxPanel *panel = wxDynamicCast(parent, wxPanel);
-        if ( panel )
-        {
-            panel->SetLastFocus(win);
-        }
-
-        win = parent;
-    }
-
-    event.Skip();
-}
-
-
 // ---------------------------------------------------------------------------
 // painting
 // ---------------------------------------------------------------------------
@@ -731,16 +720,6 @@ void wxWindowMGL::Thaw()
         Refresh();
 }
 
-static void wxWindowPainter(window_t *wnd, MGLDC *dc)
-{
-    wxWindow *w = (wxWindow*) wnd->userData;
-    if (w)
-    {
-        MGLDevCtx ctx(dc);
-        w->HandlePaint(&ctx);
-    }
-}
-
 void wxWindowMGL::HandlePaint(MGLDevCtx *dc)
 {
     if ( m_frozen )
@@ -749,14 +728,17 @@ void wxWindowMGL::HandlePaint(MGLDevCtx *dc)
         return;
     }
 
-    region_t *clip = NULL;
-    MGL_getClipRegionDC(*dc, clip);
-    m_updateRegion = wxRegion(MGLRegion(clip));
+    region_t clip;
+    MGL_getClipRegionDC(*dc, &clip);
+    m_updateRegion = wxRegion(MGLRegion(&clip));
     m_paintMGLDC = dc;
 
-    wxEraseEvent eventEr(m_windowId, NULL);
+    {
+    wxWindowDC dc((wxWindow*)this);
+    wxEraseEvent eventEr(m_windowId, &dc);
     eventEr.SetEventObject(this);
     GetEventHandler()->ProcessEvent(eventEr);
+    }
 
     wxNcPaintEvent eventNc(GetId());
     eventNc.SetEventObject(this);
@@ -765,11 +747,8 @@ void wxWindowMGL::HandlePaint(MGLDevCtx *dc)
     wxPaintEvent eventPt(GetId());
     eventPt.SetEventObject(this);
     GetEventHandler()->ProcessEvent(eventPt);
-}
 
-void wxWindowMGL::OnEraseBackground(wxEraseEvent& event)
-{
-    Clear();
+    m_paintMGLDC = NULL;
 }