1 /*
2  * This file is part of brisk-menu.
3  *
4  * Copyright © 2017-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 "sidebar-scroller.h"
18 #include <gtk/gtk.h>
19 
20 BRISK_END_PEDANTIC
21 
22 struct _BriskMenuSidebarScrollerClass {
23         GtkScrolledWindowClass parent_class;
24 };
25 
26 struct _BriskMenuSidebarScroller {
27         GtkScrolledWindow parent;
28 };
29 
30 G_DEFINE_TYPE(BriskMenuSidebarScroller, brisk_menu_sidebar_scroller, GTK_TYPE_SCROLLED_WINDOW)
31 
32 static void brisk_menu_sidebar_scroller_get_preferred_height(GtkWidget *widget, gint *min_height,
33                                                              gint *nat_height);
34 
35 /**
36  * brisk_menu_sidebar_scroller_new:
37  *
38  * Construct a new BriskMenuSidebarScroller object
39  */
brisk_menu_sidebar_scroller_new()40 GtkWidget *brisk_menu_sidebar_scroller_new()
41 {
42         return g_object_new(BRISK_TYPE_MENU_SIDEBAR_SCROLLER,
43                             "hadjustment",
44                             NULL,
45                             "vadjustment",
46                             NULL,
47                             NULL);
48 }
49 
50 /**
51  * brisk_menu_sidebar_scroller_class_init:
52  *
53  * Handle class initialisation
54  */
brisk_menu_sidebar_scroller_class_init(BriskMenuSidebarScrollerClass * klazz)55 static void brisk_menu_sidebar_scroller_class_init(BriskMenuSidebarScrollerClass *klazz)
56 {
57         GtkWidgetClass *wid_class = GTK_WIDGET_CLASS(klazz);
58         wid_class->get_preferred_height = brisk_menu_sidebar_scroller_get_preferred_height;
59 }
60 
61 /**
62  * brisk_menu_sidebar_scroller_init:
63  *
64  * Handle construction of the BriskMenuEntryButton
65  */
brisk_menu_sidebar_scroller_init(BriskMenuSidebarScroller * self)66 static void brisk_menu_sidebar_scroller_init(BriskMenuSidebarScroller *self)
67 {
68         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(self),
69                                        GTK_POLICY_NEVER,
70                                        GTK_POLICY_AUTOMATIC);
71         gtk_scrolled_window_set_overlay_scrolling(GTK_SCROLLED_WINDOW(self), FALSE);
72 }
73 
brisk_menu_sidebar_scroller_get_preferred_height(GtkWidget * widget,gint * min_height,gint * nat_height)74 static void brisk_menu_sidebar_scroller_get_preferred_height(GtkWidget *widget, gint *min_height,
75                                                              gint *nat_height)
76 {
77         GdkScreen *screen = NULL;
78         GdkWindow *window = NULL;
79         GtkStyleContext *style_context = NULL;
80         GtkStateFlags state_flags;
81         GtkBorder border;
82         GtkBorder padding;
83         GtkBorder margin;
84         gint spacing;
85         GdkRectangle geom = { 0 };
86         gint applet_x, applet_y = 0;
87         gint mon = 0;
88 
89         /* Find out where we are on screen */
90         window = gtk_widget_get_window(widget);
91         gdk_window_get_origin(window, &applet_x, &applet_y);
92 
93         /* Grab the geometry for the monitor we're currently on */
94         screen = gtk_widget_get_screen(widget);
95         mon = gdk_screen_get_monitor_at_point(screen, applet_x, applet_y);
96         gdk_screen_get_monitor_geometry(screen, mon, &geom);
97 
98         gint max_height = geom.height - 200;
99 
100         GtkBin *bin = NULL;
101         GtkWidget *child = NULL;
102 
103         bin = GTK_BIN(widget);
104         child = gtk_bin_get_child(bin);
105 
106         style_context = gtk_widget_get_style_context(widget);
107         state_flags = gtk_widget_get_state_flags(widget);
108         gtk_style_context_get_border(style_context, state_flags, &border);
109         gtk_style_context_get_padding(style_context, state_flags, &padding);
110         gtk_style_context_get_margin(style_context, state_flags, &margin);
111 
112         spacing = border.top + border.bottom + padding.top + padding.bottom + margin.top + margin.bottom;
113 
114         if (child) {
115                 gtk_widget_get_preferred_height(child, min_height, nat_height);
116                 *min_height = MIN(max_height, *min_height) + spacing;
117                 *nat_height = MIN(max_height, *nat_height) + spacing;
118         } else {
119                 *min_height = *nat_height = 0;
120         }
121 }
122 
123 /*
124  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
125  *
126  * Local variables:
127  * c-basic-offset: 8
128  * tab-width: 8
129  * indent-tabs-mode: nil
130  * End:
131  *
132  * vi: set shiftwidth=8 tabstop=8 expandtab:
133  * :indentSize=8:tabSize=8:noTabs=true:
134  */
135