X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e7dda1ffa3db91707f2a554fc3c8dffa34e0e510..818503a1826c8d32340234318afe6de35f756c2f:/src/univ/themes/win32.cpp diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index f072921aae..ca0b2fd4bc 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 @@ -228,6 +229,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, @@ -346,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(6, 6); } + 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); } @@ -475,6 +486,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]; @@ -578,14 +597,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; }; // ---------------------------------------------------------------------------- @@ -641,8 +670,8 @@ private: static const char *frame_button_close_xpm[] = { "12 10 2 1", -" c None", -". c black", +" c None", +". c black", " ", " .. .. ", " .. .. ", @@ -656,8 +685,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", " .... ", " .. .. ", " .. .. ", @@ -671,8 +700,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", " ......... ", " ......... ", " . . ", @@ -686,8 +715,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", " ", " ", " ", @@ -701,8 +730,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", " ...... ", " ...... ", " . . ", @@ -1068,7 +1097,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 { @@ -1110,6 +1139,12 @@ static const char ** } }; +static const char **xpmChecked[IndicatorStatus_Max] = +{ + checked_item_xpm, + unchecked_item_xpm +}; + // ============================================================================ // implementation // ============================================================================ @@ -1212,6 +1247,10 @@ 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 wxWin32FrameInputHandler(GetDefaultInputHandler()); else @@ -1299,8 +1338,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)); @@ -1323,7 +1366,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 @@ -2171,8 +2214,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, @@ -2207,14 +2258,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, @@ -2273,19 +2329,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, @@ -2296,18 +2349,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)); - DrawCheckOrRadioButton(dc, label, - cbitmap, - rect, flags, align, indexAccel, - 0); // no focus rect offset for checkboxes + 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); } } @@ -3445,7 +3527,7 @@ void wxWin32Renderer::DrawFrameTitle(wxDC& dc, dc.SetFont(m_titlebarFont); dc.SetTextForeground(col); - + wxCoord textW; dc.GetTextExtent(title, &textW, NULL); if ( textW > r.width ) @@ -3472,11 +3554,11 @@ void wxWin32Renderer::DrawFrameTitle(wxDC& dc, s << title[i]; } s << wxT("..."); - dc.DrawLabel(s, wxNullBitmap, r, + dc.DrawLabel(s, wxNullBitmap, r, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL); } else - dc.DrawLabel(title, wxNullBitmap, r, + dc.DrawLabel(title, wxNullBitmap, r, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL); } @@ -3808,7 +3890,7 @@ static inline int GetTextBorderWidth() } wxRect wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text, - const wxRect& rect) + const wxRect& rect) const { wxRect rectTotal = rect; @@ -3823,7 +3905,7 @@ wxRect wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text, wxRect wxWin32Renderer::GetTextClientArea(const wxTextCtrl *text, const wxRect& rect, - wxCoord *extraSpaceBeyond) + wxCoord *extraSpaceBeyond) const { wxRect rectText = rect; @@ -3914,7 +3996,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(); @@ -4184,12 +4268,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; @@ -4251,26 +4350,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 = + 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); + 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); +}