#include "wx/timer.h"
#include "wx/dcbuffer.h"
-#include "wx/clipbrd.h"
-#include "wx/dataobj.h"
#ifdef __WXMSW__
#include "wx/msw/private.h"
IMPLEMENT_DYNAMIC_CLASS(wxPGGlobalVarsClassManager, wxModule)
+// When wxPG is loaded dynamically after the application is already running
+// then the built-in module system won't pick this one up. Add it manually.
+void wxPGInitResourceModule()
+{
+ wxModule* module = new wxPGGlobalVarsClassManager;
+ module->Init();
+ wxModule::RegisterModule(module);
+}
+
wxPGGlobalVarsClass* wxPGGlobalVars = NULL;
wxVariant v;
- // Prepare some shared variants
+ // Prepare some shared variants
m_vEmptyString = wxString();
m_vZero = (long) 0;
m_vMinusOne = (long) -1;
m_strlong = wxS("long");
m_strbool = wxS("bool");
m_strlist = wxS("list");
+ m_strDefaultValue = wxS("DefaultValue");
m_strMin = wxS("Min");
m_strMax = wxS("Max");
m_strUnits = wxS("Units");
m_strInlineHelp = wxS("InlineHelp");
-#ifdef __WXDEBUG__
m_warnings = 0;
-#endif
}
{
}
-// -----------------------------------------------------------------------
-// wxPGTLWHandler
-// Intercepts Close-events sent to wxPropertyGrid's top-level parent,
-// and tries to commit property value.
-// -----------------------------------------------------------------------
-
-class wxPGTLWHandler : public wxEvtHandler
-{
-public:
-
- wxPGTLWHandler( wxPropertyGrid* pg )
- : wxEvtHandler()
- {
- m_pg = pg;
- }
-
-protected:
-
- void OnClose( wxCloseEvent& event )
- {
- // ClearSelection forces value validation/commit.
- if ( event.CanVeto() && !m_pg->ClearSelection() )
- {
- event.Veto();
- return;
- }
-
- event.Skip();
- }
-
-private:
- wxPropertyGrid* m_pg;
-
- DECLARE_EVENT_TABLE()
-};
-
-BEGIN_EVENT_TABLE(wxPGTLWHandler, wxEvtHandler)
- EVT_CLOSE(wxPGTLWHandler::OnClose)
-END_EVENT_TABLE()
-
// -----------------------------------------------------------------------
// wxPGCanvas
// -----------------------------------------------------------------------
m_propHover = NULL;
m_eventObject = this;
m_curFocused = NULL;
- m_tlwHandler = NULL;
m_sortFunction = NULL;
m_inDoPropertyChanged = 0;
m_inCommitChangesFromEditor = 0;
#endif
#ifndef wxPG_ICON_WIDTH
- m_expandbmp = NULL;
- m_collbmp = NULL;
- m_iconWidth = 11;
- m_iconHeight = 11;
+ m_expandbmp = NULL;
+ m_collbmp = NULL;
+ m_iconWidth = 11;
+ m_iconHeight = 11;
#else
m_iconWidth = wxPG_ICON_WIDTH;
#endif
#ifndef wxPG_ICON_WIDTH
// create two bitmap nodes for drawing
- m_expandbmp = new wxBitmap(expand_xpm);
- m_collbmp = new wxBitmap(collapse_xpm);
+ m_expandbmp = new wxBitmap(expand_xpm);
+ m_collbmp = new wxBitmap(collapse_xpm);
- // calculate average font height for bitmap centering
+ // calculate average font height for bitmap centering
- m_iconWidth = m_expandbmp->GetWidth();
- m_iconHeight = m_expandbmp->GetHeight();
+ m_iconWidth = m_expandbmp->GetWidth();
+ m_iconHeight = m_expandbmp->GetHeight();
#endif
m_curcursor = wxCURSOR_ARROW;
m_cursorSizeWE = new wxCursor( wxCURSOR_SIZEWE );
- // adjust bitmap icon y position so they are centered
+ // adjust bitmap icon y position so they are centered
m_vspacing = wxPG_DEFAULT_VSPACING;
CalculateFontAndBitmapStuff( wxPG_DEFAULT_VSPACING );
// This helps with flicker
SetBackgroundStyle( wxBG_STYLE_CUSTOM );
- // Hook the TLW
- wxPGTLWHandler* handler = new wxPGTLWHandler(this);
- m_tlp = ::wxGetTopLevelParent(this);
- m_tlwHandler = handler;
- m_tlp->PushEventHandler(handler);
+ // Hook the top-level parent
+ m_tlp = NULL;
+ OnTLPChanging(NULL);
- // set virtual size to this window size
+ // set virtual size to this window size
wxSize wndsize = GetSize();
- SetVirtualSize(wndsize.GetWidth(), wndsize.GetWidth());
+ SetVirtualSize(wndsize.GetWidth(), wndsize.GetWidth());
m_timeCreated = ::wxGetLocalTimeMillis();
if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED )
m_canvas->ReleaseMouse();
- wxPGTLWHandler* handler = (wxPGTLWHandler*) m_tlwHandler;
- m_tlp->RemoveEventHandler(handler);
- delete handler;
+ // Do TLP check, recommend use of OnTLPChanging()
+ wxWindow* tlp = ::wxGetTopLevelParent(this);
+ if ( tlp == m_tlp )
+ {
+ m_tlp->Disconnect( wxEVT_CLOSE_WINDOW,
+ wxCloseEventHandler(wxPropertyGrid::OnTLPClose),
+ NULL, this );
+ }
+ else if ( tlp )
+ {
+ wxLogError("Top-level parent of wxPropertyGrid has changed. "
+ "Consider calling wxPropertyGrid::OnTLPChanging() "
+ "when appropriate.");
+ }
-#ifdef __WXDEBUG__
- if ( IsEditorsValueModified() )
- ::wxMessageBox(wxS("Most recent change in property editor was lost!!!\n\n(if you don't want this to happen, close your frames and dialogs using Close(false).)"),
- wxS("wxPropertyGrid Debug Warning") );
-#endif
+ wxASSERT_MSG( !IsEditorsValueModified(),
+ wxS("Most recent change in property editor was lost!!! ")
+ wxS("(if you don't want this to happen, close your frames ")
+ wxS("and dialogs using Close(false).)") );
#if wxPG_DOUBLE_BUFFER
if ( m_doubleBuffer )
delete m_cursorSizeWE;
#ifndef wxPG_ICON_WIDTH
- delete m_expandbmp;
- delete m_collbmp;
+ delete m_expandbmp;
+ delete m_collbmp;
#endif
// Delete common value records
// returns the best acceptable minimal size
wxSize wxPropertyGrid::DoGetBestSize() const
{
- int hei = 15;
- if ( m_lineHeight > hei )
- hei = m_lineHeight;
- wxSize sz = wxSize( 60, hei+40 );
+ int lineHeight = wxMax(15, m_lineHeight);
+ // don't make the grid too tall (limit height to 10 items) but don't
+ // make it too small neither
+ int numLines = wxMin
+ (
+ wxMax(m_pState->m_properties->GetChildCount(), 3),
+ 10
+ );
+
+ const wxSize sz = wxSize(60, lineHeight*numLines + 40);
CacheBestSize(sz);
return sz;
}
+ // -----------------------------------------------------------------------
+
+void wxPropertyGrid::OnTLPChanging( wxWindow* newTLP )
+{
+ //
+ // Parent changed so let's redetermine and re-hook the
+ // correct top-level window.
+ if ( m_tlp )
+ {
+ wxASSERT_MSG( m_tlp == ::wxGetTopLevelParent(this),
+ "You must call OnTLPChanging() before the "
+ "top-level parent has changed.");
+
+ m_tlp->Disconnect( wxEVT_CLOSE_WINDOW,
+ wxCloseEventHandler(wxPropertyGrid::OnTLPClose),
+ NULL, this );
+ }
+
+ if ( !newTLP )
+ newTLP = ::wxGetTopLevelParent(this);
+
+ m_tlp = newTLP;
+ m_tlp->Connect( wxEVT_CLOSE_WINDOW,
+ wxCloseEventHandler(wxPropertyGrid::OnTLPClose),
+ NULL, this );
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::OnTLPClose( wxCloseEvent& event )
+{
+ // ClearSelection forces value validation/commit.
+ if ( event.CanVeto() && !ClearSelection() )
+ {
+ event.Veto();
+ return;
+ }
+
+ event.Skip();
+}
+
+// -----------------------------------------------------------------------
+
+bool wxPropertyGrid::Reparent( wxWindowBase *newParent )
+{
+ OnTLPChanging((wxWindow*)newParent);
+
+ bool res = wxScrolledWindow::Reparent(newParent);
+
+ return res;
+}
+
// -----------------------------------------------------------------------
// wxPropertyGrid Font and Colour Methods
// -----------------------------------------------------------------------
void wxPropertyGrid::CalculateFontAndBitmapStuff( int vspacing )
{
- int x = 0, y = 0;
+ int x = 0, y = 0;
m_captionFont = wxScrolledWindow::GetFont();
- GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
+ GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
m_subgroup_extramargin = x + (x/2);
- m_fontHeight = y;
+ m_fontHeight = y;
#if wxPG_USE_RENDERER_NATIVE
m_iconWidth = wxPG_ICON_WIDTH;
m_marginWidth = m_gutterWidth*2 + m_iconWidth;
m_captionFont.SetWeight(wxBOLD);
- GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
+ GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
m_lineHeight = m_fontHeight+(2*m_spacingy)+1;
ClearSelection(false);
bool res = wxScrolledWindow::SetFont( font );
- if ( res )
+ if ( res && GetParent()) // may not have been Create()ed yet
{
CalculateFontAndBitmapStuff( m_vspacing );
Refresh();
wxVariant pendingValue(selected->GetValueRef());
wxWindow* wnd = GetEditorControl();
+ wxWindow* editorWnd = wxDynamicCast(event.GetEventObject(), wxWindow);
int selFlags = 0;
bool wasUnspecified = selected->IsValueUnspecified();
int usesAutoUnspecified = selected->UsesAutoUnspecified();
-
bool valueIsPending = false;
m_chgInfo_changedProperty = NULL;
if ( !buttonWasHandled )
{
- if ( wnd )
+ if ( wnd || m_wndEditor2 )
{
// First call editor class' event handler.
const wxPGEditor* editor = selected->GetEditorClass();
- if ( editor->OnEvent( this, selected, wnd, event ) )
+ if ( editor->OnEvent( this, selected, editorWnd, event ) )
{
// If changes, validate them
if ( DoEditorValidate() )
{
- if ( editor->GetValueFromControl( pendingValue, m_selected, wnd ) )
+ if ( editor->GetValueFromControl( pendingValue,
+ m_selected,
+ wnd ) )
valueIsPending = true;
}
else
// Then the property's custom handler (must be always called, unless
// validation failed).
if ( !validationFailure )
- buttonWasHandled = selected->OnEvent( this, wnd, event );
+ buttonWasHandled = selected->OnEvent( this, editorWnd, event );
}
// SetValueInEvent(), as called in one of the functions referred above
{
int itemy = p->GetY2(m_lineHeight);
int vy = 0;
- int cust_img_space = 0;
int splitterX = m_pState->DoGetSplitterPosition(column-1);
int colEnd = splitterX + m_pState->m_colWidths[column];
+ int imageOffset = 0;
// TODO: If custom image detection changes from current, change this.
- if ( m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE /*p->m_flags & wxPG_PROP_CUSTOMIMAGE*/ )
+ if ( m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE )
{
//m_iFlags |= wxPG_FL_CUR_USES_CUSTOM_IMAGE;
- int imwid = p->OnMeasureImage().x;
- if ( imwid < 1 ) imwid = wxPG_CUSTOM_IMAGE_WIDTH;
- cust_img_space = imwid + wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2;
+ int iw = p->OnMeasureImage().x;
+ if ( iw < 1 )
+ iw = wxPG_CUSTOM_IMAGE_WIDTH;
+ imageOffset = p->GetImageOffset(iw);
}
return wxRect
(
- splitterX+cust_img_space+wxPG_XBEFOREWIDGET+wxPG_CONTROL_MARGIN+1,
+ splitterX+imageOffset+wxPG_XBEFOREWIDGET+wxPG_CONTROL_MARGIN+1,
itemy-vy,
- colEnd-splitterX-wxPG_XBEFOREWIDGET-wxPG_CONTROL_MARGIN-cust_img_space-1,
+ colEnd-splitterX-wxPG_XBEFOREWIDGET-wxPG_CONTROL_MARGIN-imageOffset-1,
m_lineHeight-1
);
}
m_pState->EnsureVirtualHeight();
-#ifdef __WXDEBUG__
- int by1 = m_pState->GetVirtualHeight();
- int by2 = m_pState->GetActualVirtualHeight();
- if ( by1 != by2 )
- {
- wxString s = wxString::Format(wxT("VirtualHeight=%i, ActualVirtualHeight=%i, should match!"), by1, by2);
- wxFAIL_MSG(s.c_str());
- wxLogDebug(s);
- }
-#endif
+ wxASSERT_LEVEL_2_MSG(
+ m_pState->GetVirtualHeight() == m_pState->GetActualVirtualHeight(),
+ "VirtualHeight and ActualVirtualHeight should match"
+ );
m_iFlags |= wxPG_FL_RECALCULATING_VIRTUAL_SIZE;
GetClientSize(&width,&height);
// Now adjust virtual size.
- SetVirtualSize(x, y);
+ SetVirtualSize(x, y);
int xAmount = 0;
int xPos = 0;
if ( space )
{
int tw, th;
- GetTextExtent( tipString, &tw, &th, 0, 0 );
+ GetTextExtent( tipString, &tw, &th, 0, 0 );
if ( tw > space )
{
SetToolTip( tipString );
// Travel and expand/collapse
int selectDir = -2;
- if ( p->GetChildCount() &&
- !(p->m_flags & wxPG_PROP_DISABLED)
- )
+ if ( p->GetChildCount() )
{
if ( action == wxPG_ACTION_COLLAPSE_PROPERTY || secondAction == wxPG_ACTION_COLLAPSE_PROPERTY )
{
// -----------------------------------------------------------------------
// noDefCheck = true prevents infinite recursion.
-wxPGEditor* wxPropertyGrid::RegisterEditorClass( wxPGEditor* editorClass,
- bool noDefCheck )
+wxPGEditor* wxPropertyGrid::DoRegisterEditorClass( wxPGEditor* editorClass,
+ const wxString& editorName,
+ bool noDefCheck )
{
wxASSERT( editorClass );
if ( !noDefCheck && wxPGGlobalVars->m_mapEditorClasses.empty() )
RegisterDefaultEditors();
- wxString name = editorClass->GetName();
+ wxString name = editorName;
+ if ( name.length() == 0 )
+ name = editorClass->GetName();
// Existing editor under this name?
wxPGHashMapS2P::iterator vt_it = wxPGGlobalVars->m_mapEditorClasses.find(name);
wxPGChoicesData::wxPGChoicesData()
{
- m_refCount = 1;
}
wxPGChoicesData::~wxPGChoicesData()