#include "wx/timer.h"
#include "wx/dcbuffer.h"
-#include "wx/clipbrd.h"
-#include "wx/dataobj.h"
-
-#ifdef __WXMSW__
- #include "wx/msw/private.h"
-#endif
// Two pics for the expand / collapse buttons.
// Files are not supplied with this project (since it is
IMPLEMENT_DYNAMIC_CLASS(wxPGGlobalVarsClassManager, wxModule)
-wxPGGlobalVarsClass* wxPGGlobalVars = (wxPGGlobalVarsClass*) NULL;
+// When wxPG is loaded dynamically after the application is already running
+// then the built-in module system won't pick this one up. Add it manually.
+void wxPGInitResourceModule()
+{
+ wxModule* module = new wxPGGlobalVarsClassManager;
+ module->Init();
+ wxModule::RegisterModule(module);
+}
+
+wxPGGlobalVarsClass* wxPGGlobalVars = NULL;
wxPGGlobalVarsClass::wxPGGlobalVarsClass()
m_boolChoices.Add(_("False"));
m_boolChoices.Add(_("True"));
- m_fontFamilyChoices = (wxPGChoices*) NULL;
+ m_fontFamilyChoices = NULL;
m_defaultRenderer = new wxPGDefaultRenderer();
wxVariant v;
- // Prepare some shared variants
+ // Prepare some shared variants
m_vEmptyString = wxString();
m_vZero = (long) 0;
m_vMinusOne = (long) -1;
m_strlong = wxS("long");
m_strbool = wxS("bool");
m_strlist = wxS("list");
+ m_strDefaultValue = wxS("DefaultValue");
m_strMin = wxS("Min");
m_strMax = wxS("Max");
m_strUnits = wxS("Units");
m_strInlineHelp = wxS("InlineHelp");
-#ifdef __WXDEBUG__
m_warnings = 0;
-#endif
}
{
}
-// -----------------------------------------------------------------------
-// wxPGTLWHandler
-// Intercepts Close-events sent to wxPropertyGrid's top-level parent,
-// and tries to commit property value.
-// -----------------------------------------------------------------------
-
-class wxPGTLWHandler : public wxEvtHandler
-{
-public:
-
- wxPGTLWHandler( wxPropertyGrid* pg )
- : wxEvtHandler()
- {
- m_pg = pg;
- }
-
-protected:
-
- void OnClose( wxCloseEvent& event )
- {
- // ClearSelection forces value validation/commit.
- if ( event.CanVeto() && !m_pg->ClearSelection() )
- {
- event.Veto();
- return;
- }
-
- event.Skip();
- }
-
-private:
- wxPropertyGrid* m_pg;
-
- DECLARE_EVENT_TABLE()
-};
-
-BEGIN_EVENT_TABLE(wxPGTLWHandler, wxEvtHandler)
- EVT_CLOSE(wxPGTLWHandler::OnClose)
-END_EVENT_TABLE()
-
// -----------------------------------------------------------------------
// wxPGCanvas
// -----------------------------------------------------------------------
// Update everything inside the box
wxRect r = GetUpdateRegion().GetBox();
+ // FIXME: This is just a workaround for a bug that causes splitters not
+ // to paint when other windows are being dragged over the grid.
+ wxRect fullRect = GetRect();
+ r.x = fullRect.x;
+ r.width = fullRect.width;
+
// Repaint this rectangle
pg->DrawItems( dc, r.y, r.y + r.height, &r );
const wxString& name )
{
- if ( !(style&wxBORDER_MASK) )
- style |= wxSIMPLE_BORDER;
+ if (!(style&wxBORDER_MASK))
+ {
+ style |= wxBORDER_THEME;
+ }
style |= wxVSCROLL;
wxPropertyGrid::RegisterDefaultEditors();
m_iFlags = 0;
- m_pState = (wxPropertyGridPageState*) NULL;
- m_wndEditor = m_wndEditor2 = (wxWindow*) NULL;
- m_selected = (wxPGProperty*) NULL;
- m_selColumn = -1;
- m_propHover = (wxPGProperty*) NULL;
+ m_pState = NULL;
+ m_wndEditor = m_wndEditor2 = NULL;
+ m_selColumn = 1;
+ m_colHover = 1;
+ m_propHover = NULL;
+ m_labelEditor = NULL;
+ m_labelEditorProperty = NULL;
m_eventObject = this;
- m_curFocused = (wxWindow*) NULL;
- m_tlwHandler = NULL;
+ m_curFocused = NULL;
+ m_processedEvent = NULL;
m_sortFunction = NULL;
m_inDoPropertyChanged = 0;
m_inCommitChangesFromEditor = 0;
m_canvas = NULL;
#if wxPG_DOUBLE_BUFFER
- m_doubleBuffer = (wxBitmap*) NULL;
+ m_doubleBuffer = NULL;
#endif
#ifndef wxPG_ICON_WIDTH
- m_expandbmp = NULL;
- m_collbmp = NULL;
- m_iconWidth = 11;
- m_iconHeight = 11;
+ m_expandbmp = NULL;
+ m_collbmp = NULL;
+ m_iconWidth = 11;
+ m_iconHeight = 11;
#else
m_iconWidth = wxPG_ICON_WIDTH;
#endif
#ifndef wxPG_ICON_WIDTH
// create two bitmap nodes for drawing
- m_expandbmp = new wxBitmap(expand_xpm);
- m_collbmp = new wxBitmap(collapse_xpm);
+ m_expandbmp = new wxBitmap(expand_xpm);
+ m_collbmp = new wxBitmap(collapse_xpm);
- // calculate average font height for bitmap centering
+ // calculate average font height for bitmap centering
- m_iconWidth = m_expandbmp->GetWidth();
- m_iconHeight = m_expandbmp->GetHeight();
+ m_iconWidth = m_expandbmp->GetWidth();
+ m_iconHeight = m_expandbmp->GetHeight();
#endif
m_curcursor = wxCURSOR_ARROW;
m_cursorSizeWE = new wxCursor( wxCURSOR_SIZEWE );
- // adjust bitmap icon y position so they are centered
+ // adjust bitmap icon y position so they are centered
m_vspacing = wxPG_DEFAULT_VSPACING;
- if ( !m_font.Ok() )
- {
- wxFont useFont = wxScrolledWindow::GetFont();
- wxScrolledWindow::SetOwnFont( useFont );
- }
- else
- {
- // This should be otherwise called by SetOwnFont
- CalculateFontAndBitmapStuff( wxPG_DEFAULT_VSPACING );
- }
+ CalculateFontAndBitmapStuff( wxPG_DEFAULT_VSPACING );
// Allocate cell datas indirectly by calling setter
m_propertyDefaultCell.SetBgCol(*wxBLACK);
// This helps with flicker
SetBackgroundStyle( wxBG_STYLE_CUSTOM );
- // Hook the TLW
- wxPGTLWHandler* handler = new wxPGTLWHandler(this);
- m_tlp = ::wxGetTopLevelParent(this);
- m_tlwHandler = handler;
- m_tlp->PushEventHandler(handler);
+ // Hook the top-level parent
+ m_tlp = NULL;
+ m_tlpClosed = NULL;
+ m_tlpClosedTime = 0;
- // set virtual size to this window size
+ // set virtual size to this window size
wxSize wndsize = GetSize();
- SetVirtualSize(wndsize.GetWidth(), wndsize.GetWidth());
+ SetVirtualSize(wndsize.GetWidth(), wndsize.GetWidth());
m_timeCreated = ::wxGetLocalTimeMillis();
m_canvas = new wxPGCanvas();
- m_canvas->Create(this, 1, wxPoint(0, 0), GetClientSize(),
+ m_canvas->Create(this, wxID_ANY, wxPoint(0, 0), GetClientSize(),
wxWANTS_CHARS | wxCLIP_CHILDREN);
m_canvas->SetBackgroundStyle( wxBG_STYLE_CUSTOM );
{
size_t i;
- DoSelectProperty(NULL);
+ if ( m_processedEvent )
+ {
+ // All right... we are being deleted while wxPropertyGrid event
+ // is being sent. Make sure that event propagates as little
+ // as possible (although usually this is not enough to prevent
+ // a crash).
+ m_processedEvent->Skip(false);
+ m_processedEvent->StopPropagation();
+
+ // Let's use wxMessageBox to make the message appear more
+ // reliably (and *before* the crash can happend).
+ ::wxMessageBox("wxPropertyGrid was being destroyed in an event "
+ "generated by it. This usually leads to a crash "
+ "so it is recommended to destroy the control "
+ "at idle time instead.");
+ }
+
+ 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);
if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED )
m_canvas->ReleaseMouse();
- wxPGTLWHandler* handler = (wxPGTLWHandler*) m_tlwHandler;
- m_tlp->RemoveEventHandler(handler);
- delete handler;
+ // Call with NULL to disconnect event handling
+ if ( GetExtraStyle() & wxPG_EX_ENABLE_TLP_TRACKING )
+ {
+ OnTLPChanging(NULL);
-#ifdef __WXDEBUG__
- if ( IsEditorsValueModified() )
- ::wxMessageBox(wxS("Most recent change in property editor was lost!!!\n\n(if you don't want this to happen, close your frames and dialogs using Close(false).)"),
- wxS("wxPropertyGrid Debug Warning") );
-#endif
+ wxASSERT_MSG( !IsEditorsValueModified(),
+ wxS("Most recent change in property editor was ")
+ wxS("lost!!! (if you don't want this to happen, ")
+ wxS("close your frames and dialogs using ")
+ wxS("Close(false).)") );
+ }
#if wxPG_DOUBLE_BUFFER
if ( m_doubleBuffer )
delete m_doubleBuffer;
#endif
- //m_selected = (wxPGProperty*) NULL;
-
if ( m_iFlags & wxPG_FL_CREATEDSTATE )
delete m_pState;
delete m_cursorSizeWE;
#ifndef wxPG_ICON_WIDTH
- delete m_expandbmp;
- delete m_collbmp;
+ delete m_expandbmp;
+ delete m_collbmp;
#endif
// Delete common value records
for ( i=0; i<m_commonValues.size(); i++ )
{
- delete GetCommonValue(i);
+ // Use temporary variable to work around possible strange VC6 (asserts because m_size is zero)
+ wxPGCommonValue* value = m_commonValues[i];
+ delete value;
}
}
//
// Tooltips disabled
//
- m_canvas->SetToolTip( (wxToolTip*) NULL );
+ m_canvas->SetToolTip( NULL );
}
#endif
}
#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 );
+ }
+
+ DrawItem(prop);
+ }
+
+ 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
+ {
+ m_pState->DoRemoveFromSelection(prop);
+ DrawItem(prop);
+ res = true;
+ }
+
+ return res;
+}
+
+// -----------------------------------------------------------------------
+
+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 )
+{
+ 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 DoSelectAndEdit(prop, colIndex, 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 = DoSelectAndEdit(prop, colIndex, 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::MakeColumnEditable( unsigned int column,
+ bool editable )
+{
+ wxASSERT( column != 1 );
+
+ wxArrayInt& cols = m_pState->m_editableColumns;
+
+ if ( editable )
+ {
+ cols.push_back(column);
+ }
+ else
+ {
+ for ( int i = cols.size() - 1; i > 0; i-- )
+ {
+ if ( cols[i] == (int)column )
+ cols.erase( cols.begin() + i );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+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_ENABLE_TLP_TRACKING )
+ OnTLPChanging(::wxGetTopLevelParent(this));
+ else
+ OnTLPChanging(NULL);
+
if ( exStyle & wxPG_EX_NATIVE_DOUBLE_BUFFERING )
{
#if defined(__WXMSW__)
// returns the best acceptable minimal size
wxSize wxPropertyGrid::DoGetBestSize() const
{
- int hei = 15;
- if ( m_lineHeight > hei )
- hei = m_lineHeight;
- wxSize sz = wxSize( 60, hei+40 );
+ int lineHeight = wxMax(15, m_lineHeight);
+
+ // don't make the grid too tall (limit height to 10 items) but don't
+ // make it too small neither
+ int numLines = wxMin
+ (
+ wxMax(m_pState->m_properties->GetChildCount(), 3),
+ 10
+ );
+
+ wxClientDC dc(const_cast<wxPropertyGrid *>(this));
+ int width = m_marginWidth;
+ for ( unsigned int i = 0; i < m_pState->m_colWidths.size(); i++ )
+ {
+ width += m_pState->GetColumnFitWidth(dc, m_pState->DoGetRoot(), i, true);
+ }
+
+ const wxSize sz = wxSize(width, lineHeight*numLines + 40);
CacheBestSize(sz);
return sz;
}
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::OnTLPChanging( wxWindow* newTLP )
+{
+ if ( newTLP == m_tlp )
+ return;
+
+ wxLongLong currentTime = ::wxGetLocalTimeMillis();
+
+ //
+ // Parent changed so let's redetermine and re-hook the
+ // correct top-level window.
+ if ( m_tlp )
+ {
+ m_tlp->Disconnect( wxEVT_CLOSE_WINDOW,
+ wxCloseEventHandler(wxPropertyGrid::OnTLPClose),
+ NULL, this );
+ m_tlpClosed = m_tlp;
+ m_tlpClosedTime = currentTime;
+ }
+
+ if ( newTLP )
+ {
+ // Only accept new tlp if same one was not just dismissed.
+ if ( newTLP != m_tlpClosed ||
+ m_tlpClosedTime+250 < currentTime )
+ {
+ newTLP->Connect( wxEVT_CLOSE_WINDOW,
+ wxCloseEventHandler(wxPropertyGrid::OnTLPClose),
+ NULL, this );
+ m_tlpClosed = NULL;
+ }
+ else
+ {
+ newTLP = NULL;
+ }
+ }
+
+ m_tlp = newTLP;
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::OnTLPClose( wxCloseEvent& event )
+{
+ // ClearSelection forces value validation/commit.
+ if ( event.CanVeto() && !DoClearSelection() )
+ {
+ event.Veto();
+ return;
+ }
+
+ // Ok, it can close, set tlp pointer to NULL. Some other event
+ // handler can of course veto the close, but our OnIdle() should
+ // then be able to regain the tlp pointer.
+ OnTLPChanging(NULL);
+
+ event.Skip();
+}
+
+// -----------------------------------------------------------------------
+
+bool wxPropertyGrid::Reparent( wxWindowBase *newParent )
+{
+ OnTLPChanging((wxWindow*)newParent);
+
+ bool res = wxScrolledWindow::Reparent(newParent);
+
+ return res;
+}
+
// -----------------------------------------------------------------------
// wxPropertyGrid Font and Colour Methods
// -----------------------------------------------------------------------
void wxPropertyGrid::CalculateFontAndBitmapStuff( int vspacing )
{
- int x = 0, y = 0;
+ int x = 0, y = 0;
m_captionFont = wxScrolledWindow::GetFont();
- GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
+ GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
m_subgroup_extramargin = x + (x/2);
- m_fontHeight = y;
+ m_fontHeight = y;
#if wxPG_USE_RENDERER_NATIVE
m_iconWidth = wxPG_ICON_WIDTH;
m_marginWidth = m_gutterWidth*2 + m_iconWidth;
m_captionFont.SetWeight(wxBOLD);
- GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
+ GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
m_lineHeight = m_fontHeight+(2*m_spacingy)+1;
bool wxPropertyGrid::SetFont( const wxFont& font )
{
// Must disable active editor.
- ClearSelection(false);
+ DoClearSelection();
- // TODO: Following code is disabled with wxMac because
- // it is reported to fail. I (JMS) cannot debug it
- // personally right now.
- // CS: should be fixed now, leaving old code in just in case, TODO: REMOVE
-#if 1 // !defined(__WXMAC__)
bool res = wxScrolledWindow::SetFont( font );
- if ( res )
+ if ( res && GetParent()) // may not have been Create()ed yet if SetFont called from SetWindowVariant
{
CalculateFontAndBitmapStuff( m_vspacing );
-
- if ( m_pState )
- m_pState->CalculateFontAndBitmapStuff(m_vspacing);
-
Refresh();
}
return res;
-#else
- // ** wxMAC Only **
- // TODO: Remove after SetFont crash fixed.
- if ( m_iFlags & wxPG_FL_INITIALIZED )
- {
- wxLogDebug(wxT("WARNING: propGrid.cpp: wxPropertyGrid::SetFont has been disabled on wxMac since there has been crash reported in it. If you are willing to debug the cause, replace line '#if !defined(__WXMAC__)' with line '#if 1' in wxPropertyGrid::SetFont."));
- }
- return false;
-#endif
}
// -----------------------------------------------------------------------
{
// Outside?
if ( y < 0 )
- return (wxPGProperty*) NULL;
+ return NULL;
unsigned int a = 0;
return m_pState->m_properties->GetItemAtY(y, m_lineHeight, &a);
if ( dcPtr )
{
dc.SetClippingRegion( *clipRect );
- paintFinishY = DoDrawItems( *dcPtr, NULL, NULL, clipRect, isBuffered );
+ paintFinishY = DoDrawItems( *dcPtr, clipRect, isBuffered );
}
#if wxPG_DOUBLE_BUFFER
// -----------------------------------------------------------------------
int wxPropertyGrid::DoDrawItems( wxDC& dc,
- const wxPGProperty* firstItem,
- const wxPGProperty* lastItem,
- const wxRect* clipRect,
- bool isBuffered ) const
-{
- // TODO: This should somehow be eliminated.
- wxRect tempClipRect;
- if ( !clipRect )
- {
- wxASSERT(firstItem);
- wxASSERT(lastItem);
- tempClipRect = GetPropertyRect(firstItem, lastItem);
- clipRect = &tempClipRect;
- }
+ const wxRect* clipRect,
+ bool isBuffered ) const
+{
+ const wxPGProperty* firstItem;
+ const wxPGProperty* lastItem;
- if ( !firstItem )
- firstItem = DoGetItemAtY(clipRect->y);
+ firstItem = DoGetItemAtY(clipRect->y);
+ lastItem = DoGetItemAtY(clipRect->y+clipRect->height-1);
if ( !lastItem )
- {
- lastItem = DoGetItemAtY(clipRect->y+clipRect->height-1);
- if ( !lastItem )
- lastItem = GetLastItem( wxPG_ITERATE_VISIBLE );
- }
+ lastItem = GetLastItem( wxPG_ITERATE_VISIBLE );
if ( m_frozen || m_height < 1 || firstItem == NULL )
return clipRect->y;
int x = m_marginWidth - xRelMod;
- const wxFont& normalfont = m_font;
+ wxFont normalFont = GetFont();
bool reallyFocused = (m_iFlags & wxPG_FL_FOCUSED) != 0;
- bool isEnabled = IsEnabled();
+ bool isPgEnabled = IsEnabled();
//
// Prepare some pens and brushes that are often changed to.
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);
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
// TODO: Only render columns that are within clipping region.
- dc.SetFont(normalfont);
+ dc.SetFont(normalFont);
wxPropertyGridConstIterator it( state, wxPG_ITERATE_VISIBLE, firstItem );
int endScanBottomY = lastItemBottomY + lh;
int y2 = y + lh;
+#ifdef __WXMSW__
// Margin Edge
- dc.DrawLine( greyDepthX, y, greyDepthX, y2 );
+ // Modified by JACS to not draw a margin if wxPG_HIDE_MARGIN is specified, since it
+ // looks better, at least under Windows when we have a themed border (the themed-window-specific
+ // whitespace between the real border and the propgrid margin exacerbates the double-border look).
+
+ // Is this or its parent themed?
+ bool suppressMarginEdge = (GetWindowStyle() & wxPG_HIDE_MARGIN) &&
+ (((GetWindowStyle() & wxBORDER_MASK) == wxBORDER_THEME) ||
+ (((GetWindowStyle() & wxBORDER_MASK) == wxBORDER_NONE) && ((GetParent()->GetWindowStyle() & wxBORDER_MASK) == wxBORDER_THEME)));
+#else
+ bool suppressMarginEdge = false;
+#endif
+ if (!suppressMarginEdge)
+ dc.DrawLine( greyDepthX, y, greyDepthX, y2 );
+ else
+ {
+ // Blank out the margin edge
+ dc.SetPen(wxPen(GetBackgroundColour()));
+ dc.DrawLine( greyDepthX, y, greyDepthX, y2 );
+ dc.SetPen( linepen );
+ }
// Splitters
unsigned int si;
wxColour rowFgCol;
wxColour rowBgCol;
- if ( p != selected )
+ bool isSelected = state->DoIsPropertySelected(p);
+
+ if ( !isSelected )
{
// Disabled may get different colour.
if ( !p->IsEnabled() )
}
else
{
+#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
+ if ( p == firstSelected )
+ wasSelectedPainted = true;
+#endif
+
renderFlags |= wxPGCellRenderer::Selected;
if ( !p->IsCategory() )
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;
- rowBgCol = m_colMargin;
+ if ( p == firstSelected )
+ rowBgCol = m_colMargin;
+ else
+ rowBgCol = selBackCol;
}
else
{
rowFgCol = m_colDisPropFore;
- rowBgCol = m_colSelBack;
+ rowBgCol = selBackCol;
}
}
}
{
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 ( p == selected && m_wndEditor && ci == 1 )
+ if ( isSelected && (ci == 1 || ci == m_selColumn) )
{
- 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) )
- ctrlCell = true;
+ 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 =
+ 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) )
+ cellEditor = NULL;
+ }
+ 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
{
cellRect.width -= textXAdd;
// Foreground
- if ( !ctrlCell )
+ if ( !cellEditor )
{
wxPGCellRenderer* renderer;
int cmnVal = p->GetCommonValue();
}
if ( fontChanged )
- dc.SetFont(normalfont);
+ dc.SetFont(normalFont);
y += rowHeight;
}
if ( m_width < 10 || m_height < 10 ||
!m_pState->m_properties->GetChildCount() ||
- p1 == (wxPGProperty*) NULL )
+ p1 == NULL )
return wxRect(0,0,0,0);
int vy = 0;
// 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();
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);
}
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();
void wxPropertyGrid::Clear()
{
- ClearSelection(false);
-
m_pState->DoClear();
m_propHover = NULL;
bool wxPropertyGrid::EnableCategories( bool enable )
{
- ClearSelection(false);
+ DoClearSelection();
if ( enable )
{
if ( pNewState == m_pState )
return;
- wxPGProperty* oldSelection = m_selected;
+ wxArrayPGProperty oldSelection = m_pState->m_selection;
- ClearSelection(false);
+ // 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();
pNewState->OnClientWidthChange( pgWidth, pgWidth - pNewState->m_width );
}
- m_propHover = (wxPGProperty*) NULL;
+ m_propHover = NULL;
// If necessary, convert state to correct mode.
if ( orig_mode != new_state_mode )
// 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();
if ( refresh )
{
- if ( m_selected )
+ if ( GetSelection() )
CorrectEditorWidgetSizeX();
Refresh();
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
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;
}
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();
}
if ( evtChangingProperty->HasFlag(wxPG_PROP_COMPOSED_VALUE) )
{
- if ( changedProperty == m_selected )
+ if ( changedProperty == GetSelection() )
{
wxWindow* editor = GetEditorControl();
wxASSERT( editor->IsKindOf(CLASSINFO(wxTextCtrl)) );
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;
}
}
#endif
- ::wxMessageBox(msg, _T("Property Error"));
+ ::wxMessageBox(msg, wxT("Property Error"));
}
// -----------------------------------------------------------------------
//
// 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);
}
DrawItemAndChildren(property);
- if ( property == m_selected )
+ if ( property == GetSelection() )
{
SetInternalFlag(wxPG_FL_CELL_OVERRIDES_SEL);
wxString msg = m_validationInfo.m_failureMessage;
if ( !msg.length() )
- msg = _T("You have entered invalid value. Press ESC to cancel editing.");
+ msg = wxT("You have entered invalid value. Press ESC to cancel editing.");
DoShowPropertyError(property, msg);
}
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);
return true;
wxWindow* editor = GetEditorControl();
+ wxPGProperty* selected = GetSelection();
m_pState->m_anyModified = 1;
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();
{
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();
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;
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 )
wxVariant pendingValue(selected->GetValueRef());
wxWindow* wnd = GetEditorControl();
+ wxWindow* editorWnd = wxDynamicCast(event.GetEventObject(), wxWindow);
int selFlags = 0;
bool wasUnspecified = selected->IsValueUnspecified();
int usesAutoUnspecified = selected->UsesAutoUnspecified();
-
bool valueIsPending = false;
m_chgInfo_changedProperty = NULL;
if ( !buttonWasHandled )
{
- if ( wnd )
+ if ( wnd || m_wndEditor2 )
{
// First call editor class' event handler.
const wxPGEditor* editor = selected->GetEditorClass();
- if ( editor->OnEvent( this, selected, wnd, event ) )
+ if ( editor->OnEvent( this, selected, editorWnd, event ) )
{
// If changes, validate them
if ( DoEditorValidate() )
{
- if ( editor->GetValueFromControl( pendingValue, m_selected, wnd ) )
+ if ( editor->GetValueFromControl( pendingValue,
+ selected,
+ wnd ) )
valueIsPending = true;
}
else
// Then the property's custom handler (must be always called, unless
// validation failed).
if ( !validationFailure )
- buttonWasHandled = selected->OnEvent( this, wnd, event );
+ buttonWasHandled = selected->OnEvent( this, editorWnd, event );
}
// SetValueInEvent(), as called in one of the functions referred above
}
if ( !validationFailure && valueIsPending )
- if ( !PerformValidation(m_selected, pendingValue) )
+ if ( !PerformValidation(selected, pendingValue) )
validationFailure = true;
if ( validationFailure)
{
int itemy = p->GetY2(m_lineHeight);
int vy = 0;
- int cust_img_space = 0;
int splitterX = m_pState->DoGetSplitterPosition(column-1);
int colEnd = splitterX + m_pState->m_colWidths[column];
+ int imageOffset = 0;
// TODO: If custom image detection changes from current, change this.
- if ( m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE /*p->m_flags & wxPG_PROP_CUSTOMIMAGE*/ )
+ if ( m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE )
{
//m_iFlags |= wxPG_FL_CUR_USES_CUSTOM_IMAGE;
- int imwid = p->OnMeasureImage().x;
- if ( imwid < 1 ) imwid = wxPG_CUSTOM_IMAGE_WIDTH;
- cust_img_space = imwid + wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2;
+ int iw = p->OnMeasureImage().x;
+ if ( iw < 1 )
+ iw = wxPG_CUSTOM_IMAGE_WIDTH;
+ imageOffset = p->GetImageOffset(iw);
}
return wxRect
(
- splitterX+cust_img_space+wxPG_XBEFOREWIDGET+wxPG_CONTROL_MARGIN+1,
+ splitterX+imageOffset+wxPG_XBEFOREWIDGET+wxPG_CONTROL_MARGIN+1,
itemy-vy,
- colEnd-splitterX-wxPG_XBEFOREWIDGET-wxPG_CONTROL_MARGIN-cust_img_space-1,
+ colEnd-splitterX-wxPG_XBEFOREWIDGET-wxPG_CONTROL_MARGIN-imageOffset-1,
m_lineHeight-1
);
}
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()
{
//
// Do not free editors immediately if processing events
if ( m_wndEditor2 )
{
- m_wndEditor2->PopEventHandler(true);
+ wxEvtHandler* handler = m_wndEditor2->PopEventHandler(false);
m_wndEditor2->Hide();
- wxPendingDelete.Append( m_wndEditor2 );
- m_wndEditor2 = (wxWindow*) NULL;
+ wxPendingDelete.Append( handler );
+ DestroyEditorWnd(m_wndEditor2);
+ m_wndEditor2 = NULL;
}
if ( m_wndEditor )
{
- m_wndEditor->PopEventHandler(true);
+ wxEvtHandler* handler = m_wndEditor->PopEventHandler(false);
m_wndEditor->Hide();
- wxPendingDelete.Append( m_wndEditor );
- m_wndEditor = (wxWindow*) NULL;
+ wxPendingDelete.Append( handler );
+ DestroyEditorWnd(m_wndEditor);
+ m_wndEditor = NULL;
}
}
{
/*
if (p)
+ {
wxLogDebug(wxT("SelectProperty( %s (%s[%i]) )"),p->m_label.c_str(),
p->m_parent->m_label.c_str(),p->GetIndexInParent());
+ }
else
+ {
wxLogDebug(wxT("SelectProperty( NULL, -1 )"));
+ }
*/
if ( m_inDoSelectProperty )
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;
+
+ // Always send event, as this is indirect call
+ DoEndLabelEdit(true, wxPG_SEL_NOVALIDATE);
+
/*
- 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" );
{
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.
FreeEditors();
// Prevent any further selection measures in this call
- p = (wxPGProperty*) NULL;
+ p = NULL;
}
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 )
//
// 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) )
{
}
FreeEditors();
- m_selColumn = -1;
-
- m_selected = (wxPGProperty*) NULL;
- m_pState->m_selected = (wxPGProperty*) NULL;
-
- // We need to always fully refresh the grid here
- Refresh(false);
m_iFlags &= ~(wxPG_FL_ABNORMAL_EDITOR);
EditorsValueWasNotModified();
SetInternalFlag(wxPG_FL_IN_SELECT_PROPERTY);
+ 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 )
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 == (wxWindow*) NULL );
+ wxASSERT( m_wndEditor == NULL );
//
// Only create editor for non-disabled non-caption
wxRect grect = GetEditorWidgetRect(p, m_selColumn);
wxPoint goodPos = grect.GetPosition();
- #if wxPG_CREATE_CONTROLS_HIDDEN
- int coord_adjust = m_height - goodPos.y;
- goodPos.y += coord_adjust;
- #endif
const wxPGEditor* editor = p->GetEditorClass();
wxCHECK_MSG(editor, false,
if ( (p->m_flags & wxPG_PROP_MODIFIED) && (m_windowStyle & wxPG_BOLD_MODIFIED) )
SetCurControlBoldFont();
- //
- // Fix TextCtrl indentation
- #if defined(__WXMSW__) && !defined(__WXWINCE__)
- wxTextCtrl* tc = NULL;
- if ( primaryCtrl->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) )
- tc = ((wxOwnerDrawnComboBox*)primaryCtrl)->GetTextCtrl();
- else
- tc = wxDynamicCast(primaryCtrl, wxTextCtrl);
- if ( tc )
- ::SendMessage(GetHwndOf(tc), EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0, 0));
- #endif
-
// Store x relative to splitter (we'll need it).
m_ctrlXAdjust = m_wndEditor->GetPosition().x - splitterX;
m_wndEditor->SetSizeHints(3, 3);
- #if wxPG_CREATE_CONTROLS_HIDDEN
- m_wndEditor->Show(false);
- m_wndEditor->Freeze();
-
- goodPos = m_wndEditor->GetPosition();
- goodPos.y -= coord_adjust;
- m_wndEditor->Move( goodPos );
- #endif
-
SetupChildEventHandling(primaryCtrl);
// Focus and select all (wxTextCtrl, wxComboBox etc)
m_wndEditor2->SetSizeHints(3,3);
- #if wxPG_CREATE_CONTROLS_HIDDEN
- wxRect sec_rect = m_wndEditor2->GetRect();
- sec_rect.y -= coord_adjust;
-
- // Fine tuning required to fix "oversized"
- // button disappearance bug.
- if ( sec_rect.y < 0 )
- {
- sec_rect.height += sec_rect.y;
- sec_rect.y = 0;
- }
- m_wndEditor2->SetSize( sec_rect );
- #endif
m_wndEditor2->Show();
SetupChildEventHandling(m_wndEditor2);
if ( m_wndEditor )
{
- #if wxPG_CREATE_CONTROLS_HIDDEN
- m_wndEditor->Thaw();
- #endif
m_wndEditor->Show(true);
}
- DrawItems(p, p);
+ if ( !(flags & wxPG_SEL_NO_REFRESH) )
+ DrawItem(p);
}
else
{
if ( !(GetExtraStyle() & wxPG_EX_HELP_AS_TOOLTIPS) )
{
- wxStatusBar* statusbar = (wxStatusBar*) NULL;
+ wxStatusBar* statusbar = NULL;
if ( !(m_iFlags & wxPG_FL_NOSTATUSBARHELP) )
{
wxFrame* frame = wxDynamicCast(::wxGetTopLevelParent(this),wxFrame);
m_inDoSelectProperty = 0;
// call wx event handler (here so that it also occurs on deselection)
- SendEvent( wxEVT_PG_SELECTED, m_selected, NULL, flags );
+ if ( !(flags & wxPG_SEL_DONT_SEND_EVENT) )
+ SendEvent( wxEVT_PG_SELECTED, p, NULL );
return true;
}
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;
}
void wxPropertyGrid::RefreshEditor()
{
- wxPGProperty* p = m_selected;
- if ( !p )
+ wxPGProperty* p = GetSelection();
+ if ( !p )
return;
wxWindow* wnd = GetEditorControl();
// -----------------------------------------------------------------------
-// This method is not inline because it called dozens of times
-// (i.e. two-arg function calls create smaller code size).
-bool wxPropertyGrid::DoClearSelection()
+bool wxPropertyGrid::SelectProperty( wxPGPropArg id, bool focus )
{
- return DoSelectProperty((wxPGProperty*)NULL);
+ wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
+
+ int flags = wxPG_SEL_DONT_SEND_EVENT;
+ if ( focus )
+ flags |= wxPG_SEL_FOCUS;
+
+ return DoSelectProperty(p, flags);
}
// -----------------------------------------------------------------------
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) )
{
- ClearSelection(false);
+ DoClearSelection();
}
// Store dont-center-splitter flag 'cause we need to temporarily set it
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++ )
+ {
+ wxPGProperty* selected = selection[i];
+ if ( selected == p || selected->IsSomeParent(p) )
{
- ClearSelection(false);
+ if ( !DoRemoveFromSelection(p, flags) )
+ return false;
+ selRemoveCount += 1;
}
+ }
m_pState->DoHideProperty(p, hide, flags);
m_pState->EnsureVirtualHeight();
-#ifdef __WXDEBUG__
- int by1 = m_pState->GetVirtualHeight();
- int by2 = m_pState->GetActualVirtualHeight();
- if ( by1 != by2 )
- {
- wxString s = wxString::Format(wxT("VirtualHeight=%i, ActualVirtualHeight=%i, should match!"), by1, by2);
- wxFAIL_MSG(s.c_str());
- wxLogDebug(s);
- }
-#endif
+ wxASSERT_LEVEL_2_MSG(
+ m_pState->GetVirtualHeight() == m_pState->GetActualVirtualHeight(),
+ "VirtualHeight and ActualVirtualHeight should match"
+ );
m_iFlags |= wxPG_FL_RECALCULATING_VIRTUAL_SIZE;
GetClientSize(&width,&height);
// Now adjust virtual size.
- SetVirtualSize(x, y);
+ SetVirtualSize(x, y);
int xAmount = 0;
int xPos = 0;
else if ( xPos > (xAmount-(width/wxPG_PIXELS_PER_UNIT)) )
xPos = 0;
- int yAmount = (y+wxPG_PIXELS_PER_UNIT+2)/wxPG_PIXELS_PER_UNIT;
+ int yAmount = y / wxPG_PIXELS_PER_UNIT;
int yPos = GetScrollPos( wxVERTICAL );
SetScrollbars( wxPG_PIXELS_PER_UNIT, wxPG_PIXELS_PER_UNIT,
m_width = width;
m_height = height;
- m_canvas->SetSize( x, y );
+ // Explicitly pass the position - works around a bug in wxWidgets when the property grid
+ // has a native XP border and a contained window creeps up-and-left when size is set without
+ // the position.
+ m_canvas->SetSize( 0, 0, x, y );
m_pState->CheckColumnWidths();
- if ( m_selected )
+ if ( GetSelection() )
CorrectEditorWidgetSizeX();
m_iFlags &= ~wxPG_FL_RECALCULATING_VIRTUAL_SIZE;
// 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);
+ }
+
+ m_processedEvent = &evt;
+
wxEvtHandler* evtHandler = m_eventObject->GetEventHandler();
+ m_processedEvent = NULL;
+
evtHandler->ProcessEvent(evt);
return evt.WasVetoed();
)
)
{
- if ( !DoSelectProperty( p ) )
+ if ( !AddToSelectionFromInputEvent( p,
+ columnHit,
+ &event ) )
return res;
// On double-click, expand/collapse.
m_iFlags |= wxPG_FL_ACTIVATION_BY_CLICK;
selFlag = wxPG_SEL_FOCUS;
}
- if ( !DoSelectProperty( p, 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
// -----------------------------------------------------------------------
-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, m_colHover, &event);
// Send right click event.
SendEvent( wxEVT_PG_RIGHT_CLICK, p );
// -----------------------------------------------------------------------
-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, 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) &&
state->DoSetSplitterPosition( newSplitterX, m_draggedSplitter, false );
state->m_fSplitterX = (float) newSplitterX;
- if ( m_selected )
+ if ( GetSelection() )
CorrectEditorWidgetSizeX();
Update();
if ( space )
{
int tw, th;
- GetTextExtent( tipString, &tw, &th, 0, 0, &m_font );
+ GetTextExtent( tipString, &tw, &th, 0, 0 );
if ( tw > space )
{
SetToolTip( tipString );
CustomSetCursor( wxCURSOR_ARROW );
}
}
+
+ //
+ // Multi select by dragging
+ //
+ if ( (GetExtraStyle() & wxPG_EX_MULTIPLE_SELECTION) &&
+ event.LeftIsDown() &&
+ m_propHover &&
+ GetSelection() &&
+ columnHit != 1 &&
+ !state->DoIsPropertySelected(m_propHover) )
+ {
+ // Additional requirement is that the hovered property
+ // is adjacent to edges of selection.
+ const wxArrayPGProperty& selection = GetSelectedProperties();
+
+ // Since categories cannot be selected along with 'other'
+ // properties, exclude them from iterator flags.
+ int iterFlags = wxPG_ITERATE_VISIBLE & (~wxPG_PROP_CATEGORY);
+
+ for ( int i=(selection.size()-1); i>=0; i-- )
+ {
+ // TODO: This could be optimized by keeping track of
+ // which properties are at the edges of selection.
+ wxPGProperty* selProp = selection[i];
+ if ( state->ArePropertiesAdjacent(m_propHover, selProp,
+ iterFlags) )
+ {
+ DoAddToSelection(m_propHover);
+ break;
+ }
+ }
+ }
}
return true;
}
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 )
{
wxRect r;
if ( wnd )
r = wnd->GetRect();
- if ( wnd == (wxWindow*) NULL || m_dragStatus ||
+ if ( wnd == NULL || m_dragStatus ||
(
ux <= (splitterX + wxPG_SPLITTERX_DETECTMARGIN2) ||
ux >= (r.x+r.width) ||
// 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();
}
void wxPropertyGrid::ClearActionTriggers( int action )
{
wxPGHashMapI2I::iterator it;
+ bool didSomething;
- for ( it = m_actionTriggers.begin(); it != m_actionTriggers.end(); ++it )
+ do
{
- if ( it->second == action )
+ didSomething = false;
+
+ for ( it = m_actionTriggers.begin();
+ it != m_actionTriggers.end();
+ it++ )
{
- m_actionTriggers.erase(it);
+ if ( it->second == action )
+ {
+ m_actionTriggers.erase(it);
+ didSomething = true;
+ break;
+ }
}
}
+ while ( didSomething );
}
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();
{
if ( !editorFocused && m_wndEditor )
{
- DoSelectProperty( m_selected, wxPG_SEL_FOCUS );
+ DoSelectProperty( selected, wxPG_SEL_FOCUS );
}
else
{
EditorsValueWasNotModified();
// Update the control as well
- m_selected->GetEditorClass()->SetControlStringValue( m_selected,
- GetEditorControl(),
- m_selected->GetDisplayedString() );
+ selected->GetEditorClass()->
+ SetControlStringValue( selected,
+ GetEditorControl(),
+ selected->GetDisplayedString() );
}
- OnValidationFailureReset(m_selected);
+ OnValidationFailureReset(selected);
UnfocusEditor();
return;
// Except for TAB and ESC, handle child control events in child control
if ( fromChild )
{
+ // Only propagate event if it had modifiers
+ if ( !event.HasModifiers() )
+ {
+ event.StopPropagation();
+ }
event.Skip();
return;
}
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;
- if ( p->GetChildCount() &&
- !(p->m_flags & wxPG_PROP_DISABLED)
- )
+ if ( p->GetChildCount() )
{
if ( action == wxPG_ACTION_COLLAPSE_PROPERTY || secondAction == wxPG_ACTION_COLLAPSE_PROPERTY )
{
void wxPropertyGrid::OnKey( wxKeyEvent &event )
{
+ // If there was editor open and focused, then this event should not
+ // really be processed here.
+ if ( IsEditorFocused() )
+ {
+ // However, if event had modifiers, it is probably still best
+ // to skip it.
+ if ( event.HasModifiers() )
+ event.Skip();
+ else
+ event.StopPropagation();
+ return;
+ }
+
HandleKeyEvent(event, false);
}
if ( newFocused != m_curFocused )
HandleFocusChange( newFocused );
+
+ //
+ // Check if top-level parent has changed
+ if ( GetExtraStyle() & wxPG_EX_ENABLE_TLP_TRACKING )
+ {
+ wxWindow* tlp = ::wxGetTopLevelParent(this);
+ if ( tlp != m_tlp )
+ OnTLPChanging(tlp);
+ }
}
bool wxPropertyGrid::IsEditorFocused() const
}
// 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 );
}
}
void wxPropertyGrid::OnChildFocusEvent( wxChildFocusEvent& event )
{
HandleFocusChange((wxWindow*)event.GetEventObject());
-
- //
- // event.Skip() being commented out is aworkaround for bug reported
- // in ticket #4840 (wxScrolledWindow problem with automatic scrolling).
- //event.Skip();
+ event.Skip();
}
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// noDefCheck = true prevents infinite recursion.
-wxPGEditor* wxPropertyGrid::RegisterEditorClass( wxPGEditor* editorClass,
- bool noDefCheck )
+wxPGEditor* wxPropertyGrid::DoRegisterEditorClass( wxPGEditor* editorClass,
+ const wxString& editorName,
+ bool noDefCheck )
{
wxASSERT( editorClass );
if ( !noDefCheck && wxPGGlobalVars->m_mapEditorClasses.empty() )
RegisterDefaultEditors();
- wxString name = editorClass->GetName();
+ wxString name = editorName;
+ if ( name.length() == 0 )
+ name = editorClass->GetName();
// Existing editor under this name?
wxPGHashMapS2P::iterator vt_it = wxPGGlobalVars->m_mapEditorClasses.find(name);
// Use this in RegisterDefaultEditors.
#define wxPGRegisterDefaultEditorClass(EDITOR) \
- if ( wxPGEditor_##EDITOR == (wxPGEditor*) NULL ) \
+ if ( wxPGEditor_##EDITOR == NULL ) \
{ \
wxPGEditor_##EDITOR = wxPropertyGrid::RegisterEditorClass( \
new wxPG##EDITOR##Editor, true ); \
wxPGChoicesData::wxPGChoicesData()
{
- m_refCount = 1;
}
wxPGChoicesData::~wxPGChoicesData()
return ownEntry;
}
-// -----------------------------------------------------------------------
-// wxPGChoices
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::Add( const wxString& label, int value )
-{
- EnsureData();
-
- wxPGChoiceEntry entry(label, value);
- return m_data->Insert( -1, entry );
-}
-
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::Add( const wxString& label, const wxBitmap& bitmap, int value )
-{
- EnsureData();
-
- wxPGChoiceEntry entry(label, value);
- entry.SetBitmap(bitmap);
- return m_data->Insert( -1, entry );
-}
-
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::Insert( const wxPGChoiceEntry& entry, int index )
-{
- EnsureData();
- return m_data->Insert( index, entry );
-}
-
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::Insert( const wxString& label, int index, int value )
-{
- EnsureData();
-
- wxPGChoiceEntry entry(label, value);
- return m_data->Insert( index, entry );
-}
-
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::AddAsSorted( const wxString& label, int value )
-{
- EnsureData();
-
- size_t index = 0;
-
- while ( index < GetCount() )
- {
- int cmpRes = GetLabel(index).Cmp(label);
- if ( cmpRes > 0 )
- break;
- index++;
- }
-
- wxPGChoiceEntry entry(label, value);
- return m_data->Insert( index, entry );
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::Add( const wxChar** labels, const ValArrItem* values )
-{
- EnsureData();
-
- unsigned int itemcount = 0;
- const wxChar** p = &labels[0];
- while ( *p ) { p++; itemcount++; }
-
- unsigned int i;
- for ( i = 0; i < itemcount; i++ )
- {
- int value = i;
- if ( values )
- value = values[i];
- wxPGChoiceEntry entry(labels[i], value);
- m_data->Insert( i, entry );
- }
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::Add( const wxArrayString& arr, const wxArrayInt& arrint )
-{
- EnsureData();
-
- unsigned int i;
- unsigned int itemcount = arr.size();
-
- for ( i = 0; i < itemcount; i++ )
- {
- int value = i;
- if ( &arrint && arrint.size() )
- value = arrint[i];
- wxPGChoiceEntry entry(arr[i], value);
- m_data->Insert( i, entry );
- }
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::RemoveAt(size_t nIndex, size_t count)
-{
- wxASSERT( m_data->m_refCount != 0xFFFFFFF );
- m_data->m_items.erase(m_data->m_items.begin()+nIndex,
- m_data->m_items.begin()+nIndex+count);
-}
-
-// -----------------------------------------------------------------------
-
-int wxPGChoices::Index( const wxString& str ) const
-{
- if ( IsOk() )
- {
- unsigned int i;
- for ( i=0; i< m_data->GetCount(); i++ )
- {
- const wxPGChoiceEntry& entry = m_data->Item(i);
- if ( entry.HasText() && entry.GetText() == str )
- return i;
- }
- }
- return -1;
-}
-
-// -----------------------------------------------------------------------
-
-int wxPGChoices::Index( int val ) const
-{
- if ( IsOk() )
- {
- unsigned int i;
- for ( i=0; i< m_data->GetCount(); i++ )
- {
- const wxPGChoiceEntry& entry = m_data->Item(i);
- if ( entry.GetValue() == val )
- return i;
- }
- }
- return -1;
-}
-
-// -----------------------------------------------------------------------
-
-wxArrayString wxPGChoices::GetLabels() const
-{
- wxArrayString arr;
- unsigned int i;
-
- if ( this && IsOk() )
- for ( i=0; i<GetCount(); i++ )
- arr.push_back(GetLabel(i));
-
- return arr;
-}
-
-// -----------------------------------------------------------------------
-
-wxArrayInt wxPGChoices::GetValuesForStrings( const wxArrayString& strings ) const
-{
- wxArrayInt arr;
-
- if ( IsOk() )
- {
- unsigned int i;
- for ( i=0; i< strings.size(); i++ )
- {
- int index = Index(strings[i]);
- if ( index >= 0 )
- arr.Add(GetValue(index));
- else
- arr.Add(wxPG_INVALID_VALUE);
- }
- }
-
- return arr;
-}
-
-// -----------------------------------------------------------------------
-
-wxArrayInt wxPGChoices::GetIndicesForStrings( const wxArrayString& strings,
- wxArrayString* unmatched ) const
-{
- wxArrayInt arr;
-
- if ( IsOk() )
- {
- unsigned int i;
- for ( i=0; i< strings.size(); i++ )
- {
- const wxString& str = strings[i];
- int index = Index(str);
- if ( index >= 0 )
- arr.Add(index);
- else if ( unmatched )
- unmatched->Add(str);
- }
- }
-
- return arr;
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::AssignData( wxPGChoicesData* data )
-{
- Free();
-
- if ( data != wxPGChoicesEmptyData )
- {
- m_data = data;
- data->m_refCount++;
- }
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::Init()
-{
- m_data = wxPGChoicesEmptyData;
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::Free()
-{
- if ( m_data != wxPGChoicesEmptyData )
- {
- m_data->DecRef();
- m_data = wxPGChoicesEmptyData;
- }
-}
-
// -----------------------------------------------------------------------
// wxPropertyGridEvent
// -----------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxPropertyGridEvent, wxCommandEvent)
-wxDEFINE_EVENT( wxEVT_PG_SELECTED, wxPropertyGridEvent )
-wxDEFINE_EVENT( wxEVT_PG_CHANGING, wxPropertyGridEvent )
-wxDEFINE_EVENT( wxEVT_PG_CHANGED, wxPropertyGridEvent )
-wxDEFINE_EVENT( wxEVT_PG_HIGHLIGHTED, wxPropertyGridEvent )
-wxDEFINE_EVENT( wxEVT_PG_RIGHT_CLICK, wxPropertyGridEvent )
-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_SELECTED, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_CHANGING, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_CHANGED, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_HIGHLIGHTED, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_RIGHT_CLICK, wxPropertyGridEvent );
+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;
}