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