/**
Returns wxPGCell of given column.
+
+ @remarks const version of this member function returns 'default'
+ wxPGCell object if the property itself didn't hold
+ cell data.
*/
const wxPGCell& GetCell( unsigned int column ) const;
- wxPGCell& GetCell( unsigned int column );
+ /**
+ Returns wxPGCell of given column, creating one if necessary.
+ */
+ wxPGCell& GetCell( unsigned int column )
+ {
+ return GetOrCreateCell(column);
+ }
+
+ /**
+ Returns wxPGCell of given column, creating one if necessary.
+ */
+ wxPGCell& GetOrCreateCell( unsigned int column );
/** Return number of displayed common values for this property.
*/
/** Deletes all sub-properties. */
void Empty();
+ bool HasCell( unsigned int column ) const
+ {
+ if ( m_cells.size() > column )
+ return true;
+ return false;
+ }
+
void InitAfterAdded( wxPropertyGridPageState* pageState,
wxPropertyGrid* propgrid );
// wxPropertyGrid::DoSelectProperty flags (selFlags)
// Focuses to created editor
-#define wxPG_SEL_FOCUS 0x01
+#define wxPG_SEL_FOCUS 0x0001
// Forces deletion and recreation of editor
-#define wxPG_SEL_FORCE 0x02
+#define wxPG_SEL_FORCE 0x0002
// For example, doesn't cause EnsureVisible
-#define wxPG_SEL_NONVISIBLE 0x04
+#define wxPG_SEL_NONVISIBLE 0x0004
// Do not validate editor's value before selecting
-#define wxPG_SEL_NOVALIDATE 0x08
+#define wxPG_SEL_NOVALIDATE 0x0008
// Property being deselected is about to be deleted
-#define wxPG_SEL_DELETING 0x10
+#define wxPG_SEL_DELETING 0x0010
// Property's values was set to unspecified by the user
-#define wxPG_SEL_SETUNSPEC 0x20
+#define wxPG_SEL_SETUNSPEC 0x0020
// Property's event handler changed the value
-#define wxPG_SEL_DIALOGVAL 0x40
+#define wxPG_SEL_DIALOGVAL 0x0040
// Set to disable sending of wxEVT_PG_SELECTED event
-#define wxPG_SEL_DONT_SEND_EVENT 0x80
-
+#define wxPG_SEL_DONT_SEND_EVENT 0x0080
+// Don't make any graphics updates
+#define wxPG_SEL_NO_REFRESH 0x0100
// -----------------------------------------------------------------------
@event{EVT_PG_ITEM_EXPANDED(id, func)}
Respond to wxEVT_PG_ITEM_EXPANDED event, generated when user expands
a property or category..
+ @event{EVT_PG_LABEL_EDIT_BEGIN(id, func)}
+ Respond to wxEVT_PG_LABEL_EDIT_BEGIN event, generated when is about to
+ begin editing a property label. You can veto this event to prevent the
+ action.
+ @event{EVT_PG_LABEL_EDIT_ENDING(id, func)}
+ Respond to wxEVT_PG_LABEL_EDIT_ENDING event, generated when is about to
+ end editing of a property label. You can veto this event to prevent the
+ action.
@endEventTable
@remarks
return DoRemoveFromSelection(p, wxPG_SEL_DONT_SEND_EVENT);
}
+ /**
+ Makes given column editable by user.
+
+ @see BeginLabelEdit(), EndLabelEdit()
+ */
+ void MakeColumnEditable( unsigned int column )
+ {
+ wxASSERT( column != 1 );
+ m_pState->m_editableColumns.push_back(column);
+ }
+
+ /**
+ Creates label editor wxTextCtrl for given column, for property
+ that is currently selected. When multiple selection is
+ enabled, this applies to whatever property GetSelection()
+ returns.
+
+ @param colIndex
+ Which column's label to edit. Note that you should not
+ use value 1, which is reserved for property value
+ column.
+
+ @see EndLabelEdit(), MakeColumnEditable()
+ */
+ void BeginLabelEdit( unsigned int column = 0 )
+ {
+ DoBeginLabelEdit(column, wxPG_SEL_DONT_SEND_EVENT);
+ }
+
+ /**
+ Destroys label editor wxTextCtrl, if any.
+
+ @param commit
+ Use @true (default) to store edited label text in
+ property cell data.
+
+ @see BeginLabelEdit(), MakeColumnEditable()
+ */
+ void EndLabelEdit( bool commit = true )
+ {
+ DoEndLabelEdit(commit, wxPG_SEL_DONT_SEND_EVENT);
+ }
+
+ /**
+ Returns currently active label editor, NULL if none.
+ */
+ wxTextCtrl* GetLabelEditor() const
+ {
+ return m_labelEditor;
+ }
+
/** Sets category caption background colour. */
void SetCaptionBackgroundColour(const wxColour& col);
shown).
*/
void FixPosForTextCtrl( wxWindow* ctrl,
+ unsigned int forColumn = 1,
const wxPoint& offset = wxPoint(0, 0) );
/** Shortcut for creating text editor widget.
const wxString& value,
wxWindow* secondary,
int extraStyle = 0,
- int maxLen = 0 );
+ int maxLen = 0,
+ unsigned int forColumn = 1 );
/* Generates both textctrl and button.
*/
/** When drawing next time, clear this many item slots at the end. */
int m_clearThisMany;
+ // Mouse is hovering over this column (index)
+ unsigned int m_colHover;
+
// pointer to property that has mouse hovering
wxPGProperty* m_propHover;
+ // Active label editor
+ wxTextCtrl* m_labelEditor;
+
+ // For which property the label editor is active
+ wxPGProperty* m_labelEditorProperty;
+
// EventObject for wxPropertyGridEvents
wxWindow* m_eventObject;
// y coordinate of property that mouse hovering
int m_propHoverY;
+
// Which column's editor is selected (usually 1)?
- int m_selColumn;
+ unsigned int m_selColumn;
// x relative to splitter (needed for resize).
int m_ctrlXAdjust;
protected:
bool AddToSelectionFromInputEvent( wxPGProperty* prop,
+ unsigned int colIndex,
wxMouseEvent* event = NULL,
int selFlags = 0 );
bool DoEditorValidate();
+ // Similar to DoSelectProperty() but also works on columns
+ // other than 1. Does not active editor if column is not
+ // editable.
+ bool DoSelectAndEdit( wxPGProperty* prop,
+ unsigned int colIndex,
+ unsigned int selFlags );
+
void DoSetSelection( const wxArrayPGProperty& newSelection,
int selFlags = 0 );
bool DoRemoveFromSelection( wxPGProperty* prop,
int selFlags = 0 );
+ void DoBeginLabelEdit( unsigned int colIndex, int selFlags = 0 );
+ void DoEndLabelEdit( bool commit, int selFlags = 0 );
+ void OnLabelEditorEnterPress( wxCommandEvent& event );
+ void OnLabelEditorKeyPress( wxKeyEvent& event );
+
wxPGProperty* DoGetItemAtY( int y ) const;
void DoSetSplitterPosition_( int newxpos,
int splitterIndex = 0,
bool allPages = false );
+ void DestroyEditorWnd( wxWindow* wnd );
void FreeEditors();
virtual bool DoExpand( wxPGProperty* p, bool sendEvent = false );
void PrepareAfterItemsAdded();
- bool SendEvent( int eventType,
- wxPGProperty* p,
+ // Omit the wxPG_SEL_NOVALIDATE flag to allow vetoing the event
+ bool SendEvent( int eventType, wxPGProperty* p,
wxVariant* pValue = NULL,
- unsigned int selFlags = 0 );
+ unsigned int selFlags = wxPG_SEL_NOVALIDATE,
+ unsigned int column = 1 );
void SetFocusOnCanvas();
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_PROPGRID, wxEVT_PG_ITEM_COLLAPSED, wxPropertyGridEvent );
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_PROPGRID, wxEVT_PG_ITEM_EXPANDED, wxPropertyGridEvent );
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_PROPGRID, wxEVT_PG_DOUBLE_CLICK, wxPropertyGridEvent );
+wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_PROPGRID,
+ wxEVT_PG_LABEL_EDIT_BEGIN, wxPropertyGridEvent );
+wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_PROPGRID,
+ wxEVT_PG_LABEL_EDIT_ENDING, wxPropertyGridEvent );
#else
enum {
wxEVT_PG_PAGE_CHANGED,
wxEVT_PG_ITEM_COLLAPSED,
wxEVT_PG_ITEM_EXPANDED,
- wxEVT_PG_DOUBLE_CLICK
+ wxEVT_PG_DOUBLE_CLICK,
+ wxEVT_PG_LABEL_EDIT_BEGIN,
+ wxEVT_PG_LABEL_EDIT_ENDING
};
#endif
#define EVT_PG_PAGE_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_PAGE_CHANGED, id, -1, wxEVENT_HANDLER_CAST( wxPropertyGridEventFunction, fn ), NULL ),
#define EVT_PG_ITEM_COLLAPSED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_ITEM_COLLAPSED, id, -1, wxEVENT_HANDLER_CAST( wxPropertyGridEventFunction, fn ), NULL ),
#define EVT_PG_ITEM_EXPANDED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_ITEM_EXPANDED, id, -1, wxEVENT_HANDLER_CAST( wxPropertyGridEventFunction, fn ), NULL ),
+#define EVT_PG_LABEL_EDIT_BEGIN(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_LABEL_EDIT_BEGIN, id, -1, wxEVENT_HANDLER_CAST( wxPropertyGridEventFunction, fn ), NULL ),
+#define EVT_PG_LABEL_EDIT_ENDING(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_LABEL_EDIT_ENDING, id, -1, wxEVENT_HANDLER_CAST( wxPropertyGridEventFunction, fn ), NULL ),
#define wxPropertyGridEventHandler(fn) \
wxEVENT_HANDLER_CAST( wxPropertyGridEventFunction, fn )
/** Copyer. */
virtual wxEvent* Clone() const;
+ /**
+ Returns the column index associated with this event.
+ */
+ unsigned int GetColumn() const
+ {
+ return m_column;
+ }
+
wxPGProperty* GetMainParent() const
{
wxASSERT(m_property);
return m_validationInfo->GetFailureBehavior();
}
+ void SetColumn( unsigned int column )
+ {
+ m_column = column;
+ }
+
void SetCanVeto( bool canVeto ) { m_canVeto = canVeto; }
bool WasVetoed() const { return m_wasVetoed; }
wxPropertyGrid* m_pg;
wxPGValidationInfo* m_validationInfo;
+ unsigned int m_column;
+
bool m_canVeto;
bool m_wasVetoed;
static wxPGEditor* GetEditorByName( const wxString& editorName );
+ // NOTE: This function reselects the property and may cause
+ // excess flicker, so to just call Refresh() on a rect
+ // of single property, call DrawItem() instead.
virtual void RefreshProperty( wxPGProperty* p ) = 0;
protected:
/** List of column widths (first column does not include margin). */
wxArrayInt m_colWidths;
+ /** List of indices of columns the user can edit by clicking it. */
+ wxArrayInt m_editableColumns;
+
double m_fSplitterX;
/** Most recently added category. */
/**
Returns wxPGCell of given column.
+
+ @remarks const version of this member function returns 'default'
+ wxPGCell object if the property itself didn't hold
+ cell data.
*/
const wxPGCell& GetCell( unsigned int column ) const;
+ /**
+ Returns wxPGCell of given column, creating one if necessary.
+ */
+ wxPGCell& GetCell( unsigned int column );
+
+ /**
+ Returns wxPGCell of given column, creating one if necessary.
+ */
+ wxPGCell& GetOrCreateCell( unsigned int column );
+
/**
Returns number of child properties.
*/
@event{EVT_PG_ITEM_EXPANDED(id, func)}
Respond to wxEVT_PG_ITEM_EXPANDED event, generated when user expands
a property or category.
+ @event{EVT_PG_LABEL_EDIT_BEGIN(id, func)}
+ Respond to wxEVT_PG_LABEL_EDIT_BEGIN event, generated when is about to
+ begin editing a property label. You can veto this event to prevent the
+ action.
+ @event{EVT_PG_LABEL_EDIT_ENDING(id, func)}
+ Respond to wxEVT_PG_LABEL_EDIT_ENDING event, generated when is about to
+ end editing of a property label. You can veto this event to prevent the
+ action.
@endEventTable
@remarks
*/
static void AutoGetTranslation( bool enable );
+ /**
+ Creates label editor wxTextCtrl for given column, for property
+ that is currently selected. When multiple selection is
+ enabled, this applies to whatever property GetSelection()
+ returns.
+
+ @param colIndex
+ Which column's label to edit. Note that you should not
+ use value 1, which is reserved for property value
+ column.
+
+ @see EndLabelEdit(), MakeColumnEditable()
+ */
+ void BeginLabelEdit( unsigned int column = 0 );
+
/**
Changes value of a property, as if from an editor. Use this instead of
SetPropertyValue() if you need the value to run through validation
*/
bool EnableCategories( bool enable );
+ /**
+ Destroys label editor wxTextCtrl, if any.
+
+ @param commit
+ Use @true (default) to store edited label text in
+ property cell data.
+
+ @see BeginLabelEdit(), MakeColumnEditable()
+ */
+ void EndLabelEdit( bool commit = true );
+
/**
Scrolls and/or expands items to ensure that the given item is visible.
*/
wxSize FitColumns();
+ /**
+ Returns currently active label editor, NULL if none.
+ */
+ wxTextCtrl* GetLabelEditor() const;
+
/**
Returns wxWindow that the properties are painted on, and which should be
used as the parent for editor controls.
*/
bool IsFrozen() const;
+ /**
+ Makes given column editable by user.
+
+ @see BeginLabelEdit(), EndLabelEdit()
+ */
+ void MakeColumnEditable( unsigned int column );
+
/**
It is recommended that you call this function any time your code causes
wxPropertyGrid's top-level parent to change. wxPropertyGrid's OnIdle()
ID_SELECTSTYLE,
ID_SAVESTATE,
ID_RESTORESTATE,
- ID_RUNMINIMAL
+ ID_RUNMINIMAL,
+ ID_ENABLELABELEDITING
};
// -----------------------------------------------------------------------
EVT_PG_DOUBLE_CLICK( PGID, FormMain::OnPropertyGridItemDoubleClick )
// This occurs when propgridmanager's page changes.
EVT_PG_PAGE_CHANGED( PGID, FormMain::OnPropertyGridPageChange )
+ // This occurs when user starts editing a property label
+ EVT_PG_LABEL_EDIT_BEGIN( PGID,
+ FormMain::OnPropertyGridLabelEditBegin )
+ // This occurs when user stops editing a property label
+ EVT_PG_LABEL_EDIT_ENDING( PGID,
+ FormMain::OnPropertyGridLabelEditEnding )
// This occurs when property's editor button (if any) is clicked.
EVT_BUTTON( PGID, FormMain::OnPropertyGridButtonClick )
EVT_MENU( ID_SETBGCOLOURRECUR, FormMain::OnSetBackgroundColour )
EVT_MENU( ID_CLEARMODIF, FormMain::OnClearModifyStatusClick )
EVT_MENU( ID_FREEZE, FormMain::OnFreezeClick )
+ EVT_MENU( ID_ENABLELABELEDITING, FormMain::OnEnableLabelEditing )
EVT_MENU( ID_DUMPLIST, FormMain::OnDumpList )
EVT_MENU( ID_COLOURSCHEME1, FormMain::OnColourScheme )
// -----------------------------------------------------------------------
+void FormMain::OnPropertyGridLabelEditBegin( wxPropertyGridEvent& event )
+{
+ wxLogDebug("wxPG_EVT_LABEL_EDIT_BEGIN(%s)",
+ event.GetProperty()->GetLabel().c_str());
+}
+
+// -----------------------------------------------------------------------
+
+void FormMain::OnPropertyGridLabelEditEnding( wxPropertyGridEvent& event )
+{
+ wxLogDebug("wxPG_EVT_LABEL_EDIT_ENDING(%s)",
+ event.GetProperty()->GetLabel().c_str());
+}
+
+// -----------------------------------------------------------------------
+
void FormMain::OnPropertyGridHighlight( wxPropertyGridEvent& WXUNUSED(event) )
{
}
menuTry->Append(ID_SELECTSTYLE, wxT("Set Window Style"),
wxT("Select window style flags used by the grid."));
+ menuTry->Append(ID_ENABLELABELEDITING, "Enable label editing",
+ "This calls wxPropertyGrid::MakeColumnEditable(0)");
menuTry->AppendSeparator();
menuTry->AppendRadioItem( ID_COLOURSCHEME1, wxT("Standard Colour Scheme") );
menuTry->AppendRadioItem( ID_COLOURSCHEME2, wxT("White Colour Scheme") );
// -----------------------------------------------------------------------
+void FormMain::OnEnableLabelEditing( wxCommandEvent& WXUNUSED(event) )
+{
+ m_propGrid->MakeColumnEditable(0);
+}
+
+// -----------------------------------------------------------------------
+
void FormMain::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxString msg;
void OnSetBackgroundColour( wxCommandEvent& event );
void OnClearModifyStatusClick( wxCommandEvent& event );
void OnFreezeClick( wxCommandEvent& event );
+ void OnEnableLabelEditing( wxCommandEvent& event );
void OnDumpList( wxCommandEvent& event );
void OnCatColours( wxCommandEvent& event );
void OnSetColumns( wxCommandEvent& event );
void OnPropertyGridKeyEvent( wxKeyEvent& event );
void OnPropertyGridItemCollapse( wxPropertyGridEvent& event );
void OnPropertyGridItemExpand( wxPropertyGridEvent& event );
+ void OnPropertyGridLabelEditBegin( wxPropertyGridEvent& event );
+ void OnPropertyGridLabelEditEnding( wxPropertyGridEvent& event );
void OnAbout( wxCommandEvent& event );
// 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 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;
+ int textCtrlXAdjust = wxPG_TEXTCTRLXADJUST;
+
+ if ( forColumn != 1 )
+ textCtrlXAdjust -= 3; // magic number!
finalPos.x += textCtrlXAdjust;
finalPos.width -= textCtrlXAdjust;
const wxString& value,
wxWindow* secondary,
int extraStyle,
- int maxLen )
+ int maxLen,
+ unsigned int forColumn )
{
wxWindowID id = wxPG_SUBID1;
wxPGProperty* prop = GetSelection();
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);
// Center the control vertically
if ( !hasSpecialSize )
- FixPosForTextCtrl(tc);
+ FixPosForTextCtrl(tc, forColumn);
+
+ if ( forColumn != 1 )
+ {
+ tc->SetBackgroundColour(m_colSelBack);
+ tc->SetForegroundColour(m_colSelFore);
+ }
#ifdef __WXMSW__
tc->Show();
return pg->GetPropertyDefaultCell();
}
-wxPGCell& wxPGProperty::GetCell( unsigned int column )
+wxPGCell& wxPGProperty::GetOrCreateCell( unsigned int column )
{
EnsureCells(column);
return m_cells[column];
m_iFlags = 0;
m_pState = NULL;
m_wndEditor = m_wndEditor2 = NULL;
- m_selColumn = -1;
+ m_selColumn = 1;
+ m_colHover = 1;
m_propHover = NULL;
+ m_labelEditor = NULL;
+ m_labelEditorProperty = NULL;
m_eventObject = this;
m_curFocused = NULL;
m_sortFunction = NULL;
if ( !(selFlags & wxPG_SEL_DONT_SEND_EVENT) )
{
- SendEvent( wxEVT_PG_SELECTED, prop, NULL, selFlags );
+ SendEvent( wxEVT_PG_SELECTED, prop, NULL );
}
- // For some reason, if we use RefreshProperty(prop) here,
- // we may go into infinite drawing loop.
- Refresh();
+ DrawItem(prop);
}
return true;
else
{
m_pState->DoRemoveFromSelection(prop);
- RefreshProperty(prop);
+ DrawItem(prop);
res = true;
}
// -----------------------------------------------------------------------
+bool wxPropertyGrid::DoSelectAndEdit( wxPGProperty* prop,
+ unsigned int colIndex,
+ unsigned int selFlags )
+{
+ //
+ // NB: Enable following if label editor background colour is
+ // ever changed to any other than m_colSelBack.
+ //
+ // We use this workaround to prevent visible flicker when editing
+ // a cell. Atleast on wxMSW, there is a difficult to find
+ // (and perhaps prevent) redraw somewhere between making property
+ // selected and enabling label editing.
+ //
+ //wxColour prevColSelBack = m_colSelBack;
+ //m_colSelBack = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
+
+ bool res;
+
+ if ( colIndex == 1 )
+ {
+ res = DoSelectProperty(prop, selFlags);
+ }
+ else
+ {
+ // send event
+ DoClearSelection(false, wxPG_SEL_NO_REFRESH);
+
+ if ( m_pState->m_editableColumns.Index(colIndex) == wxNOT_FOUND )
+ {
+ res = DoAddToSelection(prop, selFlags);
+ }
+ else
+ {
+ res = DoAddToSelection(prop, selFlags|wxPG_SEL_NO_REFRESH);
+
+ DoBeginLabelEdit(colIndex, selFlags);
+ }
+ }
+
+ //m_colSelBack = prevColSelBack;
+ return res;
+}
+
+// -----------------------------------------------------------------------
+
bool wxPropertyGrid::AddToSelectionFromInputEvent( wxPGProperty* prop,
+ unsigned int colIndex,
wxMouseEvent* mouseEvent,
int selFlags )
{
// disturbing the selection.
if ( GetSelectedProperties().size() <= 1 ||
!alreadySelected )
- return DoSelectProperty(prop, selFlags);
+ return DoSelectAndEdit(prop, colIndex, selFlags);
return true;
}
else
}
else
{
- res = DoSelectProperty(prop, selFlags);
+ res = DoSelectAndEdit(prop, colIndex, selFlags);
}
return res;
// -----------------------------------------------------------------------
+void wxPropertyGrid::DoBeginLabelEdit( unsigned int colIndex,
+ int selFlags )
+{
+ wxPGProperty* selected = GetSelection();
+ wxCHECK_RET(selected, wxT("No property selected"));
+ wxCHECK_RET(colIndex != 1, wxT("Do not use this for column 1"));
+
+ if ( !(selFlags & wxPG_SEL_DONT_SEND_EVENT) )
+ {
+ if ( SendEvent( wxEVT_PG_LABEL_EDIT_BEGIN,
+ selected, NULL, 0,
+ colIndex ) )
+ return;
+ }
+
+ wxString text;
+ const wxPGCell* cell = NULL;
+ if ( selected->HasCell(colIndex) )
+ {
+ cell = &selected->GetCell(colIndex);
+ if ( !cell->HasText() && colIndex == 0 )
+ text = selected->GetLabel();
+ }
+
+ if ( !cell )
+ {
+ if ( colIndex == 0 )
+ text = selected->GetLabel();
+ else
+ cell = &selected->GetOrCreateCell(colIndex);
+ }
+
+ if ( cell && cell->HasText() )
+ text = cell->GetText();
+
+ DoEndLabelEdit(true, wxPG_SEL_NOVALIDATE); // send event
+
+ m_selColumn = colIndex;
+
+ wxRect r = GetEditorWidgetRect(selected, m_selColumn);
+
+ wxWindow* tc = GenerateEditorTextCtrl(r.GetPosition(),
+ r.GetSize(),
+ text,
+ NULL,
+ wxTE_PROCESS_ENTER,
+ 0,
+ colIndex);
+
+ wxWindowID id = tc->GetId();
+ tc->Connect(id, wxEVT_COMMAND_TEXT_ENTER,
+ wxCommandEventHandler(wxPropertyGrid::OnLabelEditorEnterPress),
+ NULL, this);
+ tc->Connect(id, wxEVT_KEY_DOWN,
+ wxKeyEventHandler(wxPropertyGrid::OnLabelEditorKeyPress),
+ NULL, this);
+
+ tc->SetFocus();
+
+ m_labelEditor = wxStaticCast(tc, wxTextCtrl);
+ m_labelEditorProperty = selected;
+}
+
+// -----------------------------------------------------------------------
+
+void
+wxPropertyGrid::OnLabelEditorEnterPress( wxCommandEvent& WXUNUSED(event) )
+{
+ DoEndLabelEdit(true);
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::OnLabelEditorKeyPress( wxKeyEvent& event )
+{
+ int keycode = event.GetKeyCode();
+
+ if ( keycode == WXK_ESCAPE )
+ {
+ DoEndLabelEdit(false);
+ }
+ else
+ {
+ event.Skip();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::DoEndLabelEdit( bool commit, int selFlags )
+{
+ if ( !m_labelEditor )
+ return;
+
+ wxPGProperty* prop = m_labelEditorProperty;
+ wxASSERT(prop);
+
+ if ( commit )
+ {
+ if ( !(selFlags & wxPG_SEL_DONT_SEND_EVENT) )
+ {
+ // wxPG_SEL_NOVALIDATE is passed correctly in selFlags
+ if ( SendEvent( wxEVT_PG_LABEL_EDIT_ENDING,
+ prop, NULL, selFlags,
+ m_selColumn ) )
+ return;
+ }
+
+ wxString text = m_labelEditor->GetValue();
+ wxPGCell* cell = NULL;
+ if ( prop->HasCell(m_selColumn) )
+ {
+ cell = &prop->GetCell(m_selColumn);
+ }
+ else
+ {
+ if ( m_selColumn == 0 )
+ prop->SetLabel(text);
+ else
+ cell = &prop->GetOrCreateCell(m_selColumn);
+ }
+
+ if ( cell )
+ cell->SetText(text);
+ }
+
+ m_selColumn = 1;
+
+ DestroyEditorWnd(m_labelEditor);
+ m_labelEditor = NULL;
+ m_labelEditorProperty = NULL;
+
+ DrawItem(prop);
+}
+
+// -----------------------------------------------------------------------
+
void wxPropertyGrid::SetExtraStyle( long exStyle )
{
if ( exStyle & wxPG_EX_NATIVE_DOUBLE_BUFFERING )
{
cellRect.width = nextCellWidth - 1;
- bool ctrlCell = false;
+ wxWindow* cellEditor = NULL;
int cellRenderFlags = renderFlags;
- // Tree Item Button
+ // Tree Item Button (must be drawn before clipping is set up)
if ( ci == 0 && !HasFlag(wxPG_HIDE_MARGIN) && p->HasVisibleChildren() )
DrawExpanderButton( dc, butRect, p );
// Background
- if ( isSelected && ci == 1 )
+ if ( isSelected && (ci == 1 || ci == m_selColumn) )
{
- if ( p == firstSelected && m_wndEditor )
+ if ( p == firstSelected )
+ {
+ if ( ci == 1 && m_wndEditor )
+ cellEditor = m_wndEditor;
+ else if ( ci == m_selColumn && m_labelEditor )
+ cellEditor = m_labelEditor;
+ }
+
+ if ( cellEditor )
{
wxColour editorBgCol =
- GetEditorControl()->GetBackgroundColour();
+ cellEditor->GetBackgroundColour();
dc.SetBrush(editorBgCol);
dc.SetPen(editorBgCol);
dc.SetTextForeground(m_colPropFore);
dc.DrawRectangle(cellRect);
- if ( m_dragStatus == 0 &&
- !(m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE) )
- ctrlCell = true;
+ if ( m_dragStatus != 0 ||
+ (m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE) )
+ cellEditor = NULL;
}
else
{
cellRect.width -= textXAdd;
// Foreground
- if ( !ctrlCell )
+ if ( !cellEditor )
{
wxPGCellRenderer* renderer;
int cmnVal = p->GetCommonValue();
if ( flags & SendEvtChanging )
{
// SendEvent returns true if event was vetoed
- if ( SendEvent( wxEVT_PG_CHANGING, evtChangingProperty, &evtChangingValue, 0 ) )
+ if ( SendEvent( wxEVT_PG_CHANGING, evtChangingProperty,
+ &evtChangingValue ) )
return false;
}
while ( pwc != changedProperty )
{
- SendEvent( wxEVT_PG_CHANGED, pwc, NULL, selFlags );
+ SendEvent( wxEVT_PG_CHANGED, pwc, NULL );
pwc = pwc->GetParent();
}
}
- SendEvent( wxEVT_PG_CHANGED, changedProperty, NULL, selFlags );
+ SendEvent( wxEVT_PG_CHANGED, changedProperty, NULL );
m_inDoPropertyChanged = 0;
NULL, this);
}
+void wxPropertyGrid::DestroyEditorWnd( wxWindow* wnd )
+{
+ if ( !wnd )
+ return;
+
+ wnd->Hide();
+
+ // Do not free editors immediately (for sake of processing events)
+ wxPendingDelete.Append(wnd);
+}
+
void wxPropertyGrid::FreeEditors()
{
//
wxEvtHandler* handler = m_wndEditor2->PopEventHandler(false);
m_wndEditor2->Hide();
wxPendingDelete.Append( handler );
- wxPendingDelete.Append( m_wndEditor2 );
+ DestroyEditorWnd(m_wndEditor2);
m_wndEditor2 = NULL;
}
wxEvtHandler* handler = m_wndEditor->PopEventHandler(false);
m_wndEditor->Hide();
wxPendingDelete.Append( handler );
- wxPendingDelete.Append( m_wndEditor );
+ DestroyEditorWnd(m_wndEditor);
m_wndEditor = NULL;
}
}
if ( prevFirstSel && prevFirstSel->HasFlag(wxPG_PROP_BEING_DELETED) )
prevFirstSel = NULL;
+ // Always send event, as this is indirect call
+ DoEndLabelEdit(true, wxPG_SEL_NOVALIDATE);
+
/*
if ( prevFirstSel )
wxPrintf( "Selected %s\n", prevFirstSel->GetClassInfo()->GetClassName() );
{
m_iFlags &= ~(wxPG_FL_ABNORMAL_EDITOR);
m_editorFocused = 0;
- m_selColumn = 1;
m_pState->DoSetSelection(p);
// If frozen, always free controls. But don't worry, as Thaw will
}
FreeEditors();
- m_selColumn = -1;
-
- // We need to always fully refresh the grid here
- Refresh(false);
m_iFlags &= ~(wxPG_FL_ABNORMAL_EDITOR);
EditorsValueWasNotModified();
m_pState->DoSetSelection(p);
+ // Redraw unselected
+ for ( unsigned int i=0; i<prevSelection.size(); i++ )
+ {
+ DrawItem(prevSelection[i]);
+ }
+
//
// Then, activate the one given.
if ( p )
m_wndEditor->Show(true);
}
- DrawItems(p, p);
+ if ( !(flags & wxPG_SEL_NO_REFRESH) )
+ DrawItem(p);
}
else
{
// call wx event handler (here so that it also occurs on deselection)
if ( !(flags & wxPG_SEL_DONT_SEND_EVENT) )
- SendEvent( wxEVT_PG_SELECTED, p, NULL, flags );
+ SendEvent( wxEVT_PG_SELECTED, p, NULL );
return true;
}
// selFlags uses same values DoSelectProperty's flags
// Returns true if event was vetoed.
-bool wxPropertyGrid::SendEvent( int eventType, wxPGProperty* p, wxVariant* pValue, unsigned int WXUNUSED(selFlags) )
+bool wxPropertyGrid::SendEvent( int eventType, wxPGProperty* p,
+ wxVariant* pValue,
+ unsigned int selFlags,
+ unsigned int column )
{
// Send property grid event of specific type and with specific property
wxPropertyGridEvent evt( eventType, m_eventObject->GetId() );
evt.SetPropertyGrid(this);
evt.SetEventObject(m_eventObject);
evt.SetProperty(p);
+ evt.SetColumn(column);
if ( pValue )
{
evt.SetCanVeto(true);
evt.SetupValidationInfo();
m_validationInfo.m_pValue = pValue;
}
+ else if ( !(selFlags & wxPG_SEL_NOVALIDATE) )
+ {
+ evt.SetCanVeto(true);
+ }
+
wxEvtHandler* evtHandler = m_eventObject->GetEventHandler();
evtHandler->ProcessEvent(evt);
)
)
{
- if ( !AddToSelectionFromInputEvent( p, &event ) )
+ if ( !AddToSelectionFromInputEvent( p,
+ columnHit,
+ &event ) )
return res;
// On double-click, expand/collapse.
m_iFlags |= wxPG_FL_ACTIVATION_BY_CLICK;
selFlag = wxPG_SEL_FOCUS;
}
- if ( !AddToSelectionFromInputEvent( p, &event, selFlag ) )
+ if ( !AddToSelectionFromInputEvent( p,
+ columnHit,
+ &event,
+ selFlag ) )
return res;
m_iFlags &= ~(wxPG_FL_ACTIVATION_BY_CLICK);
}
else if ( m_dragStatus == 0 )
{
- //
- // Begin draggin the splitter
- //
+ //
+ // Begin draggin the splitter
+ //
+
+ // send event
+ DoEndLabelEdit(true, wxPG_SEL_NOVALIDATE);
+
if ( m_wndEditor )
{
// Changes must be committed here or the
{
// Select property here as well
wxPGProperty* p = m_propHover;
- AddToSelectionFromInputEvent(p, &event);
+ AddToSelectionFromInputEvent(p, m_colHover, &event);
// Send right click event.
SendEvent( wxEVT_PG_RIGHT_CLICK, p );
// Select property here as well
wxPGProperty* p = m_propHover;
- AddToSelectionFromInputEvent(p, &event);
+ AddToSelectionFromInputEvent(p, m_colHover, &event);
// Send double-click event.
SendEvent( wxEVT_PG_DOUBLE_CLICK, m_propHover );
int columnHit = state->HitTestH( x, &splitterHit, &splitterHitOffset );
int splitterX = x - splitterHitOffset;
+ m_colHover = columnHit;
+
if ( m_dragStatus > 0 )
{
if ( x > (m_marginWidth + wxPG_DRAG_MARGIN) &&
wxDEFINE_EVENT( wxEVT_PG_ITEM_EXPANDED, wxPropertyGridEvent );
wxDEFINE_EVENT( wxEVT_PG_ITEM_COLLAPSED, wxPropertyGridEvent );
wxDEFINE_EVENT( wxEVT_PG_DOUBLE_CLICK, wxPropertyGridEvent );
-
+wxDEFINE_EVENT( wxEVT_PG_LABEL_EDIT_BEGIN, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_LABEL_EDIT_ENDING, wxPropertyGridEvent );
// -----------------------------------------------------------------------
void wxPropertyGridEvent::Init()
{
m_validationInfo = NULL;
+ m_column = 1;
m_canVeto = false;
m_wasVetoed = false;
}
bool wxPropertyGridInterface::ClearSelection( bool validation )
{
- return DoClearSelection(validation, wxPG_SEL_DONT_SEND_EVENT);
+ bool res = DoClearSelection(validation, wxPG_SEL_DONT_SEND_EVENT);
+ GetPropertyGrid()->Refresh();
+ return res;
}
// -----------------------------------------------------------------------
m_colWidths.push_back( wxPG_DEFAULT_SPLITTERX );
m_colWidths.push_back( wxPG_DEFAULT_SPLITTERX );
m_fSplitterX = wxPG_DEFAULT_SPLITTERX;
+
+ // By default, we only have the 'value' column editable
+ m_editableColumns.push_back(1);
}
// -----------------------------------------------------------------------