Added label editing capability into wxPropertyGrid

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61743 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Jaakko Salli 2009-08-23 15:31:03 +00:00
parent 7a34307e24
commit 58935d4a5c
13 changed files with 548 additions and 62 deletions

View File

@ -1561,10 +1561,25 @@ public:
/**
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.
*/
@ -2242,6 +2257,13 @@ protected:
/** 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 );

View File

@ -448,22 +448,23 @@ enum wxPG_KEYBOARD_ACTIONS
// 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
// -----------------------------------------------------------------------
@ -583,6 +584,14 @@ enum wxPG_KEYBOARD_ACTIONS
@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
@ -1000,6 +1009,57 @@ public:
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);
@ -1199,6 +1259,7 @@ public:
shown).
*/
void FixPosForTextCtrl( wxWindow* ctrl,
unsigned int forColumn = 1,
const wxPoint& offset = wxPoint(0, 0) );
/** Shortcut for creating text editor widget.
@ -1222,7 +1283,8 @@ public:
const wxString& value,
wxWindow* secondary,
int extraStyle = 0,
int maxLen = 0 );
int maxLen = 0,
unsigned int forColumn = 1 );
/* Generates both textctrl and button.
*/
@ -1677,9 +1739,18 @@ protected:
/** 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;
@ -1701,8 +1772,9 @@ protected:
// 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;
@ -1804,6 +1876,7 @@ protected:
protected:
bool AddToSelectionFromInputEvent( wxPGProperty* prop,
unsigned int colIndex,
wxMouseEvent* event = NULL,
int selFlags = 0 );
@ -1858,6 +1931,13 @@ protected:
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 );
@ -1867,6 +1947,11 @@ protected:
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,
@ -1874,6 +1959,7 @@ protected:
int splitterIndex = 0,
bool allPages = false );
void DestroyEditorWnd( wxWindow* wnd );
void FreeEditors();
virtual bool DoExpand( wxPGProperty* p, bool sendEvent = false );
@ -1900,10 +1986,11 @@ protected:
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();
@ -1980,6 +2067,10 @@ wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_PROPGRID, wxEVT_PG_PAGE_CHANGED, wxPropert
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 {
@ -1991,7 +2082,9 @@ wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_PROPGRID, wxEVT_PG_DOUBLE_CLICK, wxPropert
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
@ -2012,6 +2105,8 @@ typedef void (wxEvtHandler::*wxPropertyGridEventFunction)(wxPropertyGridEvent&);
#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 )
@ -2043,6 +2138,14 @@ public:
/** 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);
@ -2114,6 +2217,11 @@ public:
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; }
@ -2137,6 +2245,8 @@ private:
wxPropertyGrid* m_pg;
wxPGValidationInfo* m_validationInfo;
unsigned int m_column;
bool m_canVeto;
bool m_wasVetoed;

View File

@ -1287,6 +1287,9 @@ public:
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:

View File

@ -668,6 +668,9 @@ 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. */

View File

@ -1028,9 +1028,23 @@ public:
/**
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.
*/

View File

@ -359,6 +359,14 @@ typedef int (*wxPGSortCallback)(wxPropertyGrid* propGrid,
@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
@ -430,6 +438,21 @@ public:
*/
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
@ -491,6 +514,17 @@ public:
*/
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.
@ -515,6 +549,11 @@ public:
*/
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.
@ -696,6 +735,13 @@ public:
*/
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()

View File

@ -687,7 +687,8 @@ enum
ID_SELECTSTYLE,
ID_SAVESTATE,
ID_RESTORESTATE,
ID_RUNMINIMAL
ID_RUNMINIMAL,
ID_ENABLELABELEDITING
};
// -----------------------------------------------------------------------
@ -713,6 +714,12 @@ BEGIN_EVENT_TABLE(FormMain, wxFrame)
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 )
@ -745,6 +752,7 @@ BEGIN_EVENT_TABLE(FormMain, wxFrame)
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 )
@ -1018,6 +1026,22 @@ void FormMain::OnPropertyGridPageChange( wxPropertyGridEvent& WXUNUSED(event) )
// -----------------------------------------------------------------------
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) )
{
}
@ -2219,6 +2243,8 @@ FormMain::FormMain(const wxString& title, const wxPoint& pos, const wxSize& size
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") );
@ -2762,6 +2788,13 @@ void FormMain::OnFreezeClick( wxCommandEvent& event )
// -----------------------------------------------------------------------
void FormMain::OnEnableLabelEditing( wxCommandEvent& WXUNUSED(event) )
{
m_propGrid->MakeColumnEditable(0);
}
// -----------------------------------------------------------------------
void FormMain::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxString msg;

View File

@ -184,6 +184,7 @@ public:
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 );
@ -230,6 +231,8 @@ public:
void OnPropertyGridKeyEvent( wxKeyEvent& event );
void OnPropertyGridItemCollapse( wxPropertyGridEvent& event );
void OnPropertyGridItemExpand( wxPropertyGridEvent& event );
void OnPropertyGridLabelEditBegin( wxPropertyGridEvent& event );
void OnPropertyGridLabelEditEnding( wxPropertyGridEvent& event );
void OnAbout( wxCommandEvent& event );

View File

