X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0da1f1c4cc2fd8e8b6774b8e20b941bee759075f..9914bfbb77f48baf869b63aff58feb2b145ff4d3:/src/propgrid/propgrid.cpp diff --git a/src/propgrid/propgrid.cpp b/src/propgrid/propgrid.cpp index a87ebc07cc..e98e86097c 100644 --- a/src/propgrid/propgrid.cpp +++ b/src/propgrid/propgrid.cpp @@ -115,6 +115,11 @@ //#define wxPG_TOOLTIP_DELAY 1000 +// This is the number of pixels the expander button inside +// property cells (i.e. not in the grey margin area are +// adjusted. +#define IN_CELL_EXPANDER_BUTTON_X_ADJUST 2 + // ----------------------------------------------------------------------- #if wxUSE_INTL @@ -195,7 +200,10 @@ wxPGGlobalVarsClass::wxPGGlobalVarsClass() 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; } @@ -320,6 +328,7 @@ void wxPropertyGrid::Init1() if ( wxPGGlobalVars->m_mapEditorClasses.empty() ) wxPropertyGrid::RegisterDefaultEditors(); + m_validatingEditor = 0; m_iFlags = 0; m_pState = NULL; m_wndEditor = m_wndEditor2 = NULL; @@ -340,6 +349,9 @@ void wxPropertyGrid::Init1() 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 ); @@ -436,9 +448,9 @@ void wxPropertyGrid::Init2() 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(); @@ -662,7 +674,7 @@ void wxPropertyGrid::Thaw() // Force property re-selection // NB: We must copy the selection. wxArrayPGProperty selection = m_pState->m_selection; - DoSetSelection(selection, wxPG_SEL_FORCE); + DoSetSelection(selection, wxPG_SEL_FORCE | wxPG_SEL_NONVISIBLE); } } @@ -774,9 +786,12 @@ bool wxPropertyGrid::AddToSelectionFromInputEvent( wxPGProperty* prop, 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 ) { @@ -794,21 +809,24 @@ bool wxPropertyGrid::AddToSelectionFromInputEvent( wxPGProperty* prop, } 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); @@ -818,6 +836,59 @@ bool wxPropertyGrid::AddToSelectionFromInputEvent( wxPGProperty* prop, 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; iGetY(); + 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); @@ -1001,11 +1072,17 @@ void wxPropertyGrid::DoEndLabelEdit( bool commit, int selFlags ) } 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); } @@ -1320,6 +1397,8 @@ void wxPropertyGrid::RegainColours() 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) ) @@ -1327,6 +1406,8 @@ void wxPropertyGrid::RegainColours() 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) ) @@ -1398,6 +1479,7 @@ void wxPropertyGrid::SetCellBackgroundColour( const wxColour& col ) m_coloursCustomized |= 0x08; m_propertyDefaultCell.GetData()->SetBgCol(col); + m_unspecifiedAppearance.SetBgCol(col); Refresh(); } @@ -1410,6 +1492,7 @@ void wxPropertyGrid::SetCellTextColour( const wxColour& col ) m_coloursCustomized |= 0x10; m_propertyDefaultCell.GetData()->SetFgCol(col); + m_unspecifiedAppearance.SetFgCol(col); Refresh(); } @@ -1488,6 +1571,9 @@ void wxPropertyGrid::PrepareAfterItemsAdded() Sort(wxPG_SORT_TOP_LEVEL_ONLY); RecalculateVirtualSize(); + + // Fix editor position + CorrectEditorWidgetPosY(); } // ----------------------------------------------------------------------- @@ -1740,9 +1826,8 @@ void wxPropertyGrid::OnPaint( wxPaintEvent& WXUNUSED(event) ) // 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 ); @@ -1982,13 +2067,13 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc, long windowStyle = m_windowStyle; int xRelMod = 0; - int yRelMod = 0; // // With wxPG_DOUBLE_BUFFER, do double buffering // - buffer's y = 0, so align drawRect and coordinates to that // #if wxPG_DOUBLE_BUFFER + int yRelMod = 0; wxRect cr2; @@ -2048,6 +2133,7 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc, const wxPGProperty* firstSelected = GetSelection(); const wxPropertyGridPageState* state = m_pState; + const wxArrayInt& colWidths = state->m_colWidths; #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT bool wasSelectedPainted = false; @@ -2147,9 +2233,9 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc, unsigned int si; int sx = x; - for ( si=0; sim_colWidths.size(); si++ ) + for ( si=0; sim_colWidths[si]; + sx += colWidths[si]; dc.DrawLine( sx, y, sx, y2 ); } @@ -2245,12 +2331,16 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc, 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 ) { @@ -2262,121 +2352,154 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc, { 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 ( p->m_flags & wxPG_PROP_MODIFIED && (windowStyle & wxPG_BOLD_MODIFIED) ) + // Fine tune button rectangle to actually fit the cell + if ( butRect.x > 0 ) + butRect.x += IN_CELL_EXPANDER_BUTTON_X_ADJUST; + + 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; cim_colWidths.size(); ci++ ) + int textXAdd = 0; + + if ( ci == 0 ) { - cellRect.width = nextCellWidth - 1; + textXAdd = textMarginHere - greyDepthX; + cellRect.width = firstCellWidth; + cellRect.x = firstCellX; + } + else + { + int colWidth = colWidths[ci]; + cellRect.width = colWidth; + cellRect.x -= colWidth; + } + + // Merge with column to the right? + if ( !prevFilled && isCategory ) + { + cellRect.width += colWidths[ci+1]; + } - wxWindow* cellEditor = NULL; - int cellRenderFlags = renderFlags; + if ( !isCategory ) + cellRect.width -= 1; - // Tree Item Button (must be drawn before clipping is set up) - if ( ci == 0 && !HasFlag(wxPG_HIDE_MARGIN) && p->HasVisibleChildren() ) - DrawExpanderButton( dc, butRect, p ); + wxWindow* cellEditor = NULL; + int cellRenderFlags = renderFlags; - // Background - if ( isSelected && (ci == 1 || ci == m_selColumn) ) + // 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) ) + { + 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); @@ -2414,6 +2537,8 @@ wxRect wxPropertyGrid::GetPropertyRect( const wxPGProperty* p1, const wxPGProper // // Return rect which encloses the given property range + // (in logical grid coordinates) + // int visTop = p1->GetY(); int visBottom; @@ -2456,6 +2581,13 @@ void wxPropertyGrid::DrawItems( const wxPGProperty* p1, const wxPGProperty* p2 ) 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); } } @@ -2669,32 +2801,49 @@ void wxPropertyGrid::SwitchState( wxPropertyGridPageState* pNewState ) // 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::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 enableAutoCentering ) +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; } @@ -3263,6 +3412,25 @@ wxVariant wxPropertyGrid::GetUncommittedPropertyValue() // 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; } @@ -3270,6 +3438,21 @@ bool wxPropertyGrid::DoEditorValidate() 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. @@ -3295,21 +3478,30 @@ void wxPropertyGrid::HandleCustomEditorEvent( wxEvent &event ) 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); @@ -3432,14 +3624,21 @@ wxRect wxPropertyGrid::GetEditorWidgetRect( wxPGProperty* p, int column ) const 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 @@ -3542,6 +3741,21 @@ void wxPropertyGrid::CustomSetCursor( int type, bool override ) 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 // ----------------------------------------------------------------------- @@ -3568,6 +3782,13 @@ private: 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); } @@ -3800,8 +4021,6 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags ) 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 ); @@ -3823,6 +4042,9 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags ) 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")); @@ -3892,6 +4114,12 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags ) p->GetEditorClass()->OnFocus(p, primaryCtrl); } + else + { + if ( p->IsValueUnspecified() ) + SetEditorAppearance(m_unspecifiedAppearance, + true); + } } if ( m_wndEditor2 ) @@ -4058,7 +4286,7 @@ void wxPropertyGrid::RefreshEditor() editorClass->UpdateControl(p, wnd); if ( p->IsValueUnspecified() ) - editorClass ->SetValueToUnspecified(p, wnd); + SetEditorAppearance(m_unspecifiedAppearance, true); } // ----------------------------------------------------------------------- @@ -4172,7 +4400,11 @@ bool wxPropertyGrid::DoHideProperty( wxPGProperty* p, bool hide, int flags ) 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; // @@ -4334,6 +4566,9 @@ bool wxPropertyGrid::SendEvent( int eventType, wxPGProperty* p, 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); @@ -4356,9 +4591,10 @@ bool wxPropertyGrid::SendEvent( int eventType, wxPGProperty* p, evt.SetCanVeto(true); } + wxPropertyGridEvent* prevProcessedEvent = m_processedEvent; m_processedEvent = &evt; m_eventObject->HandleWindowEvent(evt); - m_processedEvent = NULL; + m_processedEvent = prevProcessedEvent; return evt.WasVetoed(); } @@ -4457,7 +4693,16 @@ bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &even 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 ) { @@ -4468,33 +4713,39 @@ bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &even // 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; + } } } } @@ -4506,6 +4757,10 @@ bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &even { int nx = x + m_marginWidth - marginEnds; // Normalize x. + // Fine tune cell button x + if ( !p->IsCategory() ) + nx -= IN_CELL_EXPANDER_BUTTON_X_ADJUST; + if ( (nx >= m_gutterWidth && nx < (m_gutterWidth+m_iconWidth)) ) { int y2 = y % m_lineHeight; @@ -4615,23 +4870,21 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, { 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; @@ -4849,8 +5102,20 @@ bool wxPropertyGrid::HandleMouseUp( int x, unsigned int WXUNUSED(y), // (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 ) @@ -5430,6 +5695,27 @@ void wxPropertyGrid::OnIdle( wxIdleEvent& WXUNUSED(event) ) 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 0 ) + { + wxArrayPGProperty& arr = m_removedProperties; + for ( unsigned int i=0; iGetParent(); } + // 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) != @@ -5767,6 +6071,9 @@ 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 ); +wxDEFINE_EVENT( wxEVT_PG_COL_BEGIN_DRAG, wxPropertyGridEvent ); +wxDEFINE_EVENT( wxEVT_PG_COL_DRAGGING, wxPropertyGridEvent ); +wxDEFINE_EVENT( wxEVT_PG_COL_END_DRAG, wxPropertyGridEvent ); // -----------------------------------------------------------------------