gsch2pcb: Make --m4-file and -m4-pcbdir arguments work again.
[geda-gaf/peter-b.git] / gattrib / src / x_gtksheet.c
blobf49991f4400487d1c4ddf262ced5d943e6b6846b
1 /* gEDA - GPL Electronic Design Automation
2 * gattrib -- gEDA component and net attribute manipulation using spreadsheet.
3 * Copyright (C) 2003-2010 Stuart D. Brorson.
5 * This program 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 2 of the License, or
8 * (at your option) any later version.
10 * This program 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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 /*------------------------------------------------------------------*/
21 /*! \file
22 * \brief Functions to interface to the spreadsheet widget.
24 * This file holds functions used to handle the spreadsheet widget.
25 * Much of this was hacked from testgtksheet.c starting in Jan 2004
26 * by SDB.
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
33 /*------------------------------------------------------------------
34 * Includes required to run graphical widgets.
35 *------------------------------------------------------------------*/
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <gtk/gtk.h>
39 #include <gdk/gdk.h>
40 #include <gdk/gdkkeysyms.h>
42 #include <glib.h>
43 #include <glib-object.h>
45 #ifdef HAVE_STRING_H
46 #include <string.h>
47 #endif
50 /*------------------------------------------------------------------
51 * Gattrib specific includes
52 *------------------------------------------------------------------*/
53 #include <libgeda/libgeda.h> /* geda library fcns */
54 #include "../include/struct.h" /* typdef and struct declarations */
55 #include "../include/prototype.h" /* function prototypes */
56 #include "../include/globals.h"
59 #ifdef HAVE_LIBDMALLOC
60 #include <dmalloc.h>
61 #endif
63 static void show_entry(GtkWidget *widget, gpointer data);
65 /*! \brief Create the GtkSheet
67 * Creates and initializes the GtkSheet widget, which is the
68 * spreadsheet widget used for displaying the data.
70 void
71 x_gtksheet_init()
73 gint i;
74 gchar *folder[]= {"Components",
75 "Nets",
76 "Pins"};
79 /* --- Create three new sheets. were malloc'ed in x_window_init --- */
81 /* ----- Components ----- */
82 if ((sheet_head->comp_count > 0) && (sheet_head->comp_attrib_count >0)) {
83 sheets[0] = (GtkSheet *) gtk_sheet_new((guint) sheet_head->comp_count, (guint) sheet_head->comp_attrib_count, "Components");
84 } else {
85 x_dialog_fatal_error("No components found in design. Please check your schematic and try again!\n", 1);
89 #ifdef UNIMPLEMENTED_FEATURES
90 /* ----- Nets ----- */
91 if ((sheet_head->net_count > 0) && (sheet_head->net_attrib_count >0)) {
92 sheets[1] = (GtkSheet *) gtk_sheet_new(sheet_head->net_count, sheet_head->net_attrib_count, "Nets");
93 gtk_sheet_set_locked(GTK_SHEET(sheets[1]), TRUE); /* disallow editing of attribs for now */
94 } else {
95 sheets[1] = (GtkSheet *) gtk_sheet_new(1, 1, "Nets");
96 gtk_sheet_row_button_add_label(sheets[1], 0, "TBD");
97 gtk_sheet_row_button_justify(sheets[1], 0, GTK_JUSTIFY_LEFT);
98 gtk_sheet_column_button_add_label(sheets[1], 0, "TBD");
99 gtk_sheet_column_button_justify(sheets[1], 0, GTK_JUSTIFY_LEFT);
100 gtk_sheet_set_locked(GTK_SHEET(sheets[1]), TRUE); /* disallow editing of attribs for now */
102 #endif
105 #ifdef UNIMPLEMENTED_FEATURES
106 /* ----- Pins ----- */
107 if ((sheet_head->pin_count > 0) && (sheet_head->pin_attrib_count >0)) {
108 sheets[2] = (GtkSheet *) gtk_sheet_new(sheet_head->pin_count, sheet_head->pin_attrib_count, "Pins");
109 gtk_sheet_set_locked(GTK_SHEET(sheets[2]), TRUE); /* disallow editing of attribs for now */
110 } else {
111 sheets[2] = (GtkSheet *) gtk_sheet_new(1, 1, "Pins");
112 gtk_sheet_set_locked(GTK_SHEET(sheets[2]), TRUE); /* disallow editing of attribs for now */
114 #endif
118 /* --- Finally stick labels on the notebooks holding the two sheets. --- */
119 for(i=0; i<NUM_SHEETS; i++){
120 if (sheets[i] != NULL) { /* is this check needed?
121 * Yes, it prevents us from segfaulting on empty nets sheet. */
124 scrolled_windows=(GtkWidget **)realloc(scrolled_windows, (i+1)*sizeof(GtkWidget *));
125 scrolled_windows[i]=gtk_scrolled_window_new(NULL, NULL);
127 gtk_container_add( GTK_CONTAINER(scrolled_windows[i]), GTK_WIDGET(sheets[i]) );
129 /* First remove old notebook page. I should probably do some checking here. */
130 if (notebook != NULL)
131 gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), i);
134 /* Then add new, updated notebook page */
135 label= gtk_label_new(folder[i]);
137 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), GTK_WIDGET(scrolled_windows[i]),
138 GTK_WIDGET(label) );
140 gtk_widget_show( GTK_WIDGET(sheets[i]) );
141 gtk_widget_show( GTK_WIDGET(scrolled_windows[i]) );
142 gtk_widget_show( GTK_WIDGET(notebook) ); /* show updated notebook */
145 /* "changed" signal raised when user changes anything in entry cell */
146 /* Note that the entry cell is the text entry field at the top of the
147 * sheet's working area (like in MS E*cel). I have removed this from
148 * gattrib, but leave the code in just in case I want to put it back. */
149 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(GTK_SHEET(sheets[i]))),
150 "changed", (GtkSignalFunc) show_entry, NULL);
157 /*------------------------------------------------------------------*/
158 /*! \brief Add row labels to GtkSheet
160 * Add row labels to GtkSheet
161 * \param sheet Pointer to the GtkSheet object
162 * \param count Number of row labels to add
163 * \param list_head Top of the string list
165 void
166 x_gtksheet_add_row_labels(GtkSheet *sheet, int count, STRING_LIST *list_head)
168 STRING_LIST *string_list_item;
169 gchar *text;
170 int j;
171 int width = 0;
172 int new_width = 0;
173 int char_width;
175 /* Leave if no items to add are available */
176 if ((count == 0) || (list_head == NULL)) return;
178 /* Get character width based upon "X", which is a large char.
179 * font_combo is a global. Where is it set? */
180 if ( GTK_WIDGET(sheet)->style->private_font )
181 char_width = gdk_char_width (GTK_WIDGET(sheet)->style->private_font, (gchar)'X');
182 else
183 char_width = 12;
185 string_list_item = list_head;
186 for (j = 0; j < count; j++) {
187 text = (gchar *) g_strdup(string_list_item->data);
188 new_width = char_width * strlen(text);
189 if (new_width > width)
190 width = new_width;
192 gtk_sheet_row_button_add_label(sheet, j, text);
193 gtk_sheet_row_button_justify(sheet, j, GTK_JUSTIFY_LEFT);
194 g_free(text);
195 string_list_item = string_list_item->next;
199 gtk_sheet_set_row_titles_width(sheet, width+8);
203 /*------------------------------------------------------------------*/
204 /*! \brief Add column labels to GtkSheet
206 * Add column labels to GtkSheet.
207 * \param sheet GtkSheet to add columns to
208 * \param count
209 * \param list_head pointer to top of STRING_LIST
211 void
212 x_gtksheet_add_col_labels(GtkSheet *sheet, int count, STRING_LIST *list_head)
214 STRING_LIST *string_list_item;
215 gchar *text;
216 int j;
218 /* Leave if no items to add are available */
219 if ((count == 0) || (list_head == NULL)) return;
221 string_list_item = list_head;
222 for (j = 0; j < count; j++) {
223 text = (gchar *) g_strdup(string_list_item->data);
224 gtk_sheet_column_button_add_label(sheet, j, text);
225 gtk_sheet_column_button_justify(sheet, j, GTK_JUSTIFY_LEFT);
226 /* need to resize the column width here . . . */
227 g_free(text);
228 string_list_item = string_list_item->next;
233 /*------------------------------------------------------------------*/
234 /*! \brief Add a cell item to the GtkSheet
236 * Add a cell item to the GtkSheet
237 * \param sheet GtkSheet to add the cell item to
238 * \param i
239 * \param j
240 * \param text
241 * \param visibility
242 * \param show_name_value
244 void
245 x_gtksheet_add_cell_item(GtkSheet *sheet,gint i, gint j,
246 gchar *text,
247 gint visibility,
248 gint show_name_value)
251 /* Should I do some sanity checking here? */
253 gtk_sheet_set_cell(sheet, i, j, GTK_JUSTIFY_LEFT, text);
254 if (visibility == INVISIBLE) {
255 x_gtksheet_set_cell_text_color(sheet, i, j, GREY);
256 } else {
257 switch(show_name_value) {
259 case(SHOW_NAME_VALUE):
260 x_gtksheet_set_cell_text_color(sheet, i, j, BLUE);
261 break;
263 case(SHOW_NAME):
264 x_gtksheet_set_cell_text_color(sheet, i, j, RED);
265 break;
267 case(SHOW_VALUE):
268 x_gtksheet_set_cell_text_color(sheet, i, j, BLACK);
269 break;
271 } /* if (visibility == INVISIBLE) */
275 /* Need to find a way to ensure that the text in a cell is clipped.
276 * Otherwise, long attribs overwrite adjacent cells. */
280 /*! \brief Get the first column selected in the GtkSheet
282 * Get the first column selected in the GtkSheet
283 * Returns the index of the first column selected, or -1 if
284 * no column is selected.
285 * \param sheet GtkSheet to query
286 * \returns index of the first column selected, or -1 if
287 * no column is selected.
289 int x_gtksheet_get_min_col(GtkSheet *sheet) {
290 if (sheet->state == GTK_SHEET_COLUMN_SELECTED) {
291 return sheet->range.col0;
292 } else {
293 return -1;
298 /*! \brief Get the last column selected in the GtkSheet
300 * Get the last column selected in the GtkSheet
301 * \param GtkSheet to query
302 * \returns the index of the last column selected, or -1 if
303 * no column is selected.
305 int x_gtksheet_get_max_col(GtkSheet *sheet) {
306 if (sheet->state == GTK_SHEET_COLUMN_SELECTED) {
307 return sheet->range.coli;
308 } else {
309 return -1;
314 /*! \brief Set the text color of a cell
316 * Sets the color of a cell identified by row, col.
317 * \param sheet GtkSheet to operate on
318 * \param row Row of cell to set
319 * \param col Column of cell to set
320 * \param color_name Color to set text to
322 void x_gtksheet_set_cell_text_color(GtkSheet *sheet, gint row, gint col,
323 gint color_name)
325 GtkSheetRange *range;
326 GdkColormap *cmap;
327 GdkColor *color;
329 /* First get the system color map and allocate the color */
330 cmap = gdk_colormap_get_system ();
331 color = g_malloc(sizeof(GdkColor));
332 switch(color_name) {
333 case RED:
334 color->red = 0xffff;
335 color->green = 0x0;
336 color->blue = 0x0;
337 break;
339 case BLUE:
340 color->red = 0x0;
341 color->green = 0x0;
342 color->blue = 0xffff;
343 break;
345 case BLACK:
346 color->red = 0x0;
347 color->green = 0x0;
348 color->blue = 0x0;
349 break;
351 case GREY:
352 color->red = 0x9999;
353 color->green = 0x9999;
354 color->blue = 0x9999;
355 break;
358 if (!gdk_colormap_alloc_color (cmap, color, FALSE, FALSE)) {
359 g_error ("couldn't allocate color");
360 return;
362 /* g_free(cmap); */
364 /* XXXXX Attempt to set cell color */
365 range = g_malloc(sizeof(GtkSheetRange));
366 range->row0 = row;
367 range->rowi = row;
368 range->col0 = col;
369 range->coli = col;
371 /* Now set color */
372 gtk_sheet_range_set_foreground(sheet, range, color);
373 g_free(color);
374 g_free(range);
378 /*! \brief Show text entry box
380 * Displays a text entry box at the top of the working area.
381 * It is removed since it is not needed now, but may come in
382 * handy later. Therefore I keep the code around.
383 * \param widget
384 * \param data
386 static void
387 show_entry(GtkWidget *widget, gpointer data)
389 gchar *text;
390 GtkSheet *sheet;
391 GtkWidget *sheet_entry = NULL;
392 gint cur_page;
394 if(!GTK_WIDGET_HAS_FOCUS(widget)) {
395 return;
398 cur_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
400 sheet = GTK_SHEET(sheets[cur_page]);
401 if (sheet != NULL) {
402 sheet_entry = gtk_sheet_get_entry( GTK_SHEET(sheet) );
405 /* Here's another place where we mix entry and sheet_entry */
406 if (entry != NULL) {
407 text = (gchar *) gtk_entry_get_text (GTK_ENTRY(sheet_entry));
408 if( text != NULL ) {
409 gtk_entry_set_text(GTK_ENTRY(entry), text);
411 else {
412 gtk_entry_set_text(GTK_ENTRY(entry), (const gchar *) "");
413 /* gtk_entry_set_text(GTK_ENTRY(entry), NULL); */