1 /* Copyright (C) 2014 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef INCLUDED_TOOLS 19 #define INCLUDED_TOOLS 20 21 #include "General/AtlasWindowCommand.h" 22 #include "General/Observable.h" 23 24 class wxMouseEvent; 25 class wxKeyEvent; 26 class ScenarioEditor; 27 28 class ITool : public wxObject 29 { 30 public: 31 enum KeyEventType { KEY_DOWN, KEY_UP, KEY_CHAR }; 32 33 virtual void Init(void* initData, ScenarioEditor* scenarioEditor) = 0; 34 virtual void Shutdown() = 0; 35 virtual bool OnMouse(wxMouseEvent& evt) = 0; // return true if handled 36 virtual bool OnKey(wxKeyEvent& evt, KeyEventType dir) = 0; // return true if handled 37 virtual void OnTick(float dt) = 0; // dt in seconds 38 virtual void OnCommand(const wxString& command, void* userData) = 0; 39 ~ITool()40 virtual ~ITool() {}; 41 }; 42 43 struct ToolManagerImpl; 44 class ToolManager 45 { 46 private: // NONCOPYABLE 47 ToolManager(const ToolManager&); 48 const ToolManager& operator=(const ToolManager&); 49 50 public: 51 ToolManager(ScenarioEditor* scenarioEditor); 52 ~ToolManager(); 53 ObservablePtr<ITool>& GetCurrentTool(); 54 wxString GetCurrentToolName(); 55 void SetCurrentTool(const wxString& name, void* initData = NULL); 56 private: 57 ToolManagerImpl* m; 58 ScenarioEditor* m_ScenarioEditor; 59 }; 60 61 class ToolButton; 62 extern void RegisterToolButton(ToolButton* button, const wxString& toolName); 63 extern void RegisterToolBarButton(wxToolBar* toolbar, int buttonId, const wxString& toolName); 64 65 ////////////////////////////////////////////////////////////////////////// 66 67 68 namespace AtlasMessage { struct mWorldCommand; } 69 class WorldCommand : public AtlasWindowCommand 70 { 71 DECLARE_CLASS(WorldCommand); 72 73 bool m_AlreadyDone; 74 public: 75 WorldCommand(AtlasMessage::mWorldCommand* command); 76 ~WorldCommand(); 77 bool Do(); 78 bool Undo(); 79 bool Merge(AtlasWindowCommand* previousCommand); 80 81 private: 82 AtlasMessage::mWorldCommand* m_Command; 83 }; 84 85 #define POST_COMMAND(type, data) ScenarioEditor::GetCommandProc().Submit(new WorldCommand(new AtlasMessage::m##type(AtlasMessage::d##type data))) 86 87 ////////////////////////////////////////////////////////////////////////// 88 89 #define SET_STATE(s) obj->SetState(&obj->s) 90 91 template <typename T> 92 class StateDrivenTool : public ITool 93 { 94 public: StateDrivenTool()95 StateDrivenTool() 96 : m_CurrentState(&Disabled), m_ScenarioEditor(NULL) 97 { 98 } 99 Init(void * WXUNUSED (initData),ScenarioEditor * scenarioEditor)100 virtual void Init(void* WXUNUSED(initData), ScenarioEditor* scenarioEditor) 101 { 102 m_ScenarioEditor = scenarioEditor; 103 } 104 Shutdown()105 virtual void Shutdown() 106 { 107 // This can't be done in the destructor, because ~StateDrivenTool 108 // is not called until after the subclass has been destroyed and its 109 // vtable (containing OnDisable) has been removed. 110 SetState(&Disabled); 111 } 112 113 protected: 114 // Called when the tool is enabled/disabled; always called in zero or 115 // more enable-->disable pairs per object instance. OnEnable()116 virtual void OnEnable() {} OnDisable()117 virtual void OnDisable() {} 118 119 struct State 120 { ~StateState121 virtual ~State() {} OnEnterState122 virtual void OnEnter(T* WXUNUSED(obj)) {} OnLeaveState123 virtual void OnLeave(T* WXUNUSED(obj)) {} OnTickState124 virtual void OnTick (T* WXUNUSED(obj), float WXUNUSED(dt)) {} 125 126 // Should return true if the event has been handled (else the event will 127 // be passed to a lower-priority level) OnMouseState128 virtual bool OnMouse(T* WXUNUSED(obj), wxMouseEvent& WXUNUSED(evt)) { return false; } OnKeyState129 virtual bool OnKey(T* WXUNUSED(obj), wxKeyEvent& WXUNUSED(evt), KeyEventType WXUNUSED(type)) { return false; } 130 }; 131 132 133 struct sDisabled : public State 134 { OnEntersDisabled135 void OnEnter(T* obj) { obj->OnDisable(); } OnLeavesDisabled136 void OnLeave(T* obj) { obj->OnEnable(); } 137 } 138 Disabled; 139 SetState(State * state)140 void SetState(State* state) 141 { 142 m_CurrentState->OnLeave(static_cast<T*>(this)); 143 // this cast is safe as long as the class is used as in 144 // "class Something : public StateDrivenTool<Something> { ... }" 145 m_CurrentState = state; 146 m_CurrentState->OnEnter(static_cast<T*>(this)); 147 } 148 GetScenarioEditor()149 ScenarioEditor& GetScenarioEditor() { wxASSERT(m_ScenarioEditor); return *m_ScenarioEditor; } 150 151 private: 152 State* m_CurrentState; 153 154 ScenarioEditor* m_ScenarioEditor; // not NULL, except before Init has been called 155 OnMouse(wxMouseEvent & evt)156 virtual bool OnMouse(wxMouseEvent& evt) 157 { 158 return m_CurrentState->OnMouse(static_cast<T*>(this), evt); 159 } 160 OnKey(wxKeyEvent & evt,KeyEventType dir)161 virtual bool OnKey(wxKeyEvent& evt, KeyEventType dir) 162 { 163 return m_CurrentState->OnKey(static_cast<T*>(this), evt, dir); 164 } 165 OnTick(float dt)166 virtual void OnTick(float dt) 167 { 168 m_CurrentState->OnTick(static_cast<T*>(this), dt); 169 } 170 OnCommand(const wxString & WXUNUSED (command),void * WXUNUSED (userData))171 virtual void OnCommand(const wxString& WXUNUSED(command), void* WXUNUSED(userData)) 172 { 173 } 174 }; 175 176 177 #endif // INCLUDED_TOOLS 178