]> git.saurik.com Git - wxWidgets.git/blobdiff - src/univ/topluniv.cpp
implemented writing in original encoding
[wxWidgets.git] / src / univ / topluniv.cpp
index 556873599f2059cc1d89d60f9af98bd862ebba2d..c5ffe12df3f0faf8e155292566e5fba6bc6bf7cd 100644 (file)
@@ -37,6 +37,7 @@
 #include "wx/bitmap.h"
 #include "wx/image.h"
 #include "wx/cshelp.h"
+#include "wx/evtloop.h"
 
 
 // ----------------------------------------------------------------------------
@@ -55,6 +56,7 @@ WX_FORWARD_TO_INPUT_CONSUMER(wxTopLevelWindow)
 // ============================================================================
 
 int wxTopLevelWindow::ms_drawDecorations = -1;
+int wxTopLevelWindow::ms_canIconize = -1;
 
 void wxTopLevelWindow::Init()
 {
@@ -76,10 +78,18 @@ bool wxTopLevelWindow::Create(wxWindow *parent,
          exstyleOrig = 0;
 
     if ( ms_drawDecorations == -1 )
-        ms_drawDecorations = !wxSystemSettings::HasFrameDecorations() ||
-                             wxGetEnv(wxT("WXDECOR"), NULL);
+    {
+        ms_drawDecorations = 
+            !wxSystemSettings::HasFeature(wxSYS_CAN_DRAW_FRAME_DECORATIONS) 
+            || wxGetEnv(wxT("WXDECOR"), NULL);
         // FIXME -- wxUniv should provide a way to force non-native decorations!
         //          $WXDECOR is just a hack in absence of better wxUniv solution
+    }
+
+    if ( ms_canIconize == -1 )
+    {
+        ms_canIconize = wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME);
+    }
 
     if ( ms_drawDecorations )
     {
@@ -138,7 +148,7 @@ long wxTopLevelWindow::GetDecorationsStyle() const
     if ( m_windowStyle & wxCAPTION )
     {
         style |= wxTOPLEVEL_TITLEBAR | wxTOPLEVEL_BUTTON_CLOSE;
-        if ( m_windowStyle & wxMINIMIZE_BOX )
+        if ( (m_windowStyle & wxMINIMIZE_BOX) && ms_canIconize )
             style |= wxTOPLEVEL_BUTTON_ICONIZE;
         if ( m_windowStyle & wxMAXIMIZE_BOX )
         {
@@ -256,7 +266,7 @@ long wxTopLevelWindow::HitTest(const wxPoint& pt) const
     wxTopLevelWindowNative::DoGetClientSize(&w, &h);
     wxRect rect(wxTopLevelWindowNative::GetClientAreaOrigin(), wxSize(w, h));
 
-    return m_renderer->HitTestFrame(rect, pt, GetDecorationsStyle());
+    return m_renderer->HitTestFrame(rect, pt+GetClientAreaOrigin(), GetDecorationsStyle());
 }
 
 // ----------------------------------------------------------------------------
@@ -291,6 +301,222 @@ void wxTopLevelWindow::SetIcon(const wxIcon& icon)
     }
 }
 
+// ----------------------------------------------------------------------------
+// interactive manipulation
+// ----------------------------------------------------------------------------
+
+#define wxINTERACTIVE_RESIZE_DIR \
+          (wxINTERACTIVE_RESIZE_W | wxINTERACTIVE_RESIZE_E | \
+           wxINTERACTIVE_RESIZE_S | wxINTERACTIVE_RESIZE_N)
+
+struct wxInteractiveMoveData
+{
+    wxTopLevelWindowBase *m_window;
+    wxEventLoop          *m_evtLoop;
+    int                   m_flags;
+    wxRect                m_rect;
+    wxRect                m_rectOrig;
+    wxPoint               m_pos;
+    wxSize                m_minSize, m_maxSize;
+};
+
+class wxInteractiveMoveHandler : public wxEvtHandler
+{
+public:
+    wxInteractiveMoveHandler(wxInteractiveMoveData& data) : m_data(data) {}
+    
+private:
+    DECLARE_EVENT_TABLE()
+    void OnMouseMove(wxMouseEvent& event);
+    void OnMouseDown(wxMouseEvent& event);
+    void OnMouseUp(wxMouseEvent& event);
+    void OnKeyDown(wxKeyEvent& event);
+
+    wxInteractiveMoveData& m_data;
+};
+
+BEGIN_EVENT_TABLE(wxInteractiveMoveHandler, wxEvtHandler)
+    EVT_MOTION(wxInteractiveMoveHandler::OnMouseMove)
+    EVT_LEFT_DOWN(wxInteractiveMoveHandler::OnMouseDown)
+    EVT_LEFT_UP(wxInteractiveMoveHandler::OnMouseUp)
+    EVT_KEY_DOWN(wxInteractiveMoveHandler::OnKeyDown)
+END_EVENT_TABLE()
+
+
+static inline LINKAGEMODE 
+void wxApplyResize(wxInteractiveMoveData& data, const wxPoint& diff)
+{
+    if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
+    {
+        data.m_rect.x += diff.x;
+        data.m_rect.width -= diff.x;
+    }
+    else if ( data.m_flags & wxINTERACTIVE_RESIZE_E )
+    {
+        data.m_rect.width += diff.x;
+    }
+    if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
+    {
+        data.m_rect.y += diff.y;
+        data.m_rect.height -= diff.y;
+    }
+    else if ( data.m_flags & wxINTERACTIVE_RESIZE_S )
+    {
+        data.m_rect.height += diff.y;
+    }
+    
+    if ( data.m_minSize.x != -1 && data.m_rect.width < data.m_minSize.x )
+    {
+        if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
+            data.m_rect.x -= data.m_minSize.x - data.m_rect.width;
+        data.m_rect.width = data.m_minSize.x;
+    }
+    if ( data.m_maxSize.x != -1 && data.m_rect.width > data.m_maxSize.x )
+    {
+        if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
+            data.m_rect.x -= data.m_minSize.x - data.m_rect.width;
+        data.m_rect.width = data.m_maxSize.x;
+    }
+    if ( data.m_minSize.y != -1 && data.m_rect.height < data.m_minSize.y )
+    {
+        if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
+            data.m_rect.y -= data.m_minSize.y - data.m_rect.height;
+        data.m_rect.height = data.m_minSize.y;
+    }
+    if ( data.m_maxSize.y != -1 && data.m_rect.height > data.m_maxSize.y )
+    {
+        if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
+            data.m_rect.y -= data.m_minSize.y - data.m_rect.height;
+        data.m_rect.height = data.m_maxSize.y;
+    }
+}
+
+void wxInteractiveMoveHandler::OnMouseMove(wxMouseEvent& event)
+{
+    if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
+        event.Skip();
+
+    else if ( m_data.m_flags & wxINTERACTIVE_MOVE )
+    {
+        wxPoint diff = wxGetMousePosition() - m_data.m_pos;
+        m_data.m_rect = m_data.m_rectOrig;
+        m_data.m_rect.Offset(diff);
+        m_data.m_window->Move(m_data.m_rect.GetPosition());
+    }
+
+    else if ( m_data.m_flags & wxINTERACTIVE_RESIZE )
+    {
+        wxPoint diff = wxGetMousePosition() - m_data.m_pos;
+        m_data.m_rect = m_data.m_rectOrig;
+        wxApplyResize(m_data, diff);
+        m_data.m_window->SetSize(m_data.m_rect);
+    }
+}
+
+void wxInteractiveMoveHandler::OnMouseDown(wxMouseEvent& event)
+{
+    if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
+    {
+        m_data.m_flags &= ~wxINTERACTIVE_WAIT_FOR_INPUT;
+        m_data.m_pos = wxGetMousePosition();
+    }
+}
+
+void wxInteractiveMoveHandler::OnKeyDown(wxKeyEvent& event)
+{
+    if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
+    {
+        m_data.m_flags &= ~wxINTERACTIVE_WAIT_FOR_INPUT;
+        m_data.m_pos = wxGetMousePosition();
+    }
+    
+    wxPoint diff(-1,-1);
+    
+    switch ( event.GetKeyCode() )
+    {
+        case WXK_UP:    diff = wxPoint(0, -16); break;
+        case WXK_DOWN:  diff = wxPoint(0, 16);  break;
+        case WXK_LEFT:  diff = wxPoint(-16, 0); break;
+        case WXK_RIGHT: diff = wxPoint(16, 0);  break;
+        case WXK_ESCAPE:
+            m_data.m_window->SetSize(m_data.m_rectOrig);
+            m_data.m_evtLoop->Exit();
+            return;
+        case WXK_RETURN:
+            m_data.m_evtLoop->Exit();
+            return;
+    }
+    
+    if ( diff.x != -1 )
+    {
+        if ( m_data.m_flags & wxINTERACTIVE_MOVE )
+        {
+            m_data.m_rect.Offset(diff);
+            m_data.m_window->Move(m_data.m_rect.GetPosition());
+        }
+        else /* wxINTERACTIVE_RESIZE */
+        {
+            if ( !(m_data.m_flags & wxINTERACTIVE_RESIZE_DIR) )
+            {
+                if ( diff.y < 0 )
+                    m_data.m_flags |= wxINTERACTIVE_RESIZE_N;
+                else if ( diff.y > 0 )
+                    m_data.m_flags |= wxINTERACTIVE_RESIZE_S;
+                if ( diff.x < 0 )
+                    m_data.m_flags |= wxINTERACTIVE_RESIZE_W;
+                else if ( diff.x > 0 )
+                    m_data.m_flags |= wxINTERACTIVE_RESIZE_E;
+            }
+
+            wxApplyResize(m_data, diff);
+            m_data.m_window->SetSize(m_data.m_rect);
+        }
+    }
+}
+
+void wxInteractiveMoveHandler::OnMouseUp(wxMouseEvent& event)
+{
+    m_data.m_evtLoop->Exit();
+}
+
+
+void wxTopLevelWindow::InteractiveMove(int flags)
+{
+    wxASSERT_MSG( !((flags & wxINTERACTIVE_MOVE) && (flags & wxINTERACTIVE_RESIZE)),
+                  wxT("can't move and resize window at the same time") );
+
+    wxASSERT_MSG( !(flags & wxINTERACTIVE_RESIZE) || 
+                  (flags & wxINTERACTIVE_WAIT_FOR_INPUT) || 
+                  (flags & wxINTERACTIVE_RESIZE_DIR),
+                  wxT("direction of resizing not specified") );
+
+    wxInteractiveMoveData data;
+    wxEventLoop loop;
+    wxWindow *focus = FindFocus();
+    
+    // FIXME - display resize cursor if waiting for initial input
+
+    data.m_window = this;
+    data.m_evtLoop = &loop;
+    data.m_flags = flags;
+    data.m_rect = data.m_rectOrig = GetRect();
+    data.m_pos = wxGetMousePosition();
+    data.m_minSize = wxSize(GetMinWidth(), GetMinHeight());
+    data.m_maxSize = wxSize(GetMaxWidth(), GetMaxHeight());
+
+    this->PushEventHandler(new wxInteractiveMoveHandler(data));
+    if ( focus )
+        focus->PushEventHandler(new wxInteractiveMoveHandler(data));
+
+    CaptureMouse();
+    loop.Run();
+    ReleaseMouse();
+
+    this->PopEventHandler(TRUE/*delete*/);
+    if ( focus )
+        focus->PopEventHandler(TRUE/*delete*/);
+}
+
 // ----------------------------------------------------------------------------
 // actions
 // ----------------------------------------------------------------------------
@@ -365,13 +591,13 @@ bool wxTopLevelWindow::PerformAction(const wxControlAction& action,
         ClickTitleBarButton(numArg);
         return TRUE;
     }
-    
+
     else if ( action == wxACTION_TOPLEVEL_MOVE )
     {
         InteractiveMove(wxINTERACTIVE_MOVE);
         return TRUE;
     }
-    
+
     else if ( action == wxACTION_TOPLEVEL_RESIZE )
     {
         int flags = wxINTERACTIVE_RESIZE;
@@ -386,7 +612,7 @@ bool wxTopLevelWindow::PerformAction(const wxControlAction& action,
         InteractiveMove(flags);
         return TRUE;
     }
-    
+
     else
         return FALSE;
 }
@@ -486,25 +712,25 @@ bool wxStdFrameInputHandler::HandleMouseMove(wxInputConsumer *consumer,
     }
     else if ( consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER )
     {
-        wxTopLevelWindow *win = wxStaticCast(consumer->GetInputWindow(), 
+        wxTopLevelWindow *win = wxStaticCast(consumer->GetInputWindow(),
                                              wxTopLevelWindow);
         long hit = win->HitTest(event.GetPosition());
-        
+
         if ( hit != m_winHitTest )
         {
             m_winHitTest = hit;
-            
+
             if ( m_borderCursorOn )
             {
                 m_borderCursorOn = FALSE;
                 win->SetCursor(m_origCursor);
             }
-            
+
             if ( hit & wxHT_TOPLEVEL_ANY_BORDER )
             {
                 m_borderCursorOn = TRUE;
                 wxCursor cur;
-            
+
                 switch (hit)
                 {
                     case wxHT_TOPLEVEL_BORDER_N: