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 #include "core/event/ace_event_helper.h"
20
21 namespace OHOS::Ace {
22
RenderMultimodal()23 RenderMultimodal::RenderMultimodal()
24 : subscriptSwitchCallback_(std::bind(&RenderMultimodal::OnSubscriptSwitchChange, this, std::placeholders::_1))
25 {}
26
PerformLayout()27 void RenderMultimodal::PerformLayout()
28 {
29 Size layoutSize;
30 const auto& children = GetChildren();
31 if (!children.empty()) {
32 auto child = children.front();
33 child->Layout(GetLayoutParam());
34 child->SetPosition(Offset::Zero());
35 layoutSize = child->GetLayoutSize();
36 }
37 SetLayoutSize(layoutSize);
38 }
39
Update(const RefPtr<Component> & component)40 void RenderMultimodal::Update(const RefPtr<Component>& component)
41 {
42 auto multiModalComponent = DynamicCast<MultimodalComponent>(component);
43 ACE_DCHECK(multiModalComponent);
44 clickCallback_ = AceAsyncEvent<void(const ClickInfo&)>::Create(multiModalComponent->GetOnClickId(), context_);
45 pageId_ = multiModalComponent->GetPageId();
46 if (!multimodalEventCallback_) {
47 multimodalEventCallback_ = [weak = WeakClaim(this)](const AceMultimodalEvent&) {
48 auto renderMultiModal = weak.Upgrade();
49 if (renderMultiModal) {
50 renderMultiModal->OnEventTrigger();
51 }
52 };
53 }
54 if (multiModalScene_.Invalid()) {
55 auto pipelineContext = GetContext().Upgrade();
56 if (!pipelineContext) {
57 LOGW("the pipeline context is null");
58 return;
59 }
60 auto multimodalManager = pipelineContext->GetMultiModalManager();
61 if (!multimodalManager) {
62 LOGW("the multimodal manager is null");
63 return;
64 }
65 auto multiModalScene = multimodalManager->GetMultiModalScene(pageId_);
66 multiModalScene->SubscribeSubscriptSwitchEvent(subscriptSwitchCallback_);
67 multiModalScene_ = multiModalScene;
68 }
69 PrepareMultimodalEvent(multiModalComponent->GetMultimodalProperties());
70 MarkNeedLayout();
71 }
72
PrepareMultimodalEvent(const CommonMultimodalAttribute & multimodalProperties)73 void RenderMultimodal::PrepareMultimodalEvent(const CommonMultimodalAttribute& multimodalProperties)
74 {
75 auto multiModalScene = multiModalScene_.Upgrade();
76 if (!multiModalScene) {
77 LOGE("fail to prepare multimodal event due to scene is null");
78 return;
79 }
80 if (!multimodalProperties.voiceLabel.empty() &&
81 (voiceEvent_.GetVoiceContent() != multimodalProperties.voiceLabel)) {
82 multiModalScene->UnSubscribeVoiceEvent(voiceEvent_);
83 voiceEvent_ = VoiceEvent(multimodalProperties.voiceLabel, multimodalProperties.scene);
84 multiModalScene->SubscribeVoiceEvent(voiceEvent_, multimodalEventCallback_);
85 }
86 if (!multimodalProperties.useSubscript) {
87 if (useSubscript_) {
88 multiModalScene->UnSubscribeVoiceEvent(subscript_);
89 useSubscript_ = false;
90 if (useAutoSubscriptId_) {
91 multiModalScene->RemoveSubscriptId(subscript_.GetVoiceContent());
92 useAutoSubscriptId_ = false;
93 }
94 }
95 return;
96 }
97 if (!multimodalProperties.subscriptLabel.empty() &&
98 subscript_.GetVoiceContent() != multimodalProperties.subscriptLabel) {
99 multiModalScene->UnSubscribeVoiceEvent(subscript_);
100 if (useAutoSubscriptId_) {
101 multiModalScene->RemoveSubscriptId(subscript_.GetVoiceContent());
102 useAutoSubscriptId_ = false;
103 }
104 subscript_ = VoiceEvent(multimodalProperties.subscriptLabel, multimodalProperties.scene);
105 multiModalScene->SubscribeVoiceEvent(subscript_, multimodalEventCallback_);
106 return;
107 }
108 if (subscript_.GetVoiceContent().empty()) {
109 useAutoSubscriptId_ = true;
110 subscript_ = VoiceEvent(multiModalScene->GetAvailableSubscriptId(), SceneLabel::PAGE, true);
111 subscript_.SetBadgeList({ { "1", multiModalScene->GetCurrentMaxSubscriptId() } });
112 multiModalScene->SubscribeVoiceEvent(subscript_, multimodalEventCallback_);
113 }
114 }
115
OnEventTrigger()116 void RenderMultimodal::OnEventTrigger()
117 {
118 if (clickCallback_) {
119 clickCallback_(ClickInfo(-1));
120 }
121 }
122
~RenderMultimodal()123 RenderMultimodal::~RenderMultimodal()
124 {
125 auto multiModalScene = multiModalScene_.Upgrade();
126 if (!multiModalScene) {
127 LOGE("fail to destroy multimodal event due to multiModalScene is null");
128 return;
129 }
130 if (!voiceEvent_.GetVoiceContent().empty()) {
131 multiModalScene->UnSubscribeVoiceEvent(voiceEvent_);
132 }
133 if (!subscript_.GetVoiceContent().empty()) {
134 multiModalScene->UnSubscribeVoiceEvent(subscript_);
135 if (useAutoSubscriptId_) {
136 multiModalScene->RemoveSubscriptId(subscript_.GetVoiceContent());
137 useAutoSubscriptId_ = false;
138 }
139 }
140 multiModalScene->UnSubscribeSubscriptSwitchEvent(subscriptSwitchCallback_);
141 }
142
OnHiddenChanged(bool hidden)143 void RenderMultimodal::OnHiddenChanged(bool hidden)
144 {
145 auto multiModalScene = multiModalScene_.Upgrade();
146 if (!multiModalScene) {
147 LOGE("fail to destroy multimodal event due to multiModalScene is null");
148 return;
149 }
150 // If it is hidden, release subscriptId and voiceEvent.
151 if (!voiceEvent_.GetVoiceContent().empty()) {
152 if (hidden) {
153 multiModalScene->UnSubscribeVoiceEvent(voiceEvent_);
154 } else {
155 multiModalScene->SubscribeVoiceEvent(voiceEvent_, multimodalEventCallback_);
156 }
157 }
158 if (!subscript_.GetVoiceContent().empty()) {
159 if (hidden) {
160 multiModalScene->UnSubscribeVoiceEvent(subscript_);
161 } else {
162 multiModalScene->SubscribeVoiceEvent(subscript_, multimodalEventCallback_);
163 }
164 }
165 }
166
OnSubscriptSwitchChange(bool isOn)167 void RenderMultimodal::OnSubscriptSwitchChange(bool isOn)
168 {
169 if (isSubscriptShow_ != isOn) {
170 isSubscriptShow_ = isOn;
171 MarkNeedRender();
172 }
173 }
174
175 } // namespace OHOS::Ace