* Copyright (c) 2020-2021 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 "components/ui_dialog.h"
#include "common/screen.h"
#include "common/typed_text.h"
#if ENABLE_DEBUG
#include "gfx_utils/graphic_assert.h"
#endif
#include "gfx_utils/graphic_log.h"
#if ENABLE_WINDOW
#include "window/window.h"
#endif
#if ENABLE_WINDOW
namespace OHOS {
class UIDialogLabelButton : public UILabelButton {
public:
explicit UIDialogLabelButton(UIDialog* dialog)
{
dialog_ = dialog;
}
virtual ~UIDialogLabelButton() {}
virtual bool OnClickEvent(const ClickEvent& event)
{
bool ret = true;
if (dialog_ != nullptr) {
dialog_->DestroyWindow();
dialog_->isShowing_ = false;
}
if (onClickListener_ != nullptr) {
ret = onClickListener_->OnClick(*this, event);
}
return ret;
}
private:
UIDialog* dialog_;
};
class UIDialogClickListener : public UIView::OnClickListener {
public:
explicit UIDialogClickListener(UIDialog* dialog)
{
dialog_ = dialog;
}
virtual ~UIDialogClickListener() {}
bool OnClick(UIView& view, const ClickEvent& event) override
{
bool ret = true;
if ((dialog_ != nullptr) && (dialog_->dialogLayer_ != nullptr) &&
!dialog_->dialogLayer_->GetRect().IsContains(event.GetCurrentPos())) {
if (dialog_->enableAutoCancel_) {
dialog_->DestroyWindow();
dialog_->isShowing_ = false;
}
if (dialog_->onCancelListener_ != nullptr) {
ret = dialog_->onCancelListener_->OnClick(view, event);
}
}
return ret;
}
private:
UIDialog* dialog_;
};
UIDialog::UIDialog()
: isShowing_(false),
enableAutoCancel_(false),
buttonNum_(0),
title_(nullptr),
text_(nullptr),
button1_(nullptr),
button2_(nullptr),
button3_(nullptr),
dialogLayer_(nullptr),
windowRootView_(nullptr),
onCancelListener_(nullptr),
dialogClickListener_(nullptr),
window_(nullptr),
line1_(nullptr),
line2_(nullptr),
titleText_(nullptr),
textText_(nullptr)
{
uint16_t screenWidth = Screen::GetInstance().GetWidth();
uint16_t screenHeight = Screen::GetInstance().GetHeight();
widthMax_ = screenWidth * MAX_WIDTH_PERCENT / 100;
heightMax_ = screenHeight * MAX_HEIGHT_PERCENT / 100;
colorType1_ = Color::White();
colorType2_ = Color::White();
colorType3_ = Color::White();
}
UIDialog::~UIDialog()
{
onCancelListener_ = nullptr;
if (dialogLayer_ != nullptr) {
dialogLayer_->RemoveAll();
delete dialogLayer_;
dialogLayer_ = nullptr;
}
if (title_ != nullptr) {
delete title_;
title_ = nullptr;
}
if (text_ != nullptr) {
delete text_;
text_ = nullptr;
}
if (button1_ != nullptr) {
delete button1_;
button1_ = nullptr;
}
if (button2_ != nullptr) {
delete button2_;
button2_ = nullptr;
}
if (button3_ != nullptr) {
delete button3_;
button3_ = nullptr;
}
if (line1_ != nullptr) {
delete line1_;
line1_ = nullptr;
}
if (line2_ != nullptr) {
delete line2_;
line2_ = nullptr;
}
if ((windowRootView_ != nullptr) && !RootView::DestroyWindowRootView(windowRootView_)) {
windowRootView_ = nullptr;
}
if (dialogClickListener_ != nullptr) {
delete dialogClickListener_;
dialogClickListener_ = nullptr;
}
}
void UIDialog::SetTitle(const char* title)
{
if (title == nullptr) {
return;
}
titleText_ = title;
}
void UIDialog::SetText(const char* text)
{
if (text == nullptr) {
return;
}
textText_ = text;
}
void UIDialog::SetButton(DialogButtonType buttonType, const char* text, UIView::OnClickListener* listener)
{
switch (buttonType) {
case DialogButtonType::BUTTON_LEFT:
if (button1_ == nullptr) {
button1_ = new UIDialogLabelButton(this);
if (button1_ == nullptr) {
GRAPHIC_LOGE("new UIDialogLabelButton fail");
return;
}
button1_->SetViewId(BUTTON1_ID);
AddButton(buttonType, button1_, text, listener);
} else {
button1_->SetText(text);
button1_->SetOnClickListener(listener);
}
break;
case DialogButtonType::BUTTON_MID:
if (button2_ == nullptr) {
button2_ = new UIDialogLabelButton(this);
if (button2_ == nullptr) {
GRAPHIC_LOGE("new UIDialogLabelButton fail");
return;
}
button2_->SetViewId(BUTTON2_ID);
AddButton(buttonType, button2_, text, listener);
} else {
button2_->SetText(text);
button2_->SetOnClickListener(listener);
}
break;
case DialogButtonType::BUTTON_RIGHT:
if (button3_ == nullptr) {
button3_ = new UIDialogLabelButton(this);
if (button3_ == nullptr) {
GRAPHIC_LOGE("new UIDialogLabelButton fail");
return;
}
AddButton(buttonType, button3_, text, listener);
} else {
button3_->SetText(text);
button3_->SetOnClickListener(listener);
}
break;
default:
break;
}
}
void UIDialog::AddButton(DialogButtonType buttonType,
UILabelButton* button,
const char* text,
UIView::OnClickListener* listener)
{
buttonNum_++;
button->SetText(text);
button->SetOnClickListener(listener);
button->SetFont(DEFAULT_VECTOR_FONT_FILENAME, BUTTON_FONT_SIZE);
button->SetTextColor(Color::Blue());
button->SetStyleForState(STYLE_BACKGROUND_COLOR, Color::White().full, UIButton::ButtonState::RELEASED);
button->SetStyleForState(STYLE_BACKGROUND_COLOR, Color::Black().full, UIButton::ButtonState::PRESSED);
button->SetStyleForState(STYLE_BACKGROUND_OPA, BUTTON_PRESS_OPA, UIButton::ButtonState::PRESSED);
button->SetStyleForState(STYLE_BORDER_WIDTH, 0, UIButton::ButtonState::RELEASED);
button->SetStyleForState(STYLE_BORDER_WIDTH, 0, UIButton::ButtonState::PRESSED);
button->SetHeight(BUTTON_HEIGHT);
}
void UIDialog::Show()
{
if (isShowing_) {
return;
}
SetTitleLabel();
SetTextLabel();
InitDialog();
AddComponents();
MeasureSize();
Layout();
CreateDialogWindow();
window_->Show();
isShowing_ = true;
}
void UIDialog::SetTitleLabel()
{
if (titleText_ == nullptr) {
return;
}
if (title_ == nullptr) {
title_ = new UILabel();
if (title_ == nullptr) {
GRAPHIC_LOGE("new UILabel fail");
return;
}
title_->SetViewId(TITLE_ID);
title_->SetFont(DEFAULT_VECTOR_FONT_FILENAME, TITLE_FONT_SIZE);
title_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT);
title_->SetStyle(STYLE_TEXT_COLOR, Color::Black().full);
title_->SetStyle(STYLE_TEXT_OPA, TITLE_TEXT_OPA);
title_->SetStyle(STYLE_BACKGROUND_COLOR, Color::White().full);
}
title_->SetText(titleText_);
}
void UIDialog::SetTextLabel()
{
if (textText_ == nullptr) {
return;
}
if (text_ == nullptr) {
text_ = new UILabel();
if (text_ == nullptr) {
GRAPHIC_LOGE("new UILabel fail");
return;
}
text_->SetFont(DEFAULT_VECTOR_FONT_FILENAME, TEXT_FONT_SIZE);
text_->SetStyle(STYLE_TEXT_COLOR, Color::Black().full);
text_->SetStyle(STYLE_TEXT_OPA, TITLE_TEXT_OPA);
text_->SetStyle(STYLE_BACKGROUND_COLOR, Color::White().full);
}
text_->SetText(textText_);
}
void UIDialog::InitDialog()
{
if (dialogLayer_ == nullptr) {
dialogLayer_ = new UIViewGroup();
if (dialogLayer_ == nullptr) {
GRAPHIC_LOGE("new UIViewGroup fail");
return;
}
dialogLayer_->SetStyle(STYLE_BACKGROUND_COLOR, Color::White().full);
}
if (windowRootView_ == nullptr) {
windowRootView_ = RootView::GetWindowRootView();
windowRootView_->SetWidth(Screen::GetInstance().GetWidth());
windowRootView_->SetHeight(Screen::GetInstance().GetHeight());
windowRootView_->SetTouchable(true);
windowRootView_->Add(dialogLayer_);
}
if (dialogClickListener_ == nullptr) {
dialogClickListener_ = new UIDialogClickListener(this);
if (dialogClickListener_ == nullptr) {
GRAPHIC_LOGE("new UIDialogClickListener fail");
return;
}
windowRootView_->SetOnClickListener(dialogClickListener_);
}
}
void UIDialog::AddComponents()
{
if (title_ != nullptr) {
dialogLayer_->Add(title_);
}
if (text_ != nullptr) {
dialogLayer_->Add(text_);
}
if (button1_ != nullptr) {
dialogLayer_->Add(button1_);
}
if (button2_ != nullptr) {
dialogLayer_->Add(button2_);
}
if (button3_ != nullptr) {
dialogLayer_->Add(button3_);
}
if (buttonNum_ > 1) {
line1_ = new UIView();
if (line1_ == nullptr) {
GRAPHIC_LOGE("new UIView fail");
return;
}
line1_->SetHeight(LINE_HEIGHT);
line1_->SetWidth(LINE_WIDTH);
line1_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full);
line1_->SetStyle(STYLE_BACKGROUND_OPA, LINE_OPA);
dialogLayer_->Add(line1_);
}
if (buttonNum_ == 3) {
line2_ = new UIView();
if (line2_ == nullptr) {
GRAPHIC_LOGE("new UIView fail");
return;
}
line2_->SetHeight(LINE_HEIGHT);
line2_->SetWidth(LINE_WIDTH);
line2_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full);
line2_->SetStyle(STYLE_BACKGROUND_OPA, LINE_OPA);
dialogLayer_->Add(line2_);
}
}
void UIDialog::MeasureSize()
{
uint16_t width = MeasureMaxWidth();
uint16_t height = 0;
if (buttonNum_ > 0) {
uint16_t buttonWidth = (width - 2 * BUTTON_PADDING - (buttonNum_ - 1) * BUTTON_MID_PADDING) / buttonNum_;
width = static_cast<uint32_t>(buttonWidth) * buttonNum_ + (buttonNum_ - 1) * BUTTON_MID_PADDING +
2 * BUTTON_PADDING;
height += BUTTON_TOTAL_HEIGHT;
height += TEXT_BUTTON_PADDING;
if (button1_ != nullptr) {
button1_->SetWidth(buttonWidth);
}
if (button2_ != nullptr) {
button2_->SetWidth(buttonWidth);
}
if (button3_ != nullptr) {
button3_->SetWidth(buttonWidth);
}
} else {
height += PADDING;
}
if (title_ != nullptr) {
title_->SetWidth(width - 2 * PADDING);
height += TITLE_TOTAL_HEIGHT;
} else {
height += PADDING;
}
if (text_ != nullptr) {
text_->SetWidth(width - 2 * PADDING);
uint16_t textHightMax = heightMax_ - height;
if (text_->GetTextHeight() < textHightMax) {
text_->SetHeight(text_->GetTextHeight());
} else {
text_->SetHeight(textHightMax);
text_->SetLineBreakMode(UILabel::LINE_BREAK_ELLIPSIS);
}
height += text_->GetHeight();
}
uint16_t dialogHeight = height;
dialogLayer_->SetHeight(dialogHeight);
dialogLayer_->SetWidth(width);
}
uint16_t UIDialog::MeasureMaxWidth()
{
uint16_t titleWidth = 0;
uint16_t textWidth = 0;
uint16_t buttonTotalWidth = 0;
if (title_ != nullptr) {
titleWidth = MeasureTitleWidth();
titleWidth += 2 * PADDING;
}
if (text_ != nullptr) {
textWidth = MeasureTextWidth();
textWidth += 2 * PADDING;
}
if (buttonNum_ > 0) {
buttonTotalWidth =
static_cast<uint32_t>(MeasureButtonWidth()) * buttonNum_ + (buttonNum_ - 1) * BUTTON_MID_PADDING;
buttonTotalWidth += 2 * BUTTON_PADDING;
}
return MATH_MAX(titleWidth, MATH_MAX(textWidth, buttonTotalWidth));
}
uint16_t UIDialog::MeasureTitleWidth()
{
uint16_t titleWidth = 0;
uint16_t widthMaxNoPadding = widthMax_ - 2 * PADDING;
title_->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT);
if (title_->GetTextWidth() > widthMaxNoPadding) {
titleWidth = widthMaxNoPadding;
title_->SetLineBreakMode(UILabel::LINE_BREAK_ELLIPSIS);
} else {
titleWidth = title_->GetTextWidth();
}
title_->SetHeight(title_->GetTextHeight());
return titleWidth;
}
uint16_t UIDialog::MeasureTextWidth()
{
uint16_t textWidth = 0;
uint16_t widthMaxNoPadding = widthMax_ - 2 * PADDING;
if (title_ != nullptr) {
text_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT);
} else {
text_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
}
text_->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT);
textWidth = text_->GetTextWidth();
if (text_->GetTextWidth() > widthMaxNoPadding) {
text_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT);
textWidth = widthMaxNoPadding;
text_->SetLineBreakMode(UILabel::LINE_BREAK_WRAP);
}
return textWidth;
}
uint16_t UIDialog::MeasureButtonWidth()
{
if (buttonNum_ == 0) {
return 0;
}
uint16_t buttonTextWidth = 0;
uint16_t buttonMaxWidth = (widthMax_ - 2 * BUTTON_PADDING - (buttonNum_ - 1) * BUTTON_MID_PADDING) / buttonNum_;
if (button1_ != nullptr) {
const char* text1 = button1_->GetText();
buttonTextWidth =
MATH_MAX(buttonTextWidth, TypedText::GetTextSize(text1, button1_->GetFontId(), BUTTON_FONT_SIZE,
button1_->GetStyleConst().letterSpace_,
button1_->GetStyleConst().lineHeight_, widthMax_, 0).x);
}
if (button2_ != nullptr) {
const char* text2 = button2_->GetText();
buttonTextWidth =
MATH_MAX(buttonTextWidth, TypedText::GetTextSize(text2, button2_->GetFontId(), BUTTON_FONT_SIZE,
button2_->GetStyleConst().letterSpace_,
button2_->GetStyleConst().lineHeight_, widthMax_, 0).x);
}
if (button3_ != nullptr) {
const char* text3 = button3_->GetText();
buttonTextWidth =
MATH_MAX(buttonTextWidth, TypedText::GetTextSize(text3, button3_->GetFontId(), BUTTON_FONT_SIZE,
button3_->GetStyleConst().letterSpace_,
button3_->GetStyleConst().lineHeight_, widthMax_, 0).x);
}
return (buttonTextWidth + BUTTON_HEIGHT) > buttonMaxWidth ? buttonMaxWidth : (buttonTextWidth + BUTTON_HEIGHT);
}
void UIDialog::Layout()
{
if (title_ != nullptr) {
uint8_t padding = (TITLE_TOTAL_HEIGHT - title_->GetHeight()) / 2;
title_->LayoutLeftOfParent(PADDING);
title_->LayoutTopOfParent(padding);
if (text_ != nullptr) {
text_->LayoutLeftOfParent(PADDING);
text_->LayoutBottomToSibling(TITLE_ID, padding);
}
} else {
if (text_ != nullptr) {
text_->LayoutLeftOfParent(PADDING);
text_->LayoutTopOfParent(PADDING);
}
}
LayoutButton();
}
void UIDialog::LayoutButton()
{
if (button1_ != nullptr) {
button1_->LayoutLeftOfParent(BUTTON_PADDING);
button1_->LayoutBottomOfParent(BUTTON_PADDING);
if (button2_ != nullptr) {
button2_->LayoutRightToSibling(BUTTON1_ID, BUTTON_MID_PADDING);
button2_->LayoutBottomOfParent(BUTTON_PADDING);
}
} else if (button2_ != nullptr) {
button2_->LayoutLeftOfParent(BUTTON_PADDING);
button2_->LayoutBottomOfParent(BUTTON_PADDING);
}
if (button3_ != nullptr) {
button3_->LayoutRightOfParent(BUTTON_PADDING);
button3_->LayoutBottomOfParent(BUTTON_PADDING);
}
if (buttonNum_ == 3) {
line1_->LayoutBottomOfParent(LINE_BOTTOM_PADDING);
line1_->LayoutRightToSibling(BUTTON1_ID, LINE_BUTTON_PADDING);
line2_->LayoutBottomOfParent(LINE_BOTTOM_PADDING);
line2_->LayoutRightToSibling(BUTTON2_ID, LINE_BUTTON_PADDING);
} else if (buttonNum_ == 2) {
if (button1_ != nullptr) {
line1_->LayoutBottomOfParent(LINE_BOTTOM_PADDING);
line1_->LayoutRightToSibling(BUTTON1_ID, LINE_BUTTON_PADDING);
} else {
line1_->LayoutBottomOfParent(LINE_BOTTOM_PADDING);
line1_->LayoutRightToSibling(BUTTON2_ID, LINE_BUTTON_PADDING);
}
}
}
void UIDialog::CreateDialogWindow()
{
dialogLayer_->LayoutCenterOfParent();
Rect rect = dialogLayer_->GetRect();
int16_t offset_x = dialogLayer_->GetX();
int16_t offset_y = dialogLayer_->GetY();
windowRootView_->SetPosition(-offset_x, -offset_y);
windowRootView_->Invalidate();
WindowConfig config = {};
config.rect = rect;
config.rect.SetPosition(offset_x, offset_y);
config.isModal = true;
window_ = Window::CreateWindow(config);
if (window_ != nullptr) {
window_->BindRootView(windowRootView_);
} else {
GRAPHIC_LOGE("Create window false!");
}
}
void UIDialog::SetButtonColor(DialogButtonType buttonType, ColorType color)
{
switch (buttonType) {
case DialogButtonType::BUTTON_LEFT:
if (button1_ != nullptr) {
button1_->SetStyleForState(STYLE_BACKGROUND_COLOR, color.full, UIButton::ButtonState::RELEASED);
button1_->SetStyleForState(STYLE_BACKGROUND_OPA, color.alpha, UIButton::ButtonState::RELEASED);
colorType1_ = color;
}
break;
case DialogButtonType::BUTTON_MID:
if (button2_ != nullptr) {
button2_->SetStyleForState(STYLE_BACKGROUND_COLOR, color.full, UIButton::ButtonState::RELEASED);
button2_->SetStyleForState(STYLE_BACKGROUND_OPA, color.alpha, UIButton::ButtonState::RELEASED);
colorType2_ = color;
}
break;
case DialogButtonType::BUTTON_RIGHT:
if (button3_ != nullptr) {
button3_->SetStyleForState(STYLE_BACKGROUND_COLOR, color.full, UIButton::ButtonState::RELEASED);
button3_->SetStyleForState(STYLE_BACKGROUND_COLOR, color.alpha, UIButton::ButtonState::RELEASED);
colorType3_ = color;
}
break;
default:
break;
}
}
void UIDialog::SetOnCancelListener(UIView::OnClickListener* onCancelListener)
{
if (onCancelListener == nullptr) {
return;
}
onCancelListener_ = onCancelListener;
}
void UIDialog::EnableAutoCancel(bool enable)
{
enableAutoCancel_ = enable;
}
void UIDialog::DestroyWindow()
{
if (window_ != nullptr) {
Window::DestroyWindow(window_);
window_ = nullptr;
}
}
#ifdef ENABLE_DEBUG
const char* UIDialog::GetButtonText(DialogButtonType buttonType) const
{
switch (buttonType) {
case DialogButtonType::BUTTON_LEFT:
if (button1_ != nullptr) {
return button1_->GetText();
}
return nullptr;
case DialogButtonType::BUTTON_MID:
if (button2_ != nullptr) {
return button2_->GetText();
}
return nullptr;
case DialogButtonType::BUTTON_RIGHT:
if (button3_ != nullptr) {
return button3_->GetText();
}
return nullptr;
default:
return nullptr;
}
}
UIView::OnClickListener* UIDialog::GetButtonListener(DialogButtonType buttonType) const
{
switch (buttonType) {
case DialogButtonType::BUTTON_LEFT:
if (button1_ != nullptr) {
return button1_->GetOnClickListener();
}
return nullptr;
case DialogButtonType::BUTTON_MID:
if (button2_ != nullptr) {
return button2_->GetOnClickListener();
}
return nullptr;
case DialogButtonType::BUTTON_RIGHT:
if (button3_ != nullptr) {
return button3_->GetOnClickListener();
}
return nullptr;
default:
return nullptr;
}
}
ColorType UIDialog::GetButtonColor(DialogButtonType buttonType) const
{
switch (buttonType) {
case DialogButtonType::BUTTON_LEFT:
if (button1_ != nullptr) {
return colorType1_;
}
break;
case DialogButtonType::BUTTON_MID:
if (button2_ != nullptr) {
return colorType2_;
}
break;
case DialogButtonType::BUTTON_RIGHT:
if (button3_ != nullptr) {
return colorType3_;
}
break;
default:
break;
}
ASSERT(0);
}
#endif
}
#endif