1 /*
2  Copyright (C) 2010-2014 Kristian Duske
3 
4  This file is part of TrenchBroom.
5 
6  TrenchBroom is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  TrenchBroom 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 TrenchBroom.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "SmartAttributeEditorManager.h"
21 
22 #include "CollectionUtils.h"
23 #include "View/MapDocument.h"
24 #include "View/SmartChoiceEditor.h"
25 #include "View/SmartChoiceEditorMatcher.h"
26 #include "View/SmartColorEditor.h"
27 #include "View/SmartDefaultAttributeEditor.h"
28 #include "View/SmartAttributeEditor.h"
29 #include "View/SmartAttributeEditorMatcher.h"
30 #include "View/SmartSpawnflagsEditor.h"
31 
32 #include <wx/panel.h>
33 #include <wx/sizer.h>
34 
35 namespace TrenchBroom {
36     namespace View {
SmartAttributeEditorManager(wxWindow * parent,View::MapDocumentWPtr document)37         SmartAttributeEditorManager::SmartAttributeEditorManager(wxWindow* parent, View::MapDocumentWPtr document) :
38         wxPanel(parent),
39         m_document(document),
40         m_name("") {
41             createEditors();
42             activateEditor(defaultEditor(), "");
43             bindObservers();
44         }
45 
~SmartAttributeEditorManager()46         SmartAttributeEditorManager::~SmartAttributeEditorManager() {
47             unbindObservers();
48             deactivateEditor();
49         }
50 
switchEditor(const Model::AttributeName & name,const Model::AttributableNodeList & attributables)51         void SmartAttributeEditorManager::switchEditor(const Model::AttributeName& name, const Model::AttributableNodeList& attributables) {
52             EditorPtr editor = selectEditor(name, attributables);
53             activateEditor(editor, name);
54             updateEditor();
55         }
56 
createEditors()57         void SmartAttributeEditorManager::createEditors() {
58             m_editors.push_back(MatcherEditorPair(MatcherPtr(new SmartAttributeEditorKeyMatcher("spawnflags")),
59                                                   EditorPtr(new SmartSpawnflagsEditor(m_document))));
60             m_editors.push_back(MatcherEditorPair(MatcherPtr(new SmartAttributeEditorKeyMatcher("_color", "_sunlight_color", "_sunlight_color2")),
61                                                   EditorPtr(new SmartColorEditor(m_document))));
62             m_editors.push_back(MatcherEditorPair(MatcherPtr(new SmartChoiceEditorMatcher()),
63                                                   EditorPtr(new SmartChoiceEditor(m_document))));
64             m_editors.push_back(MatcherEditorPair(MatcherPtr(new SmartAttributeEditorDefaultMatcher()),
65                                                   EditorPtr(new SmartDefaultAttributeEditor(m_document))));
66         }
67 
bindObservers()68         void SmartAttributeEditorManager::bindObservers() {
69             MapDocumentSPtr document = lock(m_document);
70             document->selectionDidChangeNotifier.addObserver(this, &SmartAttributeEditorManager::selectionDidChange);
71             document->nodesDidChangeNotifier.addObserver(this, &SmartAttributeEditorManager::nodesDidChange);
72         }
73 
unbindObservers()74         void SmartAttributeEditorManager::unbindObservers() {
75             if (!expired(m_document)) {
76                 MapDocumentSPtr document = lock(m_document);
77                 document->selectionDidChangeNotifier.removeObserver(this, &SmartAttributeEditorManager::selectionDidChange);
78                 document->nodesDidChangeNotifier.removeObserver(this, &SmartAttributeEditorManager::nodesDidChange);
79             }
80         }
81 
selectionDidChange(const Selection & selection)82         void SmartAttributeEditorManager::selectionDidChange(const Selection& selection) {
83             MapDocumentSPtr document = lock(m_document);
84             switchEditor(m_name, document->allSelectedAttributableNodes());
85         }
86 
nodesDidChange(const Model::NodeList & nodes)87         void SmartAttributeEditorManager::nodesDidChange(const Model::NodeList& nodes) {
88             MapDocumentSPtr document = lock(m_document);
89             switchEditor(m_name, document->allSelectedAttributableNodes());
90         }
91 
selectEditor(const Model::AttributeName & name,const Model::AttributableNodeList & attributables) const92         SmartAttributeEditorManager::EditorPtr SmartAttributeEditorManager::selectEditor(const Model::AttributeName& name, const Model::AttributableNodeList& attributables) const {
93             EditorList::const_iterator it, end;
94             for (it = m_editors.begin(), end = m_editors.end(); it != end; ++it) {
95                 const MatcherEditorPair& pair = *it;
96                 const MatcherPtr matcher = pair.first;
97                 if (matcher->matches(name, attributables))
98                     return pair.second;
99             }
100 
101             // should never happen
102             assert(false);
103             return defaultEditor();
104         }
105 
106 
defaultEditor() const107         SmartAttributeEditorManager::EditorPtr SmartAttributeEditorManager::defaultEditor() const {
108             return m_editors.back().second;
109         }
110 
activateEditor(EditorPtr editor,const Model::AttributeName & name)111         void SmartAttributeEditorManager::activateEditor(EditorPtr editor, const Model::AttributeName& name) {
112             if (m_activeEditor != editor || !m_activeEditor->usesName(name)) {
113                 deactivateEditor();
114                 m_activeEditor = editor;
115                 m_name = name;
116                 wxWindow* window = m_activeEditor->activate(this, m_name);
117 
118                 wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
119                 sizer->Add(window, 1, wxEXPAND);
120                 SetSizer(sizer);
121                 Layout();
122             }
123         }
124 
deactivateEditor()125         void SmartAttributeEditorManager::deactivateEditor() {
126             if (m_activeEditor.get() != NULL) {
127                 m_activeEditor->deactivate();
128                 m_activeEditor = EditorPtr();
129                 m_name = "";
130             }
131         }
132 
updateEditor()133         void SmartAttributeEditorManager::updateEditor() {
134             if (m_activeEditor.get() != NULL) {
135                 MapDocumentSPtr document = lock(m_document);
136                 m_activeEditor->update(document->allSelectedAttributableNodes());
137             }
138         }
139     }
140 }
141