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 |