Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
module_toolbox.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011 Henrik Andersson.
4 Copyright (C) 2012 Richard Wonka.
5 Copyright (C) 2012, 2014, 2016-2017 Tobias Ellinghaus.
6 Copyright (C) 2014-2016 Roman Lebedev.
7 Copyright (C) 2015 Jérémy Rosen.
8 Copyright (C) 2019, 2023, 2025 Aurélien PIERRE.
9 Copyright (C) 2020-2021 Pascal Obry.
10 Copyright (C) 2021 Ralf Brown.
11 Copyright (C) 2022 Martin Bařinka.
12
13 darktable is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 darktable is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with darktable. If not, see <http://www.gnu.org/licenses/>.
25*/
26
27#include "system/macros.h"
29#include "libs/lib.h"
30#include "libs/lib_api.h"
31#include "views/view.h"
32#include "gui/window_manager.h"
34#include "widgets/container.h"
35
36DT_MODULE(1)
37
38/* proxy function, to add a widget to toolbox */
40
41
48
54
55const char *name(struct dt_lib_module_t *self)
56{
57 return _("module toolbox");
58}
59
60const char **views(dt_lib_module_t *self)
61{
62 static const char *v[] = {"darkroom", "studio_capture", NULL};
63 return v;
64}
65
70
72{
73 return 0;
74}
75
77{
78 return 100;
79}
80
81
83{
84 /* initialize ui widgets */
86 self->data = (void *)d;
87
88 /* the toolbar container: use a flow box so children wrap to new lines when
89 * there are more buttons than fit in one row. */
90 d->container = self->widget = gtk_flow_box_new();
91 /* set a small spacing and a style class so we can target it in CSS */
92 gtk_flow_box_set_column_spacing(GTK_FLOW_BOX(d->container), DT_GUI_BOX_SPACING);
93 gtk_flow_box_set_row_spacing(GTK_FLOW_BOX(d->container), DT_GUI_BOX_SPACING);
94 /* allow children to keep their natural widths (don't force uniform cells) */
95 gtk_flow_box_set_homogeneous(GTK_FLOW_BOX(d->container), FALSE);
96 gtk_flow_box_set_max_children_per_line(GTK_FLOW_BOX(d->container), 20);
97 dt_gui_flow_box_as_layout(GTK_FLOW_BOX(d->container));
98
99 gtk_style_context_add_class(gtk_widget_get_style_context(d->container), "dt-module-toolbox");
100
101 /* setup proxy */
104}
105
107{
108 if(IS_NULL_PTR(self->data)) return;
110 g_list_free_full(d->child_views, dt_free_gpointer);
111 d->child_views = NULL;
112 dt_free(self->data);
113}
114
115void view_enter(struct dt_lib_module_t *self,struct dt_view_t *old_view,struct dt_view_t *new_view)
116{
118 dt_view_type_flags_t nv= new_view->view(new_view);
119 for(const GList *child_elt = d->child_views; child_elt; child_elt = g_list_next(child_elt))
120 {
121 child_data_t* child_data = (child_data_t*)child_elt->data;
122 // Hide/show the flow box's own wrapper (the GtkFlowBoxChild gtk_container_add()/
123 // gtk_flow_box_insert() auto-created around the button), not just the button
124 // itself: a visible-but-empty wrapper still reserves a cell and its spacing
125 // in the flow layout, leaving gaps and misaligning the buttons that ARE shown.
126 GtkWidget *wrapper = gtk_widget_get_parent(GTK_WIDGET(child_data->child));
127 GtkWidget *item = GTK_IS_FLOW_BOX_CHILD(wrapper) ? wrapper : GTK_WIDGET(child_data->child);
128 if(child_data->views & nv)
129 {
130 gtk_widget_show_all(item);
131 }
132 else
133 {
134 gtk_widget_hide(item);
135 }
136 }
137}
138
140{
142 /* If caller set a priority flag on the widget, insert it first and add a
143 * separator after it. This is used to place the autoset button first. */
144 gpointer prio = g_object_get_data(G_OBJECT(widget), "dt-toolbox-priority");
145 if(prio && GPOINTER_TO_INT(prio) == 1)
146 {
147 /* insert widget at position 0 */
148 /* mark widget for css styling and insert at the first position */
149 gtk_style_context_add_class(gtk_widget_get_style_context(GTK_WIDGET(widget)), "dt-module-toolbox-item");
150 gtk_style_context_add_class(gtk_widget_get_style_context(GTK_WIDGET(widget)), "dt-toolbox-priority");
151 gtk_widget_set_hexpand(GTK_WIDGET(widget), FALSE);
152 gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
153 gtk_flow_box_insert(GTK_FLOW_BOX(d->container), GTK_WIDGET(widget), 0);
154 // The box was made a layout container in gui_init(), but this child is new: its own
155 // wrapper has just been created and would otherwise take the toolbar's keyboard focus.
156 dt_gui_flow_box_child_as_layout(GTK_WIDGET(widget));
157
158 /* register both in child_views so view visibility logic applies */
159 child_data_t *child_data = malloc(sizeof(child_data_t));
160 child_data->child = widget;
161 child_data->views = views;
162 d->child_views = g_list_prepend(d->child_views, child_data);
163
164 gtk_widget_show_all(GTK_WIDGET(widget));
165 return;
166 }
167
168 /* Add widget to flow container so it participates in wrapping. */
169 gtk_style_context_add_class(gtk_widget_get_style_context(GTK_WIDGET(widget)), "dt-module-toolbox-item");
170 gtk_widget_set_hexpand(GTK_WIDGET(widget), FALSE);
171 gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
172 gtk_container_add(GTK_CONTAINER(d->container), GTK_WIDGET(widget));
173 gtk_widget_show_all(GTK_WIDGET(widget));
174
175 child_data_t *child_data = malloc(sizeof(child_data_t));
176 child_data->child = widget;
177 child_data->views = views;
178 d->child_views = g_list_prepend(d->child_views, child_data);
179
180}
181// clang-format off
182// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
183// vim: shiftwidth=2 expandtab tabstop=2 cindent
184// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
185// clang-format on
#define FALSE
Definition ashift_lsd.c:158
const float v
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
void dt_gui_flow_box_as_layout(GtkFlowBox *box)
Definition container.c:98
void dt_gui_flow_box_child_as_layout(GtkWidget *child)
Definition container.c:105
struct dt_view_manager_t * dt_view_manager_get_global(void)
Definition darktable.c:599
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition macros.h:96
static void dt_free_gpointer(gpointer ptr)
g_free() one pointer, with the signature GDestroyNotify wants.
Definition mem_alloc.h:184
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
static void _lib_module_toolbox_add(dt_lib_module_t *self, GtkWidget *widget, dt_view_type_flags_t views)
void gui_cleanup(dt_lib_module_t *self)
uint32_t container(dt_lib_module_t *self)
void gui_init(dt_lib_module_t *self)
void view_enter(struct dt_lib_module_t *self, struct dt_view_t *old_view, struct dt_view_t *new_view)
int position()
const char ** views(dt_lib_module_t *self)
int expandable(dt_lib_module_t *self)
#define DT_MODULE(MODVER)
Instantiate the version handshake every module must export. Use once, at file scope,...
const char * name
Definition pdf.h:90
dt_view_type_flags_t views
GtkWidget * child
GModule *void * data
Definition lib.h:79
GtkWidget * widget
Definition lib.h:83
struct dt_view_manager_t::@60 proxy
struct dt_view_manager_t::@60::@61 module_toolbox
struct dt_lib_module_t *void(* add)(struct dt_lib_module_t *, GtkWidget *, dt_view_type_flags_t)
Definition view.h:224
dt_view_type_flags_t
Definition view.h:76
#define DT_GUI_BOX_SPACING
@ DT_UI_CONTAINER_PANEL_LEFT_BOTTOM