dialog-stf-fixed-page.c 14.9 KB
Newer Older
1
/*
Morten Welinder's avatar
Morten Welinder committed
2
 * dialog-stf-fixed-page.c : Controls the widgets on the fixed page of the dialog (fixed-width page that is)
3
 *
4 5
 * Copyright 2001 Almer S. Tigelaar <almer@gnome.org>
 * Copyright 2003 Morten Welinder <terra@gnome.org>
6
 *
jpekka's avatar
jpekka committed
7 8 9 10 11 12 13 14 15 16 17 18 19
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 21
 */

22 23
#undef GTK_DISABLE_DEPRECATED
#warning "This file uses GTK_DISABLE_DEPRECATED"
24
#include <gnumeric-config.h>
Zbigniew Chyla's avatar
Zbigniew Chyla committed
25
#include <gnumeric-i18n.h>
26
#include <gnumeric.h>
27
#include "dialog-stf.h"
28
#include <gui-util.h>
29 30 31 32 33

/*************************************************************************************************
 * MISC UTILITY FUNCTIONS
 *************************************************************************************************/

34 35 36
/**
 * fixed_page_autodiscover:
 * @pagedata: a mother struct
37
 *
38 39 40 41
 * Use the STF's autodiscovery function and put the
 * result in the fixed_collist
 **/
static void
42
fixed_page_autodiscover (StfDialogData *pagedata)
43
{
44
	guint i = 1;
45
	char *tset[2];
46

47
	stf_parse_options_fixed_autodiscover (pagedata->parseoptions,
48
					      pagedata->cur, pagedata->cur_end);
49

50
	gtk_clist_clear (pagedata->fixed.fixed_collist);
51
	while (i < pagedata->parseoptions->splitpositions->len) {
52
		tset[0] = g_strdup_printf ("%d", i - 1);
53
		tset[1] = g_strdup_printf ("%d", g_array_index (pagedata->parseoptions->splitpositions,
54 55
								int,
								i));
56
		gtk_clist_append (pagedata->fixed.fixed_collist, tset);
57

58 59 60 61 62 63
		g_free (tset[0]);
		g_free (tset[1]);

		i++;
	}

64
	tset[0] = g_strdup_printf ("%d", i - 1);
65
	tset[1] = g_strdup_printf ("%d", -1);
66

67
	gtk_clist_append (pagedata->fixed.fixed_collist, tset);
68

69 70 71 72 73 74 75 76
	g_free (tset[0]);
	g_free (tset[1]);

	/*
	 * If there are no splitpositions than apparantly
	 * no columns where found
	 */

77
	if (pagedata->parseoptions->splitpositions->len < 1) {
78 79 80 81 82 83
		GtkWidget *dialog = gtk_message_dialog_new (NULL,
			GTK_DIALOG_DESTROY_WITH_PARENT,
			GTK_MESSAGE_INFO,
			GTK_BUTTONS_OK,
			_("Autodiscovery did not find any columns in the text. Try manually"));
		gnumeric_dialog_run (pagedata->wbcg, GTK_DIALOG (dialog));
84 85 86
	}
}

87
static void fixed_page_update_preview (StfDialogData *pagedata);
88

89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
static void
make_new_column (StfDialogData *pagedata, int col, int dx, GtkWidget *w)
{
	PangoLayout *layout;
	PangoFontDescription *font_desc;
	int charindex, width;
	GtkCellRenderer *cell =	stf_preview_get_cell_renderer (pagedata->fixed.renderdata, col);
	int i, colstart, colend;
	char *row[2];

	if (col == 0)
		colstart = 0;
	else {
		gtk_clist_get_text (pagedata->fixed.fixed_collist, col - 1, 1, row);
		colstart = atoi (row[0]);
	}
	gtk_clist_get_text (pagedata->fixed.fixed_collist, col, 1, row);
	colend = atoi (row[0]);

	g_object_get (G_OBJECT (cell), "font_desc", &font_desc, NULL);
	layout = gtk_widget_create_pango_layout (w, "x");
	pango_layout_set_font_description (layout, font_desc);
	pango_layout_get_pixel_size (layout, &width, NULL);
	if (width < 1) width = 1;
	charindex = colstart + (dx + width / 2) / width;
	g_object_unref (layout);
	pango_font_description_free (font_desc);

	if (charindex <= colstart || (colend != -1 && charindex >= colend))
		return;

	row[0] = g_strdup_printf ("%d", col + 1);
	row[1] = g_strdup_printf ("%d", charindex);
	gtk_clist_insert (pagedata->fixed.fixed_collist, col, row);
	g_free (row[0]);
	g_free (row[1]);

	/* Patch the following column numbers in the list.  */
	for (i = col; i < GTK_CLIST (pagedata->fixed.fixed_collist)->rows; i++) {
		char *text = g_strdup_printf ("%d", i);
		gtk_clist_set_text (pagedata->fixed.fixed_collist, i, 0, text);
		g_free (text);
	}

	fixed_page_update_preview (pagedata);
}


