MyGUI 3.4.3
MyGUI_Widget.cpp
Go to the documentation of this file.
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#include "MyGUI_Precompiled.h"
8#include "MyGUI_Widget.h"
9#include "MyGUI_Gui.h"
10#include "MyGUI_InputManager.h"
11#include "MyGUI_SkinManager.h"
13#include "MyGUI_WidgetManager.h"
14#include "MyGUI_ResourceSkin.h"
15#include "MyGUI_WidgetDefines.h"
16#include "MyGUI_LayerItem.h"
17#include "MyGUI_LayerManager.h"
18#include "MyGUI_RenderItem.h"
19#include "MyGUI_ISubWidget.h"
21#include "MyGUI_TextBox.h"
24#include "MyGUI_RenderManager.h"
26#include "MyGUI_LayoutManager.h"
27
28namespace MyGUI
29{
30
32 WidgetStyle _style,
33 const IntCoord& _coord,
34 std::string_view _skinName,
35 Widget* _parent,
36 ICroppedRectangle* _croppedParent,
37 std::string_view _name)
38 {
39 ResourceSkin* skinInfo = nullptr;
40 ResourceLayout* templateInfo = nullptr;
41
42 if (LayoutManager::getInstance().isExist(_skinName))
43 templateInfo = LayoutManager::getInstance().getByName(_skinName);
44 else
45 skinInfo = SkinManager::getInstance().getByName(_skinName);
46
47 mCoord = _coord;
48
49 mAlign = Align::Default;
50 mWidgetStyle = _style;
51 mName = _name;
52
53 mCroppedParent = _croppedParent;
54 mParent = _parent;
55
56
57#if MYGUI_DEBUG_MODE == 1
58 // проверяем соответсвие входных данных
59 if (mWidgetStyle == WidgetStyle::Child)
60 {
61 MYGUI_ASSERT(mCroppedParent, "must be cropped");
62 MYGUI_ASSERT(mParent, "must be parent");
63 }
64 else if (mWidgetStyle == WidgetStyle::Overlapped)
65 {
66 MYGUI_ASSERT((mParent == nullptr) == (mCroppedParent == nullptr), "error cropped");
67 }
68 else if (mWidgetStyle == WidgetStyle::Popup)
69 {
70 MYGUI_ASSERT(!mCroppedParent, "cropped must be nullptr");
71 MYGUI_ASSERT(mParent, "must be parent");
72 }
73#endif
74
75 // корректируем абсолютные координаты
76 mAbsolutePosition = _coord.point();
77
78 if (nullptr != mCroppedParent)
79 mAbsolutePosition += mCroppedParent->getAbsolutePosition();
80
81 const WidgetInfo* root = initialiseWidgetSkinBase(skinInfo, templateInfo);
82
83 // дочернее окно обыкновенное
84 if (mWidgetStyle == WidgetStyle::Child)
85 {
86 if (mParent)
87 mParent->addChildItem(this);
88 }
89 // дочернее нуно перекрывающееся
90 else if (mWidgetStyle == WidgetStyle::Overlapped)
91 {
92 // дочернее перекрывающееся
93 if (mParent)
94 mParent->addChildNode(this);
95 }
96
97 // витр метод для наследников
99
100 if (skinInfo != nullptr)
101 setSkinProperty(skinInfo);
102
103 if (root != nullptr)
104 {
105 for (const auto& property : root->properties)
106 {
107 setProperty(property.first, property.second);
108 }
109 }
110 }
111
113 {
115
117
118 // витр метод для наследников
120
121 shutdownWidgetSkinBase();
122
124
125 // дочернее окно обыкновенное
126 if (mWidgetStyle == WidgetStyle::Child)
127 {
128 if (mParent)
129 mParent->removeChildItem(this);
130 }
131 // дочернее нуно перекрывающееся
132 else if (mWidgetStyle == WidgetStyle::Overlapped)
133 {
134 // дочернее перекрывающееся
135 if (mParent)
136 mParent->removeChildNode(this);
137 }
138
139 mParent = nullptr;
140 mCroppedParent = nullptr;
141 }
142
143 void Widget::changeWidgetSkin(std::string_view _skinName)
144 {
145 ResourceSkin* skinInfo = nullptr;
146 ResourceLayout* templateInfo = nullptr;
147
148 if (LayoutManager::getInstance().isExist(_skinName))
149 templateInfo = LayoutManager::getInstance().getByName(_skinName);
150 else
151 skinInfo = SkinManager::getInstance().getByName(_skinName);
152
154
156
157 shutdownWidgetSkinBase();
158 const WidgetInfo* root = initialiseWidgetSkinBase(skinInfo, templateInfo);
159
161
163
164 if (skinInfo != nullptr)
165 setSkinProperty(skinInfo);
166
167 if (root != nullptr)
169 for (const auto& property : root->properties)
170 {
171 setProperty(property.first, property.second);
172 }
173 }
174 }
176 const WidgetInfo* Widget::initialiseWidgetSkinBase(ResourceSkin* _skinInfo, ResourceLayout* _templateInfo)
178 const WidgetInfo* root = nullptr;
179 bool skinOnly = false;
180
181 if (_skinInfo == nullptr)
182 {
183 skinOnly = true;
184 std::string_view skinName;
185
186 const VectorWidgetInfo& data = _templateInfo->getLayoutData();
187 for (const auto& item : data)
188 {
189 if (item.name == "Root")
190 {
191 skinName = item.skin;
192 root = &item;
193 break;
194 }
195 }
196
197 _skinInfo = SkinManager::getInstance().getByName(skinName);
198 }
199
200 //SAVE
201 const IntSize& _size = mCoord.size();
202
203 if (_skinInfo != nullptr)
204 {
205 //FIXME - явный вызов
206 Widget::setSize(_skinInfo->getSize());
207
208 _createSkinItem(_skinInfo);
209 }
210
211 // выставляем альфу, корректировка по отцу автоматически
212 _updateAlpha();
213 _updateEnabled();
214 _updateVisible();
215
216 if (!skinOnly)
217 {
218#ifndef MYGUI_DONT_USE_OBSOLETE
219 const MapString& properties = _skinInfo->getProperties();
220 for (const auto& property : properties)
221 {
222 if (BackwardCompatibility::isIgnoreProperty(property.first))
223 {
224 MYGUI_LOG(
225 Warning,
226 property.first
227 << " skin property is deprecated, move it to UserString in a widget in ResourceLayout"
229 setUserString(property.first, property.second);
230 }
231 }
232#endif
233
234 // create skin childs
235 const VectorChildSkinInfo& child = _skinInfo->getChild();
236 for (const auto& iter : child)
237 {
238 Widget* widget = baseCreateWidget(
239 iter.style,
240 iter.type,
241 iter.skin,
242 iter.coord,
243 iter.align,
244 iter.layer,
245 iter.name,
246 true);
247 // fill UserString with skin properties
248 for (const auto& prop : iter.params)
249 widget->setUserString(prop.first, prop.second);
250 }
251 }
252
253 if (root != nullptr)
254 {
255 //FIXME - явный вызов
257
258 for (const auto& userString : root->userStrings)
259 {
260 setUserString(userString.first, userString.second);
261 }
262
263 for (const auto& iter : root->childWidgetsInfo)
264 {
265 _templateInfo->createWidget(iter, {}, this, true);
266 }
267 }
268
269 //FIXME - явный вызов
270 Widget::setSize(_size);
271
272 return root;
273 }
274
275 void Widget::shutdownWidgetSkinBase()
276 {
277 setMaskPick(MaskPickInfo{});
278
280
281 // удаляем виджеты чтобы ли в скине
282 for (auto& iter : mWidgetChildSkin)
283 {
284 // Добавляем себя чтобы удалилось
285 mWidgetChild.push_back(iter);
287 }
288 mWidgetChildSkin.clear();
289
290 mWidgetClient = nullptr;
291 }
292
294 WidgetStyle _style,
295 std::string_view _type,
296 std::string_view _skin,
297 const IntCoord& _coord,
298 Align _align,
299 std::string_view _layer,
300 std::string_view _name,
301 bool _template)
302 {
303 Widget* widget = nullptr;
304
305 if (_template)
306 {
308 _style,
309 _type,
310 _skin,
311 _coord,
312 this,
313 _style == WidgetStyle::Popup ? nullptr : this,
314 _name);
315 mWidgetChildSkin.push_back(widget);
316 }
317 else
318 {
319 if (mWidgetClient != nullptr)
320 {
321 widget =
322 mWidgetClient->baseCreateWidget(_style, _type, _skin, _coord, _align, _layer, _name, _template);
323 onWidgetCreated(widget);
324 return widget;
325 }
326
328 _style,
329 _type,
330 _skin,
331 _coord,
332 this,
333 _style == WidgetStyle::Popup ? nullptr : this,
334 _name);
335 addWidget(widget);
336 }
337
338 widget->setAlign(_align);
339
340 // присоединяем виджет с уровню
341 if (!_layer.empty() && widget->isRootWidget())
343
344 onWidgetCreated(widget);
345
346 return widget;
347 }
348
350 std::string_view _type,
351 std::string_view _skin,
352 const FloatCoord& _coord,
353 Align _align,
354 std::string_view _name)
355 {
356 return createWidgetT(_type, _skin, CoordConverter::convertFromRelative(_coord, getSize()), _align, _name);
357 }
358
360 {
361 bool margin = mCroppedParent ? _checkMargin() : false;
362
363 // вьюпорт стал битым
364 if (margin)
365 {
366 // проверка на полный выход за границу
367 if (_checkOutside())
368 {
369 // запоминаем текущее состояние
370 mIsMargin = margin;
371
372 // скрываем
373 _setSubSkinVisible(false);
374
375 // вся иерархия должна быть проверенна
376 for (auto& widget : mWidgetChild)
377 widget->_updateView();
378 for (auto& widget : mWidgetChildSkin)
379 widget->_updateView();
380
381 return;
382 }
383 }
384 // мы не обрезаны и были нормальные
385 else if (!mIsMargin)
386 {
388 return;
389 }
390
391 // запоминаем текущее состояние
392 mIsMargin = margin;
393
394 // если скин был скрыт, то покажем
395 _setSubSkinVisible(true);
396
397 // обновляем наших детей, а они уже решат обновлять ли своих детей
398 for (auto& widget : mWidgetChild)
399 widget->_updateView();
400 for (auto& widget : mWidgetChildSkin)
401 widget->_updateView();
402
404 }
405
406 bool Widget::_setWidgetState(std::string_view _state)
407 {
408 return _setSkinItemState(_state);
409 }
410
412 {
413 MYGUI_ASSERT(nullptr != _widget, "invalid widget pointer");
414
415 if (mParent != nullptr && mParent->getClientWidget() == this)
416 mParent->onWidgetDestroy(_widget);
417
418 onWidgetDestroy(_widget);
419
420 VectorWidgetPtr::iterator iter = std::find(mWidgetChild.begin(), mWidgetChild.end(), _widget);
421 if (iter != mWidgetChild.end())
422 {
423 // сохраняем указатель
424 MyGUI::Widget* widget = *iter;
425
426 // удаляем из списка
427 mWidgetChild.erase(iter);
428
429 // отписываем от всех
431
432 // непосредственное удаление
434 }
435 else
436 {
437 MYGUI_EXCEPT("Widget '" << _widget->getName() << "' not found");
438 }
439 }
440
441 // удаляет всех детей
443 {
445 while (!mWidgetChild.empty())
446 {
447 // сразу себя отписывем, иначе вложенной удаление убивает все
448 Widget* widget = mWidgetChild.back();
449 mWidgetChild.pop_back();
450
451 // отписываем от всех
452 manager.unlinkFromUnlinkers(widget);
453
454 // и сами удалим, так как его больше в списке нет
456 }
457 }
458
460 {
461 if (mWidgetClient != nullptr)
462 return mWidgetClient->getCoord();
463 return {0, 0, mCoord.width, mCoord.height};
464 }
465
466 void Widget::setAlpha(float _alpha)
467 {
468 if (mAlpha == _alpha)
469 return;
470 mAlpha = _alpha;
471
472 _updateAlpha();
473 }
474
475 void Widget::_updateAlpha()
476 {
477 if (nullptr != mParent)
478 mRealAlpha = mAlpha * (mInheritsAlpha ? mParent->_getRealAlpha() : ALPHA_MAX);
479 else
480 mRealAlpha = mAlpha;
481
482 for (auto& widget : mWidgetChild)
483 widget->_updateAlpha();
484 for (auto& widget : mWidgetChildSkin)
485 widget->_updateAlpha();
486
487 _setSkinItemAlpha(mRealAlpha);
488 }
489
490 void Widget::setInheritsAlpha(bool _inherits)
491 {
492 mInheritsAlpha = _inherits;
493 _updateAlpha();
494 }
495
496 ILayerItem* Widget::getLayerItemByPoint(int _left, int _top) const
497 {
498 // проверяем попадание
499 if (!mEnabled || !mInheritedVisible || (!getNeedMouseFocus() && !getInheritsPick()) ||
500 !_checkPoint(_left, _top)
501 // если есть маска, проверяем еще и по маске
502 || !isMaskPickInside(IntPoint(_left - mCoord.left, _top - mCoord.top), mCoord))
503 return nullptr;
504
505 // спрашиваем у детишек
506 for (VectorWidgetPtr::const_reverse_iterator widget = mWidgetChild.rbegin(); widget != mWidgetChild.rend();
507 ++widget)
508 {
509 // общаемся только с послушными детьми
510 if ((*widget)->mWidgetStyle == WidgetStyle::Popup)
511 continue;
512
513 ILayerItem* item = (*widget)->getLayerItemByPoint(_left - mCoord.left, _top - mCoord.top);
514 if (item != nullptr)
515 return item;
516 }
517 // спрашиваем у детишек скина
518 for (VectorWidgetPtr::const_reverse_iterator widget = mWidgetChildSkin.rbegin();
519 widget != mWidgetChildSkin.rend();
520 ++widget)
521 {
522 ILayerItem* item = (*widget)->getLayerItemByPoint(_left - mCoord.left, _top - mCoord.top);
523 if (item != nullptr)
524 return item;
525 }
526
527 // непослушные дети
528 return getInheritsPick() ? nullptr : const_cast<Widget*>(this);
529 }
530
531 void Widget::_updateAbsolutePoint()
532 {
533 // мы рут, нам не надо
534 if (!mCroppedParent)
535 return;
536
538
539 for (auto& widget : mWidgetChild)
540 widget->_updateAbsolutePoint();
541 for (auto& widget : mWidgetChildSkin)
542 widget->_updateAbsolutePoint();
543
545 }
546
548 {
549 if (mWidgetClient != nullptr)
550 {
551 mWidgetClient->_forcePick(_widget);
552 return;
553 }
554
555 auto iter = std::find(mWidgetChild.begin(), mWidgetChild.end(), _widget);
556 if (iter == mWidgetChild.end())
557 return;
558
559 for (auto& widget : mWidgetChild)
560 {
561 if (widget == _widget)
562 widget->mDepth = -1;
563 else if (widget->getDepth() == -1)
564 widget->mDepth = 0;
565 }
566 // code below is an optimized way to setDepth for multiple widgets
567 // without calling slow Windget::_updateChilds multiple times
568 std::stable_sort(
569 mWidgetChild.begin(),
570 mWidgetChild.end(),
571 [](Widget* lhs, Widget* rhs) { return lhs->getDepth() < rhs->getDepth(); });
573 }
574
575 Widget* Widget::findWidget(std::string_view _name)
576 {
577 if (_name == mName)
578 return this;
579 if (mWidgetClient != nullptr)
580 return mWidgetClient->findWidget(_name);
581
582 for (const auto& widget : mWidgetChild)
583 {
584 Widget* find = widget->findWidget(_name);
585 if (nullptr != find)
586 return find;
587 }
588 return nullptr;
589 }
590
592 {
594 _point,
595 mCroppedParent == nullptr ? RenderManager::getInstance().getViewSize() : mCroppedParent->getSize()));
596 }
597
599 {
601 _size,
602 mCroppedParent == nullptr ? RenderManager::getInstance().getViewSize() : mCroppedParent->getSize()));
603 }
604
606 {
608 _coord,
609 mCroppedParent == nullptr ? RenderManager::getInstance().getViewSize() : mCroppedParent->getSize()));
610 }
611
612 void Widget::_setAlign(const IntSize& _oldsize, const IntSize& _newSize)
613 {
614 const IntSize& size = _newSize; //getParentSize();
615
616 bool need_move = false;
617 bool need_size = false;
618 IntCoord coord = mCoord;
619
620 // первоначальное выравнивание
621 if (mAlign.isHStretch())
622 {
623 // растягиваем
624 coord.width = mCoord.width + (size.width - _oldsize.width);
625 need_size = true;
626 }
627 else if (mAlign.isRight())
628 {
629 // двигаем по правому краю
630 coord.left = mCoord.left + (size.width - _oldsize.width);
631 need_move = true;
632 }
633 else if (mAlign.isHCenter())
634 {
635 // выравнивание по горизонтали без растяжения
636 coord.left = (size.width - mCoord.width) / 2;
637 need_move = true;
638 }
639
640 if (mAlign.isVStretch())
641 {
642 // растягиваем
643 coord.height = mCoord.height + (size.height - _oldsize.height);
644 need_size = true;
645 }
646 else if (mAlign.isBottom())
647 {
648 // двигаем по нижнему краю
649 coord.top = mCoord.top + (size.height - _oldsize.height);
650 need_move = true;
651 }
652 else if (mAlign.isVCenter())
653 {
654 // выравнивание по вертикали без растяжения
655 coord.top = (size.height - mCoord.height) / 2;
656 need_move = true;
657 }
658
659 if (need_move)
660 {
661 if (need_size)
662 setCoord(coord);
663 else
664 setPosition(coord.point());
665 }
666 else if (need_size)
667 {
668 setSize(coord.size());
669 }
670 else
671 {
672 _updateView(); // только если не вызвано передвижение и сайз
673 }
674 }
675
676 void Widget::setPosition(const IntPoint& _point)
677 {
678 // обновляем абсолютные координаты
679 mAbsolutePosition += _point - mCoord.point();
680
681 for (auto& widget : mWidgetChild)
682 widget->_updateAbsolutePoint();
683 for (auto& widget : mWidgetChildSkin)
684 widget->_updateAbsolutePoint();
685
686 mCoord = _point;
687
688 _updateView();
689
690 eventChangeCoord(this);
691 }
692
693 void Widget::setSize(const IntSize& _size)
694 {
695 // устанавливаем новую координату а старую пускаем в расчеты
696 IntSize old = mCoord.size();
697 mCoord = _size;
698
699 bool visible = true;
700
701 // обновляем выравнивание
702 bool margin = mCroppedParent ? _checkMargin() : false;
703
704 if (margin)
705 {
706 // проверка на полный выход за границу
707 if (_checkOutside())
708 {
709 // скрываем
710 visible = false;
711 }
712 }
713
714 _setSubSkinVisible(visible);
715
716 // передаем старую координату , до вызова, текущая координата отца должна быть новой
717 for (auto& widget : mWidgetChild)
718 widget->_setAlign(old, getSize());
719 for (auto& widget : mWidgetChildSkin)
720 widget->_setAlign(old, getSize());
721
723
724 // запоминаем текущее состояние
725 mIsMargin = margin;
726
727 eventChangeCoord(this);
728 }
729
730 void Widget::setCoord(const IntCoord& _coord)
731 {
732 // обновляем абсолютные координаты
733 mAbsolutePosition += _coord.point() - mCoord.point();
734
735 for (auto& widget : mWidgetChild)
736 widget->_updateAbsolutePoint();
737 for (auto& widget : mWidgetChildSkin)
738 widget->_updateAbsolutePoint();
739
740 // устанавливаем новую координату а старую пускаем в расчеты
741 IntCoord old = mCoord;
742 mCoord = _coord;
743
744 bool visible = true;
745
746 // обновляем выравнивание
747 bool margin = mCroppedParent ? _checkMargin() : false;
748
749 if (margin)
750 {
751 // проверка на полный выход за границу
752 if (_checkOutside())
753 {
754 // скрываем
755 visible = false;
756 }
757 }
758
759 _setSubSkinVisible(visible);
760
761 // передаем старую координату , до вызова, текущая координата отца должна быть новой
762 for (auto& widget : mWidgetChild)
763 widget->_setAlign(old.size(), getSize());
764 for (auto& widget : mWidgetChildSkin)
765 widget->_setAlign(old.size(), getSize());
766
767 _setSkinItemAlign(old.size());
768
769 // запоминаем текущее состояние
770 mIsMargin = margin;
771
772 eventChangeCoord(this);
773 }
774
776 {
777 mAlign = _value;
778 }
779
780 void Widget::detachFromWidget(std::string_view _layer)
781 {
782 std::string_view oldlayer;
783 if (getLayer())
784 oldlayer = getLayer()->getName();
785
786 Widget* parent = getParent();
787 if (parent)
788 {
789 // отдетачиваемся от лееров
790 if (!isRootWidget())
791 {
793
794 if (mWidgetStyle == WidgetStyle::Child)
795 {
796 mParent->removeChildItem(this);
797 }
798 else if (mWidgetStyle == WidgetStyle::Overlapped)
799 {
800 mParent->removeChildNode(this);
801 }
802
803 mWidgetStyle = WidgetStyle::Overlapped;
804
805 mCroppedParent = nullptr;
806
807 // обновляем координаты
808 mAbsolutePosition = mCoord.point();
809
810 for (auto& widget : mWidgetChild)
811 widget->_updateAbsolutePoint();
812 for (auto& widget : mWidgetChildSkin)
813 widget->_updateAbsolutePoint();
814
815 // сбрасываем обрезку
816 mMargin.clear();
817
818 _updateView();
819 }
820
821 // нам нужен самый рутовый парент
822 while (parent->getParent())
823 parent = parent->getParent();
824
826 mParent->_unlinkChildWidget(this);
827 mParent = nullptr;
828 }
829
830 if (!_layer.empty())
831 {
833 }
834 else if (!oldlayer.empty())
835 {
837 }
838
839 _updateAlpha();
840 }
841
842 void Widget::attachToWidget(Widget* _parent, WidgetStyle _style, std::string_view _layer)
843 {
844 MYGUI_ASSERT(_parent, "parent must be valid");
845 MYGUI_ASSERT(_parent != this, "cyclic attach (attaching to self)");
846
847 // attach to client if widget have it
848 if (_parent->getClientWidget())
849 _parent = _parent->getClientWidget();
850
851 Widget* parent = _parent;
852 while (parent->getParent())
853 {
854 MYGUI_ASSERT(parent != this, "cyclic attach");
855 parent = parent->getParent();
856 }
857
859
860 mWidgetStyle = _style;
861
862 if (_style == WidgetStyle::Popup)
863 {
864 if (mParent == nullptr)
866 else
867 mParent->_unlinkChildWidget(this);
868
869 mParent = _parent;
870 mParent->_linkChildWidget(this);
871
872 mCroppedParent = nullptr;
873
874 if (!_layer.empty())
875 {
877 }
878 }
879 else if (_style == WidgetStyle::Child)
880 {
882
883 if (mParent == nullptr)
885 else
886 mParent->_unlinkChildWidget(this);
887
888 mParent = _parent;
889 mParent->addChildItem(this);
890 mParent->_linkChildWidget(this);
891
892 mCroppedParent = _parent;
893 mAbsolutePosition = _parent->getAbsolutePosition() + mCoord.point();
894
895 for (auto& widget : mWidgetChild)
896 widget->_updateAbsolutePoint();
897 for (auto& widget : mWidgetChildSkin)
898 widget->_updateAbsolutePoint();
899
900 _updateView();
901 }
902 else if (_style == WidgetStyle::Overlapped)
903 {
905
906 if (mParent == nullptr)
908 else
909 mParent->_unlinkChildWidget(this);
910
911 mParent = _parent;
912 mParent->_linkChildWidget(this);
913
914 mCroppedParent = _parent;
915 mAbsolutePosition = _parent->getAbsolutePosition() + mCoord.point();
916
917 for (auto& widget : mWidgetChild)
918 widget->_updateAbsolutePoint();
919 for (auto& widget : mWidgetChildSkin)
920 widget->_updateAbsolutePoint();
921
922 mParent->addChildNode(this);
923
924 _updateView();
925 }
926
927 _updateAlpha();
928 }
929
930 void Widget::setWidgetStyle(WidgetStyle _style, std::string_view _layer)
931 {
932 if (_style == mWidgetStyle)
933 return;
934 if (nullptr == getParent())
935 return;
936
937 Widget* parent = mParent;
938
940 attachToWidget(parent, _style, _layer);
941 // ищем леер к которому мы присоедененны
942 }
943
945 std::string_view _type,
946 std::string_view _skin,
947 const IntCoord& _coord,
948 Align _align,
949 std::string_view _name)
950 {
951 return baseCreateWidget(WidgetStyle::Child, _type, _skin, _coord, _align, {}, _name, false);
952 }
953
955 std::string_view _type,
956 std::string_view _skin,
957 int _left,
958 int _top,
959 int _width,
960 int _height,
961 Align _align,
962 std::string_view _name)
963 {
964 return createWidgetT(_type, _skin, IntCoord(_left, _top, _width, _height), _align, _name);
965 }
966
968 std::string_view _type,
969 std::string_view _skin,
970 float _left,
971 float _top,
972 float _width,
973 float _height,
974 Align _align,
975 std::string_view _name)
976 {
977 return createWidgetRealT(_type, _skin, FloatCoord(_left, _top, _width, _height), _align, _name);
978 }
979
981 WidgetStyle _style,
982 std::string_view _type,
983 std::string_view _skin,
984 const IntCoord& _coord,
985 Align _align,
986 std::string_view _layer,
987 std::string_view _name)
988 {
989 return baseCreateWidget(_style, _type, _skin, _coord, _align, _layer, _name, false);
990 }
991
993 {
994 if (mWidgetClient != nullptr)
995 return mWidgetClient->getEnumerator();
996 return {mWidgetChild.begin(), mWidgetChild.end()};
997 }
998
1000 {
1001 if (mWidgetClient != nullptr)
1002 return mWidgetClient->getChildCount();
1003 return mWidgetChild.size();
1004 }
1005
1006 Widget* Widget::getChildAt(size_t _index) const
1007 {
1008 if (mWidgetClient != nullptr)
1009 return mWidgetClient->getChildAt(_index);
1010 MYGUI_ASSERT_RANGE(_index, mWidgetChild.size(), "Widget::getChildAt");
1011 return mWidgetChild[_index];
1012 }
1013
1015 {
1016 if (getInheritedEnabled())
1017 _setWidgetState("normal");
1018 else
1019 _setWidgetState("disabled");
1020 }
1021
1022 void Widget::setVisible(bool _value)
1023 {
1024 if (mVisible == _value)
1025 return;
1026 mVisible = _value;
1027
1028 _updateVisible();
1029 }
1030
1031 void Widget::_updateVisible()
1032 {
1033 mInheritedVisible = mParent == nullptr || mParent->getInheritedVisible();
1034 mInheritedVisible = mVisible && mInheritedVisible;
1035
1036 _setSkinItemVisible(mInheritedVisible);
1037
1038 for (auto& widget : mWidgetChild)
1039 widget->_updateVisible();
1040 for (auto& widget : mWidgetChildSkin)
1041 widget->_updateVisible();
1042
1043 if (!mInheritedVisible && InputManager::getInstance().getMouseFocusWidget() == this)
1045 if (!mInheritedVisible && InputManager::getInstance().getKeyFocusWidget() == this)
1047 }
1048
1049 void Widget::setEnabled(bool _value)
1050 {
1051 if (mEnabled == _value)
1052 return;
1053 mEnabled = _value;
1054
1055 _updateEnabled();
1056 }
1057
1058 void Widget::_updateEnabled()
1059 {
1060 mInheritedEnabled = mParent == nullptr || (mParent->getInheritedEnabled());
1061 mInheritedEnabled = mInheritedEnabled && mEnabled;
1062
1063 for (auto& iter : mWidgetChild)
1064 iter->_updateEnabled();
1065 for (auto& iter : mWidgetChildSkin)
1066 iter->_updateEnabled();
1067
1069
1070 if (!mInheritedEnabled)
1072 }
1073
1074 void Widget::setColour(const Colour& _value)
1075 {
1076 _setSkinItemColour(_value);
1077
1078 for (auto& widget : mWidgetChildSkin)
1079 widget->setColour(_value);
1080 }
1081
1083 {
1084 if (mCroppedParent)
1085 return static_cast<Widget*>(mCroppedParent)->getSize();
1086 if (getLayer())
1087 return getLayer()->getSize();
1088
1090 }
1091
1092 void Widget::_resetContainer(bool _updateOnly)
1093 {
1094 if (getNeedToolTip())
1096 }
1097
1098 bool Widget::_checkPoint(int _left, int _top) const
1099 {
1100 return (_getViewLeft() <= _left) && (_getViewTop() <= _top) && (_getViewRight() >= _left) &&
1101 (_getViewBottom() >= _top);
1102 }
1103
1104 void Widget::_linkChildWidget(Widget* _widget)
1105 {
1106 VectorWidgetPtr::iterator iter = std::find(mWidgetChild.begin(), mWidgetChild.end(), _widget);
1107 MYGUI_ASSERT(iter == mWidgetChild.end(), "widget already exist");
1108 addWidget(_widget);
1109 }
1110
1111 void Widget::_unlinkChildWidget(Widget* _widget)
1112 {
1113 VectorWidgetPtr::iterator iter = std::remove(mWidgetChild.begin(), mWidgetChild.end(), _widget);
1114 MYGUI_ASSERT(iter != mWidgetChild.end(), "widget not found");
1115 mWidgetChild.erase(iter);
1116 }
1117
1119 {
1120 }
1121
1123 {
1125 assignWidget(mWidgetClient, "Client");
1126 }
1127
1128 void Widget::setSkinProperty(ResourceSkin* _info)
1129 {
1130 const MapString& properties = _info->getProperties();
1131 for (const auto& property : properties)
1132 setProperty(property.first, property.second);
1133 }
1134
1135 void Widget::setProperty(std::string_view _key, std::string_view _value)
1136 {
1137 std::string key{_key};
1138 std::string value{_value};
1139
1140 if (BackwardCompatibility::checkProperty(this, key, value))
1141 {
1142 size_t index = key.find('_');
1143 if (index != std::string::npos)
1144 {
1145 MYGUI_LOG(
1146 Warning,
1147 "Widget property '" << key << "' have type prefix - use '" << key.substr(index + 1) << "' instead ["
1148 << LayoutManager::getInstance().getCurrentLayout() << "]");
1149 key = key.substr(index + 1);
1150 }
1151
1152 setPropertyOverride(key, value);
1153 }
1154 }
1155
1156 VectorWidgetPtr Widget::getSkinWidgetsByName(std::string_view _name) const
1157 {
1158 VectorWidgetPtr result;
1159
1160 for (const auto& childSkin : mWidgetChildSkin)
1161 childSkin->findWidgets(_name, result);
1162
1163 return result;
1164 }
1165
1166 void Widget::findWidgets(std::string_view _name, VectorWidgetPtr& _result)
1167 {
1168 if (_name == mName)
1169 _result.push_back(this);
1170
1171 if (mWidgetClient != nullptr)
1172 {
1173 mWidgetClient->findWidgets(_name, _result);
1174 }
1175 else
1176 {
1177 for (const auto& widget : mWidgetChild)
1178 widget->findWidgets(_name, _result);
1179 }
1180 }
1181
1183 {
1184 }
1185
1187 {
1188 }
1189
1191 {
1192 MYGUI_ASSERT(mWidgetClient != this, "mWidgetClient can not be this widget");
1193 mWidgetClient = _widget;
1194 }
1195
1197 {
1198 return getClientWidget() == nullptr ? this : getClientWidget();
1199 }
1200
1202 {
1203 return getClientWidget() == nullptr ? this : getClientWidget();
1204 }
1205
1207 WidgetStyle _style,
1208 std::string_view _type,
1209 std::string_view _skin,
1210 const IntCoord& _coord,
1211 Align _align,
1212 std::string_view _layer,
1213 std::string_view _name)
1214 {
1215 return baseCreateWidget(_style, _type, _skin, _coord, _align, _layer, _name, true);
1216 }
1217
1218 void Widget::setPropertyOverride(std::string_view _key, std::string_view _value)
1219 {
1221 if (_key == "Position")
1223
1225 else if (_key == "Size")
1227
1229 else if (_key == "Coord")
1231
1233 else if (_key == "Visible")
1235
1237 else if (_key == "Depth")
1239
1241 else if (_key == "Alpha")
1243
1245 else if (_key == "Colour")
1247
1249 else if (_key == "InheritsAlpha")
1251
1253 else if (_key == "InheritsPick")
1255
1257 else if (_key == "MaskPick")
1258 setMaskPick(std::string{_value});
1259
1261 else if (_key == "NeedKey")
1263
1265 else if (_key == "NeedMouse")
1267
1269 else if (_key == "Enabled")
1271
1273 else if (_key == "NeedToolTip")
1275
1277 else if (_key == "Pointer")
1278 setPointer(_value);
1279
1280 else
1281 {
1282 MYGUI_LOG(
1283 Warning,
1284 "Widget '" << getName() << "|" << getTypeName() << "' have unknown property '" << _key << "' "
1285 << " [" << LayoutManager::getInstance().getCurrentLayout() << "]");
1286 return;
1287 }
1288
1289 eventChangeProperty(this, _key, _value);
1290 }
1291
1292 void Widget::setPosition(int _left, int _top)
1293 {
1294 setPosition(IntPoint(_left, _top));
1295 }
1296
1297 void Widget::setSize(int _width, int _height)
1298 {
1299 setSize(IntSize(_width, _height));
1300 }
1301
1302 void Widget::setCoord(int _left, int _top, int _width, int _height)
1303 {
1304 setCoord(IntCoord(_left, _top, _width, _height));
1305 }
1306
1307 void Widget::setRealPosition(float _left, float _top)
1308 {
1309 setRealPosition(FloatPoint(_left, _top));
1310 }
1311
1312 void Widget::setRealSize(float _width, float _height)
1313 {
1314 setRealSize(FloatSize(_width, _height));
1315 }
1316
1317 void Widget::setRealCoord(float _left, float _top, float _width, float _height)
1318 {
1319 setRealCoord(FloatCoord(_left, _top, _width, _height));
1320 }
1321
1322 const std::string& Widget::getName() const
1323 {
1324 return mName;
1325 }
1326
1328 {
1329 return mVisible;
1330 }
1331
1333 {
1334 return mAlign;
1335 }
1336
1337 float Widget::getAlpha() const
1338 {
1339 return mAlpha;
1340 }
1341
1343 {
1344 return mInheritsAlpha;
1345 }
1346
1348 {
1349 return nullptr == mCroppedParent;
1350 }
1351
1353 {
1354 return mParent;
1355 }
1356
1358 {
1359 mEnabled = _value;
1360 }
1361
1363 {
1364 return mEnabled;
1365 }
1366
1368 {
1369 return mWidgetClient;
1370 }
1371
1373 {
1374 return mWidgetClient;
1375 }
1376
1378 {
1379 return mWidgetStyle;
1380 }
1381
1382 size_t Widget::_getItemIndex(Widget* _item) const
1383 {
1384 return ITEM_NONE;
1385 }
1386
1388 {
1389 mContainer = _value;
1390 }
1391
1393 {
1394 return mContainer;
1395 }
1396
1397 size_t Widget::_getContainerIndex(const IntPoint& _point) const
1398 {
1399 return ITEM_NONE;
1400 }
1401
1403 {
1404 return mCoord;
1405 }
1406
1407 float Widget::_getRealAlpha() const
1408 {
1409 return mRealAlpha;
1410 }
1411
1413 {
1414 return mInheritedEnabled;
1415 }
1416
1418 {
1419 return mInheritedVisible;
1420 }
1421
1422 void Widget::resizeLayerItemView(const IntSize& _oldView, const IntSize& _newView)
1423 {
1424 _setAlign(_oldView, _newView);
1425 }
1426
1427 void Widget::setDepth(int _value)
1428 {
1429 if (mDepth == _value)
1430 return;
1431
1432 mDepth = _value;
1433
1434 if (mParent != nullptr)
1435 {
1436 mParent->_unlinkChildWidget(this);
1437 mParent->_linkChildWidget(this);
1438 mParent->_updateChilds();
1439 }
1440 }
1441
1443 {
1444 return mDepth;
1445 }
1446
1447 void Widget::addWidget(Widget* _widget)
1448 {
1449 // сортировка глубины от большого к меньшему
1450
1451 int depth = _widget->getDepth();
1452
1453 for (size_t index = 0; index < mWidgetChild.size(); ++index)
1454 {
1455 Widget* widget = mWidgetChild[index];
1456 if (widget->getDepth() < depth)
1457 {
1458 mWidgetChild.insert(mWidgetChild.begin() + index, _widget);
1459 _updateChilds();
1460 return;
1461 }
1462 }
1463
1464 mWidgetChild.push_back(_widget);
1465 }
1466
1468 {
1469 for (auto& widget : mWidgetChild)
1470 {
1471 if (widget->getWidgetStyle() == WidgetStyle::Child)
1472 {
1473 widget->detachFromLayerItemNode(false);
1474 removeChildItem(widget);
1475 }
1476 }
1477
1478 for (auto& widget : mWidgetChild)
1479 {
1480 if (widget->getWidgetStyle() == WidgetStyle::Child)
1481 {
1482 addChildItem(widget);
1483 widget->_updateView();
1484 }
1485 }
1486 }
1487
1488} // namespace MyGUI
#define MYGUI_ASSERT(exp, dest)
#define MYGUI_EXCEPT(dest)
#define MYGUI_ASSERT_RANGE(index, size, owner)
#define MYGUI_LOG(level, text)
static const Any Null
Definition MyGUI_Any.h:58
static bool isIgnoreProperty(std::string_view _key)
static bool checkProperty(Widget *_owner, std::string &_key, std::string &_value)
static IntCoord convertFromRelative(const FloatCoord &_coord, const IntSize &_view)
void _unlinkChildWidget(Widget *_widget)
void _linkChildWidget(Widget *_widget)
static Gui & getInstance()
Definition MyGUI_Gui.cpp:34
const IntPoint & getAbsolutePosition() const
const std::string & getName() const
virtual const IntSize & getSize() const =0
virtual ILayerItem * getLayerItemByPoint(int _left, int _top) const =0
void unlinkWidget(Widget *_widget)
void resetKeyFocusWidget(Widget *_widget)
static InputManager & getInstance()
void detachFromLayerItemNode(bool _deep)
void addChildItem(LayerItem *_item)
void removeChildItem(LayerItem *_item)
ILayer * getLayer() const
void detachFromLayer(Widget *_item)
static LayerManager & getInstance()
void attachToLayerNode(std::string_view _name, Widget *_item)
const std::string & getCurrentLayout() const
static LayoutManager & getInstance()
ResourceLayout * getByName(std::string_view _name, bool _throw=true) const
virtual const IntSize & getViewSize() const =0
static RenderManager & getInstance()
Widget * createWidget(const WidgetInfo &_widgetInfo, std::string_view _prefix={}, Widget *_parent=nullptr, bool _template=false)
const VectorWidgetInfo & getLayoutData() const
const IntSize & getSize() const
const MapString & getProperties() const
const VectorChildSkinInfo & getChild() const
void _setSkinItemAlpha(float _value)
void _createSkinItem(ResourceSkin *_info)
void _setSkinItemColour(const Colour &_value)
bool _setSkinItemState(std::string_view _state)
void _setSubSkinVisible(bool _visible)
void _setSkinItemAlign(const IntSize &_size)
void _setSkinItemVisible(bool _value)
static SkinManager & getInstance()
ResourceSkin * getByName(std::string_view _name) const
static ToolTipManager & getInstance()
void _unlinkWidget(Widget *_widget) override
void setUserString(std::string_view _key, std::string_view _value)
void setUserData(Any _data)
widget description should be here.
Widget * getParent() const
void setAlpha(float _alpha)
bool getInheritedEnabled() const
void _destroyAllChildWidget()
ILayerItem * getLayerItemByPoint(int _left, int _top) const override
void setSize(const IntSize &_size) override
bool _checkPoint(int _left, int _top) const
void _destroyChildWidget(Widget *_widget)
void setProperty(std::string_view _key, std::string_view _value)
virtual void onWidgetDestroy(Widget *_widget)
VectorWidgetPtr getSkinWidgetsByName(std::string_view _name) const
EventHandle_WidgetStringString eventChangeProperty
bool _setWidgetState(std::string_view _state)
virtual void initialiseOverride()
size_t getChildCount() const
const std::string & getName() const
Get name of widget.
Widget * getChildAt(size_t _index) const
virtual void setPropertyOverride(std::string_view _key, std::string_view _value)
Widget * createWidgetRealT(std::string_view _type, std::string_view _skin, const FloatCoord &_coord, Align _align, std::string_view _name={})
virtual void setVisible(bool _value)
bool getEnabled() const
void _setAlign(const IntSize &_oldsize, const IntSize &_newSize)
virtual void baseUpdateEnable()
void setPosition(const IntPoint &_point) override
void _initialise(WidgetStyle _style, const IntCoord &_coord, std::string_view _skinName, Widget *_parent, ICroppedRectangle *_croppedParent, std::string_view _name)
virtual void setEnabled(bool _value)
void attachToWidget(Widget *_parent, WidgetStyle _style=WidgetStyle::Child, std::string_view _layer={})
friend class WidgetManager
const IntCoord & getLayerItemCoord() const override
IntSize getParentSize() const
void changeWidgetSkin(std::string_view _skinName)
void setInheritsAlpha(bool _inherits)
bool getVisible() const
void setDepth(int _value)
Widget * createWidgetT(std::string_view _type, std::string_view _skin, const IntCoord &_coord, Align _align, std::string_view _name={})
Widget * getClientWidget()
void detachFromWidget(std::string_view _layer={})
IntCoord getClientCoord() const
bool isRootWidget() const
Widget * findWidget(std::string_view _name)
void setWidgetStyle(WidgetStyle _style, std::string_view _layer={})
Align getAlign() const
void setRealPosition(const FloatPoint &_point)
EventHandle_WidgetVoid eventChangeCoord
virtual void onWidgetCreated(Widget *_widget)
virtual void setAlign(Align _value)
int getDepth() const
virtual void _resetContainer(bool _update)
WidgetStyle getWidgetStyle() const
void setRealCoord(const FloatCoord &_coord)
bool getInheritsAlpha() const
void assignWidget(T *&_widget, std::string_view _name)
void setWidgetClient(Widget *_widget)
float getAlpha() const
void setColour(const Colour &_value)
Widget * _getContainer() const
Widget * _createSkinWidget(WidgetStyle _style, std::string_view _type, std::string_view _skin, const IntCoord &_coord, Align _align, std::string_view _layer={}, std::string_view _name={})
void _setContainer(Widget *_value)
virtual size_t _getContainerIndex(const IntPoint &_point) const
virtual std::string_view getTypeName() const override
void _forcePick(Widget *_widget)
void findWidgets(std::string_view _name, VectorWidgetPtr &_result)
EventHandle_WidgetVoid eventWidgetDestroyed
virtual size_t _getItemIndex(Widget *_item) const
virtual void shutdownOverride()
Widget * baseCreateWidget(WidgetStyle _style, std::string_view _type, std::string_view _skin, const IntCoord &_coord, Align _align, std::string_view _layer, std::string_view _name, bool _template)
void setCoord(const IntCoord &_coord) override
void setRealSize(const FloatSize &_size)
void setEnabledSilent(bool _value)
EnumeratorWidgetPtr getEnumerator() const
Widget * _getClientWidget()
If there is client widget return it, otherwise return this.
bool getInheritedVisible() const
void setNeedMouseFocus(bool _value)
void setMaskPick(const std::string &_filename)
void setNeedKeyFocus(bool _value)
bool isMaskPickInside(const IntPoint &_point, const IntCoord &_coord) const
void setInheritsPick(bool _value)
void setPointer(std::string_view _value)
void setNeedToolTip(bool _value)
Widget * createWidget(WidgetStyle _style, std::string_view _type, std::string_view _skin, const IntCoord &_coord, Widget *_parent, ICroppedRectangle *_cropeedParent, std::string_view _name)
static WidgetManager & getInstance()
void _deleteWidget(Widget *_widget)
void unlinkFromUnlinkers(Widget *_widget)
T parseValue(std::string_view _value)
constexpr float ALPHA_MAX
types::TPoint< int > IntPoint
Definition MyGUI_Types.h:27
types::TCoord< float > FloatCoord
Definition MyGUI_Types.h:37
std::map< std::string, std::string, std::less<> > MapString
Definition MyGUI_Types.h:40
std::vector< WidgetInfo > VectorWidgetInfo
Enumerator< VectorWidgetPtr > EnumeratorWidgetPtr
types::TPoint< float > FloatPoint
Definition MyGUI_Types.h:28
constexpr size_t ITEM_NONE
types::TSize< float > FloatSize
Definition MyGUI_Types.h:31
types::TCoord< int > IntCoord
Definition MyGUI_Types.h:36
types::TSize< int > IntSize
Definition MyGUI_Types.h:30
std::vector< Widget * > VectorWidgetPtr
std::vector< ChildSkinInfo > VectorChildSkinInfo
VectorStringPairs properties
std::vector< WidgetInfo > childWidgetsInfo
TPoint< T > point() const
TSize< T > size() const