| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ASH_STYLE_SYSTEM_DIALOG_DELEGATE_VIEW_H_ |
| #define ASH_STYLE_SYSTEM_DIALOG_DELEGATE_VIEW_H_ |
| |
| #include <string> |
| |
| #include "ash/ash_export.h" |
| #include "ash/style/pill_button.h" |
| #include "ash/style/system_shadow.h" |
| #include "base/functional/callback_forward.h" |
| #include "ui/base/interaction/element_identifier.h" |
| #include "ui/base/metadata/metadata_header_macros.h" |
| #include "ui/base/mojom/ui_base_types.mojom-shared.h" |
| #include "ui/base/ui_base_types.h" |
| #include "ui/gfx/vector_icon_types.h" |
| #include "ui/views/layout/layout_types.h" |
| #include "ui/views/metadata/view_factory.h" |
| #include "ui/views/widget/widget_delegate.h" |
| |
| namespace views { |
| class ImageView; |
| class Label; |
| } // namespace views |
| |
| namespace ash { |
| |
| // The contents of a dialog that displays information or prompts the user input. |
| // A dialog may include an icon, a title, a description, top and middle contents |
| // , and a button container. The button container typically contains an |
| // accept button and a cancel button, but it may also include an additional |
| // view. The layout of the dialog with all the elements is shown below: |
| // +----------------------------------------------------+ |
| // | +----------------------------------------------+ | |
| // | | Top content | | |
| // | +----------------------------------------------+ | |
| // | +----+ | |
| // | | |- Icon | |
| // | +----+ | |
| // | | |
| // | Title | |
| // | | |
| // | Description text | |
| // | +----------------------------------------------+ | |
| // | | Middle content | | |
| // | +----------------------------------------------+ | |
| // | +-----+ +--------+ +--------+ | |
| // | | |- Additional view | Cancel | | OK | | |
| // | +-----+ +--------+ +--------+ | |
| // +----------------------------------------------------+ |
| // |
| // The dialog would display all or some of above elements, depending on the |
| // clients' needs. |
| class ASH_EXPORT SystemDialogDelegateView : public views::WidgetDelegateView { |
| METADATA_HEADER(SystemDialogDelegateView, views::WidgetDelegateView) |
| |
| public: |
| DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kAcceptButtonIdForTesting); |
| DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kCancelButtonIdForTesting); |
| DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kDescriptionTextIdForTesting); |
| DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kTitleTextIdForTesting); |
| |
| SystemDialogDelegateView(); |
| SystemDialogDelegateView(const SystemDialogDelegateView&) = delete; |
| SystemDialogDelegateView& operator=(const SystemDialogDelegateView&) = delete; |
| ~SystemDialogDelegateView() override; |
| |
| // Sets the leading icon of the dialog. There is no icon by default. |
| void SetIcon(const gfx::VectorIcon& icon); |
| |
| // Sets title and description text. There will be no title or description if |
| // their texts are empty. |
| void SetTitleText(const std::u16string& title); |
| void SetDescription(const std::u16string& description); |
| void SetDescriptionAccessibleName(const std::u16string& accessible_name); |
| |
| // Sets the visibility of the accept and cancel buttons. Both buttons are |
| // visible by default. |
| void SetAcceptButtonVisible(bool visible); |
| void SetCancelButtonVisible(bool visible); |
| |
| // Sets the text of accept and cancel buttons. The default accept button text |
| // is "OK", and cancel button is "Cancel". |
| void SetAcceptButtonText(const std::u16string& accept_text); |
| void SetCancelButtonText(const std::u16string& cancel_text); |
| |
| // Sets accept and cancel button callbacks. If the callback is not set, |
| // clicking the corresponding button would only close the dialog without |
| // performing any additional actions. |
| void SetAcceptCallback(base::OnceClosure accept_callback) { |
| accept_callback_ = std::move(accept_callback); |
| } |
| void SetCancelCallback(base::OnceClosure cancel_callback) { |
| cancel_callback_ = std::move(cancel_callback); |
| } |
| |
| // Sets dialog close callback. The close callback is called when the dialog is |
| // closed without clicking the accept or cancel button. For example, when the |
| // dialog's parent window is destroyed. |
| void SetCloseCallback(base::OnceClosure close_callback) { |
| close_callback_ = std::move(close_callback); |
| } |
| |
| // Sets the top content view. |
| template <typename T> |
| T* SetTopContentView(std::unique_ptr<T> view) { |
| T* ptr = view.get(); |
| SetContentInternal(std::move(view), ContentType::kTop); |
| return ptr; |
| } |
| |
| // Sets the middle content view. |
| template <typename T> |
| T* SetMiddleContentView(std::unique_ptr<T> view) { |
| T* ptr = view.get(); |
| SetContentInternal(std::move(view), ContentType::kMiddle); |
| return ptr; |
| } |
| |
| // Sets the additional view in the button container. |
| template <typename T> |
| T* SetAdditionalViewInButtonRow(std::unique_ptr<T> view) { |
| T* ptr = view.get(); |
| SetAdditionalViewInButtonRowInternal(std::move(view)); |
| return ptr; |
| } |
| |
| // Sets the main axis alignment of the button container which is end aligned |
| // by default. Note this will only work if there is no additional view set in |
| // the button row. If an additional view is set, the button row will follow |
| // the default layout with the additional view at the start and button |
| // container at the end. |
| void SetButtonContainerAlignment(views::LayoutAlignment alignment); |
| |
| // Sets the cross axis alignment of the existing content which is center |
| // aligned by default. |
| void SetTopContentAlignment(views::LayoutAlignment alignment); |
| void SetMiddleContentAlignment(views::LayoutAlignment alignment); |
| |
| // Sets the margins for the title label view. |
| void SetTitleMargins(const gfx::Insets& margins); |
| |
| // views::WidgetDelegateView: |
| gfx::Size CalculatePreferredSize( |
| const views::SizeBounds& available_size) const override; |
| gfx::Size GetMinimumSize() const override; |
| gfx::Size GetMaximumSize() const override; |
| void OnWidgetInitialized() override; |
| void OnWorkAreaChanged() override; |
| |
| // Helper function to access buttons for tests. |
| const PillButton* GetAcceptButtonForTesting() const; |
| const PillButton* GetCancelButtonForTesting() const; |
| |
| protected: |
| virtual void UpdateDialogSize(); |
| |
| private: |
| class ButtonContainer; |
| |
| enum class ContentType { |
| kTop, // The content at the top of the dialog. |
| kMiddle, // The content in the middle of description and button container. |
| }; |
| |
| // Get the index of the content with given type in current layout. |
| size_t GetContentIndex(ContentType type) const; |
| |
| // Internal methods of adding the additional views into the dialog. |
| void SetContentInternal(std::unique_ptr<views::View> view, ContentType type); |
| void SetAdditionalViewInButtonRowInternal(std::unique_ptr<views::View> view); |
| |
| // The actual callbacks of accept and cancel buttons. When the accept/cancel |
| // button is clicked, the corresponding `accept_callback_`/`cancel_callback_` |
| // will be called if exists and the dialog will be closed. |
| void Accept(); |
| void Cancel(); |
| |
| // The callback when the dialog will be closed. |
| void Close(); |
| |
| // Run the given `callback` and close the dialog with `closed_reason`. |
| void RunCallbackAndCloseDialog(base::OnceClosure callback, |
| views::Widget::ClosedReason closed_reason); |
| |
| // The callbacks of the buttons and closing dialog. |
| base::OnceClosure accept_callback_; |
| base::OnceClosure cancel_callback_; |
| base::OnceClosure close_callback_; |
| |
| // The view of each element owned by the dialog. |
| raw_ptr<views::ImageView> icon_ = nullptr; |
| raw_ptr<views::Label> title_ = nullptr; |
| raw_ptr<views::Label> description_ = nullptr; |
| raw_ptr<ButtonContainer> button_container_ = nullptr; |
| base::flat_map<ContentType, raw_ptr<views::View>> contents_; |
| |
| // The dialog shadow. |
| std::unique_ptr<SystemShadow> shadow_; |
| |
| // Indicates if the dialog is being closed. |
| bool closing_dialog_ = false; |
| }; |
| |
| BEGIN_VIEW_BUILDER(ASH_EXPORT, |
| SystemDialogDelegateView, |
| views::WidgetDelegateView) |
| VIEW_BUILDER_PROPERTY(const gfx::VectorIcon&, Icon, const gfx::VectorIcon&) |
| VIEW_BUILDER_PROPERTY(const std::u16string&, TitleText) |
| VIEW_BUILDER_PROPERTY(const std::u16string&, Description) |
| VIEW_BUILDER_PROPERTY(const std::u16string&, DescriptionAccessibleName) |
| VIEW_BUILDER_PROPERTY(const std::u16string&, AcceptButtonText) |
| VIEW_BUILDER_PROPERTY(const std::u16string&, CancelButtonText) |
| VIEW_BUILDER_PROPERTY(base::OnceClosure, AcceptCallback) |
| VIEW_BUILDER_PROPERTY(base::OnceClosure, CancelCallback) |
| VIEW_BUILDER_PROPERTY(base::OnceClosure, CloseCallback) |
| VIEW_BUILDER_VIEW_TYPE_PROPERTY(views::View, TopContentView) |
| VIEW_BUILDER_VIEW_TYPE_PROPERTY(views::View, MiddleContentView) |
| VIEW_BUILDER_VIEW_TYPE_PROPERTY(views::View, AdditionalViewInButtonRow) |
| VIEW_BUILDER_PROPERTY(views::LayoutAlignment, TopContentAlignment) |
| VIEW_BUILDER_PROPERTY(views::LayoutAlignment, MiddleContentAlignment) |
| VIEW_BUILDER_PROPERTY(bool, AcceptButtonVisible) |
| VIEW_BUILDER_PROPERTY(const gfx::Insets&, TitleMargins) |
| VIEW_BUILDER_PROPERTY(ui::mojom::ModalType, ModalType) |
| END_VIEW_BUILDER |
| |
| } // namespace ash |
| |
| DEFINE_VIEW_BUILDER(ASH_EXPORT, ash::SystemDialogDelegateView) |
| |
| #endif // ASH_STYLE_SYSTEM_DIALOG_DELEGATE_VIEW_H_ |