static gint
cb_treeview_event (GtkWidget *treeview,
		   GdkEvent *event,
		   StfDialogData *pagedata)
{
	if (event->type == GDK_BUTTON_PRESS) {
		GdkEventButton *bevent = (GdkEventButton *)event;

		if (bevent->button == 1) {
			/* Split column.  */
			int dx = (int)bevent->x;
			int col;

			/* Figure out what column we pressed in.  */
			for (col = 0; col < GTK_CLIST (pagedata->fixed.fixed_collist)->rows; col++) {
				GtkTreeViewColumn *column =
					stf_preview_get_column (pagedata->fixed.renderdata, col);
				GtkWidget *w = GTK_BIN (column->button)->child;
				if (dx < w->allocation.x + w->allocation.width) {
					dx -= w->allocation.x;
					break;
				}
			}

			make_new_column (pagedata, col, dx, treeview);
			return TRUE;
		}

	}
	return FALSE;
}


170 171 172 173 174 175 176 177
static gint
cb_col_event (GtkWidget *button,
	      GdkEvent  *event,
	      gpointer   _col)
{
	int col = GPOINTER_TO_INT (_col);

	if (event->type == GDK_BUTTON_PRESS) {
178
		StfDialogData *data = g_object_get_data (G_OBJECT (button), "fixed-data");
179 180 181 182
		GdkEventButton *bevent = (GdkEventButton *)event;

		if (bevent->button == 1) {
			/* Split column.  */
183
			int dx;
184 185

			dx = (int)bevent->x - (GTK_BIN (button)->child->allocation.x - button->allocation.x);
186
			make_new_column (data, col, dx, button);
187 188 189 190 191 192

			return TRUE;
		}

		if (bevent->button == 3) {
			/* Remove column.  */
193 194
			gtk_clist_select_row (data->fixed.fixed_collist, col, 0);
			gnumeric_clist_moveto (data->fixed.fixed_collist, col);
195

196
			gtk_signal_emit_by_name (GTK_OBJECT (data->fixed.fixed_remove),
197 198 199 200 201 202 203 204 205 206
						 "clicked",
						 data);
			return TRUE;
		}
	}
	    
	return FALSE;
}


207 208 209 210 211 212 213 214 215
/**
 * fixed_page_update_preview
 * @pagedata : mother struct
 *
 * Will simply update the preview
 *
 * returns : nothing
 **/
static void
216
fixed_page_update_preview (StfDialogData *pagedata)
217
{
218
	StfParseOptions_t *parseoptions = pagedata->parseoptions;
Morten Welinder's avatar
Morten Welinder committed
219
	RenderData_t *renderdata = pagedata->fixed.renderdata;
220 221 222
	int i;
	GPtrArray *lines;
	StfTrimType_t trim;
223 224

	stf_parse_options_fixed_splitpositions_clear (parseoptions);
225
	for (i = 0; i < GTK_CLIST (pagedata->fixed.fixed_collist)->rows; i++) {
226 227
		char *t[2];

228
		gtk_clist_get_text (pagedata->fixed.fixed_collist, i, 1, t);
229
		stf_parse_options_fixed_splitpositions_add (parseoptions, atoi (t[0]));
230 231
	}

232 233 234 235 236 237 238 239
	/* Don't trim on this page.  */
	trim = parseoptions->trim_spaces;	
	stf_parse_options_set_trim_spaces (parseoptions, TRIM_TYPE_NEVER);
	lines = stf_parse_general (parseoptions,
				   pagedata->cur, pagedata->cur_end);
	stf_parse_options_set_trim_spaces (parseoptions, trim);

	stf_preview_set_lines (renderdata, lines);
240

241 242 243 244 245
	for (i = 0; i < renderdata->colcount; i++) {
		GtkTreeViewColumn *column =
			stf_preview_get_column (renderdata, i);
		GtkCellRenderer *cell =
			stf_preview_get_cell_renderer (renderdata, i);
246

247 248 249 250 251 252 253 254 255 256
		g_object_set (G_OBJECT (cell),
			      "family", "monospace",
			      NULL);

		g_object_set_data (G_OBJECT (column->button), "fixed-data", pagedata);
		g_object_set (G_OBJECT (column), "clickable", TRUE, NULL);
		g_signal_connect (column->button, "event",
				  G_CALLBACK (cb_col_event),
				  GINT_TO_POINTER (i));
	}
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
}

