summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorMarkus Mohrhard <markus.mohrhard@googlemail.com>2013-06-28 23:28:36 +0200
committerMarkus Mohrhard <markus.mohrhard@googlemail.com>2013-06-29 00:08:17 +0200
commit17cb1d6d82db56761c86ee95195689cc155901b3 (patch)
treeacce5799ac6a7693f34a53a51606a9090002dc07 /sc
parenta539cf2c09bdd62d1c4a0124ed536f88d4fd01d5 (diff)
allow these cond formats to be updated when formula val changes,fdo#64401
When the formulas depend on cells outside of the paint range we need to update the whole range. This approach will update the range more often than necessary but prevents that we need to mess with ScFormulaCell. In the future we should replace ScFormulaCell in this part of the code with something simpler that will correctly fix this problem. Change-Id: Ie8a8e5205f9ea1e43bb6d9f8bee6e0bab29e4840
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/colorscale.hxx35
-rw-r--r--sc/inc/conditio.hxx2
-rw-r--r--sc/source/core/data/colorscale.cxx154
-rw-r--r--sc/source/core/data/conditio.cxx17
4 files changed, 203 insertions, 5 deletions
diff --git a/sc/inc/colorscale.hxx b/sc/inc/colorscale.hxx
index 5a390de6e430..832e09b9b026 100644
--- a/sc/inc/colorscale.hxx
+++ b/sc/inc/colorscale.hxx
@@ -17,6 +17,9 @@
#include <rangelst.hxx>
#include "conditio.hxx"
+#include <svl/listener.hxx>
+#include <svl/broadcast.hxx>
+
#include <vector>
//TODO: merge this with conditio.hxx
@@ -27,6 +30,24 @@ class ScTokenArray;
struct ScDataBarInfo;
class BitmapEx;
+class ScFormulaListener : public SvtListener
+{
+private:
+ std::vector<ScRange> maCells;
+ mutable bool mbDirty;
+ ScDocument* mpDoc;
+
+ void startListening(ScTokenArray* pTokens, const ScAddress& rPos);
+
+public:
+ ScFormulaListener(ScFormulaCell* pCell);
+ virtual ~ScFormulaListener();
+
+ void Notify( SvtBroadcaster& rBC, const SfxHint& rHint );
+
+ bool NeedsRepaint() const;
+};
+
// don't change the order
// they are also used in the dialog to determine the position
// in the list box
@@ -47,6 +68,7 @@ private:
double mnVal;
Color maColor;
boost::scoped_ptr<ScFormulaCell> mpCell;
+ boost::scoped_ptr<ScFormulaListener> mpListener;
ScColorScaleEntryType meType;
public:
@@ -60,7 +82,9 @@ public:
void SetColor(const Color&);
double GetValue() const;
void SetValue(double nValue);
- void SetFormula(const OUString& rFormula, ScDocument* pDoc, const ScAddress& rAddr, formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT);
+ void SetFormula(const OUString& rFormula, ScDocument* pDoc, const ScAddress& rAddr,
+ formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT);
+
void UpdateMoveTab(SCTAB nOldTab, SCTAB nNewTab, SCTAB nTabNo);
void UpdateReference( UpdateRefMode eUpdateRefMode,
const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
@@ -71,6 +95,7 @@ public:
ScColorScaleEntryType GetType() const;
void SetType( ScColorScaleEntryType eType );
+ bool NeedsRepaint() const;
};
namespace databar
@@ -200,6 +225,8 @@ public:
virtual void startRendering();
virtual void endRendering();
+ virtual bool NeedsRepaint() const = 0;
+
protected:
std::vector<double>& getValues() const;
@@ -243,6 +270,8 @@ public:
virtual void UpdateReference( UpdateRefMode eUpdateRefMode,
const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
+ virtual bool NeedsRepaint() const;
+
virtual condformat::ScFormatEntryType GetType() const;
typedef ColorScaleEntries::iterator iterator;
typedef ColorScaleEntries::const_iterator const_iterator;
@@ -271,6 +300,8 @@ public:
virtual void UpdateReference( UpdateRefMode eUpdateRefMode,
const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
+ virtual bool NeedsRepaint() const;
+
virtual condformat::ScFormatEntryType GetType() const;
private:
@@ -313,6 +344,8 @@ public:
virtual void UpdateReference( UpdateRefMode eUpdateRefMode,
const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
+ virtual bool NeedsRepaint() const;
+
virtual condformat::ScFormatEntryType GetType() const;
static ScIconSetMap* getIconSetMap();
diff --git a/sc/inc/conditio.hxx b/sc/inc/conditio.hxx
index 87cfcc30446d..42ad1f73e322 100644
--- a/sc/inc/conditio.hxx
+++ b/sc/inc/conditio.hxx
@@ -390,6 +390,8 @@ public:
// don't use the same name as for the const version
ScRangeList& GetRangeList() { return maRanges; }
+ ScDocument* GetDocument() { return pDoc; }
+
bool IsEmpty() const;
size_t size() const;
diff --git a/sc/source/core/data/colorscale.cxx b/sc/source/core/data/colorscale.cxx
index 70865be1a577..9d4d71b56ee5 100644
--- a/sc/source/core/data/colorscale.cxx
+++ b/sc/source/core/data/colorscale.cxx
@@ -13,12 +13,117 @@
#include "fillinfo.hxx"
#include "iconsets.hrc"
#include "scresid.hxx"
+#include "tokenarray.hxx"
+
+#include "formula/token.hxx"
#include <algorithm>
+ScFormulaListener::ScFormulaListener(ScFormulaCell* pCell):
+ mbDirty(false),
+ mpDoc(pCell->GetDocument())
+{
+ startListening( pCell->GetCode(), pCell->aPos );
+}
+
+void ScFormulaListener::startListening(ScTokenArray* pArr, const ScAddress& rPos)
+{
+ pArr->Reset();
+ ScToken* t;
+ while ( ( t = static_cast<ScToken*>(pArr->GetNextReferenceRPN()) ) != NULL )
+ {
+ switch (t->GetType())
+ {
+ case formula::svSingleRef:
+ {
+ ScAddress aCell = t->GetSingleRef().toAbs(rPos);
+ if (aCell.IsValid())
+ mpDoc->StartListeningCell(aCell, this);
+
+ maCells.push_back(aCell);
+ }
+ break;
+ case formula::svDoubleRef:
+ {
+ const ScSingleRefData& rRef1 = t->GetSingleRef();
+ const ScSingleRefData& rRef2 = t->GetSingleRef2();
+ ScAddress aCell1 = rRef1.toAbs(rPos);
+ ScAddress aCell2 = rRef2.toAbs(rPos);
+ if (aCell1.IsValid() && aCell2.IsValid())
+ {
+ if (t->GetOpCode() == ocColRowNameAuto)
+ { // automagically
+ if ( rRef1.IsColRel() )
+ { // ColName
+ aCell2.SetRow(MAXROW);
+ }
+ else
+ { // RowName
+ aCell2.SetCol(MAXCOL);
+ }
+ }
+ mpDoc->StartListeningArea(ScRange(aCell1, aCell2), this);
+ maCells.push_back(ScRange(aCell1, aCell2));
+ }
+ }
+ break;
+ default:
+ ; // nothing
+ }
+ }
+
+}
+
+namespace {
+
+struct StopListeningCell
+{
+ StopListeningCell(ScDocument* pDoc, SvtListener* pListener):
+ mpDoc(pDoc), mpListener(pListener) {}
+
+ void operator()(const ScRange& rRange)
+ {
+ for(SCTAB nTab = rRange.aStart.Tab(),
+ nTabEnd = rRange.aEnd.Tab(); nTab <= nTabEnd; ++nTab)
+ {
+ for(SCCOL nCol = rRange.aStart.Col(),
+ nColEnd = rRange.aEnd.Col(); nCol <= nColEnd; ++nCol)
+ {
+ for(SCROW nRow = rRange.aStart.Row(),
+ nRowEnd = rRange.aEnd.Row(); nRow <= nRowEnd; ++nRow)
+ {
+ mpDoc->EndListeningCell(ScAddress(nCol, nRow, nTab), mpListener);
+ }
+ }
+ }
+ }
+
+private:
+ ScDocument* mpDoc;
+ SvtListener* mpListener;
+};
+
+}
+
+ScFormulaListener::~ScFormulaListener()
+{
+ std::for_each(maCells.begin(), maCells.end(), StopListeningCell(mpDoc, this));
+}
+
+void ScFormulaListener::Notify(SvtBroadcaster&, const SfxHint&)
+{
+ mbDirty = true;
+}
+
+bool ScFormulaListener::NeedsRepaint() const
+{
+ bool bRet = mbDirty;
+ mbDirty = false;
+ return bRet;
+}
+
ScColorScaleEntry::ScColorScaleEntry():
mnVal(0),
- mpCell(NULL),
meType(COLORSCALE_VALUE)
{
}
@@ -26,7 +131,6 @@ ScColorScaleEntry::ScColorScaleEntry():
ScColorScaleEntry::ScColorScaleEntry(double nVal, const Color& rCol):
mnVal(nVal),
maColor(rCol),
- mpCell(NULL),
meType(COLORSCALE_VALUE)
{
}
@@ -34,13 +138,13 @@ ScColorScaleEntry::ScColorScaleEntry(double nVal, const Color& rCol):
ScColorScaleEntry::ScColorScaleEntry(const ScColorScaleEntry& rEntry):
mnVal(rEntry.mnVal),
maColor(rEntry.maColor),
- mpCell(),
meType(rEntry.meType)
{
if(rEntry.mpCell)
{
mpCell.reset(new ScFormulaCell(*rEntry.mpCell, *rEntry.mpCell->GetDocument(), rEntry.mpCell->aPos, SC_CLONECELL_NOMAKEABS_EXTERNAL));
mpCell->StartListeningTo( mpCell->GetDocument() );
+ mpListener.reset(new ScFormulaListener(mpCell.get()));
}
}
@@ -54,6 +158,7 @@ ScColorScaleEntry::ScColorScaleEntry(ScDocument* pDoc, const ScColorScaleEntry&
{
mpCell.reset(new ScFormulaCell(*rEntry.mpCell, *rEntry.mpCell->GetDocument(), rEntry.mpCell->aPos, SC_CLONECELL_NOMAKEABS_EXTERNAL));
mpCell->StartListeningTo( pDoc );
+ mpListener.reset(new ScFormulaListener(mpCell.get()));
}
}
@@ -67,6 +172,7 @@ void ScColorScaleEntry::SetFormula( const OUString& rFormula, ScDocument* pDoc,
{
mpCell.reset(new ScFormulaCell( pDoc, rAddr, rFormula, eGrammar ));
mpCell->StartListeningTo( pDoc );
+ mpListener.reset(new ScFormulaListener(mpCell.get()));
}
const ScTokenArray* ScColorScaleEntry::GetFormula() const
@@ -107,6 +213,7 @@ double ScColorScaleEntry::GetValue() const
void ScColorScaleEntry::SetValue(double nValue)
{
mnVal = nValue;
+ mpCell.reset();
}
void ScColorScaleEntry::UpdateMoveTab( SCTAB nOldTab, SCTAB nNewTab, SCTAB nTabNo )
@@ -114,6 +221,7 @@ void ScColorScaleEntry::UpdateMoveTab( SCTAB nOldTab, SCTAB nNewTab, SCTAB nTabN
if(mpCell)
{
mpCell->UpdateMoveTab( nOldTab, nNewTab, nTabNo );
+ mpListener.reset(new ScFormulaListener(mpCell.get()));
}
}
@@ -123,9 +231,18 @@ void ScColorScaleEntry::UpdateReference( UpdateRefMode eUpdateRefMode,
if(mpCell)
{
mpCell->UpdateReference( eUpdateRefMode, rRange, nDx, nDy, nDz );
+ mpListener.reset(new ScFormulaListener(mpCell.get()));
}
}
+bool ScColorScaleEntry::NeedsRepaint() const
+{
+ if(mpListener)
+ return mpListener->NeedsRepaint();
+
+ return false;
+}
+
const Color& ScColorScaleEntry::GetColor() const
{
return maColor;
@@ -182,7 +299,10 @@ void ScColorScaleEntry::SetType( ScColorScaleEntryType eType )
{
meType = eType;
if(eType != COLORSCALE_FORMULA)
+ {
mpCell.reset();
+ mpListener.reset();
+ }
}
ScColorScaleEntryType ScColorScaleEntry::GetType() const
@@ -445,6 +565,17 @@ void ScColorScaleFormat::UpdateReference( UpdateRefMode eUpdateRefMode,
}
}
+bool ScColorScaleFormat::NeedsRepaint() const
+{
+ for(const_iterator itr = begin(), itrEnd = end();
+ itr != itrEnd; ++itr)
+ {
+ if(itr->NeedsRepaint())
+ return true;
+ }
+ return false;
+}
+
bool ScColorScaleFormat::CheckEntriesForRel(const ScRange& rRange) const
{
bool bNeedUpdate = false;
@@ -547,6 +678,12 @@ void ScDataBarFormat::UpdateReference( UpdateRefMode eRefMode,
mpFormatData->mpLowerLimit->UpdateReference( eRefMode, rRange, nDx, nDy, nDz );
}
+bool ScDataBarFormat::NeedsRepaint() const
+{
+ return mpFormatData->mpUpperLimit->NeedsRepaint() ||
+ mpFormatData->mpLowerLimit->NeedsRepaint();
+}
+
namespace {
bool NeedUpdate(ScColorScaleEntry* pEntry)
@@ -854,6 +991,17 @@ void ScIconSetFormat::UpdateReference( UpdateRefMode eUpdateRefMode,
}
}
+bool ScIconSetFormat::NeedsRepaint() const
+{
+ for(const_iterator itr = begin(); itr != end(); ++itr)
+ {
+ if(itr->NeedsRepaint())
+ return true;
+ }
+
+ return false;
+}
+
ScIconSetFormat::iterator ScIconSetFormat::begin()
{
return mpFormatData->maEntries.begin();
diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx
index 88028cf317f3..3792d5d29679 100644
--- a/sc/source/core/data/conditio.cxx
+++ b/sc/source/core/data/conditio.cxx
@@ -2053,11 +2053,26 @@ void ScConditionalFormat::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos )
void ScConditionalFormat::SourceChanged( const ScAddress& rAddr )
{
for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
- if(itr->GetType() == condformat::CONDITION)
+ {
+ condformat::ScFormatEntryType eEntryType = itr->GetType();
+ if( eEntryType == condformat::CONDITION)
{
ScCondFormatEntry& rFormat = static_cast<ScCondFormatEntry&>(*itr);
rFormat.SourceChanged( rAddr );
}
+ else if( eEntryType == condformat::COLORSCALE ||
+ eEntryType == condformat::DATABAR ||
+ eEntryType == condformat::ICONSET )
+ {
+ ScColorFormat& rFormat = static_cast<ScColorFormat&>(*itr);
+ if(rFormat.NeedsRepaint())
+ {
+ // we need to repaint the whole range anyway
+ DoRepaint(NULL);
+ return;
+ }
+ }
+ }
}
bool ScConditionalFormat::MarkUsedExternalReferences() const