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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 /*------------------------------------------------------------------*/
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
33 /*------------------------------------------------------------------
34 * Includes required to run graphical widgets.
35 *------------------------------------------------------------------*/
40 #include <gdk/gdkkeysyms.h>
43 #include <glib-object.h>
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
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.
74 gchar
*folder
[]= {"Components",
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");
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 */
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 */
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 */
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 */
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
]),
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
166 x_gtksheet_add_row_labels(GtkSheet
*sheet
, int count
, STRING_LIST
*list_head
)
168 STRING_LIST
*string_list_item
;
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');
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
)
192 gtk_sheet_row_button_add_label(sheet
, j
, text
);
193 gtk_sheet_row_button_justify(sheet
, j
, GTK_JUSTIFY_LEFT
);
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
209 * \param list_head pointer to top of STRING_LIST
212 x_gtksheet_add_col_labels(GtkSheet
*sheet
, int count
, STRING_LIST
*list_head
)
214 STRING_LIST
*string_list_item
;
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 . . . */
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
242 * \param show_name_value
245 x_gtksheet_add_cell_item(GtkSheet
*sheet
,gint i
, gint j
,
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
);
257 switch(show_name_value
) {
259 case(SHOW_NAME_VALUE
):
260 x_gtksheet_set_cell_text_color(sheet
, i
, j
, BLUE
);
264 x_gtksheet_set_cell_text_color(sheet
, i
, j
, RED
);
268 x_gtksheet_set_cell_text_color(sheet
, i
, j
, BLACK
);
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
;
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
;
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
,
325 GtkSheetRange
*range
;
329 /* First get the system color map and allocate the color */
330 cmap
= gdk_colormap_get_system ();
331 color
= g_malloc(sizeof(GdkColor
));
342 color
->blue
= 0xffff;
353 color
->green
= 0x9999;
354 color
->blue
= 0x9999;
358 if (!gdk_colormap_alloc_color (cmap
, color
, FALSE
, FALSE
)) {
359 g_error ("couldn't allocate color");
364 /* XXXXX Attempt to set cell color */
365 range
= g_malloc(sizeof(GtkSheetRange
));
372 gtk_sheet_range_set_foreground(sheet
, range
, color
);
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.
387 show_entry(GtkWidget
*widget
, gpointer data
)
391 GtkWidget
*sheet_entry
= NULL
;
394 if(!GTK_WIDGET_HAS_FOCUS(widget
)) {
398 cur_page
= gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
));
400 sheet
= GTK_SHEET(sheets
[cur_page
]);
402 sheet_entry
= gtk_sheet_get_entry( GTK_SHEET(sheet
) );
405 /* Here's another place where we mix entry and sheet_entry */
407 text
= (gchar
*) gtk_entry_get_text (GTK_ENTRY(sheet_entry
));
409 gtk_entry_set_text(GTK_ENTRY(entry
), text
);
412 gtk_entry_set_text(GTK_ENTRY(entry
), (const gchar
*) "");
413 /* gtk_entry_set_text(GTK_ENTRY(entry), NULL); */