//#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
}
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 )
{
// 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);
}
}
// 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 );
// topy and bottomy are already unscrolled (ie. physical)
//
void wxPropertyGrid::DrawItems( wxDC& dc,
- unsigned int topy,
- unsigned int bottomy,
+ unsigned int topItemY,
+ unsigned int bottomItemY,
const wxRect* drawRect )
{
- if ( m_frozen || m_height < 1 || bottomy < topy || !m_pState )
+ if ( m_frozen ||
+ m_height < 1 ||
+ bottomItemY < topItemY ||
+ !m_pState )
return;
m_pState->EnsureVirtualHeight();
wxRect tempDrawRect;
if ( !drawRect )
{
- tempDrawRect = wxRect(0, topy,
+ tempDrawRect = wxRect(0, topItemY,
m_pState->m_width,
- bottomy);
+ bottomItemY);
drawRect = &tempDrawRect;
}
paintFinishY = DoDrawItems( *dcPtr, drawRect, isBuffered );
int drawBottomY = drawRect->y + drawRect->height;
- // Clear area beyond bottomY?
+ // Clear area beyond last painted property
if ( paintFinishY < drawBottomY )
{
dcPtr->SetPen(m_colEmptySpace);
// -----------------------------------------------------------------------
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;
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;
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;
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;
}
}
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);
{
//
// 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;
// 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, bool refresh,
+ int splitterIndex,
+ bool allPages )
{
if ( ( newxpos < wxPG_DRAG_MARGIN ) )
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;
}
// -----------------------------------------------------------------------
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.
}
// 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);
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;
}
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);
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;
}
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;
//
{
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;
if ( newSplitterX != splitterX )
{
// Move everything
- SetInternalFlag(wxPG_FL_DONT_CENTER_SPLITTER);
+ state->m_dontCenterSplitter = true;
state->DoSetSplitterPosition(newSplitterX,
m_draggedSplitter,
false);
//splitterX = x;
// 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 )