1 /*
2 * This file is part of GNOME Twitch - 'Enjoy Twitch on your GNU/Linux desktop'
3 * Copyright © 2017 Vincent Szolnoky <vinszent@vinszent.com>
4 *
5 * GNOME Twitch 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 * GNOME Twitch 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 GNOME Twitch. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "gt-container-view.h"
20 #include "gt-item-container.h"
21
22 #define TAG "GtContainerView"
23 #include "gnome-twitch/gt-log.h"
24
25 typedef struct
26 {
27 gboolean search_active;
28 gboolean show_back_button;
29
30 GtkWidget* search_bar;
31 GtkWidget* search_entry;
32 GtkWidget* menu_button;
33 GtkWidget* container_stack;
34 } GtContainerViewPrivate;
35
36 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(GtContainerView, gt_container_view, GTK_TYPE_BOX);
37
38 enum
39 {
40 PROP_0,
41 PROP_SEARCH_ACTIVE,
42 PROP_SHOW_BACK_BUTTON,
43 NUM_PROPS
44 };
45
46 static GParamSpec* props[NUM_PROPS];
47
48 static void
get_property(GObject * obj,guint prop,GValue * val,GParamSpec * pspec)49 get_property(GObject* obj,
50 guint prop,
51 GValue* val,
52 GParamSpec* pspec)
53 {
54 GtContainerView* self = GT_CONTAINER_VIEW(obj);
55 GtContainerViewPrivate* priv = gt_container_view_get_instance_private(self);
56
57 switch (prop)
58 {
59 case PROP_SEARCH_ACTIVE:
60 g_value_set_boolean(val, priv->search_active);
61 break;
62 case PROP_SHOW_BACK_BUTTON:
63 g_value_set_boolean(val, priv->show_back_button);
64 break;
65 default:
66 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop, pspec);
67 }
68 }
69
70 static void
set_property(GObject * obj,guint prop,const GValue * val,GParamSpec * pspec)71 set_property(GObject* obj,
72 guint prop,
73 const GValue* val,
74 GParamSpec* pspec)
75 {
76 GtContainerView* self = GT_CONTAINER_VIEW(obj);
77 GtContainerViewPrivate* priv = gt_container_view_get_instance_private(self);
78
79 switch (prop)
80 {
81 case PROP_SEARCH_ACTIVE:
82 priv->search_active = g_value_get_boolean(val);
83 break;
84 case PROP_SHOW_BACK_BUTTON:
85 priv->show_back_button = g_value_get_boolean(val);
86 break;
87 default:
88 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop, pspec);
89 }
90 }
91
92
93 static void
gt_container_view_class_init(GtContainerViewClass * klass)94 gt_container_view_class_init(GtContainerViewClass* klass)
95 {
96 G_OBJECT_CLASS(klass)->get_property = get_property;
97 G_OBJECT_CLASS(klass)->set_property = set_property;
98
99 props[PROP_SHOW_BACK_BUTTON] = g_param_spec_boolean(
100 "show-back-button",
101 "Show back button",
102 "Whether showing back button",
103 FALSE,
104 G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
105
106 props[PROP_SEARCH_ACTIVE] = g_param_spec_boolean(
107 "search-active",
108 "Search active",
109 "Whether search active",
110 FALSE,
111 G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
112
113 g_object_class_install_properties(G_OBJECT_CLASS(klass), NUM_PROPS, props);
114
115 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS(klass),
116 "/com/vinszent/GnomeTwitch/ui/gt-container-view.ui");
117
118 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS(klass), GtContainerView, container_stack);
119 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS(klass), GtContainerView, search_bar);
120 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS(klass), GtContainerView, search_entry);
121 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS(klass), GtContainerView, menu_button);
122 }
123
124 static void
gt_container_view_init(GtContainerView * self)125 gt_container_view_init(GtContainerView* self)
126 {
127 GtContainerViewPrivate* priv = gt_container_view_get_instance_private(self);
128
129 gtk_widget_init_template(GTK_WIDGET(self));
130
131 gtk_search_bar_connect_entry(GTK_SEARCH_BAR(priv->search_bar),
132 GTK_ENTRY(priv->search_entry));
133
134 g_object_bind_property(self, "search-active",
135 priv->search_bar, "search-mode-enabled",
136 G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
137 }
138
139 /* Should only be used by children */
140 void
gt_container_view_add_container(GtContainerView * self,GtItemContainer * container)141 gt_container_view_add_container(GtContainerView* self, GtItemContainer* container)
142 {
143 GtContainerViewPrivate* priv = gt_container_view_get_instance_private(self);
144
145 gtk_container_add(GTK_CONTAINER(priv->container_stack),
146 GTK_WIDGET(container));
147
148 gtk_widget_show_all(GTK_WIDGET(container));
149 }
150
151 void
gt_container_view_set_search_popover_widget(GtContainerView * self,GtkWidget * widget)152 gt_container_view_set_search_popover_widget(GtContainerView* self, GtkWidget* widget)
153 {
154 g_assert(GT_IS_CONTAINER_VIEW(self));
155 g_assert(GTK_IS_WIDGET(widget));
156
157 GtContainerViewPrivate* priv = gt_container_view_get_instance_private(self);
158 GtkWidget* popover = gtk_popover_new(priv->menu_button);
159
160 gtk_container_add(GTK_CONTAINER(popover), widget);
161
162 gtk_menu_button_set_popover(GTK_MENU_BUTTON(priv->menu_button), GTK_WIDGET(popover));
163
164 gtk_widget_show_all(priv->menu_button);
165 gtk_widget_show_all(widget);
166 }
167
168 void
gt_container_view_refresh(GtContainerView * self)169 gt_container_view_refresh(GtContainerView* self)
170 {
171 g_assert(GT_IS_CONTAINER_VIEW(self));
172 g_assert_nonnull(GT_CONTAINER_VIEW_GET_CLASS(self)->refresh);
173
174 GT_CONTAINER_VIEW_GET_CLASS(self)->refresh(self);
175 }
176
177 void
gt_container_view_go_back(GtContainerView * self)178 gt_container_view_go_back(GtContainerView* self)
179 {
180 g_assert(GT_IS_CONTAINER_VIEW(self));
181 g_assert_nonnull(GT_CONTAINER_VIEW_GET_CLASS(self)->go_back);
182
183 GT_CONTAINER_VIEW_GET_CLASS(self)->go_back(self);
184 }
185
186 void
gt_container_view_set_search_active(GtContainerView * self,gboolean search_active)187 gt_container_view_set_search_active(GtContainerView* self, gboolean search_active)
188 {
189 g_assert(GT_IS_CONTAINER_VIEW(self));
190
191 GtContainerViewPrivate* priv = gt_container_view_get_instance_private(self);
192
193 priv->search_active = search_active;
194 }
195
196 gboolean
gt_container_view_get_search_active(GtContainerView * self)197 gt_container_view_get_search_active(GtContainerView* self)
198 {
199 g_assert(GT_IS_CONTAINER_VIEW(self));
200
201 GtContainerViewPrivate* priv = gt_container_view_get_instance_private(self);
202
203 return priv->search_active;
204 }
205
206 gboolean
gt_container_view_get_show_back_button(GtContainerView * self)207 gt_container_view_get_show_back_button(GtContainerView* self)
208 {
209 g_assert(GT_IS_CONTAINER_VIEW(self));
210
211 GtContainerViewPrivate* priv = gt_container_view_get_instance_private(self);
212
213 return priv->show_back_button;
214 }
215
216 GtkWidget*
gt_container_view_get_container_stack(GtContainerView * self)217 gt_container_view_get_container_stack(GtContainerView* self)
218 {
219 GtContainerViewPrivate* priv = gt_container_view_get_instance_private(self);
220
221 g_assert(GT_IS_CONTAINER_VIEW(self));
222
223 return priv->container_stack;
224 }
225
226 GtkWidget*
gt_container_view_get_search_entry(GtContainerView * self)227 gt_container_view_get_search_entry(GtContainerView* self)
228 {
229 GtContainerViewPrivate* priv = gt_container_view_get_instance_private(self);
230
231 g_assert(GT_IS_CONTAINER_VIEW(self));
232
233 return priv->search_entry;
234 }
235
236 GtkWidget*
gt_container_view_get_search_bar(GtContainerView * self)237 gt_container_view_get_search_bar(GtContainerView* self)
238 {
239 g_assert(GT_IS_CONTAINER_VIEW(self));
240
241 GtContainerViewPrivate* priv = gt_container_view_get_instance_private(self);
242
243 return priv->search_bar;
244 }
245