void wxPGInitResourceModule()
{
wxModule* module = new wxPGGlobalVarsClassManager;
- module->Init();
wxModule::RegisterModule(module);
+ wxModule::InitializeModules();
}
wxPGGlobalVarsClass* wxPGGlobalVars = NULL;
delete ((wxPGEditor*)vt_it->second);
}
+ // Make sure the global pointers have been reset
+ wxASSERT(wxPG_EDITOR(TextCtrl) == NULL);
+ wxASSERT(wxPG_EDITOR(ChoiceAndButton) == NULL);
+
delete wxPGProperty::sm_wxPG_LABEL;
}
m_eventObject = this;
m_curFocused = NULL;
m_processedEvent = NULL;
+ m_tlp = NULL;
m_sortFunction = NULL;
m_inDoPropertyChanged = false;
m_inCommitChangesFromEditor = false;
m_coloursCustomized = 0;
m_frozen = 0;
-#if wxPG_DOUBLE_BUFFER
m_doubleBuffer = NULL;
-#endif
#ifndef wxPG_ICON_WIDTH
m_expandbmp = NULL;
SetBackgroundStyle( wxBG_STYLE_CUSTOM );
// Hook the top-level parent
- m_tlp = NULL;
m_tlpClosed = NULL;
m_tlpClosedTime = 0;
wxS("Close(false).)") );
}
-#if wxPG_DOUBLE_BUFFER
if ( m_doubleBuffer )
delete m_doubleBuffer;
-#endif
if ( m_iFlags & wxPG_FL_CREATEDSTATE )
delete m_pState;
{
wxControl::Thaw();
RecalculateVirtualSize();
- #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
Refresh();
- #endif
// Force property re-selection
// NB: We must copy the selection.
colIndex);
wxWindowID id = tc->GetId();
- tc->Connect(id, wxEVT_COMMAND_TEXT_ENTER,
+ tc->Connect(id, wxEVT_TEXT_ENTER,
wxCommandEventHandler(wxPropertyGrid::OnLabelEditorEnterPress),
NULL, this);
tc->Connect(id, wxEVT_KEY_DOWN,
}
else
{
- #if wxPG_DOUBLE_BUFFER
wxDELETE(m_doubleBuffer);
- #endif
}
}
wxString& wxPropertyGrid::ExpandEscapeSequences( wxString& dst_str, wxString& src_str )
{
- if ( src_str.length() == 0 )
+ if ( src_str.empty() )
{
dst_str = src_str;
return src_str;
wxString& wxPropertyGrid::CreateEscapeSequences( wxString& dst_str, wxString& src_str )
{
- if ( src_str.length() == 0 )
+ if ( src_str.empty() )
{
dst_str = src_str;
return src_str;
vx *= wxPG_PIXELS_PER_UNIT;
vy *= wxPG_PIXELS_PER_UNIT;
+ // itemRect is in virtual grid space
wxRect drawRect(itemsRect->x - vx,
itemsRect->y - vy,
itemsRect->width,
wxDC* dcPtr = &dc;
bool isBuffered = false;
- #if wxPG_DOUBLE_BUFFER
wxMemoryDC* bufferDC = NULL;
if ( !(GetExtraStyle() & wxPG_EX_NATIVE_DOUBLE_BUFFERING) )
isBuffered = true;
}
}
- #endif
if ( dcPtr )
{
+ // paintFinishY and drawBottomY are in buffer/physical space
paintFinishY = DoDrawItems( *dcPtr, itemsRect, isBuffered );
- int drawBottomY = itemsRect->y + itemsRect->height;
+ int drawBottomY = itemsRect->y + itemsRect->height - vy;
// Clear area beyond last painted property
if ( paintFinishY < drawBottomY )
{
- wxLogDebug("%i", paintFinishY);
dcPtr->SetPen(m_colEmptySpace);
dcPtr->SetBrush(m_colEmptySpace);
dcPtr->DrawRectangle(0, paintFinishY,
}
}
- #if wxPG_DOUBLE_BUFFER
if ( bufferDC )
{
dc.Blit( drawRect.x, drawRect.y, drawRect.width,
bufferDC, 0, 0, wxCOPY );
delete bufferDC;
}
- #endif
}
else
{
int xRelMod = 0;
//
- // With wxPG_DOUBLE_BUFFER, do double buffering
+ // For now, do some manual calculation for double buffering
// - buffer's y = 0, so align itemsRect and coordinates to that
//
-#if wxPG_DOUBLE_BUFFER
+ // TODO: In future use wxAutoBufferedPaintDC (for example)
+ //
int yRelMod = 0;
wxRect cr2;
firstItemTopY -= yRelMod;
lastItemBottomY -= yRelMod;
}
-#else
- wxUnusedVar(isBuffered);
-#endif
int x = m_marginWidth - xRelMod;
const wxPropertyGridPageState* state = m_pState;
const wxArrayInt& colWidths = state->m_colWidths;
-#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
- bool wasSelectedPainted = false;
-#endif
-
// TODO: Only render columns that are within clipping region.
dc.SetFont(normalFont);
}
else
{
-#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
- if ( p == firstSelected )
- wasSelectedPainted = true;
-#endif
-
renderFlags |= wxPGCellRenderer::Selected;
if ( !p->IsCategory() )
y += rowHeight;
}
- // Refresh editor controls (seems not needed on msw)
- // NOTE: This code is mandatory for GTK!
-#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
- if ( wasSelectedPainted )
- {
- if ( m_wndEditor )
- m_wndEditor->Refresh();
- if ( m_wndEditor2 )
- m_wndEditor2->Refresh();
- }
-#endif
-
return y;
}
//
// Return rect which encloses the given property range
// (in logical grid coordinates)
- //
+ //
int visTop = p1->GetY();
int visBottom;
void wxPropertyGrid::RefreshProperty( wxPGProperty* p )
{
- if ( m_pState->DoIsPropertySelected(p) )
+ if ( m_pState->DoIsPropertySelected(p) || p->IsChildSelected(true) )
{
// NB: We must copy the selection.
wxArrayPGProperty selection = m_pState->m_selection;
wxWindow::Refresh(false, rect);
-#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
+#if wxPG_REFRESH_CONTROLS
// I think this really helps only GTK+1.2
if ( m_wndEditor ) m_wndEditor->Refresh();
if ( m_wndEditor2 ) m_wndEditor2->Refresh();
if ( changedProperty == GetSelection() )
{
wxWindow* editor = GetEditorControl();
- wxASSERT( editor->IsKindOf(CLASSINFO(wxTextCtrl)) );
+ wxASSERT( wxDynamicCast(editor, wxTextCtrl) );
evtChangingValue = wxStaticCast(editor, wxTextCtrl)->GetValue();
}
else
wxStatusBar* wxPropertyGrid::GetStatusBar()
{
wxWindow* topWnd = ::wxGetTopLevelParent(this);
- if ( topWnd && topWnd->IsKindOf(CLASSINFO(wxFrame)) )
+ if ( wxDynamicCast(topWnd, wxFrame) )
{
wxFrame* pFrame = wxStaticCast(topWnd, wxFrame);
if ( pFrame )
void wxPropertyGrid::DoShowPropertyError( wxPGProperty* WXUNUSED(property), const wxString& msg )
{
- if ( !msg.length() )
+ if ( msg.empty() )
return;
#if wxUSE_STATUSBAR
//
// For non-wxTextCtrl editors, we do need to revert the value
- if ( !editor->IsKindOf(CLASSINFO(wxTextCtrl)) &&
+ if ( !wxDynamicCast(editor, wxTextCtrl) &&
property == GetSelection() )
{
property->GetEditorClass()->UpdateControl(property, editor);
{
wxString msg = m_validationInfo.m_failureMessage;
- if ( !msg.length() )
+ if ( msg.empty() )
msg = _("You have entered invalid value. Press ESC to cancel editing.");
#if wxUSE_STATUSBAR
}
else
{
-#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
+#if wxPG_REFRESH_CONTROLS
if ( m_wndEditor ) m_wndEditor->Refresh();
if ( m_wndEditor2 ) m_wndEditor2->Refresh();
#endif
// -----------------------------------------------------------------------
-void wxPropertyGrid::HandleCustomEditorEvent( wxEvent &event )
+bool wxPropertyGrid::HandleCustomEditorEvent( wxEvent &event )
{
+ //
+ // NB: We should return true if the event was recognized as
+ // a dedicated wxPropertyGrid event, and as such was
+ // either properly handled or ignored.
+ //
+
// 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;
+ return false;
// Don't care about the event if it originated from the
// 'label editor'. In this function we only care about the
if ( m_labelEditor && event.GetId() == m_labelEditor->GetId() )
{
event.Skip();
- return;
+ return true;
}
wxPGProperty* selected = GetSelection();
// similar is currently doing something (showing a
// message box, for instance).
m_processedEvent )
- return;
+ return true;
if ( m_iFlags & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT )
- return;
+ return true;
wxVariant pendingValue(selected->GetValueRef());
wxWindow* wnd = GetEditorControl();
//
// Filter out excess wxTextCtrl modified events
- if ( event.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED && wnd )
+ if ( event.GetEventType() == wxEVT_TEXT && wnd )
{
- if ( wnd->IsKindOf(CLASSINFO(wxTextCtrl)) )
+ if ( wxDynamicCast(wnd, wxTextCtrl) )
{
wxTextCtrl* tc = (wxTextCtrl*) wnd;
wxString newTcValue = tc->GetValue();
if ( m_prevTcValue == newTcValue )
- return;
+ return true;
m_prevTcValue = newTcValue;
}
- else if ( wnd->IsKindOf(CLASSINFO(wxComboCtrl)) )
+ else if ( wxDynamicCast(wnd, wxComboCtrl) )
{
+ // In some cases we might stumble unintentionally on
+ // wxComboCtrl's embedded wxTextCtrl's events. Let's
+ // avoid them.
+ if ( wxDynamicCast(editorWnd, wxTextCtrl) )
+ return false;
+
wxComboCtrl* cc = (wxComboCtrl*) wnd;
wxString newTcValue = cc->GetTextCtrl()->GetValue();
if ( m_prevTcValue == newTcValue )
- return;
+ return true;
m_prevTcValue = newTcValue;
}
}
bool validationFailure = false;
bool buttonWasHandled = false;
+ bool result = false;
//
// Try common button handling
- if ( m_wndEditor2 && event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED )
+ if ( m_wndEditor2 && event.GetEventType() == wxEVT_BUTTON )
{
wxPGEditorDialogAdapter* adapter = selected->GetEditorDialog();
{
buttonWasHandled = true;
// Store as res2, as previously (and still currently alternatively)
- // dialogs can be shown by handling wxEVT_COMMAND_BUTTON_CLICKED
+ // dialogs can be shown by handling wxEVT_BUTTON
// in wxPGProperty::OnEvent().
adapter->ShowDialog( this, selected );
delete adapter;
if ( editor->OnEvent( this, selected, editorWnd, event ) )
{
+ result = true;
+
// If changes, validate them
if ( DoEditorValidate() )
{
// Regardless of editor type, unfocus editor on
// text-editing related enter press.
- if ( event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER )
+ if ( event.GetEventType() == wxEVT_TEXT_ENTER )
{
SetFocusOnCanvas();
}
// Regardless of editor type, unfocus editor on
// text-editing related enter press.
- if ( event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER )
+ if ( event.GetEventType() == wxEVT_TEXT_ENTER )
{
SetFocusOnCanvas();
}
// Let unhandled button click events go to the parent
- if ( !buttonWasHandled && event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED )
+ if ( !buttonWasHandled && event.GetEventType() == wxEVT_BUTTON )
{
- wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED,GetId());
+ result = true;
+ wxCommandEvent evt(wxEVT_BUTTON,GetId());
GetEventHandler()->AddPendingEvent(evt);
}
}
ClearInternalFlag(wxPG_FL_IN_HANDLECUSTOMEDITOREVENT);
+
+ return result;
}
// -----------------------------------------------------------------------
m_propGrid->HandleCustomEditorEvent(event);
+ //
+ // NB: We should return true if the event was recognized as
+ // a dedicated wxPropertyGrid event, and as such was
+ // either properly handled or ignored.
+ //
+ if ( m_propGrid->IsMainButtonEvent(event) )
+ return true;
+
//
// 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 )
+ if ( event.GetEventType() == wxEVT_TEXT_ENTER )
return true;
return wxEvtHandler::ProcessEvent(event);
// Return focus back to canvas from children (this is required at least for
// GTK+, which, unlike Windows, clears focus when control is destroyed
// instead of moving it to closest parent).
- wxWindow* focus = wxWindow::FindFocus();
- if ( focus )
- {
- wxWindow* parent = focus->GetParent();
- while ( parent )
- {
- if ( parent == this )
- {
- SetFocusOnCanvas();
- break;
- }
- parent = parent->GetParent();
- }
- }
+ SetFocusOnCanvas();
// Do not free editors immediately if processing events
if ( m_wndEditor2 )
wxStatusBar* statusbar = GetStatusBar();
if ( statusbar )
{
- if ( pHelpString && pHelpString->length() )
+ if ( pHelpString && !pHelpString->empty() )
{
// Set help box text.
statusbar->SetStatusText( *pHelpString );
//
// Show help as a tool tip on the editor control.
//
- if ( pHelpString && pHelpString->length() &&
+ if ( pHelpString && !pHelpString->empty() &&
primaryCtrl )
{
primaryCtrl->SetToolTip(*pHelpString);
SetScrollbars( wxPG_PIXELS_PER_UNIT, wxPG_PIXELS_PER_UNIT,
xAmount, yAmount, xPos, yPos, true );
+ // This may be needed in addition to calling SetScrollbars()
+ // when class inherits from wxScrollHelper instead of
+ // actual wxScrolled<T>.
+ AdjustScrollbars();
+
// Must re-get size now
GetClientSize(&width,&height);
if ( !HasVirtualWidth() )
{
m_pState->SetVirtualWidth(width);
- x = width;
}
m_width = width;
m_width = width;
m_height = height;
-#if wxPG_DOUBLE_BUFFER
if ( !(GetExtraStyle() & wxPG_EX_NATIVE_DOUBLE_BUFFERING) )
{
int dblh = (m_lineHeight*2);
}
}
-#endif
-
m_pState->OnClientWidthChange( width, event.GetSize().x - m_ncWidth, true );
m_ncWidth = event.GetSize().x;
void wxPropertyGrid::SetFocusOnCanvas()
{
- SetFocus();
+ // To prevent wxPropertyGrid from stealing focus from other controls,
+ // only move focus to the grid if it was already in one if its child
+ // controls.
+ wxWindow* focus = wxWindow::FindFocus();
+ if ( focus )
+ {
+ wxWindow* parent = focus->GetParent();
+ while ( parent )
+ {
+ if ( parent == this )
+ {
+ SetFocus();
+ break;
+ }
+ parent = parent->GetParent();
+ }
+ }
+
m_editorFocused = 0;
}
}
// Do not Skip() the event after selection has been made.
- // Otherwise default event handling behavior kicks in
+ // Otherwise default event handling behaviour kicks in
// and may revert focus back to the main canvas.
res = true;
}
m_draggedSplitter = splitterHit;
m_dragOffset = splitterHitOffset;
- #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
+ #if wxPG_REFRESH_CONTROLS
// Fixes button disappearance bug
if ( m_wndEditor2 )
m_wndEditor2->Show ( false );
int splitterHitOffset;
state->HitTestH( x, &splitterHit, &splitterHitOffset );
- // No event type check - basicly calling this method should
+ // No event type check - basically calling this method should
// just stop dragging.
// Left up after dragged?
if ( m_dragStatus >= 1 )
// 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 -
+ int posDiff = abs(m_startingSplitterX -
GetSplitterPosition(m_draggedSplitter));
if ( posDiff > 1 )
m_wndEditor->Show ( true );
}
- #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
+ #if wxPG_REFRESH_CONTROLS
// Fixes button disappearance bug
if ( m_wndEditor2 )
m_wndEditor2->Show ( true );
// Hide popup on clicks
if ( event.GetEventType() != wxEVT_MOTION )
- if ( wnd && wnd->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) )
+ if ( wxDynamicCast(wnd, wxOwnerDrawnComboBox) )
{
((wxOwnerDrawnComboBox*)wnd)->HidePopup();
}
if ( keycode == WXK_TAB )
{
+#if defined(__WXGTK__)
wxWindow* mainControl;
if ( HasInternalFlag(wxPG_FL_IN_MANAGER) )
mainControl = GetParent();
else
mainControl = this;
+#endif
if ( !event.ShiftDown() )
{
wxPGProperty* p = selected;
+ if ( action == wxPG_ACTION_EDIT && !editorFocused )
+ {
+ DoSelectProperty( p, wxPG_SEL_FOCUS );
+ wasHandled = true;
+ }
+
// Travel and expand/collapse
int selectDir = -2;
if ( action == wxPG_ACTION_PRESS_BUTTON &&
m_wndEditor2 )
{
- wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED, m_wndEditor2->GetId());
+ wxCommandEvent evt(wxEVT_BUTTON, m_wndEditor2->GetId());
GetEventHandler()->AddPendingEvent(evt);
return true;
}
RegisterDefaultEditors();
wxString name = editorName;
- if ( name.length() == 0 )
+ if ( name.empty() )
name = editorClass->GetName();
// Existing editor under this name?
m_column = 1;
m_canVeto = false;
m_wasVetoed = false;
+ m_pg = NULL;
}
// -----------------------------------------------------------------------
return NULL;
}
- if ( !classInfo || !classInfo->IsKindOf(CLASSINFO(wxPGProperty)) )
+ if ( !classInfo || !classInfo->IsKindOf(wxCLASSINFO(wxPGProperty)) )
{
ProcessError(wxString::Format(wxT("'%s' is not valid property class"),propClass.c_str()));
return NULL;
else
{
bool found = false;
- if ( idString.length() )
+ if ( !idString.empty() )
{
wxPGHashMapS2P::iterator it = m_dictIdChoices.find(idString);
if ( it != m_dictIdChoices.end() )
}
// Assign to id
- if ( idString.length() )
+ if ( !idString.empty() )
m_dictIdChoices[idString] = choices.GetData();
}
}
wxString valuel = value.Lower();
wxVariant variant;
- if ( type.length() == 0 )
+ if ( type.empty() )
{
long v;