Commit 9c17bce2 authored by Robert Liao's avatar Robert Liao Committed by Commit Bot

Make EditableCombobox Default Constructable

BUG=1108460

Change-Id: Ie5eb700075a15cc1cec52f500831115a161f100c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2364080Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Robert Liao <robliao@chromium.org>
Cr-Commit-Position: refs/heads/master@{#799912}
parent 53b382e0
......@@ -334,6 +334,8 @@ component("views") {
"controls/button/toggle_button.cc",
"controls/combobox/combobox.cc",
"controls/combobox/combobox_util.cc",
"controls/combobox/empty_combobox_model.cc",
"controls/combobox/empty_combobox_model.h",
"controls/editable_combobox/editable_combobox.cc",
"controls/focus_ring.cc",
"controls/focusable_border.cc",
......
......@@ -32,6 +32,7 @@
#include "ui/views/controls/button/button_controller.h"
#include "ui/views/controls/combobox/combobox_listener.h"
#include "ui/views/controls/combobox/combobox_util.h"
#include "ui/views/controls/combobox/empty_combobox_model.h"
#include "ui/views/controls/focus_ring.h"
#include "ui/views/controls/focusable_border.h"
#include "ui/views/controls/menu/menu_config.h"
......@@ -51,23 +52,6 @@ namespace {
// Used to indicate that no item is currently selected by the user.
constexpr int kNoSelection = -1;
// An empty model for a combo box.
class EmptyComboboxModel final : public ui::ComboboxModel {
public:
EmptyComboboxModel() = default;
EmptyComboboxModel(EmptyComboboxModel&) = delete;
EmptyComboboxModel& operator=(const EmptyComboboxModel&) = delete;
~EmptyComboboxModel() override = default;
// ui::ComboboxModel:
int GetItemCount() const override { return 0; }
base::string16 GetItemAt(int index) const override {
NOTREACHED();
return base::string16();
}
int GetDefaultIndex() const override { return -1; }
};
SkColor GetTextColorForEnableState(const Combobox& combobox, bool enabled) {
const int style = enabled ? style::STYLE_PRIMARY : style::STYLE_DISABLED;
return style::GetColor(combobox, style::CONTEXT_TEXTFIELD, style);
......@@ -248,7 +232,7 @@ class Combobox::ComboboxMenuModel : public ui::MenuModel {
// Combobox, public:
Combobox::Combobox(int text_context, int text_style)
: Combobox(std::make_unique<EmptyComboboxModel>()) {}
: Combobox(std::make_unique<internal::EmptyComboboxModel>()) {}
Combobox::Combobox(std::unique_ptr<ui::ComboboxModel> model,
int text_context,
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/views/controls/combobox/empty_combobox_model.h"
#include "base/notreached.h"
#include "base/strings/string16.h"
namespace views {
namespace internal {
EmptyComboboxModel::EmptyComboboxModel() = default;
EmptyComboboxModel::~EmptyComboboxModel() = default;
int EmptyComboboxModel::GetItemCount() const {
return 0;
}
base::string16 EmptyComboboxModel::GetItemAt(int index) const {
NOTREACHED();
return base::string16();
}
int EmptyComboboxModel::GetDefaultIndex() const {
return -1;
}
} // namespace internal
} // namespace views
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_VIEWS_CONTROLS_COMBOBOX_EMPTY_COMBOBOX_MODEL_H_
#define UI_VIEWS_CONTROLS_COMBOBOX_EMPTY_COMBOBOX_MODEL_H_
#include "ui/base/models/combobox_model.h"
namespace views {
namespace internal {
// An empty model for a combo box.
class EmptyComboboxModel final : public ui::ComboboxModel {
public:
EmptyComboboxModel();
EmptyComboboxModel(EmptyComboboxModel&) = delete;
EmptyComboboxModel& operator=(const EmptyComboboxModel&) = delete;
~EmptyComboboxModel() override;
// ui::ComboboxModel:
int GetItemCount() const override;
base::string16 GetItemAt(int index) const override;
int GetDefaultIndex() const override;
};
} // namespace internal
} // namespace views
#endif // UI_VIEWS_CONTROLS_COMBOBOX_EMPTY_COMBOBOX_MODEL_H_
......@@ -44,6 +44,7 @@
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/button_controller.h"
#include "ui/views/controls/combobox/combobox_util.h"
#include "ui/views/controls/combobox/empty_combobox_model.h"
#include "ui/views/controls/menu/menu_config.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/menu/menu_types.h"
......@@ -301,6 +302,9 @@ class EditableCombobox::EditableComboboxPreTargetHandler
DISALLOW_COPY_AND_ASSIGN(EditableComboboxPreTargetHandler);
};
EditableCombobox::EditableCombobox()
: EditableCombobox(std::make_unique<internal::EmptyComboboxModel>()) {}
EditableCombobox::EditableCombobox(
std::unique_ptr<ui::ComboboxModel> combobox_model,
const bool filter_on_edit,
......@@ -310,16 +314,13 @@ EditableCombobox::EditableCombobox(
const int text_style,
const bool display_arrow)
: textfield_(new Textfield()),
combobox_model_(std::move(combobox_model)),
menu_model_(
std::make_unique<EditableComboboxMenuModel>(this,
combobox_model_.get(),
filter_on_edit,
show_on_empty)),
text_context_(text_context),
text_style_(text_style),
type_(type),
filter_on_edit_(filter_on_edit),
show_on_empty_(show_on_empty),
showing_password_text_(type != Type::kPassword) {
SetModel(std::move(combobox_model));
observer_.Add(textfield_);
textfield_->set_controller(this);
textfield_->SetFontList(GetFontList());
......@@ -341,6 +342,13 @@ EditableCombobox::~EditableCombobox() {
textfield_->set_controller(nullptr);
}
void EditableCombobox::SetModel(std::unique_ptr<ui::ComboboxModel> model) {
CloseMenu();
combobox_model_.swap(model);
menu_model_ = std::make_unique<EditableComboboxMenuModel>(
this, combobox_model_.get(), filter_on_edit_, show_on_empty_);
}
const base::string16& EditableCombobox::GetText() const {
return textfield_->GetText();
}
......
......@@ -56,6 +56,8 @@ class VIEWS_EXPORT EditableCombobox
static constexpr int kDefaultTextContext = style::CONTEXT_BUTTON;
static constexpr int kDefaultTextStyle = style::STYLE_PRIMARY;
EditableCombobox();
// |combobox_model|: The ComboboxModel that gives us the items to show in the
// menu.
// |filter_on_edit|: Whether to only show the items that are case-insensitive
......@@ -66,16 +68,18 @@ class VIEWS_EXPORT EditableCombobox
// |text_context| and |text_style|: Together these indicate the font to use.
// |display_arrow|: Whether to display an arrow in the combobox to indicate
// that there is a drop-down list.
EditableCombobox(std::unique_ptr<ui::ComboboxModel> combobox_model,
bool filter_on_edit,
bool show_on_empty,
Type type = Type::kRegular,
int text_context = kDefaultTextContext,
int text_style = kDefaultTextStyle,
bool display_arrow = true);
explicit EditableCombobox(std::unique_ptr<ui::ComboboxModel> combobox_model,
bool filter_on_edit = false,
bool show_on_empty = true,
Type type = Type::kRegular,
int text_context = kDefaultTextContext,
int text_style = kDefaultTextStyle,
bool display_arrow = true);
~EditableCombobox() override;
void SetModel(std::unique_ptr<ui::ComboboxModel> model);
const base::string16& GetText() const;
void SetText(const base::string16& text);
......@@ -167,6 +171,12 @@ class VIEWS_EXPORT EditableCombobox
const Type type_;
// Whether to adapt the items shown to the textfield content.
bool filter_on_edit_;
// Whether to show options when the textfield is empty.
bool show_on_empty_;
// Set while the drop-down is showing.
std::unique_ptr<MenuRunner> menu_runner_;
......
......@@ -829,5 +829,67 @@ TEST_F(EditableComboboxTest, NoCrashWithoutWidget) {
combobox->RevealPasswords(true);
}
using EditableComboboxDefaultTest = ViewsTestBase;
class ConfigurableComboboxModel final : public ui::ComboboxModel {
public:
explicit ConfigurableComboboxModel(bool* destroyed = nullptr)
: destroyed_(destroyed) {
if (destroyed_)
*destroyed_ = false;
}
ConfigurableComboboxModel(ConfigurableComboboxModel&) = delete;
ConfigurableComboboxModel& operator=(const ConfigurableComboboxModel&) =
delete;
~ConfigurableComboboxModel() override {
if (destroyed_)
*destroyed_ = true;
}
// ui::ComboboxModel:
int GetItemCount() const override { return item_count_; }
base::string16 GetItemAt(int index) const override {
DCHECK_LT(index, item_count_);
return base::NumberToString16(index);
}
void SetItemCount(int item_count) { item_count_ = item_count; }
private:
bool* const destroyed_;
int item_count_ = 0;
};
} // namespace
TEST_F(EditableComboboxDefaultTest, Default) {
auto combobox = std::make_unique<EditableCombobox>();
EXPECT_EQ(0, combobox->GetItemCountForTest());
}
TEST_F(EditableComboboxDefaultTest, SetModel) {
std::unique_ptr<ConfigurableComboboxModel> model =
std::make_unique<ConfigurableComboboxModel>();
model->SetItemCount(42);
auto combobox = std::make_unique<EditableCombobox>();
combobox->SetModel(std::move(model));
EXPECT_EQ(42, combobox->GetItemCountForTest());
}
TEST_F(EditableComboboxDefaultTest, SetModelOverwrite) {
bool destroyed_first = false;
bool destroyed_second = false;
{
auto combobox = std::make_unique<EditableCombobox>();
combobox->SetModel(
std::make_unique<ConfigurableComboboxModel>(&destroyed_first));
ASSERT_FALSE(destroyed_first);
combobox->SetModel(
std::make_unique<ConfigurableComboboxModel>(&destroyed_second));
EXPECT_TRUE(destroyed_first);
ASSERT_FALSE(destroyed_second);
}
EXPECT_TRUE(destroyed_second);
}
} // namespace views
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