Added multiple selection feature to wxPropertyGrid (enabled by setting wxPG_EX_MULTIPLE_SELECTION style)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61681 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Jaakko Salli
2009-08-17 18:36:00 +00:00
parent 17a5460272
commit fc72fab6c6
15 changed files with 663 additions and 197 deletions

View File

@@ -491,6 +491,12 @@ public:
*/
bool IsPageModified( size_t index ) const;
/**
Returns true if property is selected. Since selection is page
based, this function checks every page in the manager.
*/
virtual bool IsPropertySelected( wxPGPropArg id ) const;
virtual void Refresh( bool eraseBackground = true,
const wxRect* rect = (const wxRect*) NULL );

View File

@@ -435,7 +435,11 @@ wxPG_PROP_CLASS_SPECIFIC_1 = 0x00080000,
/** Indicates the bit useable by derived properties.
*/
wxPG_PROP_CLASS_SPECIFIC_2 = 0x00100000
wxPG_PROP_CLASS_SPECIFIC_2 = 0x00100000,
/** Indicates that the property is being deleted and should be ignored.
*/
wxPG_PROP_BEING_DELETED = 0x00200000
};

View File

@@ -247,7 +247,20 @@ wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES = 0x00400000,
/** Hides page selection buttons from toolbar.
*/
wxPG_EX_HIDE_PAGE_BUTTONS = 0x01000000
wxPG_EX_HIDE_PAGE_BUTTONS = 0x01000000,
/** Allows multiple properties to be selected by user (by pressing SHIFT
when clicking on a property, or by dragging with left mouse button
down).
You can get array of selected properties with
wxPropertyGridInterface::GetSelectedProperties(). In multiple selection
mode wxPropertyGridInterface::GetSelection() returns
property which has editor active (usually the first one
selected). Other useful member functions are ClearSelection(),
AddToSelection() and RemoveFromSelection().
*/
wxPG_EX_MULTIPLE_SELECTION = 0x02000000
};
@@ -839,12 +852,6 @@ public:
/** Returns currently selected property. */
wxPGProperty* GetSelectedProperty() const { return GetSelection(); }
/** Returns currently selected property. */
wxPGProperty* GetSelection() const
{
return m_selected;
}
/** Returns current selection background colour. */
wxColour GetSelectionBackgroundColour() const { return m_colSelBack; }
@@ -953,10 +960,46 @@ public:
wxEVT_PG_SELECTED. In wxWidgets 2.9 and later, it no longer
does that.
@see wxPropertyGrid::Unselect
@remarks This clears any previous selection.
*/
bool SelectProperty( wxPGPropArg id, bool focus = false );
/**
Set entire new selection from given list of properties.
*/
void SetSelection( const wxArrayPGProperty& newSelection )
{
DoSetSelection( newSelection, wxPG_SEL_DONT_SEND_EVENT );
}
/**
Adds given property into selection. If wxPG_EX_MULTIPLE_SELECTION
extra style is not used, then this has same effect as
calling SelectProperty().
@remarks Multiple selection is not supported for categories. This
means that if you have properties selected, you cannot
add category to selection, and also if you have category
selected, you cannot add other properties to selection.
This member function will fail silently in these cases,
even returning true.
*/
bool AddToSelection( wxPGPropArg id )
{
wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
return DoAddToSelection(p, wxPG_SEL_DONT_SEND_EVENT);
}
/**
Removes given property from selection. If property is not selected,
an assertion failure will occur.
*/
bool RemoveFromSelection( wxPGPropArg id )
{
wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
return DoRemoveFromSelection(p, wxPG_SEL_DONT_SEND_EVENT);
}
/** Sets category caption background colour. */
void SetCaptionBackgroundColour(const wxColour& col);
@@ -1443,7 +1486,6 @@ public:
//
// Public methods for semi-public use
// (not protected for optimization)
//
bool DoSelectProperty( wxPGProperty* p, unsigned int flags = 0 );
@@ -1635,12 +1677,6 @@ protected:
/** When drawing next time, clear this many item slots at the end. */
int m_clearThisMany;
/** Pointer to selected property. Note that this is duplicated in
m_state for better transiency between pages so that the selected
item can be retained.
*/
wxPGProperty* m_selected;
// pointer to property that has mouse hovering
wxPGProperty* m_propHover;
@@ -1767,6 +1803,10 @@ protected:
protected:
bool AddToSelectionFromInputEvent( wxPGProperty* prop,
wxMouseEvent* event = NULL,
int selFlags = 0 );
/**
Adjust the centering of the bitmap icons (collapse / expand) when the
caption font changes.
@@ -1786,14 +1826,6 @@ protected:
*/
void CorrectEditorWidgetPosY();
/** Deselect current selection, if any. Returns true if success
(ie. validator did not intercept).
Unlike ClearSelection(), DoClearSelection() sends the
wxEVT_PG_SELECTED event.
*/
bool DoClearSelection();
int DoDrawItems( wxDC& dc,
const wxRect* clipRect,
bool isBuffered ) const;
@@ -1826,6 +1858,15 @@ protected:
bool DoEditorValidate();
void DoSetSelection( const wxArrayPGProperty& newSelection,
int selFlags = 0 );
bool DoAddToSelection( wxPGProperty* prop,
int selFlags = 0 );
bool DoRemoveFromSelection( wxPGProperty* prop,
int selFlags = 0 );
wxPGProperty* DoGetItemAtY( int y ) const;
void DoSetSplitterPosition_( int newxpos,

View File

@@ -591,10 +591,23 @@ public:
}
#endif
/** Returns currently selected property. */
wxPGProperty* GetSelection() const
/**
Returns currently selected property. NULL if none.
@remarks When wxPG_EX_MULTIPLE_SELECTION extra style is used, this
member function returns the focused property, that is the
one which can have active editor.
*/
wxPGProperty* GetSelection() const;
/**
Returns list of currently selected properties.
@remarks wxArrayPGProperty should be compatible with std::vector API.
*/
const wxArrayPGProperty& GetSelectedProperties() const
{
return m_pState->GetSelection();
return m_pState->m_selection;
}
#ifndef SWIG
@@ -724,6 +737,15 @@ public:
return ( (p->GetFlags() & wxPG_PROP_MODIFIED) ? true : false );
}
/**
Returns true if property is selected.
*/
bool IsPropertySelected( wxPGPropArg id ) const
{
wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
return m_pState->DoIsPropertySelected(p);
}
/**
Returns true if property is shown (ie hideproperty with true not
called for it).
@@ -1269,6 +1291,9 @@ public:
protected:
bool DoClearSelection( bool validation = false,
int selFlags = 0 );
/**
In derived class, implement to set editable state component with
given name to given value.

View File

@@ -475,11 +475,6 @@ public:
return (unsigned int) m_colWidths.size();
}
wxPGProperty* GetSelection() const
{
return m_selected;
}
int GetColumnMinWidth( int column ) const;
int GetColumnWidth( unsigned int column ) const
@@ -500,6 +495,28 @@ public:
return ((wxPropertyGridPageState*)this)->GetLastItem(flags);
}
/**
Returns currently selected property.
*/
wxPGProperty* GetSelection() const
{
if ( m_selection.size() == 0 )
return NULL;
return m_selection[0];
}
void DoSetSelection( wxPGProperty* prop )
{
m_selection.clear();
if ( prop )
m_selection.push_back(prop);
}
bool DoClearSelection()
{
return DoSelectProperty(NULL);
}
wxPropertyCategory* GetPropertyCategory( const wxPGProperty* p ) const;
wxPGProperty* GetPropertyByLabel( const wxString& name,
@@ -590,8 +607,6 @@ public:
bool PrepareAfterItemsAdded();
void SetSelection( wxPGProperty* p ) { m_selected = p; }
/** Called after virtual height needs to be recalculated.
*/
void VirtualHeightChanged()
@@ -605,14 +620,11 @@ public:
/** Returns property by its name. */
wxPGProperty* BaseGetPropertyByName( const wxString& name ) const;
void DoClearSelection()
{
m_selected = NULL;
}
/** Called in, for example, wxPropertyGrid::Clear. */
void DoClear();
bool DoIsPropertySelected( wxPGProperty* prop ) const;
bool DoCollapse( wxPGProperty* p );
bool DoExpand( wxPGProperty* p );
@@ -659,8 +671,8 @@ protected:
/** Most recently added category. */
wxPropertyCategory* m_currentCategory;
/** Pointer to selected property. */
wxPGProperty* m_selected;
/** Array of selected property. */
wxArrayPGProperty m_selection;
/** Virtual width. */
int m_width;

View File

@@ -388,6 +388,12 @@ public:
*/
bool IsPageModified( size_t index ) const;
/**
Returns true if property is selected. Since selection is page
based, this function checks every page in the manager.
*/
virtual bool IsPropertySelected( wxPGPropArg id ) const;
/**
Removes a page.

View File

@@ -152,7 +152,20 @@ wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES = 0x00400000,
/**
Hides page selection buttons from tool bar.
*/
wxPG_EX_HIDE_PAGE_BUTTONS = 0x01000000
wxPG_EX_HIDE_PAGE_BUTTONS = 0x01000000,
/** Allows multiple properties to be selected by user (by pressing SHIFT
when clicking on a property, or by dragging with left mouse button
down).
You can get array of selected properties with
wxPropertyGridInterface::GetSelectedProperties(). In multiple selection
mode wxPropertyGridInterface::GetSelection() returns
property which has editor active (usually the first one
selected). Other useful member functions are ClearSelection(),
AddToSelection() and RemoveFromSelection().
*/
wxPG_EX_MULTIPLE_SELECTION = 0x02000000
};
@@ -394,6 +407,20 @@ public:
*/
void AddActionTrigger( int action, int keycode, int modifiers = 0 );
/**
Adds given property into selection. If wxPG_EX_MULTIPLE_SELECTION
extra style is not used, then this has same effect as
calling SelectProperty().
@remarks Multiple selection is not supported for categories. This
means that if you have properties selected, you cannot
add category to selection, and also if you have category
selected, you cannot add other properties to selection.
This member function will fail silently in these cases,
even returning true.
*/
bool AddToSelection( wxPGPropArg id );
/**
This static function enables or disables automatic use of
wxGetTranslation() for following strings: wxEnumProperty list labels,
@@ -708,6 +735,12 @@ public:
*/
void ResetColours();
/**
Removes given property from selection. If property is not selected,
an assertion failure will occur.
*/
bool RemoveFromSelection( wxPGPropArg id );
/**
Selects a property. Editor widget is automatically created, but
not focused unless focus is true.
@@ -725,6 +758,8 @@ public:
wxEVT_PG_SELECTED. In wxWidgets 2.9 and later, it no longer
does that.
@remarks This clears any previous selection.
@see wxPropertyGridInterface::ClearSelection()
*/
bool SelectProperty( wxPGPropArg id, bool focus = false );
@@ -790,6 +825,11 @@ public:
*/
void SetMarginColour(const wxColour& col);
/**
Set entire new selection from given list of properties.
*/
void SetSelection( const wxArrayPGProperty& newSelection );
/**
Sets selection background colour - applies to selected property name
background.

View File

@@ -418,7 +418,20 @@ public:
wxVariant GetPropertyValues( const wxString& listname = wxEmptyString,
wxPGProperty* baseparent = NULL, long flags = 0 ) const;
/** Returns currently selected property. */
/**
Returns list of currently selected properties.
@remarks wxArrayPGProperty should be compatible with std::vector API.
*/
const wxArrayPGProperty& GetSelectedProperties() const;
/**
Returns currently selected property. NULL if none.
@remarks When wxPG_EX_MULTIPLE_SELECTION extra style is used, this
member function returns the focused property, that is the
one which can have active editor.
*/
wxPGProperty* GetSelection() const;
/**
@@ -538,6 +551,11 @@ public:
*/
bool IsPropertyModified( wxPGPropArg id ) const;
/**
Returns true if property is selected.
*/
virtual bool IsPropertySelected( wxPGPropArg id ) const;
/**
Returns @true if property is shown (ie. HideProperty() with @true not
called for it).

View File

@@ -2045,7 +2045,8 @@ void FormMain::CreateGrid( int style, int extraStyle )
if ( extraStyle == -1 )
// default extra style
extraStyle = wxPG_EX_MODE_BUTTONS;
extraStyle = wxPG_EX_MODE_BUTTONS |
wxPG_EX_MULTIPLE_SELECTION;
//| wxPG_EX_AUTO_UNSPECIFIED_VALUES
//| wxPG_EX_GREY_LABEL_WHEN_DISABLED
//| wxPG_EX_NATIVE_DOUBLE_BUFFERING
@@ -2140,7 +2141,8 @@ FormMain::FormMain(const wxString& title, const wxPoint& pos, const wxSize& size
wxPG_TOOLBAR |
wxPG_DESCRIPTION,
// extra style
wxPG_EX_MODE_BUTTONS
wxPG_EX_MODE_BUTTONS |
wxPG_EX_MULTIPLE_SELECTION
//| wxPG_EX_AUTO_UNSPECIFIED_VALUES
//| wxPG_EX_GREY_LABEL_WHEN_DISABLED
//| wxPG_EX_NATIVE_DOUBLE_BUFFERING
@@ -2928,6 +2930,8 @@ void FormMain::OnSelectStyle( wxCommandEvent& WXUNUSED(event) )
ADD_FLAG(wxPG_EX_NATIVE_DOUBLE_BUFFERING)
ADD_FLAG(wxPG_EX_AUTO_UNSPECIFIED_VALUES)
ADD_FLAG(wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES)
ADD_FLAG(wxPG_EX_HIDE_PAGE_BUTTONS)
ADD_FLAG(wxPG_EX_MULTIPLE_SELECTION)
wxMultiChoiceDialog dlg( this, wxT("Select extra window styles to use"),
wxT("wxPropertyGrid Extra Style"), chs );
dlg.SetSelections(sel);

View File

@@ -249,6 +249,10 @@ protected:
failures++; \
}
#define RT_ASSERT(COND) \
if (!(COND)) \
RT_FAILURE()
#define RT_FAILURE_MSG(MSG) \
{ \
wxString s1 = wxString::Format(wxT("Test failure in tests.cpp, line %i."),__LINE__-1); \
@@ -714,6 +718,63 @@ bool FormMain::RunTests( bool fullTest, bool interactive )
#endif
}
{
//
// Test multiple selection
RT_START_TEST(MULTIPLE_SELECTION)
if ( !(pgman->GetExtraStyle() & wxPG_EX_MULTIPLE_SELECTION) )
CreateGrid( -1, wxPG_EX_MULTIPLE_SELECTION);
pgman = m_pPropGridManager;
wxPropertyGrid* pg = pgman->GetGrid();
wxPGProperty* prop1 = pg->GetProperty(wxT("Label"));
wxPGProperty* prop2 = pg->GetProperty(wxT("Cell Text Colour"));
wxPGProperty* prop3 = pg->GetProperty(wxT("Height"));
wxPGProperty* catProp = pg->GetProperty(wxT("Appearance"));
RT_ASSERT( prop1 && prop2 && prop3 );
pg->ClearSelection();
pg->AddToSelection(prop1);
pg->AddToSelection(prop2);
pg->AddToSelection(prop3);
// Adding category to selection should fail silently
pg->AddToSelection(catProp);
wxArrayPGProperty selectedProperties = pg->GetSelectedProperties();
RT_ASSERT( selectedProperties.size() == 3 )
RT_ASSERT( pg->IsPropertySelected(prop1) )
RT_ASSERT( pg->IsPropertySelected(prop2) )
RT_ASSERT( pg->IsPropertySelected(prop3) )
RT_ASSERT( !pg->IsPropertySelected(catProp) )
pg->RemoveFromSelection(prop1);
wxArrayPGProperty selectedProperties2 = pg->GetSelectedProperties();
RT_ASSERT( selectedProperties2.size() == 2 )
RT_ASSERT( !pg->IsPropertySelected(prop1) )
RT_ASSERT( pg->IsPropertySelected(prop2) )
RT_ASSERT( pg->IsPropertySelected(prop3) )
pg->ClearSelection();
wxArrayPGProperty selectedProperties3 = pg->GetSelectedProperties();
RT_ASSERT( selectedProperties3.size() == 0 )
RT_ASSERT( !pg->IsPropertySelected(prop1) )
RT_ASSERT( !pg->IsPropertySelected(prop2) )
RT_ASSERT( !pg->IsPropertySelected(prop3) )
pg->SelectProperty(prop2);
RT_ASSERT( !pg->IsPropertySelected(prop1) )
RT_ASSERT( pg->IsPropertySelected(prop2) )
RT_ASSERT( !pg->IsPropertySelected(prop3) )
}
{
RT_START_TEST(Attributes)
@@ -985,8 +1046,7 @@ bool FormMain::RunTests( bool fullTest, bool interactive )
pgman = m_pPropGridManager;
}
/*
{
/*{
// TODO: This test fails.
RT_START_TEST(SetSplitterPosition)
@@ -1023,8 +1083,7 @@ bool FormMain::RunTests( bool fullTest, bool interactive )
// Recreate the original grid
CreateGrid( -1, -1 );
pgman = m_pPropGridManager;
}
*/
}*/
{
RT_START_TEST(HideProperty)
@@ -1178,7 +1237,7 @@ bool FormMain::RunTests( bool fullTest, bool interactive )
wxASSERT(wxPG_EX_INIT_NOCAT == 0x00001000);
for ( i=12; i<24; i++ )
for ( i=12; i<26; i++ )
{
int flag = 1<<i;
RT_MSG(wxString::Format(wxT("ExStyle: 0x%X"),flag));

View File

@@ -608,7 +608,7 @@ void wxPropertyGrid::OnComboItemPaint( const wxPGComboBox* pCb,
// Sanity check
wxASSERT( IsKindOf(CLASSINFO(wxPropertyGrid)) );
wxPGProperty* p = m_selected;
wxPGProperty* p = GetSelection();
wxString text;
const wxPGChoices& choices = p->GetChoices();
@@ -1576,9 +1576,9 @@ void wxPropertyGrid::CorrectEditorWidgetPosY()
if ( m_selColumn == -1 )
return;
if ( m_selected && (m_wndEditor || m_wndEditor2) )
if ( GetSelection() && (m_wndEditor || m_wndEditor2) )
{
wxRect r = GetEditorWidgetRect(m_selected, m_selColumn);
wxRect r = GetEditorWidgetRect(GetSelection(), m_selColumn);
if ( m_wndEditor )
{
@@ -1637,7 +1637,7 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos,
int maxLen )
{
wxWindowID id = wxPG_SUBID1;
wxPGProperty* prop = m_selected;
wxPGProperty* prop = GetSelection();
wxASSERT(prop);
int tcFlags = wxTE_PROCESS_ENTER | extraStyle;
@@ -1708,7 +1708,7 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos,
wxWindow* wxPropertyGrid::GenerateEditorButton( const wxPoint& pos, const wxSize& sz )
{
wxWindowID id = wxPG_SUBID2;
wxPGProperty* selected = m_selected;
wxPGProperty* selected = GetSelection();
wxASSERT(selected);
#ifdef __WXMAC__

View File

@@ -423,8 +423,9 @@ wxPropertyGridManager::~wxPropertyGridManager()
{
END_MOUSE_CAPTURE
m_pPropGrid->DoSelectProperty(NULL);
m_pPropGrid->m_pState = NULL;
//m_pPropGrid->ClearSelection();
delete m_pPropGrid;
m_pPropGrid = NULL;
size_t i;
for ( i=0; i<m_arrPages.size(); i++ )
@@ -553,7 +554,7 @@ bool wxPropertyGridManager::DoSelectPage( int index )
if ( m_selPage == index )
return true;
if ( m_pPropGrid->m_selected )
if ( m_pPropGrid->GetSelection() )
{
if ( !m_pPropGrid->ClearSelection() )
return false;
@@ -883,6 +884,19 @@ bool wxPropertyGridManager::IsPageModified( size_t index ) const
// -----------------------------------------------------------------------
bool wxPropertyGridManager::IsPropertySelected( wxPGPropArg id ) const
{
wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
for ( unsigned int i=0; i<GetPageCount(); i++ )
{
if ( GetPageState(i)->DoIsPropertySelected(p) )
return true;
}
return false;
}
// -----------------------------------------------------------------------
wxPGProperty* wxPropertyGridManager::GetPageRoot( int index ) const
{
wxASSERT( index >= 0 );

View File

@@ -428,7 +428,6 @@ void wxPropertyGrid::Init1()
m_iFlags = 0;
m_pState = NULL;
m_wndEditor = m_wndEditor2 = NULL;
m_selected = NULL;
m_selColumn = -1;
m_propHover = NULL;
m_eventObject = this;
@@ -582,7 +581,7 @@ wxPropertyGrid::~wxPropertyGrid()
{
size_t i;
DoSelectProperty(NULL);
DoSelectProperty(NULL, wxPG_SEL_NOVALIDATE|wxPG_SEL_DONT_SEND_EVENT);
// This should do prevent things from going too badly wrong
m_iFlags &= ~(wxPG_FL_INITIALIZED);
@@ -603,8 +602,6 @@ wxPropertyGrid::~wxPropertyGrid()
delete m_doubleBuffer;
#endif
//m_selected = NULL;
if ( m_iFlags & wxPG_FL_CREATEDSTATE )
delete m_pState;
@@ -731,13 +728,153 @@ void wxPropertyGrid::Thaw()
#endif
// Force property re-selection
if ( m_selected )
DoSelectProperty(m_selected, wxPG_SEL_FORCE);
// NB: We must copy the selection.
wxArrayPGProperty selection = m_pState->m_selection;
DoSetSelection(selection, wxPG_SEL_FORCE);
}
}
// -----------------------------------------------------------------------
bool wxPropertyGrid::DoAddToSelection( wxPGProperty* prop, int selFlags )
{
wxCHECK( prop, false );
if ( !(GetExtraStyle() & wxPG_EX_MULTIPLE_SELECTION) )
return DoSelectProperty(prop, selFlags);
wxArrayPGProperty& selection = m_pState->m_selection;
if ( !selection.size() )
{
return DoSelectProperty(prop, selFlags);
}
else
{
// For categories, only one can be selected at a time
if ( prop->IsCategory() || selection[0]->IsCategory() )
return true;
selection.push_back(prop);
if ( !(selFlags & wxPG_SEL_DONT_SEND_EVENT) )
{
SendEvent( wxEVT_PG_SELECTED, prop, NULL, selFlags );
}
// For some reason, if we use RefreshProperty(prop) here,
// we may go into infinite drawing loop.
Refresh();
}
return true;
}
// -----------------------------------------------------------------------
bool wxPropertyGrid::DoRemoveFromSelection( wxPGProperty* prop, int selFlags )
{
wxCHECK( prop, false );
bool res;
wxArrayPGProperty& selection = m_pState->m_selection;
if ( selection.size() <= 1 )
{
res = DoSelectProperty(NULL, selFlags);
}
else
{
selection.Remove(prop);
RefreshProperty(prop);
res = true;
}
return res;
}
// -----------------------------------------------------------------------
bool wxPropertyGrid::AddToSelectionFromInputEvent( wxPGProperty* prop,
wxMouseEvent* mouseEvent,
int selFlags )
{
bool alreadySelected = m_pState->DoIsPropertySelected(prop);
bool res = true;
bool addToExistingSelection;
if ( GetExtraStyle() & wxPG_EX_MULTIPLE_SELECTION )
{
if ( mouseEvent )
{
if ( mouseEvent->GetEventType() == wxEVT_RIGHT_DOWN ||
mouseEvent->GetEventType() == wxEVT_RIGHT_UP )
{
// Allow right-click for context menu without
// disturbing the selection.
if ( GetSelectedProperties().size() <= 1 ||
!alreadySelected )
return DoSelectProperty(prop, selFlags);
return true;
}
else
{
addToExistingSelection = mouseEvent->ShiftDown();
}
}
else
{
addToExistingSelection = false;
}
}
else
{
addToExistingSelection = false;
}
if ( addToExistingSelection )
{
if ( !alreadySelected )
{
res = DoAddToSelection(prop, selFlags);
}
else if ( GetSelectedProperties().size() > 1 )
{
res = DoRemoveFromSelection(prop, selFlags);
}
}
else
{
res = DoSelectProperty(prop, selFlags);
}
return res;
}
// -----------------------------------------------------------------------
void wxPropertyGrid::DoSetSelection( const wxArrayPGProperty& newSelection,
int selFlags )
{
if ( newSelection.size() > 0 )
{
if ( !DoSelectProperty(newSelection[0], selFlags) )
return;
}
else
{
DoClearSelection(false, selFlags);
}
for ( unsigned int i = 1; i < newSelection.size(); i++ )
{
DoAddToSelection(newSelection[i], selFlags);
}
Refresh();
}
// -----------------------------------------------------------------------
void wxPropertyGrid::SetExtraStyle( long exStyle )
{
if ( exStyle & wxPG_EX_NATIVE_DOUBLE_BUFFERING )
@@ -1684,7 +1821,7 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
bool reallyFocused = (m_iFlags & wxPG_FL_FOCUSED) != 0;
bool isEnabled = IsEnabled();
bool isPgEnabled = IsEnabled();
//
// Prepare some pens and brushes that are often changed to.
@@ -1695,6 +1832,12 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
wxBrush capbgbrush(m_colCapBack,wxSOLID);
wxPen linepen(m_colLine,1,wxSOLID);
wxColour selBackCol;
if ( isPgEnabled )
selBackCol = m_colSelBack;
else
selBackCol = m_colMargin;
// pen that has same colour as text
wxPen outlinepen(m_colPropFore,1,wxSOLID);
@@ -1708,7 +1851,7 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
dc.DrawRectangle(-1-xRelMod,firstItemTopY-1,x+2,lastItemBottomY-firstItemTopY+2);
}
const wxPGProperty* selected = m_selected;
const wxPGProperty* firstSelected = GetSelection();
const wxPropertyGridPageState* state = m_pState;
#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
@@ -1808,7 +1951,9 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
wxColour rowFgCol;
wxColour rowBgCol;
if ( p != selected )
bool isSelected = state->DoIsPropertySelected(p);
if ( !isSelected )
{
// Disabled may get different colour.
if ( !p->IsEnabled() )
@@ -1820,6 +1965,11 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
}
else
{
#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
if ( p == firstSelected )
wasSelectedPainted = true;
#endif
renderFlags |= wxPGCellRenderer::Selected;
if ( !p->IsCategory() )
@@ -1827,25 +1977,23 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
renderFlags |= wxPGCellRenderer::DontUseCellFgCol |
wxPGCellRenderer::DontUseCellBgCol;
#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
wasSelectedPainted = true;
#endif
// Selected gets different colour.
if ( reallyFocused )
if ( reallyFocused && p == firstSelected )
{
rowFgCol = m_colSelFore;
rowBgCol = m_colSelBack;
rowBgCol = selBackCol;
}
else if ( isEnabled )
else if ( isPgEnabled )
{
rowFgCol = m_colPropFore;
if ( p == firstSelected )
rowBgCol = m_colMargin;
else
rowBgCol = selBackCol;
}
else
{
rowFgCol = m_colDisPropFore;
rowBgCol = m_colSelBack;
rowBgCol = selBackCol;
}
}
}
@@ -1934,18 +2082,33 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
DrawExpanderButton( dc, butRect, p );
// Background
if ( p == selected && m_wndEditor && ci == 1 )
if ( isSelected && ci == 1 )
{
wxColour editorBgCol = GetEditorControl()->GetBackgroundColour();
if ( p == firstSelected && m_wndEditor )
{
wxColour editorBgCol =
GetEditorControl()->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) )
if ( m_dragStatus == 0 &&
!(m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE) )
ctrlCell = true;
}
else
{
dc.SetBrush(m_colPropBack);
dc.SetPen(m_colPropBack);
dc.SetTextForeground(m_colDisPropFore);
if ( p->IsEnabled() )
dc.SetTextForeground(rowFgCol);
else
dc.SetTextForeground(m_colDisPropFore);
}
}
else
{
if ( renderFlags & wxPGCellRenderer::DontUseCellBgCol )
{
@@ -2038,7 +2201,7 @@ wxRect wxPropertyGrid::GetPropertyRect( const wxPGProperty* p1, const wxPGProper
// If seleced property is inside the range, we'll extend the range to include
// control's size.
wxPGProperty* selected = m_selected;
wxPGProperty* selected = GetSelection();
if ( selected )
{
int selectedY = selected->GetY();
@@ -2078,8 +2241,12 @@ void wxPropertyGrid::DrawItems( const wxPGProperty* p1, const wxPGProperty* p2 )
void wxPropertyGrid::RefreshProperty( wxPGProperty* p )
{
if ( p == m_selected )
DoSelectProperty(p, wxPG_SEL_FORCE);
if ( m_pState->DoIsPropertySelected(p) )
{
// NB: We must copy the selection.
wxArrayPGProperty selection = m_pState->m_selection;
DoSetSelection(selection, wxPG_SEL_FORCE);
}
DrawItemAndChildren(p);
}
@@ -2118,7 +2285,8 @@ void wxPropertyGrid::DrawItemAndChildren( wxPGProperty* p )
return;
// Update child control.
if ( m_selected && m_selected->GetParent() == p )
wxPGProperty* selected = GetSelection();
if ( selected && selected->GetParent() == p )
RefreshEditor();
const wxPGProperty* lastDrawn = p->GetLastVisibleSubItem();
@@ -2218,11 +2386,13 @@ void wxPropertyGrid::SwitchState( wxPropertyGridPageState* pNewState )
if ( pNewState == m_pState )
return;
wxPGProperty* oldSelection = m_selected;
wxArrayPGProperty oldSelection = m_pState->m_selection;
DoClearSelection();
// Call ClearSelection() instead of DoClearSelection()
// so that selection clear events are not sent.
ClearSelection();
m_pState->m_selected = oldSelection;
m_pState->m_selection = oldSelection;
bool orig_mode = m_pState->IsInNonCatMode();
bool new_state_mode = pNewState->IsInNonCatMode();
@@ -2263,9 +2433,9 @@ void wxPropertyGrid::SwitchState( wxPropertyGridPageState* pNewState )
// Refresh, if not frozen.
m_pState->PrepareAfterItemsAdded();
// Reselect
if ( m_pState->m_selected )
DoSelectProperty( m_pState->m_selected );
// Reselect (Use SetSelection() instead of Do-variant so that
// events won't be sent).
SetSelection(m_pState->m_selection);
RecalculateVirtualSize(0);
Refresh();
@@ -2289,7 +2459,7 @@ void wxPropertyGrid::DoSetSplitterPosition_( int newxpos, bool refresh, int spli
if ( refresh )
{
if ( m_selected )
if ( GetSelection() )
CorrectEditorWidgetSizeX();
Refresh();
@@ -2360,14 +2530,16 @@ bool wxPropertyGrid::CommitChangesFromEditor( wxUint32 flags )
return false;
}
wxPGProperty* selected = GetSelection();
if ( m_wndEditor &&
IsEditorsValueModified() &&
(m_iFlags & wxPG_FL_INITIALIZED) &&
m_selected )
selected )
{
m_inCommitChangesFromEditor = 1;
wxVariant variant(m_selected->GetValueRef());
wxVariant variant(selected->GetValueRef());
bool valueIsPending = false;
// JACS - necessary to avoid new focus being found spuriously within OnIdle
@@ -2380,10 +2552,13 @@ bool wxPropertyGrid::CommitChangesFromEditor( wxUint32 flags )
m_chgInfo_changedProperty = NULL;
// If truly modified, schedule value as pending.
if ( m_selected->GetEditorClass()->GetValueFromControl( variant, m_selected, GetEditorControl() ) )
if ( selected->GetEditorClass()->
GetValueFromControl( variant,
selected,
GetEditorControl() ) )
{
if ( DoEditorValidate() &&
PerformValidation(m_selected, variant) )
PerformValidation(selected, variant) )
{
valueIsPending = true;
}
@@ -2409,18 +2584,18 @@ bool wxPropertyGrid::CommitChangesFromEditor( wxUint32 flags )
m_curFocused = oldFocus;
}
res = OnValidationFailure(m_selected, variant);
res = OnValidationFailure(selected, variant);
// Now prevent further validation failure messages
if ( res )
{
EditorsValueWasNotModified();
OnValidationFailureReset(m_selected);
OnValidationFailureReset(selected);
}
}
else if ( valueIsPending )
{
DoPropertyChanged( m_selected, flags );
DoPropertyChanged( selected, flags );
EditorsValueWasNotModified();
}
@@ -2523,7 +2698,7 @@ bool wxPropertyGrid::PerformValidation( wxPGProperty* p, wxVariant& pendingValue
if ( evtChangingProperty->HasFlag(wxPG_PROP_COMPOSED_VALUE) )
{
if ( changedProperty == m_selected )
if ( changedProperty == GetSelection() )
{
wxWindow* editor = GetEditorControl();
wxASSERT( editor->IsKindOf(CLASSINFO(wxTextCtrl)) );
@@ -2617,7 +2792,7 @@ bool wxPropertyGrid::OnValidationFailure( wxPGProperty* property,
//
// For non-wxTextCtrl editors, we do need to revert the value
if ( !editor->IsKindOf(CLASSINFO(wxTextCtrl)) &&
property == m_selected )
property == GetSelection() )
{
property->GetEditorClass()->UpdateControl(property, editor);
}
@@ -2656,7 +2831,7 @@ bool wxPropertyGrid::DoOnValidationFailure( wxPGProperty* property, wxVariant& W
DrawItemAndChildren(property);
if ( property == m_selected )
if ( property == GetSelection() )
{
SetInternalFlag(wxPG_FL_CELL_OVERRIDES_SEL);
@@ -2695,7 +2870,7 @@ void wxPropertyGrid::DoOnValidationFailureReset( wxPGProperty* property )
ClearInternalFlag(wxPG_FL_CELL_OVERRIDES_SEL);
if ( property == m_selected && GetEditorControl() )
if ( property == GetSelection() && GetEditorControl() )
{
// Calling this will recreate the control, thus resetting its colour
RefreshProperty(property);
@@ -2716,6 +2891,7 @@ bool wxPropertyGrid::DoPropertyChanged( wxPGProperty* p, unsigned int selFlags )
return true;
wxWindow* editor = GetEditorControl();
wxPGProperty* selected = GetSelection();
m_pState->m_anyModified = 1;
@@ -2742,7 +2918,7 @@ bool wxPropertyGrid::DoPropertyChanged( wxPGProperty* p, unsigned int selFlags )
if ( !(p->m_flags & wxPG_PROP_MODIFIED) )
{
p->m_flags |= wxPG_PROP_MODIFIED;
if ( p == m_selected && (m_windowStyle & wxPG_BOLD_MODIFIED) )
if ( p == selected && (m_windowStyle & wxPG_BOLD_MODIFIED) )
{
if ( editor )
SetCurControlBoldFont();
@@ -2759,7 +2935,7 @@ bool wxPropertyGrid::DoPropertyChanged( wxPGProperty* p, unsigned int selFlags )
{
pwc->m_flags |= wxPG_PROP_MODIFIED;
if ( pwc == m_selected && (m_windowStyle & wxPG_BOLD_MODIFIED) )
if ( pwc == selected && (m_windowStyle & wxPG_BOLD_MODIFIED) )
{
if ( editor )
SetCurControlBoldFont();
@@ -2867,11 +3043,11 @@ bool wxPropertyGrid::DoEditorValidate()
void wxPropertyGrid::HandleCustomEditorEvent( wxEvent &event )
{
wxPGProperty* selected = m_selected;
wxPGProperty* selected = GetSelection();
// Somehow, event is handled after property has been deselected.
// Possibly, but very rare.
if ( !selected )
if ( !selected || selected->HasFlag(wxPG_PROP_BEING_DELETED) )
return;
if ( m_iFlags & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT )
@@ -2939,7 +3115,7 @@ void wxPropertyGrid::HandleCustomEditorEvent( wxEvent &event )
if ( DoEditorValidate() )
{
if ( editor->GetValueFromControl( pendingValue,
m_selected,
selected,
wnd ) )
valueIsPending = true;
}
@@ -2966,7 +3142,7 @@ void wxPropertyGrid::HandleCustomEditorEvent( wxEvent &event )
}
if ( !validationFailure && valueIsPending )
if ( !PerformValidation(m_selected, pendingValue) )
if ( !PerformValidation(selected, pendingValue) )
validationFailure = true;
if ( validationFailure)
@@ -3260,17 +3436,26 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
m_inDoSelectProperty = 1;
wxPGProperty* prev = m_selected;
if ( !m_pState )
{
m_inDoSelectProperty = 0;
return false;
}
wxArrayPGProperty prevSelection = m_pState->m_selection;
wxPGProperty* prevFirstSel;
if ( prevSelection.size() > 0 )
prevFirstSel = prevSelection[0];
else
prevFirstSel = NULL;
if ( prevFirstSel && prevFirstSel->HasFlag(wxPG_PROP_BEING_DELETED) )
prevFirstSel = NULL;
/*
if (m_selected)
wxPrintf( "Selected %s\n", m_selected->GetClassInfo()->GetClassName() );
if ( prevFirstSel )
wxPrintf( "Selected %s\n", prevFirstSel->GetClassInfo()->GetClassName() );
else
wxPrintf( "None selected\n" );
@@ -3285,9 +3470,8 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
{
m_iFlags &= ~(wxPG_FL_ABNORMAL_EDITOR);
m_editorFocused = 0;
m_selected = p;
m_selColumn = 1;
m_pState->m_selected = p;
m_pState->DoSetSelection(p);
// If frozen, always free controls. But don't worry, as Thaw will
// recall SelectProperty to recreate them.
@@ -3299,7 +3483,9 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
else
{
// Is it the same?
if ( m_selected == p && !(flags & wxPG_SEL_FORCE) )
if ( prevFirstSel == p &&
prevSelection.size() <= 1 &&
!(flags & wxPG_SEL_FORCE) )
{
// Only set focus if not deselecting
if ( p )
@@ -3324,13 +3510,12 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
//
// First, deactivate previous
if ( m_selected )
if ( prevFirstSel )
{
OnValidationFailureReset(m_selected);
OnValidationFailureReset(prevFirstSel);
// Must double-check if this is an selected in case of forceswitch
if ( p != prev )
if ( p != prevFirstSel )
{
if ( !CommitChangesFromEditor(flags) )
{
@@ -3345,9 +3530,6 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
FreeEditors();
m_selColumn = -1;
m_selected = NULL;
m_pState->m_selected = NULL;
// We need to always fully refresh the grid here
Refresh(false);
@@ -3357,6 +3539,8 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
SetInternalFlag(wxPG_FL_IN_SELECT_PROPERTY);
m_pState->DoSetSelection(p);
//
// Then, activate the one given.
if ( p )
@@ -3365,10 +3549,8 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
int splitterX = GetSplitterPosition();
m_editorFocused = 0;
m_selected = p;
m_pState->m_selected = p;
m_iFlags |= wxPG_FL_PRIMARY_FILLS_ENTIRE;
if ( p != prev )
if ( p != prevFirstSel )
m_iFlags &= ~(wxPG_FL_VALIDATION_FAILED);
wxASSERT( m_wndEditor == NULL );
@@ -3609,7 +3791,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, m_selected, NULL, flags );
SendEvent( wxEVT_PG_SELECTED, p, NULL, flags );
return true;
}
@@ -3618,14 +3800,16 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
bool wxPropertyGrid::UnfocusEditor()
{
if ( !m_selected || !m_wndEditor || m_frozen )
wxPGProperty* selected = GetSelection();
if ( !selected || !m_wndEditor || m_frozen )
return true;
if ( !CommitChangesFromEditor(0) )
return false;
SetFocusOnCanvas();
DrawItem(m_selected);
DrawItem(selected);
return true;
}
@@ -3634,7 +3818,7 @@ bool wxPropertyGrid::UnfocusEditor()
void wxPropertyGrid::RefreshEditor()
{
wxPGProperty* p = m_selected;
wxPGProperty* p = GetSelection();
if ( !p )
return;
@@ -3673,14 +3857,6 @@ bool wxPropertyGrid::SelectProperty( wxPGPropArg id, bool focus )
return DoSelectProperty(p, flags);
}
// -----------------------------------------------------------------------
bool wxPropertyGrid::DoClearSelection()
{
// Unlike ClearSelection(), here we send the wxEVT_PG_SELECTED event.
return DoSelectProperty(NULL, 0);
}
// -----------------------------------------------------------------------
// wxPropertyGrid expand/collapse state
// -----------------------------------------------------------------------
@@ -3688,9 +3864,10 @@ bool wxPropertyGrid::DoClearSelection()
bool wxPropertyGrid::DoCollapse( wxPGProperty* p, bool sendEvents )
{
wxPGProperty* pwc = wxStaticCast(p, wxPGProperty);
wxPGProperty* selected = GetSelection();
// If active editor was inside collapsed section, then disable it
if ( m_selected && m_selected->IsSomeParent(p) )
if ( selected && selected->IsSomeParent(p) )
{
DoClearSelection();
}
@@ -3773,11 +3950,17 @@ bool wxPropertyGrid::DoHideProperty( wxPGProperty* p, bool hide, int flags )
if ( m_frozen )
return m_pState->DoHideProperty(p, hide, flags);
if ( m_selected &&
( m_selected == p || m_selected->IsSomeParent(p) )
)
wxArrayPGProperty selection = m_pState->m_selection; // Must use a copy
int selRemoveCount = 0;
for ( unsigned int i=0; i<selection.size(); i++ )
{
DoClearSelection();
wxPGProperty* selected = selection[i];
if ( selected == p || selected->IsSomeParent(p) )
{
if ( !DoRemoveFromSelection(p, flags) )
return false;
selRemoveCount += 1;
}
}
m_pState->DoHideProperty(p, hide, flags);
@@ -3860,7 +4043,7 @@ void wxPropertyGrid::RecalculateVirtualSize( int forceXPos )
m_pState->CheckColumnWidths();
if ( m_selected )
if ( GetSelection() )
CorrectEditorWidgetSizeX();
m_iFlags &= ~wxPG_FL_RECALCULATING_VIRTUAL_SIZE;
@@ -4019,7 +4202,7 @@ bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &even
)
)
{
if ( !DoSelectProperty( p ) )
if ( !AddToSelectionFromInputEvent( p, &event ) )
return res;
// On double-click, expand/collapse.
@@ -4039,7 +4222,7 @@ bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &even
m_iFlags |= wxPG_FL_ACTIVATION_BY_CLICK;
selFlag = wxPG_SEL_FOCUS;
}
if ( !DoSelectProperty( p, selFlag ) )
if ( !AddToSelectionFromInputEvent( p, &event, selFlag ) )
return res;
m_iFlags &= ~(wxPG_FL_ACTIVATION_BY_CLICK);
@@ -4130,15 +4313,15 @@ bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &even
// -----------------------------------------------------------------------
bool wxPropertyGrid::HandleMouseRightClick( int WXUNUSED(x), unsigned int WXUNUSED(y),
wxMouseEvent& WXUNUSED(event) )
bool wxPropertyGrid::HandleMouseRightClick( int WXUNUSED(x),
unsigned int WXUNUSED(y),
wxMouseEvent& event )
{
if ( m_propHover )
{
// Select property here as well
wxPGProperty* p = m_propHover;
if ( p != m_selected )
DoSelectProperty( p );
AddToSelectionFromInputEvent(p, &event);
// Send right click event.
SendEvent( wxEVT_PG_RIGHT_CLICK, p );
@@ -4150,16 +4333,16 @@ bool wxPropertyGrid::HandleMouseRightClick( int WXUNUSED(x), unsigned int WXUNUS
// -----------------------------------------------------------------------
bool wxPropertyGrid::HandleMouseDoubleClick( int WXUNUSED(x), unsigned int WXUNUSED(y),
wxMouseEvent& WXUNUSED(event) )
bool wxPropertyGrid::HandleMouseDoubleClick( int WXUNUSED(x),
unsigned int WXUNUSED(y),
wxMouseEvent& event )
{
if ( m_propHover )
{
// Select property here as well
wxPGProperty* p = m_propHover;
if ( p != m_selected )
DoSelectProperty( p );
AddToSelectionFromInputEvent(p, &event);
// Send double-click event.
SendEvent( wxEVT_PG_DOUBLE_CLICK, m_propHover );
@@ -4226,7 +4409,7 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event
state->DoSetSplitterPosition( newSplitterX, m_draggedSplitter, false );
state->m_fSplitterX = (float) newSplitterX;
if ( m_selected )
if ( GetSelection() )
CorrectEditorWidgetSizeX();
Update();
@@ -4385,6 +4568,18 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event
CustomSetCursor( wxCURSOR_ARROW );
}
}
//
// Multi select by dragging
//
if ( GetExtraStyle() & wxPG_EX_MULTIPLE_SELECTION &&
event.LeftIsDown() &&
m_propHover &&
GetSelection() &&
!state->DoIsPropertySelected(m_propHover) )
{
DoAddToSelection(m_propHover);
}
}
return true;
}
@@ -4434,8 +4629,9 @@ bool wxPropertyGrid::HandleMouseUp( int x, unsigned int WXUNUSED(y),
m_dragStatus = 0;
// Control background needs to be cleared
if ( !(m_iFlags & wxPG_FL_PRIMARY_FILLS_ENTIRE) && m_selected )
DrawItem( m_selected );
wxPGProperty* selected = GetSelection();
if ( !(m_iFlags & wxPG_FL_PRIMARY_FILLS_ENTIRE) && selected )
DrawItem( selected );
if ( m_wndEditor )
{
@@ -4659,8 +4855,10 @@ void wxPropertyGrid::OnMouseRightClickChild( wxMouseEvent &event )
// but that should not matter (right click is about item, not position).
wxPoint pt = m_wndEditor->GetPosition();
CalcUnscrolledPosition( event.m_x + pt.x, event.m_y + pt.y, &x, &y );
wxASSERT( m_selected );
m_propHover = m_selected;
// FIXME: Used to set m_propHover to selection here. Was it really
// necessary?
bool res = HandleMouseRightClick(x,y,event);
if ( !res ) event.Skip();
}
@@ -4758,6 +4956,7 @@ void wxPropertyGrid::HandleKeyEvent( wxKeyEvent &event, bool fromChild )
wxCHECK2(!m_frozen, return);
// Travelsal between items, collapsing/expanding, etc.
wxPGProperty* selected = GetSelection();
int keycode = event.GetKeyCode();
bool editorFocused = IsEditorFocused();
@@ -4774,7 +4973,7 @@ void wxPropertyGrid::HandleKeyEvent( wxKeyEvent &event, bool fromChild )
{
if ( !editorFocused && m_wndEditor )
{
DoSelectProperty( m_selected, wxPG_SEL_FOCUS );
DoSelectProperty( selected, wxPG_SEL_FOCUS );
}
else
{
@@ -4833,12 +5032,13 @@ void wxPropertyGrid::HandleKeyEvent( wxKeyEvent &event, bool fromChild )
EditorsValueWasNotModified();
// Update the control as well
m_selected->GetEditorClass()->SetControlStringValue( m_selected,
selected->GetEditorClass()->
SetControlStringValue( selected,
GetEditorControl(),
m_selected->GetDisplayedString() );
selected->GetDisplayedString() );
}
OnValidationFailureReset(m_selected);
OnValidationFailureReset(selected);
UnfocusEditor();
return;
@@ -4858,13 +5058,13 @@ void wxPropertyGrid::HandleKeyEvent( wxKeyEvent &event, bool fromChild )
bool wasHandled = false;
if ( m_selected )
if ( selected )
{
// Show dialog?
if ( ButtonTriggerKeyTest(action, event) )
return;
wxPGProperty* p = m_selected;
wxPGProperty* p = selected;
// Travel and expand/collapse
int selectDir = -2;
@@ -5065,8 +5265,9 @@ void wxPropertyGrid::HandleFocusChange( wxWindow* newFocused )
}
// Redraw selected
if ( m_selected && (m_iFlags & wxPG_FL_INITIALIZED) )
DrawItem( m_selected );
wxPGProperty* selected = GetSelection();
if ( selected && (m_iFlags & wxPG_FL_INITIALIZED) )
DrawItem( selected );
}
}

View File

@@ -147,10 +147,6 @@ void wxPropertyGridInterface::DeleteProperty( wxPGPropArg id )
wxPG_PROP_ARG_CALL_PROLOG()
wxPropertyGridPageState* state = p->GetParentState();
wxPropertyGrid* grid = state->GetGrid();
if ( grid->GetState() == state )
grid->DoSelectProperty(NULL, wxPG_SEL_DELETING|wxPG_SEL_NOVALIDATE);
state->DoDelete( p, true );
@@ -167,13 +163,6 @@ wxPGProperty* wxPropertyGridInterface::RemoveProperty( wxPGPropArg id )
wxNullProperty);
wxPropertyGridPageState* state = p->GetParentState();
wxPropertyGrid* grid = state->GetGrid();
if ( grid->GetState() == state )
{
grid->DoSelectProperty(NULL,
wxPG_SEL_DELETING|wxPG_SEL_NOVALIDATE);
}
state->DoDelete( p, false );
@@ -218,11 +207,25 @@ wxPGProperty* wxPropertyGridInterface::ReplaceProperty( wxPGPropArg id, wxPGProp
// wxPropertyGridInterface property operations
// -----------------------------------------------------------------------
wxPGProperty* wxPropertyGridInterface::GetSelection() const
{
return m_pState->GetSelection();
}
// -----------------------------------------------------------------------
bool wxPropertyGridInterface::ClearSelection( bool validation )
{
int flags = wxPG_SEL_DONT_SEND_EVENT;
return DoClearSelection(validation, wxPG_SEL_DONT_SEND_EVENT);
}
// -----------------------------------------------------------------------
bool wxPropertyGridInterface::DoClearSelection( bool validation,
int selFlags )
{
if ( !validation )
flags |= wxPG_SEL_NOVALIDATE;
selFlags |= wxPG_SEL_NOVALIDATE;
wxPropertyGridPageState* state = m_pState;
@@ -230,9 +233,9 @@ bool wxPropertyGridInterface::ClearSelection( bool validation )
{
wxPropertyGrid* pg = state->GetGrid();
if ( pg->GetState() == state )
return pg->DoSelectProperty(NULL, flags);
return pg->DoSelectProperty(NULL, selFlags);
else
state->SetSelection(NULL);
state->DoSetSelection(NULL);
}
return true;
@@ -1026,7 +1029,7 @@ bool wxPropertyGridInterface::RestoreEditableState( const wxString& src, int res
else
{
if ( values[0].length() )
pageState->SetSelection(GetPropertyByName(value));
pageState->DoSetSelection(GetPropertyByName(value));
else
pageState->DoClearSelection();
}

View File

@@ -206,7 +206,6 @@ wxPropertyGridPageState::wxPropertyGridPageState()
m_properties = &m_regularArray;
m_abcArray = NULL;
m_currentCategory = NULL;
m_selected = NULL;
m_width = 0;
m_virtualHeight = 0;
m_lastCaptionBottomnest = 1;
@@ -274,7 +273,7 @@ void wxPropertyGridPageState::DoClear()
}
else
{
m_selected = NULL;
m_selection.clear();
}
m_regularArray.Empty();
@@ -1150,7 +1149,8 @@ bool wxPropertyGridPageState::DoSetPropertyValueString( wxPGProperty* p, const w
if ( res )
{
p->SetValue(variant);
if ( m_selected==p && this==m_pPropGrid->GetState() )
if ( p == m_pPropGrid->GetSelection() &&
this == m_pPropGrid->GetState() )
m_pPropGrid->RefreshEditor();
}
@@ -1166,7 +1166,8 @@ bool wxPropertyGridPageState::DoSetPropertyValue( wxPGProperty* p, wxVariant& va
if ( p )
{
p->SetValue(value);
if ( m_selected==p && this==m_pPropGrid->GetState() )
if ( p == m_pPropGrid->GetSelection() &&
this == m_pPropGrid->GetState() )
m_pPropGrid->RefreshEditor();
return true;
@@ -1192,6 +1193,21 @@ bool wxPropertyGridPageState::DoSetPropertyValueWxObjectPtr( wxPGProperty* p, wx
// wxPropertyGridPageState property operations
// -----------------------------------------------------------------------
bool wxPropertyGridPageState::DoIsPropertySelected( wxPGProperty* prop ) const
{
const wxArrayPGProperty& selection = m_selection;
for ( unsigned int i=0; i<selection.size(); i++ )
{
if ( selection[i] == prop )
return true;
}
return false;
}
// -----------------------------------------------------------------------
bool wxPropertyGridPageState::DoCollapse( wxPGProperty* p )
{
wxCHECK_MSG( p, false, wxT("invalid property id") );
@@ -1231,7 +1247,7 @@ bool wxPropertyGridPageState::DoSelectProperty( wxPGProperty* p, unsigned int fl
if ( this == m_pPropGrid->GetState() )
return m_pPropGrid->DoSelectProperty( p, flags );
m_selected = p;
DoSetSelection(p);
return true;
}
@@ -1711,6 +1727,25 @@ void wxPropertyGridPageState::DoDelete( wxPGProperty* item, bool doDelete )
wxCHECK_RET( !parent->HasFlag(wxPG_PROP_AGGREGATE),
wxT("wxPropertyGrid: Do not attempt to remove sub-properties.") );
wxASSERT( item->GetParentState() == this );
wxPropertyGrid* pg = GetGrid();
if ( DoIsPropertySelected(item) )
{
if ( pg && pg->GetState() == this )
{
pg->DoRemoveFromSelection(item,
wxPG_SEL_DELETING|wxPG_SEL_NOVALIDATE);
}
else
{
m_selection.Remove(item);
}
}
item->SetFlag(wxPG_PROP_BEING_DELETED);
// Delete children
if ( item->GetChildCount() && !item->HasFlag(wxPG_PROP_AGGREGATE) )
{
@@ -1780,8 +1815,6 @@ void wxPropertyGridPageState::DoDelete( wxPGProperty* item, bool doDelete )
(parent->IsCategory() || parent->IsRoot()) )
m_dictName.erase(item->GetBaseName());
wxPropertyGrid* pg = GetGrid();
// We need to clear parent grid's m_propHover, if it matches item
if ( pg && pg->m_propHover == item )
pg->m_propHover = NULL;