Index: ash/ime/candidate_window_view.cc |
diff --git a/ash/ime/candidate_window_view.cc b/ash/ime/candidate_window_view.cc |
deleted file mode 100644 |
index 66b54d5852fd11cbc58a4a35fb7e38e2840d7a86..0000000000000000000000000000000000000000 |
--- a/ash/ime/candidate_window_view.cc |
+++ /dev/null |
@@ -1,406 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "ash/ime/candidate_window_view.h" |
- |
-#include <string> |
- |
-#include "ash/ime/candidate_view.h" |
-#include "ash/ime/candidate_window_constants.h" |
-#include "base/strings/utf_string_conversions.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/box_layout.h" |
-#include "ui/views/layout/fill_layout.h" |
-#include "ui/wm/core/window_animations.h" |
- |
-namespace ash { |
-namespace ime { |
- |
-namespace { |
- |
-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); |
- } |
- ~CandidateWindowBorder() override {} |
- |
- void set_offset(int offset) { offset_ = offset; } |
- |
- private: |
- // Overridden from views::BubbleBorder: |
- 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())); |
- |
- // 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()); |
- |
- return bounds; |
- } |
- |
- gfx::Insets GetInsets() const override { return gfx::Insets(); } |
- |
- gfx::NativeView parent_; |
- int offset_; |
- |
- 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 |
-// page, as the index is zero-origin). Returns -1 on error. |
-int ComputePageIndex(const ui::CandidateWindow& candidate_window) { |
- if (candidate_window.page_size() > 0) |
- return candidate_window.cursor_position() / candidate_window.page_size(); |
- return -1; |
-} |
- |
-} // namespace |
- |
-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 min_width) |
- : min_width_(min_width) { |
- label_ = new views::Label; |
- label_->SetHorizontalAlignment(align); |
- label_->SetBorder(views::Border::CreateEmptyBorder(2, 2, 2, 4)); |
- |
- SetLayoutManager(new views::FillLayout()); |
- AddChildView(label_); |
- set_background(views::Background::CreateSolidBackground( |
- color_utils::AlphaBlend(SK_ColorBLACK, |
- GetNativeTheme()->GetSystemColor( |
- ui::NativeTheme::kColorId_WindowBackground), |
- 0x10))); |
- } |
- |
- // Sets the text alignment. |
- void SetAlignment(gfx::HorizontalAlignment alignment) { |
- label_->SetHorizontalAlignment(alignment); |
- } |
- |
- // Sets the displayed text. |
- void SetText(const base::string16& text) { |
- label_->SetText(text); |
- } |
- |
- // Sets the border thickness for top/bottom. |
- void SetBorderFromPosition(BorderPosition position) { |
- SetBorder(views::Border::CreateSolidSidedBorder( |
- (position == TOP) ? 1 : 0, |
- 0, |
- (position == BOTTOM) ? 1 : 0, |
- 0, |
- GetNativeTheme()->GetSystemColor( |
- ui::NativeTheme::kColorId_MenuBorderColor))); |
- } |
- |
- protected: |
- gfx::Size GetPreferredSize() const override { |
- gfx::Size size = views::View::GetPreferredSize(); |
- size.SetToMax(gfx::Size(min_width_, 0)); |
- return size; |
- } |
- |
- private: |
- views::Label* label_; |
- int min_width_; |
- |
- DISALLOW_COPY_AND_ASSIGN(InformationTextArea); |
-}; |
- |
-CandidateWindowView::CandidateWindowView(gfx::NativeView parent) |
- : selected_candidate_index_in_page_(-1), |
- should_show_at_composition_head_(false), |
- should_show_upper_side_(false), |
- was_candidate_window_open_(false) { |
- set_can_activate(false); |
- set_parent_window(parent); |
- set_margins(gfx::Insets()); |
- |
- // Set the background and the border of the view. |
- ui::NativeTheme* theme = GetNativeTheme(); |
- set_background( |
- views::Background::CreateSolidBackground(theme->GetSystemColor( |
- ui::NativeTheme::kColorId_WindowBackground))); |
- SetBorder(views::Border::CreateSolidBorder( |
- 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_->SetBorderFromPosition(InformationTextArea::BOTTOM); |
- if (candidate_window_.orientation() == ui::CandidateWindow::VERTICAL) { |
- AddChildView(preedit_); |
- AddChildView(candidate_area_); |
- AddChildView(auxiliary_text_); |
- auxiliary_text_->SetBorderFromPosition(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_->SetBorderFromPosition(InformationTextArea::BOTTOM); |
- candidate_area_->SetLayoutManager(new views::BoxLayout( |
- views::BoxLayout::kHorizontal, 0, 0, 0)); |
- } |
-} |
- |
-CandidateWindowView::~CandidateWindowView() { |
-} |
- |
-views::Widget* CandidateWindowView::InitWidget() { |
- views::Widget* widget = BubbleDelegateView::CreateBubble(this); |
- |
- wm::SetWindowVisibilityAnimationType( |
- widget->GetNativeView(), |
- wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); |
- |
- GetBubbleFrameView()->SetBubbleBorder(scoped_ptr<views::BubbleBorder>( |
- new CandidateWindowBorder(parent_window()))); |
- return widget; |
-} |
- |
-void CandidateWindowView::UpdateVisibility() { |
- if (candidate_area_->visible() || auxiliary_text_->visible() || |
- preedit_->visible()) { |
- SizeToContents(); |
- } else { |
- GetWidget()->Close(); |
- } |
-} |
- |
-void CandidateWindowView::HideLookupTable() { |
- candidate_area_->SetVisible(false); |
- auxiliary_text_->SetVisible(false); |
- UpdateVisibility(); |
-} |
- |
-void CandidateWindowView::HidePreeditText() { |
- preedit_->SetVisible(false); |
- UpdateVisibility(); |
-} |
- |
-void CandidateWindowView::ShowPreeditText() { |
- preedit_->SetVisible(true); |
- UpdateVisibility(); |
-} |
- |
-void CandidateWindowView::UpdatePreeditText(const base::string16& text) { |
- preedit_->SetText(text); |
-} |
- |
-void CandidateWindowView::ShowLookupTable() { |
- candidate_area_->SetVisible(true); |
- auxiliary_text_->SetVisible(candidate_window_.is_auxiliary_text_visible()); |
- UpdateVisibility(); |
-} |
- |
-void CandidateWindowView::UpdateCandidates( |
- const ui::CandidateWindow& new_candidate_window) { |
- // Updating the candidate views is expensive. We'll skip this if possible. |
- 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() == ui::CandidateWindow::VERTICAL) { |
- ReorderChildView(auxiliary_text_, -1); |
- auxiliary_text_->SetAlignment(gfx::ALIGN_RIGHT); |
- auxiliary_text_->SetBorderFromPosition(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_->SetBorderFromPosition(InformationTextArea::BOTTOM); |
- candidate_area_->SetLayoutManager(new views::BoxLayout( |
- views::BoxLayout::kHorizontal, 0, 0, 0)); |
- } |
- } |
- |
- // Initialize candidate views if necessary. |
- MaybeInitializeCandidateViews(new_candidate_window); |
- |
- should_show_at_composition_head_ |
- = 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) |
- return; |
- |
- // Update the candidates in the current page. |
- const size_t start_from = |
- current_page_index * new_candidate_window.page_size(); |
- |
- 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 candidate text. |
- if (candidate_index < new_candidate_window.candidates().size()) { |
- const ui::CandidateWindow::Entry& entry = |
- new_candidate_window.candidates()[candidate_index]; |
- candidate_view->SetEntry(entry); |
- candidate_view->SetEnabled(true); |
- candidate_view->SetInfolistIcon(!entry.description_title.empty()); |
- } else { |
- // Disable the empty row. |
- candidate_view->SetEntry(ui::CandidateWindow::Entry()); |
- candidate_view->SetEnabled(false); |
- candidate_view->SetInfolistIcon(false); |
- } |
- if (new_candidate_window.orientation() == ui::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() == ui::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() == ui::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_. |
- candidate_window_.CopyFrom(new_candidate_window); |
- |
- // Select the current candidate in the page. |
- if (candidate_window_.is_cursor_visible()) { |
- if (candidate_window_.page_size()) { |
- const int current_candidate_in_page = |
- candidate_window_.cursor_position() % candidate_window_.page_size(); |
- SelectCandidateAt(current_candidate_in_page); |
- } |
- } else { |
- // 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_]->SetHighlighted( |
- false); |
- selected_candidate_index_in_page_ = -1; |
- } |
- } |
- |
- // Updates auxiliary text |
- auxiliary_text_->SetVisible(candidate_window_.is_auxiliary_text_visible()); |
- auxiliary_text_->SetText(base::UTF8ToUTF16( |
- 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 ui::CandidateWindow& candidate_window) { |
- const ui::CandidateWindow::Orientation orientation = |
- candidate_window.orientation(); |
- const size_t page_size = candidate_window.page_size(); |
- |
- // Reset all candidate_views_ when orientation changes. |
- if (orientation != candidate_window_.orientation()) |
- STLDeleteElements(&candidate_views_); |
- |
- while (page_size < candidate_views_.size()) { |
- delete candidate_views_.back(); |
- candidate_views_.pop_back(); |
- } |
- while (page_size > candidate_views_.size()) { |
- CandidateView* new_candidate = new CandidateView(this, orientation); |
- candidate_area_->AddChildView(new_candidate); |
- candidate_views_.push_back(new_candidate); |
- } |
-} |
- |
-void CandidateWindowView::SelectCandidateAt(int index_in_page) { |
- const int current_page_index = ComputePageIndex(candidate_window_); |
- if (current_page_index < 0) { |
- return; |
- } |
- |
- const int cursor_absolute_index = |
- candidate_window_.page_size() * current_page_index + index_in_page; |
- // Ignore click on out of range views. |
- if (cursor_absolute_index < 0 || |
- candidate_window_.candidates().size() <= |
- static_cast<size_t>(cursor_absolute_index)) { |
- return; |
- } |
- |
- // 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]->SetHighlighted(true); |
- |
- // Update the cursor indexes in the model. |
- candidate_window_.set_cursor_position(cursor_absolute_index); |
-} |
- |
-void CandidateWindowView::ButtonPressed(views::Button* sender, |
- const ui::Event& event) { |
- for (size_t i = 0; i < candidate_views_.size(); ++i) { |
- if (sender == candidate_views_[i]) { |
- FOR_EACH_OBSERVER(Observer, observers_, OnCandidateCommitted(i)); |
- return; |
- } |
- } |
-} |
- |
-} // namespace ime |
-} // namespace ash |