1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // wxFormBuilder - A Visual Dialog Editor for wxWidgets.
4 // Copyright (C) 2005 José Antonio Hurtado
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 //
20 // Written by
21 //   José Antonio Hurtado - joseantonio.hurtado@gmail.com
22 //   Juan Antonio Ortega  - jortegalalmolda@gmail.com
23 //
24 // Modified by
25 //   Andrea Zanellato - zanellato.andrea@gmail.com
26 //
27 ///////////////////////////////////////////////////////////////////////////////
28 
29 #include <wx/wxprec.h>
30 
31 #ifndef WX_PRECOMP
32     #include <wx/wx.h>
33 #endif
34 
35 #include <wx/propgrid/propgrid.h>
36 #include <wx/propgrid/advprops.h>
37 #include <wx/propgrid/manager.h>
38 
39 #include "objinspect.h"
40 #include "wxfbadvprops.h"
41 
42 #include "model/objectbase.h"
43 #include "utils/debug.h"
44 #include "utils/typeconv.h"
45 
46 #include "rad/appdata.h"
47 #include "rad/bitmaps.h"
48 #include "rad/wxfbevent.h"
49 #include "rad/auitabart.h"
50 
51 #include <wx/tokenzr.h>
52 #include <wx/config.h>
53 
54 static int wxEVT_FB_PROP_BITMAP_CHANGED = wxNewEventType();
55 
56 #define WXFB_PROPERTY_GRID 1000
57 #define WXFB_EVENT_GRID    1001
58 
59 // -----------------------------------------------------------------------
60 // ObjectInspector
61 // -----------------------------------------------------------------------
BEGIN_EVENT_TABLE(ObjectInspector,wxPanel)62 BEGIN_EVENT_TABLE(ObjectInspector, wxPanel)
63     EVT_PG_CHANGING(WXFB_PROPERTY_GRID, ObjectInspector::OnPropertyGridChanging)
64     EVT_PG_CHANGED(WXFB_PROPERTY_GRID, ObjectInspector::OnPropertyGridChanged)
65     EVT_PG_CHANGED(WXFB_EVENT_GRID, ObjectInspector::OnEventGridChanged)
66     EVT_PG_DOUBLE_CLICK(WXFB_EVENT_GRID, ObjectInspector::OnEventGridDblClick)
67     EVT_PG_DOUBLE_CLICK(WXFB_PROPERTY_GRID, ObjectInspector::OnPropertyGridDblClick)
68     EVT_PG_ITEM_COLLAPSED(WXFB_PROPERTY_GRID, ObjectInspector::OnPropertyGridExpand)
69     EVT_PG_ITEM_EXPANDED(WXFB_PROPERTY_GRID, ObjectInspector::OnPropertyGridExpand)
70     EVT_PG_ITEM_COLLAPSED(WXFB_EVENT_GRID, ObjectInspector::OnEventGridExpand)
71     EVT_PG_ITEM_EXPANDED(WXFB_EVENT_GRID, ObjectInspector::OnEventGridExpand)
72 	EVT_PG_SELECTED(WXFB_PROPERTY_GRID, ObjectInspector::OnPropertyGridItemSelected)
73 	EVT_PG_SELECTED(WXFB_EVENT_GRID, ObjectInspector::OnPropertyGridItemSelected)
74 
75     EVT_FB_OBJECT_SELECTED( ObjectInspector::OnObjectSelected )
76     EVT_FB_PROJECT_REFRESH( ObjectInspector::OnProjectRefresh )
77     EVT_FB_PROPERTY_MODIFIED( ObjectInspector::OnPropertyModified )
78     EVT_FB_EVENT_HANDLER_MODIFIED( ObjectInspector::OnEventHandlerModified )
79 #if wxVERSION_NUMBER >= 2900
80 	EVT_CHILD_FOCUS( ObjectInspector::OnChildFocus )
81 #endif
82 END_EVENT_TABLE()
83 
84 ObjectInspector::ObjectInspector( wxWindow* parent, int id, int style )
85 : wxPanel(parent,id), m_style(style)
86 {
87     AppData()->AddHandler( this->GetEventHandler() );
88     m_currentSel = PObjectBase();
89 
90 #ifdef USE_FLATNOTEBOOK
91     long nbStyle;
92     wxConfigBase* config = wxConfigBase::Get();
93     config->Read( wxT("/mainframe/objectInspector/notebook_style"), &nbStyle, wxFNB_NO_X_BUTTON | wxFNB_NO_NAV_BUTTONS | wxFNB_NODRAG | wxFNB_DROPDOWN_TABS_LIST | wxFNB_FF2 | wxFNB_CUSTOM_DLG );
94 
95     m_nb = new wxFlatNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, FNB_STYLE_OVERRIDES( nbStyle ) );
96     m_nb->SetCustomizeOptions( wxFNB_CUSTOM_TAB_LOOK | wxFNB_CUSTOM_ORIENTATION | wxFNB_CUSTOM_LOCAL_DRAG );
97 
98     m_icons.Add( AppBitmaps::GetBitmap( wxT("properties"), 16 ) );
99     m_icons.Add( AppBitmaps::GetBitmap( wxT("events"), 16 ) );
100     m_nb->SetImageList( &m_icons );
101 #else
102 	m_nb = new wxAuiNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP );
103 	m_nb->SetArtProvider( new AuiTabArt() );
104 #endif
105 
106     // The colour of property grid description looks ugly if we don't set this colour
107     m_nb->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
108 
109     // Register the slider editor
110 #if wxUSE_SLIDER
111     #if wxVERSION_NUMBER < 2900
112         wxPGEditor* sliderEditor = new wxPGSliderEditor();
113         wxPropertyGrid::RegisterEditorClass( sliderEditor, wxT("Slider") );
114     #else
115         // TODO
116     #endif
117 #endif
118     m_pg = CreatePropertyGridManager(m_nb, WXFB_PROPERTY_GRID);
119     m_eg = CreatePropertyGridManager(m_nb, WXFB_EVENT_GRID);
120 
121     m_nb->AddPage( m_pg, _("Properties"), false, 0 );
122     m_nb->AddPage( m_eg, _("Events"),     false, 1 );
123 
124 #ifndef USE_FLATNOTEBOOK
125 	m_nb->SetPageBitmap( 0, AppBitmaps::GetBitmap( wxT("properties"), 16 ) );
126 	m_nb->SetPageBitmap( 1, AppBitmaps::GetBitmap( wxT("events"), 16 ) );
127 #endif
128 
129     wxBoxSizer* topSizer = new wxBoxSizer( wxVERTICAL );
130     topSizer->Add( m_nb, 1, wxALL | wxEXPAND, 0 );
131     SetSizer( topSizer );
132 
133 	Connect( wxID_ANY, wxEVT_FB_PROP_BITMAP_CHANGED, wxCommandEventHandler( ObjectInspector::OnBitmapPropertyChanged) );
134 }
135 
~ObjectInspector()136 ObjectInspector::~ObjectInspector()
137 {
138 	Disconnect( wxID_ANY, wxEVT_FB_PROP_BITMAP_CHANGED, wxCommandEventHandler( ObjectInspector::OnBitmapPropertyChanged) );
139 
140     AppData()->RemoveHandler( this->GetEventHandler() );
141 }
142 
SavePosition()143 void ObjectInspector::SavePosition()
144 {
145     // Save Layout
146     wxConfigBase* config = wxConfigBase::Get();
147     config->Write( wxT("/mainframe/objectInspector/DescBoxHeight" ), m_pg->GetDescBoxHeight() );
148 #ifdef USE_FLATNOTEBOOK
149     config->Write( wxT("/mainframe/objectInspector/notebook_style"), m_nb->GetWindowStyleFlag() );
150 #endif
151 }
152 
Create(bool force)153 void ObjectInspector::Create( bool force )
154 {
155     PObjectBase sel_obj = AppData()->GetSelectedObject();
156     if ( sel_obj && ( sel_obj != m_currentSel || force ) )
157     {
158         Freeze();
159 
160         m_currentSel = sel_obj;
161 
162         int pageNumber = m_pg->GetSelectedPage();
163         wxString pageName;
164         if ( pageNumber != wxNOT_FOUND )
165         {
166             pageName = m_pg->GetPageName( pageNumber );
167         }
168 
169         // Clear Property Grid Manager
170         m_pg->Clear();
171 
172         // Now we do the same thing for event grid...
173         m_eg->Clear();
174 
175         m_propMap.clear();
176         m_eventMap.clear();
177 
178         PObjectInfo obj_desc = sel_obj->GetObjectInfo();
179         if (obj_desc)
180         {
181             PropertyMap propMap, dummyPropMap;
182             EventMap eventMap, dummyEventMap;
183 
184             // We create the categories with the properties of the object organized by "classes"
185             CreateCategory( obj_desc->GetClassName(), sel_obj, obj_desc, propMap, false );
186             CreateCategory( obj_desc->GetClassName(), sel_obj, obj_desc, eventMap, true );
187 
188             for (unsigned int i=0; i<obj_desc->GetBaseClassCount() ; i++)
189             {
190                 PObjectInfo info_base = obj_desc->GetBaseClass(i);
191                 CreateCategory( info_base->GetClassName(), sel_obj, info_base, propMap, false );
192                 CreateCategory( info_base->GetClassName(), sel_obj, info_base, eventMap, true );
193             }
194 
195             PObjectBase parent = sel_obj->GetParent();
196             if ( parent )
197             {
198                 PObjectInfo parent_desc = parent->GetObjectInfo();
199                 if ( parent_desc->GetObjectType()->IsItem())
200                 {
201                     CreateCategory( parent_desc->GetClassName(), parent, parent_desc, dummyPropMap, false );
202                     CreateCategory( parent_desc->GetClassName(), parent, parent_desc, dummyEventMap, true );
203 
204                     for (unsigned int i=0; i<parent_desc->GetBaseClassCount() ; i++)
205                     {
206                         PObjectInfo info_base = parent_desc->GetBaseClass(i);
207                         CreateCategory( info_base->GetClassName(), parent, info_base, dummyPropMap, false );
208                         CreateCategory( info_base->GetClassName(), parent, info_base, dummyEventMap, true );
209                     }
210                 }
211             }
212 
213             // Select previously selected page, or first page
214             if ( m_pg->GetPageCount() > 0 )
215             {
216                 int pageIndex = m_pg->GetPageByName( pageName );
217                 if ( wxNOT_FOUND != pageIndex )
218                 {
219                     m_pg->SelectPage( pageIndex );
220                 }
221                 else
222                 {
223                     m_pg->SelectPage( 0 );
224                 }
225             }
226         }
227 
228         m_pg->Refresh();
229         m_pg->Update();
230         m_eg->Refresh();
231         m_eg->Update();
232         Thaw();
233 
234 		RestoreLastSelectedPropItem();
235     }
236 }
237 
StringToBits(const wxString & strVal,wxPGChoices & constants)238 int ObjectInspector::StringToBits(const wxString& strVal, wxPGChoices& constants)
239 {
240     wxStringTokenizer strTok(strVal, wxT(" |"));
241     int val = 0;
242     while (strTok.HasMoreTokens())
243     {
244         wxString token = strTok.GetNextToken();
245         unsigned int i = 0;
246         bool done = false;
247         while (i < constants.GetCount() && !done)
248         {
249             if (constants.GetLabel(i) == token)
250             {
251                 val |= constants.GetValue(i);
252                 done = true;
253             }
254             i++;
255         }
256     }
257     return val;
258 }
259 
GetProperty(PProperty prop)260 wxPGProperty* ObjectInspector::GetProperty( PProperty prop )
261 {
262     wxPGProperty *result = NULL;
263     PropertyType type = prop->GetType();
264     wxString name = prop->GetName();
265     wxVariant vTrue = wxVariant( true, wxT("true") );
266 
267     if (type == PT_MACRO)
268     {
269         result = new wxStringProperty( name, wxPG_LABEL, prop->GetValueAsString() );
270     }
271     else if (type == PT_INT)
272     {
273         result = new wxIntProperty( name, wxPG_LABEL, prop->GetValueAsInteger() );
274     }
275     else if (type == PT_UINT)
276     {
277         result = new wxUIntProperty( name, wxPG_LABEL, (unsigned)prop->GetValueAsInteger() );
278     }
279 	else if (type == PT_WXSTRING || type == PT_WXSTRING_I18N)
280     {
281 		result = new wxLongStringProperty( name, wxPG_LABEL, prop->GetValueAsText() );
282 	}
283 	else if (type == PT_TEXT)
284     {
285         result = new wxLongStringProperty( name, wxPG_LABEL, prop->GetValueAsString() );
286         result->ChangeFlag( wxPG_PROP_NO_ESCAPE, true );
287     }
288     else if (type == PT_BOOL)
289     {
290         result = new wxBoolProperty( name, wxPG_LABEL, prop->GetValue() == wxT("1") );
291     }
292     else if (type == PT_BITLIST)
293     {
294         PPropertyInfo prop_desc = prop->GetPropertyInfo();
295         POptionList opt_list = prop_desc->GetOptionList();
296 
297         assert(opt_list && opt_list->GetOptionCount() > 0);
298 
299         wxPGChoices constants;
300         const std::map< wxString, wxString > options = opt_list->GetOptions();
301         std::map< wxString, wxString >::const_iterator it;
302         unsigned int i = 0;
303         for( it = options.begin(); it != options.end(); ++it )
304         {
305             constants.Add( it->first, 1 << i++ );
306         }
307 
308         int val = StringToBits(prop->GetValueAsString(), constants);
309         result = new wxFlagsProperty(name, wxPG_LABEL, constants, val);
310 
311         // Workaround to set the help strings for individual members of a wxFlagsProperty
312         wxFlagsProperty* flagsProp = dynamic_cast< wxFlagsProperty* >( result );
313         if ( NULL != flagsProp )
314         {
315             for ( size_t i = 0; i < flagsProp->GetItemCount(); i++ )
316             {
317                 wxPGProperty* prop = flagsProp->Item( i );
318                 std::map< wxString, wxString >::const_iterator option = options.find( prop->GetLabel() );
319                 if ( option != options.end() )
320                 {
321                     m_pg->SetPropertyHelpString( prop, option->second );
322                 }
323             }
324         }
325     }
326     else if (type == PT_INTLIST || type == PT_UINTLIST)
327     {
328         result = new wxStringProperty( name, wxPG_LABEL, IntList( prop->GetValueAsString(), type == PT_UINTLIST ).ToString() );
329     }
330     else if (type == PT_OPTION)
331     {
332         PPropertyInfo prop_desc = prop->GetPropertyInfo();
333         POptionList opt_list = prop_desc->GetOptionList();
334 
335         assert(opt_list && opt_list->GetOptionCount() > 0);
336 
337         wxString value = prop->GetValueAsString();
338         wxString help;
339 
340         wxPGChoices constants;
341         const std::map< wxString, wxString > options = opt_list->GetOptions();
342         std::map< wxString, wxString >::const_iterator it;
343         unsigned int i = 0;
344         for( it = options.begin(); it != options.end(); ++it )
345         {
346             constants.Add( it->first, i++ );
347             if ( it->first == value )
348             {
349                 // Save help
350                 help = it->second;
351             }
352         }
353 
354         result = new wxEnumProperty( name, wxPG_LABEL, constants );
355         result->SetValueFromString( value, 0 );
356         wxString desc = prop_desc->GetDescription();
357         if ( desc.empty() )
358         {
359             desc = value + wxT(":\n") + help;
360         }
361         else
362         {
363             desc += wxT("\n\n") + value + wxT(":\n") + help;
364         }
365         result->SetHelpString( wxGetTranslation( desc ) );
366 
367     }
368     else if (type == PT_WXPOINT)
369     {
370         result = new wxFBPointProperty( name, wxPG_LABEL, prop->GetValueAsPoint() );
371     }
372     else if (type == PT_WXSIZE)
373     {
374         result = new wxFBSizeProperty( name, wxPG_LABEL, prop->GetValueAsSize() );
375     }
376     else if (type == PT_WXFONT)
377     {
378         result = new wxFBFontProperty( name, wxPG_LABEL, TypeConv::StringToFont( prop->GetValueAsString() ) );
379     }
380     else if (type == PT_WXCOLOUR)
381     {
382         wxString value = prop->GetValueAsString();
383         if ( value.empty() )  // Default Colour
384         {
385             wxColourPropertyValue colProp;
386             colProp.m_type = wxSYS_COLOUR_WINDOW;
387             colProp.m_colour = TypeConv::StringToSystemColour( wxT("wxSYS_COLOUR_WINDOW") );
388             result = new wxSystemColourProperty( name, wxPG_LABEL, colProp );
389         }
390         else
391         {
392             if ( value.find_first_of( wxT("wx") ) == 0 )
393             {
394                 wxColourPropertyValue def; // System Colour
395                 def.m_type = TypeConv::StringToSystemColour( value );
396                 result = new wxSystemColourProperty( name, wxPG_LABEL, def );
397             }
398             else
399             {
400                 result = new wxSystemColourProperty( name, wxPG_LABEL, prop->GetValueAsColour() );
401             }
402         }
403     }
404     else if (type == PT_PATH)
405     {
406         result = new wxDirProperty( name, wxPG_LABEL, prop->GetValueAsString() );
407     }
408     else if (type == PT_FILE)
409     {
410         result = new wxFileProperty( name, wxPG_LABEL, prop->GetValueAsString() );
411     }
412     else if (type == PT_BITMAP)
413     {
414         wxLogDebug( wxT("OI::GetProperty: prop:%s"), prop->GetValueAsString().c_str() );
415 
416         result = new wxFBBitmapProperty( name, wxPG_LABEL, prop->GetValueAsString() );
417     }
418     else if (type == PT_STRINGLIST)
419     {
420         result = new wxArrayStringProperty( name, wxPG_LABEL,prop->GetValueAsArrayString() );
421 #if wxVERSION_NUMBER >= 2901
422         wxVariant v("\"");
423         result->DoSetAttribute(wxPG_ARRAY_DELIMITER, v);
424 #endif
425     }
426     else if (type == PT_FLOAT)
427     {
428         result = new wxFloatProperty( name, wxPG_LABEL, prop->GetValueAsFloat() );
429     }
430     else if ( type == PT_PARENT )
431     {
432 		result = new wxPGProperty( name, wxPG_LABEL );
433 
434 		/*wxPGProperty* parent = new wxPGProperty( name, wxPG_LABEL );
435 		parent->SetValueFromString( prop->GetValueAsString(), wxPG_FULL_VALUE );
436         //wxPGProperty* parent = new wxStringProperty( name, wxPG_LABEL, wxT("<composed>") );
437         //parent->SetValueFromString( prop->GetValueAsString() );
438 
439         PPropertyInfo prop_desc = prop->GetPropertyInfo();
440         std::list< PropertyChild >* children = prop_desc->GetChildren();
441         std::list< PropertyChild >::iterator it;
442         for ( it = children->begin(); it != children->end(); ++it )
443         {
444             wxPGProperty* child = new wxStringProperty( it->m_name, wxPG_LABEL, wxEmptyString );
445 			parent->AppendChild( child );
446             m_pg->SetPropertyHelpString( child, it->m_description );
447         }
448 
449         result = parent;*/
450     }
451     else // Unknown property
452     {
453         result = new wxStringProperty( name, wxPG_LABEL, prop->GetValueAsString() );
454         result->SetAttribute( wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING, vTrue );
455         wxLogError(_("Property type Unknown") );
456     }
457 
458     return result;
459 }
460 
AddItems(const wxString & name,PObjectBase obj,PObjectInfo obj_info,PPropertyCategory category,PropertyMap & properties)461 void ObjectInspector::AddItems( const wxString& name, PObjectBase obj,
462   PObjectInfo obj_info, PPropertyCategory category, PropertyMap &properties )
463 {
464     size_t propCount = category->GetPropertyCount();
465     for ( size_t i = 0; i < propCount; i++ )
466     {
467         wxString propName = category->GetPropertyName( i );
468         PProperty prop = obj->GetProperty( propName );
469 
470         if ( !prop )
471             continue;
472 
473         PPropertyInfo propInfo = prop->GetPropertyInfo();
474 
475         // we do not want to duplicate inherited properties
476         if ( properties.find( propName ) == properties.end() )
477         {
478             wxPGProperty* id       = m_pg->Append( GetProperty( prop ) );
479             int           propType = prop->GetType();
480 
481             if ( propType != PT_OPTION )
482             {
483                 m_pg->SetPropertyHelpString( id, propInfo->GetDescription() );
484 
485                 if ( propType == PT_BITMAP )
486                 {
487                     wxFBBitmapProperty *bp = wxDynamicCast( id, wxFBBitmapProperty );
488                     if ( bp )
489                     {
490                         bp->CreateChildren();
491 
492 						// perform delayed child properties update
493 						wxCommandEvent e( wxEVT_FB_PROP_BITMAP_CHANGED );
494 						e.SetString( bp->GetName() + wxT(":") + prop->GetValue() );
495 						GetEventHandler()->AddPendingEvent( e );
496 
497                         //AppData()->ModifyProperty( prop, bp->GetValueAsString() );
498                     }
499                 }
500 				else if( propType == PT_PARENT )
501 				{
502 					PPropertyInfo prop_desc = prop->GetPropertyInfo();
503 					std::list< PropertyChild >* children = prop_desc->GetChildren();
504 					std::list< PropertyChild >::iterator it;
505 					wxArrayString values = wxStringTokenize( prop->GetValueAsString(), wxT(";"), wxTOKEN_RET_EMPTY_ALL );
506 					size_t i = 0;
507 					wxString value;
508 
509 					for ( it = children->begin(); it != children->end(); ++it )
510 					{
511 						if( values.GetCount() > i ) value = values[i++].Trim().Trim(false);
512 						else value = wxT("");
513 
514 						wxPGProperty* child = new wxStringProperty( it->m_name, wxPG_LABEL, value );
515 						id->AppendChild( child );
516 						m_pg->SetPropertyHelpString( child, it->m_description );
517 					}
518 				}
519             }
520 
521             wxString customEditor = propInfo->GetCustomEditor();
522             if ( !customEditor.empty() )
523             {
524                 wxPGEditor* editor = m_pg->GetEditorByName( customEditor );
525                 if ( editor )
526                 {
527                     m_pg->SetPropertyEditor( id, editor );
528                 }
529             }
530 
531             if (m_style != wxFB_OI_MULTIPAGE_STYLE)
532             {
533                 // Most common classes will be showed with a slightly different colour.
534                 if (name == wxT("wxWindow"))
535                     m_pg->SetPropertyBackgroundColour(id,wxColour(255,255,205)); // yellow
536 				else if (name == wxT("AUI"))
537                     m_pg->SetPropertyBackgroundColour(id,wxColour(240,240,255)); // light blue
538                 else if (name == wxT("sizeritem") || name == wxT("gbsizeritem") || name == wxT("sizeritembase") )
539                     m_pg->SetPropertyBackgroundColour(id,wxColour(220,255,255)); // cyan
540             }
541 
542             ExpandMap::iterator it = m_isExpanded.find( propName );
543             if ( it != m_isExpanded.end() )
544             {
545                 if ( it->second )
546                 {
547                     m_pg->Expand( id );
548                 }
549                 else
550                 {
551                     m_pg->Collapse( id );
552                 }
553             }
554 
555             properties.insert( PropertyMap::value_type( propName, prop ) );
556             m_propMap.insert( ObjInspectorPropertyMap::value_type( id, prop ) );
557         }
558     }
559 
560     size_t catCount = category->GetCategoryCount();
561     for ( size_t i = 0; i < catCount; i++ )
562     {
563         PPropertyCategory nextCat = category->GetCategory( i );
564         if ( 0 == nextCat->GetCategoryCount() && 0 == nextCat->GetPropertyCount() )
565         {
566             continue;
567         }
568         wxPGProperty* catId = m_pg->AppendIn( category->GetName() , new wxPropertyCategory( nextCat->GetName() ) );
569 
570         AddItems( name, obj, obj_info, nextCat, properties );
571 
572         ExpandMap::iterator it = m_isExpanded.find( nextCat->GetName() );
573         if ( it != m_isExpanded.end() )
574         {
575             if ( it->second )
576             {
577                 m_pg->Expand( catId );
578             }
579             else
580             {
581                 m_pg->Collapse( catId );
582             }
583         }
584     }
585 }
586 
AddItems(const wxString & name,PObjectBase obj,PObjectInfo obj_info,PPropertyCategory category,EventMap & events)587 void ObjectInspector::AddItems( const wxString& name, PObjectBase obj,
588   PObjectInfo obj_info, PPropertyCategory category, EventMap &events )
589 {
590     size_t eventCount = category->GetEventCount();
591     for ( size_t i = 0; i < eventCount; i++ )
592     {
593         wxString eventName = category->GetEventName( i );
594         PEvent event = obj->GetEvent( eventName );
595 
596         if ( !event )
597             continue;
598 
599         PEventInfo eventInfo = event->GetEventInfo();
600 
601         // We do not want to duplicate inherited events
602         if ( events.find( eventName ) == events.end() )
603         {
604             wxPGProperty* pgProp = new wxStringProperty( eventInfo->GetName(), wxPG_LABEL, event->GetValue() );
605             wxPGProperty* id = m_eg->Append( pgProp );
606 
607             m_eg->SetPropertyHelpString( id, wxGetTranslation( eventInfo->GetDescription() ) );
608 
609             if (m_style != wxFB_OI_MULTIPAGE_STYLE)
610             {
611                 // Most common classes will be showed with a slightly different colour.
612                 if (name == wxT("wxWindow"))
613                     m_eg->SetPropertyBackgroundColour( id, wxColour( 255, 255, 205 ) ); // Yellow
614 				else if (name == wxT("AUI Events"))
615                     m_eg->SetPropertyBackgroundColour( id, wxColour(240,240,255) ); // light blue
616                 else if (name == wxT("sizeritem") || name == wxT("gbsizeritem") || name == wxT("sizeritembase") )
617                     m_eg->SetPropertyBackgroundColour( id, wxColour( 220, 255, 255 ) ); // Cyan
618             }
619 
620             ExpandMap::iterator it = m_isExpanded.find(eventName);
621             if ( it != m_isExpanded.end() )
622             {
623                 if ( it->second )
624                 {
625                     m_eg->Expand( id );
626                 }
627                 else
628                 {
629                     m_eg->Collapse( id );
630                 }
631             }
632 
633             events.insert( EventMap::value_type( eventName, event ) );
634             m_eventMap.insert( ObjInspectorEventMap::value_type( id, event ) );
635         }
636     }
637 
638     size_t catCount = category->GetCategoryCount();
639     for ( size_t i = 0; i < catCount; i++ )
640     {
641         PPropertyCategory nextCat = category->GetCategory( i );
642         if ( 0 == nextCat->GetCategoryCount() && 0 == nextCat->GetEventCount() )
643         {
644             continue;
645         }
646         wxPGProperty* catId = m_eg->AppendIn( category->GetName(), new wxPropertyCategory( nextCat->GetName() ) );
647 
648         AddItems( name, obj, obj_info, nextCat, events );
649 
650         ExpandMap::iterator it = m_isExpanded.find( nextCat->GetName() );
651         if ( it != m_isExpanded.end() )
652         {
653             if ( it->second )
654             {
655                 m_eg->Expand( catId );
656             }
657             else
658             {
659                 m_eg->Collapse( catId );
660             }
661         }
662     }
663 }
664 
OnPropertyGridChanging(wxPropertyGridEvent & event)665 void ObjectInspector::OnPropertyGridChanging( wxPropertyGridEvent& event )
666 {
667     wxImageFileProperty *imgFileProp = wxDynamicCast( event.GetProperty(), wxImageFileProperty );
668 
669     if ( imgFileProp )
670     {
671         // GetValue() returns the pending value, but is only supported by wxEVT_PG_CHANGING.
672         wxFBBitmapProperty *bmpProp = wxDynamicCast( imgFileProp->GetParent(), wxFBBitmapProperty );
673 
674         if ( bmpProp )
675         {
676             wxString img = bmpProp->SetupImage( event.GetValue().GetString() );
677             if ( img == wxEmptyString )
678             {
679                 event.Veto();
680                 return;
681             }
682         }
683     }
684 }
685 
OnPropertyGridChanged(wxPropertyGridEvent & event)686 void ObjectInspector::OnPropertyGridChanged( wxPropertyGridEvent& event )
687 {
688     wxPGProperty* propPtr = event.GetProperty();
689 
690 //    wxPGProperty       *parent  = propPtr->GetParent();
691 //    wxFBBitmapProperty *bp = wxDynamicCast( parent, wxFBBitmapProperty );
692 //
693 //    // Handle the main bitmap property
694 //    if ( bp )
695 //    {
696 //#if wxVERSION_NUMBER >= 2900
697 //        // GetValue() returns wxVariant, but it is converted transparently to wxAny
698 //        wxAny
699 //#else
700 //        wxVariant
701 //#endif
702 //        childValue = propPtr->GetValue();
703 //
704 //        // Also, handle the case where property value is unspecified
705 //        if ( childValue.IsNull() )
706 //            return;
707 //
708 //        // bp->GetValue() have no updated value...
709 //        wxString bmpVal = bp->GetValueAsString( wxPG_FULL_VALUE );
710 //
711 //        // Handle changes in values, as needed
712 //        wxVariant    thisValue  = WXVARIANT( bmpVal );
713 //        unsigned int childIndex = propPtr->GetIndexInParent();
714 //
715 //wxLogDebug( wxT("OI::OnPGChanged: thisValue (AsString):%s"),  bp->GetValueAsString().c_str() );
716 //wxLogDebug( wxT("OI::OnPGChanged: childValue (AsString):%s"), propPtr->GetValueAsString().c_str() );
717 //wxLogDebug( wxT("OI::OnPGChanged: thisValue:%s childIndex:%i childValue:%s" ),
718 //        thisValue.GetString().c_str(), childIndex, childValue.GetString().c_str() );
719 //
720 //        ObjInspectorPropertyMap::iterator itBmp = m_propMap.find( bp );
721 //        PProperty bmpProp = itBmp->second;
722 //
723 //#if wxVERSION_NUMBER >= 2900
724 //        wxVariant newVal =
725 //#endif
726 //        bp->ChildChanged( thisValue, propPtr->GetIndexInParent(), childValue );
727 //
728 //#if wxVERSION_NUMBER >= 2900
729 //        AppData()->ModifyProperty( bmpProp, newVal.GetString() );
730 //#else
731 //        wxLogDebug( wxT("OI::OnPGChanged: Setting prop value to %s"), thisValue.GetString().c_str() );
732 //        AppData()->ModifyProperty( bmpProp, thisValue.GetString() );
733 //        wxLogDebug( wxT("OI::OnPGChanged: Changed prop value to %s"), bmpProp->GetValueAsString().c_str() );
734 //#endif
735 //    }
736 
737     ObjInspectorPropertyMap::iterator it = m_propMap.find( propPtr );
738 
739     if ( m_propMap.end() == it )
740     {
741         // Could be a child property
742         propPtr = propPtr->GetParent();
743         it = m_propMap.find( propPtr );
744     }
745     if ( it != m_propMap.end() )
746     {
747         PProperty prop = it->second;
748         switch ( prop->GetType() )
749         {
750 
751             case PT_FLOAT:
752             {
753                 // Use typeconv to properly handle locale
754                 double val = m_pg->GetPropertyValueAsDouble( propPtr );
755                 ModifyProperty( prop, TypeConv::FloatToString( val ) );
756                 break;
757             }
758             case PT_TEXT:
759             case PT_MACRO:
760             case PT_INT:
761             case PT_UINT:
762             {
763                 ModifyProperty( prop, m_pg->GetPropertyValueAsString( propPtr ) );
764                 break;
765             }
766             case PT_OPTION:
767             {
768                 wxString value = m_pg->GetPropertyValueAsString( propPtr );
769                 ModifyProperty( prop, value );
770 
771                 // Update displayed description for the new selection
772                 PPropertyInfo prop_desc = prop->GetPropertyInfo();
773                 POptionList opt_list = prop_desc->GetOptionList();
774 
775                 wxString helpString = prop_desc->GetDescription();
776                 if ( opt_list && opt_list->GetOptionCount() > 0 )
777                 {
778                     const std::map< wxString, wxString > options = opt_list->GetOptions();
779                     std::map< wxString, wxString >::const_iterator option = options.find( value );
780                     if ( option != options.end() )
781                     {
782                         if ( helpString.empty() )
783                         {
784                             helpString = value + wxT(":\n") + option->second;
785                         }
786                         else
787                         {
788                             helpString += wxT("\n\n") + value + wxT(":\n") + option->second;
789                         }
790                     }
791                 }
792                 wxString localized = wxGetTranslation( helpString );
793                 m_pg->SetPropertyHelpString( propPtr, localized );
794                 m_pg->SetDescription( propPtr->GetLabel(), localized );
795                 break;
796             }
797             case PT_PARENT:
798             {
799 #if wxVERSION_NUMBER >= 2900
800 				ModifyProperty( prop, propPtr->GenerateComposedValue( ));
801 #else
802                 ModifyProperty( prop, propPtr->GetValueAsString( wxPG_FULL_VALUE ) );
803 #endif
804                 break;
805             }
806             case PT_WXSTRING:
807             case PT_WXSTRING_I18N:
808             {
809                 // ObjectInspector's text strings are formatted.
810                 wxString value = TypeConv::TextToString( m_pg->GetPropertyValueAsString( propPtr ) );
811                 ModifyProperty( prop, value );
812                 break;
813             }
814             case PT_BOOL:
815             {
816                 if( prop->GetName() == wxT("aui_managed") )
817                 {
818                     PObjectBase propobj = prop->GetObject();
819                     if( propobj->GetChildCount() )
820                     {
821                         wxMessageBox(_("You have to remove all child widgets first."));
822 #if wxVERSION_NUMBER < 2900
823                         m_pg->SetPropertyValueBool( propPtr, !m_pg->GetPropertyValueAsBool( propPtr )  );
824 #else
825                         m_pg->SetPropertyValue( propPtr, !m_pg->GetPropertyValueAsBool( propPtr )  );
826 #endif
827                     }
828                     else
829                         ModifyProperty( prop, m_pg->GetPropertyValueAsBool( propPtr ) ? wxT("1") : wxT("0") );
830                 }
831                 else
832                     ModifyProperty( prop, m_pg->GetPropertyValueAsBool( propPtr ) ? wxT("1") : wxT("0") );
833                 break;
834             }
835             case PT_BITLIST:
836             {
837                 wxString aux = m_pg->GetPropertyValueAsString( propPtr );
838                 aux.Replace( wxT(" "), wxT("") );
839                 aux.Replace( wxT(","), wxT("|") );
840                 ModifyProperty( prop, aux );
841                 break;
842             }
843             case PT_WXPOINT:
844             {
845 #if wxVERSION_NUMBER < 2900
846                 wxPoint point = wxPointFromVariant( event.GetPropertyValue () );
847 #else
848                 wxPoint point = wxPointRefFromVariant( event.GetPropertyValue () );
849 #endif
850                 ModifyProperty( prop, wxString::Format(  wxT("%i,%i"), point.x, point.y ) );
851                 break;
852             }
853             case PT_WXSIZE:
854             {
855 #if wxVERSION_NUMBER < 2900
856                 wxSize size = wxSizeFromVariant( event.GetPropertyValue() );
857 #else
858                 wxSize size = wxSizeRefFromVariant( event.GetPropertyValue() );
859 #endif
860                 ModifyProperty( prop, wxString::Format( wxT("%i,%i"), size.GetWidth(), size.GetHeight() ) );
861                 break;
862             }
863             case PT_WXFONT:
864             {
865 				ModifyProperty( prop, event.GetPropertyValue().GetString() );
866                 break;
867             }
868             case PT_WXCOLOUR:
869             {
870                 wxColourPropertyValue colour;
871                 colour << event.GetPropertyValue();
872                 switch ( colour.m_type ) {
873                 case wxSYS_COLOUR_MAX:
874                     ModifyProperty( prop, wxT("") );
875                     break;
876                 case wxPG_COLOUR_CUSTOM:
877                     ModifyProperty( prop, TypeConv::ColourToString( colour.m_colour ) );
878                     break;
879                 default:
880                     wxString sCol = TypeConv::SystemColourToString( colour.m_type );
881                     ModifyProperty( prop, sCol );
882                 }
883                 break;
884             }
885             case PT_INTLIST:
886             case PT_UINTLIST:
887             {
888                 IntList il( event.GetPropertyValue(), PT_UINTLIST == prop->GetType() );
889                 ModifyProperty( prop, il.ToString() );
890                 break;
891             }
892             case PT_BITMAP:
893             {
894 				wxVariant childValue = event.GetProperty()->GetValue();
895 
896 				// Also, handle the case where property value is unspecified
897 				if ( childValue.IsNull() )
898 					return;
899 
900 				// bp->GetValue() have no updated value...
901 				wxString bmpVal = propPtr->GetValueAsString( wxPG_FULL_VALUE );
902 
903 				// Handle changes in values, as needed
904 				wxVariant thisValue  = WXVARIANT(bmpVal);
905 
906 #if wxVERSION_NUMBER >= 2900
907 				wxVariant newVal =
908                 propPtr->ChildChanged( thisValue, (int)event.GetProperty()->GetIndexInParent(), childValue );
909 #else
910 				propPtr->ChildChanged( thisValue, event.GetProperty()->GetIndexInParent(), childValue );
911 #endif
912 
913 #if wxVERSION_NUMBER >= 2900
914 				ModifyProperty( prop, newVal.GetString() );
915 #else
916 				ModifyProperty( prop, bmpVal);
917 #endif
918 
919 				if( event.GetProperty()->GetIndexInParent() > 0 )
920 				{
921 					// perform delayed child properties update
922 					wxCommandEvent e( wxEVT_FB_PROP_BITMAP_CHANGED );
923 					e.SetString( propPtr->GetName() + wxT(":") + bmpVal );
924 					GetEventHandler()->AddPendingEvent( e );
925 				}
926 
927                 break;
928             }
929 
930             default:
931                 //ModifyProperty( prop, event.GetPropertyValue() );
932                 ModifyProperty( prop, propPtr->GetValueAsString() );
933         }
934     }
935 }
936 
OnEventGridChanged(wxPropertyGridEvent & event)937 void ObjectInspector::OnEventGridChanged( wxPropertyGridEvent& event )
938 {
939     ObjInspectorEventMap::iterator it = m_eventMap.find( event.GetProperty() );
940 
941     if ( it != m_eventMap.end() )
942     {
943         PEvent evt = it->second;
944         wxString handler = event.GetPropertyValue();
945         handler.Trim();
946         handler.Trim( false );
947         AppData()->ModifyEventHandler( evt, handler );
948     }
949 }
950 
OnPropertyGridExpand(wxPropertyGridEvent & event)951 void ObjectInspector::OnPropertyGridExpand( wxPropertyGridEvent& event )
952 {
953     m_isExpanded[event.GetPropertyName()] = event.GetProperty()->IsExpanded();
954 
955     wxPGProperty* egProp = m_eg->GetProperty( event.GetProperty()->GetName() );
956     if ( egProp )
957     {
958         if ( event.GetProperty()->IsExpanded() )
959         {
960             m_eg->Expand( egProp );
961         }
962         else
963         {
964             m_eg->Collapse( egProp );
965         }
966     }
967 }
968 
OnEventGridExpand(wxPropertyGridEvent & event)969 void ObjectInspector::OnEventGridExpand( wxPropertyGridEvent& event )
970 {
971     m_isExpanded[event.GetPropertyName()] = event.GetProperty()->IsExpanded();
972 
973     wxPGProperty* pgProp = m_pg->GetProperty( event.GetProperty()->GetName() );
974     if ( pgProp )
975     {
976         if ( event.GetProperty()->IsExpanded() )
977         {
978             m_pg->Expand( pgProp );
979         }
980         else
981         {
982             m_pg->Collapse( pgProp );
983         }
984     }
985 }
986 
987 ///////////////////////////////////////////////////////////////////////////////
OnObjectSelected(wxFBObjectEvent & event)988 void ObjectInspector::OnObjectSelected( wxFBObjectEvent& event)
989 {
990     bool isForced = ( event.GetString() == wxT("force") );
991 
992     Create( isForced );
993 }
994 
OnProjectRefresh(wxFBEvent &)995 void ObjectInspector::OnProjectRefresh( wxFBEvent& )
996 {
997     Create( true );
998 }
999 
OnEventHandlerModified(wxFBEventHandlerEvent & event)1000 void ObjectInspector::OnEventHandlerModified( wxFBEventHandlerEvent& event )
1001 {
1002     PEvent e = event.GetFBEventHandler();
1003     m_eg->SetPropertyValue( e->GetName(), e->GetValue() );
1004     m_eg->Refresh();
1005 }
1006 
OnPropertyModified(wxFBPropertyEvent & event)1007 void ObjectInspector::OnPropertyModified( wxFBPropertyEvent& event )
1008 {
1009 	LogDebug("");
1010     PProperty prop = event.GetFBProperty();
1011 
1012     PObjectBase propobj = prop->GetObject();
1013     PObjectBase appobj = AppData()->GetSelectedObject();
1014 
1015     bool shouldContinue = ( prop->GetObject() == AppData()->GetSelectedObject() );
1016     if ( !shouldContinue )
1017     {
1018         // Item objects cannot be selected - their children are selected instead
1019         if ( propobj->GetObjectInfo()->GetObjectType()->IsItem() )
1020         {
1021             if ( propobj->GetChildCount() > 0 )
1022             {
1023                 shouldContinue = ( appobj == propobj->GetChild( 0 ) );
1024             }
1025         }
1026     }
1027     if ( !shouldContinue )
1028     {
1029         return;
1030     }
1031 
1032     wxPGProperty* pgProp = m_pg->GetPropertyByLabel(prop->GetName() );
1033     if ( pgProp == NULL ) return; // Maybe now isn't showing this page
1034 
1035 
1036     switch (prop->GetType())
1037     {
1038     case PT_FLOAT:
1039     {
1040         // Use float instead of string -> typeconv handles locale
1041         pgProp->SetValue( WXVARIANT( prop->GetValueAsFloat() ) );
1042         break;
1043     }
1044     case PT_INT:
1045     case PT_UINT:
1046     {
1047         pgProp->SetValueFromString(prop->GetValueAsString(), 0);
1048         break;
1049     }
1050     case PT_TEXT:
1051         pgProp->SetValueFromString(prop->GetValueAsString(), 0);
1052         break;
1053     case PT_MACRO:
1054     case PT_OPTION:
1055     case PT_PARENT:
1056     case PT_WXSTRING:
1057         pgProp->SetValueFromString(prop->GetValueAsText(), 0);
1058         break;
1059     case PT_WXSTRING_I18N:
1060         pgProp->SetValueFromString(prop->GetValueAsText(), 0);
1061         break;
1062     case PT_BOOL:
1063         pgProp->SetValueFromInt(prop->GetValueAsString() == wxT("0") ? 0 : 1, 0);
1064         break;
1065     case PT_BITLIST:
1066         {
1067             wxString aux = prop->GetValueAsString();
1068             aux.Replace(wxT("|"), wxT(", "));
1069             if (aux == wxT("0")) aux = wxT("");
1070             pgProp->SetValueFromString(aux, 0);
1071         }
1072         break;
1073     case PT_WXPOINT:
1074 		{
1075 			//m_pg->SetPropertyValue( pgProp, prop->GetValue() );
1076 			wxString aux = prop->GetValueAsString();
1077             aux.Replace(wxT(","), wxT(";"));
1078             pgProp->SetValueFromString(aux, 0);
1079 		}
1080         break;
1081     case PT_WXSIZE:
1082 		{
1083 			//m_pg->SetPropertyValue( pgProp, prop->GetValue() );
1084 			wxString aux = prop->GetValueAsString();
1085             aux.Replace(wxT(","), wxT(";"));
1086             pgProp->SetValueFromString(aux, 0);
1087 		}
1088         break;
1089     case PT_WXFONT:
1090 		pgProp->SetValue( WXVARIANT( prop->GetValueAsString() ) );
1091         break;
1092     case PT_WXCOLOUR:
1093         {
1094             wxString value = prop->GetValueAsString();
1095             if ( value.empty() )  // Default Colour
1096             {
1097                 wxColourPropertyValue def;
1098                 def.m_type = wxSYS_COLOUR_WINDOW;
1099                 def.m_colour = TypeConv::StringToSystemColour( wxT("wxSYS_COLOUR_WINDOW") );
1100                 m_pg->SetPropertyValue( pgProp, def );
1101             }
1102             else
1103             {
1104                 if ( value.find_first_of( wxT("wx") ) == 0 )
1105                 {
1106                     // System Colour
1107                     wxColourPropertyValue def;
1108                     def.m_type = TypeConv::StringToSystemColour( value );
1109                     def.m_colour = prop->GetValueAsColour();
1110                     m_pg->SetPropertyValue( pgProp, WXVARIANT( def ) );
1111                 }
1112                 else
1113                 {
1114                     wxColourPropertyValue def( wxPG_COLOUR_CUSTOM, prop->GetValueAsColour() );
1115                     m_pg->SetPropertyValue( pgProp, WXVARIANT( def ) );
1116                 }
1117             }
1118         }
1119         break;
1120     case PT_BITMAP:
1121 //      pgProp->SetValue( WXVARIANT( prop->GetValueAsString() ) );
1122         wxLogDebug( wxT("OI::OnPropertyModified: prop:%s"), prop->GetValueAsString().c_str() );
1123         break;
1124     default:
1125         pgProp->SetValueFromString(prop->GetValueAsString(), wxPG_FULL_VALUE);
1126     }
1127     AutoGenerateId(AppData()->GetSelectedObject(), event.GetFBProperty(), wxT("PropChange"));
1128     m_pg->Refresh();
1129 }
1130 
CreatePropertyGridManager(wxWindow * parent,wxWindowID id)1131 wxPropertyGridManager* ObjectInspector::CreatePropertyGridManager(wxWindow *parent, wxWindowID id)
1132 {
1133     int pgStyle;
1134     int defaultDescBoxHeight;
1135 
1136     switch (m_style)
1137     {
1138         case wxFB_OI_MULTIPAGE_STYLE:
1139             pgStyle = wxPG_BOLD_MODIFIED | wxPG_SPLITTER_AUTO_CENTER | wxPG_TOOLBAR | wxPG_DESCRIPTION | wxPGMAN_DEFAULT_STYLE;
1140             defaultDescBoxHeight = 50;
1141             break;
1142 
1143         case wxFB_OI_DEFAULT_STYLE:
1144         case wxFB_OI_SINGLE_PAGE_STYLE:
1145         default:
1146             pgStyle = wxPG_BOLD_MODIFIED | wxPG_SPLITTER_AUTO_CENTER | wxPG_DESCRIPTION | wxPGMAN_DEFAULT_STYLE;
1147             defaultDescBoxHeight = 150;
1148             break;
1149     }
1150 
1151     int descBoxHeight;
1152     wxConfigBase* config = wxConfigBase::Get();
1153     config->Read( wxT( "/mainframe/objectInspector/DescBoxHeight" ), &descBoxHeight, defaultDescBoxHeight );
1154     if ( -1 == descBoxHeight )
1155     {
1156         descBoxHeight = defaultDescBoxHeight;
1157     }
1158 
1159     wxPropertyGridManager* pg;
1160     pg = new wxPropertyGridManager( parent, id, wxDefaultPosition, wxDefaultSize, pgStyle );
1161     pg->SetDescBoxHeight( descBoxHeight );
1162 //  pg->SetExtraStyle( wxPG_EX_NATIVE_DOUBLE_BUFFERING ); Both seems to no more needed.
1163 //  pg->SetExtraStyle( wxPG_EX_PROCESS_EVENTS_IMMEDIATELY );
1164 
1165     return pg;
1166 }
1167 
OnPropertyGridDblClick(wxPropertyGridEvent & event)1168 void ObjectInspector::OnPropertyGridDblClick(wxPropertyGridEvent& event)
1169 {
1170     PObjectBase obj = AppData()->GetSelectedObject();
1171     if( obj )
1172     {
1173 #if wxVERSION_NUMBER < 2900
1174         wxString propName = event.GetPropertyPtr()->GetLabel();
1175 #else
1176         wxString propName = event.GetProperty()->GetLabel();
1177 #endif
1178         AutoGenerateId(obj, obj->GetProperty(propName), wxT("DblClk"));
1179         m_pg->Refresh();
1180     }
1181 }
1182 
OnEventGridDblClick(wxPropertyGridEvent & event)1183 void ObjectInspector::OnEventGridDblClick(wxPropertyGridEvent& event)
1184 {
1185     wxPGProperty *pgProp = m_pg->GetPropertyByLabel( wxT("name") );
1186     if ( !pgProp ) return;
1187 
1188 #if wxVERSION_NUMBER < 2900
1189     wxPGProperty *p = event.GetPropertyPtr();
1190     p->SetValueFromString( pgProp->GetDisplayedString() + event.GetPropertyLabel() );
1191 #else
1192     wxPGProperty *p = event.GetProperty();
1193     p->SetValueFromString( pgProp->GetDisplayedString() + event.GetProperty()->GetLabel() );
1194 #endif
1195     ObjInspectorEventMap::iterator it = m_eventMap.find( p );
1196     if ( it != m_eventMap.end() )
1197     {
1198         PEvent evt = it->second;
1199 #if wxVERSION_NUMBER < 2900
1200         wxString handler = event.GetPropertyValueAsString();
1201 #else
1202         wxString handler = p->GetValueAsString();
1203 #endif
1204         handler.Trim();
1205         handler.Trim( false );
1206         AppData()->ModifyEventHandler( evt, handler );
1207     };
1208 }
1209 
AutoGenerateId(PObjectBase objectChanged,PProperty propChanged,wxString reason)1210 void ObjectInspector::AutoGenerateId(PObjectBase objectChanged, PProperty propChanged, wxString reason)
1211 {
1212     if(objectChanged && propChanged)
1213     {
1214         PProperty prop;
1215         if((propChanged->GetName() == wxT("name") && reason == wxT("PropChange")) ||
1216             (propChanged->GetName() == wxT("id") && reason == wxT("DblClk")))
1217         {
1218             //wxPGId pgid = m_pg->GetPropertyByLabel(wxT(""));
1219             prop = AppData()->GetProjectData()->GetProperty( wxT("event_generation") );
1220             if ( prop )
1221             {
1222                 if(prop->GetValueAsString() == wxT("table"))
1223                 {
1224                     prop = objectChanged->GetProperty(wxT("id"));
1225                     if ( prop )
1226                     {
1227                         if(prop->GetValueAsString() == wxT("wxID_ANY") || reason == wxT("DblClk"))
1228                         {
1229                             PProperty name(objectChanged->GetProperty(wxT("name")));
1230                             wxString idString;
1231                             idString << wxT("ID_");
1232                             idString << name->GetValueAsString().Upper();
1233                             ModifyProperty( prop, idString);
1234 
1235                             wxPGProperty *pgid = m_pg->GetPropertyByLabel(wxT("id"));
1236                             if ( !pgid ) return;
1237                             m_pg->SetPropertyValue( pgid, idString );
1238                         }
1239                     }
1240                 }
1241                 else
1242                 {
1243                     prop = objectChanged->GetProperty(wxT("id"));
1244                     if ( prop )
1245                     {
1246                         ModifyProperty( prop, wxT("wxID_ANY"));
1247                         wxPGProperty *pgid = m_pg->GetPropertyByLabel(wxT("id"));
1248                         if ( !pgid ) return;
1249                         m_pg->SetPropertyValue( pgid, wxT("wxID_ANY") );
1250                     }
1251                 }
1252             }
1253         }
1254     }
1255     m_pg->Update();
1256 }
1257 
OnBitmapPropertyChanged(wxCommandEvent & event)1258 void ObjectInspector::OnBitmapPropertyChanged( wxCommandEvent& event )
1259 {
1260 	wxLogDebug( wxT("OI::BitmapPropertyChanged: %s"), event.GetString().c_str() );
1261 
1262 	wxString propName = event.GetString().BeforeFirst( ':' );
1263 	wxString propVal = event.GetString().AfterFirst( ':' );
1264 
1265 	if( !propVal.IsEmpty() )
1266 	{
1267 		wxFBBitmapProperty *bp = wxDynamicCast( m_pg->GetPropertyByLabel( propName ), wxFBBitmapProperty );
1268 		if( bp )
1269 		{
1270 			bp->UpdateChildValues( propVal );
1271 		}
1272 	}
1273 }
1274 
ModifyProperty(PProperty prop,const wxString & str)1275 void ObjectInspector::ModifyProperty( PProperty prop, const wxString& str )
1276 {
1277 	AppData()->RemoveHandler( this->GetEventHandler() );
1278 	AppData()->ModifyProperty( prop, str );
1279 	AppData()->AddHandler( this->GetEventHandler() );
1280 }
1281 
1282 #if wxVERSION_NUMBER >= 2900
OnChildFocus(wxChildFocusEvent & event)1283 void ObjectInspector::OnChildFocus( wxChildFocusEvent& event )
1284 {
1285 	// do nothing to avoid "scrollbar jump" if wx2.9 is used
1286 }
1287 #endif
1288 
OnPropertyGridItemSelected(wxPropertyGridEvent & event)1289 void ObjectInspector::OnPropertyGridItemSelected( wxPropertyGridEvent& event )
1290 {
1291 	wxPGProperty *p = event.GetProperty();
1292 	if( p )
1293 	{
1294 		if( m_nb->GetSelection() == 0 )
1295 		{
1296 			m_strSelPropItem = m_pg->GetPropertyLabel( p );
1297 			m_pageName = wxT("Properties");
1298 		}
1299 		else
1300 		{
1301 			m_strSelPropItem = m_eg->GetPropertyLabel( p );
1302 			m_pageName = wxT("Events");
1303 		}
1304 	}
1305 }
1306 
RestoreLastSelectedPropItem()1307 void ObjectInspector::RestoreLastSelectedPropItem()
1308 {
1309 	if( m_pageName == wxT("Properties") )
1310 	{
1311 		wxPGProperty* p = m_pg->GetPropertyByLabel( m_strSelPropItem );
1312 		if( p )
1313 		{
1314 			m_pg->SelectProperty(p, true);
1315 			m_pg->SetFocus();
1316 		}
1317 	}
1318 	else if( m_pageName == wxT("Events") )
1319 	{
1320 		wxPGProperty* p = m_eg->GetPropertyByLabel(m_strSelPropItem);
1321 		if( p )
1322 		{
1323 			m_eg->SelectProperty(p, true);
1324 			m_eg->SetFocus();
1325 		}
1326 	}
1327 }