Commit b6724743 authored by Robert Liao's avatar Robert Liao Committed by Commit Bot

Remove Combobox::ModelChanged And Use ComboboxModelObserver Instead

ComboboxModelObserver already exists that provides this functionality,
and ComboboxModel implementors already presume the existence of
ComboboxModelObserver via ComboboxModel::[Add|Remove]Observer.

Additionally, consumers of Combobox really shouldn't manually
call Combobox::ModelChanged(). This should be handled on the model
and the model itself needs to signal when changes occur.

This change as a result has the Combobox start listening to model
changes a la ComboboxModelObserver. This is a no-op for read-only
models as they get the no-op [Add|Remove]Observer default
implementation.

Dependent components have also been updated to account for this change
in behavior.

BUG=946299

Change-Id: Ie71949685dfa8015bad6fdb973512b7efb38c7a3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1610229Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Robert Liao <robliao@chromium.org>
Cr-Commit-Position: refs/heads/master@{#659676}
parent 0fdfc2b2
...@@ -126,7 +126,6 @@ PermissionCombobox::PermissionCombobox(ComboboxModelAdapter* model, ...@@ -126,7 +126,6 @@ PermissionCombobox::PermissionCombobox(ComboboxModelAdapter* model,
SetEnabled(enabled); SetEnabled(enabled);
UpdateSelectedIndex(use_default); UpdateSelectedIndex(use_default);
set_size_to_largest_label(false); set_size_to_largest_label(false);
ModelChanged();
} }
PermissionCombobox::~PermissionCombobox() {} PermissionCombobox::~PermissionCombobox() {}
......
...@@ -14,12 +14,10 @@ ValidatingCombobox::ValidatingCombobox( ...@@ -14,12 +14,10 @@ ValidatingCombobox::ValidatingCombobox(
std::unique_ptr<ui::ComboboxModel> model, std::unique_ptr<ui::ComboboxModel> model,
std::unique_ptr<ValidationDelegate> delegate) std::unique_ptr<ValidationDelegate> delegate)
: Combobox(std::move(model)), delegate_(std::move(delegate)) { : Combobox(std::move(model)), delegate_(std::move(delegate)) {
// No need to remove observer on owned model.
this->model()->AddObserver(this);
SetFocusBehavior(FocusBehavior::ALWAYS); SetFocusBehavior(FocusBehavior::ALWAYS);
} }
ValidatingCombobox::~ValidatingCombobox() {} ValidatingCombobox::~ValidatingCombobox() = default;
void ValidatingCombobox::OnBlur() { void ValidatingCombobox::OnBlur() {
Combobox::OnBlur(); Combobox::OnBlur();
...@@ -41,9 +39,8 @@ void ValidatingCombobox::OnContentsChanged() { ...@@ -41,9 +39,8 @@ void ValidatingCombobox::OnContentsChanged() {
Validate(); Validate();
} }
void ValidatingCombobox::OnComboboxModelChanged( void ValidatingCombobox::OnComboboxModelChanged(ui::ComboboxModel* model) {
ui::ComboboxModel* unused_model) { views::Combobox::OnComboboxModelChanged(model);
ModelChanged();
delegate_->ComboboxModelChanged(this); delegate_->ComboboxModelChanged(this);
} }
......
...@@ -14,8 +14,7 @@ ...@@ -14,8 +14,7 @@
namespace payments { namespace payments {
class ValidatingCombobox : public views::Combobox, class ValidatingCombobox : public views::Combobox {
public ui::ComboboxModelObserver {
public: public:
ValidatingCombobox(std::unique_ptr<ui::ComboboxModel> model, ValidatingCombobox(std::unique_ptr<ui::ComboboxModel> model,
std::unique_ptr<ValidationDelegate> delegate); std::unique_ptr<ValidationDelegate> delegate);
...@@ -31,7 +30,7 @@ class ValidatingCombobox : public views::Combobox, ...@@ -31,7 +30,7 @@ class ValidatingCombobox : public views::Combobox,
// Called when the combobox contents is changed. May do validation. // Called when the combobox contents is changed. May do validation.
void OnContentsChanged(); void OnContentsChanged();
// ui::ComboboxModelObserver: // views::Combobox:
void OnComboboxModelChanged(ui::ComboboxModel* model) override; void OnComboboxModelChanged(ui::ComboboxModel* model) override;
// Identifies whether the current content if valid or not. // Identifies whether the current content if valid or not.
......
...@@ -121,15 +121,11 @@ int GetAdjacentIndex(ui::ComboboxModel* model, int increment, int index) { ...@@ -121,15 +121,11 @@ int GetAdjacentIndex(ui::ComboboxModel* model, int increment, int index) {
const char Combobox::kViewClassName[] = "views/Combobox"; const char Combobox::kViewClassName[] = "views/Combobox";
// Adapts a ui::ComboboxModel to a ui::MenuModel. // Adapts a ui::ComboboxModel to a ui::MenuModel.
class Combobox::ComboboxMenuModel : public ui::MenuModel, class Combobox::ComboboxMenuModel : public ui::MenuModel {
public ui::ComboboxModelObserver {
public: public:
ComboboxMenuModel(Combobox* owner, ui::ComboboxModel* model) ComboboxMenuModel(Combobox* owner, ui::ComboboxModel* model)
: owner_(owner), model_(model) { : owner_(owner), model_(model) {}
model_->AddObserver(this); ~ComboboxMenuModel() override = default;
}
~ComboboxMenuModel() override { model_->RemoveObserver(this); }
private: private:
bool UseCheckmarks() const { bool UseCheckmarks() const {
...@@ -201,11 +197,6 @@ class Combobox::ComboboxMenuModel : public ui::MenuModel, ...@@ -201,11 +197,6 @@ class Combobox::ComboboxMenuModel : public ui::MenuModel,
MenuModel* GetSubmenuModelAt(int index) const override { return nullptr; } MenuModel* GetSubmenuModelAt(int index) const override { return nullptr; }
// Overridden from ComboboxModelObserver:
void OnComboboxModelChanged(ui::ComboboxModel* model) override {
owner_->ModelChanged();
}
Combobox* owner_; // Weak. Owns this. Combobox* owner_; // Weak. Owns this.
ui::ComboboxModel* model_; // Weak. ui::ComboboxModel* model_; // Weak.
...@@ -232,7 +223,8 @@ Combobox::Combobox(ui::ComboboxModel* model, int text_context, int text_style) ...@@ -232,7 +223,8 @@ Combobox::Combobox(ui::ComboboxModel* model, int text_context, int text_style)
menu_model_(new ComboboxMenuModel(this, model)), menu_model_(new ComboboxMenuModel(this, model)),
arrow_button_(new TransparentButton(this)), arrow_button_(new TransparentButton(this)),
size_to_largest_label_(true) { size_to_largest_label_(true) {
ModelChanged(); model_->AddObserver(this);
OnComboboxModelChanged(model_);
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
#else #else
...@@ -257,26 +249,13 @@ Combobox::~Combobox() { ...@@ -257,26 +249,13 @@ Combobox::~Combobox() {
// Combobox should have been blurred before destroy. // Combobox should have been blurred before destroy.
DCHECK(selector_.get() != GetInputMethod()->GetTextInputClient()); DCHECK(selector_.get() != GetInputMethod()->GetTextInputClient());
} }
model_->RemoveObserver(this);
} }
const gfx::FontList& Combobox::GetFontList() const { const gfx::FontList& Combobox::GetFontList() const {
return style::GetFont(text_context_, text_style_); return style::GetFont(text_context_, text_style_);
} }
void Combobox::ModelChanged() {
// If the selection is no longer valid (or the model is empty), restore the
// default index.
if (selected_index_ >= model_->GetItemCount() ||
model_->GetItemCount() == 0 ||
model_->IsItemSeparatorAt(selected_index_)) {
selected_index_ = model_->GetDefaultIndex();
}
content_size_ = GetContentSize();
PreferredSizeChanged();
SchedulePaint();
}
void Combobox::SetSelectedIndex(int index) { void Combobox::SetSelectedIndex(int index) {
if (selected_index_ == index) if (selected_index_ == index)
return; return;
...@@ -541,6 +520,22 @@ void Combobox::ButtonPressed(Button* sender, const ui::Event& event) { ...@@ -541,6 +520,22 @@ void Combobox::ButtonPressed(Button* sender, const ui::Event& event) {
ShowDropDownMenu(source_type); ShowDropDownMenu(source_type);
} }
void Combobox::OnComboboxModelChanged(ui::ComboboxModel* model) {
DCHECK_EQ(model_, model);
// If the selection is no longer valid (or the model is empty), restore the
// default index.
if (selected_index_ >= model_->GetItemCount() ||
model_->GetItemCount() == 0 ||
model_->IsItemSeparatorAt(selected_index_)) {
selected_index_ = model_->GetDefaultIndex();
}
content_size_ = GetContentSize();
PreferredSizeChanged();
SchedulePaint();
}
void Combobox::UpdateBorder() { void Combobox::UpdateBorder() {
std::unique_ptr<FocusableBorder> border(new FocusableBorder()); std::unique_ptr<FocusableBorder> border(new FocusableBorder());
if (invalid_) if (invalid_)
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "ui/base/models/combobox_model_observer.h"
#include "ui/views/controls/button/button.h" #include "ui/views/controls/button/button.h"
#include "ui/views/controls/prefix_delegate.h" #include "ui/views/controls/prefix_delegate.h"
#include "ui/views/style/typography.h" #include "ui/views/style/typography.h"
...@@ -35,7 +36,8 @@ class PrefixSelector; ...@@ -35,7 +36,8 @@ class PrefixSelector;
// Combobox has two distinct parts, the drop down arrow and the text. // Combobox has two distinct parts, the drop down arrow and the text.
class VIEWS_EXPORT Combobox : public View, class VIEWS_EXPORT Combobox : public View,
public PrefixDelegate, public PrefixDelegate,
public ButtonListener { public ButtonListener,
public ui::ComboboxModelObserver {
public: public:
METADATA_HEADER(Combobox); METADATA_HEADER(Combobox);
...@@ -59,9 +61,6 @@ class VIEWS_EXPORT Combobox : public View, ...@@ -59,9 +61,6 @@ class VIEWS_EXPORT Combobox : public View,
// Sets the listener which will be called when a selection has been made. // Sets the listener which will be called when a selection has been made.
void set_listener(ComboboxListener* listener) { listener_ = listener; } void set_listener(ComboboxListener* listener) { listener_ = listener; }
// Informs the combobox that its model changed.
void ModelChanged();
// Gets/Sets the selected index. // Gets/Sets the selected index.
int GetSelectedIndex() const { return selected_index_; } int GetSelectedIndex() const { return selected_index_; }
void SetSelectedIndex(int index); void SetSelectedIndex(int index);
...@@ -112,6 +111,9 @@ class VIEWS_EXPORT Combobox : public View, ...@@ -112,6 +111,9 @@ class VIEWS_EXPORT Combobox : public View,
size_to_largest_label_ = size_to_largest_label; size_to_largest_label_ = size_to_largest_label;
} }
// Overridden from ComboboxModelObserver:
void OnComboboxModelChanged(ui::ComboboxModel* model) override;
private: private:
friend class test::ComboboxTestApi; friend class test::ComboboxTestApi;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "ui/base/ime/input_method.h" #include "ui/base/ime/input_method.h"
#include "ui/base/ime/text_input_client.h" #include "ui/base/ime/text_input_client.h"
#include "ui/base/models/combobox_model.h" #include "ui/base/models/combobox_model.h"
#include "ui/base/models/combobox_model_observer.h"
#include "ui/base/models/menu_model.h" #include "ui/base/models/menu_model.h"
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/events/event_constants.h" #include "ui/events/event_constants.h"
...@@ -100,13 +101,30 @@ class TestComboboxModel : public ui::ComboboxModel { ...@@ -100,13 +101,30 @@ class TestComboboxModel : public ui::ComboboxModel {
return 0; return 0;
} }
void AddObserver(ui::ComboboxModelObserver* observer) override {
observers_.AddObserver(observer);
}
void RemoveObserver(ui::ComboboxModelObserver* observer) override {
observers_.RemoveObserver(observer);
}
void SetSeparators(const std::set<int>& separators) { void SetSeparators(const std::set<int>& separators) {
separators_ = separators; separators_ = separators;
OnModelChanged();
} }
void set_item_count(int item_count) { item_count_ = item_count; } void set_item_count(int item_count) {
item_count_ = item_count;
OnModelChanged();
}
private: private:
void OnModelChanged() {
for (auto& observer : observers_)
observer.OnComboboxModelChanged(this);
}
base::ObserverList<ui::ComboboxModelObserver>::Unchecked observers_;
std::set<int> separators_; std::set<int> separators_;
int item_count_ = kItemCount; int item_count_ = kItemCount;
...@@ -131,10 +149,22 @@ class VectorComboboxModel : public ui::ComboboxModel { ...@@ -131,10 +149,22 @@ class VectorComboboxModel : public ui::ComboboxModel {
} }
bool IsItemSeparatorAt(int index) override { return false; } bool IsItemSeparatorAt(int index) override { return false; }
int GetDefaultIndex() const override { return default_index_; } int GetDefaultIndex() const override { return default_index_; }
void AddObserver(ui::ComboboxModelObserver* observer) override {
observers_.AddObserver(observer);
}
void RemoveObserver(ui::ComboboxModelObserver* observer) override {
observers_.RemoveObserver(observer);
}
void ValuesChanged() {
for (auto& observer : observers_)
observer.OnComboboxModelChanged(this);
}
private: private:
std::vector<std::string>* values_; base::ObserverList<ui::ComboboxModelObserver>::Unchecked observers_;
int default_index_ = 0; int default_index_ = 0;
std::vector<std::string>* const values_;
DISALLOW_COPY_AND_ASSIGN(VectorComboboxModel); DISALLOW_COPY_AND_ASSIGN(VectorComboboxModel);
}; };
...@@ -693,19 +723,19 @@ TEST_F(ComboboxTest, ContentWidth) { ...@@ -693,19 +723,19 @@ TEST_F(ComboboxTest, ContentWidth) {
values.resize(1); values.resize(1);
values[0] = long_item; values[0] = long_item;
combobox.ModelChanged(); model.ValuesChanged();
const int long_item_width = test_api.content_size().width(); const int long_item_width = test_api.content_size().width();
values[0] = short_item; values[0] = short_item;
combobox.ModelChanged(); model.ValuesChanged();
const int short_item_width = test_api.content_size().width(); const int short_item_width = test_api.content_size().width();
values.resize(2); values.resize(2);
values[0] = short_item; values[0] = short_item;
values[1] = long_item; values[1] = long_item;
combobox.ModelChanged(); model.ValuesChanged();
// The width will fit with the longest item. // The width will fit with the longest item.
EXPECT_EQ(long_item_width, test_api.content_size().width()); EXPECT_EQ(long_item_width, test_api.content_size().width());
...@@ -724,12 +754,10 @@ TEST_F(ComboboxTest, ModelChanged) { ...@@ -724,12 +754,10 @@ TEST_F(ComboboxTest, ModelChanged) {
EXPECT_EQ(4, combobox_->GetSelectedRow()); EXPECT_EQ(4, combobox_->GetSelectedRow());
model_->set_item_count(5); model_->set_item_count(5);
combobox_->ModelChanged();
EXPECT_EQ(5, combobox_->GetRowCount()); EXPECT_EQ(5, combobox_->GetRowCount());
EXPECT_EQ(4, combobox_->GetSelectedRow()); // Unchanged. EXPECT_EQ(4, combobox_->GetSelectedRow()); // Unchanged.
model_->set_item_count(4); model_->set_item_count(4);
combobox_->ModelChanged();
EXPECT_EQ(4, combobox_->GetRowCount()); EXPECT_EQ(4, combobox_->GetRowCount());
EXPECT_EQ(0, combobox_->GetSelectedRow()); // Resets. EXPECT_EQ(0, combobox_->GetSelectedRow()); // Resets.
...@@ -741,7 +769,6 @@ TEST_F(ComboboxTest, ModelChanged) { ...@@ -741,7 +769,6 @@ TEST_F(ComboboxTest, ModelChanged) {
std::set<int> separators; std::set<int> separators;
separators.insert(2); separators.insert(2);
model_->SetSeparators(separators); model_->SetSeparators(separators);
combobox_->ModelChanged();
EXPECT_EQ(4, combobox_->GetRowCount()); EXPECT_EQ(4, combobox_->GetRowCount());
EXPECT_EQ(0, combobox_->GetSelectedRow()); // Resets. EXPECT_EQ(0, combobox_->GetSelectedRow()); // Resets.
...@@ -751,7 +778,6 @@ TEST_F(ComboboxTest, ModelChanged) { ...@@ -751,7 +778,6 @@ TEST_F(ComboboxTest, ModelChanged) {
// Test an empty model. // Test an empty model.
model_->set_item_count(0); model_->set_item_count(0);
combobox_->ModelChanged();
EXPECT_EQ(0, combobox_->GetRowCount()); EXPECT_EQ(0, combobox_->GetRowCount());
EXPECT_EQ(0, combobox_->GetSelectedRow()); // Resets. EXPECT_EQ(0, combobox_->GetSelectedRow()); // Resets.
} }
......
...@@ -144,12 +144,11 @@ class ExamplesWindowContents : public WidgetDelegateView, ...@@ -144,12 +144,11 @@ class ExamplesWindowContents : public WidgetDelegateView,
on_close_(std::move(on_close)) { on_close_(std::move(on_close)) {
auto combobox_model = std::make_unique<ComboboxModelExampleList>(); auto combobox_model = std::make_unique<ComboboxModelExampleList>();
combobox_model_ = combobox_model.get(); combobox_model_ = combobox_model.get();
combobox_model_->SetExamples(std::move(examples));
combobox_ = new Combobox(std::move(combobox_model)); combobox_ = new Combobox(std::move(combobox_model));
instance_ = this; instance_ = this;
combobox_->set_listener(this); combobox_->set_listener(this);
combobox_model_->SetExamples(std::move(examples));
combobox_->ModelChanged();
SetBackground(CreateStandardPanelBackground()); SetBackground(CreateStandardPanelBackground());
GridLayout* layout = GridLayout* layout =
......
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