@ -1603,7 +1603,9 @@ void wxPropertyGrid::CorrectEditorWidgetPosY()
// 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();
@ -1616,7 +1618,10 @@ void wxPropertyGrid::FixPosForTextCtrl( wxWindow* ctrl, const wxPoint& offset )
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;
@ -1634,7 +1639,8 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos,
const wxString& value,
wxWindow* secondary,
int extraStyle,
int maxLen )
int maxLen,
unsigned int forColumn )
{
wxWindowID id = wxPG_SUBID1;
wxPGProperty* prop = GetSelection();
@ -1653,6 +1659,10 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos,
s.x -= 8;
#endif
// For label editors, trim the size to allow better splitter grabbing
if ( forColumn != 1 )
s.x -= 2;
// Take button into acccount
if ( secondary )
{
@ -1681,7 +1691,13 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos,
// 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();

View File

@ -1511,7 +1511,7 @@ const wxPGCell& wxPGProperty::GetCell( unsigned int column ) const
return pg->GetPropertyDefaultCell();
}
wxPGCell& wxPGProperty::GetCell( unsigned int column )
wxPGCell& wxPGProperty::GetOrCreateCell( unsigned int column )
{
EnsureCells(column);
return m_cells[column];

View File

@ -428,8 +428,11 @@ void wxPropertyGrid::Init1()
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;
@ -759,12 +762,10 @@ bool wxPropertyGrid::DoAddToSelection( wxPGProperty* prop, int selFlags )
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;
@ -785,7 +786,7 @@ bool wxPropertyGrid::DoRemoveFromSelection( wxPGProperty* prop, int selFlags )
else
{
m_pState->DoRemoveFromSelection(prop);
RefreshProperty(prop);
DrawItem(prop);
res = true;
}
@ -794,7 +795,53 @@ bool wxPropertyGrid::DoRemoveFromSelection( wxPGProperty* prop, int selFlags )
// -----------------------------------------------------------------------
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 )
{
@ -813,7 +860,7 @@ bool wxPropertyGrid::AddToSelectionFromInputEvent( wxPGProperty* prop,
// disturbing the selection.
if ( GetSelectedProperties().size() <= 1 ||
!alreadySelected )
return DoSelectProperty(prop, selFlags);
return DoSelectAndEdit(prop, colIndex, selFlags);
return true;
}
else
@ -844,7 +891,7 @@ bool wxPropertyGrid::AddToSelectionFromInputEvent( wxPGProperty* prop,
}
else
{
res = DoSelectProperty(prop, selFlags);
res = DoSelectAndEdit(prop, colIndex, selFlags);
}
return res;
@ -875,6 +922,143 @@ void wxPropertyGrid::DoSetSelection( const wxArrayPGProperty& newSelection,
// -----------------------------------------------------------------------
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 )
@ -2074,28 +2258,36 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
{
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
{
@ -2128,7 +2320,7 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
cellRect.width -= textXAdd;
// Foreground
if ( !ctrlCell )
if ( !cellEditor )
{
wxPGCellRenderer* renderer;
int cmnVal = p->GetCommonValue();
@ -2732,7 +2924,8 @@ bool wxPropertyGrid::PerformValidation( wxPGProperty* p, wxVariant& pendingValue
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;
}
@ -2974,12 +3167,12 @@ bool wxPropertyGrid::DoPropertyChanged( wxPGProperty* p, unsigned int selFlags )
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;
@ -3375,6 +3568,17 @@ void wxPropertyGrid::SetupChildEventHandling( wxWindow* argWnd )
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()
{
//
@ -3402,7 +3606,7 @@ 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;
}
@ -3411,7 +3615,7 @@ void wxPropertyGrid::FreeEditors()
wxEvtHandler* handler = m_wndEditor->PopEventHandler(false);
m_wndEditor->Hide();
wxPendingDelete.Append( handler );
wxPendingDelete.Append( m_wndEditor );
DestroyEditorWnd(m_wndEditor);
m_wndEditor = NULL;
}
}
@ -3453,6 +3657,9 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
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() );
@ -3470,7 +3677,6 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
{
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
@ -3528,10 +3734,6 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
}
FreeEditors();
m_selColumn = -1;
// We need to always fully refresh the grid here
Refresh(false);
m_iFlags &= ~(wxPG_FL_ABNORMAL_EDITOR);
EditorsValueWasNotModified();
@ -3541,6 +3743,12 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
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 )
@ -3731,7 +3939,8 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
m_wndEditor->Show(true);
}
DrawItems(p, p);
if ( !(flags & wxPG_SEL_NO_REFRESH) )
DrawItem(p);
}
else
{
@ -3791,7 +4000,7 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
// 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;
}
@ -4137,19 +4346,28 @@ void wxPropertyGrid::SetFocusOnCanvas()
// 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);
@ -4202,7 +4420,9 @@ bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &even
)
)
{
if ( !AddToSelectionFromInputEvent( p, &event ) )
if ( !AddToSelectionFromInputEvent( p,
columnHit,
&event ) )
return res;
// On double-click, expand/collapse.
@ -4222,7 +4442,10 @@ bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &even
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);
@ -4253,6 +4476,10 @@ bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &even
//
// Begin draggin the splitter
//
// send event
DoEndLabelEdit(true, wxPG_SEL_NOVALIDATE);
if ( m_wndEditor )
{
// Changes must be committed here or the
@ -4321,7 +4548,7 @@ bool wxPropertyGrid::HandleMouseRightClick( int WXUNUSED(x),
{
// 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 );
@ -4342,7 +4569,7 @@ bool wxPropertyGrid::HandleMouseDoubleClick( int WXUNUSED(x),
// 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 );
@ -4392,6 +4619,8 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event
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) &&
@ -5523,13 +5752,15 @@ wxDEFINE_EVENT( wxEVT_PG_PAGE_CHANGED, wxPropertyGridEvent );
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;
}

View File

@ -216,7 +216,9 @@ wxPGProperty* wxPropertyGridInterface::GetSelection() const
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;
}
// -----------------------------------------------------------------------

View File

@ -215,6 +215,9 @@ wxPropertyGridPageState::wxPropertyGridPageState()
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);
}
// -----------------------------------------------------------------------