From: Kevin Ollivier Date: Sat, 13 Dec 2008 17:36:27 +0000 (+0000) Subject: Forward port new wxRenderer methods in 2.8 to trunk. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/e413198572959f013fc2537a3c8cc184c9ac820d Forward port new wxRenderer methods in 2.8 to trunk. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57313 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/gtk/private.h b/include/wx/gtk/private.h index 7be4c61cf3..4bba0963a0 100644 --- a/include/wx/gtk/private.h +++ b/include/wx/gtk/private.h @@ -119,9 +119,12 @@ namespace wxGTKPrivate // shutdown GtkWidget *GetButtonWidget(); GtkWidget *GetCheckButtonWidget(); +GtkWidget *GetComboBoxWidget(); GtkWidget *GetEntryWidget(); GtkWidget *GetHeaderButtonWidget(); +GtkWidget *GetRadioButtonWidget(); GtkWidget *GetSplitterWidget(); +GtkWidget *GetTextEntryWidget(); GtkWidget *GetTreeWidget(); } // wxGTKPrivate diff --git a/include/wx/renderer.h b/include/wx/renderer.h index 54929645c5..1c54983345 100644 --- a/include/wx/renderer.h +++ b/include/wx/renderer.h @@ -256,6 +256,18 @@ public: // only wxCONTROL_SELECTED makes sense in flags here virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0) = 0; + // Draw a native wxChoice + virtual void DrawChoice(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0) = 0; + + // Draw a native wxComboBox + virtual void DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0) = 0; + + // Draw a native wxTextCtrl frame + virtual void DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0) = 0; + + // Draw a native wxRadioButton (just the graphical portion) + virtual void DrawRadioButton(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0) = 0; + // geometry functions // ------------------ @@ -395,6 +407,18 @@ public: virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0) { m_rendererNative.DrawFocusRect( win, dc, rect, flags ); } + virtual void DrawChoice(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0) + { m_rendererNative.DrawChoice( win, dc, rect, flags); } + + virtual void DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0) + { m_rendererNative.DrawComboBox( win, dc, rect, flags); } + + virtual void DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0) + { m_rendererNative.DrawTextCtrl( win, dc, rect, flags); } + + virtual void DrawRadioButton(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0) + { m_rendererNative.DrawRadioButton( win, dc, rect, flags); } + virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win) { return m_rendererNative.GetSplitterParams(win); } diff --git a/src/generic/renderg.cpp b/src/generic/renderg.cpp index 0a8193808b..906a9b342a 100644 --- a/src/generic/renderg.cpp +++ b/src/generic/renderg.cpp @@ -112,6 +112,14 @@ public: virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0); + virtual void DrawChoice(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0); + + virtual void DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0); + + virtual void DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0); + + virtual void DrawRadioButton(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0); + virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win); virtual wxRendererVersion GetVersion() const @@ -726,6 +734,33 @@ wxRendererGeneric::DrawFocusRect(wxWindow* WXUNUSED(win), wxDC& dc, const wxRect dc.SetLogicalFunction(wxCOPY); } +void wxRendererGeneric::DrawChoice(wxWindow* WXUNUSED(win), wxDC& WXUNUSED(dc), + const wxRect& WXUNUSED(rect), int WXUNUSED(flags)) +{ + // FIXME: Implement +} + +void wxRendererGeneric::DrawComboBox(wxWindow* WXUNUSED(win), wxDC& WXUNUSED(dc), + const wxRect& WXUNUSED(rect), int WXUNUSED(flags)) +{ + // FIXME: Implement +} + +void wxRendererGeneric::DrawRadioButton(wxWindow* WXUNUSED(win), wxDC& WXUNUSED(dc), + const wxRect& WXUNUSED(rect), int WXUNUSED(flags)) +{ + // FIXME: Implement +} + +void wxRendererGeneric::DrawTextCtrl(wxWindow* WXUNUSED(win), wxDC& WXUNUSED(dc), + const wxRect& WXUNUSED(rect), int WXUNUSED(flags)) +{ + // FIXME: Implement +} + + + + // ---------------------------------------------------------------------------- // A module to allow cleanup of generic renderer. // ---------------------------------------------------------------------------- diff --git a/src/gtk/private.cpp b/src/gtk/private.cpp index 3f421fbb2c..795b4b0667 100644 --- a/src/gtk/private.cpp +++ b/src/gtk/private.cpp @@ -78,6 +78,24 @@ GtkWidget *GetCheckButtonWidget() return s_button; } +GtkWidget * GetComboBoxWidget() +{ + static GtkWidget *s_button = NULL; + static GtkWidget *s_window = NULL; + + if ( !s_button ) + { + s_window = gtk_window_new( GTK_WINDOW_POPUP ); + gtk_widget_realize( s_window ); + s_button = gtk_combo_box_new(); + gtk_container_add( GTK_CONTAINER(s_window), s_button ); + gtk_widget_realize( s_button ); + } + + return s_button; +} + + GtkWidget *GetEntryWidget() { static GtkWidget *s_entry = NULL; @@ -112,6 +130,23 @@ GtkWidget *GetHeaderButtonWidget() return s_button; } +GtkWidget * GetRadioButtonWidget() +{ + static GtkWidget *s_button = NULL; + static GtkWidget *s_window = NULL; + + if ( !s_button ) + { + s_window = gtk_window_new( GTK_WINDOW_POPUP ); + gtk_widget_realize( s_window ); + s_button = gtk_radio_button_new(NULL); + gtk_container_add( GTK_CONTAINER(s_window), s_button ); + gtk_widget_realize( s_button ); + } + + return s_button; +} + GtkWidget* GetSplitterWidget() { static GtkWidget* widget; @@ -126,6 +161,23 @@ GtkWidget* GetSplitterWidget() return widget; } +GtkWidget * GetTextEntryWidget() +{ + static GtkWidget *s_button = NULL; + static GtkWidget *s_window = NULL; + + if ( !s_button ) + { + s_window = gtk_window_new( GTK_WINDOW_POPUP ); + gtk_widget_realize( s_window ); + s_button = gtk_entry_new(); + gtk_container_add( GTK_CONTAINER(s_window), s_button ); + gtk_widget_realize( s_button ); + } + + return s_button; +} + GtkWidget *GetTreeWidget() { static GtkWidget *s_tree = NULL; diff --git a/src/gtk/renderer.cpp b/src/gtk/renderer.cpp index a3490229d3..7cb8da4000 100644 --- a/src/gtk/renderer.cpp +++ b/src/gtk/renderer.cpp @@ -95,6 +95,26 @@ public: const wxRect& rect, int flags = 0); + virtual void DrawChoice(wxWindow* win, + wxDC& dc, + const wxRect& rect, + int flags=0); + + virtual void DrawComboBox(wxWindow* win, + wxDC& dc, + const wxRect& rect, + int flags=0); + + virtual void DrawTextCtrl(wxWindow* win, + wxDC& dc, + const wxRect& rect, + int flags=0); + + virtual void DrawRadioButton(wxWindow* win, + wxDC& dc, + const wxRect& rect, + int flags=0); + virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0); virtual wxSize GetCheckBoxSize(wxWindow *win); @@ -114,6 +134,20 @@ wxRendererNative& wxRendererNative::GetDefault() return s_rendererGTK; } +GdkWindow* wxGetGdkWindowForDC(wxWindow* win, wxDC& dc) +{ + GdkWindow* gdk_window = NULL; +#if wxUSE_NEW_DC + wxDCImpl *impl = dc.GetImpl(); + wxGTKDCImpl *gtk_impl = wxDynamicCast( impl, wxGTKDCImpl ); + if (gtk_impl) + gdk_window = gtk_impl->GetGDKWindow(); +#else + gdk_window = dc.GetGDKWindow(); +#endif + return gdk_window; +} + // ---------------------------------------------------------------------------- // list/tree controls drawing // ---------------------------------------------------------------------------- @@ -129,15 +163,7 @@ wxRendererGTK::DrawHeaderButton(wxWindow *win, GtkWidget *button = wxGTKPrivate::GetHeaderButtonWidget(); - GdkWindow* gdk_window = NULL; -#if wxUSE_NEW_DC - wxDCImpl *impl = dc.GetImpl(); - wxGTKDCImpl *gtk_impl = wxDynamicCast( impl, wxGTKDCImpl ); - if (gtk_impl) - gdk_window = gtk_impl->GetGDKWindow(); -#else - gdk_window = dc.GetGDKWindow(); -#endif + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); wxASSERT_MSG( gdk_window, wxT("cannot use wxRendererNative on wxDC of this type") ); @@ -176,15 +202,7 @@ wxRendererGTK::DrawTreeItemButton(wxWindow* win, { GtkWidget *tree = wxGTKPrivate::GetTreeWidget(); - GdkWindow* gdk_window = NULL; -#if wxUSE_NEW_DC - wxDCImpl *impl = dc.GetImpl(); - wxGTKDCImpl *gtk_impl = wxDynamicCast( impl, wxGTKDCImpl ); - if (gtk_impl) - gdk_window = gtk_impl->GetGDKWindow(); -#else - gdk_window = dc.GetGDKWindow(); -#endif + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); wxASSERT_MSG( gdk_window, wxT("cannot use wxRendererNative on wxDC of this type") ); @@ -263,15 +281,7 @@ wxRendererGTK::DrawSplitterSash(wxWindow *win, return; } - GdkWindow* gdk_window = NULL; -#if wxUSE_NEW_DC - wxDCImpl *impl = dc.GetImpl(); - wxGTKDCImpl *gtk_impl = wxDynamicCast( impl, wxGTKDCImpl ); - if (gtk_impl) - gdk_window = gtk_impl->GetGDKWindow(); -#else - gdk_window = dc.GetGDKWindow(); -#endif + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); wxASSERT_MSG( gdk_window, wxT("cannot use wxRendererNative on wxDC of this type") ); @@ -331,15 +341,7 @@ wxRendererGTK::DrawDropArrow(wxWindow *WXUNUSED(win), // work for wxMemoryDC. So that is why we assume wxDC // is wxWindowDC (wxClientDC, wxMemoryDC and wxPaintDC // are derived from it) and use its m_window. - GdkWindow* gdk_window = NULL; -#if wxUSE_NEW_DC - wxDCImpl *impl = dc.GetImpl(); - wxGTKDCImpl *gtk_impl = wxDynamicCast( impl, wxGTKDCImpl ); - if (gtk_impl) - gdk_window = gtk_impl->GetGDKWindow(); -#else - gdk_window = dc.GetGDKWindow(); -#endif + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); wxASSERT_MSG( gdk_window, wxT("cannot use wxRendererNative on wxDC of this type") ); @@ -414,15 +416,7 @@ wxRendererGTK::DrawCheckBox(wxWindow *WXUNUSED(win), { GtkWidget *button = wxGTKPrivate::GetCheckButtonWidget(); - GdkWindow* gdk_window = NULL; -#if wxUSE_NEW_DC - wxDCImpl *impl = dc.GetImpl(); - wxGTKDCImpl *gtk_impl = wxDynamicCast( impl, wxGTKDCImpl ); - if (gtk_impl) - gdk_window = gtk_impl->GetGDKWindow(); -#else - gdk_window = dc.GetGDKWindow(); -#endif + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); wxASSERT_MSG( gdk_window, wxT("cannot use wxRendererNative on wxDC of this type") ); @@ -466,15 +460,7 @@ wxRendererGTK::DrawPushButton(wxWindow *WXUNUSED(win), { GtkWidget *button = wxGTKPrivate::GetButtonWidget(); - GdkWindow* gdk_window = NULL; -#if wxUSE_NEW_DC - wxDCImpl *impl = dc.GetImpl(); - wxGTKDCImpl *gtk_impl = wxDynamicCast( impl, wxGTKDCImpl ); - if (gtk_impl) - gdk_window = gtk_impl->GetGDKWindow(); -#else - gdk_window = dc.GetGDKWindow(); -#endif + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); wxASSERT_MSG( gdk_window, wxT("cannot use wxRendererNative on wxDC of this type") ); @@ -499,7 +485,10 @@ wxRendererGTK::DrawPushButton(wxWindow *WXUNUSED(win), NULL, button, "button", - rect.x, rect.y, rect.width, rect.height + dc.LogicalToDeviceX(rect.x), + dc.LogicalToDeviceY(rect.y), + rect.width, + rect.height ); } @@ -509,15 +498,7 @@ wxRendererGTK::DrawItemSelectionRect(wxWindow *win, const wxRect& rect, int flags ) { - GdkWindow* gdk_window = NULL; -#if wxUSE_NEW_DC - wxDCImpl *impl = dc.GetImpl(); - wxGTKDCImpl *gtk_impl = wxDynamicCast( impl, wxGTKDCImpl ); - if (gtk_impl) - gdk_window = gtk_impl->GetGDKWindow(); -#else - gdk_window = dc.GetGDKWindow(); -#endif + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); wxASSERT_MSG( gdk_window, wxT("cannot use wxRendererNative on wxDC of this type") ); @@ -571,15 +552,7 @@ wxRendererGTK::DrawItemSelectionRect(wxWindow *win, void wxRendererGTK::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags) { - GdkWindow* gdk_window = NULL; -#if wxUSE_NEW_DC - wxDCImpl *impl = dc.GetImpl(); - wxGTKDCImpl *gtk_impl = wxDynamicCast( impl, wxGTKDCImpl ); - if (gtk_impl) - gdk_window = gtk_impl->GetGDKWindow(); -#else - gdk_window = dc.GetGDKWindow(); -#endif + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); wxASSERT_MSG( gdk_window, wxT("cannot use wxRendererNative on wxDC of this type") ); @@ -600,3 +573,156 @@ void wxRendererGTK::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, i rect.width, rect.height ); } + +// Uses the theme to draw the border and fill for something like a wxTextCtrl +void wxRendererGTK::DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags) +{ + GtkWidget *entry = wxGTKPrivate::GetTextEntryWidget(); + + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); + + GtkStateType state = GTK_STATE_NORMAL; + if ( flags & wxCONTROL_DISABLED ) + state = GTK_STATE_INSENSITIVE; + + if (flags & wxCONTROL_CURRENT ) + GTK_WIDGET_SET_FLAGS( entry, GTK_HAS_FOCUS ); + else + GTK_WIDGET_UNSET_FLAGS( entry, GTK_HAS_FOCUS ); + + gtk_paint_shadow + ( + entry->style, + gdk_window, + state, + GTK_SHADOW_OUT, + NULL, + entry, + "entry", + dc.LogicalToDeviceX(rect.x), + dc.LogicalToDeviceY(rect.y), + rect.width, + rect.height + ); +} + +// Draw the equivallent of a wxComboBox +void wxRendererGTK::DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags) +{ + GtkWidget *combo = wxGTKPrivate::GetComboBoxWidget(); + + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); + + GtkStateType state = GTK_STATE_NORMAL; + if ( flags & wxCONTROL_DISABLED ) + state = GTK_STATE_INSENSITIVE; + + if (flags & wxCONTROL_CURRENT ) + GTK_WIDGET_SET_FLAGS( combo, GTK_HAS_FOCUS ); + else + GTK_WIDGET_UNSET_FLAGS( combo, GTK_HAS_FOCUS ); + + gtk_paint_shadow + ( + combo->style, + gdk_window, + state, + GTK_SHADOW_OUT, + NULL, + combo, + "combobox", + dc.LogicalToDeviceX(rect.x), + dc.LogicalToDeviceY(rect.y), + rect.width, + rect.height + ); + + wxRect r = rect; + int extent = rect.height / 2; + r.x += rect.width - extent - extent/2; + r.y += extent/2; + r.width = extent; + r.height = extent; + + gtk_paint_arrow + ( + combo->style, + gdk_window, + state, + GTK_SHADOW_OUT, + NULL, + combo, + "arrow", + GTK_ARROW_DOWN, + TRUE, + dc.LogicalToDeviceX(r.x), + dc.LogicalToDeviceY(r.y), + r.width, + r.height + ); + + r = rect; + r.x += rect.width - 2*extent; + r.width = 2; + + gtk_paint_box + ( + combo->style, + gdk_window, + state, + GTK_SHADOW_ETCHED_OUT, + NULL, + combo, + "vseparator", + dc.LogicalToDeviceX(r.x), + dc.LogicalToDeviceY(r.y+1), + r.width, + r.height-2 + ); +} + + +void wxRendererGTK::DrawChoice(wxWindow* win, wxDC& dc, + const wxRect& rect, int flags) +{ + DrawComboBox( win, dc, rect, flags ); +} + + +// Draw a themed radio button +void wxRendererGTK::DrawRadioButton(wxWindow* win, wxDC& dc, const wxRect& rect, int flags) +{ + GtkWidget *button = wxGTKPrivate::GetRadioButtonWidget(); + + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); + + GtkShadowType shadow_type = GTK_SHADOW_OUT; + if ( flags & wxCONTROL_CHECKED ) + shadow_type = GTK_SHADOW_IN; + else if ( flags & wxCONTROL_UNDETERMINED ) + shadow_type = GTK_SHADOW_ETCHED_IN; + + GtkStateType state = GTK_STATE_NORMAL; + if ( flags & wxCONTROL_DISABLED ) + state = GTK_STATE_INSENSITIVE; + if ( flags & wxCONTROL_PRESSED ) + state = GTK_STATE_ACTIVE; +/* + Don't know when to set this + state_type = GTK_STATE_PRELIGHT; +*/ + + gtk_paint_option + ( + button->style, + gdk_window, + state, + shadow_type, + NULL, + button, + "radiobutton", + dc.LogicalToDeviceX(rect.x), + dc.LogicalToDeviceY(rect.y), + rect.width, rect.height + ); +} diff --git a/src/msw/renderer.cpp b/src/msw/renderer.cpp index c2b4173972..ea483718a8 100644 --- a/src/msw/renderer.cpp +++ b/src/msw/renderer.cpp @@ -38,11 +38,29 @@ #include "wx/msw/dc.h" #include "wx/msw/uxtheme.h" +#if wxUSE_GRAPHICS_CONTEXT +// TODO remove this dependency (gdiplus needs the macros) +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#include "gdiplus.h" +using namespace Gdiplus; +#endif + // tmschema.h is in Win32 Platform SDK and might not be available with earlier // compilers #ifndef CP_DROPDOWNBUTTON #define BP_PUSHBUTTON 1 + #define BP_RADIOBUTTON 2 #define BP_CHECKBOX 3 + #define RBS_UNCHECKEDNORMAL 1 + #define RBS_CHECKEDNORMAL (RBS_UNCHECKEDNORMAL + 4) + #define RBS_MIXEDNORMAL (RBS_CHECKEDNORMAL + 4) #define CBS_UNCHECKEDNORMAL 1 #define CBS_CHECKEDNORMAL (CBS_UNCHECKEDNORMAL + 4) #define CBS_MIXEDNORMAL (CBS_CHECKEDNORMAL + 4) @@ -76,8 +94,60 @@ #define HP_HEADERSORTARROW 4 #define HSAS_SORTEDUP 1 #define HSAS_SORTEDDOWN 2 + + #define EP_EDITTEXT 1 + #define ETS_NORMAL 1 + #define ETS_HOT 2 + #define ETS_SELECTED 3 + #define ETS_DISABLED 4 + #define ETS_FOCUSED 5 + #define ETS_READONLY 6 + #define ETS_ASSIST 7 + #define TMT_FILLCOLOR 3802 + #define TMT_TEXTCOLOR 3803 + #define TMT_BORDERCOLOR 3801 + #define TMT_EDGEFILLCOLOR 3808 #endif + +// ---------------------------------------------------------------------------- +// If the DC is a wxGCDC then pull out the HDC from the GraphicsContext when +// it is needed, and handle the Release when done. + +class GraphicsHDC +{ +public: + GraphicsHDC(wxDC* dc) + { +#if wxUSE_GRAPHICS_CONTEXT + m_graphics = NULL; + wxGCDC* gcdc = wxDynamicCast(dc, wxGCDC); + if (gcdc) { + m_graphics = (Graphics*)gcdc->GetGraphicsContext()->GetNativeContext(); + m_hdc = m_graphics->GetHDC(); + } + else +#endif + m_hdc = GetHdcOf(*dc); + } + + ~GraphicsHDC() + { +#if wxUSE_GRAPHICS_CONTEXT + if (m_graphics) + m_graphics->ReleaseHDC(m_hdc); +#endif + } + + operator HDC() const { return m_hdc; } + +private: + HDC m_hdc; +#if wxUSE_GRAPHICS_CONTEXT + Graphics* m_graphics; +#endif +}; + #if defined(__WXWINCE__) #ifndef DFCS_FLAT #define DFCS_FLAT 0 @@ -122,6 +192,26 @@ public: const wxRect& rect, int flags = 0); + virtual void DrawChoice(wxWindow* win, + wxDC& dc, + const wxRect& rect, + int flags=0); + + virtual void DrawComboBox(wxWindow* win, + wxDC& dc, + const wxRect& rect, + int flags=0); + + virtual void DrawTextCtrl(wxWindow* win, + wxDC& dc, + const wxRect& rect, + int flags=0); + + virtual void DrawRadioButton(wxWindow* win, + wxDC& dc, + const wxRect& rect, + int flags=0); + virtual wxSize GetCheckBoxSize(wxWindow *win); virtual int GetHeaderButtonHeight(wxWindow *win); @@ -230,7 +320,7 @@ wxRendererMSW::DrawComboBoxDropButton(wxWindow * WXUNUSED(win), if ( flags & wxCONTROL_PRESSED ) style |= DFCS_PUSHED | DFCS_FLAT; - ::DrawFrameControl(GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())), &r, DFC_SCROLL, style); + ::DrawFrameControl(GraphicsHDC(((wxMSWDCImpl*)dc.GetImpl())), &r, DFC_SCROLL, style); } void @@ -254,7 +344,7 @@ wxRendererMSW::DrawCheckBox(wxWindow * WXUNUSED(win), if ( flags & wxCONTROL_CURRENT ) style |= DFCS_HOT; - ::DrawFrameControl(GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())), &r, DFC_BUTTON, style); + ::DrawFrameControl(GraphicsHDC((wxMSWDCImpl*)dc.GetImpl())), &r, DFC_BUTTON, style); } void @@ -283,7 +373,7 @@ wxRendererMSW::DrawPushButton(wxWindow * WXUNUSED(win), RECT rc; wxCopyRectToRECT(rect, rc); - ::DrawFrameControl(GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())), &rc, DFC_BUTTON, style); + ::DrawFrameControl(GraphicsHDC((wxMSWDCImpl*)dc.GetImpl())), &rc, DFC_BUTTON, style); } void wxRendererMSW::DrawFocusRect(wxWindow * WXUNUSED(win), @@ -294,7 +384,7 @@ void wxRendererMSW::DrawFocusRect(wxWindow * WXUNUSED(win), RECT rc; wxCopyRectToRECT(rect, rc); - ::DrawFocusRect(GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())), &rc); + ::DrawFocusRect(GraphicsHDC((wxMSWDCImpl*)dc.GetImpl())), &rc); } wxSize wxRendererMSW::GetCheckBoxSize(wxWindow * WXUNUSED(win)) @@ -326,6 +416,112 @@ int wxRendererMSW::GetHeaderButtonHeight(wxWindow * WXUNUSED(win)) return Header_Layout(hwndHeader, &hdl) ? wp.cy : DEFAULT_HEIGHT; } +// Uses the theme to draw the border and fill for something like a wxTextCtrl +void wxRendererMSW::DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags) +{ + wxColour fill; + wxColour bdr; + COLORREF cref; + +#if wxUSE_UXTHEME + wxUxThemeHandle hTheme(win, L"EDIT"); + if (hTheme) + { + wxUxThemeEngine::Get()->GetThemeColor(hTheme, EP_EDITTEXT, + ETS_NORMAL, TMT_FILLCOLOR, &cref); + fill = wxRGBToColour(cref); + + int etsState; + if ( flags & wxCONTROL_DISABLED ) + etsState = ETS_DISABLED; + else + etsState = ETS_NORMAL; + + wxUxThemeEngine::Get()->GetThemeColor(hTheme, EP_EDITTEXT, + etsState, TMT_BORDERCOLOR, &cref); + bdr = wxRGBToColour(cref); + } + else +#endif + { + fill = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + bdr = *wxBLACK; + } + + dc.SetPen( bdr ); + dc.SetBrush( fill ); + dc.DrawRectangle(rect); +} + + +// Draw the equivallent of a wxComboBox +void wxRendererMSW::DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags) +{ + // Draw the main part of the control same as TextCtrl + DrawTextCtrl(win, dc, rect, flags); + + // Draw the button inside the border, on the right side + wxRect br(rect); + br.height -= 2; + br.x += br.width - br.height - 1; + br.width = br.height; + br.y += 1; + + DrawComboBoxDropButton(win, dc, br, flags); +} + + +void wxRendererMSW::DrawChoice(wxWindow* win, wxDC& dc, + const wxRect& rect, int flags) +{ + DrawComboBox(win, dc, rect, flags); +} + + +// Draw a themed radio button +void wxRendererMSW::DrawRadioButton(wxWindow* win, wxDC& dc, const wxRect& rect, int flags) +{ +#if wxUSE_UXTHEME + wxUxThemeHandle hTheme(win, L"BUTTON"); + if ( !hTheme ) +#endif + { + // ??? m_rendererNative.DrawRadioButton(win, dc, rect, flags); + return; + } + +#if wxUSE_UXTHEME + RECT r; + wxCopyRectToRECT(rect, r); + + int state; + if ( flags & wxCONTROL_CHECKED ) + state = RBS_CHECKEDNORMAL; + else if ( flags & wxCONTROL_UNDETERMINED ) + state = RBS_MIXEDNORMAL; + else + state = RBS_UNCHECKEDNORMAL; + + // RBS_XXX is followed by RBX_XXXGOT, then RBS_XXXPRESSED and DISABLED + if ( flags & wxCONTROL_CURRENT ) + state += 1; + else if ( flags & wxCONTROL_PRESSED ) + state += 2; + else if ( flags & wxCONTROL_DISABLED ) + state += 3; + + wxUxThemeEngine::Get()->DrawThemeBackground + ( + hTheme, + GraphicsHDC(&dc), + BP_RADIOBUTTON, + state, + &r, + NULL + ); +#endif +} + // ============================================================================ // wxRendererXP implementation // ============================================================================ @@ -452,6 +648,8 @@ wxRendererXP::DrawTreeItemButton(wxWindow *win, ); } + + void wxRendererXP::DrawCheckBox(wxWindow *win, wxDC& dc, @@ -539,7 +737,6 @@ wxRendererXP::DrawPushButton(wxWindow * win, &r, NULL ); - } void diff --git a/src/osx/carbon/renderer.cpp b/src/osx/carbon/renderer.cpp index ee4b05d680..1d8bbd4df7 100644 --- a/src/osx/carbon/renderer.cpp +++ b/src/osx/carbon/renderer.cpp @@ -35,6 +35,14 @@ #include #endif +// check if we're currently in a paint event +inline bool wxInPaintEvent(wxWindow* win, wxDC& dc) +{ + return ( win->MacGetCGContextRef() != NULL ); +} + + + class WXDLLEXPORT wxRendererMac : public wxDelegateRendererNative { public: @@ -86,6 +94,14 @@ public: virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0); + virtual void DrawChoice(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0); + + virtual void DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0); + + virtual void DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0); + + virtual void DrawRadioButton(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0); + private: void DrawMacThemeButton(wxWindow *win, wxDC& dc, @@ -126,7 +142,7 @@ int wxRendererMac::DrawHeaderButton( wxWindow *win, dc.SetBrush( *wxTRANSPARENT_BRUSH ); HIRect headerRect = CGRectMake( x, y, w, h ); - if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) ) + if ( !wxInPaintEvent(win, dc) ) { win->Refresh( &rect ); } @@ -209,7 +225,7 @@ void wxRendererMac::DrawTreeItemButton( wxWindow *win, dc.SetBrush( *wxTRANSPARENT_BRUSH ); HIRect headerRect = CGRectMake( x, y, w, h ); - if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) ) + if ( !wxInPaintEvent(win, dc) ) { win->Refresh( &rect ); } @@ -255,7 +271,7 @@ void wxRendererMac::DrawSplitterSash( wxWindow *win, // under compositing we should only draw when called by the OS, otherwise just issue a redraw command // strange redraw errors occur if we don't do this - if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) ) + if ( !wxInPaintEvent(win, dc) ) { wxRect rect( (int) splitterRect.origin.x, (int) splitterRect.origin.y, (int) splitterRect.size.width, (int) splitterRect.size.height ); @@ -312,7 +328,7 @@ wxRendererMac::DrawMacThemeButton(wxWindow *win, dc.SetBrush( *wxTRANSPARENT_BRUSH ); HIRect headerRect = CGRectMake( x, y, w, h ); - if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) ) + if ( !wxInPaintEvent(win, dc) ) { win->Refresh( &rect ); } @@ -333,7 +349,9 @@ wxRendererMac::DrawMacThemeButton(wxWindow *win, if (flags & wxCONTROL_UNDETERMINED) drawInfo.value = kThemeButtonMixed; drawInfo.adornment = adornment; - + if (flags & wxCONTROL_FOCUSED) + drawInfo.adornment |= kThemeAdornmentFocus; + HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect ); } } @@ -347,8 +365,20 @@ wxRendererMac::DrawCheckBox(wxWindow *win, if (flags & wxCONTROL_CHECKED) flags |= wxCONTROL_SELECTED; + int kind; + + if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || + (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL)) + kind = kThemeCheckBoxSmall; + else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || + (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI)) + kind = kThemeCheckBoxMini; + else + kind = kThemeCheckBox; + + DrawMacThemeButton(win, dc, rect, flags, - kThemeCheckBox, kThemeAdornmentNone); + kind, kThemeAdornmentNone); } wxSize wxRendererMac::GetCheckBoxSize(wxWindow* WXUNUSED(win)) @@ -421,6 +451,7 @@ wxRendererMac::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int fl CGRect cgrect = CGRectMake( rect.x , rect.y , rect.width, rect.height ) ; HIThemeFrameDrawInfo info ; + memset( &info, 0 , sizeof(info) ) ; info.version = 0 ; @@ -433,3 +464,110 @@ wxRendererMac::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int fl HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ; } + +void wxRendererMac::DrawChoice(wxWindow* win, wxDC& dc, + const wxRect& rect, int flags) +{ + int kind; + + if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || + (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL)) + kind = kThemePopupButtonSmall; + else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || + (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI)) + kind = kThemePopupButtonMini; + else + kind = kThemePopupButton; + + DrawMacThemeButton(win, dc, rect, flags, kind, kThemeAdornmentNone); +} + + +void wxRendererMac::DrawComboBox(wxWindow* win, wxDC& dc, + const wxRect& rect, int flags) +{ + int kind; + + if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || + (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL)) + kind = kThemeComboBoxSmall; + else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || + (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI)) + kind = kThemeComboBoxMini; + else + kind = kThemeComboBox; + + DrawMacThemeButton(win, dc, rect, flags, kind, kThemeAdornmentNone); +} + +void wxRendererMac::DrawRadioButton(wxWindow* win, wxDC& dc, + const wxRect& rect, int flags) +{ + int kind; + + if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || + (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL)) + kind = kThemeRadioButtonSmall; + else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || + (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI)) + kind = kThemeRadioButtonMini; + else + kind = kThemeRadioButton; + + if (flags & wxCONTROL_CHECKED) + flags |= wxCONTROL_SELECTED; + + DrawMacThemeButton(win, dc, rect, flags, + kind, kThemeAdornmentNone); +} + +void wxRendererMac::DrawTextCtrl(wxWindow* win, wxDC& dc, + const wxRect& rect, int flags) +{ + const wxCoord x = rect.x; + const wxCoord y = rect.y; + const wxCoord w = rect.width; + const wxCoord h = rect.height; + + dc.SetBrush( *wxWHITE_BRUSH ); + dc.SetPen( *wxTRANSPARENT_PEN ); + dc.DrawRectangle(rect); + + dc.SetBrush( *wxTRANSPARENT_BRUSH ); + + HIRect hiRect = CGRectMake( x, y, w, h ); + if ( !wxInPaintEvent(win, dc) ) + { + Rect r = + { + (short) hiRect.origin.y, (short) hiRect.origin.x, + (short) (hiRect.origin.y + hiRect.size.height), + (short) (hiRect.origin.x + hiRect.size.width) + }; + + RgnHandle updateRgn = NewRgn(); + RectRgn( updateRgn, &r ); + HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true ); + DisposeRgn( updateRgn ); + } + else + { + CGContextRef cgContext; + + cgContext = (CGContextRef) static_cast(dc.GetImpl())->GetGraphicsContext()->GetNativeContext(); + + { + HIThemeFrameDrawInfo drawInfo; + + memset( &drawInfo, 0, sizeof(drawInfo) ); + drawInfo.version = 0; + drawInfo.kind = kHIThemeFrameTextFieldSquare; + drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive; + if (flags & wxCONTROL_FOCUSED) + drawInfo.isFocused = true; + + HIThemeDrawFrame( &hiRect, &drawInfo, cgContext, kHIThemeOrientationNormal); + } + } +} +