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

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

Issue 9443007: Add Chrome To Mobile Service and Views Page Action. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Bail on empty GetOAuth2LoginRefreshToken(). Created 8 years, 9 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
OLDNEW
(Empty)
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/chrome_to_mobile_bubble_view.h"
6
7 #include "base/bind.h"
8 #include "base/file_util.h"
9 #include "base/string16.h"
10 #include "base/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "chrome/app/chrome_command_ids.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/chrome_to_mobile_service.h"
15 #include "chrome/browser/chrome_to_mobile_service_factory.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/ui/views/window.h"
18 #include "grit/generated_resources.h"
19 #include "grit/theme_resources.h"
20 #include "ui/base/animation/throb_animation.h"
21 #include "ui/base/keycodes/keyboard_codes.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/base/resource/resource_bundle.h"
24 #include "ui/base/text/bytes_formatting.h"
25 #include "ui/views/controls/button/checkbox.h"
26 #include "ui/views/controls/button/radio_button.h"
27 #include "ui/views/controls/button/text_button.h"
28 #include "ui/views/controls/label.h"
29 #include "ui/views/events/event.h"
30 #include "ui/views/layout/grid_layout.h"
31 #include "ui/views/layout/layout_constants.h"
32
33 using views::GridLayout;
34
35 namespace {
36
37 // The millisecond duration of the "Sending..." progress throb animation.
38 const size_t kProgressThrobDurationMS = 2400;
39
40 // The bubble's margin for the "Sending..." and "Sent" states.
41 const size_t kProgressMargin = 20;
42
43 // The title label's color; matches the bookmark bubble's title.
44 const SkColor kTitleColor = 0xFF062D75;
45
46 } // namespace
47
48 // Declared in browser_dialogs.h so callers don't have to depend on our header.
49
50 namespace browser {
51
52 void ShowChromeToMobileBubbleView(views::View* anchor_view, Profile* profile) {
53 ChromeToMobileBubbleView::ShowBubble(anchor_view, profile);
54 }
55
56 void HideChromeToMobileBubbleView() {
57 ChromeToMobileBubbleView::Hide();
58 }
59
60 bool IsChromeToMobileBubbleViewShowing() {
61 return ChromeToMobileBubbleView::IsShowing();
62 }
63
64 } // namespace browser
65
66 // ChromeToMobileBubbleView ----------------------------------------------------
67
68 ChromeToMobileBubbleView* ChromeToMobileBubbleView::bubble_ = NULL;
69
70 ChromeToMobileBubbleView::~ChromeToMobileBubbleView() {}
71
72 // static
73 void ChromeToMobileBubbleView::ShowBubble(views::View* anchor_view,
74 Profile* profile) {
75 if (IsShowing())
76 return;
77
78 bubble_ = new ChromeToMobileBubbleView(anchor_view, profile);
79 browser::CreateViewsBubble(bubble_);
80 bubble_->Show();
81 }
82
83 // static
84 bool ChromeToMobileBubbleView::IsShowing() {
85 return bubble_ != NULL;
86 }
87
88 void ChromeToMobileBubbleView::Hide() {
89 if (IsShowing())
90 bubble_->GetWidget()->Close();
91 }
92
93 views::View* ChromeToMobileBubbleView::GetInitiallyFocusedView() {
94 return send_;
95 }
96
97 gfx::Rect ChromeToMobileBubbleView::GetAnchorRect() {
98 // Compensate for some built-in padding in the arrow image.
99 gfx::Rect rect(BubbleDelegateView::GetAnchorRect());
100 rect.Inset(0, anchor_view() ? 5 : 0);
101 return rect;
102 }
103
104 void ChromeToMobileBubbleView::WindowClosing() {
105 // We have to reset |bubble_| here, not in our destructor, because we'll be
106 // destroyed asynchronously and the shown state will be checked before then.
107 DCHECK(bubble_ == this);
108 bubble_ = NULL;
109 }
110
111 bool ChromeToMobileBubbleView::AcceleratorPressed(
112 const ui::Accelerator& accelerator) {
113 if (accelerator.key_code() == ui::VKEY_RETURN &&
114 (send_->HasFocus() || cancel_->HasFocus())) {
115 HandleButtonPressed(send_->HasFocus() ? send_ : cancel_);
116 return true;
117 }
118 return BubbleDelegateView::AcceleratorPressed(accelerator);
119 }
120
121 void ChromeToMobileBubbleView::AnimationProgressed(
122 const ui::Animation* animation) {
123 if (animation == progress_animation_.get()) {
124 double animation_value = animation->GetCurrentValue();
125 int message = IDS_CHROME_TO_MOBILE_BUBBLE_SENDING_3;
126 // Show each of four messages for 1/4 of the animation.
127 if (animation_value < 0.25)
128 message = IDS_CHROME_TO_MOBILE_BUBBLE_SENDING_0;
129 else if (animation_value < 0.5)
130 message = IDS_CHROME_TO_MOBILE_BUBBLE_SENDING_1;
131 else if (animation_value < 0.75)
132 message = IDS_CHROME_TO_MOBILE_BUBBLE_SENDING_2;
133 progress_label_->SetText(l10n_util::GetStringUTF16(message));
134 // Run Layout but do not resize the bubble for each progress message.
135 Layout();
136 return;
137 }
138 views::BubbleDelegateView::AnimationProgressed(animation);
139 }
140
141 void ChromeToMobileBubbleView::ButtonPressed(views::Button* sender,
142 const views::Event& event) {
143 HandleButtonPressed(sender);
144 }
145
146 void ChromeToMobileBubbleView::SnapshotGenerated(const FilePath& path,
147 int64 bytes) {
148 if (bytes > 0) {
149 snapshot_path_ = path;
150 send_copy_->SetText(l10n_util::GetStringFUTF16(
151 IDS_CHROME_TO_MOBILE_BUBBLE_SEND_COPY, ui::FormatBytes(bytes)));
152 send_copy_->SetEnabled(true);
153 } else {
154 send_copy_->SetText(l10n_util::GetStringUTF16(
155 IDS_CHROME_TO_MOBILE_BUBBLE_SEND_COPY_FAILED));
156 }
157 Layout();
158 }
159
160 void ChromeToMobileBubbleView::OnSendComplete(bool success) {
161 progress_animation_->Stop();
162 progress_label_->SetText(l10n_util::GetStringUTF16(success ?
163 IDS_CHROME_TO_MOBILE_BUBBLE_SENT : IDS_CHROME_TO_MOBILE_BUBBLE_ERROR));
164 SizeToContents();
165 }
166
167 void ChromeToMobileBubbleView::Init() {
168 GridLayout* layout = new GridLayout(this);
169 SetLayoutManager(layout);
170
171 const size_t single_column_set_id = 0;
172 views::ColumnSet* cs = layout->AddColumnSet(single_column_set_id);
173 cs->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
174 GridLayout::USE_PREF, 0, 0);
175 cs->AddPaddingColumn(1, 0);
176
177 const size_t button_column_set_id = 1;
178 cs = layout->AddColumnSet(button_column_set_id);
179 cs->AddPaddingColumn(1, 0);
180 cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0,
181 GridLayout::USE_PREF, 0, 0);
182 // Subtract 2px for the natural button padding and to correspond with row
183 // separation height; like BookmarkBubbleView.
184 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing - 2);
185 cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0,
186 GridLayout::USE_PREF, 0, 0);
187
188 std::vector<DictionaryValue*> mobiles =
189 ChromeToMobileServiceFactory::GetForProfile(profile_)->mobiles();
190 DCHECK_GT(mobiles.size(), 0U);
191
192 layout->StartRow(0, single_column_set_id);
193 views::Label* title_label = new views::Label();
194 title_label->SetFont(
195 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont));
196 title_label->SetEnabledColor(kTitleColor);
197 layout->AddView(title_label);
198
199 if (mobiles.size() == 1) {
200 selected_mobile_ = mobiles[0];
201 string16 mobile_name;
202 mobiles[0]->GetString("name", &mobile_name);
203 title_label->SetText(l10n_util::GetStringFUTF16(
204 IDS_CHROME_TO_MOBILE_BUBBLE_SINGLE_TITLE, mobile_name));
205 } else {
206 title_label->SetText(l10n_util::GetStringUTF16(
207 IDS_CHROME_TO_MOBILE_BUBBLE_MULTI_TITLE));
208
209 const size_t radio_column_set_id = 2;
210 cs = layout->AddColumnSet(radio_column_set_id);
211 cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
212 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
213 GridLayout::USE_PREF, 0, 0);
214
215 views::RadioButton* radio;
216 layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
217 for (std::vector<DictionaryValue*>::const_iterator it = mobiles.begin();
218 it != mobiles.end(); ++it) {
219 string16 name;
220 (*it)->GetString("name", &name);
221 radio = new views::RadioButton(name, 0);
222 radio->set_listener(this);
223 mobile_map_[radio] = *it;
224 layout->StartRow(0, radio_column_set_id);
225 layout->AddView(radio);
226 }
227 mobile_map_.begin()->first->SetChecked(true);
228 selected_mobile_ = mobile_map_.begin()->second;
229 }
230
231 send_copy_ = new views::Checkbox(
232 l10n_util::GetStringFUTF16(IDS_CHROME_TO_MOBILE_BUBBLE_SEND_COPY,
233 l10n_util::GetStringUTF16(
234 IDS_CHROME_TO_MOBILE_BUBBLE_SEND_COPY_GENERATING)));
235 send_copy_->SetEnabled(false);
236 layout->StartRow(0, single_column_set_id);
237 layout->AddView(send_copy_);
238
239 layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
240 send_ = new views::NativeTextButton(
241 this, l10n_util::GetStringUTF16(IDS_CHROME_TO_MOBILE_BUBBLE_SEND));
242 send_->SetIsDefault(true);
243 cancel_ = new views::NativeTextButton(
244 this, l10n_util::GetStringUTF16(IDS_CANCEL));
245 layout->StartRow(0, button_column_set_id);
246 layout->AddView(send_);
247 layout->AddView(cancel_);
248
249 AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, 0));
250 }
251
252 ChromeToMobileBubbleView::ChromeToMobileBubbleView(views::View* anchor_view,
253 Profile* profile)
254 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
255 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
256 profile_(profile),
257 selected_mobile_(NULL),
258 send_copy_(NULL),
259 send_(NULL),
260 cancel_(NULL),
261 progress_label_(NULL) {
262 // Generate the MHTML snapshot now to report its size in the bubble.
263 ChromeToMobileServiceFactory::GetForProfile(profile)->
264 GenerateSnapshot(weak_ptr_factory_.GetWeakPtr());
265 }
266
267 void ChromeToMobileBubbleView::HandleButtonPressed(views::Button* sender) {
268 if (sender == send_) {
269 Send();
270 } else if (sender == cancel_) {
271 GetWidget()->Close();
272 } else {
273 // The sender is a mobile radio button
274 views::RadioButton* radio = static_cast<views::RadioButton*>(sender);
275 DCHECK(mobile_map_.find(radio) != mobile_map_.end());
276 selected_mobile_ = mobile_map_.find(radio)->second;
277 }
278 }
279
280 void ChromeToMobileBubbleView::Send() {
281 string16 mobile_id;
282 selected_mobile_->GetString("id", &mobile_id);
283 ChromeToMobileServiceFactory::GetForProfile(profile_)->SendToMobile(
284 mobile_id, send_copy_->checked() ? snapshot_path_ : FilePath(),
285 weak_ptr_factory_.GetWeakPtr());
286
287 // Re-initialize the view's contents to show progress sending the page.
288 RemoveAllChildViews(true);
289 send_copy_ = NULL;
290 send_ = NULL;
291 cancel_ = NULL;
292
293 GridLayout* layout = new GridLayout(this);
294 SetLayoutManager(layout);
295
296 const size_t single_column_set_id = 0;
297 views::ColumnSet* cs = layout->AddColumnSet(single_column_set_id);
298 cs->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
299 GridLayout::USE_PREF, 0, 0);
300 set_margin(kProgressMargin);
301
302 // Use the final (longest) progress label string to resize the bubble.
303 layout->StartRow(0, single_column_set_id);
304 progress_label_ = new views::Label(
305 l10n_util::GetStringUTF16(IDS_CHROME_TO_MOBILE_BUBBLE_SENDING_3));
306 progress_label_->SetFont(
307 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont));
308 progress_label_->SetEnabledColor(kTitleColor);
309 layout->AddView(progress_label_);
310 SizeToContents();
311
312 progress_animation_.reset(new ui::ThrobAnimation(this));
313 progress_animation_->SetDuration(kProgressThrobDurationMS);
314 progress_animation_->StartThrobbing(-1);
315 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/chrome_to_mobile_bubble_view.h ('k') | chrome/browser/ui/views/frame/browser_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698