Line data Source code
1 : /**
2 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "MaterialMenuButton.h"
24 : #include "MaterialFloatingMenu.h"
25 : #include "MaterialLabel.h"
26 : #include "MaterialScene.h"
27 :
28 : namespace STAPPLER_VERSIONIZED stappler::xenolith::material2d {
29 :
30 0 : float MenuButton::getMaxWidthForButton(MenuSourceButton *btn, font::FontController *c, float density) {
31 0 : float widthFront = 12.0f;
32 0 : float widthBack = 12.0f;
33 :
34 0 : if (btn->getNameIcon() != IconName::None) {
35 0 : widthFront += 18.0f + 12.0f;
36 : }
37 :
38 0 : if (!btn->getName().empty()) {
39 0 : auto style = TypescaleLabel::getTypescaleRoleStyle(TypescaleRole::LabelLarge, density);
40 0 : style.text.textTransform = font::TextTransform::Uppercase;
41 0 : widthFront += Label::getStringWidth(c, style, btn->getName(), true);
42 : }
43 :
44 0 : if (btn->getValueIcon() != IconName::None) {
45 0 : widthBack += 18.0f + 12.0f;
46 : }
47 :
48 0 : if (!btn->getValue().empty()) {
49 0 : auto style = TypescaleLabel::getTypescaleRoleStyle(TypescaleRole::LabelLarge, density);
50 0 : widthFront += Label::getStringWidth(c, style, btn->getValue(), true);
51 : }
52 :
53 0 : return widthFront + 4.0f + widthBack;
54 : }
55 :
56 40 : bool MenuButton::init(Menu *menu, MenuSourceButton *button) {
57 40 : if (!Button::init(SurfaceStyle({
58 0 : Elevation::Level1,
59 0 : ColorRole::Primary,
60 0 : NodeStyle::Text,
61 80 : ShapeStyle::None
62 : }))) {
63 0 : return false;
64 : }
65 :
66 40 : setMenu(menu);
67 40 : setMenuSourceButton(button);
68 40 : setFollowContentSize(false);
69 40 : setTapCallback(std::bind(&MenuButton::handleButton, this));
70 :
71 40 : return true;
72 : }
73 :
74 0 : void MenuButton::setWrapName(bool val) {
75 0 : if (_wrapName != val) {
76 0 : _wrapName = val;
77 0 : _contentSizeDirty = true;
78 : }
79 0 : }
80 :
81 0 : bool MenuButton::isWrapName() const {
82 0 : return _wrapName;
83 : }
84 :
85 10 : void MenuButton::handleButton() {
86 10 : if (auto s = _menuButtonListener->getSubscription()) {
87 10 : Rc<Menu> menu = getMenu();
88 10 : if (auto cb = s->getCallback()) {
89 10 : cb(this, s);
90 10 : }
91 10 : if (auto nextMenu = s->getNextMenu()) {
92 0 : if (auto content = dynamic_cast<SceneContent2d *>(_scene->getContent())) {
93 0 : auto posRight = content->convertToNodeSpace(convertToWorldSpace(Vec2(_contentSize.width, _contentSize.height)));
94 :
95 0 : FloatingMenu::push(content, nextMenu, posRight,
96 : FloatingMenu::Binding::OriginRight, _menu);
97 : }
98 : }
99 10 : if (menu) {
100 10 : menu->onMenuButtonPressed(this);
101 : }
102 10 : }
103 10 : }
104 :
105 120 : void MenuButton::layoutContent() {
106 120 : float offsetFront = 12.0f;
107 120 : float offsetBack = _contentSize.width - 12.0f;
108 :
109 120 : if (getTrailingIconName() != IconName::None) {
110 90 : _trailingIcon->setAnchorPoint(Anchor::MiddleRight);
111 90 : _trailingIcon->setPosition(Vec2(offsetBack, _contentSize.height / 2));
112 90 : offsetBack -= _trailingIcon->getContentSize().width + 12.0f;
113 : }
114 :
115 120 : if (!_labelValue->empty()) {
116 90 : _labelValue->setAnchorPoint(Anchor::MiddleRight);
117 90 : _labelValue->setPosition(Vec2(offsetBack, _contentSize.height / 2));
118 90 : offsetBack -= _labelValue->getContentSize().width + 12.0f;
119 : }
120 :
121 120 : if (getLeadingIconName() != IconName::None) {
122 60 : _leadingIcon->setAnchorPoint(Anchor::MiddleLeft);
123 60 : _leadingIcon->setPosition(Vec2(offsetFront, _contentSize.height / 2));
124 60 : offsetFront += _leadingIcon->getContentSize().width + 12.0f;
125 : }
126 :
127 120 : _labelText->setAnchorPoint(Anchor::MiddleLeft);
128 120 : _labelText->setPosition(Vec2(offsetFront, _contentSize.height / 2));
129 120 : _labelText->setTextTransform(font::TextTransform::Uppercase);
130 :
131 120 : if (_wrapName) {
132 120 : _labelText->setWidth(offsetBack - offsetFront - 4.0f);
133 : } else {
134 0 : _labelText->setMaxWidth(offsetBack - offsetFront - 4.0f);
135 : }
136 120 : }
137 :
138 : }
|