1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components/multimodal/render_multimodal.h"
17 
18 #include "core/components/multimodal/multimodal_component.h"
19 
20 namespace OHOS::Ace {
21 
RenderMultimodal()22 RenderMultimodal::RenderMultimodal()
23     : subscriptSwitchCallback_(std::bind(&RenderMultimodal::OnSubscriptSwitchChange, this, std::placeholders::_1))
24 {}
25 
PerformLayout()26 void RenderMultimodal::PerformLayout()
27 {
28     Size layoutSize;
29     const auto& children = GetChildren();
30     if (!children.empty()) {
31         auto child = children.front();
32         child->Layout(GetLayoutParam());
33         child->SetPosition(Offset::Zero());
34         layoutSize = child->GetLayoutSize();
35     }
36     SetLayoutSize(layoutSize);
37 }
38 
Update(const RefPtr<Component> & component)39 void RenderMultimodal::Update(const RefPtr<Component>& component)
40 {
41     auto multiModalComponent = DynamicCast<MultimodalComponent>(component);
42     ACE_DCHECK(multiModalComponent);
43     clickCallback_ = AceAsyncEvent<void(const ClickInfo&)>::Create(multiModalComponent->GetOnClickId(), context_);
44     pageId_ = multiModalComponent->GetPageId();
45     if (!multimodalEventCallback_) {
46         multimodalEventCallback_ = [weak = WeakClaim(this)](const AceMultimodalEvent&) {
47             auto renderMultiModal = weak.Upgrade();
48             if (renderMultiModal) {
49                 renderMultiModal->OnEventTrigger();
50             }
51         };
52     }
53     if (multiModalScene_.Invalid()) {
54         auto pipelineContext = GetContext().Upgrade();
55         if (!pipelineContext) {
56             LOGW("the pipeline context is null");
57             return;
58         }
59         auto multimodalManager = pipelineContext->GetMultiModalManager();
60         if (!multimodalManager) {
61             LOGW("the multimodal manager is null");
62             return;
63         }
64         auto multiModalScene = multimodalManager->GetMultiModalScene(pageId_);
65         multiModalScene->SubscribeSubscriptSwitchEvent(subscriptSwitchCallback_);
66         multiModalScene_ = multiModalScene;
67     }
68     PrepareMultimodalEvent(multiModalComponent->GetMultimodalProperties());
69     MarkNeedLayout();
70 }
71 
PrepareMultimodalEvent(const CommonMultimodalAttribute & multimodalProperties)72 void RenderMultimodal::PrepareMultimodalEvent(const CommonMultimodalAttribute& multimodalProperties)
73 {
74     auto multiModalScene = multiModalScene_.Upgrade();
75     if (!multiModalScene) {
76         LOGE("fail to prepare multimodal event due to scene is null");
77         return;
78     }
79     if (!multimodalProperties.voiceLabel.empty() &&
80         (voiceEvent_.GetVoiceContent() != multimodalProperties.voiceLabel)) {
81         multiModalScene->UnSubscribeVoiceEvent(voiceEvent_);
82         voiceEvent_ = VoiceEvent(multimodalProperties.voiceLabel, multimodalProperties.scene);
83         multiModalScene->SubscribeVoiceEvent(voiceEvent_, multimodalEventCallback_);
84     }
85     if (!multimodalProperties.useSubscript) {
86         if (useSubscript_) {
87             multiModalScene->UnSubscribeVoiceEvent(subscript_);
88             useSubscript_ = false;
89             if (useAutoSubscriptId_) {
90                 multiModalScene->RemoveSubscriptId(subscript_.GetVoiceContent());
91                 useAutoSubscriptId_ = false;
92             }
93         }
94         return;
95     }
96     if (!multimodalProperties.subscriptLabel.empty() &&
97         subscript_.GetVoiceContent() != multimodalProperties.subscriptLabel) {
98         multiModalScene->UnSubscribeVoiceEvent(subscript_);
99         if (useAutoSubscriptId_) {
100             multiModalScene->RemoveSubscriptId(subscript_.GetVoiceContent());
101             useAutoSubscriptId_ = false;
102         }
103         subscript_ = VoiceEvent(multimodalProperties.subscriptLabel, multimodalProperties.scene);
104         multiModalScene->SubscribeVoiceEvent(subscript_, multimodalEventCallback_);
105         return;
106     }
107     if (subscript_.GetVoiceContent().empty()) {
108         useAutoSubscriptId_ = true;
109         subscript_ = VoiceEvent(multiModalScene->GetAvailableSubscriptId(), SceneLabel::PAGE, true);
110         subscript_.SetBadgeList({ { "1", multiModalScene->GetCurrentMaxSubscriptId() } });
111         multiModalScene->SubscribeVoiceEvent(subscript_, multimodalEventCallback_);
112     }
113 }
114 
OnEventTrigger()115 void RenderMultimodal::OnEventTrigger()
116 {
117     if (clickCallback_) {
118         clickCallback_(ClickInfo(-1));
119     }
120 }
121 
~RenderMultimodal()122 RenderMultimodal::~RenderMultimodal()
123 {
124     auto multiModalScene = multiModalScene_.Upgrade();
125     if (!multiModalScene) {
126         LOGE("fail to destroy multimodal event due to multiModalScene is null");
127         return;
128     }
129     if (!voiceEvent_.GetVoiceContent().empty()) {
130         multiModalScene->UnSubscribeVoiceEvent(voiceEvent_);
131     }
132     if (!subscript_.GetVoiceContent().empty()) {
133         multiModalScene->UnSubscribeVoiceEvent(subscript_);
134         if (useAutoSubscriptId_) {
135             multiModalScene->RemoveSubscriptId(subscript_.GetVoiceContent());
136             useAutoSubscriptId_ = false;
137         }
138     }
139     multiModalScene->UnSubscribeSubscriptSwitchEvent(subscriptSwitchCallback_);
140 }
141 
OnHiddenChanged(bool hidden)142 void RenderMultimodal::OnHiddenChanged(bool hidden)
143 {
144     auto multiModalScene = multiModalScene_.Upgrade();
145     if (!multiModalScene) {
146         LOGE("fail to destroy multimodal event due to multiModalScene is null");
147         return;
148     }
149     // If it is hidden, release subscriptId and voiceEvent.
150     if (!voiceEvent_.GetVoiceContent().empty()) {
151         if (hidden) {
152             multiModalScene->UnSubscribeVoiceEvent(voiceEvent_);
153         } else {
154             multiModalScene->SubscribeVoiceEvent(voiceEvent_, multimodalEventCallback_);
155         }
156     }
157     if (!subscript_.GetVoiceContent().empty()) {
158         if (hidden) {
159             multiModalScene->UnSubscribeVoiceEvent(subscript_);
160         } else {
161             multiModalScene->SubscribeVoiceEvent(subscript_, multimodalEventCallback_);
162         }
163     }
164 }
165 
OnSubscriptSwitchChange(bool isOn)166 void RenderMultimodal::OnSubscriptSwitchChange(bool isOn)
167 {
168     if (isSubscriptShow_ != isOn) {
169         isSubscriptShow_ = isOn;
170         MarkNeedRender();
171     }
172 }
173 
174 } // namespace OHOS::Ace