Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(814)

Side by Side Diff: chrome/browser/ui/views/web_intent_picker_view.cc

Issue 9148032: [Web Intents] Refactor picker to use WebIntentPickerModel. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: groby's fix Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/tab_contents/tab_contents_wrapper.cc ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
18 #include "grit/theme_resources_standard.h"
19 #include "grit/ui_resources.h"
20 #include "ui/base/l10n/l10n_util.h" 19 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/resource/resource_bundle.h"
22 #include "ui/gfx/canvas.h" 20 #include "ui/gfx/canvas.h"
23 #include "ui/gfx/canvas_skia.h" 21 #include "ui/gfx/canvas_skia.h"
24 #include "ui/gfx/image/image.h" 22 #include "ui/gfx/image/image.h"
25 #include "ui/views/bubble/bubble_delegate.h" 23 #include "ui/views/bubble/bubble_delegate.h"
26 #include "ui/views/controls/button/image_button.h" 24 #include "ui/views/controls/button/text_button.h"
27 #include "ui/views/controls/image_view.h" 25 #include "ui/views/controls/image_view.h"
28 #include "ui/views/controls/label.h" 26 #include "ui/views/controls/label.h"
29 #include "ui/views/layout/box_layout.h" 27 #include "ui/views/layout/box_layout.h"
30 28
31 using content::WebContents; 29 using content::WebContents;
32 30
33 namespace { 31 namespace {
34 32
35 // The space in pixels between the top-level groups in the dialog. 33 // The space in pixels between the top-level groups in the dialog.
36 const int kContentAreaSpacing = 18; 34 const int kContentAreaSpacing = 18;
37 35
38 // The space in pixels between the top-level groups and the dialog border. 36 // The space in pixels between the top-level groups and the dialog border.
39 const int kContentAreaBorder = 12; 37 const int kContentAreaBorder = 12;
40 38
41 // The space in pixels between controls in a group. 39 // The space in pixels between controls in a group.
42 const int kControlSpacing = 6; 40 const int kControlSpacing = 6;
43 41
44 // The size, relative to default, of the Chrome Web store label. 42 // The size, relative to default, of the Chrome Web store label.
45 const int kWebStoreLabelFontDelta = -2; 43 const int kWebStoreLabelFontDelta = -2;
46 44
47 // Create a new image where |image| is drawn on top of the image identified by
48 // |bg_id|. The result is drawn to |out_image|.
49 void CreateButtonImage(int bg_id, const SkBitmap& image, SkBitmap* out_image) {
50 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
51 SkBitmap bg_bitmap = rb.GetImageNamed(bg_id);
52 bg_bitmap.copyTo(out_image, SkBitmap::kARGB_8888_Config);
53
54 SkPaint paint;
55 paint.setXfermode(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
56
57 SkCanvas bg_canvas(*out_image);
58 bg_canvas.drawBitmap(image,
59 SkIntToScalar((bg_bitmap.width() - image.width()) / 2),
60 SkIntToScalar((bg_bitmap.height() - image.height()) / 2),
61 &paint);
62 }
63
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 45 } // namespace
84 46
85 // Views implementation of WebIntentPicker. 47 // Views implementation of WebIntentPicker.
86 class WebIntentPickerView : public views::BubbleDelegateView, 48 class WebIntentPickerView : public views::BubbleDelegateView,
87 public views::ButtonListener, 49 public views::ButtonListener,
88 public WebIntentPicker { 50 public WebIntentPicker,
51 public WebIntentPickerModelObserver {
89 public: 52 public:
90 WebIntentPickerView(views::View* anchor_view, 53 WebIntentPickerView(views::View* anchor_view,
91 TabContentsWrapper* tab_contents, 54 TabContentsWrapper* tab_contents,
92 WebIntentPickerDelegate* delegate); 55 WebIntentPickerDelegate* delegate,
56 WebIntentPickerModel* model);
93 virtual ~WebIntentPickerView(); 57 virtual ~WebIntentPickerView();
94 58
95 // views::ButtonListener implementation. 59 // views::ButtonListener implementation.
96 virtual void ButtonPressed(views::Button* sender, 60 virtual void ButtonPressed(views::Button* sender,
97 const views::Event& event) OVERRIDE; 61 const views::Event& event) OVERRIDE;
98 62
99 // views::WidgetDelegate implementation. 63 // views::WidgetDelegate implementation.
100 virtual void WindowClosing() OVERRIDE; 64 virtual void WindowClosing() OVERRIDE;
101 65
102 // WebIntentPicker implementation. 66 // 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; 67 virtual void Close() OVERRIDE;
107 virtual content::WebContents* SetInlineDisposition(const GURL& url) OVERRIDE; 68
69 // WebIntentPickerModelObserver implementation.
70 virtual void OnModelChanged(WebIntentPickerModel* model) OVERRIDE;
71 virtual void OnFaviconChanged(WebIntentPickerModel* model,
72 size_t index) OVERRIDE;
73 virtual void OnInlineDisposition(WebIntentPickerModel* model) OVERRIDE;
108 74
109 protected: 75 protected:
110 // views::BubbleDelegateView overrides: 76 // views::BubbleDelegateView overrides:
111 void Init() OVERRIDE; 77 void Init() OVERRIDE;
112 78
113 private: 79 private:
114 // A weak pointer to the WebIntentPickerDelegate to notify when the user 80 // A weak pointer to the WebIntentPickerDelegate to notify when the user
115 // chooses a service or cancels. 81 // chooses a service or cancels.
116 WebIntentPickerDelegate* delegate_; 82 WebIntentPickerDelegate* delegate_;
117 83
84 // Web pointer to the picker model.
85 WebIntentPickerModel* model_;
86
118 // A weak pointer to the hbox that contains the buttons used to choose the 87 // A weak pointer to the hbox that contains the buttons used to choose the
119 // service. 88 // service.
120 views::View* button_hbox_; 89 views::View* button_vbox_;
121 90
122 // A vector of weak pointers to each of the service buttons. 91 // A vector of weak pointers to each of the service buttons.
123 std::vector<views::Button*> buttons_; 92 std::vector<views::TextButton*> buttons_;
124
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 93
129 DISALLOW_COPY_AND_ASSIGN(WebIntentPickerView); 94 DISALLOW_COPY_AND_ASSIGN(WebIntentPickerView);
130 }; 95 };
131 96
132 // static 97 // static
133 WebIntentPicker* WebIntentPicker::Create(Browser* browser, 98 WebIntentPicker* WebIntentPicker::Create(Browser* browser,
134 TabContentsWrapper* wrapper, 99 TabContentsWrapper* wrapper,
135 WebIntentPickerDelegate* delegate) { 100 WebIntentPickerDelegate* delegate,
101 WebIntentPickerModel* model) {
136 // Find where to point the bubble at. 102 // Find where to point the bubble at.
137 BrowserView* browser_view = 103 BrowserView* browser_view =
138 BrowserView::GetBrowserViewForBrowser(browser); 104 BrowserView::GetBrowserViewForBrowser(browser);
139 views::View* anchor_view = 105 views::View* anchor_view =
140 browser_view->toolbar()->location_bar()->location_icon_view(); 106 browser_view->toolbar()->location_bar()->location_icon_view();
141 WebIntentPickerView* bubble_delegate = 107 WebIntentPickerView* bubble_delegate =
142 new WebIntentPickerView(anchor_view, wrapper, delegate); 108 new WebIntentPickerView(anchor_view, wrapper, delegate, model);
143 browser::CreateViewsBubble(bubble_delegate); 109 browser::CreateViewsBubble(bubble_delegate);
144 bubble_delegate->Show(); 110 bubble_delegate->Show();
145 return bubble_delegate; 111 return bubble_delegate;
146 } 112 }
147 113
148 WebIntentPickerView::WebIntentPickerView(views::View* anchor_view, 114 WebIntentPickerView::WebIntentPickerView(views::View* anchor_view,
149 TabContentsWrapper* wrapper, 115 TabContentsWrapper* wrapper,
150 WebIntentPickerDelegate* delegate) 116 WebIntentPickerDelegate* delegate,
117 WebIntentPickerModel* model)
151 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT), 118 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT),
152 delegate_(delegate), 119 delegate_(delegate),
153 button_hbox_(NULL), 120 model_(model),
154 plus_button_(NULL) { 121 button_vbox_(NULL) {
122 model_->set_observer(this);
155 } 123 }
156 124
157 WebIntentPickerView::~WebIntentPickerView() { 125 WebIntentPickerView::~WebIntentPickerView() {
126 model_->set_observer(NULL);
158 } 127 }
159 128
160 void WebIntentPickerView::ButtonPressed(views::Button* sender, 129 void WebIntentPickerView::ButtonPressed(views::Button* sender,
161 const views::Event& event) { 130 const views::Event& event) {
162 // TODO(binji) When we support the plus button, pressing it should forward the 131 std::vector<views::TextButton*>::iterator iter =
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 =
168 std::find(buttons_.begin(), buttons_.end(), sender); 132 std::find(buttons_.begin(), buttons_.end(), sender);
169 DCHECK(iter != buttons_.end()); 133 DCHECK(iter != buttons_.end());
170 134
171 size_t index = iter - buttons_.begin(); 135 size_t index = iter - buttons_.begin();
172 delegate_->OnServiceChosen(index); 136 const WebIntentPickerModel::Item& item = model_->GetItemAt(index);
137
138 delegate_->OnServiceChosen(index, item.disposition);
173 } 139 }
174 140
175 void WebIntentPickerView::WindowClosing() { 141 void WebIntentPickerView::WindowClosing() {
176 delegate_->OnCancelled(); 142 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 } 143 }
211 144
212 void WebIntentPickerView::Close() { 145 void WebIntentPickerView::Close() {
213 GetWidget()->Close(); 146 GetWidget()->Close();
214 } 147 }
215 148
216 WebContents* WebIntentPickerView::SetInlineDisposition(const GURL& url) { 149 void WebIntentPickerView::OnModelChanged(WebIntentPickerModel* model) {
150 button_vbox_->RemoveAllChildViews(true);
151 buttons_.clear();
152
153 for (size_t i = 0; i < model->GetItemCount(); ++i) {
154 const WebIntentPickerModel::Item& item = model_->GetItemAt(i);
155
156 views::TextButton* button = new views::TextButton(this, item.title);
157 button->SetTooltipText(UTF8ToUTF16(item.url.spec().c_str()));
158 button->SetIcon(*item.favicon.ToSkBitmap());
159 button_vbox_->AddChildView(button);
160
161 buttons_.push_back(button);
162 }
163 }
164
165 void WebIntentPickerView::OnFaviconChanged(WebIntentPickerModel* model,
166 size_t index) {
167 const WebIntentPickerModel::Item& item = model_->GetItemAt(index);
168 views::TextButton* button = buttons_[index];
169
170 button->SetIcon(*item.favicon.ToSkBitmap());
171
172 Layout();
173 SizeToContents();
174 }
175
176 void WebIntentPickerView::OnInlineDisposition(WebIntentPickerModel* model) {
217 // TODO(gbillock): add support here. 177 // TODO(gbillock): add support here.
218 return NULL; 178 delegate_->OnInlineDispositionWebContentsCreated(NULL);
219 } 179 }
220 180
221 void WebIntentPickerView::Init() { 181 void WebIntentPickerView::Init() {
222 SetLayoutManager(new views::BoxLayout( 182 SetLayoutManager(new views::BoxLayout(
223 views::BoxLayout::kHorizontal, 183 views::BoxLayout::kHorizontal,
224 kContentAreaBorder, // inside border horizontal spacing 184 kContentAreaBorder, // inside border horizontal spacing
225 kContentAreaBorder, // inside border vertical spacing 185 kContentAreaBorder, // inside border vertical spacing
226 kContentAreaSpacing)); // between child spacing 186 kContentAreaSpacing)); // between child spacing
227 187
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(); 188 views::View* main_content = new views::View();
236 main_content->SetLayoutManager(new views::BoxLayout( 189 main_content->SetLayoutManager(new views::BoxLayout(
237 views::BoxLayout::kVertical, 190 views::BoxLayout::kVertical,
238 0, // inside border horizontal spacing 191 0, // inside border horizontal spacing
239 0, // inside border vertical spacing 192 0, // inside border vertical spacing
240 kContentAreaSpacing)); // between child spacing 193 kContentAreaSpacing)); // between child spacing
241 194
242 views::Label* top_label = new views::Label( 195 views::Label* top_label = new views::Label(
243 l10n_util::GetStringUTF16(IDS_CHOOSE_INTENT_HANDLER_MESSAGE)); 196 l10n_util::GetStringUTF16(IDS_CHOOSE_INTENT_HANDLER_MESSAGE));
244 top_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 197 top_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
245 main_content->AddChildView(top_label); 198 main_content->AddChildView(top_label);
246 199
247 button_hbox_ = new views::View(); 200 button_vbox_ = new views::View();
248 button_hbox_->SetLayoutManager(new views::BoxLayout( 201 button_vbox_->SetLayoutManager(new views::BoxLayout(
249 views::BoxLayout::kHorizontal, 202 views::BoxLayout::kVertical,
250 0, // inside border horizontal spacing 203 0, // inside border horizontal spacing
251 0, // inside border vertical spacing 204 0, // inside border vertical spacing
252 kControlSpacing)); // between child spacing 205 kControlSpacing)); // between child spacing
253 main_content->AddChildView(button_hbox_); 206 main_content->AddChildView(button_vbox_);
254 207
255 views::Label* bottom_label = new views::Label( 208 views::Label* bottom_label = new views::Label(
256 l10n_util::GetStringUTF16(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE)); 209 l10n_util::GetStringUTF16(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE));
257 bottom_label->SetMultiLine(true); 210 bottom_label->SetMultiLine(true);
258 bottom_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 211 bottom_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
259 bottom_label->SetFont( 212 bottom_label->SetFont(
260 bottom_label->font().DeriveFont(kWebStoreLabelFontDelta)); 213 bottom_label->font().DeriveFont(kWebStoreLabelFontDelta));
261 main_content->AddChildView(bottom_label); 214 main_content->AddChildView(bottom_label);
262 215
263 AddChildView(main_content); 216 AddChildView(main_content);
264 } 217 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/tab_contents/tab_contents_wrapper.cc ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698