Commit 4f0abdd2 authored by Jody Goldberg's avatar Jody Goldberg Committed by Jody Goldberg
Browse files

- Col/Row hide undo - Keep selection extension cell visible - Improve

- Col/Row hide undo
- Keep selection extension cell visible
- Improve selection overlap range fragmentation, and debugging.

2000-01-20  Jody Goldberg <jgoldberg@home.com>

	* src/workbook-cmd-format.c (workbook_cmd_format_{col,row}_{hide,unhide}) :
	  Use the undo framework.

	* src/sheet.c (sheet_fill_selection_with) : Take a context.

	* src/gnumeric-sheet.c (gnumeric_sheet_key_mode_sheet) : Add
	  Alt-Pg{Up,Down}.  sheet_fill_selection_with now takes a context.

	* src/commands.c (cmd_hide_selection_rows_cols) : Implement undo for
	  row/col hiding.
	(cmd_hide_row_col_{undo,redo,destroy}) : Ditto.

	* src/item-grid.c (context_{col,row}_{hide,unhide}) : Use undo support.

	* src/selection.c (selection_get_ranges) : Improve heuristics.
	(sheet_selection_extend_{horizontal,vertical}) : Ensure that the cell
	  being moved stays visible.
parent 3660764b
2000-01-20 Jody Goldberg <jgoldberg@home.com>
* src/workbook-cmd-format.c (workbook_cmd_format_{col,row}_{hide,unhide}) :
Use the undo framework.
* src/sheet.c (sheet_fill_selection_with) : Take a context.
* src/gnumeric-sheet.c (gnumeric_sheet_key_mode_sheet) : Add
Alt-Pg{Up,Down}. sheet_fill_selection_with now takes a context.
* src/commands.c (cmd_hide_selection_rows_cols) : Implement undo for
row/col hiding.
(cmd_hide_row_col_{undo,redo,destroy}) : Ditto.
* src/item-grid.c (context_{col,row}_{hide,unhide}) : Use undo support.
* src/selection.c (selection_get_ranges) : Improve heuristics.
(sheet_selection_extend_{horizontal,vertical}) : Ensure that the cell
being moved stays visible.
2000-01-20 Jon K Hellan <hellan@acm.org>
* src/dialogs/dialog-autosave.c (dialog_autosave): Re-enable
......
......@@ -4,12 +4,11 @@ Miguel:
* Fix annoying flashing cursor bug.
Jody:
* Parse errors in formulas.
* Improve xml export of borders to include cleared borders.
* Improve inter{sheet,book} references.
* Clipboard fixes.
* Undo.
* Row/Col hiding.
* Keep cursor visible, Add Alt-Pg{Up,down}
* Clipboard, Selection, & border fixes.
Morten:
* Revamp the memory handling of the parser.
......
2000-01-20 Jody Goldberg <jgoldberg@home.com>
* src/workbook-cmd-format.c (workbook_cmd_format_{col,row}_{hide,unhide}) :
Use the undo framework.
* src/sheet.c (sheet_fill_selection_with) : Take a context.
* src/gnumeric-sheet.c (gnumeric_sheet_key_mode_sheet) : Add
Alt-Pg{Up,Down}. sheet_fill_selection_with now takes a context.
* src/commands.c (cmd_hide_selection_rows_cols) : Implement undo for
row/col hiding.
(cmd_hide_row_col_{undo,redo,destroy}) : Ditto.
* src/item-grid.c (context_{col,row}_{hide,unhide}) : Use undo support.
* src/selection.c (selection_get_ranges) : Improve heuristics.
(sheet_selection_extend_{horizontal,vertical}) : Ensure that the cell
being moved stays visible.
2000-01-20 Jon K Hellan <hellan@acm.org>
* src/dialogs/dialog-autosave.c (dialog_autosave): Re-enable
......
......@@ -66,6 +66,8 @@ GNUMERIC_BASE_SOURCES = \
collect.c \
color.c \
color.h \
colrow.c \
colrow.h \
commands.h \
commands.c \
command-context.h \
......
/*
* colrow.c: Utilities for Rows and Columns
*
* Author:
* Miguel de Icaza (miguel@gnu.org).
* Jody Goldberg (jgoldberg@home.org)
*
* (C) 1998, 1999, 2000 Miguel de Icaza, Jody Goldberg
*/
#include <config.h>
#include "colrow.h"
#include "selection.h"
struct row_col_visiblity
{
gboolean is_col, visible;
ColRowVisList elements;
};
struct pair_int
{
int index, count;
};
static void
cb_row_col_visibility (Sheet *sheet,
int start_col, int start_row,
int end_col, int end_row,
void *closure)
{
struct row_col_visiblity * const dat = closure;
gboolean const visible = dat->visible;
ColRowInfo * (*fetch) (Sheet *sheet, int pos);
int i, j, end;
if (dat->is_col) {
i = start_col;
end = end_col;
fetch = &sheet_col_fetch;
} else
{
i = start_row;
end = end_row;
fetch = &sheet_row_fetch;
}
/* Find the begining of a segment that will be toggled */
while (i <= end) {
ColRowInfo *cri = (*fetch) (sheet, i++);
if (visible != (cri->pixels >= 0)) {
struct pair_int *res = g_new(struct pair_int, 1);
/* Find the end */
for (j = i; j <= end ;) {
ColRowInfo * cri = (*fetch) (sheet, j++);
if (visible == (cri->pixels >= 0))
break;
}
res->index = i - 1;
res->count = j - i + 1;
#if 0
printf ("%d %d\n", res->index, res->count);
#endif
dat->elements = g_slist_prepend (dat->elements, res);
i = j;
}
}
}
/*
* col_row_get_visiblity_toggle :
* @sheet : The sheet whose selection we are interested in.
* @is_col: A flag indicating whether this it is a column or a row.
* @is_visible: Should we unhide or hide the cols/rows.
*
* Searches the selection list and generates a list of index,count
* pairs of row/col ranges that need to be hidden or unhiden.
*/
ColRowVisList
col_row_get_visiblity_toggle (Sheet *sheet, gboolean const is_col,
gboolean const visible)
{
struct row_col_visiblity closure;
closure.is_col = is_col;
closure.visible = visible;
closure.elements = NULL;
selection_apply (sheet, &cb_row_col_visibility, FALSE, &closure);
return closure.elements;
}
ColRowVisList
col_row_vis_list_destroy (ColRowVisList list)
{
while (list != NULL) {
g_free (list->data);
list = g_slist_remove (list, list->data);
}
return NULL;
}
/*
* col_row_set_visiblity :
*
* This is the high level command that is wrapped by undo and redo.
* It should not be called by other commands.
*/
void
col_row_set_visiblity (Sheet *sheet, gboolean const is_col,
gboolean const visible, ColRowVisList list)
{
/* Trivial optimization */
if (list == NULL)
return;
for (; list != NULL ; list = list->next) {
struct pair_int *info = list->data;
sheet_row_col_visible (sheet, is_col, visible,
info->index, info->count);
}
sheet_redraw_all (sheet);
sheet_redraw_cols (sheet);
sheet_redraw_rows (sheet);
}
#ifndef GNUMERIC_COLROW_H
#define GNUMERIC_COLROW_H
#include <glib.h>
#include "gnumeric.h"
typedef GSList *ColRowVisList;
ColRowVisList col_row_get_visiblity_toggle (Sheet *sheet, gboolean const is_col,
gboolean const visible);
ColRowVisList col_row_vis_list_destroy (ColRowVisList list);
void col_row_set_visiblity (Sheet *sheet, gboolean const is_col,
gboolean const visible,
ColRowVisList list);
#endif /* GNUMERIC_COLROW_H */
......@@ -17,6 +17,7 @@
#include "clipboard.h"
#include "selection.h"
#include "datetime.h"
#include "colrow.h"
/*
* NOTE : This is a work in progress
......@@ -57,6 +58,9 @@
*
* TODO : Reqs for selective undo
* TODO : Add Repeat last command
*
* Future thoughts
* - undoable preference setting ? XL does not have this. Do we want it ?
*/
/******************************************************************/
......@@ -1079,9 +1083,11 @@ cmd_set_date_time_redo (GnumericCommand *cmd, CommandContext *context)
v = value_new_int (datetime_timet_to_serial (time (NULL)));
/* FIXME : the '>' prefix is intended to give the translators
* a change to provide a locale specific date format.
* a chance to provide a locale specific date format.
* This is ugly because the format may not show up in the
* list of date formats, and will be marked custom
* list of date formats, and will be marked custom. In addition
* translators should be aware that the leading character of the
* result will be ignored.
*/
prefered_format = _(">mm/dd/yyyy");
} else {
......@@ -1346,18 +1352,95 @@ cmd_sort (CommandContext *context, Sheet *sheet,
me->parent.cmd_descriptor =
g_strdup_printf (_("Sorting %s"), range_name(me->range));
cmd_sort_redo (me, context);
cmd_sort_redo (GNUMERIC_COMMAND(me), context);
/* Register the command object */
return command_push_undo (sheet->workbook, obj, FALSE);
}
/******************************************************************/
/* TODO : Make a list of commands that should have undo support that dont
* even have stubs
#define CMD_HIDE_ROW_COL_TYPE (cmd_hide_row_col_get_type ())
#define CMD_HIDE_ROW_COL(o) (GTK_CHECK_CAST ((o), CMD_HIDE_ROW_COL_TYPE, CmdHideRowCol))
typedef struct
{
GnumericCommand parent;
Sheet *sheet;
gboolean is_cols;
gboolean visible;
ColRowVisList elements;
} CmdHideRowCol;
GNUMERIC_MAKE_COMMAND (CmdHideRowCol, cmd_hide_row_col);
static gboolean
cmd_hide_row_col_undo (GnumericCommand *cmd, CommandContext *context)
{
CmdHideRowCol *me = CMD_HIDE_ROW_COL(cmd);
g_return_val_if_fail (me != NULL, TRUE);
col_row_set_visiblity (me->sheet, me->is_cols,
!me->visible, me->elements);
return FALSE;
}
static gboolean
cmd_hide_row_col_redo (GnumericCommand *cmd, CommandContext *context)
{
CmdHideRowCol *me = CMD_HIDE_ROW_COL(cmd);
g_return_val_if_fail (me != NULL, TRUE);
col_row_set_visiblity (me->sheet, me->is_cols,
me->visible, me->elements);
return FALSE;
}
static void
cmd_hide_row_col_destroy (GtkObject *cmd)
{
CmdHideRowCol *me = CMD_HIDE_ROW_COL (cmd);
me->elements = col_row_vis_list_destroy (me->elements);
gnumeric_command_destroy (cmd);
}
gboolean
cmd_hide_selection_rows_cols (CommandContext *context, Sheet *sheet,
gboolean const is_cols, gboolean const visible)
{
GtkObject *obj;
CmdHideRowCol *me;
g_return_val_if_fail (sheet != NULL, TRUE);
obj = gtk_type_new (CMD_HIDE_ROW_COL_TYPE);
me = CMD_HIDE_ROW_COL (obj);
me->sheet = sheet;
me->is_cols = is_cols;
me->visible = visible;
me->elements = col_row_get_visiblity_toggle (sheet, is_cols, visible);
me->parent.cmd_descriptor = g_strdup (is_cols
? (visible ? _("Unhide columns") : _("Hide columns"))
: (visible ? _("Unhide rows") : _("Hide rows")));
cmd_hide_row_col_redo (GNUMERIC_COMMAND(me), context);
/* Register the command object */
return command_push_undo (sheet->workbook, obj, FALSE);
}
/******************************************************************/
/* TODO : Make a list of commands that should have undo support
* that do not even have stubs
*
* - Autofill
* - Array formula creation.
* - Row/Col hide/unhide
* - SheetObject creation & manipulation.
*/
......@@ -43,4 +43,7 @@ gboolean cmd_sort (CommandContext *context, Sheet *sheet,
gboolean cmd_clear_selection (CommandContext *context, Sheet *sheet, int const clear_flags);
gboolean cmd_hide_selection_rows_cols (CommandContext *context, Sheet *sheet,
gboolean const is_cols, gboolean const visible);
#endif /* GNUMERIC_COMMAND_CONTEXT_H */
......@@ -763,16 +763,20 @@ gnumeric_sheet_key_mode_sheet (GnumericSheet *gsheet, GdkEventKey *event)
case GDK_Page_Up:
if ((event->state & GDK_CONTROL_MASK) != 0)
gtk_notebook_prev_page (GTK_NOTEBOOK (wb->notebook));
else
else if ((event->state & GDK_MOD1_MASK) == 0)
(*movefn_vertical)(gsheet, -(gsheet->last_visible_row-gsheet->top_row), FALSE);
else
(*movefn_horizontal)(gsheet, -(gsheet->last_visible_col-gsheet->left_col), FALSE);
break;
case GDK_KP_Page_Down:
case GDK_Page_Down:
if ((event->state & GDK_CONTROL_MASK) != 0)
gtk_notebook_next_page (GTK_NOTEBOOK (wb->notebook));
else
else if ((event->state & GDK_MOD1_MASK) == 0)
(*movefn_vertical)(gsheet, gsheet->last_visible_row-gsheet->top_row, FALSE);
else
(*movefn_horizontal)(gsheet, gsheet->last_visible_col-gsheet->left_col, FALSE);
break;
case GDK_KP_Home:
......@@ -818,8 +822,8 @@ gnumeric_sheet_key_mode_sheet (GnumericSheet *gsheet, GdkEventKey *event)
*/
g_return_val_if_fail (cell != NULL, 1);
text = cell_get_text (cell);
sheet_fill_selection_with (sheet, text,
is_array);
sheet_fill_selection_with (workbook_command_context_gui (wb),
sheet, text, is_array);
g_free (text);
} else {
gtk_widget_grab_focus (gsheet->entry);
......
......@@ -763,16 +763,20 @@ gnumeric_sheet_key_mode_sheet (GnumericSheet *gsheet, GdkEventKey *event)
case GDK_Page_Up:
if ((event->state & GDK_CONTROL_MASK) != 0)
gtk_notebook_prev_page (GTK_NOTEBOOK (wb->notebook));
else
else if ((event->state & GDK_MOD1_MASK) == 0)
(*movefn_vertical)(gsheet, -(gsheet->last_visible_row-gsheet->top_row), FALSE);
else
(*movefn_horizontal)(gsheet, -(gsheet->last_visible_col-gsheet->left_col), FALSE);
break;
case GDK_KP_Page_Down:
case GDK_Page_Down:
if ((event->state & GDK_CONTROL_MASK) != 0)
gtk_notebook_next_page (GTK_NOTEBOOK (wb->notebook));
else
else if ((event->state & GDK_MOD1_MASK) == 0)
(*movefn_vertical)(gsheet, gsheet->last_visible_row-gsheet->top_row, FALSE);
else
(*movefn_horizontal)(gsheet, gsheet->last_visible_col-gsheet->left_col, FALSE);
break;
case GDK_KP_Home:
......@@ -818,8 +822,8 @@ gnumeric_sheet_key_mode_sheet (GnumericSheet *gsheet, GdkEventKey *event)
*/
g_return_val_if_fail (cell != NULL, 1);
text = cell_get_text (cell);
sheet_fill_selection_with (sheet, text,
is_array);
sheet_fill_selection_with (workbook_command_context_gui (wb),
sheet, text, is_array);
g_free (text);
} else {
gtk_widget_grab_focus (gsheet->entry);
......
......@@ -623,25 +623,29 @@ context_row_height (GtkWidget *widget, Sheet *sheet)
static void
context_col_hide (GtkWidget *widget, Sheet *sheet)
{
selection_row_col_visible (sheet, TRUE, FALSE);
cmd_hide_selection_rows_cols (workbook_command_context_gui (sheet->workbook),
sheet, TRUE, FALSE);
context_destroy_menu (widget);
}
static void
context_col_unhide (GtkWidget *widget, Sheet *sheet)
{
selection_row_col_visible (sheet, TRUE, TRUE);
cmd_hide_selection_rows_cols (workbook_command_context_gui (sheet->workbook),
sheet, TRUE, TRUE);
context_destroy_menu (widget);
}
static void
context_row_hide (GtkWidget *widget, Sheet *sheet)
{
selection_row_col_visible (sheet, FALSE, FALSE);
cmd_hide_selection_rows_cols (workbook_command_context_gui (sheet->workbook),
sheet, FALSE, FALSE);
context_destroy_menu (widget);
}
static void
context_row_unhide (GtkWidget *widget, Sheet *sheet)
{
selection_row_col_visible (sheet, FALSE, TRUE);
cmd_hide_selection_rows_cols (workbook_command_context_gui (sheet->workbook),
sheet, FALSE, TRUE);
context_destroy_menu (widget);
}
......
......@@ -306,6 +306,7 @@ sheet_selection_extend_horizontal (Sheet *sheet, int n, gboolean jump_to_boundar
{
SheetSelection *ss;
SheetSelection old_selection;
int row, col;
g_return_if_fail (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
......@@ -314,19 +315,19 @@ sheet_selection_extend_horizontal (Sheet *sheet, int n, gboolean jump_to_boundar
old_selection = *ss;
if (ss->base.col < ss->user.end.col)
ss->user.end.col =
col = ss->user.end.col =
sheet_find_boundary_horizontal (sheet,
ss->user.end.col, ss->user.end.row,
ss->user.end.col, row = ss->user.end.row,
n, jump_to_boundaries);
else if (ss->base.col > ss->user.start.col || n < 0)
ss->user.start.col =
col = ss->user.start.col =
sheet_find_boundary_horizontal (sheet,
ss->user.start.col, ss->user.start.row,
ss->user.start.col, row = ss->user.start.row,
n, jump_to_boundaries);
else
ss->user.end.col =
col = ss->user.end.col =
sheet_find_boundary_horizontal (sheet,
ss->user.end.col, ss->user.end.row,
ss->user.end.col, row = ss->user.end.row,
n, jump_to_boundaries);
if (ss->user.end.col < ss->user.start.col) {
......@@ -335,6 +336,7 @@ sheet_selection_extend_horizontal (Sheet *sheet, int n, gboolean jump_to_boundar
ss->user.end.col = tmp;
}
sheet_selection_change (sheet, &old_selection, ss);
sheet_make_cell_visible (sheet, col, row);
}
/*
......@@ -348,6 +350,7 @@ sheet_selection_extend_vertical (Sheet *sheet, int n, gboolean jump_to_boundarie
{
SheetSelection *ss;
SheetSelection old_selection;
int row, col;
g_return_if_fail (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
......@@ -356,19 +359,19 @@ sheet_selection_extend_vertical (Sheet *sheet, int n, gboolean jump_to_boundarie
old_selection = *ss;
if (ss->base.row < ss->user.end.row)
ss->user.end.row =
row = ss->user.end.row =
sheet_find_boundary_vertical (sheet,
ss->user.end.col, ss->user.end.row,
col = ss->user.end.col, ss->user.end.row,
n, jump_to_boundaries);
else if (ss->base.row > ss->user.start.row || n < 0)
ss->user.start.row =
row = ss->user.start.row =
sheet_find_boundary_vertical (sheet,
ss->user.start.col, ss->user.start.row,
col = ss->user.start.col, ss->user.start.row,
n, jump_to_boundaries);
else
ss->user.end.row =
row = ss->user.end.row =
sheet_find_boundary_vertical (sheet,
ss->user.end.col, ss->user.end.row,
col = ss->user.end.col, ss->user.end.row,
n, jump_to_boundaries);
if (ss->user.end.row < ss->user.start.row) {
......@@ -377,6 +380,7 @@ sheet_selection_extend_vertical (Sheet *sheet, int n, gboolean jump_to_boundarie
ss->user.end.row = tmp;
}
sheet_selection_change (sheet, &old_selection, ss);
sheet_make_cell_visible (sheet, col, row);
}
void
......@@ -807,10 +811,14 @@ selection_get_ranges (Sheet * sheet, gboolean const allow_intersection)
b->start.col, b->end.col);
#ifdef DEBUG_SELECTION
fprintf (stderr, "col = %d\na = %d -> %d\nb = %d -> %d\n",
col_intersect,
a->start.col, a->end.col,
b->start.col, b->end.col);
fprintf (stderr, "col = %d\na = %s", col_intersect, col_name(a->start.col));
if (a->start.col != a->end.col)
fprintf (stderr, " -> %s", col_name(a->end.col));
fprintf (stderr, "\nb = %s", col_name(b->start.col));
if (b->start.col != b->end.col)
fprintf (stderr, " -> %s\n", col_name(b->end.col));
else
fputc ('\n', stderr);
#endif
/* No intersection */
......@@ -823,10 +831,14 @@ selection_get_ranges (Sheet * sheet, gboolean const allow_intersection)
segments_intersect (a->start.row, a->end.row,
b->start.row, b->end.row);
#ifdef DEBUG_SELECTION
fprintf (stderr, "row = %d\na = %d -> %d\nb = %d -> %d\n",
row_intersect,
a->start.row, a->end.row,
b->start.row, b->end.row);
fprintf (stderr, "row = %d\na = %d", row_intersect, a->start.row +1);
if (a->start.row != a->end.row)
fprintf (stderr, " -> %d", a->end.row +1);
fprintf (stderr, "\nb = %d", b->start.row +1);
if (b->start.row != b->end.row)
fprintf (stderr, " -> %d\n", b->end.row +1);
else
fputc ('\n', stderr);
#endif
/* No intersection */
......@@ -841,9 +853,13 @@ selection_get_ranges (Sheet * sheet, gboolean const allow_intersection)
row_intersect = 4;
if (row_intersect == 4 || row_intersect == 2)
col_intersect = row_intersect;
else
col_intersect = 4;
} else if (row_intersect == 5) {
if (col_intersect == 4 || col_intersect == 2)
row_intersect = col_intersect;
else
row_intersect = 4;
}
/* Cross product of intersection cases */
......@@ -860,7 +876,7 @@ selection_get_ranges (Sheet * sheet, gboolean const allow_intersection)
case 3 : /* overlap top */
/* Shrink existing range */
b->end.row = a->start.row - 1;
b->start.row = a->end.row + 1;
break;
case 2 : /* b contains a */
......@@ -868,19 +884,20 @@ selection_get_ranges (Sheet * sheet, gboolean const allow_intersection)
/* Shrink existing range */
a->end.col = b->start.col - 1;
break;
} else if (a->start.col != b->start.col &&
b->start.col > 0) {
}
if (a->start.col != b->start.col) {
/* Split existing range */
tmp = range_copy (a);
tmp->end.col = b->start.col - 1;
clear = g_slist_prepend (clear,
tmp);
clear = g_slist_prepend (clear, tmp);
}
/* Fall through to do bottom segment */