X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b22d16ad20a51052d24d538c22237c97b0ee0b53..859e65deb544f039ff4a889da0a8047a0b8c9ca2:/src/univ/topluniv.cpp diff --git a/src/univ/topluniv.cpp b/src/univ/topluniv.cpp index 959e5f278a..c5ffe12df3 100644 --- a/src/univ/topluniv.cpp +++ b/src/univ/topluniv.cpp @@ -26,12 +26,18 @@ #endif #include "wx/defs.h" + +#ifndef WX_PRECOMP + #include "wx/dcclient.h" + #include "wx/settings.h" +#endif + #include "wx/toplevel.h" #include "wx/univ/renderer.h" -#include "wx/dcclient.h" #include "wx/bitmap.h" #include "wx/image.h" #include "wx/cshelp.h" +#include "wx/evtloop.h" // ---------------------------------------------------------------------------- @@ -50,6 +56,7 @@ WX_FORWARD_TO_INPUT_CONSUMER(wxTopLevelWindow) // ============================================================================ int wxTopLevelWindow::ms_drawDecorations = -1; +int wxTopLevelWindow::ms_canIconize = -1; void wxTopLevelWindow::Init() { @@ -71,9 +78,18 @@ bool wxTopLevelWindow::Create(wxWindow *parent, exstyleOrig = 0; if ( ms_drawDecorations == -1 ) - ms_drawDecorations = TRUE; - // FIXME_MGL -- this is temporary; we assume for now that native TLW - // can't do decorations, which is not true + { + 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 ) { @@ -93,15 +109,6 @@ bool wxTopLevelWindow::Create(wxWindow *parent, size, style, name) ) return FALSE; - // FIXME: to be removed as soon as wxTLW/wxFrame/wxDialog creation code in - // wxMSW is rationalized -#ifdef __WXMSW__ - extern const wxChar *wxFrameClassName; - if ( !MSWCreate(id, NULL, wxFrameClassName, this, title, - pos.x, pos.y, size.x, size.y, style) ) - return FALSE; -#endif // __WXMSW__ - if ( ms_drawDecorations ) { m_windowStyle = styleOrig; @@ -141,10 +148,15 @@ 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 ) - style |= wxTOPLEVEL_BUTTON_MAXIMIZE; + { + if ( IsMaximized() ) + style |= wxTOPLEVEL_BUTTON_RESTORE; + else + style |= wxTOPLEVEL_BUTTON_MAXIMIZE; + } #if wxUSE_HELP if ( m_exStyle & (wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP)) style |= wxTOPLEVEL_BUTTON_HELP; @@ -254,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()); } // ---------------------------------------------------------------------------- @@ -264,29 +276,247 @@ long wxTopLevelWindow::HitTest(const wxPoint& pt) const void wxTopLevelWindow::SetIcon(const wxIcon& icon) { wxTopLevelWindowNative::SetIcon(icon); - if ( !m_renderer ) return; - wxSize size = m_renderer->GetFrameIconSize(); - - if ( !icon.Ok() || size.x == -1 ) - m_titlebarIcon = icon; - else + if ( ms_drawDecorations && m_renderer ) { - wxBitmap bmp1; - bmp1.CopyFromIcon(icon); - if ( !bmp1.Ok() ) - m_titlebarIcon = wxNullIcon; - else if ( bmp1.GetWidth() == size.x && bmp1.GetHeight() == size.y ) + wxSize size = m_renderer->GetFrameIconSize(); + + if ( !icon.Ok() || size.x == -1 ) m_titlebarIcon = icon; else { - wxImage img = bmp1.ConvertToImage(); - img.Rescale(size.x, size.y); - m_titlebarIcon.CopyFromBitmap(wxBitmap(img)); + wxBitmap bmp1; + bmp1.CopyFromIcon(icon); + if ( !bmp1.Ok() ) + m_titlebarIcon = wxNullIcon; + else if ( bmp1.GetWidth() == size.x && bmp1.GetHeight() == size.y ) + m_titlebarIcon = icon; + else + { + wxImage img = bmp1.ConvertToImage(); + img.Rescale(size.x, size.y); + m_titlebarIcon.CopyFromBitmap(wxBitmap(img)); + } } } } +// ---------------------------------------------------------------------------- +// 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 // ---------------------------------------------------------------------------- @@ -361,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; @@ -382,7 +612,7 @@ bool wxTopLevelWindow::PerformAction(const wxControlAction& action, InteractiveMove(flags); return TRUE; } - + else return FALSE; } @@ -482,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: