1 /*
2  *      fm-tab-label.c
3  *
4  *      Copyright 2010 PCMan <pcman.tw@gmail.com>
5  *
6  *      This program is free software; you can redistribute it and/or modify
7  *      it under the terms of the GNU General Public License as published by
8  *      the Free Software Foundation; either version 2 of the License, or
9  *      (at your option) any later version.
10  *
11  *      This program is distributed in the hope that it will be useful,
12  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *      GNU General Public License for more details.
15  *
16  *      You should have received a copy of the GNU General Public License
17  *      along with this program; if not, write to the Free Software
18  *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *      MA 02110-1301, USA.
20  */
21 
22 /**
23  * SECTION:fm-tab-label
24  * @short_description: A tab label widget.
25  * @title: FmTabLabel
26  *
27  * @include: libfm/fm-gtk.h
28  *
29  * The #FmTabLabel is a widget that can be used as a label of tab in
30  * notebook-like folders view.
31  */
32 
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36 
37 #include <glib/gi18n-lib.h>
38 
39 #include "fm-tab-label.h"
40 
41 G_DEFINE_TYPE(FmTabLabel, fm_tab_label, GTK_TYPE_EVENT_BOX);
42 
43 #if GTK_CHECK_VERSION(3, 0, 0)
44 GtkCssProvider *provider;
45 #endif
46 
fm_tab_label_class_init(FmTabLabelClass * klass)47 static void fm_tab_label_class_init(FmTabLabelClass *klass)
48 {
49     /* special style used by close button */
50 #if GTK_CHECK_VERSION(3, 0, 0)
51     provider = gtk_css_provider_new();
52     gtk_css_provider_load_from_data(provider,
53         "#tab-close-btn {\n"
54             "-GtkWidget-focus-padding : 0;\n"
55             "-GtkWidget-focus-line-width : 0;\n"
56             "padding : 0;\n"
57         "}\n", -1, NULL);
58 #else
59     gtk_rc_parse_string(
60         "style \"close-btn-style\" {\n"
61             "GtkWidget::focus-padding = 0\n"
62             "GtkWidget::focus-line-width = 0\n"
63             "xthickness = 0\n"
64             "ythickness = 0\n"
65         "}\n"
66         "widget \"*.tab-close-btn\" style \"close-btn-style\"");
67 #endif
68 }
69 
70 /* FIXME: add g_object_unref (provider); on class destroy? */
71 
on_close_btn_style_set(GtkWidget * btn,GtkRcStyle * prev,gpointer data)72 static void on_close_btn_style_set(GtkWidget *btn, GtkRcStyle *prev, gpointer data)
73 {
74     gint w, h;
75     gtk_icon_size_lookup_for_settings(gtk_widget_get_settings(btn), GTK_ICON_SIZE_MENU, &w, &h);
76     gtk_widget_set_size_request(btn, w + 2, h + 2);
77 }
78 
on_query_tooltip(GtkWidget * widget,gint x,gint y,gboolean keyboard_mode,GtkTooltip * tooltip,gpointer user_data)79 static gboolean on_query_tooltip(GtkWidget *widget, gint x, gint y,
80                                  gboolean    keyboard_mode,
81                                  GtkTooltip *tooltip, gpointer user_data)
82 {
83     /* We should only show the tooltip if the text is ellipsized */
84     GtkLabel* label = GTK_LABEL(widget);
85     PangoLayout* layout = gtk_label_get_layout(label);
86     if(pango_layout_is_ellipsized(layout))
87     {
88         gtk_tooltip_set_text(tooltip, gtk_label_get_text(label));
89         return TRUE;
90     }
91     return FALSE;
92 }
93 
fm_tab_label_init(FmTabLabel * self)94 static void fm_tab_label_init(FmTabLabel *self)
95 {
96     GtkBox* hbox;
97 #if GTK_CHECK_VERSION(3, 0, 0)
98     GtkStyleContext *context = gtk_widget_get_style_context(GTK_WIDGET(self));
99 #endif
100 
101     gtk_event_box_set_visible_window(GTK_EVENT_BOX(self), FALSE);
102 #if GTK_CHECK_VERSION(3, 2, 0)
103     /* FIXME: migrate to GtkGrid */
104     hbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));
105 #else
106     hbox = GTK_BOX(gtk_hbox_new(FALSE, 0));
107 #endif
108 
109     self->label = (GtkLabel*)gtk_label_new("");
110     gtk_widget_set_has_tooltip((GtkWidget*)self->label, TRUE);
111     gtk_box_pack_start(hbox, (GtkWidget*)self->label, FALSE, FALSE, 4 );
112     g_signal_connect(self->label, "query-tooltip", G_CALLBACK(on_query_tooltip), self);
113 
114     self->close_btn = (GtkButton*)gtk_button_new();
115     gtk_button_set_focus_on_click(self->close_btn, FALSE);
116     gtk_button_set_relief(self->close_btn, GTK_RELIEF_NONE );
117     gtk_container_add ( GTK_CONTAINER ( self->close_btn ),
118                         gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU));
119     gtk_container_set_border_width(GTK_CONTAINER(self->close_btn), 0);
120     gtk_widget_set_name((GtkWidget*)self->close_btn, "tab-close-btn");
121     g_signal_connect(self->close_btn, "style-set", G_CALLBACK(on_close_btn_style_set), NULL);
122 
123     gtk_box_pack_end( hbox, (GtkWidget*)self->close_btn, FALSE, FALSE, 0 );
124 
125     gtk_container_add(GTK_CONTAINER(self), (GtkWidget*)hbox);
126     gtk_widget_show_all((GtkWidget*)hbox);
127 
128 #if GTK_CHECK_VERSION(3, 0, 0)
129     gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider),
130                                    GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
131 #endif
132 
133 /*
134     gtk_drag_dest_set ( GTK_WIDGET( evt_box ), GTK_DEST_DEFAULT_ALL,
135                         drag_targets,
136                         sizeof( drag_targets ) / sizeof( GtkTargetEntry ),
137                         GDK_ACTION_DEFAULT | GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK );
138     g_signal_connect ( ( gpointer ) evt_box, "drag-motion",
139                        G_CALLBACK ( on_tab_drag_motion ),
140                        file_browser );
141 */
142 }
143 
144 /**
145  * fm_tab_label_new
146  * @text: text to display as a tab label
147  *
148  * Creates new tab label widget.
149  *
150  * Returns: (transfer full): a new #FmTabLabel widget.
151  *
152  * Since: 0.1.10
153  */
fm_tab_label_new(const char * text)154 FmTabLabel *fm_tab_label_new(const char* text)
155 {
156     FmTabLabel* label = (FmTabLabel*)g_object_new(FM_TYPE_TAB_LABEL, NULL);
157     AtkObject *obj;
158     obj = gtk_widget_get_accessible(GTK_WIDGET(label));
159     atk_object_set_description(obj, _("Changes active tab"));
160     gtk_label_set_text(label->label, text);
161     return label;
162 }
163 
164 /**
165  * fm_tab_label_set_text
166  * @label: a tab label widget
167  * @text: text to display as a tab label
168  *
169  * Changes text on the @label.
170  *
171  * Since: 0.1.10
172  */
fm_tab_label_set_text(FmTabLabel * label,const char * text)173 void fm_tab_label_set_text(FmTabLabel* label, const char* text)
174 {
175     gtk_label_set_text(label->label, text);
176 }
177 
178 /**
179  * fm_tab_label_set_tooltip_text
180  * @label: a tab label widget
181  * @text: text to display in label tooltip
182  *
183  * Changes text of tooltip on the @label.
184  *
185  * Since: 1.0.0
186  */
fm_tab_label_set_tooltip_text(FmTabLabel * label,const char * text)187 void fm_tab_label_set_tooltip_text(FmTabLabel* label, const char* text)
188 {
189     gtk_widget_set_tooltip_text(GTK_WIDGET(label->label), text);
190 }
191 
192 /**
193  * fm_tab_label_set_icon
194  * @label: a tab label widget
195  * @icon: (allow-none): an icon to show before text or %NULL
196  *
197  * Sets an optional @icon to be shown before text in the @label.
198  *
199  * Since: 1.2.0
200  */
fm_tab_label_set_icon(FmTabLabel * label,FmIcon * icon)201 void fm_tab_label_set_icon(FmTabLabel *label, FmIcon *icon)
202 {
203     g_return_if_fail(FM_IS_TAB_LABEL(label));
204     if (icon)
205     {
206         gint height, width;
207         GdkPixbuf *pixbuf;
208 
209         if (!gtk_icon_size_lookup(GTK_ICON_SIZE_BUTTON, &width, &height))
210             height = 20; /* fallback size, is that ever needed? */
211         pixbuf = fm_pixbuf_from_icon(icon, height);
212         if (pixbuf == NULL)
213             goto _no_image;
214         if (label->image)
215         {
216             gtk_image_set_from_pixbuf((GtkImage*)label->image, pixbuf);
217             gtk_widget_queue_draw(GTK_WIDGET(label));
218         }
219         else
220         {
221             /* hbox is only child of the label */
222             GtkWidget *hbox = gtk_bin_get_child(GTK_BIN(label));
223 
224             label->image = gtk_image_new_from_pixbuf(pixbuf);
225             gtk_box_pack_start(GTK_BOX(hbox), label->image, FALSE, FALSE, 0);
226             gtk_widget_show(label->image);
227         }
228         g_object_unref(pixbuf);
229         return;
230     }
231 _no_image:
232     if (label->image)
233     {
234         gtk_widget_destroy(label->image);
235         label->image = NULL;
236     }
237 }
238