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 "MaterialEasing.h" 24 : #include "MaterialLayerSurface.h" 25 : #include "MaterialSurfaceInterior.h" 26 : #include "MaterialStyleContainer.h" 27 : #include "XLFrameInfo.h" 28 : #include "XL2dCommandList.h" 29 : 30 : namespace STAPPLER_VERSIONIZED stappler::xenolith::material2d { 31 : 32 260 : bool LayerSurface::init(const SurfaceStyle &style) { 33 260 : if (!Layer::init(Color::White)) { 34 0 : return false; 35 : } 36 : 37 260 : _interior = addComponent(Rc<SurfaceInterior>::create()); 38 : 39 260 : _styleOrigin = _styleTarget = style; 40 260 : _styleDirty = true; 41 : 42 260 : return true; 43 : } 44 : 45 0 : void LayerSurface::setStyle(const SurfaceStyle &style) { 46 0 : if (_inTransition) { 47 0 : _styleDirty = true; 48 0 : stopAllActionsByTag(TransitionActionTag); 49 0 : _inTransition = false; 50 0 : _styleProgress = 0.0f; 51 : } 52 : 53 0 : if (_styleOrigin != style) { 54 0 : _styleOrigin = _styleTarget = move(style); 55 0 : _styleDirty = true; 56 : } 57 0 : } 58 : 59 0 : void LayerSurface::setStyle(const SurfaceStyle &style, float duration) { 60 0 : if (duration <= 0.0f || !_running) { 61 0 : setStyle(style); 62 0 : return; 63 : } 64 : 65 0 : if (_inTransition || getActionByTag(TransitionActionTag)) { 66 0 : _styleDirty = true; 67 0 : stopAllActionsByTag(TransitionActionTag); 68 0 : _inTransition = false; 69 0 : _styleProgress = 0.0f; 70 : } 71 : 72 0 : if (_styleOrigin != style) { 73 0 : _styleTarget = move(style); 74 0 : runAction(makeEasing(Rc<ActionProgress>::create(duration, [this] (float progress) { 75 0 : _styleProgress = progress; 76 0 : _styleDirty = true; 77 0 : }, [this] { 78 0 : _inTransition = true; 79 0 : }, [this] { 80 0 : _styleOrigin = _styleTarget; 81 0 : _styleDirty = true; 82 0 : _inTransition = false; 83 0 : _styleProgress = 0.0f; 84 0 : })), TransitionActionTag); 85 0 : _styleDirty = true; 86 : } 87 : } 88 : 89 0 : void LayerSurface::setColorRole(ColorRole value) { 90 0 : if (_styleTarget.colorRole != value) { 91 0 : if (_styleOrigin == _styleTarget) { 92 0 : _styleTarget.colorRole = _styleOrigin.colorRole = value; 93 0 : _styleDirty = true; 94 : } else { 95 0 : _styleTarget.colorRole = value; 96 0 : _styleDirty = true; 97 : } 98 : } 99 0 : } 100 : 101 0 : void LayerSurface::setElevation(Elevation value) { 102 0 : if (_styleTarget.elevation != value) { 103 0 : if (_styleOrigin == _styleTarget) { 104 0 : _styleTarget.elevation = _styleOrigin.elevation = value; 105 0 : _styleDirty = true; 106 : } else { 107 0 : _styleTarget.elevation = value; 108 0 : _styleDirty = true; 109 : } 110 : } 111 0 : } 112 : 113 0 : void LayerSurface::setShapeFamily(ShapeFamily value) { 114 0 : if (_styleTarget.shapeFamily != value) { 115 0 : if (_styleOrigin == _styleTarget) { 116 0 : _styleTarget.shapeFamily = _styleOrigin.shapeFamily = value; 117 0 : _styleDirty = true; 118 : } else { 119 0 : _styleTarget.shapeFamily = value; 120 0 : _styleDirty = true; 121 : } 122 : } 123 0 : } 124 : 125 0 : void LayerSurface::setShapeStyle(ShapeStyle value) { 126 0 : if (_styleTarget.shapeStyle != value) { 127 0 : if (_styleOrigin == _styleTarget) { 128 0 : _styleTarget.shapeStyle = _styleOrigin.shapeStyle = value; 129 0 : _styleDirty = true; 130 : } else { 131 0 : _styleTarget.shapeStyle = value; 132 0 : _styleDirty = true; 133 : } 134 : } 135 0 : } 136 : 137 0 : void LayerSurface::setNodeStyle(NodeStyle value) { 138 0 : if (_styleTarget.nodeStyle != value) { 139 0 : if (_styleOrigin == _styleTarget) { 140 0 : _styleTarget.nodeStyle = _styleOrigin.nodeStyle = value; 141 0 : _styleDirty = true; 142 : } else { 143 0 : _styleTarget.nodeStyle = value; 144 0 : _styleDirty = true; 145 : } 146 : } 147 0 : } 148 : 149 0 : void LayerSurface::setActivityState(ActivityState value) { 150 0 : if (_styleTarget.activityState != value) { 151 0 : if (_styleOrigin == _styleTarget) { 152 0 : _styleTarget.activityState = _styleOrigin.activityState = value; 153 0 : _styleDirty = true; 154 : } else { 155 0 : _styleTarget.activityState = value; 156 0 : _styleDirty = true; 157 : } 158 : } 159 0 : } 160 : 161 104 : void LayerSurface::setStyleDirtyCallback(Function<void(const SurfaceStyleData &)> &&cb) { 162 104 : _styleDirtyCallback = move(cb); 163 104 : _styleDirty = true; 164 104 : } 165 : 166 8285 : bool LayerSurface::visitDraw(FrameInfo &frame, NodeFlags parentFlags) { 167 8285 : if (!_visible) { 168 0 : return false; 169 : } 170 : 171 8285 : auto style = getStyleContainerForFrame(frame); 172 8285 : if (!style) { 173 0 : return false; 174 : } 175 : 176 8285 : if (style) { 177 8285 : if (_styleTarget.apply(_styleDataTarget, _contentSize, style, getSurfaceInteriorForFrame(frame))) { 178 2060 : _styleDirty = true; 179 : } 180 8285 : if (_styleOrigin.apply(_styleDataOrigin, _contentSize, style, getSurfaceInteriorForFrame(frame))) { 181 2060 : _styleDirty = true; 182 : } 183 : } 184 : 185 8285 : if (_styleDirty || _contentSizeDirty) { 186 2060 : if (_styleProgress > 0.0f) { 187 0 : _styleDataCurrent = progress(_styleDataOrigin, _styleDataTarget, _styleProgress); 188 : } else { 189 2060 : _styleDataCurrent = _styleDataOrigin; 190 : } 191 2060 : applyStyle(_styleDataCurrent); 192 2060 : _interior->setStyle(SurfaceStyleData(_styleDataCurrent)); 193 : } 194 : 195 8285 : return Layer::visitDraw(frame, parentFlags); 196 : } 197 : 198 2060 : void LayerSurface::applyStyle(const SurfaceStyleData &style) { 199 2060 : if (_styleDirtyCallback) { 200 824 : _styleDirtyCallback(style); 201 : } 202 : 203 2060 : setColor(style.colorElevation, false); 204 2060 : setDepthIndex(style.shadowValue); 205 2060 : _styleDirty = false; 206 2060 : } 207 : 208 8285 : StyleContainer *LayerSurface::getStyleContainerForFrame(FrameInfo &frame) const { 209 8285 : return frame.getComponent<StyleContainer>(StyleContainer::ComponentFrameTag); 210 : } 211 : 212 16570 : SurfaceInterior *LayerSurface::getSurfaceInteriorForFrame(FrameInfo &frame) const { 213 16570 : return frame.getComponent<SurfaceInterior>(SurfaceInterior::ComponentFrameTag); 214 : } 215 : 216 780 : RenderingLevel LayerSurface::getRealRenderingLevel() const { 217 780 : auto l = Layer::getRealRenderingLevel(); 218 780 : if (l == RenderingLevel::Transparent) { 219 260 : l = RenderingLevel::Surface; 220 : } 221 780 : return l; 222 : } 223 : 224 : }