1 // Copyright (c) 2012 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 "ui/app_list/search_result_view.h"
7 #include "ui/app_list/search_result.h"
8 #include "ui/app_list/search_result_list_view.h"
9 #include "ui/gfx/canvas.h"
10 #include "ui/gfx/font.h"
11 #include "ui/gfx/render_text.h"
12 #include "ui/views/controls/image_view.h"
16 const int kPreferredWidth
= 300;
17 const int kPreferredHeight
= 52;
18 const int kIconDimension
= 32;
19 const int kIconPadding
= 14;
20 const int kIconViewWidth
= kIconDimension
+ 2 * kIconPadding
;
21 const int kTextTrailPadding
= kIconPadding
;
22 const int kBorderSize
= 1;
24 const SkColor kBorderColor
= SkColorSetARGB(0x0F, 0, 0, 0);
26 const SkColor kDefaultTextColor
= SkColorSetRGB(0x33, 0x33, 0x33);
27 const SkColor kDimmedTextColor
= SkColorSetRGB(0x96, 0x96, 0x96);
28 const SkColor kURLTextColor
= SkColorSetRGB(0x00, 0x99, 0x33);
30 const SkColor kSelectedBorderColor
= kBorderColor
;
31 const SkColor kSelectedBackgroundColor
= SkColorSetARGB(0x0F, 0x4D, 0x90, 0xFE);
32 const SkColor kHoverAndPushedColor
= SkColorSetARGB(0x05, 0, 0, 0);
34 // A non-interactive image view to display result icon.
35 class IconView
: public views::ImageView
{
37 IconView() : ImageView() {}
38 virtual ~IconView() {}
41 // views::View overrides:
42 virtual bool HitTest(const gfx::Point
& l
) const OVERRIDE
{
46 DISALLOW_COPY_AND_ASSIGN(IconView
);
49 // Creates a RenderText of given |text| and |styles|. Callers takes ownership
50 // of returned RenderText.
51 gfx::RenderText
* CreateRenderText(const string16
& text
,
52 const app_list::SearchResult::Tags
& tags
) {
53 gfx::RenderText
* render_text
= gfx::RenderText::CreateRenderText();
54 render_text
->SetText(text
);
56 gfx::StyleRange default_style
;
57 default_style
.foreground
= kDefaultTextColor
;
58 render_text
->set_default_style(default_style
);
59 render_text
->ApplyDefaultStyle();
61 for (app_list::SearchResult::Tags::const_iterator it
= tags
.begin();
64 // NONE means default style so do nothing.
65 if (it
->styles
== app_list::SearchResult::Tag::NONE
)
68 gfx::StyleRange style
;
69 style
.range
= it
->range
;
71 if (it
->styles
& app_list::SearchResult::Tag::MATCH
)
72 style
.font_style
= gfx::Font::BOLD
;
73 if (it
->styles
& app_list::SearchResult::Tag::URL
)
74 style
.foreground
= kURLTextColor
;
75 if (it
->styles
& app_list::SearchResult::Tag::DIM
)
76 style
.foreground
= kDimmedTextColor
;
78 render_text
->ApplyStyleRange(style
);
89 const char SearchResultView::kViewClassName
[] = "ui/app_list/SearchResultView";
91 SearchResultView::SearchResultView(SearchResultListView
* list_view
,
92 views::ButtonListener
* listener
)
93 : views::CustomButton(listener
),
95 list_view_(list_view
),
101 SearchResultView::~SearchResultView() {
103 result_
->RemoveObserver(this);
106 void SearchResultView::SetResult(SearchResult
* result
) {
108 result_
->RemoveObserver(this);
113 result_
->AddObserver(this);
115 icon_
->SetImage(result_
? result_
->icon() : gfx::ImageSkia());
121 void SearchResultView::UpdateTitleText() {
122 if (!result_
|| result_
->title().empty()) {
125 title_text_
.reset(CreateRenderText(result_
->title(),
126 result_
->title_tags()));
130 void SearchResultView::UpdateDetailsText() {
131 if (!result_
|| result_
->details().empty()) {
132 details_text_
.reset();
134 details_text_
.reset(CreateRenderText(result_
->details(),
135 result_
->details_tags()));
139 std::string
SearchResultView::GetClassName() const {
140 return kViewClassName
;
143 gfx::Size
SearchResultView::GetPreferredSize() {
144 return gfx::Size(kPreferredWidth
, kPreferredHeight
);
147 void SearchResultView::Layout() {
148 gfx::Rect
rect(GetContentsBounds());
152 gfx::Rect
icon_bounds(rect
);
153 icon_bounds
.set_width(kIconViewWidth
);
154 icon_bounds
.Inset(kIconPadding
, (rect
.height() - kIconDimension
) / 2);
155 icon_
->SetBoundsRect(icon_bounds
.Intersect(rect
));
158 void SearchResultView::OnPaint(gfx::Canvas
* canvas
) {
159 gfx::Rect
rect(GetContentsBounds());
163 gfx::Rect
content_rect(rect
);
164 content_rect
.set_height(rect
.height() - kBorderSize
);
166 bool selected
= list_view_
->IsResultViewSelected(this);
168 canvas
->FillRect(content_rect
, kSelectedBackgroundColor
);
169 } else if (state() == BS_HOT
|| state() == BS_PUSHED
) {
170 canvas
->FillRect(content_rect
, kHoverAndPushedColor
);
173 gfx::Rect border_bottom
= rect
.Subtract(content_rect
);
174 canvas
->FillRect(border_bottom
,
175 selected
? kSelectedBorderColor
: kBorderColor
);
177 gfx::Rect
text_bounds(rect
);
178 text_bounds
.set_x(kIconViewWidth
);
179 text_bounds
.set_width(rect
.width() - kIconViewWidth
- kTextTrailPadding
);
181 if (title_text_
.get() && details_text_
.get()) {
182 gfx::Size
title_size(text_bounds
.width(),
183 title_text_
->GetStringSize().height());
184 gfx::Size
details_size(text_bounds
.width(),
185 details_text_
->GetStringSize().height());
186 int total_height
= title_size
.height() + + details_size
.height();
187 int y
= text_bounds
.y() + (text_bounds
.height() - total_height
) / 2;
189 title_text_
->SetDisplayRect(gfx::Rect(gfx::Point(text_bounds
.x(), y
),
191 title_text_
->Draw(canvas
);
193 y
+= title_size
.height();
194 details_text_
->SetDisplayRect(gfx::Rect(gfx::Point(text_bounds
.x(), y
),
196 details_text_
->Draw(canvas
);
197 } else if (title_text_
.get()) {
198 gfx::Size
title_size(text_bounds
.width(),
199 title_text_
->GetStringSize().height());
200 title_text_
->SetDisplayRect(text_bounds
.Center(title_size
));
201 title_text_
->Draw(canvas
);
205 void SearchResultView::OnIconChanged() {
209 } // namespace app_list