X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/62e1ba759a61210a7facf7b9de39fc8bf0f4b479..baaae89f09ece7ab8a17570ee535683b9d14aeda:/src/univ/themes/win32.cpp diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index 75adfec94e..ccf87bc3ff 100644 --- a/src/univ/themes/win32.cpp +++ b/src/univ/themes/win32.cpp @@ -38,6 +38,7 @@ #include "wx/scrolbar.h" #include "wx/slider.h" #include "wx/textctrl.h" + #include "wx/toolbar.h" #ifdef __WXMSW__ // for COLOR_* constants @@ -49,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" @@ -146,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, @@ -228,6 +231,11 @@ public: int flags = 0, wxAlignment align = wxALIGN_LEFT, int indexAccel = -1); + virtual void DrawToolBarButton(wxDC& dc, + const wxString& label, + const wxBitmap& bitmap, + const wxRect& rect, + int flags); virtual void DrawTextLine(wxDC& dc, const wxString& text, const wxRect& rect, @@ -311,11 +319,10 @@ public: int flags = 0); virtual wxRect GetFrameClientArea(const wxRect& rect, int flags) const; virtual wxSize GetFrameTotalSize(const wxSize& clientSize, int flags) const; + virtual wxSize GetFrameMinSize(int flags) const; 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, @@ -345,11 +352,16 @@ public: virtual wxCoord GetCheckItemMargin() const { return 0; } + virtual wxSize GetToolBarButtonSize(wxCoord *separator) const + { if ( separator ) *separator = 5; return wxSize(16, 15); } + virtual wxSize GetToolBarMargin() const + { return wxSize(4, 4); } + virtual wxRect GetTextTotalArea(const wxTextCtrl *text, - const wxRect& rect); + const wxRect& rect) const; virtual wxRect GetTextClientArea(const wxTextCtrl *text, const wxRect& rect, - wxCoord *extraSpaceBeyond); + wxCoord *extraSpaceBeyond) const; virtual wxSize GetTabIndent() const { return wxSize(2, 2); } virtual wxSize GetTabPadding() const { return wxSize(6, 5); } @@ -393,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 @@ -474,6 +487,14 @@ private: wxFont m_titlebarFont; + // the checked and unchecked bitmaps for DrawCheckItem() + wxBitmap m_bmpCheckBitmaps[IndicatorStatus_Max]; + + // the bitmaps returned by GetIndicator() + wxBitmap m_bmpIndicators[IndicatorType_Max] + [IndicatorState_Max] + [IndicatorStatus_Max]; + // titlebar icons: wxBitmap m_bmpFrameButtons[FrameButton_Max]; @@ -577,6 +598,26 @@ private: bool m_isOnGrip; }; +class wxWin32SystemMenuEvtHandler; + +class wxWin32FrameInputHandler : public wxStdFrameInputHandler +{ +public: + 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; +}; + // ---------------------------------------------------------------------------- // wxWin32ColourScheme: uses (default) Win32 colours // ---------------------------------------------------------------------------- @@ -588,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 // ---------------------------------------------------------------------------- @@ -601,6 +654,7 @@ public: virtual ~wxWin32Theme(); virtual wxRenderer *GetRenderer(); + virtual wxArtProvider *GetArtProvider(); virtual wxInputHandler *GetInputHandler(const wxString& control); virtual wxColourScheme *GetColourScheme(); @@ -609,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) @@ -630,8 +686,8 @@ private: static const char *frame_button_close_xpm[] = { "12 10 2 1", -" c None", -". c black", +" c None", +". c black", " ", " .. .. ", " .. .. ", @@ -645,8 +701,8 @@ static const char *frame_button_close_xpm[] = { static const char *frame_button_help_xpm[] = { "12 10 2 1", -" c None", -". c #000000", +" c None", +". c #000000", " .... ", " .. .. ", " .. .. ", @@ -660,8 +716,8 @@ static const char *frame_button_help_xpm[] = { static const char *frame_button_maximize_xpm[] = { "12 10 2 1", -" c None", -". c #000000", +" c None", +". c #000000", " ......... ", " ......... ", " . . ", @@ -675,8 +731,8 @@ static const char *frame_button_maximize_xpm[] = { static const char *frame_button_minimize_xpm[] = { "12 10 2 1", -" c None", -". c #000000", +" c None", +". c #000000", " ", " ", " ", @@ -690,8 +746,8 @@ static const char *frame_button_minimize_xpm[] = { static const char *frame_button_restore_xpm[] = { "12 10 2 1", -" c None", -". c #000000", +" c None", +". c #000000", " ...... ", " ...... ", " . . ", @@ -1057,7 +1113,7 @@ static const char *pressed_unchecked_radio_xpm[] = { }; static const char ** - bmpIndicators[IndicatorType_Max][IndicatorState_Max][IndicatorStatus_Max] = + xpmIndicators[IndicatorType_Max][IndicatorState_Max][IndicatorStatus_Max] = { // checkboxes first { @@ -1099,6 +1155,12 @@ static const char ** } }; +static const char **xpmChecked[IndicatorStatus_Max] = +{ + checked_item_xpm, + unchecked_item_xpm +}; + // ============================================================================ // implementation // ============================================================================ @@ -1114,6 +1176,7 @@ wxWin32Theme::wxWin32Theme() m_scheme = NULL; m_renderer = NULL; m_handlerDefault = NULL; + m_artProvider = NULL; } wxWin32Theme::~wxWin32Theme() @@ -1129,6 +1192,7 @@ wxWin32Theme::~wxWin32Theme() delete m_renderer; delete m_scheme; + wxArtProvider::RemoveProvider(m_artProvider); } wxRenderer *wxWin32Theme::GetRenderer() @@ -1141,6 +1205,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 ) @@ -1201,8 +1275,12 @@ wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control) else if ( control == wxINP_HANDLER_STATUSBAR ) handler = new wxWin32StatusBarInputHandler(GetDefaultInputHandler()); #endif // wxUSE_STATUSBAR +#if wxUSE_TOOLBAR + else if ( control == wxINP_HANDLER_TOOLBAR ) + handler = new wxStdToolbarInputHandler(GetDefaultInputHandler()); +#endif // wxUSE_TOOLBAR else if ( control == wxINP_HANDLER_TOPLEVEL ) - handler = new wxStdFrameInputHandler(GetDefaultInputHandler()); + handler = new wxWin32FrameInputHandler(GetDefaultInputHandler()); else handler = GetDefaultInputHandler(); @@ -1261,7 +1339,7 @@ wxColour wxWin32ColourScheme::GetBackground(wxWindow *win) const // the colour set by the user should be used for the normal state // and for the states for which we don't have any specific colours - if ( !col.Ok() || (flags != 0) ) + if ( !col.Ok() || (flags & wxCONTROL_PRESSED) != 0 ) { if ( wxDynamicCast(win, wxScrollBar) ) col = Get(flags & wxCONTROL_PRESSED ? SCROLLBAR_PRESSED @@ -1288,8 +1366,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)); @@ -1297,7 +1379,7 @@ wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col) const #if defined(COLOR_3DDKSHADOW) case SHADOW_DARK: return wxColour(GetSysColor(COLOR_3DDKSHADOW)); #else - case SHADOW_DARK: return *wxBLACK; + case SHADOW_DARK: return wxColour(GetSysColor(COLOR_3DHADOW)); #endif case CONTROL_TEXT_DISABLED: @@ -1312,7 +1394,7 @@ wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col) const case TITLEBAR_ACTIVE: return wxColour(GetSysColor(COLOR_ACTIVECAPTION)); case TITLEBAR_TEXT: return wxColour(GetSysColor(COLOR_INACTIVECAPTIONTEXT)); case TITLEBAR_ACTIVE_TEXT: return wxColour(GetSysColor(COLOR_CAPTIONTEXT)); - + case DESKTOP: return wxColour(0x808000); #else // !__WXMSW__ // use the standard Windows colours elsewhere @@ -1348,6 +1430,8 @@ wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col) const case DESKTOP: return wxColour(0x808000); #endif // __WXMSW__ + case GAUGE: return Get(HIGHLIGHT); + case MAX: default: wxFAIL_MSG(_T("invalid standard colour")); @@ -1380,7 +1464,7 @@ wxWin32Renderer::wxWin32Renderer(const wxColourScheme *scheme) m_colHighlight = wxSCHEME_COLOUR(scheme, SHADOW_HIGHLIGHT); m_penHighlight = wxPen(m_colHighlight, 0, wxSOLID); - m_titlebarFont = wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT); + m_titlebarFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); m_titlebarFont.SetWeight(wxFONTWEIGHT_BOLD); // init the arrow bitmaps @@ -1784,8 +1868,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: @@ -2158,8 +2246,16 @@ void wxWin32Renderer::DrawCheckItem(wxDC& dc, } else // use default bitmap { - bmp = wxBitmap(flags & wxCONTROL_CHECKED ? checked_item_xpm - : unchecked_item_xpm); + IndicatorStatus i = flags & wxCONTROL_CHECKED + ? IndicatorStatus_Checked + : IndicatorStatus_Unchecked; + + if ( !m_bmpCheckBitmaps[i].Ok() ) + { + m_bmpCheckBitmaps[i] = wxBitmap(xpmChecked[i]); + } + + bmp = m_bmpCheckBitmaps[i]; } dc.DrawBitmap(bmp, rect.x, rect.y + (rect.height - bmp.GetHeight()) / 2 - 1, @@ -2194,14 +2290,19 @@ wxBitmap wxWin32Renderer::GetIndicator(IndicatorType indType, int flags) ? IndicatorStatus_Checked : IndicatorStatus_Unchecked; - const char **xpm = bmpIndicators[indType][indState][indStatus]; - if (xpm) + wxBitmap bmp = m_bmpIndicators[indType][indState][indStatus]; + if ( !bmp.Ok() ) { - wxBitmap bmp(xpm); - return bmp; + const char **xpm = xpmIndicators[indType][indState][indStatus]; + if ( xpm ) + { + // create and cache it + bmp = wxBitmap(xpm); + m_bmpIndicators[indType][indState][indStatus] = bmp; + } } - else - return wxNullBitmap; + + return bmp; } void wxWin32Renderer::DrawCheckOrRadioButton(wxDC& dc, @@ -2239,7 +2340,6 @@ void wxWin32Renderer::DrawCheckOrRadioButton(wxDC& dc, rectLabel.SetRight(rect.GetRight()); } - // THIS IS THE CULPRIT -- JACS dc.DrawBitmap(bitmap, xBmp, yBmp, TRUE /* use mask */); DoDrawLabel( @@ -2261,19 +2361,16 @@ void wxWin32Renderer::DrawRadioButton(wxDC& dc, wxAlignment align, int indexAccel) { - if (bitmap.Ok()) - DrawCheckOrRadioButton(dc, label, - bitmap, - rect, flags, align, indexAccel, - FOCUS_RECT_OFFSET_Y); // default focus rect offset + wxBitmap bmp; + if ( bitmap.Ok() ) + bmp = bitmap; else - { - wxBitmap rbitmap(GetRadioBitmap(flags)); - DrawCheckOrRadioButton(dc, label, - rbitmap, + bmp = GetRadioBitmap(flags); + + DrawCheckOrRadioButton(dc, label, + bmp, rect, flags, align, indexAccel, - FOCUS_RECT_OFFSET_Y); // default focus rect offset - } + FOCUS_RECT_OFFSET_Y); // default focus rect offset } void wxWin32Renderer::DrawCheckButton(wxDC& dc, @@ -2284,20 +2381,47 @@ void wxWin32Renderer::DrawCheckButton(wxDC& dc, wxAlignment align, int indexAccel) { - if (bitmap.Ok()) - DrawCheckOrRadioButton(dc, label, - bitmap, - rect, flags, align, indexAccel, - 0); // no focus rect offset for checkboxes + wxBitmap bmp; + if ( bitmap.Ok() ) + bmp = bitmap; else + bmp = GetCheckBitmap(flags); + + DrawCheckOrRadioButton(dc, label, + bmp, + rect, flags, align, indexAccel, + 0); // no focus rect offset for checkboxes +} + +void wxWin32Renderer::DrawToolBarButton(wxDC& dc, + const wxString& label, + const wxBitmap& bitmap, + const wxRect& rectOrig, + int flags) +{ + if ( !label.empty() || bitmap.Ok() ) { - wxBitmap cbitmap(GetCheckBitmap(flags)); -#if 1 - DrawCheckOrRadioButton(dc, label, - cbitmap, - rect, flags, align, indexAccel, - 0); // no focus rect offset for checkboxes -#endif + wxRect rect = rectOrig; + rect.Deflate(BORDER_THICKNESS); + + if ( flags & wxCONTROL_PRESSED ) + { + DrawBorder(dc, wxBORDER_SUNKEN, rect, flags); + } + else if ( flags & wxCONTROL_CURRENT ) + { + DrawBorder(dc, wxBORDER_RAISED, rect, flags); + } + + dc.DrawLabel(label, bitmap, rect, wxALIGN_CENTRE); + } + else // a separator + { + // 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); } } @@ -2876,7 +3000,7 @@ wxMenuGeometryInfo *wxWin32Renderer::GetMenuGeometry(wxWindow *win, { // prepare the dc: for now we draw all the items with the system font wxClientDC dc(win); - dc.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT)); + dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); // the height of a normal item wxCoord heightText = dc.GetCharHeight(); @@ -3083,7 +3207,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); @@ -3094,11 +3219,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 ); } // ---------------------------------------------------------------------------- @@ -3412,13 +3538,62 @@ void wxWin32Renderer::DrawFrameTitle(wxDC& dc, wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR); r.height = FRAME_TITLEBAR_HEIGHT; if ( flags & wxTOPLEVEL_ICON ) + { r.x += FRAME_TITLEBAR_HEIGHT; + r.width -= FRAME_TITLEBAR_HEIGHT + 2; + } else + { r.x += 1; + r.width -= 3; + } + + if ( flags & wxTOPLEVEL_BUTTON_CLOSE ) + r.width -= FRAME_BUTTON_WIDTH + 2; + if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE ) + r.width -= FRAME_BUTTON_WIDTH; + if ( flags & wxTOPLEVEL_BUTTON_RESTORE ) + r.width -= FRAME_BUTTON_WIDTH; + if ( flags & wxTOPLEVEL_BUTTON_ICONIZE ) + r.width -= FRAME_BUTTON_WIDTH; + if ( flags & wxTOPLEVEL_BUTTON_HELP ) + r.width -= FRAME_BUTTON_WIDTH; dc.SetFont(m_titlebarFont); dc.SetTextForeground(col); - dc.DrawLabel(title, wxNullBitmap, r, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL); + + wxCoord textW; + dc.GetTextExtent(title, &textW, NULL); + if ( textW > r.width ) + { + // text is too big, let's shorten it and add "..." after it: + size_t len = title.length(); + wxCoord WSoFar, letterW; + + dc.GetTextExtent(wxT("..."), &WSoFar, NULL); + if ( WSoFar > r.width ) + { + // not enough space to draw anything + return; + } + + wxString s; + s.Alloc(len); + for (size_t i = 0; i < len; i++) + { + dc.GetTextExtent(title[i], &letterW, NULL); + if ( letterW + WSoFar > r.width ) + break; + WSoFar += letterW; + s << title[i]; + } + s << wxT("..."); + dc.DrawLabel(s, wxNullBitmap, r, + wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL); + } + else + dc.DrawLabel(title, wxNullBitmap, r, + wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL); } void wxWin32Renderer::DrawFrameIcon(wxDC& dc, @@ -3509,6 +3684,40 @@ wxSize wxWin32Renderer::GetFrameTotalSize(const wxSize& clientSize, return s; } +wxSize wxWin32Renderer::GetFrameMinSize(int flags) const +{ + wxSize s(0, 0); + + if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) ) + { + int border = (flags & wxTOPLEVEL_RESIZEABLE) ? + RESIZEABLE_FRAME_BORDER_THICKNESS : + FRAME_BORDER_THICKNESS; + s.x += 2*border; + s.y += 2*border; + } + + if ( flags & wxTOPLEVEL_TITLEBAR ) + { + s.y += FRAME_TITLEBAR_HEIGHT; + + if ( flags & wxTOPLEVEL_ICON ) + s.x += FRAME_TITLEBAR_HEIGHT + 2; + if ( flags & wxTOPLEVEL_BUTTON_CLOSE ) + s.x += FRAME_BUTTON_WIDTH + 2; + if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE ) + s.x += FRAME_BUTTON_WIDTH; + if ( flags & wxTOPLEVEL_BUTTON_RESTORE ) + s.x += FRAME_BUTTON_WIDTH; + if ( flags & wxTOPLEVEL_BUTTON_ICONIZE ) + s.x += FRAME_BUTTON_WIDTH; + if ( flags & wxTOPLEVEL_BUTTON_HELP ) + s.x += FRAME_BUTTON_WIDTH; + } + + return s; +} + wxSize wxWin32Renderer::GetFrameIconSize() const { return wxSize(16, 16); @@ -3682,26 +3891,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; } @@ -3715,7 +3917,7 @@ static inline int GetTextBorderWidth() } wxRect wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text, - const wxRect& rect) + const wxRect& rect) const { wxRect rectTotal = rect; @@ -3730,7 +3932,7 @@ wxRect wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text, wxRect wxWin32Renderer::GetTextClientArea(const wxTextCtrl *text, const wxRect& rect, - wxCoord *extraSpaceBeyond) + wxCoord *extraSpaceBeyond) const { wxRect rectText = rect; @@ -3821,7 +4023,9 @@ bool wxWin32InputHandler::HandleMouse(wxInputConsumer *control, if ( event.ButtonDown() ) { wxWindow *win = control->GetInputWindow(); - if ( wxWindow::FindFocus() != control->GetInputWindow() ) + + if (( wxWindow::FindFocus() != control->GetInputWindow() ) && + ( win->AcceptsFocus() ) ) { win->SetFocus(); @@ -3947,6 +4151,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()); @@ -3955,6 +4161,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 @@ -4091,12 +4312,27 @@ bool wxWin32StatusBarInputHandler::IsOnGrip(wxWindow *statbar, const wxPoint& pt) const { if ( statbar->HasFlag(wxST_SIZEGRIP) && - statbar->GetParent()->HasFlag(wxRESIZE_BORDER) ) + statbar->GetParent()->HasFlag(wxRESIZE_BORDER) ) { - wxSize sizeSbar = statbar->GetSize(); + wxTopLevelWindow * + parentTLW = wxDynamicCast(statbar->GetParent(), wxTopLevelWindow); + + wxCHECK_MSG( parentTLW, FALSE, + _T("the status bar should be a child of a TLW") ); - return (sizeSbar.x - pt.x) < (wxCoord)STATUSBAR_GRIP_SIZE && - (sizeSbar.y - pt.y) < (wxCoord)STATUSBAR_GRIP_SIZE; + // a maximized window can't be resized anyhow + if ( !parentTLW->IsMaximized() ) + { + // VZ: I think that the standard Windows behaviour is to only + // show the resizing cursor when the mouse is on top of the + // grip itself but apparently different Windows versions behave + // differently (?) and it seems a better UI to allow resizing + // the status bar even when the mouse is above the grip + wxSize sizeSbar = statbar->GetSize(); + + int diff = sizeSbar.x - pt.x; + return diff >= 0 && diff < (wxCoord)STATUSBAR_GRIP_SIZE; + } } return FALSE; @@ -4154,3 +4390,192 @@ bool wxWin32StatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer, return wxStdInputHandler::HandleMouseMove(consumer, event); } +// ---------------------------------------------------------------------------- +// 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() || event.LeftDown() || event.RightDown() ) + { + wxTopLevelWindow *tlw = + wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow); + + long hit = tlw->HitTest(event.GetPosition()); + + 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); +}