summaryrefslogtreecommitdiffstats
path: root/ash/ime
diff options
context:
space:
mode:
authormukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-25 03:37:40 +0000
committermukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-25 03:37:40 +0000
commit44e111cbe420a952d8c995d89c16c352b89cc909 (patch)
tree2a74b9392cfa24ce28f2e9f498626c3707e08f29 /ash/ime
parentafd51ef55d60f5c9ad3c29e94f9703053438302c (diff)
downloadchromium_src-44e111cbe420a952d8c995d89c16c352b89cc909.zip
chromium_src-44e111cbe420a952d8c995d89c16c352b89cc909.tar.gz
chromium_src-44e111cbe420a952d8c995d89c16c352b89cc909.tar.bz2
Introduces 'highlighted' property to candidate view.
With my previous 'cleanup', the candidate view becomes a CustomButton and the 'PRESSED' button status indicates the highlighted. I thought this is good enough, but hovering also changes the button state. Using a button state is a bad idea, so this CL adds a boolean flag for highlighted status. BUG=365959 R=oshima@chromium.org TEST=manually, ash_unittests Review URL: https://codereview.chromium.org/258463002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@266123 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/ime')
-rw-r--r--ash/ime/candidate_view.cc31
-rw-r--r--ash/ime/candidate_view.h8
-rw-r--r--ash/ime/candidate_view_unittest.cc185
-rw-r--r--ash/ime/candidate_window_view.cc10
4 files changed, 218 insertions, 16 deletions
diff --git a/ash/ime/candidate_view.cc b/ash/ime/candidate_view.cc
index 83c930f..4071071 100644
--- a/ash/ime/candidate_view.cc
+++ b/ash/ime/candidate_view.cc
@@ -140,7 +140,10 @@ CandidateView::CandidateView(
shortcut_label_(NULL),
candidate_label_(NULL),
annotation_label_(NULL),
- infolist_icon_(NULL) {
+ infolist_icon_(NULL),
+ shortcut_width_(0),
+ candidate_width_(0),
+ highlighted_(false) {
SetBorder(views::Border::CreateEmptyBorder(1, 1, 1, 1));
const ui::NativeTheme& theme = *GetNativeTheme();
@@ -188,9 +191,12 @@ void CandidateView::SetInfolistIcon(bool enable) {
SchedulePaint();
}
-void CandidateView::StateChanged() {
- shortcut_label_->SetEnabled(state() != STATE_DISABLED);
- if (state() == STATE_PRESSED) {
+void CandidateView::SetHighlighted(bool highlighted) {
+ if (highlighted_ == highlighted)
+ return;
+
+ highlighted_ = highlighted;
+ if (highlighted) {
ui::NativeTheme* theme = GetNativeTheme();
set_background(
views::Background::CreateSolidBackground(theme->GetSystemColor(
@@ -203,13 +209,20 @@ void CandidateView::StateChanged() {
for (int i = 0; i < parent()->child_count(); ++i) {
CandidateView* view =
static_cast<CandidateView*>((parent()->child_at(i)));
- if (view != this && view->state() == STATE_PRESSED)
- view->SetState(STATE_NORMAL);
+ if (view != this)
+ view->SetHighlighted(false);
}
} else {
set_background(NULL);
SetBorder(views::Border::CreateEmptyBorder(1, 1, 1, 1));
}
+ SchedulePaint();
+}
+
+void CandidateView::StateChanged() {
+ shortcut_label_->SetEnabled(state() != STATE_DISABLED);
+ if (state() == STATE_PRESSED)
+ SetHighlighted(true);
}
bool CandidateView::OnMouseDragged(const ui::MouseEvent& event) {
@@ -218,14 +231,16 @@ bool CandidateView::OnMouseDragged(const ui::MouseEvent& event) {
gfx::Point location_in_widget(event.location());
ConvertPointToWidget(this, &location_in_widget);
for (int i = 0; i < parent()->child_count(); ++i) {
- views::View* sibling = parent()->child_at(i);
+ CandidateView* sibling =
+ static_cast<CandidateView*>(parent()->child_at(i));
if (sibling == this)
continue;
gfx::Point location_in_sibling(location_in_widget);
ConvertPointFromWidget(sibling, &location_in_sibling);
if (sibling->HitTestPoint(location_in_sibling)) {
GetWidget()->GetRootView()->SetMouseHandler(sibling);
- return sibling->OnMouseDragged(event);
+ sibling->SetHighlighted(true);
+ return sibling->OnMouseDragged(ui::MouseEvent(event, this, sibling));
}
}
diff --git a/ash/ime/candidate_view.h b/ash/ime/candidate_view.h
index 6f58957..ad316d0 100644
--- a/ash/ime/candidate_view.h
+++ b/ash/ime/candidate_view.h
@@ -33,6 +33,8 @@ class ASH_EXPORT CandidateView : public views::CustomButton {
// Sets infolist icon.
void SetInfolistIcon(bool enable);
+ void SetHighlighted(bool highlighted);
+
private:
friend class CandidateWindowViewTest;
FRIEND_TEST_ALL_PREFIXES(CandidateWindowViewTest, ShortcutSettingTest);
@@ -57,12 +59,12 @@ class ASH_EXPORT CandidateView : public views::CustomButton {
views::Label* candidate_label_;
// The annotation label renders annotations.
views::Label* annotation_label_;
+ // The infolist icon.
+ views::View* infolist_icon_;
int shortcut_width_;
int candidate_width_;
-
- // The infolist icon.
- views::View* infolist_icon_;
+ bool highlighted_;
DISALLOW_COPY_AND_ASSIGN(CandidateView);
};
diff --git a/ash/ime/candidate_view_unittest.cc b/ash/ime/candidate_view_unittest.cc
new file mode 100644
index 0000000..708ec92
--- /dev/null
+++ b/ash/ime/candidate_view_unittest.cc
@@ -0,0 +1,185 @@
+// Copyright 2014 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 "ash/ime/candidate_view.h"
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/aura/window.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/fill_layout.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/widget/widget_delegate.h"
+
+namespace ash {
+namespace ime {
+namespace {
+
+const char* const kDummyCandidates[] = {
+ "candidate1",
+ "candidate2",
+ "candidate3",
+};
+
+} // namespace
+
+class CandidateViewTest : public views::ViewsTestBase,
+ public views::ButtonListener {
+ public:
+ CandidateViewTest() : widget_(NULL), last_pressed_(NULL) {}
+ virtual ~CandidateViewTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ views::ViewsTestBase::SetUp();
+
+ views::Widget::InitParams init_params(CreateParams(
+ views::Widget::InitParams::TYPE_WINDOW));
+
+ init_params.delegate = new views::WidgetDelegateView();
+
+ container_ = init_params.delegate->GetContentsView();
+ container_->SetLayoutManager(
+ new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
+ for (size_t i = 0; i < arraysize(kDummyCandidates); ++i) {
+ CandidateView* candidate = new CandidateView(
+ this, ui::CandidateWindow::VERTICAL);
+ ui::CandidateWindow::Entry entry;
+ entry.value = base::UTF8ToUTF16(kDummyCandidates[i]);
+ candidate->SetEntry(entry);
+ container_->AddChildView(candidate);
+ }
+
+ widget_ = new views::Widget();
+ widget_->Init(init_params);
+ widget_->Show();
+
+ aura::Window* native_window = widget_->GetNativeWindow();
+ event_generator_.reset(new aura::test::EventGenerator(
+ native_window->GetRootWindow(), native_window));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ widget_->Close();
+
+ views::ViewsTestBase::TearDown();
+ }
+
+ protected:
+ CandidateView* GetCandidateAt(int index) {
+ return static_cast<CandidateView*>(container_->child_at(index));
+ }
+
+ int GetHighlightedIndex(int* highlighted_count) const {
+ *highlighted_count = 0;
+ int last_highlighted = -1;
+ for (int i = 0; i < container_->child_count(); ++i) {
+ if (container_->child_at(i)->background() != NULL) {
+ (*highlighted_count)++;
+ last_highlighted = i;
+ }
+ }
+ return last_highlighted;
+ }
+
+ int GetLastPressedIndexAndReset() {
+ for (int i = 0; i < container_->child_count(); ++i) {
+ if (last_pressed_ == container_->child_at(i)) {
+ last_pressed_ = NULL;
+ return i;
+ }
+ }
+
+ DCHECK(last_pressed_ == NULL);
+ last_pressed_ = NULL;
+ return -1;
+ }
+
+ aura::test::EventGenerator* event_generator() {
+ return event_generator_.get();
+ }
+
+ private:
+ virtual void ButtonPressed(views::Button* sender,
+ const ui::Event& event) OVERRIDE {
+ last_pressed_ = sender;
+ }
+
+ views::Widget* widget_;
+ views::View* container_;
+ scoped_ptr<aura::test::EventGenerator> event_generator_;
+ views::View* last_pressed_;
+
+ DISALLOW_COPY_AND_ASSIGN(CandidateViewTest);
+};
+
+TEST_F(CandidateViewTest, MouseHovers) {
+ GetCandidateAt(0)->SetHighlighted(true);
+
+ int highlighted_count = 0;
+ EXPECT_EQ(0, GetHighlightedIndex(&highlighted_count));
+ EXPECT_EQ(1, highlighted_count);
+
+ // Mouse hover shouldn't change the background.
+ event_generator()->MoveMouseTo(
+ GetCandidateAt(0)->GetBoundsInScreen().CenterPoint());
+ EXPECT_EQ(0, GetHighlightedIndex(&highlighted_count));
+ EXPECT_EQ(1, highlighted_count);
+
+ // Mouse hover shouldn't change the background.
+ event_generator()->MoveMouseTo(
+ GetCandidateAt(1)->GetBoundsInScreen().CenterPoint());
+ EXPECT_EQ(0, GetHighlightedIndex(&highlighted_count));
+ EXPECT_EQ(1, highlighted_count);
+
+ // Mouse hover shouldn't change the background.
+ event_generator()->MoveMouseTo(
+ GetCandidateAt(2)->GetBoundsInScreen().CenterPoint());
+ EXPECT_EQ(0, GetHighlightedIndex(&highlighted_count));
+ EXPECT_EQ(1, highlighted_count);
+}
+
+TEST_F(CandidateViewTest, MouseClick) {
+ event_generator()->MoveMouseTo(
+ GetCandidateAt(1)->GetBoundsInScreen().CenterPoint());
+ event_generator()->ClickLeftButton();
+ EXPECT_EQ(1, GetLastPressedIndexAndReset());
+}
+
+TEST_F(CandidateViewTest, ClickAndMove) {
+ GetCandidateAt(0)->SetHighlighted(true);
+
+ int highlighted_count = 0;
+ EXPECT_EQ(0, GetHighlightedIndex(&highlighted_count));
+ EXPECT_EQ(1, highlighted_count);
+
+ event_generator()->MoveMouseTo(
+ GetCandidateAt(2)->GetBoundsInScreen().CenterPoint());
+ event_generator()->PressLeftButton();
+ EXPECT_EQ(2, GetHighlightedIndex(&highlighted_count));
+ EXPECT_EQ(1, highlighted_count);
+
+ // Highlight follows the drag.
+ event_generator()->MoveMouseTo(
+ GetCandidateAt(1)->GetBoundsInScreen().CenterPoint());
+ EXPECT_EQ(1, GetHighlightedIndex(&highlighted_count));
+ EXPECT_EQ(1, highlighted_count);
+
+ event_generator()->MoveMouseTo(
+ GetCandidateAt(0)->GetBoundsInScreen().CenterPoint());
+ EXPECT_EQ(0, GetHighlightedIndex(&highlighted_count));
+ EXPECT_EQ(1, highlighted_count);
+
+ event_generator()->MoveMouseTo(
+ GetCandidateAt(1)->GetBoundsInScreen().CenterPoint());
+ EXPECT_EQ(1, GetHighlightedIndex(&highlighted_count));
+ EXPECT_EQ(1, highlighted_count);
+
+ event_generator()->ReleaseLeftButton();
+ EXPECT_EQ(1, GetLastPressedIndexAndReset());
+}
+
+} // namespace ime
+} // namespace ash
diff --git a/ash/ime/candidate_window_view.cc b/ash/ime/candidate_window_view.cc
index 87a39f5..861e812 100644
--- a/ash/ime/candidate_window_view.cc
+++ b/ash/ime/candidate_window_view.cc
@@ -283,12 +283,12 @@ void CandidateWindowView::UpdateCandidates(
const ui::CandidateWindow::Entry& entry =
new_candidate_window.candidates()[candidate_index];
candidate_view->SetEntry(entry);
- candidate_view->SetState(views::Button::STATE_NORMAL);
+ candidate_view->SetEnabled(true);
candidate_view->SetInfolistIcon(!entry.description_title.empty());
} else {
// Disable the empty row.
candidate_view->SetEntry(ui::CandidateWindow::Entry());
- candidate_view->SetState(views::Button::STATE_DISABLED);
+ candidate_view->SetEnabled(false);
candidate_view->SetInfolistIcon(false);
}
if (new_candidate_window.orientation() == ui::CandidateWindow::VERTICAL) {
@@ -328,8 +328,8 @@ void CandidateWindowView::UpdateCandidates(
if (0 <= selected_candidate_index_in_page_ &&
static_cast<size_t>(selected_candidate_index_in_page_) <
candidate_views_.size()) {
- candidate_views_[selected_candidate_index_in_page_]->SetState(
- views::Button::STATE_NORMAL);
+ candidate_views_[selected_candidate_index_in_page_]->SetHighlighted(
+ false);
selected_candidate_index_in_page_ = -1;
}
}
@@ -388,7 +388,7 @@ void CandidateWindowView::SelectCandidateAt(int index_in_page) {
selected_candidate_index_in_page_ = index_in_page;
// Select the candidate specified by index_in_page.
- candidate_views_[index_in_page]->SetState(views::Button::STATE_PRESSED);
+ candidate_views_[index_in_page]->SetHighlighted(true);
// Update the cursor indexes in the model.
candidate_window_.set_cursor_position(cursor_absolute_index);