From e30fef09c8eea39133d3082a0ed1ddee257520ac Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Mar 2014 20:38:52 +0800 Subject: [PATCH] gtk: Add gtk_util from Chromium. --- atom.gyp | 2 + browser/ui/gtk/gtk_util.cc | 89 ++++++++++++++++++++++++++++++++++++++ browser/ui/gtk/gtk_util.h | 31 +++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 browser/ui/gtk/gtk_util.cc create mode 100644 browser/ui/gtk/gtk_util.h diff --git a/atom.gyp b/atom.gyp index cce3b2de432f..b2f65d5d32d8 100644 --- a/atom.gyp +++ b/atom.gyp @@ -127,6 +127,8 @@ 'browser/ui/gtk/gtk_custom_menu.h', 'browser/ui/gtk/gtk_custom_menu_item.cc', 'browser/ui/gtk/gtk_custom_menu_item.h', + 'browser/ui/gtk/gtk_util.cc', + 'browser/ui/gtk/gtk_util.h', 'browser/ui/gtk/gtk_window_util.cc', 'browser/ui/gtk/gtk_window_util.h', 'browser/ui/message_box.h', diff --git a/browser/ui/gtk/gtk_util.cc b/browser/ui/gtk/gtk_util.cc new file mode 100644 index 000000000000..efb1b3429030 --- /dev/null +++ b/browser/ui/gtk/gtk_util.cc @@ -0,0 +1,89 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "browser/ui/gtk/gtk_util.h" + +#include + +#include "base/logging.h" + +namespace gtk_util { + +namespace { + +const char kBoldLabelMarkup[] = "%s"; + +// Returns the approximate number of characters that can horizontally fit in +// |pixel_width| pixels. +int GetCharacterWidthForPixels(GtkWidget* widget, int pixel_width) { + DCHECK(gtk_widget_get_realized(widget)) + << " widget must be realized to compute font metrics correctly"; + + PangoContext* context = gtk_widget_create_pango_context(widget); + GtkStyle* style = gtk_widget_get_style(widget); + PangoFontMetrics* metrics = pango_context_get_metrics(context, + style->font_desc, pango_context_get_language(context)); + + // This technique (max of char and digit widths) matches the code in + // gtklabel.c. + int char_width = pixel_width * PANGO_SCALE / + std::max(pango_font_metrics_get_approximate_char_width(metrics), + pango_font_metrics_get_approximate_digit_width(metrics)); + + pango_font_metrics_unref(metrics); + g_object_unref(context); + + return char_width; +} + +void OnLabelRealize(GtkWidget* label, gpointer pixel_width) { + gtk_label_set_width_chars( + GTK_LABEL(label), + GetCharacterWidthForPixels(label, GPOINTER_TO_INT(pixel_width))); +} + +} // namespace + +GtkWidget* LeftAlignMisc(GtkWidget* misc) { + gtk_misc_set_alignment(GTK_MISC(misc), 0, 0.5); + return misc; +} + +GtkWidget* CreateBoldLabel(const std::string& text) { + GtkWidget* label = gtk_label_new(NULL); + char* markup = g_markup_printf_escaped(kBoldLabelMarkup, text.c_str()); + gtk_label_set_markup(GTK_LABEL(label), markup); + g_free(markup); + + return LeftAlignMisc(label); +} + +bool IsWidgetAncestryVisible(GtkWidget* widget) { + GtkWidget* parent = widget; + while (parent && gtk_widget_get_visible(parent)) + parent = gtk_widget_get_parent(parent); + return !parent; +} + +void SetLabelWidth(GtkWidget* label, int pixel_width) { + gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + + // Do the simple thing in LTR because the bug only affects right-aligned + // text. Also, when using the workaround, the label tries to maintain + // uniform line-length, which we don't really want. + if (gtk_widget_get_direction(label) == GTK_TEXT_DIR_LTR) { + gtk_widget_set_size_request(label, pixel_width, -1); + } else { + // The label has to be realized before we can adjust its width. + if (gtk_widget_get_realized(label)) { + OnLabelRealize(label, GINT_TO_POINTER(pixel_width)); + } else { + g_signal_connect(label, "realize", G_CALLBACK(OnLabelRealize), + GINT_TO_POINTER(pixel_width)); + } + } +} + +} // namespace gtk_util diff --git a/browser/ui/gtk/gtk_util.h b/browser/ui/gtk/gtk_util.h new file mode 100644 index 000000000000..38961fc0b9dc --- /dev/null +++ b/browser/ui/gtk/gtk_util.h @@ -0,0 +1,31 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_UI_GTK_GTK_UTIL_H_ +#define ATOM_BROWSER_UI_GTK_GTK_UTIL_H_ + +#include +#include + +namespace gtk_util { + +// Left-align the given GtkMisc and return the same pointer. +GtkWidget* LeftAlignMisc(GtkWidget* misc); + +// Create a left-aligned label with the given text in bold. +GtkWidget* CreateBoldLabel(const std::string& text); + +// Checks whether a widget is actually visible, i.e. whether it and all its +// ancestors up to its toplevel are visible. +bool IsWidgetAncestryVisible(GtkWidget* widget); + +// Sets the given label's size request to |pixel_width|. This will cause the +// label to wrap if it needs to. The reason for this function is that some +// versions of GTK mis-align labels that have a size request and line wrapping, +// and this function hides the complexity of the workaround. +void SetLabelWidth(GtkWidget* label, int pixel_width); + +} // namespace gtk_util + +#endif // ATOM_BROWSER_UI_GTK_GTK_UTIL_H_