4 * Copyright (C) 2002-2006 Jody Goldberg (jody@gnome.org)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) version 3.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
22 #include <gnumeric-config.h>
23 #include <glib/gi18n-lib.h>
27 #include <sheet-view.h>
29 #include <sheet-merge.h>
30 #include <sheet-filter.h>
31 #include <gnm-sheet-slicer.h>
32 #include <sheet-private.h>
33 #include <sheet-control.h>
34 #include <sheet-control-priv.h>
35 #include <workbook-view.h>
36 #include <workbook-control.h>
38 #include <selection.h>
39 #include <application.h>
41 #include <parse-util.h>
42 #include <expr-name.h>
43 #include <command-context.h>
44 #include <gnumeric-conf.h>
45 #include <sheet-style.h>
49 #include <gsf/gsf-impl-utils.h>
51 #define GNM_SHEET_VIEW_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GNM_SHEET_VIEW_TYPE, SheetViewClass))
52 static GObjectClass
*parent_class
;
54 /*************************************************************************/
57 auto_expr_timer_clear (SheetView
*sv
)
59 if (sv
->auto_expr_timer
!= 0) {
60 g_source_remove (sv
->auto_expr_timer
);
61 sv
->auto_expr_timer
= 0;
66 cb_update_auto_expr (gpointer data
)
68 SheetView
*sv
= (SheetView
*) data
;
70 if (wb_view_cur_sheet_view (sv
->sv_wbv
) == sv
)
71 wb_view_auto_expr_recalc (sv
->sv_wbv
);
73 sv
->auto_expr_timer
= 0;
77 /*************************************************************************/
80 sv_sheet_name_changed (G_GNUC_UNUSED Sheet
*sheet
,
81 G_GNUC_UNUSED GParamSpec
*pspec
,
84 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
85 sv
->edit_pos_changed
.content
= TRUE
;
89 sv_sheet_visibility_changed (Sheet
*sheet
,
90 G_GNUC_UNUSED GParamSpec
*pspec
,
93 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
95 if (sheet_is_visible (sheet
) && !wb_view_cur_sheet (sv
->sv_wbv
))
96 wb_view_sheet_focus (sv
->sv_wbv
, sheet
);
100 sv_sheet_r1c1_changed (G_GNUC_UNUSED Sheet
*sheet
,
101 G_GNUC_UNUSED GParamSpec
*pspec
,
104 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
105 sv
->edit_pos_changed
.location
= TRUE
;
112 * Returns: (transfer none): the sheet.
115 sv_sheet (SheetView
const *sv
)
117 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), NULL
);
125 * Returns: (transfer none): the workbook view.
128 sv_wbv (SheetView
const *sv
)
130 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), NULL
);
135 sv_init_sc (SheetView
const *sv
, SheetControl
*sc
)
139 sc_scale_changed (sc
);
141 /* set_panes will change the initial so cache it */
142 initial
= sv
->initial_top_left
;
145 /* And this will restore it */
146 sc_set_top_left (sc
, initial
.col
, initial
.row
);
147 sc_scrollbar_config (sc
);
149 /* Set the visible bound, not the logical bound */
150 sc_cursor_bound (sc
, selection_first_range (sv
, NULL
, NULL
));
155 gnm_sheet_view_attach_control (SheetView
*sv
, SheetControl
*sc
)
157 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
158 g_return_if_fail (GNM_IS_SHEET_CONTROL (sc
));
159 g_return_if_fail (sc
->view
== NULL
);
161 g_ptr_array_add (sv
->controls
, sc
);
167 gnm_sheet_view_detach_control (SheetView
*sv
, SheetControl
*sc
)
169 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
170 g_return_if_fail (GNM_IS_SHEET_CONTROL (sc
));
171 g_return_if_fail (sv
== sc
->view
);
173 g_ptr_array_remove (sv
->controls
, sc
);
178 sv_weakref_notify (SheetView
**ptr
, GObject
*sv
)
180 g_return_if_fail (ptr
!= NULL
);
181 g_return_if_fail (*ptr
== (SheetView
*)sv
); /* remember sv is dead */
186 gnm_sheet_view_weak_ref (SheetView
*sv
, SheetView
**ptr
)
188 g_return_if_fail (ptr
!= NULL
);
192 g_object_weak_ref (G_OBJECT (sv
),
193 (GWeakNotify
) sv_weakref_notify
,
198 gnm_sheet_view_weak_unref (SheetView
**ptr
)
200 g_return_if_fail (ptr
!= NULL
);
203 g_object_weak_unref (G_OBJECT (*ptr
),
204 (GWeakNotify
) sv_weakref_notify
,
211 sv_finalize (GObject
*object
)
213 SheetView
*sv
= GNM_SHEET_VIEW (object
);
214 g_ptr_array_free (sv
->controls
, TRUE
);
215 parent_class
->finalize (object
);
219 sv_real_dispose (GObject
*object
)
221 SheetView
*sv
= GNM_SHEET_VIEW (object
);
223 while (sv
->controls
->len
> 0) {
224 SheetControl
*control
=
225 g_ptr_array_index (sv
->controls
,
226 sv
->controls
->len
- 10);
227 gnm_sheet_view_detach_control (sv
, control
);
228 g_object_unref (control
);
232 Sheet
*sheet
= sv
->sheet
;
234 g_ptr_array_remove (sheet
->sheet_views
, sv
);
235 g_signal_handlers_disconnect_by_func (sheet
, sv_sheet_name_changed
, sv
);
236 g_signal_handlers_disconnect_by_func (sheet
, sv_sheet_visibility_changed
, sv
);
237 g_signal_handlers_disconnect_by_func (sheet
, sv_sheet_r1c1_changed
, sv
);
239 g_object_unref (sheet
);
242 gnm_sheet_view_unant (sv
);
243 sv_selection_free (sv
);
244 sv_selection_simplified_free (sv
);
245 auto_expr_timer_clear (sv
);
247 parent_class
->dispose (object
);
251 gnm_sheet_view_class_init (GObjectClass
*klass
)
253 SheetViewClass
*wbc_class
= GNM_SHEET_VIEW_CLASS (klass
);
255 g_return_if_fail (wbc_class
!= NULL
);
257 parent_class
= g_type_class_peek_parent (klass
);
258 klass
->dispose
= sv_real_dispose
;
259 klass
->finalize
= sv_finalize
;
263 gnm_sheet_view_init (GObject
*object
)
265 SheetView
*sv
= GNM_SHEET_VIEW (object
);
267 sv
->controls
= g_ptr_array_new ();
269 /* Init menu states */
270 sv
->enable_insert_rows
= TRUE
;
271 sv
->enable_insert_cols
= TRUE
;
272 sv
->enable_insert_cells
= TRUE
;
274 sv
->edit_pos_changed
.location
= TRUE
;
275 sv
->edit_pos_changed
.content
= TRUE
;
276 sv
->edit_pos_changed
.style
= TRUE
;
277 sv
->selection_content_changed
= TRUE
;
278 sv
->reposition_selection
= TRUE
;
279 sv
->auto_expr_timer
= 0;
281 sv
->frozen_top_left
.col
= sv
->frozen_top_left
.row
=
282 sv
->unfrozen_top_left
.col
= sv
->unfrozen_top_left
.row
= -1;
283 sv
->initial_top_left
.col
= sv
->initial_top_left
.row
= 0;
285 sv
->selections
= NULL
;
286 sv
->selection_mode
= GNM_SELECTION_MODE_ADD
;
287 sv
->selections_simplified
= NULL
;
288 sv_selection_add_pos (sv
, 0, 0, GNM_SELECTION_MODE_ADD
);
291 GSF_CLASS (SheetView
, gnm_sheet_view
,
292 gnm_sheet_view_class_init
, gnm_sheet_view_init
,
296 gnm_sheet_view_new (Sheet
*sheet
, WorkbookView
*wbv
)
300 g_return_val_if_fail (IS_SHEET (sheet
), NULL
);
302 sv
= g_object_new (GNM_SHEET_VIEW_TYPE
, NULL
);
303 sv
->sheet
= g_object_ref (sheet
);
305 g_ptr_array_add (sheet
->sheet_views
, sv
);
308 g_signal_connect (G_OBJECT (sheet
),
310 G_CALLBACK (sv_sheet_name_changed
),
313 g_signal_connect (G_OBJECT (sheet
),
314 "notify::visibility",
315 G_CALLBACK (sv_sheet_visibility_changed
),
318 g_signal_connect (G_OBJECT (sheet
),
320 G_CALLBACK (sv_sheet_r1c1_changed
),
323 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
324 sv_init_sc (sv
, control
););
329 gnm_sheet_view_dispose (SheetView
*sv
)
331 g_object_run_dispose (G_OBJECT (sv
));
335 gnm_sheet_view_unant (SheetView
*sv
)
339 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
341 if (sv
->ants
== NULL
)
343 for (ptr
= sv
->ants
; ptr
!= NULL
; ptr
= ptr
->next
)
345 g_list_free (sv
->ants
);
348 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
349 sc_unant (control
););
353 * gnm_sheet_view_ant:
355 * @ranges: (element-type GnmRange) (transfer none): The ranges to ant.
358 gnm_sheet_view_ant (SheetView
*sv
, GList
*ranges
)
362 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
363 g_return_if_fail (ranges
!= NULL
);
365 if (sv
->ants
!= NULL
)
366 gnm_sheet_view_unant (sv
);
367 for (ptr
= ranges
; ptr
!= NULL
; ptr
= ptr
->next
)
368 sv
->ants
= g_list_prepend (sv
->ants
, gnm_range_dup (ptr
->data
));
369 sv
->ants
= g_list_reverse (sv
->ants
);
371 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
376 gnm_sheet_view_make_cell_visible (SheetView
*sv
, int col
, int row
,
377 gboolean couple_panes
)
379 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
380 SHEET_VIEW_FOREACH_CONTROL(sv
, control
,
381 sc_make_cell_visible (control
, col
, row
, couple_panes
););
385 gnm_sheet_view_redraw_range (SheetView
*sv
, GnmRange
const *r
)
387 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
389 SHEET_VIEW_FOREACH_CONTROL (sv
, sc
, sc_redraw_range (sc
, r
););
393 gnm_sheet_view_redraw_headers (SheetView
const *sv
,
394 gboolean col
, gboolean row
,
395 GnmRange
const* r
/* optional == NULL */)
397 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
399 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
400 sc_redraw_headers (control
, col
, row
, r
););
404 gnm_sheet_view_resize (SheetView
*sv
, gboolean force_scroll
)
406 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
408 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
409 sc_resize (control
, force_scroll
););
414 gnm_sheet_view_selection_copy (SheetView
*sv
, WorkbookControl
*wbc
)
418 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), FALSE
);
419 if (!(sel
= selection_first_range (sv
, GO_CMD_CONTEXT (wbc
), _("Copy"))))
422 gnm_app_clipboard_cut_copy (wbc
, FALSE
, sv
, sel
, TRUE
);
428 gnm_sheet_view_selection_cut (SheetView
*sv
, WorkbookControl
*wbc
)
432 /* 'cut' is a poor description of what we're
433 * doing here. 'move' would be a better
434 * approximation. The key portion of this process is that
435 * the range being moved has all
436 * - references to it adjusted to the new site.
437 * - relative references from it adjusted.
439 * NOTE : This command DOES NOT MOVE ANYTHING !
440 * We only store the src, paste does the move.
442 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), FALSE
);
444 if (!(sel
= selection_first_range (sv
, GO_CMD_CONTEXT (wbc
), _("Cut"))))
447 if (sheet_range_splits_region (sv_sheet (sv
), sel
, NULL
, GO_CMD_CONTEXT (wbc
), _("Cut")))
450 gnm_app_clipboard_cut_copy (wbc
, TRUE
, sv
, sel
, TRUE
);
456 * gnm_sheet_view_cursor_set:
463 * @bound: (nullable): A range that should contain all the supplied points
466 gnm_sheet_view_cursor_set (SheetView
*sv
,
467 GnmCellPos
const *edit
,
468 int base_col
, int base_row
,
469 int move_col
, int move_row
,
470 GnmRange
const *bound
)
474 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
476 /* Change the edit position */
477 gnm_sheet_view_set_edit_pos (sv
, edit
);
479 sv
->cursor
.base_corner
.col
= base_col
;
480 sv
->cursor
.base_corner
.row
= base_row
;
481 sv
->cursor
.move_corner
.col
= move_col
;
482 sv
->cursor
.move_corner
.row
= move_row
;
485 if (base_col
< move_col
) {
486 r
.start
.col
= base_col
;
487 r
.end
.col
= move_col
;
489 r
.end
.col
= base_col
;
490 r
.start
.col
= move_col
;
492 if (base_row
< move_row
) {
493 r
.start
.row
= base_row
;
494 r
.end
.row
= move_row
;
496 r
.end
.row
= base_row
;
497 r
.start
.row
= move_row
;
502 g_return_if_fail (range_is_sane (bound
));
504 SHEET_VIEW_FOREACH_CONTROL(sv
, control
,
505 sc_cursor_bound (control
, bound
););
509 gnm_sheet_view_set_edit_pos (SheetView
*sv
, GnmCellPos
const *pos
)
512 GnmRange
const *merged
;
514 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
515 g_return_if_fail (pos
!= NULL
);
518 sv
->first_tab_col
= -1; /* invalidate */
520 if (old
.col
== pos
->col
&& old
.row
== pos
->row
)
523 g_return_if_fail (IS_SHEET (sv
->sheet
));
524 g_return_if_fail (pos
->col
>= 0);
525 g_return_if_fail (pos
->col
< gnm_sheet_get_max_cols (sv
->sheet
));
526 g_return_if_fail (pos
->row
>= 0);
527 g_return_if_fail (pos
->row
< gnm_sheet_get_max_rows (sv
->sheet
));
530 merged
= gnm_sheet_merge_is_corner (sv
->sheet
, &old
);
532 sv
->edit_pos_changed
.location
=
533 sv
->edit_pos_changed
.content
=
534 sv
->edit_pos_changed
.style
= TRUE
;
536 /* Redraw before change */
537 if (merged
== NULL
) {
538 GnmRange tmp
; tmp
.start
= tmp
.end
= old
;
539 gnm_sheet_view_redraw_range (sv
, &tmp
);
541 gnm_sheet_view_redraw_range (sv
, merged
);
543 sv
->edit_pos_real
= *pos
;
545 /* Redraw after change (handling merged cells) */
546 merged
= gnm_sheet_merge_contains_pos (sv
->sheet
, &sv
->edit_pos_real
);
547 if (merged
== NULL
) {
548 GnmRange tmp
; tmp
.start
= tmp
.end
= *pos
;
549 gnm_sheet_view_redraw_range (sv
, &tmp
);
550 sv
->edit_pos
= sv
->edit_pos_real
;
552 gnm_sheet_view_redraw_range (sv
, merged
);
553 sv
->edit_pos
= merged
->start
;
558 * gnm_sheet_view_flag_status_update_pos:
562 * flag the view as requiring an update to the status display
563 * if the supplied cell location is the edit cursor, or part of the
566 * Will cause the format toolbar, the edit area, and the auto expressions to be
567 * updated if appropriate.
570 gnm_sheet_view_flag_status_update_pos (SheetView
*sv
, GnmCellPos
const *pos
)
572 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
573 g_return_if_fail (pos
!= NULL
);
575 /* if a part of the selected region changed value update
576 * the auto expressions
578 if (sv_is_pos_selected (sv
, pos
->col
, pos
->row
))
579 sv
->selection_content_changed
= TRUE
;
581 /* If the edit cell changes value update the edit area
582 * and the format toolbar
584 if (pos
->col
== sv
->edit_pos
.col
&& pos
->row
== sv
->edit_pos
.row
)
585 sv
->edit_pos_changed
.content
=
586 sv
->edit_pos_changed
.style
= TRUE
;
590 * gnm_sheet_view_flag_status_update_range:
592 * @range: (nullable): If %NULL then force an update.
594 * flag the sheet as requiring an update to the status display if the supplied
595 * cell location contains the edit cursor, or intersects of the selected region.
597 * Will cause the format toolbar, the edit area, and the auto expressions to be
598 * updated if appropriate.
601 gnm_sheet_view_flag_status_update_range (SheetView
*sv
, GnmRange
const *range
)
603 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
605 /* Force an update */
607 sv
->selection_content_changed
= TRUE
;
608 sv
->edit_pos_changed
.location
=
609 sv
->edit_pos_changed
.content
=
610 sv
->edit_pos_changed
.style
= TRUE
;
614 /* if a part of the selected region changed value update
615 * the auto expressions
617 if (sv_is_range_selected (sv
, range
))
618 sv
->selection_content_changed
= TRUE
;
620 /* If the edit cell changes value update the edit area
621 * and the format toolbar
623 if (range_contains (range
, sv
->edit_pos
.col
, sv
->edit_pos
.row
))
624 sv
->edit_pos_changed
.content
= sv
->edit_pos_changed
.style
= TRUE
;
628 * gnm_sheet_view_flag_style_update_range:
629 * @sv: The sheet being changed
630 * @range: the range that is changing.
632 * Flag style changes that will require updating the style indicators.
635 gnm_sheet_view_flag_style_update_range (SheetView
*sv
, GnmRange
const *range
)
637 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
638 g_return_if_fail (range
!= NULL
);
639 if (range_contains (range
, sv
->edit_pos
.col
, sv
->edit_pos
.row
))
640 sv
->edit_pos_changed
.style
= TRUE
;
644 * gnm_sheet_view_flag_selection_change:
647 * flag the sheet as requiring an update to the status display
649 * Will cause auto expressions to be updated
652 gnm_sheet_view_flag_selection_change (SheetView
*sv
)
654 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
655 sv
->selection_content_changed
= TRUE
;
659 sheet_view_edit_pos_tool_tips (SheetView
*sv
)
661 GnmStyle
const *style
;
662 GnmInputMsg
*im
= NULL
;
664 style
= sheet_style_get (sv
->sheet
,
667 if (style
!= NULL
&& gnm_style_is_element_set (style
, MSTYLE_INPUT_MSG
))
668 im
= gnm_style_get_input_msg (style
);
670 /* We need to call these even with im == NULL to remove the old tooltip.*/
671 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
672 sc_show_im_tooltip (control
, im
, &sv
->edit_pos
););
676 gnm_sheet_view_update (SheetView
*sv
)
678 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
680 if (sv
->edit_pos_changed
.content
) {
681 sv
->edit_pos_changed
.content
= FALSE
;
682 if (wb_view_cur_sheet_view (sv
->sv_wbv
) == sv
)
683 wb_view_edit_line_set (sv
->sv_wbv
, NULL
);
686 if (sv
->edit_pos_changed
.style
) {
687 sv
->edit_pos_changed
.style
= FALSE
;
688 if (wb_view_cur_sheet_view (sv
->sv_wbv
) == sv
)
689 wb_view_style_feedback (sv
->sv_wbv
);
692 if (sv
->edit_pos_changed
.location
) {
693 sv
->edit_pos_changed
.location
= FALSE
;
694 if (wb_view_cur_sheet_view (sv
->sv_wbv
) == sv
) {
695 wb_view_selection_desc (sv
->sv_wbv
, TRUE
, NULL
);
696 SHEET_VIEW_FOREACH_CONTROL
697 (sv
, sc
, wb_control_menu_state_update
699 MS_COMMENT_LINKS
| MS_PAGE_BREAKS
););
700 sheet_view_edit_pos_tool_tips (sv
);
704 if (sv
->selection_content_changed
) {
705 int const lag
= gnm_conf_get_core_gui_editing_recalclag ();
706 sv
->selection_content_changed
= FALSE
;
707 if (sv
->auto_expr_timer
== 0 || lag
< 0) {
708 auto_expr_timer_clear (sv
);
709 sv
->auto_expr_timer
= g_timeout_add_full (0, abs (lag
), /* seems ok */
710 cb_update_auto_expr
, (gpointer
) sv
, NULL
);
712 SHEET_VIEW_FOREACH_CONTROL (sv
, sc
,
713 wb_control_menu_state_update (sc_wbc (sc
), MS_ADD_VS_REMOVE_FILTER
|
714 MS_COMMENT_LINKS_RANGE
););
717 SHEET_VIEW_FOREACH_CONTROL (sv
, sc
,
718 wb_control_menu_state_update
719 (sc_wbc (sc
), MS_SELECT_OBJECT
););
724 * gnm_sheet_view_editpos_in_filter:
727 * Returns: (nullable): #GnmFilter that overlaps the sv::edit_pos
730 gnm_sheet_view_editpos_in_filter (SheetView
const *sv
)
732 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), NULL
);
733 return gnm_sheet_filter_at_pos (sv
->sheet
, &sv
->edit_pos
);
737 * gnm_sheet_view_selection_intersects_filter_rows:
740 * Returns: (nullable): #GnmFilter whose rows intersect the rows
741 * of the current selection.
744 gnm_sheet_view_selection_intersects_filter_rows (SheetView
const *sv
)
747 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), NULL
);
748 r
= selection_first_range (sv
, NULL
, NULL
);
750 return r
? gnm_sheet_filter_intersect_rows
751 (sv
->sheet
, r
->start
.row
, r
->end
.row
) : NULL
;
755 * gnm_sheet_view_selection_extends_filter:
758 * Returns: (nullable): #GnmFilter whose rows intersect the rows
759 * of the current selection range to which the filter can be
763 gnm_sheet_view_selection_extends_filter (SheetView
const *sv
,
767 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), NULL
);
768 r
= selection_first_range (sv
, NULL
, NULL
);
770 return gnm_sheet_filter_can_be_extended (sv
->sheet
, f
, r
);
777 * gnm_sheet_view_editpos_in_slicer:
780 * Returns: (transfer none) (nullable): #GnmSheetSlicer that overlaps the
784 gnm_sheet_view_editpos_in_slicer (SheetView
const *sv
)
786 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), NULL
);
787 return gnm_sheet_slicers_at_pos (sv
->sheet
, &sv
->edit_pos
);
791 * gnm_sheet_view_freeze_panes:
793 * @frozen_top_left: (nullable): top left corner of the frozen region
794 * @unfrozen_top_left: (nullable): top left corner of the unfrozen region
796 * By definition the unfrozen region must be below the frozen.
797 * If @frozen_top_left == @unfrozen_top_left or @frozen_top_left == NULL unfreeze
800 gnm_sheet_view_freeze_panes (SheetView
*sv
,
801 GnmCellPos
const *frozen
,
802 GnmCellPos
const *unfrozen
)
804 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
806 if (gnm_debug_flag ("frozen-panes")) {
807 g_printerr ("Frozen: %-10s",
808 frozen
? cellpos_as_string (frozen
) : "-");
809 g_printerr ("Unfrozen: %s\n",
810 unfrozen
? cellpos_as_string (unfrozen
) : "-");
813 if (frozen
!= NULL
) {
814 g_return_if_fail (unfrozen
!= NULL
);
815 g_return_if_fail (unfrozen
->col
>= frozen
->col
);
816 g_return_if_fail (unfrozen
->row
>= frozen
->row
);
819 if (unfrozen
->col
!= gnm_sheet_get_last_col (sv
->sheet
) &&
820 unfrozen
->row
!= gnm_sheet_get_last_row (sv
->sheet
) &&
821 !gnm_cellpos_equal (frozen
, unfrozen
)) {
822 sv
->frozen_top_left
= *frozen
;
823 sv
->unfrozen_top_left
= *unfrozen
;
824 if (sv
->frozen_top_left
.col
== sv
->unfrozen_top_left
.col
)
825 sv
->frozen_top_left
.col
= sv
->unfrozen_top_left
.col
= 0;
826 if (sv
->frozen_top_left
.row
== sv
->unfrozen_top_left
.row
)
827 sv
->frozen_top_left
.row
= sv
->unfrozen_top_left
.row
= 0;
829 frozen
= unfrozen
= NULL
;
832 if (frozen
== NULL
) {
833 g_return_if_fail (unfrozen
== NULL
);
836 if (sv
->frozen_top_left
.col
< 0 &&
837 sv
->frozen_top_left
.row
< 0 &&
838 sv
->unfrozen_top_left
.col
< 0 &&
839 sv
->unfrozen_top_left
.row
< 0)
842 sv
->initial_top_left
= sv
->frozen_top_left
;
843 sv
->frozen_top_left
.col
= sv
->frozen_top_left
.row
=
844 sv
->unfrozen_top_left
.col
= sv
->unfrozen_top_left
.row
= -1;
847 SHEET_VIEW_FOREACH_CONTROL (sv
, control
,
848 sv_init_sc (sv
, control
););
850 WORKBOOK_VIEW_FOREACH_CONTROL(sv
->sv_wbv
, wbc
,
851 wb_control_menu_state_update (wbc
, MS_FREEZE_VS_THAW
););
855 * gnm_sheet_view_panes_insdel_colrow:
857 * @is_cols: %TRUE for columns, %FALSE for rows.
862 * Adjust the positions of frozen panes as necessary to handle col/row
863 * insertions and deletions. note this assumes that the ins/del operations
864 * have already set the flags that will force a resize.
867 gnm_sheet_view_panes_insdel_colrow (SheetView
*sv
, gboolean is_cols
,
868 gboolean is_insert
, int start
, int count
)
873 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
875 tl
= sv
->frozen_top_left
; /* _copy_ them */
876 br
= sv
->unfrozen_top_left
;
879 /* ignore if not frozen, or acting in unfrozen region */
880 if (br
.col
<= tl
.col
|| br
.col
<= start
)
886 if (br
.col
< tl
.col
|| br
.col
>= gnm_sheet_get_max_cols (sv
->sheet
))
890 tl
.col
-= MIN (count
, tl
.col
- start
);
892 if (br
.col
<= tl
.col
)
896 /* ignore if not frozen, or acting in unfrozen region */
897 if (br
.row
<= tl
.row
|| br
.row
<= start
)
903 if (br
.row
< tl
.row
|| br
.row
>= gnm_sheet_get_max_rows (sv
->sheet
))
907 tl
.row
-= MIN (count
, tl
.row
- start
);
909 if (br
.row
<= tl
.row
)
913 gnm_sheet_view_freeze_panes (sv
, &tl
, &br
);
917 gnm_sheet_view_is_frozen (SheetView
const *sv
)
919 g_return_val_if_fail (GNM_IS_SHEET_VIEW (sv
), FALSE
);
921 /* be flexible, in the future we will support 2 way splits too */
922 return sv
->unfrozen_top_left
.col
>= 0 ||
923 sv
->unfrozen_top_left
.row
>= 0;
927 gnm_sheet_view_set_initial_top_left:
928 * @sv: the sheet view.
932 * Sets the top left cell that a newly created sheet control should display.
933 * This corresponds to the top left cell visible in pane 0 (frozen or not).
934 * NOTE : the unfrozen_top_left != initial_top_left. Unfrozen is the first
935 * unfrozen cell, and corresponds to the _minimum_ cell in pane 0. However,
936 * the pane can scroll and may have something else currently visible as the top
940 gnm_sheet_view_set_initial_top_left (SheetView
*sv
, int col
, int row
)
942 g_return_if_fail (GNM_IS_SHEET_VIEW (sv
));
943 g_return_if_fail (0 <= col
&& col
< gnm_sheet_get_max_cols (sv
->sheet
));
944 g_return_if_fail (0 <= row
&& row
< gnm_sheet_get_max_rows (sv
->sheet
));
945 g_return_if_fail (!gnm_sheet_view_is_frozen (sv
) ||
946 (sv
->unfrozen_top_left
.col
<= col
&&
947 sv
->unfrozen_top_left
.row
<= row
));
949 sv
->initial_top_left
.col
= col
;
950 sv
->initial_top_left
.row
= row
;