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 "EntityBrowser.h"
21 
22 #include "PreferenceManager.h"
23 #include "Preferences.h"
24 #include "Assets/EntityDefinitionManager.h"
25 #include "View/EntityBrowserView.h"
26 #include "View/ViewConstants.h"
27 #include "View/MapDocument.h"
28 
29 #include <wx/choice.h>
30 #include <wx/event.h>
31 #include <wx/tglbtn.h>
32 #include <wx/srchctrl.h>
33 #include <wx/sizer.h>
34 
35 namespace TrenchBroom {
36     namespace View {
EntityBrowser(wxWindow * parent,MapDocumentWPtr document,GLContextManager & contextManager)37         EntityBrowser::EntityBrowser(wxWindow* parent, MapDocumentWPtr document, GLContextManager& contextManager) :
38         wxPanel(parent),
39         m_document(document) {
40             createGui(contextManager);
41             bindObservers();
42         }
43 
~EntityBrowser()44         EntityBrowser::~EntityBrowser() {
45             unbindObservers();
46         }
47 
reload()48         void EntityBrowser::reload() {
49             if (m_view != NULL) {
50                 m_view->clear();
51                 m_view->reload();
52             }
53         }
54 
OnSortOrderChanged(wxCommandEvent & event)55         void EntityBrowser::OnSortOrderChanged(wxCommandEvent& event) {
56             if (IsBeingDeleted()) return;
57 
58             const Assets::EntityDefinition::SortOrder sortOrder = event.GetSelection() == 0 ? Assets::EntityDefinition::Name : Assets::EntityDefinition::Usage;
59             m_view->setSortOrder(sortOrder);
60         }
61 
OnGroupButtonToggled(wxCommandEvent & event)62         void EntityBrowser::OnGroupButtonToggled(wxCommandEvent& event) {
63             if (IsBeingDeleted()) return;
64 
65             m_view->setGroup(m_groupButton->GetValue());
66         }
67 
OnUsedButtonToggled(wxCommandEvent & event)68         void EntityBrowser::OnUsedButtonToggled(wxCommandEvent& event) {
69             if (IsBeingDeleted()) return;
70 
71             m_view->setHideUnused(m_usedButton->GetValue());
72         }
73 
OnFilterPatternChanged(wxCommandEvent & event)74         void EntityBrowser::OnFilterPatternChanged(wxCommandEvent& event) {
75             if (IsBeingDeleted()) return;
76 
77             m_view->setFilterText(m_filterBox->GetValue().ToStdString());
78         }
79 
createGui(GLContextManager & contextManager)80         void EntityBrowser::createGui(GLContextManager& contextManager) {
81             wxPanel* browserPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
82             m_scrollBar = new wxScrollBar(browserPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL);
83 
84             MapDocumentSPtr document = lock(m_document);
85             m_view = new EntityBrowserView(browserPanel, m_scrollBar,
86                                            contextManager,
87                                            document->entityDefinitionManager(),
88                                            document->entityModelManager(),
89                                            *document);
90 
91             wxSizer* browserPanelSizer = new wxBoxSizer(wxHORIZONTAL);
92             browserPanelSizer->Add(m_view, 1, wxEXPAND);
93             browserPanelSizer->Add(m_scrollBar, 0, wxEXPAND);
94             browserPanel->SetSizerAndFit(browserPanelSizer);
95 
96             const wxString sortOrders[2] = { "Name", "Usage" };
97             m_sortOrderChoice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 2, sortOrders);
98             m_sortOrderChoice->SetSelection(0);
99             m_sortOrderChoice->SetToolTip("Select ordering criterion");
100 
101             m_groupButton = new wxToggleButton(this, wxID_ANY, "Group", wxDefaultPosition, wxDefaultSize, LayoutConstants::ToggleButtonStyle | wxBU_EXACTFIT);
102             m_groupButton->SetToolTip("Group entity definitions by category");
103 
104             m_usedButton = new wxToggleButton(this, wxID_ANY, "Used", wxDefaultPosition, wxDefaultSize, LayoutConstants::ToggleButtonStyle | wxBU_EXACTFIT);
105             m_usedButton->SetToolTip("Only show entity definitions currently in use");
106 
107             m_filterBox = new wxSearchCtrl(this, wxID_ANY);
108             m_filterBox->ShowCancelButton(true);
109 
110             m_sortOrderChoice->Bind(wxEVT_CHOICE, &EntityBrowser::OnSortOrderChanged, this);
111             m_groupButton->Bind(wxEVT_TOGGLEBUTTON, &EntityBrowser::OnGroupButtonToggled, this);
112             m_usedButton->Bind(wxEVT_TOGGLEBUTTON, &EntityBrowser::OnUsedButtonToggled, this);
113             m_filterBox->Bind(wxEVT_TEXT, &EntityBrowser::OnFilterPatternChanged, this);
114 
115             wxSizer* controlSizer = new wxBoxSizer(wxHORIZONTAL);
116             controlSizer->AddSpacer(LayoutConstants::ChoiceLeftMargin);
117             controlSizer->Add(m_sortOrderChoice, 0, wxTOP, LayoutConstants::ChoiceTopMargin);
118             controlSizer->AddSpacer(LayoutConstants::NarrowHMargin);
119             controlSizer->Add(m_groupButton, 0);
120             controlSizer->AddSpacer(LayoutConstants::NarrowHMargin);
121             controlSizer->Add(m_usedButton, 0);
122             controlSizer->AddSpacer(LayoutConstants::NarrowHMargin);
123             controlSizer->Add(m_filterBox, 1, wxEXPAND);
124 
125             wxSizer* outerSizer = new wxBoxSizer(wxVERTICAL);
126             outerSizer->Add(browserPanel, 1, wxEXPAND);
127             outerSizer->AddSpacer(LayoutConstants::NarrowVMargin);
128             outerSizer->Add(controlSizer, 0, wxEXPAND | wxLEFT | wxRIGHT, LayoutConstants::NarrowHMargin);
129             outerSizer->AddSpacer(LayoutConstants::NarrowVMargin);
130 
131             SetBackgroundColour(*wxWHITE);
132             SetSizer(outerSizer);
133         }
134 
bindObservers()135         void EntityBrowser::bindObservers() {
136             MapDocumentSPtr document = lock(m_document);
137             document->documentWasNewedNotifier.addObserver(this, &EntityBrowser::documentWasNewed);
138             document->documentWasLoadedNotifier.addObserver(this, &EntityBrowser::documentWasLoaded);
139             document->modsDidChangeNotifier.addObserver(this, &EntityBrowser::modsDidChange);
140             document->entityDefinitionsDidChangeNotifier.addObserver(this, &EntityBrowser::entityDefinitionsDidChange);
141 
142             PreferenceManager& prefs = PreferenceManager::instance();
143             prefs.preferenceDidChangeNotifier.addObserver(this, &EntityBrowser::preferenceDidChange);
144         }
145 
unbindObservers()146         void EntityBrowser::unbindObservers() {
147             if (!expired(m_document)) {
148             MapDocumentSPtr document = lock(m_document);
149                 document->documentWasNewedNotifier.removeObserver(this, &EntityBrowser::documentWasNewed);
150                 document->documentWasLoadedNotifier.removeObserver(this, &EntityBrowser::documentWasLoaded);
151                 document->modsDidChangeNotifier.removeObserver(this, &EntityBrowser::modsDidChange);
152                 document->entityDefinitionsDidChangeNotifier.removeObserver(this, &EntityBrowser::entityDefinitionsDidChange);
153             }
154 
155             PreferenceManager& prefs = PreferenceManager::instance();
156             prefs.preferenceDidChangeNotifier.removeObserver(this, &EntityBrowser::preferenceDidChange);
157         }
158 
documentWasNewed(MapDocument * document)159         void EntityBrowser::documentWasNewed(MapDocument* document) {
160             reload();
161         }
162 
documentWasLoaded(MapDocument * document)163         void EntityBrowser::documentWasLoaded(MapDocument* document) {
164             reload();
165         }
166 
modsDidChange()167         void EntityBrowser::modsDidChange() {
168             reload();
169         }
170 
entityDefinitionsDidChange()171         void EntityBrowser::entityDefinitionsDidChange() {
172             reload();
173         }
174 
preferenceDidChange(const IO::Path & path)175         void EntityBrowser::preferenceDidChange(const IO::Path& path) {
176             MapDocumentSPtr document = lock(m_document);
177             if (document->isGamePathPreference(path))
178                 reload();
179             else
180                 m_view->Refresh();
181         }
182     }
183 }
184