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 "FrameManager.h"
21 
22 #include "Exceptions.h"
23 #include "Macros.h"
24 #include "View/MapDocument.h"
25 #include "View/MapDocumentCommandFacade.h"
26 #include "View/MapFrame.h"
27 
28 #include <cassert>
29 
30 #include <wx/display.h>
31 #include <wx/persist.h>
32 #include <wx/persist/toplevel.h>
33 
34 namespace TrenchBroom {
35     namespace View {
FrameManager(const bool singleFrame)36         FrameManager::FrameManager(const bool singleFrame) :
37         m_singleFrame(singleFrame),
38         m_topFrame(NULL) {}
39 
~FrameManager()40         FrameManager::~FrameManager() {
41             closeAllFrames(true);
42         }
43 
newFrame()44         MapFrame* FrameManager::newFrame() {
45             return createOrReuseFrame();
46         }
47 
frames() const48         FrameList FrameManager::frames() const {
49             return m_frames;
50         }
51 
closeAllFrames()52         bool FrameManager::closeAllFrames() {
53             return closeAllFrames(false);
54         }
55 
allFramesClosed() const56         bool FrameManager::allFramesClosed() const {
57             return m_frames.empty();
58         }
59 
OnFrameActivate(wxActivateEvent & event)60         void FrameManager::OnFrameActivate(wxActivateEvent& event) {
61             if (event.GetActive())
62                 m_topFrame = static_cast<MapFrame*>(event.GetEventObject());
63             event.Skip();
64         }
65 
createOrReuseFrame()66         MapFrame* FrameManager::createOrReuseFrame() {
67             assert(!m_singleFrame || m_frames.size() <= 1);
68             if (!m_singleFrame || m_frames.empty()) {
69                 MapDocumentSPtr document = MapDocumentCommandFacade::newMapDocument();
70                 MapFrame* frame = createFrame(document);
71                 m_frames.push_back(frame);
72             }
73             return m_frames.back();
74         }
75 
createFrame(MapDocumentSPtr document)76         MapFrame* FrameManager::createFrame(MapDocumentSPtr document) {
77             MapFrame* frame = new MapFrame(this, document);
78             frame->SetName("MapFrame");
79             if (!wxPersistenceManager::Get().RegisterAndRestore(frame))
80                frame->positionOnScreen(m_topFrame);
81 
82             frame->Bind(wxEVT_ACTIVATE, &FrameManager::OnFrameActivate, this);
83             frame->Show();
84             frame->Raise();
85             return frame;
86         }
87 
closeAllFrames(bool force)88         bool FrameManager::closeAllFrames(bool force) {
89             MapFrame* lastFrame = NULL;
90             unused(lastFrame);
91             while (!m_frames.empty()) {
92                 MapFrame* frame = m_frames.front();
93                 assert(frame != lastFrame);
94                 if (!frame->Close(force))
95                     return false;
96             }
97             assert(m_frames.empty());
98             return true;
99         }
100 
removeAndDestroyFrame(MapFrame * frame)101         void FrameManager::removeAndDestroyFrame(MapFrame* frame) {
102             FrameList::iterator it = std::find(m_frames.begin(), m_frames.end(), frame);
103             if (it != m_frames.end()) // On OS X, we sometimes get two close events for a frame when terminating the app from the dock.
104                 m_frames.erase(it);
105 
106             if (m_topFrame == frame)
107                 m_topFrame = NULL;
108 
109             frame->Unbind(wxEVT_ACTIVATE, &FrameManager::OnFrameActivate, this);
110             // wxPersistenceManager::Get().SaveAndUnregister(frame);
111             frame->Destroy();
112         }
113     }
114 }
115