Disable TabDragController tests that fail with a real compositor.
[chromium-blink-merge.git] / ash / ime / infolist_window.cc
blobd72eed33bc3f2313826a2bcd4faaa3345a9dc1cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/ime/infolist_window.h"
7 #include <string>
8 #include <vector>
10 #include "ash/ime/candidate_window_constants.h"
11 #include "base/logging.h"
12 #include "grit/ash_strings.h"
13 #include "ui/base/l10n/l10n_util.h"
14 #include "ui/gfx/color_utils.h"
15 #include "ui/gfx/font.h"
16 #include "ui/native_theme/native_theme.h"
17 #include "ui/views/background.h"
18 #include "ui/views/border.h"
19 #include "ui/views/bubble/bubble_border.h"
20 #include "ui/views/bubble/bubble_frame_view.h"
21 #include "ui/views/controls/label.h"
22 #include "ui/views/corewm/window_animations.h"
23 #include "ui/views/layout/box_layout.h"
24 #include "ui/views/widget/widget.h"
26 namespace ash {
27 namespace ime {
29 namespace {
30 // The width of an info-list.
31 const int kInfolistEntryWidth = 200;
33 // The milliseconds of the delay to show the infolist window.
34 const int kInfolistShowDelayMilliSeconds = 500;
35 // The milliseconds of the delay to hide the infolist window.
36 const int kInfolistHideDelayMilliSeconds = 500;
38 ///////////////////////////////////////////////////////////////////////////////
39 // InfolistBorder
40 // The BubbleBorder subclass to draw the border and determine its position.
41 class InfolistBorder : public views::BubbleBorder {
42 public:
43 InfolistBorder();
44 virtual ~InfolistBorder();
46 // views::BubbleBorder implementation.
47 virtual gfx::Rect GetBounds(const gfx::Rect& anchor_rect,
48 const gfx::Size& contents_size) const OVERRIDE;
49 virtual gfx::Insets GetInsets() const OVERRIDE;
51 private:
52 DISALLOW_COPY_AND_ASSIGN(InfolistBorder);
55 InfolistBorder::InfolistBorder()
56 : views::BubbleBorder(views::BubbleBorder::LEFT_CENTER,
57 views::BubbleBorder::NO_SHADOW,
58 SK_ColorTRANSPARENT) {
59 set_paint_arrow(views::BubbleBorder::PAINT_NONE);
62 InfolistBorder::~InfolistBorder() {}
64 gfx::Rect InfolistBorder::GetBounds(const gfx::Rect& anchor_rect,
65 const gfx::Size& contents_size) const {
66 gfx::Rect bounds(contents_size);
67 bounds.set_x(is_arrow_on_left(arrow()) ?
68 anchor_rect.right() : anchor_rect.x() - contents_size.width());
69 // InfolistBorder modifies the vertical position based on the arrow offset
70 // although it doesn't draw the arrow. The arrow offset is the half of
71 // |contents_size| by default but can be modified through the off-screen logic
72 // in BubbleFrameView.
73 bounds.set_y(anchor_rect.y() + contents_size.height() / 2 -
74 GetArrowOffset(contents_size));
75 return bounds;
78 gfx::Insets InfolistBorder::GetInsets() const {
79 // This has to be specified and return empty insets to place the infolist
80 // window without the gap.
81 return gfx::Insets();
84 } // namespace
86 // InfolistRow renderes a row of a infolist.
87 class InfolistEntryView : public views::View {
88 public:
89 InfolistEntryView(const ui::InfolistEntry& entry,
90 const gfx::FontList& title_font,
91 const gfx::FontList& description_font);
92 virtual ~InfolistEntryView();
94 void SetEntry(const ui::InfolistEntry& entry);
96 private:
97 // views::View implementation.
98 virtual gfx::Size GetPreferredSize() OVERRIDE;
100 void UpdateBackground();
102 ui::InfolistEntry entry_;
104 // The title label. Owned by views hierarchy.
105 views::Label* title_label_;
107 // The description label. Owned by views hierarchy.
108 views::Label* description_label_;
110 DISALLOW_COPY_AND_ASSIGN(InfolistEntryView);
113 InfolistEntryView::InfolistEntryView(const ui::InfolistEntry& entry,
114 const gfx::FontList& title_font,
115 const gfx::FontList& description_font)
116 : entry_(entry) {
117 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
119 title_label_ = new views::Label(entry.title);
120 title_label_->SetPosition(gfx::Point(0, 0));
121 title_label_->SetFontList(title_font);
122 title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
123 title_label_->set_border(
124 views::Border::CreateEmptyBorder(4, 7, 2, 4));
126 description_label_ = new views::Label(entry.body);
127 description_label_->SetPosition(gfx::Point(0, 0));
128 description_label_->SetFontList(description_font);
129 description_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
130 description_label_->SetMultiLine(true);
131 description_label_->SizeToFit(kInfolistEntryWidth);
132 description_label_->set_border(
133 views::Border::CreateEmptyBorder(2, 17, 4, 4));
134 AddChildView(title_label_);
135 AddChildView(description_label_);
136 UpdateBackground();
139 InfolistEntryView::~InfolistEntryView() {}
141 void InfolistEntryView::SetEntry(const ui::InfolistEntry& entry) {
142 if (entry_ == entry)
143 return;
145 entry_ = entry;
146 title_label_->SetText(entry_.title);
147 description_label_->SetText(entry_.body);
148 UpdateBackground();
151 gfx::Size InfolistEntryView::GetPreferredSize() {
152 return gfx::Size(kInfolistEntryWidth, GetHeightForWidth(kInfolistEntryWidth));
155 void InfolistEntryView::UpdateBackground() {
156 if (entry_.highlighted) {
157 set_background(
158 views::Background::CreateSolidBackground(GetNativeTheme()->GetSystemColor(
159 ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused)));
160 set_border(
161 views::Border::CreateSolidBorder(1, GetNativeTheme()->GetSystemColor(
162 ui::NativeTheme::kColorId_FocusedBorderColor)));
163 } else {
164 set_background(NULL);
165 set_border(views::Border::CreateEmptyBorder(1, 1, 1, 1));
167 SchedulePaint();
170 ///////////////////////////////////////////////////////////////////////////////
171 // InfolistWindow
173 InfolistWindow::InfolistWindow(views::View* candidate_window,
174 const std::vector<ui::InfolistEntry>& entries)
175 : views::BubbleDelegateView(candidate_window, views::BubbleBorder::NONE),
176 title_font_(gfx::Font(kJapaneseFontName, kFontSizeDelta + 15)),
177 description_font_(gfx::Font(kJapaneseFontName, kFontSizeDelta + 11)) {
178 set_move_with_anchor(true);
179 set_margins(gfx::Insets());
181 set_background(
182 views::Background::CreateSolidBackground(GetNativeTheme()->GetSystemColor(
183 ui::NativeTheme::kColorId_WindowBackground)));
184 set_border(
185 views::Border::CreateSolidBorder(1, GetNativeTheme()->GetSystemColor(
186 ui::NativeTheme::kColorId_MenuBorderColor)));
188 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
190 views::Label* caption_label = new views::Label(
191 l10n_util::GetStringUTF16(IDS_ASH_IME_INFOLIST_WINDOW_TITLE));
192 caption_label->SetFontList(
193 caption_label->font_list().DeriveFontList(kFontSizeDelta - 2));
194 caption_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
195 caption_label->SetEnabledColor(GetNativeTheme()->GetSystemColor(
196 ui::NativeTheme::kColorId_LabelEnabledColor));
197 caption_label->set_border(views::Border::CreateEmptyBorder(2, 2, 2, 2));
198 caption_label->set_background(views::Background::CreateSolidBackground(
199 color_utils::AlphaBlend(SK_ColorBLACK,
200 GetNativeTheme()->GetSystemColor(
201 ui::NativeTheme::kColorId_WindowBackground),
202 0x10)));
204 AddChildView(caption_label);
206 for (size_t i = 0; i < entries.size(); ++i) {
207 entry_views_.push_back(
208 new InfolistEntryView(entries[i], title_font_, description_font_));
209 AddChildView(entry_views_.back());
213 InfolistWindow::~InfolistWindow() {
216 void InfolistWindow::InitWidget() {
217 views::Widget* widget = views::BubbleDelegateView::CreateBubble(this);
218 views::corewm::SetWindowVisibilityAnimationType(
219 widget->GetNativeView(),
220 views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
222 // BubbleFrameView will be initialized through CreateBubble.
223 GetBubbleFrameView()->SetBubbleBorder(new InfolistBorder());
224 SizeToContents();
227 void InfolistWindow::Relayout(const std::vector<ui::InfolistEntry>& entries) {
228 size_t i = 0;
229 for (; i < entries.size(); ++i) {
230 if (i < entry_views_.size()) {
231 entry_views_[i]->SetEntry(entries[i]);
232 } else {
233 InfolistEntryView* new_entry = new InfolistEntryView(
234 entries[i], title_font_, description_font_);
235 AddChildView(new_entry);
236 entry_views_.push_back(new_entry);
240 if (i < entry_views_.size()) {
241 for (; i < entry_views_.size(); ++i)
242 delete entry_views_[i];
243 entry_views_.resize(entries.size());
246 Layout();
247 GetBubbleFrameView()->bubble_border()->set_arrow_offset(0);
248 SizeToContents();
251 void InfolistWindow::ShowWithDelay() {
252 show_hide_timer_.Start(
253 FROM_HERE,
254 base::TimeDelta::FromMilliseconds(kInfolistShowDelayMilliSeconds),
255 GetWidget(),
256 &views::Widget::Show);
259 void InfolistWindow::HideWithDelay() {
260 show_hide_timer_.Start(
261 FROM_HERE,
262 base::TimeDelta::FromMilliseconds(kInfolistHideDelayMilliSeconds),
263 GetWidget(),
264 &views::Widget::Close);
267 void InfolistWindow::ShowImmediately() {
268 show_hide_timer_.Stop();
269 GetWidget()->Show();
272 void InfolistWindow::HideImmediately() {
273 show_hide_timer_.Stop();
274 GetWidget()->Close();
277 void InfolistWindow::WindowClosing() {
278 show_hide_timer_.Stop();
281 } // namespace ime
282 } // namespace ash