From 961baa0d3d2691ebeabc3f51fdab8d816b32c563 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 30 May 2011 00:36:58 -0700 Subject: Queue swatch updates during periods of high UI usage, such as dragging gradient handles. Fixes bug #734981. Fixed bugs: - https://launchpad.net/bugs/734981 (bzr r10244) --- src/ui/dialog/swatches.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++-- src/ui/dialog/swatches.h | 3 ++ 2 files changed, 89 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index b2b1b26da..935fe9806 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "color-item.h" @@ -63,8 +64,6 @@ namespace Dialogs { void _loadPaletteFile( gchar const *filename ); -class DocTrack; - std::vector possible; static std::map docPalettes; static std::vector docTrackings; @@ -715,14 +714,31 @@ class DocTrack public: DocTrack(SPDocument *doc, sigc::connection &gradientRsrcChanged, sigc::connection &defsChanged, sigc::connection &defsModified) : doc(doc), + updatePending(false), + lastGradientUpdate(0.0), gradientRsrcChanged(gradientRsrcChanged), defsChanged(defsChanged), defsModified(defsModified) { + if ( !timer ) { + timer = new Glib::Timer(); + refreshTimer = Glib::signal_timeout().connect( sigc::ptr_fun(handleTimerCB), 33 ); + } + timerRefCount++; } ~DocTrack() { + timerRefCount--; + if ( timerRefCount <= 0 ) { + refreshTimer.disconnect(); + timerRefCount = 0; + if ( timer ) { + timer->stop(); + delete timer; + timer = 0; + } + } if (doc) { gradientRsrcChanged.disconnect(); defsChanged.disconnect(); @@ -730,7 +746,22 @@ public: } } + static bool handleTimerCB(); + + /** + * Checks if update should be queued or executed immediately. + * + * @return true if the update was queued and should not be immediately executed. + */ + static bool queueUpdateIfNeeded(SPDocument *doc); + + static Glib::Timer *timer; + static int timerRefCount; + static sigc::connection refreshTimer; + SPDocument *doc; + bool updatePending; + double lastGradientUpdate; sigc::connection gradientRsrcChanged; sigc::connection defsChanged; sigc::connection defsModified; @@ -740,6 +771,58 @@ private: DocTrack &operator=(DocTrack const &); // no assign }; +Glib::Timer *DocTrack::timer = 0; +int DocTrack::timerRefCount = 0; +sigc::connection DocTrack::refreshTimer; + +static const double DOC_UPDATE_THREASHOLD = 0.090; + +bool DocTrack::handleTimerCB() +{ + double now = timer->elapsed(); + + std::vector needCallback; + for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) { + DocTrack *track = *it; + if ( track->updatePending && ( (now - track->lastGradientUpdate) >= DOC_UPDATE_THREASHOLD) ) { + needCallback.push_back(track); + } + } + + for (std::vector::iterator it = needCallback.begin(); it != needCallback.end(); ++it) { + DocTrack *track = *it; + if ( std::find(docTrackings.begin(), docTrackings.end(), track) != docTrackings.end() ) { // Just in case one gets deleted while we are looping + // Note: calling handleDefsModified will call queueUpdateIfNeeded and thus update the time and flag. + SwatchesPanel::handleDefsModified(track->doc); + } + } + + return true; +} + +bool DocTrack::queueUpdateIfNeeded( SPDocument *doc ) +{ + bool deferProcessing = false; + for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) { + DocTrack *track = *it; + if ( track->doc == doc ) { + double now = timer->elapsed(); + double elapsed = now - track->lastGradientUpdate; + + if ( elapsed < DOC_UPDATE_THREASHOLD ) { + deferProcessing = true; + track->updatePending = true; + } else { + track->lastGradientUpdate = now; + track->updatePending = false; + } + + break; + } + } + return deferProcessing; +} + void SwatchesPanel::_trackDocument( SwatchesPanel *panel, SPDocument *document ) { SPDocument *oldDoc = 0; @@ -897,7 +980,7 @@ void SwatchesPanel::handleGradientsChange(SPDocument *document) void SwatchesPanel::handleDefsModified(SPDocument *document) { SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0; - if (docPalette) { + if (docPalette && !DocTrack::queueUpdateIfNeeded(document) ) { std::vector tmpColors; std::map tmpPrevs; std::map tmpGrads; diff --git a/src/ui/dialog/swatches.h b/src/ui/dialog/swatches.h index f9f3daf91..95d7acb00 100644 --- a/src/ui/dialog/swatches.h +++ b/src/ui/dialog/swatches.h @@ -23,6 +23,7 @@ namespace Dialogs { class ColorItem; class SwatchPage; +class DocTrack; /** * A panel that displays paint swatches. @@ -68,6 +69,8 @@ private: sigc::connection _documentConnection; sigc::connection _selChanged; + + friend class DocTrack; }; } //namespace Dialogs -- cgit v1.2.3