X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/253293c10326afa0226932eab4753d188e1e22e2..3242feb1c09fd28c5a41ed1ee76e37d56213f19b:/src/univ/topluniv.cpp diff --git a/src/univ/topluniv.cpp b/src/univ/topluniv.cpp index 27a2633365..f16864f80a 100644 --- a/src/univ/topluniv.cpp +++ b/src/univ/topluniv.cpp @@ -2,7 +2,7 @@ // Name: topluniv.cpp // Author: Vaclav Slavik // Id: $Id$ -// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com) +// Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com) // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -37,6 +37,7 @@ #include "wx/bitmap.h" #include "wx/image.h" #include "wx/cshelp.h" +#include "wx/evtloop.h" // ---------------------------------------------------------------------------- @@ -46,6 +47,7 @@ BEGIN_EVENT_TABLE(wxTopLevelWindow, wxTopLevelWindowNative) WX_EVENT_TABLE_INPUT_CONSUMER(wxTopLevelWindow) EVT_NC_PAINT(wxTopLevelWindow::OnNcPaint) + EVT_MENU_RANGE(wxID_CLOSE_FRAME, wxID_RESTORE_FRAME, wxTopLevelWindow::OnSystemMenu) END_EVENT_TABLE() WX_FORWARD_TO_INPUT_CONSUMER(wxTopLevelWindow) @@ -79,7 +81,7 @@ bool wxTopLevelWindow::Create(wxWindow *parent, if ( ms_drawDecorations == -1 ) { ms_drawDecorations = - !wxSystemSettings::GetCapability(wxSYS_CAN_DRAW_FRAME_DECORATIONS) + !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 @@ -87,7 +89,7 @@ bool wxTopLevelWindow::Create(wxWindow *parent, if ( ms_canIconize == -1 ) { - ms_canIconize = wxSystemSettings::GetCapability(wxSYS_CAN_ICONIZE_FRAME); + ms_canIconize = wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME); } if ( ms_drawDecorations ) @@ -265,7 +267,29 @@ 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()); +} + +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(); } // ---------------------------------------------------------------------------- @@ -300,6 +324,333 @@ void wxTopLevelWindow::SetIcon(const wxIcon& icon) } } +// ---------------------------------------------------------------------------- +// interactive manipulation +// ---------------------------------------------------------------------------- + + +static bool wxGetResizingCursor(long hitTestResult, wxCursor& cursor) +{ + if ( hitTestResult & wxHT_TOPLEVEL_ANY_BORDER ) + { + switch (hitTestResult) + { + case wxHT_TOPLEVEL_BORDER_N: + case wxHT_TOPLEVEL_BORDER_S: + cursor = wxCursor(wxCURSOR_SIZENS); + break; + case wxHT_TOPLEVEL_BORDER_W: + case wxHT_TOPLEVEL_BORDER_E: + cursor = wxCursor(wxCURSOR_SIZEWE); + break; + case wxHT_TOPLEVEL_BORDER_NE: + case wxHT_TOPLEVEL_BORDER_SW: + cursor = wxCursor(wxCURSOR_SIZENESW); + break; + case wxHT_TOPLEVEL_BORDER_NW: + case wxHT_TOPLEVEL_BORDER_SE: + cursor = wxCursor(wxCURSOR_SIZENWSE); + break; + default: + return FALSE; + break; + } + return TRUE; + } + + return FALSE; +} + +#define wxINTERACTIVE_RESIZE_DIR \ + (wxINTERACTIVE_RESIZE_W | wxINTERACTIVE_RESIZE_E | \ + wxINTERACTIVE_RESIZE_S | wxINTERACTIVE_RESIZE_N) + +struct wxInteractiveMoveData +{ + wxTopLevelWindow *m_window; + wxEventLoop *m_evtLoop; + int m_flags; + wxRect m_rect; + wxRect m_rectOrig; + wxPoint m_pos; + wxSize m_minSize, m_maxSize; + bool m_sizingCursor; +}; + +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_evtLoop->Exit(); + } +} + +void wxInteractiveMoveHandler::OnKeyDown(wxKeyEvent& event) +{ + 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_WAIT_FOR_INPUT ) + { + m_data.m_flags &= ~wxINTERACTIVE_WAIT_FOR_INPUT; + if ( m_data.m_sizingCursor ) + { + wxEndBusyCursor(); + m_data.m_sizingCursor = FALSE; + } + + if ( m_data.m_flags & wxINTERACTIVE_MOVE ) + { + m_data.m_pos = m_data.m_window->GetPosition() + + wxPoint(m_data.m_window->GetSize().x/2, 8); + } + } + + wxPoint warp; + bool changeCur = FALSE; + + if ( m_data.m_flags & wxINTERACTIVE_MOVE ) + { + m_data.m_rect.Offset(diff); + m_data.m_window->Move(m_data.m_rect.GetPosition()); + warp = wxPoint(m_data.m_window->GetSize().x/2, 8); + } + else /* wxINTERACTIVE_RESIZE */ + { + if ( !(m_data.m_flags & + (wxINTERACTIVE_RESIZE_N | wxINTERACTIVE_RESIZE_S)) ) + { + if ( diff.y < 0 ) + { + m_data.m_flags |= wxINTERACTIVE_RESIZE_N; + m_data.m_pos.y = m_data.m_window->GetPosition().y; + changeCur = TRUE; + } + else if ( diff.y > 0 ) + { + m_data.m_flags |= wxINTERACTIVE_RESIZE_S; + m_data.m_pos.y = m_data.m_window->GetPosition().y + + m_data.m_window->GetSize().y; + changeCur = TRUE; + } + } + if ( !(m_data.m_flags & + (wxINTERACTIVE_RESIZE_W | wxINTERACTIVE_RESIZE_E)) ) + { + if ( diff.x < 0 ) + { + m_data.m_flags |= wxINTERACTIVE_RESIZE_W; + m_data.m_pos.x = m_data.m_window->GetPosition().x; + changeCur = TRUE; + } + else if ( diff.x > 0 ) + { + m_data.m_flags |= wxINTERACTIVE_RESIZE_E; + m_data.m_pos.x = m_data.m_window->GetPosition().x + + m_data.m_window->GetSize().x; + changeCur = TRUE; + } + } + + wxApplyResize(m_data, diff); + m_data.m_window->SetSize(m_data.m_rect); + + if ( m_data.m_flags & wxINTERACTIVE_RESIZE_W ) + warp.x = 0; + else if ( m_data.m_flags & wxINTERACTIVE_RESIZE_E ) + warp.x = m_data.m_window->GetSize().x-1; + else + warp.x = wxGetMousePosition().x - m_data.m_window->GetPosition().x; + + if ( m_data.m_flags & wxINTERACTIVE_RESIZE_N ) + warp.y = 0; + else if ( m_data.m_flags & wxINTERACTIVE_RESIZE_S ) + warp.y = m_data.m_window->GetSize().y-1; + else + warp.y = wxGetMousePosition().y - m_data.m_window->GetPosition().y; + } + + warp -= m_data.m_window->GetClientAreaOrigin(); + m_data.m_window->WarpPointer(warp.x, warp.y); + + if ( changeCur ) + { + long hit = m_data.m_window->HitTest(warp); + wxCursor cur; + if ( wxGetResizingCursor(hit, cur) ) + { + if ( m_data.m_sizingCursor ) + wxEndBusyCursor(); + wxBeginBusyCursor(&cur); + m_data.m_sizingCursor = TRUE; + } + } + } +} + +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; + + SetFocus(); + +#ifndef __WXGTK__ + if ( flags & wxINTERACTIVE_WAIT_FOR_INPUT ) + { + wxCursor sizingCursor(wxCURSOR_SIZING); + wxBeginBusyCursor(&sizingCursor); + data.m_sizingCursor = TRUE; + } + else +#endif + data.m_sizingCursor = FALSE; + + 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()); + + wxEvtHandler *handler = new wxInteractiveMoveHandler(data); + this->PushEventHandler(handler); + + CaptureMouse(); + loop.Run(); + ReleaseMouse(); + + this->RemoveEventHandler(handler); + delete handler; + + if ( data.m_sizingCursor ) + wxEndBusyCursor(); +} + // ---------------------------------------------------------------------------- // actions // ---------------------------------------------------------------------------- @@ -400,6 +751,43 @@ bool wxTopLevelWindow::PerformAction(const wxControlAction& action, return FALSE; } +void wxTopLevelWindow::OnSystemMenu(wxCommandEvent& event) +{ + bool ret = TRUE; + + switch (event.GetId()) + { + case wxID_CLOSE_FRAME: + ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, + wxTOPLEVEL_BUTTON_CLOSE); + break; + case wxID_MOVE_FRAME: + InteractiveMove(wxINTERACTIVE_MOVE | wxINTERACTIVE_WAIT_FOR_INPUT); + break; + case wxID_RESIZE_FRAME: + InteractiveMove(wxINTERACTIVE_RESIZE | wxINTERACTIVE_WAIT_FOR_INPUT); + break; + case wxID_MAXIMIZE_FRAME: + ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, + wxTOPLEVEL_BUTTON_MAXIMIZE); + break; + case wxID_ICONIZE_FRAME: + ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, + wxTOPLEVEL_BUTTON_ICONIZE); + break; + case wxID_RESTORE_FRAME: + ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, + wxTOPLEVEL_BUTTON_RESTORE); + break; + + default: + ret = FALSE; + } + + if ( !ret ) + event.Skip(); +} + // ============================================================================ // wxStdFrameInputHandler: handles focus, resizing and titlebar buttons clicks @@ -441,7 +829,7 @@ bool wxStdFrameInputHandler::HandleMouse(wxInputConsumer *consumer, consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed); return TRUE; } - else if ( hit & wxHT_TOPLEVEL_TITLEBAR ) + else if ( (hit & wxHT_TOPLEVEL_TITLEBAR) && !w->IsMaximized() ) { consumer->PerformAction(wxACTION_TOPLEVEL_MOVE); return TRUE; @@ -511,31 +899,9 @@ bool wxStdFrameInputHandler::HandleMouseMove(wxInputConsumer *consumer, if ( hit & wxHT_TOPLEVEL_ANY_BORDER ) { - m_borderCursorOn = TRUE; wxCursor cur; - switch (hit) - { - case wxHT_TOPLEVEL_BORDER_N: - case wxHT_TOPLEVEL_BORDER_S: - cur = wxCursor(wxCURSOR_SIZENS); - break; - case wxHT_TOPLEVEL_BORDER_W: - case wxHT_TOPLEVEL_BORDER_E: - cur = wxCursor(wxCURSOR_SIZEWE); - break; - case wxHT_TOPLEVEL_BORDER_NE: - case wxHT_TOPLEVEL_BORDER_SW: - cur = wxCursor(wxCURSOR_SIZENESW); - break; - case wxHT_TOPLEVEL_BORDER_NW: - case wxHT_TOPLEVEL_BORDER_SE: - cur = wxCursor(wxCURSOR_SIZENWSE); - break; - default: - m_borderCursorOn = FALSE; - break; - } + m_borderCursorOn = wxGetResizingCursor(hit, cur); if ( m_borderCursorOn ) { m_origCursor = win->GetCursor();