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 "IssueBrowser.h" 21 22 #include "Macros.h" 23 #include "Model/Issue.h" 24 #include "Model/IssueGenerator.h" 25 #include "Model/World.h" 26 #include "View/FlagChangedCommand.h" 27 #include "View/FlagsPopupEditor.h" 28 #include "View/IssueBrowserView.h" 29 #include "View/MapDocument.h" 30 #include "View/ViewConstants.h" 31 32 #include <wx/checkbox.h> 33 #include <wx/menu.h> 34 #include <wx/simplebook.h> 35 #include <wx/sizer.h> 36 37 #include <cassert> 38 39 namespace TrenchBroom { 40 namespace View { IssueBrowser(wxWindow * parent,MapDocumentWPtr document)41 IssueBrowser::IssueBrowser(wxWindow* parent, MapDocumentWPtr document) : 42 TabBookPage(parent), 43 m_document(document), 44 m_view(new IssueBrowserView(this, m_document)), 45 m_showHiddenIssuesCheckBox(NULL), 46 m_filterEditor(NULL) { 47 wxSizer* sizer = new wxBoxSizer(wxVERTICAL); 48 sizer->Add(m_view, 1, wxEXPAND); 49 SetSizerAndFit(sizer); 50 51 bindObservers(); 52 } 53 ~IssueBrowser()54 IssueBrowser::~IssueBrowser() { 55 unbindObservers(); 56 } 57 createTabBarPage(wxWindow * parent)58 wxWindow* IssueBrowser::createTabBarPage(wxWindow* parent) { 59 wxPanel* barPage = new wxPanel(parent); 60 m_showHiddenIssuesCheckBox = new wxCheckBox(barPage, wxID_ANY, "Show hidden issues"); 61 m_showHiddenIssuesCheckBox->Bind(wxEVT_CHECKBOX, &IssueBrowser::OnShowHiddenIssuesChanged, this); 62 63 m_filterEditor = new FlagsPopupEditor(barPage, 1, "Filter", false); 64 m_filterEditor->Bind(FLAG_CHANGED_EVENT, &IssueBrowser::OnFilterChanged, this); 65 66 wxBoxSizer* barPageSizer = new wxBoxSizer(wxHORIZONTAL); 67 barPageSizer->Add(m_showHiddenIssuesCheckBox, 0, wxALIGN_CENTER_VERTICAL); 68 barPageSizer->AddSpacer(LayoutConstants::MediumHMargin); 69 barPageSizer->Add(m_filterEditor, 0, wxALIGN_CENTER_VERTICAL); 70 barPage->SetSizer(barPageSizer); 71 72 return barPage; 73 } 74 OnShowHiddenIssuesChanged(wxCommandEvent & event)75 void IssueBrowser::OnShowHiddenIssuesChanged(wxCommandEvent& event) { 76 if (IsBeingDeleted()) return; 77 78 m_view->setShowHiddenIssues(m_showHiddenIssuesCheckBox->IsChecked()); 79 } 80 OnFilterChanged(FlagChangedCommand & command)81 void IssueBrowser::OnFilterChanged(FlagChangedCommand& command) { 82 if (IsBeingDeleted()) return; 83 84 m_view->setHiddenGenerators(~command.flagSetValue()); 85 } 86 bindObservers()87 void IssueBrowser::bindObservers() { 88 MapDocumentSPtr document = lock(m_document); 89 document->documentWasSavedNotifier.addObserver(this, &IssueBrowser::documentWasSaved); 90 document->documentWasNewedNotifier.addObserver(this, &IssueBrowser::documentWasNewedOrLoaded); 91 document->documentWasLoadedNotifier.addObserver(this, &IssueBrowser::documentWasNewedOrLoaded); 92 document->nodesWereAddedNotifier.addObserver(this, &IssueBrowser::nodesWereAdded); 93 document->nodesWereRemovedNotifier.addObserver(this, &IssueBrowser::nodesWereRemoved); 94 document->nodesDidChangeNotifier.addObserver(this, &IssueBrowser::nodesDidChange); 95 document->brushFacesDidChangeNotifier.addObserver(this, &IssueBrowser::brushFacesDidChange); 96 } 97 unbindObservers()98 void IssueBrowser::unbindObservers() { 99 if (!expired(m_document)) { 100 MapDocumentSPtr document = lock(m_document); 101 document->documentWasSavedNotifier.removeObserver(this, &IssueBrowser::documentWasSaved); 102 document->documentWasNewedNotifier.removeObserver(this, &IssueBrowser::documentWasNewedOrLoaded); 103 document->documentWasLoadedNotifier.removeObserver(this, &IssueBrowser::documentWasNewedOrLoaded); 104 document->nodesWereAddedNotifier.removeObserver(this, &IssueBrowser::nodesWereAdded); 105 document->nodesWereRemovedNotifier.removeObserver(this, &IssueBrowser::nodesWereRemoved); 106 document->nodesDidChangeNotifier.removeObserver(this, &IssueBrowser::nodesDidChange); 107 document->brushFacesDidChangeNotifier.removeObserver(this, &IssueBrowser::brushFacesDidChange); 108 } 109 } 110 documentWasNewedOrLoaded(MapDocument * document)111 void IssueBrowser::documentWasNewedOrLoaded(MapDocument* document) { 112 updateFilterFlags(); 113 m_view->reset(); 114 } 115 documentWasSaved(MapDocument * document)116 void IssueBrowser::documentWasSaved(MapDocument* document) { 117 m_view->Refresh(); 118 } 119 nodesWereAdded(const Model::NodeList & nodes)120 void IssueBrowser::nodesWereAdded(const Model::NodeList& nodes) { 121 m_view->reset(); 122 } 123 nodesWereRemoved(const Model::NodeList & nodes)124 void IssueBrowser::nodesWereRemoved(const Model::NodeList& nodes) { 125 m_view->reset(); 126 } 127 nodesDidChange(const Model::NodeList & nodes)128 void IssueBrowser::nodesDidChange(const Model::NodeList& nodes) { 129 m_view->reset(); 130 } 131 brushFacesDidChange(const Model::BrushFaceList & faces)132 void IssueBrowser::brushFacesDidChange(const Model::BrushFaceList& faces) { 133 m_view->reset(); 134 } 135 issueIgnoreChanged(Model::Issue * issue)136 void IssueBrowser::issueIgnoreChanged(Model::Issue* issue) { 137 m_view->Refresh(); 138 } 139 updateFilterFlags()140 void IssueBrowser::updateFilterFlags() { 141 MapDocumentSPtr document = lock(m_document); 142 const Model::World* world = document->world(); 143 const Model::IssueGeneratorList& generators = world->registeredIssueGenerators(); 144 145 wxArrayInt flags; 146 wxArrayString labels; 147 148 Model::IssueGeneratorList::const_iterator it, end; 149 for (it = generators.begin(), end = generators.end(); it != end; ++it) { 150 const Model::IssueGenerator* generator = *it; 151 const Model::IssueType flag = generator->type(); 152 const String& description = generator->description(); 153 154 flags.push_back(flag); 155 labels.push_back(description); 156 } 157 158 m_filterEditor->setFlags(flags, labels); 159 m_view->setHiddenGenerators(0); 160 m_filterEditor->setFlagValue(~0); 161 } 162 } 163 } 164