/*************************************************************************************************
 * SIGNAL HANDLERS
 *************************************************************************************************/

/**
 * fixed_page_collist_select_row
 * @clist : the GtkClist that emitted the signal
 * @row : row the user clicked on
 * @column : column the user clicked on
 * @event : information on the buttons that were pressed
 * @data : mother struct
 *
 * This will update the widgets on the right side of the dialog to
 * reflect the new column selection
 *
 * returns : nothing
 **/
static void
277
fixed_page_collist_select_row (GtkCList *clist, int row,
Morten Welinder's avatar
Morten Welinder committed
278 279
			       G_GNUC_UNUSED int column,
			       G_GNUC_UNUSED GdkEventButton *event,
280
			       StfDialogData *data)
281 282 283
{
	char *t[2];

Morten Welinder's avatar
Morten Welinder committed
284
	data->fixed.index = row;
285

286
	gtk_clist_get_text (clist, row, 1, t);
287
	gtk_spin_button_set_value (data->fixed.fixed_colend, atoi (t[0]));
288

289
	gtk_widget_set_sensitive (GTK_WIDGET (data->fixed.fixed_colend), !(row == clist->rows - 1));
290 291 292 293 294 295 296 297
}

/**
 * fixed_page_colend_changed
 * @button : the gtkspinbutton that emitted the signal
 * @data : a mother struct
 *
 * if the user changes the end of the current column the preview will be redrawn
298
 * and the @data->fixed_data->fixed.fixed_collist will be updated
299 300 301 302
 *
 * returns : nothing
 **/
static void
303
fixed_page_colend_changed (GtkSpinButton *button, StfDialogData *data)
304 305 306
{
	char *text;

Morten Welinder's avatar
Morten Welinder committed
307
	if (data->fixed.index < 0 || (data->fixed.index == GTK_CLIST (data->fixed.fixed_collist)->rows - 1))
308
		return;
309

310
	text = gtk_editable_get_chars (GTK_EDITABLE (button), 0, -1);
Morten Welinder's avatar
Morten Welinder committed
311
	gtk_clist_set_text (data->fixed.fixed_collist, data->fixed.index, 1, text);
312 313 314 315 316 317 318 319 320 321
	g_free (text);

	fixed_page_update_preview (data);
}

/**
 * fixed_page_add_clicked
 * @button : the GtkButton that emitted the signal
 * @data : the mother struct
 *
322
 * This will add a new column to the @data->fixed_data->fixed.fixed_collist
323 324 325 326
 *
 * returns : nothing
 **/
static void
Morten Welinder's avatar
Morten Welinder committed
327
fixed_page_add_clicked (G_GNUC_UNUSED GtkButton *button,
328
			StfDialogData *data)
