// Created: 2007-04-14
// RCS-ID: $Id$
// Copyright: (c) Jaakko Salli
-// Licence: wxWindows license
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx/wx.h".
return GetClassInfo()->GetClassName();
}
-void wxPGEditor::DrawValue( wxDC& dc, const wxRect& rect, wxPGProperty* property, const wxString& text ) const
+void wxPGEditor::DrawValue( wxDC& dc, const wxRect& rect,
+ wxPGProperty* WXUNUSED(property),
+ const wxString& text ) const
{
- if ( !property->IsValueUnspecified() )
- dc.DrawText( text, rect.x+wxPG_XBEFORETEXT, rect.y );
+ dc.DrawText( text, rect.x+wxPG_XBEFORETEXT, rect.y );
}
bool wxPGEditor::GetValueFromControl( wxVariant&, wxPGProperty*, wxWindow* ) const
{
}
+void wxPGEditor::SetControlAppearance( wxPropertyGrid* pg,
+ wxPGProperty* property,
+ wxWindow* ctrl,
+ const wxPGCell& cell,
+ const wxPGCell& oCell,
+ bool unspecified ) const
+{
+ // Get old editor appearance
+ wxTextCtrl* tc = NULL;
+ wxComboCtrl* cb = NULL;
+ if ( ctrl->IsKindOf(CLASSINFO(wxTextCtrl)) )
+ {
+ tc = (wxTextCtrl*) ctrl;
+ }
+ else
+ {
+ if ( ctrl->IsKindOf(CLASSINFO(wxComboCtrl)) )
+ {
+ cb = (wxComboCtrl*) ctrl;
+ tc = cb->GetTextCtrl();
+ }
+ }
+
+ if ( tc || cb )
+ {
+ wxString tcText;
+ bool changeText = false;
+
+ 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;
+ }
+
+ if ( changeText )
+ {
+ // This prevents value from being modified
+ if ( tc )
+ {
+ pg->SetupTextCtrlValue(tcText);
+ tc->SetValue(tcText);
+ }
+ else
+ {
+ cb->SetText(tcText);
+ }
+ }
+ }
+
+ // 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();
+
+ // Foreground colour
+ const wxColour& fgCol = cell.GetFgCol();
+ if ( fgCol.IsOk() )
+ {
+ ctrl->SetForegroundColour(fgCol);
+ }
+ else if ( oCell.GetFgCol().IsOk() )
+ {
+ ctrl->SetForegroundColour(vattrs.colFg);
+ }
+
+ // 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);
+ }
+
+ // Also call the old SetValueToUnspecified()
+ if ( unspecified )
+ SetValueToUnspecified(property, ctrl);
+}
+
+void wxPGEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property),
+ wxWindow* WXUNUSED(ctrl) ) const
+{
+}
bool wxPGEditor::CanContainCustomImage() const
{
property->GetChildCount() )
return NULL;
- if ( !property->IsValueUnspecified() )
- text = property->GetValueAsString(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) &&
else
s = property->GetDisplayedString();
+ wxPropertyGrid* pg = property->GetGrid();
+
+ pg->SetupTextCtrlValue(s);
tc->SetValue(s);
//
}
-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;
+}
// -----------------------------------------------------------------------
int flags ) const
{
wxPropertyGrid* pg = GetGrid();
- pg->OnComboItemPaint( 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
if ( pDc )
pDc->SetBrush(*wxWHITE_BRUSH);
+ wxPGCellRenderer* renderer = NULL;
+ const wxPGChoiceEntry* cell = NULL;
+
if ( rect.x >= 0 )
{
//
rect.y + 1);
int renderFlags = wxPGCellRenderer::DontUseCellColours;
+ bool useCustomPaintProcedure;
+
+ // 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 ( 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;
- if ( flags & wxODCB_PAINTING_SELECTED )
- renderFlags |= wxPGCellRenderer::Selected;
+ // 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 ( 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 ( useCustomPaintProcedure )
{
pt.x += wxCC_CUSTOM_IMAGE_MARGIN1;
wxRect r(pt.x,pt.y,cis.x,cis.y);
if ( choices.IsOk() && item >= 0 && comValIndex < 0 )
{
- const wxPGChoiceEntry& cell = choices.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
{
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
const wxSize& sz,
long extraStyle ) const
{
+ // 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();
- bool isUnspecified = property->IsValueUnspecified();
-
- if ( !isUnspecified )
- defString = property->GetDisplayedString();
+ int argFlags = 0;
+ if ( !property->HasFlag(wxPG_PROP_READONLY) &&
+ !property->IsValueUnspecified() )
+ argFlags |= wxPG_EDITABLE_VALUE;
+ defString = property->GetValueAsString(argFlags);
wxArrayString labels = choices.GetLabels();
unsigned int cmnVals = property->GetDisplayedCommonValueCount();
if ( cmnVals )
{
- if ( !isUnspecified )
+ if ( !property->IsValueUnspecified() )
{
int cmnVal = property->GetCommonValue();
if ( cmnVal >= 0 )
cb->SetButtonPosition(si.y,0,wxRIGHT);
cb->SetMargins(wxPG_XBEFORETEXT-1);
- wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb, property->GetCommonValue() );
+ // Set hint text
+ cb->SetHint(property->GetHintText());
+
+ wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb,
+ property->GetCommonValue() );
if ( index >= 0 && index < (int)cb->GetCount() )
{
cb->SetText( defString );
}
else if ( !(extraStyle & wxCB_READONLY) && defString.length() )
+ {
+ propGrid->SetupTextCtrlValue(defString);
cb->SetValue( defString );
+ }
else
+ {
cb->SetSelection( -1 );
+ }
#ifdef __WXMSW__
cb->Show();
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;
}
}
}
-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;
+}
// -----------------------------------------------------------------------
void wxPGComboBoxEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const
{
wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
- cb->SetValue(property->GetValueAsString(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.
}
}
-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;
+}
+
// -----------------------------------------------------------------------
}
-wxPGChoiceAndButtonEditor::~wxPGChoiceAndButtonEditor() { }
-
+wxPGChoiceAndButtonEditor::~wxPGChoiceAndButtonEditor()
+{
+ wxPG_EDITOR(ChoiceAndButton) = NULL;
+}
// -----------------------------------------------------------------------
// wxPGTextCtrlAndButtonEditor
}
-wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor() { }
-
+wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor()
+{
+ wxPG_EDITOR(TextCtrlAndButton) = NULL;
+}
// -----------------------------------------------------------------------
// wxPGCheckBoxEditor
static void DrawSimpleCheckBox( wxDC& dc, const wxRect& rect, int box_hei,
- int state, const wxColour& lineCol )
+ int state )
{
// Box rectangle.
wxRect r(rect.x+wxPG_XBEFORETEXT,rect.y+((rect.height-box_hei)/2),
box_hei,box_hei);
- wxColour useCol = lineCol;
+ wxColour useCol = dc.GetTextForeground();
if ( state & wxSCB_STATE_UNSPECIFIED )
{
wxSimpleCheckBox::~wxSimpleCheckBox()
{
- delete ms_doubleBuffer;
- ms_doubleBuffer = NULL;
+ wxDELETE(ms_doubleBuffer);
}
wxBitmap* wxSimpleCheckBox::ms_doubleBuffer = NULL;
dc.SetPen( bgcol );
dc.DrawRectangle( rect );
- wxColour txcol = GetForegroundColour();
+ 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,txcol);
+ DrawSimpleCheckBox(dc, rect, m_boxHeight, state);
}
void wxSimpleCheckBox::OnLeftClick( wxMouseEvent& event )
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;
const wxString& WXUNUSED(text) ) const
{
int state = wxSCB_STATE_UNCHECKED;
- wxColour rectCol = dc.GetTextForeground();
if ( !property->IsValueUnspecified() )
{
state |= wxSCB_STATE_UNSPECIFIED;
}
- DrawSimpleCheckBox(dc, rect, dc.GetCharHeight(), state, rectCol);
+ DrawSimpleCheckBox(dc, rect, dc.GetCharHeight(), state);
}
void wxPGCheckBoxEditor::UpdateControl( wxPGProperty* property,
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
void wxPropertyGrid::CorrectEditorWidgetSizeX()
{
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 ( GetSelection() && (m_wndEditor || m_wndEditor2) )
- {
- wxRect r = GetEditorWidgetRect(GetSelection(), 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);
+
+ if ( m_wndEditor )
+ {
+ wxPoint pos = m_wndEditor->GetPosition();
+
+ // Calculate y offset
+ int offset = pos.y % m_lineHeight;
+
+ m_wndEditor->Move(pos.x, r.y + offset);
+ }
+
+ if ( m_wndEditor2 )
+ {
+ wxPoint pos = m_wndEditor2->GetPosition();
- m_wndEditor2->Move(pos.x, r.y);
+ m_wndEditor2->Move(pos.x, r.y);
+ }
}
}
}
SetupTextCtrlValue(value);
tc->Create(ctrlParent,id,value, p, s,tcFlags);
+#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(tc, forColumn);
tc->AutoComplete(attrVal.GetArrayString());
}
+ // Set hint text
+ tc->SetHint(prop->GetHintText());
+
return tc;
}
// -----------------------------------------------------------------------
+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();