X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c579ac6280f819e8e6fb2adf80d345d84b0bfcfe..d6b17e1aa398f19b9f1b7024eb3923da01430aff:/src/propgrid/propgrid.cpp diff --git a/src/propgrid/propgrid.cpp b/src/propgrid/propgrid.cpp index 3030939a1a..c11f78d36f 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 @@ -233,113 +238,6 @@ void wxPropertyGridInitGlobalsIfNeeded() { } -// ----------------------------------------------------------------------- -// wxPGCanvas -// ----------------------------------------------------------------------- - -// -// wxPGCanvas acts as a graphics sub-window of the -// wxScrolledWindow that wxPropertyGrid is. -// -class wxPGCanvas : public wxPanel -{ -public: - wxPGCanvas() : wxPanel() - { - } - virtual ~wxPGCanvas() { } - -protected: - void OnMouseMove( wxMouseEvent &event ) - { - wxPropertyGrid* pg = wxStaticCast(GetParent(), wxPropertyGrid); - pg->OnMouseMove( event ); - } - - void OnMouseClick( wxMouseEvent &event ) - { - wxPropertyGrid* pg = wxStaticCast(GetParent(), wxPropertyGrid); - pg->OnMouseClick( event ); - } - - void OnMouseUp( wxMouseEvent &event ) - { - wxPropertyGrid* pg = wxStaticCast(GetParent(), wxPropertyGrid); - pg->OnMouseUp( event ); - } - - void OnMouseRightClick( wxMouseEvent &event ) - { - wxPropertyGrid* pg = wxStaticCast(GetParent(), wxPropertyGrid); - pg->OnMouseRightClick( event ); - } - - void OnMouseDoubleClick( wxMouseEvent &event ) - { - wxPropertyGrid* pg = wxStaticCast(GetParent(), wxPropertyGrid); - pg->OnMouseDoubleClick( event ); - } - - void OnKey( wxKeyEvent& event ) - { - wxPropertyGrid* pg = wxStaticCast(GetParent(), wxPropertyGrid); - pg->OnKey( event ); - } - - void OnPaint( wxPaintEvent& event ); - - // Always be focussable, even with child windows - virtual void SetCanFocus(bool WXUNUSED(canFocus)) - { wxPanel::SetCanFocus(true); } - - -private: - DECLARE_EVENT_TABLE() - DECLARE_ABSTRACT_CLASS(wxPGCanvas) -}; - - -IMPLEMENT_ABSTRACT_CLASS(wxPGCanvas,wxPanel) - -BEGIN_EVENT_TABLE(wxPGCanvas, wxPanel) - EVT_MOTION(wxPGCanvas::OnMouseMove) - EVT_PAINT(wxPGCanvas::OnPaint) - EVT_LEFT_DOWN(wxPGCanvas::OnMouseClick) - EVT_LEFT_UP(wxPGCanvas::OnMouseUp) - EVT_RIGHT_UP(wxPGCanvas::OnMouseRightClick) - EVT_LEFT_DCLICK(wxPGCanvas::OnMouseDoubleClick) - EVT_KEY_DOWN(wxPGCanvas::OnKey) -END_EVENT_TABLE() - - -void wxPGCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) ) -{ - wxPropertyGrid* pg = wxStaticCast(GetParent(), wxPropertyGrid); - wxASSERT( pg->IsKindOf(CLASSINFO(wxPropertyGrid)) ); - - wxPaintDC dc(this); - - // Don't paint after destruction has begun - if ( !(pg->GetInternalFlags() & wxPG_FL_INITIALIZED) ) - return; - - // 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 ); - - // We assume that the size set when grid is shown - // is what is desired. - pg->SetInternalFlag(wxPG_FL_GOOD_SIZE_SET); -} - // ----------------------------------------------------------------------- // wxPropertyGrid // ----------------------------------------------------------------------- @@ -348,7 +246,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxPropertyGrid, wxScrolledWindow) BEGIN_EVENT_TABLE(wxPropertyGrid, wxScrolledWindow) EVT_IDLE(wxPropertyGrid::OnIdle) - EVT_MOTION(wxPropertyGrid::OnMouseMoveBottom) EVT_PAINT(wxPropertyGrid::OnPaint) EVT_SIZE(wxPropertyGrid::OnResize) EVT_ENTER_WINDOW(wxPropertyGrid::OnMouseEntry) @@ -359,9 +256,14 @@ BEGIN_EVENT_TABLE(wxPropertyGrid, wxScrolledWindow) EVT_SET_FOCUS(wxPropertyGrid::OnFocusEvent) EVT_KILL_FOCUS(wxPropertyGrid::OnFocusEvent) EVT_SYS_COLOUR_CHANGED(wxPropertyGrid::OnSysColourChanged) + EVT_MOTION(wxPropertyGrid::OnMouseMove) + EVT_LEFT_DOWN(wxPropertyGrid::OnMouseClick) + EVT_LEFT_UP(wxPropertyGrid::OnMouseUp) + EVT_RIGHT_UP(wxPropertyGrid::OnMouseRightClick) + EVT_LEFT_DCLICK(wxPropertyGrid::OnMouseDoubleClick) + EVT_KEY_DOWN(wxPropertyGrid::OnKey) END_EVENT_TABLE() - // ----------------------------------------------------------------------- wxPropertyGrid::wxPropertyGrid() @@ -457,8 +359,6 @@ void wxPropertyGrid::Init1() m_coloursCustomized = 0; m_frozen = 0; - m_canvas = NULL; - #if wxPG_DOUBLE_BUFFER m_doubleBuffer = NULL; #endif @@ -511,7 +411,7 @@ void wxPropertyGrid::Init2() } if ( !(m_windowStyle & wxPG_SPLITTER_AUTO_CENTER) ) - m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER; + m_pState->m_dontCenterSplitter = true; if ( m_windowStyle & wxPG_HIDE_CATEGORIES ) { @@ -561,10 +461,9 @@ void wxPropertyGrid::Init2() m_timeCreated = ::wxGetLocalTimeMillis(); - m_canvas = new wxPGCanvas(); - m_canvas->Create(this, wxID_ANY, wxPoint(0, 0), GetClientSize(), - wxWANTS_CHARS | wxCLIP_CHILDREN); - m_canvas->SetBackgroundStyle( wxBG_STYLE_CUSTOM ); + //m_canvas->Create(this, wxID_ANY, wxPoint(0, 0), GetClientSize(), + // wxWANTS_CHARS | wxCLIP_CHILDREN); + SetBackgroundStyle( wxBG_STYLE_CUSTOM ); m_iFlags |= wxPG_FL_INITIALIZED; @@ -619,7 +518,7 @@ wxPropertyGrid::~wxPropertyGrid() m_iFlags &= ~(wxPG_FL_INITIALIZED); if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED ) - m_canvas->ReleaseMouse(); + ReleaseMouse(); // Call with NULL to disconnect event handling if ( GetExtraStyle() & wxPG_EX_ENABLE_TLP_TRACKING ) @@ -662,7 +561,7 @@ wxPropertyGrid::~wxPropertyGrid() bool wxPropertyGrid::Destroy() { if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED ) - m_canvas->ReleaseMouse(); + ReleaseMouse(); return wxScrolledWindow::Destroy(); } @@ -723,7 +622,7 @@ void wxPropertyGrid::SetWindowStyleFlag( long style ) // // Tooltips disabled // - m_canvas->SetToolTip( NULL ); + wxScrolledWindow::SetToolTip( NULL ); } #endif } @@ -762,13 +661,13 @@ void wxPropertyGrid::Thaw() wxScrolledWindow::Thaw(); RecalculateVirtualSize(); #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT - m_canvas->Refresh(); + Refresh(); #endif // 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); } } @@ -880,9 +779,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 ) { @@ -900,21 +802,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); @@ -924,6 +829,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); @@ -1828,13 +1786,33 @@ wxPGProperty* wxPropertyGrid::DoGetItemAtY( int y ) const void wxPropertyGrid::OnPaint( wxPaintEvent& WXUNUSED(event) ) { wxPaintDC dc(this); + PrepareDC(dc); + + // Don't paint after destruction has begun + if ( !HasInternalFlag(wxPG_FL_INITIALIZED) ) + return; + + // Find out where the window is scrolled to + int vx,vy; // Top left corner of client + GetViewStart(&vx,&vy); + vy *= wxPG_PIXELS_PER_UNIT; // Update everything inside the box wxRect r = GetUpdateRegion().GetBox(); - dc.SetPen(m_colEmptySpace); - dc.SetBrush(m_colEmptySpace); - dc.DrawRectangle(r); + r.y += vy; + + // FIXME: This is just a workaround for a bug that causes splitters not + // to paint when other windows are being dragged over the grid. + r.x = 0; + r.width = GetClientSize().x; + + // Repaint this rectangle + DrawItems( dc, r.y, r.y + r.height, &r ); + + // We assume that the size set when grid is shown + // is what is desired. + SetInternalFlag(wxPG_FL_GOOD_SIZE_SET); } // ----------------------------------------------------------------------- @@ -1916,19 +1894,25 @@ void wxPropertyGrid::DrawExpanderButton( wxDC& dc, const wxRect& rect, // topy and bottomy are already unscrolled (ie. physical) // void wxPropertyGrid::DrawItems( wxDC& dc, - unsigned int topy, - unsigned int bottomy, - const wxRect* clipRect ) -{ - if ( m_frozen || m_height < 1 || bottomy < topy || !m_pState ) return; + unsigned int topItemY, + unsigned int bottomItemY, + const wxRect* drawRect ) +{ + if ( m_frozen || + m_height < 1 || + bottomItemY < topItemY || + !m_pState ) + return; m_pState->EnsureVirtualHeight(); - wxRect tempClipRect; - if ( !clipRect ) + wxRect tempDrawRect; + if ( !drawRect ) { - tempClipRect = wxRect(0,topy,m_pState->m_width,bottomy); - clipRect = &tempClipRect; + tempDrawRect = wxRect(0, topItemY, + m_pState->m_width, + bottomItemY); + drawRect = &tempDrawRect; } // items added check @@ -1948,7 +1932,7 @@ void wxPropertyGrid::DrawItems( wxDC& dc, { if ( !m_doubleBuffer ) { - paintFinishY = clipRect->y; + paintFinishY = drawRect->y; dcPtr = NULL; } else @@ -1966,49 +1950,62 @@ void wxPropertyGrid::DrawItems( wxDC& dc, if ( dcPtr ) { - dc.SetClippingRegion( *clipRect ); - paintFinishY = DoDrawItems( *dcPtr, clipRect, isBuffered ); + dc.SetClippingRegion( *drawRect ); + paintFinishY = DoDrawItems( *dcPtr, drawRect, isBuffered ); + int drawBottomY = drawRect->y + drawRect->height; + + // Clear area beyond last painted property + if ( paintFinishY < drawBottomY ) + { + dcPtr->SetPen(m_colEmptySpace); + dcPtr->SetBrush(m_colEmptySpace); + dcPtr->DrawRectangle(0, paintFinishY, + m_width, + drawBottomY ); + } + + dc.DestroyClippingRegion(); } #if wxPG_DOUBLE_BUFFER if ( bufferDC ) { - dc.Blit( clipRect->x, clipRect->y, clipRect->width, clipRect->height, - bufferDC, 0, 0, wxCOPY ); - dc.DestroyClippingRegion(); // Is this really necessary? + dc.Blit( drawRect->x, drawRect->y, drawRect->width, + drawRect->height, + bufferDC, 0, 0, wxCOPY ); delete bufferDC; } #endif } - - // Clear area beyond bottomY? - if ( paintFinishY < (clipRect->y+clipRect->height) ) + else { + // Just clear the area dc.SetPen(m_colEmptySpace); dc.SetBrush(m_colEmptySpace); - dc.DrawRectangle( 0, paintFinishY, m_width, (clipRect->y+clipRect->height) ); + dc.DrawRectangle(*drawRect); } } // ----------------------------------------------------------------------- int wxPropertyGrid::DoDrawItems( wxDC& dc, - const wxRect* clipRect, + const wxRect* drawRect, bool isBuffered ) const { const wxPGProperty* firstItem; const wxPGProperty* lastItem; - firstItem = DoGetItemAtY(clipRect->y); - lastItem = DoGetItemAtY(clipRect->y+clipRect->height-1); + firstItem = DoGetItemAtY(drawRect->y); + lastItem = DoGetItemAtY(drawRect->y+drawRect->height-1); if ( !lastItem ) lastItem = GetLastItem( wxPG_ITERATE_VISIBLE ); if ( m_frozen || m_height < 1 || firstItem == NULL ) - return clipRect->y; + return drawRect->y; - wxCHECK_MSG( !m_pState->m_itemsAdded, clipRect->y, wxT("no items added") ); + wxCHECK_MSG( !m_pState->m_itemsAdded, drawRect->y, + "no items added" ); wxASSERT( m_pState->m_properties->GetChildCount() ); int lh = m_lineHeight; @@ -2016,8 +2013,8 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc, int firstItemTopY; int lastItemBottomY; - firstItemTopY = clipRect->y; - lastItemBottomY = clipRect->y + clipRect->height; + firstItemTopY = drawRect->y; + lastItemBottomY = drawRect->y + drawRect->height; // Align y coordinates to item boundaries firstItemTopY -= firstItemTopY % lh; @@ -2025,19 +2022,22 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc, lastItemBottomY -= 1; // Entire range outside scrolled, visible area? - if ( firstItemTopY >= (int)m_pState->GetVirtualHeight() || lastItemBottomY <= 0 ) - return clipRect->y; - - wxCHECK_MSG( firstItemTopY < lastItemBottomY, clipRect->y, wxT("invalid y values") ); + if ( firstItemTopY >= (int)m_pState->GetVirtualHeight() || + lastItemBottomY <= 0 ) + return drawRect->y; + wxCHECK_MSG( firstItemTopY < lastItemBottomY, + drawRect->y, + "invalid y values" ); /* - wxLogDebug(wxT(" -> DoDrawItems ( \"%s\" -> \"%s\", height=%i (ch=%i), clipRect = 0x%lX )"), + wxLogDebug(" -> DoDrawItems ( \"%s\" -> \"%s\" + "height=%i (ch=%i), drawRect = 0x%lX )", firstItem->GetLabel().c_str(), lastItem->GetLabel().c_str(), (int)(lastItemBottomY - firstItemTopY), (int)m_height, - (unsigned long)clipRect ); + (unsigned long)drawRect ); */ wxRect r; @@ -2045,27 +2045,27 @@ 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 cliprect and coordinates to that + // - buffer's y = 0, so align drawRect and coordinates to that // #if wxPG_DOUBLE_BUFFER + int yRelMod = 0; wxRect cr2; if ( isBuffered ) { - xRelMod = clipRect->x; - yRelMod = clipRect->y; + xRelMod = drawRect->x; + yRelMod = drawRect->y; // - // clipRect conversion - cr2 = *clipRect; + // drawRect conversion + cr2 = *drawRect; cr2.x -= xRelMod; cr2.y -= yRelMod; - clipRect = &cr2; + drawRect = &cr2; firstItemTopY -= yRelMod; lastItemBottomY -= yRelMod; } @@ -2335,6 +2335,10 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc, } else { + // 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); @@ -2459,7 +2463,7 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc, } #endif - return y + yRelMod; + return y; } // ----------------------------------------------------------------------- @@ -2519,7 +2523,7 @@ void wxPropertyGrid::DrawItems( const wxPGProperty* p1, const wxPGProperty* p2 ) wxRect r = GetPropertyRect(p1, p2); if ( r.width > 0 ) { - m_canvas->RefreshRect(r); + RefreshRect(r); } } @@ -2587,10 +2591,7 @@ void wxPropertyGrid::Refresh( bool WXUNUSED(eraseBackground), { PrepareAfterItemsAdded(); - wxWindow::Refresh(false); - if ( m_canvas ) - // TODO: Coordinate translation - m_canvas->Refresh(false, rect); + wxWindow::Refresh(false, rect); #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT // I think this really helps only GTK+1.2 @@ -2700,10 +2701,11 @@ void wxPropertyGrid::SwitchState( wxPropertyGridPageState* pNewState ) { // // Just in case, fully re-center splitter - if ( HasFlag( wxPG_SPLITTER_AUTO_CENTER ) ) - pNewState->m_fSplitterX = -1.0; + //if ( HasFlag( wxPG_SPLITTER_AUTO_CENTER ) ) + // pNewState->m_fSplitterX = -1.0; - pNewState->OnClientWidthChange( pgWidth, pgWidth - pNewState->m_width ); + pNewState->OnClientWidthChange(pgWidth, + pgWidth - pNewState->m_width); } m_propHover = NULL; @@ -2734,31 +2736,38 @@ 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::CenterSplitter( bool enableAutoCentering ) { - SetSplitterPosition( m_width/2, true ); - if ( enableAutoCentering && ( m_windowStyle & wxPG_SPLITTER_AUTO_CENTER ) ) - m_iFlags &= ~(wxPG_FL_DONT_CENTER_SPLITTER); + SetSplitterPosition( m_width/2 ); + if ( enableAutoCentering && HasFlag(wxPG_SPLITTER_AUTO_CENTER) ) + m_pState->m_dontCenterSplitter = false; } // ----------------------------------------------------------------------- @@ -3333,6 +3342,12 @@ 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; + wxPGProperty* selected = GetSelection(); // Somehow, event is handled after property has been deselected. @@ -3487,11 +3502,14 @@ void wxPropertyGrid::HandleCustomEditorEvent( wxEvent &event ) wxRect wxPropertyGrid::GetEditorWidgetRect( wxPGProperty* p, int column ) const { int itemy = p->GetY2(m_lineHeight); - int vy = 0; int splitterX = m_pState->DoGetSplitterPosition(column-1); int colEnd = splitterX + m_pState->m_colWidths[column]; int imageOffset = 0; + int vx, vy; // Top left corner of client + 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 ) { @@ -3597,7 +3615,7 @@ void wxPropertyGrid::CustomSetCursor( int type, bool override ) if ( type == wxCURSOR_SIZEWE ) cursor = m_cursorSizeWE; - m_canvas->SetCursor( *cursor ); + SetCursor( *cursor ); m_curcursor = type; } @@ -3693,7 +3711,7 @@ void wxPropertyGrid::FreeEditors() wxWindow* parent = focus->GetParent(); while ( parent ) { - if ( parent == m_canvas ) + if ( parent == this ) { SetFocusOnCanvas(); break; @@ -3889,10 +3907,11 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags ) m_iFlags &= ~wxPG_FL_FIXED_WIDTH_EDITOR; - wxPGWindowList wndList = editor->CreateControls(this, - p, - goodPos, - grect.GetSize()); + wxPGWindowList wndList = + editor->CreateControls(this, + p, + goodPos, + grect.GetSize()); m_wndEditor = wndList.m_primary; m_wndEditor2 = wndList.m_secondary; @@ -3902,15 +3921,17 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags ) // Essentially, primaryCtrl == m_wndEditor // - // NOTE: It is allowed for m_wndEditor to be NULL - in this case - // value is drawn as normal, and m_wndEditor2 is assumed - // to be a right-aligned button that triggers a separate editorCtrl - // window. + // NOTE: It is allowed for m_wndEditor to be NULL - in this + // case value is drawn as normal, and m_wndEditor2 is + // assumed to be a right-aligned button that triggers + // a separate editorCtrl window. if ( m_wndEditor ) { wxASSERT_MSG( m_wndEditor->GetParent() == GetPanel(), - wxT("CreateControls must use result of wxPropertyGrid::GetPanel() as parent of controls.") ); + "CreateControls must use result of " + "wxPropertyGrid::GetPanel() as parent " + "of controls." ); // Set validator, if any #if wxUSE_VALIDATORS @@ -3924,7 +3945,8 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags ) // If it has modified status, use bold font // (must be done before capturing m_ctrlXAdjust) - if ( (p->m_flags & wxPG_PROP_MODIFIED) && (m_windowStyle & wxPG_BOLD_MODIFIED) ) + if ( (p->m_flags & wxPG_PROP_MODIFIED) && + (m_windowStyle & wxPG_BOLD_MODIFIED) ) SetCurControlBoldFont(); // Store x relative to splitter (we'll need it). @@ -3953,7 +3975,9 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags ) if ( m_wndEditor2 ) { wxASSERT_MSG( m_wndEditor2->GetParent() == GetPanel(), - wxT("CreateControls must use result of wxPropertyGrid::GetPanel() as parent of controls.") ); + "CreateControls must use result of " + "wxPropertyGrid::GetPanel() as parent " + "of controls." ); // Get proper id for wndSecondary m_wndSecId = m_wndEditor2->GetId(); @@ -3984,7 +4008,8 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags ) } else { - // Make sure focus is in grid canvas (important for wxGTK, at least) + // Make sure focus is in grid canvas (important for wxGTK, + // at least) SetFocusOnCanvas(); } @@ -4143,8 +4168,8 @@ bool wxPropertyGrid::DoCollapse( wxPGProperty* p, bool sendEvents ) } // Store dont-center-splitter flag 'cause we need to temporarily set it - wxUint32 old_flag = m_iFlags & wxPG_FL_DONT_CENTER_SPLITTER; - m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER; + bool prevDontCenterSplitter = m_pState->m_dontCenterSplitter; + m_pState->m_dontCenterSplitter = true; bool res = m_pState->DoCollapse(pwc); @@ -4154,20 +4179,10 @@ bool wxPropertyGrid::DoCollapse( wxPGProperty* p, bool sendEvents ) SendEvent( wxEVT_PG_ITEM_COLLAPSED, p ); RecalculateVirtualSize(); - - // Redraw etc. only if collapsed was visible. - if (pwc->IsVisible() && - !m_frozen && - ( !pwc->IsCategory() || !(m_windowStyle & wxPG_HIDE_CATEGORIES) ) ) - { - // When item is collapsed so that scrollbar would move, - // graphics mess is about (unless we redraw everything). - Refresh(); - } + Refresh(); } - // Clear dont-center-splitter flag if it wasn't set - m_iFlags = (m_iFlags & ~wxPG_FL_DONT_CENTER_SPLITTER) | old_flag; + m_pState->m_dontCenterSplitter = prevDontCenterSplitter; return res; } @@ -4181,8 +4196,8 @@ bool wxPropertyGrid::DoExpand( wxPGProperty* p, bool sendEvents ) wxPGProperty* pwc = (wxPGProperty*)p; // Store dont-center-splitter flag 'cause we need to temporarily set it - wxUint32 old_flag = m_iFlags & wxPG_FL_DONT_CENTER_SPLITTER; - m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER; + bool prevDontCenterSplitter = m_pState->m_dontCenterSplitter; + m_pState->m_dontCenterSplitter = true; bool res = m_pState->DoExpand(pwc); @@ -4192,23 +4207,10 @@ bool wxPropertyGrid::DoExpand( wxPGProperty* p, bool sendEvents ) SendEvent( wxEVT_PG_ITEM_EXPANDED, p ); RecalculateVirtualSize(); - - // Redraw etc. only if expanded was visible. - if ( pwc->IsVisible() && !m_frozen && - ( !pwc->IsCategory() || !(m_windowStyle & wxPG_HIDE_CATEGORIES) ) - ) - { - // Redraw - #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT - Refresh(); - #else - DrawItems(pwc, NULL); - #endif - } + Refresh(); } - // Clear dont-center-splitter flag if it wasn't set - m_iFlags = (m_iFlags & ~wxPG_FL_DONT_CENTER_SPLITTER) | old_flag; + m_pState->m_dontCenterSplitter = prevDontCenterSplitter; return res; } @@ -4248,7 +4250,9 @@ bool wxPropertyGrid::DoHideProperty( wxPGProperty* p, bool hide, int flags ) void wxPropertyGrid::RecalculateVirtualSize( int forceXPos ) { - if ( (m_iFlags & wxPG_FL_RECALCULATING_VIRTUAL_SIZE) || m_frozen ) + if ( (m_iFlags & wxPG_FL_RECALCULATING_VIRTUAL_SIZE) || + m_frozen || + !m_pState ) return; // @@ -4309,11 +4313,6 @@ void wxPropertyGrid::RecalculateVirtualSize( int forceXPos ) m_width = width; m_height = height; - // 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 ( GetSelection() ) @@ -4330,7 +4329,7 @@ void wxPropertyGrid::OnResize( wxSizeEvent& event ) return; int width, height; - GetClientSize(&width,&height); + GetClientSize(&width, &height); m_width = width; m_height = height; @@ -4400,7 +4399,7 @@ void wxPropertyGrid::SetVirtualWidth( int width ) void wxPropertyGrid::SetFocusOnCanvas() { - m_canvas->SetFocusIgnoringChildren(); + SetFocusIgnoringChildren(); m_editorFocused = 0; } @@ -4415,6 +4414,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); @@ -4538,7 +4540,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 ) + { + CenterSplitter( true ); + + SendEvent(wxEVT_PG_COL_DRAGGING, + m_propHover, + NULL, + wxPG_SEL_NOVALIDATE, + (unsigned int)m_draggedSplitter); + } } else if ( m_dragStatus == 0 ) { @@ -4549,35 +4560,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; - - m_wndEditor->Show ( false ); - } + if ( m_wndEditor ) + { + // Changes must be committed here or the + // value won't be drawn correctly + if ( !CommitChangesFromEditor() ) + return res; - if ( !(m_iFlags & wxPG_FL_MOUSE_CAPTURED) ) - { - m_canvas->CaptureMouse(); - m_iFlags |= wxPG_FL_MOUSE_CAPTURED; - } + m_wndEditor->Show ( false ); + } - m_dragStatus = 1; - m_draggedSplitter = splitterHit; - m_dragOffset = splitterHitOffset; + if ( !(m_iFlags & wxPG_FL_MOUSE_CAPTURED) ) + { + CaptureMouse(); + m_iFlags |= wxPG_FL_MOUSE_CAPTURED; + } - wxClientDC dc(m_canvas); + 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; + } } } } @@ -4589,6 +4604,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; @@ -4656,14 +4675,14 @@ void wxPropertyGrid::SetToolTip( const wxString& tipString ) { if ( tipString.length() ) { - m_canvas->SetToolTip(tipString); + wxScrolledWindow::SetToolTip(tipString); } else { #if wxPG_ALLOW_EMPTY_TOOLTIPS - m_canvas->SetToolTip( m_emptyString ); + wxScrolledWindow::SetToolTip( m_emptyString ); #else - m_canvas->SetToolTip( NULL ); + wxScrolledWindow::SetToolTip( NULL ); #endif } } @@ -4673,13 +4692,14 @@ void wxPropertyGrid::SetToolTip( const wxString& tipString ) // ----------------------------------------------------------------------- // Return false if should be skipped -bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event ) +bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, + wxMouseEvent &event ) { // Safety check (needed because mouse capturing may // otherwise freeze the control) if ( m_dragStatus > 0 && !event.Dragging() ) { - HandleMouseUp(x,y,event); + HandleMouseUp(x, y, event); } wxPropertyGridPageState* state = m_pState; @@ -4703,15 +4723,16 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event if ( newSplitterX != splitterX ) { // Move everything - SetInternalFlag(wxPG_FL_DONT_CENTER_SPLITTER); - 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; @@ -4760,7 +4781,7 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event // if ( m_windowStyle & wxPG_TOOLTIPS ) { - wxToolTip* tooltip = m_canvas->GetToolTip(); + wxToolTip* tooltip = GetToolTip(); if ( m_propHover != prevHover || prevSide != m_mouseSide ) { @@ -4791,7 +4812,9 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event space = m_width - splitterX; if ( m_propHover->m_flags & wxPG_PROP_CUSTOMIMAGE ) - space -= wxPG_CUSTOM_IMAGE_WIDTH + wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2; + space -= wxPG_CUSTOM_IMAGE_WIDTH + + wxCC_CUSTOM_IMAGE_MARGIN1 + + wxCC_CUSTOM_IMAGE_MARGIN2; } if ( space ) @@ -4808,9 +4831,9 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event if ( tooltip ) { #if wxPG_ALLOW_EMPTY_TOOLTIPS - m_canvas->SetToolTip( m_emptyString ); + SetToolTip( m_emptyString ); #else - m_canvas->SetToolTip( NULL ); + wxScrolledWindow::SetToolTip( NULL ); #endif } } @@ -4822,9 +4845,9 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event if ( tooltip ) { #if wxPG_ALLOW_EMPTY_TOOLTIPS - m_canvas->SetToolTip( m_emptyString ); + SetToolTip( m_emptyString ); #else - m_canvas->SetToolTip( NULL ); + wxScrolledWindow::SetToolTip( NULL ); #endif } } @@ -4852,8 +4875,8 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event // hovering on splitter - // NB: Condition disabled since MouseLeave event (from the editor control) cannot be - // reliably detected. + // NB: Condition disabled since MouseLeave event (from the + // editor control) cannot be reliably detected. //if ( m_curcursor != wxCURSOR_SIZEWE ) CustomSetCursor( wxCURSOR_SIZEWE, true ); @@ -4927,13 +4950,19 @@ bool wxPropertyGrid::HandleMouseUp( int x, unsigned int WXUNUSED(y), // (it is only here as a reminder to not to do it) //splitterX = x; + SendEvent(wxEVT_PG_COL_END_DRAG, + m_propHover, + NULL, + wxPG_SEL_NOVALIDATE, + (unsigned int)m_draggedSplitter); + // Disable splitter auto-centering - m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER; + state->m_dontCenterSplitter = true; // This is necessary to return cursor if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED ) { - m_canvas->ReleaseMouse(); + ReleaseMouse(); m_iFlags &= ~(wxPG_FL_MOUSE_CAPTURED); } @@ -4975,10 +5004,8 @@ bool wxPropertyGrid::OnMouseCommon( wxMouseEvent& event, int* px, int* py ) { int splitterX = GetSplitterPosition(); - //int ux, uy; - //CalcUnscrolledPosition( event.m_x, event.m_y, &ux, &uy ); - int ux = event.m_x; - int uy = event.m_y; + int ux, uy; + CalcUnscrolledPosition( event.m_x, event.m_y, &ux, &uy ); wxWindow* wnd = GetEditorControl(); @@ -5061,14 +5088,6 @@ void wxPropertyGrid::OnMouseMove( wxMouseEvent &event ) // ----------------------------------------------------------------------- -void wxPropertyGrid::OnMouseMoveBottom( wxMouseEvent& WXUNUSED(event) ) -{ - // Called when mouse moves in the empty space below the properties. - CustomSetCursor( wxCURSOR_ARROW ); -} - -// ----------------------------------------------------------------------- - void wxPropertyGrid::OnMouseUp( wxMouseEvent &event ) { int x, y; @@ -5103,7 +5122,7 @@ void wxPropertyGrid::OnMouseEntry( wxMouseEvent &event ) else if ( event.Leaving() ) { // Without this, wxSpinCtrl editor will sometimes have wrong cursor - m_canvas->SetCursor( wxNullCursor ); + SetCursor( wxNullCursor ); // Get real cursor position wxPoint pt = ScreenToClient(::wxGetMousePosition()); @@ -5855,6 +5874,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 ); // -----------------------------------------------------------------------