1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
5 * Copyright (C) 2002-2006 Jody Goldberg (jody@gnome.org)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) version 3.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
23 #include <gnumeric-config.h>
24 #include <glib/gi18n-lib.h>
28 #include "sheet-view.h"
30 #include "sheet-merge.h"
31 #include "sheet-filter.h"
32 #include "gnm-sheet-slicer.h"
33 #include "sheet-private.h"
34 #include "sheet-control.h"
35 #include "sheet-control-priv.h"
36 #include "workbook-view.h"
37 #include "workbook-control.h"
39 #include "selection.h"
40 #include "application.h"
42 #include "parse-util.h"
43 #include "expr-name.h"
44 #include "command-context.h"
45 #include "gnumeric-conf.h"
46 #include "sheet-style.h"
50 #include <gsf/gsf-impl-utils.h>
52 /*************************************************************************/
55 auto_expr_timer_clear (SheetView
*sv
)
57 if (sv
->auto_expr_timer
!= 0) {
58 g_source_remove (sv
->auto_expr_timer
);
59 sv
->auto_expr_timer
= 0;
64 cb_update_auto_expr (gpointer data
)
66 SheetView
*sv
= (SheetView
*) data
;
68 if (wb_view_cur_sheet_view (sv
->sv_wbv
) == sv
)
69 wb_view_auto_expr_recalc (sv
->sv_wbv
);
71 sv
->auto_expr_timer
= 0;
75 /*************************************************************************/
78 sv_sheet_name_changed (G_GNUC_UNUSED Sheet
*sheet
,
79 G_GNUC_UNUSED GParamSpec
*pspec
,
82 g_return_if_fail (GNM_IS_SV (sv
));
83 sv
->edit_pos_changed
.content
= TRUE
;
87 sv_sheet_visibility_changed (Sheet
*sheet
,
88 G_GNUC_UNUSED GParamSpec
*pspec
,
91 g_return_if_fail (GNM_IS_SV (sv
));
93 if (sheet_is_visible (sheet
) && !wb_view_cur_sheet (sv
->sv_wbv
))
94 wb_view_sheet_focus (sv
->sv_wbv
, sheet
);
98 sv_sheet_r1c1_changed (G_GNUC_UNUSED Sheet
*sheet
,
99 G_GNUC_UNUSED GParamSpec
*pspec
,
102 g_return_if_fail (GNM_IS_SV (sv
));
103 sv
->edit_pos_changed
.location
= TRUE
;
110 * Returns: (transfer none): the sheet.
113 sv_sheet (SheetView
const *sv
)
115 g_return_val_if_fail (GNM_IS_SV (sv
), NULL
);
123 * Returns: (transfer none): the workbook view.
126 sv_wbv (SheetView
const *sv
)
128 g_return_val_if_fail (GNM_IS_SV (sv
), NULL
);
133 sv_init_sc (SheetView
const *sv
, SheetControl
*sc
)
137 sc_scale_changed (sc
);
139 /* set_panes will change the initial so cache it */
140 initial
= sv
->initial_top_left
;
143 /* And this will restore it */
144 sc_set_top_left (sc
, initial
.col
, initial
.row
);
145 sc_scrollbar_config (sc
);
147 /* Set the visible bound, not the logical bound */
148 sc_cursor_bound (sc
, selection_first_range (sv
, NULL
, NULL
));
153 sv_attach_control (SheetView
*sv
, SheetControl
*sc
)
155 g_return_if_fail (GNM_IS_SV (sv
));
156 g_return_if_fail (GNM_IS_SC (sc
));
157 g_return_if_fail (sc
->view
== NULL
);
159 if (sv
->controls
== NULL
)
160 sv
->controls
= g_ptr_array_new ();
161 g_ptr_array_add (sv
->controls
, sc
);
167 sv_detach_control (SheetControl
*sc
)
169 g_return_if_fail (GNM_IS_SC (sc
));
170 g_return_if_fail (GNM_IS_SV (sc
->view
));
172 g_ptr_array_remove (sc
->view
->controls
, sc
);
173 if (sc
->view
->controls
->len
== 0) {
174 g_ptr_array_free (sc
->view
->controls
, TRUE
);
175 sc
->view
->controls
= NULL
;
181 sv_weakref_notify (SheetView
**ptr
, GObject
*sv
)
183 g_return_if_fail (ptr
!= NULL
);
184 g_return_if_fail (*ptr
== (SheetView
*)sv
); /* remember sv is dead */
189 sv_weak_ref (SheetView
*sv
, SheetView
**ptr
)
191 g_return_if_fail (ptr
!= NULL
);
195 g_object_weak_ref (G_OBJECT (sv
),
196 (GWeakNotify
) sv_weakref_notify
,
201 sv_weak_unref (SheetView
**ptr
)
203 g_return_if_fail (ptr
!= NULL
);
206 g_object_weak_unref (G_OBJECT (*ptr
),
207 (GWeakNotify
) sv_weakref_notify
,
213 static GObjectClass
*parent_class
;
216 sv_real_dispose (GObject
*object
)
218 SheetView
*sv
= GNM_SV (object
);
220 if (sv
->controls
!= NULL
) {
221 SHEET_VIEW_FOREACH_CONTROL (sv
, control
, {
222 sv_detach_control (control
);
223 g_object_unref (control
);
225 if (sv
->controls
!= NULL
)
226 g_warning ("Unexpected left-over controls");
230 Sheet
*sheet
= sv
->sheet
;
232 g_ptr_array_remove (sheet
->sheet_views
, sv
);
233 g_signal_handlers_disconnect_by_func (sheet
, sv_sheet_name_changed
, sv
);
234 g_signal_handlers_disconnect_by_func (sheet
, sv_sheet_visibility_changed
, sv
);
235 g_signal_handlers_disconnect_by_func (sheet
, sv_sheet_r1c1_changed
, sv
);
237 g_object_unref (sheet
);
241 sv_selection_free (sv
);
242 sv_selection_simplified_free (sv
);
243 auto_expr_timer_clear (sv
);
245 parent_class
->dispose (object
);
249 sheet_view_class_init (GObjectClass
*klass
)
251 SheetViewClass
*wbc_class
= GNM_SV_CLASS (klass
);
253 g_return_if_fail (wbc_class
!= NULL
);
255 parent_class
= g_type_class_peek_parent (klass
);
256 klass
->dispose
= sv_real_dispose
;
260 sheet_view_init (GObject
*object
)
262 SheetView
*sv
= GNM_SV (object
);
264 /* Init menu states */
265 sv
->enable_insert_rows
= TRUE
;
266 sv
->enable_insert_cols
= TRUE
;
267 sv
->enable_insert_cells
= TRUE
;
269 sv
->edit_pos_changed
.location
= TRUE
;
270 sv
->edit_pos_changed
.content
= TRUE
;
271 sv
->edit_pos_changed
.style
= TRUE
;
272 sv
->selection_content_changed
= TRUE
;
273 sv
->reposition_selection
= TRUE
;
274 sv
->auto_expr_timer
= 0;
276 sv
->frozen_top_left
.col
= sv
->frozen_top_left
.row
=
277 sv
->unfrozen_top_left
.col
= sv
->unfrozen_top_left
.row
= -1;
278 sv
->initial_top_left
.col
= sv
->initial_top_left
.row
= 0;
280 sv
->selections
= NULL
;
281 sv
->selection_mode
= GNM_SELECTION_MODE_ADD
;
282 sv
->selections_simplified
= NULL
;
283 sv_selection_add_pos (sv
, 0, 0, GNM_SELECTION_MODE_ADD
);
286 GSF_CLASS (SheetView
, sheet_view
,
287 sheet_view_class_init
, sheet_view_init
,
291 sheet_view_new (Sheet
*sheet
, WorkbookView
*wbv
)
295 g_return_val_if_fail (IS_SHEET (sheet
), NULL
);
297 sv
= g_object_new (GNM_SV_TYPE
, NULL
);
298 sv
->sheet
= g_object_ref (sheet
);
300 g_ptr_array_add (sheet
->sheet_views
, sv
);
303 g_signal_connect (G_OBJECT (sheet
),
305 G_CALLBACK (sv_sheet_name_changed
),
308 g_signal_connect (G_OBJECT (sheet
),
309 "notify::visibility",
310 G_CALLBACK (sv_sheet_visibility_changed
),
313 g_signal_connect (G_OBJECT (sheet
),
315 G_CALLBACK (sv_sheet_r1c1_changed
),
318 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
319 sv_init_sc (sv
, control
););
324 sv_dispose (SheetView
*sv
)
326 g_object_run_dispose (G_OBJECT (sv
));
330 sv_unant (SheetView
*sv
)
334 g_return_if_fail (GNM_IS_SV (sv
));
336 if (sv
->ants
== NULL
)
338 for (ptr
= sv
->ants
; ptr
!= NULL
; ptr
= ptr
->next
)
340 g_list_free (sv
->ants
);
343 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
344 sc_unant (control
););
350 * @ranges: (element-type GnmRange):
353 sv_ant (SheetView
*sv
, GList
*ranges
)
357 g_return_if_fail (GNM_IS_SV (sv
));
358 g_return_if_fail (ranges
!= NULL
);
360 if (sv
->ants
!= NULL
)
362 for (ptr
= ranges
; ptr
!= NULL
; ptr
= ptr
->next
)
363 sv
->ants
= g_list_prepend (sv
->ants
, gnm_range_dup (ptr
->data
));
364 sv
->ants
= g_list_reverse (sv
->ants
);
366 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
371 sv_make_cell_visible (SheetView
*sv
, int col
, int row
,
372 gboolean couple_panes
)
374 g_return_if_fail (GNM_IS_SV (sv
));
375 SHEET_VIEW_FOREACH_CONTROL(sv
, control
,
376 sc_make_cell_visible (control
, col
, row
, couple_panes
););
380 sv_redraw_range (SheetView
*sv
, GnmRange
const *r
)
382 g_return_if_fail (GNM_IS_SV (sv
));
384 SHEET_VIEW_FOREACH_CONTROL (sv
, sc
, sc_redraw_range (sc
, r
););
388 sv_redraw_headers (SheetView
const *sv
,
389 gboolean col
, gboolean row
,
390 GnmRange
const* r
/* optional == NULL */)
392 g_return_if_fail (GNM_IS_SV (sv
));
394 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
395 sc_redraw_headers (control
, col
, row
, r
););
399 sv_selection_copy (SheetView
*sv
, WorkbookControl
*wbc
)
403 g_return_val_if_fail (GNM_IS_SV (sv
), FALSE
);
404 if (!(sel
= selection_first_range (sv
, GO_CMD_CONTEXT (wbc
), _("Copy"))))
407 gnm_app_clipboard_cut_copy (wbc
, FALSE
, sv
, sel
, TRUE
);
413 sv_selection_cut (SheetView
*sv
, WorkbookControl
*wbc
)
417 /* 'cut' is a poor description of what we're
418 * doing here. 'move' would be a better
419 * approximation. The key portion of this process is that
420 * the range being moved has all
421 * - references to it adjusted to the new site.
422 * - relative references from it adjusted.
424 * NOTE : This command DOES NOT MOVE ANYTHING !
425 * We only store the src, paste does the move.
427 g_return_val_if_fail (GNM_IS_SV (sv
), FALSE
);
429 if (!(sel
= selection_first_range (sv
, GO_CMD_CONTEXT (wbc
), _("Cut"))))
432 if (sheet_range_splits_region (sv_sheet (sv
), sel
, NULL
, GO_CMD_CONTEXT (wbc
), _("Cut")))
435 gnm_app_clipboard_cut_copy (wbc
, TRUE
, sv
, sel
, TRUE
);
448 * @bound: An optionally NULL range that should contain all the supplied points
451 sv_cursor_set (SheetView
*sv
,
452 GnmCellPos
const *edit
,
453 int base_col
, int base_row
,
454 int move_col
, int move_row
,
455 GnmRange
const *bound
)
459 g_return_if_fail (GNM_IS_SV (sv
));
461 /* Change the edit position */
462 sv_set_edit_pos (sv
, edit
);
464 sv
->cursor
.base_corner
.col
= base_col
;
465 sv
->cursor
.base_corner
.row
= base_row
;
466 sv
->cursor
.move_corner
.col
= move_col
;
467 sv
->cursor
.move_corner
.row
= move_row
;
470 if (base_col
< move_col
) {
471 r
.start
.col
= base_col
;
472 r
.end
.col
= move_col
;
474 r
.end
.col
= base_col
;
475 r
.start
.col
= move_col
;
477 if (base_row
< move_row
) {
478 r
.start
.row
= base_row
;
479 r
.end
.row
= move_row
;
481 r
.end
.row
= base_row
;
482 r
.start
.row
= move_row
;
487 g_return_if_fail (range_is_sane (bound
));
489 SHEET_VIEW_FOREACH_CONTROL(sv
, control
,
490 sc_cursor_bound (control
, bound
););
494 sv_set_edit_pos (SheetView
*sv
, GnmCellPos
const *pos
)
497 GnmRange
const *merged
;
499 g_return_if_fail (GNM_IS_SV (sv
));
500 g_return_if_fail (pos
!= NULL
);
503 sv
->first_tab_col
= -1; /* invalidate */
505 if (old
.col
== pos
->col
&& old
.row
== pos
->row
)
508 g_return_if_fail (IS_SHEET (sv
->sheet
));
509 g_return_if_fail (pos
->col
>= 0);
510 g_return_if_fail (pos
->col
< gnm_sheet_get_max_cols (sv
->sheet
));
511 g_return_if_fail (pos
->row
>= 0);
512 g_return_if_fail (pos
->row
< gnm_sheet_get_max_rows (sv
->sheet
));
515 merged
= gnm_sheet_merge_is_corner (sv
->sheet
, &old
);
517 sv
->edit_pos_changed
.location
=
518 sv
->edit_pos_changed
.content
=
519 sv
->edit_pos_changed
.style
= TRUE
;
521 /* Redraw before change */
522 if (merged
== NULL
) {
523 GnmRange tmp
; tmp
.start
= tmp
.end
= old
;
524 sv_redraw_range (sv
, &tmp
);
526 sv_redraw_range (sv
, merged
);
528 sv
->edit_pos_real
= *pos
;
530 /* Redraw after change (handling merged cells) */
531 merged
= gnm_sheet_merge_contains_pos (sv
->sheet
, &sv
->edit_pos_real
);
532 if (merged
== NULL
) {
533 GnmRange tmp
; tmp
.start
= tmp
.end
= *pos
;
534 sv_redraw_range (sv
, &tmp
);
535 sv
->edit_pos
= sv
->edit_pos_real
;
537 sv_redraw_range (sv
, merged
);
538 sv
->edit_pos
= merged
->start
;
543 * sv_flag_status_update_pos:
547 * flag the view as requiring an update to the status display
548 * if the supplied cell location is the edit cursor, or part of the
551 * Will cause the format toolbar, the edit area, and the auto expressions to be
552 * updated if appropriate.
555 sv_flag_status_update_pos (SheetView
*sv
, GnmCellPos
const *pos
)
557 g_return_if_fail (GNM_IS_SV (sv
));
558 g_return_if_fail (pos
!= NULL
);
560 /* if a part of the selected region changed value update
561 * the auto expressions
563 if (sv_is_pos_selected (sv
, pos
->col
, pos
->row
))
564 sv
->selection_content_changed
= TRUE
;
566 /* If the edit cell changes value update the edit area
567 * and the format toolbar
569 if (pos
->col
== sv
->edit_pos
.col
&& pos
->row
== sv
->edit_pos
.row
)
570 sv
->edit_pos_changed
.content
=
571 sv
->edit_pos_changed
.style
= TRUE
;
575 * sv_flag_status_update_range:
577 * @range: If NULL then force an update.
579 * flag the sheet as requiring an update to the status display if the supplied
580 * cell location contains the edit cursor, or intersects of the selected region.
582 * Will cause the format toolbar, the edit area, and the auto expressions to be
583 * updated if appropriate.
586 sv_flag_status_update_range (SheetView
*sv
, GnmRange
const *range
)
588 g_return_if_fail (GNM_IS_SV (sv
));
590 /* Force an update */
592 sv
->selection_content_changed
= TRUE
;
593 sv
->edit_pos_changed
.location
=
594 sv
->edit_pos_changed
.content
=
595 sv
->edit_pos_changed
.style
= TRUE
;
599 /* if a part of the selected region changed value update
600 * the auto expressions
602 if (sv_is_range_selected (sv
, range
))
603 sv
->selection_content_changed
= TRUE
;
605 /* If the edit cell changes value update the edit area
606 * and the format toolbar
608 if (range_contains (range
, sv
->edit_pos
.col
, sv
->edit_pos
.row
))
609 sv
->edit_pos_changed
.content
= sv
->edit_pos_changed
.style
= TRUE
;
613 * sv_flag_style_update_range:
614 * @sv: The sheet being changed
615 * @range: the range that is changing.
617 * Flag style changes that will require updating the style indicators.
620 sv_flag_style_update_range (SheetView
*sv
, GnmRange
const *range
)
622 g_return_if_fail (GNM_IS_SV (sv
));
623 g_return_if_fail (range
!= NULL
);
624 if (range_contains (range
, sv
->edit_pos
.col
, sv
->edit_pos
.row
))
625 sv
->edit_pos_changed
.style
= TRUE
;
629 * sv_flag_selection_change:
632 * flag the sheet as requiring an update to the status display
634 * Will cause auto expressions to be updated
637 sv_flag_selection_change (SheetView
*sv
)
639 g_return_if_fail (GNM_IS_SV (sv
));
640 sv
->selection_content_changed
= TRUE
;
644 sheet_view_edit_pos_tool_tips (SheetView
*sv
)
646 GnmStyle
const *style
;
647 GnmInputMsg
*im
= NULL
;
649 style
= sheet_style_get (sv
->sheet
,
652 if (style
!= NULL
&& gnm_style_is_element_set (style
, MSTYLE_INPUT_MSG
))
653 im
= gnm_style_get_input_msg (style
);
655 /* We need to call these even with im == NULL to remove the old tooltip.*/
656 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
657 sc_show_im_tooltip (control
, im
, &sv
->edit_pos
););
661 sv_update (SheetView
*sv
)
663 g_return_if_fail (GNM_IS_SV (sv
));
665 if (sv
->edit_pos_changed
.content
) {
666 sv
->edit_pos_changed
.content
= FALSE
;
667 if (wb_view_cur_sheet_view (sv
->sv_wbv
) == sv
)
668 wb_view_edit_line_set (sv
->sv_wbv
, NULL
);
671 if (sv
->edit_pos_changed
.style
) {
672 sv
->edit_pos_changed
.style
= FALSE
;
673 if (wb_view_cur_sheet_view (sv
->sv_wbv
) == sv
)
674 wb_view_style_feedback (sv
->sv_wbv
);
677 if (sv
->edit_pos_changed
.location
) {
678 sv
->edit_pos_changed
.location
= FALSE
;
679 if (wb_view_cur_sheet_view (sv
->sv_wbv
) == sv
) {
680 wb_view_selection_desc (sv
->sv_wbv
, TRUE
, NULL
);
681 SHEET_VIEW_FOREACH_CONTROL
682 (sv
, sc
, wb_control_menu_state_update
684 MS_COMMENT_LINKS
| MS_PAGE_BREAKS
););
685 sheet_view_edit_pos_tool_tips (sv
);
689 if (sv
->selection_content_changed
) {
690 int const lag
= gnm_conf_get_core_gui_editing_recalclag ();
691 sv
->selection_content_changed
= FALSE
;
692 if (sv
->auto_expr_timer
== 0 || lag
< 0) {
693 auto_expr_timer_clear (sv
);
694 sv
->auto_expr_timer
= g_timeout_add_full (0, abs (lag
), /* seems ok */
695 cb_update_auto_expr
, (gpointer
) sv
, NULL
);
697 SHEET_VIEW_FOREACH_CONTROL (sv
, sc
,
698 wb_control_menu_state_update (sc_wbc (sc
), MS_ADD_VS_REMOVE_FILTER
|
699 MS_COMMENT_LINKS_RANGE
););
702 SHEET_VIEW_FOREACH_CONTROL (sv
, sc
,
703 wb_control_menu_state_update
704 (sc_wbc (sc
), MS_SELECT_OBJECT
););
709 * sv_editpos_in_filter:
712 * Returns: %NULL or GnmFilter that overlaps the sv::edit_pos
715 sv_editpos_in_filter (SheetView
const *sv
)
717 g_return_val_if_fail (GNM_IS_SV (sv
), NULL
);
718 return gnm_sheet_filter_at_pos (sv
->sheet
, &sv
->edit_pos
);
722 * sv_selection_intersects_filter_rows:
725 * Returns: %NULL or GnmFilter whose rows intersect the rows
726 * of the current selection.
729 sv_selection_intersects_filter_rows (SheetView
const *sv
)
732 g_return_val_if_fail (GNM_IS_SV (sv
), NULL
);
733 r
= selection_first_range (sv
, NULL
, NULL
);
735 return r
? gnm_sheet_filter_intersect_rows
736 (sv
->sheet
, r
->start
.row
, r
->end
.row
) : NULL
;
740 * sv_selection_extends_filter:
743 * Returns: %NULL or GnmFilter whose rows intersect the rows
744 * of the current selectiona range to which the filter can be
748 sv_selection_extends_filter (SheetView
const *sv
, GnmFilter
const *f
)
751 g_return_val_if_fail (GNM_IS_SV (sv
), NULL
);
752 r
= selection_first_range (sv
, NULL
, NULL
);
754 return gnm_sheet_filter_can_be_extended (sv
->sheet
, f
, r
);
761 * sv_editpos_in_slicer:
764 * Returns: (transfer none): %NULL or #GnmSheetSlicer that overlaps the
768 sv_editpos_in_slicer (SheetView
const *sv
)
770 g_return_val_if_fail (GNM_IS_SV (sv
), NULL
);
771 return gnm_sheet_slicers_at_pos (sv
->sheet
, &sv
->edit_pos
);
777 * @frozen_top_left: top left corner of the frozen region
778 * @unfrozen_top_left: top left corner of the unfrozen region
780 * By definition the unfrozen region must be below the frozen.
781 * If @frozen_top_left == @unfrozen_top_left or @frozen_top_left == NULL unfreeze
784 sv_freeze_panes (SheetView
*sv
,
785 GnmCellPos
const *frozen
,
786 GnmCellPos
const *unfrozen
)
788 g_return_if_fail (GNM_IS_SV (sv
));
790 if (gnm_debug_flag ("frozen-panes")) {
791 g_printerr ("Frozen: %-10s",
792 frozen
? cellpos_as_string (frozen
) : "-");
793 g_printerr ("Unfrozen: %s\n",
794 unfrozen
? cellpos_as_string (unfrozen
) : "-");
797 if (frozen
!= NULL
) {
798 g_return_if_fail (unfrozen
!= NULL
);
799 g_return_if_fail (unfrozen
->col
>= frozen
->col
);
800 g_return_if_fail (unfrozen
->row
>= frozen
->row
);
803 if (unfrozen
->col
!= gnm_sheet_get_last_col (sv
->sheet
) &&
804 unfrozen
->row
!= gnm_sheet_get_last_row (sv
->sheet
) &&
805 !gnm_cellpos_equal (frozen
, unfrozen
)) {
806 sv
->frozen_top_left
= *frozen
;
807 sv
->unfrozen_top_left
= *unfrozen
;
808 if (sv
->frozen_top_left
.col
== sv
->unfrozen_top_left
.col
)
809 sv
->frozen_top_left
.col
= sv
->unfrozen_top_left
.col
= 0;
810 if (sv
->frozen_top_left
.row
== sv
->unfrozen_top_left
.row
)
811 sv
->frozen_top_left
.row
= sv
->unfrozen_top_left
.row
= 0;
813 frozen
= unfrozen
= NULL
;
816 if (frozen
== NULL
) {
817 g_return_if_fail (unfrozen
== NULL
);
820 if (sv
->frozen_top_left
.col
< 0 &&
821 sv
->frozen_top_left
.row
< 0 &&
822 sv
->unfrozen_top_left
.col
< 0 &&
823 sv
->unfrozen_top_left
.row
< 0)
826 sv
->initial_top_left
= sv
->frozen_top_left
;
827 sv
->frozen_top_left
.col
= sv
->frozen_top_left
.row
=
828 sv
->unfrozen_top_left
.col
= sv
->unfrozen_top_left
.row
= -1;
831 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
832 sv_init_sc (sv
, control
););
834 WORKBOOK_VIEW_FOREACH_CONTROL(sv
->sv_wbv
, wbc
,
835 wb_control_menu_state_update (wbc
, MS_FREEZE_VS_THAW
););
839 * sv_panes_insdel_colrow:
846 * Adjust the positions of frozen panes as necessary to handle col/row
847 * insertions and deletions. note this assumes that the ins/del operations
848 * have already set the flags that will force a resize.
851 sv_panes_insdel_colrow (SheetView
*sv
, gboolean is_cols
,
852 gboolean is_insert
, int start
, int count
)
857 g_return_if_fail (GNM_IS_SV (sv
));
859 tl
= sv
->frozen_top_left
; /* _copy_ them */
860 br
= sv
->unfrozen_top_left
;
863 /* ignore if not frozen, or acting in unfrozen region */
864 if (br
.col
<= tl
.col
|| br
.col
<= start
)
870 if (br
.col
< tl
.col
|| br
.col
>= gnm_sheet_get_max_cols (sv
->sheet
))
874 tl
.col
-= MIN (count
, tl
.col
- start
);
876 if (br
.col
<= tl
.col
)
880 /* ignore if not frozen, or acting in unfrozen region */
881 if (br
.row
<= tl
.row
|| br
.row
<= start
)
887 if (br
.row
< tl
.row
|| br
.row
>= gnm_sheet_get_max_rows (sv
->sheet
))
891 tl
.row
-= MIN (count
, tl
.row
- start
);
893 if (br
.row
<= tl
.row
)
897 sv_freeze_panes (sv
, &tl
, &br
);
901 sv_is_frozen (SheetView
const *sv
)
903 g_return_val_if_fail (GNM_IS_SV (sv
), FALSE
);
905 /* be flexible, in the future we will support 2 way splits too */
906 return sv
->unfrozen_top_left
.col
>= 0 ||
907 sv
->unfrozen_top_left
.row
>= 0;
911 sv_set_initial_top_left:
912 * @sv: the sheet view.
916 * Sets the top left cell that a newly created sheet control should display.
917 * This corresponds to the top left cell visible in pane 0 (frozen or not).
918 * NOTE : the unfrozen_top_left != initial_top_left. Unfrozen is the first
919 * unfrozen cell, and corresponds to the _minimum_ cell in pane 0. However,
920 * the pane can scroll and may have something else currently visible as the top
924 sv_set_initial_top_left (SheetView
*sv
, int col
, int row
)
926 g_return_if_fail (GNM_IS_SV (sv
));
927 g_return_if_fail (0 <= col
&& col
< gnm_sheet_get_max_cols (sv
->sheet
));
928 g_return_if_fail (0 <= row
&& row
< gnm_sheet_get_max_rows (sv
->sheet
));
929 g_return_if_fail (!sv_is_frozen (sv
) ||
930 (sv
->unfrozen_top_left
.col
<= col
&&
931 sv
->unfrozen_top_left
.row
<= row
));
933 sv
->initial_top_left
.col
= col
;
934 sv
->initial_top_left
.row
= row
;