GDS-Render v1.2.1
conv-settings-dialog.c
Go to the documentation of this file.
1/*
2 * GDSII-Converter
3 * Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
4 *
5 * This file is part of GDSII-Converter.
6 *
7 * GDSII-Converter is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * GDSII-Converter is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
18 */
19
33#include <glib/gi18n.h>
34
36 GtkDialog parent;
37 /* Private loot */
38 GtkWidget *radio_latex;
39 GtkWidget *radio_cairo_pdf;
40 GtkWidget *radio_cairo_svg;
41 GtkWidget *scale;
42 GtkWidget *layer_check;
43 GtkWidget *standalone_check;
44 GtkDrawingArea *shape_drawing;
45 GtkLabel *x_label;
46 GtkLabel *y_label;
47
48 GtkLabel *x_output_label;
49 GtkLabel *y_output_label;
50
51 unsigned int cell_height;
52 unsigned int cell_width;
54};
55
56G_DEFINE_TYPE(RendererSettingsDialog, renderer_settings_dialog, GTK_TYPE_DIALOG)
57
58enum {
61};
62
63static GParamSpec *properties[PROP_COUNT];
64
65static void renderer_settings_dialog_set_property(GObject *object, guint property_id,
66 const GValue *value, GParamSpec *pspec)
67{
68 const gchar *title = NULL;
69
70 switch (property_id) {
71 case PROP_CELL_NAME:
72 title = g_value_get_string(value);
73 if (title)
74 gtk_window_set_title(GTK_WINDOW(object), title);
75 break;
76 default:
77 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
78 break;
79 }
80}
81
82static void renderer_settings_dialog_get_property(GObject *object, guint property_id,
83 GValue *value, GParamSpec *pspec)
84{
85 const gchar *title;
86
87 switch (property_id) {
88 case PROP_CELL_NAME:
89 title = gtk_window_get_title(GTK_WINDOW(object));
90 g_value_set_string(value, title);
91 break;
92 default:
93 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
94 break;
95 }
96}
97
98static void renderer_settings_dialog_class_init(RendererSettingsDialogClass *klass)
99{
100 GObjectClass *oclass = G_OBJECT_CLASS(klass);
101
102 /* Override virtual functions */
103 oclass->set_property = renderer_settings_dialog_set_property;
104 oclass->get_property = renderer_settings_dialog_get_property;
105
106 properties[PROP_CELL_NAME] = g_param_spec_string(N_("cell-name"),
107 N_("cell-name"),
108 N_("Cell name to be displayed in header bar"),
109 "",
110 G_PARAM_READWRITE);
111 g_object_class_install_properties(oclass, PROP_COUNT, properties);
112}
113
114static void show_tex_options(RendererSettingsDialog *self)
115{
116 gtk_widget_show(self->layer_check);
117 gtk_widget_show(self->standalone_check);
118
119}
120
121static void hide_tex_options(RendererSettingsDialog *self)
122{
123 gtk_widget_hide(self->layer_check);
124 gtk_widget_hide(self->standalone_check);
125}
126
127static void latex_render_callback(GtkToggleButton *radio, RendererSettingsDialog *dialog)
128{
129 if (gtk_toggle_button_get_active(radio))
130 show_tex_options(dialog);
131 else
132 hide_tex_options(dialog);
133}
134
135static gboolean shape_drawer_drawing_callback(GtkWidget *widget, cairo_t *cr, gpointer data)
136{
137 int width;
138 int height;
139 GtkStyleContext *style_context;
140 GdkRGBA foreground_color;
141 RendererSettingsDialog *dialog = (RendererSettingsDialog *)data;
142 double usable_width;
143 double usable_height;
144 double height_scale;
145 double width_scale;
146 double final_scale_value;
147
148 style_context = gtk_widget_get_style_context(widget);
149 width = gtk_widget_get_allocated_width(widget);
150 height = gtk_widget_get_allocated_height(widget);
151
152 gtk_render_background(style_context, cr, 0, 0, width, height);
153
154 gtk_style_context_get_color(style_context, gtk_style_context_get_state(style_context),
155 &foreground_color);
156
157 gdk_cairo_set_source_rgba(cr, &foreground_color);
158
159 cairo_save(cr);
160
161 /* Tranform coordiante system */
162 cairo_scale(cr, 1, -1);
163 cairo_translate(cr, (double)width/2.0, -(double)height/2.0);
164
165 /* Define usable drawing area */
166 usable_width = (0.95*(double)width) - 15.0;
167 usable_height = (0.95*(double)height) - 15.0;
168
169 width_scale = usable_width/(double)dialog->cell_width;
170 height_scale = usable_height/(double)dialog->cell_height;
171
172 final_scale_value = (width_scale < height_scale ? width_scale : height_scale);
173
174 cairo_rectangle(cr,
175 -(double)dialog->cell_width * final_scale_value / 2.0,
176 -(double)dialog->cell_height * final_scale_value / 2.0,
177 (double)dialog->cell_width * final_scale_value,
178 (double)dialog->cell_height * final_scale_value);
179 cairo_stroke(cr);
180 cairo_restore(cr);
181
182 return FALSE;
183}
184
185static double convert_number_to_engineering(double input, const char **out_prefix)
186{
187 const char *selected_prefix = NULL;
188 double return_val = 0.0;
189 int idx;
190 static const char * const prefixes[] = {"y", "z", "a", "f", "p", "n", "u", "m", "c", "d", /* < 1 */
191 "", /* 1 */
192 "h", "k", "M", "G", "T", "P", "E", "Z", "Y"}; /* > 1 */
193 static const double scale[] = {1E-24, 1E-21, 1E-18, 1E-15, 1E-12, 1E-9, 1E-6, 1E-3, 1E-2, 1E-1,
194 1,
195 1E2, 1E3, 1E6, 1E9, 1E12, 1E15, 1E18, 1E21, 1E24};
196 const int prefix_count = (int)(sizeof(prefixes)/sizeof(char *));
197
198 /* If pointer is invalid, return NaN */
199 if (!out_prefix)
200 return (0.0 / 0.0);
201
202 /* Start with the 2nd smallest prefix */
203 for (idx = 1; idx < prefix_count; idx++) {
204 if (input < scale[idx]) {
205 /* This prefix is bigger than the number. Take the previous one */
206 selected_prefix = prefixes[idx-1];
207 return_val = input / scale[idx-1];
208 break;
209 }
210 }
211
212 /* Check if prefix was set by loop. Else take the largest in the list */
213 if (selected_prefix == NULL) {
214 selected_prefix = prefixes[prefix_count-1];
215 return_val = input / scale[prefix_count-1];
216 }
217
218 if (out_prefix)
219 *out_prefix = selected_prefix;
220
221 return return_val;
222}
223
224static void renderer_settings_dialog_update_labels(RendererSettingsDialog *self)
225{
226 char default_buff[100];
227 double scale;
228 double width_meters;
229 double height_meters;
230 double width_engineering;
231 const char *width_prefix;
232 double height_engineering;
233 const char *height_prefix;
234
235 if (!self)
236 return;
237
238 width_meters = (double)self->cell_width * self->unit_in_meters;
239 height_meters = (double)self->cell_height * self->unit_in_meters;
240
241 width_engineering = convert_number_to_engineering(width_meters, &width_prefix);
242 height_engineering = convert_number_to_engineering(height_meters, &height_prefix);
243
244 snprintf(default_buff, sizeof(default_buff), _("Width: %.3lf %sm"), width_engineering, width_prefix);
245 gtk_label_set_text(self->x_label, default_buff);
246 snprintf(default_buff, sizeof(default_buff), _("Height: %.3lf %sm"), height_engineering, height_prefix);
247 gtk_label_set_text(self->y_label, default_buff);
248
249 scale = gtk_range_get_value(GTK_RANGE(self->scale));
250
251 /* Set the pixel sizes */
252 snprintf(default_buff, sizeof(default_buff), _("Output Width: %u px"),
253 (unsigned int)((double)self->cell_width / scale));
254 gtk_label_set_text(self->x_output_label, default_buff);
255 snprintf(default_buff, sizeof(default_buff), _("Output Height: %u px"),
256 (unsigned int)((double)self->cell_height / scale));
257 gtk_label_set_text(self->y_output_label, default_buff);
258}
259
260static void scale_value_changed(GtkRange *range, gpointer user_data)
261{
262 (void)range;
263 RendererSettingsDialog *dialog;
264
265 dialog = RENDERER_SETTINGS_DIALOG(user_data);
267}
268
269static void renderer_settings_dialog_init(RendererSettingsDialog *self)
270{
271 GtkBuilder *builder;
272 GtkWidget *box;
273 GtkDialog *dialog;
274
275 dialog = &self->parent;
276
277 builder = gtk_builder_new_from_resource("/gui/dialog.glade");
278 box = GTK_WIDGET(gtk_builder_get_object(builder, "dialog-box"));
279 self->radio_latex = GTK_WIDGET(gtk_builder_get_object(builder, "latex-radio"));
280 self->radio_cairo_pdf = GTK_WIDGET(gtk_builder_get_object(builder, "cairo-pdf-radio"));
281 self->radio_cairo_svg = GTK_WIDGET(gtk_builder_get_object(builder, "cairo-svg-radio"));
282 self->scale = GTK_WIDGET(gtk_builder_get_object(builder, "dialog-scale"));
283 self->standalone_check = GTK_WIDGET(gtk_builder_get_object(builder, "standalone-check"));
284 self->layer_check = GTK_WIDGET(gtk_builder_get_object(builder, "layer-check"));
285 self->shape_drawing = GTK_DRAWING_AREA(gtk_builder_get_object(builder, "shape-drawer"));
286 self->x_label = GTK_LABEL(gtk_builder_get_object(builder, "x-label"));
287 self->y_label = GTK_LABEL(gtk_builder_get_object(builder, "y-label"));
288 self->x_output_label = GTK_LABEL(gtk_builder_get_object(builder, "x-output-label"));
289 self->y_output_label = GTK_LABEL(gtk_builder_get_object(builder, "y-output-label"));
290
291 gtk_dialog_add_buttons(dialog, _("Cancel"), GTK_RESPONSE_CANCEL, _("OK"), GTK_RESPONSE_OK, NULL);
292 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dialog)), box);
293 gtk_window_set_title(GTK_WINDOW(self), _("Renderer Settings"));
294
295 g_signal_connect(self->radio_latex, "toggled", G_CALLBACK(latex_render_callback), (gpointer)self);
296 g_signal_connect(G_OBJECT(self->shape_drawing),
297 "draw", G_CALLBACK(shape_drawer_drawing_callback), (gpointer)self);
298
299 g_signal_connect(self->scale, "value-changed", G_CALLBACK(scale_value_changed), (gpointer)self);
300
301 /* Default values */
302 self->cell_width = 1;
303 self->cell_height = 1;
304 self->unit_in_meters = 1E-6;
306
307 g_object_unref(builder);
308}
309
310RendererSettingsDialog *renderer_settings_dialog_new(GtkWindow *parent)
311{
312 RendererSettingsDialog *res;
313
314 res = RENDERER_SETTINGS_DIALOG(g_object_new(RENDERER_TYPE_SETTINGS_DIALOG, NULL));
315 if (res && parent)
316 gtk_window_set_transient_for(GTK_WINDOW(res), parent);
317
318 return res;
319}
320
321void renderer_settings_dialog_get_settings(RendererSettingsDialog *dialog, struct render_settings *settings)
322{
323
324 if (!settings || !dialog)
325 return;
326 settings->scale = gtk_range_get_value(GTK_RANGE(dialog->scale));
327
328 /* Get active radio button selection */
329 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_latex)) == TRUE)
330 settings->renderer = RENDERER_LATEX_TIKZ;
331 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_pdf)) == TRUE)
333 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_svg)) == TRUE)
335
336 settings->tex_pdf_layers = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->layer_check));
337 settings->tex_standalone = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->standalone_check));
338}
339
340void renderer_settings_dialog_set_settings(RendererSettingsDialog *dialog, struct render_settings *settings)
341{
342 if (!settings || !dialog)
343 return;
344
345 gtk_range_set_value(GTK_RANGE(dialog->scale), settings->scale);
346 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->layer_check), settings->tex_pdf_layers);
347 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->standalone_check), settings->tex_standalone);
348
349 switch (settings->renderer) {
351 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_latex), TRUE);
352 show_tex_options(dialog);
353 break;
355 hide_tex_options(dialog);
356 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_pdf), TRUE);
357 break;
359 hide_tex_options(dialog);
360 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_svg), TRUE);
361 break;
362 }
363}
364
365void renderer_settings_dialog_set_cell_width(RendererSettingsDialog *dialog, unsigned int width)
366{
367 if (!dialog)
368 return;
369
370 if (width == 0)
371 width = 1;
372
373 dialog->cell_width = width;
375}
376
377void renderer_settings_dialog_set_cell_height(RendererSettingsDialog *dialog, unsigned int height)
378{
379 if (!dialog)
380 return;
381
382 if (height == 0)
383 height = 1;
384
385 dialog->cell_height = height;
387}
388
389void renderer_settings_dialog_set_database_unit_scale(RendererSettingsDialog *dialog, double unit_in_meters)
390{
391 if (!dialog)
392 return;
393
394 if (unit_in_meters < 0)
395 unit_in_meters *= -1;
396
397 dialog->unit_in_meters = unit_in_meters;
399}
400
Header file for the Conversion Settings Dialog.
static void hide_tex_options(RendererSettingsDialog *self)
static GParamSpec * properties[PROP_COUNT]
static double convert_number_to_engineering(double input, const char **out_prefix)
static void renderer_settings_dialog_update_labels(RendererSettingsDialog *self)
void renderer_settings_dialog_get_settings(RendererSettingsDialog *dialog, struct render_settings *settings)
Get the settings configured in the dialog.
void renderer_settings_dialog_set_cell_height(RendererSettingsDialog *dialog, unsigned int height)
renderer_settings_dialog_set_cell_height Set height for rendered cell
static void renderer_settings_dialog_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
static void latex_render_callback(GtkToggleButton *radio, RendererSettingsDialog *dialog)
static void renderer_settings_dialog_class_init(RendererSettingsDialogClass *klass)
static void show_tex_options(RendererSettingsDialog *self)
void renderer_settings_dialog_set_database_unit_scale(RendererSettingsDialog *dialog, double unit_in_meters)
renderer_settings_dialog_set_database_unit_scale Set database scale
static void scale_value_changed(GtkRange *range, gpointer user_data)
G_END_DECLS void renderer_settings_dialog_set_settings(RendererSettingsDialog *dialog, struct render_settings *settings)
Apply settings to dialog.
static gboolean shape_drawer_drawing_callback(GtkWidget *widget, cairo_t *cr, gpointer data)
static void renderer_settings_dialog_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
static void renderer_settings_dialog_init(RendererSettingsDialog *self)
#define RENDERER_TYPE_SETTINGS_DIALOG
void renderer_settings_dialog_set_cell_width(RendererSettingsDialog *dialog, unsigned int width)
renderer_settings_dialog_set_cell_width Set width for rendered cell
RendererSettingsDialog * renderer_settings_dialog_new(GtkWindow *parent)
Create a new RedererSettingsDialog GObject.
@ PROP_COUNT
@ PROP_CELL_NAME
@ RENDERER_CAIROGRAPHICS_PDF
@ RENDERER_CAIROGRAPHICS_SVG
@ RENDERER_LATEX_TIKZ
GtkDrawingArea * shape_drawing
This struct holds the renderer configuration.
double scale
Scale image down by this factor.
enum output_renderer renderer