1 /*
2 This file is part of darktable,
3 copyright (c)2020 Aldric Renaudin.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "thumbnail_btn.h"
19 #include "gui/gtk.h"
20 #include <string.h>
21
22 static void _thumbnail_btn_class_init(GtkDarktableThumbnailBtnClass *klass);
23 static void _thumbnail_btn_init(GtkDarktableThumbnailBtn *button);
24 static gboolean _thumbnail_btn_draw(GtkWidget *widget, cairo_t *cr);
25 static gboolean _thumbnail_btn_enter_notify_callback(GtkWidget *widget, GdkEventCrossing *event);
26 static gboolean _thumbnail_btn_leave_notify_callback(GtkWidget *widget, GdkEventCrossing *event);
27
_thumbnail_btn_class_init(GtkDarktableThumbnailBtnClass * klass)28 static void _thumbnail_btn_class_init(GtkDarktableThumbnailBtnClass *klass)
29 {
30 GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
31
32 widget_class->draw = _thumbnail_btn_draw;
33 widget_class->enter_notify_event = _thumbnail_btn_enter_notify_callback;
34 widget_class->leave_notify_event = _thumbnail_btn_leave_notify_callback;
35 }
36
_thumbnail_btn_init(GtkDarktableThumbnailBtn * button)37 static void _thumbnail_btn_init(GtkDarktableThumbnailBtn *button)
38 {
39 }
40
_thumbnail_btn_draw(GtkWidget * widget,cairo_t * cr)41 static gboolean _thumbnail_btn_draw(GtkWidget *widget, cairo_t *cr)
42 {
43 g_return_val_if_fail(DTGTK_IS_THUMBNAIL_BTN(widget), FALSE);
44
45 if(gtk_widget_get_allocated_height(widget) < 2 || gtk_widget_get_allocated_width(widget) < 2) return TRUE;
46
47 GtkStateFlags state = gtk_widget_get_state_flags(widget);
48
49 GdkRGBA *fg_color, *bg_color;
50 GtkStyleContext *context = gtk_widget_get_style_context(widget);
51 gtk_style_context_get(context, state, GTK_STYLE_PROPERTY_COLOR, &fg_color, GTK_STYLE_PROPERTY_BACKGROUND_COLOR,
52 &bg_color, NULL);
53 if(fg_color->alpha == 0 && bg_color->alpha == 0)
54 {
55 DTGTK_THUMBNAIL_BTN(widget)->hidden = TRUE;
56 gdk_rgba_free(fg_color);
57 gdk_rgba_free(bg_color);
58 return TRUE;
59 }
60 DTGTK_THUMBNAIL_BTN(widget)->hidden = FALSE;
61
62 cairo_save(cr);
63 gdk_cairo_set_source_rgba(cr, fg_color);
64
65 /* draw icon */
66 if(DTGTK_THUMBNAIL_BTN(widget)->icon)
67 {
68 GtkAllocation allocation;
69 gtk_widget_get_allocation(widget, &allocation);
70
71 int flags = DTGTK_THUMBNAIL_BTN(widget)->icon_flags;
72 if(state & GTK_STATE_FLAG_PRELIGHT)
73 flags |= CPF_PRELIGHT;
74 else
75 flags &= ~CPF_PRELIGHT;
76
77 if(state & GTK_STATE_FLAG_ACTIVE)
78 flags |= CPF_ACTIVE;
79 else
80 flags &= ~CPF_ACTIVE;
81
82 if(flags & CPF_DO_NOT_USE_BORDER)
83 {
84 DTGTK_THUMBNAIL_BTN(widget)->icon(cr, 0, 0, allocation.width, allocation.height, flags,
85 DTGTK_THUMBNAIL_BTN(widget)->icon_data ? DTGTK_THUMBNAIL_BTN(widget)->icon_data : bg_color);
86 }
87 else
88 {
89 DTGTK_THUMBNAIL_BTN(widget)->icon(cr, 0.125 * allocation.width, 0.125 * allocation.height,
90 0.75 * allocation.width, 0.75 * allocation.height, flags,
91 DTGTK_THUMBNAIL_BTN(widget)->icon_data ? DTGTK_THUMBNAIL_BTN(widget)->icon_data : bg_color);
92 }
93 }
94 // and eventually the image border
95 cairo_restore(cr);
96 gtk_render_frame(context, cr, 0, 0, gtk_widget_get_allocated_width(widget),
97 gtk_widget_get_allocated_height(widget));
98
99 gdk_rgba_free(fg_color);
100 gdk_rgba_free(bg_color);
101 return TRUE;
102 }
103
_thumbnail_btn_enter_notify_callback(GtkWidget * widget,GdkEventCrossing * event)104 static gboolean _thumbnail_btn_enter_notify_callback(GtkWidget *widget, GdkEventCrossing *event)
105 {
106 g_return_val_if_fail(widget != NULL, FALSE);
107
108 int flags = gtk_widget_get_state_flags(widget);
109 flags |= GTK_STATE_FLAG_PRELIGHT;
110
111 gtk_widget_set_state_flags(widget, flags, TRUE);
112 gtk_widget_queue_draw(widget);
113 return FALSE;
114 }
_thumbnail_btn_leave_notify_callback(GtkWidget * widget,GdkEventCrossing * event)115 static gboolean _thumbnail_btn_leave_notify_callback(GtkWidget *widget, GdkEventCrossing *event)
116 {
117 g_return_val_if_fail(widget != NULL, FALSE);
118
119 int flags = gtk_widget_get_state_flags(widget);
120 flags &= ~GTK_STATE_FLAG_PRELIGHT;
121
122 gtk_widget_set_state_flags(widget, flags, TRUE);
123 gtk_widget_queue_draw(widget);
124 return FALSE;
125 }
126
127 // Public functions
dtgtk_thumbnail_btn_new(DTGTKCairoPaintIconFunc paint,gint paintflags,void * paintdata)128 GtkWidget *dtgtk_thumbnail_btn_new(DTGTKCairoPaintIconFunc paint, gint paintflags, void *paintdata)
129 {
130 GtkDarktableThumbnailBtn *button;
131 button = g_object_new(dtgtk_thumbnail_btn_get_type(), NULL);
132 GtkStyleContext *context = gtk_widget_get_style_context(GTK_WIDGET(button));
133 gtk_style_context_add_class(context, "dt_thumb_btn");
134 button->icon = paint;
135 button->icon_flags = paintflags;
136 button->icon_data = paintdata;
137 gtk_widget_set_events(GTK_WIDGET(button), GDK_EXPOSURE_MASK
138 | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK
139 | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK
140 | GDK_ENTER_NOTIFY_MASK | GDK_ALL_EVENTS_MASK);
141 gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE);
142 gtk_widget_set_name(GTK_WIDGET(button), "thumbnail_btn");
143 return (GtkWidget *)button;
144 }
145
dtgtk_thumbnail_btn_get_type()146 GType dtgtk_thumbnail_btn_get_type()
147 {
148 static GType dtgtk_thumbnail_btn_type = 0;
149 if(!dtgtk_thumbnail_btn_type)
150 {
151 static const GTypeInfo dtgtk_thumbnail_btn_info = {
152 sizeof(GtkDarktableThumbnailBtnClass),
153 (GBaseInitFunc)NULL,
154 (GBaseFinalizeFunc)NULL,
155 (GClassInitFunc)_thumbnail_btn_class_init,
156 NULL, /* class_finalize */
157 NULL, /* class_data */
158 sizeof(GtkDarktableThumbnailBtn),
159 0, /* n_preallocs */
160 (GInstanceInitFunc)_thumbnail_btn_init,
161 };
162 dtgtk_thumbnail_btn_type
163 = g_type_register_static(GTK_TYPE_DRAWING_AREA, "GtkDarktableThumbnailBtn", &dtgtk_thumbnail_btn_info, 0);
164 }
165 return dtgtk_thumbnail_btn_type;
166 }
167
dtgtk_thumbnail_btn_is_hidden(GtkWidget * widget)168 gboolean dtgtk_thumbnail_btn_is_hidden(GtkWidget *widget)
169 {
170 g_return_val_if_fail(DTGTK_IS_THUMBNAIL_BTN(widget), TRUE);
171
172 return DTGTK_THUMBNAIL_BTN(widget)->hidden;
173 }
174 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
175 // vim: shiftwidth=2 expandtab tabstop=2 cindent
176 // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
177