1 /*
2 * Copyright (C) 2019-2021 Alexandros Theodotou <alex at zrythm dot org>
3 *
4 * This file is part of Zrythm
5 *
6 * Zrythm is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Zrythm 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 Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "gui/widgets/expander_box.h"
21 #include "utils/resources.h"
22
23 #include <gtk/gtk.h>
24
G_DEFINE_TYPE_WITH_PRIVATE(ExpanderBoxWidget,expander_box_widget,GTK_TYPE_BOX)25 G_DEFINE_TYPE_WITH_PRIVATE (
26 ExpanderBoxWidget,
27 expander_box_widget,
28 GTK_TYPE_BOX)
29
30 #define GET_PRIVATE(s) \
31 ExpanderBoxWidgetPrivate * prv = \
32 expander_box_widget_get_private (s);
33
34 static void
35 on_clicked (
36 GtkButton *button,
37 ExpanderBoxWidget * self)
38 {
39 GET_PRIVATE (self);
40
41 bool revealed =
42 !gtk_revealer_get_reveal_child (
43 prv->revealer);
44 gtk_revealer_set_reveal_child (
45 prv->revealer, revealed);
46 gtk_widget_set_visible (
47 GTK_WIDGET (prv->revealer), revealed);
48
49 if (prv->reveal_cb)
50 {
51 prv->reveal_cb (
52 self, revealed, prv->user_data);
53 }
54 }
55
56 /**
57 * Gets the private.
58 */
59 ExpanderBoxWidgetPrivate *
expander_box_widget_get_private(ExpanderBoxWidget * self)60 expander_box_widget_get_private (
61 ExpanderBoxWidget * self)
62 {
63 return expander_box_widget_get_instance_private (
64 self);
65 }
66
67 /**
68 * Reveals or hides the expander box's contents.
69 */
70 void
expander_box_widget_set_reveal(ExpanderBoxWidget * self,int reveal)71 expander_box_widget_set_reveal (
72 ExpanderBoxWidget * self,
73 int reveal)
74 {
75 GET_PRIVATE (self);
76 gtk_revealer_set_reveal_child (
77 prv->revealer, reveal);
78 gtk_widget_set_visible (
79 GTK_WIDGET (prv->revealer), reveal);
80 }
81
82 /**
83 * Sets the label to show.
84 */
85 void
expander_box_widget_set_label(ExpanderBoxWidget * self,const char * label)86 expander_box_widget_set_label (
87 ExpanderBoxWidget * self,
88 const char * label)
89 {
90 GET_PRIVATE (self);
91
92 gtk_label_set_text (
93 prv->btn_label, label);
94 }
95
96 void
expander_box_widget_set_orientation(ExpanderBoxWidget * self,GtkOrientation orientation)97 expander_box_widget_set_orientation (
98 ExpanderBoxWidget * self,
99 GtkOrientation orientation)
100 {
101 ExpanderBoxWidgetPrivate * prv =
102 expander_box_widget_get_private (self);
103
104 /* set the main orientation */
105 prv->orientation = orientation;
106 gtk_orientable_set_orientation (
107 GTK_ORIENTABLE (self),
108 orientation);
109
110 /* set the orientation of the box inside the
111 * expander button */
112 gtk_orientable_set_orientation (
113 GTK_ORIENTABLE (prv->btn_box),
114 orientation == GTK_ORIENTATION_HORIZONTAL ?
115 GTK_ORIENTATION_VERTICAL :
116 GTK_ORIENTATION_HORIZONTAL);
117
118 /* set the label angle */
119 if (orientation == GTK_ORIENTATION_HORIZONTAL)
120 gtk_label_set_angle (
121 prv->btn_label, 90.0);
122 else
123 gtk_label_set_angle (
124 prv->btn_label, 0.0);
125
126 if (orientation == GTK_ORIENTATION_HORIZONTAL)
127 {
128 gtk_widget_set_hexpand (
129 GTK_WIDGET (prv->btn_label), 0);
130 gtk_widget_set_vexpand (
131 GTK_WIDGET (prv->btn_label), 1);
132 }
133 else
134 {
135 gtk_widget_set_hexpand (
136 GTK_WIDGET (prv->btn_label), 1);
137 gtk_widget_set_vexpand (
138 GTK_WIDGET (prv->btn_label), 0);
139 }
140 }
141
142 /**
143 * Sets the icon name to show.
144 */
145 void
expander_box_widget_set_icon_name(ExpanderBoxWidget * self,const char * icon_name)146 expander_box_widget_set_icon_name (
147 ExpanderBoxWidget * self,
148 const char * icon_name)
149 {
150 GET_PRIVATE (self);
151
152 gtk_image_set_from_icon_name (
153 prv->btn_img,
154 icon_name,
155 GTK_ICON_SIZE_BUTTON);
156 }
157
158 void
expander_box_widget_set_vexpand(ExpanderBoxWidget * self,bool expand)159 expander_box_widget_set_vexpand (
160 ExpanderBoxWidget * self,
161 bool expand)
162 {
163 GET_PRIVATE (self);
164
165 gtk_widget_set_vexpand (
166 GTK_WIDGET (prv->content), expand);
167 }
168
169 void
expander_box_widget_set_reveal_callback(ExpanderBoxWidget * self,ExpanderBoxRevealFunc cb,void * user_data)170 expander_box_widget_set_reveal_callback (
171 ExpanderBoxWidget * self,
172 ExpanderBoxRevealFunc cb,
173 void * user_data)
174 {
175 GET_PRIVATE (self);
176
177 prv->reveal_cb = cb;
178 prv->user_data = user_data;
179 }
180
181 ExpanderBoxWidget *
expander_box_widget_new(const char * label,const char * icon_name,GtkOrientation orientation)182 expander_box_widget_new (
183 const char * label,
184 const char * icon_name,
185 GtkOrientation orientation)
186 {
187 ExpanderBoxWidget * self =
188 g_object_new (EXPANDER_BOX_WIDGET_TYPE,
189 "visible", 1,
190 NULL);
191
192 expander_box_widget_set_icon_name (
193 self, icon_name);
194 expander_box_widget_set_orientation (
195 self, orientation);
196 expander_box_widget_set_label (
197 self, label);
198
199 return self;
200 }
201
202 static void
expander_box_widget_class_init(ExpanderBoxWidgetClass * _klass)203 expander_box_widget_class_init (
204 ExpanderBoxWidgetClass * _klass)
205 {
206 GtkWidgetClass * klass = GTK_WIDGET_CLASS (_klass);
207 resources_set_class_template (
208 klass, "expander_box.ui");
209 gtk_widget_class_set_css_name (
210 klass, "expander-box");
211
212 #define BIND_CHILD(x) \
213 gtk_widget_class_bind_template_child_private ( \
214 klass, ExpanderBoxWidget, x)
215
216 BIND_CHILD (button);
217 BIND_CHILD (revealer);
218 BIND_CHILD (content);
219
220 #undef BIND_CHILD
221 }
222
223 static void
expander_box_widget_init(ExpanderBoxWidget * self)224 expander_box_widget_init (ExpanderBoxWidget * self)
225 {
226 gtk_widget_init_template (GTK_WIDGET (self));
227
228 GET_PRIVATE (self);
229
230 prv->btn_label =
231 GTK_LABEL (gtk_label_new ("Label"));
232 gtk_widget_set_halign (
233 GTK_WIDGET (prv->btn_label),
234 GTK_ALIGN_START);
235 prv->btn_img =
236 GTK_IMAGE (
237 gtk_image_new_from_icon_name (
238 "plugins",
239 GTK_ICON_SIZE_BUTTON));
240 GtkWidget * box =
241 gtk_box_new (GTK_ORIENTATION_HORIZONTAL,
242 2);
243 gtk_container_add (
244 GTK_CONTAINER (box),
245 GTK_WIDGET (prv->btn_label));
246 gtk_container_add (
247 GTK_CONTAINER (box),
248 GTK_WIDGET (
249 gtk_separator_new (GTK_ORIENTATION_VERTICAL)));
250 gtk_box_pack_end (
251 GTK_BOX (box),
252 GTK_WIDGET (prv->btn_img), 0, 1, 0);
253 gtk_container_add (
254 GTK_CONTAINER (prv->button),
255 GTK_WIDGET (box));
256 prv->btn_box = GTK_BOX (box);
257
258 gtk_widget_show_all (GTK_WIDGET (self));
259
260 g_signal_connect (
261 G_OBJECT (prv->button), "clicked",
262 G_CALLBACK (on_clicked), self);
263 }
264