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

Side by Side Diff: chrome/browser/gtk/notifications/balloon_view_gtk.cc

Issue 1353003: GTK: Provide GTK+ themed notifications. (Closed)
Patch Set: Redraw on change Created 10 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
« no previous file with comments | « chrome/browser/gtk/notifications/balloon_view_gtk.h ('k') | no next file » | 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "chrome/browser/gtk/notifications/balloon_view_gtk.h" 5 #include "chrome/browser/gtk/notifications/balloon_view_gtk.h"
6 6
7 #include <gtk/gtk.h>
8
7 #include <string> 9 #include <string>
8 #include <vector> 10 #include <vector>
9 11
10 #include "app/l10n_util.h" 12 #include "app/l10n_util.h"
11 #include "app/resource_bundle.h" 13 #include "app/resource_bundle.h"
12 #include "app/slide_animation.h" 14 #include "app/slide_animation.h"
13 #include "base/message_loop.h" 15 #include "base/message_loop.h"
14 #include "base/string_util.h" 16 #include "base/string_util.h"
15 #include "chrome/browser/browser_list.h" 17 #include "chrome/browser/browser_list.h"
16 #include "chrome/browser/browser_theme_provider.h" 18 #include "chrome/browser/browser_theme_provider.h"
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 html_contents_->Shutdown(); 129 html_contents_->Shutdown();
128 if (frame_container_) { 130 if (frame_container_) {
129 // It's possible that |frame_container_| was destroyed before the 131 // It's possible that |frame_container_| was destroyed before the
130 // BalloonViewImpl if our related browser window was closed first. 132 // BalloonViewImpl if our related browser window was closed first.
131 gtk_widget_hide(frame_container_); 133 gtk_widget_hide(frame_container_);
132 } 134 }
133 balloon_->OnClose(by_user); 135 balloon_->OnClose(by_user);
134 } 136 }
135 137
136 void BalloonViewImpl::RepositionToBalloon() { 138 void BalloonViewImpl::RepositionToBalloon() {
137 DCHECK(frame_container_); 139 if (!frame_container_) {
140 // No need to create a slide animation when this balloon is fading out.
141 return;
142 }
143
138 DCHECK(balloon_); 144 DCHECK(balloon_);
139 145
140 // Create an amination from the current position to the desired one. 146 // Create an amination from the current position to the desired one.
141 int start_x; 147 int start_x;
142 int start_y; 148 int start_y;
143 int start_w; 149 int start_w;
144 int start_h; 150 int start_h;
145 gtk_window_get_position(GTK_WINDOW(frame_container_), &start_x, &start_y); 151 gtk_window_get_position(GTK_WINDOW(frame_container_), &start_x, &start_y);
146 gtk_window_get_size(GTK_WINDOW(frame_container_), &start_w, &start_h); 152 gtk_window_get_size(GTK_WINDOW(frame_container_), &start_w, &start_h);
147 153
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 201
196 GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); 202 GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
197 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 1, 1, 1, 1); 203 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 1, 1, 1, 1);
198 gtk_container_add(GTK_CONTAINER(alignment), box); 204 gtk_container_add(GTK_CONTAINER(alignment), box);
199 gtk_container_add(GTK_CONTAINER(button), alignment); 205 gtk_container_add(GTK_CONTAINER(button), alignment);
200 206
201 gtk_widget_show_all(alignment); 207 gtk_widget_show_all(alignment);
202 } 208 }
203 209
204 void BalloonViewImpl::Show(Balloon* balloon) { 210 void BalloonViewImpl::Show(Balloon* balloon) {
205 GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom( 211 theme_provider_ = GtkThemeProvider::GetFrom(balloon->profile());
206 balloon->profile());
207 212
208 const std::string source_label_text = l10n_util::GetStringFUTF8( 213 const std::string source_label_text = l10n_util::GetStringFUTF8(
209 IDS_NOTIFICATION_BALLOON_SOURCE_LABEL, 214 IDS_NOTIFICATION_BALLOON_SOURCE_LABEL,
210 WideToUTF16(balloon->notification().display_source())); 215 WideToUTF16(balloon->notification().display_source()));
211 const std::string options_text = 216 const std::string options_text =
212 l10n_util::GetStringUTF8(IDS_NOTIFICATION_OPTIONS_MENU_LABEL); 217 l10n_util::GetStringUTF8(IDS_NOTIFICATION_OPTIONS_MENU_LABEL);
213 const std::string dismiss_text = 218 const std::string dismiss_text =
214 l10n_util::GetStringUTF8(IDS_NOTIFICATION_BALLOON_DISMISS_LABEL); 219 l10n_util::GetStringUTF8(IDS_NOTIFICATION_BALLOON_DISMISS_LABEL);
215 220
216 balloon_ = balloon; 221 balloon_ = balloon;
(...skipping 18 matching lines...) Expand all
235 GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); 240 GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
236 gtk_alignment_set_padding( 241 gtk_alignment_set_padding(
237 GTK_ALIGNMENT(alignment), 242 GTK_ALIGNMENT(alignment),
238 kTopMargin, kBottomMargin, kLeftMargin, kRightMargin); 243 kTopMargin, kBottomMargin, kLeftMargin, kRightMargin);
239 gtk_widget_show_all(alignment); 244 gtk_widget_show_all(alignment);
240 gtk_container_add(GTK_CONTAINER(alignment), contents); 245 gtk_container_add(GTK_CONTAINER(alignment), contents);
241 gtk_container_add(GTK_CONTAINER(vbox), alignment); 246 gtk_container_add(GTK_CONTAINER(vbox), alignment);
242 247
243 shelf_ = gtk_hbox_new(0, 0); 248 shelf_ = gtk_hbox_new(0, 0);
244 GtkWidget* alignment2 = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); 249 GtkWidget* alignment2 = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
245 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment2), 0, 0, 10, 0); 250 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment2), 2, 2, 10, 0);
246 gtk_container_add(GTK_CONTAINER(vbox), shelf_); 251 gtk_container_add(GTK_CONTAINER(vbox), shelf_);
247 252
248 // Create a toolbar and add it to the shelf. 253 // Create a toolbar and add it to the shelf.
249 hbox_ = gtk_hbox_new(FALSE, 0); 254 hbox_ = gtk_hbox_new(FALSE, 0);
250 // gtk_util::SuppressDefaultPainting(hbox_);
251 gtk_widget_set_size_request(GTK_WIDGET(hbox_), -1, GetShelfHeight()); 255 gtk_widget_set_size_request(GTK_WIDGET(hbox_), -1, GetShelfHeight());
252 gtk_container_add(GTK_CONTAINER(alignment2), hbox_); 256 gtk_container_add(GTK_CONTAINER(alignment2), hbox_);
253 gtk_container_add(GTK_CONTAINER(shelf_), alignment2); 257 gtk_container_add(GTK_CONTAINER(shelf_), alignment2);
254 gtk_widget_show_all(vbox); 258 gtk_widget_show_all(vbox);
255 259
256 g_signal_connect(frame_container_, "expose-event", 260 g_signal_connect(frame_container_, "expose-event",
257 G_CALLBACK(OnExposeThunk), this); 261 G_CALLBACK(OnExposeThunk), this);
258 g_signal_connect(frame_container_, "destroy", 262 g_signal_connect(frame_container_, "destroy",
259 G_CALLBACK(OnDestroyThunk), this); 263 G_CALLBACK(OnDestroyThunk), this);
260 264
261 // Create a label for the source of the notification and add it to the 265 // Create a label for the source of the notification and add it to the
262 // toolbar. 266 // toolbar.
263 GtkWidget* source_label_ = gtk_label_new(NULL); 267 GtkWidget* source_label_ = gtk_label_new(NULL);
264 char* markup = g_markup_printf_escaped(kLabelMarkup, 268 char* markup = g_markup_printf_escaped(kLabelMarkup,
265 source_label_text.c_str()); 269 source_label_text.c_str());
266 gtk_label_set_markup(GTK_LABEL(source_label_), markup); 270 gtk_label_set_markup(GTK_LABEL(source_label_), markup);
267 g_free(markup); 271 g_free(markup);
268 gtk_label_set_max_width_chars(GTK_LABEL(source_label_), 272 gtk_label_set_max_width_chars(GTK_LABEL(source_label_),
269 kOriginLabelCharacters); 273 kOriginLabelCharacters);
270 gtk_label_set_ellipsize(GTK_LABEL(source_label_), PANGO_ELLIPSIZE_END); 274 gtk_label_set_ellipsize(GTK_LABEL(source_label_), PANGO_ELLIPSIZE_END);
271 gtk_box_pack_start(GTK_BOX(hbox_), source_label_, FALSE, FALSE, 0); 275 gtk_box_pack_start(GTK_BOX(hbox_), source_label_, FALSE, FALSE, 0);
272 276
273 // Create a button for showing the options menu, and add it to the toolbar. 277 // Create a button for showing the options menu, and add it to the toolbar.
274 options_menu_button_ = theme_provider->BuildChromeButton(); 278 options_menu_button_ = theme_provider_->BuildChromeButton();
275 g_signal_connect(options_menu_button_, "clicked", 279 g_signal_connect(options_menu_button_, "clicked",
276 G_CALLBACK(OnOptionsMenuButtonThunk), this); 280 G_CALLBACK(OnOptionsMenuButtonThunk), this);
277 PrepareButtonWithIcon(options_menu_button_, options_text, 281 PrepareButtonWithIcon(options_menu_button_, options_text,
278 IDR_BALLOON_OPTIONS_ARROW_HOVER); 282 IDR_BALLOON_OPTIONS_ARROW_HOVER);
279 gtk_box_pack_start(GTK_BOX(hbox_), options_menu_button_, FALSE, FALSE, 0); 283 gtk_box_pack_start(GTK_BOX(hbox_), options_menu_button_, FALSE, FALSE, 0);
280 284
281 // Create a button to dismiss the balloon and add it to the toolbar. 285 // Create a button to dismiss the balloon and add it to the toolbar.
282 close_button_ = theme_provider->BuildChromeButton(); 286 close_button_ = theme_provider_->BuildChromeButton();
283 g_signal_connect(close_button_, "clicked", 287 g_signal_connect(close_button_, "clicked",
284 G_CALLBACK(OnCloseButtonThunk), this); 288 G_CALLBACK(OnCloseButtonThunk), this);
285 PrepareButtonWithIcon(close_button_, dismiss_text, IDR_BALLOON_CLOSE_HOVER); 289 PrepareButtonWithIcon(close_button_, dismiss_text, IDR_BALLOON_CLOSE_HOVER);
286 gtk_box_pack_start(GTK_BOX(hbox_), close_button_, FALSE, FALSE, 0); 290 gtk_box_pack_start(GTK_BOX(hbox_), close_button_, FALSE, FALSE, 0);
287 291
292 notification_registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
293 NotificationService::AllSources());
294 // We don't do InitThemesFor() because it just forces a redraw.
295
288 // Position the view elements according to the balloon position and show. 296 // Position the view elements according to the balloon position and show.
289 RepositionToBalloon(); 297 RepositionToBalloon();
290 gtk_widget_show_all(GTK_WIDGET(hbox_)); 298 gtk_widget_show_all(GTK_WIDGET(hbox_));
291 gtk_widget_show(frame_container_); 299 gtk_widget_show(frame_container_);
292 300
293 gtk_util::ActAsRoundedWindow(frame_container_, gfx::kGdkBlack, 3, 301 gtk_util::ActAsRoundedWindow(frame_container_, gfx::kGdkBlack, 3,
294 gtk_util::ROUNDED_ALL, 302 gtk_util::ROUNDED_ALL,
295 gtk_util::BORDER_ALL); 303 gtk_util::BORDER_ALL);
296 304
297 notification_registrar_.Add(this, 305 notification_registrar_.Add(this,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 gfx::Point offset = GetContentsOffset(); 339 gfx::Point offset = GetContentsOffset();
332 int x = 0, y = 0; 340 int x = 0, y = 0;
333 gtk_window_get_position(GTK_WINDOW(frame_container_), &x, &y); 341 gtk_window_get_position(GTK_WINDOW(frame_container_), &x, &y);
334 return gfx::Rect(x + offset.x(), y + offset.y(), 342 return gfx::Rect(x + offset.x(), y + offset.y(),
335 content_size.width(), content_size.height()); 343 content_size.width(), content_size.height());
336 } 344 }
337 345
338 void BalloonViewImpl::Observe(NotificationType type, 346 void BalloonViewImpl::Observe(NotificationType type,
339 const NotificationSource& source, 347 const NotificationSource& source,
340 const NotificationDetails& details) { 348 const NotificationDetails& details) {
341 if (type != NotificationType::NOTIFY_BALLOON_DISCONNECTED) { 349 if (type == NotificationType::NOTIFY_BALLOON_DISCONNECTED) {
350 // If the renderer process attached to this balloon is disconnected
351 // (e.g., because of a crash), we want to close the balloon.
352 notification_registrar_.Remove(this,
353 NotificationType::NOTIFY_BALLOON_DISCONNECTED,
354 Source<Balloon>(balloon_));
355 Close(false);
356 } else if (type == NotificationType::BROWSER_THEME_CHANGED) {
357 // Since all the buttons change their own properties, and our expose does
358 // all the real differences, we'll need a redraw.
359 gtk_widget_queue_draw(frame_container_);
360 } else {
342 NOTREACHED(); 361 NOTREACHED();
343 return; 362 }
363 }
364
365 gboolean BalloonViewImpl::OnExpose(GtkWidget* sender, GdkEventExpose* event) {
366 if (theme_provider_->UseGtkTheme()) {
367 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(sender->window));
368 gdk_cairo_rectangle(cr, &event->area);
369 cairo_clip(cr);
370
371 gfx::Size content_size = balloon_->content_size();
372 gfx::Point offset = GetContentsOffset();
373
374 // Draw lines of the content border color around the html content.
375 GdkColor color = theme_provider_->GetBorderColor();
376 gdk_cairo_set_source_color(cr, &color);
377 cairo_rectangle(cr, offset.x() - 1, offset.y() - 1,
378 offset.x() + content_size.width() + 1,
379 offset.y() + content_size.height());
380 cairo_fill(cr);
381
382 // Now draw a one pixel black line under the separator stuff.
383 cairo_move_to(cr, 0, offset.y() + content_size.height() + 1.5);
384 cairo_line_to(cr, offset.x() + content_size.width() + 1,
385 offset.y() + content_size.height() + 1.5);
386 cairo_set_line_width(cr, 1.0);
387 cairo_set_source_rgb(cr, 0, 0, 0);
388 cairo_stroke(cr);
389
390 cairo_destroy(cr);
391 } else {
392 // Draw the background images.
393 balloon_background_->RenderToWidget(frame_container_);
394 shelf_background_->RenderToWidget(shelf_);
344 } 395 }
345 396
346 // If the renderer process attached to this balloon is disconnected
347 // (e.g., because of a crash), we want to close the balloon.
348 notification_registrar_.Remove(this,
349 NotificationType::NOTIFY_BALLOON_DISCONNECTED, Source<Balloon>(balloon_));
350 Close(false);
351 }
352
353 gboolean BalloonViewImpl::OnExpose(GtkWidget* sender, GdkEventExpose* e) {
354 // Draw the background images.
355 balloon_background_->RenderToWidget(frame_container_);
356 shelf_background_->RenderToWidget(shelf_);
357 return FALSE; 397 return FALSE;
358 } 398 }
359 399
360 void BalloonViewImpl::OnOptionsMenuButton(GtkWidget* widget) { 400 void BalloonViewImpl::OnOptionsMenuButton(GtkWidget* widget) {
361 options_menu_->PopupAsContext(gtk_get_current_event_time()); 401 options_menu_->PopupAsContext(gtk_get_current_event_time());
362 } 402 }
363 403
364 gboolean BalloonViewImpl::OnDestroy(GtkWidget* widget) { 404 gboolean BalloonViewImpl::OnDestroy(GtkWidget* widget) {
365 frame_container_ = NULL; 405 frame_container_ = NULL;
366 Close(false); 406 Close(false);
367 return FALSE; // Propagate. 407 return FALSE; // Propagate.
368 } 408 }
OLDNEW
« no previous file with comments | « chrome/browser/gtk/notifications/balloon_view_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698