1 /*
2 * This file is part of brisk-menu.
3 *
4 * Copyright © 2016-2020 Brisk Menu Developers
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
12 #define _GNU_SOURCE
13
14 #include "util.h"
15
16 BRISK_BEGIN_PEDANTIC
17 #include "category-button.h"
18 #include "menu-private.h"
19 #include <glib/gi18n.h>
20 #include <gtk/gtk.h>
21 BRISK_END_PEDANTIC
22
23 struct _BriskClassicCategoryButtonClass {
24 GtkRadioButtonClass parent_class;
25 };
26
27 /**
28 * BriskClassicCategoryButton is the toplevel window type used within the applet.
29 */
30 struct _BriskClassicCategoryButton {
31 GtkRadioButton parent;
32 BriskSection *section;
33 GtkWidget *label;
34 GtkWidget *image;
35 };
36
37 G_DEFINE_TYPE(BriskClassicCategoryButton, brisk_classic_category_button, GTK_TYPE_RADIO_BUTTON)
38
39 enum { PROP_SECTION = 1, N_PROPS };
40
41 static GParamSpec *obj_properties[N_PROPS] = {
42 NULL,
43 };
44
brisk_classic_category_button_set_property(GObject * object,guint id,const GValue * value,GParamSpec * spec)45 static void brisk_classic_category_button_set_property(GObject *object, guint id,
46 const GValue *value, GParamSpec *spec)
47 {
48 BriskClassicCategoryButton *self = BRISK_CLASSIC_CATEGORY_BUTTON(object);
49
50 switch (id) {
51 case PROP_SECTION:
52 self->section = g_value_get_pointer(value);
53 break;
54 default:
55 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, id, spec);
56 break;
57 }
58 }
59
brisk_classic_category_button_get_property(GObject * object,guint id,GValue * value,GParamSpec * spec)60 static void brisk_classic_category_button_get_property(GObject *object, guint id, GValue *value,
61 GParamSpec *spec)
62 {
63 BriskClassicCategoryButton *self = BRISK_CLASSIC_CATEGORY_BUTTON(object);
64
65 switch (id) {
66 case PROP_SECTION:
67 g_value_set_pointer(value, self->section);
68 break;
69 default:
70 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, id, spec);
71 break;
72 }
73 }
74
75 /**
76 * brisk_classic_category_button_new:
77 *
78 * Construct a new BriskClassicCategoryButton object
79 */
brisk_classic_category_button_new(BriskSection * section)80 GtkWidget *brisk_classic_category_button_new(BriskSection *section)
81 {
82 return g_object_new(BRISK_TYPE_CLASSIC_CATEGORY_BUTTON, "section", section, NULL);
83 }
84
85 /**
86 * brisk_classic_category_button_dispose:
87 *
88 * Clean up a BriskClassicCategoryButton instance
89 */
brisk_classic_category_button_dispose(GObject * obj)90 static void brisk_classic_category_button_dispose(GObject *obj)
91 {
92 BriskClassicCategoryButton *self = BRISK_CLASSIC_CATEGORY_BUTTON(obj);
93
94 g_clear_object(&self->section);
95
96 G_OBJECT_CLASS(brisk_classic_category_button_parent_class)->dispose(obj);
97 }
98
99 /**
100 * Handle constructor specifics for our button
101 */
brisk_classic_category_button_constructed(GObject * obj)102 static void brisk_classic_category_button_constructed(GObject *obj)
103 {
104 BriskClassicCategoryButton *self = NULL;
105
106 self = BRISK_CLASSIC_CATEGORY_BUTTON(obj);
107
108 /* If we have a section, use it, otherwise we're a special "All" button */
109 if (self->section) {
110 gtk_label_set_label(GTK_LABEL(self->label), brisk_section_get_name(self->section));
111 gtk_image_set_from_gicon(GTK_IMAGE(self->image),
112 (GIcon *)brisk_section_get_icon(self->section),
113 GTK_ICON_SIZE_BUTTON);
114 } else {
115 gtk_label_set_label(GTK_LABEL(self->label), _("All"));
116 gtk_image_set_from_icon_name(GTK_IMAGE(self->image),
117 "starred",
118 GTK_ICON_SIZE_BUTTON);
119 }
120
121 gtk_image_set_pixel_size(GTK_IMAGE(self->image), 16);
122
123 G_OBJECT_CLASS(brisk_classic_category_button_parent_class)->constructed(obj);
124 }
125
126 /**
127 * brisk_classic_category_button_class_init:
128 *
129 * Handle class initialisation
130 */
brisk_classic_category_button_class_init(BriskClassicCategoryButtonClass * klazz)131 static void brisk_classic_category_button_class_init(BriskClassicCategoryButtonClass *klazz)
132 {
133 GObjectClass *obj_class = G_OBJECT_CLASS(klazz);
134
135 /* gobject vtable hookup */
136 obj_class->dispose = brisk_classic_category_button_dispose;
137 obj_class->set_property = brisk_classic_category_button_set_property;
138 obj_class->get_property = brisk_classic_category_button_get_property;
139 obj_class->constructed = brisk_classic_category_button_constructed;
140
141 obj_properties[PROP_SECTION] = g_param_spec_pointer("section",
142 "The BriskSection",
143 "Section that this category represents",
144 G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
145 g_object_class_install_properties(obj_class, N_PROPS, obj_properties);
146 }
147
148 /**
149 * brisk_classic_category_button_init:
150 *
151 * Handle construction of the BriskClassicCategoryButton
152 */
brisk_classic_category_button_init(BriskClassicCategoryButton * self)153 static void brisk_classic_category_button_init(BriskClassicCategoryButton *self)
154 {
155 GtkStyleContext *style = NULL;
156 GtkWidget *label = NULL;
157 GtkWidget *image = NULL;
158 GtkWidget *layout = NULL;
159
160 /* Main layout */
161 layout = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
162 gtk_container_add(GTK_CONTAINER(self), layout);
163
164 /* Image on the left */
165 image = gtk_image_new();
166 self->image = image;
167 gtk_widget_set_margin_end(image, 7);
168 gtk_box_pack_start(GTK_BOX(layout), image, FALSE, FALSE, 0);
169
170 /* Display label */
171 label = gtk_label_new("");
172 self->label = label;
173 g_object_set(self->label,
174 "halign",
175 GTK_ALIGN_START,
176 "valign",
177 GTK_ALIGN_CENTER,
178 "margin-end",
179 15,
180 NULL);
181 gtk_box_pack_start(GTK_BOX(layout), label, TRUE, TRUE, 0);
182
183 /* Look like a button */
184 g_object_set(G_OBJECT(self), "draw-indicator", FALSE, NULL);
185 gtk_widget_set_can_focus(GTK_WIDGET(self), TRUE);
186
187 /* Flatten the button */
188 style = gtk_widget_get_style_context(GTK_WIDGET(self));
189 gtk_style_context_add_class(style, GTK_STYLE_CLASS_FLAT);
190 }
191
192 /*
193 * Editor modelines - https://www.wireshark.org/tools/modelines.html
194 *
195 * Local variables:
196 * c-basic-offset: 8
197 * tab-width: 8
198 * indent-tabs-mode: nil
199 * End:
200 *
201 * vi: set shiftwidth=8 tabstop=8 expandtab:
202 * :indentSize=8:tabSize=8:noTabs=true:
203 */
204