invert_bubble_view.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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. 4 5#include "chrome/browser/ui/views/accessibility/invert_bubble_view.h" 6 7#include "base/prefs/pref_service.h" 8#include "chrome/browser/profiles/profile.h" 9#include "chrome/browser/ui/browser.h" 10#include "chrome/browser/ui/views/frame/browser_view.h" 11#include "chrome/browser/ui/views/toolbar/toolbar_view.h" 12#include "chrome/common/pref_names.h" 13#include "content/public/browser/page_navigator.h" 14#include "grit/generated_resources.h" 15#include "ui/base/l10n/l10n_util.h" 16#include "ui/base/resource/resource_bundle.h" 17#include "ui/base/window_open_disposition.h" 18#include "ui/views/bubble/bubble_delegate.h" 19#include "ui/views/controls/label.h" 20#include "ui/views/controls/link.h" 21#include "ui/views/controls/link_listener.h" 22#include "ui/views/layout/grid_layout.h" 23#include "ui/views/layout/layout_constants.h" 24#include "ui/views/widget/widget.h" 25 26namespace { 27 28const char kHighContrastExtensionUrl[] = 29 "https://chrome.google.com/webstore/detail/djcfdncoelnlbldjfhinnjlhdjlikmph"; 30const char kDarkThemeSearchUrl[] = 31 "https://chrome.google.com/webstore/search-themes/dark"; 32const char kLearnMoreUrl[] = 33 "https://groups.google.com/a/googleproductforums.com/d/topic/chrome/Xrco2HsXS-8/discussion"; 34const int kBubbleWidth = 500; 35 36class InvertBubbleView : public views::BubbleDelegateView, 37 public views::LinkListener { 38 public: 39 InvertBubbleView(Browser* browser, views::View* anchor_view); 40 virtual ~InvertBubbleView(); 41 42 private: 43 // Overridden from views::BubbleDelegateView: 44 virtual void Init() OVERRIDE; 45 46 // Overridden from views::LinkListener: 47 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 48 49 void OpenLink(const std::string& url, int event_flags); 50 51 Browser* browser_; 52 views::Link* high_contrast_; 53 views::Link* dark_theme_; 54 views::Link* learn_more_; 55 views::Link* close_; 56 57 DISALLOW_COPY_AND_ASSIGN(InvertBubbleView); 58}; 59 60InvertBubbleView::InvertBubbleView(Browser* browser, views::View* anchor_view) 61 : views::BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT), 62 browser_(browser), 63 high_contrast_(NULL), 64 dark_theme_(NULL), 65 learn_more_(NULL), 66 close_(NULL) { 67} 68 69InvertBubbleView::~InvertBubbleView() { 70} 71 72void InvertBubbleView::Init() { 73 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 74 const gfx::FontList& original_font_list = 75 rb.GetFontList(ui::ResourceBundle::MediumFont); 76 77 views::Label* title = new views::Label( 78 l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_NOTIFICATION), 79 original_font_list.Derive(2, gfx::Font::BOLD)); 80 title->SetMultiLine(true); 81 title->SizeToFit(kBubbleWidth); 82 83 learn_more_ = new views::Link(l10n_util::GetStringUTF16(IDS_LEARN_MORE)); 84 learn_more_->SetFontList(original_font_list); 85 learn_more_->set_listener(this); 86 87 high_contrast_ = 88 new views::Link(l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_EXT)); 89 high_contrast_->SetFontList(original_font_list); 90 high_contrast_->set_listener(this); 91 92 dark_theme_ = 93 new views::Link(l10n_util::GetStringUTF16(IDS_DARK_THEME)); 94 dark_theme_->SetFontList(original_font_list); 95 dark_theme_->set_listener(this); 96 97 close_ = new views::Link(l10n_util::GetStringUTF16(IDS_CLOSE)); 98 close_->SetFontList(original_font_list); 99 close_->set_listener(this); 100 101 views::GridLayout* layout = views::GridLayout::CreatePanel(this); 102 SetLayoutManager(layout); 103 104 views::ColumnSet* columns = layout->AddColumnSet(0); 105 for (int i = 0; i < 4; i++) { 106 columns->AddColumn(views::GridLayout::LEADING, 107 views::GridLayout::LEADING, 0, 108 views::GridLayout::USE_PREF, 0, 0); 109 } 110 111 layout->StartRow(0, 0); 112 layout->AddView(title, 4, 1); 113 layout->StartRowWithPadding(0, 0, 0, 114 views::kRelatedControlSmallVerticalSpacing); 115 layout->AddView(high_contrast_); 116 layout->AddView(dark_theme_); 117 layout->AddView(learn_more_); 118 layout->AddView(close_); 119 120 // Switching to high-contrast mode has a nasty habit of causing Chrome 121 // top-level windows to lose focus, so closing the bubble on deactivate 122 // makes it disappear before the user has even seen it. This forces the 123 // user to close it explicitly, which should be okay because it affects 124 // a small minority of users, and only once. 125 set_close_on_deactivate(false); 126 set_move_with_anchor(true); 127} 128 129void InvertBubbleView::LinkClicked(views::Link* source, int event_flags) { 130 if (source == high_contrast_) 131 OpenLink(kHighContrastExtensionUrl, event_flags); 132 else if (source == dark_theme_) 133 OpenLink(kDarkThemeSearchUrl, event_flags); 134 else if (source == learn_more_) 135 OpenLink(kLearnMoreUrl, event_flags); 136 else if (source == close_) 137 GetWidget()->Close(); 138 else 139 NOTREACHED(); 140} 141 142void InvertBubbleView::OpenLink(const std::string& url, int event_flags) { 143 WindowOpenDisposition disposition = 144 ui::DispositionFromEventFlags(event_flags); 145 content::OpenURLParams params( 146 GURL(url), content::Referrer(), 147 disposition == CURRENT_TAB ? NEW_FOREGROUND_TAB : disposition, 148 content::PAGE_TRANSITION_LINK, false); 149 browser_->OpenURL(params); 150} 151 152} // namespace 153 154namespace chrome { 155 156void MaybeShowInvertBubbleView(BrowserView* browser_view) { 157 Browser* browser = browser_view->browser(); 158 PrefService* pref_service = browser->profile()->GetPrefs(); 159 views::View* anchor = browser_view->toolbar()->app_menu(); 160 if (gfx::IsInvertedColorScheme() && anchor && anchor->GetWidget() && 161 !pref_service->GetBoolean(prefs::kInvertNotificationShown)) { 162 pref_service->SetBoolean(prefs::kInvertNotificationShown, true); 163 InvertBubbleView* delegate = new InvertBubbleView(browser, anchor); 164 views::BubbleDelegateView::CreateBubble(delegate)->Show(); 165 } 166} 167 168} // namespace chrome 169