m_strMin = wxS("Min");
m_strMax = wxS("Max");
m_strUnits = wxS("Units");
+ m_strHint = wxS("Hint");
+#if wxPG_COMPATIBILITY_1_4
m_strInlineHelp = wxS("InlineHelp");
+#endif
m_warnings = 0;
}
if ( wxPGGlobalVars->m_mapEditorClasses.empty() )
wxPropertyGrid::RegisterDefaultEditors();
+ m_validatingEditor = 0;
m_iFlags = 0;
m_pState = NULL;
m_wndEditor = m_wndEditor2 = NULL;
m_mouseSide = 16;
m_editorFocused = 0;
+ // Set up default unspecified value 'colour'
+ m_unspecifiedAppearance.SetFgCol(*wxLIGHT_GREY);
+
// Set default keys
AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_RIGHT );
AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_DOWN );
CalculateFontAndBitmapStuff( wxPG_DEFAULT_VSPACING );
- // Allocate cell datas indirectly by calling setter
- m_propertyDefaultCell.SetBgCol(*wxBLACK);
- m_categoryDefaultCell.SetBgCol(*wxBLACK);
+ // Allocate cell datas
+ m_propertyDefaultCell.SetEmptyData();
+ m_categoryDefaultCell.SetEmptyData();
RegainColours();
wxMouseEvent* mouseEvent,
int selFlags )
{
+ const wxArrayPGProperty& selection = GetSelectedProperties();
bool alreadySelected = m_pState->DoIsPropertySelected(prop);
bool res = true;
- bool addToExistingSelection;
+
+ // Set to 2 if also add all items in between
+ int addToExistingSelection = 0;
if ( GetExtraStyle() & wxPG_EX_MULTIPLE_SELECTION )
{
}
else
{
- addToExistingSelection = mouseEvent->ShiftDown();
+ if ( mouseEvent->ControlDown() )
+ {
+ addToExistingSelection = 1;
+ }
+ else if ( mouseEvent->ShiftDown() )
+ {
+ if ( selection.size() > 0 && !prop->IsCategory() )
+ addToExistingSelection = 2;
+ else
+ addToExistingSelection = 1;
+ }
}
}
- else
- {
- addToExistingSelection = false;
- }
- }
- else
- {
- addToExistingSelection = false;
}
- if ( addToExistingSelection )
+ if ( addToExistingSelection == 1 )
{
+ // Add/remove one
if ( !alreadySelected )
{
res = DoAddToSelection(prop, selFlags);
res = DoRemoveFromSelection(prop, selFlags);
}
}
+ else if ( addToExistingSelection == 2 )
+ {
+ // Add this, and all in between
+
+ // Find top selected property
+ wxPGProperty* topSelProp = selection[0];
+ int topSelPropY = topSelProp->GetY();
+ for ( unsigned int i=1; i<selection.size(); i++ )
+ {
+ wxPGProperty* p = selection[i];
+ int y = p->GetY();
+ if ( y < topSelPropY )
+ {
+ topSelProp = p;
+ topSelPropY = y;
+ }
+ }
+
+ wxPGProperty* startFrom;
+ wxPGProperty* stopAt;
+
+ if ( prop->GetY() <= topSelPropY )
+ {
+ // Property is above selection (or same)
+ startFrom = prop;
+ stopAt = topSelProp;
+ }
+ else
+ {
+ // Property is below selection
+ startFrom = topSelProp;
+ stopAt = prop;
+ }
+
+ // Iterate through properties in-between, and select them
+ wxPropertyGridIterator it;
+
+ for ( it = GetIterator(wxPG_ITERATE_VISIBLE, startFrom);
+ !it.AtEnd();
+ it++ )
+ {
+ wxPGProperty* p = *it;
+
+ if ( !p->IsCategory() &&
+ !m_pState->DoIsPropertySelected(p) )
+ {
+ DoAddToSelection(p, selFlags);
+ }
+
+ if ( p == stopAt )
+ break;
+ }
+ }
else
{
res = DoSelectAndEdit(prop, colIndex, selFlags);
}
else
{
- event.Skip();
+ HandleKeyEvent(event, true);
}
}
}
m_selColumn = 1;
+ int wasFocused = m_iFlags & wxPG_FL_FOCUSED;
DestroyEditorWnd(m_labelEditor);
+
m_labelEditor = NULL;
m_labelEditorProperty = NULL;
+ // Fix focus (needed at least on wxGTK)
+ if ( wasFocused )
+ SetFocusOnCanvas();
+
DrawItem(prop);
}
wxColour bgCol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
m_colPropBack = bgCol;
m_propertyDefaultCell.GetData()->SetBgCol(bgCol);
+ if ( !m_unspecifiedAppearance.GetBgCol().IsOk() )
+ m_unspecifiedAppearance.SetBgCol(bgCol);
}
if ( !(m_coloursCustomized & 0x0010) )
wxColour fgCol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
m_colPropFore = fgCol;
m_propertyDefaultCell.GetData()->SetFgCol(fgCol);
+ if ( !m_unspecifiedAppearance.GetFgCol().IsOk() )
+ m_unspecifiedAppearance.SetFgCol(fgCol);
}
if ( !(m_coloursCustomized & 0x0020) )
m_coloursCustomized |= 0x08;
m_propertyDefaultCell.GetData()->SetBgCol(col);
+ m_unspecifiedAppearance.SetBgCol(col);
Refresh();
}
m_coloursCustomized |= 0x10;
m_propertyDefaultCell.GetData()->SetFgCol(col);
+ m_unspecifiedAppearance.SetFgCol(col);
Refresh();
}
Sort(wxPG_SORT_TOP_LEVEL_ONLY);
RecalculateVirtualSize();
+
+ // Fix editor position
+ CorrectEditorWidgetPosY();
}
// -----------------------------------------------------------------------
// Control font changer helper.
void wxPropertyGrid::SetCurControlBoldFont()
{
- wxASSERT( m_wndEditor );
- m_wndEditor->SetFont( m_captionFont );
+ wxWindow* editor = GetEditorControl();
+ editor->SetFont( m_captionFont );
}
// -----------------------------------------------------------------------
// 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;
+ r.x = 0;
+ r.width = GetClientSize().x;
// Repaint this rectangle
DrawItems( dc, r.y, r.y + r.height, &r );
const wxPGProperty* firstSelected = GetSelection();
const wxPropertyGridPageState* state = m_pState;
+ const wxArrayInt& colWidths = state->m_colWidths;
#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
bool wasSelectedPainted = false;
unsigned int si;
int sx = x;
- for ( si=0; si<state->m_colWidths.size(); si++ )
+ for ( si=0; si<colWidths.size(); si++ )
{
- sx += state->m_colWidths[si];
+ sx += colWidths[si];
dc.DrawLine( sx, y, sx, y2 );
}
m_marginWidth,
lh );
- if ( p->IsCategory() )
+ // Default cell rect fill the entire row
+ wxRect cellRect(greyDepthX, y,
+ gridWidth - greyDepth + 2, rowHeight-1 );
+
+ bool isCategory = p->IsCategory();
+
+ if ( isCategory )
{
- // Captions have their cell areas merged as one
dc.SetFont(m_captionFont);
fontChanged = true;
- wxRect cellRect(greyDepthX, y, gridWidth - greyDepth + 2, rowHeight-1 );
if ( renderFlags & wxPGCellRenderer::DontUseCellBgCol )
{
{
dc.SetTextForeground(rowFgCol);
}
-
- wxPGCellRenderer* renderer = p->GetCellRenderer(0);
- renderer->Render( dc, cellRect, this, p, 0, -1, renderFlags );
-
- // Tree Item Button
- if ( !HasFlag(wxPG_HIDE_MARGIN) && p->HasVisibleChildren() )
- DrawExpanderButton( dc, butRect, p );
}
else
{
if ( butRect.x > 0 )
butRect.x += IN_CELL_EXPANDER_BUTTON_X_ADJUST;
- if ( p->m_flags & wxPG_PROP_MODIFIED && (windowStyle & wxPG_BOLD_MODIFIED) )
+ if ( p->m_flags & wxPG_PROP_MODIFIED &&
+ (windowStyle & wxPG_BOLD_MODIFIED) )
{
dc.SetFont(m_captionFont);
fontChanged = true;
}
- unsigned int ci;
- int cellX = x + 1;
- int nextCellWidth = state->m_colWidths[0] -
- (greyDepthX - m_marginWidth);
- wxRect cellRect(greyDepthX+1, y, 0, rowHeight-1);
- int textXAdd = textMarginHere - greyDepthX;
+ // Magic fine-tuning for non-category rows
+ cellRect.x += 1;
+ }
+
+ int firstCellWidth = colWidths[0] - (greyDepthX - m_marginWidth);
+ int firstCellX = cellRect.x;
+
+ // Calculate cellRect.x for the last cell
+ unsigned int ci = 0;
+ int cellX = x + 1;
+ for ( ci=0; ci<colWidths.size(); ci++ )
+ cellX += colWidths[ci];
+ cellRect.x = cellX;
+
+ // Draw cells from back to front so that we can easily tell if the
+ // cell on the right was empty from text
+ bool prevFilled = true;
+ ci = colWidths.size();
+ do
+ {
+ ci--;
+
+ int textXAdd = 0;
+
+ if ( ci == 0 )
+ {
+ textXAdd = textMarginHere - greyDepthX;
+ cellRect.width = firstCellWidth;
+ cellRect.x = firstCellX;
+ }
+ else
+ {
+ int colWidth = colWidths[ci];
+ cellRect.width = colWidth;
+ cellRect.x -= colWidth;
+ }
- for ( ci=0; ci<state->m_colWidths.size(); ci++ )
+ // Merge with column to the right?
+ if ( !prevFilled && isCategory )
{
- cellRect.width = nextCellWidth - 1;
+ cellRect.width += colWidths[ci+1];
+ }
+
+ if ( !isCategory )
+ cellRect.width -= 1;
- wxWindow* cellEditor = NULL;
- int cellRenderFlags = renderFlags;
+ wxWindow* cellEditor = NULL;
+ int cellRenderFlags = renderFlags;
- // Tree Item Button (must be drawn before clipping is set up)
- if ( ci == 0 && !HasFlag(wxPG_HIDE_MARGIN) && p->HasVisibleChildren() )
- DrawExpanderButton( dc, butRect, p );
+ // Tree Item Button (must be drawn before clipping is set up)
+ if ( ci == 0 && !HasFlag(wxPG_HIDE_MARGIN) && p->HasVisibleChildren() )
+ DrawExpanderButton( dc, butRect, p );
- // Background
- if ( isSelected && (ci == 1 || ci == m_selColumn) )
+ // Background
+ if ( isSelected && (ci == 1 || ci == m_selColumn) )
+ {
+ if ( p == firstSelected )
{
- if ( p == firstSelected )
- {
- if ( ci == 1 && m_wndEditor )
- cellEditor = m_wndEditor;
- else if ( ci == m_selColumn && m_labelEditor )
- cellEditor = m_labelEditor;
- }
+ 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);
+ 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);
+ if ( p->IsEnabled() )
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
+ }
+ else
+ {
+ if ( renderFlags & wxPGCellRenderer::DontUseCellBgCol )
{
- if ( renderFlags & wxPGCellRenderer::DontUseCellBgCol )
- {
- dc.SetBrush(rowBgBrush);
- dc.SetPen(rowBgCol);
- }
+ dc.SetBrush(rowBgBrush);
+ dc.SetPen(rowBgCol);
+ }
- if ( renderFlags & wxPGCellRenderer::DontUseCellFgCol )
- {
- dc.SetTextForeground(rowFgCol);
- }
+ if ( renderFlags & wxPGCellRenderer::DontUseCellFgCol )
+ {
+ dc.SetTextForeground(rowFgCol);
}
+ }
- dc.SetClippingRegion(cellRect);
+ dc.SetClippingRegion(cellRect);
- cellRect.x += textXAdd;
- cellRect.width -= textXAdd;
+ cellRect.x += textXAdd;
+ cellRect.width -= textXAdd;
- // Foreground
- if ( !cellEditor )
+ // Foreground
+ if ( !cellEditor )
+ {
+ wxPGCellRenderer* renderer;
+ int cmnVal = p->GetCommonValue();
+ if ( cmnVal == -1 || ci != 1 )
{
- wxPGCellRenderer* renderer;
- int cmnVal = p->GetCommonValue();
- if ( cmnVal == -1 || ci != 1 )
- {
- renderer = p->GetCellRenderer(ci);
- renderer->Render( dc, cellRect, this, p, ci, -1,
- cellRenderFlags );
- }
- else
- {
- renderer = GetCommonValue(cmnVal)->GetRenderer();
- renderer->Render( dc, cellRect, this, p, ci, -1,
- cellRenderFlags );
- }
+ renderer = p->GetCellRenderer(ci);
+ prevFilled = renderer->Render(dc, cellRect, this,
+ p, ci, -1,
+ cellRenderFlags );
+ }
+ else
+ {
+ renderer = GetCommonValue(cmnVal)->GetRenderer();
+ prevFilled = renderer->Render(dc, cellRect, this,
+ p, ci, -1,
+ cellRenderFlags );
}
-
- cellX += state->m_colWidths[ci];
- if ( ci < (state->m_colWidths.size()-1) )
- nextCellWidth = state->m_colWidths[ci+1];
- cellRect.x = cellX;
- dc.DestroyClippingRegion(); // Is this really necessary?
- textXAdd = 0;
}
+ else
+ {
+ prevFilled = true;
+ }
+
+ dc.DestroyClippingRegion(); // Is this really necessary?
}
+ while ( ci > 0 );
if ( fontChanged )
dc.SetFont(normalFont);
//
// Return rect which encloses the given property range
+ // (in logical grid coordinates)
+ //
int visTop = p1->GetY();
int visBottom;
wxRect r = GetPropertyRect(p1, p2);
if ( r.width > 0 )
{
+ // Convert rectangle from logical grid coordinates to physical ones
+ int vx, vy;
+ GetViewStart(&vx, &vy);
+ vx *= wxPG_PIXELS_PER_UNIT;
+ vy *= wxPG_PIXELS_PER_UNIT;
+ r.x -= vx;
+ r.y -= vy;
RefreshRect(r);
}
}
// Call to SetSplitterPosition will always disable splitter auto-centering
// if parent window is shown.
-void wxPropertyGrid::DoSetSplitterPosition_( int newxpos, bool refresh,
- int splitterIndex,
- bool allPages )
+void wxPropertyGrid::DoSetSplitterPosition( int newxpos,
+ int splitterIndex,
+ int flags )
{
if ( ( newxpos < wxPG_DRAG_MARGIN ) )
return;
wxPropertyGridPageState* state = m_pState;
- state->DoSetSplitterPosition( newxpos, splitterIndex, allPages );
+ if ( flags & wxPG_SPLITTER_FROM_EVENT )
+ state->m_dontCenterSplitter = true;
+
+ state->DoSetSplitterPosition(newxpos, splitterIndex, flags);
- if ( refresh )
+ if ( flags & wxPG_SPLITTER_REFRESH )
{
if ( GetSelection() )
CorrectEditorWidgetSizeX();
Refresh();
}
+
+ return;
}
// -----------------------------------------------------------------------
-void wxPropertyGrid::CenterSplitter( bool enableAutoCentering )
+void wxPropertyGrid::ResetColumnSizes( bool enableAutoResizing )
+{
+ wxPropertyGridPageState* state = m_pState;
+ if ( state )
+ state->ResetColumnSizes(0);
+
+ if ( enableAutoResizing && HasFlag(wxPG_SPLITTER_AUTO_CENTER) )
+ m_pState->m_dontCenterSplitter = false;
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::CenterSplitter( bool enableAutoResizing )
{
SetSplitterPosition( m_width/2 );
- if ( enableAutoCentering && HasFlag(wxPG_SPLITTER_AUTO_CENTER) )
+ if ( enableAutoResizing && HasFlag(wxPG_SPLITTER_AUTO_CENTER) )
m_pState->m_dontCenterSplitter = false;
}
if ( m_inDoPropertyChanged )
return true;
- wxWindow* editor = GetEditorControl();
wxPGProperty* selected = GetSelection();
m_pState->m_anyModified = 1;
changedProperty->SetValue(value, &m_chgInfo_valueList, wxPG_SETVAL_BY_USER);
+ // NB: Call GetEditorControl() as late as possible, because OnSetValue()
+ // and perhaps other user-defined virtual functions may change it.
+ wxWindow* editor = GetEditorControl();
+
// Set as Modified (not if dragging just began)
if ( !(p->m_flags & wxPG_PROP_MODIFIED) )
{
// Runs wxValidator for the selected property
bool wxPropertyGrid::DoEditorValidate()
{
+#if wxUSE_VALIDATORS
+ wxRecursionGuard guard(m_validatingEditor);
+ if ( guard.IsInside() )
+ return false;
+
+ wxPGProperty* selected = GetSelection();
+ if ( selected )
+ {
+ wxWindow* wnd = GetEditorControl();
+
+ wxValidator* validator = selected->GetValidator();
+ if ( validator && wnd )
+ {
+ validator->SetWindow(wnd);
+ if ( !validator->Validate(this) )
+ return false;
+ }
+ }
+#endif
return true;
}
void wxPropertyGrid::HandleCustomEditorEvent( wxEvent &event )
{
+ // It is possible that this handler receives event even before
+ // the control has been properly initialized. Let's skip the
+ // event handling in that case.
+ if ( !m_pState )
+ return;
+
+ // Don't care about the event if it originated from the
+ // 'label editor'. In this function we only care about the
+ // property value editor.
+ if ( m_labelEditor && event.GetId() == m_labelEditor->GetId() )
+ {
+ event.Skip();
+ return;
+ }
+
wxPGProperty* selected = GetSelection();
// Somehow, event is handled after property has been deselected.
m_chgInfo_changedProperty = NULL;
- m_iFlags &= ~(wxPG_FL_VALIDATION_FAILED|wxPG_FL_VALUE_CHANGE_IN_EVENT);
+ m_iFlags &= ~wxPG_FL_VALUE_CHANGE_IN_EVENT;
//
// Filter out excess wxTextCtrl modified events
- if ( event.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED &&
- wnd &&
- wnd->IsKindOf(CLASSINFO(wxTextCtrl)) )
+ if ( event.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED && wnd )
{
- wxTextCtrl* tc = (wxTextCtrl*) wnd;
+ if ( wnd->IsKindOf(CLASSINFO(wxTextCtrl)) )
+ {
+ wxTextCtrl* tc = (wxTextCtrl*) wnd;
- wxString newTcValue = tc->GetValue();
- if ( m_prevTcValue == newTcValue )
- return;
+ wxString newTcValue = tc->GetValue();
+ if ( m_prevTcValue == newTcValue )
+ return;
+ m_prevTcValue = newTcValue;
+ }
+ else if ( wnd->IsKindOf(CLASSINFO(wxComboCtrl)) )
+ {
+ wxComboCtrl* cc = (wxComboCtrl*) wnd;
- m_prevTcValue = newTcValue;
+ wxString newTcValue = cc->GetTextCtrl()->GetValue();
+ if ( m_prevTcValue == newTcValue )
+ return;
+ m_prevTcValue = newTcValue;
+ }
}
SetInternalFlag(wxPG_FL_IN_HANDLECUSTOMEDITOREVENT);
GetViewStart(&vx, &vy);
vy *= wxPG_PIXELS_PER_UNIT;
- // TODO: If custom image detection changes from current, change this.
- if ( m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE )
+ if ( column == 1 )
+ {
+ // TODO: If custom image detection changes from current, change this.
+ if ( m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE )
+ {
+ //m_iFlags |= wxPG_FL_CUR_USES_CUSTOM_IMAGE;
+ int iw = p->OnMeasureImage().x;
+ if ( iw < 1 )
+ iw = wxPG_CUSTOM_IMAGE_WIDTH;
+ imageOffset = p->GetImageOffset(iw);
+ }
+ }
+ else if ( column == 0 )
{
- //m_iFlags |= wxPG_FL_CUR_USES_CUSTOM_IMAGE;
- int iw = p->OnMeasureImage().x;
- if ( iw < 1 )
- iw = wxPG_CUSTOM_IMAGE_WIDTH;
- imageOffset = p->GetImageOffset(iw);
+ splitterX += (p->m_depth - 1) * m_subgroup_extramargin;
}
return wxRect
m_curcursor = type;
}
+// -----------------------------------------------------------------------
+
+wxString
+wxPropertyGrid::GetUnspecifiedValueText( int argFlags ) const
+{
+ const wxPGCell& ua = GetUnspecifiedValueAppearance();
+
+ if ( ua.HasText() &&
+ !(argFlags & wxPG_FULL_VALUE) &&
+ !(argFlags & wxPG_EDITABLE_VALUE) )
+ return ua.GetText();
+
+ return wxEmptyString;
+}
+
// -----------------------------------------------------------------------
// wxPropertyGrid property selection, editor creation
// -----------------------------------------------------------------------
m_propGrid->HandleCustomEditorEvent(event);
+ //
+ // NB: On wxMSW, a wxTextCtrl with wxTE_PROCESS_ENTER
+ // may beep annoyingly if that event is skipped
+ // and passed to parent event handler.
+ if ( event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER )
+ return true;
+
return wxEvtHandler::ProcessEvent(event);
}
int splitterX = GetSplitterPosition();
m_editorFocused = 0;
m_iFlags |= wxPG_FL_PRIMARY_FILLS_ENTIRE;
- if ( p != prevFirstSel )
- m_iFlags &= ~(wxPG_FL_VALIDATION_FAILED);
wxASSERT( m_wndEditor == NULL );
wxRect grect = GetEditorWidgetRect(p, m_selColumn);
wxPoint goodPos = grect.GetPosition();
+ // Editor appearance can now be considered clear
+ m_editorAppearance.SetEmptyData();
+
const wxPGEditor* editor = p->GetEditorClass();
wxCHECK_MSG(editor, false,
wxT("NULL editor class not allowed"));
p->GetEditorClass()->OnFocus(p, primaryCtrl);
}
+ else
+ {
+ if ( p->IsValueUnspecified() )
+ SetEditorAppearance(m_unspecifiedAppearance,
+ true);
+ }
}
if ( m_wndEditor2 )
editorClass->UpdateControl(p, wnd);
if ( p->IsValueUnspecified() )
- editorClass ->SetValueToUnspecified(p, wnd);
+ SetEditorAppearance(m_unspecifiedAppearance, true);
}
// -----------------------------------------------------------------------
void wxPropertyGrid::RecalculateVirtualSize( int forceXPos )
{
- if ( (m_iFlags & wxPG_FL_RECALCULATING_VIRTUAL_SIZE) || m_frozen )
+ // Don't check for !HasInternalFlag(wxPG_FL_INITIALIZED) here. Otherwise
+ // virtual size calculation may go wrong.
+ if ( HasInternalFlag(wxPG_FL_RECALCULATING_VIRTUAL_SIZE) ||
+ m_frozen ||
+ !m_pState )
return;
//
unsigned int selFlags,
unsigned int column )
{
+ // selFlags should have wxPG_SEL_NOVALIDATE if event is not
+ // vetoable.
+
// Send property grid event of specific type and with specific property
wxPropertyGridEvent evt( eventType, m_eventObject->GetId() );
evt.SetPropertyGrid(this);
evt.SetCanVeto(true);
}
+ wxPropertyGridEvent* prevProcessedEvent = m_processedEvent;
m_processedEvent = &evt;
m_eventObject->HandleWindowEvent(evt);
- m_processedEvent = NULL;
+ m_processedEvent = prevProcessedEvent;
return evt.WasVetoed();
}
if ( event.GetEventType() == wxEVT_LEFT_DCLICK )
{
// Double-clicking the splitter causes auto-centering
- CenterSplitter( true );
+ if ( m_pState->GetColumnCount() <= 2 )
+ {
+ ResetColumnSizes( true );
+
+ SendEvent(wxEVT_PG_COL_DRAGGING,
+ m_propHover,
+ NULL,
+ wxPG_SEL_NOVALIDATE,
+ (unsigned int)m_draggedSplitter);
+ }
}
else if ( m_dragStatus == 0 )
{
// send event
DoEndLabelEdit(true, wxPG_SEL_NOVALIDATE);
- if ( m_wndEditor )
+ // Allow application to veto dragging
+ if ( !SendEvent(wxEVT_PG_COL_BEGIN_DRAG,
+ p, NULL, 0,
+ (unsigned int)splitterHit) )
{
- // Changes must be committed here or the
- // value won't be drawn correctly
- if ( !CommitChangesFromEditor() )
- return res;
+ if ( m_wndEditor )
+ {
+ // Changes must be committed here or the
+ // value won't be drawn correctly
+ if ( !CommitChangesFromEditor() )
+ return res;
- m_wndEditor->Show ( false );
- }
+ m_wndEditor->Show ( false );
+ }
- if ( !(m_iFlags & wxPG_FL_MOUSE_CAPTURED) )
- {
- CaptureMouse();
- m_iFlags |= wxPG_FL_MOUSE_CAPTURED;
- }
+ if ( !(m_iFlags & wxPG_FL_MOUSE_CAPTURED) )
+ {
+ CaptureMouse();
+ m_iFlags |= wxPG_FL_MOUSE_CAPTURED;
+ }
- m_dragStatus = 1;
- m_draggedSplitter = splitterHit;
- m_dragOffset = splitterHitOffset;
+ m_dragStatus = 1;
+ m_draggedSplitter = splitterHit;
+ m_dragOffset = splitterHitOffset;
- #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
- // Fixes button disappearance bug
- if ( m_wndEditor2 )
- m_wndEditor2->Show ( false );
- #endif
+ #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
+ // Fixes button disappearance bug
+ if ( m_wndEditor2 )
+ m_wndEditor2->Show ( false );
+ #endif
- m_startingSplitterX = x - splitterHitOffset;
+ m_startingSplitterX = x - splitterHitOffset;
+ }
}
}
}
{
int newSplitterX = x - m_dragOffset;
- int splitterX = x - splitterHitOffset;
// Splitter redraw required?
if ( newSplitterX != splitterX )
{
// Move everything
- state->m_dontCenterSplitter = true;
- state->DoSetSplitterPosition(newSplitterX,
- m_draggedSplitter,
- false);
- state->m_fSplitterX = (float) newSplitterX;
-
- if ( GetSelection() )
- CorrectEditorWidgetSizeX();
-
- Update();
- Refresh();
+ DoSetSplitterPosition(newSplitterX,
+ m_draggedSplitter,
+ wxPG_SPLITTER_REFRESH |
+ wxPG_SPLITTER_FROM_EVENT);
+
+ SendEvent(wxEVT_PG_COL_DRAGGING,
+ m_propHover,
+ NULL,
+ wxPG_SEL_NOVALIDATE,
+ (unsigned int)m_draggedSplitter);
}
m_dragStatus = 2;
// (it is only here as a reminder to not to do it)
//splitterX = x;
- // Disable splitter auto-centering
- state->m_dontCenterSplitter = true;
+ SendEvent(wxEVT_PG_COL_END_DRAG,
+ m_propHover,
+ NULL,
+ wxPG_SEL_NOVALIDATE,
+ (unsigned int)m_draggedSplitter);
+
+ // Disable splitter auto-centering (but only if moved any -
+ // otherwise we end up disabling auto-center even after a
+ // recentering double-click).
+ int posDiff = abs(m_startingSplitterX -
+ GetSplitterPosition(m_draggedSplitter));
+
+ if ( posDiff > 1 )
+ state->m_dontCenterSplitter = true;
// This is necessary to return cursor
if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED )
return;
}
- // Except for TAB and ESC, handle child control events in child control
- if ( fromChild )
+ // Except for TAB, ESC, and any keys specifically dedicated to
+ // wxPropertyGrid itself, handle child control events in child control.
+ if ( fromChild &&
+ wxPGFindInVector(m_dedicatedKeys, keycode) == wxNOT_FOUND )
{
// Only propagate event if it had modifiers
if ( !event.HasModifiers() )
{
p = wxPropertyGridIterator::OneStep( m_pState, wxPG_ITERATE_VISIBLE, p, selectDir );
if ( p )
- DoSelectProperty(p);
+ {
+ int selFlags = 0;
+ int reopenLabelEditorCol = -1;
+
+ if ( editorFocused )
+ {
+ // If editor was focused, then make the next editor
+ // focused as well
+ selFlags |= wxPG_SEL_FOCUS;
+ }
+ else
+ {
+ // Also maintain the same label editor focus state
+ if ( m_labelEditor )
+ reopenLabelEditorCol = m_selColumn;
+ }
+
+ DoSelectProperty(p, selFlags);
+
+ if ( reopenLabelEditorCol >= 0 )
+ DoBeginLabelEdit(reopenLabelEditorCol);
+ }
wasHandled = true;
}
}
if ( tlp != m_tlp )
OnTLPChanging(tlp);
}
+
+ //
+ // Resolve pending property removals
+ if ( m_deletedProperties.size() > 0 )
+ {
+ wxArrayPGProperty& arr = m_deletedProperties;
+ for ( unsigned int i=0; i<arr.size(); i++ )
+ {
+ DeleteProperty(arr[i]);
+ }
+ arr.clear();
+ }
+ if ( m_removedProperties.size() > 0 )
+ {
+ wxArrayPGProperty& arr = m_removedProperties;
+ for ( unsigned int i=0; i<arr.size(); i++ )
+ {
+ RemoveProperty(arr[i]);
+ }
+ arr.clear();
+ }
}
bool wxPropertyGrid::IsEditorFocused() const
void wxPropertyGrid::HandleFocusChange( wxWindow* newFocused )
{
unsigned int oldFlags = m_iFlags;
+ bool wasEditorFocused = false;
+ wxWindow* wndEditor = m_wndEditor;
m_iFlags &= ~(wxPG_FL_FOCUSED);
// This must be one of nextFocus' parents.
while ( parent )
{
+ if ( parent == wndEditor )
+ {
+ wasEditorFocused = true;
+ }
// Use m_eventObject, which is either wxPropertyGrid or
// wxPropertyGridManager, as appropriate.
- if ( parent == m_eventObject )
+ else if ( parent == m_eventObject )
{
m_iFlags |= wxPG_FL_FOCUSED;
break;
parent = parent->GetParent();
}
+ // Notify editor control when it receives a focus
+ if ( wasEditorFocused && m_curFocused != newFocused )
+ {
+ wxPGProperty* p = GetSelection();
+ if ( p )
+ {
+ const wxPGEditor* editor = p->GetEditorClass();
+ ResetEditorAppearance();
+ editor->OnFocus(p, GetEditorControl());
+ }
+ }
+
m_curFocused = newFocused;
if ( (m_iFlags & wxPG_FL_FOCUSED) !=
wxDEFINE_EVENT( wxEVT_PG_DOUBLE_CLICK, wxPropertyGridEvent );
wxDEFINE_EVENT( wxEVT_PG_LABEL_EDIT_BEGIN, wxPropertyGridEvent );
wxDEFINE_EVENT( wxEVT_PG_LABEL_EDIT_ENDING, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_COL_BEGIN_DRAG, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_COL_DRAGGING, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_COL_END_DRAG, wxPropertyGridEvent );
// -----------------------------------------------------------------------