[gnumeric] Deps: delay redraws triggered by conditional styling.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Deps: delay redraws triggered by conditional styling.
- Date: Sun, 26 Apr 2020 20:28:40 +0000 (UTC)
commit 7aa3a3542ca82dc1c848f0cbcba85fdf9f2bf481
Author: Morten Welinder <terra gnome org>
Date: Sun Apr 26 16:26:11 2020 -0400
Deps: delay redraws triggered by conditional styling.
Do them in the main loop.
ChangeLog | 10 +++++++
NEWS | 2 +-
src/dependent.c | 15 ++++++----
src/sheet.c | 85 +++++++++++++++++++++++++++++++++++++++++++--------------
src/sheet.h | 6 +++-
5 files changed, 90 insertions(+), 28 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 7b616e757..679e3dd97 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2020-04-26 Morten Welinder <terra gnome org>
+
+ * src/dependent.c (style_dep_unrender): Queue the redraw instead
+ of doing it.
+
+ * src/sheet.c (sheet_redraw_region): We don't need the redraw-all
+ hack here. It's also in sc_redraw_range.
+ (sheet_queue_redraw_range): New function for queueing redraws that
+ we cannot actually handle happening right now.
+
2020-04-26 Jean Brefort <jean brefort normalesup org>
* src/sheet-object-component.c (sheet_object_component_new): really fix
diff --git a/NEWS b/NEWS
index 3503bb0c9..c9ecb7631 100644
--- a/NEWS
+++ b/NEWS
@@ -13,7 +13,7 @@ Morten:
* Doc fixes.
* Fix CELL crash. [#479]
* Handle export options for ssconvert --export-graphs.
- * Fix deps cash. [#480]
+ * Fix deps crash. [#480]
--------------------------------------------------------------------------
Gnumeric 1.12.46
diff --git a/src/dependent.c b/src/dependent.c
index 432385309..988641b76 100644
--- a/src/dependent.c
+++ b/src/dependent.c
@@ -1377,6 +1377,7 @@ style_dep_unrender (GnmDependent *dep, const char *what)
GnmCellPos const *pos = dependent_pos (dep);
GnmCell *cell;
Sheet *sheet = dep->sheet;
+ GnmRange r;
if (debug_style_deps ())
g_printerr ("StyleDep %p at %s %s\n",
@@ -1390,9 +1391,12 @@ style_dep_unrender (GnmDependent *dep, const char *what)
if (cell)
gnm_cell_unrender (cell);
- sheet_redraw_region (sheet,
- pos->col, pos->row,
- pos->col, pos->row);
+ // Redraws may involve computation (via conditional styling,
+ // for example) so doing it now is no good. See #480 for a
+ // particular nasty example involving conditional styling and
+ // dynamic dependents.
+ range_init_cellpos (&r, pos);
+ sheet_queue_redraw_range (sheet, &r);
}
static void
@@ -2881,11 +2885,10 @@ dynamic_dep_free (DynamicDep *dyn)
{
GnmDependent *dep = dyn->container;
GnmCellPos const *pos = dependent_pos (dep);
- GnmRangeRef *rr;
GSList *ptr;
for (ptr = dyn->singles ; ptr != NULL ; ptr = ptr->next) {
- rr = ptr->data;
+ GnmRangeRef *rr = ptr->data;
unlink_single_dep (&dyn->base, pos, &rr->a);
g_free (rr);
}
@@ -2893,7 +2896,7 @@ dynamic_dep_free (DynamicDep *dyn)
dyn->singles = NULL;
for (ptr = dyn->ranges ; ptr != NULL ; ptr = ptr->next) {
- rr = ptr->data;
+ GnmRangeRef *rr = ptr->data;
link_unlink_cellrange_dep (&dyn->base, pos,
&rr->a, &rr->b, FALSE);
g_free (rr);
diff --git a/src/sheet.c b/src/sheet.c
index 02cd6e503..f44620c87 100644
--- a/src/sheet.c
+++ b/src/sheet.c
@@ -853,6 +853,8 @@ gnm_sheet_init (Sheet *sheet)
sheet->style_data = NULL;
sheet->index_in_wb = -1;
+
+ sheet->pending_redraw_src = 0;
}
static Sheet the_invalid_sheet;
@@ -3204,45 +3206,85 @@ void
sheet_redraw_region (Sheet const *sheet,
int start_col, int start_row,
int end_col, int end_row)
+{
+ GnmRange r;
+ g_return_if_fail (IS_SHEET (sheet));
+
+ range_init (&r, start_col, start_row, end_col, end_row);
+ sheet_redraw_range (sheet, &r);
+}
+
+
+/**
+ * sheet_redraw_range:
+ * @sheet: sheet to redraw
+ * @range: range to redraw
+ *
+ * Redraw the indicated range, or at least the visible parts of it.
+ */
+void
+sheet_redraw_range (Sheet const *sheet, GnmRange const *range)
{
GnmRange bound;
g_return_if_fail (IS_SHEET (sheet));
+ g_return_if_fail (range != NULL);
- /*
- * Getting the bounding box causes row respans to be done if
- * needed. That can be expensive, so just redraw the whole
- * sheet if the row count is too big.
- */
- if (end_row - start_row > 500) {
- sheet_redraw_all (sheet, FALSE);
- return;
- }
-
- /* We potentially do a lot of recalcs as part of this, so make sure
- stuff that caches sub-computations see the whole thing instead
- of clearing between cells. */
+ // We potentially do a lot of recalcs as part of this, so make sure
+ // stuff that caches sub-computations see the whole thing instead
+ // of clearing between cells.
gnm_app_recalc_start ();
- sheet_range_bounding_box (sheet,
- range_init (&bound, start_col, start_row, end_col, end_row));
+ bound = *range;
+ sheet_range_bounding_box (sheet, &bound);
+
SHEET_FOREACH_CONTROL (sheet, view, control,
sc_redraw_range (control, &bound););
gnm_app_recalc_finish ();
}
+static gboolean
+cb_pending_redraw_handler (Sheet *sheet)
+{
+ while (sheet->pending_redraw) {
+ GnmRange *r = sheet->pending_redraw->data;
+ sheet->pending_redraw =
+ g_slist_delete_link (sheet->pending_redraw,
+ sheet->pending_redraw);
+ sheet_redraw_range (sheet, r);
+ g_free (r);
+ }
+
+ sheet->pending_redraw_src = 0;
+ return FALSE;
+}
+
+/**
+ * sheet_queue_redraw_range:
+ * @sheet: sheet to redraw
+ * @range: range to redraw
+ *
+ * This queues a redraw for the indicated range. The redraw will happen
+ * when Gnumeric returns to the gui main loop.
+ */
void
-sheet_redraw_range (Sheet const *sheet, GnmRange const *range)
+sheet_queue_redraw_range (Sheet *sheet, GnmRange const *range)
{
g_return_if_fail (IS_SHEET (sheet));
g_return_if_fail (range != NULL);
- sheet_redraw_region (sheet,
- range->start.col, range->start.row,
- range->end.col, range->end.row);
+ sheet->pending_redraw =
+ g_slist_prepend (sheet->pending_redraw,
+ g_memdup (range, sizeof (*range)));
+ if (sheet->pending_redraw_src == 0)
+ sheet->pending_redraw_src =
+ g_timeout_add (0,
+ (GSourceFunc)cb_pending_redraw_handler,
+ sheet);
}
+
/****************************************************************************/
gboolean
@@ -4852,7 +4894,10 @@ gnm_sheet_finalize (GObject *obj)
sheet_style_shutdown (sheet);
- (void) g_idle_remove_by_data (sheet);
+ if (sheet->pending_redraw_src) {
+ g_source_remove (sheet->pending_redraw_src);
+ sheet->pending_redraw_src = 0;
+ }
if (debug_FMR) {
g_printerr ("Sheet %p is %s\n", sheet, sheet->name_quoted);
diff --git a/src/sheet.h b/src/sheet.h
index 83b56e238..4ec65cc50 100644
--- a/src/sheet.h
+++ b/src/sheet.h
@@ -107,6 +107,9 @@ struct _Sheet {
GnmDepContainer *deps;
+ GSList *pending_redraw;
+ guint pending_redraw_src;
+
GSList *slicers;
GSList *filters;
GSList *list_merged;
@@ -316,7 +319,8 @@ gconstpointer gnm_sheet_find_sort_setup (Sheet *sheet, char const *key);
/* Redraw */
#define sheet_is_visible(_sheet) ((_sheet)->visibility == GNM_SHEET_VISIBILITY_VISIBLE)
void sheet_redraw_all (Sheet const *sheet, gboolean header);
-void sheet_redraw_range (Sheet const *sheet, GnmRange const *r);
+void sheet_redraw_range (Sheet const *sheet, GnmRange const *range);
+void sheet_queue_redraw_range (Sheet *sheet, GnmRange const *range);
void sheet_redraw_region (Sheet const *sheet,
int start_col, int start_row,
int end_col, int end_row);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]