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