Chromium Code Reviews| Index: ui/app_list/search_result_view.cc |
| diff --git a/ui/app_list/search_result_view.cc b/ui/app_list/search_result_view.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c4028d7f37af79961bd963c33ae376052d33c5b4 |
| --- /dev/null |
| +++ b/ui/app_list/search_result_view.cc |
| @@ -0,0 +1,202 @@ |
| +// 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 "ui/app_list/search_result_view.h" |
| + |
| +#include "ui/app_list/search_result.h" |
| +#include "ui/gfx/canvas.h" |
| +#include "ui/gfx/font.h" |
| +#include "ui/gfx/render_text.h" |
| +#include "ui/views/controls/image_view.h" |
| + |
| +namespace { |
| + |
| +const int kPreferredWidth = 300; |
| +const int kPreferredHeight = 48; |
| +const int kIconViewWidth = 48; |
| +const int kIconPadding = 8; |
| +const int kBorderSize = 1; |
| + |
| +const SkColor kBorderColor = SkColorSetRGB(0xF1, 0xF1, 0xF1); |
| + |
| +const SkColor kDefaultTextColor = SkColorSetRGB(0x33, 0x33, 0x33); |
| +const SkColor kDimmedTextColor = SK_ColorGRAY; |
| +const SkColor kURLTextColor = SkColorSetRGB(0x00, 0x99, 0x33); |
| + |
| +// rgba(77,144,254,0.2) |
| +const SkColor kSelectedBorderColor = SkColorSetARGB(51, 77, 144, 254); |
| +// rgba(77,144,254,0.33) |
| +const SkColor kSelectedBackgroundColor = SkColorSetARGB(84, 77, 144, 254); |
| +const SkColor kHoverAndPushedColor = SkColorSetARGB(51, 77, 144, 254); |
| + |
| +// A non-interactive image view to display result icon. |
| +class IconView : public views::ImageView { |
| + public: |
| + IconView() : ImageView() {} |
| + virtual ~IconView() {} |
| + |
| + private: |
| + // views::View overrides: |
| + virtual bool HitTest(const gfx::Point& l) const OVERRIDE { |
|
sky
2012/05/22 22:16:06
Why do you need this?
xiyuan
2012/05/23 21:25:22
If we don't do this, the parent SearchResultView l
|
| + return false; |
| + } |
| + |
| + DISALLOW_COPY_AND_ASSIGN(IconView); |
| +}; |
| + |
| +// Creates a RenderText of given |text| and |styles|. Callers takes ownership |
| +// of returned RenderText. |
| +gfx::RenderText* CreateRenderText(const string16& text, |
| + const app_list::SearchResult::Tags& tags) { |
| + gfx::RenderText* render_text = gfx::RenderText::CreateRenderText(); |
| + render_text->SetText(text); |
| + |
| + gfx::StyleRange default_style; |
| + default_style.foreground = kDefaultTextColor; |
| + render_text->set_default_style(default_style); |
| + render_text->ApplyDefaultStyle(); |
| + |
| + for (app_list::SearchResult::Tags::const_iterator it = tags.begin(); |
| + it != tags.end(); |
| + ++it) { |
| + // NONE means default style so do nothing. |
| + if (it->styles == app_list::SearchResult::Tag::NONE) |
| + continue; |
| + |
| + gfx::StyleRange style; |
| + style.range = it->range; |
| + |
| + if (it->styles & app_list::SearchResult::Tag::MATCH) |
| + style.font_style = gfx::Font::BOLD; |
| + if (it->styles & app_list::SearchResult::Tag::URL) |
| + style.foreground = kURLTextColor; |
| + if (it->styles & app_list::SearchResult::Tag::DIM) |
| + style.foreground = kDimmedTextColor; |
| + |
| + render_text->ApplyStyleRange(style); |
| + } |
| + |
| + return render_text; |
| +} |
| + |
| +} // namespace |
| + |
| +namespace app_list { |
| + |
| +// static |
| +const char SearchResultView::kViewClassName[] = "ui/app_list/SearchResultView"; |
| + |
| +SearchResultView::SearchResultView(views::ButtonListener* listener) |
| + : views::CustomButton(listener), |
| + result_(NULL), |
| + selected_(false), |
| + icon_(NULL) { |
| + icon_ = new IconView; |
| + AddChildView(icon_); |
| +} |
| + |
| +SearchResultView::~SearchResultView() { |
| +} |
| + |
| +void SearchResultView::SetResult(const SearchResult* result) { |
| + result_ = result; |
| + |
| + icon_->SetImage(result_ ? result_->icon() : SkBitmap()); |
| + UpdateTitleText(); |
| + UpdateDetailsText(); |
| + SchedulePaint(); |
| +} |
| + |
| +void SearchResultView::SetSelected(bool selected) { |
| + if (selected_ == selected) |
| + return; |
| + |
| + selected_ = selected; |
| + SchedulePaint(); |
| +} |
| + |
| +void SearchResultView::UpdateTitleText() { |
| + if (!result_ || result_->title().empty()) { |
| + title_text_.reset(); |
| + } else { |
| + title_text_.reset(CreateRenderText(result_->title(), |
| + result_->title_tags())); |
| + } |
| +} |
| + |
| +void SearchResultView::UpdateDetailsText() { |
| + if (!result_ || result_->details().empty()) { |
| + details_text_.reset(); |
| + } else { |
| + details_text_.reset(CreateRenderText(result_->details(), |
| + result_->details_tags())); |
| + } |
| +} |
| + |
| +std::string SearchResultView::GetClassName() const { |
| + return kViewClassName; |
| +} |
| + |
| +gfx::Size SearchResultView::GetPreferredSize() { |
| + return gfx::Size(kPreferredWidth, kPreferredHeight); |
| +} |
| + |
| +void SearchResultView::Layout() { |
| + gfx::Rect rect(GetContentsBounds()); |
| + if (rect.IsEmpty()) |
| + return; |
| + |
| + gfx::Rect icon_bounds(rect); |
| + icon_bounds.set_width(kIconViewWidth); |
| + icon_bounds.Inset(kIconPadding, kIconPadding); |
| + icon_->SetBoundsRect(icon_bounds.Intersect(rect)); |
| +} |
| + |
| +void SearchResultView::OnPaint(gfx::Canvas* canvas) { |
| + gfx::Rect rect(GetContentsBounds()); |
| + if (rect.IsEmpty()) |
| + return; |
| + |
| + gfx::Rect content_rect(rect); |
| + content_rect.set_height(rect.height() - kBorderSize); |
| + |
| + if (selected_) { |
| + canvas->FillRect(content_rect, kSelectedBackgroundColor); |
| + } else if (state() == BS_HOT || state() == BS_PUSHED) { |
| + canvas->FillRect(content_rect, kHoverAndPushedColor); |
| + } |
| + |
| + gfx::Rect border_bottom = rect.Subtract(content_rect); |
| + canvas->FillRect(border_bottom, |
| + selected_ ? kSelectedBorderColor : kBorderColor); |
| + |
| + gfx::Rect text_bounds(rect); |
| + text_bounds.set_x(kIconViewWidth); |
| + text_bounds.set_width(rect.width() - kIconViewWidth); |
| + |
| + if (title_text_.get() && details_text_.get()) { |
| + gfx::Size title_size(text_bounds.width(), |
| + title_text_->GetStringSize().height()); |
| + gfx::Size details_size(text_bounds.width(), |
| + details_text_->GetStringSize().height()); |
| + int total_height = title_size.height() + + details_size.height(); |
| + int y = text_bounds.y() + (text_bounds.height() - total_height) / 2; |
| + |
| + title_text_->SetDisplayRect(gfx::Rect(gfx::Point(text_bounds.x(), y), |
| + title_size)); |
| + title_text_->Draw(canvas); |
| + |
| + y += title_size.height(); |
| + details_text_->SetDisplayRect(gfx::Rect(gfx::Point(text_bounds.x(), y), |
| + details_size)); |
| + details_text_->Draw(canvas); |
| + } else if (title_text_.get()) { |
| + gfx::Size title_size(text_bounds.width(), |
|
sky
2012/05/22 22:16:06
Don't you want the title to always get the same bo
xiyuan
2012/05/23 21:25:22
Per mock, we should vertically center title text.
|
| + title_text_->GetStringSize().height()); |
| + title_text_->SetDisplayRect(text_bounds.Center(title_size)); |
| + title_text_->Draw(canvas); |
| + } |
| +} |
| + |
| +} // namespace app_list |