X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9b8270da40a00836c356b36a02905f2b80a51aa1..dfe8399aa013a1fa6487d008bf1176078f218c6d:/src/univ/themes/win32.cpp diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index 936c895687..4f02fc9394 100644 --- a/src/univ/themes/win32.cpp +++ b/src/univ/themes/win32.cpp @@ -50,9 +50,10 @@ #include "wx/spinbutt.h" #include "wx/settings.h" #include "wx/menu.h" +#include "wx/artprov.h" +#include "wx/toplevel.h" #include "wx/univ/scrtimer.h" -#include "wx/toplevel.h" #include "wx/univ/renderer.h" #include "wx/univ/inphand.h" #include "wx/univ/colschem.h" @@ -147,7 +148,8 @@ public: virtual void DrawBackground(wxDC& dc, const wxColour& col, const wxRect& rect, - int flags = 0); + int flags = 0, + wxWindow *window = NULL); virtual void DrawLabel(wxDC& dc, const wxString& label, const wxRect& rect, @@ -321,8 +323,6 @@ public: virtual wxSize GetFrameIconSize() const; virtual int HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const; - virtual wxIcon GetStdIcon(int which) const; - virtual void GetComboBitmaps(wxBitmap *bmpNormal, wxBitmap *bmpFocus, wxBitmap *bmpPressed, @@ -355,7 +355,7 @@ public: virtual wxSize GetToolBarButtonSize(wxCoord *separator) const { if ( separator ) *separator = 5; return wxSize(16, 15); } virtual wxSize GetToolBarMargin() const - { return wxSize(6, 6); } + { return wxSize(4, 4); } virtual wxRect GetTextTotalArea(const wxTextCtrl *text, const wxRect& rect) const; @@ -405,7 +405,8 @@ protected: // DrawButtonBorder() helper void DoDrawBackground(wxDC& dc, const wxColour& col, - const wxRect& rect); + const wxRect& rect, + wxWindow *window = NULL ); // DrawBorder() helpers: all of them shift and clip the DC after drawing // the border @@ -597,14 +598,24 @@ private: bool m_isOnGrip; }; +class wxWin32SystemMenuEvtHandler; + class wxWin32FrameInputHandler : public wxStdFrameInputHandler { public: - wxWin32FrameInputHandler(wxInputHandler *handler) - : wxStdFrameInputHandler(handler) { } + wxWin32FrameInputHandler(wxInputHandler *handler); + ~wxWin32FrameInputHandler(); virtual bool HandleMouse(wxInputConsumer *control, const wxMouseEvent& event); + + virtual bool HandleActivation(wxInputConsumer *consumer, bool activated); + + void PopupSystemMenu(wxTopLevelWindow *window, const wxPoint& pos) const; + +private: + // was the mouse over the grip last time we checked? + wxWin32SystemMenuEvtHandler *m_menuHandler; }; // ---------------------------------------------------------------------------- @@ -618,6 +629,18 @@ public: virtual wxColour GetBackground(wxWindow *win) const; }; +// ---------------------------------------------------------------------------- +// wxWin32ArtProvider +// ---------------------------------------------------------------------------- + +class wxWin32ArtProvider : public wxArtProvider +{ +protected: + virtual wxBitmap CreateBitmap(const wxArtID& id, + const wxArtClient& client, + const wxSize& size); +}; + // ---------------------------------------------------------------------------- // wxWin32Theme // ---------------------------------------------------------------------------- @@ -631,6 +654,7 @@ public: virtual ~wxWin32Theme(); virtual wxRenderer *GetRenderer(); + virtual wxArtProvider *GetArtProvider(); virtual wxInputHandler *GetInputHandler(const wxString& control); virtual wxColourScheme *GetColourScheme(); @@ -639,6 +663,8 @@ private: wxInputHandler *GetDefaultInputHandler(); wxWin32Renderer *m_renderer; + + wxWin32ArtProvider *m_artProvider; // the names of the already created handlers and the handlers themselves // (these arrays are synchronized) @@ -1177,6 +1203,16 @@ wxRenderer *wxWin32Theme::GetRenderer() return m_renderer; } +wxArtProvider *wxWin32Theme::GetArtProvider() +{ + if ( !m_artProvider ) + { + m_artProvider = new wxWin32ArtProvider; + } + + return m_artProvider; +} + wxInputHandler *wxWin32Theme::GetDefaultInputHandler() { if ( !m_handlerDefault ) @@ -1328,8 +1364,12 @@ wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col) const case CONTROL_TEXT: return wxColour(GetSysColor(COLOR_BTNTEXT)); - case SCROLLBAR: return wxColour(GetSysColor(COLOR_SCROLLBAR)); - case SCROLLBAR_PRESSED: return wxColour(GetSysColor(COLOR_HIGHLIGHT)); +#if defined(COLOR_3DLIGHT) + case SCROLLBAR: return wxColour(GetSysColor(COLOR_3DLIGHT)); +#else + case SCROLLBAR: return wxColour(0xe0e0e0); +#endif + case SCROLLBAR_PRESSED: return wxColour(GetSysColor(COLOR_BTNTEXT)); case HIGHLIGHT: return wxColour(GetSysColor(COLOR_HIGHLIGHT)); case HIGHLIGHT_TEXT: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT)); @@ -1826,8 +1866,12 @@ wxRect wxWin32Renderer::GetBorderDimensions(wxBorder border) const break; default: + { + // char *crash = NULL; + // *crash = 0; wxFAIL_MSG(_T("unknown border type")); // fall through + } case wxBORDER_DEFAULT: case wxBORDER_NONE: @@ -2371,7 +2415,11 @@ void wxWin32Renderer::DrawToolBarButton(wxDC& dc, } else // a separator { - // TODO + // leave a small gap aroudn the line, also account for the toolbar + // border itself + DrawVerticalLine(dc, rectOrig.x + rectOrig.width/2, + rectOrig.y + 2*BORDER_THICKNESS, + rectOrig.GetBottom() - BORDER_THICKNESS); } } @@ -3157,7 +3205,8 @@ void wxWin32Renderer::GetComboBitmaps(wxBitmap *bmpNormal, void wxWin32Renderer::DoDrawBackground(wxDC& dc, const wxColour& col, - const wxRect& rect) + const wxRect& rect, + wxWindow *window ) { wxBrush brush(col, wxSOLID); dc.SetBrush(brush); @@ -3168,11 +3217,12 @@ void wxWin32Renderer::DoDrawBackground(wxDC& dc, void wxWin32Renderer::DrawBackground(wxDC& dc, const wxColour& col, const wxRect& rect, - int flags) + int flags, + wxWindow *window ) { // just fill it with the given or default bg colour wxColour colBg = col.Ok() ? col : wxSCHEME_COLOUR(m_scheme, CONTROL); - DoDrawBackground(dc, colBg, rect); + DoDrawBackground(dc, colBg, rect, window ); } // ---------------------------------------------------------------------------- @@ -3839,26 +3889,19 @@ static char *warning_xpm[]={ "....ddddddddddddddddddddddddddd.", ".....ddddddddddddddddddddddddd.."}; -wxIcon wxWin32Renderer::GetStdIcon(int which) const +wxBitmap wxWin32ArtProvider::CreateBitmap(const wxArtID& id, + const wxArtClient& WXUNUSED(client), + const wxSize& WXUNUSED(size)) { - 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); - } + if ( id == wxART_INFORMATION ) + return wxBitmap(info_xpm); + if ( id == wxART_ERROR ) + return wxBitmap(error_xpm); + if ( id == wxART_WARNING ) + return wxBitmap(warning_xpm); + if ( id == wxART_QUESTION ) + return wxBitmap(question_xpm); + return wxNullBitmap; } @@ -4106,6 +4149,8 @@ bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxInputConsumer *control, // if we're scrolling the scrollbar because the arrow or the shaft was // pressed, check that the mouse stays on the same scrollbar element +#if 0 + // Always let thumb jump back if we leave the scrollbar if ( event.Moving() ) { ht = m_renderer->HitTestScrollbar(scrollbar, event.GetPosition()); @@ -4114,6 +4159,21 @@ bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxInputConsumer *control, { ht = wxHT_NOWHERE; } +#else + // Jump back only if we get far away from it + wxPoint pos = event.GetPosition(); + if (scrollbar->HasFlag( wxVERTICAL )) + { + if (pos.x > -40 && pos.x < scrollbar->GetSize().x+40) + pos.x = 5; + } + else + { + if (pos.y > -40 && pos.y < scrollbar->GetSize().y+40) + pos.y = 5; + } + ht = m_renderer->HitTestScrollbar(scrollbar, pos ); +#endif // if we're dragging the thumb and the mouse stays in the scrollbar, it // is still ok - we only want to catch the case when the mouse leaves @@ -4332,25 +4392,188 @@ bool wxWin32StatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer, // wxWin32FrameInputHandler // ---------------------------------------------------------------------------- +class wxWin32SystemMenuEvtHandler : public wxEvtHandler +{ +public: + wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler); + + void Attach(wxInputConsumer *consumer); + void Detach(); + +private: + DECLARE_EVENT_TABLE() + void OnSystemMenu(wxCommandEvent &event); + void OnCloseFrame(wxCommandEvent &event); + void OnClose(wxCloseEvent &event); + + wxWin32FrameInputHandler *m_inputHnd; + wxTopLevelWindow *m_wnd; + wxAcceleratorTable m_oldAccelTable; +}; + +wxWin32SystemMenuEvtHandler::wxWin32SystemMenuEvtHandler( + wxWin32FrameInputHandler *handler) +{ + m_inputHnd = handler; + m_wnd = NULL; +} + +void wxWin32SystemMenuEvtHandler::Attach(wxInputConsumer *consumer) +{ + wxASSERT_MSG( m_wnd == NULL, _T("can't attach the handler twice!") ); + + m_wnd = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow); + m_wnd->PushEventHandler(this); + + // VS: This code relies on using generic implementation of + // wxAcceleratorTable in wxUniv! + wxAcceleratorTable table = *m_wnd->GetAcceleratorTable(); + m_oldAccelTable = table; + table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_SPACE, wxID_SYSTEM_MENU)); + table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_F4, wxID_CLOSE_FRAME)); + m_wnd->SetAcceleratorTable(table); +} + +void wxWin32SystemMenuEvtHandler::Detach() +{ + if ( m_wnd ) + { + m_wnd->SetAcceleratorTable(m_oldAccelTable); + m_wnd->RemoveEventHandler(this); + m_wnd = NULL; + } +} + +BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler, wxEvtHandler) + EVT_MENU(wxID_SYSTEM_MENU, wxWin32SystemMenuEvtHandler::OnSystemMenu) + EVT_MENU(wxID_CLOSE_FRAME, wxWin32SystemMenuEvtHandler::OnCloseFrame) + EVT_CLOSE(wxWin32SystemMenuEvtHandler::OnClose) +END_EVENT_TABLE() + +void wxWin32SystemMenuEvtHandler::OnSystemMenu(wxCommandEvent &WXUNUSED(event)) +{ + int border = ((m_wnd->GetWindowStyle() & wxRESIZE_BORDER) && + !m_wnd->IsMaximized()) ? + RESIZEABLE_FRAME_BORDER_THICKNESS : + FRAME_BORDER_THICKNESS; + wxPoint pt = m_wnd->GetClientAreaOrigin(); + pt.x = -pt.x + border; + pt.y = -pt.y + border + FRAME_TITLEBAR_HEIGHT; + + wxAcceleratorTable table = *m_wnd->GetAcceleratorTable(); + m_wnd->SetAcceleratorTable(wxNullAcceleratorTable); + m_inputHnd->PopupSystemMenu(m_wnd, pt); + m_wnd->SetAcceleratorTable(table); +} + +void wxWin32SystemMenuEvtHandler::OnCloseFrame(wxCommandEvent &WXUNUSED(event)) +{ + m_wnd->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, + wxTOPLEVEL_BUTTON_CLOSE); +} + +void wxWin32SystemMenuEvtHandler::OnClose(wxCloseEvent &event) +{ + m_wnd = NULL; + event.Skip(); +} + + +wxWin32FrameInputHandler::wxWin32FrameInputHandler(wxInputHandler *handler) + : wxStdFrameInputHandler(handler) +{ + m_menuHandler = new wxWin32SystemMenuEvtHandler(this); +} + +wxWin32FrameInputHandler::~wxWin32FrameInputHandler() +{ + if ( m_menuHandler ) + { + m_menuHandler->Detach(); + delete m_menuHandler; + } +} + bool wxWin32FrameInputHandler::HandleMouse(wxInputConsumer *consumer, const wxMouseEvent& event) { - if ( event.LeftDClick() ) + if ( event.LeftDClick() || event.LeftDown() || event.RightDown() ) { wxTopLevelWindow *tlw = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow); long hit = tlw->HitTest(event.GetPosition()); - if ( hit == wxHT_TOPLEVEL_TITLEBAR ) + if ( event.LeftDClick() && hit == wxHT_TOPLEVEL_TITLEBAR ) { tlw->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, tlw->IsMaximized() ? wxTOPLEVEL_BUTTON_RESTORE : wxTOPLEVEL_BUTTON_MAXIMIZE); return TRUE; } + else if ( tlw->GetWindowStyle() & wxSYSTEM_MENU ) + { + if ( (event.LeftDown() && hit == wxHT_TOPLEVEL_ICON) || + (event.RightDown() && + (hit == wxHT_TOPLEVEL_TITLEBAR || + hit == wxHT_TOPLEVEL_ICON)) ) + { + PopupSystemMenu(tlw, event.GetPosition()); + return TRUE; + } + } } return wxStdFrameInputHandler::HandleMouse(consumer, event); } +void wxWin32FrameInputHandler::PopupSystemMenu(wxTopLevelWindow *window, + const wxPoint& pos) const +{ + wxMenu *menu = new wxMenu; + + if ( window->GetWindowStyle() & wxMAXIMIZE_BOX ) + menu->Append(wxID_RESTORE_FRAME , _("&Restore")); + menu->Append(wxID_MOVE_FRAME , _("&Move")); + if ( window->GetWindowStyle() & wxRESIZE_BORDER ) + menu->Append(wxID_RESIZE_FRAME , _("&Size")); + if ( wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME) ) + menu->Append(wxID_ICONIZE_FRAME , _("Mi&nimize")); + if ( window->GetWindowStyle() & wxMAXIMIZE_BOX ) + menu->Append(wxID_MAXIMIZE_FRAME , _("Ma&ximize")); + menu->AppendSeparator(); + menu->Append(wxID_CLOSE_FRAME, _("Close\tAlt-F4")); + + if ( window->GetWindowStyle() & wxMAXIMIZE_BOX ) + { + if ( window->IsMaximized() ) + { + menu->Enable(wxID_MAXIMIZE_FRAME, FALSE); + menu->Enable(wxID_MOVE_FRAME, FALSE); + if ( window->GetWindowStyle() & wxRESIZE_BORDER ) + menu->Enable(wxID_RESIZE_FRAME, FALSE); + } + else + menu->Enable(wxID_RESTORE_FRAME, FALSE); + } + + window->PopupMenu(menu, pos); + delete menu; +} + +bool wxWin32FrameInputHandler::HandleActivation(wxInputConsumer *consumer, + bool activated) +{ + if ( consumer->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU ) + { + // always detach if active frame changed: + m_menuHandler->Detach(); + + if ( activated ) + { + m_menuHandler->Attach(consumer); + } + } + + return wxStdFrameInputHandler::HandleActivation(consumer, activated); +}