Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/status_bubble_gtk.h" | 5 #include "chrome/browser/gtk/status_bubble_gtk.h" |
| 6 | 6 |
| 7 #include <gtk/gtk.h> | |
| 8 | |
| 9 #include "base/gfx/gtk_util.h" | |
| 7 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| 11 #include "chrome/browser/gtk/slide_animator_gtk.h" | |
| 12 #include "chrome/common/gtk_util.h" | |
| 8 #include "googleurl/src/gurl.h" | 13 #include "googleurl/src/gurl.h" |
| 9 | 14 |
| 10 // NOTE: this code is probably the wrong approach for the status bubble. | 15 namespace { |
| 11 // Talk to evanm before you attempt to fix bugs in it -- we're probably | |
| 12 // better off restructuring it. | |
| 13 | 16 |
| 14 StatusBubbleGtk::StatusBubbleGtk(GtkWindow* parent) | 17 const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xe6, 0xed, 0xf4); |
| 15 : parent_(parent), window_(NULL) { | 18 const GdkColor kFrameBorderColor = GDK_COLOR_RGB(0xbe, 0xc8, 0xd4); |
| 19 | |
| 20 // Inner padding between the border and the text label. | |
| 21 const int kInternalTopBottomPadding = 1; | |
| 22 const int kInternalLeftRightPadding = 2; | |
| 23 | |
| 24 // Border of color kFrameBorderColor around the status bubble. | |
| 25 const int kBorderPadding = 1; | |
| 26 | |
| 27 } // namespace | |
| 28 | |
| 29 StatusBubbleGtk::StatusBubbleGtk() | |
| 30 : parent_(NULL) { | |
| 31 InitWidgets(); | |
| 16 } | 32 } |
| 17 | 33 |
| 18 StatusBubbleGtk::~StatusBubbleGtk() { | 34 StatusBubbleGtk::~StatusBubbleGtk() { |
| 19 Hide(); | 35 container_.Destroy(); |
| 20 } | 36 } |
| 21 | 37 |
| 22 void StatusBubbleGtk::SetStatus(const std::string& status) { | 38 void StatusBubbleGtk::SetStatus(const std::string& status) { |
| 23 if (status.empty()) { | 39 if (status.empty()) { |
| 24 Hide(); | 40 Hide(); |
| 25 return; | 41 return; |
| 26 } | 42 } |
| 27 | 43 |
| 28 if (!window_) | 44 gtk_label_set_text(GTK_LABEL(label_), status.c_str()); |
| 29 Create(); | |
| 30 | 45 |
| 31 gtk_label_set_text(GTK_LABEL(label_), status.c_str()); | 46 Show(); |
| 32 Reposition(); | |
| 33 gtk_widget_show(window_); | |
| 34 } | 47 } |
| 35 | 48 |
| 36 void StatusBubbleGtk::SetStatus(const std::wstring& status) { | 49 void StatusBubbleGtk::SetStatus(const std::wstring& status) { |
| 37 SetStatus(WideToUTF8(status)); | 50 SetStatus(WideToUTF8(status)); |
| 38 } | 51 } |
| 39 | 52 |
| 53 void StatusBubbleGtk::SetParentAllocation( | |
| 54 GtkWidget* parent, GtkAllocation* allocation) { | |
| 55 parent_ = parent; | |
| 56 parent_allocation_ = *allocation; | |
| 57 SetStatusBubbleSize(); | |
| 58 } | |
| 59 | |
| 40 void StatusBubbleGtk::SetURL(const GURL& url, const std::wstring& languages) { | 60 void StatusBubbleGtk::SetURL(const GURL& url, const std::wstring& languages) { |
| 41 SetStatus(url.possibly_invalid_spec()); | 61 SetStatus(url.possibly_invalid_spec()); |
| 42 } | 62 } |
| 43 | 63 |
| 64 void StatusBubbleGtk::Show() { | |
| 65 SetStatusBubbleSize(); | |
| 66 gtk_widget_show_all(container_.get()); | |
| 67 | |
| 68 if (container_.get()->window) | |
| 69 gdk_window_raise(container_.get()->window); | |
| 70 } | |
| 71 | |
| 44 void StatusBubbleGtk::Hide() { | 72 void StatusBubbleGtk::Hide() { |
| 45 if (!window_) | 73 gtk_widget_hide_all(container_.get()); |
| 46 return; | 74 } |
| 47 gtk_widget_destroy(window_); | 75 |
| 48 window_ = NULL; | 76 void StatusBubbleGtk::SetStatusBubbleSize() { |
| 77 if (parent_) { | |
| 78 GtkRequisition requisition; | |
| 79 gtk_widget_size_request(container_.get(), &requisition); | |
| 80 | |
| 81 // TODO(erg): Previously, I put a call to gtk_fixed_put() here. It appears | |
| 82 // that doing this sets off a size-allocate storm, since gtk_fixed_put() | |
| 83 // calls gtk_widget_queue_resize on the GtkFixed that caused this message. | |
| 84 // The real solution may be creating a subclass of GtkVBox that has extra | |
| 85 // code to deal with floating widgets, but this hack is good enough for | |
| 86 // Friday. evanm says that there's a a GtkFixed subclass in test_shell that | |
| 87 // we'll be stealing for plugin support anyway that should also do the same | |
| 88 // task. | |
| 89 | |
| 90 GtkAllocation widget_allocation; | |
| 91 int child_y = std::max( | |
| 92 parent_allocation_.y + parent_allocation_.height - requisition.height, | |
| 93 0); | |
| 94 widget_allocation.x = 0; | |
| 95 widget_allocation.y = child_y; | |
| 96 widget_allocation.width = std::min(requisition.width, | |
| 97 parent_allocation_.width); | |
| 98 widget_allocation.height = requisition.height; | |
| 99 gtk_widget_size_allocate(container_.get(), &widget_allocation); | |
| 100 } | |
| 49 } | 101 } |
| 50 | 102 |
| 51 void StatusBubbleGtk::MouseMoved() { | 103 void StatusBubbleGtk::MouseMoved() { |
| 52 if (!window_) | 104 // We can't do that fancy sliding behaviour where the status bubble slides |
| 53 return; | 105 // out of the window because the window manager gets in the way. So totally |
| 54 // We ignore for now. | 106 // ignore this message for now. |
| 55 // TODO(port): the fancy sliding behavior. | 107 // |
| 108 // TODO(erg): At least get some sliding behaviour so that it slides out of | |
| 109 // the way to hide the status bubble on mouseover. | |
| 56 } | 110 } |
| 57 | 111 |
| 58 void StatusBubbleGtk::Create() { | 112 void StatusBubbleGtk::InitWidgets() { |
| 59 if (window_) | 113 label_ = gtk_label_new(NULL); |
| 60 return; | |
| 61 | 114 |
| 62 window_ = gtk_window_new(GTK_WINDOW_POPUP); | 115 GtkWidget* padding = gtk_alignment_new(0, 0, 1, 1); |
| 63 gtk_window_set_transient_for(GTK_WINDOW(window_), parent_); | 116 gtk_alignment_set_padding(GTK_ALIGNMENT(padding), |
| 64 gtk_container_set_border_width(GTK_CONTAINER(window_), 2); | 117 kInternalTopBottomPadding, kInternalTopBottomPadding, |
| 65 label_ = gtk_label_new(""); | 118 kInternalLeftRightPadding, kInternalLeftRightPadding); |
| 66 gtk_widget_show(label_); | 119 gtk_container_add(GTK_CONTAINER(padding), label_); |
| 67 gtk_container_add(GTK_CONTAINER(window_), label_); | 120 |
| 121 GtkWidget* bg_box = gtk_event_box_new(); | |
| 122 gtk_container_add(GTK_CONTAINER(bg_box), padding); | |
| 123 gtk_widget_modify_bg(bg_box, GTK_STATE_NORMAL, &kBackgroundColor); | |
| 124 | |
| 125 container_.Own(gtk_util::CreateGtkBorderBin(bg_box, &kFrameBorderColor, | |
| 126 kBorderPadding, kBorderPadding, kBorderPadding, kBorderPadding)); | |
| 127 gtk_widget_set_name(container_.get(), "status-bubble"); | |
| 128 gtk_widget_set_app_paintable(container_.get(), TRUE); | |
|
Evan Stade
2009/05/19 23:41:25
why app paintable?
| |
| 68 } | 129 } |
| 69 | |
| 70 void StatusBubbleGtk::Reposition() { | |
| 71 int x, y, width, parent_height; | |
| 72 gdk_window_get_position(GTK_WIDGET(parent_)->window, &x, &y); | |
| 73 gtk_window_get_size(parent_, &width, &parent_height); | |
| 74 GtkRequisition requisition; | |
| 75 gtk_widget_size_request(window_, &requisition); | |
| 76 // TODO(port): RTL positioning. | |
| 77 gtk_window_move(GTK_WINDOW(window_), x, | |
| 78 y + parent_height - requisition.height); | |
| 79 } | |
| OLD | NEW |