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 #define GNM_SHEET_VIEW_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GNM_SHEET_VIEW_TYPE, SheetViewClass))
53 static GObjectClass
*parent_class
;
55 /*************************************************************************/
58 auto_expr_timer_clear (SheetView
*sv
)
60 if (sv
->auto_expr_timer
!= 0) {
61 g_source_remove (sv
->auto_expr_timer
);
62 sv
->auto_expr_timer
= 0;
67 cb_update_auto_expr (gpointer data
)
69 SheetView
*sv
= (SheetView
*) data
;
71 if (wb_view_cur_sheet_view (sv
->sv_wbv
) == sv
)
72 wb_view_auto_expr_recalc (sv
->sv_wbv
);
74 sv
->auto_expr_timer
= 0;
78 /*************************************************************************/
81 sv_sheet_name_changed (G_GNUC_UNUSED Sheet
*sheet
,
82 G_GNUC_UNUSED GParamSpec
*pspec
,
85 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
86 sv
->edit_pos_changed
.content
= TRUE
;
90 sv_sheet_visibility_changed (Sheet
*sheet
,
91 G_GNUC_UNUSED GParamSpec
*pspec
,
94 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
96 if (sheet_is_visible (sheet
) && !wb_view_cur_sheet (sv
->sv_wbv
))
97 wb_view_sheet_focus (sv
->sv_wbv
, sheet
);
101 sv_sheet_r1c1_changed (G_GNUC_UNUSED Sheet
*sheet
,
102 G_GNUC_UNUSED GParamSpec
*pspec
,
105 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
106 sv
->edit_pos_changed
.location
= TRUE
;
113 * Returns: (transfer none): the sheet.
116 sv_sheet (SheetView
const *sv
)
118 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), NULL
);
126 * Returns: (transfer none): the workbook view.
129 sv_wbv (SheetView
const *sv
)
131 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), NULL
);
136 sv_init_sc (SheetView
const *sv
, SheetControl
*sc
)
140 sc_scale_changed (sc
);
142 /* set_panes will change the initial so cache it */
143 initial
= sv
->initial_top_left
;
146 /* And this will restore it */
147 sc_set_top_left (sc
, initial
.col
, initial
.row
);
148 sc_scrollbar_config (sc
);
150 /* Set the visible bound, not the logical bound */
151 sc_cursor_bound (sc
, selection_first_range (sv
, NULL
, NULL
));
156 gnm_sheet_view_attach_control (SheetView
*sv
, SheetControl
*sc
)
158 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
159 g_return_if_fail (GNM_IS_SHEET_CONTROL (sc
));
160 g_return_if_fail (sc
->view
== NULL
);
162 g_ptr_array_add (sv
->controls
, sc
);
168 gnm_sheet_view_detach_control (SheetView
*sv
, SheetControl
*sc
)
170 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
171 g_return_if_fail (GNM_IS_SHEET_CONTROL (sc
));
172 g_return_if_fail (sv
== sc
->view
);
174 g_ptr_array_remove (sv
->controls
, sc
);
179 sv_weakref_notify (SheetView
**ptr
, GObject
*sv
)
181 g_return_if_fail (ptr
!= NULL
);
182 g_return_if_fail (*ptr
== (SheetView
*)sv
); /* remember sv is dead */
187 gnm_sheet_view_weak_ref (SheetView
*sv
, SheetView
**ptr
)
189 g_return_if_fail (ptr
!= NULL
);
193 g_object_weak_ref (G_OBJECT (sv
),
194 (GWeakNotify
) sv_weakref_notify
,
199 gnm_sheet_view_weak_unref (SheetView
**ptr
)
201 g_return_if_fail (ptr
!= NULL
);
204 g_object_weak_unref (G_OBJECT (*ptr
),
205 (GWeakNotify
) sv_weakref_notify
,
212 sv_finalize (GObject
*object
)
214 SheetView
*sv
= GNM_SHEET_VIEW (object
);
215 g_ptr_array_free (sv
->controls
, TRUE
);
216 parent_class
->finalize (object
);
220 sv_real_dispose (GObject
*object
)
222 SheetView
*sv
= GNM_SHEET_VIEW (object
);
224 while (sv
->controls
->len
> 0) {
225 SheetControl
*control
=
226 g_ptr_array_index (sv
->controls
,
227 sv
->controls
->len
- 10);
228 gnm_sheet_view_detach_control (sv
, control
);
229 g_object_unref (control
);
233 Sheet
*sheet
= sv
->sheet
;
235 g_ptr_array_remove (sheet
->sheet_views
, sv
);
236 g_signal_handlers_disconnect_by_func (sheet
, sv_sheet_name_changed
, sv
);
237 g_signal_handlers_disconnect_by_func (sheet
, sv_sheet_visibility_changed
, sv
);
238 g_signal_handlers_disconnect_by_func (sheet
, sv_sheet_r1c1_changed
, sv
);
240 g_object_unref (sheet
);
243 gnm_sheet_view_unant (sv
);
244 sv_selection_free (sv
);
245 sv_selection_simplified_free (sv
);
246 auto_expr_timer_clear (sv
);
248 parent_class
->dispose (object
);
252 gnm_sheet_view_class_init (GObjectClass
*klass
)
254 SheetViewClass
*wbc_class
= GNM_SHEET_VIEW_CLASS (klass
);
256 g_return_if_fail (wbc_class
!= NULL
);
258 parent_class
= g_type_class_peek_parent (klass
);
259 klass
->dispose
= sv_real_dispose
;
260 klass
->finalize
= sv_finalize
;
264 gnm_sheet_view_init (GObject
*object
)
266 SheetView
*sv
= GNM_SHEET_VIEW (object
);
268 sv
->controls
= g_ptr_array_new ();
270 /* Init menu states */
271 sv
->enable_insert_rows
= TRUE
;
272 sv
->enable_insert_cols
= TRUE
;
273 sv
->enable_insert_cells
= TRUE
;
275 sv
->edit_pos_changed
.location
= TRUE
;
276 sv
->edit_pos_changed
.content
= TRUE
;
277 sv
->edit_pos_changed
.style
= TRUE
;
278 sv
->selection_content_changed
= TRUE
;
279 sv
->reposition_selection
= TRUE
;
280 sv
->auto_expr_timer
= 0;
282 sv
->frozen_top_left
.col
= sv
->frozen_top_left
.row
=
283 sv
->unfrozen_top_left
.col
= sv
->unfrozen_top_left
.row
= -1;
284 sv
->initial_top_left
.col
= sv
->initial_top_left
.row
= 0;
286 sv
->selections
= NULL
;
287 sv
->selection_mode
= GNM_SELECTION_MODE_ADD
;
288 sv
->selections_simplified
= NULL
;
289 sv_selection_add_pos (sv
, 0, 0, GNM_SELECTION_MODE_ADD
);
292 GSF_CLASS (SheetView
, gnm_sheet_view
,
293 gnm_sheet_view_class_init
, gnm_sheet_view_init
,
297 gnm_sheet_view_new (Sheet
*sheet
, WorkbookView
*wbv
)
301 g_return_val_if_fail (IS_SHEET (sheet
), NULL
);
303 sv
= g_object_new (GNM_SHEET_VIEW_TYPE
, NULL
);
304 sv
->sheet
= g_object_ref (sheet
);
306 g_ptr_array_add (sheet
->sheet_views
, sv
);
309 g_signal_connect (G_OBJECT (sheet
),
311 G_CALLBACK (sv_sheet_name_changed
),
314 g_signal_connect (G_OBJECT (sheet
),
315 "notify::visibility",
316 G_CALLBACK (sv_sheet_visibility_changed
),
319 g_signal_connect (G_OBJECT (sheet
),
321 G_CALLBACK (sv_sheet_r1c1_changed
),
324 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
325 sv_init_sc (sv
, control
););
330 gnm_sheet_view_dispose (SheetView
*sv
)
332 g_object_run_dispose (G_OBJECT (sv
));
336 gnm_sheet_view_unant (SheetView
*sv
)
340 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
342 if (sv
->ants
== NULL
)
344 for (ptr
= sv
->ants
; ptr
!= NULL
; ptr
= ptr
->next
)
346 g_list_free (sv
->ants
);
349 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
350 sc_unant (control
););
354 * gnm_sheet_view_ant:
356 * @ranges: (element-type GnmRange) (transfer none): The ranges to ant.
359 gnm_sheet_view_ant (SheetView
*sv
, GList
*ranges
)
363 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
364 g_return_if_fail (ranges
!= NULL
);
366 if (sv
->ants
!= NULL
)
367 gnm_sheet_view_unant (sv
);
368 for (ptr
= ranges
; ptr
!= NULL
; ptr
= ptr
->next
)
369 sv
->ants
= g_list_prepend (sv
->ants
, gnm_range_dup (ptr
->data
));
370 sv
->ants
= g_list_reverse (sv
->ants
);
372 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
377 gnm_sheet_view_make_cell_visible (SheetView
*sv
, int col
, int row
,
378 gboolean couple_panes
)
380 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
381 SHEET_VIEW_FOREACH_CONTROL(sv
, control
,
382 sc_make_cell_visible (control
, col
, row
, couple_panes
););
386 gnm_sheet_view_redraw_range (SheetView
*sv
, GnmRange
const *r
)
388 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
390 SHEET_VIEW_FOREACH_CONTROL (sv
, sc
, sc_redraw_range (sc
, r
););
394 gnm_sheet_view_redraw_headers (SheetView
const *sv
,
395 gboolean col
, gboolean row
,
396 GnmRange
const* r
/* optional == NULL */)
398 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
400 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
401 sc_redraw_headers (control
, col
, row
, r
););
405 gnm_sheet_view_resize (SheetView
*sv
, gboolean force_scroll
)
407 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
409 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
410 sc_resize (control
, force_scroll
););
415 gnm_sheet_view_selection_copy (SheetView
*sv
, WorkbookControl
*wbc
)
419 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), FALSE
);
420 if (!(sel
= selection_first_range (sv
, GO_CMD_CONTEXT (wbc
), _("Copy"))))
423 gnm_app_clipboard_cut_copy (wbc
, FALSE
, sv
, sel
, TRUE
);
429 gnm_sheet_view_selection_cut (SheetView
*sv
, WorkbookControl
*wbc
)
433 /* 'cut' is a poor description of what we're
434 * doing here. 'move' would be a better
435 * approximation. The key portion of this process is that
436 * the range being moved has all
437 * - references to it adjusted to the new site.
438 * - relative references from it adjusted.
440 * NOTE : This command DOES NOT MOVE ANYTHING !
441 * We only store the src, paste does the move.
443 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), FALSE
);
445 if (!(sel
= selection_first_range (sv
, GO_CMD_CONTEXT (wbc
), _("Cut"))))
448 if (sheet_range_splits_region (sv_sheet (sv
), sel
, NULL
, GO_CMD_CONTEXT (wbc
), _("Cut")))
451 gnm_app_clipboard_cut_copy (wbc
, TRUE
, sv
, sel
, TRUE
);
457 * gnm_sheet_view_cursor_set:
464 * @bound: (nullable): A range that should contain all the supplied points
467 gnm_sheet_view_cursor_set (SheetView
*sv
,
468 GnmCellPos
const *edit
,
469 int base_col
, int base_row
,
470 int move_col
, int move_row
,
471 GnmRange
const *bound
)
475 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
477 /* Change the edit position */
478 gnm_sheet_view_set_edit_pos (sv
, edit
);
480 sv
->cursor
.base_corner
.col
= base_col
;
481 sv
->cursor
.base_corner
.row
= base_row
;
482 sv
->cursor
.move_corner
.col
= move_col
;
483 sv
->cursor
.move_corner
.row
= move_row
;
486 if (base_col
< move_col
) {
487 r
.start
.col
= base_col
;
488 r
.end
.col
= move_col
;
490 r
.end
.col
= base_col
;
491 r
.start
.col
= move_col
;
493 if (base_row
< move_row
) {
494 r
.start
.row
= base_row
;
495 r
.end
.row
= move_row
;
497 r
.end
.row
= base_row
;
498 r
.start
.row
= move_row
;
503 g_return_if_fail (range_is_sane (bound
));
505 SHEET_VIEW_FOREACH_CONTROL(sv
, control
,
506 sc_cursor_bound (control
, bound
););
510 gnm_sheet_view_set_edit_pos (SheetView
*sv
, GnmCellPos
const *pos
)
513 GnmRange
const *merged
;
515 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
516 g_return_if_fail (pos
!= NULL
);
519 sv
->first_tab_col
= -1; /* invalidate */
521 if (old
.col
== pos
->col
&& old
.row
== pos
->row
)
524 g_return_if_fail (IS_SHEET (sv
->sheet
));
525 g_return_if_fail (pos
->col
>= 0);
526 g_return_if_fail (pos
->col
< gnm_sheet_get_max_cols (sv
->sheet
));
527 g_return_if_fail (pos
->row
>= 0);
528 g_return_if_fail (pos
->row
< gnm_sheet_get_max_rows (sv
->sheet
));
531 merged
= gnm_sheet_merge_is_corner (sv
->sheet
, &old
);
533 sv
->edit_pos_changed
.location
=
534 sv
->edit_pos_changed
.content
=
535 sv
->edit_pos_changed
.style
= TRUE
;
537 /* Redraw before change */
538 if (merged
== NULL
) {
539 GnmRange tmp
; tmp
.start
= tmp
.end
= old
;
540 gnm_sheet_view_redraw_range (sv
, &tmp
);
542 gnm_sheet_view_redraw_range (sv
, merged
);
544 sv
->edit_pos_real
= *pos
;
546 /* Redraw after change (handling merged cells) */
547 merged
= gnm_sheet_merge_contains_pos (sv
->sheet
, &sv
->edit_pos_real
);
548 if (merged
== NULL
) {
549 GnmRange tmp
; tmp
.start
= tmp
.end
= *pos
;
550 gnm_sheet_view_redraw_range (sv
, &tmp
);
551 sv
->edit_pos
= sv
->edit_pos_real
;
553 gnm_sheet_view_redraw_range (sv
, merged
);
554 sv
->edit_pos
= merged
->start
;
559 * gnm_sheet_view_flag_status_update_pos:
563 * flag the view as requiring an update to the status display
564 * if the supplied cell location is the edit cursor, or part of the
567 * Will cause the format toolbar, the edit area, and the auto expressions to be
568 * updated if appropriate.
571 gnm_sheet_view_flag_status_update_pos (SheetView
*sv
, GnmCellPos
const *pos
)
573 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
574 g_return_if_fail (pos
!= NULL
);
576 /* if a part of the selected region changed value update
577 * the auto expressions
579 if (sv_is_pos_selected (sv
, pos
->col
, pos
->row
))
580 sv
->selection_content_changed
= TRUE
;
582 /* If the edit cell changes value update the edit area
583 * and the format toolbar
585 if (pos
->col
== sv
->edit_pos
.col
&& pos
->row
== sv
->edit_pos
.row
)
586 sv
->edit_pos_changed
.content
=
587 sv
->edit_pos_changed
.style
= TRUE
;
591 * gnm_sheet_view_flag_status_update_range:
593 * @range: (nullable): If %NULL then force an update.
595 * flag the sheet as requiring an update to the status display if the supplied
596 * cell location contains the edit cursor, or intersects of the selected region.
598 * Will cause the format toolbar, the edit area, and the auto expressions to be
599 * updated if appropriate.
602 gnm_sheet_view_flag_status_update_range (SheetView
*sv
, GnmRange
const *range
)
604 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
606 /* Force an update */
608 sv
->selection_content_changed
= TRUE
;
609 sv
->edit_pos_changed
.location
=
610 sv
->edit_pos_changed
.content
=
611 sv
->edit_pos_changed
.style
= TRUE
;
615 /* if a part of the selected region changed value update
616 * the auto expressions
618 if (sv_is_range_selected (sv
, range
))
619 sv
->selection_content_changed
= TRUE
;
621 /* If the edit cell changes value update the edit area
622 * and the format toolbar
624 if (range_contains (range
, sv
->edit_pos
.col
, sv
->edit_pos
.row
))
625 sv
->edit_pos_changed
.content
= sv
->edit_pos_changed
.style
= TRUE
;
629 * gnm_sheet_view_flag_style_update_range:
630 * @sv: The sheet being changed
631 * @range: the range that is changing.
633 * Flag style changes that will require updating the style indicators.
636 gnm_sheet_view_flag_style_update_range (SheetView
*sv
, GnmRange
const *range
)
638 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
639 g_return_if_fail (range
!= NULL
);
640 if (range_contains (range
, sv
->edit_pos
.col
, sv
->edit_pos
.row
))
641 sv
->edit_pos_changed
.style
= TRUE
;
645 * gnm_sheet_view_flag_selection_change:
648 * flag the sheet as requiring an update to the status display
650 * Will cause auto expressions to be updated
653 gnm_sheet_view_flag_selection_change (SheetView
*sv
)
655 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
656 sv
->selection_content_changed
= TRUE
;
660 sheet_view_edit_pos_tool_tips (SheetView
*sv
)
662 GnmStyle
const *style
;
663 GnmInputMsg
*im
= NULL
;
665 style
= sheet_style_get (sv
->sheet
,
668 if (style
!= NULL
&& gnm_style_is_element_set (style
, MSTYLE_INPUT_MSG
))
669 im
= gnm_style_get_input_msg (style
);
671 /* We need to call these even with im == NULL to remove the old tooltip.*/
672 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
673 sc_show_im_tooltip (control
, im
, &sv
->edit_pos
););
677 gnm_sheet_view_update (SheetView
*sv
)
679 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
681 if (sv
->edit_pos_changed
.content
) {
682 sv
->edit_pos_changed
.content
= FALSE
;
683 if (wb_view_cur_sheet_view (sv
->sv_wbv
) == sv
)
684 wb_view_edit_line_set (sv
->sv_wbv
, NULL
);
687 if (sv
->edit_pos_changed
.style
) {
688 sv
->edit_pos_changed
.style
= FALSE
;
689 if (wb_view_cur_sheet_view (sv
->sv_wbv
) == sv
)
690 wb_view_style_feedback (sv
->sv_wbv
);
693 if (sv
->edit_pos_changed
.location
) {
694 sv
->edit_pos_changed
.location
= FALSE
;
695 if (wb_view_cur_sheet_view (sv
->sv_wbv
) == sv
) {
696 wb_view_selection_desc (sv
->sv_wbv
, TRUE
, NULL
);
697 SHEET_VIEW_FOREACH_CONTROL
698 (sv
, sc
, wb_control_menu_state_update
700 MS_COMMENT_LINKS
| MS_PAGE_BREAKS
););
701 sheet_view_edit_pos_tool_tips (sv
);
705 if (sv
->selection_content_changed
) {
706 int const lag
= gnm_conf_get_core_gui_editing_recalclag ();
707 sv
->selection_content_changed
= FALSE
;
708 if (sv
->auto_expr_timer
== 0 || lag
< 0) {
709 auto_expr_timer_clear (sv
);
710 sv
->auto_expr_timer
= g_timeout_add_full (0, abs (lag
), /* seems ok */
711 cb_update_auto_expr
, (gpointer
) sv
, NULL
);
713 SHEET_VIEW_FOREACH_CONTROL (sv
, sc
,
714 wb_control_menu_state_update (sc_wbc (sc
), MS_ADD_VS_REMOVE_FILTER
|
715 MS_COMMENT_LINKS_RANGE
););
718 SHEET_VIEW_FOREACH_CONTROL (sv
, sc
,
719 wb_control_menu_state_update
720 (sc_wbc (sc
), MS_SELECT_OBJECT
););
725 * gnm_sheet_view_editpos_in_filter:
728 * Returns: (nullable): #GnmFilter that overlaps the sv::edit_pos
731 gnm_sheet_view_editpos_in_filter (SheetView
const *sv
)
733 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), NULL
);
734 return gnm_sheet_filter_at_pos (sv
->sheet
, &sv
->edit_pos
);
738 * gnm_sheet_view_selection_intersects_filter_rows:
741 * Returns: (nullable): #GnmFilter whose rows intersect the rows
742 * of the current selection.
745 gnm_sheet_view_selection_intersects_filter_rows (SheetView
const *sv
)
748 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), NULL
);
749 r
= selection_first_range (sv
, NULL
, NULL
);
751 return r
? gnm_sheet_filter_intersect_rows
752 (sv
->sheet
, r
->start
.row
, r
->end
.row
) : NULL
;
756 * gnm_sheet_view_selection_extends_filter:
759 * Returns: (nullable): #GnmFilter whose rows intersect the rows
760 * of the current selection range to which the filter can be
764 gnm_sheet_view_selection_extends_filter (SheetView
const *sv
,
768 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), NULL
);
769 r
= selection_first_range (sv
, NULL
, NULL
);
771 return gnm_sheet_filter_can_be_extended (sv
->sheet
, f
, r
);
778 * gnm_sheet_view_editpos_in_slicer:
781 * Returns: (transfer none) (nullable): #GnmSheetSlicer that overlaps the
785 gnm_sheet_view_editpos_in_slicer (SheetView
const *sv
)
787 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), NULL
);
788 return gnm_sheet_slicers_at_pos (sv
->sheet
, &sv
->edit_pos
);
792 * gnm_sheet_view_freeze_panes:
794 * @frozen_top_left: (nullable): top left corner of the frozen region
795 * @unfrozen_top_left: (nullable): top left corner of the unfrozen region
797 * By definition the unfrozen region must be below the frozen.
798 * If @frozen_top_left == @unfrozen_top_left or @frozen_top_left == NULL unfreeze
801 gnm_sheet_view_freeze_panes (SheetView
*sv
,
802 GnmCellPos
const *frozen
,
803 GnmCellPos
const *unfrozen
)
805 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
807 if (gnm_debug_flag ("frozen-panes")) {
808 g_printerr ("Frozen: %-10s",
809 frozen
? cellpos_as_string (frozen
) : "-");
810 g_printerr ("Unfrozen: %s\n",
811 unfrozen
? cellpos_as_string (unfrozen
) : "-");
814 if (frozen
!= NULL
) {
815 g_return_if_fail (unfrozen
!= NULL
);
816 g_return_if_fail (unfrozen
->col
>= frozen
->col
);
817 g_return_if_fail (unfrozen
->row
>= frozen
->row
);
820 if (unfrozen
->col
!= gnm_sheet_get_last_col (sv
->sheet
) &&
821 unfrozen
->row
!= gnm_sheet_get_last_row (sv
->sheet
) &&
822 !gnm_cellpos_equal (frozen
, unfrozen
)) {
823 sv
->frozen_top_left
= *frozen
;
824 sv
->unfrozen_top_left
= *unfrozen
;
825 if (sv
->frozen_top_left
.col
== sv
->unfrozen_top_left
.col
)
826 sv
->frozen_top_left
.col
= sv
->unfrozen_top_left
.col
= 0;
827 if (sv
->frozen_top_left
.row
== sv
->unfrozen_top_left
.row
)
828 sv
->frozen_top_left
.row
= sv
->unfrozen_top_left
.row
= 0;
830 frozen
= unfrozen
= NULL
;
833 if (frozen
== NULL
) {
834 g_return_if_fail (unfrozen
== NULL
);
837 if (sv
->frozen_top_left
.col
< 0 &&
838 sv
->frozen_top_left
.row
< 0 &&
839 sv
->unfrozen_top_left
.col
< 0 &&
840 sv
->unfrozen_top_left
.row
< 0)
843 sv
->initial_top_left
= sv
->frozen_top_left
;
844 sv
->frozen_top_left
.col
= sv
->frozen_top_left
.row
=
845 sv
->unfrozen_top_left
.col
= sv
->unfrozen_top_left
.row
= -1;
848 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
849 sv_init_sc (sv
, control
););
851 WORKBOOK_VIEW_FOREACH_CONTROL(sv
->sv_wbv
, wbc
,
852 wb_control_menu_state_update (wbc
, MS_FREEZE_VS_THAW
););
856 * gnm_sheet_view_panes_insdel_colrow:
863 * Adjust the positions of frozen panes as necessary to handle col/row
864 * insertions and deletions. note this assumes that the ins/del operations
865 * have already set the flags that will force a resize.
868 gnm_sheet_view_panes_insdel_colrow (SheetView
*sv
, gboolean is_cols
,
869 gboolean is_insert
, int start
, int count
)
874 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
876 tl
= sv
->frozen_top_left
; /* _copy_ them */
877 br
= sv
->unfrozen_top_left
;
880 /* ignore if not frozen, or acting in unfrozen region */
881 if (br
.col
<= tl
.col
|| br
.col
<= start
)
887 if (br
.col
< tl
.col
|| br
.col
>= gnm_sheet_get_max_cols (sv
->sheet
))
891 tl
.col
-= MIN (count
, tl
.col
- start
);
893 if (br
.col
<= tl
.col
)
897 /* ignore if not frozen, or acting in unfrozen region */
898 if (br
.row
<= tl
.row
|| br
.row
<= start
)
904 if (br
.row
< tl
.row
|| br
.row
>= gnm_sheet_get_max_rows (sv
->sheet
))
908 tl
.row
-= MIN (count
, tl
.row
- start
);
910 if (br
.row
<= tl
.row
)
914 gnm_sheet_view_freeze_panes (sv
, &tl
, &br
);
918 gnm_sheet_view_is_frozen (SheetView
const *sv
)
920 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), FALSE
);
922 /* be flexible, in the future we will support 2 way splits too */
923 return sv
->unfrozen_top_left
.col
>= 0 ||
924 sv
->unfrozen_top_left
.row
>= 0;
928 gnm_sheet_view_set_initial_top_left:
929 * @sv: the sheet view.
933 * Sets the top left cell that a newly created sheet control should display.
934 * This corresponds to the top left cell visible in pane 0 (frozen or not).
935 * NOTE : the unfrozen_top_left != initial_top_left. Unfrozen is the first
936 * unfrozen cell, and corresponds to the _minimum_ cell in pane 0. However,
937 * the pane can scroll and may have something else currently visible as the top
941 gnm_sheet_view_set_initial_top_left (SheetView
*sv
, int col
, int row
)
943 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
944 g_return_if_fail (0 <= col
&& col
< gnm_sheet_get_max_cols (sv
->sheet
));
945 g_return_if_fail (0 <= row
&& row
< gnm_sheet_get_max_rows (sv
->sheet
));
946 g_return_if_fail (!gnm_sheet_view_is_frozen (sv
) ||
947 (sv
->unfrozen_top_left
.col
<= col
&&
948 sv
->unfrozen_top_left
.row
<= row
));
950 sv
->initial_top_left
.col
= col
;
951 sv
->initial_top_left
.row
= row
;