1 /*
2 * This file is part of wxSmith plugin for Code::Blocks Studio
3 * Copyright (C) 2006-2007  Bartlomiej Swiecki
4 *
5 * wxSmith is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * wxSmith is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with wxSmith. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * $Revision: 10771 $
19 * $Id: wxsitemeditor.cpp 10771 2016-02-06 14:29:31Z mortenmacfly $
20 * $HeadURL: svn://svn.code.sf.net/p/codeblocks/code/branches/release-20.xx/src/plugins/contrib/wxSmith/wxwidgets/wxsitemeditor.cpp $
21 */
22 
23 #include <wx/dcmemory.h>
24 #include "wxsitemeditor.h"
25 #include "wxsitemeditorcontent.h"
26 #include "wxsitemfactory.h"
27 #include "wxsitemresdata.h"
28 #include "wxstoolspace.h"
29 #include "wxsitem.h"
30 #include "wxstool.h"
31 #include "wxsparent.h"
32 #include "../wxsproject.h"
33 #include <logmanager.h>
34 
35 namespace
36 {
37     const long wxsInsPointId   = wxNewId();
38     const long wxsInsIntoId    = wxNewId();
39     const long wxsInsBeforeId  = wxNewId();
40     const long wxsInsAfterId   = wxNewId();
41     const long wxsDelId        = wxNewId();
42     const long wxsPreviewId    = wxNewId();
43     const long wxsQuickPropsId = wxNewId();
44 
ToolIconSize()45     inline int ToolIconSize() { return Manager::Get()->GetConfigManager(_T("wxsmith"))->ReadInt(_T("/tooliconsize"),32L); }
PalIconSize()46     inline int PalIconSize()  { return Manager::Get()->GetConfigManager(_T("wxsmith"))->ReadInt(_T("/paletteiconsize"),16L); }
47 }
48 
wxsItemEditor(wxWindow * parent,wxsItemRes * Resource)49 wxsItemEditor::wxsItemEditor(wxWindow* parent,wxsItemRes* Resource):
50     wxsEditor(parent,wxEmptyString,Resource),
51     m_Data(0),
52     m_Content(0),
53     m_WidgetsSet(0),
54     m_VertSizer(0),
55     m_HorizSizer(0),
56     m_QPSizer(0),
57     m_OpsSizer(0),
58     m_QPArea(0),
59     m_InsIntoBtn(0),
60     m_InsBeforeBtn(0),
61     m_InsAfterBtn(0),
62     m_DelBtn(0),
63     m_PreviewBtn(0),
64     m_QuickPanelBtn(0),
65     m_TopPreview(0),
66     m_PreviewBackground(0),
67     m_InsType(itPoint),
68     m_InsTypeMask(itPoint),
69     m_QuickPropsOpen(false),
70     m_PopupCaller(0)
71 {
72     InitializeResourceData();
73     InitializeVisualStuff();
74     m_AllEditors.insert(this);
75 }
76 
~wxsItemEditor()77 wxsItemEditor::~wxsItemEditor()
78 {
79     delete m_Data;
80     m_AllEditors.erase(this);
81 }
82 
InitializeResourceData()83 void wxsItemEditor::InitializeResourceData()
84 {
85     m_Data = GetItemRes()->BuildResData(this);
86 
87     if ( !m_Data->IsOk() )
88     {
89         // TODO: Some communicate (couldn't load resource) ?
90     }
91 
92     if ( GetItemRes()->GetEditMode() == wxsItemRes::File )
93     {
94         InitFilename(GetXrcFileName());
95         SetTitle(m_Shortname);
96     }
97     else
98     {
99         InitFilename(GetWxsFileName());
100         SetTitle(m_Shortname);
101     }
102 
103 }
104 
InitializeVisualStuff()105 void wxsItemEditor::InitializeVisualStuff()
106 {
107     // Loading images if needed
108     InitializeImages();
109 
110     // Creating content of editor window
111     m_VertSizer = new wxBoxSizer(wxVERTICAL);
112     m_WidgetsSet = new wxNotebook(this,-1);
113     BuildPalette(m_WidgetsSet);
114     m_ToolSpace = new wxsToolSpace(this,m_Data);
115     m_VertSizer->Add(m_ToolSpace,0,wxEXPAND);
116     m_HorizSizer = new wxBoxSizer(wxHORIZONTAL);
117     m_VertSizer->Add(m_HorizSizer,1,wxEXPAND);
118     m_VertSizer->Add(m_WidgetsSet,0,wxEXPAND);
119 
120     m_Content = new wxsItemEditorContent(this,m_Data,this);
121     m_HorizSizer->Add(m_Content,1,wxEXPAND);
122 
123     m_QPArea = new wxScrolledWindow(this,-1,wxDefaultPosition,wxDefaultSize,wxVSCROLL|wxHSCROLL|wxSUNKEN_BORDER/*|wxALWAYS_SHOW_SB*/);
124     m_QPArea->SetScrollbars(0,5,0,0);
125     m_HorizSizer->Add(m_QPArea,0,wxEXPAND);
126     m_QPSizer = new wxBoxSizer(wxVERTICAL);
127     m_QPArea->SetSizer(m_QPSizer);
128 
129     m_OpsSizer = new wxBoxSizer(wxVERTICAL);
130     m_HorizSizer->Add(m_OpsSizer,0,wxEXPAND);
131 
132     m_OpsSizer->Add(m_InsPointBtn  = new wxBitmapButton(this,wxsInsPointId,m_InsPointImg));
133     m_OpsSizer->Add(m_InsIntoBtn   = new wxBitmapButton(this,wxsInsIntoId,m_InsIntoImg));
134     m_OpsSizer->Add(m_InsBeforeBtn = new wxBitmapButton(this,wxsInsBeforeId,m_InsBeforeImg));
135     m_OpsSizer->Add(m_InsAfterBtn  = new wxBitmapButton(this,wxsInsAfterId,m_InsAfterImg));
136     m_OpsSizer->Add(1,5);
137     m_OpsSizer->Add(m_DelBtn       = new wxBitmapButton(this,wxsDelId,m_DelImg));
138     m_OpsSizer->Add(m_PreviewBtn   = new wxBitmapButton(this,wxsPreviewId,m_PreviewImg));
139     m_OpsSizer->Add(1,5);
140     m_OpsSizer->Add(m_QuickPanelBtn = new wxBitmapButton(this,wxsQuickPropsId,m_QuickPropsImgOpen));
141     m_InsPointBtn  ->SetToolTip(_("Insert new widgets by pointing with mouse"));
142     m_InsIntoBtn   ->SetToolTip(_("Insert new widgets into current selection"));
143     m_InsBeforeBtn ->SetToolTip(_("Insert new widgets before current selection"));
144     m_InsAfterBtn  ->SetToolTip(_("Insert new widgets after current selection"));
145     m_DelBtn       ->SetToolTip(_("Delete current selection"));
146     m_PreviewBtn   ->SetToolTip(_("Show preview"));
147     m_QuickPanelBtn->SetToolTip(_("Open / Close Quick Properties panel"));
148     SetSizer(m_VertSizer);
149 
150     SetInsertionTypeMask(0);
151     ToggleQuickPropsPanel(false);       // TODO: Shouldn't store initial state of panel somewhere?
152 
153     RebuildPreview();
154     UpdateSelection();
155 }
156 
ConfigChanged()157 void wxsItemEditor::ConfigChanged()
158 {
159     ReloadImages();
160     RefreshContents();
161 }
162 
ReloadImages()163 void wxsItemEditor::ReloadImages()
164 {
165     m_ImagesLoaded = false;
166     InitializeImages();
167     for ( WindowSet::iterator i=m_AllEditors.begin(); i!=m_AllEditors.end(); ++i )
168     {
169         (*i)->RebuildIcons();
170     }
171 }
172 
RefreshContents()173 void wxsItemEditor::RefreshContents()
174 {
175     for ( WindowSet::iterator i=m_AllEditors.begin(); i!=m_AllEditors.end(); ++i )
176     {
177         (*i)->RebuildPreview();
178     }
179 }
180 
RebuildPreview()181 void wxsItemEditor::RebuildPreview()
182 {
183     // Checking if we've already initialized visual stuff
184     if ( !m_Content ) return;
185 
186     m_Content->BeforePreviewChanged();
187     m_ToolSpace->BeforePreviewChanged();
188 
189     Freeze();
190 
191     // If there's previous preview, deleting it
192     if ( m_PreviewBackground )
193     {
194         m_Content->SetSizer(0);
195         m_PreviewBackground->Destroy();
196         m_PreviewBackground = 0;
197         m_TopPreview = 0;
198     }
199 
200     // Generating preview
201     m_PreviewBackground = new wxPanel(m_Content,-1,wxDefaultPosition,wxDefaultSize,wxRAISED_BORDER);
202     wxObject* TopPreviewObject = m_Data->GetRootItem()->BuildPreview(m_PreviewBackground,0);
203     m_TopPreview = wxDynamicCast(TopPreviewObject,wxWindow);
204     if ( !m_TopPreview )
205     {
206         Manager::Get()->GetLogManager()->DebugLog(_T("One of root items returned class not derived from wxWindow"));
207         m_PreviewBackground->Destroy();
208         m_PreviewBackground = 0;
209         m_TopPreview = 0;
210     }
211     else
212     {
213         wxSizer* BackgroundSizer = new wxBoxSizer(wxHORIZONTAL);
214         BackgroundSizer->Add(m_TopPreview,0,0,0);
215         m_PreviewBackground->SetSizer(BackgroundSizer);
216         BackgroundSizer->Fit(m_PreviewBackground);
217         wxSizer* NewSizer = new wxGridSizer(1);
218         NewSizer->Add(m_PreviewBackground,0,wxALL,10);
219 #if !wxCHECK_VERSION(3, 0, 0)
220         m_Content->SetVirtualSizeHints(1,1);
221 #endif
222         m_Content->SetSizer(NewSizer);
223 #if wxCHECK_VERSION(3, 0, 0)
224         NewSizer->FitInside(m_Content);
225 #else
226         NewSizer->SetVirtualSizeHints(m_Content);
227 #endif
228         m_PreviewBackground->Layout();
229         m_Content->Layout();
230         m_HorizSizer->Layout();
231     }
232 
233     m_ToolSpace->AfterPreviewChanged();
234     if ( m_ToolSpace->AreAnyTools() )
235     {
236         m_VertSizer->Show(m_ToolSpace,true,false);
237     }
238     else
239     {
240         m_VertSizer->Show(m_ToolSpace,false,false);
241     }
242     m_VertSizer->Layout();
243 
244     Layout();
245     Thaw();
246     Refresh();
247 
248     // Updating all informations in Content
249     m_Content->AfterPreviewChanged();
250 }
251 
UpdateSelection()252 void wxsItemEditor::UpdateSelection()
253 {
254     // Checking if we've already initialized visual stuff
255     if ( !m_Content ) return;
256 
257     // Updating drag point data
258     m_Content->RefreshSelection();
259     m_ToolSpace->RefreshSelection();
260 
261     // Updating insertion type mask
262     wxsItem* Item = m_Data->GetRootSelection();
263     int itMask = 0;
264     if ( Item )
265     {
266         if ( Item->GetParent() )
267         {
268             // When sizer is added into non-sizer parent, no other items can be added to
269             // this parent
270             if ( Item->GetType() != wxsTSizer ||
271                  Item->GetParent()->GetType() == wxsTSizer )
272             {
273                 itMask |= itBefore | itAfter;
274             }
275         }
276 
277         if ( Item->ConvertToParent() )
278         {
279             itMask |= itInto;
280         }
281     }
282     if ( m_Data->GetRootItem()->ConvertToParent() )
283     {
284         itMask |= itPoint;
285     }
286 
287     SetInsertionTypeMask(itMask);
288     RebuildQuickProps(Item);
289 
290     // TODO: Refresh set of available items inside palette
291 }
292 
Save()293 bool wxsItemEditor::Save()
294 {
295     if ( !m_Data->Save() )
296     {
297         // TODO: Some message here please
298     }
299     UpdateModified();
300     return true;
301 }
302 
GetModified() const303 bool wxsItemEditor::GetModified() const
304 {
305     return m_Data ? m_Data->GetModified() : false;
306 }
307 
UpdateModified()308 void wxsItemEditor::UpdateModified()
309 {
310     if ( m_Data && m_Data->GetModified() )
311     {
312         SetTitle(_T("*") + GetShortName());
313     }
314     else
315     {
316         SetTitle(GetShortName());
317     }
318 }
319 
CanUndo() const320 bool wxsItemEditor::CanUndo() const
321 {
322     return m_Data ? m_Data->CanUndo() : false;
323 }
324 
CanRedo() const325 bool wxsItemEditor::CanRedo() const
326 {
327     return m_Data ? m_Data->CanRedo() : false;
328 }
329 
Undo()330 void wxsItemEditor::Undo()
331 {
332     if ( m_Data ) m_Data->Undo();
333 }
334 
Redo()335 void wxsItemEditor::Redo()
336 {
337     if ( m_Data ) m_Data->Redo();
338 }
339 
HasSelection() const340 bool wxsItemEditor::HasSelection() const
341 {
342     return m_Data ? m_Data->AnySelected() : false;
343 }
344 
CanPaste() const345 bool wxsItemEditor::CanPaste() const
346 {
347     return m_Data ? m_Data->CanPaste() : false;
348 }
349 
IsReadOnly() const350 bool wxsItemEditor::IsReadOnly() const
351 {
352     return m_Data ? m_Data->IsReadOnly() : false;
353 }
354 
Cut()355 void wxsItemEditor::Cut()
356 {
357     if ( m_Data ) m_Data->Cut();
358 }
359 
Copy()360 void wxsItemEditor::Copy()
361 {
362     if ( m_Data ) m_Data->Copy();
363 }
364 
Paste()365 void wxsItemEditor::Paste()
366 {
367     if ( !m_Data ) return;
368 
369     wxsItem* Reference = GetReferenceItem(m_InsType);
370     if ( !Reference ) return;
371     wxsParent* Parent = Reference->GetParent();
372     int RefIndex = Parent ? Parent->GetChildIndex(Reference) : -1;
373 
374     switch ( m_InsType )
375     {
376         case itAfter:
377             RefIndex++;
378             break;
379 
380         case itInto:
381             Parent = Reference->ConvertToParent();
382             RefIndex = Parent ? Parent->GetChildCount() : 0;
383             break;
384 
385         default:
386             break;
387     }
388 
389     m_Data->Paste(Parent,RefIndex);
390 }
391 
InsertRequest(const wxString & Name)392 void wxsItemEditor::InsertRequest(const wxString& Name)
393 {
394     const wxsItemInfo* Info = wxsItemFactory::GetInfo(Name);
395     if ( !Info ) return;
396     bool IsTool = Info->Type == wxsTTool;
397 
398     if ( !IsTool && m_InsType==itPoint )
399     {
400         StartInsertPointSequence(Info);
401         return;
402     }
403 
404     wxsItem* Reference = GetReferenceItem(m_InsType);
405     if ( !Reference )
406     {
407         Manager::Get()->GetLogManager()->DebugLog(_T("wxSmith: No item selected - couldn't create new item"));
408         return;
409     }
410 
411     wxsItem* New = wxsItemFactory::Build(Name,m_Data);
412     if ( !New )
413     {
414         Manager::Get()->GetLogManager()->DebugLog(_T("wxSmith: Couldn't generate item inside factory"));
415         return;
416     }
417 
418     m_Data->BeginChange();
419     wxsParent* Parent = Reference->GetParent();
420     int RefIndex = Parent ? Parent->GetChildIndex(Reference) : -1;
421 
422     switch ( m_InsType )
423     {
424         case itAfter:
425             RefIndex++;
426             // We don't break here - continuing on itBefore code
427 
428         case itBefore:
429             if ( Parent )
430             {
431                 // Checking if this is tool, tools can be added
432                 // into other tools or into resource only
433                 if ( IsTool &&
434                      ( !Parent->ConvertToTool() ||
435                        !New->CanAddToParent(Parent,false)) )
436                 {
437                     // Trying to add to resource
438                     if ( !New->ConvertToTool()->CanAddToResource(m_Data,true) )
439                     {
440                         delete New;
441                     }
442                     else
443                     {
444                         if ( m_Data->InsertNewTool(New->ConvertToTool()) )
445                         {
446                             m_Data->SelectItem(New,true);
447                         }
448                     }
449                 }
450                 else
451                 {
452                     if ( m_Data->InsertNew(New,Parent,RefIndex) )
453                     {
454                         m_Data->SelectItem(New,true);
455                     }
456                 }
457 
458             }
459             else
460             {
461                 delete New;
462             }
463             break;
464 
465         case itInto:
466         case itPoint:       // This will cover tools when itPoint is used
467         {
468             if ( IsTool &&
469                  (!Reference->ConvertToTool() ||
470                   !New->CanAddToParent(Reference->ConvertToParent(),false)) )
471             {
472                 // Trying to add to resource
473                 if ( !New->ConvertToTool()->CanAddToResource(m_Data,true) )
474                 {
475                     delete New;
476                 }
477                 else
478                 {
479                     if ( m_Data->InsertNewTool(New->ConvertToTool()) )
480                     {
481                         m_Data->SelectItem(New,true);
482                     }
483                 }
484             }
485             else
486             {
487                 if ( m_Data->InsertNew(New,Reference->ConvertToParent(),-1) )
488                 {
489                     m_Data->SelectItem(New,true);
490                 }
491             }
492             break;
493         }
494 
495         default:
496         {
497             delete New;
498         }
499 
500     }
501     m_Data->EndChange();
502 }
503 
InitializeImages()504 void wxsItemEditor::InitializeImages()
505 {
506     if ( m_ImagesLoaded ) return;
507     wxString basePath = ConfigManager::GetDataFolder() + _T("/images/wxsmith/");
508 
509     static const wxString NormalNames[] =
510     {
511         _T("insertpoint32.png"),
512         _T("insertinto32.png"),
513         _T("insertafter32.png"),
514         _T("insertbefore32.png"),
515         _T("deletewidget32.png"),
516         _T("showpreview32.png"),
517         _T("quickpropsopen32.png"),
518         _T("quickpropsclose32.png"),
519         _T("selected32.png")
520     };
521 
522     static const wxString SmallNames[] =
523     {
524         _T("insertpoint16.png"),
525         _T("insertinto16.png"),
526         _T("insertafter16.png"),
527         _T("insertbefore16.png"),
528         _T("deletewidget16.png"),
529         _T("showpreview16.png"),
530         _T("quickpropsopen16.png"),
531         _T("quickpropsclose16.png"),
532         _T("selected16.png")
533     };
534 
535     const wxString* Array = ( ToolIconSize() == 16L ) ? SmallNames : NormalNames;
536 
537     m_InsPointImg.LoadFile(basePath + Array[0]);
538     m_InsIntoImg.LoadFile(basePath + Array[1]);
539     m_InsAfterImg.LoadFile(basePath + Array[2]);
540     m_InsBeforeImg.LoadFile(basePath + Array[3]);
541     m_DelImg.LoadFile(basePath + Array[4]);
542     m_PreviewImg.LoadFile(basePath + Array[5]);
543     m_QuickPropsImgOpen.LoadFile(basePath + Array[6]);
544     m_QuickPropsImgClose.LoadFile(basePath + Array[7]);
545     m_SelectedImg.LoadFile(basePath + Array[8]);
546 
547     m_ImagesLoaded = true;
548 }
549 
OnButton(wxCommandEvent & event)550 void wxsItemEditor::OnButton(wxCommandEvent& event)
551 {
552     wxWindow* Btn = (wxWindow*)event.GetEventObject();
553     if ( Btn )
554     {
555         InsertRequest(Btn->GetName());
556     }
557 }
558 
SetInsertionTypeMask(int Mask)559 void wxsItemEditor::SetInsertionTypeMask(int Mask)
560 {
561     m_InsTypeMask = Mask;
562     SetInsertionType(m_InsType);
563 }
564 
SetInsertionType(int Type)565 void wxsItemEditor::SetInsertionType(int Type)
566 {
567     Type &= m_InsTypeMask;
568 
569     if ( !Type )
570     {
571         Type = m_InsTypeMask;
572     }
573 
574     if ( Type & itPoint )
575     {
576         m_InsType = itPoint;
577     }
578     else if ( Type & itInto )
579     {
580         m_InsType = itInto;
581     }
582     else if ( Type & itAfter )
583     {
584         m_InsType = itAfter;
585     }
586     else if ( Type & itBefore )
587     {
588         m_InsType = itBefore;
589     }
590     else
591     {
592         m_InsType = 0;
593     }
594 
595     RebuildInsTypeIcons();
596 }
597 
RebuildInsTypeIcons()598 void wxsItemEditor::RebuildInsTypeIcons()
599 {
600     BuildInsTypeIcon(m_InsPointBtn,m_InsPointImg,itPoint);
601     BuildInsTypeIcon(m_InsIntoBtn,m_InsIntoImg,itInto);
602     BuildInsTypeIcon(m_InsBeforeBtn,m_InsBeforeImg,itBefore);
603     BuildInsTypeIcon(m_InsAfterBtn,m_InsAfterImg,itAfter);
604 }
605 
BuildInsTypeIcon(wxBitmapButton * Btn,const wxImage & Original,int ButtonType)606 void wxsItemEditor::BuildInsTypeIcon(wxBitmapButton* Btn,const wxImage& Original,int ButtonType)
607 {
608     bool Selected = (m_InsType & ButtonType) != 0;
609     bool Enabled = (m_InsTypeMask & ButtonType) != 0;
610 
611     if ( !Enabled || !Selected )
612     {
613         Btn->SetBitmapLabel(Original);
614     }
615     else
616     {
617         wxBitmap Copy = Original;
618         wxMemoryDC DC;
619         DC.SelectObject(Copy);
620         DC.DrawBitmap(m_SelectedImg,0,0);
621         Btn->SetBitmapLabel(Copy);
622     }
623 
624     Btn->Enable(Enabled);
625     Btn->Refresh();
626 }
627 
RebuildQuickPropsIcon()628 void wxsItemEditor::RebuildQuickPropsIcon()
629 {
630     m_QuickPanelBtn->SetBitmapLabel( m_QuickPropsOpen ? m_QuickPropsImgClose : m_QuickPropsImgOpen );
631 }
632 
RebuildIcons()633 void wxsItemEditor::RebuildIcons()
634 {
635     RebuildInsTypeIcons();
636     RebuildQuickPropsIcon();
637     m_DelBtn->SetBitmapLabel(m_DelImg);
638     m_PreviewBtn->SetBitmapLabel(m_PreviewImg);
639     BuildPalette(m_WidgetsSet);
640     Layout();
641 }
642 
643 namespace
644 {
PrioritySort(const wxsItemInfo ** it1,const wxsItemInfo ** it2)645     int PrioritySort(const wxsItemInfo** it1,const wxsItemInfo** it2)
646     {
647         return (*it1)->Priority - (*it2)->Priority;
648     }
649 
650     WX_DEFINE_ARRAY(const wxsItemInfo*,ItemsT);
651 
CategorySort(ItemsT * it1,ItemsT * it2)652     int CategorySort(ItemsT* it1, ItemsT* it2)
653     {
654         if (it1->Item(0)->Category.IsSameAs(_T("Standard")))
655             return -1;
656 
657         if (it2->Item(0)->Category.IsSameAs(_T("Standard")))
658             return 1;
659 
660         return wxStrcmp(it1->Item(0)->Category, it2->Item(0)->Category);
661     }
662 
663     WX_DECLARE_STRING_HASH_MAP(ItemsT,MapT);
664     WX_DEFINE_SORTED_ARRAY(ItemsT*,ArrayOfItemsT);
665 }
666 
BuildPalette(wxNotebook * Palette)667 void wxsItemEditor::BuildPalette(wxNotebook* Palette)
668 {
669     Palette->DeleteAllPages();
670     bool AllowNonXRCItems = (m_Data->GetPropertiesFilter() & flSource);
671 
672     // First we need to split all widgets into groups
673     // it will be done using multimap (map of arrays)
674 
675     MapT Map;
676     ArrayOfItemsT aoi(CategorySort);
677 
678     for ( const wxsItemInfo* Info = wxsItemFactory::GetFirstInfo(); Info; Info = wxsItemFactory::GetNextInfo() )
679     {
680         if ( !Info->Category.empty() )
681         {
682             Map[Info->Category].Add(Info);
683         }
684     }
685 
686     for ( MapT::iterator i = Map.begin(); i!=Map.end(); ++i )
687     {
688         aoi.Add(&(i->second));
689     }
690     for (size_t i = 0; i < aoi.Count(); ++i)
691     {
692         ItemsT* Items = aoi.Item(i);
693         Items->Sort(PrioritySort);
694         wxScrolledWindow* CurrentPanel = new wxScrolledWindow(Palette,-1,wxDefaultPosition,wxDefaultSize,0/*wxALWAYS_SHOW_SB|wxHSCROLL*/);
695         CurrentPanel->SetScrollRate(1,0);
696         Palette->AddPage(CurrentPanel,Items->Item(0)->Category);
697         wxSizer* RowSizer = new wxBoxSizer(wxHORIZONTAL);
698 
699         for ( size_t j=Items->Count(); j-->0; )
700         {
701             const wxsItemInfo* Info = Items->Item(j);
702             const wxBitmap& Icon = ( PalIconSize() == 16L ) ? Info->Icon16 : Info->Icon32;
703 
704             if ( AllowNonXRCItems || Info->AllowInXRC )
705             {
706                 wxWindow* Btn;
707                 if ( Icon.Ok() )
708                 {
709                     Btn = new wxBitmapButton(CurrentPanel,-1,Icon,
710                               wxDefaultPosition,wxDefaultSize,wxBU_AUTODRAW,
711                               wxDefaultValidator, Info->ClassName);
712                     RowSizer->Add(Btn,0,wxALIGN_CENTER);
713                 }
714                 else
715                 {
716                     Btn = new wxButton(CurrentPanel,-1,Info->ClassName,
717                               wxDefaultPosition,wxDefaultSize,0,
718                               wxDefaultValidator,Info->ClassName);
719                     RowSizer->Add(Btn,0,wxGROW);
720                 }
721                 Btn->SetToolTip(Info->ClassName);
722             }
723         }
724         CurrentPanel->SetSizer(RowSizer);
725 #if wxCHECK_VERSION(3, 0, 0)
726         RowSizer->FitInside(CurrentPanel);
727 #else
728         RowSizer->SetVirtualSizeHints(CurrentPanel);
729 #endif
730     }
731 }
732 
OnInsPoint(cb_unused wxCommandEvent & event)733 void wxsItemEditor::OnInsPoint(cb_unused wxCommandEvent& event)
734 {
735     SetInsertionType(itPoint);
736 }
737 
OnInsInto(cb_unused wxCommandEvent & event)738 void wxsItemEditor::OnInsInto(cb_unused wxCommandEvent& event)
739 {
740     SetInsertionType(itInto);
741 }
742 
OnInsAfter(cb_unused wxCommandEvent & event)743 void wxsItemEditor::OnInsAfter(cb_unused wxCommandEvent& event)
744 {
745     SetInsertionType(itAfter);
746 }
747 
OnInsBefore(cb_unused wxCommandEvent & event)748 void wxsItemEditor::OnInsBefore(cb_unused wxCommandEvent& event)
749 {
750     SetInsertionType(itBefore);
751 }
752 
OnDelete(cb_unused wxCommandEvent & event)753 void wxsItemEditor::OnDelete(cb_unused wxCommandEvent& event)
754 {
755     if ( !m_Data ) return;
756     m_Data->BeginChange();
757     m_Data->DeleteSelected();
758     m_Data->EndChange();
759 }
760 
OnPreview(cb_unused wxCommandEvent & event)761 void wxsItemEditor::OnPreview(cb_unused wxCommandEvent& event)
762 {
763     if ( !m_Data ) return;
764 
765     m_Content->BlockFetch(true);
766 
767     if ( m_Data->IsPreview() )
768     {
769         m_Data->HidePreview();
770     }
771     else
772     {
773         m_Data->ShowPreview();
774     }
775 
776     m_Content->BlockFetch(false);
777 }
778 
OnQuickProps(cb_unused wxCommandEvent & event)779 void wxsItemEditor::OnQuickProps(cb_unused wxCommandEvent& event)
780 {
781     m_QuickPropsOpen = !m_QuickPropsOpen;
782     RebuildQuickPropsIcon();
783     ToggleQuickPropsPanel(m_QuickPropsOpen);
784 }
785 
ToggleQuickPropsPanel(bool Open)786 void wxsItemEditor::ToggleQuickPropsPanel(bool Open)
787 {
788     m_HorizSizer->Show(m_QPArea,Open,true);
789     Layout();
790 }
791 
RebuildQuickProps(wxsItem * Selection)792 void wxsItemEditor::RebuildQuickProps(wxsItem* Selection)
793 {
794     // Checking if we've already initialized visual stuff
795     if ( !m_Content ) return;
796 
797     Freeze();
798 
799     int QPx, QPy;
800     // TODO: Check if content of previous QPPanel shouldn't be stored into item
801     m_QPArea->GetViewStart(&QPx,&QPy);
802     m_QPArea->SetSizer(0);
803     m_QPArea->DestroyChildren();
804     m_QPSizer = new wxBoxSizer(wxVERTICAL);
805     m_QPArea->SetSizer(m_QPSizer);
806 
807     if ( Selection )
808     {
809         wxWindow* QPPanel = Selection->BuildQuickPropertiesPanel(m_QPArea);
810         if ( QPPanel )
811         {
812             m_QPSizer->Add(QPPanel,0,wxEXPAND);
813         }
814     }
815     m_QPSizer->Layout();
816     m_QPSizer->Fit(m_QPArea);
817     Layout();
818     m_QPArea->Scroll(QPx,QPy);
819     Thaw();
820 }
821 
GetReferenceItem(int & InsertionType)822 wxsItem* wxsItemEditor::GetReferenceItem(int& InsertionType)
823 {
824     wxsItem* Reference = m_Data->GetLastSelection();
825     if ( !Reference )
826     {
827         // Fixing up reference item when there's nothing selected
828         InsertionType = itInto;
829         Reference = m_Data->GetRootItem();
830         wxsParent* AsParent = Reference->ConvertToParent();
831         if ( AsParent &&
832              AsParent->GetChildCount() == 1 &&
833              AsParent->GetChild(0)->GetType() == wxsTSizer )
834         {
835             Reference = AsParent->GetChild(0);
836         }
837     }
838     return Reference;
839 }
840 
OnKeyDown(wxKeyEvent & event)841 void wxsItemEditor::OnKeyDown(wxKeyEvent& event)
842 {
843     switch ( event.GetKeyCode() )
844     {
845         case WXK_DELETE:
846             if ( !m_Data ) break;
847             m_Data->BeginChange();
848             m_Data->DeleteSelected();
849             m_Data->EndChange();
850             break;
851 
852         default:
853             break;
854     }
855 }
856 
StartInsertPointSequence(const wxsItemInfo * Info)857 void wxsItemEditor::StartInsertPointSequence(const wxsItemInfo* Info)
858 {
859     if ( m_Content )
860     {
861         m_Content->InsertByPointing(Info);
862     }
863 }
864 
ShowPopup(wxsItem * Item,wxMenu * Popup)865 void wxsItemEditor::ShowPopup(wxsItem* Item,wxMenu* Popup)
866 {
867     m_PopupCaller = Item;
868     PopupMenu(Popup);
869 }
870 
OnPopup(wxCommandEvent & event)871 void wxsItemEditor::OnPopup(wxCommandEvent& event)
872 {
873     if ( m_PopupCaller )
874     {
875         if ( !m_PopupCaller->PopupMenu(event.GetId()) )
876         {
877             event.Skip();
878         }
879     }
880 }
881 
882 wxImage wxsItemEditor::m_InsPointImg;
883 wxImage wxsItemEditor::m_InsIntoImg;
884 wxImage wxsItemEditor::m_InsBeforeImg;
885 wxImage wxsItemEditor::m_InsAfterImg;
886 wxImage wxsItemEditor::m_DelImg;
887 wxImage wxsItemEditor::m_PreviewImg;
888 wxImage wxsItemEditor::m_QuickPropsImgOpen;
889 wxImage wxsItemEditor::m_QuickPropsImgClose;
890 wxImage wxsItemEditor::m_SelectedImg;
891 wxsItemEditor::WindowSet wxsItemEditor::m_AllEditors;
892 bool wxsItemEditor::m_ImagesLoaded = false;
893 
894 BEGIN_EVENT_TABLE(wxsItemEditor,wxsEditor)
895     EVT_BUTTON(wxsInsPointId,wxsItemEditor::OnInsPoint)
896     EVT_BUTTON(wxsInsIntoId,wxsItemEditor::OnInsInto)
897     EVT_BUTTON(wxsInsBeforeId,wxsItemEditor::OnInsBefore)
898     EVT_BUTTON(wxsInsAfterId,wxsItemEditor::OnInsAfter)
899     EVT_BUTTON(wxsDelId,wxsItemEditor::OnDelete)
900     EVT_BUTTON(wxsPreviewId,wxsItemEditor::OnPreview)
901     EVT_BUTTON(wxsQuickPropsId,wxsItemEditor::OnQuickProps)
902     EVT_BUTTON(-1,wxsItemEditor::OnButton)
903     EVT_KEY_DOWN(wxsItemEditor::OnKeyDown)
904     EVT_MENU(wxID_ANY,wxsItemEditor::OnPopup)
905 END_EVENT_TABLE()
906