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 ///////////////////////////////////////////////////////////////////////////////
25
26 #include "appdata.h"
27 #include "bitmaps.h"
28 #include "wxfbevent.h"
29 #include "wxfbmanager.h"
30
31 #include "model/objectbase.h"
32 #include "utils/typeconv.h"
33 #include "utils/debug.h"
34 #include "utils/stringutils.h"
35 #include "utils/wxfbipc.h"
36 #include "utils/wxfbexception.h"
37 #include "codegen/cppcg.h"
38 #include "codegen/pythoncg.h"
39 #include "codegen/phpcg.h"
40 #include "codegen/luacg.h"
41 #include "codegen/xrccg.h"
42 #include "codegen/codewriter.h"
43 #include "rad/xrcpreview/xrcpreview.h"
44 #include "rad/dataobject/dataobject.h"
45
46 #include <ticpp.h>
47 #include <set>
48 #include <iterator>
49 #include <sstream>
50 #include <algorithm>
51
52 #include <wx/tokenzr.h>
53 #include <wx/ffile.h>
54 #include <wx/filename.h>
55 #include <wx/clipbrd.h>
56 #include <wx/fs_mem.h>
57 #include <wx/fs_arc.h>
58 #include <wx/fs_filter.h>
59
60 using namespace TypeConv;
61
62
63 ///////////////////////////////////////////////////////////////////////////////
64 // Comandos
65 ///////////////////////////////////////////////////////////////////////////////
66
67 /** Command for expanding an object in the object tree */
68
69 class ExpandObjectCmd : public Command
70 {
71
72 private:
73 PObjectBase m_object;
74 bool m_expand;
75
76 protected:
77 void DoExecute();
78 void DoRestore();
79
80 public:
81 ExpandObjectCmd( PObjectBase object, bool expand );
82 };
83
84 /**
85 * Comando para insertar un objeto en el árbol.
86 */
87
88 class InsertObjectCmd : public Command
89 {
90
91 private:
92 ApplicationData *m_data;
93 PObjectBase m_parent;
94 PObjectBase m_object;
95 int m_pos;
96 PObjectBase m_oldSelected;
97
98
99 protected:
100 void DoExecute();
101 void DoRestore();
102
103 public:
104 InsertObjectCmd( ApplicationData *data, PObjectBase object, PObjectBase parent, int pos = -1 );
105 };
106
107 /**
108 * Comando para borrar un objeto.
109 */
110
111 class RemoveObjectCmd : public Command
112 {
113
114 private:
115 ApplicationData *m_data;
116 PObjectBase m_parent;
117 PObjectBase m_object;
118 int m_oldPos;
119 PObjectBase m_oldSelected;
120
121 protected:
122 void DoExecute();
123 void DoRestore();
124
125 public:
126 RemoveObjectCmd( ApplicationData *data, PObjectBase object );
127 };
128
129 /**
130 * Comando para modificar una propiedad.
131 */
132
133 class ModifyPropertyCmd : public Command
134 {
135
136 private:
137 PProperty m_property;
138 wxString m_oldValue, m_newValue;
139
140 protected:
141 void DoExecute();
142 void DoRestore();
143
144 public:
145 ModifyPropertyCmd( PProperty prop, wxString value );
146 };
147
148 /**
149 * Command for modifying an event
150 */
151
152 class ModifyEventHandlerCmd : public Command
153 {
154
155 private:
156 PEvent m_event;
157 wxString m_oldValue, m_newValue;
158
159 protected:
160 void DoExecute();
161 void DoRestore();
162
163 public:
164 ModifyEventHandlerCmd( PEvent event, wxString value );
165 };
166
167 /**
168 * Comando para mover de posición un objeto.
169 */
170
171 class ShiftChildCmd : public Command
172 {
173
174 private:
175 PObjectBase m_object;
176 int m_oldPos, m_newPos;
177
178 protected:
179 void DoExecute();
180 void DoRestore();
181
182 public:
183 ShiftChildCmd( PObjectBase object, int pos );
184
185 };
186
187 /**
188 * CutObjectCmd ademas de eliminar el objeto del árbol se asegura
189 * de eliminar la referencia "clipboard" deshacer el cambio.
190 */
191
192 class CutObjectCmd : public Command
193 {
194
195 private:
196 // necesario para consultar/modificar el objeto "clipboard"
197 ApplicationData *m_data;
198 //PObjectBase m_clipboard;
199 PObjectBase m_parent;
200 PObjectBase m_object;
201 int m_oldPos;
202 PObjectBase m_oldSelected;
203
204 protected:
205 void DoExecute();
206 void DoRestore();
207
208 public:
209 CutObjectCmd( ApplicationData *data, PObjectBase object );
210 };
211
212 /**
213 * Cambia el padre.
214 */
215
216 class ReparentObjectCmd : public Command
217 {
218
219 private:
220 PObjectBase m_sizeritem;
221 PObjectBase m_sizer;
222 PObjectBase m_oldSizer;
223 int m_oldPosition;
224
225 protected:
226 void DoExecute();
227 void DoRestore();
228
229 public:
230 ReparentObjectCmd ( PObjectBase sizeritem, PObjectBase sizer );
231 };
232
233 ///////////////////////////////////////////////////////////////////////////////
234 // Implementación de los Comandos
235 ///////////////////////////////////////////////////////////////////////////////
ExpandObjectCmd(PObjectBase object,bool expand)236 ExpandObjectCmd::ExpandObjectCmd( PObjectBase object, bool expand )
237 : m_object( object ), m_expand( expand )
238 {
239 }
240
DoExecute()241 void ExpandObjectCmd::DoExecute()
242 {
243 m_object->SetExpanded( m_expand );
244 }
245
DoRestore()246 void ExpandObjectCmd::DoRestore()
247 {
248 m_object->SetExpanded( !m_expand );
249 }
250
InsertObjectCmd(ApplicationData * data,PObjectBase object,PObjectBase parent,int pos)251 InsertObjectCmd::InsertObjectCmd( ApplicationData *data, PObjectBase object,
252 PObjectBase parent, int pos )
253 : m_data( data ), m_parent( parent ), m_object( object ), m_pos( pos )
254 {
255 m_oldSelected = data->GetSelectedObject();
256 }
257
DoExecute()258 void InsertObjectCmd::DoExecute()
259 {
260 m_parent->AddChild( m_object );
261 m_object->SetParent( m_parent );
262
263 if ( m_pos >= 0 )
264 m_parent->ChangeChildPosition( m_object, m_pos );
265
266 PObjectBase obj = m_object;
267 while ( obj && obj->GetObjectInfo()->GetObjectType()->IsItem() )
268 {
269 if ( obj->GetChildCount() > 0 )
270 obj = obj->GetChild( 0 );
271 else
272 return;
273 }
274 m_data->SelectObject( obj, false, false );
275 }
276
DoRestore()277 void InsertObjectCmd::DoRestore()
278 {
279 m_parent->RemoveChild( m_object );
280 m_object->SetParent( PObjectBase() );
281 m_data->SelectObject( m_oldSelected );
282 }
283
284 //-----------------------------------------------------------------------------
285
RemoveObjectCmd(ApplicationData * data,PObjectBase object)286 RemoveObjectCmd::RemoveObjectCmd( ApplicationData *data, PObjectBase object )
287 {
288 m_data = data;
289 m_object = object;
290 m_parent = object->GetParent();
291 m_oldPos = m_parent->GetChildPosition( object );
292 m_oldSelected = data->GetSelectedObject();
293 }
294
DoExecute()295 void RemoveObjectCmd::DoExecute()
296 {
297 m_parent->RemoveChild( m_object );
298 m_object->SetParent( PObjectBase() );
299 m_data->DetermineObjectToSelect( m_parent, m_oldPos );
300 }
301
DoRestore()302 void RemoveObjectCmd::DoRestore()
303 {
304 m_parent->AddChild( m_object );
305 m_object->SetParent( m_parent );
306
307 // restauramos la posición
308 m_parent->ChangeChildPosition( m_object, m_oldPos );
309 m_data->SelectObject( m_oldSelected, true, false );
310 }
311
312 //-----------------------------------------------------------------------------
313
ModifyPropertyCmd(PProperty prop,wxString value)314 ModifyPropertyCmd::ModifyPropertyCmd( PProperty prop, wxString value )
315 : m_property( prop ), m_newValue( value )
316 {
317 m_oldValue = prop->GetValue();
318 }
319
DoExecute()320 void ModifyPropertyCmd::DoExecute()
321 {
322 m_property->SetValue( m_newValue );
323 }
324
DoRestore()325 void ModifyPropertyCmd::DoRestore()
326 {
327 m_property->SetValue( m_oldValue );
328 }
329
330 //-----------------------------------------------------------------------------
331
ModifyEventHandlerCmd(PEvent event,wxString value)332 ModifyEventHandlerCmd::ModifyEventHandlerCmd( PEvent event, wxString value )
333 : m_event( event ), m_newValue( value )
334 {
335 m_oldValue = event->GetValue();
336 }
337
DoExecute()338 void ModifyEventHandlerCmd::DoExecute()
339 {
340 m_event->SetValue( m_newValue );
341 }
342
DoRestore()343 void ModifyEventHandlerCmd::DoRestore()
344 {
345 m_event->SetValue( m_oldValue );
346 }
347
348 //-----------------------------------------------------------------------------
349
ShiftChildCmd(PObjectBase object,int pos)350 ShiftChildCmd::ShiftChildCmd( PObjectBase object, int pos )
351 {
352 m_object = object;
353 PObjectBase parent = object->GetParent();
354
355 assert( parent );
356
357 m_oldPos = parent->GetChildPosition( object );
358 m_newPos = pos;
359 }
360
DoExecute()361 void ShiftChildCmd::DoExecute()
362 {
363 if ( m_oldPos != m_newPos )
364 {
365 PObjectBase parent ( m_object->GetParent() );
366 parent->ChangeChildPosition( m_object, m_newPos );
367 }
368 }
369
DoRestore()370 void ShiftChildCmd::DoRestore()
371 {
372 if ( m_oldPos != m_newPos )
373 {
374 PObjectBase parent ( m_object->GetParent() );
375 parent->ChangeChildPosition( m_object, m_oldPos );
376 }
377 }
378
379 //-----------------------------------------------------------------------------
380
CutObjectCmd(ApplicationData * data,PObjectBase object)381 CutObjectCmd::CutObjectCmd( ApplicationData *data, PObjectBase object )
382 {
383 m_data = data;
384 m_object = object;
385 m_parent = object->GetParent();
386 m_oldPos = m_parent->GetChildPosition( object );
387 m_oldSelected = data->GetSelectedObject();
388 }
389
DoExecute()390 void CutObjectCmd::DoExecute()
391 {
392 // guardamos el clipboard ???
393 //m_clipboard = m_data->GetClipboardObject();
394
395 m_data->SetClipboardObject( m_object );
396 m_parent->RemoveChild( m_object );
397 m_object->SetParent( PObjectBase() );
398 m_data->DetermineObjectToSelect( m_parent, m_oldPos );
399 }
400
DoRestore()401 void CutObjectCmd::DoRestore()
402 {
403 // reubicamos el objeto donde estaba
404 m_parent->AddChild( m_object );
405 m_object->SetParent( m_parent );
406 m_parent->ChangeChildPosition( m_object, m_oldPos );
407
408
409
410 // restauramos el clipboard
411 //m_data->SetClipboardObject(m_clipboard);
412 m_data->SetClipboardObject( PObjectBase() );
413 m_data->SelectObject( m_oldSelected, true, false );
414 }
415
416 //-----------------------------------------------------------------------------
417
ReparentObjectCmd(PObjectBase sizeritem,PObjectBase sizer)418 ReparentObjectCmd ::ReparentObjectCmd ( PObjectBase sizeritem, PObjectBase sizer )
419 {
420 m_sizeritem = sizeritem;
421 m_sizer = sizer;
422 m_oldSizer = m_sizeritem->GetParent();
423 m_oldPosition = m_oldSizer->GetChildPosition(sizeritem);
424 }
425
DoExecute()426 void ReparentObjectCmd::DoExecute()
427 {
428 m_oldSizer->RemoveChild( m_sizeritem );
429 m_sizeritem->SetParent( m_sizer );
430 m_sizer->AddChild( m_sizeritem );
431 }
432
DoRestore()433 void ReparentObjectCmd::DoRestore()
434 {
435 m_sizer->RemoveChild( m_sizeritem );
436 m_sizeritem->SetParent( m_oldSizer );
437 m_oldSizer->AddChild( m_sizeritem );
438 m_oldSizer->ChangeChildPosition( m_sizeritem, m_oldPosition);
439 }
440
441 ///////////////////////////////////////////////////////////////////////////////
442 // ApplicationData
443 ///////////////////////////////////////////////////////////////////////////////
444
445 ApplicationData* ApplicationData::s_instance = NULL;
446
Get(const wxString & rootdir)447 ApplicationData* ApplicationData::Get( const wxString &rootdir )
448 {
449 if ( !s_instance )
450 s_instance = new ApplicationData( rootdir );
451
452 return s_instance;
453 }
454
Destroy()455 void ApplicationData::Destroy()
456
457 {
458 if ( s_instance )
459 delete s_instance;
460
461 s_instance = NULL;
462 }
463
Initialize()464 void ApplicationData::Initialize()
465 {
466 ApplicationData* appData = ApplicationData::Get();
467 appData->LoadApp();
468 }
469
ApplicationData(const wxString & rootdir)470 ApplicationData::ApplicationData( const wxString &rootdir )
471 :
472 m_rootDir( rootdir ),
473 m_modFlag( false ),
474 m_warnOnAdditionsUpdate( true ),
475 m_objDb( new ObjectDatabase() ),
476 m_manager( new wxFBManager ),
477 m_ipc( new wxFBIPC ),
478 m_fbpVerMajor( 1 ),
479 m_fbpVerMinor( 13 )
480 {
481 #ifdef __WXFB_DEBUG__
482 //wxLog* log = wxLog::SetActiveTarget( NULL );
483 m_debugLogTarget = new wxLogWindow( NULL, wxT( "Logging" ) );
484 //wxLog::SetActiveTarget( log );
485 #endif
486 m_objDb->SetXmlPath( m_rootDir + wxFILE_SEP_PATH + wxT( "xml" ) + wxFILE_SEP_PATH ) ;
487 m_objDb->SetIconPath( m_rootDir + wxFILE_SEP_PATH + wxT( "resources" ) + wxFILE_SEP_PATH + wxT( "icons" ) + wxFILE_SEP_PATH );
488 m_objDb->SetPluginPath( m_rootDir + wxFILE_SEP_PATH + wxT( "plugins" ) + wxFILE_SEP_PATH ) ;
489
490 // Support loading files from memory
491 // Used to load the XRC preview, but could be useful elsewhere
492 wxFileSystem::AddHandler( new wxMemoryFSHandler );
493
494 // Support for loading files from archives
495 wxFileSystem::AddHandler( new wxArchiveFSHandler );
496 wxFileSystem::AddHandler( new wxFilterFSHandler );
497 }
498
~ApplicationData()499 ApplicationData::~ApplicationData()
500 {
501 #ifdef __WXFB_DEBUG__
502 delete m_debugLogTarget;
503 m_debugLogTarget = 0;
504 #endif
505 }
506
LoadApp()507 void ApplicationData::LoadApp()
508
509 {
510 wxString bitmapPath = m_objDb->GetXmlPath() + wxT( "icons.xml" );
511 AppBitmaps::LoadBitmaps( bitmapPath, m_objDb->GetIconPath() );
512 m_objDb->LoadObjectTypes();
513 m_objDb->LoadPlugins( m_manager );
514 }
515
GetManager()516 PwxFBManager ApplicationData::GetManager()
517 {
518 return m_manager;
519 }
520
GetSelectedObject()521 PObjectBase ApplicationData::GetSelectedObject()
522 {
523 return m_selObj;
524 }
525
GetSelectedForm()526 PObjectBase ApplicationData::GetSelectedForm()
527 {
528 if( ( m_selObj->GetObjectTypeName() == wxT( "form" ) ) ||
529 ( m_selObj->GetObjectTypeName() == wxT("wizard") ) ||
530 ( m_selObj->GetObjectTypeName() == wxT( "menubar_form" ) ) ||
531 ( m_selObj->GetObjectTypeName() == wxT( "toolbar_form" ) ) )
532 return m_selObj;
533 else
534 return m_selObj->FindParentForm();
535 }
536
537
GetProjectData()538 PObjectBase ApplicationData::GetProjectData()
539 {
540 return m_project;
541 }
542
BuildNameSet(PObjectBase obj,PObjectBase top,std::set<wxString> & name_set)543 void ApplicationData::BuildNameSet( PObjectBase obj, PObjectBase top, std::set< wxString >& name_set )
544 {
545 if ( obj != top )
546 {
547 PProperty nameProp = top->GetProperty( wxT( "name" ) );
548
549 if ( nameProp )
550 name_set.insert( nameProp->GetValue() );
551 }
552
553 for ( unsigned int i = 0; i < top->GetChildCount(); i++ )
554 BuildNameSet( obj, top->GetChild( i ), name_set );
555 }
556
ResolveNameConflict(PObjectBase obj)557 void ApplicationData::ResolveNameConflict( PObjectBase obj )
558 {
559 while ( obj && obj->GetObjectInfo()->GetObjectType()->IsItem() )
560 {
561 if ( obj->GetChildCount() > 0 )
562 obj = obj->GetChild( 0 );
563 else
564 return;
565 }
566
567 PProperty nameProp = obj->GetProperty( wxT( "name" ) );
568
569 if ( !nameProp )
570 return;
571
572 // Save the original name for use later.
573 wxString originalName = nameProp->GetValue();
574
575 // el nombre no puede estar repetido dentro del mismo form
576 /*PObjectBase top = obj->FindNearAncestor( wxT( "form" ) );*/
577 PObjectBase top = obj->FindParentForm();
578
579 if ( !top )
580 top = m_project; // el objeto es un form.
581
582 // construimos el conjunto de nombres
583 std::set<wxString> name_set;
584
585 BuildNameSet( obj, top, name_set );
586
587 // comprobamos si hay conflicto
588 std::set<wxString>::iterator it = name_set.find( originalName );
589
590 int i = 0;
591
592 wxString name = originalName; // The name that gets incremented.
593
594 while ( it != name_set.end() )
595 {
596 i++;
597 name = wxString::Format( wxT( "%s%i" ), originalName.c_str(), i );
598 it = name_set.find( name );
599 }
600
601 nameProp->SetValue( name );
602 }
603
ResolveSubtreeNameConflicts(PObjectBase obj,PObjectBase topObj)604 void ApplicationData::ResolveSubtreeNameConflicts( PObjectBase obj, PObjectBase topObj )
605 {
606 if ( !topObj )
607 {
608 /*topObj = obj->FindNearAncestor( wxT( "form" ) );*/
609 topObj = obj->FindParentForm();
610
611 if ( !topObj )
612 topObj = m_project; // object is the project
613 }
614
615 // Ignore item objects
616 while ( obj && obj->GetObjectInfo()->GetObjectType()->IsItem() )
617 {
618 if ( obj->GetChildCount() > 0 )
619 obj = obj->GetChild( 0 );
620 else
621 return; // error
622 }
623
624 // Resolve a possible name conflict
625 ResolveNameConflict( obj );
626
627 // Recurse through all children
628 for ( unsigned int i = 0 ; i < obj->GetChildCount() ; i++ )
629 ResolveSubtreeNameConflicts( obj->GetChild( i ), topObj );
630 }
631
CalcPositionOfInsertion(PObjectBase selected,PObjectBase parent)632 int ApplicationData::CalcPositionOfInsertion( PObjectBase selected, PObjectBase parent )
633 {
634 int pos = -1;
635
636 if ( parent && selected )
637 {
638 PObjectBase parentSelected = selected->GetParent();
639
640 while ( parentSelected && parentSelected != parent )
641 {
642 selected = parentSelected;
643 parentSelected = selected->GetParent();
644 }
645
646 if ( parentSelected && parentSelected == parent )
647 pos = parent->GetChildPosition( selected ) + 1;
648 }
649
650 return pos;
651 }
652
RemoveEmptyItems(PObjectBase obj)653 void ApplicationData::RemoveEmptyItems( PObjectBase obj )
654 {
655 if ( !obj->GetObjectInfo()->GetObjectType()->IsItem() )
656 {
657 bool emptyItem = true;
658
659 // esto es un algoritmo ineficiente pero "seguro" con los índices
660
661 while ( emptyItem )
662 {
663 emptyItem = false;
664
665 for ( unsigned int i = 0; !emptyItem && i < obj->GetChildCount(); i++ )
666 {
667 PObjectBase child = obj->GetChild( i );
668
669 if ( child->GetObjectInfo()->GetObjectType()->IsItem() &&
670 child->GetChildCount() == 0 )
671 {
672 obj->RemoveChild( child ); // borramos el item
673 child->SetParent( PObjectBase() );
674
675 emptyItem = true; // volvemos a recorrer
676 wxString msg;
677 msg.Printf( wxT( "Empty item removed under %s" ), obj->GetPropertyAsString( wxT( "name" ) ).c_str() );
678 wxLogWarning( msg );
679 }
680 }
681 }
682 }
683
684 for ( unsigned int i = 0; i < obj->GetChildCount() ; i++ )
685 RemoveEmptyItems( obj->GetChild( i ) );
686 }
687
SearchSizerInto(PObjectBase obj)688 PObjectBase ApplicationData::SearchSizerInto( PObjectBase obj )
689 {
690 PObjectBase theSizer;
691
692 if ( obj->GetObjectInfo()->IsSubclassOf( wxT("sizer") ) || obj->GetObjectInfo()->IsSubclassOf( wxT("gbsizer") ) )
693 theSizer = obj;
694 else
695 {
696 for ( unsigned int i = 0; !theSizer && i < obj->GetChildCount(); i++ )
697 theSizer = SearchSizerInto( obj->GetChild( i ) );
698 }
699
700 return theSizer;
701 }
702
703 ///////////////////////////////////////////////////////////////////////////////
704
ExpandObject(PObjectBase obj,bool expand)705 void ApplicationData::ExpandObject( PObjectBase obj, bool expand )
706 {
707 PCommand command( new ExpandObjectCmd( obj, expand ) );
708 Execute( command );
709
710 // collapse also all children ...
711 PropagateExpansion( obj, expand, !expand );
712
713 NotifyObjectExpanded( obj );
714 }
715
PropagateExpansion(PObjectBase obj,bool expand,bool up)716 void ApplicationData::PropagateExpansion( PObjectBase obj, bool expand, bool up )
717 {
718 if( obj )
719 {
720 if( up )
721 {
722 PObjectBase child;
723
724 for( size_t i = 0; i < obj->GetChildCount(); i++ )
725 {
726 child = obj->GetChild(i);
727
728 PCommand command( new ExpandObjectCmd( child, expand ) );
729 Execute( command );
730
731 PropagateExpansion( child, expand, up );
732 }
733 }
734 else
735 {
736 PropagateExpansion( obj->GetParent(), expand, up );
737
738 PCommand command( new ExpandObjectCmd( obj, expand ) );
739 Execute( command );
740 }
741 }
742 }
743
SelectObject(PObjectBase obj,bool force,bool notify)744 bool ApplicationData::SelectObject( PObjectBase obj, bool force /*= false*/, bool notify /*= true */ )
745 {
746 if ( ( obj == m_selObj ) && !force )
747 {
748 return false;
749 }
750
751 m_selObj = obj;
752
753 if ( notify )
754 {
755 NotifyObjectSelected( obj, force );
756 }
757 return true;
758 }
759
CreateObject(wxString name)760 void ApplicationData::CreateObject( wxString name )
761 {
762 try
763 {
764 #if wxVERSION_NUMBER < 2900
765 LogDebug( wxT( "[ApplicationData::CreateObject] New %s" ), name.c_str() );
766 #else
767 LogDebug("[ApplicationData::CreateObject] New " + name );
768 #endif
769 PObjectBase old_selected = GetSelectedObject();
770 PObjectBase parent = old_selected;
771 PObjectBase obj;
772
773 if ( parent )
774 {
775 bool created = false;
776
777 // Para que sea más práctico, si el objeto no se puede crear debajo
778 // del objeto seleccionado vamos a intentarlo en el padre del seleccionado
779 // y seguiremos subiendo hasta que ya no podamos crear el objeto.
780
781 while ( parent && !created )
782 {
783 // además, el objeto se insertará a continuación del objeto seleccionado
784 obj = m_objDb->CreateObject( _STDSTR( name ), parent );
785
786 if ( obj )
787 {
788 int pos = CalcPositionOfInsertion( GetSelectedObject(), parent );
789
790 PCommand command( new InsertObjectCmd( this, obj, parent, pos ) );
791 Execute( command ); //m_cmdProc.Execute(command);
792 created = true;
793 ResolveNameConflict( obj );
794 }
795 else
796 {
797 // lo vamos a seguir intentando con el padre, pero cuidado, el padre
798 // no puede ser un item!
799 parent = parent->GetParent();
800
801 while ( parent && parent->GetObjectInfo()->GetObjectType()->IsItem() )
802 parent = parent->GetParent();
803 }
804 }
805 }
806
807 // Seleccionamos el objeto, si este es un item entonces se selecciona
808 // el objeto contenido. ¿Tiene sentido tener un item debajo de un item?
809
810 while ( obj && obj->GetObjectInfo()->GetObjectType()->IsItem() )
811 obj = ( obj->GetChildCount() > 0 ? obj->GetChild( 0 ) : PObjectBase() );
812
813 NotifyObjectCreated( obj );
814
815 if ( obj )
816 {
817 SelectObject( obj, true, true );
818 }
819 else
820 {
821 SelectObject( old_selected, true, true );
822 }
823 }
824 catch ( wxFBException& ex )
825 {
826 wxLogError( ex.what() );
827 }
828 }
829
RemoveObject(PObjectBase obj)830 void ApplicationData::RemoveObject( PObjectBase obj )
831 {
832 DoRemoveObject( obj, false );
833 }
834
CutObject(PObjectBase obj)835 void ApplicationData::CutObject( PObjectBase obj )
836 {
837 DoRemoveObject( obj, true );
838 }
839
DoRemoveObject(PObjectBase obj,bool cutObject)840 void ApplicationData::DoRemoveObject( PObjectBase obj, bool cutObject )
841 {
842 // Note:
843 // When removing an object it is important that the "item" objects
844 // are not left behind
845 PObjectBase parent = obj->GetParent();
846 PObjectBase deleted_obj = obj;
847
848 if ( parent )
849 {
850 // Get the top item
851 while ( parent && parent->GetObjectInfo()->GetObjectType()->IsItem() )
852 {
853 obj = parent;
854 parent = obj->GetParent();
855 }
856
857 if ( cutObject )
858 {
859 m_copyOnPaste = false;
860 PCommand command( new CutObjectCmd( this, obj ) );
861 Execute( command );
862 }
863 else
864 {
865 PCommand command( new RemoveObjectCmd( this, obj ) );
866 Execute( command );
867 }
868
869 NotifyObjectRemoved( deleted_obj );
870 SelectObject( GetSelectedObject(), true, true );
871 }
872 else
873 {
874 if ( obj->GetObjectTypeName() != wxT( "project" ) )
875 assert( false );
876 }
877
878 CheckProjectTree( m_project );
879 }
880
DetermineObjectToSelect(PObjectBase parent,unsigned int pos)881 void ApplicationData::DetermineObjectToSelect( PObjectBase parent, unsigned int pos )
882 {
883 // get position of next control or last control
884 PObjectBase objToSelect;
885 unsigned int count = parent->GetChildCount();
886 if ( 0 == count )
887 {
888 objToSelect = parent;
889 }
890 else
891 {
892 pos = ( pos < count ? pos : count - 1 );
893 objToSelect = parent->GetChild( pos );
894 }
895
896 while ( objToSelect && objToSelect->GetObjectInfo()->GetObjectType()->IsItem() )
897 {
898 objToSelect = objToSelect->GetChild( 0 );
899 }
900
901 SelectObject( objToSelect );
902 }
903
CopyObjectToClipboard(PObjectBase obj)904 void ApplicationData::CopyObjectToClipboard( PObjectBase obj )
905 {
906 // Write some text to the clipboard
907
908 // Do not call Open() when the clipboard is opened
909 if( !wxTheClipboard->IsOpened() )
910 {
911 if ( !wxTheClipboard->Open() )
912 {
913 return;
914 }
915 }
916
917 // This data objects are held by the clipboard,
918 // so do not delete them in the app.
919 wxTheClipboard->SetData( new wxFBDataObject( obj ) );
920 wxTheClipboard->Close();
921 }
922
PasteObjectFromClipboard(PObjectBase parent)923 bool ApplicationData::PasteObjectFromClipboard( PObjectBase parent )
924 {
925 // Do not call Open() when the clipboard is opened
926 if( !wxTheClipboard->IsOpened() )
927 {
928 if ( !wxTheClipboard->Open() )
929 {
930 return false;
931 }
932 }
933
934 if ( wxTheClipboard->IsSupported( wxFBDataObjectFormat ) )
935 {
936 wxFBDataObject data;
937 if ( wxTheClipboard->GetData( data ) )
938 {
939 PObjectBase obj = data.GetObj();
940 if ( obj )
941 {
942 wxTheClipboard->Close();
943 return PasteObject( parent, obj );
944 }
945 }
946 }
947
948 wxTheClipboard->Close();
949
950 return false;
951 }
952
CanPasteObjectFromClipboard()953 bool ApplicationData::CanPasteObjectFromClipboard()
954 {
955 // Do not call Open() when the clipboard is opened
956 if( !wxTheClipboard->IsOpened() )
957 {
958 if ( !wxTheClipboard->Open() )
959 {
960 return false;
961 }
962 }
963
964 bool canPaste = wxTheClipboard->IsSupported( wxFBDataObjectFormat );
965
966 if( wxTheClipboard->IsOpened() )
967 wxTheClipboard->Close();
968
969 return canPaste;
970 }
971
CopyObject(PObjectBase obj)972 void ApplicationData::CopyObject( PObjectBase obj )
973 {
974 m_copyOnPaste = true;
975
976 // Make a copy of the object on the clipboard, otherwise
977 // modifications to the object after the copy will also
978 // be made on the clipboard.
979 m_clipboard = m_objDb->CopyObject( obj );
980
981 CheckProjectTree( m_project );
982 }
983
PasteObject(PObjectBase parent,PObjectBase objToPaste)984 bool ApplicationData::PasteObject( PObjectBase parent, PObjectBase objToPaste )
985 {
986 try
987 {
988 PObjectBase clipboard;
989 if ( objToPaste )
990 {
991 clipboard = objToPaste;
992 }
993 else if ( m_clipboard )
994 {
995 if ( m_copyOnPaste )
996 {
997 clipboard = m_objDb->CopyObject( m_clipboard );
998 }
999 else
1000 {
1001 clipboard = m_clipboard;
1002 }
1003 }
1004
1005 if ( !clipboard )
1006 {
1007 return false;
1008 }
1009
1010 // Remove parent/child relationship from clipboard object
1011 PObjectBase clipParent = clipboard->GetParent();
1012 if ( clipParent )
1013 {
1014 clipParent->RemoveChild( clipboard );
1015 clipboard->SetParent( PObjectBase() );
1016 }
1017
1018 // Vamos a hacer un pequeño truco, intentaremos crear un objeto nuevo
1019 // del mismo tipo que el guardado en m_clipboard debajo de parent.
1020 // El objeto devuelto quizá no sea de la misma clase que m_clipboard debido
1021 // a que esté incluido dentro de un "item".
1022 // Por tanto, si el objeto devuelto es no-nulo, entonces vamos a descender
1023 // en el arbol hasta que el objeto sea de la misma clase que m_clipboard,
1024 // momento en que cambiaremos dicho objeto por m_clipboard.
1025 //
1026 // Ejemplo:
1027 //
1028 // m_clipboard :: wxButton
1029 // parent :: wxBoxSizer
1030 //
1031 // obj = CreateObject(m_clipboard->GetObjectInfo()->GetClassName(), parent)
1032 //
1033 // obj :: sizeritem
1034 // /
1035 // wxButton <- Cambiamos este por m_clipboard
1036 PObjectBase old_parent = parent;
1037
1038 PObjectBase obj = m_objDb->CreateObject( _STDSTR( clipboard->GetObjectInfo()->GetClassName() ), parent );
1039
1040 // If the object is already contained in an item, we may need to get the object out of the first
1041 // item before pasting
1042 if ( !obj )
1043 {
1044
1045 PObjectBase tempItem = clipboard;
1046 while ( tempItem->GetObjectInfo()->GetObjectType()->IsItem() )
1047 {
1048 tempItem = tempItem->GetChild( 0 );
1049 if ( !tempItem )
1050 {
1051 break;
1052 }
1053
1054 obj = m_objDb->CreateObject( _STDSTR( tempItem->GetObjectInfo()->GetClassName() ), parent );
1055 if ( obj )
1056 {
1057 clipboard = tempItem;
1058 break;
1059 }
1060 }
1061 }
1062
1063 int pos = -1;
1064
1065 if ( !obj )
1066 {
1067 // si no se ha podido crear el objeto vamos a intentar crearlo colgado
1068 // del padre de "parent" y además vamos a insertarlo en la posición
1069 // siguiente a "parent"
1070 PObjectBase selected = parent;
1071 parent = selected->GetParent();
1072
1073 while ( parent && parent->GetObjectInfo()->GetObjectType()->IsItem() )
1074 {
1075 selected = parent;
1076 parent = selected->GetParent();
1077 }
1078
1079 if ( parent )
1080 {
1081 obj = m_objDb->CreateObject( _STDSTR( clipboard->GetObjectInfo()->GetClassName() ), parent );
1082 if ( obj )
1083 {
1084 pos = CalcPositionOfInsertion( selected, parent );
1085 }
1086 }
1087 }
1088
1089 if ( !obj )
1090 {
1091 return false;
1092 }
1093
1094 PObjectBase aux = obj;
1095
1096 while ( aux && aux->GetObjectInfo() != clipboard->GetObjectInfo() )
1097 aux = ( aux->GetChildCount() > 0 ? aux->GetChild( 0 ) : PObjectBase() );
1098
1099 if ( aux && aux != obj )
1100 {
1101 // sustituimos aux por clipboard
1102 PObjectBase auxParent = aux->GetParent();
1103 auxParent->RemoveChild( aux );
1104 aux->SetParent( PObjectBase() );
1105
1106 auxParent->AddChild( clipboard );
1107 clipboard->SetParent( auxParent );
1108 }
1109 else
1110 obj = clipboard;
1111
1112 // y finalmente insertamos en el arbol
1113 PCommand command( new InsertObjectCmd( this, obj, parent, pos ) );
1114
1115 Execute( command );
1116
1117 if ( !m_copyOnPaste )
1118 m_clipboard.reset();
1119
1120 ResolveSubtreeNameConflicts( obj );
1121
1122 NotifyProjectRefresh();
1123
1124 // vamos a mantener seleccionado el nuevo objeto creado
1125 // pero hay que tener en cuenta que es muy probable que el objeto creado
1126 // sea un "item"
1127 while ( obj && obj->GetObjectInfo()->GetObjectType()->IsItem() )
1128 {
1129 assert( obj->GetChildCount() > 0 );
1130 obj = obj->GetChild( 0 );
1131 }
1132
1133 SelectObject( obj, true, true );
1134
1135 CheckProjectTree( m_project );
1136 }
1137 catch ( wxFBException& ex )
1138 {
1139 wxLogError( ex.what() );
1140 return false;
1141 }
1142
1143 return true;
1144 }
1145
InsertObject(PObjectBase obj,PObjectBase parent)1146 void ApplicationData::InsertObject( PObjectBase obj, PObjectBase parent )
1147 {
1148 // FIXME! comprobar obj se puede colgar de parent
1149 // if (parent->GetObjectInfo()->GetObjectType()->FindChildType(
1150 // obj->GetObjectInfo()->GetObjectType()))
1151 // {
1152 PCommand command( new InsertObjectCmd( this, obj, parent ) );
1153 Execute( command ); //m_cmdProc.Execute(command);
1154 NotifyProjectRefresh();
1155 // }
1156 }
1157
MergeProject(PObjectBase project)1158 void ApplicationData::MergeProject( PObjectBase project )
1159 {
1160 // FIXME! comprobar obj se puede colgar de parent
1161
1162 for ( unsigned int i = 0; i < project->GetChildCount(); i++ )
1163 {
1164 //m_project->AddChild(project->GetChild(i));
1165 //project->GetChild(i)->SetParent(m_project);
1166
1167 PObjectBase child = project->GetChild( i );
1168 RemoveEmptyItems( child );
1169
1170 InsertObject( child, m_project );
1171 }
1172
1173 // Merge bitmaps and icons properties
1174 PObjectBase thisProject = GetProjectData();
1175 PProperty prop = thisProject->GetProperty( _("bitmaps") );
1176 if ( prop )
1177 {
1178 wxString value = prop->GetValue();
1179 value.Trim();
1180 value << wxT(" ") << project->GetPropertyAsString( _("bitmaps") );
1181 prop->SetValue( value );
1182 }
1183 prop = thisProject->GetProperty( _("icons") );
1184 if ( prop )
1185 {
1186 wxString value = prop->GetValue();
1187 value.Trim();
1188 value << wxT(" ") << project->GetPropertyAsString( _("icons") );
1189 prop->SetValue( value );
1190 }
1191
1192 NotifyProjectRefresh();
1193 }
1194
ModifyProperty(PProperty prop,wxString str)1195 void ApplicationData::ModifyProperty( PProperty prop, wxString str )
1196 {
1197 PObjectBase object = prop->GetObject();
1198
1199 if ( str != prop->GetValue() )
1200 {
1201 PCommand command( new ModifyPropertyCmd( prop, str ) );
1202 Execute( command ); //m_cmdProc.Execute(command);
1203
1204 NotifyPropertyModified( prop );
1205 }
1206 }
1207
ModifyEventHandler(PEvent evt,wxString value)1208 void ApplicationData::ModifyEventHandler( PEvent evt, wxString value )
1209 {
1210 PObjectBase object = evt->GetObject();
1211
1212 if ( value != evt->GetValue() )
1213 {
1214 PCommand command( new ModifyEventHandlerCmd( evt, value ) );
1215 Execute( command ); //m_cmdProc.Execute(command);
1216
1217 NotifyEventHandlerModified( evt );
1218 }
1219 }
1220
SaveProject(const wxString & filename)1221 void ApplicationData::SaveProject( const wxString& filename )
1222 {
1223 // Make sure this file is not already open
1224
1225 if ( !m_ipc->VerifySingleInstance( filename, false ) )
1226 {
1227 if ( wxYES == wxMessageBox( wxT( "You cannot save over a file that is currently open in another instance.\nWould you like to switch to that instance?" ),
1228 wxT( "Open in Another Instance" ), wxICON_QUESTION | wxYES_NO, wxTheApp->GetTopWindow() ) )
1229 {
1230 m_ipc->VerifySingleInstance( filename, true );
1231 }
1232
1233 return;
1234 }
1235
1236 try
1237 {
1238 ticpp::Document doc;
1239 m_project->Serialize( &doc );
1240 doc.SaveFile( std::string( filename.mb_str( wxConvFile ) ) );
1241
1242 m_projectFile = filename;
1243 SetProjectPath( ::wxPathOnly( filename ) );
1244 m_modFlag = false;
1245 m_cmdProc.SetSavePoint();
1246 NotifyProjectSaved();
1247 }
1248 catch ( ticpp::Exception& ex )
1249 {
1250 wxString message = _WXSTR( ex.m_details );
1251
1252 if ( message.empty() )
1253 {
1254 message = wxString( ex.m_details.c_str(), wxConvFile );
1255 }
1256
1257 THROW_WXFBEX( message )
1258 }
1259 }
1260
LoadProject(const wxString & file,bool checkSingleInstance)1261 bool ApplicationData::LoadProject( const wxString &file, bool checkSingleInstance )
1262
1263 {
1264 LogDebug( wxT( "LOADING" ) );
1265
1266 if ( !wxFileName::FileExists( file ) )
1267 {
1268 wxLogError( wxT( "This file does not exist: %s" ), file.c_str() );
1269 return false;
1270 }
1271
1272 if ( checkSingleInstance )
1273 {
1274 if ( !m_ipc->VerifySingleInstance( file ) )
1275 {
1276 return false;
1277 }
1278 }
1279
1280 try
1281 {
1282 ticpp::Document doc;
1283 XMLUtils::LoadXMLFile( doc, false, file );
1284
1285 ticpp::Element* root = doc.FirstChildElement();
1286
1287 m_objDb->ResetObjectCounters();
1288
1289 int fbpVerMajor = 0;
1290 int fbpVerMinor = 0;
1291
1292 if ( root->Value() != std::string( "object" ) )
1293 {
1294 try
1295 {
1296 ticpp::Element* fileVersion = root->FirstChildElement( "FileVersion" );
1297 fileVersion->GetAttributeOrDefault( "major", &fbpVerMajor, 0 );
1298 fileVersion->GetAttributeOrDefault( "minor", &fbpVerMinor, 0 );
1299 }
1300 catch( ticpp::Exception& )
1301 {
1302 }
1303 }
1304
1305 bool older = false;
1306 bool newer = false;
1307
1308 if ( m_fbpVerMajor == fbpVerMajor )
1309 {
1310 older = ( fbpVerMinor < m_fbpVerMinor );
1311 newer = ( fbpVerMinor > m_fbpVerMinor );
1312 }
1313 else
1314 {
1315 older = ( fbpVerMajor < m_fbpVerMajor );
1316 newer = ( fbpVerMajor > m_fbpVerMajor );
1317 }
1318
1319 if ( newer )
1320 {
1321 wxMessageBox( wxT( "This project file is newer than this version of wxFormBuilder.\n" )
1322 wxT( "It cannot be opened.\n\n" )
1323 wxT( "Please download an updated version from http://www.wxFormBuilder.org" ), _( "New Version" ), wxICON_ERROR );
1324 return false;
1325 }
1326
1327 if ( older )
1328 {
1329 if ( wxYES == wxMessageBox( wxT( "This project file is not of the current version.\n" )
1330 wxT( "Would you to attempt automatic conversion?\n\n" )
1331 wxT( "NOTE: This will modify your project file on disk!" ), _( "Old Version" ), wxYES_NO ) )
1332 {
1333 // we make a backup of the project
1334 ::wxCopyFile( file, file + wxT( ".bak" ) );
1335
1336 if ( !ConvertProject( file, fbpVerMajor, fbpVerMinor ) )
1337 {
1338 wxLogError( wxT( "Unable to convert project" ) );
1339 return false;
1340 }
1341
1342 XMLUtils::LoadXMLFile( doc, false, file );
1343 root = doc.FirstChildElement();
1344 }
1345 else
1346 {
1347 return false;
1348 }
1349 }
1350
1351 ticpp::Element* object = root->FirstChildElement( "object" );
1352 PObjectBase proj;
1353
1354 try
1355 {
1356 proj = m_objDb->CreateObject( object );
1357 }
1358 catch ( wxFBException& ex )
1359 {
1360 wxLogError( ex.what() );
1361 return false;
1362 }
1363
1364 if ( proj && proj->GetObjectTypeName() == wxT( "project" ) )
1365 {
1366 PObjectBase old_proj = m_project;
1367 m_project = proj;
1368 m_selObj = m_project;
1369 m_modFlag = false;
1370 m_cmdProc.Reset();
1371 m_projectFile = file;
1372 SetProjectPath( ::wxPathOnly( file ) );
1373 NotifyProjectLoaded();
1374 NotifyProjectRefresh();
1375 }
1376 }
1377 catch( ticpp::Exception& ex )
1378 {
1379 wxLogError( _WXSTR( ex.m_details ) );
1380 return false;
1381 }
1382
1383 return true;
1384 }
1385
ConvertProject(const wxString & path,int fileMajor,int fileMinor)1386 bool ApplicationData::ConvertProject( const wxString& path, int fileMajor, int fileMinor )
1387 {
1388 try
1389 {
1390 ticpp::Document doc;
1391 XMLUtils::LoadXMLFile( doc, false, path );
1392
1393 ticpp::Element* root = doc.FirstChildElement();
1394
1395 if ( root->Value() == std::string( "object" ) )
1396 {
1397 ConvertProjectProperties( root, path, fileMajor, fileMinor );
1398 ConvertObject( root, fileMajor, fileMinor );
1399
1400 // Create a clone of now-converted object tree, so it can be linked
1401 // underneath the root element
1402 std::auto_ptr< ticpp::Node > objectTree = root->Clone();
1403
1404 // Clear the document to add the declatation and the root element
1405 doc.Clear();
1406
1407 // Add the declaration
1408 doc.LinkEndChild( new ticpp::Declaration( "1.0", "UTF-8", "yes" ) );
1409
1410 // Add the root element, with file version
1411 ticpp::Element* newRoot = new ticpp::Element( "wxFormBuilder_Project" );
1412
1413 ticpp::Element* fileVersion = new ticpp::Element( "FileVersion" );
1414 fileVersion->SetAttribute( "major", m_fbpVerMajor );
1415 fileVersion->SetAttribute( "minor", m_fbpVerMinor );
1416
1417 newRoot->LinkEndChild( fileVersion );
1418
1419 // Add the object tree
1420 newRoot->LinkEndChild( objectTree.release() );
1421
1422 doc.LinkEndChild( newRoot );
1423 }
1424 else
1425 {
1426 // Handle project separately because it only occurs once
1427 ticpp::Element* project = root->FirstChildElement( "object" );
1428 ConvertProjectProperties( project, path, fileMajor, fileMinor );
1429 ConvertObject( project, fileMajor, fileMinor );
1430 ticpp::Element* fileVersion = root->FirstChildElement( "FileVersion" );
1431 fileVersion->SetAttribute( "major", m_fbpVerMajor );
1432 fileVersion->SetAttribute( "minor", m_fbpVerMinor );
1433 }
1434
1435 doc.SaveFile();
1436 }
1437 catch ( ticpp::Exception& ex )
1438 {
1439 wxLogError( _WXSTR( ex.m_details ) );
1440 return false;
1441 }
1442
1443 return true;
1444 }
1445
ConvertProjectProperties(ticpp::Element * project,const wxString & path,int fileMajor,int fileMinor)1446 void ApplicationData::ConvertProjectProperties( ticpp::Element* project, const wxString& path, int fileMajor, int fileMinor )
1447
1448 {
1449 // Ensure that this is the "project" element
1450 std::string objClass;
1451 project->GetAttribute( "class", &objClass );
1452
1453 if ( objClass != "Project" )
1454 {
1455 return;
1456 }
1457
1458 // Reusable sets for finding properties
1459 std::set< std::string > oldProps;
1460 std::set< ticpp::Element* > newProps;
1461
1462 if ( fileMajor < 1 || ( 1 == fileMajor && fileMinor < 5 ) )
1463 {
1464 // Find the user_headers property
1465
1466 oldProps.insert( "user_headers" );
1467 GetPropertiesToConvert( project, oldProps, &newProps );
1468
1469 std::string user_headers;
1470 if ( !newProps.empty() )
1471 {
1472 user_headers = ( *newProps.begin() )->GetText( false );
1473 project->RemoveChild( *newProps.begin() );
1474 }
1475
1476 if ( !user_headers.empty() )
1477 {
1478 wxString msg = _( "The \"user_headers\" property has been removed.\n" );
1479 msg += _( "Its purpose was to provide a place to include precompiled headers or\n" );
1480 msg += _( "headers for subclasses.\n" );
1481 msg += _( "There is now a \"precompiled_header\" property and a \"header\" subitem\n" );
1482 msg += _( "on the subclass property.\n\n" );
1483 msg += _( "Would you like the current value of the \"user_headers\" property to be saved\n" );
1484 msg += _( "to a file so that you can distribute the headers among the \"precompiled_header\"\n" );
1485 msg += _( "and \"subclass\" properties\?" );
1486
1487 if ( wxYES == wxMessageBox( msg, _( "The \"user_headers\" property has been removed" ), wxICON_QUESTION | wxYES_NO | wxYES_DEFAULT, wxTheApp->GetTopWindow() ) )
1488 {
1489 wxString name;
1490 wxFileName::SplitPath( path, NULL, NULL, &name, NULL );
1491 wxFileDialog dialog( wxTheApp->GetTopWindow(), _( "Save \"user_headers\"" ), ::wxPathOnly( path ),
1492 name + wxT( "_user_headers.txt" ), wxT( "All files (*.*)|*.*" ), wxFD_SAVE );
1493
1494 if ( dialog.ShowModal() == wxID_OK )
1495 {
1496 wxString wxuser_headers = _WXSTR( user_headers );
1497 wxString filename = dialog.GetPath();
1498 bool success = false;
1499 wxFFile output( filename, wxT( "w" ) );
1500
1501 if ( output.IsOpened() )
1502 {
1503 if ( output.Write( wxuser_headers ) )
1504 {
1505 output.Close();
1506 success = true;
1507 }
1508 }
1509
1510 if ( !success )
1511 {
1512 wxLogError( _( "Unable to open %s for writing.\nUser Headers:\n%s" ), filename.c_str(), wxuser_headers.c_str() );
1513 }
1514 }
1515 }
1516 }
1517 }
1518
1519
1520 // The pch property is now the exact code to be generated, not just the header filename
1521 // The goal of this conversion block is to determine which of two possible pch blocks to use
1522 // The pch block that wxFB generated changed in version 1.6
1523 if ( fileMajor < 1 || ( 1 == fileMajor && fileMinor < 8 ) )
1524 {
1525 oldProps.clear();
1526 newProps.clear();
1527 oldProps.insert( "precompiled_header" );
1528 GetPropertiesToConvert( project, oldProps, &newProps );
1529
1530 if ( !newProps.empty() )
1531 {
1532 std::string pch = ( *newProps.begin() )->GetText( false );
1533 if ( !pch.empty() )
1534 {
1535 if ( fileMajor < 1 || ( 1 == fileMajor && fileMinor < 6 ) )
1536 {
1537 // use the older block
1538 ( *newProps.begin() )->SetText(
1539 "#include \"" + pch + "\""
1540 "\n"
1541 "\n#ifdef __BORLANDC__"
1542 "\n#pragma hdrstop"
1543 "\n#endif //__BORLANDC__"
1544 "\n"
1545 "\n#ifndef WX_PRECOMP"
1546 "\n#include <wx/wx.h>"
1547 "\n#endif //WX_PRECOMP"
1548 );
1549 }
1550 else
1551 {
1552 // use the newer block
1553 ( *newProps.begin() )->SetText(
1554 "#ifdef WX_PRECOMP"
1555 "\n"
1556 "\n#include \"" + pch + "\""
1557 "\n"
1558 "\n#ifdef __BORLANDC__"
1559 "\n#pragma hdrstop"
1560 "\n#endif //__BORLANDC__"
1561 "\n"
1562 "\n#else"
1563 "\n#include <wx/wx.h>"
1564 "\n#endif //WX_PRECOMP"
1565 );
1566 }
1567 }
1568 }
1569 }
1570
1571 // The format of string list properties changed in version 1.9
1572 if ( fileMajor < 1 || ( 1 == fileMajor && fileMinor < 9 ) )
1573 {
1574 oldProps.clear();
1575 newProps.clear();
1576 oldProps.insert( "namespace" );
1577 oldProps.insert( "bitmaps" );
1578 oldProps.insert( "icons" );
1579 GetPropertiesToConvert( project, oldProps, &newProps );
1580
1581 std::set< ticpp::Element* >::iterator prop;
1582 for ( prop = newProps.begin(); prop != newProps.end(); ++prop )
1583 {
1584 std::string value = ( *prop )->GetText( false );
1585 if ( !value.empty() )
1586 {
1587 wxArrayString array = TypeConv::OldStringToArrayString( _WXSTR( value ) );
1588 ( *prop )->SetText( _STDSTR( TypeConv::ArrayStringToString( array ) ) );
1589 }
1590 }
1591 }
1592
1593 // event_handler moved to the forms in version 1.10
1594 if ( fileMajor < 1 || ( 1 == fileMajor && fileMinor < 10 ) )
1595 {
1596 oldProps.clear();
1597 newProps.clear();
1598 oldProps.insert( "event_handler" );
1599 GetPropertiesToConvert( project, oldProps, &newProps );
1600
1601
1602 if ( !newProps.empty() )
1603 {
1604 ticpp::Iterator< ticpp::Element > object( "object" );
1605 for ( object = project->FirstChildElement( "object", false ); object != object.end(); ++object )
1606 {
1607 object->LinkEndChild( ( *newProps.begin() )->Clone().get() );
1608 }
1609
1610 project->RemoveChild( *newProps.begin() );
1611 }
1612 }
1613 }
1614
ConvertObject(ticpp::Element * parent,int fileMajor,int fileMinor)1615 void ApplicationData::ConvertObject( ticpp::Element* parent, int fileMajor, int fileMinor )
1616 {
1617 ticpp::Iterator< ticpp::Element > object( "object" );
1618
1619 for ( object = parent->FirstChildElement( "object", false ); object != object.end(); ++object )
1620 {
1621 ConvertObject( object.Get(), fileMajor, fileMinor );
1622 }
1623
1624 // Reusable sets to find properties with
1625 std::set< std::string > oldProps;
1626
1627 std::set< ticpp::Element* > newProps;
1628
1629 std::set< ticpp::Element* >::iterator newProp;
1630
1631 // Get the class of the object
1632 std::string objClass;
1633
1634 parent->GetAttribute( "class", &objClass );
1635
1636 /* The changes below will convert an unversioned file to version 1.3 */
1637
1638 if ( fileMajor < 1 || ( 1 == fileMajor && fileMinor < 3 ) )
1639 {
1640 // The property 'option' became 'proportion'
1641
1642 if ( objClass == "sizeritem" || objClass == "gbsizeritem" || objClass == "spacer" )
1643 {
1644 oldProps.clear();
1645 newProps.clear();
1646 oldProps.insert( "option" );
1647 GetPropertiesToConvert( parent, oldProps, &newProps );
1648
1649 if ( !newProps.empty() )
1650 {
1651 // One in, one out
1652 ( *newProps.begin() )->SetAttribute( "name", "proportion" );
1653 }
1654 }
1655
1656 // The 'style' property used to have both wxWindow styles and the styles of the specific controls
1657 // now it only has the styles of the specfic controls, and wxWindow styles are saved in window_style
1658 // This also applies to 'extra_style', which was once combined with 'style'.
1659 // And they were named 'WindowStyle' and one point, too...
1660
1661 std::set< wxString > windowStyles;
1662 windowStyles.insert( wxT( "wxSIMPLE_BORDER" ) );
1663 windowStyles.insert( wxT( "wxDOUBLE_BORDER" ) );
1664 windowStyles.insert( wxT( "wxSUNKEN_BORDER" ) );
1665 windowStyles.insert( wxT( "wxRAISED_BORDER" ) );
1666 windowStyles.insert( wxT( "wxSTATIC_BORDER" ) );
1667 windowStyles.insert( wxT( "wxNO_BORDER" ) );
1668 windowStyles.insert( wxT( "wxTRANSPARENT_WINDOW" ) );
1669 windowStyles.insert( wxT( "wxTAB_TRAVERSAL" ) );
1670 windowStyles.insert( wxT( "wxWANTS_CHARS" ) );
1671 windowStyles.insert( wxT( "wxVSCROLL" ) );
1672 windowStyles.insert( wxT( "wxHSCROLL" ) );
1673 windowStyles.insert( wxT( "wxALWAYS_SHOW_SB" ) );
1674 windowStyles.insert( wxT( "wxCLIP_CHILDREN" ) );
1675 windowStyles.insert( wxT( "wxFULL_REPAINT_ON_RESIZE" ) );
1676
1677 // Transfer the window styles
1678 oldProps.clear();
1679 newProps.clear();
1680
1681 oldProps.insert( "style" );
1682
1683 oldProps.insert( "WindowStyle" );
1684
1685 GetPropertiesToConvert( parent, oldProps, &newProps );
1686
1687 for ( newProp = newProps.begin(); newProp != newProps.end(); ++newProp )
1688 {
1689 TransferOptionList( *newProp, &windowStyles, "window_style" );
1690 }
1691
1692
1693 std::set< wxString > extraWindowStyles;
1694 extraWindowStyles.insert( wxT( "wxWS_EX_VALIDATE_RECURSIVELY" ) );
1695 extraWindowStyles.insert( wxT( "wxWS_EX_BLOCK_EVENTS" ) );
1696 extraWindowStyles.insert( wxT( "wxWS_EX_TRANSIENT" ) );
1697 extraWindowStyles.insert( wxT( "wxWS_EX_PROCESS_IDLE" ) );
1698 extraWindowStyles.insert( wxT( "wxWS_EX_PROCESS_UI_UPDATES" ) );
1699
1700 // Transfer the window extra styles
1701 oldProps.clear();
1702 newProps.clear();
1703
1704 oldProps.insert( "style" );
1705
1706 oldProps.insert( "extra_style" );
1707
1708 oldProps.insert( "WindowStyle" );
1709
1710 GetPropertiesToConvert( parent, oldProps, &newProps );
1711
1712 for ( newProp = newProps.begin(); newProp != newProps.end(); ++newProp )
1713 {
1714 TransferOptionList( *newProp, &extraWindowStyles, "window_extra_style" );
1715 }
1716 }
1717
1718 /* The file is now at least version 1.3 */
1719
1720 if ( fileMajor < 1 || ( 1 == fileMajor && fileMinor < 4 ) )
1721 {
1722 if ( objClass == "wxCheckList" )
1723 {
1724 // The class we once named "wxCheckList" really represented a "wxCheckListBox", now that we use the #class macro in
1725 // code generation, it generates the wrong code
1726 parent->SetAttribute( "class", "wxCheckListBox" );
1727 }
1728 }
1729
1730 /* The file is now at least version 1.4 */
1731
1732 if ( fileMajor < 1 || ( 1 == fileMajor && fileMinor < 6 ) )
1733 {
1734 if ( objClass == "spacer" )
1735 {
1736 // spacer used to be represented by its own class, it is now under a sizeritem like everything else.
1737 // no need to check for a wxGridBagSizer, because it was introduced at the same time.
1738
1739 // the goal is to change the class to sizeritem, then create a spacer child, then move "width" and "height" to the spacer
1740 parent->SetAttribute( "class", "sizeritem" );
1741 ticpp::Element spacer( "object" );
1742 spacer.SetAttribute( "class", "spacer" );
1743
1744 oldProps.clear();
1745 newProps.clear();
1746 oldProps.insert( "width" );
1747 GetPropertiesToConvert( parent, oldProps, &newProps );
1748
1749 if ( !newProps.empty() )
1750 {
1751 // One in, one out
1752 ticpp::Element* width = *newProps.begin();
1753 spacer.LinkEndChild( width->Clone().release() );
1754 parent->RemoveChild( width );
1755 }
1756
1757 oldProps.clear();
1758 newProps.clear();
1759 oldProps.insert( "height" );
1760 GetPropertiesToConvert( parent, oldProps, &newProps );
1761
1762 if ( !newProps.empty() )
1763 {
1764 // One in, one out
1765 ticpp::Element* height = *newProps.begin();
1766 spacer.LinkEndChild( height->Clone().release() );
1767 parent->RemoveChild( height );
1768 }
1769 parent->LinkEndChild( &spacer );
1770 }
1771 }
1772
1773 /* The file is now at least version 1.6 */
1774
1775 // Version 1.7 now stores all font properties.
1776 // The font property conversion is automatic because it is just an extension of the old values.
1777
1778 if ( fileMajor < 1 || ( 1 == fileMajor && fileMinor < 7 ) )
1779 {
1780 // Remove deprecated 2.6 things
1781
1782 // wxDialog styles wxTHICK_FRAME and wxNO_3D
1783 if ( objClass == "Dialog" )
1784 {
1785 oldProps.clear();
1786 newProps.clear();
1787 oldProps.insert( "style" );
1788 GetPropertiesToConvert( parent, oldProps, &newProps );
1789
1790 if ( !newProps.empty() )
1791 {
1792 ticpp::Element* style = *newProps.begin();
1793 wxString styles = _WXSTR( style->GetText( false ) );
1794 if ( !styles.empty() )
1795 {
1796 if ( TypeConv::FlagSet( wxT("wxTHICK_FRAME"), styles ) )
1797 {
1798 styles = TypeConv::ClearFlag( wxT("wxTHICK_FRAME"), styles );
1799 styles = TypeConv::SetFlag( wxT("wxRESIZE_BORDER"), styles );
1800 }
1801
1802 styles = TypeConv::ClearFlag( wxT("wxNO_3D"), styles );
1803 style->SetText( _STDSTR( styles ) );
1804 }
1805 }
1806 }
1807 }
1808
1809 /* The file is now at least version 1.7 */
1810
1811 // The update to 1.8 only affected project properties
1812 // See ConvertProjectProperties
1813
1814 /* The file is now at least version 1.8 */
1815
1816 // stringlist properties are stored in a different format as of version 1.9
1817 if ( fileMajor < 1 || ( 1 == fileMajor && fileMinor < 9 ) )
1818 {
1819 oldProps.clear();
1820 newProps.clear();
1821
1822 if ( objClass == "wxComboBox" ||
1823 objClass == "wxChoice" ||
1824 objClass == "wxListBox" ||
1825 objClass == "wxRadioBox" ||
1826 objClass == "wxCheckListBox"
1827 )
1828 {
1829 oldProps.insert( "choices" );
1830 }
1831 else if ( objClass == "wxGrid" )
1832 {
1833 oldProps.insert( "col_label_values" );
1834 oldProps.insert( "row_label_values" );
1835 }
1836
1837 if ( !oldProps.empty() )
1838 {
1839 GetPropertiesToConvert( parent, oldProps, &newProps );
1840
1841 std::set< ticpp::Element* >::iterator prop;
1842 for ( prop = newProps.begin(); prop != newProps.end(); ++prop )
1843 {
1844 std::string value = ( *prop )->GetText( false );
1845 if ( !value.empty() )
1846 {
1847 wxArrayString array = TypeConv::OldStringToArrayString( _WXSTR( value ) );
1848 ( *prop )->SetText( _STDSTR( TypeConv::ArrayStringToString( array ) ) );
1849 }
1850 }
1851 }
1852 }
1853
1854 /* The file is now at least version 1.9 */
1855
1856 // Version 1.11 now stores bitmap property in the following format:
1857 // 'source'; 'data' instead of old form 'data'; 'source'.
1858
1859 if ( fileMajor < 1 || ( 1 == fileMajor && fileMinor < 11 ) )
1860 {
1861 oldProps.clear();
1862 newProps.clear();
1863 oldProps.insert( "bitmap" );
1864 GetPropertiesToConvert( parent, oldProps, &newProps );
1865
1866 std::set< ticpp::Element* >::iterator prop;
1867 for ( prop = newProps.begin(); prop != newProps.end(); ++prop )
1868 {
1869 ticpp::Element* bitmap = *prop;
1870
1871 wxString image = _WXSTR( bitmap->GetText( false ) );
1872 if ( !image.empty() )
1873 {
1874 if( image.AfterLast( ';' ).Contains( _("Load From") ) )
1875 {
1876 wxString source = image.AfterLast( ';' ).Trim().Trim(false);
1877 wxString data = image.BeforeLast( ';' ).Trim().Trim(false);
1878
1879 bitmap->SetText( _STDSTR( source + wxT("; ") + data ) );
1880 }
1881 }
1882 }
1883
1884 /* oldProps.clear();
1885 newProps.clear();
1886 oldProps.insert( "choices" );
1887 GetPropertiesToConvert( parent, oldProps, &newProps );
1888
1889 for ( prop = newProps.begin(); prop != newProps.end(); ++prop )
1890 {
1891 ticpp::Element* choices = *prop;
1892
1893 wxString content = _WXSTR( choices->GetText( false ) );
1894 if ( !content.empty() )
1895 {
1896 content.Replace( wxT("\" \""), wxT(";") );
1897 content.Replace( wxT("\""), wxT("") );
1898
1899 choices->SetText( _STDSTR( content ) );
1900 }
1901 }*/
1902 }
1903
1904 /* The file is now at least version 1.11 */
1905 if ( fileMajor < 1 || ( 1 == fileMajor && fileMinor < 12 ) )
1906 {
1907 bool classUpdated = false;
1908 if( "wxScintilla" == objClass )
1909 {
1910 objClass = "wxStyledTextCtrl";
1911 parent->SetAttribute( "class", objClass );
1912 classUpdated = true;
1913 }
1914 if( "wxTreeListCtrl" == objClass )
1915 {
1916 objClass = "wxadditions::wxTreeListCtrl";
1917 parent->SetAttribute( "class", objClass );
1918 classUpdated = true;
1919 }
1920 if( "wxTreeListCtrlColumn" == objClass )
1921 {
1922 objClass = "wxadditions::wxTreeListCtrlColumn";
1923 parent->SetAttribute( "class", objClass );
1924 classUpdated = true;
1925 }
1926 if( m_warnOnAdditionsUpdate && classUpdated )
1927 {
1928 m_warnOnAdditionsUpdate = false;
1929 wxLogWarning( _("Updated classes from wxAdditions. You must use the latest version of wxAdditions to continue.\nNote wxScintilla is now wxStyledListCtrl, wxTreeListCtrl is now wxadditions::wxTreeListCtrl, and wxTreeListCtrlColumn is now wxadditions::wxTreeListCtrlColumn") );
1930 }
1931
1932 typedef std::map< std::string, std::set< std::string > > PropertiesToRemove;
1933
1934 static std::set< std::string > propertyRemovalWarnings;
1935 const PropertiesToRemove& propertiesToRemove = GetPropertiesToRemove_v1_12();
1936 PropertiesToRemove::const_iterator it = propertiesToRemove.find( objClass );
1937 if( it != propertiesToRemove.end() )
1938 {
1939 RemoveProperties( parent, it->second );
1940 if( 0 == propertyRemovalWarnings.count( objClass ) )
1941 {
1942 std::stringstream ss;
1943 std::ostream_iterator< std::string > out_it (ss, ", ");
1944 std::copy( it->second.begin(), it->second.end(), out_it );
1945
1946 wxLogMessage( _("Removed properties for class %s because they are no longer supported: %s"), objClass, ss.str() );
1947 propertyRemovalWarnings.insert( objClass );
1948 }
1949 }
1950 }
1951 /* The file is now at least version 1.12 */
1952 }
1953
GetPropertiesToConvert(ticpp::Node * parent,const std::set<std::string> & names,std::set<ticpp::Element * > * properties)1954 void ApplicationData::GetPropertiesToConvert( ticpp::Node* parent, const std::set< std::string >& names, std::set< ticpp::Element* >* properties )
1955 {
1956 // Clear result set
1957 properties->clear();
1958
1959 ticpp::Iterator< ticpp::Element > prop( "property" );
1960
1961 for ( prop = parent->FirstChildElement( "property", false ); prop != prop.end(); ++prop )
1962 {
1963 std::string name;
1964 prop->GetAttribute( "name", &name );
1965
1966 if ( names.find( name ) != names.end() )
1967 {
1968 properties->insert( prop.Get() );
1969 }
1970 }
1971 }
1972
RemoveProperties(ticpp::Node * parent,const std::set<std::string> & names)1973 void ApplicationData::RemoveProperties( ticpp::Node* parent, const std::set< std::string >& names )
1974 {
1975 ticpp::Iterator< ticpp::Element > prop( "property" );
1976
1977 for ( prop = parent->FirstChildElement( "property", false ); prop != prop.end(); )
1978 {
1979 ticpp::Element element = *prop;
1980 ++prop;
1981
1982 std::string name;
1983 element.GetAttribute( "name", &name );
1984
1985 if ( names.find( name ) != names.end() )
1986 {
1987 parent->RemoveChild( &element );
1988 }
1989 }
1990 }
1991
TransferOptionList(ticpp::Element * prop,std::set<wxString> * options,const std::string & newPropName)1992 void ApplicationData::TransferOptionList( ticpp::Element* prop, std::set< wxString >* options, const std::string& newPropName )
1993
1994 {
1995 wxString value = _WXSTR( prop->GetText( false ) );
1996
1997 std::set< wxString > transfer;
1998
1999 std::set< wxString > keep;
2000
2001 // Sort options - if in the 'options' set, they should be transferred to a property named 'newPropName'
2002 // otherwise, they should stay
2003 wxStringTokenizer tkz( value, wxT( "|" ), wxTOKEN_RET_EMPTY_ALL );
2004
2005 while ( tkz.HasMoreTokens() )
2006 {
2007 wxString option = tkz.GetNextToken();
2008 option.Trim( false );
2009 option.Trim( true );
2010
2011 if ( options->find( option ) != options->end() )
2012 {
2013 // Needs to be transferred
2014 transfer.insert( option );
2015 }
2016 else
2017 {
2018 // Should be kept
2019 keep.insert( option );
2020 }
2021 }
2022
2023 // Reusable sets to find properties with
2024 std::set< std::string > oldProps;
2025
2026 std::set< ticpp::Element* > newProps;
2027
2028 // If there are any to transfer, add to the target property, or make a new one
2029 ticpp::Node* parent = prop->Parent();
2030
2031 if ( !transfer.empty() )
2032 {
2033 // Check for the target property
2034 ticpp::Element* newProp;
2035 wxString newOptionList;
2036
2037 oldProps.clear();
2038 oldProps.insert( newPropName );
2039 GetPropertiesToConvert( parent, oldProps, &newProps );
2040
2041 if ( !newProps.empty() )
2042 {
2043 newProp = *newProps.begin();
2044 newOptionList << wxT( "|" ) << _WXSTR( newProp->GetText( false ) );
2045 }
2046 else
2047 {
2048 newProp = new ticpp::Element( "property" );
2049 newProp->SetAttribute( "name", newPropName );
2050 }
2051
2052 std::set< wxString >::iterator option;
2053
2054 for ( option = transfer.begin(); option != transfer.end(); ++option )
2055 {
2056 newOptionList << wxT( "|" ) << *option;
2057 }
2058
2059 newProp->SetText( _STDSTR( newOptionList.substr( 1 ) ) );
2060
2061 if ( newProps.empty() )
2062 {
2063 parent->InsertBeforeChild( prop, *newProp );
2064 delete newProp;
2065 }
2066 }
2067
2068 // Set the value of the property to whatever is left
2069 if ( keep.empty() )
2070 {
2071 parent->RemoveChild( prop );
2072 }
2073 else
2074 {
2075
2076 std::set< wxString >::iterator option;
2077
2078 wxString newOptionList;
2079
2080 for ( option = keep.begin(); option != keep.end(); ++option )
2081 {
2082 newOptionList << wxT( "|" ) << *option;
2083 }
2084
2085 prop->SetText( _STDSTR( newOptionList.substr( 1 ) ) );
2086 }
2087 }
2088
NewProject()2089 void ApplicationData::NewProject()
2090
2091 {
2092 m_project = m_objDb->CreateObject( "Project" );
2093 m_selObj = m_project;
2094 m_modFlag = false;
2095 m_cmdProc.Reset();
2096 m_projectFile = wxT( "" );
2097 SetProjectPath( wxT( "" ) );
2098 m_ipc->Reset();
2099 NotifyProjectRefresh();
2100 }
2101
GenerateCode(bool panelOnly)2102 void ApplicationData::GenerateCode( bool panelOnly )
2103 {
2104 #ifdef USE_FLATNOTEBOOK
2105 NotifyCodeGeneration( panelOnly );
2106 #else
2107 NotifyCodeGeneration( panelOnly, true );
2108 #endif
2109 }
2110
GenerateInheritedClass(PObjectBase form,wxString className,wxString path,wxString file)2111 void ApplicationData::GenerateInheritedClass( PObjectBase form, wxString className, wxString path, wxString file )
2112 {
2113 try
2114 {
2115 PObjectBase project = GetProjectData();
2116 if ( !project )
2117 {
2118 wxLogWarning( _("No Project?!") );
2119 return;
2120 }
2121
2122 if ( !::wxDirExists( path ) )
2123 {
2124 wxLogWarning( _("Invalid Path: %s"), path.c_str() );
2125 return;
2126 }
2127
2128 PObjectBase obj = m_objDb->CreateObject( "UserClasses", PObjectBase() );
2129
2130 PProperty baseNameProp = obj->GetProperty( wxT( "basename" ) );
2131 PProperty nameProp = obj->GetProperty( wxT( "name" ) );
2132 PProperty fileProp = obj->GetProperty( wxT( "file" ) );
2133 PProperty genfileProp = obj->GetProperty( wxT( "gen_file" ) );
2134 PProperty typeProp = obj->GetProperty( wxT( "type" ) );
2135
2136 if ( !( baseNameProp && nameProp && fileProp && typeProp && genfileProp ) )
2137 {
2138 wxLogWarning( wxT("Missing Property") );
2139 return;
2140 }
2141
2142 wxFileName inherFile( file );
2143 if ( !inherFile.MakeAbsolute( path ) )
2144 {
2145 wxLogWarning( _("Unable to make \"%s\" absolute to \"%s\""), file.c_str(), path.c_str() );
2146 return;
2147 }
2148
2149 const wxString& genFileValue = project->GetPropertyAsString( _("file") );
2150 wxFileName genFile( genFileValue );
2151 if ( !genFile.MakeAbsolute( path ) )
2152 {
2153 wxLogWarning( _("Unable to make \"%s\" absolute to \"%s\""), genFileValue.c_str(), path.c_str() );
2154 return;
2155 }
2156
2157 const wxString& genFileFullPath = genFile.GetFullPath();
2158 if ( !genFile.MakeRelativeTo( inherFile.GetPath( wxPATH_GET_VOLUME ) ) )
2159 {
2160 wxLogWarning( _("Unable to make \"%s\" relative to \"%s\""), genFileFullPath.c_str(), inherFile.GetPath( wxPATH_GET_VOLUME ).c_str() );
2161 return;
2162 }
2163
2164 baseNameProp->SetValue( form->GetPropertyAsString( _("name") ) );
2165 nameProp->SetValue( className );
2166 fileProp->SetValue( inherFile.GetName() );
2167 genfileProp->SetValue( genFile.GetFullPath() );
2168 typeProp->SetValue( form->GetClassName() );
2169
2170 // Determine if Microsoft BOM should be used
2171 bool useMicrosoftBOM = false;
2172 PProperty pUseMicrosoftBOM = project->GetProperty( _("use_microsoft_bom") );
2173
2174 if ( pUseMicrosoftBOM )
2175 {
2176 useMicrosoftBOM = ( pUseMicrosoftBOM->GetValueAsInteger() != 0 );
2177 }
2178
2179 // Determine if Utf8 or Ansi is to be created
2180 bool useUtf8 = false;
2181 PProperty pUseUtf8 = project->GetProperty( _("encoding") );
2182
2183 if ( pUseUtf8 )
2184 {
2185 useUtf8 = ( pUseUtf8->GetValueAsString() != wxT("ANSI") );
2186 }
2187
2188 PProperty pCodeGen = project->GetProperty( wxT( "code_generation" ) );
2189 if ( pCodeGen && TypeConv::FlagSet( wxT("C++"), pCodeGen->GetValue() ) )
2190 {
2191 CppCodeGenerator codegen;
2192 const wxString& fullPath = inherFile.GetFullPath();
2193 codegen.ParseFiles(fullPath + wxT(".h"), fullPath + wxT(".cpp"));
2194
2195 PCodeWriter h_cw( new FileCodeWriter( fullPath + wxT(".h"), useMicrosoftBOM, useUtf8 ) );
2196 PCodeWriter cpp_cw( new FileCodeWriter( fullPath + wxT(".cpp"), useMicrosoftBOM, useUtf8 ) );
2197
2198 codegen.SetHeaderWriter( h_cw );
2199 codegen.SetSourceWriter( cpp_cw );
2200
2201 codegen.GenerateInheritedClass( obj, form );
2202 }
2203 else if( pCodeGen && TypeConv::FlagSet( wxT("Python"), pCodeGen->GetValue() ) )
2204 {
2205 PythonCodeGenerator codegen;
2206
2207 const wxString& fullPath = inherFile.GetFullPath();
2208 PCodeWriter python_cw( new FileCodeWriter( fullPath + wxT(".py"), useMicrosoftBOM, useUtf8 ) );
2209
2210 codegen.SetSourceWriter( python_cw );
2211
2212 codegen.GenerateInheritedClass( obj, form );
2213 }
2214 else if( pCodeGen && TypeConv::FlagSet( wxT("PHP"), pCodeGen->GetValue() ) )
2215 {
2216 PHPCodeGenerator codegen;
2217
2218 const wxString& fullPath = inherFile.GetFullPath();
2219 PCodeWriter php_cw( new FileCodeWriter( fullPath + wxT(".php"), useMicrosoftBOM, useUtf8 ) );
2220
2221 codegen.SetSourceWriter( php_cw );
2222
2223 codegen.GenerateInheritedClass( obj, form );
2224 }
2225 else if( pCodeGen && TypeConv::FlagSet( wxT("Lua"), pCodeGen->GetValue() ) )
2226 {
2227 LuaCodeGenerator codegen;
2228
2229 const wxString& fullPath = inherFile.GetFullPath();
2230 PCodeWriter lua_cw( new FileCodeWriter( fullPath + wxT(".lua"), useMicrosoftBOM, useUtf8 ) );
2231
2232 codegen.SetSourceWriter( lua_cw );
2233
2234 codegen.GenerateInheritedClass( obj, form, genFileFullPath );
2235 }
2236
2237 wxLogStatus( wxT( "Class generated at \'%s\'." ), path.c_str() );
2238 }
2239 catch( wxFBException& ex )
2240 {
2241 wxLogError( ex.what() );
2242 }
2243 }
2244
MovePosition(PObjectBase obj,bool right,unsigned int num)2245 void ApplicationData::MovePosition( PObjectBase obj, bool right, unsigned int num )
2246 {
2247 PObjectBase noItemObj = obj;
2248
2249 PObjectBase parent = obj->GetParent();
2250
2251 if ( parent )
2252 {
2253 // Si el objeto está incluido dentro de un item hay que desplazar
2254 // el item
2255
2256 while ( parent && parent->GetObjectInfo()->GetObjectType()->IsItem() )
2257 {
2258 obj = parent;
2259 parent = obj->GetParent();
2260 }
2261
2262 unsigned int pos = parent->GetChildPosition( obj );
2263
2264 // nos aseguramos de que los límites son correctos
2265
2266 unsigned int children_count = parent->GetChildCount();
2267
2268 if ( ( right && num + pos < children_count ) ||
2269 ( !right && ( num <= pos ) ) )
2270 {
2271 pos = ( right ? pos + num : pos - num );
2272
2273 PCommand command( new ShiftChildCmd( obj, pos ) );
2274 Execute( command ); //m_cmdProc.Execute(command);
2275 NotifyProjectRefresh();
2276 SelectObject( noItemObj, true );
2277
2278 }
2279 }
2280 }
2281
MoveHierarchy(PObjectBase obj,bool up)2282 void ApplicationData::MoveHierarchy( PObjectBase obj, bool up )
2283 {
2284 PObjectBase sizeritem = obj->GetParent();
2285 if ( !( sizeritem && sizeritem->GetObjectInfo()->IsSubclassOf( wxT("sizeritembase") ) ) )
2286 {
2287 return;
2288 }
2289
2290 PObjectBase nextSizer = sizeritem->GetParent(); // points to the object's sizer
2291 if ( nextSizer )
2292 {
2293 if ( up )
2294 {
2295 do
2296 {
2297 nextSizer = nextSizer->GetParent();
2298 }
2299 while ( nextSizer && !nextSizer->GetObjectInfo()->IsSubclassOf( wxT("sizer") ) && !nextSizer->GetObjectInfo()->IsSubclassOf( wxT("gbsizer") ) );
2300
2301 if ( nextSizer && ( nextSizer->GetObjectInfo()->IsSubclassOf( wxT("sizer") ) || nextSizer->GetObjectInfo()->IsSubclassOf( wxT("gbsizer") ) ) )
2302 {
2303 PCommand cmdReparent( new ReparentObjectCmd( sizeritem, nextSizer ) );
2304 Execute( cmdReparent );
2305 NotifyProjectRefresh();
2306 SelectObject( obj, true );
2307 }
2308 }
2309 else
2310 {
2311 // object will be move to the top sizer of the next sibling object
2312 // subtree.
2313 unsigned int pos = nextSizer->GetChildPosition( sizeritem ) + 1;
2314
2315 if ( pos < nextSizer->GetChildCount() )
2316 {
2317 nextSizer = SearchSizerInto( nextSizer->GetChild( pos ) );
2318
2319 if ( nextSizer )
2320 {
2321 PCommand cmdReparent( new ReparentObjectCmd( sizeritem, nextSizer ) );
2322 Execute( cmdReparent );
2323 NotifyProjectRefresh();
2324 SelectObject( obj, true );
2325 }
2326 }
2327 }
2328 }
2329 }
2330
2331
Undo()2332 void ApplicationData::Undo()
2333 {
2334 m_cmdProc.Undo();
2335 m_modFlag = !m_cmdProc.IsAtSavePoint();
2336 NotifyProjectRefresh();
2337 CheckProjectTree( m_project );
2338 NotifyObjectSelected( GetSelectedObject() );
2339 }
2340
Redo()2341 void ApplicationData::Redo()
2342 {
2343 m_cmdProc.Redo();
2344 m_modFlag = !m_cmdProc.IsAtSavePoint();
2345 NotifyProjectRefresh();
2346 CheckProjectTree( m_project );
2347 NotifyObjectSelected( GetSelectedObject() );
2348 }
2349
2350
ToggleExpandLayout(PObjectBase obj)2351 void ApplicationData::ToggleExpandLayout( PObjectBase obj )
2352 {
2353 if ( !obj )
2354 {
2355 return;
2356 }
2357
2358 PObjectBase parent = obj->GetParent();
2359 if ( !parent )
2360 {
2361 return;
2362 }
2363
2364 if ( !parent->GetObjectInfo()->IsSubclassOf( wxT("sizeritembase") ) )
2365 {
2366 return;
2367 }
2368
2369 PProperty propFlag = parent->GetProperty( wxT("flag") );
2370
2371 if( !propFlag )
2372 {
2373 return;
2374 }
2375
2376 wxString value;
2377 wxString currentValue = propFlag->GetValueAsString();
2378
2379 value =
2380 ( TypeConv::FlagSet( wxT("wxEXPAND"), currentValue ) ?
2381 TypeConv::ClearFlag( wxT("wxEXPAND"), currentValue ) :
2382 TypeConv::SetFlag( wxT("wxEXPAND"), currentValue ) );
2383
2384 ModifyProperty( propFlag, value );
2385 }
2386
ToggleStretchLayout(PObjectBase obj)2387 void ApplicationData::ToggleStretchLayout( PObjectBase obj )
2388 {
2389 if ( !obj )
2390 {
2391 return;
2392 }
2393
2394 PObjectBase parent = obj->GetParent();
2395 if ( !parent )
2396 {
2397 return;
2398 }
2399
2400 if ( parent->GetObjectTypeName() != wxT("sizeritem") && parent->GetObjectTypeName() != wxT("gbsizeritem") )
2401 {
2402 return;
2403 }
2404
2405 PProperty proportion = parent->GetProperty( wxT("proportion") );
2406 if ( !proportion )
2407 {
2408 return;
2409 }
2410
2411 wxString value = ( proportion->GetValue() != wxT("0") ? wxT( "0" ) : wxT( "1" ) );
2412 ModifyProperty( proportion, value );
2413 }
2414
CheckProjectTree(PObjectBase obj)2415 void ApplicationData::CheckProjectTree( PObjectBase obj )
2416 {
2417 assert( obj );
2418
2419 for ( unsigned int i = 0; i < obj->GetChildCount(); i++ )
2420 {
2421 PObjectBase child = obj->GetChild( i );
2422
2423 if ( child->GetParent() != obj )
2424 {
2425 #if wxVERSION_NUMBER < 2900
2426 wxLogError( wxString::Format( wxT( "Parent of object \'%s\' is wrong!" ), child->GetPropertyAsString( wxT( "name" ) ).c_str() ) );
2427 #else
2428 wxLogError( wxString::Format("Parent of object \'" + child->GetPropertyAsString("name") + "\' is wrong!") );
2429 #endif
2430 }
2431 CheckProjectTree( child );
2432 }
2433 }
2434
GetLayoutSettings(PObjectBase obj,int * flag,int * option,int * border,int * orient)2435 bool ApplicationData::GetLayoutSettings( PObjectBase obj, int *flag, int *option, int *border, int* orient )
2436 {
2437 if ( !obj )
2438 {
2439 return false;
2440 }
2441
2442 PObjectBase parent = obj->GetParent();
2443 if ( !parent )
2444 {
2445 return false;
2446 }
2447
2448 if ( parent->GetObjectInfo()->IsSubclassOf( wxT("sizeritembase") ) )
2449 {
2450 PProperty propOption = parent->GetProperty( wxT("proportion") );
2451 if ( propOption )
2452 {
2453 *option = propOption->GetValueAsInteger();
2454 }
2455
2456 *flag = parent->GetPropertyAsInteger( wxT("flag") );
2457 *border = parent->GetPropertyAsInteger( wxT("border") );
2458
2459 PObjectBase sizer = parent->GetParent();
2460 if ( sizer )
2461 {
2462 wxString parentName = sizer->GetClassName();
2463 if ( wxT("wxBoxSizer") == parentName || wxT("wxStaticBoxSizer") == parentName )
2464 {
2465 PProperty propOrient = sizer->GetProperty( wxT("orient") );
2466 if ( propOrient )
2467 {
2468 *orient = propOrient->GetValueAsInteger();
2469 }
2470 }
2471 }
2472 return true;
2473 }
2474
2475 return false;
2476 }
2477
ChangeAlignment(PObjectBase obj,int align,bool vertical)2478 void ApplicationData::ChangeAlignment ( PObjectBase obj, int align, bool vertical )
2479 {
2480 if ( !obj )
2481 {
2482 return;
2483 }
2484
2485 PObjectBase parent = obj->GetParent();
2486 if ( !parent )
2487 {
2488 return;
2489 }
2490
2491 if ( !parent->GetObjectInfo()->IsSubclassOf( wxT("sizeritembase") ) )
2492 {
2493 return;
2494 }
2495
2496 PProperty propFlag = parent->GetProperty( wxT( "flag" ) );
2497
2498 if ( !propFlag )
2499 {
2500 return;
2501 }
2502
2503 wxString value = propFlag->GetValueAsString();
2504
2505 // Primero borramos los flags de la configuración previa, para así
2506 // evitar conflictos de alineaciones.
2507
2508 if ( vertical )
2509 {
2510 value = TypeConv::ClearFlag( wxT( "wxALIGN_TOP" ), value );
2511 value = TypeConv::ClearFlag( wxT( "wxALIGN_BOTTOM" ), value );
2512 value = TypeConv::ClearFlag( wxT( "wxALIGN_CENTER_VERTICAL" ), value );
2513 }
2514 else
2515 {
2516 value = TypeConv::ClearFlag( wxT( "wxALIGN_LEFT" ), value );
2517 value = TypeConv::ClearFlag( wxT( "wxALIGN_RIGHT" ), value );
2518 value = TypeConv::ClearFlag( wxT( "wxALIGN_CENTER_HORIZONTAL" ), value );
2519 }
2520
2521 wxString alignStr;
2522
2523 switch ( align )
2524 {
2525
2526 case wxALIGN_RIGHT:
2527 alignStr = wxT( "wxALIGN_RIGHT" );
2528
2529 break;
2530
2531 case wxALIGN_CENTER_HORIZONTAL:
2532 alignStr = wxT( "wxALIGN_CENTER_HORIZONTAL" );
2533
2534 break;
2535
2536 case wxALIGN_BOTTOM:
2537 alignStr = wxT( "wxALIGN_BOTTOM" );
2538
2539 break;
2540
2541 case wxALIGN_CENTER_VERTICAL:
2542 alignStr = wxT( "wxALIGN_CENTER_VERTICAL" );
2543
2544 break;
2545 }
2546
2547 value = TypeConv::SetFlag( alignStr, value );
2548
2549 ModifyProperty( propFlag, value );
2550 }
2551
ToggleBorderFlag(PObjectBase obj,int border)2552 void ApplicationData::ToggleBorderFlag( PObjectBase obj, int border )
2553 {
2554 if ( !obj )
2555 {
2556 return;
2557 }
2558
2559 PObjectBase parent = obj->GetParent();
2560 if ( !parent )
2561 {
2562 return;
2563 }
2564
2565 if ( !parent->GetObjectInfo()->IsSubclassOf( wxT("sizeritembase") ) )
2566 {
2567 return;
2568 }
2569
2570 PProperty propFlag = parent->GetProperty( wxT( "flag" ) );
2571
2572 if ( !propFlag )
2573 {
2574 return;
2575 }
2576
2577 wxString value = propFlag->GetValueAsString();
2578
2579 value = TypeConv::ClearFlag( wxT( "wxALL" ), value );
2580 value = TypeConv::ClearFlag( wxT( "wxTOP" ), value );
2581 value = TypeConv::ClearFlag( wxT( "wxBOTTOM" ), value );
2582 value = TypeConv::ClearFlag( wxT( "wxRIGHT" ), value );
2583 value = TypeConv::ClearFlag( wxT( "wxLEFT" ), value );
2584
2585 int intVal = propFlag->GetValueAsInteger();
2586 intVal ^= border;
2587
2588 if ( ( intVal & wxALL ) == wxALL )
2589 value = TypeConv::SetFlag( wxT( "wxALL" ), value );
2590 else
2591 {
2592 if ( ( intVal & wxTOP ) != 0 ) value = TypeConv::SetFlag( wxT( "wxTOP" ), value );
2593
2594 if ( ( intVal & wxBOTTOM ) != 0 ) value = TypeConv::SetFlag( wxT( "wxBOTTOM" ), value );
2595
2596 if ( ( intVal & wxRIGHT ) != 0 ) value = TypeConv::SetFlag( wxT( "wxRIGHT" ), value );
2597
2598 if ( ( intVal & wxLEFT ) != 0 ) value = TypeConv::SetFlag( wxT( "wxLEFT" ), value );
2599 }
2600
2601 ModifyProperty( propFlag, value );
2602 }
2603
CreateBoxSizerWithObject(PObjectBase obj)2604 void ApplicationData::CreateBoxSizerWithObject( PObjectBase obj )
2605 {
2606 PObjectBase parent = obj->GetParent();
2607 if ( !parent )
2608 {
2609 return;
2610 }
2611
2612 PObjectBase grandParent = parent->GetParent();
2613 if ( !grandParent )
2614 {
2615 return;
2616 }
2617
2618 int childPos = -1;
2619 if ( parent->GetObjectInfo()->IsSubclassOf( wxT("sizeritembase") ) )
2620 {
2621 childPos = (int)grandParent->GetChildPosition( parent );
2622 parent = grandParent;
2623 }
2624
2625 // Must first cut the old object in case it is the only allowable object
2626 PObjectBase clipboard = m_clipboard;
2627 CutObject( obj );
2628
2629 // Create the wxBoxSizer
2630 PObjectBase newSizer = m_objDb->CreateObject( "wxBoxSizer", parent );
2631
2632 if ( newSizer )
2633 {
2634 PCommand cmd( new InsertObjectCmd( this, newSizer, parent, childPos ) );
2635 Execute( cmd );
2636
2637 if ( newSizer->GetObjectTypeName() == wxT("sizeritem") )
2638 newSizer = newSizer->GetChild( 0 );
2639
2640 PasteObject( newSizer );
2641 m_clipboard = clipboard;
2642
2643 //NotifyProjectRefresh();
2644 }
2645 else
2646 {
2647 Undo();
2648 m_clipboard = clipboard;
2649 }
2650 }
2651
ShowXrcPreview()2652 void ApplicationData::ShowXrcPreview()
2653 {
2654 PObjectBase form = GetSelectedForm();
2655
2656 if ( form == NULL )
2657 {
2658 wxMessageBox( wxT( "Please select a form and try again." ), wxT( "XRC Preview" ), wxICON_ERROR );
2659 return;
2660 }
2661 else if( form->GetPropertyAsInteger( wxT("aui_managed") ) )
2662 {
2663 wxMessageBox( wxT( "XRC preview doesn't support AUI-managed frames." ), wxT( "XRC Preview" ), wxICON_ERROR );
2664 return;
2665 }
2666
2667 XRCPreview::Show( form, GetProjectPath() );
2668 }
2669
CanPasteObject()2670 bool ApplicationData::CanPasteObject()
2671 {
2672 PObjectBase obj = GetSelectedObject();
2673
2674 if ( obj && obj->GetObjectTypeName() != wxT( "project" ) )
2675 return ( m_clipboard != NULL );
2676
2677 return false;
2678 }
2679
CanCopyObject()2680 bool ApplicationData::CanCopyObject()
2681 {
2682 PObjectBase obj = GetSelectedObject();
2683
2684 if ( obj && obj->GetObjectTypeName() != wxT( "project" ) )
2685 return true;
2686
2687 return false;
2688 }
2689
IsModified()2690 bool ApplicationData::IsModified()
2691 {
2692 return m_modFlag;
2693 }
2694
Execute(PCommand cmd)2695 void ApplicationData::Execute( PCommand cmd )
2696 {
2697 m_modFlag = true;
2698 m_cmdProc.Execute( cmd );
2699 }
2700
2701 //////////////////////////////////////////////////////////////////////////////
AddHandler(wxEvtHandler * handler)2702 void ApplicationData::AddHandler( wxEvtHandler* handler )
2703 {
2704 m_handlers.push_back( handler );
2705 }
2706
RemoveHandler(wxEvtHandler * handler)2707 void ApplicationData::RemoveHandler( wxEvtHandler* handler )
2708 {
2709 for ( HandlerVector::iterator it = m_handlers.begin(); it != m_handlers.end(); ++it )
2710 {
2711 if ( *it == handler )
2712 {
2713 m_handlers.erase( it );
2714 break;
2715 }
2716 }
2717 }
2718
NotifyEvent(wxFBEvent & event,bool forcedelayed)2719 void ApplicationData::NotifyEvent( wxFBEvent& event, bool forcedelayed )
2720 {
2721
2722 if ( !forcedelayed )
2723 {
2724 LogDebug( "event: %s", event.GetEventName().c_str() );
2725
2726 std::vector< wxEvtHandler* >::iterator handler;
2727
2728 for ( handler = m_handlers.begin(); handler != m_handlers.end(); handler++ )
2729 {
2730 ( *handler )->ProcessEvent( event );
2731 }
2732 }
2733 else
2734 {
2735 LogDebug( "Pending event: %s", event.GetEventName().c_str() );
2736
2737 std::vector< wxEvtHandler* >::iterator handler;
2738
2739 for ( handler = m_handlers.begin(); handler != m_handlers.end(); handler++ )
2740 {
2741 ( *handler )->AddPendingEvent( event );
2742 }
2743 }
2744 }
2745
NotifyProjectLoaded()2746 void ApplicationData::NotifyProjectLoaded()
2747 {
2748 wxFBEvent event( wxEVT_FB_PROJECT_LOADED );
2749 NotifyEvent( event );
2750 }
2751
NotifyProjectSaved()2752 void ApplicationData::NotifyProjectSaved()
2753 {
2754 wxFBEvent event( wxEVT_FB_PROJECT_SAVED );
2755 NotifyEvent( event );
2756 }
2757
NotifyObjectExpanded(PObjectBase obj)2758 void ApplicationData::NotifyObjectExpanded( PObjectBase obj )
2759 {
2760 wxFBObjectEvent event( wxEVT_FB_OBJECT_EXPANDED, obj );
2761 NotifyEvent( event );
2762 }
2763
NotifyObjectSelected(PObjectBase obj,bool force)2764 void ApplicationData::NotifyObjectSelected( PObjectBase obj, bool force )
2765 {
2766 wxFBObjectEvent event( wxEVT_FB_OBJECT_SELECTED, obj );
2767 if( force ) event.SetString( wxT("force") );
2768
2769 NotifyEvent( event );
2770 }
2771
NotifyObjectCreated(PObjectBase obj)2772 void ApplicationData::NotifyObjectCreated( PObjectBase obj )
2773 {
2774 wxFBObjectEvent event( wxEVT_FB_OBJECT_CREATED, obj );
2775 NotifyEvent( event );
2776 }
2777
NotifyObjectRemoved(PObjectBase obj)2778 void ApplicationData::NotifyObjectRemoved( PObjectBase obj )
2779 {
2780 wxFBObjectEvent event( wxEVT_FB_OBJECT_REMOVED, obj );
2781 NotifyEvent( event );
2782 }
2783
NotifyPropertyModified(PProperty prop)2784 void ApplicationData::NotifyPropertyModified( PProperty prop )
2785 {
2786 wxFBPropertyEvent event( wxEVT_FB_PROPERTY_MODIFIED, prop );
2787 NotifyEvent( event );
2788 }
2789
NotifyEventHandlerModified(PEvent evtHandler)2790 void ApplicationData::NotifyEventHandlerModified( PEvent evtHandler )
2791 {
2792 wxFBEventHandlerEvent event( wxEVT_FB_EVENT_HANDLER_MODIFIED, evtHandler );
2793 NotifyEvent( event );
2794 }
2795
NotifyCodeGeneration(bool panelOnly,bool forcedelayed)2796 void ApplicationData::NotifyCodeGeneration( bool panelOnly, bool forcedelayed )
2797 {
2798 wxFBEvent event( wxEVT_FB_CODE_GENERATION );
2799
2800 // Using the previously unused Id field in the event to carry a boolean
2801 event.SetId( ( panelOnly ? 1 : 0 ) );
2802
2803 NotifyEvent( event, forcedelayed );
2804 }
2805
NotifyProjectRefresh()2806 void ApplicationData::NotifyProjectRefresh()
2807 {
2808 wxFBEvent event( wxEVT_FB_PROJECT_REFRESH );
2809 NotifyEvent( event );
2810 }
2811
VerifySingleInstance(const wxString & file,bool switchTo)2812 bool ApplicationData::VerifySingleInstance( const wxString& file, bool switchTo )
2813 {
2814 return m_ipc->VerifySingleInstance( file, switchTo );
2815 }
2816
GetPathProperty(const wxString & pathName)2817 wxString ApplicationData::GetPathProperty( const wxString& pathName )
2818 {
2819 PObjectBase project = GetProjectData();
2820 wxFileName path;
2821 // Get the output path
2822 PProperty ppath = project->GetProperty( pathName );
2823
2824 if ( ppath )
2825 {
2826 wxString pathEntry = ppath->GetValue();
2827
2828 if ( pathEntry.empty() )
2829 {
2830 THROW_WXFBEX( wxT( "You must set the \"") + pathName + wxT("\" property of the project to a valid path for output files" ) );
2831 }
2832
2833 path = wxFileName::DirName( pathEntry );
2834
2835 if ( !path.IsAbsolute() )
2836 {
2837 wxString projectPath = AppData()->GetProjectPath();
2838
2839 if ( projectPath.empty() )
2840 {
2841 THROW_WXFBEX( wxT( "You must save the project when using a relative path for output files" ) );
2842 }
2843
2844 path = wxFileName( projectPath +
2845 wxFileName::GetPathSeparator() +
2846 pathEntry +
2847 wxFileName::GetPathSeparator() );
2848
2849 path.Normalize();
2850
2851 // this approach is probably incorrect if the fb project is located under a symlink
2852 /*path.SetCwd( projectPath );
2853 path.MakeAbsolute();*/
2854 }
2855 }
2856
2857 if ( !path.DirExists() )
2858 {
2859 THROW_WXFBEX( wxT( "Invalid Path: " ) << path.GetPath() << wxT( "\nYou must set the \"") + pathName + wxT("\" property of the project to a valid path for output files" ) );
2860 }
2861
2862 return path.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR );
2863 }
2864
GetOutputPath()2865 wxString ApplicationData::GetOutputPath()
2866 {
2867 return GetPathProperty( wxT("path") );
2868 }
2869
GetEmbeddedFilesOutputPath()2870 wxString ApplicationData::GetEmbeddedFilesOutputPath()
2871 {
2872 return GetPathProperty( wxT("embedded_files_path") );
2873 }
2874
GetPropertiesToRemove_v1_12(void) const2875 ApplicationData::PropertiesToRemove& ApplicationData::GetPropertiesToRemove_v1_12( void ) const
2876 {
2877 static PropertiesToRemove propertiesToRemove;
2878 if( propertiesToRemove.empty() )
2879 {
2880 propertiesToRemove[ "Dialog" ].insert( "BottomDockable" );
2881 propertiesToRemove[ "Dialog" ].insert( "LeftDockable" );
2882 propertiesToRemove[ "Dialog" ].insert( "RightDockable" );
2883 propertiesToRemove[ "Dialog" ].insert( "TopDockable" );
2884 propertiesToRemove[ "Dialog" ].insert( "caption_visible" );
2885 propertiesToRemove[ "Dialog" ].insert( "center_pane" );
2886 propertiesToRemove[ "Dialog" ].insert( "close_button" );
2887 propertiesToRemove[ "Dialog" ].insert( "default_pane" );
2888 propertiesToRemove[ "Dialog" ].insert( "dock" );
2889 propertiesToRemove[ "Dialog" ].insert( "dock_fixed" );
2890 propertiesToRemove[ "Dialog" ].insert( "docking" );
2891 propertiesToRemove[ "Dialog" ].insert( "floatable" );
2892 propertiesToRemove[ "Dialog" ].insert( "gripper" );
2893 propertiesToRemove[ "Dialog" ].insert( "maximize_button" );
2894 propertiesToRemove[ "Dialog" ].insert( "minimize_button" );
2895 propertiesToRemove[ "Dialog" ].insert( "moveable" );
2896 propertiesToRemove[ "Dialog" ].insert( "pane_border" );
2897 propertiesToRemove[ "Dialog" ].insert( "pin_button" );
2898 propertiesToRemove[ "Dialog" ].insert( "resize" );
2899 propertiesToRemove[ "Dialog" ].insert( "show" );
2900 propertiesToRemove[ "Dialog" ].insert( "toolbar_pane" );
2901 propertiesToRemove[ "Dialog" ].insert( "validator_style" );
2902 propertiesToRemove[ "Dialog" ].insert( "validator_type" );
2903 propertiesToRemove[ "Dialog" ].insert( "aui_name" );
2904
2905 propertiesToRemove[ "Panel" ].insert( "BottomDockable" );
2906 propertiesToRemove[ "Panel" ].insert( "LeftDockable" );
2907 propertiesToRemove[ "Panel" ].insert( "RightDockable" );
2908 propertiesToRemove[ "Panel" ].insert( "TopDockable" );
2909 propertiesToRemove[ "Panel" ].insert( "caption_visible" );
2910 propertiesToRemove[ "Panel" ].insert( "center_pane" );
2911 propertiesToRemove[ "Panel" ].insert( "close_button" );
2912 propertiesToRemove[ "Panel" ].insert( "default_pane" );
2913 propertiesToRemove[ "Panel" ].insert( "dock" );
2914 propertiesToRemove[ "Panel" ].insert( "dock_fixed" );
2915 propertiesToRemove[ "Panel" ].insert( "docking" );
2916 propertiesToRemove[ "Panel" ].insert( "floatable" );
2917 propertiesToRemove[ "Panel" ].insert( "gripper" );
2918 propertiesToRemove[ "Panel" ].insert( "maximize_button" );
2919 propertiesToRemove[ "Panel" ].insert( "minimize_button" );
2920 propertiesToRemove[ "Panel" ].insert( "moveable" );
2921 propertiesToRemove[ "Panel" ].insert( "pane_border" );
2922 propertiesToRemove[ "Panel" ].insert( "pin_button" );
2923 propertiesToRemove[ "Panel" ].insert( "resize" );
2924 propertiesToRemove[ "Panel" ].insert( "show" );
2925 propertiesToRemove[ "Panel" ].insert( "toolbar_pane" );
2926 propertiesToRemove[ "Panel" ].insert( "validator_style" );
2927 propertiesToRemove[ "Panel" ].insert( "validator_type" );
2928
2929 propertiesToRemove[ "wxStaticText" ].insert( "validator_style" );
2930 propertiesToRemove[ "wxStaticText" ].insert( "validator_type" );
2931 propertiesToRemove[ "CustomControl" ].insert( "validator_style" );
2932 propertiesToRemove[ "CustomControl" ].insert( "validator_type" );
2933 propertiesToRemove[ "wxAuiNotebook" ].insert( "validator_style" );
2934 propertiesToRemove[ "wxAuiNotebook" ].insert( "validator_type" );
2935 propertiesToRemove[ "wxPanel" ].insert( "validator_style" );
2936 propertiesToRemove[ "wxPanel" ].insert( "validator_type" );
2937 propertiesToRemove[ "wxToolBar" ].insert( "validator_style" );
2938 propertiesToRemove[ "wxToolBar" ].insert( "validator_type" );
2939 propertiesToRemove[ "wxStyledTextCtrl" ].insert( "use_wxAddition" );
2940 propertiesToRemove[ "wxStyledTextCtrl" ].insert( "validator_style" );
2941 propertiesToRemove[ "wxStyledTextCtrl" ].insert( "validator_type" );
2942 propertiesToRemove[ "wxPropertyGridManager" ].insert( "use_wxAddition" );
2943 propertiesToRemove[ "wxPropertyGridManager" ].insert( "validator_style" );
2944 propertiesToRemove[ "wxPropertyGridManager" ].insert( "validator_type" );
2945
2946 propertiesToRemove[ "wxadditions::wxTreeListCtrl" ].insert( "validator_style" );
2947 propertiesToRemove[ "wxadditions::wxTreeListCtrl" ].insert( "validator_type" );
2948 }
2949 return propertiesToRemove;
2950 }
2951