X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b72a54d1a573e76d99aa4fa4d3334add1cabdc29..baaae89f09ece7ab8a17570ee535683b9d14aeda:/src/univ/themes/win32.cpp?ds=sidebyside diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index fae4a4a885..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/univ/renderer.h" #include "wx/univ/inphand.h" #include "wx/univ/colschem.h" @@ -67,6 +69,17 @@ static const int BORDER_THICKNESS = 2; static const int FOCUS_RECT_OFFSET_X = 1; static const int FOCUS_RECT_OFFSET_Y = 1; +static const int FRAME_BORDER_THICKNESS = 3; +static const int RESIZEABLE_FRAME_BORDER_THICKNESS = 4; +static const int FRAME_TITLEBAR_HEIGHT = 18; +static const int FRAME_BUTTON_WIDTH = 16; +static const int FRAME_BUTTON_HEIGHT = 14; + +static const size_t NUM_STATUSBAR_GRIP_BANDS = 3; +static const size_t WIDTH_STATUSBAR_GRIP_BAND = 4; +static const size_t STATUSBAR_GRIP_SIZE = + WIDTH_STATUSBAR_GRIP_BAND*NUM_STATUSBAR_GRIP_BANDS; + enum IndicatorType { IndicatorType_Check, @@ -118,6 +131,16 @@ public: Arrow_StateMax }; + enum wxFrameButtonType + { + FrameButton_Close, + FrameButton_Minimize, + FrameButton_Maximize, + FrameButton_Restore, + FrameButton_Help, + FrameButton_Max + }; + // ctor wxWin32Renderer(const wxColourScheme *scheme); @@ -125,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, @@ -207,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, @@ -239,7 +268,6 @@ public: int end, int step = 1, int flags = 0); -#if wxUSE_MENUS virtual void DrawMenuBarItem(wxDC& dc, const wxRect& rect, @@ -257,7 +285,44 @@ public: virtual void DrawMenuSeparator(wxDC& dc, wxCoord y, const wxMenuGeometryInfo& geomInfo); -#endif + + virtual void DrawStatusField(wxDC& dc, + const wxRect& rect, + const wxString& label, + int flags = 0); + + // titlebars + virtual void DrawFrameTitleBar(wxDC& dc, + const wxRect& rect, + const wxString& title, + const wxIcon& icon, + int flags, + int specialButton = 0, + int specialButtonFlags = 0); + virtual void DrawFrameBorder(wxDC& dc, + const wxRect& rect, + int flags); + virtual void DrawFrameBackground(wxDC& dc, + const wxRect& rect, + int flags); + virtual void DrawFrameTitle(wxDC& dc, + const wxRect& rect, + const wxString& title, + int flags); + virtual void DrawFrameIcon(wxDC& dc, + const wxRect& rect, + const wxIcon& icon, + int flags); + virtual void DrawFrameButton(wxDC& dc, + wxCoord x, wxCoord y, + int button, + 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 void GetComboBitmaps(wxBitmap *bmpNormal, wxBitmap *bmpFocus, wxBitmap *bmpPressed, @@ -287,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); } @@ -304,11 +374,12 @@ public: wxOrientation orient) const; virtual wxSize GetProgressBarStep() const { return wxSize(16, 32); } -#if wxUSE_MENUS virtual wxSize GetMenuBarItemSize(const wxSize& sizeText) const; virtual wxMenuGeometryInfo *GetMenuGeometry(wxWindow *win, const wxMenu& menu) const; -#endif + + virtual wxSize GetStatusBarBorders(wxCoord *borderBetweenFields) const; + protected: // helper of DrawLabel() and DrawCheckOrRadioButton() void DoDrawLabel(wxDC& dc, @@ -334,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 @@ -413,6 +485,19 @@ private: m_penLightGrey, m_penHighlight; + 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]; + // first row is for the normal state, second - for the disabled wxBitmap m_bmpArrows[Arrow_StateMax][Arrow_Max]; }; @@ -427,10 +512,10 @@ class wxWin32InputHandler : public wxInputHandler public: wxWin32InputHandler(wxWin32Renderer *renderer); - virtual bool HandleKey(wxControl *control, + virtual bool HandleKey(wxInputConsumer *control, const wxKeyEvent& event, bool pressed); - virtual bool HandleMouse(wxControl *control, + virtual bool HandleMouse(wxInputConsumer *control, const wxMouseEvent& event); protected: @@ -443,8 +528,8 @@ public: wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer, wxInputHandler *handler); - virtual bool HandleMouse(wxControl *control, const wxMouseEvent& event); - virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event); + virtual bool HandleMouse(wxInputConsumer *control, const wxMouseEvent& event); + virtual bool HandleMouseMove(wxInputConsumer *control, const wxMouseEvent& event); virtual bool OnScrollTimer(wxScrollBar *scrollbar, const wxControlAction& action); @@ -474,7 +559,7 @@ public: wxWin32CheckboxInputHandler(wxInputHandler *handler) : wxStdCheckboxInputHandler(handler) { } - virtual bool HandleKey(wxControl *control, + virtual bool HandleKey(wxInputConsumer *control, const wxKeyEvent& event, bool pressed); }; @@ -485,11 +570,54 @@ public: wxWin32TextCtrlInputHandler(wxInputHandler *handler) : wxStdTextCtrlInputHandler(handler) { } - virtual bool HandleKey(wxControl *control, + virtual bool HandleKey(wxInputConsumer *control, const wxKeyEvent& event, bool pressed); }; +class wxWin32StatusBarInputHandler : public wxStdInputHandler +{ +public: + wxWin32StatusBarInputHandler(wxInputHandler *handler); + + virtual bool HandleMouse(wxInputConsumer *consumer, + const wxMouseEvent& event); + + virtual bool HandleMouseMove(wxInputConsumer *consumer, + const wxMouseEvent& event); + +protected: + // is the given point over the statusbar grip? + bool IsOnGrip(wxWindow *statbar, const wxPoint& pt) const; + +private: + // the cursor we had replaced with the resize one + wxCursor m_cursorOld; + + // was the mouse over the grip last time we checked? + 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 // ---------------------------------------------------------------------------- @@ -501,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 // ---------------------------------------------------------------------------- @@ -513,7 +653,8 @@ public: wxWin32Theme(); virtual ~wxWin32Theme(); - virtual wxRenderer *GetRenderer() { return m_renderer; } + virtual wxRenderer *GetRenderer(); + virtual wxArtProvider *GetArtProvider(); virtual wxInputHandler *GetInputHandler(const wxString& control); virtual wxColourScheme *GetColourScheme(); @@ -522,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) @@ -539,6 +682,83 @@ private: // standard bitmaps // ---------------------------------------------------------------------------- +// frame buttons bitmaps + +static const char *frame_button_close_xpm[] = { +"12 10 2 1", +" c None", +". c black", +" ", +" .. .. ", +" .. .. ", +" .... ", +" .. ", +" .... ", +" .. .. ", +" .. .. ", +" ", +" "}; + +static const char *frame_button_help_xpm[] = { +"12 10 2 1", +" c None", +". c #000000", +" .... ", +" .. .. ", +" .. .. ", +" .. ", +" .. ", +" .. ", +" ", +" .. ", +" .. ", +" "}; + +static const char *frame_button_maximize_xpm[] = { +"12 10 2 1", +" c None", +". c #000000", +" ......... ", +" ......... ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" ......... ", +" "}; + +static const char *frame_button_minimize_xpm[] = { +"12 10 2 1", +" c None", +". c #000000", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ...... ", +" ...... ", +" "}; + +static const char *frame_button_restore_xpm[] = { +"12 10 2 1", +" c None", +". c #000000", +" ...... ", +" ...... ", +" . . ", +" ...... . ", +" ...... . ", +" . ... ", +" . . ", +" . . ", +" ...... ", +" "}; + // menu bitmaps static const char *checked_menu_xpm[] = { @@ -893,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 { @@ -935,6 +1155,12 @@ static const char ** } }; +static const char **xpmChecked[IndicatorStatus_Max] = +{ + checked_item_xpm, + unchecked_item_xpm +}; + // ============================================================================ // implementation // ============================================================================ @@ -947,9 +1173,10 @@ WX_IMPLEMENT_THEME(wxWin32Theme, win32, wxTRANSLATE("Win32 theme")); wxWin32Theme::wxWin32Theme() { - m_scheme = new wxWin32ColourScheme; - m_renderer = new wxWin32Renderer(m_scheme); + m_scheme = NULL; + m_renderer = NULL; m_handlerDefault = NULL; + m_artProvider = NULL; } wxWin32Theme::~wxWin32Theme() @@ -965,6 +1192,27 @@ wxWin32Theme::~wxWin32Theme() delete m_renderer; delete m_scheme; + wxArtProvider::RemoveProvider(m_artProvider); +} + +wxRenderer *wxWin32Theme::GetRenderer() +{ + if ( !m_renderer ) + { + m_renderer = new wxWin32Renderer(GetColourScheme()); + } + + return m_renderer; +} + +wxArtProvider *wxWin32Theme::GetArtProvider() +{ + if ( !m_artProvider ) + { + m_artProvider = new wxWin32ArtProvider; + } + + return m_artProvider; } wxInputHandler *wxWin32Theme::GetDefaultInputHandler() @@ -1023,6 +1271,16 @@ wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control) else if ( control == wxINP_HANDLER_NOTEBOOK ) handler = new wxStdNotebookInputHandler(GetDefaultInputHandler()); #endif // wxUSE_NOTEBOOK +#if wxUSE_STATUSBAR + 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 wxWin32FrameInputHandler(GetDefaultInputHandler()); else handler = GetDefaultInputHandler(); @@ -1039,6 +1297,10 @@ wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control) wxColourScheme *wxWin32Theme::GetColourScheme() { + if ( !m_scheme ) + { + m_scheme = new wxWin32ColourScheme; + } return m_scheme; } @@ -1077,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 @@ -1104,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)); @@ -1113,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: @@ -1123,6 +1389,13 @@ wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col) const case CONTROL_TEXT_DISABLED_SHADOW: case SHADOW_OUT: return wxColour(GetSysColor(COLOR_BTNSHADOW)); + + case TITLEBAR: return wxColour(GetSysColor(COLOR_INACTIVECAPTION)); + 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 case WINDOW: return *wxWHITE; @@ -1141,15 +1414,24 @@ wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col) const case SHADOW_DARK: return *wxBLACK; - case CONTROL_TEXT_DISABLED: - case SHADOW_HIGHLIGHT: return wxColour(0xe0e0e0); + case CONTROL_TEXT_DISABLED:return wxColour(0xe0e0e0); + case SHADOW_HIGHLIGHT: return wxColour(0xffffff); case SHADOW_IN: return wxColour(0xc0c0c0); case CONTROL_TEXT_DISABLED_SHADOW: case SHADOW_OUT: return wxColour(0x7f7f7f); + + case TITLEBAR: return wxColour(0xaeaaae); + case TITLEBAR_ACTIVE: return wxColour(0x820300); + case TITLEBAR_TEXT: return wxColour(0xc0c0c0); + case TITLEBAR_ACTIVE_TEXT:return *wxWHITE; + + case DESKTOP: return wxColour(0x808000); #endif // __WXMSW__ + case GAUGE: return Get(HIGHLIGHT); + case MAX: default: wxFAIL_MSG(_T("invalid standard colour")); @@ -1182,6 +1464,9 @@ wxWin32Renderer::wxWin32Renderer(const wxColourScheme *scheme) m_colHighlight = wxSCHEME_COLOUR(scheme, SHADOW_HIGHLIGHT); m_penHighlight = wxPen(m_colHighlight, 0, wxSOLID); + m_titlebarFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + m_titlebarFont.SetWeight(wxFONTWEIGHT_BOLD); + // init the arrow bitmaps static const size_t ARROW_WIDTH = 7; static const size_t ARROW_LENGTH = 4; @@ -1351,6 +1636,13 @@ wxWin32Renderer::wxWin32Renderer(const wxColourScheme *scheme) m_bmpArrows[Arrow_Pressed][n] = m_bmpArrows[Arrow_Normal][n]; } + + // init the frame buttons bitmaps + m_bmpFrameButtons[FrameButton_Close] = wxBitmap(frame_button_close_xpm); + m_bmpFrameButtons[FrameButton_Minimize] = wxBitmap(frame_button_minimize_xpm); + m_bmpFrameButtons[FrameButton_Maximize] = wxBitmap(frame_button_maximize_xpm); + m_bmpFrameButtons[FrameButton_Restore] = wxBitmap(frame_button_restore_xpm); + m_bmpFrameButtons[FrameButton_Help] = wxBitmap(frame_button_help_xpm); } // ---------------------------------------------------------------------------- @@ -1576,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: @@ -1950,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, @@ -1986,8 +2290,19 @@ wxBitmap wxWin32Renderer::GetIndicator(IndicatorType indType, int flags) ? IndicatorStatus_Checked : IndicatorStatus_Unchecked; - const char **xpm = bmpIndicators[indType][indState][indStatus]; - return xpm ? wxBitmap(xpm) : wxNullBitmap; + wxBitmap bmp = m_bmpIndicators[indType][indState][indStatus]; + if ( !bmp.Ok() ) + { + const char **xpm = xpmIndicators[indType][indState][indStatus]; + if ( xpm ) + { + // create and cache it + bmp = wxBitmap(xpm); + m_bmpIndicators[indType][indState][indStatus] = bmp; + } + } + + return bmp; } void wxWin32Renderer::DrawCheckOrRadioButton(wxDC& dc, @@ -2046,8 +2361,14 @@ void wxWin32Renderer::DrawRadioButton(wxDC& dc, wxAlignment align, int indexAccel) { + wxBitmap bmp; + if ( bitmap.Ok() ) + bmp = bitmap; + else + bmp = GetRadioBitmap(flags); + DrawCheckOrRadioButton(dc, label, - bitmap.Ok() ? bitmap : GetRadioBitmap(flags), + bmp, rect, flags, align, indexAccel, FOCUS_RECT_OFFSET_Y); // default focus rect offset } @@ -2060,12 +2381,50 @@ void wxWin32Renderer::DrawCheckButton(wxDC& dc, wxAlignment align, int indexAccel) { + wxBitmap bmp; + if ( bitmap.Ok() ) + bmp = bitmap; + else + bmp = GetCheckBitmap(flags); + DrawCheckOrRadioButton(dc, label, - bitmap.Ok() ? bitmap : GetCheckBitmap(flags), + 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() ) + { + 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); + } +} + // ---------------------------------------------------------------------------- // text control // ---------------------------------------------------------------------------- @@ -2360,6 +2719,7 @@ void wxWin32Renderer::DrawSliderThumb(wxDC& dc, rectInt.SetBottom(y3); rectInt.Deflate(2); +#if !defined(__WXMGL__) static const char *stipple_xpm[] = { /* columns rows colors chars-per-pixel */ "2 2 2 1", @@ -2369,6 +2729,24 @@ void wxWin32Renderer::DrawSliderThumb(wxDC& dc, "w ", " w", }; +#else + // VS: MGL can only do 8x8 stipple brushes + static const char *stipple_xpm[] = { + /* columns rows colors chars-per-pixel */ + "8 8 2 1", + " c None", + "w c white", + /* pixels */ + "w w w w ", + " w w w w", + "w w w w ", + " w w w w", + "w w w w ", + " w w w w", + "w w w w ", + " w w w w", + }; +#endif dc.SetBrush(wxBrush(stipple_xpm)); dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, SHADOW_HIGHLIGHT)); @@ -2450,8 +2828,6 @@ void wxWin32Renderer::DrawSliderTicks(wxDC& dc, // menu and menubar // ---------------------------------------------------------------------------- -#if wxUSE_MENUS - // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer class WXDLLEXPORT wxWin32MenuGeometryInfo : public wxMenuGeometryInfo { @@ -2476,12 +2852,10 @@ private: // the height of a normal (not separator) item wxCoord m_heightItem; - friend wxMenuGeometryInfo *wxWin32Renderer:: - GetMenuGeometry(wxWindow *, const wxMenu&) const; + friend wxMenuGeometryInfo * + wxWin32Renderer::GetMenuGeometry(wxWindow *, const wxMenu&) const; }; -#endif // wxUSE_MENUS - // FIXME: all constants are hardcoded but shouldn't be static const wxCoord MENU_LEFT_MARGIN = 9; static const wxCoord MENU_RIGHT_MARGIN = 18; @@ -2501,10 +2875,6 @@ static const wxCoord MENU_SEPARATOR_HEIGHT = 3; // the size of the standard checkmark bitmap static const wxCoord MENU_CHECK_SIZE = 9; -// we can't implement these methods without wxMenuGeometryInfo implementation -// which we don't have if !wxUSE_MENUS -#if wxUSE_MENUS - void wxWin32Renderer::DrawMenuBarItem(wxDC& dc, const wxRect& rectOrig, const wxString& label, @@ -2630,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(); @@ -2716,48 +3086,81 @@ wxMenuGeometryInfo *wxWin32Renderer::GetMenuGeometry(wxWindow *win, return gi; } -#else // !wxUSE_MENUS +// ---------------------------------------------------------------------------- +// status bar +// ---------------------------------------------------------------------------- + +static const wxCoord STATBAR_BORDER_X = 2; +static const wxCoord STATBAR_BORDER_Y = 2; -/* -void wxWin32Renderer::DrawMenuBarItem(wxDC& WXUNUSED(dc), - const wxRect& WXUNUSED(rectOrig), - const wxString& WXUNUSED(label), - int WXUNUSED(flags), - int WXUNUSED(indexAccel)) +wxSize wxWin32Renderer::GetStatusBarBorders(wxCoord *borderBetweenFields) const { -} + if ( borderBetweenFields ) + *borderBetweenFields = 2; -void wxWin32Renderer::DrawMenuItem(wxDC& WXUNUSED(dc), - wxCoord WXUNUSED(y), - const wxMenuGeometryInfo& WXUNUSED(gi), - const wxString& WXUNUSED(label), - const wxString& WXUNUSED(accel), - const wxBitmap& WXUNUSED(bitmap), - int WXUNUSED(flags), - int WXUNUSED(indexAccel)) -{ + return wxSize(STATBAR_BORDER_X, STATBAR_BORDER_Y); } -void wxWin32Renderer::DrawMenuSeparator(wxDC& WXUNUSED(dc), - wxCoord WXUNUSED(y), - const wxMenuGeometryInfo& WXUNUSED(gi)) +void wxWin32Renderer::DrawStatusField(wxDC& dc, + const wxRect& rect, + const wxString& label, + int flags) { -} + wxRect rectIn; -wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& size) const -{ - return size; -} + if ( flags & wxCONTROL_ISDEFAULT ) + { + // draw the size grip: it is a normal rect except that in the lower + // right corner we have several bands which may be used for dragging + // the status bar corner + // + // each band consists of 4 stripes: m_penHighlight, double + // m_penDarkGrey and transparent one + wxCoord x2 = rect.GetRight(), + y2 = rect.GetBottom(); + + // draw the upper left part of the rect normally + dc.SetPen(m_penDarkGrey); + dc.DrawLine(rect.GetLeft(), rect.GetTop(), rect.GetLeft(), y2); + dc.DrawLine(rect.GetLeft() + 1, rect.GetTop(), x2, rect.GetTop()); + + // draw the grey stripes of the grip + size_t n; + wxCoord ofs = WIDTH_STATUSBAR_GRIP_BAND - 1; + for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND ) + { + dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs); + dc.DrawLine(x2 - ofs, y2 - 1, x2, y2 - ofs - 1); + } -wxMenuGeometryInfo * -wxWin32Renderer::GetMenuGeometry(wxWindow *WXUNUSED(win), - const wxMenu& WXUNUSED(menu)) const -{ - return NULL; -} -*/ + // draw the white stripes + dc.SetPen(m_penHighlight); + ofs = WIDTH_STATUSBAR_GRIP_BAND + 1; + for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND ) + { + dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs); + } + + // draw the remaining rect boundaries + ofs -= WIDTH_STATUSBAR_GRIP_BAND; + dc.DrawLine(x2, rect.GetTop(), x2, y2 - ofs + 1); + dc.DrawLine(rect.GetLeft(), y2, x2 - ofs + 1, y2); + + rectIn = rect; + rectIn.Deflate(1); -#endif // wxUSE_MENUS/!wxUSE_MENUS + rectIn.width -= STATUSBAR_GRIP_SIZE; + } + else // normal pane + { + DrawBorder(dc, wxBORDER_STATIC, rect, flags, &rectIn); + } + + rectIn.Deflate(STATBAR_BORDER_X, STATBAR_BORDER_Y); + + wxDCClipper clipper(dc, rectIn); + DrawLabel(dc, label, rectIn, flags, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL); +} // ---------------------------------------------------------------------------- // combobox @@ -2804,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); @@ -2815,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 ); } // ---------------------------------------------------------------------------- @@ -2948,6 +3353,560 @@ int wxWin32Renderer::PixelToScrollbar(const wxScrollBar *scrollbar, return StandardPixelToScrollbar(scrollbar, coord, m_sizeScrollbarArrow); } +// ---------------------------------------------------------------------------- +// top level windows +// ---------------------------------------------------------------------------- + +int wxWin32Renderer::HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const +{ + wxRect client = GetFrameClientArea(rect, flags); + + if ( client.Inside(pt) ) + return wxHT_TOPLEVEL_CLIENT_AREA; + + if ( flags & wxTOPLEVEL_TITLEBAR ) + { + wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR); + + if ( flags & wxTOPLEVEL_ICON ) + { + if ( wxRect(client.GetPosition(), GetFrameIconSize()).Inside(pt) ) + return wxHT_TOPLEVEL_ICON; + } + + wxRect btnRect(client.GetRight() - 2 - FRAME_BUTTON_WIDTH, + client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2, + FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT); + + if ( flags & wxTOPLEVEL_BUTTON_CLOSE ) + { + if ( btnRect.Inside(pt) ) + return wxHT_TOPLEVEL_BUTTON_CLOSE; + btnRect.x -= FRAME_BUTTON_WIDTH + 2; + } + if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE ) + { + if ( btnRect.Inside(pt) ) + return wxHT_TOPLEVEL_BUTTON_MAXIMIZE; + btnRect.x -= FRAME_BUTTON_WIDTH; + } + if ( flags & wxTOPLEVEL_BUTTON_RESTORE ) + { + if ( btnRect.Inside(pt) ) + return wxHT_TOPLEVEL_BUTTON_RESTORE; + btnRect.x -= FRAME_BUTTON_WIDTH; + } + if ( flags & wxTOPLEVEL_BUTTON_ICONIZE ) + { + if ( btnRect.Inside(pt) ) + return wxHT_TOPLEVEL_BUTTON_ICONIZE; + btnRect.x -= FRAME_BUTTON_WIDTH; + } + if ( flags & wxTOPLEVEL_BUTTON_HELP ) + { + if ( btnRect.Inside(pt) ) + return wxHT_TOPLEVEL_BUTTON_HELP; + btnRect.x -= FRAME_BUTTON_WIDTH; + } + + if ( pt.y >= client.y && pt.y < client.y + FRAME_TITLEBAR_HEIGHT ) + return wxHT_TOPLEVEL_TITLEBAR; + } + + if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) ) + { + // we are certainly at one of borders, lets decide which one: + + int border = 0; + // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined! + if ( pt.x < client.x ) + border |= wxHT_TOPLEVEL_BORDER_W; + else if ( pt.x >= client.width + client.x ) + border |= wxHT_TOPLEVEL_BORDER_E; + if ( pt.y < client.y ) + border |= wxHT_TOPLEVEL_BORDER_N; + else if ( pt.y >= client.height + client.y ) + border |= wxHT_TOPLEVEL_BORDER_S; + return border; + } + + return wxHT_NOWHERE; +} + +void wxWin32Renderer::DrawFrameTitleBar(wxDC& dc, + const wxRect& rect, + const wxString& title, + const wxIcon& icon, + int flags, + int specialButton, + int specialButtonFlags) +{ + if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) ) + { + DrawFrameBorder(dc, rect, flags); + } + if ( flags & wxTOPLEVEL_TITLEBAR ) + { + DrawFrameBackground(dc, rect, flags); + if ( flags & wxTOPLEVEL_ICON ) + DrawFrameIcon(dc, rect, icon, flags); + DrawFrameTitle(dc, rect, title, flags); + + wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR); + wxCoord x,y; + x = client.GetRight() - 2 - FRAME_BUTTON_WIDTH; + y = client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2; + + if ( flags & wxTOPLEVEL_BUTTON_CLOSE ) + { + DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_CLOSE, + (specialButton == wxTOPLEVEL_BUTTON_CLOSE) ? + specialButtonFlags : 0); + x -= FRAME_BUTTON_WIDTH + 2; + } + if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE ) + { + DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_MAXIMIZE, + (specialButton == wxTOPLEVEL_BUTTON_MAXIMIZE) ? + specialButtonFlags : 0); + x -= FRAME_BUTTON_WIDTH; + } + if ( flags & wxTOPLEVEL_BUTTON_RESTORE ) + { + DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_RESTORE, + (specialButton == wxTOPLEVEL_BUTTON_RESTORE) ? + specialButtonFlags : 0); + x -= FRAME_BUTTON_WIDTH; + } + if ( flags & wxTOPLEVEL_BUTTON_ICONIZE ) + { + DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_ICONIZE, + (specialButton == wxTOPLEVEL_BUTTON_ICONIZE) ? + specialButtonFlags : 0); + x -= FRAME_BUTTON_WIDTH; + } + if ( flags & wxTOPLEVEL_BUTTON_HELP ) + { + DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_HELP, + (specialButton == wxTOPLEVEL_BUTTON_HELP) ? + specialButtonFlags : 0); + x -= FRAME_BUTTON_WIDTH; + } + } +} + +void wxWin32Renderer::DrawFrameBorder(wxDC& dc, + const wxRect& rect, + int flags) +{ + if ( !(flags & wxTOPLEVEL_BORDER) ) return; + + wxRect r(rect); + + DrawShadedRect(dc, &r, m_penLightGrey, m_penBlack); + DrawShadedRect(dc, &r, m_penHighlight, m_penDarkGrey); + DrawShadedRect(dc, &r, m_penLightGrey, m_penLightGrey); + if ( flags & wxTOPLEVEL_RESIZEABLE ) + DrawShadedRect(dc, &r, m_penLightGrey, m_penLightGrey); +} + +void wxWin32Renderer::DrawFrameBackground(wxDC& dc, + const wxRect& rect, + int flags) +{ + if ( !(flags & wxTOPLEVEL_TITLEBAR) ) return; + + wxColour col = (flags & wxTOPLEVEL_ACTIVE) ? + wxSCHEME_COLOUR(m_scheme, TITLEBAR_ACTIVE) : + wxSCHEME_COLOUR(m_scheme, TITLEBAR); + + wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR); + r.height = FRAME_TITLEBAR_HEIGHT; + + DrawBackground(dc, col, r); +} + +void wxWin32Renderer::DrawFrameTitle(wxDC& dc, + const wxRect& rect, + const wxString& title, + int flags) +{ + wxColour col = (flags & wxTOPLEVEL_ACTIVE) ? + wxSCHEME_COLOUR(m_scheme, TITLEBAR_ACTIVE_TEXT) : + wxSCHEME_COLOUR(m_scheme, TITLEBAR_TEXT); + + 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); + + 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, + const wxRect& rect, + const wxIcon& icon, + int flags) +{ + if ( icon.Ok() ) + { + wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR); + dc.DrawIcon(icon, r.x, r.y); + } +} + +void wxWin32Renderer::DrawFrameButton(wxDC& dc, + wxCoord x, wxCoord y, + int button, + int flags) +{ + wxRect r(x, y, FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT); + + size_t idx = 0; + switch (button) + { + case wxTOPLEVEL_BUTTON_CLOSE: idx = FrameButton_Close; break; + case wxTOPLEVEL_BUTTON_MAXIMIZE: idx = FrameButton_Maximize; break; + case wxTOPLEVEL_BUTTON_ICONIZE: idx = FrameButton_Minimize; break; + case wxTOPLEVEL_BUTTON_RESTORE: idx = FrameButton_Restore; break; + case wxTOPLEVEL_BUTTON_HELP: idx = FrameButton_Help; break; + default: + wxFAIL_MSG(wxT("incorrect button specification")); + } + + if ( flags & wxCONTROL_PRESSED ) + { + DrawShadedRect(dc, &r, m_penBlack, m_penHighlight); + DrawShadedRect(dc, &r, m_penDarkGrey, m_penLightGrey); + DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), r); + dc.DrawBitmap(m_bmpFrameButtons[idx], r.x+1, r.y+1, TRUE); + } + else + { + DrawShadedRect(dc, &r, m_penHighlight, m_penBlack); + DrawShadedRect(dc, &r, m_penLightGrey, m_penDarkGrey); + DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), r); + dc.DrawBitmap(m_bmpFrameButtons[idx], r.x, r.y, TRUE); + } +} + + +wxRect wxWin32Renderer::GetFrameClientArea(const wxRect& rect, + int flags) const +{ + wxRect r(rect); + + if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) ) + { + int border = (flags & wxTOPLEVEL_RESIZEABLE) ? + RESIZEABLE_FRAME_BORDER_THICKNESS : + FRAME_BORDER_THICKNESS; + r.Inflate(-border); + } + if ( flags & wxTOPLEVEL_TITLEBAR ) + { + r.y += FRAME_TITLEBAR_HEIGHT; + r.height -= FRAME_TITLEBAR_HEIGHT; + } + + return r; +} + +wxSize wxWin32Renderer::GetFrameTotalSize(const wxSize& clientSize, + int flags) const +{ + wxSize s(clientSize); + + 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; + + 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); +} + + +// ---------------------------------------------------------------------------- +// standard icons +// ---------------------------------------------------------------------------- + +static char *error_xpm[]={ +"32 32 5 1", +". c None", +"# c #800000", +"b c #808080", +"a c #ff0000", +"c c #ffffff", +"...........########.............", +"........###aaaaaaaa###..........", +".......#aaaaaaaaaaaaaa#.........", +".....##aaaaaaaaaaaaaaaa##.......", +"....#aaaaaaaaaaaaaaaaaaaa#......", +"...#aaaaaaaaaaaaaaaaaaaaaa#.....", +"...#aaaaaaaaaaaaaaaaaaaaaa#b....", +"..#aaaaaacaaaaaaaaaacaaaaaa#b...", +".#aaaaaacccaaaaaaaacccaaaaaa#...", +".#aaaaacccccaaaaaacccccaaaaa#b..", +".#aaaaaacccccaaaacccccaaaaaa#bb.", +"#aaaaaaaacccccaacccccaaaaaaaa#b.", +"#aaaaaaaaaccccccccccaaaaaaaaa#b.", +"#aaaaaaaaaaccccccccaaaaaaaaaa#bb", +"#aaaaaaaaaaaccccccaaaaaaaaaaa#bb", +"#aaaaaaaaaaaccccccaaaaaaaaaaa#bb", +"#aaaaaaaaaaccccccccaaaaaaaaaa#bb", +"#aaaaaaaaaccccccccccaaaaaaaaa#bb", +"#aaaaaaaacccccaacccccaaaaaaaa#bb", +".#aaaaaacccccaaaacccccaaaaaa#bbb", +".#aaaaacccccaaaaaacccccaaaaa#bbb", +".#aaaaaacccaaaaaaaacccaaaaaa#bb.", +"..#aaaaaacaaaaaaaaaacaaaaaa#bbb.", +"...#aaaaaaaaaaaaaaaaaaaaaa#bbbb.", +"...#aaaaaaaaaaaaaaaaaaaaaa#bbb..", +"....#aaaaaaaaaaaaaaaaaaaa#bbb...", +".....##aaaaaaaaaaaaaaaa##bbbb...", +"......b#aaaaaaaaaaaaaa#bbbbb....", +".......b###aaaaaaaa###bbbbb.....", +".........bb########bbbbbb.......", +"..........bbbbbbbbbbbbbb........", +".............bbbbbbbb..........."}; + +static char *info_xpm[]={ +"32 32 6 1", +". c None", +"d c #000000", +"c c #0000ff", +"# c #808080", +"a c #c0c0c0", +"b c #ffffff", +"...........########.............", +"........###abbbbbba###..........", +"......##abbbbbbbbbbbba##........", +".....#abbbbbbbbbbbbbbbba#.......", +"....#bbbbbbbaccccabbbbbbbd......", +"...#bbbbbbbbccccccbbbbbbbbd.....", +"..#bbbbbbbbbccccccbbbbbbbbbd....", +".#abbbbbbbbbaccccabbbbbbbbbad...", +".#bbbbbbbbbbbbbbbbbbbbbbbbbbd#..", +"#abbbbbbbbbbbbbbbbbbbbbbbbbbad#.", +"#bbbbbbbbbbcccccccbbbbbbbbbbbd#.", +"#bbbbbbbbbbbbcccccbbbbbbbbbbbd##", +"#bbbbbbbbbbbbcccccbbbbbbbbbbbd##", +"#bbbbbbbbbbbbcccccbbbbbbbbbbbd##", +"#bbbbbbbbbbbbcccccbbbbbbbbbbbd##", +"#abbbbbbbbbbbcccccbbbbbbbbbbad##", +".#bbbbbbbbbbbcccccbbbbbbbbbbd###", +".#abbbbbbbbbbcccccbbbbbbbbbad###", +"..#bbbbbbbbcccccccccbbbbbbbd###.", +"...dbbbbbbbbbbbbbbbbbbbbbbd####.", +"....dbbbbbbbbbbbbbbbbbbbbd####..", +".....dabbbbbbbbbbbbbbbbad####...", +"......ddabbbbbbbbbbbbadd####....", +".......#dddabbbbbbaddd#####.....", +"........###dddabbbd#######......", +"..........####dbbbd#####........", +".............#dbbbd##...........", +"...............dbbd##...........", +"................dbd##...........", +".................dd##...........", +"..................###...........", +"...................##..........."}; + +static char *question_xpm[]={ +"32 32 6 1", +". c None", +"c c #000000", +"d c #0000ff", +"# c #808080", +"a c #c0c0c0", +"b c #ffffff", +"...........########.............", +"........###abbbbbba###..........", +"......##abbbbbbbbbbbba##........", +".....#abbbbbbbbbbbbbbbba#.......", +"....#bbbbbbbbbbbbbbbbbbbbc......", +"...#bbbbbbbaddddddabbbbbbbc.....", +"..#bbbbbbbadabbddddabbbbbbbc....", +".#abbbbbbbddbbbbddddbbbbbbbac...", +".#bbbbbbbbddddbbddddbbbbbbbbc#..", +"#abbbbbbbbddddbaddddbbbbbbbbac#.", +"#bbbbbbbbbaddabddddbbbbbbbbbbc#.", +"#bbbbbbbbbbbbbadddbbbbbbbbbbbc##", +"#bbbbbbbbbbbbbdddbbbbbbbbbbbbc##", +"#bbbbbbbbbbbbbddabbbbbbbbbbbbc##", +"#bbbbbbbbbbbbbddbbbbbbbbbbbbbc##", +"#abbbbbbbbbbbbbbbbbbbbbbbbbbac##", +".#bbbbbbbbbbbaddabbbbbbbbbbbc###", +".#abbbbbbbbbbddddbbbbbbbbbbac###", +"..#bbbbbbbbbbddddbbbbbbbbbbc###.", +"...cbbbbbbbbbaddabbbbbbbbbc####.", +"....cbbbbbbbbbbbbbbbbbbbbc####..", +".....cabbbbbbbbbbbbbbbbac####...", +"......ccabbbbbbbbbbbbacc####....", +".......#cccabbbbbbaccc#####.....", +"........###cccabbbc#######......", +"..........####cbbbc#####........", +".............#cbbbc##...........", +"...............cbbc##...........", +"................cbc##...........", +".................cc##...........", +"..................###...........", +"...................##..........."}; + +static char *warning_xpm[]={ +"32 32 6 1", +". c None", +"c c #000000", +"# c #808000", +"d c #808080", +"b c #c0c0c0", +"a c #ffff00", +".............###................", +"............#aabc...............", +"...........#aaaabcd.............", +"...........#aaaaacdd............", +"..........#aaaaaabcdd...........", +"..........#aaaaaaacdd...........", +".........#aaaaaaaabcdd..........", +".........#aaaaaaaaacdd..........", +"........#aaaaaaaaaabcdd.........", +"........#aaabcccbaaacdd.........", +".......#aaaacccccaaabcdd........", +".......#aaaacccccaaaacdd........", +"......#aaaaacccccaaaabcdd.......", +"......#aaaaacccccaaaaacdd.......", +".....#aaaaaacccccaaaaabcdd......", +".....#aaaaaa#ccc#aaaaaacdd......", +"....#aaaaaaabcccbaaaaaabcdd.....", +"....#aaaaaaaacccaaaaaaaacdd.....", +"...#aaaaaaaaa#c#aaaaaaaabcdd....", +"...#aaaaaaaaabcbaaaaaaaaacdd....", +"..#aaaaaaaaaaacaaaaaaaaaabcdd...", +"..#aaaaaaaaaaaaaaaaaaaaaaacdd...", +".#aaaaaaaaaaabccbaaaaaaaaabcdd..", +".#aaaaaaaaaaaccccaaaaaaaaaacdd..", +"#aaaaaaaaaaaaccccaaaaaaaaaabcdd.", +"#aaaaaaaaaaaabccbaaaaaaaaaaacdd.", +"#aaaaaaaaaaaaaaaaaaaaaaaaaaacddd", +"#aaaaaaaaaaaaaaaaaaaaaaaaaabcddd", +".#aaaaaaaaaaaaaaaaaaaaaaaabcdddd", +"..#ccccccccccccccccccccccccddddd", +"....ddddddddddddddddddddddddddd.", +".....ddddddddddddddddddddddddd.."}; + +wxBitmap wxWin32ArtProvider::CreateBitmap(const wxArtID& id, + const wxArtClient& WXUNUSED(client), + const wxSize& WXUNUSED(size)) +{ + 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; +} + + // ---------------------------------------------------------------------------- // text control geometry // ---------------------------------------------------------------------------- @@ -2958,7 +3917,7 @@ static inline int GetTextBorderWidth() } wxRect wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text, - const wxRect& rect) + const wxRect& rect) const { wxRect rectTotal = rect; @@ -2973,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; @@ -3050,22 +4009,28 @@ wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer *renderer) m_renderer = renderer; } -bool wxWin32InputHandler::HandleKey(wxControl *control, +bool wxWin32InputHandler::HandleKey(wxInputConsumer *control, const wxKeyEvent& event, bool pressed) { return FALSE; } -bool wxWin32InputHandler::HandleMouse(wxControl *control, +bool wxWin32InputHandler::HandleMouse(wxInputConsumer *control, const wxMouseEvent& event) { // clicking on the control gives it focus - if ( event.ButtonDown() && wxWindow::FindFocus() != control ) + if ( event.ButtonDown() ) { - control->SetFocus(); + wxWindow *win = control->GetInputWindow(); + + if (( wxWindow::FindFocus() != control->GetInputWindow() ) && + ( win->AcceptsFocus() ) ) + { + win->SetFocus(); - return TRUE; + return TRUE; + } } return FALSE; @@ -3113,7 +4078,7 @@ bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar, return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, action); } -bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl *control, +bool wxWin32ScrollBarInputHandler::HandleMouse(wxInputConsumer *control, const wxMouseEvent& event) { // remember the current state @@ -3133,7 +4098,7 @@ bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl *control, return rc; } -bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl *control, +bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxInputConsumer *control, const wxMouseEvent& event) { // we don't highlight scrollbar elements, so there is no need to process @@ -3148,7 +4113,7 @@ bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl *control, return FALSE; } - wxScrollBar *scrollbar = wxStaticCast(control, wxScrollBar); + wxScrollBar *scrollbar = wxStaticCast(control->GetInputWindow(), wxScrollBar); wxHitTest ht; if ( m_scrollPaused ) { @@ -3186,6 +4151,8 @@ bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl *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()); @@ -3194,6 +4161,21 @@ bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl *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 @@ -3240,7 +4222,7 @@ bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl *control, // wxWin32CheckboxInputHandler // ---------------------------------------------------------------------------- -bool wxWin32CheckboxInputHandler::HandleKey(wxControl *control, +bool wxWin32CheckboxInputHandler::HandleKey(wxInputConsumer *control, const wxKeyEvent& event, bool pressed) { @@ -3281,7 +4263,7 @@ bool wxWin32CheckboxInputHandler::HandleKey(wxControl *control, // wxWin32TextCtrlInputHandler // ---------------------------------------------------------------------------- -bool wxWin32TextCtrlInputHandler::HandleKey(wxControl *control, +bool wxWin32TextCtrlInputHandler::HandleKey(wxInputConsumer *control, const wxKeyEvent& event, bool pressed) { @@ -3315,3 +4297,285 @@ bool wxWin32TextCtrlInputHandler::HandleKey(wxControl *control, return wxStdTextCtrlInputHandler::HandleKey(control, event, pressed); } +// ---------------------------------------------------------------------------- +// wxWin32StatusBarInputHandler +// ---------------------------------------------------------------------------- + +wxWin32StatusBarInputHandler:: +wxWin32StatusBarInputHandler(wxInputHandler *handler) + : wxStdInputHandler(handler) +{ + m_isOnGrip = FALSE; +} + +bool wxWin32StatusBarInputHandler::IsOnGrip(wxWindow *statbar, + const wxPoint& pt) const +{ + if ( statbar->HasFlag(wxST_SIZEGRIP) && + statbar->GetParent()->HasFlag(wxRESIZE_BORDER) ) + { + wxTopLevelWindow * + parentTLW = wxDynamicCast(statbar->GetParent(), wxTopLevelWindow); + + wxCHECK_MSG( parentTLW, FALSE, + _T("the status bar should be a child of a TLW") ); + + // 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; +} + +bool wxWin32StatusBarInputHandler::HandleMouse(wxInputConsumer *consumer, + const wxMouseEvent& event) +{ + if ( event.Button(1) ) + { + if ( event.ButtonDown(1) ) + { + wxWindow *statbar = consumer->GetInputWindow(); + + if ( IsOnGrip(statbar, event.GetPosition()) ) + { + wxTopLevelWindow *tlw = wxDynamicCast(statbar->GetParent(), + wxTopLevelWindow); + if ( tlw ) + { + tlw->PerformAction(wxACTION_TOPLEVEL_RESIZE, + wxHT_TOPLEVEL_BORDER_SE); + + statbar->SetCursor(m_cursorOld); + + return TRUE; + } + } + } + } + + return wxStdInputHandler::HandleMouse(consumer, event); +} + +bool wxWin32StatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer, + const wxMouseEvent& event) +{ + wxWindow *statbar = consumer->GetInputWindow(); + + bool isOnGrip = IsOnGrip(statbar, event.GetPosition()); + if ( isOnGrip != m_isOnGrip ) + { + m_isOnGrip = isOnGrip; + if ( isOnGrip ) + { + m_cursorOld = statbar->GetCursor(); + statbar->SetCursor(wxCURSOR_SIZENWSE); + } + else + { + statbar->SetCursor(m_cursorOld); + } + } + + 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); +}