Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <algorithm> | 5 #include <algorithm> |
| 6 #include <vector> | 6 #include <vector> |
| 7 | 7 |
| 8 #include "chrome/browser/ui/browser.h" | 8 #include "chrome/browser/ui/browser.h" |
| 9 #include "chrome/browser/ui/intents/web_intent_picker.h" | 9 #include "chrome/browser/ui/intents/web_intent_picker.h" |
| 10 #include "chrome/browser/ui/intents/web_intent_picker_delegate.h" | 10 #include "chrome/browser/ui/intents/web_intent_picker_delegate.h" |
| 11 #include "chrome/browser/ui/intents/web_intent_picker_model.h" | |
| 12 #include "chrome/browser/ui/intents/web_intent_picker_model_observer.h" | |
| 11 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 13 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 12 #include "chrome/browser/ui/views/frame/browser_view.h" | 14 #include "chrome/browser/ui/views/frame/browser_view.h" |
| 13 #include "chrome/browser/ui/views/location_bar/location_icon_view.h" | 15 #include "chrome/browser/ui/views/location_bar/location_icon_view.h" |
| 14 #include "chrome/browser/ui/views/toolbar_view.h" | 16 #include "chrome/browser/ui/views/toolbar_view.h" |
| 15 #include "chrome/browser/ui/views/window.h" | 17 #include "chrome/browser/ui/views/window.h" |
| 16 #include "grit/generated_resources.h" | 18 #include "grit/generated_resources.h" |
| 17 #include "grit/theme_resources.h" | 19 #include "grit/theme_resources.h" |
| 18 #include "grit/theme_resources_standard.h" | 20 #include "grit/theme_resources_standard.h" |
| 19 #include "grit/ui_resources.h" | 21 #include "grit/ui_resources.h" |
| 20 #include "ui/base/l10n/l10n_util.h" | 22 #include "ui/base/l10n/l10n_util.h" |
| 21 #include "ui/base/resource/resource_bundle.h" | 23 #include "ui/base/resource/resource_bundle.h" |
| 22 #include "ui/gfx/canvas.h" | 24 #include "ui/gfx/canvas.h" |
| 23 #include "ui/gfx/canvas_skia.h" | 25 #include "ui/gfx/canvas_skia.h" |
| 24 #include "ui/gfx/image/image.h" | 26 #include "ui/gfx/image/image.h" |
| 25 #include "ui/views/bubble/bubble_delegate.h" | 27 #include "ui/views/bubble/bubble_delegate.h" |
| 26 #include "ui/views/controls/button/image_button.h" | 28 #include "ui/views/controls/button/text_button.h" |
| 27 #include "ui/views/controls/image_view.h" | 29 #include "ui/views/controls/image_view.h" |
| 28 #include "ui/views/controls/label.h" | 30 #include "ui/views/controls/label.h" |
| 29 #include "ui/views/layout/box_layout.h" | 31 #include "ui/views/layout/box_layout.h" |
| 30 | 32 |
| 31 using content::WebContents; | 33 using content::WebContents; |
| 32 | 34 |
| 33 namespace { | 35 namespace { |
| 34 | 36 |
| 35 // The space in pixels between the top-level groups in the dialog. | 37 // The space in pixels between the top-level groups in the dialog. |
| 36 const int kContentAreaSpacing = 18; | 38 const int kContentAreaSpacing = 18; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 54 SkPaint paint; | 56 SkPaint paint; |
| 55 paint.setXfermode(SkXfermode::Create(SkXfermode::kSrcOver_Mode)); | 57 paint.setXfermode(SkXfermode::Create(SkXfermode::kSrcOver_Mode)); |
| 56 | 58 |
| 57 SkCanvas bg_canvas(*out_image); | 59 SkCanvas bg_canvas(*out_image); |
| 58 bg_canvas.drawBitmap(image, | 60 bg_canvas.drawBitmap(image, |
| 59 SkIntToScalar((bg_bitmap.width() - image.width()) / 2), | 61 SkIntToScalar((bg_bitmap.width() - image.width()) / 2), |
| 60 SkIntToScalar((bg_bitmap.height() - image.height()) / 2), | 62 SkIntToScalar((bg_bitmap.height() - image.height()) / 2), |
| 61 &paint); | 63 &paint); |
| 62 } | 64 } |
| 63 | 65 |
| 64 // Set the images on |button| for states normal, hot, and pushed. | |
| 65 // The images are generated by drawing |image| on top of the identified by | |
| 66 // |bg_normal_id|, |bg_hot_id|, and |bg_pushed_id| respectively. | |
| 67 void SetButtonImages(views::ImageButton* button, | |
| 68 const SkBitmap& image, | |
| 69 int bg_normal_id, int bg_hot_id, int bg_pushed_id) { | |
| 70 SkBitmap image_normal; | |
| 71 CreateButtonImage(bg_normal_id, image, &image_normal); | |
| 72 button->SetImage(views::CustomButton::BS_NORMAL, &image_normal); | |
| 73 | |
| 74 SkBitmap image_hot; | |
| 75 CreateButtonImage(bg_hot_id, image, &image_hot); | |
| 76 button->SetImage(views::CustomButton::BS_HOT, &image_hot); | |
| 77 | |
| 78 SkBitmap image_pushed; | |
| 79 CreateButtonImage(bg_pushed_id, image, &image_pushed); | |
| 80 button->SetImage(views::CustomButton::BS_PUSHED, &image_pushed); | |
| 81 } | |
| 82 | |
| 83 } // namespace | 66 } // namespace |
| 84 | 67 |
| 85 // Views implementation of WebIntentPicker. | 68 // Views implementation of WebIntentPicker. |
| 86 class WebIntentPickerView : public views::BubbleDelegateView, | 69 class WebIntentPickerView : public views::BubbleDelegateView, |
| 87 public views::ButtonListener, | 70 public views::ButtonListener, |
| 88 public WebIntentPicker { | 71 public WebIntentPicker, |
| 72 public WebIntentPickerModelObserver { | |
| 89 public: | 73 public: |
| 90 WebIntentPickerView(views::View* anchor_view, | 74 WebIntentPickerView(views::View* anchor_view, |
| 91 TabContentsWrapper* tab_contents, | 75 TabContentsWrapper* tab_contents, |
| 92 WebIntentPickerDelegate* delegate); | 76 WebIntentPickerDelegate* delegate, |
| 77 WebIntentPickerModel* model); | |
| 93 virtual ~WebIntentPickerView(); | 78 virtual ~WebIntentPickerView(); |
| 94 | 79 |
| 95 // views::ButtonListener implementation. | 80 // views::ButtonListener implementation. |
| 96 virtual void ButtonPressed(views::Button* sender, | 81 virtual void ButtonPressed(views::Button* sender, |
| 97 const views::Event& event) OVERRIDE; | 82 const views::Event& event) OVERRIDE; |
| 98 | 83 |
| 99 // views::WidgetDelegate implementation. | 84 // views::WidgetDelegate implementation. |
| 100 virtual void WindowClosing() OVERRIDE; | 85 virtual void WindowClosing() OVERRIDE; |
| 101 | 86 |
| 102 // WebIntentPicker implementation. | 87 // WebIntentPicker implementation. |
| 103 virtual void SetServiceURLs(const std::vector<GURL>& urls) OVERRIDE; | |
| 104 virtual void SetServiceIcon(size_t index, const SkBitmap& icon) OVERRIDE; | |
| 105 virtual void SetDefaultServiceIcon(size_t index) OVERRIDE; | |
| 106 virtual void Close() OVERRIDE; | 88 virtual void Close() OVERRIDE; |
| 107 virtual content::WebContents* SetInlineDisposition(const GURL& url) OVERRIDE; | 89 |
| 90 // WebIntentPickerModelObserver implementation. | |
| 91 virtual void OnModelChanged(WebIntentPickerModel* model) OVERRIDE; | |
| 92 virtual void OnFaviconChanged(WebIntentPickerModel* model, | |
| 93 size_t index) OVERRIDE; | |
| 94 virtual void OnInlineDisposition(WebIntentPickerModel* model) OVERRIDE; | |
| 108 | 95 |
| 109 protected: | 96 protected: |
| 110 // views::BubbleDelegateView overrides: | 97 // views::BubbleDelegateView overrides: |
| 111 void Init() OVERRIDE; | 98 void Init() OVERRIDE; |
| 112 | 99 |
| 113 private: | 100 private: |
| 114 // A weak pointer to the WebIntentPickerDelegate to notify when the user | 101 // A weak pointer to the WebIntentPickerDelegate to notify when the user |
| 115 // chooses a service or cancels. | 102 // chooses a service or cancels. |
| 116 WebIntentPickerDelegate* delegate_; | 103 WebIntentPickerDelegate* delegate_; |
| 117 | 104 |
| 105 // Web pointer to the picker model. | |
| 106 WebIntentPickerModel* model_; | |
| 107 | |
| 118 // A weak pointer to the hbox that contains the buttons used to choose the | 108 // A weak pointer to the hbox that contains the buttons used to choose the |
| 119 // service. | 109 // service. |
| 120 views::View* button_hbox_; | 110 views::View* button_vbox_; |
| 121 | 111 |
| 122 // A vector of weak pointers to each of the service buttons. | 112 // A vector of weak pointers to each of the service buttons. |
| 123 std::vector<views::Button*> buttons_; | 113 std::vector<views::Button*> buttons_; |
| 124 | 114 |
| 125 // A weak pointer to the plus button, used to search for more services on the | |
| 126 // Chrome Web Store. | |
| 127 views::ImageButton* plus_button_; | |
| 128 | |
| 129 DISALLOW_COPY_AND_ASSIGN(WebIntentPickerView); | 115 DISALLOW_COPY_AND_ASSIGN(WebIntentPickerView); |
| 130 }; | 116 }; |
| 131 | 117 |
| 132 // static | 118 // static |
| 133 WebIntentPicker* WebIntentPicker::Create(Browser* browser, | 119 WebIntentPicker* WebIntentPicker::Create(Browser* browser, |
| 134 TabContentsWrapper* wrapper, | 120 TabContentsWrapper* wrapper, |
| 135 WebIntentPickerDelegate* delegate) { | 121 WebIntentPickerDelegate* delegate, |
| 122 WebIntentPickerModel* model) { | |
| 136 // Find where to point the bubble at. | 123 // Find where to point the bubble at. |
| 137 BrowserView* browser_view = | 124 BrowserView* browser_view = |
| 138 BrowserView::GetBrowserViewForBrowser(browser); | 125 BrowserView::GetBrowserViewForBrowser(browser); |
| 139 views::View* anchor_view = | 126 views::View* anchor_view = |
| 140 browser_view->toolbar()->location_bar()->location_icon_view(); | 127 browser_view->toolbar()->location_bar()->location_icon_view(); |
| 141 WebIntentPickerView* bubble_delegate = | 128 WebIntentPickerView* bubble_delegate = |
| 142 new WebIntentPickerView(anchor_view, wrapper, delegate); | 129 new WebIntentPickerView(anchor_view, wrapper, delegate, model); |
| 143 browser::CreateViewsBubble(bubble_delegate); | 130 browser::CreateViewsBubble(bubble_delegate); |
| 144 bubble_delegate->Show(); | 131 bubble_delegate->Show(); |
| 145 return bubble_delegate; | 132 return bubble_delegate; |
| 146 } | 133 } |
| 147 | 134 |
| 148 WebIntentPickerView::WebIntentPickerView(views::View* anchor_view, | 135 WebIntentPickerView::WebIntentPickerView(views::View* anchor_view, |
| 149 TabContentsWrapper* wrapper, | 136 TabContentsWrapper* wrapper, |
| 150 WebIntentPickerDelegate* delegate) | 137 WebIntentPickerDelegate* delegate, |
| 138 WebIntentPickerModel* model) | |
| 151 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT), | 139 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT), |
| 152 delegate_(delegate), | 140 delegate_(delegate), |
| 153 button_hbox_(NULL), | 141 model_(model), |
| 154 plus_button_(NULL) { | 142 button_vbox_(NULL) { |
| 143 model_->set_observer(this); | |
| 155 } | 144 } |
| 156 | 145 |
| 157 WebIntentPickerView::~WebIntentPickerView() { | 146 WebIntentPickerView::~WebIntentPickerView() { |
| 147 model_->set_observer(NULL); | |
| 158 } | 148 } |
| 159 | 149 |
| 160 void WebIntentPickerView::ButtonPressed(views::Button* sender, | 150 void WebIntentPickerView::ButtonPressed(views::Button* sender, |
| 161 const views::Event& event) { | 151 const views::Event& event) { |
| 162 // TODO(binji) When we support the plus button, pressing it should forward the | |
| 163 // user to services in the Chrome Web Store that provide this intent. | |
| 164 if (sender == plus_button_) | |
| 165 return; | |
| 166 | |
| 167 std::vector<views::Button*>::iterator iter = | 152 std::vector<views::Button*>::iterator iter = |
| 168 std::find(buttons_.begin(), buttons_.end(), sender); | 153 std::find(buttons_.begin(), buttons_.end(), sender); |
| 169 DCHECK(iter != buttons_.end()); | 154 DCHECK(iter != buttons_.end()); |
| 170 | 155 |
| 171 size_t index = iter - buttons_.begin(); | 156 size_t index = iter - buttons_.begin(); |
| 172 delegate_->OnServiceChosen(index); | 157 const WebIntentPickerModel::Item& item = model_->GetItemAt(index); |
| 158 | |
| 159 delegate_->OnServiceChosen(index, item.disposition); | |
| 173 } | 160 } |
| 174 | 161 |
| 175 void WebIntentPickerView::WindowClosing() { | 162 void WebIntentPickerView::WindowClosing() { |
| 176 delegate_->OnCancelled(); | 163 delegate_->OnClosing(); |
| 177 } | |
| 178 | |
| 179 void WebIntentPickerView::SetServiceURLs(const std::vector<GURL>& urls) { | |
| 180 for (size_t i = 0; i < urls.size(); ++i) { | |
| 181 views::ImageButton* button = new views::ImageButton(this); | |
| 182 button->SetTooltipText(UTF8ToUTF16(urls[i].spec().c_str())); | |
| 183 button_hbox_->AddChildView(button); | |
| 184 buttons_.push_back(button); | |
| 185 } | |
| 186 | |
| 187 // Add the '+' button, to use the Chrome Web Store. | |
| 188 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 189 plus_button_ = new views::ImageButton(this); | |
| 190 plus_button_->SetTooltipText( | |
| 191 l10n_util::GetStringUTF16(IDS_FIND_MORE_INTENT_HANDLER_TOOLTIP)); | |
| 192 SetButtonImages(plus_button_, rb.GetImageNamed(IDR_SIDETABS_NEW_TAB), | |
| 193 IDR_BROWSER_ACTION, IDR_BROWSER_ACTION_H, IDR_BROWSER_ACTION_P); | |
| 194 button_hbox_->AddChildView(plus_button_); | |
| 195 } | |
| 196 | |
| 197 void WebIntentPickerView::SetServiceIcon(size_t index, const SkBitmap& icon) { | |
| 198 views::ImageButton* button = | |
| 199 static_cast<views::ImageButton*>(button_hbox_->child_at(index)); | |
| 200 SetButtonImages(button, icon, | |
| 201 IDR_BROWSER_ACTION, IDR_BROWSER_ACTION_H, IDR_BROWSER_ACTION_P); | |
| 202 | |
| 203 Layout(); | |
| 204 SizeToContents(); | |
| 205 } | |
| 206 | |
| 207 void WebIntentPickerView::SetDefaultServiceIcon(size_t index) { | |
| 208 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 209 SetServiceIcon(index, rb.GetImageNamed(IDR_DEFAULT_FAVICON)); | |
| 210 } | 164 } |
| 211 | 165 |
| 212 void WebIntentPickerView::Close() { | 166 void WebIntentPickerView::Close() { |
| 213 GetWidget()->Close(); | 167 GetWidget()->Close(); |
| 214 } | 168 } |
| 215 | 169 |
| 216 WebContents* WebIntentPickerView::SetInlineDisposition(const GURL& url) { | 170 void WebIntentPickerView::OnModelChanged(WebIntentPickerModel* model) { |
| 171 button_vbox_->RemoveAllChildViews(true); | |
| 172 buttons_.clear(); | |
| 173 | |
| 174 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 175 | |
| 176 for (size_t i = 0; i < model->GetItemCount(); ++i) { | |
| 177 const WebIntentPickerModel::Item& item = model_->GetItemAt(i); | |
| 178 | |
| 179 views::TextButton* button = new views::TextButton(this, item.title); | |
| 180 button->SetTooltipText(UTF8ToUTF16(item.url.spec().c_str())); | |
| 181 button->SetIcon(rb.GetImageNamed(IDR_DEFAULT_FAVICON)); | |
|
groby-ooo-7-16
2012/01/25 22:03:13
Favicons should probably be handled by the model.
| |
| 182 button_vbox_->AddChildView(button); | |
| 183 | |
| 184 buttons_.push_back(button); | |
| 185 } | |
| 186 } | |
| 187 | |
| 188 void WebIntentPickerView::OnFaviconChanged(WebIntentPickerModel* model, | |
| 189 size_t index) { | |
| 190 const WebIntentPickerModel::Item& item = model_->GetItemAt(index); | |
| 191 views::TextButton* button = | |
| 192 static_cast<views::TextButton*>(buttons_[index]); | |
| 193 | |
| 194 button->SetIcon(*item.favicon->ToSkBitmap()); | |
| 195 | |
| 196 Layout(); | |
| 197 SizeToContents(); | |
| 198 } | |
| 199 | |
| 200 void WebIntentPickerView::OnInlineDisposition(WebIntentPickerModel* model) { | |
| 217 // TODO(gbillock): add support here. | 201 // TODO(gbillock): add support here. |
| 218 return NULL; | 202 delegate_->OnInlineDispositionWebContentsCreated(NULL); |
| 219 } | 203 } |
| 220 | 204 |
| 221 void WebIntentPickerView::Init() { | 205 void WebIntentPickerView::Init() { |
| 222 SetLayoutManager(new views::BoxLayout( | 206 SetLayoutManager(new views::BoxLayout( |
| 223 views::BoxLayout::kHorizontal, | 207 views::BoxLayout::kHorizontal, |
| 224 kContentAreaBorder, // inside border horizontal spacing | 208 kContentAreaBorder, // inside border horizontal spacing |
| 225 kContentAreaBorder, // inside border vertical spacing | 209 kContentAreaBorder, // inside border vertical spacing |
| 226 kContentAreaSpacing)); // between child spacing | 210 kContentAreaSpacing)); // between child spacing |
| 227 | 211 |
| 228 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 229 SkBitmap image_bitmap = rb.GetImageNamed(IDR_PAGEINFO_INFO); | |
| 230 views::ImageView* image = new views::ImageView(); | |
| 231 image->SetImage(image_bitmap); | |
| 232 image->SetVerticalAlignment(views::ImageView::LEADING); | |
| 233 AddChildView(image); | |
| 234 | |
| 235 views::View* main_content = new views::View(); | 212 views::View* main_content = new views::View(); |
| 236 main_content->SetLayoutManager(new views::BoxLayout( | 213 main_content->SetLayoutManager(new views::BoxLayout( |
| 237 views::BoxLayout::kVertical, | 214 views::BoxLayout::kVertical, |
| 238 0, // inside border horizontal spacing | 215 0, // inside border horizontal spacing |
| 239 0, // inside border vertical spacing | 216 0, // inside border vertical spacing |
| 240 kContentAreaSpacing)); // between child spacing | 217 kContentAreaSpacing)); // between child spacing |
| 241 | 218 |
| 242 views::Label* top_label = new views::Label( | 219 views::Label* top_label = new views::Label( |
| 243 l10n_util::GetStringUTF16(IDS_CHOOSE_INTENT_HANDLER_MESSAGE)); | 220 l10n_util::GetStringUTF16(IDS_CHOOSE_INTENT_HANDLER_MESSAGE)); |
| 244 top_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | 221 top_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 245 main_content->AddChildView(top_label); | 222 main_content->AddChildView(top_label); |
| 246 | 223 |
| 247 button_hbox_ = new views::View(); | 224 button_vbox_ = new views::View(); |
| 248 button_hbox_->SetLayoutManager(new views::BoxLayout( | 225 button_vbox_->SetLayoutManager(new views::BoxLayout( |
| 249 views::BoxLayout::kHorizontal, | 226 views::BoxLayout::kVertical, |
| 250 0, // inside border horizontal spacing | 227 0, // inside border horizontal spacing |
| 251 0, // inside border vertical spacing | 228 0, // inside border vertical spacing |
| 252 kControlSpacing)); // between child spacing | 229 kControlSpacing)); // between child spacing |
| 253 main_content->AddChildView(button_hbox_); | 230 main_content->AddChildView(button_vbox_); |
| 254 | 231 |
| 255 views::Label* bottom_label = new views::Label( | 232 views::Label* bottom_label = new views::Label( |
| 256 l10n_util::GetStringUTF16(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE)); | 233 l10n_util::GetStringUTF16(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE)); |
| 257 bottom_label->SetMultiLine(true); | 234 bottom_label->SetMultiLine(true); |
| 258 bottom_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | 235 bottom_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 259 bottom_label->SetFont( | 236 bottom_label->SetFont( |
| 260 bottom_label->font().DeriveFont(kWebStoreLabelFontDelta)); | 237 bottom_label->font().DeriveFont(kWebStoreLabelFontDelta)); |
| 261 main_content->AddChildView(bottom_label); | 238 main_content->AddChildView(bottom_label); |
| 262 | 239 |
| 263 AddChildView(main_content); | 240 AddChildView(main_content); |
| 264 } | 241 } |
| OLD | NEW |