1 #pragma once
2 
3 #include <map>
4 #include "iselection.h"
5 #include "iregistry.h"
6 #include "gtkutil/RegistryConnector.h"
7 #include "gtkutil/TextPanel.h"
8 #include "gtkutil/event/SingleIdleCallback.h"
9 #include "../../ui/common/ShaderChooser.h"
10 #include "../../brush/ContentsFlagsValue.h"
11 #include "../sidebar.h"
12 
13 // Forward declarations to decrease compile times
14 typedef struct _GtkSpinButton GtkSpinButton;
15 typedef struct _GtkEditable GtkEditable;
16 typedef struct _GtkTable GtkTable;
17 typedef struct _GtkWidget GtkWidget;
18 typedef struct _GtkCheckButton GtkCheckButton;
19 namespace gtkutil {
20 class ControlButton;
21 }
22 
23 namespace ui {
24 
25 class SurfaceInspector: public RegistryKeyObserver,
26 		public SelectionSystem::Observer,
27 		public ShaderChooser::ChooserClient,
28 		public SidebarComponent,
29 		public gtkutil::SingleIdleCallback {
30 		// The actual dialog window
31 		GtkWidget* _dialogVBox;
32 
33 		typedef gtkutil::ControlButton* ControlButtonPtr;
34 
35 		struct ManipulatorRow
36 		{
37 				GtkWidget* hbox;
38 				GtkWidget* label;
39 				GtkWidget* value;
40 				gulong valueChangedHandler;
41 				ControlButtonPtr smaller;
42 				ControlButtonPtr larger;
43 				GtkWidget* step;
44 				GtkWidget* steplabel;
45 		};
46 
47 		// This are the named manipulator rows (shift, scale, rotation, etc)
48 		typedef std::map<std::string, ManipulatorRow> ManipulatorMap;
49 		ManipulatorMap _manipulators;
50 
51 		GtkCheckButton* _surfaceFlags[32];
52 		GtkCheckButton* _contentFlags[32];
53 
54 		// The "shader" entry field
55 		GtkWidget* _shaderEntry;
56 		GtkWidget* _selectShaderButton;
57 
58 		ContentsFlagsValue _selectedFlags;
59 
60 		struct FitTextureWidgets
61 		{
62 				GtkWidget* hbox;
63 				GtkObject* widthAdj;
64 				GtkObject* heightAdj;
65 				GtkWidget* width;
66 				GtkWidget* height;
67 				GtkWidget* button;
68 				GtkWidget* label;
69 		} _fitTexture;
70 
71 		struct FlipTextureWidgets
72 		{
73 				GtkWidget* hbox;
74 				GtkWidget* flipX;
75 				GtkWidget* flipY;
76 				GtkWidget* label;
77 		} _flipTexture;
78 
79 		struct ApplyTextureWidgets
80 		{
81 				GtkWidget* hbox;
82 				GtkWidget* label;
83 				GtkWidget* natural;
84 		} _applyTex;
85 
86 		GtkWidget* _defaultTexScale;
87 		GtkWidget* _texLockButton;
88 
89 		gtkutil::TextPanel _valueEntryWidget;
90 		// if more than one of the selected objects has a value set, this is inconsistent and we can't know which we should take
91 		// So in this case we just don't change the old value until we explicitly edit the value entry field
92 		bool _valueInconsistent;
93 
94 		// To avoid key changed loopbacks when the registry is updated
95 		bool _callbackActive;
96 
97 		// This member takes care of importing/exporting Registry
98 		// key values from and to widgets
99 		gtkutil::RegistryConnector _connector;
100 
101 		// A reference to the SelectionInfo structure (with the counters)
102 		const SelectionInfo& _selectionInfo;
103 
104 	public:
105 
106 		// Constructor
107 		SurfaceInspector ();
108 
109 		~SurfaceInspector ();
110 
111 		/** Connect and updates the widgets
112 		 */
113 		void init ();
114 
115 		/** greebo: Some sort of "soft" destructor that de-registers
116 		 * this class from the SelectionSystem, etc.
117 		 */
118 		void shutdown ();
119 
120 		/** greebo: Contains the static instance of this dialog.
121 		 * Constructs the instance and calls toggle() when invoked.
122 		 */
123 		static SurfaceInspector& Instance ();
124 
125 		/** greebo: Gets called when the default texscale registry key changes
126 		 */
127 		void keyChanged (const std::string&, const std::string&);
128 
129 		/** greebo: SelectionSystem::Observer implementation. Gets called by
130 		 * the SelectionSystem upon selection change to allow updating of the
131 		 * texture properties.
132 		 */
133 		void selectionChanged (scene::Instance& instance, bool isComponent);
134 
135 		// Updates the widgets
136 		void queueUpdate ();
137 
138 		/** greebo: Gets called upon shader selection change (during ShaderChooser display)
139 		 */
140 		void shaderSelectionChanged (const std::string& shaderName);
141 
142 		GtkWidget* getWidget () const;
143 
144 		const std::string getTitle() const;
145 
146 		void switchPage (int pageIndex);
147 
148 		// Executes the fit command for the selection
149 		void fitTexture ();
150 
151 		// Idle callback, used for deferred updates
152 		void onGtkIdle();
153 	private:
154 		// Updates the widgets (this is private, use queueUpdate() instead)
155 		void update();
156 
157 		/** greebo: Creates a row consisting of label, value entry,
158 		 * two arrow buttons and a step entry field.
159 		 *
160 		 * @table: the GtkTable the row should be packed into.
161 		 * @row: the target row number (first table row = 0).
162 		 *
163 		 * @returns: the structure containing the widget pointers.
164 		 */
165 		ManipulatorRow createManipulatorRow (const std::string& label, GtkTable* table, int row, bool vertical);
166 
167 		const std::string& getContentFlagName (std::size_t bit) const;
168 
169 		const std::string& getSurfaceFlagName (std::size_t bit) const;
170 
171 		// Adds all the widgets to the window
172 		void populateWindow ();
173 
174 		// Connect IEvents to the widgets
175 		void connectEvents ();
176 
177 		// Updates the content- and surfaceflags
178 		void updateFlags ();
179 
180 		// Updates the texture shift/scale/rotation fields
181 		void updateTexDef ();
182 
183 		// The counter-part of updateTexDef() - emits the TexCoords to the selection
184 		void emitTexDef ();
185 
186 		// Applies the entered shader to the current selection
187 		void emitShader ();
188 
189 		void updateFlagButtons ();
190 
191 		void setFlagsForSelected (const ContentsFlagsValue& flags);
192 
193 		// Saves the connected widget content into the registry
194 		void saveToRegistry ();
195 
196 		// The callback when the "select shader" button is pressed, opens the ShaderChooser dialog
197 		static void onShaderSelect (GtkWidget* button, SurfaceInspector* self);
198 
199 		// The callback for the delete event (toggles the visibility)
200 		static gboolean onDelete (GtkWidget* widget, GdkEvent* event, SurfaceInspector* self);
201 
202 		// Gets called when the step entry fields get changed
203 		static void onStepChanged (GtkEditable* editable, SurfaceInspector* self);
204 
205 		// Gets called when the value entry field is changed (shift/scale/rotation) - emits the texcoords
206 		static gboolean onDefaultScaleChanged (GtkSpinButton* spinbutton, SurfaceInspector* self);
207 
208 		// The callback for the Fit Texture button
209 		static gboolean onFit (GtkWidget* widget, SurfaceInspector* self);
210 		static gboolean doUpdate (GtkWidget* widget, SurfaceInspector* self);
211 
212 		// the callback for the surface flag value
213 		static void onValueToggle (GtkWidget *widget, SurfaceInspector *self);
214 
215 		// the callback for the flags toggle
216 		static void onApplyFlagsToggle (GtkWidget *activatedWidget, SurfaceInspector *self);
217 
218 		// The keypress handler for catching the Enter key when in the shader entry field
219 		static gboolean onKeyPress (GtkWidget* entry, GdkEventKey* event, SurfaceInspector* self);
220 
221 		// The keypress handler for catching the Enter key when in the value entry fields
222 		static gboolean onValueKeyPress (GtkWidget* entry, GdkEventKey* event, SurfaceInspector* self);
223 
224 		// the callback for changing the surface property value like e.g. the light intensity for surface lights
225 		static gboolean onValueEntryKeyPress (GtkWindow* window, GdkEventKey* event, SurfaceInspector* self);
226 
227 		// the callback that changes the value when we focus-out the entry field
228 		static gboolean onValueEntryFocusOut (GtkWidget* widget, GdkEventKey* event, SurfaceInspector* self);
229 }; // class SurfaceInspector
230 
231 } // namespace ui
232