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

Side by Side Diff: views/widget/tooltip_manager_gtk.cc

Issue 197031: Fleshes out the tooltip implementation for views on Gtk. It doesn't... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 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 | « views/widget/tooltip_manager_gtk.h ('k') | views/widget/tooltip_manager_win.h » ('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) 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 "views/widget/tooltip_manager_gtk.h" 5 #include "views/widget/tooltip_manager_gtk.h"
6 6
7 #include "app/gfx/font.h" 7 #include "app/gfx/font.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/string_util.h"
10 #include "views/focus/focus_manager.h"
11 #include "views/widget/root_view.h"
12 #include "views/widget/widget_gtk.h"
13
14 // WARNING: this implementation is good for a start, but it doesn't give us
15 // control of tooltip positioning both on mouse events and when showing from
16 // keyboard. We may need to write our own to give us the control we need.
9 17
10 namespace views { 18 namespace views {
11 19
20 static gfx::Font* LoadDefaultFont() {
21 // Create a tooltip widget and extract the font from it (we have to realize
22 // it to make sure the correct font gets set).
23 GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP);
24 gtk_widget_set_name(window, "gtk-tooltip");
25 GtkWidget* label = gtk_label_new("");
26 gtk_widget_show(label);
27
28 gtk_container_add(GTK_CONTAINER(window), label);
29 gtk_widget_realize(window);
30
31 GtkStyle* style = gtk_widget_get_style(label);
32 PangoFontDescription* pfd = style->font_desc;
33 gfx::Font* font = new gfx::Font(gfx::Font::CreateFont(pfd));
34 pango_font_description_free(pfd);
35
36 gtk_widget_destroy(window);
37
38 return font;
39 }
40
12 // static 41 // static
13 int TooltipManager::GetTooltipHeight() { 42 int TooltipManager::GetTooltipHeight() {
14 NOTIMPLEMENTED(); 43 // This is only used to position the tooltip, and we don't yet support
44 // positioning the tooltip, it isn't worth trying to implement this.
15 return 0; 45 return 0;
16 } 46 }
17 47
18 // static 48 // static
19 gfx::Font TooltipManager::GetDefaultFont() { 49 gfx::Font TooltipManager::GetDefaultFont() {
20 NOTIMPLEMENTED(); 50 static gfx::Font* font = NULL;
21 return gfx::Font(); 51 if (!font)
52 font = LoadDefaultFont();
53
54 return *font;
22 } 55 }
23 56
24 // static 57 // static
25 const std::wstring& TooltipManager::GetLineSeparator() { 58 const std::wstring& TooltipManager::GetLineSeparator() {
26 static std::wstring* line_separator = NULL; 59 static std::wstring* line_separator = NULL;
27 if (!line_separator) 60 if (!line_separator)
28 line_separator = new std::wstring(L"\n"); 61 line_separator = new std::wstring(L"\n");
29 return *line_separator; 62 return *line_separator;
30 } 63 }
31 64
32 TooltipManagerGtk::TooltipManagerGtk(Widget* widget) : widget_(widget) { 65 // Callback from gtk_container_foreach. If |*label_p| is NULL and |widget| is
66 // a GtkLabel, |*label_p| is set to |widget|. Used to find the first GtkLabel
67 // in a container.
68 static void LabelLocatorCallback(GtkWidget* widget,
69 gpointer label_p) {
70 GtkWidget** label = static_cast<GtkWidget**>(label_p);
71 if (!*label && GTK_IS_LABEL(widget))
72 *label = widget;
73 }
74
75 // By default GtkTooltip wraps at a longish string. We want more control over
76 // that wrapping. The only way to do that is dig out the label and set
77 // gtk_label_set_max_width_chars, which is what this code does. I also tried
78 // setting a custom widget on the tooltip, but there is a bug in Gtk that
79 // triggers continually hiding/showing the widget in that case.
80 static void AdjustLabel(GtkTooltip* tooltip) {
81 static const char kAdjustedLabelPropertyValue[] = "_adjusted_label_";
82 gpointer adjusted_value = g_object_get_data(G_OBJECT(tooltip),
83 kAdjustedLabelPropertyValue);
84 if (adjusted_value)
85 return;
86
87 adjusted_value = reinterpret_cast<gpointer>(1);
88 g_object_set_data(G_OBJECT(tooltip), kAdjustedLabelPropertyValue,
89 adjusted_value);
90
91 GtkWidget* parent;
92 {
93 // Create a label so that we can get the parent. The Tooltip ends up taking
94 // ownership of the label and deleting it.
95 GtkWidget* label = gtk_label_new("");
96 gtk_tooltip_set_custom(tooltip, label);
97 parent = gtk_widget_get_parent(label);
98 gtk_tooltip_set_custom(tooltip, NULL);
99 }
100 if (parent) {
101 // We found the parent, find the first label, which is where the tooltip
102 // text ends up going.
103 GtkLabel* real_label = NULL;
104 gtk_container_foreach(GTK_CONTAINER(parent), LabelLocatorCallback,
105 static_cast<gpointer>(&real_label));
106 if (real_label)
107 gtk_label_set_max_width_chars(GTK_LABEL(real_label), 3000);
108 }
109 }
110
111 TooltipManagerGtk::TooltipManagerGtk(WidgetGtk* widget)
112 : widget_(widget),
113 keyboard_view_(NULL) {
114 }
115
116 bool TooltipManagerGtk::ShowTooltip(int x, int y, bool for_keyboard,
117 GtkTooltip* tooltip) {
118 View* view = NULL;
119 gfx::Point view_loc;
120 if (keyboard_view_) {
121 view = keyboard_view_;
122 view_loc.SetPoint(view->width() / 2, view->height() / 2);
123 } else if (!for_keyboard) {
124 RootView* root_view = widget_->GetRootView();
125 view = root_view->GetViewForPoint(gfx::Point(x, y));
126 view_loc.SetPoint(x, y);
127 View::ConvertPointFromWidget(view, &view_loc);
128 } else {
129 FocusManager* focus_manager = widget_->GetFocusManager();
130 if (focus_manager) {
131 view = focus_manager->GetFocusedView();
132 if (view)
133 view_loc.SetPoint(view->width() / 2, view->height() / 2);
134 }
135 }
136
137 if (!view)
138 return false;
139
140 std::wstring text;
141 if (!view->GetTooltipText(view_loc.x(), view_loc.y(), &text))
142 return false;
143
144 AdjustLabel(tooltip);
145
146 // Sets the area of the tooltip. This way if different views in the same
147 // widget have tooltips the tooltip doesn't get stuck at the same location.
148 gfx::Rect vis_bounds = view->GetVisibleBounds();
149 gfx::Point widget_loc(vis_bounds.x(), vis_bounds.y());
150 View::ConvertPointToWidget(view, &widget_loc);
151 GdkRectangle tip_area = { widget_loc.x(), widget_loc.y(),
152 vis_bounds.width(), vis_bounds.height() };
153 gtk_tooltip_set_tip_area(tooltip, &tip_area);
154
155 int max_width, line_count;
156 gfx::Point screen_loc(x, y);
157 View::ConvertPointToScreen(widget_->GetRootView(), &screen_loc);
158 TrimTooltipToFit(&text, &max_width, &line_count, screen_loc.x(),
159 screen_loc.y());
160 gtk_tooltip_set_text(tooltip, WideToUTF8(text).c_str());
161
162 return true;
33 } 163 }
34 164
35 void TooltipManagerGtk::UpdateTooltip() { 165 void TooltipManagerGtk::UpdateTooltip() {
36 NOTIMPLEMENTED(); 166 // UpdateTooltip may be invoked after the widget has been destroyed.
167 GtkWidget* widget = widget_->GetNativeView();
168 if (!widget)
169 return;
170
171 GdkDisplay* display = gtk_widget_get_display(widget);
172 if (display)
173 gtk_tooltip_trigger_tooltip_query(display);
37 } 174 }
38 175
39 void TooltipManagerGtk::TooltipTextChanged(View* view) { 176 void TooltipManagerGtk::TooltipTextChanged(View* view) {
40 NOTIMPLEMENTED(); 177 UpdateTooltip();
41 } 178 }
42 179
43 void TooltipManagerGtk::ShowKeyboardTooltip(View* view) { 180 void TooltipManagerGtk::ShowKeyboardTooltip(View* view) {
44 NOTIMPLEMENTED(); 181 if (view == keyboard_view_)
182 return; // We're already showing the tip for the specified view.
183
184 // We have to hide the current tooltip, then show again.
185 HideKeyboardTooltip();
186
187 std::wstring tooltip_text;
188 if (!view->GetTooltipText(0, 0, &tooltip_text))
189 return; // The view doesn't have a tooltip, nothing to do.
190
191 keyboard_view_ = view;
192 if (!SendShowHelpSignal()) {
193 keyboard_view_ = NULL;
194 return;
195 }
45 } 196 }
46 197
47 void TooltipManagerGtk::HideKeyboardTooltip() { 198 void TooltipManagerGtk::HideKeyboardTooltip() {
48 NOTIMPLEMENTED(); 199 if (!keyboard_view_)
200 return;
201
202 SendShowHelpSignal();
203 keyboard_view_ = NULL;
204 }
205
206 bool TooltipManagerGtk::SendShowHelpSignal() {
207 GtkWidget* widget = widget_->window_contents();
208 GType itype = G_TYPE_FROM_INSTANCE(G_OBJECT(widget));
209 guint signal_id;
210 GQuark detail;
211 if (!g_signal_parse_name("show_help", itype, &signal_id, &detail, FALSE)) {
212 NOTREACHED();
213 return false;
214 }
215 gboolean result;
216 g_signal_emit(widget, signal_id, 0, GTK_WIDGET_HELP_TOOLTIP, &result);
217 return true;
49 } 218 }
50 219
51 } // namespace views 220 } // namespace views
OLDNEW
« no previous file with comments | « views/widget/tooltip_manager_gtk.h ('k') | views/widget/tooltip_manager_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698