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 "objecttree.h"
27 #include "rad/bitmaps.h"
28 #include "utils/debug.h"
29 #include <wx/imaglist.h>
30 #include <wx/image.h>
31 #include "rad/menueditor.h"
32 #include "utils/typeconv.h"
33 #include "rad/wxfbevent.h"
34 #include <rad/appdata.h>
35 #include "model/objectbase.h"
36 #include <wx/utils.h>
37 
BEGIN_EVENT_TABLE(ObjectTree,wxPanel)38 BEGIN_EVENT_TABLE( ObjectTree, wxPanel )
39 	EVT_TREE_SEL_CHANGED( -1, ObjectTree::OnSelChanged )
40 	EVT_TREE_ITEM_RIGHT_CLICK( -1, ObjectTree::OnRightClick )
41 	EVT_TREE_BEGIN_DRAG( -1, ObjectTree::OnBeginDrag )
42 	EVT_TREE_END_DRAG( -1, ObjectTree::OnEndDrag )
43 	EVT_TREE_KEY_DOWN(-1, ObjectTree::OnKeyDown )
44 
45 	EVT_FB_PROJECT_LOADED( ObjectTree::OnProjectLoaded )
46 	EVT_FB_PROJECT_SAVED( ObjectTree::OnProjectSaved )
47 	EVT_FB_OBJECT_CREATED( ObjectTree::OnObjectCreated )
48 	EVT_FB_OBJECT_REMOVED( ObjectTree::OnObjectRemoved )
49 	EVT_FB_PROPERTY_MODIFIED( ObjectTree::OnPropertyModified )
50 	EVT_FB_PROJECT_REFRESH( ObjectTree::OnProjectRefresh )
51 
52 END_EVENT_TABLE()
53 
54 ObjectTree::ObjectTree( wxWindow *parent, int id )
55 :
56 wxPanel( parent, id )
57 {
58 	AppData()->AddHandler( this->GetEventHandler() );
59 	m_tcObjects = new wxTreeCtrl(this, -1, wxDefaultPosition, wxDefaultSize, wxTR_HAS_BUTTONS|wxTR_LINES_AT_ROOT|wxTR_DEFAULT_STYLE|wxSIMPLE_BORDER);
60 
61 	wxBoxSizer* sizer_1 = new wxBoxSizer(wxVERTICAL);
62     sizer_1->Add(m_tcObjects, 1, wxEXPAND, 0);
63     SetAutoLayout(true);
64     SetSizer(sizer_1);
65     sizer_1->Fit(this);
66     sizer_1->SetSizeHints(this);
67     Connect( wxID_ANY, wxEVT_FB_OBJECT_EXPANDED, wxFBObjectEventHandler( ObjectTree::OnObjectExpanded ) );
68     Connect( wxID_ANY, wxEVT_FB_OBJECT_SELECTED, wxFBObjectEventHandler( ObjectTree::OnObjectSelected ) );
69     Connect( wxID_ANY, wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxTreeEventHandler( ObjectTree::OnExpansionChange ) );
70     Connect( wxID_ANY, wxEVT_COMMAND_TREE_ITEM_COLLAPSED, wxTreeEventHandler( ObjectTree::OnExpansionChange ) );
71 
72     m_altKeyIsDown = false;
73 }
74 
OnKeyDown(wxTreeEvent & event)75 void ObjectTree::OnKeyDown(wxTreeEvent &event )
76 {
77 	if( event.GetKeyEvent().AltDown() && event.GetKeyCode() != WXK_ALT)
78 	{
79 #ifdef __WXGTK__
80 		switch (event.GetKeyCode())
81 		{
82 			case WXK_UP:
83 				AppData()->MovePosition(GetObjectFromTreeItem(m_tcObjects->GetSelection()),false);
84 				return;
85 			case WXK_DOWN:
86 				AppData()->MovePosition(GetObjectFromTreeItem(m_tcObjects->GetSelection()),true);
87 				return;
88 			case WXK_RIGHT:
89 				AppData()->MoveHierarchy(GetObjectFromTreeItem(m_tcObjects->GetSelection()),false);
90 				return;
91 			case WXK_LEFT:
92 				AppData()->MoveHierarchy(GetObjectFromTreeItem(m_tcObjects->GetSelection()),true);
93 				return;
94 		}
95 #endif
96 		event.Skip();
97 	}
98 	else
99 	{
100 		event.Skip();
101 	}
102 }
103 
104 
~ObjectTree()105 ObjectTree::~ObjectTree()
106 {
107 	AppData()->RemoveHandler( this->GetEventHandler() );
108 }
109 
GetObjectFromTreeItem(wxTreeItemId item)110 PObjectBase ObjectTree::GetObjectFromTreeItem( wxTreeItemId item )
111 {
112 	if ( item.IsOk() )
113 	{
114 		wxTreeItemData* item_data = m_tcObjects->GetItemData( item );
115 		if ( item_data )
116 		{
117 			PObjectBase obj( ((ObjectTreeItemData* )item_data)->GetObject() );
118 			return obj;
119 		}
120 	}
121 	return PObjectBase( (ObjectBase*)NULL );
122 }
123 
RebuildTree()124 void ObjectTree::RebuildTree()
125 {
126 	m_tcObjects->Freeze();
127 
128 	Disconnect( wxID_ANY, wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxTreeEventHandler( ObjectTree::OnExpansionChange ) );
129 	Disconnect( wxID_ANY, wxEVT_COMMAND_TREE_ITEM_COLLAPSED, wxTreeEventHandler( ObjectTree::OnExpansionChange ) );
130 
131 	PObjectBase project = AppData()->GetProjectData();
132 
133 	// Clear the old tree and map
134 	m_tcObjects->DeleteAllItems();
135 	m_map.clear();
136 
137 	if (project)
138 	{
139 		wxTreeItemId dummy;
140 		AddChildren(project, dummy, true );
141 
142 		// Expand items that were previously expanded
143 		RestoreItemStatus(project);
144 	}
145 
146 	Connect( wxID_ANY, wxEVT_COMMAND_TREE_ITEM_COLLAPSED, wxTreeEventHandler( ObjectTree::OnExpansionChange ) );
147 	Connect( wxID_ANY, wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxTreeEventHandler( ObjectTree::OnExpansionChange ) );
148 
149 	m_tcObjects->Thaw();
150 }
151 
OnSelChanged(wxTreeEvent & event)152 void ObjectTree::OnSelChanged(wxTreeEvent &event)
153 {
154 	wxTreeItemId id = event.GetItem();
155 	if (!id.IsOk()) return;
156 
157 	// Make selected items bold
158 	wxTreeItemId oldId = event.GetOldItem();
159 	if ( oldId.IsOk() )
160 	{
161 		m_tcObjects->SetItemBold( oldId, false );
162 	}
163 	m_tcObjects->SetItemBold( id );
164 
165 	wxTreeItemData *item_data = m_tcObjects->GetItemData(id);
166 
167 	if (item_data)
168 	{
169 		PObjectBase obj(((ObjectTreeItemData *)item_data)->GetObject());
170 		assert(obj);
171 		Disconnect( wxID_ANY, wxEVT_FB_OBJECT_SELECTED, wxFBObjectEventHandler( ObjectTree::OnObjectSelected ) );
172 		AppData()->SelectObject(obj);
173 		Connect( wxID_ANY, wxEVT_FB_OBJECT_SELECTED, wxFBObjectEventHandler( ObjectTree::OnObjectSelected ) );
174 	}
175 }
176 
OnRightClick(wxTreeEvent & event)177 void ObjectTree::OnRightClick(wxTreeEvent &event)
178 {
179 	wxTreeItemId id = event.GetItem();
180 	wxTreeItemData *item_data = m_tcObjects->GetItemData(id);
181 	if (item_data)
182 	{
183 		PObjectBase obj(((ObjectTreeItemData *)item_data)->GetObject());
184 		assert(obj);
185 		wxMenu * menu = new ItemPopupMenu(obj);
186 		wxPoint pos = event.GetPoint();
187 		menu->UpdateUI(menu);
188 		PopupMenu(menu,pos.x, pos.y);
189 	}
190 }
191 
OnBeginDrag(wxTreeEvent & event)192 void ObjectTree::OnBeginDrag(wxTreeEvent &event)
193 {
194 	// need to explicitly allow drag
195     if ( event.GetItem() == m_tcObjects->GetRootItem() )
196     {
197     	return;
198     }
199 
200 	m_draggedItem = event.GetItem();
201 	event.Allow();
202 }
203 
OnEndDrag(wxTreeEvent & event)204 void ObjectTree::OnEndDrag(wxTreeEvent& event)
205 {
206 	bool copy = ::wxGetKeyState( WXK_CONTROL );
207 
208     wxTreeItemId itemSrc = m_draggedItem,
209                  itemDst = event.GetItem();
210     m_draggedItem = (wxTreeItemId)0l;
211 
212 	// ensure that itemDst is not itemSrc or a child of itemSrc
213 	wxTreeItemId item = itemDst;
214 	while ( item.IsOk() )
215 	{
216 		if ( item == itemSrc )
217 		{
218 			return;
219 		}
220 		item = m_tcObjects->GetItemParent( item );
221 	}
222 
223 	PObjectBase objSrc = GetObjectFromTreeItem( itemSrc );
224 	if ( !objSrc )
225 	{
226 		return;
227 	}
228 
229 	PObjectBase objDst = GetObjectFromTreeItem( itemDst );
230 	if ( !objDst )
231 	{
232 		return;
233 	}
234 
235 	// backup clipboard
236 	PObjectBase clipboard = AppData()->GetClipboardObject();
237 
238 	// set object to clipboard
239 	if ( copy )
240 	{
241 		AppData()->CopyObject( objSrc );
242 	}
243 	else
244 	{
245 		AppData()->CutObject( objSrc );
246 	}
247 
248 	if ( !AppData()->PasteObject( objDst ) && !copy )
249 	{
250 		AppData()->Undo();
251 	}
252 
253 	AppData()->SetClipboardObject( clipboard );
254 }
255 
OnExpansionChange(wxTreeEvent & event)256 void ObjectTree::OnExpansionChange(wxTreeEvent &event)
257 {
258 	wxTreeItemId id = event.GetItem();
259 	wxTreeItemData *item_data = m_tcObjects->GetItemData(id);
260 	if (item_data)
261 	{
262 		PObjectBase obj(((ObjectTreeItemData *)item_data)->GetObject());
263 		assert(obj);
264 
265 		Disconnect( wxID_ANY, wxEVT_FB_OBJECT_EXPANDED, wxFBObjectEventHandler( ObjectTree::OnObjectExpanded ) );
266 		Disconnect( wxID_ANY, wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxTreeEventHandler( ObjectTree::OnExpansionChange ) );
267 
268 		AppData()->ExpandObject( obj, m_tcObjects->IsExpanded( id ) );
269 
270 		Connect( wxID_ANY, wxEVT_FB_OBJECT_EXPANDED, wxFBObjectEventHandler( ObjectTree::OnObjectExpanded ) );
271 		Connect( wxID_ANY, wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxTreeEventHandler( ObjectTree::OnExpansionChange ) );
272 	}
273 }
274 
AddChildren(PObjectBase obj,wxTreeItemId & parent,bool is_root)275 void ObjectTree::AddChildren(PObjectBase obj, wxTreeItemId &parent, bool is_root)
276 {
277 	if (obj->GetObjectInfo()->GetObjectType()->IsItem())
278 	{
279 		if (obj->GetChildCount() > 0)
280 			AddChildren(obj->GetChild(0),parent);
281 		else
282 		{
283 			// Si hemos llegado aquí ha sido porque el arbol no está bien formado
284 			// y habrá que revisar cómo se ha creado.
285 			wxString msg;
286 			PObjectBase itemParent = obj->GetParent();
287 			assert(parent);
288 
289 			msg = wxString::Format(wxT("Item without object as child of \'%s:%s\'"),
290 				itemParent->GetPropertyAsString(wxT("name")).c_str(),
291 				itemParent->GetClassName().c_str());
292 
293 			wxLogError(msg);
294 		}
295 	}
296 	else
297 	{
298 		wxTreeItemId new_parent;
299 
300 		ObjectTreeItemData *item_data = new ObjectTreeItemData(obj);
301 
302 		if (is_root)
303 			new_parent = m_tcObjects->AddRoot(wxT(""),-1,-1,item_data);
304 		else
305 		{
306 			unsigned int pos = 0;
307 
308 			PObjectBase parent_obj = obj->GetParent();
309 			// find a proper position where the added object should be displayed at
310 			if( parent_obj->GetObjectInfo()->GetObjectType()->IsItem() )
311 			{
312 				parent_obj = parent_obj->GetParent();
313 				pos = parent_obj->GetChildPosition( obj->GetParent() );
314 			}
315 			else
316 				pos = parent_obj->GetChildPosition( obj );
317 
318 			// insert tree item to proper position
319 			if( pos > 0 )
320 				new_parent = m_tcObjects->InsertItem(parent, pos, wxT(""), -1, -1, item_data);
321 			else
322 				new_parent = m_tcObjects->AppendItem(parent,wxT(""),-1,-1,item_data);
323 		}
324 
325 		// Add the item to the map
326 		m_map.insert( ObjectItemMap::value_type( obj, new_parent ) );
327 
328 		// Set the image
329 		int image_idx = GetImageIndex( obj->GetObjectInfo()->GetClassName() );
330 
331 		m_tcObjects->SetItemImage(new_parent,image_idx);
332 
333 		// Set the name
334 		UpdateItem( new_parent, obj );
335 
336 		// Add the rest of the children
337 		unsigned int count = obj->GetChildCount();
338 		unsigned int i;
339 		for (i = 0; i < count ; i++)
340 		{
341 			PObjectBase child = obj->GetChild(i);
342 			AddChildren(child, new_parent);
343 		}
344 	}
345 }
346 
347 
GetImageIndex(wxString name)348 int ObjectTree::GetImageIndex (wxString name)
349 {
350 	int index = 0; //default icon
351 
352 	IconIndexMap::iterator it = m_iconIdx.find(name);
353 	if (it != m_iconIdx.end())
354 		index = it->second;
355 
356 	return index;
357 }
358 
UpdateItem(wxTreeItemId id,PObjectBase obj)359 void ObjectTree::UpdateItem(wxTreeItemId id, PObjectBase obj)
360 {
361 	// mostramos el nombre
362 	wxString class_name( obj->GetClassName() );
363 	PProperty prop = obj->GetProperty( wxT("name") );
364 	wxString obj_name;
365 	if (prop)
366 	{
367 		obj_name =prop->GetValue();
368 	}
369 
370 	wxString text = obj_name + wxT(" : ") + class_name;
371 
372 	// actualizamos el item
373 	m_tcObjects->SetItemText(id,text);
374 }
375 
Create()376 void ObjectTree::Create()
377 {
378 	// Cramos la lista de iconos obteniendo los iconos de los paquetes.
379 	unsigned int index = 0;
380 	m_iconList = new wxImageList(ICON_SIZE,ICON_SIZE);
381 
382 	{
383 		wxBitmap icon = AppBitmaps::GetBitmap(wxT("project"), ICON_SIZE);
384 		m_iconList->Add(icon);
385 		m_iconIdx.insert(IconIndexMap::value_type( wxT("_default_"),index++));
386 	}
387 
388 	unsigned int pkg_count = AppData()->GetPackageCount();
389 	for (unsigned int i = 0; i< pkg_count;i++)
390 	{
391 		PObjectPackage pkg = AppData()->GetPackage(i);
392 
393 		unsigned int j;
394 		for (j=0;j<pkg->GetObjectCount();j++)
395 		{
396 			wxString comp_name(pkg->GetObjectInfo(j)->GetClassName());
397 			m_iconList->Add( pkg->GetObjectInfo(j)->GetIconFile() );
398 			m_iconIdx.insert(IconIndexMap::value_type(comp_name,index++));
399 		}
400 	}
401 
402 	m_tcObjects->AssignImageList(m_iconList);
403 }
404 
RestoreItemStatus(PObjectBase obj)405 void ObjectTree::RestoreItemStatus(PObjectBase obj)
406 {
407 	ObjectItemMap::iterator item_it = m_map.find(obj);
408 	if (item_it != m_map.end())
409 	{
410 		wxTreeItemId id = item_it->second;
411 
412 		if ( obj->GetExpanded() )
413 			m_tcObjects->Expand(id);
414 		/*else
415 			m_tcObjects->Collapse(id);*/
416 	}
417 
418 	unsigned int i,count = obj->GetChildCount();
419 	for (i = 0; i<count ; i++)
420 		RestoreItemStatus(obj->GetChild(i));
421 }
422 
AddItem(PObjectBase item,PObjectBase parent)423 void ObjectTree::AddItem(PObjectBase item, PObjectBase parent)
424 {
425 	if( item && parent )
426 	{
427 		// find parent item displayed in the object tree
428 		while( parent && parent->GetObjectInfo()->GetObjectType()->IsItem() ) parent = parent->GetParent();
429 
430 		// add new item to the object tree
431 		ObjectItemMap::iterator it = m_map.find( parent );
432 		if( (it != m_map.end()) && it->second.IsOk() )
433 		{
434 			AddChildren( item, it->second, false );
435 		}
436 	}
437 }
438 
RemoveItem(PObjectBase item)439 void ObjectTree::RemoveItem(PObjectBase item)
440 {
441 	// remove affected object tree items only
442 	ObjectItemMap::iterator it = m_map.find( item );
443 	if( (it != m_map.end()) && it->second.IsOk() )
444 	{
445 		m_tcObjects->Delete( it->second );
446 		// clear map records for all item's children
447 		ClearMap( it->first );
448 	}
449 }
450 
ClearMap(PObjectBase obj)451 void ObjectTree::ClearMap(PObjectBase obj)
452 {
453 	m_map.erase( obj );
454 
455 	for ( unsigned int i = 0; i < obj->GetChildCount(); i++ )
456 	{
457 		ClearMap( obj->GetChild( i ) );
458 	}
459 }
460 
461 /////////////////////////////////////////////////////////////////////////////
462 // wxFormBuilder Event Handlers
463 /////////////////////////////////////////////////////////////////////////////
OnProjectLoaded(wxFBEvent &)464 void ObjectTree::OnProjectLoaded( wxFBEvent &)
465 {
466 	RebuildTree();
467 }
468 
OnProjectSaved(wxFBEvent &)469 void ObjectTree::OnProjectSaved( wxFBEvent &)
470 {
471 }
472 
OnObjectExpanded(wxFBObjectEvent & event)473 void ObjectTree::OnObjectExpanded( wxFBObjectEvent& event )
474 {
475 	PObjectBase obj = event.GetFBObject();
476 	ObjectItemMap::iterator it = m_map.find( obj );
477 	if ( it != m_map.end() )
478 	{
479 		if ( m_tcObjects->IsExpanded( it->second ) != obj->GetExpanded() )
480 		{
481 			if ( obj->GetExpanded() )
482 			{
483 				m_tcObjects->Expand( it->second );
484 			}
485 			else
486 			{
487 				m_tcObjects->Collapse( it->second );
488 			}
489 		}
490 	}
491 }
492 
OnObjectSelected(wxFBObjectEvent & event)493 void ObjectTree::OnObjectSelected( wxFBObjectEvent &event )
494 {
495     PObjectBase obj = event.GetFBObject();
496 
497 	// Find the tree item associated with the object and select it
498 	ObjectItemMap::iterator it = m_map.find(obj);
499 	if ( it != m_map.end() )
500 	{
501 		// Ignore expand/collapse events
502 		Disconnect( wxID_ANY, wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxTreeEventHandler( ObjectTree::OnExpansionChange ) );
503 		Disconnect( wxID_ANY, wxEVT_COMMAND_TREE_ITEM_COLLAPSED, wxTreeEventHandler( ObjectTree::OnExpansionChange ) );
504 
505 		m_tcObjects->EnsureVisible( it->second );
506 		m_tcObjects->SelectItem( it->second );
507 
508 		// Restore event handling
509 		Connect( wxID_ANY, wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxTreeEventHandler( ObjectTree::OnExpansionChange ) );
510 		Connect( wxID_ANY, wxEVT_COMMAND_TREE_ITEM_COLLAPSED, wxTreeEventHandler( ObjectTree::OnExpansionChange ) );
511 	}
512 	else
513 	{
514 		wxLogError( wxT("There is no tree item associated with this object.\n\tClass: %s\n\tName: %s"), obj->GetClassName().c_str(), obj->GetPropertyAsString(wxT("name")).c_str() );
515 	}
516 }
517 
OnObjectCreated(wxFBObjectEvent & event)518 void ObjectTree::OnObjectCreated ( wxFBObjectEvent &event )
519 {
520 	//RebuildTree();
521 
522 	if( event.GetFBObject() ) AddItem( event.GetFBObject(), event.GetFBObject()->GetParent() );
523 }
524 
OnObjectRemoved(wxFBObjectEvent & event)525 void ObjectTree::OnObjectRemoved ( wxFBObjectEvent &event )
526 {
527 	//RebuildTree();
528 
529 	RemoveItem( event.GetFBObject() );
530 }
531 
OnPropertyModified(wxFBPropertyEvent & event)532 void ObjectTree::OnPropertyModified ( wxFBPropertyEvent &event )
533 {
534   PProperty prop = event.GetFBProperty();
535 
536 	if (prop->GetName() == wxT("name") )
537 	{
538 		ObjectItemMap::iterator it = m_map.find(prop->GetObject());
539 		if (it != m_map.end())
540 		{
541 			UpdateItem(it->second,it->first);
542 		}
543 	}
544 }
545 
OnProjectRefresh(wxFBEvent &)546 void ObjectTree::OnProjectRefresh ( wxFBEvent &)
547 {
548 	RebuildTree();
549 }
550 
551 ///////////////////////////////////////////////////////////////////////////////
552 
ObjectTreeItemData(PObjectBase obj)553 ObjectTreeItemData::ObjectTreeItemData(PObjectBase obj) : m_object(obj)
554 {}
555 
556 ///////////////////////////////////////////////////////////////////////////////
557 
558 #define MENU_MOVE_UP    100
559 #define MENU_MOVE_DOWN  101
560 #define MENU_MOVE_RIGHT 102
561 #define MENU_MOVE_LEFT  103
562 #define MENU_CUT        104
563 #define MENU_PASTE      105
564 #define MENU_EDIT_MENUS 106
565 #define MENU_COPY       107
566 #define MENU_MOVE_NEW_BOXSIZER   108
567 #define MENU_DELETE 109
568 
569 
BEGIN_EVENT_TABLE(ItemPopupMenu,wxMenu)570 BEGIN_EVENT_TABLE(ItemPopupMenu,wxMenu)
571 	EVT_MENU(-1, ItemPopupMenu::OnMenuEvent)
572 	EVT_UPDATE_UI(-1, ItemPopupMenu::OnUpdateEvent)
573 END_EVENT_TABLE()
574 
575 ItemPopupMenu::ItemPopupMenu(PObjectBase obj)
576 : wxMenu(), m_object(obj)
577 {
578 	Append(MENU_CUT,        wxT("Cut\tCtrl+X"));
579 	Append(MENU_COPY,       wxT("Copy\tCtrl+C"));
580 	Append(MENU_PASTE,      wxT("Paste\tCtrl+V"));
581 	AppendSeparator();
582 	Append(MENU_DELETE,     wxT("Delete\tCtrl+D"));
583 	AppendSeparator();
584 	Append(MENU_MOVE_UP,    wxT("Move Up\tAlt+Up"));
585 	Append(MENU_MOVE_DOWN,  wxT("Move Down\tAlt+Down"));
586 	Append(MENU_MOVE_LEFT,  wxT("Move Left\tAlt+Left"));
587 	Append(MENU_MOVE_RIGHT, wxT("Move Right\tAlt+Right"));
588 	AppendSeparator();
589 	Append(MENU_MOVE_NEW_BOXSIZER, wxT("Move into a new wxBoxSizer"));
590 	AppendSeparator();
591 	Append(MENU_EDIT_MENUS, wxT("Menu Editor..."));
592 }
593 
OnMenuEvent(wxCommandEvent & event)594 void ItemPopupMenu::OnMenuEvent (wxCommandEvent & event)
595 {
596 	int id = event.GetId();
597 
598 	switch (id)
599 	{
600 	case MENU_CUT:
601 		AppData()->CutObject(m_object);
602 		break;
603 	case MENU_COPY:
604 		AppData()->CopyObject(m_object);
605 		break;
606 	case MENU_PASTE:
607 		AppData()->PasteObject(m_object);
608 		break;
609 	case MENU_DELETE:
610 		AppData()->RemoveObject(m_object);
611 		break;
612 	case MENU_MOVE_UP:
613 		AppData()->MovePosition(m_object,false);
614 		break;
615 	case MENU_MOVE_DOWN:
616 		AppData()->MovePosition(m_object,true);
617 		break;
618 	case MENU_MOVE_RIGHT:
619 		AppData()->MoveHierarchy(m_object,false);
620 		break;
621 	case MENU_MOVE_LEFT:
622 		AppData()->MoveHierarchy(m_object,true);
623 		break;
624 	case MENU_MOVE_NEW_BOXSIZER:
625 		AppData()->CreateBoxSizerWithObject(m_object);
626 		break;
627 	case MENU_EDIT_MENUS:
628 		{
629 			PObjectBase obj = m_object;
630 			if (obj && (obj->GetClassName() == wxT("wxMenuBar") || obj->GetClassName() == wxT("Frame") ) )
631 			{
632 				MenuEditor me(NULL);
633 				if (obj->GetClassName() == wxT("Frame") )
634 				{
635 					bool found = false;
636 					PObjectBase menubar;
637 					for (unsigned int i = 0; i < obj->GetChildCount() && !found; i++)
638 					{
639 						menubar = obj->GetChild(i);
640 						found = menubar->GetClassName() == wxT("wxMenuBar");
641 					}
642 					if (found) obj = menubar;
643 				}
644 
645 				if (obj->GetClassName() == wxT("wxMenuBar")) me.Populate(obj);
646 				if (me.ShowModal() == wxID_OK)
647 				{
648 					if (obj->GetClassName() == wxT("wxMenuBar"))
649 					{
650 						PObjectBase menubar = me.GetMenubar(AppData()->GetObjectDatabase());
651 						while (obj->GetChildCount() > 0)
652 						{
653 							PObjectBase child = obj->GetChild(0);
654 							obj->RemoveChild(0);
655 							child->SetParent(PObjectBase());
656 						}
657 						for (unsigned int i = 0; i < menubar->GetChildCount(); i++)
658 						{
659 							PObjectBase child = menubar->GetChild(i);
660 							AppData()->InsertObject(child,obj);
661 						}
662 					}
663 					else
664 						AppData()->InsertObject(me.GetMenubar(AppData()->GetObjectDatabase()),AppData()->GetSelectedForm());
665 				}
666 			}
667 		}
668 		break;
669 	default:
670 		break;
671 	}
672 }
673 
OnUpdateEvent(wxUpdateUIEvent & e)674 void ItemPopupMenu::OnUpdateEvent(wxUpdateUIEvent& e)
675 {
676 	switch (e.GetId())
677 	{
678 	case MENU_EDIT_MENUS:
679 		e.Enable(m_object && (m_object->GetClassName() == wxT("wxMenuBar" )
680 			|| m_object->GetClassName() == wxT("Frame")));
681 		break;
682 	case MENU_CUT:
683 	case MENU_COPY:
684 	case MENU_DELETE:
685 	case MENU_MOVE_UP:
686 	case MENU_MOVE_DOWN:
687 	case MENU_MOVE_LEFT:
688 	case MENU_MOVE_RIGHT:
689 	case MENU_MOVE_NEW_BOXSIZER:
690 		e.Enable(AppData()->CanCopyObject());
691 		break;
692 	case MENU_PASTE:
693 		e.Enable(AppData()->CanPasteObject());
694 		break;
695 	}
696 }
697 
698 
699