1 /* Calf DSP Library
2  * Custom controls (line graph, knob).
3  * Copyright (C) 2007-2015 Krzysztof Foltman, Torben Hohn, Markus Schmidt
4  * and others
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General
17  * Public License along with this program; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA  02110-1301  USA
20  */
21 
22 #include <calf/ctl_combobox.h>
23 
24 using namespace calf_plugins;
25 using namespace dsp;
26 
27 
28 ///////////////////////////////////////// combo box ///////////////////////////////////////////////
29 
30 
31 //#define GTK_COMBO_BOX_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_COMBO_BOX, GtkComboBoxPrivate))
32 
33 GtkWidget *
calf_combobox_new()34 calf_combobox_new()
35 {
36     GtkWidget *widget = GTK_WIDGET( g_object_new (CALF_TYPE_COMBOBOX, NULL ));
37     GtkCellRenderer *column = gtk_cell_renderer_text_new();
38     gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), column, TRUE);
39     gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(widget), column,
40                                    "text", 0,
41                                    NULL);
42     return widget;
43 }
44 static gboolean
calf_combobox_expose(GtkWidget * widget,GdkEventExpose * event)45 calf_combobox_expose (GtkWidget *widget, GdkEventExpose *event)
46 {
47     g_assert(CALF_IS_COMBOBOX(widget));
48 
49     if (gtk_widget_is_drawable (widget)) {
50 
51         int padx = widget->style->xthickness;
52         int pady = widget->style->ythickness;
53 
54         GtkComboBox *cb = GTK_COMBO_BOX(widget);
55         CalfCombobox *ccb = CALF_COMBOBOX(widget);
56         GdkWindow *window = widget->window;
57         cairo_t *c = gdk_cairo_create(GDK_DRAWABLE(window));
58 
59         GtkTreeModel *model = gtk_combo_box_get_model(cb);
60         GtkTreeIter iter;
61         gchar *lab;
62         if (gtk_combo_box_get_active_iter (cb, &iter))
63             gtk_tree_model_get (model, &iter, 0, &lab, -1);
64         else
65             lab = g_strdup("");
66 
67         int x  = widget->allocation.x;
68         int y  = widget->allocation.y;
69         int sx = widget->allocation.width;
70         int sy = widget->allocation.height;
71         gint mx, my;
72         bool hover = false;
73 
74         create_rectangle(c, x, y, sx, sy, 0);
75         cairo_clip(c);
76 
77         gtk_widget_get_pointer(widget, &mx, &my);
78         if (mx >= 0 and mx < sx and my >= 0 and my < sy)
79             hover = true;
80 
81         // background
82         float radius, bevel, shadow, lights, lightshover, dull, dullhover;
83         gtk_widget_style_get(widget, "border-radius", &radius, "bevel",  &bevel, "shadow", &shadow, "lights", &lights, "lightshover", &lightshover, "dull", &dull, "dullhover", &dullhover, NULL);
84         display_background(widget, c, x, y, sx - padx * 2, sy - pady * 2, padx, pady, radius, bevel, g_ascii_isspace(lab[0]) ? 0 : 1, shadow, hover ? lightshover : lights, hover ? dullhover : dull);
85 
86         // text
87         gtk_container_propagate_expose (GTK_CONTAINER (widget),
88             GTK_BIN (widget)->child, event);
89 
90         // arrow
91         if (ccb->arrow) {
92             int pw = gdk_pixbuf_get_width(ccb->arrow);
93             int ph = gdk_pixbuf_get_height(ccb->arrow);
94             gdk_draw_pixbuf(GDK_DRAWABLE(window), widget->style->fg_gc[0],
95                 ccb->arrow, 0, 0,
96                 x + sx - padx - pw, y + (sy - ph) / 2, pw, ph,
97                 GDK_RGB_DITHER_NORMAL, 0, 0);
98         }
99 
100         g_free(lab);
101         cairo_destroy(c);
102     }
103     return FALSE;
104 }
105 
106 void
calf_combobox_set_arrow(CalfCombobox * self,GdkPixbuf * arrow)107 calf_combobox_set_arrow (CalfCombobox *self, GdkPixbuf *arrow)
108 {
109     self->arrow = arrow;
110 }
111 
112 static void
calf_combobox_class_init(CalfComboboxClass * klass)113 calf_combobox_class_init (CalfComboboxClass *klass)
114 {
115     GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
116     widget_class->expose_event = calf_combobox_expose;
117     gtk_widget_class_install_style_property(
118         widget_class, g_param_spec_float("border-radius", "Border Radius", "Generate round edges",
119         0, 24, 4, GParamFlags(G_PARAM_READWRITE)));
120     gtk_widget_class_install_style_property(
121         widget_class, g_param_spec_float("bevel", "Bevel", "Bevel the object",
122         -2, 2, 0.2, GParamFlags(G_PARAM_READWRITE)));
123     gtk_widget_class_install_style_property(
124         widget_class, g_param_spec_float("shadow", "Shadow", "Draw shadows inside",
125         0, 16, 4, GParamFlags(G_PARAM_READWRITE)));
126     gtk_widget_class_install_style_property(
127         widget_class, g_param_spec_float("lights", "Lights", "Draw lights inside",
128         0, 1, 0, GParamFlags(G_PARAM_READWRITE)));
129     gtk_widget_class_install_style_property(
130         widget_class, g_param_spec_float("lightshover", "Lights Hover", "Draw lights inside when hovered",
131         0, 1, 0.5, GParamFlags(G_PARAM_READWRITE)));
132     gtk_widget_class_install_style_property(
133         widget_class, g_param_spec_float("dull", "Dull", "Draw dull inside",
134         0, 1, 0.25, GParamFlags(G_PARAM_READWRITE)));
135     gtk_widget_class_install_style_property(
136         widget_class, g_param_spec_float("dullhover", "Dull Hover", "Draw dull inside when hovered",
137         0, 1, 0.1, GParamFlags(G_PARAM_READWRITE)));
138 }
139 
140 static void
calf_combobox_init(CalfCombobox * self)141 calf_combobox_init (CalfCombobox *self)
142 {
143     GtkWidget *widget = GTK_WIDGET(self);
144     widget->requisition.width = 40;
145     widget->requisition.height = 20;
146 }
147 
148 GType
calf_combobox_get_type(void)149 calf_combobox_get_type (void)
150 {
151     static GType type = 0;
152     if (!type) {
153         static const GTypeInfo type_info = {
154             sizeof(CalfComboboxClass),
155             NULL, /* base_init */
156             NULL, /* base_finalize */
157             (GClassInitFunc)calf_combobox_class_init,
158             NULL, /* class_finalize */
159             NULL, /* class_data */
160             sizeof(CalfCombobox),
161             0,    /* n_preallocs */
162             (GInstanceInitFunc)calf_combobox_init
163         };
164 
165         for (int i = 0; ; i++) {
166             const char *name = "CalfCombobox";
167             //char *name = g_strdup_printf("CalfCombobox%u%d",
168                 //((unsigned int)(intptr_t)calf_combobox_class_init) >> 16, i);
169             if (g_type_from_name(name)) {
170                 //free(name);
171                 continue;
172             }
173             type = g_type_register_static(GTK_TYPE_COMBO_BOX,
174                                           name,
175                                           &type_info,
176                                           (GTypeFlags)0);
177             //free(name);
178             break;
179         }
180     }
181     return type;
182 }
183