* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "frameworks/bridge/common/dom/dom_progress.h"
#include "frameworks/bridge/common/utils/utils.h"
namespace OHOS::Ace::Framework {
bool IsGradient(const std::string& value)
{
auto gradientJson = JsonUtil::ParseJsonString(value);
if (!gradientJson->IsObject()) {
return false;
}
return true;
}
Gradient ParseGradient(const DOMProgress& progress, const std::string& value)
{
auto gradientJson = JsonUtil::ParseJsonString(value);
Gradient gradient = Gradient();
if (!gradientJson->IsObject()) {
return gradient;
}
auto gradientValue = gradientJson->GetValue(DOM_VALUES);
if ((gradientValue == nullptr) || (!gradientValue->IsArray()) || (gradientValue->GetArraySize() <= 0)) {
return gradient;
}
auto values = gradientValue->GetArrayItem(0);
gradient.SetDirection(GradientDirection::START_TO_END);
auto colors = values->GetValue(DOM_GRADIENT_VALUES);
if (colors != nullptr && colors->IsArray()) {
for (int32_t index = 0; index < colors->GetArraySize(); index++) {
if (colors->GetArrayItem(index)->ToString().length() > 2) {
gradient.AddColor(GradientColor(progress.ParseColor(colors->GetArrayItem(index)->ToString().substr(
1, colors->GetArrayItem(index)->ToString().length() - 2))));
}
}
}
return gradient;
}
RefPtr<ProgressComponent> DOMProgress::CreateProgressComponent(
double min, double percent, double cachedValue, double max, ProgressType type)
{
if (type == ProgressType::CIRCLE) {
return AceType::MakeRefPtr<ProgressComponent>(min, percent, cachedValue, max, ProgressType::LINEAR);
}
return AceType::MakeRefPtr<ProgressComponent>(min, percent, cachedValue, max, type);
}
DOMProgress::DOMProgress(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName) {}
bool DOMProgress::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
{
static const LinearMapNode<void (*)(const std::string&, DOMProgress&)> progressAttrsOperators[] = {
{ DOM_RING_CLOCKWISH_DIRECTION,
[](const std::string& val, DOMProgress& progress) { progress.clockwiseDirection_ = StringToBool(val); } },
{ DOM_EFFECTS_ON,
[](const std::string& val, DOMProgress& progress) { progress.showAnimationEffect_ = StringToBool(val); } },
{ DOM_PROGRESS_PERCENT,
[](const std::string& val, DOMProgress& progress) {
progress.percent_ = StringToDouble(val);
if (progress.percent_ > progress.max_) {
progress.percent_ = progress.max_;
}
if (progress.percent_ < progress.min_) {
progress.percent_ = progress.min_;
}
} },
{ DOM_PROGRESS_SECONDARY_PERCENT,
[](const std::string& val, DOMProgress& progress) {
progress.cachedValue_ = StringToDouble(val);
if (progress.cachedValue_ > progress.max_) {
progress.cachedValue_ = progress.max_;
}
if (progress.cachedValue_ < progress.min_) {
progress.cachedValue_ = progress.min_;
}
} },
{ DOM_PROGRESS_TYPE,
[](const std::string& val, DOMProgress& progress) {
if (val == DOM_PROGRESS_TYPE_CIRCULAR) {
progress.type_ = ProgressType::CIRCLE;
} else if (val == DOM_PROGRESS_TYPE_RING) {
progress.type_ = ProgressType::RING;
} else if (val == DOM_PROGRESS_TYPE_HORIZONTAL) {
progress.type_ = ProgressType::LINEAR;
} else if (val == DOM_PROGRESS_TYPE_SCALE) {
progress.type_ = ProgressType::SCALE;
} else if (val == DOM_PROGRESS_TYPE_MOON) {
progress.type_ = ProgressType::MOON;
} else if ((val == DOM_PROGRESS_TYPE_ARC)) {
progress.type_ = ProgressType::ARC;
} else if ((val == DOM_PROGRESS_TYPE_BUBBLE)) {
progress.type_ = ProgressType::BUBBLE;
} else {
progress.type_ = ProgressType::LINEAR;
}
} },
};
auto operatorIter =
BinarySearchFindIndex(progressAttrsOperators, ArraySize(progressAttrsOperators), attr.first.c_str());
if (operatorIter != -1) {
progressAttrsOperators[operatorIter].value(attr.second, *this);
return true;
}
return false;
}
bool DOMProgress::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
{
static const LinearMapNode<void (*)(const std::string&, DOMProgress&)> progressStylesOperators[] = {
{ DOM_PROGRESS_BACKGROUND_COLOR,
[](const std::string& val, DOMProgress& progress) {
progress.backgroundColor_.first = progress.ParseColor(val);
progress.backgroundColor_.second = true;
} },
{ DOM_PROGRESS_BUBBLE_RADIUS,
[](const std::string& val, DOMProgress& progress) {
progress.diameter_ = progress.ParseDimension(val);
} },
{ DOM_CENTER_X,
[](const std::string& val, DOMProgress& progress) {
progress.centerX_.first = StringToDouble(val);
progress.centerX_.second = true;
} },
{ DOM_CENTER_Y,
[](const std::string& val, DOMProgress& progress) {
progress.centerY_.first = StringToDouble(val);
progress.centerY_.second = true;
} },
{ DOM_PROGRESS_COLOR,
[](const std::string& val, DOMProgress& progress) {
if (IsGradient(val)) {
progress.gradient_ = ParseGradient(progress, val);
} else {
progress.color_.first = progress.ParseColor(val);
progress.color_.second = true;
}
} },
{ DOM_PROGRESS_DIAMETER,
[](const std::string& val, DOMProgress& progress) {
progress.bubbleRadius_ = progress.ParseDimension(val);
} },
{ DOM_DIRECTION,
[](const std::string& val, DOMProgress& progress) { progress.isStartToEnd_ = val == DOM_START_TO_END; } },
{ DOM_PROGRESS_RADIUS,
[](const std::string& val, DOMProgress& progress) {
progress.radius_.first = StringToDouble(val);
progress.radius_.second = true;
} },
{ DOM_SCALE_NUMBER,
[](const std::string& val, DOMProgress& progress) {
progress.scaleNumber_.first = StringUtils::StringToInt(val);
progress.scaleNumber_.second = true;
} },
{ DOM_SCALE_WIDTH,
[](const std::string& val, DOMProgress& progress) {
progress.scaleWidth_.first = progress.ParseDimension(val);
progress.scaleWidth_.second = true;
} },
{ DOM_PROGRESS_SECONDARY_COLOR,
[](const std::string& val, DOMProgress& progress) {
progress.cachedColor_.first = progress.ParseColor(val);
progress.cachedColor_.second = true;
} },
{ DOM_START_DEGREE,
[](const std::string& val, DOMProgress& progress) { progress.startDegree_ = StringToDouble(val); } },
{ DOM_PROGRESS_STROKE_WIDTH,
[](const std::string& val, DOMProgress& progress) {
progress.strokeWidth_.first = progress.ParseDimension(val);
progress.strokeWidth_.second = true;
} },
{ DOM_SWEEP_DEGREE,
[](const std::string& val, DOMProgress& progress) { progress.sweepDegree_ = StringToDouble(val); } },
};
auto operatorIter =
BinarySearchFindIndex(progressStylesOperators, ArraySize(progressStylesOperators), style.first.c_str());
if (operatorIter != -1) {
progressStylesOperators[operatorIter].value(style.second, *this);
return true;
}
return false;
}
void DOMProgress::PrepareSpecializedComponent()
{
InitProgressIfNeed();
if (type_ == ProgressType::CIRCLE) {
loadingProgressChild_->SetProgressColor(color_.first);
return;
}
if (type_ == ProgressType::BUBBLE) {
bubbleProgressChild_->SetBubbleRadius(bubbleRadius_);
bubbleProgressChild_->SetDiameter(diameter_);
return;
}
progressChild_->SetMaxValue(max_);
progressChild_->SetMinValue(min_);
progressChild_->SetValue(percent_);
progressChild_->SetCachedValue(cachedValue_);
progressChild_->GetTrack()->SetSelectColor(color_.first);
progressChild_->GetTrack()->SetCachedColor(cachedColor_.first);
progressChild_->GetTrack()->SetBackgroundColor(backgroundColor_.first);
progressChild_->GetTrack()->SetTrackThickness(strokeWidth_.first);
progressChild_->GetTrack()->SetShowAnimation(showAnimationEffect_);
progressChild_->SetAnimationPlay(showAnimationEffect_);
progressChild_->GetTrack()->SetTextDirection(
IsRightToLeft() && isStartToEnd_ ? TextDirection::RTL : TextDirection::LTR);
if (gradient_.IsValid()) {
progressChild_->GetTrack()->SetSelectGradient(gradient_);
}
if (type_ == ProgressType::RING) {
auto info = progressChild_->GetTrack()->GetTrackInfo();
info->SetClockwise(clockwiseDirection_);
} else if (type_ == ProgressType::SCALE) {
auto info = progressChild_->GetTrack()->GetTrackInfo();
info->SetScaleWidth(scaleWidth_.first);
info->SetScaleNumber(scaleNumber_.first);
info->SetClockwise(clockwiseDirection_);
} else if (type_ == ProgressType::ARC) {
progressChild_->GetTrack()->GetTrackInfo()->SetStartDegree(startDegree_);
progressChild_->GetTrack()->GetTrackInfo()->SetSweepDegree(sweepDegree_);
if (radius_.second) {
progressChild_->GetTrack()->SetRadius(radius_.first);
}
if (centerX_.second) {
progressChild_->GetTrack()->SetCenterX(centerX_.first);
}
if (centerY_.second) {
progressChild_->GetTrack()->SetCenterY(centerY_.first);
}
}
}
void DOMProgress::OnSetStyleFinished()
{
static constexpr double defaultStartDegree = -120;
static constexpr double defaultSweepDegree = 240;
if (startDegree_ > 360.0 || startDegree_ < -360.0) {
startDegree_ = defaultStartDegree;
sweepDegree_ = defaultSweepDegree;
return;
}
if (sweepDegree_ > 360.0 || sweepDegree_ < -360.0) {
startDegree_ = defaultStartDegree;
sweepDegree_ = defaultSweepDegree;
return;
}
}
RefPtr<Component> DOMProgress::GetSpecializedComponent()
{
if (type_ == ProgressType::CIRCLE) {
return loadingProgressChild_;
} else if (type_ == ProgressType::BUBBLE) {
return bubbleProgressChild_;
} else {
return progressChild_;
}
}
void DOMProgress::InitProgressIfNeed()
{
auto theme = GetTheme<ProgressTheme>();
if (type_ == ProgressType::CIRCLE) {
if (!loadingProgressChild_) {
loadingProgressChild_ = AceType::MakeRefPtr<LoadingProgressComponent>();
}
if (theme) {
if (!color_.second) {
color_.first = theme->GetProgressColor();
}
loadingProgressChild_->SetMoveRatio(theme->GetMoveRatio());
loadingProgressChild_->SetRingRadius(theme->GetRingRadius());
loadingProgressChild_->SetOrbitRadius(theme->GetOrbitRadius());
loadingProgressChild_->SetCometTailLen(theme->GetCometTailLen());
}
return;
}
if (type_ == ProgressType::BUBBLE) {
if (!bubbleProgressChild_) {
bubbleProgressChild_ = AceType::MakeRefPtr<BubbleProgressComponent>();
}
return;
}
if (!progressChild_ || progressChild_->GetType() != type_) {
progressChild_ = CreateProgressComponent(min_, percent_, cachedValue_, max_, type_);
}
if (!theme) {
return;
}
if (!color_.second) {
color_.first = type_ == ProgressType::MOON ? theme->GetMoonFrontColor() : theme->GetTrackSelectedColor();
}
if (!backgroundColor_.second) {
backgroundColor_.first =
type_ == ProgressType::MOON ? theme->GetMoonBackgroundColor() : theme->GetTrackBgColor();
}
if (!cachedColor_.second) {
cachedColor_.first = theme->GetTrackCachedColor();
}
if (!strokeWidth_.second) {
if (type_ == ProgressType::SCALE) {
strokeWidth_.first = theme->GetScaleLength();
} else if (type_ == ProgressType::RING) {
strokeWidth_.first = theme->GetRingThickness();
} else {
strokeWidth_.first = theme->GetTrackThickness();
}
}
if (!scaleWidth_.second) {
scaleWidth_.first = theme->GetScaleWidth();
}
if (!scaleNumber_.second) {
scaleNumber_.first = theme->GetScaleNumber();
}
}
}