// 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".
#pragma hdrstop
#endif
+#if wxUSE_PROPGRID
+
#ifndef WX_PRECOMP
#include "wx/defs.h"
#include "wx/object.h"
#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"
// This define is necessary to prevent macro clearing
#define __wxPG_SOURCE_FILE__
-#include <wx/propgrid/propgrid.h>
-#include <wx/propgrid/editors.h>
-#include <wx/propgrid/props.h>
+#include "wx/propgrid/propgrid.h"
+#include "wx/propgrid/editors.h"
+#include "wx/propgrid/props.h"
#if wxPG_USE_RENDERER_NATIVE
- #include <wx/renderer.h>
+ #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 <wx/odcombo.h>
-
-#ifdef __WXMSW__
- #include <wx/msw/private.h>
-#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
#define wxPG_CHECKMARK_HADJ (-1)
#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
#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
- #define wxPG_TEXTCTRLYADJUST 3
+ #define wxPG_TEXTCTRLYADJUST 0
#else
// defaults
#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
#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
{
}
-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
{
}
-
-bool wxPGEditor::CanContainCustomImage() const
+void wxPGEditor::SetControlAppearance( wxPropertyGrid* pg,
+ wxPGProperty* property,
+ wxWindow* ctrl,
+ const wxPGCell& cell,
+ const wxPGCell& oCell,
+ bool unspecified ) 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
-{
- DECLARE_CLASS(wxPGClipperWindow)
-public:
-
- wxPGClipperWindow()
- : wxWindow()
+ // Get old editor appearance
+ wxTextCtrl* tc = NULL;
+ wxComboCtrl* cb = NULL;
+ if ( ctrl->IsKindOf(CLASSINFO(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 ( ctrl->IsKindOf(CLASSINFO(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,
// 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)) )
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;
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).
wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl);
wxString textVal = tc->GetValue();
- if ( property->UsesAutoUnspecified() && !textVal.length() )
+ if ( property->UsesAutoUnspecified() && textVal.empty() )
{
variant.MakeNull();
return true;
}
-void wxPGTextCtrlEditor::SetValueToUnspecified( wxPGProperty* property, wxWindow* ctrl ) 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);
-}
-
-
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 )
+ {
+ pg->SetupTextCtrlValue(txt);
tc->SetValue(txt);
+ }
}
-void wxPGTextCtrlEditor::OnFocus( wxPGProperty*, wxWindow* wnd ) const
+void wxPGTextCtrlEditor_OnFocus( wxPGProperty* property,
+ wxTextCtrl* tc )
{
- wxTextCtrl* tc = wxStaticCast(wnd, 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);
+
+ if ( tc->GetValue() != correctText )
+ {
+ property->GetGrid()->SetupTextCtrlValue(correctText);
+ tc->SetValue(correctText);
+ }
tc->SetSelection(-1,-1);
}
+void wxPGTextCtrlEditor::OnFocus( wxPGProperty* property,
+ wxWindow* wnd ) const
+{
+ wxTextCtrl* tc = wxStaticCast(wnd, wxTextCtrl);
+ 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;
+}
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
-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.
wxPGComboBox()
: wxOwnerDrawnComboBox()
{
- m_dclickProcessor = (wxPGDoubleClickProcessor*) NULL;
+ m_dclickProcessor = NULL;
m_sizeEventCalled = false;
}
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;
}
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
);
}
};
-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;
else
{
if ( !p->IsValueUnspecified() )
- text = p->GetValueString(0);
+ text = p->GetValueAsString(0);
}
}
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
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;
}
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);
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;
}
}
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;
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
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();
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) &&
+ (property->IsKindOf(CLASSINFO(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 )
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();
wxASSERT( ctrl );
wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
wxASSERT( cb->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)));
- int ind = property->GetChoiceInfo( (wxPGChoiceInfo*)NULL );
+ int ind = property->GetChoiceSelection();
cb->SetSelection(ind);
}
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;
}
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()
}
-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);
}
}
-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);
}
}
-wxPGChoiceEditor::~wxPGChoiceEditor() { }
+wxPGChoiceEditor::~wxPGChoiceEditor()
+{
+ wxPG_EDITOR(Choice) = NULL;
+}
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
-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.
}
wxWindow* ctrl,
wxEvent& event ) const
{
- wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*) NULL;
- wxWindow* textCtrl = (wxWindow*) NULL;
+ wxOwnerDrawnComboBox* cb = NULL;
+ wxWindow* textCtrl = NULL;
if ( ctrl )
{
wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
wxString textVal = cb->GetValue();
- if ( property->UsesAutoUnspecified() && !textVal.length() )
+ if ( property->UsesAutoUnspecified() && textVal.empty() )
{
variant.MakeNull();
return true;
}
-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;
+}
+
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
-// 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,
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__
}
-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,
}
-wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor() { }
-
+wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor()
+{
+ wxPG_EDITOR(TextCtrlAndButton) = NULL;
+}
// -----------------------------------------------------------------------
// wxPGCheckBoxEditor
#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,
// 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++;
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;
-wxBitmap* wxSimpleCheckBox::ms_doubleBuffer = (wxBitmap*) NULL;
+void wxSimpleCheckBox::OnPaint( wxPaintEvent& WXUNUSED(event) )
+{
+ wxSize clientSize = GetClientSize();
+ wxAutoBufferedPaintDC dc(this);
-// value = 2 means toggle (sorry, too lazy to do constants)
-void wxSimpleCheckBox::SetValue( int value )
+ dc.Clear();
+ wxRect rect(0,0,clientSize.x,clientSize.y);
+ rect.y += 1;
+ rect.width += 1;
+
+ 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_COMMAND_CHECKBOX_CLICKED,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( propGrid->IsKindOf(CLASSINFO(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 pt = cb->ScreenToClient(::wxGetMousePosition());
+ if ( pt.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));
+ }
}
}
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
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()
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
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;
}
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 )
{
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();
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<wxTextCtrl*>(ctrl);
+ tc->SetMargins(0);
+#else
+ int textCtrlXAdjust = wxPG_TEXTCTRLXADJUST;
+#endif
finalPos.x += textCtrlXAdjust;
finalPos.width -= textCtrlXAdjust;
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);
// 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);
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
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__
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));
if ( s.x > m_lineHeight )
s.x = m_lineHeight;
+#ifdef __WXGTK__
+ // On wxGTK, take fixed button margins into account
+ if ( s.x < 25 )
+ s.x = 25;
+#endif
+
wxPoint p(pos.x+sz.x-s.x,
pos.y+wxPG_BUTTON_SIZEDEC-wxPG_NAT_BUTTON_BORDER_Y);
wxButton* but = new wxButton();
-#ifdef __WXMSW__
+ #ifdef __WXMSW__
but->Hide();
-#endif
- but->Create(GetPanel(),wxPG_SUBID2,wxS("..."),p,s,wxWANTS_CHARS);
-
- but->SetFont( m_captionFont );
+ #endif
+ but->Create(GetPanel(),id,wxS("..."),p,s,wxWANTS_CHARS);
+
+ #ifdef __WXGTK__
+ wxFont font = GetFont();
+ font.SetPointSize(font.GetPointSize()-2);
+ but->SetFont(font);
+ #else
+ but->SetFont(GetFont());
+ #endif
#endif
if ( selected->HasFlag(wxPG_PROP_READONLY) )
// 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();
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));
}
// -----------------------------------------------------------------------
+
+#endif // wxUSE_PROPGRID