1 /*
2  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3  * Distributed under the MIT License
4  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5  */
6 
7 #ifndef MYGUI_WIDGET_H_
8 #define MYGUI_WIDGET_H_
9 
10 #include "MyGUI_Prerequest.h"
11 #include "MyGUI_Any.h"
12 #include "MyGUI_ICroppedRectangle.h"
13 #include "MyGUI_WidgetUserData.h"
14 #include "MyGUI_WidgetInput.h"
15 #include "MyGUI_ResourceSkin.h"
16 #include "MyGUI_ResourceLayout.h"
17 #include "MyGUI_IObject.h"
18 #include "MyGUI_SkinItem.h"
19 #include "MyGUI_BackwardCompatibility.h"
20 
21 namespace MyGUI
22 {
23 
24 	typedef delegates::CMultiDelegate3<Widget*, const std::string&, const std::string&> EventHandle_WidgetStringString;
25 
26 	/** \brief @wpage{Widget}
27 		Widget widget description should be here.
28 	*/
29 	class MYGUI_EXPORT Widget :
30 		public IObject,
31 		public ICroppedRectangle,
32 		public UserData,
33 		public WidgetInput,
34 		public delegates::IDelegateUnlink,
35 		public SkinItem,
36 		public MemberObsolete<Widget>
37 	{
38 		// для вызова закрытых деструкторов
39 		friend class WidgetManager;
40 
41 		MYGUI_RTTI_DERIVED( Widget )
42 
43 	public:
44 		Widget();
45 
46 		/** Create child widget
47 			@param _type widget type
48 			@param _skin widget skin
49 			@param _coord int coordinates of widget (_left, _top, _width, _height)
50 			@param _align widget align (possible values can be found in enum Align)
51 			@param _name if needed (you can use it for finding widget by name later)
52 		*/
53 		Widget* createWidgetT(const std::string& _type, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _name = "");
54 
55 		/** See Widget::createWidgetT(const std::string& _type, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _name = "") */
56 		Widget* createWidgetT(const std::string& _type, const std::string& _skin, int _left, int _top, int _width, int _height, Align _align, const std::string& _name = "");
57 
58 		/** Create widget using coordinates relative to parent. see Widget::createWidgetT(const std::string& _type, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _name = "") */
59 		Widget* createWidgetRealT(const std::string& _type, const std::string& _skin, const FloatCoord& _coord, Align _align, const std::string& _name = "");
60 
61 		/** Create widget using coordinates relative to parent. see Widget::createWidgetT(const std::string& _type, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _name = "") */
62 		Widget* createWidgetRealT(const std::string& _type, const std::string& _skin, float _left, float _top, float _width, float _height, Align _align, const std::string& _name = "");
63 
64 		// templates for creating widgets by type
65 		/** Same as Widget::createWidgetT but return T pointer instead of Widget* */
66 		template <typename T>
67 		T* createWidget(const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _name = "")
68 		{
69 			return static_cast<T*>(createWidgetT(T::getClassTypeName(), _skin, _coord, _align, _name));
70 		}
71 
72 		/** Same as Widget::createWidgetT but return T pointer instead of Widget* */
73 		template <typename T>
74 		T* createWidget(const std::string& _skin, int _left, int _top, int _width, int _height, Align _align, const std::string& _name = "")
75 		{
76 			return static_cast<T*>(createWidgetT(T::getClassTypeName(), _skin, IntCoord(_left, _top, _width, _height), _align, _name));
77 		}
78 
79 		/** Same as Widget::createWidgetRealT but return T* instead of Widget* */
80 		template <typename T>
81 		T* createWidgetReal(const std::string& _skin, const FloatCoord& _coord, Align _align, const std::string& _name = "")
82 		{
83 			return static_cast<T*>(createWidgetRealT(T::getClassTypeName(), _skin, _coord, _align, _name));
84 		}
85 
86 		/** Same as Widget::createWidgetRealT but return T* instead of Widget* */
87 		template <typename T>
88 		T* createWidgetReal(const std::string& _skin, float _left, float _top, float _width, float _height, Align _align, const std::string& _name = "")
89 		{
90 			return static_cast<T*>(createWidgetRealT(T::getClassTypeName(), _skin, _left, _top, _width, _height, _align, _name));
91 		}
92 
93 		/** Create child widget
94 			@param _style Child, Popup or Overlapped widget style
95 			@param _type widget type
96 			@param _skin widget skin
97 			@param _coord int coordinates of widget (_left, _top, _width, _height)
98 			@param _align widget align (possible values can be found in enum Align)
99 			@param _layer layer where widget will be created (all layers usually defined in core_layer.xml file).
100 			@param _name optional widget name (you can use it for finding widget by name later)
101 		*/
102 		Widget* createWidgetT(WidgetStyle _style, const std::string& _type, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _layer = "", const std::string& _name = "");
103 
104 		/** Same as Widget::createWidgetT but return T* instead of Widget* */
105 		template <typename T>
106 		T* createWidget(WidgetStyle _style, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _layer = "", const std::string& _name = "")
107 		{
108 			return static_cast<T*>(createWidgetT(_style, T::getClassTypeName(), _skin, _coord, _align, _layer, _name));
109 		}
110 
111 		/** Set widget position (position of left top corner) */
112 		void setPosition(const IntPoint& _value) override;
113 		/** Set widget size */
114 		void setSize(const IntSize& _value) override;
115 		/** Set widget position and size */
116 		void setCoord(const IntCoord& _value) override;
117 
118 		/** See Widget::setPosition(const IntPoint& _pos) */
119 		void setPosition(int _left, int _top);
120 		/** See Widget::setSize(const IntSize& _size) */
121 		void setSize(int _width, int _height);
122 		/** See Widget::setCoord(const IntCoord& _coord) */
123 		void setCoord(int _left, int _top, int _width, int _height);
124 
125 		/** Set widget position (position of left top corner)*/
126 		void setRealPosition(const FloatPoint& _value);
127 		/** Set widget size */
128 		void setRealSize(const FloatSize& _value);
129 		/** Set widget position and size*/
130 		void setRealCoord(const FloatCoord& _value);
131 
132 		/** See Widget::setRealPosition(const FloatPoint& _point) */
133 		void setRealPosition(float _left, float _top);
134 		/** See Widget::setRealSize(const FloatSize& _size) */
135 		void setRealSize(float _width, float _height);
136 		/** See Widget::setRealPosition(const FloatCoord& _coord) */
137 		void setRealCoord(float _left, float _top, float _width, float _height);
138 
139 		//! Get name of widget
140 		const std::string& getName() const;
141 
142 		/** Hide or show widget */
143 		virtual void setVisible(bool _value);
144 		/** Return true if visible */
145 		bool getVisible() const;
146 
147 		/** Set child widget rendering depth for ordering child widgets.
148 			Widget with higher depth is rendered below widget with lower depth.
149 			Available only for child widgets. For root widgets use layer property instead.
150 		*/
151 		void setDepth(int _value);
152 		/** Get child widget rendering depth */
153 		int getDepth() const;
154 
155 		/** Return widget's visibility based on it's and parents visibility. */
156 		bool getInheritedVisible() const;
157 
158 		/** Set align */
159 		virtual void setAlign(Align _value);
160 		/** Get align */
161 		Align getAlign() const;
162 
163 		/** Set widget opacity */
164 		void setAlpha(float _value);
165 		/** Get widget opacity */
166 		float getAlpha() const;
167 
168 		/** Enable or disable inherits alpha mode.\n
169 			Inherits alpha mode: when enabled widget alpha is it's own
170 			alpha value multiplied by parent's real alpha (that depend
171 			on parent's parent and so on).\n
172 			When disabled widget's alpha doesn't depend on parent's alpha.
173 			So this is used when you need things like semi-transparent
174 			window with non-transparent text on it and window's alpha
175 			changes.\n
176 			Enabled (true) by default.
177 		*/
178 		void setInheritsAlpha(bool _value);
179 		/** Get inherits alpha mode flag */
180 		bool getInheritsAlpha() const;
181 
182 		void setColour(const Colour& _value);
183 
184 		// являемся ли мы рутовым виджетом
185 		/** Is this widget is root widget (root == without parents) */
186 		bool isRootWidget() const;
187 
188 		/** Get parent widget or nullptr if no parent */
189 		Widget* getParent() const;
190 
191 		IntSize getParentSize() const;
192 
193 		/** Get child widgets Enumerator */
194 		EnumeratorWidgetPtr getEnumerator() const;
195 
196 		/** Get child count */
197 		size_t getChildCount();
198 
199 		/** Get child by index (index from 0 to child_count - 1) */
200 		Widget* getChildAt(size_t _index);
201 
202 		/** Find widget by name.
203 			Search recursively through all childs starting from this widget.
204 			@return Return first found widget with given name
205 		*/
206 		Widget* findWidget(const std::string& _name);
207 
208 		/** Find all widgets with given name and add them into _result.
209 			Search recursively through all childs starting from this widget.
210 		*/
211 		void findWidgets(const std::string& _name, VectorWidgetPtr& _result);
212 
213 		/** Enable or disable widget */
214 		virtual void setEnabled(bool _value);
215 		/** Enable or disable widget without changing widget's state */
216 		void setEnabledSilent(bool _value);
217 		/** Is widget enabled */
218 		bool getEnabled() const;
219 
220 		/** Is widget enabled and all it's parents in hierarchy are enabled. */
221 		bool getInheritedEnabled() const;
222 
223 		/** Get rectangle where child widgets placed */
224 		IntCoord getClientCoord();
225 
226 		/** Get client area widget or nullptr if widget don't have client */
227 		Widget* getClientWidget();
228 		const Widget* getClientWidget() const;
229 
230 		/** Detach widget from widgets hierarchy
231 			@param _layer Attach to specified layer (if any)
232 		*/
233 		void detachFromWidget(const std::string& _layer = "");
234 
235 		/** Attach widget to parent
236 			@param _parent New parent
237 			@param _style New widget style (see WidgetStyle::Enum)
238 			@param _layer Attach to specified layer (if any)
239 		*/
240 		void attachToWidget(Widget* _parent, WidgetStyle _style = WidgetStyle::Child, const std::string& _layer = "");
241 
242 		/** Change widget skin */
243 		void changeWidgetSkin(const std::string& _skinName);
244 
245 		/** Set widget style.
246 			@param _style New widget style (see WidgetStyle::Enum)
247 			@param _layer Attach to specified layer (if any)
248 			@note When choosing WidgetStyle::Popup style you also need attach widget to layer
249 		*/
250 		void setWidgetStyle(WidgetStyle _style, const std::string& _layer = "");
251 		/** Get widget style */
252 		WidgetStyle getWidgetStyle() const;
253 
254 		/** Set any widget property
255 			@param _key Property name (for example Alpha or Enabled)
256 			@param _value Value converted to string
257 		*/
258 		void setProperty(const std::string& _key, const std::string& _value);
259 
260 
261 		/** Event : Widget property changed through setProperty (in code, or from layout)\n
262 			signature : void method(MyGUI::Widget* _sender, const std::string& _key, const std::string& _value);
263 			@param _sender widget that called this event
264 			@param _key
265 			@param _value
266 		*/
267 		EventHandle_WidgetStringString eventChangeProperty;
268 
269 		/** Event : Widget coordinate changed (widget was resized or moved).\n
270 			signature : void method(MyGUI::Widget* _sender)
271 			@param _sender widget that called this event
272 		*/
273 		EventHandle_WidgetVoid eventChangeCoord;
274 
275 		/*internal:*/
276 		// метод для запроса номера айтема и контейнера
277 		virtual size_t _getItemIndex(Widget* _item);
278 
279 		// дает приоритет виджету при пиккинге
280 		void _forcePick(Widget* _widget);
281 
282 		void _initialise(WidgetStyle _style, const IntCoord& _coord, const std::string& _skinName, Widget* _parent, ICroppedRectangle* _croppedParent, const std::string& _name);
283 		void _shutdown();
284 
285 		// удяляет неудачника
286 		void _destroyChildWidget(Widget* _widget);
287 
288 		void _setContainer(Widget* _value);
289 		Widget* _getContainer();
290 
291 		void _setAlign(const IntSize& _oldsize, const IntSize& _newSize);
292 		bool _checkPoint(int _left, int _top) const;
293 
294 		Widget* _createSkinWidget(WidgetStyle _style, const std::string& _type, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _layer = "", const std::string& _name = "");
295 
296 		// сброс всех данных контейнера, тултипы и все остальное
297 		virtual void _resetContainer(bool _update);
298 
299 		bool _setWidgetState(const std::string& _value);
300 
301 		// перерисовывает детей
302 		void _updateChilds();
303 
304 	protected:
305 		// все создание только через фабрику
306 		~Widget() override = default;
307 
308 		virtual void shutdownOverride();
309 		virtual void initialiseOverride();
310 
311 		void _updateView(); // обновления себя и детей
312 
313 		// создает виджет
314 		Widget* baseCreateWidget(WidgetStyle _style, const std::string& _type, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _layer, const std::string& _name, bool _template);
315 
316 		// удаляет всех детей
317 		void _destroyAllChildWidget();
318 
319 		// запрашиваем у конейтера айтем по позиции мыши
320 		virtual size_t _getContainerIndex(const IntPoint& _point);
321 
322 		virtual void baseUpdateEnable();
323 
324 		// наследуемся он LayerInfo
325 		ILayerItem* getLayerItemByPoint(int _left, int _top) const override;
326 		const IntCoord& getLayerItemCoord() const override;
327 
328 		template <typename T>
assignWidget(T * & _widget,const std::string & _name)329 		void assignWidget(T*& _widget, const std::string& _name)
330 		{
331 			_widget = nullptr;
332 			for (VectorWidgetPtr::iterator iter = mWidgetChildSkin.begin(); iter != mWidgetChildSkin.end(); ++iter)
333 			{
334 				Widget* find = (*iter)->findWidget(_name);
335 				if (nullptr != find)
336 				{
337 					_widget = find->castType<T>(false);
338 					break;
339 				}
340 			}
341 		}
342 
343 		VectorWidgetPtr getSkinWidgetsByName(const std::string& _name);
344 
345 		void destroySkinWidget(Widget* _widget);
346 
347 		virtual void onWidgetCreated(Widget* _widget);
348 		virtual void onWidgetDestroy(Widget* _widget);
349 
350 		void setWidgetClient(Widget* _widget);
351 		/// If there is client widget return it, otherwise return this
352 		Widget* _getClientWidget();
353 
354 		virtual void setPropertyOverride(const std::string& _key, const std::string& _value);
355 
356 	private:
357 		const WidgetInfo* initialiseWidgetSkinBase(ResourceSkin* _info, ResourceLayout* _templateInfo);
358 		void shutdownWidgetSkinBase();
359 
360 		void _updateAlpha();
361 		void _updateAbsolutePoint();
362 
363 		// для внутреннего использования
364 		void _updateVisible();
365 
366 		void _updateEnabled();
367 
368 		float _getRealAlpha() const;
369 
370 		void _createChildSkinWidget(ResourceSkin* _info);
371 		void _destroyChildSkinWidget();
372 
373 		void _parseSkinProperties(ResourceSkin* _info);
374 		void _checkInheristProperties();
375 
376 		void _linkChildWidget(Widget* _widget);
377 		void _unlinkChildWidget(Widget* _widget);
378 
379 		void setSkinProperty(ResourceSkin* _info);
380 
381 		void resizeLayerItemView(const IntSize& _oldView, const IntSize& _newView) override;
382 
383 		void addWidget(Widget* _widget);
384 
385 	private:
386 		// клиентская зона окна
387 		// если виджет имеет пользовательские окна не в себе
388 		// то обязательно проинициализировать Client
389 		Widget* mWidgetClient;
390 
391 		// вектор всех детей виджетов
392 		VectorWidgetPtr mWidgetChild;
393 
394 		// вектор детей скина
395 		VectorWidgetPtr mWidgetChildSkin;
396 
397 		// доступен ли на виджет
398 		bool mEnabled;
399 		bool mInheritsEnabled;
400 		// для иерархического скрытия
401 		bool mInheritsVisible;
402 		// прозрачность и флаг наследования альфы нашего оверлея
403 		float mAlpha;
404 		float mRealAlpha;
405 		bool mInheritsAlpha;
406 		// имя виджета
407 		std::string mName;
408 
409 		// наш отец в иерархии виджетов
410 		Widget* mParent;
411 
412 		// поведение виджета, перекрывающийся дочерний или всплывающий
413 		WidgetStyle mWidgetStyle;
414 
415 		Widget* mContainer;
416 
417 		Align mAlign;
418 		bool mVisible;
419 		int mDepth;
420 	};
421 
422 } // namespace MyGUI
423 
424 #endif // MYGUI_WIDGET_H_
425