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