1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
|
// 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_
|