329 330
{
	char *tget[1], *tset[2];
331
	int colindex = GTK_CLIST (data->fixed.fixed_collist)->rows;
332 333

	if (colindex > 1) {
334
		gtk_clist_get_text (data->fixed.fixed_collist, colindex - 2, 1, tget);
335
		tget[0] = g_strdup_printf ("%d", atoi (tget[0]) + 1);
336
		gtk_clist_set_text (data->fixed.fixed_collist, colindex - 1, 1, tget[0]);
337
		g_free (tget[0]);
338
	} else {
339
		tget[0] = g_strdup ("1");
340
		gtk_clist_set_text (data->fixed.fixed_collist, colindex - 1, 1, tget[0]);
341 342
		g_free (tget[0]);
	}
343

344 345
	tset[0] = g_strdup_printf ("%d", colindex);
	tset[1] = g_strdup_printf ("%d", -1);
346
	gtk_clist_append (data->fixed.fixed_collist, tset);
347 348 349
	g_free (tset[0]);
	g_free (tset[1]);

350 351
	gtk_clist_select_row (data->fixed.fixed_collist, GTK_CLIST (data->fixed.fixed_collist)->rows - 2, 0);
	gnumeric_clist_moveto (data->fixed.fixed_collist, GTK_CLIST (data->fixed.fixed_collist)->rows - 2);
352

353 354 355 356 357 358 359 360
	fixed_page_update_preview (data);
}

/**
 * fixed_page_remove_clicked
 * @button : the GtkButton that emitted the signal
 * @data : the mother struct
 *
361
 * This will remove the selected item from the @data->fixed_data->fixed.fixed_collist
362 363 364 365
 *
 * returns : nothing
 **/
static void
Morten Welinder's avatar
Morten Welinder committed
366
fixed_page_remove_clicked (G_GNUC_UNUSED GtkButton *button,
367
			   StfDialogData *data)
368 369 370
{
	int i;

Morten Welinder's avatar
Morten Welinder committed
371 372
	if (data->fixed.index < 0 || (data->fixed.index == GTK_CLIST (data->fixed.fixed_collist)->rows - 1))
		data->fixed.index--;
373

Morten Welinder's avatar
Morten Welinder committed
374
	gtk_clist_remove (data->fixed.fixed_collist, data->fixed.index);
375

Morten Welinder's avatar
Morten Welinder committed
376
	for (i = data->fixed.index; i < GTK_CLIST (data->fixed.fixed_collist)->rows; i++) {
377 378
		char *text = g_strdup_printf ("%d", i);

379
		gtk_clist_set_text (data->fixed.fixed_collist, i, 0, text);
380 381
		g_free (text);
	}
382

Morten Welinder's avatar
Morten Welinder committed
383 384
	gtk_clist_select_row (data->fixed.fixed_collist, data->fixed.index, 0);
	gnumeric_clist_moveto (data->fixed.fixed_collist, data->fixed.index);
385 386 387 388

	fixed_page_update_preview (data);
}

389 390 391 392
/**
 * fixed_page_clear_clicked:
 * @button: GtkButton
 * @data: mother struct
393
 *
394 395 396
 * Will clear all entries in fixed_collist
 **/
static void
Morten Welinder's avatar
Morten Welinder committed
397
fixed_page_clear_clicked (G_GNUC_UNUSED GtkButton *button,
398
			  StfDialogData *data)
399 400
{
	char *tset[2];
401

402
	gtk_clist_clear (data->fixed.fixed_collist);
403 404 405

	tset[0] = g_strdup ("0");
	tset[1] = g_strdup ("-1");
406

407
	gtk_clist_append (data->fixed.fixed_collist, tset);
408

409 410
	g_free (tset[0]);
	g_free (tset[1]);
411

412 413 414 415 416 417 418
	fixed_page_update_preview (data);
}

/**
 * fixed_page_auto_clicked:
 * @button: GtkButton
 * @data: mother struct
419
 *
420 421 422 423
 * Will try to automatically recognize columns in the
 * text.
 **/
static void
Morten Welinder's avatar
Morten Welinder committed
424
fixed_page_auto_clicked (G_GNUC_UNUSED GtkButton *button,
425
			 StfDialogData *data)
426 427 428 429 430 431
{
	fixed_page_autodiscover (data);

	fixed_page_update_preview (data);
}

432
/**
433
 * stf_dialog_fixed_page_prepare
434 435 436 437 438 439
 * @data : mother struct
 *
 * Will prepare the fixed page
 *
 * returns : nothing
 **/
440 441
void
stf_dialog_fixed_page_prepare (StfDialogData *pagedata)
442 443
{
	GtkAdjustment *spinadjust;
444

445
	stf_parse_options_set_trim_spaces (pagedata->parseoptions, TRIM_TYPE_NEVER);
446

447
	spinadjust = gtk_spin_button_get_adjustment (pagedata->fixed.fixed_colend);
448
	spinadjust->lower = 1;
449
	spinadjust->upper = stf_parse_get_longest_row_width (pagedata->parseoptions,
450 451
							     pagedata->cur,
							     pagedata->cur_end);
452
	gtk_spin_button_set_adjustment (pagedata->fixed.fixed_colend, spinadjust);
453

454 455 456
	fixed_page_update_preview (pagedata);
}

