X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f4bc1aa27cb33f679d7e9c1518a7855bbc1fa471..12bb29f5432174ecbd65549bda832d70d34a98ae:/src/propgrid/editors.cpp diff --git a/src/propgrid/editors.cpp b/src/propgrid/editors.cpp index fd0a8c663c..1817abc615 100644 --- a/src/propgrid/editors.cpp +++ b/src/propgrid/editors.cpp @@ -4,9 +4,9 @@ // Author: Jaakko Salli // Modified by: // Created: 2007-04-14 -// RCS-ID: $Id: +// RCS-ID: $Id$ // Copyright: (c) Jaakko Salli -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx/wx.h". @@ -41,7 +41,6 @@ #include "wx/stattext.h" #include "wx/scrolwin.h" #include "wx/dirdlg.h" - #include "wx/layout.h" #include "wx/sizer.h" #include "wx/textdlg.h" #include "wx/filedlg.h" @@ -59,36 +58,29 @@ // This define is necessary to prevent macro clearing #define __wxPG_SOURCE_FILE__ -#include -#include -#include +#include "wx/propgrid/propgrid.h" +#include "wx/propgrid/editors.h" +#include "wx/propgrid/props.h" #if wxPG_USE_RENDERER_NATIVE - #include + #include "wx/renderer.h" #endif // How many pixels between textctrl and button #ifdef __WXMAC__ - #define wxPG_TEXTCTRL_AND_BUTTON_SPACING 8 + #define wxPG_TEXTCTRL_AND_BUTTON_SPACING 4 #else #define wxPG_TEXTCTRL_AND_BUTTON_SPACING 2 -#endif +#endif #define wxPG_BUTTON_SIZEDEC 0 -#include - -#ifdef __WXMSW__ - #include -#endif +#include "wx/odcombo.h" // ----------------------------------------------------------------------- #if defined(__WXMSW__) // tested - #define wxPG_NAT_TEXTCTRL_BORDER_X 0 // Unremovable border of native textctrl. - #define wxPG_NAT_TEXTCTRL_BORDER_Y 0 // Unremovable border of native textctrl. - #define wxPG_NAT_BUTTON_BORDER_ANY 1 #define wxPG_NAT_BUTTON_BORDER_X 1 #define wxPG_NAT_BUTTON_BORDER_Y 1 @@ -103,15 +95,12 @@ #elif defined(__WXGTK__) // tested - #define wxPG_CHECKMARK_XADJ 0 - #define wxPG_CHECKMARK_YADJ 0 - #define wxPG_CHECKMARK_WADJ (-1) - #define wxPG_CHECKMARK_HADJ (-1) + #define wxPG_CHECKMARK_XADJ 1 + #define wxPG_CHECKMARK_YADJ 1 + #define wxPG_CHECKMARK_WADJ (-2) + #define wxPG_CHECKMARK_HADJ (-2) #define wxPG_CHECKMARK_DEFLATE 3 - #define wxPG_NAT_TEXTCTRL_BORDER_X 3 // Unremovable border of native textctrl. - #define wxPG_NAT_TEXTCTRL_BORDER_Y 3 // Unremovable border of native textctrl. - #define wxPG_NAT_BUTTON_BORDER_ANY 1 #define wxPG_NAT_BUTTON_BORDER_X 1 #define wxPG_NAT_BUTTON_BORDER_Y 1 @@ -120,20 +109,17 @@ #elif defined(__WXMAC__) // *not* tested - #define wxPG_CHECKMARK_XADJ 0 - #define wxPG_CHECKMARK_YADJ 0 - #define wxPG_CHECKMARK_WADJ 0 - #define wxPG_CHECKMARK_HADJ 0 + #define wxPG_CHECKMARK_XADJ 4 + #define wxPG_CHECKMARK_YADJ 4 + #define wxPG_CHECKMARK_WADJ -6 + #define wxPG_CHECKMARK_HADJ -6 #define wxPG_CHECKMARK_DEFLATE 0 - #define wxPG_NAT_TEXTCTRL_BORDER_X 0 // Unremovable border of native textctrl. - #define wxPG_NAT_TEXTCTRL_BORDER_Y 0 // Unremovable border of native textctrl. - #define wxPG_NAT_BUTTON_BORDER_ANY 0 #define wxPG_NAT_BUTTON_BORDER_X 0 #define wxPG_NAT_BUTTON_BORDER_Y 0 - #define wxPG_TEXTCTRLYADJUST 3 + #define wxPG_TEXTCTRLYADJUST 0 #else // defaults @@ -143,9 +129,6 @@ #define wxPG_CHECKMARK_HADJ 0 #define wxPG_CHECKMARK_DEFLATE 0 - #define wxPG_NAT_TEXTCTRL_BORDER_X 0 // Unremovable border of native textctrl. - #define wxPG_NAT_TEXTCTRL_BORDER_Y 0 // Unremovable border of native textctrl. - #define wxPG_NAT_BUTTON_BORDER_ANY 0 #define wxPG_NAT_BUTTON_BORDER_X 0 #define wxPG_NAT_BUTTON_BORDER_Y 0 @@ -154,20 +137,19 @@ #endif -#if (!wxPG_NAT_TEXTCTRL_BORDER_X && !wxPG_NAT_TEXTCTRL_BORDER_Y) - #define wxPG_ENABLE_CLIPPER_WINDOW 0 -#else - #define wxPG_ENABLE_CLIPPER_WINDOW 1 -#endif - - // for odcombo +#ifdef __WXMAC__ +#define wxPG_CHOICEXADJUST -3 // required because wxComboCtrl reserves 3pixels for wxTextCtrl's focus ring +#define wxPG_CHOICEYADJUST -3 +#else #define wxPG_CHOICEXADJUST 0 #define wxPG_CHOICEYADJUST 0 +#endif -#define ODCB_CUST_PAINT_MARGIN 6 // Number added to image width for SetCustomPaintWidth +// Number added to image width for SetCustomPaintWidth +#define ODCB_CUST_PAINT_MARGIN 6 -// Milliseconds to wait for two mouse-ups after focus inorder +// Milliseconds to wait for two mouse-ups after focus in order // to trigger a double-click. #define DOUBLE_CLICK_CONVERSION_TRESHOLD 500 @@ -182,10 +164,16 @@ wxPGEditor::~wxPGEditor() { } -void wxPGEditor::DrawValue( wxDC& dc, const wxRect& rect, wxPGProperty* property, const wxString& text ) const +wxString wxPGEditor::GetName() const { - if ( !property->IsValueUnspecified() ) - dc.DrawText( text, rect.x+wxPG_XBEFORETEXT, rect.y ); + return GetClassInfo()->GetClassName(); +} + +void wxPGEditor::DrawValue( wxDC& dc, const wxRect& rect, + wxPGProperty* WXUNUSED(property), + const wxString& text ) const +{ + dc.DrawText( text, rect.x+wxPG_XBEFORETEXT, rect.y ); } bool wxPGEditor::GetValueFromControl( wxVariant&, wxPGProperty*, wxWindow* ) const @@ -219,206 +207,119 @@ void wxPGEditor::OnFocus( wxPGProperty*, wxWindow* ) const { } - -bool wxPGEditor::CanContainCustomImage() const -{ - return false; -} - -// ----------------------------------------------------------------------- -// wxPGClipperWindow -// ----------------------------------------------------------------------- - - -#if wxPG_ENABLE_CLIPPER_WINDOW - -// -// Clipper window is used to "remove" borders from controls -// which otherwise insist on having them despite of supplied -// wxNO_BORDER window style. -// -class wxPGClipperWindow : public wxWindow +void wxPGEditor::SetControlAppearance( wxPropertyGrid* pg, + wxPGProperty* property, + wxWindow* ctrl, + const wxPGCell& cell, + const wxPGCell& oCell, + bool unspecified ) const { - DECLARE_CLASS(wxPGClipperWindow) -public: - - wxPGClipperWindow() - : wxWindow() + // Get old editor appearance + wxTextCtrl* tc = NULL; + wxComboCtrl* cb = NULL; + if ( wxDynamicCast(ctrl, wxTextCtrl) ) { - wxPGClipperWindow::Init(); + tc = (wxTextCtrl*) ctrl; } - - wxPGClipperWindow(wxWindow* parent, - wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize) + else { - Init(); - Create(parent,id,pos,size); + if ( wxDynamicCast(ctrl, wxComboCtrl) ) + { + cb = (wxComboCtrl*) ctrl; + tc = cb->GetTextCtrl(); + } } - void Create(wxWindow* parent, - wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize); - - virtual ~wxPGClipperWindow(); - - virtual bool ProcessEvent(wxEvent& event); - - inline wxWindow* GetControl() const { return m_ctrl; } - - // This is called before wxControl is constructed. - void GetControlRect( int xadj, int yadj, wxPoint& pt, wxSize& sz ); - - // This is caleed after wxControl has been constructed. - void SetControl( wxWindow* ctrl ); - - virtual void Refresh( bool eraseBackground = true, - const wxRect *rect = (const wxRect *) NULL ); - virtual void SetFocus(); - - virtual bool SetFont(const wxFont& font); - - inline int GetXClip() const { return m_xadj; } - - inline int GetYClip() const { return m_yadj; } + if ( tc || cb ) + { + wxString tcText; + bool changeText = false; -protected: - wxWindow* m_ctrl; + if ( cell.HasText() && !pg->IsEditorFocused() ) + { + tcText = cell.GetText(); + changeText = true; + } + else if ( oCell.HasText() ) + { + tcText = property->GetValueAsString( + property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE); + changeText = true; + } - int m_xadj; // Horizontal border clip. + if ( changeText ) + { + // This prevents value from being modified + if ( tc ) + { + pg->SetupTextCtrlValue(tcText); + tc->SetValue(tcText); + } + else + { + cb->SetText(tcText); + } + } + } - int m_yadj; // Vertical border clip. + // Do not make the mistake of calling GetClassDefaultAttributes() + // here. It is static, while GetDefaultAttributes() is virtual + // and the correct one to use. + wxVisualAttributes vattrs = ctrl->GetDefaultAttributes(); -private: - void Init () + // Foreground colour + const wxColour& fgCol = cell.GetFgCol(); + if ( fgCol.IsOk() ) { - m_ctrl = (wxWindow*) NULL; + ctrl->SetForegroundColour(fgCol); + } + else if ( oCell.GetFgCol().IsOk() ) + { + ctrl->SetForegroundColour(vattrs.colFg); } -}; - - -IMPLEMENT_CLASS(wxPGClipperWindow,wxWindow) - - -// This is called before wxControl is constructed. -void wxPGClipperWindow::GetControlRect( int xadj, int yadj, wxPoint& pt, wxSize& sz ) -{ - m_xadj = xadj; - m_yadj = yadj; - pt.x = -xadj; - pt.y = -yadj; - wxSize own_size = GetSize(); - sz.x = own_size.x+(xadj*2); - sz.y = own_size.y+(yadj*2); -} - - -// This is caleed after wxControl has been constructed. -void wxPGClipperWindow::SetControl( wxWindow* ctrl ) -{ - m_ctrl = ctrl; - - // GTK requires this. - ctrl->SetSizeHints(3,3); - - // Correct size of this window to match the child. - wxSize sz = GetSize(); - wxSize chsz = ctrl->GetSize(); - - int hei_adj = chsz.y - (sz.y+(m_yadj*2)); - if ( hei_adj ) - SetSize(sz.x,chsz.y-(m_yadj*2)); - -} - - -void wxPGClipperWindow::Refresh( bool eraseBackground, const wxRect *rect ) -{ - wxWindow::Refresh(false,rect); - if ( m_ctrl ) - m_ctrl->Refresh(eraseBackground); -} - - -// Pass focus to control -void wxPGClipperWindow::SetFocus() -{ - if ( m_ctrl ) - m_ctrl->SetFocus(); - else - wxWindow::SetFocus(); -} - -bool wxPGClipperWindow::SetFont(const wxFont& font) -{ - bool res = wxWindow::SetFont(font); - if ( m_ctrl ) - return m_ctrl->SetFont(font); - return res; -} + // Background colour + const wxColour& bgCol = cell.GetBgCol(); + if ( bgCol.IsOk() ) + { + ctrl->SetBackgroundColour(bgCol); + } + else if ( oCell.GetBgCol().IsOk() ) + { + ctrl->SetBackgroundColour(vattrs.colBg); + } + // Font + const wxFont& font = cell.GetFont(); + if ( font.IsOk() ) + { + ctrl->SetFont(font); + } + else if ( oCell.GetFont().IsOk() ) + { + ctrl->SetFont(vattrs.font); + } -void wxPGClipperWindow::Create(wxWindow* parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size ) -{ - wxWindow::Create(parent,id,pos,size); + // Also call the old SetValueToUnspecified() + if ( unspecified ) + SetValueToUnspecified(property, ctrl); } - -wxPGClipperWindow::~wxPGClipperWindow() +void wxPGEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), + wxWindow* WXUNUSED(ctrl) ) const { } - -bool wxPGClipperWindow::ProcessEvent(wxEvent& event) +bool wxPGEditor::CanContainCustomImage() const { - if ( event.GetEventType() == wxEVT_SIZE ) - { - if ( m_ctrl ) - { - // Maintain correct size relationship. - wxSize sz = GetSize(); - m_ctrl->SetSize(sz.x+(m_xadj*2),sz.y+(m_yadj*2)); - event.Skip(); - return false; - } - } - return wxWindow::ProcessEvent(event); + return false; } -#endif // wxPG_ENABLE_CLIPPER_WINDOW - -/*wxWindow* wxPropertyGrid::GetActualEditorControl( wxWindow* ctrl ) -{ -#if wxPG_ENABLE_CLIPPER_WINDOW - // Pass real control instead of clipper window - if ( ctrl->IsKindOf(CLASSINFO(wxPGClipperWindow)) ) - { - return ((wxPGClipperWindow*)ctrl)->GetControl(); - } -#else - return ctrl; -#endif -}*/ - // ----------------------------------------------------------------------- // wxPGTextCtrlEditor // ----------------------------------------------------------------------- -// Clipper window support macro (depending on whether it is used -// for this editor or not) -#if wxPG_NAT_TEXTCTRL_BORDER_X || wxPG_NAT_TEXTCTRL_BORDER_Y - #define wxPG_NAT_TEXTCTRL_BORDER_ANY 1 -#else - #define wxPG_NAT_TEXTCTRL_BORDER_ANY 0 -#endif - -WX_PG_IMPLEMENT_EDITOR_CLASS(TextCtrl,wxPGTextCtrlEditor,wxPGEditor) +WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(TextCtrl,wxPGTextCtrlEditor,wxPGEditor) wxPGWindowList wxPGTextCtrlEditor::CreateControls( wxPropertyGrid* propGrid, @@ -432,17 +333,20 @@ wxPGWindowList wxPGTextCtrlEditor::CreateControls( wxPropertyGrid* propGrid, // If has children, and limited editing is specified, then don't create. if ( (property->GetFlags() & wxPG_PROP_NOEDITOR) && property->GetChildCount() ) - return (wxWindow*) NULL; + return NULL; - if ( !property->IsValueUnspecified() ) - text = property->GetValueString(property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE); + int argFlags = 0; + if ( !property->HasFlag(wxPG_PROP_READONLY) && + !property->IsValueUnspecified() ) + argFlags |= wxPG_EDITABLE_VALUE; + text = property->GetValueAsString(argFlags); int flags = 0; if ( (property->GetFlags() & wxPG_PROP_PASSWORD) && - property->IsKindOf(CLASSINFO(wxStringProperty)) ) + wxDynamicCast(property, wxStringProperty) ) flags |= wxTE_PASSWORD; - wxWindow* wnd = propGrid->GenerateEditorTextCtrl(pos,sz,text,(wxWindow*)NULL,flags, + wxWindow* wnd = propGrid->GenerateEditorTextCtrl(pos,sz,text,NULL,flags, property->GetMaxLength()); return wnd; @@ -481,9 +385,16 @@ void wxPGTextCtrlEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) else s = property->GetDisplayedString(); - tc->SetValue(s); -} + wxPropertyGrid* pg = property->GetGrid(); + pg->SetupTextCtrlValue(s); + tc->SetValue(s); + + // + // Fix indentation, just in case (change in font boldness is one good + // reason). + tc->SetMargins(0); +} // Provided so that, for example, ComboBox editor can use the same code // (multiple inheritance would get way too messy). @@ -495,14 +406,14 @@ bool wxPGTextCtrlEditor::OnTextCtrlEvent( wxPropertyGrid* propGrid, if ( !ctrl ) return false; - if ( event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER ) + if ( event.GetEventType() == wxEVT_TEXT_ENTER ) { if ( propGrid->IsEditorsValueModified() ) { return true; } } - else if ( event.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED ) + else if ( event.GetEventType() == wxEVT_TEXT ) { // // Pass this event outside wxPropertyGrid so that, @@ -533,7 +444,7 @@ bool wxPGTextCtrlEditor::GetTextCtrlValueFromControl( wxVariant& variant, wxPGPr wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl); wxString textVal = tc->GetValue(); - if ( property->UsesAutoUnspecified() && !textVal.length() ) + if ( property->UsesAutoUnspecified() && textVal.empty() ) { variant.MakeNull(); return true; @@ -557,37 +468,51 @@ bool wxPGTextCtrlEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* } -void wxPGTextCtrlEditor::SetValueToUnspecified( wxPGProperty* property, wxWindow* ctrl ) const +void wxPGTextCtrlEditor::SetControlStringValue( wxPGProperty* property, wxWindow* ctrl, const wxString& txt ) const { wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl); wxPropertyGrid* pg = property->GetGrid(); wxASSERT(pg); // Really, property grid should exist if editor does if ( pg ) - tc->SetValue(wxEmptyString); + { + pg->SetupTextCtrlValue(txt); + tc->SetValue(txt); + } } -void wxPGTextCtrlEditor::SetControlStringValue( wxPGProperty* property, wxWindow* ctrl, const wxString& txt ) const +void wxPGTextCtrlEditor_OnFocus( wxPGProperty* property, + wxTextCtrl* tc ) { - wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl); + // Make sure there is correct text (instead of unspecified value + // indicator or hint text) + int flags = property->HasFlag(wxPG_PROP_READONLY) ? + 0 : wxPG_EDITABLE_VALUE; + wxString correctText = property->GetValueAsString(flags); - wxPropertyGrid* pg = property->GetGrid(); - wxASSERT(pg); // Really, property grid should exist if editor does - if ( pg ) - tc->SetValue(txt); -} + if ( tc->GetValue() != correctText ) + { + property->GetGrid()->SetupTextCtrlValue(correctText); + tc->SetValue(correctText); + } + tc->SelectAll(); +} -void wxPGTextCtrlEditor::OnFocus( wxPGProperty*, wxWindow* wnd ) const +void wxPGTextCtrlEditor::OnFocus( wxPGProperty* property, + wxWindow* wnd ) const { wxTextCtrl* tc = wxStaticCast(wnd, wxTextCtrl); - - tc->SetSelection(-1,-1); + wxPGTextCtrlEditor_OnFocus(property, tc); } - -wxPGTextCtrlEditor::~wxPGTextCtrlEditor() { } +wxPGTextCtrlEditor::~wxPGTextCtrlEditor() +{ + // Reset the global pointer. Useful when wxPropertyGrid is accessed + // from an external main loop. + wxPG_EDITOR(TextCtrl) = NULL; +} // ----------------------------------------------------------------------- @@ -595,7 +520,7 @@ wxPGTextCtrlEditor::~wxPGTextCtrlEditor() { } // ----------------------------------------------------------------------- -WX_PG_IMPLEMENT_EDITOR_CLASS(Choice,wxPGChoiceEditor,wxPGEditor) +WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(Choice,wxPGChoiceEditor,wxPGEditor) // This is a special enhanced double-click processor class. @@ -622,7 +547,7 @@ protected: int evtType = event.GetEventType(); if ( m_property->HasFlag(wxPG_PROP_USE_DCC) && - m_property->IsKindOf(CLASSINFO(wxBoolProperty)) && + wxDynamicCast(m_property, wxBoolProperty) && !m_combo->IsPopupShown() ) { // Just check that it is in the text area @@ -692,7 +617,7 @@ public: wxPGComboBox() : wxOwnerDrawnComboBox() { - m_dclickProcessor = (wxPGDoubleClickProcessor*) NULL; + m_dclickProcessor = NULL; m_sizeEventCalled = false; } @@ -726,31 +651,47 @@ public: name ) ) return false; - m_dclickProcessor = new wxPGDoubleClickProcessor(this, GetGrid()->GetSelection() ); + m_dclickProcessor = new + wxPGDoubleClickProcessor( this, GetGrid()->GetSelection() ); PushEventHandler(m_dclickProcessor); return true; } - virtual void OnDrawItem( wxDC& dc, const wxRect& rect, int item, int flags ) const + virtual void OnDrawItem( wxDC& dc, + const wxRect& rect, + int item, + int flags ) const { wxPropertyGrid* pg = GetGrid(); - pg->OnComboItemPaint((wxPGCustomComboControl*)this,item,dc,(wxRect&)rect,flags); + + // Handle hint text via super class + if ( (flags & wxODCB_PAINTING_CONTROL) && + ShouldUseHintText(flags) ) + { + wxOwnerDrawnComboBox::OnDrawItem(dc, rect, item, flags); + } + else + { + pg->OnComboItemPaint( this, item, &dc, (wxRect&)rect, flags ); + } } + virtual wxCoord OnMeasureItem( size_t item ) const { wxPropertyGrid* pg = GetGrid(); wxRect rect; rect.x = -1; rect.width = 0; - pg->OnComboItemPaint((wxPGCustomComboControl*)this,item,*((wxDC*)NULL),rect,0); + pg->OnComboItemPaint( this, item, NULL, rect, 0 ); return rect.height; } wxPropertyGrid* GetGrid() const { - wxPropertyGrid* pg = wxDynamicCast(GetParent()->GetParent(),wxPropertyGrid); + wxPropertyGrid* pg = wxDynamicCast(GetParent(), + wxPropertyGrid); wxASSERT(pg); return pg; } @@ -761,15 +702,20 @@ public: wxRect rect; rect.x = -1; rect.width = -1; - pg->OnComboItemPaint((wxPGCustomComboControl*)this,item,*((wxDC*)NULL),rect,0); + pg->OnComboItemPaint( this, item, NULL, rect, 0 ); return rect.width; } - virtual void PositionTextCtrl( int WXUNUSED(textCtrlXAdjust), int WXUNUSED(textCtrlYAdjust) ) + virtual void PositionTextCtrl( int textCtrlXAdjust, + int WXUNUSED(textCtrlYAdjust) ) { wxPropertyGrid* pg = GetGrid(); + #ifdef wxPG_TEXTCTRLXADJUST + textCtrlXAdjust = wxPG_TEXTCTRLXADJUST - + (wxPG_XBEFOREWIDGET+wxPG_CONTROL_MARGIN+1) - 1, + #endif wxOwnerDrawnComboBox::PositionTextCtrl( - wxPG_TEXTCTRLXADJUST - (wxPG_XBEFOREWIDGET+wxPG_CONTROL_MARGIN+1) - 1, + textCtrlXAdjust, pg->GetSpacingY() + 2 ); } @@ -780,25 +726,24 @@ private: }; -void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc, +void wxPropertyGrid::OnComboItemPaint( const wxPGComboBox* pCb, int item, - wxDC& dc, + wxDC* pDc, wxRect& rect, int flags ) { - wxPGComboBox* pCb = (wxPGComboBox*)pCc; - - // Sanity check - wxASSERT( IsKindOf(CLASSINFO(wxPropertyGrid)) ); - - wxPGProperty* p = m_selected; + wxPGProperty* p = GetSelection(); wxString text; - const wxPGChoices* pChoices = &p->GetChoices(); + const wxPGChoices& choices = p->GetChoices(); const wxPGCommonValue* comVal = NULL; - int choiceCount = p->GetChoiceCount(); int comVals = p->GetDisplayedCommonValueCount(); int comValIndex = -1; + + int choiceCount = 0; + if ( choices.IsOk() ) + choiceCount = choices.GetCount(); + if ( item >= choiceCount && comVals > 0 ) { comValIndex = item - choiceCount; @@ -815,7 +760,7 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc, else { if ( !p->IsValueUnspecified() ) - text = p->GetValueString(0); + text = p->GetValueAsString(0); } } @@ -826,8 +771,8 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc, const wxBitmap* itemBitmap = NULL; - if ( item >= 0 && pChoices && pChoices->Item(item).GetBitmap().Ok() && comValIndex == -1 ) - itemBitmap = &pChoices->Item(item).GetBitmap(); + if ( item >= 0 && choices.IsOk() && choices.Item(item).GetBitmap().IsOk() && comValIndex == -1 ) + itemBitmap = &choices.Item(item).GetBitmap(); // // Decide what custom image size to use @@ -847,7 +792,7 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc, if ( rect.width < 0 ) { wxCoord x, y; - GetTextExtent(text, &x, &y, 0, 0, &m_font); + pCb->GetTextExtent(text, &x, &y, 0, 0); rect.width = cis.x + wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2 + 9 + x; } @@ -863,30 +808,64 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc, if ( (flags & wxODCB_PAINTING_CONTROL) ) paintdata.m_choiceItem = -1; - if ( &dc ) - dc.SetBrush(*wxWHITE_BRUSH); + if ( pDc ) + pDc->SetBrush(*wxWHITE_BRUSH); + + wxPGCellRenderer* renderer = NULL; + const wxPGChoiceEntry* cell = NULL; if ( rect.x >= 0 ) { // // DrawItem call + wxDC& dc = *pDc; wxPoint pt(rect.x + wxPG_CONTROL_MARGIN - wxPG_CHOICEXADJUST - 1, rect.y + 1); - int renderFlags = 0; + int renderFlags = wxPGCellRenderer::DontUseCellColours; + bool useCustomPaintProcedure; - if ( flags & wxODCB_PAINTING_CONTROL ) - renderFlags |= wxPGCellRenderer::Control; + // If custom image had some size, we will start from the assumption + // that custom paint procedure is required + if ( cis.x > 0 ) + useCustomPaintProcedure = true; + else + useCustomPaintProcedure = false; if ( flags & wxODCB_PAINTING_SELECTED ) renderFlags |= wxPGCellRenderer::Selected; - if ( cis.x > 0 && (p->HasFlag(wxPG_PROP_CUSTOMIMAGE) || !(flags & wxODCB_PAINTING_CONTROL)) && - ( !p->m_valueBitmap || item == pCb->GetSelection() ) && - ( item >= 0 || (flags & wxODCB_PAINTING_CONTROL) ) && - !itemBitmap - ) + if ( flags & wxODCB_PAINTING_CONTROL ) + { + renderFlags |= wxPGCellRenderer::Control; + + // If wxPG_PROP_CUSTOMIMAGE was set, then that means any custom + // image will not appear on the control row (it may be too + // large to fit, for instance). Also do not draw custom image + // if no choice was selected. + if ( !p->HasFlag(wxPG_PROP_CUSTOMIMAGE) || item < 0 ) + useCustomPaintProcedure = false; + } + else + { + renderFlags |= wxPGCellRenderer::ChoicePopup; + + // For consistency, always use normal font when drawing drop down + // items + dc.SetFont(GetFont()); + } + + // If not drawing a selected popup item, then give property's + // m_valueBitmap a chance. + if ( p->m_valueBitmap && item != pCb->GetSelection() ) + useCustomPaintProcedure = false; + // If current choice had a bitmap set by the application, then + // use it instead of any custom paint procedure. + else if ( itemBitmap ) + useCustomPaintProcedure = false; + + if ( useCustomPaintProcedure ) { pt.x += wxCC_CUSTOM_IMAGE_MARGIN1; wxRect r(pt.x,pt.y,cis.x,cis.y); @@ -903,7 +882,7 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc, if ( comValIndex >= 0 ) { const wxPGCommonValue* cv = GetCommonValue(comValIndex); - wxPGCellRenderer* renderer = cv->GetRenderer(); + renderer = cv->GetRenderer(); r.width = rect.width; renderer->Render( dc, r, this, p, m_selColumn, comValIndex, renderFlags ); return; @@ -929,13 +908,15 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc, if ( item < 0 && (flags & wxODCB_PAINTING_CONTROL) ) item = pCb->GetSelection(); - if ( pChoices && item >= 0 && comValIndex < 0 ) + if ( choices.IsOk() && item >= 0 && comValIndex < 0 ) { - const wxPGChoiceEntry& cell = pChoices->Item(item); - wxPGCellRenderer* renderer = wxPGGlobalVars->m_defaultRenderer; - int imageOffset = renderer->PreDrawCell( dc, rect, cell, renderFlags ); + cell = &choices.Item(item); + renderer = wxPGGlobalVars->m_defaultRenderer; + int imageOffset = renderer->PreDrawCell(dc, rect, *cell, + renderFlags ); if ( imageOffset ) - imageOffset += wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2; + imageOffset += wxCC_CUSTOM_IMAGE_MARGIN1 + + wxCC_CUSTOM_IMAGE_MARGIN2; pt.x += imageOffset; } } @@ -949,11 +930,15 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc, pt.x += 1; dc.DrawText( text, pt.x + wxPG_XBEFORETEXT, pt.y ); + + if ( renderer ) + renderer->PostDrawCell(dc, this, *cell, renderFlags); } else { // // MeasureItem call + wxDC& dc = *pDc; p->OnCustomPaint( dc, rect, paintdata ); rect.height = paintdata.m_drawnHeight + 2; @@ -966,23 +951,35 @@ bool wxPGChoiceEditor_SetCustomPaintWidth( wxPropertyGrid* propGrid, wxPGComboBo wxPGProperty* property = propGrid->GetSelectedProperty(); wxASSERT( property ); + wxSize imageSize; + bool res; + + // TODO: Do this always when cell has custom text. + if ( property->IsValueUnspecified() ) + { + cb->SetCustomPaintWidth( 0 ); + return true; + } + if ( cmnVal >= 0 ) { // Yes, a common value is being selected property->SetCommonValue( cmnVal ); - wxSize imageSize = propGrid->GetCommonValue(cmnVal)-> + imageSize = propGrid->GetCommonValue(cmnVal)-> GetRenderer()->GetImageSize(property, 1, cmnVal); - if ( imageSize.x ) imageSize.x += ODCB_CUST_PAINT_MARGIN; - cb->SetCustomPaintWidth( imageSize.x ); - return false; + res = false; } else { - wxSize imageSize = propGrid->GetImageSize(property, -1); - if ( imageSize.x ) imageSize.x += ODCB_CUST_PAINT_MARGIN; - cb->SetCustomPaintWidth( imageSize.x ); - return true; + imageSize = propGrid->GetImageSize(property, -1); + res = true; } + + if ( imageSize.x ) + imageSize.x += ODCB_CUST_PAINT_MARGIN; + cb->SetCustomPaintWidth( imageSize.x ); + + return res; } // CreateControls calls this with CB_READONLY in extraStyle @@ -992,19 +989,21 @@ wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid, const wxSize& sz, long extraStyle ) const { - wxString defString; - - // Get choices. - int index = property->GetChoiceInfo( NULL ); - - bool isUnspecified = property->IsValueUnspecified(); - - if ( isUnspecified ) - index = -1; - else - defString = property->GetDisplayedString(); + // Since it is not possible (yet) to create a read-only combo box in + // the same sense that wxTextCtrl is read-only, simply do not create + // the control in this case. + if ( property->HasFlag(wxPG_PROP_READONLY) ) + return NULL; const wxPGChoices& choices = property->GetChoices(); + wxString defString; + int index = property->GetChoiceSelection(); + + int argFlags = 0; + if ( !property->HasFlag(wxPG_PROP_READONLY) && + !property->IsValueUnspecified() ) + argFlags |= wxPG_EDITABLE_VALUE; + defString = property->GetValueAsString(argFlags); wxArrayString labels = choices.GetLabels(); @@ -1019,14 +1018,18 @@ wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid, si.x -= wxPG_CHOICEXADJUST; wxWindow* ctrlParent = propGrid->GetPanel(); - int odcbFlags = extraStyle | wxNO_BORDER | wxTE_PROCESS_ENTER; + int odcbFlags = extraStyle | wxBORDER_NONE | wxTE_PROCESS_ENTER; + + if ( (property->GetFlags() & wxPG_PROP_USE_DCC) && + wxDynamicCast(property, wxBoolProperty) ) + odcbFlags |= wxODCB_DCLICK_CYCLES; // // If common value specified, use appropriate index unsigned int cmnVals = property->GetDisplayedCommonValueCount(); if ( cmnVals ) { - if ( !isUnspecified ) + if ( !property->IsValueUnspecified() ) { int cmnVal = property->GetCommonValue(); if ( cmnVal >= 0 ) @@ -1052,31 +1055,30 @@ wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid, labels, odcbFlags); - //int extRight = propGrid->GetClientSize().x - (po.x+si.x); - //int extRight = - (po.x+si.x); - cb->SetButtonPosition(si.y,0,wxRIGHT); - //cb->SetPopupExtents( 1, extRight ); - cb->SetTextIndent(wxPG_XBEFORETEXT-1); + cb->SetMargins(wxPG_XBEFORETEXT-1); - wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb, property->GetCommonValue() ); - /*if ( property->GetFlags() & wxPG_PROP_CUSTOMIMAGE ) - { - wxSize imageSize = propGrid->GetImageSize(property, index); - if ( imageSize.x ) imageSize.x += ODCB_CUST_PAINT_MARGIN; - cb->SetCustomPaintWidth( imageSize.x ); - }*/ + // Set hint text + cb->SetHint(property->GetHintText()); + + wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb, + property->GetCommonValue() ); if ( index >= 0 && index < (int)cb->GetCount() ) { cb->SetSelection( index ); - if ( defString.length() ) + if ( !defString.empty() ) cb->SetText( defString ); } - else if ( !(extraStyle & wxCB_READONLY) && defString.length() ) + else if ( !(extraStyle & wxCB_READONLY) && !defString.empty() ) + { + propGrid->SetupTextCtrlValue(defString); cb->SetValue( defString ); + } else + { cb->SetSelection( -1 ); + } #ifdef __WXMSW__ cb->Show(); @@ -1090,8 +1092,8 @@ void wxPGChoiceEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) c { wxASSERT( ctrl ); wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl; - wxASSERT( cb->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox))); - int ind = property->GetChoiceInfo( (wxPGChoiceInfo*)NULL ); + wxASSERT( wxDynamicCast(cb, wxOwnerDrawnComboBox)); + int ind = property->GetChoiceSelection(); cb->SetSelection(ind); } @@ -1106,7 +1108,7 @@ int wxPGChoiceEditor::InsertItem( wxWindow* ctrl, const wxString& label, int ind { wxASSERT( ctrl ); wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl; - wxASSERT( cb->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox))); + wxASSERT( wxDynamicCast(cb, wxOwnerDrawnComboBox)); if (index < 0) index = cb->GetCount(); @@ -1119,7 +1121,7 @@ void wxPGChoiceEditor::DeleteItem( wxWindow* ctrl, int index ) const { wxASSERT( ctrl ); wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl; - wxASSERT( cb->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox))); + wxASSERT( wxDynamicCast(cb, wxOwnerDrawnComboBox)); cb->Delete(index); } @@ -1127,7 +1129,7 @@ void wxPGChoiceEditor::DeleteItem( wxWindow* ctrl, int index ) const bool wxPGChoiceEditor::OnEvent( wxPropertyGrid* propGrid, wxPGProperty* property, wxWindow* ctrl, wxEvent& event ) const { - if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED ) + if ( event.GetEventType() == wxEVT_COMBOBOX ) { wxPGComboBox* cb = (wxPGComboBox*)ctrl; int index = cb->GetSelection(); @@ -1148,11 +1150,16 @@ bool wxPGChoiceEditor::OnEvent( wxPropertyGrid* propGrid, wxPGProperty* property propGrid->SetInternalFlag(wxPG_FL_VALUE_CHANGE_IN_EVENT); property->SetValueToUnspecified(); if ( !cb->HasFlag(wxCB_READONLY) ) - cb->GetTextCtrl()->SetValue(wxEmptyString); + { + wxString unspecValueText; + unspecValueText = propGrid->GetUnspecifiedValueText(); + propGrid->SetupTextCtrlValue(unspecValueText); + cb->GetTextCtrl()->SetValue(unspecValueText); + } return false; } } - return wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb, cmnValIndex ); + return wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb, cmnValIndex ); } return false; } @@ -1164,7 +1171,7 @@ bool wxPGChoiceEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* pr int index = cb->GetSelection(); - if ( index != property->GetChoiceInfo( (wxPGChoiceInfo*) NULL ) || + if ( index != property->GetChoiceSelection() || // Changing unspecified always causes event (returning // true here should be enough to trigger it). property->IsValueUnspecified() @@ -1176,10 +1183,13 @@ bool wxPGChoiceEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* pr } -void wxPGChoiceEditor::SetControlStringValue( wxPGProperty* WXUNUSED(property), wxWindow* ctrl, const wxString& txt ) const +void wxPGChoiceEditor::SetControlStringValue( wxPGProperty* property, + wxWindow* ctrl, + const wxString& txt ) const { wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl; wxASSERT( cb ); + property->GetGrid()->SetupTextCtrlValue(txt); cb->SetValue(txt); } @@ -1192,10 +1202,13 @@ void wxPGChoiceEditor::SetControlIntValue( wxPGProperty* WXUNUSED(property), wxW } -void wxPGChoiceEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* ctrl ) const +void wxPGChoiceEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), + wxWindow* ctrl ) const { wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl; - cb->SetSelection(-1); + + if ( cb->HasFlag(wxCB_READONLY) ) + cb->SetSelection(-1); } @@ -1205,7 +1218,10 @@ bool wxPGChoiceEditor::CanContainCustomImage() const } -wxPGChoiceEditor::~wxPGChoiceEditor() { } +wxPGChoiceEditor::~wxPGChoiceEditor() +{ + wxPG_EDITOR(Choice) = NULL; +} // ----------------------------------------------------------------------- @@ -1213,13 +1229,17 @@ wxPGChoiceEditor::~wxPGChoiceEditor() { } // ----------------------------------------------------------------------- -WX_PG_IMPLEMENT_EDITOR_CLASS(ComboBox,wxPGComboBoxEditor,wxPGChoiceEditor) +WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(ComboBox, + wxPGComboBoxEditor, + wxPGChoiceEditor) void wxPGComboBoxEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const { wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl; - cb->SetValue(property->GetValueString(wxPG_EDITABLE_VALUE)); + wxString s = property->GetValueAsString(wxPG_EDITABLE_VALUE); + property->GetGrid()->SetupTextCtrlValue(s); + cb->SetValue(s); // TODO: If string matches any selection, then select that. } @@ -1239,8 +1259,8 @@ bool wxPGComboBoxEditor::OnEvent( wxPropertyGrid* propGrid, wxWindow* ctrl, wxEvent& event ) const { - wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*) NULL; - wxWindow* textCtrl = (wxWindow*) NULL; + wxOwnerDrawnComboBox* cb = NULL; + wxWindow* textCtrl = NULL; if ( ctrl ) { @@ -1260,7 +1280,7 @@ bool wxPGComboBoxEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl; wxString textVal = cb->GetValue(); - if ( property->UsesAutoUnspecified() && !textVal.length() ) + if ( property->UsesAutoUnspecified() && textVal.empty() ) { variant.MakeNull(); return true; @@ -1277,14 +1297,19 @@ bool wxPGComboBoxEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* } -void wxPGComboBoxEditor::OnFocus( wxPGProperty*, wxWindow* ctrl ) const +void wxPGComboBoxEditor::OnFocus( wxPGProperty* property, + wxWindow* ctrl ) const { wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl; - cb->GetTextCtrl()->SetSelection(-1,-1); + wxPGTextCtrlEditor_OnFocus(property, cb->GetTextCtrl()); } -wxPGComboBoxEditor::~wxPGComboBoxEditor() { } +wxPGComboBoxEditor::~wxPGComboBoxEditor() +{ + wxPG_EDITOR(ComboBox) = NULL; +} + // ----------------------------------------------------------------------- @@ -1292,8 +1317,9 @@ wxPGComboBoxEditor::~wxPGComboBoxEditor() { } // ----------------------------------------------------------------------- -// This simpler implement_editor macro doesn't define class body. -WX_PG_IMPLEMENT_EDITOR_CLASS(ChoiceAndButton,wxPGChoiceAndButtonEditor,wxPGChoiceEditor) +WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(ChoiceAndButton, + wxPGChoiceAndButtonEditor, + wxPGChoiceEditor) wxPGWindowList wxPGChoiceAndButtonEditor::CreateControls( wxPropertyGrid* propGrid, @@ -1324,7 +1350,7 @@ wxPGWindowList wxPGChoiceAndButtonEditor::CreateControls( wxPropertyGrid* propGr ch_sz.x -= wxPG_TEXTCTRL_AND_BUTTON_SPACING; #endif - wxWindow* ch = wxPG_EDITOR(Choice)->CreateControls(propGrid,property, + wxWindow* ch = wxPGEditor_Choice->CreateControls(propGrid,property, pos,ch_sz).m_primary; #ifdef __WXMSW__ @@ -1335,16 +1361,18 @@ wxPGWindowList wxPGChoiceAndButtonEditor::CreateControls( wxPropertyGrid* propGr } -wxPGChoiceAndButtonEditor::~wxPGChoiceAndButtonEditor() { } - +wxPGChoiceAndButtonEditor::~wxPGChoiceAndButtonEditor() +{ + wxPG_EDITOR(ChoiceAndButton) = NULL; +} // ----------------------------------------------------------------------- // wxPGTextCtrlAndButtonEditor // ----------------------------------------------------------------------- - -// This simpler implement_editor macro doesn't define class body. -WX_PG_IMPLEMENT_EDITOR_CLASS(TextCtrlAndButton,wxPGTextCtrlAndButtonEditor,wxPGTextCtrlEditor) +WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(TextCtrlAndButton, + wxPGTextCtrlAndButtonEditor, + wxPGTextCtrlEditor) wxPGWindowList wxPGTextCtrlAndButtonEditor::CreateControls( wxPropertyGrid* propGrid, @@ -1360,8 +1388,10 @@ wxPGWindowList wxPGTextCtrlAndButtonEditor::CreateControls( wxPropertyGrid* prop } -wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor() { } - +wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor() +{ + wxPG_EDITOR(TextCtrlAndButton) = NULL; +} // ----------------------------------------------------------------------- // wxPGCheckBoxEditor @@ -1369,20 +1399,39 @@ wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor() { } #if wxPG_INCLUDE_CHECKBOX -WX_PG_IMPLEMENT_EDITOR_CLASS(CheckBox,wxPGCheckBoxEditor,wxPGEditor) +WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(CheckBox, + wxPGCheckBoxEditor, + wxPGEditor) -// state argument: 0x01 = set if checked -// 0x02 = set if rectangle should be bold -static void DrawSimpleCheckBox( wxDC& dc, const wxRect& rect, int box_hei, int state, const wxColour& linecol ) +// Check box state flags +enum { + wxSCB_STATE_UNCHECKED = 0, + wxSCB_STATE_CHECKED = 1, + wxSCB_STATE_BOLD = 2, + wxSCB_STATE_UNSPECIFIED = 4 +}; + +const int wxSCB_SETVALUE_CYCLE = 2; + +static void DrawSimpleCheckBox( wxDC& dc, const wxRect& rect, int box_hei, + int state ) +{ // Box rectangle. - wxRect r(rect.x+wxPG_XBEFORETEXT,rect.y+((rect.height-box_hei)/2),box_hei,box_hei); + wxRect r(rect.x+wxPG_XBEFORETEXT,rect.y+((rect.height-box_hei)/2), + box_hei,box_hei); + wxColour useCol = dc.GetTextForeground(); + + if ( state & wxSCB_STATE_UNSPECIFIED ) + { + useCol = wxColour(220, 220, 220); + } // Draw check mark first because it is likely to overdraw the // surrounding rectangle. - if ( state & 1 ) + if ( state & wxSCB_STATE_CHECKED ) { wxRect r2(r.x+wxPG_CHECKMARK_XADJ, r.y+wxPG_CHECKMARK_YADJ, @@ -1396,18 +1445,17 @@ static void DrawSimpleCheckBox( wxDC& dc, const wxRect& rect, int box_hei, int s // This would draw a simple cross check mark. // dc.DrawLine(r.x,r.y,r.x+r.width-1,r.y+r.height-1); // dc.DrawLine(r.x,r.y+r.height-1,r.x+r.width-1,r.y); - } - if ( !(state & 2) ) + if ( !(state & wxSCB_STATE_BOLD) ) { // Pen for thin rectangle. - dc.SetPen(linecol); + dc.SetPen(useCol); } else { // Pen for bold rectangle. - wxPen linepen(linecol,2,wxSOLID); + wxPen linepen(useCol,2,wxSOLID); linepen.SetJoin(wxJOIN_MITER); // This prevents round edges. dc.SetPen(linepen); r.x++; @@ -1435,198 +1483,155 @@ public: wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize ) - : wxControl(parent,id,pos,size,wxNO_BORDER|wxWANTS_CHARS) + : wxControl(parent,id,pos,size,wxBORDER_NONE|wxWANTS_CHARS) { // Due to SetOwnFont stuff necessary for GTK+ 1.2, we need to have this SetFont( parent->GetFont() ); m_state = 0; - wxPropertyGrid* pg = (wxPropertyGrid*) parent->GetParent(); - wxASSERT( pg->IsKindOf(CLASSINFO(wxPropertyGrid)) ); - m_boxHeight = pg->GetFontHeight(); - SetBackgroundStyle( wxBG_STYLE_COLOUR ); + m_boxHeight = 12; + + SetBackgroundStyle( wxBG_STYLE_CUSTOM ); } virtual ~wxSimpleCheckBox(); - virtual bool ProcessEvent(wxEvent& event); - int m_state; int m_boxHeight; +private: + void OnPaint( wxPaintEvent& event ); + void OnLeftClick( wxMouseEvent& event ); + void OnKeyDown( wxKeyEvent& event ); + + void OnResize( wxSizeEvent& event ) + { + Refresh(); + event.Skip(); + } + static wxBitmap* ms_doubleBuffer; + DECLARE_EVENT_TABLE() }; +BEGIN_EVENT_TABLE(wxSimpleCheckBox, wxControl) + EVT_PAINT(wxSimpleCheckBox::OnPaint) + EVT_LEFT_DOWN(wxSimpleCheckBox::OnLeftClick) + EVT_LEFT_DCLICK(wxSimpleCheckBox::OnLeftClick) + EVT_KEY_DOWN(wxSimpleCheckBox::OnKeyDown) + EVT_SIZE(wxSimpleCheckBox::OnResize) +END_EVENT_TABLE() + wxSimpleCheckBox::~wxSimpleCheckBox() { - delete ms_doubleBuffer; - ms_doubleBuffer = NULL; + wxDELETE(ms_doubleBuffer); } +wxBitmap* wxSimpleCheckBox::ms_doubleBuffer = NULL; + +void wxSimpleCheckBox::OnPaint( wxPaintEvent& WXUNUSED(event) ) +{ + wxSize clientSize = GetClientSize(); + wxAutoBufferedPaintDC dc(this); -wxBitmap* wxSimpleCheckBox::ms_doubleBuffer = (wxBitmap*) NULL; + dc.Clear(); + wxRect rect(0,0,clientSize.x,clientSize.y); + rect.y += 1; + rect.width += 1; -// value = 2 means toggle (sorry, too lazy to do constants) -void wxSimpleCheckBox::SetValue( int value ) + wxColour bgcol = GetBackgroundColour(); + dc.SetBrush( bgcol ); + dc.SetPen( bgcol ); + dc.DrawRectangle( rect ); + + dc.SetTextForeground(GetForegroundColour()); + + int state = m_state; + if ( !(state & wxSCB_STATE_UNSPECIFIED) && + GetFont().GetWeight() == wxBOLD ) + state |= wxSCB_STATE_BOLD; + + DrawSimpleCheckBox(dc, rect, m_boxHeight, state); +} + +void wxSimpleCheckBox::OnLeftClick( wxMouseEvent& event ) { - if ( value > 1 ) + if ( (event.m_x > (wxPG_XBEFORETEXT-2)) && + (event.m_x <= (wxPG_XBEFORETEXT-2+m_boxHeight)) ) { - m_state++; - if ( m_state > 1 ) m_state = 0; + SetValue(wxSCB_SETVALUE_CYCLE); } - else +} + +void wxSimpleCheckBox::OnKeyDown( wxKeyEvent& event ) +{ + if ( event.GetKeyCode() == WXK_SPACE ) { - m_state = value; + SetValue(wxSCB_SETVALUE_CYCLE); } - Refresh(); - - wxCommandEvent evt(wxEVT_COMMAND_CHECKBOX_CLICKED,GetParent()->GetId()); - - wxPropertyGrid* propGrid = (wxPropertyGrid*) GetParent()->GetParent(); - wxASSERT( propGrid->IsKindOf(CLASSINFO(wxPropertyGrid)) ); - propGrid->OnCustomEditorEvent(evt); } - -bool wxSimpleCheckBox::ProcessEvent(wxEvent& event) +void wxSimpleCheckBox::SetValue( int value ) { - wxPropertyGrid* propGrid = (wxPropertyGrid*) GetParent()->GetParent(); - wxASSERT( propGrid->IsKindOf(CLASSINFO(wxPropertyGrid)) ); - - if ( event.GetEventType() == wxEVT_NAVIGATION_KEY ) + if ( value == wxSCB_SETVALUE_CYCLE ) { - //wxLogDebug(wxT("wxEVT_NAVIGATION_KEY")); - //SetFocusFromKbd(); - //event.Skip(); - //return wxControl::ProcessEvent(event); + if ( m_state & wxSCB_STATE_CHECKED ) + m_state &= ~wxSCB_STATE_CHECKED; + else + m_state |= wxSCB_STATE_CHECKED; } else - if ( ( (event.GetEventType() == wxEVT_LEFT_DOWN || event.GetEventType() == wxEVT_LEFT_DCLICK) - && ((wxMouseEvent&)event).m_x > (wxPG_XBEFORETEXT-2) - && ((wxMouseEvent&)event).m_x <= (wxPG_XBEFORETEXT-2+m_boxHeight) ) - ) { - SetValue(2); - return true; + m_state = value; } - else if ( event.GetEventType() == wxEVT_PAINT ) - { - wxSize clientSize = GetClientSize(); - wxPaintDC dc(this); - - /* - // Buffered paint DC doesn't seem to do much good - if ( !ms_doubleBuffer || - clientSize.x > ms_doubleBuffer->GetWidth() || - clientSize.y > ms_doubleBuffer->GetHeight() ) - { - delete ms_doubleBuffer; - ms_doubleBuffer = new wxBitmap(clientSize.x+25,clientSize.y+25); - } - - wxBufferedPaintDC dc(this,*ms_doubleBuffer); - */ - - wxRect rect(0,0,clientSize.x,clientSize.y); - //rect.x -= 1; - rect.y += 1; - rect.width += 1; - - m_boxHeight = propGrid->GetFontHeight(); - - wxColour bgcol = GetBackgroundColour(); - dc.SetBrush( bgcol ); - dc.SetPen( bgcol ); - dc.DrawRectangle( rect ); - - wxColour txcol = GetForegroundColour(); - - int state = m_state; - if ( m_font.GetWeight() == wxBOLD ) - state |= 2; - - DrawSimpleCheckBox(dc,rect,m_boxHeight,state,txcol); - - // If focused, indicate it somehow. - /* - if ( wxWindow::FindFocus() == this ) - { - rect.x += 1; - rect.width -= 1; - - wxPGDrawFocusRect(dc,rect); - } - */ + Refresh(); - return true; - } - else if ( event.GetEventType() == wxEVT_SIZE || - event.GetEventType() == wxEVT_SET_FOCUS || - event.GetEventType() == wxEVT_KILL_FOCUS - ) - { - Refresh(); - } - else if ( event.GetEventType() == wxEVT_KEY_DOWN ) - { - wxKeyEvent& keyEv = (wxKeyEvent&) event; + wxCommandEvent evt(wxEVT_CHECKBOX,GetParent()->GetId()); - if ( keyEv.GetKeyCode() == WXK_TAB ) - { - propGrid->SendNavigationKeyEvent( keyEv.ShiftDown()?0:1 ); - return true; - } - else - if ( keyEv.GetKeyCode() == WXK_SPACE ) - { - SetValue(2); - return true; - } - } - return wxControl::ProcessEvent(event); + wxPropertyGrid* propGrid = (wxPropertyGrid*) GetParent(); + wxASSERT( wxDynamicCast(propGrid, wxPropertyGrid) ); + propGrid->HandleCustomEditorEvent(evt); } - wxPGWindowList wxPGCheckBoxEditor::CreateControls( wxPropertyGrid* propGrid, wxPGProperty* property, const wxPoint& pos, const wxSize& size ) const { + if ( property->HasFlag(wxPG_PROP_READONLY) ) + return NULL; + wxPoint pt = pos; pt.x -= wxPG_XBEFOREWIDGET; wxSize sz = size; sz.x = propGrid->GetFontHeight() + (wxPG_XBEFOREWIDGET*2) + 4; - wxSimpleCheckBox* cb = new wxSimpleCheckBox(propGrid->GetPanel(),wxPG_SUBID1,pt,sz); + wxSimpleCheckBox* cb = new wxSimpleCheckBox(propGrid->GetPanel(), + wxPG_SUBID1, pt, sz); cb->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - cb->Connect( wxPG_SUBID1, wxEVT_LEFT_DOWN, - (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) - &wxPropertyGrid::OnCustomEditorEvent, NULL, propGrid ); - - cb->Connect( wxPG_SUBID1, wxEVT_LEFT_DCLICK, - (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) - &wxPropertyGrid::OnCustomEditorEvent, NULL, propGrid ); + UpdateControl(property, cb); - if ( property->GetChoiceInfo((wxPGChoiceInfo*)NULL) && - !property->IsValueUnspecified() ) - cb->m_state = 1; - - // If mouse cursor was on the item, toggle the value now. - if ( propGrid->GetInternalFlags() & wxPG_FL_ACTIVATION_BY_CLICK ) + if ( !property->IsValueUnspecified() ) { - wxPoint pt = cb->ScreenToClient(::wxGetMousePosition()); - if ( pt.x <= (wxPG_XBEFORETEXT-2+cb->m_boxHeight) ) + // If mouse cursor was on the item, toggle the value now. + if ( propGrid->GetInternalFlags() & wxPG_FL_ACTIVATION_BY_CLICK ) { - cb->m_state++; - - if ( cb->m_state > 1 ) - cb->m_state = 0; - - // Makes sure wxPG_EVT_CHANGING etc. is sent for this initial click - propGrid->ChangePropertyValue(property, wxPGVariant_Bool(cb->m_state)); + wxPoint point = cb->ScreenToClient(::wxGetMousePosition()); + if ( point.x <= (wxPG_XBEFORETEXT-2+cb->m_boxHeight) ) + { + if ( cb->m_state & wxSCB_STATE_CHECKED ) + cb->m_state &= ~wxSCB_STATE_CHECKED; + else + cb->m_state |= wxSCB_STATE_CHECKED; + + // Makes sure wxPG_EVT_CHANGING etc. is sent for this initial + // click + propGrid->ChangePropertyValue(property, + wxPGVariant_Bool(cb->m_state)); + } } } @@ -1635,58 +1640,47 @@ wxPGWindowList wxPGCheckBoxEditor::CreateControls( wxPropertyGrid* propGrid, return cb; } -/* -class wxPGCheckBoxRenderer : public wxPGDefaultRenderer +void wxPGCheckBoxEditor::DrawValue( wxDC& dc, const wxRect& rect, + wxPGProperty* property, + const wxString& WXUNUSED(text) ) const { -public: + int state = wxSCB_STATE_UNCHECKED; - virtual void Render( wxDC& dc, const wxRect& rect, - const wxPropertyGrid* WXUNUSED(propertyGrid), wxPGProperty* property, - int WXUNUSED(column), int WXUNUSED(item), int WXUNUSED(flags) ) const + if ( !property->IsValueUnspecified() ) { - int state = 0; - if ( !(property->GetFlags() & wxPG_PROP_UNSPECIFIED) ) - { - state = ((wxPGProperty*)property)->GetChoiceInfo((wxPGChoiceInfo*)NULL); - if ( dc.GetFont().GetWeight() == wxBOLD ) state |= 2; - } - DrawSimpleCheckBox(dc,rect,dc.GetCharHeight(),state,dc.GetTextForeground()); + state = property->GetChoiceSelection(); + if ( dc.GetFont().GetWeight() == wxBOLD ) + state |= wxSCB_STATE_BOLD; + } + else + { + state |= wxSCB_STATE_UNSPECIFIED; } -protected: -}; - -wxPGCheckBoxRenderer g_wxPGCheckBoxRenderer; - -wxPGCellRenderer* wxPGCheckBoxEditor::GetCellRenderer() const -{ - return &g_wxPGCheckBoxRenderer; + DrawSimpleCheckBox(dc, rect, dc.GetCharHeight(), state); } -*/ -void wxPGCheckBoxEditor::DrawValue( wxDC& dc, const wxRect& rect, wxPGProperty* property, const wxString& WXUNUSED(text) ) const +void wxPGCheckBoxEditor::UpdateControl( wxPGProperty* property, + wxWindow* ctrl ) const { - int state = 0; + wxSimpleCheckBox* cb = (wxSimpleCheckBox*) ctrl; + wxASSERT( cb ); + if ( !property->IsValueUnspecified() ) - { - state = property->GetChoiceInfo((wxPGChoiceInfo*)NULL); - if ( dc.GetFont().GetWeight() == wxBOLD ) state |= 2; - } - DrawSimpleCheckBox(dc,rect,dc.GetCharHeight(),state,dc.GetTextForeground()); -} + cb->m_state = property->GetChoiceSelection(); + else + cb->m_state = wxSCB_STATE_UNSPECIFIED; -void wxPGCheckBoxEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const -{ - wxASSERT( ctrl ); - ((wxSimpleCheckBox*)ctrl)->m_state = property->GetChoiceInfo((wxPGChoiceInfo*)NULL); - ctrl->Refresh(); -} + wxPropertyGrid* propGrid = property->GetGrid(); + cb->m_boxHeight = propGrid->GetFontHeight(); + cb->Refresh(); +} bool wxPGCheckBoxEditor::OnEvent( wxPropertyGrid* WXUNUSED(propGrid), wxPGProperty* WXUNUSED(property), wxWindow* WXUNUSED(ctrl), wxEvent& event ) const { - if ( event.GetEventType() == wxEVT_COMMAND_CHECKBOX_CLICKED ) + if ( event.GetEventType() == wxEVT_CHECKBOX ) { return true; } @@ -1700,7 +1694,7 @@ bool wxPGCheckBoxEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* int index = cb->m_state; - if ( index != property->GetChoiceInfo( (wxPGChoiceInfo*) NULL ) || + if ( index != property->GetChoiceSelection() || // Changing unspecified always causes event (returning // true here should be enough to trigger it). property->IsValueUnspecified() @@ -1722,13 +1716,15 @@ void wxPGCheckBoxEditor::SetControlIntValue( wxPGProperty* WXUNUSED(property), w void wxPGCheckBoxEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* ctrl ) const { - ((wxSimpleCheckBox*)ctrl)->m_state = 0; + ((wxSimpleCheckBox*)ctrl)->m_state = wxSCB_STATE_UNSPECIFIED; ctrl->Refresh(); } -wxPGCheckBoxEditor::~wxPGCheckBoxEditor() { } - +wxPGCheckBoxEditor::~wxPGCheckBoxEditor() +{ + wxPG_EDITOR(CheckBox) = NULL; +} #endif // wxPG_INCLUDE_CHECKBOX @@ -1741,14 +1737,6 @@ wxWindow* wxPropertyGrid::GetEditorControl() const if ( !ctrl ) return ctrl; - // If it's clipper window, return its child instead -#if wxPG_ENABLE_CLIPPER_WINDOW - if ( ctrl->IsKindOf(CLASSINFO(wxPGClipperWindow)) ) - { - return ((wxPGClipperWindow*)ctrl)->GetControl(); - } -#endif - return ctrl; } @@ -1756,12 +1744,11 @@ wxWindow* wxPropertyGrid::GetEditorControl() const void wxPropertyGrid::CorrectEditorWidgetSizeX() { - if ( m_selColumn == -1 ) - return; - int secWid = 0; - int newSplitterx = m_pState->DoGetSplitterPosition(m_selColumn-1); - int newWidth = newSplitterx + m_pState->m_colWidths[m_selColumn]; + + // Use fixed selColumn 1 for main editor widgets + int newSplitterx = m_pState->DoGetSplitterPosition(0); + int newWidth = newSplitterx + m_pState->m_colWidths[1]; if ( m_wndEditor2 ) { @@ -1776,7 +1763,7 @@ void wxPropertyGrid::CorrectEditorWidgetSizeX() #ifdef __WXMAC__ if ( m_wndEditor ) #else - if ( m_wndEditor && m_wndEditor->IsKindOf(CLASSINFO(wxTextCtrl)) ) + if ( wxDynamicCast(m_wndEditor, wxTextCtrl) ) #endif secWid += wxPG_TEXTCTRL_AND_BUTTON_SPACING; } @@ -1801,57 +1788,52 @@ void wxPropertyGrid::CorrectEditorWidgetSizeX() void wxPropertyGrid::CorrectEditorWidgetPosY() { - if ( m_selected && (m_wndEditor || m_wndEditor2) ) - { - wxRect r = GetEditorWidgetRect(m_selected, m_selColumn); + wxPGProperty* selected = GetSelection(); - if ( m_wndEditor ) + if ( selected ) + { + if ( m_labelEditor ) { - wxPoint pos = m_wndEditor->GetPosition(); + wxRect r = GetEditorWidgetRect(selected, m_selColumn); + wxPoint pos = m_labelEditor->GetPosition(); // Calculate y offset int offset = pos.y % m_lineHeight; - m_wndEditor->Move(pos.x, r.y + offset); + m_labelEditor->Move(pos.x, r.y + offset); } - if ( m_wndEditor2 ) + if ( m_wndEditor || m_wndEditor2 ) { - wxPoint pos = m_wndEditor2->GetPosition(); + wxRect r = GetEditorWidgetRect(selected, 1); - m_wndEditor2->Move(pos.x, r.y); - } - } -} + if ( m_wndEditor ) + { + wxPoint pos = m_wndEditor->GetPosition(); -// ----------------------------------------------------------------------- + // Calculate y offset + int offset = pos.y % m_lineHeight; -bool wxPropertyGrid::AdjustPosForClipperWindow( wxWindow* topCtrlWnd, int* x, int* y ) -{ -#if wxPG_ENABLE_CLIPPER_WINDOW - // Take clipper window into account - if (topCtrlWnd->GetPosition().x < 1 && - !topCtrlWnd->IsKindOf(CLASSINFO(wxPGClipperWindow))) - { - topCtrlWnd = topCtrlWnd->GetParent(); - wxASSERT( topCtrlWnd->IsKindOf(CLASSINFO(wxPGClipperWindow)) ); - *x -= ((wxPGClipperWindow*)topCtrlWnd)->GetXClip(); - *y -= ((wxPGClipperWindow*)topCtrlWnd)->GetYClip(); - return true; + m_wndEditor->Move(pos.x, r.y + offset); + } + + if ( m_wndEditor2 ) + { + wxPoint pos = m_wndEditor2->GetPosition(); + + m_wndEditor2->Move(pos.x, r.y); + } + } } -#else - wxUnusedVar(topCtrlWnd); - wxUnusedVar(x); - wxUnusedVar(y); -#endif - return false; } // ----------------------------------------------------------------------- // Fixes position of wxTextCtrl-like control (wxSpinCtrl usually // fits into that category as well). -void wxPropertyGrid::FixPosForTextCtrl( wxWindow* ctrl, const wxPoint& offset ) +void wxPropertyGrid::FixPosForTextCtrl( wxWindow* ctrl, + unsigned int WXUNUSED(forColumn), + const wxPoint& offset ) { // Center the control vertically wxRect finalPos = ctrl->GetRect(); @@ -1864,7 +1846,14 @@ void wxPropertyGrid::FixPosForTextCtrl( wxWindow* ctrl, const wxPoint& offset ) finalPos.y += y_adj; finalPos.height -= (y_adj+sz_dec); - const int textCtrlXAdjust = wxPG_TEXTCTRLXADJUST; +#ifndef wxPG_TEXTCTRLXADJUST + int textCtrlXAdjust = wxPG_XBEFORETEXT - 1; + + wxTextCtrl* tc = static_cast(ctrl); + tc->SetMargins(0); +#else + int textCtrlXAdjust = wxPG_TEXTCTRLXADJUST; +#endif finalPos.x += textCtrlXAdjust; finalPos.width -= textCtrlXAdjust; @@ -1882,14 +1871,16 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos, const wxString& value, wxWindow* secondary, int extraStyle, - int maxLen ) + int maxLen, + unsigned int forColumn ) { - wxPGProperty* selected = m_selected; - wxASSERT(selected); + wxWindowID id = wxPG_SUBID1; + wxPGProperty* prop = GetSelection(); + wxASSERT(prop); int tcFlags = wxTE_PROCESS_ENTER | extraStyle; - if ( selected->HasFlag(wxPG_PROP_READONLY) ) + if ( prop->HasFlag(wxPG_PROP_READONLY) && forColumn == 1 ) tcFlags |= wxTE_READONLY; wxPoint p(pos.x,pos.y); @@ -1897,10 +1888,14 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos, // Need to reduce width of text control on Mac #if defined(__WXMAC__) - s.x -= 8; + s.x -= 8; #endif - // Take button into acccount + // For label editors, trim the size to allow better splitter grabbing + if ( forColumn != 1 ) + s.x -= 2; + + // Take button into acccount if ( secondary ) { s.x -= (secondary->GetSize().x + wxPG_TEXTCTRL_AND_BUTTON_SPACING); @@ -1913,53 +1908,50 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos, if ( (sz.y - m_lineHeight) > 5 ) hasSpecialSize = true; -#if wxPG_NAT_TEXTCTRL_BORDER_ANY - - // Create clipper window - wxPGClipperWindow* wnd = new wxPGClipperWindow(); -#if defined(__WXMSW__) - wnd->Hide(); -#endif - wnd->Create(GetPanel(),wxPG_SUBID1,p,s); - - // This generates rect of the control inside the clipper window - if ( !hasSpecialSize ) - wnd->GetControlRect(wxPG_NAT_TEXTCTRL_BORDER_X, wxPG_NAT_TEXTCTRL_BORDER_Y, p, s); - else - wnd->GetControlRect(0, 0, p, s); - - wxWindow* ctrlParent = wnd; - -#else - wxWindow* ctrlParent = GetPanel(); if ( !hasSpecialSize ) - tcFlags |= wxNO_BORDER; - -#endif + tcFlags |= wxBORDER_NONE; wxTextCtrl* tc = new wxTextCtrl(); -#if defined(__WXMSW__) && !wxPG_NAT_TEXTCTRL_BORDER_ANY +#if defined(__WXMSW__) tc->Hide(); #endif SetupTextCtrlValue(value); - tc->Create(ctrlParent,wxPG_SUBID1,value, p, s,tcFlags); + tc->Create(ctrlParent,id,value, p, s,tcFlags); -#if wxPG_NAT_TEXTCTRL_BORDER_ANY - wxWindow* ed = wnd; - wnd->SetControl(tc); -#else - wxWindow* ed = tc; +#if defined(__WXMSW__) + // On Windows, we need to override read-only text ctrl's background + // colour to white. One problem with native 'grey' background is that + // tc->GetBackgroundColour() doesn't seem to return correct value + // for it. + if ( tcFlags & wxTE_READONLY ) + { + wxVisualAttributes vattrs = tc->GetDefaultAttributes(); + tc->SetBackgroundColour(vattrs.colBg); + } #endif + // This code is repeated from DoSelectProperty(). However, font boldness + // must be set before margin is set up below in FixPosForTextCtrl(). + if ( forColumn == 1 && + prop->HasFlag(wxPG_PROP_MODIFIED) && + HasFlag(wxPG_BOLD_MODIFIED) ) + tc->SetFont( m_captionFont ); + // Center the control vertically if ( !hasSpecialSize ) - FixPosForTextCtrl(ed); + FixPosForTextCtrl(tc, forColumn); + + if ( forColumn != 1 ) + { + tc->SetBackgroundColour(m_colSelBack); + tc->SetForegroundColour(m_colSelFore); + } #ifdef __WXMSW__ - ed->Show(); + tc->Show(); if ( secondary ) secondary->Show(); #endif @@ -1968,14 +1960,25 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos, if ( maxLen > 0 ) tc->SetMaxLength( maxLen ); - return (wxWindow*) ed; + wxVariant attrVal = prop->GetAttribute(wxPG_ATTR_AUTOCOMPLETE); + if ( !attrVal.IsNull() ) + { + wxASSERT(attrVal.GetType() == wxS("arrstring")); + tc->AutoComplete(attrVal.GetArrayString()); + } + + // Set hint text + tc->SetHint(prop->GetHintText()); + + return tc; } // ----------------------------------------------------------------------- wxWindow* wxPropertyGrid::GenerateEditorButton( const wxPoint& pos, const wxSize& sz ) { - wxPGProperty* selected = m_selected; + wxWindowID id = wxPG_SUBID2; + wxPGProperty* selected = GetSelection(); wxASSERT(selected); #ifdef __WXMAC__ @@ -1987,13 +1990,13 @@ wxWindow* wxPropertyGrid::GenerateEditorButton( const wxPoint& pos, const wxSize wxSize s(25, -1); wxButton* but = new wxButton(); - but->Create(GetPanel(),wxPG_SUBID2,wxS("..."),p,s,wxWANTS_CHARS); + but->Create(GetPanel(),id,wxS("..."),p,s,wxWANTS_CHARS); // Now that we know the size, move to the correct position p.x = pos.x + sz.x - but->GetSize().x - 2; but->Move(p); -#else +#else wxSize s(sz.y-(wxPG_BUTTON_SIZEDEC*2)+(wxPG_NAT_BUTTON_BORDER_Y*2), sz.y-(wxPG_BUTTON_SIZEDEC*2)+(wxPG_NAT_BUTTON_BORDER_Y*2)); @@ -2014,7 +2017,7 @@ wxWindow* wxPropertyGrid::GenerateEditorButton( const wxPoint& pos, const wxSize #ifdef __WXMSW__ but->Hide(); #endif - but->Create(GetPanel(),wxPG_SUBID2,wxS("..."),p,s,wxWANTS_CHARS); + but->Create(GetPanel(),id,wxS("..."),p,s,wxWANTS_CHARS); #ifdef __WXGTK__ wxFont font = GetFont(); @@ -2048,19 +2051,41 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrlAndButton( const wxPoint& pos, // There is button Show in GenerateEditorTextCtrl as well but->Show(); #endif - return (wxWindow*) NULL; + return NULL; } wxString text; if ( !property->IsValueUnspecified() ) - text = property->GetValueString(property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE); + text = property->GetValueAsString(property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE); return GenerateEditorTextCtrl(pos,sz,text,but,property->m_maxLen); } // ----------------------------------------------------------------------- +void wxPropertyGrid::SetEditorAppearance( const wxPGCell& cell, + bool unspecified ) +{ + wxPGProperty* property = GetSelection(); + if ( !property ) + return; + wxWindow* ctrl = GetEditorControl(); + if ( !ctrl ) + return; + + property->GetEditorClass()->SetControlAppearance( this, + property, + ctrl, + cell, + m_editorAppearance, + unspecified ); + + m_editorAppearance = cell; +} + +// ----------------------------------------------------------------------- + wxTextCtrl* wxPropertyGrid::GetEditorTextCtrl() const { wxWindow* wnd = GetEditorControl(); @@ -2068,10 +2093,10 @@ wxTextCtrl* wxPropertyGrid::GetEditorTextCtrl() const if ( !wnd ) return NULL; - if ( wnd->IsKindOf(CLASSINFO(wxTextCtrl)) ) + if ( wxDynamicCast(wnd, wxTextCtrl) ) return wxStaticCast(wnd, wxTextCtrl); - if ( wnd->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) ) + if ( wxDynamicCast(wnd, wxOwnerDrawnComboBox) ) { wxOwnerDrawnComboBox* cb = wxStaticCast(wnd, wxOwnerDrawnComboBox); return cb->GetTextCtrl(); @@ -2125,36 +2150,48 @@ wxPGMultiButton::wxPGMultiButton( wxPropertyGrid* pg, const wxSize& sz ) SetBackgroundColour(pg->GetCellBackgroundColour()); } -int wxPGMultiButton::GenId( int id ) const +void wxPGMultiButton::Finalize( wxPropertyGrid* WXUNUSED(propGrid), + const wxPoint& pos ) { - if ( id < -1 ) + Move( pos.x + m_fullEditorSize.x - m_buttonsWidth, pos.y ); +} + +int wxPGMultiButton::GenId( int itemid ) const +{ + if ( itemid < -1 ) { if ( m_buttons.size() ) - id = GetButton(m_buttons.size()-1)->GetId() + 1; + itemid = GetButton(m_buttons.size()-1)->GetId() + 1; else - id = wxPG_SUBID2; + itemid = wxPG_SUBID2; } - return id; + return itemid; } #if wxUSE_BMPBUTTON -void wxPGMultiButton::Add( const wxBitmap& bitmap, int id ) +void wxPGMultiButton::Add( const wxBitmap& bitmap, int itemid ) { - id = GenId(id); + itemid = GenId(itemid); wxSize sz = GetSize(); - wxButton* button = new wxBitmapButton( this, id, bitmap, wxPoint(sz.x, 0), wxSize(sz.y, sz.y) ); - m_buttons.push_back(button); - int bw = button->GetSize().x; - SetSize(wxSize(sz.x+bw,sz.y)); - m_buttonsWidth += bw; + wxButton* button = new wxBitmapButton( this, itemid, bitmap, + wxPoint(sz.x, 0), + wxSize(sz.y, sz.y) ); + DoAddButton( button, sz ); } #endif -void wxPGMultiButton::Add( const wxString& label, int id ) +void wxPGMultiButton::Add( const wxString& label, int itemid ) { - id = GenId(id); + itemid = GenId(itemid); wxSize sz = GetSize(); - wxButton* button = new wxButton( this, id, label, wxPoint(sz.x, 0), wxSize(sz.y, sz.y) ); + wxButton* button = new wxButton( this, itemid, label, wxPoint(sz.x, 0), + wxSize(sz.y, sz.y) ); + DoAddButton( button, sz ); +} + +void wxPGMultiButton::DoAddButton( wxWindow* button, + const wxSize& sz ) +{ m_buttons.push_back(button); int bw = button->GetSize().x; SetSize(wxSize(sz.x+bw,sz.y));