]> git.saurik.com Git - wxWidgets.git/blobdiff - src/univ/topluniv.cpp
Updates for Y positioning
[wxWidgets.git] / src / univ / topluniv.cpp
index 6dceed79d762bf611e01f4ed19484a2efbc160bd..869a53a14abbe63cc38907b363edb1a7ec47f47a 100644 (file)
@@ -37,6 +37,7 @@
 #include "wx/bitmap.h"
 #include "wx/image.h"
 #include "wx/cshelp.h"
 #include "wx/bitmap.h"
 #include "wx/image.h"
 #include "wx/cshelp.h"
+#include "wx/evtloop.h"
 
 
 // ----------------------------------------------------------------------------
 
 
 // ----------------------------------------------------------------------------
@@ -268,6 +269,28 @@ long wxTopLevelWindow::HitTest(const wxPoint& pt) const
     return m_renderer->HitTestFrame(rect, pt+GetClientAreaOrigin(), GetDecorationsStyle());
 }
 
     return m_renderer->HitTestFrame(rect, pt+GetClientAreaOrigin(), GetDecorationsStyle());
 }
 
+int wxTopLevelWindow::GetMinWidth() const
+{
+    if ( ms_drawDecorations )
+    {
+        return wxMax(wxTopLevelWindowNative::GetMinWidth(),
+                     m_renderer->GetFrameMinSize(GetDecorationsStyle()).x);
+    }
+    else
+        return wxTopLevelWindowNative::GetMinWidth();
+}
+
+int wxTopLevelWindow::GetMinHeight() const
+{
+    if ( ms_drawDecorations )
+    {
+        return wxMax(wxTopLevelWindowNative::GetMinHeight(),
+                     m_renderer->GetFrameMinSize(GetDecorationsStyle()).y);
+    }
+    else
+        return wxTopLevelWindowNative::GetMinHeight();
+}
+
 // ----------------------------------------------------------------------------
 // icons
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // icons
 // ----------------------------------------------------------------------------
@@ -300,6 +323,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
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // actions
 // ----------------------------------------------------------------------------