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 "SelectionCommand.h"
21 
22 #include "Macros.h"
23 #include "Model/Brush.h"
24 #include "Model/EditorContext.h"
25 #include "Model/Entity.h"
26 #include "Model/Group.h"
27 #include "Model/NodeVisitor.h"
28 #include "Model/World.h"
29 #include "View/MapDocumentCommandFacade.h"
30 
31 namespace TrenchBroom {
32     namespace View {
33         const Command::CommandType SelectionCommand::Type = Command::freeType();
34 
select(const Model::NodeList & nodes)35         SelectionCommand* SelectionCommand::select(const Model::NodeList& nodes) {
36             return new SelectionCommand(Action_SelectNodes, nodes, Model::EmptyBrushFaceList);
37         }
38 
select(const Model::BrushFaceList & faces)39         SelectionCommand* SelectionCommand::select(const Model::BrushFaceList& faces) {
40             return new SelectionCommand(Action_SelectFaces, Model::EmptyNodeList, faces);
41         }
42 
convertToFaces()43         SelectionCommand* SelectionCommand::convertToFaces() {
44             return new SelectionCommand(Action_ConvertToFaces, Model::EmptyNodeList, Model::EmptyBrushFaceList);
45         }
46 
selectAllNodes()47         SelectionCommand* SelectionCommand::selectAllNodes() {
48             return new SelectionCommand(Action_SelectAllNodes, Model::EmptyNodeList, Model::EmptyBrushFaceList);
49         }
50 
selectAllFaces()51         SelectionCommand* SelectionCommand::selectAllFaces() {
52             return new SelectionCommand(Action_SelectAllFaces, Model::EmptyNodeList, Model::EmptyBrushFaceList);
53         }
54 
deselect(const Model::NodeList & nodes)55         SelectionCommand* SelectionCommand::deselect(const Model::NodeList& nodes) {
56             return new SelectionCommand(Action_DeselectNodes, nodes, Model::EmptyBrushFaceList);
57         }
58 
deselect(const Model::BrushFaceList & faces)59         SelectionCommand* SelectionCommand::deselect(const Model::BrushFaceList& faces) {
60             return new SelectionCommand(Action_DeselectFaces, Model::EmptyNodeList, faces);
61         }
62 
deselectAll()63         SelectionCommand* SelectionCommand::deselectAll() {
64             return new SelectionCommand(Action_DeselectAll, Model::EmptyNodeList, Model::EmptyBrushFaceList);
65         }
66 
SelectionCommand(const Action action,const Model::NodeList & nodes,const Model::BrushFaceList & faces)67         SelectionCommand::SelectionCommand(const Action action, const Model::NodeList& nodes, const Model::BrushFaceList& faces) :
68         UndoableCommand(Type, makeName(action, nodes, faces)),
69         m_action(action),
70         m_nodes(nodes),
71         m_faces(faces) {}
72 
makeName(const Action action,const Model::NodeList & nodes,const Model::BrushFaceList & faces)73         String SelectionCommand::makeName(const Action action, const Model::NodeList& nodes, const Model::BrushFaceList& faces) {
74             StringStream result;
75             switch (action) {
76                 case Action_SelectNodes:
77                     result << "Select " << nodes.size() << " " << StringUtils::safePlural(nodes.size(), "Object", "Objects");
78                     break;
79                 case Action_SelectFaces:
80                     result << "Select " << faces.size() << " " << StringUtils::safePlural(nodes.size(), "Brush Face", "Brush Faces");
81                     break;
82                 case Action_SelectAllNodes:
83                     result << "Select All Objects";
84                     break;
85                 case Action_SelectAllFaces:
86                     result << "Select All Brush Faces";
87                     break;
88                 case Action_ConvertToFaces:
89                     result << "Convert to Brush Face Selection";
90                     break;
91                 case Action_DeselectNodes:
92                     result << "Deselect " << nodes.size() << " " << StringUtils::safePlural(nodes.size(), "Object", "Objects");
93                     break;
94                 case Action_DeselectFaces:
95                     result << "Deselect " << faces.size() << " " << StringUtils::safePlural(nodes.size(), "Brush Face", "Brush Faces");
96                     break;
97                 case Action_DeselectAll:
98                     return "Select None";
99                 switchDefault()
100             }
101             return result.str();
102         }
103 
doPerformDo(MapDocumentCommandFacade * document)104         bool SelectionCommand::doPerformDo(MapDocumentCommandFacade* document) {
105             m_previouslySelectedNodes = document->selectedNodes().nodes();
106             m_previouslySelectedFaces = document->selectedBrushFaces();
107 
108             switch (m_action) {
109                 case Action_SelectNodes:
110                     document->performSelect(m_nodes);
111                     break;
112                 case Action_SelectFaces:
113                     document->performSelect(m_faces);
114                     break;
115                 case Action_SelectAllNodes:
116                     document->performSelectAllNodes();
117                     break;
118                 case Action_SelectAllFaces:
119                     document->performSelectAllBrushFaces();
120                     break;
121                 case Action_ConvertToFaces:
122                     document->performConvertToBrushFaceSelection();
123                     break;
124                 case Action_DeselectNodes:
125                     document->performDeselect(m_nodes);
126                     break;
127                 case Action_DeselectFaces:
128                     document->performDeselect(m_faces);
129                     break;
130                 case Action_DeselectAll:
131                     document->performDeselectAll();
132                     break;
133             }
134             return true;
135         }
136 
doPerformUndo(MapDocumentCommandFacade * document)137         bool SelectionCommand::doPerformUndo(MapDocumentCommandFacade* document) {
138             document->performDeselectAll();
139             if (!m_previouslySelectedNodes.empty())
140                 document->performSelect(m_previouslySelectedNodes);
141             if (!m_previouslySelectedFaces.empty())
142                 document->performSelect(m_previouslySelectedFaces);
143             return true;
144         }
145 
doIsRepeatDelimiter() const146         bool SelectionCommand::doIsRepeatDelimiter() const {
147             return true;
148         }
149 
doIsRepeatable(MapDocumentCommandFacade * document) const150         bool SelectionCommand::doIsRepeatable(MapDocumentCommandFacade* document) const {
151             return false;
152         }
153 
doCollateWith(UndoableCommand::Ptr command)154         bool SelectionCommand::doCollateWith(UndoableCommand::Ptr command) {
155             return false;
156         }
157     }
158 }
159