diff options
author | mukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-25 03:37:40 +0000 |
---|---|---|
committer | mukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-25 03:37:40 +0000 |
commit | 44e111cbe420a952d8c995d89c16c352b89cc909 (patch) | |
tree | 2a74b9392cfa24ce28f2e9f498626c3707e08f29 /ash/ime | |
parent | afd51ef55d60f5c9ad3c29e94f9703053438302c (diff) | |
download | chromium_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.cc | 31 | ||||
-rw-r--r-- | ash/ime/candidate_view.h | 8 | ||||
-rw-r--r-- | ash/ime/candidate_view_unittest.cc | 185 | ||||
-rw-r--r-- | ash/ime/candidate_window_view.cc | 10 |
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); |