summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-06 17:03:25 +0000
committermukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-06 17:03:25 +0000
commit1e936b74a528257a3391d4b2a427ee9f2e358368 (patch)
tree7ab3483212948f112190591c42de50689eb0ace9
parent64b1d4eaffb35f10f5fdc591a680036063d9b78d (diff)
downloadchromium_src-1e936b74a528257a3391d4b2a427ee9f2e358368.zip
chromium_src-1e936b74a528257a3391d4b2a427ee9f2e358368.tar.gz
chromium_src-1e936b74a528257a3391d4b2a427ee9f2e358368.tar.bz2
Cleanup CandidateWindowView.
- moves the implementation of CandidateView as a separate cc file. - CandidateView is now a button to reduce the click handling. - introduces canceling drag logic over CandidateViews - CandidateWindowView is now a BubbleDelegateView - HidableArea is removed. It's not used anymore. - removes complex GridLayout logic and use BoxLayout. BUG=325813 R=komatsu@chromium.org TEST=unit_tests pass, manually check Review URL: https://codereview.chromium.org/121163003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243106 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/input_method/candidate_view.cc286
-rw-r--r--chrome/browser/chromeos/input_method/candidate_view.h64
-rw-r--r--chrome/browser/chromeos/input_method/candidate_window_controller_impl.cc95
-rw-r--r--chrome/browser/chromeos/input_method/candidate_window_controller_impl.h12
-rw-r--r--chrome/browser/chromeos/input_method/candidate_window_view.cc1048
-rw-r--r--chrome/browser/chromeos/input_method/candidate_window_view.h137
-rw-r--r--chrome/browser/chromeos/input_method/candidate_window_view_unittest.cc197
-rw-r--r--chrome/browser/chromeos/input_method/hidable_area.cc48
-rw-r--r--chrome/browser/chromeos/input_method/hidable_area.h48
-rw-r--r--chrome/chrome_browser_chromeos.gypi4
10 files changed, 670 insertions, 1269 deletions
diff --git a/chrome/browser/chromeos/input_method/candidate_view.cc b/chrome/browser/chromeos/input_method/candidate_view.cc
new file mode 100644
index 0000000..fd655e8
--- /dev/null
+++ b/chrome/browser/chromeos/input_method/candidate_view.cc
@@ -0,0 +1,286 @@
+// 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 "chrome/browser/chromeos/input_method/candidate_view.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/chromeos/input_method/candidate_window_constants.h"
+#include "chromeos/ime/candidate_window.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/native_theme/native_theme.h"
+#include "ui/views/background.h"
+#include "ui/views/border.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/widget/widget.h"
+
+namespace chromeos {
+namespace input_method {
+
+namespace {
+
+// VerticalCandidateLabel is used for rendering candidate text in
+// the vertical candidate window.
+class VerticalCandidateLabel : public views::Label {
+ public:
+ VerticalCandidateLabel() {}
+
+ private:
+ virtual ~VerticalCandidateLabel() {}
+
+ // Returns the preferred size, but guarantees that the width has at
+ // least kMinCandidateLabelWidth pixels.
+ virtual gfx::Size GetPreferredSize() OVERRIDE {
+ gfx::Size size = Label::GetPreferredSize();
+ size.SetToMax(gfx::Size(kMinCandidateLabelWidth, 0));
+ size.SetToMin(gfx::Size(kMaxCandidateLabelWidth, size.height()));
+ return size;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(VerticalCandidateLabel);
+};
+
+// Creates the shortcut label, and returns it (never returns NULL).
+// The label text is not set in this function.
+views::Label* CreateShortcutLabel(
+ CandidateWindow::Orientation orientation,
+ const ui::NativeTheme& theme) {
+ // Create the shortcut label. The label will be owned by
+ // |wrapped_shortcut_label|, hence it's deleted when
+ // |wrapped_shortcut_label| is deleted.
+ views::Label* shortcut_label = new views::Label;
+
+ if (orientation == CandidateWindow::VERTICAL) {
+ shortcut_label->SetFontList(
+ shortcut_label->font_list().DeriveFontListWithSizeDeltaAndStyle(
+ kFontSizeDelta, gfx::Font::BOLD));
+ } else {
+ shortcut_label->SetFontList(
+ shortcut_label->font_list().DeriveFontListWithSizeDelta(
+ kFontSizeDelta));
+ }
+ // TODO(satorux): Maybe we need to use language specific fonts for
+ // candidate_label, like Chinese font for Chinese input method?
+ shortcut_label->SetEnabledColor(theme.GetSystemColor(
+ ui::NativeTheme::kColorId_LabelEnabledColor));
+ shortcut_label->SetDisabledColor(theme.GetSystemColor(
+ ui::NativeTheme::kColorId_LabelDisabledColor));
+
+ // Setup paddings.
+ const gfx::Insets kVerticalShortcutLabelInsets(1, 6, 1, 6);
+ const gfx::Insets kHorizontalShortcutLabelInsets(1, 3, 1, 0);
+ const gfx::Insets insets =
+ (orientation == CandidateWindow::VERTICAL ?
+ kVerticalShortcutLabelInsets :
+ kHorizontalShortcutLabelInsets);
+ shortcut_label->set_border(views::Border::CreateEmptyBorder(
+ insets.top(), insets.left(), insets.bottom(), insets.right()));
+
+ // Add decoration based on the orientation.
+ if (orientation == CandidateWindow::VERTICAL) {
+ // Set the background color.
+ SkColor blackish = color_utils::AlphaBlend(
+ SK_ColorBLACK,
+ theme.GetSystemColor(ui::NativeTheme::kColorId_WindowBackground),
+ 0x40);
+ SkColor transparent_blakish = color_utils::AlphaBlend(
+ SK_ColorTRANSPARENT, blackish, 0xE0);
+ shortcut_label->set_background(
+ views::Background::CreateSolidBackground(transparent_blakish));
+ }
+
+ return shortcut_label;
+}
+
+// Creates the candidate label, and returns it (never returns NULL).
+// The label text is not set in this function.
+views::Label* CreateCandidateLabel(
+ CandidateWindow::Orientation orientation) {
+ views::Label* candidate_label = NULL;
+
+ // Create the candidate label. The label will be added to |this| as a
+ // child view, hence it's deleted when |this| is deleted.
+ if (orientation == CandidateWindow::VERTICAL) {
+ candidate_label = new VerticalCandidateLabel;
+ } else {
+ candidate_label = new views::Label;
+ }
+
+ // Change the font size.
+ candidate_label->SetFontList(
+ candidate_label->font_list().DeriveFontListWithSizeDelta(kFontSizeDelta));
+ candidate_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+
+ return candidate_label;
+}
+
+// Creates the annotation label, and return it (never returns NULL).
+// The label text is not set in this function.
+views::Label* CreateAnnotationLabel(
+ CandidateWindow::Orientation orientation, const ui::NativeTheme& theme) {
+ // Create the annotation label.
+ views::Label* annotation_label = new views::Label;
+
+ // Change the font size and color.
+ annotation_label->SetFontList(
+ annotation_label->font_list().DeriveFontListWithSizeDelta(
+ kFontSizeDelta));
+ annotation_label->SetEnabledColor(theme.GetSystemColor(
+ ui::NativeTheme::kColorId_LabelDisabledColor));
+ annotation_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+
+ return annotation_label;
+}
+
+} // namespace
+
+CandidateView::CandidateView(
+ views::ButtonListener* listener,
+ CandidateWindow::Orientation orientation)
+ : views::CustomButton(listener),
+ orientation_(orientation),
+ shortcut_label_(NULL),
+ candidate_label_(NULL),
+ annotation_label_(NULL),
+ infolist_icon_(NULL) {
+ set_border(views::Border::CreateEmptyBorder(1, 1, 1, 1));
+
+ const ui::NativeTheme& theme = *GetNativeTheme();
+ shortcut_label_ = CreateShortcutLabel(orientation, theme);
+ candidate_label_ = CreateCandidateLabel(orientation);
+ annotation_label_ = CreateAnnotationLabel(orientation, theme);
+
+ AddChildView(shortcut_label_);
+ AddChildView(candidate_label_);
+ AddChildView(annotation_label_);
+
+ if (orientation == CandidateWindow::VERTICAL) {
+ infolist_icon_ = new views::View;
+ infolist_icon_->set_background(
+ views::Background::CreateSolidBackground(theme.GetSystemColor(
+ ui::NativeTheme::kColorId_FocusedBorderColor)));
+ AddChildView(infolist_icon_);
+ }
+}
+
+void CandidateView::GetPreferredWidths(int* shortcut_width,
+ int* candidate_width) {
+ *shortcut_width = shortcut_label_->GetPreferredSize().width();
+ *candidate_width = candidate_label_->GetPreferredSize().width();
+}
+
+void CandidateView::SetWidths(int shortcut_width, int candidate_width) {
+ shortcut_width_ = shortcut_width;
+ shortcut_label_->SetVisible(shortcut_width_ != 0);
+ candidate_width_ = candidate_width;
+}
+
+void CandidateView::SetEntry(const CandidateWindow::Entry& entry) {
+ std::string label = entry.label;
+ if (!label.empty() && orientation_ != CandidateWindow::VERTICAL)
+ label += '.';
+ shortcut_label_->SetText(base::UTF8ToUTF16(label));
+ candidate_label_->SetText(base::UTF8ToUTF16(entry.value));
+ annotation_label_->SetText(base::UTF8ToUTF16(entry.annotation));
+}
+
+void CandidateView::SetInfolistIcon(bool enable) {
+ if (infolist_icon_)
+ infolist_icon_->SetVisible(enable);
+ SchedulePaint();
+}
+
+void CandidateView::StateChanged() {
+ shortcut_label_->SetEnabled(state() != STATE_DISABLED);
+ if (state() == STATE_PRESSED) {
+ ui::NativeTheme* theme = GetNativeTheme();
+ set_background(
+ views::Background::CreateSolidBackground(theme->GetSystemColor(
+ ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused)));
+ set_border(views::Border::CreateSolidBorder(
+ 1, theme->GetSystemColor(
+ ui::NativeTheme::kColorId_FocusedBorderColor)));
+
+ // Cancel currently focused one.
+ 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);
+ }
+ } else {
+ set_background(NULL);
+ set_border(views::Border::CreateEmptyBorder(1, 1, 1, 1));
+ }
+}
+
+bool CandidateView::OnMouseDragged(const ui::MouseEvent& event) {
+ if (!HitTestPoint(event.location())) {
+ // Moves the drag target to the sibling view.
+ 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);
+ 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);
+ }
+ }
+
+ return false;
+ }
+
+ return views::CustomButton::OnMouseDragged(event);
+}
+
+void CandidateView::Layout() {
+ const int padding_width =
+ orientation_ == CandidateWindow::VERTICAL ? 4 : 6;
+ int x = 0;
+ shortcut_label_->SetBounds(x, 0, shortcut_width_, height());
+ if (shortcut_width_ > 0)
+ x += shortcut_width_ + padding_width;
+ candidate_label_->SetBounds(x, 0, candidate_width_, height());
+ x += candidate_width_ + padding_width;
+
+ int right = bounds().right();
+ if (infolist_icon_ && infolist_icon_->visible()) {
+ infolist_icon_->SetBounds(
+ right - kInfolistIndicatorIconWidth - kInfolistIndicatorIconPadding,
+ kInfolistIndicatorIconPadding,
+ kInfolistIndicatorIconWidth,
+ height() - kInfolistIndicatorIconPadding * 2);
+ right -= kInfolistIndicatorIconWidth + kInfolistIndicatorIconPadding * 2;
+ }
+ annotation_label_->SetBounds(x, 0, right - x, height());
+}
+
+gfx::Size CandidateView::GetPreferredSize() {
+ const int padding_width =
+ orientation_ == CandidateWindow::VERTICAL ? 4 : 6;
+ gfx::Size size;
+ if (shortcut_label_->visible()) {
+ size = shortcut_label_->GetPreferredSize();
+ size.Enlarge(padding_width, 0);
+ }
+ gfx::Size candidate_size = candidate_label_->GetPreferredSize();
+ size.Enlarge(candidate_size.width() + padding_width, 0);
+ size.SetToMax(candidate_size);
+ if (annotation_label_->visible()) {
+ gfx::Size annotation_size = annotation_label_->GetPreferredSize();
+ size.Enlarge(annotation_size.width() + padding_width, 0);
+ size.SetToMax(annotation_size);
+ }
+
+ // Reserves the margin for infolist_icon even if it's not visible.
+ size.Enlarge(
+ kInfolistIndicatorIconWidth + kInfolistIndicatorIconPadding * 2, 0);
+ return size;
+}
+
+} // namespace input_method
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/candidate_view.h b/chrome/browser/chromeos/input_method/candidate_view.h
index d5ad243..4c8834a 100644
--- a/chrome/browser/chromeos/input_method/candidate_view.h
+++ b/chrome/browser/chromeos/input_method/candidate_view.h
@@ -7,78 +7,46 @@
#include "base/gtest_prod_util.h"
#include "chromeos/ime/candidate_window.h"
+#include "ui/views/controls/button/custom_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/view.h"
namespace chromeos {
namespace input_method {
-class CandidateWindowView;
-
// CandidateView renderes a row of a candidate.
-class CandidateView : public views::View {
+class CandidateView : public views::CustomButton {
public:
- CandidateView(CandidateWindowView* parent_candidate_window,
- int index_in_page,
+ CandidateView(views::ButtonListener* listener,
CandidateWindow::Orientation orientation);
virtual ~CandidateView() {}
- // Initializes the candidate view with the given column widths.
- // A width of 0 means that the column is resizable.
- void Init(int shortcut_column_width,
- int candidate_column_width,
- int annotation_column_width,
- int column_height);
- // Sets candidate text to the given text.
- void SetCandidateText(const base::string16& text);
+ void GetPreferredWidths(int* shortcut_width,
+ int* candidate_width);
- // Sets shortcut text to the given text.
- void SetShortcutText(const base::string16& text);
+ void SetWidths(int shortcut_width,
+ int candidate_width);
- // Sets annotation text to the given text.
- void SetAnnotationText(const base::string16& text);
+ void SetEntry(const CandidateWindow::Entry& entry);
// Sets infolist icon.
void SetInfolistIcon(bool enable);
- // Selects the candidate row. Changes the appearance to make it look
- // like a selected candidate.
- void Select();
-
- // Unselects the candidate row. Changes the appearance to make it look
- // like an unselected candidate.
- void Unselect();
-
- // Enables or disables the candidate row based on |enabled|. Changes the
- // appearance to make it look like unclickable area.
- void SetRowEnabled(bool enabled);
-
- // Returns the relative position of the candidate label.
- gfx::Point GetCandidateLabelPosition() const;
-
private:
friend class CandidateWindowViewTest;
FRIEND_TEST_ALL_PREFIXES(CandidateWindowViewTest, ShortcutSettingTest);
- // Overridden from View:
- virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
-
- // Selects the candidate located at the point.
- void SelectCandidateAt(const gfx::Point& location);
- // Notifies labels of their new background colors. Called whenever the view's
- // background color changes.
- void UpdateLabelBackgroundColors();
+ // Overridden from views::CustomButton:
+ virtual void StateChanged() OVERRIDE;
- // Zero-origin index in the current page.
- int index_in_page_;
+ // Overridden from View:
+ virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
+ virtual void Layout() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() OVERRIDE;
// The orientation of the candidate view.
CandidateWindow::Orientation orientation_;
- // The parent candidate window that contains this view.
- CandidateWindowView* parent_candidate_window_;
-
// Views created in the class will be part of tree of |this|, so these
// child views will be deleted when |this| is deleted.
@@ -89,9 +57,11 @@ class CandidateView : public views::View {
// The annotation label renders annotations.
views::Label* annotation_label_;
+ int shortcut_width_;
+ int candidate_width_;
+
// The infolist icon.
views::View* infolist_icon_;
- bool infolist_icon_enabled_;
DISALLOW_COPY_AND_ASSIGN(CandidateView);
};
diff --git a/chrome/browser/chromeos/input_method/candidate_window_controller_impl.cc b/chrome/browser/chromeos/input_method/candidate_window_controller_impl.cc
index a203a7c..5adab64 100644
--- a/chrome/browser/chromeos/input_method/candidate_window_controller_impl.cc
+++ b/chrome/browser/chromeos/input_method/candidate_window_controller_impl.cc
@@ -31,49 +31,38 @@ CandidateWindowControllerImpl::CandidateWindowControllerImpl()
: candidate_window_view_(NULL),
infolist_window_(NULL) {
IBusBridge::Get()->SetCandidateWindowHandler(this);
- CreateView();
+ // Create the mode indicator controller.
+ mode_indicator_controller_.reset(
+ new ModeIndicatorController(InputMethodManager::Get()));
}
CandidateWindowControllerImpl::~CandidateWindowControllerImpl() {
IBusBridge::Get()->SetCandidateWindowHandler(NULL);
- candidate_window_view_->RemoveObserver(this);
+ if (candidate_window_view_) {
+ candidate_window_view_->RemoveObserver(this);
+ candidate_window_view_->GetWidget()->RemoveObserver(this);
+ }
}
-void CandidateWindowControllerImpl::CreateView() {
- // Create a non-decorated frame.
- frame_.reset(new views::Widget);
- // The size is initially zero.
- views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
- // |frame_| is owned by controller impl so
- // they should use WIDGET_OWNS_NATIVE_WIDGET ownership.
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- // Show the candidate window always on top
- params.parent = ash::Shell::GetContainer(
- ash::Shell::GetTargetRootWindow(),
- ash::internal::kShellWindowId_InputMethodContainer);
- frame_->Init(params);
-
- views::corewm::SetWindowVisibilityAnimationType(
- frame_->GetNativeView(),
- views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
+void CandidateWindowControllerImpl::InitCandidateWindowView() {
+ if (candidate_window_view_)
+ return;
- // Create the candidate window.
- candidate_window_view_ = new CandidateWindowView(frame_.get());
- candidate_window_view_->Init();
+ candidate_window_view_ = new CandidateWindowView(ash::Shell::GetContainer(
+ ash::Shell::GetTargetRootWindow(),
+ ash::internal::kShellWindowId_InputMethodContainer));
candidate_window_view_->AddObserver(this);
-
- frame_->SetContentsView(candidate_window_view_);
-
- // Create the mode indicator controller.
- mode_indicator_controller_.reset(
- new ModeIndicatorController(InputMethodManager::Get()));
+ candidate_window_view_->SetCursorBounds(cursor_bounds_, composition_head_);
+ views::Widget* widget = candidate_window_view_->InitWidget();
+ widget->AddObserver(this);
+ widget->Show();
+ FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_,
+ CandidateWindowOpened());
}
void CandidateWindowControllerImpl::Hide() {
- // To hide the candidate window we have to call HideLookupTable and
- // HideAuxiliaryText. Without calling HideAuxiliaryText the
- // auxiliary text area will remain.
- candidate_window_view_->HideLookupTable();
+ if (candidate_window_view_)
+ candidate_window_view_->GetWidget()->Close();
if (infolist_window_)
infolist_window_->HideImmediately();
}
@@ -84,8 +73,10 @@ void CandidateWindowControllerImpl::SetCursorBounds(
// A workaround for http://crosbug.com/6460. We should ignore very short Y
// move to prevent the window from shaking up and down.
const int kKeepPositionThreshold = 2; // px
- const gfx::Rect& last_bounds =
- candidate_window_view_->cursor_bounds();
+ gfx::Rect last_bounds;
+ if (candidate_window_view_)
+ last_bounds = candidate_window_view_->GetAnchorRect();
+
const int delta_y = abs(last_bounds.y() - cursor_bounds.y());
if ((last_bounds.x() == cursor_bounds.x()) &&
(delta_y <= kKeepPositionThreshold)) {
@@ -93,11 +84,12 @@ void CandidateWindowControllerImpl::SetCursorBounds(
return;
}
+ cursor_bounds_ = cursor_bounds;
+ composition_head_ = composition_head;
+
// Remember the cursor bounds.
- candidate_window_view_->set_cursor_bounds(cursor_bounds);
- candidate_window_view_->set_composition_head_bounds(composition_head);
- // Move the window per the cursor bounds.
- candidate_window_view_->ResizeAndMoveParentFrame();
+ if (candidate_window_view_)
+ candidate_window_view_->SetCursorBounds(cursor_bounds, composition_head);
// Mode indicator controller also needs the cursor bounds.
mode_indicator_controller_->SetCursorBounds(cursor_bounds);
@@ -141,7 +133,8 @@ void CandidateWindowControllerImpl::UpdateLookupTable(
bool visible) {
// If it's not visible, hide the lookup table and return.
if (!visible) {
- candidate_window_view_->HideLookupTable();
+ if (candidate_window_view_)
+ candidate_window_view_->HideLookupTable();
if (infolist_window_)
infolist_window_->HideImmediately();
// TODO(nona): Introduce unittests for crbug.com/170036.
@@ -149,6 +142,8 @@ void CandidateWindowControllerImpl::UpdateLookupTable(
return;
}
+ if (!candidate_window_view_)
+ InitCandidateWindowView();
candidate_window_view_->UpdateCandidates(candidate_window);
candidate_window_view_->ShowLookupTable();
@@ -191,9 +186,12 @@ void CandidateWindowControllerImpl::UpdatePreeditText(
const std::string& utf8_text, unsigned int cursor, bool visible) {
// If it's not visible, hide the preedit text and return.
if (!visible || utf8_text.empty()) {
- candidate_window_view_->HidePreeditText();
+ if (candidate_window_view_)
+ candidate_window_view_->HidePreeditText();
return;
}
+ if (!candidate_window_view_)
+ InitCandidateWindowView();
candidate_window_view_->UpdatePreeditText(utf8_text);
candidate_window_view_->ShowPreeditText();
}
@@ -203,20 +201,17 @@ void CandidateWindowControllerImpl::OnCandidateCommitted(int index) {
CandidateClicked(index));
}
-void CandidateWindowControllerImpl::OnCandidateWindowOpened() {
- FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_,
- CandidateWindowOpened());
-}
-
-void CandidateWindowControllerImpl::OnCandidateWindowClosed() {
- FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_,
- CandidateWindowClosed());
-}
-
void CandidateWindowControllerImpl::OnWidgetClosing(views::Widget* widget) {
if (infolist_window_ && widget == infolist_window_->GetWidget()) {
widget->RemoveObserver(this);
infolist_window_ = NULL;
+ } else if (candidate_window_view_ &&
+ widget == candidate_window_view_->GetWidget()) {
+ widget->RemoveObserver(this);
+ candidate_window_view_->RemoveObserver(this);
+ candidate_window_view_ = NULL;
+ FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_,
+ CandidateWindowClosed());
}
}
diff --git a/chrome/browser/chromeos/input_method/candidate_window_controller_impl.h b/chrome/browser/chromeos/input_method/candidate_window_controller_impl.h
index 5356bb4..5396525 100644
--- a/chrome/browser/chromeos/input_method/candidate_window_controller_impl.h
+++ b/chrome/browser/chromeos/input_method/candidate_window_controller_impl.h
@@ -55,8 +55,6 @@ class CandidateWindowControllerImpl
private:
// CandidateWindowView::Observer implementation.
virtual void OnCandidateCommitted(int index) OVERRIDE;
- virtual void OnCandidateWindowOpened() OVERRIDE;
- virtual void OnCandidateWindowClosed() OVERRIDE;
// views::WidgetObserver implementation.
virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE;
@@ -70,19 +68,17 @@ class CandidateWindowControllerImpl
unsigned int cursor, bool visible) OVERRIDE;
virtual void FocusStateChanged(bool is_focused) OVERRIDE;
- // Creates the candidate window view.
- void CreateView();
+ void InitCandidateWindowView();
// The candidate window view.
CandidateWindowView* candidate_window_view_;
- // This is the outer frame of the candidate window view. The frame will
- // own |candidate_window_|.
- scoped_ptr<views::Widget> frame_;
-
// This is the outer frame of the infolist window view. Owned by the widget.
InfolistWindow* infolist_window_;
+ gfx::Rect cursor_bounds_;
+ gfx::Rect composition_head_;
+
// This is the controller of the IME mode indicator.
scoped_ptr<ModeIndicatorController> mode_indicator_controller_;
diff --git a/chrome/browser/chromeos/input_method/candidate_window_view.cc b/chrome/browser/chromeos/input_method/candidate_window_view.cc
index bd97f6e..23acaa9 100644
--- a/chrome/browser/chromeos/input_method/candidate_window_view.cc
+++ b/chrome/browser/chromeos/input_method/candidate_window_view.cc
@@ -5,216 +5,72 @@
#include <string>
-#include "ash/shell.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chromeos/input_method/candidate_view.h"
#include "chrome/browser/chromeos/input_method/candidate_window_constants.h"
-#include "chrome/browser/chromeos/input_method/hidable_area.h"
#include "chromeos/ime/candidate_window.h"
#include "ui/gfx/color_utils.h"
+#include "ui/gfx/screen.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
+#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/label.h"
-#include "ui/views/layout/grid_layout.h"
-#include "ui/views/widget/widget.h"
+#include "ui/views/corewm/window_animations.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/fill_layout.h"
namespace chromeos {
namespace input_method {
namespace {
-// VerticalCandidateLabel is used for rendering candidate text in
-// the vertical candidate window.
-class VerticalCandidateLabel : public views::Label {
- public:
- VerticalCandidateLabel() {}
-
- private:
- virtual ~VerticalCandidateLabel() {}
- // Returns the preferred size, but guarantees that the width has at
- // least kMinCandidateLabelWidth pixels.
- virtual gfx::Size GetPreferredSize() OVERRIDE {
- gfx::Size size = Label::GetPreferredSize();
- // Hack. +2 is needed to prevent labels from getting elided like
- // "abc..." in some cases. TODO(satorux): Figure out why it's
- // necessary.
- size.set_width(size.width() + 2);
- if (size.width() < kMinCandidateLabelWidth) {
- size.set_width(kMinCandidateLabelWidth);
- }
- if (size.width() > kMaxCandidateLabelWidth) {
- size.set_width(kMaxCandidateLabelWidth);
- }
- return size;
+class CandidateWindowBorder : public views::BubbleBorder {
+ public:
+ explicit CandidateWindowBorder(gfx::NativeView parent)
+ : views::BubbleBorder(views::BubbleBorder::TOP_CENTER,
+ views::BubbleBorder::NO_SHADOW,
+ SK_ColorTRANSPARENT),
+ parent_(parent),
+ offset_(0) {
+ set_paint_arrow(views::BubbleBorder::PAINT_NONE);
}
+ virtual ~CandidateWindowBorder() {}
- DISALLOW_COPY_AND_ASSIGN(VerticalCandidateLabel);
-};
-
-// Wraps the given view with some padding, and returns it.
-views::View* WrapWithPadding(views::View* view, const gfx::Insets& insets) {
- views::View* wrapper = new views::View;
- // Use GridLayout to give some insets inside.
- views::GridLayout* layout = new views::GridLayout(wrapper);
- wrapper->SetLayoutManager(layout); // |wrapper| owns |layout|.
- layout->SetInsets(insets);
-
- views::ColumnSet* column_set = layout->AddColumnSet(0);
- column_set->AddColumn(
- views::GridLayout::FILL, views::GridLayout::FILL,
- 1, views::GridLayout::USE_PREF, 0, 0);
- layout->StartRow(0, 0);
-
- // Add the view contents.
- layout->AddView(view); // |view| is owned by |wraper|, not |layout|.
- return wrapper;
-}
-
-// Creates shortcut text from the given index and the orientation.
-base::string16 CreateShortcutText(size_t index,
- const CandidateWindow& candidate_window) {
- if (index >= candidate_window.candidates().size())
- return base::string16();
- std::string shortcut_text = candidate_window.candidates()[index].label;
- if (!shortcut_text.empty() &&
- candidate_window.orientation() != CandidateWindow::VERTICAL)
- shortcut_text += '.';
- return base::UTF8ToUTF16(shortcut_text);
-}
-
-// Creates the shortcut label, and returns it (never returns NULL).
-// The label text is not set in this function.
-views::Label* CreateShortcutLabel(
- CandidateWindow::Orientation orientation, const ui::NativeTheme& theme) {
- // Create the shortcut label. The label will be owned by
- // |wrapped_shortcut_label|, hence it's deleted when
- // |wrapped_shortcut_label| is deleted.
- views::Label* shortcut_label = new views::Label;
-
- if (orientation == CandidateWindow::VERTICAL) {
- shortcut_label->SetFontList(
- shortcut_label->font_list().DeriveFontListWithSizeDeltaAndStyle(
- kFontSizeDelta, gfx::Font::BOLD));
- } else {
- shortcut_label->SetFontList(
- shortcut_label->font_list().DeriveFontListWithSizeDelta(
- kFontSizeDelta));
- }
- // TODO(satorux): Maybe we need to use language specific fonts for
- // candidate_label, like Chinese font for Chinese input method?
- shortcut_label->SetEnabledColor(theme.GetSystemColor(
- ui::NativeTheme::kColorId_LabelEnabledColor));
- shortcut_label->SetDisabledColor(theme.GetSystemColor(
- ui::NativeTheme::kColorId_LabelDisabledColor));
+ void set_offset(int offset) { offset_ = offset; }
- return shortcut_label;
-}
+ private:
+ // Overridden from views::BubbleBorder:
+ virtual gfx::Rect GetBounds(const gfx::Rect& anchor_rect,
+ const gfx::Size& content_size) const OVERRIDE {
+ gfx::Rect bounds(content_size);
+ bounds.set_origin(gfx::Point(
+ anchor_rect.x() - offset_,
+ is_arrow_on_top(arrow()) ?
+ anchor_rect.bottom() : anchor_rect.y() - content_size.height()));
-// Wraps the shortcut label, then decorates wrapped shortcut label
-// and returns it (never returns NULL).
-// The label text is not set in this function.
-views::View* CreateWrappedShortcutLabel(
- views::Label* shortcut_label,
- CandidateWindow::Orientation orientation,
- const ui::NativeTheme& theme) {
- // Wrap it with padding.
- const gfx::Insets kVerticalShortcutLabelInsets(1, 6, 1, 6);
- const gfx::Insets kHorizontalShortcutLabelInsets(1, 3, 1, 0);
- const gfx::Insets insets =
- (orientation == CandidateWindow::VERTICAL ?
- kVerticalShortcutLabelInsets :
- kHorizontalShortcutLabelInsets);
- views::View* wrapped_shortcut_label =
- WrapWithPadding(shortcut_label, insets);
+ // It cannot use the normal logic of arrow offset for horizontal offscreen,
+ // because the arrow must be in the content's edge. But CandidateWindow has
+ // to be visible even when |anchor_rect| is out of the screen.
+ gfx::Rect work_area = gfx::Screen::GetNativeScreen()->
+ GetDisplayNearestWindow(parent_).work_area();
+ if (bounds.right() > work_area.right())
+ bounds.set_x(work_area.right() - bounds.width());
+ if (bounds.x() < work_area.x())
+ bounds.set_x(work_area.x());
- // Add decoration based on the orientation.
- if (orientation == CandidateWindow::VERTICAL) {
- // Set the background color.
- SkColor blackish = color_utils::AlphaBlend(
- SK_ColorBLACK,
- theme.GetSystemColor(ui::NativeTheme::kColorId_WindowBackground),
- 0x40);
- SkColor transparent_blakish = color_utils::AlphaBlend(
- SK_ColorTRANSPARENT, blackish, 0xE0);
- wrapped_shortcut_label->set_background(
- views::Background::CreateSolidBackground(transparent_blakish));
- shortcut_label->SetBackgroundColor(
- wrapped_shortcut_label->background()->get_color());
+ return bounds;
}
- return wrapped_shortcut_label;
-}
-
-// Creates the candidate label, and returns it (never returns NULL).
-// The label text is not set in this function.
-views::Label* CreateCandidateLabel(
- CandidateWindow::Orientation orientation) {
- views::Label* candidate_label = NULL;
-
- // Create the candidate label. The label will be added to |this| as a
- // child view, hence it's deleted when |this| is deleted.
- if (orientation == CandidateWindow::VERTICAL) {
- candidate_label = new VerticalCandidateLabel;
- } else {
- candidate_label = new views::Label;
+ virtual gfx::Insets GetInsets() const OVERRIDE {
+ return gfx::Insets();
}
- // Change the font size.
- candidate_label->SetFontList(
- candidate_label->font_list().DeriveFontListWithSizeDelta(kFontSizeDelta));
- candidate_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-
- return candidate_label;
-}
-
-// Creates the annotation label, and return it (never returns NULL).
-// The label text is not set in this function.
-views::Label* CreateAnnotationLabel(
- CandidateWindow::Orientation orientation, const ui::NativeTheme& theme) {
- // Create the annotation label.
- views::Label* annotation_label = new views::Label;
-
- // Change the font size and color.
- annotation_label->SetFontList(
- annotation_label->font_list().DeriveFontListWithSizeDelta(
- kFontSizeDelta));
- annotation_label->SetEnabledColor(theme.GetSystemColor(
- ui::NativeTheme::kColorId_LabelDisabledColor));
- annotation_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-
- return annotation_label;
-}
-
-// Computes shortcut column size.
-gfx::Size ComputeShortcutColumnSize(
- const CandidateWindow& candidate_window,
- const ui::NativeTheme& theme) {
- int shortcut_column_width = 0;
- int shortcut_column_height = 0;
- // Create the shortcut label. The label will be owned by
- // |wrapped_shortcut_label|, hence it's deleted when
- // |wrapped_shortcut_label| is deleted.
- views::Label* shortcut_label = CreateShortcutLabel(
- candidate_window.orientation(), theme);
- scoped_ptr<views::View> wrapped_shortcut_label(
- CreateWrappedShortcutLabel(shortcut_label,
- candidate_window.orientation(),
- theme));
-
- // Compute the max width and height in shortcut labels.
- // We'll create temporary shortcut labels, and choose the largest width and
- // height.
- for (size_t i = 0; i < candidate_window.page_size(); ++i) {
- shortcut_label->SetText(CreateShortcutText(i, candidate_window));
- gfx::Size text_size = wrapped_shortcut_label->GetPreferredSize();
- shortcut_column_width = std::max(shortcut_column_width, text_size.width());
- shortcut_column_height = std::max(shortcut_column_height,
- text_size.height());
- }
+ gfx::NativeView parent_;
+ int offset_;
- return gfx::Size(shortcut_column_width, shortcut_column_height);
-}
+ DISALLOW_COPY_AND_ASSIGN(CandidateWindowBorder);
+};
// Computes the page index. For instance, if the page size is 9, and the
// cursor is pointing to 13th candidate, the page index will be 1 (2nd
@@ -225,467 +81,178 @@ int ComputePageIndex(const CandidateWindow& candidate_window) {
return -1;
}
-// Computes candidate column size.
-gfx::Size ComputeCandidateColumnSize(
- const CandidateWindow& candidate_window) {
- int candidate_column_width = 0;
- int candidate_column_height = 0;
- scoped_ptr<views::Label> candidate_label(
- CreateCandidateLabel(candidate_window.orientation()));
-
- // Compute the start index of |candidate_window_|.
- const int current_page_index = ComputePageIndex(candidate_window);
- if (current_page_index < 0)
- return gfx::Size(0, 0);
- const size_t start_from = current_page_index * candidate_window.page_size();
-
- // Compute the max width and height in candidate labels.
- // We'll create temporary candidate labels, and choose the largest width and
- // height.
- for (size_t i = 0;
- i + start_from < candidate_window.candidates().size();
- ++i) {
- const size_t index = start_from + i;
-
- candidate_label->SetText(
- base::UTF8ToUTF16(candidate_window.candidates()[index].value));
- gfx::Size text_size = candidate_label->GetPreferredSize();
- candidate_column_width = std::max(candidate_column_width,
- text_size.width());
- candidate_column_height = std::max(candidate_column_height,
- text_size.height());
- }
-
- return gfx::Size(candidate_column_width, candidate_column_height);
-}
-
-// Computes annotation column size.
-gfx::Size ComputeAnnotationColumnSize(
- const CandidateWindow& candidate_window, const ui::NativeTheme& theme) {
- int annotation_column_width = 0;
- int annotation_column_height = 0;
- scoped_ptr<views::Label> annotation_label(
- CreateAnnotationLabel(candidate_window.orientation(), theme));
-
- // Compute the start index of |candidate_window_|.
- const int current_page_index = ComputePageIndex(candidate_window);
- if (current_page_index < 0)
- return gfx::Size(0, 0);
- const size_t start_from = current_page_index * candidate_window.page_size();
-
- // Compute max width and height in annotation labels.
- // We'll create temporary annotation labels, and choose the largest width and
- // height.
- for (size_t i = 0;
- i + start_from < candidate_window.candidates().size();
- ++i) {
- const size_t index = start_from + i;
-
- annotation_label->SetText(
- base::UTF8ToUTF16(candidate_window.candidates()[index].annotation));
- gfx::Size text_size = annotation_label->GetPreferredSize();
- annotation_column_width = std::max(annotation_column_width,
- text_size.width());
- annotation_column_height = std::max(annotation_column_height,
- text_size.height());
- }
-
- return gfx::Size(annotation_column_width, annotation_column_height);
-}
-
} // namespace
-// InformationTextArea is a HidableArea having a single Label in it.
-class InformationTextArea : public HidableArea {
+class InformationTextArea : public views::View {
public:
+ // InformationTextArea's border is drawn as a separator, it should appear
+ // at either top or bottom.
+ enum BorderPosition {
+ TOP,
+ BOTTOM
+ };
+
// Specify the alignment and initialize the control.
- InformationTextArea(gfx::HorizontalAlignment align, int minWidth)
- : minWidth_(minWidth) {
+ InformationTextArea(gfx::HorizontalAlignment align, int min_width)
+ : min_width_(min_width) {
label_ = new views::Label;
label_->SetHorizontalAlignment(align);
+ label_->set_border(views::Border::CreateEmptyBorder(2, 2, 2, 4));
- const gfx::Insets kInsets(2, 2, 2, 4);
- views::View* contents = WrapWithPadding(label_, kInsets);
- SetContents(contents);
- contents->set_border(views::Border::CreateSolidBorder(
- 1,
- GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_MenuBorderColor)));
- contents->set_background(views::Background::CreateSolidBackground(
+ SetLayoutManager(new views::FillLayout());
+ AddChildView(label_);
+ set_background(views::Background::CreateSolidBackground(
color_utils::AlphaBlend(SK_ColorBLACK,
GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_WindowBackground),
0x10)));
- label_->SetBackgroundColor(contents->background()->get_color());
}
- // Set the displayed text.
+ // Sets the text alignment.
+ void SetAlignment(gfx::HorizontalAlignment alignment) {
+ label_->SetHorizontalAlignment(alignment);
+ }
+
+ // Sets the displayed text.
void SetText(const std::string& utf8_text) {
label_->SetText(base::UTF8ToUTF16(utf8_text));
}
+ // Sets the border thickness for top/bottom.
+ void SetBorder(BorderPosition position) {
+ set_border(views::Border::CreateSolidSidedBorder(
+ (position == TOP) ? 1 : 0, 0, (position == BOTTOM) ? 1 : 0, 0,
+ GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_MenuBorderColor)));
+ }
+
protected:
virtual gfx::Size GetPreferredSize() OVERRIDE {
- gfx::Size size = HidableArea::GetPreferredSize();
- // Hack. +2 is needed as the same reason as in VerticalCandidateLabel
- size.set_width(size.width() + 2);
- if (size.width() < minWidth_) {
- size.set_width(minWidth_);
- }
+ gfx::Size size = views::View::GetPreferredSize();
+ size.SetToMax(gfx::Size(min_width_, 0));
return size;
}
private:
views::Label* label_;
- int minWidth_;
+ int min_width_;
DISALLOW_COPY_AND_ASSIGN(InformationTextArea);
};
-CandidateView::CandidateView(
- CandidateWindowView* parent_candidate_window,
- int index_in_page,
- CandidateWindow::Orientation orientation)
- : index_in_page_(index_in_page),
- orientation_(orientation),
- parent_candidate_window_(parent_candidate_window),
- shortcut_label_(NULL),
- candidate_label_(NULL),
- annotation_label_(NULL),
- infolist_icon_(NULL),
- infolist_icon_enabled_(false) {
-}
-
-void CandidateView::Init(int shortcut_column_width,
- int candidate_column_width,
- int annotation_column_width,
- int column_height) {
- views::GridLayout* layout = new views::GridLayout(this);
- SetLayoutManager(layout); // |this| owns |layout|.
-
- // Create Labels.
- const ui::NativeTheme& theme = *GetNativeTheme();
- shortcut_label_ = CreateShortcutLabel(orientation_, theme);
- views::View* wrapped_shortcut_label =
- CreateWrappedShortcutLabel(shortcut_label_, orientation_, theme);
- candidate_label_ = CreateCandidateLabel(orientation_);
- annotation_label_ = CreateAnnotationLabel(orientation_, theme);
-
- // Initialize the column set with three columns.
- views::ColumnSet* column_set = layout->AddColumnSet(0);
-
- // If orientation is vertical, each column width is fixed.
- // Otherwise the width is resizable.
- const views::GridLayout::SizeType column_type =
- orientation_ == CandidateWindow::VERTICAL ?
- views::GridLayout::FIXED : views::GridLayout::USE_PREF;
-
- const int padding_column_width =
- orientation_ == CandidateWindow::VERTICAL ? 4 : 6;
-
- // Set shortcut column type and width.
- column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
- 0, column_type, shortcut_column_width, 0);
- column_set->AddPaddingColumn(0, padding_column_width);
-
- // Set candidate column type and width.
- column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
- 1, views::GridLayout::USE_PREF, 0,
- orientation_ == CandidateWindow::VERTICAL ?
- candidate_column_width : 0);
- column_set->AddPaddingColumn(0, padding_column_width);
-
- // Set annotation column type and width.
- column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
- 0, column_type, annotation_column_width, 0);
-
- if (orientation_ == CandidateWindow::VERTICAL) {
- column_set->AddPaddingColumn(0, 1);
- column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
- views::GridLayout::FIXED, kInfolistIndicatorIconWidth,
- 0);
- column_set->AddPaddingColumn(0, 2);
- } else {
- column_set->AddPaddingColumn(0, padding_column_width);
- }
-
- // Add the shortcut label, the candidate label, and annotation label.
- layout->StartRow(0, 0);
- // |wrapped_shortcut_label|, |candidate_label_|, and |annotation_label_|
- // will be owned by |this|.
- layout->AddView(wrapped_shortcut_label,
- 1, // Column span.
- 1, // Row span.
- views::GridLayout::FILL, // Horizontal alignment.
- views::GridLayout::FILL, // Vertical alignment.
- -1, // Preferred width, not specified.
- column_height); // Preferred height.
- layout->AddView(candidate_label_,
- 1, // Column span.
- 1, // Row span.
- views::GridLayout::FILL, // Horizontal alignment.
- views::GridLayout::FILL, // Vertical alignment.
- -1, // Preferred width, not specified.
- column_height); // Preferred height.
- layout->AddView(annotation_label_,
- 1, // Column span.
- 1, // Row span.
- views::GridLayout::FILL, // Horizontal alignment.
- views::GridLayout::FILL, // Vertical alignemnt.
- -1, // Preferred width, not specified.
- column_height); // Preferred height.
- if (orientation_ == CandidateWindow::VERTICAL) {
- infolist_icon_ = new views::View;
- views::View* infolist_icon_wrapper = new views::View;
- views::GridLayout* infolist_icon_layout =
- new views::GridLayout(infolist_icon_wrapper);
- // |infolist_icon_layout| is owned by |infolist_icon_wrapper|.
- infolist_icon_wrapper->SetLayoutManager(infolist_icon_layout);
- infolist_icon_layout->AddColumnSet(0)->AddColumn(
- views::GridLayout::FILL, views::GridLayout::FILL,
- 0, views::GridLayout::FIXED, kInfolistIndicatorIconWidth, 0);
- infolist_icon_layout->AddPaddingRow(0, kInfolistIndicatorIconPadding);
- infolist_icon_layout->StartRow(1.0, 0); // infolist_icon_ is resizable.
- // |infolist_icon_| is owned by |infolist_icon_wrapper|.
- infolist_icon_layout->AddView(infolist_icon_);
- infolist_icon_layout->AddPaddingRow(0, kInfolistIndicatorIconPadding);
- // |infolist_icon_wrapper| is owned by |this|.
- layout->AddView(infolist_icon_wrapper);
- }
- UpdateLabelBackgroundColors();
-}
-
-void CandidateView::SetCandidateText(const base::string16& text) {
- candidate_label_->SetText(text);
-}
-
-void CandidateView::SetShortcutText(const base::string16& text) {
- shortcut_label_->SetText(text);
-}
-
-void CandidateView::SetAnnotationText(const base::string16& text) {
- annotation_label_->SetText(text);
-}
-
-void CandidateView::SetInfolistIcon(bool enable) {
- if (!infolist_icon_ || (infolist_icon_enabled_ == enable))
- return;
- infolist_icon_enabled_ = enable;
- infolist_icon_->set_background(
- enable ?
- views::Background::CreateSolidBackground(GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_FocusedBorderColor)) :
- NULL);
- UpdateLabelBackgroundColors();
- SchedulePaint();
-}
-
-void CandidateView::Select() {
- set_background(
- views::Background::CreateSolidBackground(GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused)));
- set_border(views::Border::CreateSolidBorder(
- 1, GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_FocusedBorderColor)));
- UpdateLabelBackgroundColors();
- // Need to call SchedulePaint() for background and border color changes.
- SchedulePaint();
-}
-
-void CandidateView::Unselect() {
- set_background(NULL);
- set_border(NULL);
- UpdateLabelBackgroundColors();
- SchedulePaint(); // See comments at Select().
-}
-
-void CandidateView::SetRowEnabled(bool enabled) {
- shortcut_label_->SetEnabled(enabled);
-}
-
-gfx::Point CandidateView::GetCandidateLabelPosition() const {
- return candidate_label_->GetMirroredPosition();
-}
-
-bool CandidateView::OnMousePressed(const ui::MouseEvent& event) {
- // TODO(kinaba): On Windows and MacOS, candidate windows typically commits a
- // candidate at OnMouseReleased event. We have chosen OnMousePressed here for
- // working around several obstacle rising from views implementation over GTK.
- // See: http://crosbug.com/11423#c11. Since we have moved from GTK to Aura,
- // the reasoning should have became obsolete. We might want to reconsider
- // implementing mouse-up selection.
- SelectCandidateAt(event.location());
- return false;
-}
-
-void CandidateView::OnGestureEvent(ui::GestureEvent* event) {
- if (event->type() == ui::ET_GESTURE_TAP) {
- SelectCandidateAt(event->location());
- event->SetHandled();
- return;
- }
- View::OnGestureEvent(event);
-}
-
-void CandidateView::SelectCandidateAt(const gfx::Point& location) {
- gfx::Point location_in_candidate_window = location;
- views::View::ConvertPointToTarget(this, parent_candidate_window_,
- &location_in_candidate_window);
- parent_candidate_window_->OnCandidatePressed(location_in_candidate_window);
- parent_candidate_window_->CommitCandidate();
-}
-
-void CandidateView::UpdateLabelBackgroundColors() {
- SkColor color = background() ?
- background()->get_color() :
- GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_WindowBackground);
- if (orientation_ != CandidateWindow::VERTICAL)
- shortcut_label_->SetBackgroundColor(color);
- candidate_label_->SetBackgroundColor(color);
- annotation_label_->SetBackgroundColor(color);
-}
-
-CandidateWindowView::CandidateWindowView(views::Widget* parent_frame)
+CandidateWindowView::CandidateWindowView(gfx::NativeView parent)
: selected_candidate_index_in_page_(-1),
- parent_frame_(parent_frame),
- preedit_area_(NULL),
- header_area_(NULL),
- candidate_area_(NULL),
- footer_area_(NULL),
- previous_shortcut_column_size_(0, 0),
- previous_candidate_column_size_(0, 0),
- previous_annotation_column_size_(0, 0),
should_show_at_composition_head_(false),
should_show_upper_side_(false),
was_candidate_window_open_(false) {
-}
-
-CandidateWindowView::~CandidateWindowView() {
-}
+ set_parent_window(parent);
+ set_margins(gfx::Insets());
-void CandidateWindowView::Init() {
// Set the background and the border of the view.
+ ui::NativeTheme* theme = GetNativeTheme();
set_background(
- views::Background::CreateSolidBackground(GetNativeTheme()->GetSystemColor(
+ views::Background::CreateSolidBackground(theme->GetSystemColor(
ui::NativeTheme::kColorId_WindowBackground)));
set_border(views::Border::CreateSolidBorder(
- 1, GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_MenuBorderColor)));
-
- // Create areas.
- preedit_area_ = new InformationTextArea(gfx::ALIGN_LEFT,
- kMinPreeditAreaWidth);
- header_area_ = new InformationTextArea(gfx::ALIGN_LEFT, 0);
- candidate_area_ = new HidableArea;
- candidate_area_->SetContents(new views::View);
- footer_area_ = new InformationTextArea(gfx::ALIGN_RIGHT, 0);
-
- // Set the window layout of the view
- views::GridLayout* layout = new views::GridLayout(this);
- SetLayoutManager(layout); // |this| owns |layout|.
- views::ColumnSet* column_set = layout->AddColumnSet(0);
- column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
- 0, views::GridLayout::USE_PREF, 0, 0);
-
- // Add the preedit area
- layout->StartRow(0, 0);
- layout->AddView(preedit_area_); // |preedit_area_| is owned by |this|.
+ 1, theme->GetSystemColor(ui::NativeTheme::kColorId_MenuBorderColor)));
+
+ SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
+ auxiliary_text_ = new InformationTextArea(gfx::ALIGN_RIGHT, 0);
+ preedit_ = new InformationTextArea(gfx::ALIGN_LEFT, kMinPreeditAreaWidth);
+ candidate_area_ = new views::View;
+ auxiliary_text_->SetVisible(false);
+ preedit_->SetVisible(false);
+ candidate_area_->SetVisible(false);
+ preedit_->SetBorder(InformationTextArea::BOTTOM);
+ if (candidate_window_.orientation() == CandidateWindow::VERTICAL) {
+ AddChildView(preedit_);
+ AddChildView(candidate_area_);
+ AddChildView(auxiliary_text_);
+ auxiliary_text_->SetBorder(InformationTextArea::TOP);
+ candidate_area_->SetLayoutManager(new views::BoxLayout(
+ views::BoxLayout::kVertical, 0, 0, 0));
+ } else {
+ AddChildView(preedit_);
+ AddChildView(auxiliary_text_);
+ AddChildView(candidate_area_);
+ auxiliary_text_->SetAlignment(gfx::ALIGN_LEFT);
+ auxiliary_text_->SetBorder(InformationTextArea::BOTTOM);
+ candidate_area_->SetLayoutManager(new views::BoxLayout(
+ views::BoxLayout::kHorizontal, 0, 0, 0));
+ }
+}
- // Add the header area.
- layout->StartRow(0, 0);
- layout->AddView(header_area_); // |header_area_| is owned by |this|.
+CandidateWindowView::~CandidateWindowView() {
+}
- // Add the candidate area.
- layout->StartRow(0, 0);
- layout->AddView(candidate_area_); // |candidate_area_| is owned by |this|.
+views::Widget* CandidateWindowView::InitWidget() {
+ views::Widget* widget = BubbleDelegateView::CreateBubble(this);
- // Add the footer area.
- layout->StartRow(0, 0);
- layout->AddView(footer_area_); // |footer_area_| is owned by |this|.
-}
+ views::corewm::SetWindowVisibilityAnimationType(
+ widget->GetNativeView(),
+ views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
-void CandidateWindowView::HideAll() {
- parent_frame_->Hide();
- NotifyIfCandidateWindowOpenedOrClosed();
+ GetBubbleFrameView()->SetBubbleBorder(
+ new CandidateWindowBorder(parent_window()));
+ return widget;
}
-void CandidateWindowView::UpdateParentArea() {
- if (candidate_area_->IsShown() ||
- header_area_->IsShown() ||
- footer_area_->IsShown() ||
- preedit_area_->IsShown()) {
- ResizeAndMoveParentFrame();
- parent_frame_->Show();
+void CandidateWindowView::UpdateVisibility() {
+ if (candidate_area_->visible() || auxiliary_text_->visible() ||
+ preedit_->visible()) {
+ SizeToContents();
} else {
- parent_frame_->Hide();
+ GetWidget()->Close();
}
- NotifyIfCandidateWindowOpenedOrClosed();
}
void CandidateWindowView::HideLookupTable() {
- candidate_area_->Hide();
- header_area_->Hide();
- footer_area_->Hide();
- UpdateParentArea();
+ candidate_area_->SetVisible(false);
+ UpdateVisibility();
}
void CandidateWindowView::HidePreeditText() {
- preedit_area_->Hide();
- UpdateParentArea();
+ preedit_->SetVisible(false);
+ UpdateVisibility();
}
void CandidateWindowView::ShowPreeditText() {
- preedit_area_->Show();
- UpdateParentArea();
+ preedit_->SetVisible(true);
+ UpdateVisibility();
}
void CandidateWindowView::UpdatePreeditText(const std::string& utf8_text) {
- preedit_area_->SetText(utf8_text);
+ preedit_->SetText(utf8_text);
}
void CandidateWindowView::ShowLookupTable() {
- if (!candidate_area_->IsShown())
- should_show_upper_side_ = false;
- candidate_area_->Show();
-
- // Show auxiliary text.
- if (!candidate_window_.is_auxiliary_text_visible()) {
- header_area_->Hide();
- footer_area_->Hide();
- } else if (candidate_window_.orientation() == CandidateWindow::HORIZONTAL) {
- header_area_->Show();
- footer_area_->Hide();
- } else {
- header_area_->Hide();
- footer_area_->Show();
- }
-
- UpdateParentArea();
-}
-
-void CandidateWindowView::NotifyIfCandidateWindowOpenedOrClosed() {
- bool is_open = IsCandidateWindowOpen();
- if (!was_candidate_window_open_ && is_open) {
- FOR_EACH_OBSERVER(Observer, observers_, OnCandidateWindowOpened());
- } else if (was_candidate_window_open_ && !is_open) {
- FOR_EACH_OBSERVER(Observer, observers_, OnCandidateWindowClosed());
- }
- was_candidate_window_open_ = is_open;
-}
-
-bool CandidateWindowView::ShouldUpdateCandidateViews(
- const CandidateWindow& old_candidate_window,
- const CandidateWindow& new_candidate_window) {
- return !old_candidate_window.IsEqual(new_candidate_window);
+ candidate_area_->SetVisible(true);
+ auxiliary_text_->SetVisible(candidate_window_.is_auxiliary_text_visible());
+ UpdateVisibility();
}
void CandidateWindowView::UpdateCandidates(
const CandidateWindow& new_candidate_window) {
- const bool should_update = ShouldUpdateCandidateViews(candidate_window_,
- new_candidate_window);
// Updating the candidate views is expensive. We'll skip this if possible.
- if (should_update) {
+ if (!candidate_window_.IsEqual(new_candidate_window)) {
+ if (candidate_window_.orientation() != new_candidate_window.orientation()) {
+ // If the new layout is vertical, the aux text should appear at the
+ // bottom. If horizontal, it should appear between preedit and candidates.
+ if (new_candidate_window.orientation() == CandidateWindow::VERTICAL) {
+ ReorderChildView(auxiliary_text_, -1);
+ auxiliary_text_->SetAlignment(gfx::ALIGN_RIGHT);
+ auxiliary_text_->SetBorder(InformationTextArea::TOP);
+ candidate_area_->SetLayoutManager(new views::BoxLayout(
+ views::BoxLayout::kVertical, 0, 0, 0));
+ } else {
+ ReorderChildView(auxiliary_text_, 1);
+ auxiliary_text_->SetAlignment(gfx::ALIGN_LEFT);
+ auxiliary_text_->SetBorder(InformationTextArea::BOTTOM);
+ candidate_area_->SetLayoutManager(new views::BoxLayout(
+ views::BoxLayout::kHorizontal, 0, 0, 0));
+ }
+ }
+
// Initialize candidate views if necessary.
MaybeInitializeCandidateViews(new_candidate_window);
@@ -693,57 +260,52 @@ void CandidateWindowView::UpdateCandidates(
= new_candidate_window.show_window_at_composition();
// Compute the index of the current page.
const int current_page_index = ComputePageIndex(new_candidate_window);
- if (current_page_index < 0) {
+ if (current_page_index < 0)
return;
- }
// Update the candidates in the current page.
const size_t start_from =
current_page_index * new_candidate_window.page_size();
- // In some cases, engines send empty shortcut labels. For instance,
- // ibus-mozc sends empty labels when they show suggestions. In this
- // case, we should not show shortcut labels.
- bool no_shortcut_mode = true;
- for (size_t i = 0; i < new_candidate_window.candidates().size(); ++i) {
- if (!new_candidate_window.candidates()[i].label.empty()) {
- no_shortcut_mode = false;
- break;
- }
- }
-
+ int max_shortcut_width = 0;
+ int max_candidate_width = 0;
for (size_t i = 0; i < candidate_views_.size(); ++i) {
const size_t index_in_page = i;
const size_t candidate_index = start_from + index_in_page;
CandidateView* candidate_view = candidate_views_[index_in_page];
- // Set the shortcut text.
- if (no_shortcut_mode) {
- candidate_view->SetShortcutText(base::string16());
- } else {
- // At this moment, we don't use labels sent from engines for UX
- // reasons. First, we want to show shortcut labels in empty rows
- // (ex. show 6, 7, 8, ... in empty rows when the number of
- // candidates is 5). Second, we want to add a period after each
- // shortcut label when the candidate window is horizontal.
- candidate_view->SetShortcutText(
- CreateShortcutText(i, new_candidate_window));
- }
// Set the candidate text.
- if (candidate_index < new_candidate_window.candidates().size()) {
- const CandidateWindow::Entry& entry =
- new_candidate_window.candidates()[candidate_index];
- candidate_view->SetCandidateText(base::UTF8ToUTF16(entry.value));
- candidate_view->SetAnnotationText(base::UTF8ToUTF16(entry.annotation));
- candidate_view->SetRowEnabled(true);
- candidate_view->SetInfolistIcon(!entry.description_title.empty());
+ if (candidate_index < new_candidate_window.candidates().size()) {
+ const CandidateWindow::Entry& entry =
+ new_candidate_window.candidates()[candidate_index];
+ candidate_view->SetEntry(entry);
+ candidate_view->SetState(views::Button::STATE_NORMAL);
+ candidate_view->SetInfolistIcon(!entry.description_title.empty());
} else {
// Disable the empty row.
- candidate_view->SetCandidateText(base::string16());
- candidate_view->SetAnnotationText(base::string16());
- candidate_view->SetRowEnabled(false);
+ candidate_view->SetEntry(CandidateWindow::Entry());
+ candidate_view->SetState(views::Button::STATE_DISABLED);
candidate_view->SetInfolistIcon(false);
}
+ if (new_candidate_window.orientation() == CandidateWindow::VERTICAL) {
+ int shortcut_width = 0;
+ int candidate_width = 0;
+ candidate_views_[i]->GetPreferredWidths(
+ &shortcut_width, &candidate_width);
+ max_shortcut_width = std::max(max_shortcut_width, shortcut_width);
+ max_candidate_width = std::max(max_candidate_width, candidate_width);
+ }
+ }
+ if (new_candidate_window.orientation() == CandidateWindow::VERTICAL) {
+ for (size_t i = 0; i < candidate_views_.size(); ++i)
+ candidate_views_[i]->SetWidths(max_shortcut_width, max_candidate_width);
}
+
+ CandidateWindowBorder* border = static_cast<CandidateWindowBorder*>(
+ GetBubbleFrameView()->bubble_border());
+ if (new_candidate_window.orientation() == CandidateWindow::VERTICAL)
+ border->set_offset(max_shortcut_width);
+ else
+ border->set_offset(0);
}
// Update the current candidate window. We'll use candidate_window_ from here.
// Note that SelectCandidateAt() uses candidate_window_.
@@ -761,142 +323,44 @@ 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_]->Unselect();
+ candidate_views_[selected_candidate_index_in_page_]->SetState(
+ views::Button::STATE_NORMAL);
selected_candidate_index_in_page_ = -1;
}
}
// Updates auxiliary text
- if (candidate_window_.is_auxiliary_text_visible()) {
- header_area_->SetText(candidate_window_.auxiliary_text());
- footer_area_->SetText(candidate_window_.auxiliary_text());
- }
+ auxiliary_text_->SetVisible(candidate_window_.is_auxiliary_text_visible());
+ auxiliary_text_->SetText(candidate_window_.auxiliary_text());
+}
+
+void CandidateWindowView::SetCursorBounds(const gfx::Rect& cursor_bounds,
+ const gfx::Rect& composition_head) {
+ if (candidate_window_.show_window_at_composition())
+ SetAnchorRect(composition_head);
+ else
+ SetAnchorRect(cursor_bounds);
}
void CandidateWindowView::MaybeInitializeCandidateViews(
const CandidateWindow& candidate_window) {
const CandidateWindow::Orientation orientation =
candidate_window.orientation();
- const int page_size = candidate_window.page_size();
- views::View* candidate_area_contents = candidate_area_->contents();
-
- // Current column width.
- gfx::Size shortcut_column_size(0, 0);
- gfx::Size candidate_column_size(0,0);
- gfx::Size annotation_column_size(0, 0);
-
- // If orientation is horizontal, don't need to compute width,
- // because each label is left aligned.
- if (orientation == CandidateWindow::VERTICAL) {
- const ui::NativeTheme& theme = *GetNativeTheme();
- shortcut_column_size = ComputeShortcutColumnSize(candidate_window, theme);
- candidate_column_size = ComputeCandidateColumnSize(candidate_window);
- annotation_column_size = ComputeAnnotationColumnSize(candidate_window,
- theme);
- }
-
- // If the requested number of views matches the number of current views, and
- // previous and current column width are same, just reuse these.
- //
- // Note that the early exit logic is not only useful for improving
- // performance, but also necessary for the horizontal candidate window
- // to be redrawn properly. If we get rid of the logic, the horizontal
- // candidate window won't get redrawn properly for some reason when
- // there is no size change. You can test this by removing "return" here
- // and type "ni" with Pinyin input method.
- if (static_cast<int>(candidate_views_.size()) == page_size &&
- candidate_window_.orientation() == orientation &&
- previous_shortcut_column_size_ == shortcut_column_size &&
- previous_candidate_column_size_ == candidate_column_size &&
- previous_annotation_column_size_ == annotation_column_size) {
- return;
- }
-
- // Update the previous column widths.
- previous_shortcut_column_size_ = shortcut_column_size;
- previous_candidate_column_size_ = candidate_column_size;
- previous_annotation_column_size_ = annotation_column_size;
-
- // Clear the existing candidate_views if any.
- for (size_t i = 0; i < candidate_views_.size(); ++i) {
- candidate_area_contents->RemoveChildView(candidate_views_[i]);
- // Delete the view after getting out the current message loop iteration.
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, candidate_views_[i]);
- }
- candidate_views_.clear();
- selected_candidate_index_in_page_ = -1; // Invalidates the index.
-
- views::GridLayout* layout = new views::GridLayout(candidate_area_contents);
- // |candidate_area_contents| owns |layout|.
- candidate_area_contents->SetLayoutManager(layout);
- // Initialize the column set.
- views::ColumnSet* column_set = layout->AddColumnSet(0);
- if (orientation == CandidateWindow::VERTICAL) {
- column_set->AddColumn(views::GridLayout::FILL,
- views::GridLayout::FILL,
- 1, views::GridLayout::USE_PREF, 0, 0);
- } else {
- for (int i = 0; i < page_size; ++i) {
- column_set->AddColumn(views::GridLayout::FILL,
- views::GridLayout::FILL,
- 0, views::GridLayout::USE_PREF, 0, 0);
- }
- }
+ const size_t page_size = candidate_window.page_size();
- // Set insets so the border of the selected candidate is drawn inside of
- // the border of the main candidate window, but we don't have the inset
- // at the top and the bottom as we have the borders of the header and
- // footer areas.
- const gfx::Insets kCandidateAreaInsets(0, 1, 0, 1);
- layout->SetInsets(kCandidateAreaInsets.top(),
- kCandidateAreaInsets.left(),
- kCandidateAreaInsets.bottom(),
- kCandidateAreaInsets.right());
+ // Reset all candidate_views_ when orientation changes.
+ if (orientation != candidate_window_.orientation())
+ STLDeleteElements(&candidate_views_);
- // Use maximum height for all rows in candidate area.
- const int kColumnHeight = std::max(shortcut_column_size.height(),
- std::max(candidate_column_size.height(),
- annotation_column_size.height()));
-
- // Add views to the candidate area.
- if (orientation == CandidateWindow::HORIZONTAL) {
- layout->StartRow(0, 0);
+ while (page_size < candidate_views_.size()) {
+ delete candidate_views_.back();
+ candidate_views_.pop_back();
}
-
- for (int i = 0; i < page_size; ++i) {
- CandidateView* candidate_row = new CandidateView(this, i, orientation);
- candidate_row->Init(shortcut_column_size.width(),
- candidate_column_size.width(),
- annotation_column_size.width(),
- kColumnHeight);
- candidate_views_.push_back(candidate_row);
- if (orientation == CandidateWindow::VERTICAL) {
- layout->StartRow(0, 0);
- }
- // |candidate_row| will be owned by |candidate_area_contents|.
- layout->AddView(candidate_row,
- 1, // Column span.
- 1, // Row span.
- // Horizontal alignment.
- orientation == CandidateWindow::VERTICAL ?
- views::GridLayout::FILL : views::GridLayout::CENTER,
- views::GridLayout::CENTER, // Vertical alignment.
- -1, // Preferred width, not specified.
- kColumnHeight); // Preferred height.
+ while (page_size > candidate_views_.size()) {
+ CandidateView* new_candidate = new CandidateView(this, orientation);
+ candidate_area_->AddChildView(new_candidate);
+ candidate_views_.push_back(new_candidate);
}
-
- // Compute views size in |layout|.
- // If we don't call this function, GetHorizontalOffset() often
- // returns invalid value (returns 0), then candidate window
- // moves right from the correct position in ResizeAndMoveParentFrame().
- // TODO(nhiroki): Figure out why it returns invalid value.
- // It seems that the x-position of the candidate labels is not set.
- layout->Layout(candidate_area_contents);
-}
-
-bool CandidateWindowView::IsCandidateWindowOpen() const {
- return !should_show_at_composition_head_ &&
- candidate_area_->visible() && candidate_area_->IsShown();
}
void CandidateWindowView::SelectCandidateAt(int index_in_page) {
@@ -914,123 +378,25 @@ void CandidateWindowView::SelectCandidateAt(int index_in_page) {
return;
}
- // Unselect the currently selected candidate.
- 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_]->Unselect();
- }
// Remember the currently selected candidate index in the current page.
selected_candidate_index_in_page_ = index_in_page;
// Select the candidate specified by index_in_page.
- candidate_views_[index_in_page]->Select();
+ candidate_views_[index_in_page]->SetState(views::Button::STATE_PRESSED);
// Update the cursor indexes in the model.
candidate_window_.set_cursor_position(cursor_absolute_index);
}
-void CandidateWindowView::OnCandidatePressed(
- const gfx::Point& location) {
+void CandidateWindowView::ButtonPressed(views::Button* sender,
+ const ui::Event& event) {
for (size_t i = 0; i < candidate_views_.size(); ++i) {
- gfx::Point converted_location = location;
- views::View::ConvertPointToTarget(this, candidate_views_[i],
- &converted_location);
- if (candidate_views_[i]->HitTestPoint(converted_location)) {
- SelectCandidateAt(i);
- break;
+ if (sender == candidate_views_[i]) {
+ FOR_EACH_OBSERVER(Observer, observers_, OnCandidateCommitted(i));
+ return;
}
}
}
-void CandidateWindowView::CommitCandidate() {
- if (!(0 <= selected_candidate_index_in_page_ &&
- static_cast<size_t>(selected_candidate_index_in_page_) <
- candidate_views_.size())) {
- return; // Out of range, do nothing.
- }
-
- FOR_EACH_OBSERVER(Observer, observers_,
- OnCandidateCommitted(selected_candidate_index_in_page_));
-}
-
-void CandidateWindowView::ResizeAndMoveParentFrame() {
- // If rendering operation comes from mozc-engine, uses mozc specific bounds,
- // otherwise candidate window is shown under the cursor.
- const int x = should_show_at_composition_head_?
- composition_head_bounds_.x() : cursor_bounds_.x();
- // To avoid candidate-window overlapping, uses maximum y-position of mozc
- // specific bounds and cursor bounds, because mozc-engine does not
- // consider about multi-line composition.
- const int y = should_show_at_composition_head_?
- std::max(composition_head_bounds_.y(), cursor_bounds_.y()) :
- cursor_bounds_.y();
- const int height = cursor_bounds_.height();
- const int horizontal_offset = GetHorizontalOffset();
-
- gfx::Rect old_bounds = parent_frame_->GetClientAreaBoundsInScreen();
- gfx::Rect screen_bounds = ash::Shell::GetScreen()->GetDisplayMatching(
- cursor_bounds_).work_area();
- // The size.
- gfx::Rect frame_bounds = old_bounds;
- frame_bounds.set_size(GetPreferredSize());
-
- // The default position.
- frame_bounds.set_x(x + horizontal_offset);
- frame_bounds.set_y(y + height);
-
- // Handle overflow at the left and the top.
- frame_bounds.set_x(std::max(frame_bounds.x(), screen_bounds.x()));
- frame_bounds.set_y(std::max(frame_bounds.y(), screen_bounds.y()));
-
- // Handle overflow at the right.
- const int right_overflow = frame_bounds.right() - screen_bounds.right();
- if (right_overflow > 0) {
- frame_bounds.set_x(frame_bounds.x() - right_overflow);
- }
-
- // Handle overflow at the bottom.
- const int bottom_overflow = frame_bounds.bottom() - screen_bounds.bottom();
-
- // To avoid flickering window position, the candidate window should be shown
- // on upper side of composition string if it was shown there.
- if (should_show_upper_side_ || bottom_overflow > 0) {
- frame_bounds.set_y(frame_bounds.y() - height - frame_bounds.height());
- should_show_upper_side_ = true;
- }
-
- // TODO(nona): check top_overflow here.
-
- // Move the window per the cursor bounds.
- // SetBounds() is not cheap. Only call this when it is really changed.
- if (frame_bounds != old_bounds)
- parent_frame_->SetBounds(frame_bounds);
-}
-
-int CandidateWindowView::GetHorizontalOffset() {
- // Compute the horizontal offset if the candidate window is vertical.
- if (!candidate_views_.empty() &&
- candidate_window_.orientation() == CandidateWindow::VERTICAL) {
- return - candidate_views_[0]->GetCandidateLabelPosition().x();
- }
- return 0;
-}
-
-void CandidateWindowView::VisibilityChanged(View* starting_from,
- bool is_visible) {
- if (is_visible) {
- // If the visibility of candidate window is changed,
- // we should move the frame to the right position.
- ResizeAndMoveParentFrame();
- }
-}
-
-void CandidateWindowView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
- // If the bounds(size) of candidate window is changed,
- // we should move the frame to the right position.
- View::OnBoundsChanged(previous_bounds);
- ResizeAndMoveParentFrame();
-}
-
} // namespace input_method
} // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/candidate_window_view.h b/chrome/browser/chromeos/input_method/candidate_window_view.h
index dc69f75..f5848f1 100644
--- a/chrome/browser/chromeos/input_method/candidate_window_view.h
+++ b/chrome/browser/chromeos/input_method/candidate_window_view.h
@@ -5,25 +5,19 @@
#ifndef CHROME_BROWSER_CHROMEOS_INPUT_METHOD_CANDIDATE_WINDOW_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_INPUT_METHOD_CANDIDATE_WINDOW_VIEW_H_
-#include "base/gtest_prod_util.h"
-#include "base/memory/scoped_ptr.h"
#include "chromeos/ime/candidate_window.h"
-#include "ui/views/view.h"
-
-namespace gfx {
-class Font;
-}
+#include "ui/views/bubble/bubble_delegate.h"
+#include "ui/views/controls/button/button.h"
namespace chromeos {
namespace input_method {
class CandidateView;
-class CandidateWindow;
-class HidableArea;
class InformationTextArea;
// CandidateWindowView is the main container of the candidate window UI.
-class CandidateWindowView : public views::View {
+class CandidateWindowView : public views::BubbleDelegateView,
+ public views::ButtonListener {
public:
// The object can be monitored by the observer.
class Observer {
@@ -31,14 +25,11 @@ class CandidateWindowView : public views::View {
virtual ~Observer() {}
// The function is called when a candidate is committed.
virtual void OnCandidateCommitted(int index) = 0;
-
- virtual void OnCandidateWindowOpened() = 0;
- virtual void OnCandidateWindowClosed() = 0;
};
- explicit CandidateWindowView(views::Widget* parent_frame);
+ explicit CandidateWindowView(gfx::NativeView parent);
virtual ~CandidateWindowView();
- void Init();
+ views::Widget* InitWidget();
// Adds the given observer. The ownership is not transferred.
void AddObserver(Observer* observer) {
@@ -50,19 +41,6 @@ class CandidateWindowView : public views::View {
observers_.RemoveObserver(observer);
}
- // Selects the candidate specified by the index in the current page
- // (zero-origin). Changes the appearance of the selected candidate,
- // updates the information in the candidate window as needed.
- void SelectCandidateAt(int index_in_page);
-
- // The function is called when a candidate is being dragged. From the
- // given point, locates the candidate under the mouse cursor, and
- // selects it.
- void OnCandidatePressed(const gfx::Point& point);
-
- // Commits the candidate currently being selected.
- void CommitCandidate();
-
// Hides the lookup table.
void HideLookupTable();
@@ -72,9 +50,6 @@ class CandidateWindowView : public views::View {
// Hides the preedit text.
void HidePreeditText();
- // Hides whole the candidate window.
- void HideAll();
-
// Shows the lookup table.
void ShowLookupTable();
@@ -87,83 +62,27 @@ class CandidateWindowView : public views::View {
// Updates the preedit text.
void UpdatePreeditText(const std::string& utf8_text);
- // Returns true if we should update candidate views in the window. For
- // instance, if we are going to show the same candidates as before, we
- // don't have to update candidate views. This happens when the user just
- // moves the cursor in the same page in the candidate window.
- static bool ShouldUpdateCandidateViews(
- const CandidateWindow& old_candidate_window,
- const CandidateWindow& new_candidate_window);
-
// Updates candidates of the candidate window from |candidate_window|.
// Candidates are arranged per |orientation|.
void UpdateCandidates(const CandidateWindow& candidate_window);
- // Resizes and moves the parent frame. The two actions should be
- // performed consecutively as resizing may require the candidate window
- // to move. For instance, we may need to move the candidate window from
- // below the cursor to above the cursor, if the candidate window becomes
- // too big to be shown near the bottom of the screen. This function
- // needs to be called when the visible contents of the candidate window
- // are modified.
- void ResizeAndMoveParentFrame();
-
- // Returns the horizontal offset used for placing the vertical candidate
- // window so that the first candidate is aligned with the the text being
- // converted like:
- //
- // XXX <- The user is converting XXX
- // +-----+
- // |1 XXX|
- // |2 YYY|
- // |3 ZZZ|
- //
- // Returns 0 if no candidate is present.
- int GetHorizontalOffset();
-
- void set_cursor_bounds(const gfx::Rect& cursor_bounds) {
- cursor_bounds_ = cursor_bounds;
- }
-
- void set_composition_head_bounds(
- const gfx::Rect& composition_head_bounds) {
- composition_head_bounds_ = composition_head_bounds;
- }
+ void SetCursorBounds(const gfx::Rect& cursor_bounds,
+ const gfx::Rect& composition_head);
- const gfx::Rect& cursor_bounds() const { return cursor_bounds_; }
- const gfx::Rect& composition_head_bounds() const {
- return composition_head_bounds_;
- }
-
- protected:
- // Override View::VisibilityChanged()
- virtual void VisibilityChanged(View* starting_from, bool is_visible) OVERRIDE;
+ private:
+ friend class CandidateWindowViewTest;
- // Override View::OnBoundsChanged()
- virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
+ // Overridden from views::ButtonListener:
+ virtual void ButtonPressed(views::Button* sender,
+ const ui::Event& event) OVERRIDE;
- private:
- FRIEND_TEST_ALL_PREFIXES(CandidateWindowViewTest,
- UpdateCandidatesTest_CursorVisibility);
- FRIEND_TEST_ALL_PREFIXES(CandidateWindowViewTest, ShortcutSettingTest);
- FRIEND_TEST_ALL_PREFIXES(CandidateWindowViewTest,
- DoNotChangeRowHeightWithLabelSwitchTest);
+ void SelectCandidateAt(int index_in_page);
+ void UpdateVisibility();
// Initializes the candidate views if needed.
void MaybeInitializeCandidateViews(const CandidateWindow& candidate_window);
- // Returns the appropriate area (header or footer) to put auxiliary texts.
- InformationTextArea* GetAuxiliaryTextArea();
-
- // Returns true if the candidate window is open. The suggestion window does
- // not count as the candidate window.
- bool IsCandidateWindowOpen() const;
-
- // Notifies observers if the candidate window's opened/closed state has
- // changed from the previous call to this function.
- void NotifyIfCandidateWindowOpenedOrClosed();
-
- // The candidate window.
+ // The candidate window data model.
CandidateWindow candidate_window_;
// The index in the current page of the candidate currently being selected.
@@ -172,28 +91,14 @@ class CandidateWindowView : public views::View {
// The observers of the object.
ObserverList<Observer> observers_;
- // The parent frame.
- views::Widget* parent_frame_;
-
// Views created in the class will be part of tree of |this|, so these
// child views will be deleted when |this| is deleted.
+ InformationTextArea* auxiliary_text_;
+ InformationTextArea* preedit_;
+ views::View* candidate_area_;
- // The preedit area is where the preedit text is shown, if it is needed
- // in cases such as the focus is on a plugin that doesn't support in-line
- // preedit drawing.
- InformationTextArea* preedit_area_;
- // The header area is where the auxiliary text is shown, if the
- // orientation is horizontal. If the auxiliary text is not provided, we
- // show nothing. For instance, we show pinyin text like "zhong'guo".
- InformationTextArea* header_area_;
- // The candidate area is where candidates are rendered.
- HidableArea* candidate_area_;
// The candidate views are used for rendering candidates.
std::vector<CandidateView*> candidate_views_;
- // The footer area is where the auxiliary text is shown, if the
- // orientation is vertical. Usually the auxiliary text is used for
- // showing candidate number information like 2/19.
- InformationTextArea* footer_area_;
// Current columns size in |candidate_area_|.
gfx::Size previous_shortcut_column_size_;
@@ -218,10 +123,6 @@ class CandidateWindowView : public views::View {
// send OnCandidateWindowOpened and OnCandidateWindowClosed events.
bool was_candidate_window_open_;
- // This function judge whether the candidate window should be shown or not,
- // if should be, shows parent_frame and if not, hides parent_frame.
- void UpdateParentArea();
-
DISALLOW_COPY_AND_ASSIGN(CandidateWindowView);
};
diff --git a/chrome/browser/chromeos/input_method/candidate_window_view_unittest.cc b/chrome/browser/chromeos/input_method/candidate_window_view_unittest.cc
index dbd8915..f63d7d6 100644
--- a/chrome/browser/chromeos/input_method/candidate_window_view_unittest.cc
+++ b/chrome/browser/chromeos/input_method/candidate_window_view_unittest.cc
@@ -63,7 +63,41 @@ void InitCandidateWindowWithCandidatesFilled(
} // namespace
class CandidateWindowViewTest : public views::ViewsTestBase {
+ public:
+ CandidateWindowViewTest() {}
+ virtual ~CandidateWindowViewTest() {}
+
protected:
+ virtual void SetUp() {
+ views::ViewsTestBase::SetUp();
+ candidate_window_view_ = new CandidateWindowView(GetContext());
+ candidate_window_view_->InitWidget();
+ }
+
+ CandidateWindowView* candidate_window_view() {
+ return candidate_window_view_;
+ }
+
+ int selected_candidate_index_in_page() {
+ return candidate_window_view_->selected_candidate_index_in_page_;
+ }
+
+ size_t GetCandidatesSize() const {
+ return candidate_window_view_->candidate_views_.size();
+ }
+
+ CandidateView* GetCandidateAt(size_t i) {
+ return candidate_window_view_->candidate_views_[i];
+ }
+
+ void SelectCandidateAt(int index_in_page) {
+ candidate_window_view_->SelectCandidateAt(index_in_page);
+ }
+
+ void MaybeInitializeCandidateViews(const CandidateWindow& candidate_window) {
+ candidate_window_view_->MaybeInitializeCandidateViews(candidate_window);
+ }
+
void ExpectLabels(const std::string& shortcut,
const std::string& candidate,
const std::string& annotation,
@@ -72,61 +106,50 @@ class CandidateWindowViewTest : public views::ViewsTestBase {
EXPECT_EQ(candidate, base::UTF16ToUTF8(row->candidate_label_->text()));
EXPECT_EQ(annotation, base::UTF16ToUTF8(row->annotation_label_->text()));
}
-};
-TEST_F(CandidateWindowViewTest, UpdateCandidatesTest_CursorVisibility) {
- views::Widget* widget = new views::Widget;
- views::Widget::InitParams params =
- CreateParams(views::Widget::InitParams::TYPE_WINDOW);
- widget->Init(params);
+ private:
+ // owned by |parent_|.
+ CandidateWindowView* candidate_window_view_;
- CandidateWindowView candidate_window_view(widget);
- candidate_window_view.Init();
+ DISALLOW_COPY_AND_ASSIGN(CandidateWindowViewTest);
+};
+TEST_F(CandidateWindowViewTest, UpdateCandidatesTest_CursorVisibility) {
// Visible (by default) cursor.
CandidateWindow candidate_window;
const int candidate_window_size = 9;
InitCandidateWindowWithCandidatesFilled(candidate_window_size,
&candidate_window);
- candidate_window_view.UpdateCandidates(candidate_window);
- EXPECT_EQ(0, candidate_window_view.selected_candidate_index_in_page_);
+ candidate_window_view()->UpdateCandidates(candidate_window);
+ EXPECT_EQ(0, selected_candidate_index_in_page());
// Invisible cursor.
candidate_window.set_is_cursor_visible(false);
- candidate_window_view.UpdateCandidates(candidate_window);
- EXPECT_EQ(-1, candidate_window_view.selected_candidate_index_in_page_);
+ candidate_window_view()->UpdateCandidates(candidate_window);
+ EXPECT_EQ(-1, selected_candidate_index_in_page());
// Move the cursor to the end.
candidate_window.set_cursor_position(candidate_window_size - 1);
- candidate_window_view.UpdateCandidates(candidate_window);
- EXPECT_EQ(-1, candidate_window_view.selected_candidate_index_in_page_);
+ candidate_window_view()->UpdateCandidates(candidate_window);
+ EXPECT_EQ(-1, selected_candidate_index_in_page());
// Change the cursor to visible. The cursor must be at the end.
candidate_window.set_is_cursor_visible(true);
- candidate_window_view.UpdateCandidates(candidate_window);
- EXPECT_EQ(candidate_window_size - 1,
- candidate_window_view.selected_candidate_index_in_page_);
+ candidate_window_view()->UpdateCandidates(candidate_window);
+ EXPECT_EQ(candidate_window_size - 1, selected_candidate_index_in_page());
}
TEST_F(CandidateWindowViewTest, SelectCandidateAtTest) {
- views::Widget* widget = new views::Widget;
- views::Widget::InitParams params =
- CreateParams(views::Widget::InitParams::TYPE_WINDOW);
- widget->Init(params);
-
- CandidateWindowView candidate_window_view(widget);
- candidate_window_view.Init();
-
// Set 9 candidates.
CandidateWindow candidate_window_large;
const int candidate_window_large_size = 9;
InitCandidateWindowWithCandidatesFilled(candidate_window_large_size,
&candidate_window_large);
candidate_window_large.set_cursor_position(candidate_window_large_size - 1);
- candidate_window_view.UpdateCandidates(candidate_window_large);
+ candidate_window_view()->UpdateCandidates(candidate_window_large);
// Select the last candidate.
- candidate_window_view.SelectCandidateAt(candidate_window_large_size - 1);
+ SelectCandidateAt(candidate_window_large_size - 1);
// Reduce the number of candidates to 3.
CandidateWindow candidate_window_small;
@@ -136,8 +159,8 @@ TEST_F(CandidateWindowViewTest, SelectCandidateAtTest) {
candidate_window_small.set_cursor_position(candidate_window_small_size - 1);
// Make sure the test doesn't crash if the candidate window reduced
// its size. (crbug.com/174163)
- candidate_window_view.UpdateCandidates(candidate_window_small);
- candidate_window_view.SelectCandidateAt(candidate_window_small_size - 1);
+ candidate_window_view()->UpdateCandidates(candidate_window_small);
+ SelectCandidateAt(candidate_window_small_size - 1);
}
TEST_F(CandidateWindowViewTest, ShortcutSettingTest) {
@@ -145,22 +168,14 @@ TEST_F(CandidateWindowViewTest, ShortcutSettingTest) {
const char* kCustomizedLabel[] = { "a", "s", "d" };
const char* kExpectedHorizontalCustomizedLabel[] = { "a.", "s.", "d." };
- views::Widget* widget = new views::Widget;
- views::Widget::InitParams params =
- CreateParams(views::Widget::InitParams::TYPE_WINDOW);
- widget->Init(params);
-
- CandidateWindowView candidate_window_view(widget);
- candidate_window_view.Init();
-
{
SCOPED_TRACE("candidate_views allocation test");
const size_t kMaxPageSize = 16;
for (size_t i = 1; i < kMaxPageSize; ++i) {
CandidateWindow candidate_window;
InitCandidateWindow(i, &candidate_window);
- candidate_window_view.UpdateCandidates(candidate_window);
- EXPECT_EQ(i, candidate_window_view.candidate_views_.size());
+ candidate_window_view()->UpdateCandidates(candidate_window);
+ EXPECT_EQ(i, GetCandidatesSize());
}
}
{
@@ -180,12 +195,12 @@ TEST_F(CandidateWindowViewTest, ShortcutSettingTest) {
candidate_window.mutable_candidates()->push_back(entry);
}
- candidate_window_view.UpdateCandidates(candidate_window);
+ candidate_window_view()->UpdateCandidates(candidate_window);
- ASSERT_EQ(kPageSize, candidate_window_view.candidate_views_.size());
+ ASSERT_EQ(kPageSize, GetCandidatesSize());
for (size_t i = 0; i < kPageSize; ++i) {
ExpectLabels(kEmptyLabel, kSampleCandidate[i], kSampleAnnotation[i],
- candidate_window_view.candidate_views_[i]);
+ GetCandidateAt(i));
}
}
{
@@ -206,13 +221,13 @@ TEST_F(CandidateWindowViewTest, ShortcutSettingTest) {
candidate_window.mutable_candidates()->push_back(entry);
}
- candidate_window_view.UpdateCandidates(candidate_window);
+ candidate_window_view()->UpdateCandidates(candidate_window);
- ASSERT_EQ(kPageSize, candidate_window_view.candidate_views_.size());
+ ASSERT_EQ(kPageSize, GetCandidatesSize());
// Confirm actual labels not containing ".".
for (size_t i = 0; i < kPageSize; ++i) {
ExpectLabels(kEmptyLabel, kSampleCandidate[i], kSampleAnnotation[i],
- candidate_window_view.candidate_views_[i]);
+ GetCandidateAt(i));
}
}
{
@@ -232,15 +247,15 @@ TEST_F(CandidateWindowViewTest, ShortcutSettingTest) {
candidate_window.mutable_candidates()->push_back(entry);
}
- candidate_window_view.UpdateCandidates(candidate_window);
+ candidate_window_view()->UpdateCandidates(candidate_window);
- ASSERT_EQ(kPageSize, candidate_window_view.candidate_views_.size());
+ ASSERT_EQ(kPageSize, GetCandidatesSize());
// Confirm actual labels not containing ".".
for (size_t i = 0; i < kPageSize; ++i) {
ExpectLabels(kCustomizedLabel[i],
kSampleCandidate[i],
kSampleAnnotation[i],
- candidate_window_view.candidate_views_[i]);
+ GetCandidateAt(i));
}
}
{
@@ -260,20 +275,17 @@ TEST_F(CandidateWindowViewTest, ShortcutSettingTest) {
candidate_window.mutable_candidates()->push_back(entry);
}
- candidate_window_view.UpdateCandidates(candidate_window);
+ candidate_window_view()->UpdateCandidates(candidate_window);
- ASSERT_EQ(kPageSize, candidate_window_view.candidate_views_.size());
+ ASSERT_EQ(kPageSize, GetCandidatesSize());
// Confirm actual labels not containing ".".
for (size_t i = 0; i < kPageSize; ++i) {
ExpectLabels(kExpectedHorizontalCustomizedLabel[i],
kSampleCandidate[i],
kSampleAnnotation[i],
- candidate_window_view.candidate_views_[i]);
+ GetCandidateAt(i));
}
}
-
- // We should call CloseNow method, otherwise this test will leak memory.
- widget->CloseNow();
}
TEST_F(CandidateWindowViewTest, DoNotChangeRowHeightWithLabelSwitchTest) {
@@ -293,17 +305,6 @@ TEST_F(CandidateWindowViewTest, DoNotChangeRowHeightWithLabelSwitchTest) {
const char kSampleAnnotation2[] = "\xE3\x81\x82"; // multi byte string.
const char kSampleAnnotation3[] = "......";
- // For testing, we have to prepare empty widget.
- // We should NOT manually free widget by default, otherwise double free will
- // be occurred. So, we should instantiate widget class with "new" operation.
- views::Widget* widget = new views::Widget;
- views::Widget::InitParams params =
- CreateParams(views::Widget::InitParams::TYPE_WINDOW);
- widget->Init(params);
-
- CandidateWindowView candidate_window_view(widget);
- candidate_window_view.Init();
-
// Create CandidateWindow object.
InitCandidateWindow(kPageSize, &candidate_window);
@@ -336,64 +337,46 @@ TEST_F(CandidateWindowViewTest, DoNotChangeRowHeightWithLabelSwitchTest) {
// Test for shortcut mode to no-shortcut mode.
// Initialize with a shortcut mode candidate window.
- candidate_window_view.MaybeInitializeCandidateViews(candidate_window);
- ASSERT_EQ(3UL, candidate_window_view.candidate_views_.size());
+ MaybeInitializeCandidateViews(candidate_window);
+ ASSERT_EQ(3UL, GetCandidatesSize());
// Check the selected index is invalidated.
- EXPECT_EQ(-1, candidate_window_view.selected_candidate_index_in_page_);
+ EXPECT_EQ(-1, selected_candidate_index_in_page());
before_height =
- candidate_window_view.candidate_views_[0]->GetContentsBounds().height();
+ GetCandidateAt(0)->GetContentsBounds().height();
// Checks all entry have same row height.
- for (size_t i = 1; i < candidate_window_view.candidate_views_.size(); ++i) {
- const CandidateView* view = candidate_window_view.candidate_views_[i];
- EXPECT_EQ(before_height, view->GetContentsBounds().height());
- }
+ for (size_t i = 1; i < GetCandidatesSize(); ++i)
+ EXPECT_EQ(before_height, GetCandidateAt(i)->GetContentsBounds().height());
// Initialize with a no shortcut mode candidate window.
- candidate_window_view.MaybeInitializeCandidateViews(
- no_shortcut_candidate_window);
- ASSERT_EQ(3UL, candidate_window_view.candidate_views_.size());
+ MaybeInitializeCandidateViews(no_shortcut_candidate_window);
+ ASSERT_EQ(3UL, GetCandidatesSize());
// Check the selected index is invalidated.
- EXPECT_EQ(-1, candidate_window_view.selected_candidate_index_in_page_);
- EXPECT_EQ(before_height,
- candidate_window_view.candidate_views_[0]->GetContentsBounds()
- .height());
+ EXPECT_EQ(-1, selected_candidate_index_in_page());
+ EXPECT_EQ(before_height, GetCandidateAt(0)->GetContentsBounds().height());
// Checks all entry have same row height.
- for (size_t i = 1; i < candidate_window_view.candidate_views_.size(); ++i) {
- const CandidateView* view = candidate_window_view.candidate_views_[i];
- EXPECT_EQ(before_height, view->GetContentsBounds().height());
- }
+ for (size_t i = 1; i < GetCandidatesSize(); ++i)
+ EXPECT_EQ(before_height, GetCandidateAt(i)->GetContentsBounds().height());
// Test for no-shortcut mode to shortcut mode.
// Initialize with a no shortcut mode candidate window.
- candidate_window_view.MaybeInitializeCandidateViews(
- no_shortcut_candidate_window);
- ASSERT_EQ(3UL, candidate_window_view.candidate_views_.size());
+ MaybeInitializeCandidateViews(no_shortcut_candidate_window);
+ ASSERT_EQ(3UL, GetCandidatesSize());
// Check the selected index is invalidated.
- EXPECT_EQ(-1, candidate_window_view.selected_candidate_index_in_page_);
- before_height =
- candidate_window_view.candidate_views_[0]->GetContentsBounds().height();
+ EXPECT_EQ(-1, selected_candidate_index_in_page());
+ before_height = GetCandidateAt(0)->GetContentsBounds().height();
// Checks all entry have same row height.
- for (size_t i = 1; i < candidate_window_view.candidate_views_.size(); ++i) {
- const CandidateView* view = candidate_window_view.candidate_views_[i];
- EXPECT_EQ(before_height, view->GetContentsBounds().height());
- }
+ for (size_t i = 1; i < GetCandidatesSize(); ++i)
+ EXPECT_EQ(before_height, GetCandidateAt(i)->GetContentsBounds().height());
// Initialize with a shortcut mode candidate window.
- candidate_window_view.MaybeInitializeCandidateViews(candidate_window);
- ASSERT_EQ(3UL, candidate_window_view.candidate_views_.size());
+ MaybeInitializeCandidateViews(candidate_window);
+ ASSERT_EQ(3UL, GetCandidatesSize());
// Check the selected index is invalidated.
- EXPECT_EQ(-1, candidate_window_view.selected_candidate_index_in_page_);
- EXPECT_EQ(before_height,
- candidate_window_view.candidate_views_[0]->GetContentsBounds()
- .height());
+ EXPECT_EQ(-1, selected_candidate_index_in_page());
+ EXPECT_EQ(before_height, GetCandidateAt(0)->GetContentsBounds().height());
// Checks all entry have same row height.
- for (size_t i = 1; i < candidate_window_view.candidate_views_.size(); ++i) {
- const CandidateView* view = candidate_window_view.candidate_views_[i];
- EXPECT_EQ(before_height, view->GetContentsBounds().height());
- }
-
- // We should call CloseNow method, otherwise this test will leak memory.
- widget->CloseNow();
+ for (size_t i = 1; i < GetCandidatesSize(); ++i)
+ EXPECT_EQ(before_height, GetCandidateAt(i)->GetContentsBounds().height());
}
} // namespace input_method
} // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/hidable_area.cc b/chrome/browser/chromeos/input_method/hidable_area.cc
deleted file mode 100644
index 9c396c7d..0000000
--- a/chrome/browser/chromeos/input_method/hidable_area.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2012 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 "chrome/browser/chromeos/input_method/hidable_area.h"
-
-#include "ui/views/layout/fill_layout.h"
-
-namespace chromeos {
-namespace input_method {
-
-HidableArea::HidableArea() {
- place_holder_.reset(new views::View);
- place_holder_->set_owned_by_client(); // Won't own
-
- // Initially show nothing.
- SetLayoutManager(new views::FillLayout);
- AddChildView(place_holder_.get());
-}
-
-HidableArea::~HidableArea() {
-}
-
-void HidableArea::SetContents(views::View* contents) {
- contents_.reset(contents);
- contents_->set_owned_by_client(); // Won't own
-}
-
-void HidableArea::Show() {
- if (contents_.get() && contents_->parent() != this) {
- RemoveAllChildViews(false); // Don't delete child views.
- AddChildView(contents_.get());
- }
-}
-
-void HidableArea::Hide() {
- if (IsShown()) {
- RemoveAllChildViews(false); // Don't delete child views.
- AddChildView(place_holder_.get());
- }
-}
-
-bool HidableArea::IsShown() const {
- return contents_.get() && contents_->parent() == this;
-}
-
-} // namespace input_method
-} // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/hidable_area.h b/chrome/browser/chromeos/input_method/hidable_area.h
deleted file mode 100644
index 76f468a..0000000
--- a/chrome/browser/chromeos/input_method/hidable_area.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2012 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 CHROME_BROWSER_CHROMEOS_INPUT_METHOD_HIDABLE_AREA_H_
-#define CHROME_BROWSER_CHROMEOS_INPUT_METHOD_HIDABLE_AREA_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "ui/views/widget/widget.h"
-
-namespace chromeos {
-namespace input_method {
-
-// HidableArea is used as an area to place optional information that can be
-// turned displaying off if it is unnecessary.
-class HidableArea : public views::View {
- public:
- HidableArea();
- virtual ~HidableArea();
-
- // Sets the content view.
- void SetContents(views::View* contents);
-
- // Shows the content.
- void Show();
-
- // Hides the content.
- void Hide();
-
- // Returns whether the content is already set and shown.
- bool IsShown() const;
-
- // Returns the content.
- views::View* contents() {
- return contents_.get();
- }
-
- private:
- scoped_ptr<views::View> contents_;
- scoped_ptr<views::View> place_holder_;
-
- DISALLOW_COPY_AND_ASSIGN(HidableArea);
-};
-
-} // namespace input_method
-} // namespace chromeos
-
-#endif // CHROME_BROWSER_CHROMEOS_INPUT_METHOD_HIDABLE_AREA_H_
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index d68c055..feed926 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -406,14 +406,14 @@
'browser/chromeos/input_method/accessibility.h',
'browser/chromeos/input_method/browser_state_monitor.cc',
'browser/chromeos/input_method/browser_state_monitor.h',
+ 'browser/chromeos/input_method/candidate_view.cc',
+ 'browser/chromeos/input_method/candidate_view.h',
'browser/chromeos/input_method/candidate_window_controller.cc',
'browser/chromeos/input_method/candidate_window_controller.h',
'browser/chromeos/input_method/candidate_window_controller_impl.cc',
'browser/chromeos/input_method/candidate_window_controller_impl.h',
'browser/chromeos/input_method/candidate_window_view.cc',
'browser/chromeos/input_method/candidate_window_view.h',
- 'browser/chromeos/input_method/hidable_area.cc',
- 'browser/chromeos/input_method/hidable_area.h',
'browser/chromeos/input_method/infolist_window.cc',
'browser/chromeos/input_method/infolist_window.h',
'browser/chromeos/input_method/input_method_engine.cc',