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 "TextureCollectionEditor.h" 21 22 #include "PreferenceManager.h" 23 #include "Assets/TextureManager.h" 24 #include "Assets/TextureCollection.h" 25 #include "View/ChoosePathTypeDialog.h" 26 #include "View/MapDocument.h" 27 #include "View/ViewConstants.h" 28 #include "View/ViewUtils.h" 29 #include "View/wxUtils.h" 30 31 #include <wx/bmpbuttn.h> 32 #include <wx/filedlg.h> 33 #include <wx/listbox.h> 34 #include <wx/panel.h> 35 #include <wx/sizer.h> 36 37 namespace TrenchBroom { 38 namespace View { TextureCollectionEditor(wxWindow * parent,MapDocumentWPtr document)39 TextureCollectionEditor::TextureCollectionEditor(wxWindow* parent, MapDocumentWPtr document) : 40 wxPanel(parent), 41 m_document(document) { 42 createGui(); 43 bindObservers(); 44 } 45 ~TextureCollectionEditor()46 TextureCollectionEditor::~TextureCollectionEditor() { 47 unbindObservers(); 48 } 49 OnAddTextureCollectionsClicked(wxCommandEvent & event)50 void TextureCollectionEditor::OnAddTextureCollectionsClicked(wxCommandEvent& event) { 51 if (IsBeingDeleted()) return; 52 53 const wxString pathWxStr = ::wxFileSelector("Load Texture Collection", wxEmptyString, wxEmptyString, wxEmptyString, "", wxFD_OPEN); 54 if (pathWxStr.empty()) 55 return; 56 57 loadTextureCollection(m_document, this, pathWxStr); 58 } 59 OnRemoveTextureCollectionsClicked(wxCommandEvent & event)60 void TextureCollectionEditor::OnRemoveTextureCollectionsClicked(wxCommandEvent& event) { 61 if (IsBeingDeleted()) return; 62 63 wxArrayInt selections; 64 m_collections->GetSelections(selections); 65 assert(!selections.empty()); 66 67 MapDocumentSPtr document = lock(m_document); 68 69 const StringList names = document->externalTextureCollectionNames(); 70 StringList removeNames; 71 72 for (size_t i = 0; i < selections.size(); ++i) { 73 const size_t index = static_cast<size_t>(selections[i]); 74 assert(index < names.size()); 75 removeNames.push_back(names[index]); 76 } 77 78 document->removeTextureCollections(removeNames); 79 } 80 OnMoveTextureCollectionUpClicked(wxCommandEvent & event)81 void TextureCollectionEditor::OnMoveTextureCollectionUpClicked(wxCommandEvent& event) { 82 if (IsBeingDeleted()) return; 83 84 wxArrayInt selections; 85 m_collections->GetSelections(selections); 86 assert(selections.size() == 1); 87 88 MapDocumentSPtr document = lock(m_document); 89 90 const StringList names = document->externalTextureCollectionNames(); 91 92 const size_t index = static_cast<size_t>(selections.front()); 93 assert(index > 0 && index < names.size()); 94 95 document->moveTextureCollectionUp(names[index]); 96 m_collections->SetSelection(static_cast<int>(index - 1)); 97 } 98 OnMoveTextureCollectionDownClicked(wxCommandEvent & event)99 void TextureCollectionEditor::OnMoveTextureCollectionDownClicked(wxCommandEvent& event) { 100 if (IsBeingDeleted()) return; 101 102 wxArrayInt selections; 103 m_collections->GetSelections(selections); 104 assert(selections.size() == 1); 105 106 MapDocumentSPtr document = lock(m_document); 107 108 const StringList names = document->externalTextureCollectionNames(); 109 110 const size_t index = static_cast<size_t>(selections.front()); 111 assert(index < names.size() - 1); 112 113 document->moveTextureCollectionDown(names[index]); 114 m_collections->SetSelection(static_cast<int>(index + 1)); 115 } 116 OnUpdateRemoveButtonUI(wxUpdateUIEvent & event)117 void TextureCollectionEditor::OnUpdateRemoveButtonUI(wxUpdateUIEvent& event) { 118 if (IsBeingDeleted()) return; 119 120 wxArrayInt selections; 121 event.Enable(m_collections->GetSelections(selections) > 0); 122 } 123 OnUpdateMoveUpButtonUI(wxUpdateUIEvent & event)124 void TextureCollectionEditor::OnUpdateMoveUpButtonUI(wxUpdateUIEvent& event) { 125 if (IsBeingDeleted()) return; 126 127 wxArrayInt selections; 128 event.Enable(m_collections->GetSelections(selections) == 1 && selections.front() > 0); 129 } 130 OnUpdateMoveDownButtonUI(wxUpdateUIEvent & event)131 void TextureCollectionEditor::OnUpdateMoveDownButtonUI(wxUpdateUIEvent& event) { 132 if (IsBeingDeleted()) return; 133 134 const int collectionCount = static_cast<int>(m_collections->GetCount()); 135 wxArrayInt selections; 136 event.Enable(m_collections->GetSelections(selections) == 1 && selections.front() < collectionCount - 1); 137 } 138 createGui()139 void TextureCollectionEditor::createGui() { 140 static const int ListBoxMargin = 141 #ifdef __APPLE__ 142 0; 143 #else 144 LayoutConstants::NarrowHMargin; 145 #endif 146 147 m_collections = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_MULTIPLE | wxBORDER_NONE); 148 149 wxWindow* addTextureCollectionsButton = createBitmapButton(this, "Add.png", "Add texture collections from the file system"); 150 wxWindow* removeTextureCollectionsButton = createBitmapButton(this, "Remove.png", "Remove the selected texture collections"); 151 wxWindow* moveTextureCollectionUpButton = createBitmapButton(this, "Up.png", "Move the selected texture collection up"); 152 wxWindow* moveTextureCollectionDownButton = createBitmapButton(this, "Down.png", "Move the selected texture collection down"); 153 154 addTextureCollectionsButton->Bind(wxEVT_BUTTON, &TextureCollectionEditor::OnAddTextureCollectionsClicked, this); 155 removeTextureCollectionsButton->Bind(wxEVT_BUTTON, &TextureCollectionEditor::OnRemoveTextureCollectionsClicked, this); 156 moveTextureCollectionUpButton->Bind(wxEVT_BUTTON, &TextureCollectionEditor::OnMoveTextureCollectionUpClicked, this); 157 moveTextureCollectionDownButton->Bind(wxEVT_BUTTON, &TextureCollectionEditor::OnMoveTextureCollectionDownClicked, this); 158 removeTextureCollectionsButton->Bind(wxEVT_UPDATE_UI, &TextureCollectionEditor::OnUpdateRemoveButtonUI, this); 159 moveTextureCollectionUpButton->Bind(wxEVT_UPDATE_UI, &TextureCollectionEditor::OnUpdateMoveUpButtonUI, this); 160 moveTextureCollectionDownButton->Bind(wxEVT_UPDATE_UI, &TextureCollectionEditor::OnUpdateMoveDownButtonUI, this); 161 162 wxSizer* buttonSizer = new wxBoxSizer(wxHORIZONTAL); 163 buttonSizer->Add(addTextureCollectionsButton, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, LayoutConstants::NarrowVMargin); 164 buttonSizer->Add(removeTextureCollectionsButton, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, LayoutConstants::NarrowVMargin); 165 buttonSizer->AddSpacer(LayoutConstants::WideHMargin); 166 buttonSizer->Add(moveTextureCollectionUpButton, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, LayoutConstants::NarrowVMargin); 167 buttonSizer->Add(moveTextureCollectionDownButton, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, LayoutConstants::NarrowVMargin); 168 buttonSizer->AddStretchSpacer(); 169 170 wxSizer* sizer = new wxBoxSizer(wxVERTICAL); 171 sizer->Add(m_collections, 1, wxEXPAND | wxLEFT | wxRIGHT, ListBoxMargin); 172 sizer->Add(buttonSizer, 0, wxEXPAND | wxLEFT | wxRIGHT, LayoutConstants::NarrowHMargin); 173 sizer->SetItemMinSize(m_collections, 100, 70); 174 175 SetBackgroundColour(*wxWHITE); 176 SetSizerAndFit(sizer); 177 } 178 bindObservers()179 void TextureCollectionEditor::bindObservers() { 180 MapDocumentSPtr document = lock(m_document); 181 document->documentWasNewedNotifier.addObserver(this, &TextureCollectionEditor::documentWasNewed); 182 document->documentWasLoadedNotifier.addObserver(this, &TextureCollectionEditor::documentWasLoaded); 183 document->textureCollectionsDidChangeNotifier.addObserver(this, &TextureCollectionEditor::textureCollectionsDidChange); 184 185 PreferenceManager& prefs = PreferenceManager::instance(); 186 prefs.preferenceDidChangeNotifier.addObserver(this, &TextureCollectionEditor::preferenceDidChange); 187 } 188 unbindObservers()189 void TextureCollectionEditor::unbindObservers() { 190 if (!expired(m_document)) { 191 MapDocumentSPtr document = lock(m_document); 192 document->documentWasNewedNotifier.removeObserver(this, &TextureCollectionEditor::documentWasNewed); 193 document->documentWasLoadedNotifier.removeObserver(this, &TextureCollectionEditor::documentWasLoaded); 194 document->textureCollectionsDidChangeNotifier.removeObserver(this, &TextureCollectionEditor::textureCollectionsDidChange); 195 } 196 197 PreferenceManager& prefs = PreferenceManager::instance(); 198 prefs.preferenceDidChangeNotifier.removeObserver(this, &TextureCollectionEditor::preferenceDidChange); 199 } 200 documentWasNewed(MapDocument * document)201 void TextureCollectionEditor::documentWasNewed(MapDocument* document) { 202 updateControls(); 203 } 204 documentWasLoaded(MapDocument * document)205 void TextureCollectionEditor::documentWasLoaded(MapDocument* document) { 206 updateControls(); 207 } 208 textureCollectionsDidChange()209 void TextureCollectionEditor::textureCollectionsDidChange() { 210 updateControls(); 211 } 212 preferenceDidChange(const IO::Path & path)213 void TextureCollectionEditor::preferenceDidChange(const IO::Path& path) { 214 MapDocumentSPtr document = lock(m_document); 215 if (document->isGamePathPreference(path)) 216 updateControls(); 217 } 218 updateControls()219 void TextureCollectionEditor::updateControls() { 220 m_collections->Clear(); 221 222 MapDocumentSPtr document = lock(m_document); 223 const StringList names = document->externalTextureCollectionNames(); 224 StringList::const_iterator it, end; 225 for (it = names.begin(), end = names.end(); it != end; ++it) { 226 const String& name = *it; 227 m_collections->Append(name); 228 } 229 } 230 } 231 } 232