457 458 459 460
/*************************************************************************************************
 * FIXED EXPORTED FUNCTIONS
 *************************************************************************************************/

461
/**
462
 * stf_dialog_fixed_page_cleanup
463 464 465 466 467 468 469
 * @pagedata : mother struct
 *
 * Will cleanup fixed page run-time data
 *
 * returns : nothing
 **/
void
470
stf_dialog_fixed_page_cleanup (StfDialogData *pagedata)
471
{
Morten Welinder's avatar
Morten Welinder committed
472
	stf_preview_free (pagedata->fixed.renderdata);
473 474 475
}

void
476
stf_dialog_fixed_page_init (GladeXML *gui, StfDialogData *pagedata)
477 478 479 480 481
{
	char *t[2];

	g_return_if_fail (gui != NULL);
	g_return_if_fail (pagedata != NULL);
482

483
        /* Create/get object and fill information struct */
484 485 486 487 488 489 490
	pagedata->fixed.fixed_collist = GTK_CLIST       (glade_xml_get_widget (gui, "fixed_collist"));
	pagedata->fixed.fixed_colend  = GTK_SPIN_BUTTON (glade_xml_get_widget (gui, "fixed_colend"));
	pagedata->fixed.fixed_add     = GTK_BUTTON      (glade_xml_get_widget (gui, "fixed_add"));
	pagedata->fixed.fixed_remove  = GTK_BUTTON      (glade_xml_get_widget (gui, "fixed_remove"));
	pagedata->fixed.fixed_clear   = GTK_BUTTON      (glade_xml_get_widget (gui, "fixed_clear"));
	pagedata->fixed.fixed_auto    = GTK_BUTTON      (glade_xml_get_widget (gui, "fixed_auto"));
	pagedata->fixed.fixed_data_container =          (glade_xml_get_widget (gui, "fixed_data_container"));
491 492

	/* Set properties */
Morten Welinder's avatar
Morten Welinder committed
493
	pagedata->fixed.renderdata    =
494 495
		stf_preview_new (pagedata->fixed.fixed_data_container,
				 NULL);
Morten Welinder's avatar
Morten Welinder committed
496
	pagedata->fixed.index         = -1;
497

498
	gtk_clist_column_titles_passive (pagedata->fixed.fixed_collist);
499

500 501
	t[0] = g_strdup ("0");
	t[1] = g_strdup ("-1");
502
	gtk_clist_append (pagedata->fixed.fixed_collist, t);
503 504
	g_free (t[0]);
	g_free (t[1]);
505

506
	/* Connect signals */
507
	g_signal_connect (G_OBJECT (pagedata->fixed.fixed_collist),
508 509
		"select_row",
		G_CALLBACK (fixed_page_collist_select_row), pagedata);
510
	g_signal_connect (G_OBJECT (pagedata->fixed.fixed_colend),
511 512
		"changed",
		G_CALLBACK (fixed_page_colend_changed), pagedata);
513
	g_signal_connect (G_OBJECT (pagedata->fixed.fixed_add),
514 515
		"clicked",
		G_CALLBACK (fixed_page_add_clicked), pagedata);
516
	g_signal_connect (G_OBJECT (pagedata->fixed.fixed_remove),
517 518
		"clicked",
		G_CALLBACK (fixed_page_remove_clicked), pagedata);
519
	g_signal_connect (G_OBJECT (pagedata->fixed.fixed_clear),
520 521
		"clicked",
		G_CALLBACK (fixed_page_clear_clicked), pagedata);
522
	g_signal_connect (G_OBJECT (pagedata->fixed.fixed_auto),
523 524
		"clicked",
		G_CALLBACK (fixed_page_auto_clicked), pagedata);
525 526 527
	g_signal_connect (G_OBJECT (pagedata->fixed.renderdata->tree_view),
		"event",
		 G_CALLBACK (cb_treeview_event), pagedata);
528
}