Commit b6ffdf4d authored by Peter Boström's avatar Peter Boström Committed by Commit Bot

Add body text to DialogModel

This also refactors OutdatedUpgradeBubbleView to use DialogModel, which
makes use of body text.

Bug: 1106422
Change-Id: Ifae91809fc6c71274ac4c0368d427e7b094d8ddc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2351061Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Peter Boström <pbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798829}
parent 2dbb0409
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "content/public/browser/page_navigator.h" #include "content/public/browser/page_navigator.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/dialog_model.h"
#include "ui/views/bubble/bubble_dialog_model_host.h"
#include "ui/views/controls/label.h" #include "ui/views/controls/label.h"
#include "ui/views/layout/fill_layout.h" #include "ui/views/layout/fill_layout.h"
#include "ui/views/style/typography.h" #include "ui/views/style/typography.h"
...@@ -44,13 +46,85 @@ constexpr int kMaxIgnored = 50; ...@@ -44,13 +46,85 @@ constexpr int kMaxIgnored = 50;
// The number of buckets we want the NumLaterPerReinstall histogram to use. // The number of buckets we want the NumLaterPerReinstall histogram to use.
constexpr int kNumIgnoredBuckets = 5; constexpr int kNumIgnoredBuckets = 5;
class OutdatedUpgradeBubbleDelegate;
// The currently showing bubble. // The currently showing bubble.
OutdatedUpgradeBubbleView* g_upgrade_bubble = nullptr; OutdatedUpgradeBubbleDelegate* g_upgrade_bubble = nullptr;
// The number of times the user ignored the bubble before finally choosing to // The number of times the user ignored the bubble before finally choosing to
// reinstall. // reinstall.
int g_num_ignored_bubbles = 0; int g_num_ignored_bubbles = 0;
class OutdatedUpgradeBubbleDelegate : public ui::DialogModelDelegate {
public:
OutdatedUpgradeBubbleDelegate(content::PageNavigator* navigator,
bool auto_update_enabled)
: auto_update_enabled_(auto_update_enabled), navigator_(navigator) {}
OutdatedUpgradeBubbleDelegate(const OutdatedUpgradeBubbleDelegate&) = delete;
OutdatedUpgradeBubbleDelegate& operator=(
const OutdatedUpgradeBubbleDelegate&) = delete;
~OutdatedUpgradeBubbleDelegate() override {
// Increment the ignored bubble count (if this bubble wasn't ignored, this
// increment is offset by a decrement in OnDialogAccepted()).
if (g_num_ignored_bubbles < kMaxIgnored)
++g_num_ignored_bubbles;
}
void OnWindowClosing() {
// Reset |g_upgrade_bubble| here, not in destructor, because destruction is
// asynchronous and ShowBubble may be called before full destruction and
// would attempt to show a bubble that is closing.
DCHECK_EQ(g_upgrade_bubble, this);
g_upgrade_bubble = nullptr;
}
void OnDialogAccepted() {
// Offset the +1 in the dtor.
--g_num_ignored_bubbles;
if (auto_update_enabled_) {
DCHECK(UpgradeDetector::GetInstance()->is_outdated_install());
UMA_HISTOGRAM_CUSTOM_COUNTS("OutdatedUpgradeBubble.NumLaterPerReinstall",
g_num_ignored_bubbles, 1, kMaxIgnored,
kNumIgnoredBuckets);
base::RecordAction(
base::UserMetricsAction("OutdatedUpgradeBubble.Reinstall"));
navigator_->OpenURL(
content::OpenURLParams(GURL(kDownloadChromeUrl), content::Referrer(),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui::PAGE_TRANSITION_LINK, false));
#if defined(OS_WIN)
} else {
DCHECK(UpgradeDetector::GetInstance()->is_outdated_install_no_au());
UMA_HISTOGRAM_CUSTOM_COUNTS("OutdatedUpgradeBubble.NumLaterPerEnableAU",
g_num_ignored_bubbles, 1, kMaxIgnored,
kNumIgnoredBuckets);
base::RecordAction(
base::UserMetricsAction("OutdatedUpgradeBubble.EnableAU"));
// Record that the autoupdate flavour of the dialog has been shown.
if (g_browser_process->local_state()) {
g_browser_process->local_state()->SetBoolean(
prefs::kAttemptedToEnableAutoupdate, true);
}
// Re-enable updates by shelling out to setup.exe asynchronously.
base::ThreadPool::PostTask(
FROM_HERE,
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::BindOnce(&google_update::ElevateIfNeededToReenableUpdates));
#endif // defined(OS_WIN)
}
}
private:
// Identifies if auto-update is enabled or not.
const bool auto_update_enabled_;
// The PageNavigator to use for opening the Download Chrome URL.
content::PageNavigator* const navigator_;
};
} // namespace } // namespace
// OutdatedUpgradeBubbleView --------------------------------------------------- // OutdatedUpgradeBubbleView ---------------------------------------------------
...@@ -61,104 +135,38 @@ void OutdatedUpgradeBubbleView::ShowBubble(views::View* anchor_view, ...@@ -61,104 +135,38 @@ void OutdatedUpgradeBubbleView::ShowBubble(views::View* anchor_view,
bool auto_update_enabled) { bool auto_update_enabled) {
if (g_upgrade_bubble) if (g_upgrade_bubble)
return; return;
g_upgrade_bubble = new OutdatedUpgradeBubbleView(anchor_view, navigator,
auto_update_enabled); auto delegate = std::make_unique<OutdatedUpgradeBubbleDelegate>(
views::BubbleDialogDelegateView::CreateBubble(g_upgrade_bubble)->Show(); navigator, auto_update_enabled);
g_upgrade_bubble = delegate.get();
auto dialog_model =
ui::DialogModel::Builder(std::move(std::move(delegate)))
.SetShowCloseButton(true)
.SetTitle(l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_TITLE))
.AddOkButton(
base::BindOnce(&OutdatedUpgradeBubbleDelegate::OnDialogAccepted,
base::Unretained(g_upgrade_bubble)),
l10n_util::GetStringUTF16(auto_update_enabled
? IDS_REINSTALL_APP
: IDS_REENABLE_UPDATES))
.AddBodyText(l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_TEXT),
ui::DialogModelBodyText::Params().SetIsSecondary())
.SetCloseCallback(base::BindOnce(
&base::RecordAction,
base::UserMetricsAction("OutdatedUpgradeBubble.Later")))
.Build();
auto bubble =
std::make_unique<views::BubbleDialogModelHost>(std::move(dialog_model));
bubble->SetAnchorView(anchor_view);
bubble->SetArrow(views::BubbleBorder::TOP_RIGHT);
views::BubbleDialogDelegateView::CreateBubble(bubble.release())->Show();
chrome::RecordDialogCreation(chrome::DialogIdentifier::OUTDATED_UPGRADE);
base::RecordAction( base::RecordAction(
auto_update_enabled auto_update_enabled
? base::UserMetricsAction("OutdatedUpgradeBubble.Show") ? base::UserMetricsAction("OutdatedUpgradeBubble.Show")
: base::UserMetricsAction("OutdatedUpgradeBubble.ShowNoAU")); : base::UserMetricsAction("OutdatedUpgradeBubble.ShowNoAU"));
} }
OutdatedUpgradeBubbleView::~OutdatedUpgradeBubbleView() {
// Increment the ignored bubble count (if this bubble wasn't ignored, this
// increment is offset by a decrement in Accept()).
if (g_num_ignored_bubbles < kMaxIgnored)
++g_num_ignored_bubbles;
}
void OutdatedUpgradeBubbleView::WindowClosing() {
// Reset |g_upgrade_bubble| here, not in destructor, because destruction is
// asynchronous and ShowBubble may be called before full destruction and
// would attempt to show a bubble that is closing.
DCHECK_EQ(g_upgrade_bubble, this);
g_upgrade_bubble = nullptr;
}
bool OutdatedUpgradeBubbleView::ShouldShowCloseButton() const {
return true;
}
void OutdatedUpgradeBubbleView::OnDialogAccepted() {
// Offset the +1 in the dtor.
--g_num_ignored_bubbles;
if (auto_update_enabled_) {
DCHECK(UpgradeDetector::GetInstance()->is_outdated_install());
UMA_HISTOGRAM_CUSTOM_COUNTS("OutdatedUpgradeBubble.NumLaterPerReinstall",
g_num_ignored_bubbles, 1, kMaxIgnored,
kNumIgnoredBuckets);
base::RecordAction(
base::UserMetricsAction("OutdatedUpgradeBubble.Reinstall"));
navigator_->OpenURL(
content::OpenURLParams(GURL(kDownloadChromeUrl), content::Referrer(),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui::PAGE_TRANSITION_LINK, false));
#if defined(OS_WIN)
} else {
DCHECK(UpgradeDetector::GetInstance()->is_outdated_install_no_au());
UMA_HISTOGRAM_CUSTOM_COUNTS("OutdatedUpgradeBubble.NumLaterPerEnableAU",
g_num_ignored_bubbles, 1, kMaxIgnored,
kNumIgnoredBuckets);
base::RecordAction(
base::UserMetricsAction("OutdatedUpgradeBubble.EnableAU"));
// Record that the autoupdate flavour of the dialog has been shown.
if (g_browser_process->local_state()) {
g_browser_process->local_state()->SetBoolean(
prefs::kAttemptedToEnableAutoupdate, true);
}
// Re-enable updates by shelling out to setup.exe asynchronously.
base::ThreadPool::PostTask(
FROM_HERE,
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::BindOnce(&google_update::ElevateIfNeededToReenableUpdates));
#endif // defined(OS_WIN)
}
}
void OutdatedUpgradeBubbleView::Init() {
SetLayoutManager(std::make_unique<views::FillLayout>());
auto text_label = std::make_unique<views::Label>(
l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_TEXT),
views::style::CONTEXT_MESSAGE_BOX_BODY_TEXT,
views::style::STYLE_SECONDARY);
text_label->SetMultiLine(true);
text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
text_label->SizeToFit(
ChromeLayoutProvider::Get()->GetDistanceMetric(
ChromeDistanceMetric::DISTANCE_BUBBLE_PREFERRED_WIDTH) -
margins().width());
AddChildView(std::move(text_label));
}
OutdatedUpgradeBubbleView::OutdatedUpgradeBubbleView(
views::View* anchor_view,
content::PageNavigator* navigator,
bool auto_update_enabled)
: BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
auto_update_enabled_(auto_update_enabled),
navigator_(navigator) {
SetButtons(ui::DIALOG_BUTTON_OK);
SetButtonLabel(
ui::DIALOG_BUTTON_OK,
l10n_util::GetStringUTF16(auto_update_enabled_ ? IDS_REINSTALL_APP
: IDS_REENABLE_UPDATES));
SetTitle(IDS_UPGRADE_BUBBLE_TITLE);
SetAcceptCallback(base::BindOnce(&OutdatedUpgradeBubbleView::OnDialogAccepted,
base::Unretained(this)));
SetCloseCallback(
base::BindOnce(&base::RecordAction,
base::UserMetricsAction("OutdatedUpgradeBubble.Later")));
chrome::RecordDialogCreation(chrome::DialogIdentifier::OUTDATED_UPGRADE);
}
...@@ -16,32 +16,11 @@ class PageNavigator; ...@@ -16,32 +16,11 @@ class PageNavigator;
// It is intended to be used as the content of a bubble anchored off of the // It is intended to be used as the content of a bubble anchored off of the
// Chrome toolbar. Don't create an OutdatedUpgradeBubbleView directly, // Chrome toolbar. Don't create an OutdatedUpgradeBubbleView directly,
// instead use the static ShowBubble method. // instead use the static ShowBubble method.
class OutdatedUpgradeBubbleView : public views::BubbleDialogDelegateView { class OutdatedUpgradeBubbleView {
public: public:
static void ShowBubble(views::View* anchor_view, static void ShowBubble(views::View* anchor_view,
content::PageNavigator* navigator, content::PageNavigator* navigator,
bool auto_update_enabled); bool auto_update_enabled);
// views::BubbleDialogDelegateView:
void WindowClosing() override;
bool ShouldShowCloseButton() const override;
void Init() override;
private:
OutdatedUpgradeBubbleView(views::View* anchor_view,
content::PageNavigator* navigator,
bool auto_update_enabled);
~OutdatedUpgradeBubbleView() override;
void OnDialogAccepted();
// Identifies if auto-update is enabled or not.
const bool auto_update_enabled_;
// The PageNavigator to use for opening the Download Chrome URL.
content::PageNavigator* navigator_;
DISALLOW_COPY_AND_ASSIGN(OutdatedUpgradeBubbleView);
}; };
#endif // CHROME_BROWSER_UI_VIEWS_OUTDATED_UPGRADE_BUBBLE_VIEW_H_ #endif // CHROME_BROWSER_UI_VIEWS_OUTDATED_UPGRADE_BUBBLE_VIEW_H_
...@@ -84,11 +84,10 @@ DialogModel::Builder& DialogModel::Builder::AddDialogExtraButton( ...@@ -84,11 +84,10 @@ DialogModel::Builder& DialogModel::Builder::AddDialogExtraButton(
return *this; return *this;
} }
DialogModel::Builder& DialogModel::Builder::AddTextfield( DialogModel::Builder& DialogModel::Builder::AddBodyText(
base::string16 label,
base::string16 text, base::string16 text,
const DialogModelTextfield::Params& params) { const DialogModelBodyText::Params& params) {
model_->AddTextfield(std::move(label), std::move(text), params); model_->AddBodyText(std::move(text), params);
return *this; return *this;
} }
...@@ -100,6 +99,14 @@ DialogModel::Builder& DialogModel::Builder::AddCombobox( ...@@ -100,6 +99,14 @@ DialogModel::Builder& DialogModel::Builder::AddCombobox(
return *this; return *this;
} }
DialogModel::Builder& DialogModel::Builder::AddTextfield(
base::string16 label,
base::string16 text,
const DialogModelTextfield::Params& params) {
model_->AddTextfield(std::move(label), std::move(text), params);
return *this;
}
DialogModel::Builder& DialogModel::Builder::SetInitiallyFocusedField( DialogModel::Builder& DialogModel::Builder::SetInitiallyFocusedField(
int unique_id) { int unique_id) {
// This must be called with unique_id >= 0 (-1 is "no ID"). // This must be called with unique_id >= 0 (-1 is "no ID").
...@@ -118,11 +125,10 @@ DialogModel::DialogModel(util::PassKey<Builder>, ...@@ -118,11 +125,10 @@ DialogModel::DialogModel(util::PassKey<Builder>,
DialogModel::~DialogModel() = default; DialogModel::~DialogModel() = default;
void DialogModel::AddTextfield(base::string16 label, void DialogModel::AddBodyText(base::string16 text,
base::string16 text, const DialogModelBodyText::Params& params) {
const DialogModelTextfield::Params& params) { fields_.push_back(std::make_unique<DialogModelBodyText>(
fields_.push_back(std::make_unique<DialogModelTextfield>( GetPassKey(), this, std::move(text), params));
GetPassKey(), this, std::move(label), std::move(text), params));
if (host_) if (host_)
host_->OnFieldAdded(fields_.back().get()); host_->OnFieldAdded(fields_.back().get());
} }
...@@ -136,6 +142,15 @@ void DialogModel::AddCombobox(base::string16 label, ...@@ -136,6 +142,15 @@ void DialogModel::AddCombobox(base::string16 label,
host_->OnFieldAdded(fields_.back().get()); host_->OnFieldAdded(fields_.back().get());
} }
void DialogModel::AddTextfield(base::string16 label,
base::string16 text,
const DialogModelTextfield::Params& params) {
fields_.push_back(std::make_unique<DialogModelTextfield>(
GetPassKey(), this, std::move(label), std::move(text), params));
if (host_)
host_->OnFieldAdded(fields_.back().get());
}
DialogModelField* DialogModel::GetFieldByUniqueId(int unique_id) { DialogModelField* DialogModel::GetFieldByUniqueId(int unique_id) {
for (auto& field : fields_) { for (auto& field : fields_) {
if (field->unique_id_ == unique_id) if (field->unique_id_ == unique_id)
...@@ -145,12 +160,6 @@ DialogModelField* DialogModel::GetFieldByUniqueId(int unique_id) { ...@@ -145,12 +160,6 @@ DialogModelField* DialogModel::GetFieldByUniqueId(int unique_id) {
return nullptr; return nullptr;
} }
DialogModelButton* DialogModel::GetButtonByUniqueId(int unique_id) {
auto* field = GetFieldByUniqueId(unique_id);
DCHECK_EQ(field->type_, DialogModelField::kButton);
return static_cast<DialogModelButton*>(field);
}
DialogModelCombobox* DialogModel::GetComboboxByUniqueId(int unique_id) { DialogModelCombobox* DialogModel::GetComboboxByUniqueId(int unique_id) {
auto* field = GetFieldByUniqueId(unique_id); auto* field = GetFieldByUniqueId(unique_id);
......
...@@ -136,6 +136,10 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final { ...@@ -136,6 +136,10 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final {
std::unique_ptr<ui::ComboboxModel> combobox_model, std::unique_ptr<ui::ComboboxModel> combobox_model,
const DialogModelCombobox::Params& params); const DialogModelCombobox::Params& params);
// Adds body text. See DialogModel::AddBodyText().
Builder& AddBodyText(base::string16 label,
const DialogModelBodyText::Params& params);
// Sets which field should be initially focused in the dialog model. Must be // Sets which field should be initially focused in the dialog model. Must be
// called after that field has been added. Can only be called once. // called after that field has been added. Can only be called once.
Builder& SetInitiallyFocusedField(int unique_id); Builder& SetInitiallyFocusedField(int unique_id);
...@@ -152,20 +156,23 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final { ...@@ -152,20 +156,23 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final {
// during Host construction where it takes ownership of |this|. // during Host construction where it takes ownership of |this|.
DialogModelHost* host() { return host_; } DialogModelHost* host() { return host_; }
// Adds a labeled textfield (label: [text]) at the end of the dialog model. // Adds body text at the end of the dialog model.
void AddTextfield(base::string16 label, void AddBodyText(base::string16 label,
base::string16 text, const DialogModelBodyText::Params& params);
const ui::DialogModelTextfield::Params& params);
// Adds a labeled combobox (label: [model]) at the end of the dialog model. // Adds a labeled combobox (label: [model]) at the end of the dialog model.
void AddCombobox(base::string16 label, void AddCombobox(base::string16 label,
std::unique_ptr<ui::ComboboxModel> combobox_model, std::unique_ptr<ui::ComboboxModel> combobox_model,
const DialogModelCombobox::Params& params); const DialogModelCombobox::Params& params);
// Adds a labeled textfield (label: [text]) at the end of the dialog model.
void AddTextfield(base::string16 label,
base::string16 text,
const ui::DialogModelTextfield::Params& params);
// Gets DialogModelFields from their unique identifier. |unique_id| is // Gets DialogModelFields from their unique identifier. |unique_id| is
// supplied to AddX methods. // supplied to the ::Params class during construction.
DialogModelField* GetFieldByUniqueId(int unique_id); DialogModelField* GetFieldByUniqueId(int unique_id);
DialogModelButton* GetButtonByUniqueId(int unique_id);
DialogModelCombobox* GetComboboxByUniqueId(int unique_id); DialogModelCombobox* GetComboboxByUniqueId(int unique_id);
DialogModelTextfield* GetTextfieldByUniqueId(int unique_id); DialogModelTextfield* GetTextfieldByUniqueId(int unique_id);
......
...@@ -25,6 +25,13 @@ DialogModelField::~DialogModelField() = default; ...@@ -25,6 +25,13 @@ DialogModelField::~DialogModelField() = default;
DialogModelButton::Params::Params() = default; DialogModelButton::Params::Params() = default;
DialogModelButton::Params::~Params() = default; DialogModelButton::Params::~Params() = default;
DialogModelButton::Params& DialogModelButton::Params::SetUniqueId(
int unique_id) {
DCHECK_GE(unique_id, 0);
unique_id_ = unique_id;
return *this;
}
DialogModelButton::Params& DialogModelButton::Params::AddAccelerator( DialogModelButton::Params& DialogModelButton::Params::AddAccelerator(
Accelerator accelerator) { Accelerator accelerator) {
accelerators_.insert(std::move(accelerator)); accelerators_.insert(std::move(accelerator));
...@@ -54,6 +61,26 @@ void DialogModelButton::OnPressed(util::PassKey<DialogModelHost>, ...@@ -54,6 +61,26 @@ void DialogModelButton::OnPressed(util::PassKey<DialogModelHost>,
callback_.Run(event); callback_.Run(event);
} }
DialogModelBodyText::Params& DialogModelBodyText::Params::SetIsSecondary() {
is_secondary_ = true;
return *this;
}
DialogModelBodyText::DialogModelBodyText(
util::PassKey<DialogModel> pass_key,
DialogModel* model,
base::string16 text,
const DialogModelBodyText::Params& params)
: DialogModelField(pass_key,
model,
kBodyText,
-1,
base::flat_set<Accelerator>()),
text_(std::move(text)),
is_secondary_(params.is_secondary_) {}
DialogModelBodyText::~DialogModelBodyText() = default;
DialogModelCombobox::Params::Params() = default; DialogModelCombobox::Params::Params() = default;
DialogModelCombobox::Params::~Params() = default; DialogModelCombobox::Params::~Params() = default;
......
...@@ -28,7 +28,7 @@ class Event; ...@@ -28,7 +28,7 @@ class Event;
// stays in sync with the visible dialog (through DialogModelHosts). // stays in sync with the visible dialog (through DialogModelHosts).
class COMPONENT_EXPORT(UI_BASE) DialogModelField { class COMPONENT_EXPORT(UI_BASE) DialogModelField {
public: public:
enum Type { kButton, kTextfield, kCombobox }; enum Type { kButton, kBodyText, kCombobox, kTextfield };
DialogModelField(const DialogModelField&) = delete; DialogModelField(const DialogModelField&) = delete;
DialogModelField& operator=(const DialogModelField&) = delete; DialogModelField& operator=(const DialogModelField&) = delete;
...@@ -111,6 +111,47 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelButton : public DialogModelField { ...@@ -111,6 +111,47 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelButton : public DialogModelField {
base::RepeatingCallback<void(const Event&)> callback_; base::RepeatingCallback<void(const Event&)> callback_;
}; };
// Field class representing body text
class COMPONENT_EXPORT(UI_BASE) DialogModelBodyText : public DialogModelField {
public:
class COMPONENT_EXPORT(UI_BASE) Params {
public:
Params() = default;
Params(const Params&) = delete;
Params& operator=(const Params&) = delete;
// The body text is "secondary", often adding detail and context to other,
// more prominent text.
Params& SetIsSecondary();
private:
friend class DialogModelBodyText;
bool is_secondary_ = false;
};
// Note that this is constructed through a DialogModel which adds it to model
// fields.
DialogModelBodyText(util::PassKey<DialogModel> pass_key,
DialogModel* model,
base::string16 text,
const Params& params);
DialogModelBodyText(const DialogModelBodyText&) = delete;
DialogModelBodyText& operator=(const DialogModelBodyText&) = delete;
~DialogModelBodyText() override;
const base::string16& text(util::PassKey<DialogModelHost>) const {
return text_;
}
bool is_secondary(util::PassKey<DialogModelHost>) const {
return is_secondary_;
}
private:
const base::string16 text_;
const bool is_secondary_;
};
// Field class representing a combobox and corresponding label to describe the // Field class representing a combobox and corresponding label to describe the
// combobox: // combobox:
// //
...@@ -140,7 +181,6 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelCombobox : public DialogModelField { ...@@ -140,7 +181,6 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelCombobox : public DialogModelField {
private: private:
friend class DialogModelCombobox; friend class DialogModelCombobox;
const base::string16 label_;
int unique_id_ = -1; int unique_id_ = -1;
base::string16 accessible_name_; base::string16 accessible_name_;
base::RepeatingClosure callback_; base::RepeatingClosure callback_;
......
...@@ -18,12 +18,18 @@ ...@@ -18,12 +18,18 @@
namespace views { namespace views {
namespace { namespace {
constexpr int kColumnId = 0; // Note that textfields and comboboxes share column sets.
constexpr int kTextfieldColumnSetId = 0;
// Column sets used for fields where an individual control spans the entire
// dialog width.
constexpr int kSingleColumnSetId = 1;
DialogContentType FieldTypeToContentType(ui::DialogModelField::Type type) { DialogContentType FieldTypeToContentType(ui::DialogModelField::Type type) {
switch (type) { switch (type) {
case ui::DialogModelField::kButton: case ui::DialogModelField::kButton:
return DialogContentType::CONTROL; return DialogContentType::CONTROL;
case ui::DialogModelField::kBodyText:
return DialogContentType::TEXT;
case ui::DialogModelField::kTextfield: case ui::DialogModelField::kTextfield:
return DialogContentType::CONTROL; return DialogContentType::CONTROL;
case ui::DialogModelField::kCombobox: case ui::DialogModelField::kCombobox:
...@@ -95,13 +101,12 @@ BubbleDialogModelHost::~BubbleDialogModelHost() { ...@@ -95,13 +101,12 @@ BubbleDialogModelHost::~BubbleDialogModelHost() {
} }
View* BubbleDialogModelHost::GetInitiallyFocusedView() { View* BubbleDialogModelHost::GetInitiallyFocusedView() {
ui::DialogModelField* focused_field = model_->GetTextfieldByUniqueId( base::Optional<int> unique_id = model_->initially_focused_field(GetPassKey());
*model_->initially_focused_field(GetPassKey()));
if (!focused_field) if (!unique_id)
return BubbleDialogDelegateView::GetInitiallyFocusedView(); return BubbleDialogDelegateView::GetInitiallyFocusedView();
return FieldToView(focused_field); return FieldToView(model_->GetFieldByUniqueId(unique_id.value()));
} }
void BubbleDialogModelHost::OnDialogInitialized() { void BubbleDialogModelHost::OnDialogInitialized() {
...@@ -115,6 +120,12 @@ void BubbleDialogModelHost::OnDialogInitialized() { ...@@ -115,6 +120,12 @@ void BubbleDialogModelHost::OnDialogInitialized() {
} }
} }
gfx::Size BubbleDialogModelHost::CalculatePreferredSize() const {
// TODO(pbos): Move DISTANCE_BUBBLE_PREFERRED_WIDTH into views.
const int width = 320 - margins().width();
return gfx::Size(width, GetHeightForWidth(width));
}
void BubbleDialogModelHost::Close() { void BubbleDialogModelHost::Close() {
// TODO(pbos): Synchronously destroy model here, as-if closing immediately. // TODO(pbos): Synchronously destroy model here, as-if closing immediately.
DCHECK(GetWidget()); DCHECK(GetWidget());
...@@ -158,14 +169,17 @@ void BubbleDialogModelHost::AddInitialFields() { ...@@ -158,14 +169,17 @@ void BubbleDialogModelHost::AddInitialFields() {
case ui::DialogModelField::kButton: case ui::DialogModelField::kButton:
// TODO(pbos): Add support for buttons that are part of content area. // TODO(pbos): Add support for buttons that are part of content area.
continue; continue;
case ui::DialogModelField::kTextfield: case ui::DialogModelField::kBodyText:
last_view = AddOrUpdateTextfield(FieldAsTextfield(field.get())); last_view = AddOrUpdateBodyText(FieldAsBodyText(field.get()));
break; break;
case ui::DialogModelField::kCombobox: case ui::DialogModelField::kCombobox:
last_view = AddOrUpdateCombobox(FieldAsCombobox(field.get())); last_view = AddOrUpdateCombobox(FieldAsCombobox(field.get()));
break; break;
case ui::DialogModelField::kTextfield:
last_view = AddOrUpdateTextfield(FieldAsTextfield(field.get()));
break;
} }
DCHECK(last_view); DCHECK(last_view);
OnViewCreatedForField(last_view, field.get()); OnViewCreatedForField(last_view, field.get());
last_field_content_type = FieldTypeToContentType(field->type(GetPassKey())); last_field_content_type = FieldTypeToContentType(field->type(GetPassKey()));
...@@ -183,19 +197,26 @@ GridLayout* BubbleDialogModelHost::GetGridLayout() { ...@@ -183,19 +197,26 @@ GridLayout* BubbleDialogModelHost::GetGridLayout() {
} }
void BubbleDialogModelHost::ConfigureGridLayout() { void BubbleDialogModelHost::ConfigureGridLayout() {
auto* grid_layout = SetLayoutManager(std::make_unique<GridLayout>()); SetLayoutManager(std::make_unique<GridLayout>());
LayoutProvider* const provider = LayoutProvider::Get(); LayoutProvider* const provider = LayoutProvider::Get();
const int between_padding = const int between_padding =
provider->GetDistanceMetric(DISTANCE_RELATED_CONTROL_HORIZONTAL); provider->GetDistanceMetric(DISTANCE_RELATED_CONTROL_HORIZONTAL);
ColumnSet* const column_set = grid_layout->AddColumnSet(kColumnId); ColumnSet* const textfield_column_set =
column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, GetGridLayout()->AddColumnSet(kTextfieldColumnSetId);
GridLayout::kFixedSize, textfield_column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
GridLayout::ColumnSize::kUsePreferred, 0, 0); GridLayout::kFixedSize,
column_set->AddPaddingColumn(GridLayout::kFixedSize, between_padding); GridLayout::ColumnSize::kUsePreferred, 0, 0);
textfield_column_set->AddPaddingColumn(GridLayout::kFixedSize,
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1.0, between_padding);
GridLayout::ColumnSize::kFixed, 0, 0);
textfield_column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1.0,
GridLayout::ColumnSize::kFixed, 0, 0);
GetGridLayout()
->AddColumnSet(kSingleColumnSetId)
->AddColumn(GridLayout::FILL, GridLayout::FILL, 1.0,
GridLayout::ColumnSize::kUsePreferred, 0, 0);
} }
Textfield* BubbleDialogModelHost::AddOrUpdateTextfield( Textfield* BubbleDialogModelHost::AddOrUpdateTextfield(
...@@ -219,6 +240,23 @@ Textfield* BubbleDialogModelHost::AddOrUpdateTextfield( ...@@ -219,6 +240,23 @@ Textfield* BubbleDialogModelHost::AddOrUpdateTextfield(
return textfield_ptr; return textfield_ptr;
} }
Label* BubbleDialogModelHost::AddOrUpdateBodyText(
ui::DialogModelBodyText* field) {
// TODO(pbos): Handle updating existing field.
auto text_label = std::make_unique<Label>(
field->text(GetPassKey()), style::CONTEXT_MESSAGE_BOX_BODY_TEXT,
field->is_secondary(GetPassKey()) ? style::STYLE_SECONDARY
: style::STYLE_PRIMARY);
text_label->SetMultiLine(true);
text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
auto* layout = GetGridLayout();
layout->StartRow(1.0, kSingleColumnSetId);
return layout->AddView(std::move(text_label));
}
Combobox* BubbleDialogModelHost::AddOrUpdateCombobox( Combobox* BubbleDialogModelHost::AddOrUpdateCombobox(
ui::DialogModelCombobox* model) { ui::DialogModelCombobox* model) {
// TODO(pbos): Handle updating existing field. // TODO(pbos): Handle updating existing field.
...@@ -245,7 +283,7 @@ void BubbleDialogModelHost::AddLabelAndField(const base::string16& label_text, ...@@ -245,7 +283,7 @@ void BubbleDialogModelHost::AddLabelAndField(const base::string16& label_text,
int row_height = LayoutProvider::GetControlHeightForFont( int row_height = LayoutProvider::GetControlHeightForFont(
kFontContext, kFontStyle, field_font); kFontContext, kFontStyle, field_font);
GridLayout* const layout = GetGridLayout(); GridLayout* const layout = GetGridLayout();
layout->StartRow(GridLayout::kFixedSize, kColumnId, row_height); layout->StartRow(GridLayout::kFixedSize, kTextfieldColumnSetId, row_height);
layout->AddView( layout->AddView(
std::make_unique<Label>(label_text, kFontContext, kFontStyle)); std::make_unique<Label>(label_text, kFontContext, kFontStyle));
layout->AddView(std::move(field)); layout->AddView(std::move(field));
...@@ -307,6 +345,13 @@ ui::DialogModelButton* BubbleDialogModelHost::FieldAsButton( ...@@ -307,6 +345,13 @@ ui::DialogModelButton* BubbleDialogModelHost::FieldAsButton(
return static_cast<ui::DialogModelButton*>(field); return static_cast<ui::DialogModelButton*>(field);
} }
ui::DialogModelBodyText* BubbleDialogModelHost::FieldAsBodyText(
ui::DialogModelField* field) {
DCHECK(field);
DCHECK_EQ(field->type(GetPassKey()), ui::DialogModelField::kBodyText);
return static_cast<ui::DialogModelBodyText*>(field);
}
ui::DialogModelCombobox* BubbleDialogModelHost::FieldAsCombobox( ui::DialogModelCombobox* BubbleDialogModelHost::FieldAsCombobox(
ui::DialogModelField* field) { ui::DialogModelField* field) {
DCHECK(field); DCHECK(field);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
namespace views { namespace views {
class Combobox; class Combobox;
class GridLayout; class GridLayout;
class Label;
class Textfield; class Textfield;
// BubbleDialogModelHost is a views implementation of ui::DialogModelHost which // BubbleDialogModelHost is a views implementation of ui::DialogModelHost which
...@@ -45,6 +46,7 @@ class VIEWS_EXPORT BubbleDialogModelHost : public BubbleDialogDelegateView, ...@@ -45,6 +46,7 @@ class VIEWS_EXPORT BubbleDialogModelHost : public BubbleDialogDelegateView,
// GetInitiallyFocusedView(). // GetInitiallyFocusedView().
View* GetInitiallyFocusedView() override; View* GetInitiallyFocusedView() override;
void OnDialogInitialized() override; void OnDialogInitialized() override;
gfx::Size CalculatePreferredSize() const override;
// ui::DialogModelHost: // ui::DialogModelHost:
void Close() override; void Close() override;
...@@ -62,8 +64,9 @@ class VIEWS_EXPORT BubbleDialogModelHost : public BubbleDialogDelegateView, ...@@ -62,8 +64,9 @@ class VIEWS_EXPORT BubbleDialogModelHost : public BubbleDialogDelegateView,
void ConfigureGridLayout(); void ConfigureGridLayout();
void AddInitialFields(); void AddInitialFields();
Textfield* AddOrUpdateTextfield(ui::DialogModelTextfield* field); Label* AddOrUpdateBodyText(ui::DialogModelBodyText* field);
Combobox* AddOrUpdateCombobox(ui::DialogModelCombobox* field); Combobox* AddOrUpdateCombobox(ui::DialogModelCombobox* field);
Textfield* AddOrUpdateTextfield(ui::DialogModelTextfield* field);
void AddLabelAndField(const base::string16& label_text, void AddLabelAndField(const base::string16& label_text,
std::unique_ptr<views::View> field, std::unique_ptr<views::View> field,
const gfx::FontList& field_font); const gfx::FontList& field_font);
...@@ -76,6 +79,7 @@ class VIEWS_EXPORT BubbleDialogModelHost : public BubbleDialogDelegateView, ...@@ -76,6 +79,7 @@ class VIEWS_EXPORT BubbleDialogModelHost : public BubbleDialogDelegateView,
View* FieldToView(ui::DialogModelField* field); View* FieldToView(ui::DialogModelField* field);
ui::DialogModelButton* FieldAsButton(ui::DialogModelField* field); ui::DialogModelButton* FieldAsButton(ui::DialogModelField* field);
ui::DialogModelBodyText* FieldAsBodyText(ui::DialogModelField* field);
ui::DialogModelCombobox* FieldAsCombobox(ui::DialogModelField* field); ui::DialogModelCombobox* FieldAsCombobox(ui::DialogModelField* field);
ui::DialogModelTextfield* FieldAsTextfield(ui::DialogModelField* field); ui::DialogModelTextfield* FieldAsTextfield(ui::DialogModelField* field);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment