| Index: chrome/browser/views/page_info_bubble_view.cc
|
| ===================================================================
|
| --- chrome/browser/views/page_info_bubble_view.cc (revision 0)
|
| +++ chrome/browser/views/page_info_bubble_view.cc (revision 0)
|
| @@ -0,0 +1,253 @@
|
| +// Copyright (c) 2010 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/views/page_info_bubble_view.h"
|
| +
|
| +#include "app/resource_bundle.h"
|
| +#include "base/utf_string_conversions.h"
|
| +#include "chrome/browser/views/frame/browser_view.h"
|
| +#include "chrome/browser/views/info_bubble.h"
|
| +#include "chrome/browser/views/toolbar_view.h"
|
| +#include "grit/locale_settings.h"
|
| +#include "grit/theme_resources.h"
|
| +#include "views/controls/image_view.h"
|
| +#include "views/controls/label.h"
|
| +#include "views/controls/separator.h"
|
| +#include "views/grid_layout.h"
|
| +#include "views/widget/widget_win.h"
|
| +#include "views/window/window.h"
|
| +
|
| +// Layout constants.
|
| +const int kHGapToBorder = 11;
|
| +const int kVGapToImage = 10;
|
| +const int kVGapToHeadline = 7;
|
| +const int kHGapImageToDescription = 6;
|
| +const int kTextPaddingRight = 10;
|
| +const int kPaddingBelowSeparator = 4;
|
| +const int kPaddingAboveSeparator = 13;
|
| +const int kIconOffset = 28;
|
| +
|
| +// A section contains an image that shows a status (good or bad), a title, an
|
| +// optional head-line (in bold) and a description.
|
| +class Section : public views::View {
|
| + public:
|
| + Section(bool state,
|
| + const string16& headline,
|
| + const string16& description);
|
| + virtual ~Section();
|
| +
|
| + virtual int GetHeightForWidth(int w);
|
| + virtual void Layout();
|
| +
|
| + private:
|
| + // Calculate the layout if |compute_bounds_only|, otherwise does Layout also.
|
| + gfx::Size LayoutItems(bool compute_bounds_only, int width);
|
| +
|
| + // Whether to show the good/bad icon.
|
| + bool state_;
|
| +
|
| + // The first line of the description, show in bold.
|
| + string16 headline_;
|
| +
|
| + // The description, displayed below the head line.
|
| + string16 description_;
|
| +
|
| + static SkBitmap* good_state_icon_;
|
| + static SkBitmap* bad_state_icon_;
|
| +
|
| + views::ImageView* status_image_;
|
| + views::Label* headline_label_;
|
| + views::Label* description_label_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Section);
|
| +};
|
| +
|
| +// static
|
| +SkBitmap* Section::good_state_icon_ = NULL;
|
| +SkBitmap* Section::bad_state_icon_ = NULL;
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// PageInfoBubbleView
|
| +
|
| +PageInfoBubbleView::PageInfoBubbleView(Profile* profile,
|
| + const GURL& url,
|
| + const NavigationEntry::SSLStatus& ssl,
|
| + bool show_history)
|
| + : ALLOW_THIS_IN_INITIALIZER_LIST(model_(profile, url, ssl,
|
| + show_history, this)),
|
| + cert_id_(ssl.cert_id()),
|
| + info_bubble_(NULL) {
|
| + LayoutSections();
|
| +}
|
| +
|
| +PageInfoBubbleView::~PageInfoBubbleView() {
|
| +}
|
| +
|
| +void PageInfoBubbleView::LayoutSections() {
|
| + // Remove all the existing sections.
|
| + RemoveAllChildViews(true);
|
| +
|
| + views::GridLayout* layout = new views::GridLayout(this);
|
| + SetLayoutManager(layout);
|
| + views::ColumnSet* columns = layout->AddColumnSet(0);
|
| + columns->AddColumn(views::GridLayout::FILL, // Horizontal resize.
|
| + views::GridLayout::FILL, // Vertical resize.
|
| + 1, // Resize weight.
|
| + views::GridLayout::USE_PREF, // Size type.
|
| + 0, // Ignored for USE_PREF.
|
| + 0); // Minimum size.
|
| +
|
| + int count = model_.GetSectionCount();
|
| + for (int i = 0; i < count; ++i) {
|
| + PageInfoModel::SectionInfo info = model_.GetSectionInfo(i);
|
| + layout->StartRow(0, 0);
|
| + // TODO(finnur): Remove title from the info struct, since it is
|
| + // not used anymore.
|
| + layout->AddView(new Section(info.state, info.head_line, info.description));
|
| +
|
| + // Add separator after all sections except the last.
|
| + if (i < count - 1) {
|
| + layout->AddPaddingRow(0, kPaddingAboveSeparator);
|
| + layout->StartRow(0, 0);
|
| + layout->AddView(new views::Separator());
|
| + layout->AddPaddingRow(0, kPaddingBelowSeparator);
|
| + }
|
| + }
|
| +}
|
| +
|
| +gfx::Size PageInfoBubbleView::GetPreferredSize() {
|
| + gfx::Size size(views::Window::GetLocalizedContentsSize(
|
| + IDS_PAGEINFOBUBBLE_WIDTH_CHARS, IDS_PAGEINFOBUBBLE_HEIGHT_LINES));
|
| + size.set_height(0);
|
| +
|
| + int count = model_.GetSectionCount();
|
| + for (int i = 0; i < count; ++i) {
|
| + PageInfoModel::SectionInfo info = model_.GetSectionInfo(i);
|
| + Section section(info.state, info.head_line, info.description);
|
| + size.Enlarge(0, section.GetHeightForWidth(size.width()));
|
| + }
|
| +
|
| + // Account for the separators and padding.
|
| + views::Separator separator;
|
| + gfx::Size separator_size = separator.GetPreferredSize();
|
| + size.Enlarge(0, (count - 1) * (separator_size.height() +
|
| + kPaddingAboveSeparator +
|
| + kPaddingBelowSeparator));
|
| + return size;
|
| +}
|
| +
|
| +void PageInfoBubbleView::ModelChanged() {
|
| + LayoutSections();
|
| + info_bubble_->SizeToContents();
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// Section
|
| +
|
| +Section::Section(bool state,
|
| + const string16& headline,
|
| + const string16& description)
|
| + : state_(state),
|
| + headline_(headline),
|
| + description_(description) {
|
| + if (!good_state_icon_) {
|
| + ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| + good_state_icon_ = rb.GetBitmapNamed(IDR_PAGEINFO_GOOD);
|
| + bad_state_icon_ = rb.GetBitmapNamed(IDR_PAGEINFO_BAD);
|
| + }
|
| +
|
| + status_image_ = new views::ImageView();
|
| + status_image_->SetImage(state ? good_state_icon_ : bad_state_icon_);
|
| + AddChildView(status_image_);
|
| +
|
| + headline_label_ = new views::Label(UTF16ToWideHack(headline));
|
| + headline_label_->SetFont(
|
| + headline_label_->font().DeriveFont(0, gfx::Font::BOLD));
|
| + headline_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| + AddChildView(headline_label_);
|
| +
|
| + description_label_ = new views::Label(UTF16ToWideHack(description));
|
| + description_label_->SetMultiLine(true);
|
| + description_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| + // Allow linebreaking in the middle of words if necessary, so that extremely
|
| + // long hostnames (longer than one line) will still be completely shown.
|
| + description_label_->SetAllowCharacterBreak(true);
|
| + AddChildView(description_label_);
|
| +}
|
| +
|
| +Section::~Section() {
|
| +}
|
| +
|
| +int Section::GetHeightForWidth(int width) {
|
| + return LayoutItems(true, width).height();
|
| +}
|
| +
|
| +void Section::Layout() {
|
| + LayoutItems(false, width());
|
| +}
|
| +
|
| +gfx::Size Section::LayoutItems(bool compute_bounds_only, int width) {
|
| + int x = kHGapToBorder;
|
| + int y = kVGapToImage;
|
| +
|
| + // Layout the image, head-line and description.
|
| + gfx::Size size = status_image_->GetPreferredSize();
|
| + if (!compute_bounds_only)
|
| + status_image_->SetBounds(x, y, size.width(), size.height());
|
| + int image_height = y + size.height();
|
| + x += size.width() + kHGapImageToDescription;
|
| + int w = width - x - kTextPaddingRight;
|
| + y = kVGapToHeadline;
|
| + if (!headline_label_->GetText().empty()) {
|
| + size = headline_label_->GetPreferredSize();
|
| + if (!compute_bounds_only)
|
| + headline_label_->SetBounds(x, y, w > 0 ? w : 0, size.height());
|
| + y += size.height();
|
| + } else {
|
| + if (!compute_bounds_only)
|
| + headline_label_->SetBounds(x, y, 0, 0);
|
| + }
|
| + if (w > 0) {
|
| + int height = description_label_->GetHeightForWidth(w);
|
| + if (!compute_bounds_only)
|
| + description_label_->SetBounds(x, y, w, height);
|
| + y += height;
|
| + } else {
|
| + if (!compute_bounds_only)
|
| + description_label_->SetBounds(x, y, 0, 0);
|
| + }
|
| +
|
| + // Make sure the image is not truncated if the text doesn't contain much.
|
| + y = std::max(y, image_height);
|
| + return gfx::Size(width, y);
|
| +}
|
| +
|
| +namespace browser {
|
| +
|
| +void ShowPageInfoBubble(gfx::NativeWindow parent,
|
| + Profile* profile,
|
| + const GURL& url,
|
| + const NavigationEntry::SSLStatus& ssl,
|
| + bool show_history) {
|
| + // Find where to point the bubble at.
|
| + BrowserView* browser_view =
|
| + BrowserView::GetBrowserViewForNativeWindow(parent);
|
| + gfx::Rect bounds = browser_view->toolbar()->location_bar()->bounds();
|
| + gfx::Point point;
|
| + views::View::ConvertPointToScreen(browser_view->toolbar()->location_bar(),
|
| + &point);
|
| + bounds.set_origin(point);
|
| + bounds.set_width(kIconOffset);
|
| +
|
| + // Show the bubble.
|
| + PageInfoBubbleView* page_info_bubble =
|
| + new PageInfoBubbleView(profile, url, ssl, show_history);
|
| + InfoBubble* info_bubble =
|
| + InfoBubble::Show(browser_view->GetWidget(), bounds,
|
| + BubbleBorder::TOP_LEFT,
|
| + page_info_bubble, page_info_bubble);
|
| + page_info_bubble->set_info_bubble(info_bubble);
|
| +}
|
| +
|
| +}
|
|
|
| Property changes on: chrome\browser\views\page_info_bubble_view.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|