2bac61013e
Change-Id: Iade3fedac5d2f8e978b7dd9c30f001d7d1564946
515 lines
17 KiB
C++
515 lines
17 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#ifndef INCLUDED_SC_INC_CONDITIO_HXX
|
|
#define INCLUDED_SC_INC_CONDITIO_HXX
|
|
|
|
#include "global.hxx"
|
|
#include "address.hxx"
|
|
#include <formula/grammar.hxx>
|
|
#include "scdllapi.h"
|
|
#include "rangelst.hxx"
|
|
|
|
#include <rtl/math.hxx>
|
|
#include <tools/date.hxx>
|
|
|
|
#include <map>
|
|
|
|
#include <boost/noncopyable.hpp>
|
|
#include <boost/ptr_container/ptr_set.hpp>
|
|
#include <boost/ptr_container/ptr_vector.hpp>
|
|
#include <boost/scoped_ptr.hpp>
|
|
|
|
class ScFormulaCell;
|
|
class ScTokenArray;
|
|
struct ScRefCellValue;
|
|
|
|
namespace sc {
|
|
|
|
struct RefUpdateContext;
|
|
struct RefUpdateInsertTabContext;
|
|
struct RefUpdateDeleteTabContext;
|
|
struct RefUpdateMoveTabContext;
|
|
|
|
}
|
|
|
|
// nOptions Flags
|
|
#define SC_COND_NOBLANKS 1
|
|
|
|
enum ScConditionMode
|
|
{
|
|
SC_COND_EQUAL,
|
|
SC_COND_LESS,
|
|
SC_COND_GREATER,
|
|
SC_COND_EQLESS,
|
|
SC_COND_EQGREATER,
|
|
SC_COND_NOTEQUAL,
|
|
SC_COND_BETWEEN,
|
|
SC_COND_NOTBETWEEN,
|
|
SC_COND_DUPLICATE,
|
|
SC_COND_NOTDUPLICATE,
|
|
SC_COND_DIRECT,
|
|
SC_COND_TOP10,
|
|
SC_COND_BOTTOM10,
|
|
SC_COND_TOP_PERCENT,
|
|
SC_COND_BOTTOM_PERCENT,
|
|
SC_COND_ABOVE_AVERAGE,
|
|
SC_COND_BELOW_AVERAGE,
|
|
SC_COND_ABOVE_EQUAL_AVERAGE,
|
|
SC_COND_BELOW_EQUAL_AVERAGE,
|
|
SC_COND_ERROR,
|
|
SC_COND_NOERROR,
|
|
SC_COND_BEGINS_WITH,
|
|
SC_COND_ENDS_WITH,
|
|
SC_COND_CONTAINS_TEXT,
|
|
SC_COND_NOT_CONTAINS_TEXT,
|
|
SC_COND_NONE
|
|
};
|
|
|
|
class ScConditionalFormat;
|
|
struct ScDataBarInfo;
|
|
struct ScIconSetInfo;
|
|
|
|
namespace condformat
|
|
{
|
|
|
|
enum ScFormatEntryType
|
|
{
|
|
CONDITION,
|
|
COLORSCALE,
|
|
DATABAR,
|
|
ICONSET,
|
|
DATE
|
|
};
|
|
|
|
}
|
|
|
|
struct ScCondFormatData
|
|
{
|
|
ScCondFormatData():
|
|
pColorScale(NULL),
|
|
pDataBar(NULL),
|
|
pIconSet(NULL) {}
|
|
|
|
Color* pColorScale;
|
|
ScDataBarInfo* pDataBar;
|
|
ScIconSetInfo* pIconSet;
|
|
OUString aStyleName;
|
|
};
|
|
|
|
class SC_DLLPUBLIC ScFormatEntry
|
|
{
|
|
public:
|
|
ScFormatEntry(ScDocument* pDoc);
|
|
virtual ~ScFormatEntry() {}
|
|
|
|
virtual condformat::ScFormatEntryType GetType() const = 0;
|
|
virtual void UpdateReference( sc::RefUpdateContext& rCxt ) = 0;
|
|
virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt ) = 0;
|
|
virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt ) = 0;
|
|
virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt ) = 0;
|
|
|
|
virtual ScFormatEntry* Clone( ScDocument* pDoc = NULL ) const = 0;
|
|
|
|
virtual void SetParent( ScConditionalFormat* pNew ) = 0;
|
|
|
|
bool operator==( const ScFormatEntry& ) const;
|
|
|
|
virtual void startRendering();
|
|
virtual void endRendering();
|
|
protected:
|
|
ScDocument* mpDoc;
|
|
|
|
};
|
|
|
|
class approx_less : public std::binary_function<double, double, bool>
|
|
{
|
|
public:
|
|
bool operator() (double nVal1, double nVal2) const
|
|
{
|
|
if(nVal1 < nVal2 && !rtl::math::approxEqual(nVal1, nVal2))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
};
|
|
|
|
class SC_DLLPUBLIC ScConditionEntry : public ScFormatEntry
|
|
{
|
|
// stored data:
|
|
ScConditionMode eOp;
|
|
sal_uInt16 nOptions;
|
|
double nVal1; // input or calculated
|
|
double nVal2;
|
|
OUString aStrVal1; // input or calculated
|
|
OUString aStrVal2;
|
|
OUString aStrNmsp1; // namespace to be used on (re)compilation, e.g. in XML import
|
|
OUString aStrNmsp2; // namespace to be used on (re)compilation, e.g. in XML import
|
|
formula::FormulaGrammar::Grammar eTempGrammar1; // grammar to be used on (re)compilation, e.g. in XML import
|
|
formula::FormulaGrammar::Grammar eTempGrammar2; // grammar to be used on (re)compilation, e.g. in XML import
|
|
bool bIsStr1; // for recognition of empty strings
|
|
bool bIsStr2;
|
|
ScTokenArray* pFormula1; // entered formula
|
|
ScTokenArray* pFormula2;
|
|
ScAddress aSrcPos; // source position for formulas
|
|
// temporary data:
|
|
OUString aSrcString; // formula source position as text during XML import
|
|
ScFormulaCell* pFCell1;
|
|
ScFormulaCell* pFCell2;
|
|
bool bRelRef1;
|
|
bool bRelRef2;
|
|
bool bFirstRun;
|
|
|
|
void MakeCells( const ScAddress& rPos );
|
|
void Compile( const OUString& rExpr1, const OUString& rExpr2,
|
|
const OUString& rExprNmsp1, const OUString& rExprNmsp2,
|
|
formula::FormulaGrammar::Grammar eGrammar1,
|
|
formula::FormulaGrammar::Grammar eGrammar2,
|
|
bool bTextToReal );
|
|
void Interpret( const ScAddress& rPos );
|
|
|
|
bool IsValid( double nArg, const ScAddress& rPos ) const;
|
|
bool IsValidStr( const OUString& rArg, const ScAddress& rPos ) const;
|
|
|
|
public:
|
|
ScConditionEntry( ScConditionMode eOper,
|
|
const OUString& rExpr1, const OUString& rExpr2,
|
|
ScDocument* pDocument, const ScAddress& rPos,
|
|
const OUString& rExprNmsp1, const OUString& rExprNmsp2,
|
|
formula::FormulaGrammar::Grammar eGrammar1,
|
|
formula::FormulaGrammar::Grammar eGrammar2 );
|
|
ScConditionEntry( ScConditionMode eOper,
|
|
const ScTokenArray* pArr1, const ScTokenArray* pArr2,
|
|
ScDocument* pDocument, const ScAddress& rPos );
|
|
ScConditionEntry( const ScConditionEntry& r ); // flat copy of formulas
|
|
// true copy of formulas (for Ref-Undo):
|
|
ScConditionEntry( ScDocument* pDocument, const ScConditionEntry& r );
|
|
virtual ~ScConditionEntry();
|
|
|
|
bool operator== ( const ScConditionEntry& r ) const;
|
|
|
|
virtual void SetParent( ScConditionalFormat* pNew ) SAL_OVERRIDE { pCondFormat = pNew; }
|
|
|
|
bool IsCellValid( ScRefCellValue& rCell, const ScAddress& rPos ) const;
|
|
|
|
ScConditionMode GetOperation() const { return eOp; }
|
|
bool IsIgnoreBlank() const { return ( nOptions & SC_COND_NOBLANKS ) == 0; }
|
|
void SetIgnoreBlank(bool bSet);
|
|
ScAddress GetSrcPos() const { return aSrcPos; }
|
|
|
|
ScAddress GetValidSrcPos() const; // adjusted to allow textual representation of expressions
|
|
|
|
void SetSrcString( const OUString& rNew ); // for XML import
|
|
|
|
void SetFormula1( const ScTokenArray& rArray );
|
|
void SetFormula2( const ScTokenArray& rArray );
|
|
|
|
OUString GetExpression( const ScAddress& rCursor, sal_uInt16 nPos, sal_uLong nNumFmt = 0,
|
|
const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
|
|
|
|
ScTokenArray* CreateTokenArry( sal_uInt16 nPos ) const;
|
|
|
|
void CompileAll();
|
|
void CompileXML();
|
|
virtual void UpdateReference( sc::RefUpdateContext& rCxt ) SAL_OVERRIDE;
|
|
virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt ) SAL_OVERRIDE;
|
|
virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt ) SAL_OVERRIDE;
|
|
virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt ) SAL_OVERRIDE;
|
|
|
|
void SourceChanged( const ScAddress& rChanged );
|
|
|
|
bool MarkUsedExternalReferences() const;
|
|
|
|
virtual condformat::ScFormatEntryType GetType() const SAL_OVERRIDE { return condformat::CONDITION; }
|
|
|
|
virtual ScFormatEntry* Clone(ScDocument* pDoc = NULL) const SAL_OVERRIDE;
|
|
|
|
static ScConditionMode GetModeFromApi(sal_Int32 nOperator);
|
|
|
|
virtual void endRendering() SAL_OVERRIDE;
|
|
virtual void startRendering() SAL_OVERRIDE;
|
|
|
|
protected:
|
|
virtual void DataChanged( const ScRange* pModified ) const;
|
|
ScDocument* GetDocument() const { return mpDoc; }
|
|
ScConditionalFormat* pCondFormat;
|
|
|
|
private:
|
|
|
|
bool IsDuplicate(double nArg, const OUString& rStr) const;
|
|
bool IsTopNElement( double nArg ) const;
|
|
bool IsTopNPercent( double nArg ) const;
|
|
bool IsBottomNElement( double nArg ) const;
|
|
bool IsBottomNPercent( double nArg ) const;
|
|
bool IsAboveAverage( double nArg, bool bEqual ) const;
|
|
bool IsBelowAverage( double nArg, bool bEqual ) const;
|
|
|
|
bool IsError( const ScAddress& rPos ) const;
|
|
|
|
void FillCache() const;
|
|
|
|
struct ScConditionEntryCache
|
|
{
|
|
typedef std::map<OUString, sal_Int32> StringCacheType;
|
|
StringCacheType maStrings;
|
|
typedef std::map<double, sal_Int32, approx_less> ValueCacheType;
|
|
ValueCacheType maValues;
|
|
|
|
// cache them for easier access
|
|
size_t nValueItems;
|
|
|
|
ScConditionEntryCache():
|
|
nValueItems(0) {}
|
|
};
|
|
|
|
mutable boost::scoped_ptr<ScConditionEntryCache> mpCache;
|
|
};
|
|
|
|
|
|
// single entry for conditional formatting
|
|
|
|
|
|
class SC_DLLPUBLIC ScCondFormatEntry : public ScConditionEntry
|
|
{
|
|
OUString aStyleName;
|
|
|
|
using ScConditionEntry::operator==;
|
|
|
|
public:
|
|
ScCondFormatEntry( ScConditionMode eOper,
|
|
const OUString& rExpr1, const OUString& rExpr2,
|
|
ScDocument* pDocument, const ScAddress& rPos,
|
|
const OUString& rStyle,
|
|
const OUString& rExprNmsp1 = EMPTY_OUSTRING,
|
|
const OUString& rExprNmsp2 = EMPTY_OUSTRING,
|
|
formula::FormulaGrammar::Grammar eGrammar1 = formula::FormulaGrammar::GRAM_DEFAULT,
|
|
formula::FormulaGrammar::Grammar eGrammar2 = formula::FormulaGrammar::GRAM_DEFAULT );
|
|
ScCondFormatEntry( ScConditionMode eOper,
|
|
const ScTokenArray* pArr1, const ScTokenArray* pArr2,
|
|
ScDocument* pDocument, const ScAddress& rPos,
|
|
const OUString& rStyle );
|
|
ScCondFormatEntry( const ScCondFormatEntry& r );
|
|
ScCondFormatEntry( ScDocument* pDocument, const ScCondFormatEntry& r );
|
|
virtual ~ScCondFormatEntry();
|
|
|
|
bool operator== ( const ScCondFormatEntry& r ) const;
|
|
|
|
const OUString& GetStyle() const { return aStyleName; }
|
|
void UpdateStyleName(const OUString& rNew) { aStyleName=rNew; }
|
|
virtual ScFormatEntry* Clone(ScDocument* pDoc) const SAL_OVERRIDE;
|
|
|
|
protected:
|
|
virtual void DataChanged( const ScRange* pModified ) const SAL_OVERRIDE;
|
|
};
|
|
|
|
namespace condformat {
|
|
|
|
enum ScCondFormatDateType
|
|
{
|
|
TODAY,
|
|
YESTERDAY,
|
|
TOMORROW,
|
|
LAST7DAYS,
|
|
THISWEEK,
|
|
LASTWEEK,
|
|
NEXTWEEK,
|
|
THISMONTH,
|
|
LASTMONTH,
|
|
NEXTMONTH,
|
|
THISYEAR,
|
|
LASTYEAR,
|
|
NEXTYEAR
|
|
};
|
|
|
|
}
|
|
|
|
class SC_DLLPUBLIC ScCondDateFormatEntry : public ScFormatEntry
|
|
{
|
|
public:
|
|
ScCondDateFormatEntry(ScDocument* pDoc);
|
|
ScCondDateFormatEntry(ScDocument* pDoc, const ScCondDateFormatEntry& rEntry);
|
|
|
|
bool IsValid( const ScAddress& rPos ) const;
|
|
|
|
void SetDateType(condformat::ScCondFormatDateType eType);
|
|
condformat::ScCondFormatDateType GetDateType() const;
|
|
|
|
const OUString& GetStyleName() const;
|
|
void SetStyleName( const OUString& rStyleName );
|
|
|
|
virtual condformat::ScFormatEntryType GetType() const SAL_OVERRIDE { return condformat::DATE; }
|
|
virtual void UpdateReference( sc::RefUpdateContext& ) SAL_OVERRIDE {}
|
|
virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext& ) SAL_OVERRIDE {}
|
|
virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& ) SAL_OVERRIDE {}
|
|
virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext& ) SAL_OVERRIDE {}
|
|
|
|
virtual ScFormatEntry* Clone( ScDocument* pDoc = NULL ) const SAL_OVERRIDE;
|
|
|
|
virtual void SetParent( ScConditionalFormat* ) SAL_OVERRIDE {}
|
|
|
|
bool operator==( const ScFormatEntry& ) const;
|
|
|
|
virtual void startRendering() SAL_OVERRIDE;
|
|
virtual void endRendering() SAL_OVERRIDE;
|
|
|
|
private:
|
|
condformat::ScCondFormatDateType meType;
|
|
|
|
mutable boost::scoped_ptr<Date> mpCache;
|
|
|
|
OUString maStyleName;
|
|
};
|
|
|
|
|
|
// complete conditional formatting
|
|
|
|
|
|
class SC_DLLPUBLIC ScConditionalFormat: private boost::noncopyable
|
|
{
|
|
ScDocument* pDoc;
|
|
sal_uInt32 nKey; // Index in attributes
|
|
|
|
typedef boost::ptr_vector<ScFormatEntry> CondFormatContainer;
|
|
CondFormatContainer maEntries;
|
|
ScRangeList maRanges; // Ranges for conditional format
|
|
|
|
public:
|
|
ScConditionalFormat(sal_uInt32 nNewKey, ScDocument* pDocument);
|
|
~ScConditionalFormat();
|
|
|
|
// true copy of formulas (for Ref-Undo / between documents)
|
|
ScConditionalFormat* Clone(ScDocument* pNewDoc = NULL) const;
|
|
|
|
void AddEntry( ScFormatEntry* pNew );
|
|
void AddRange( const ScRangeList& rRanges );
|
|
const ScRangeList& GetRange() const { return maRanges; }
|
|
// 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;
|
|
|
|
void CompileAll();
|
|
void CompileXML();
|
|
void UpdateReference( sc::RefUpdateContext& rCxt, bool bCopyAsMove = false );
|
|
void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt );
|
|
void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt );
|
|
void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt );
|
|
|
|
void InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowStart, SCSIZE nSize);
|
|
void InsertCol(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColStart, SCSIZE nSize);
|
|
|
|
void DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
|
|
void RenameCellStyle( const OUString& rOld, const OUString& rNew );
|
|
|
|
void SourceChanged( const ScAddress& rAddr );
|
|
|
|
const ScFormatEntry* GetEntry( sal_uInt16 nPos ) const;
|
|
|
|
const OUString& GetCellStyle( ScRefCellValue& rCell, const ScAddress& rPos ) const;
|
|
|
|
ScCondFormatData GetData( ScRefCellValue& rCell, const ScAddress& rPos ) const;
|
|
|
|
bool EqualEntries( const ScConditionalFormat& r ) const;
|
|
|
|
void DoRepaint( const ScRange* pModified );
|
|
|
|
sal_uInt32 GetKey() const { return nKey; }
|
|
void SetKey(sal_uInt32 nNew) { nKey = nNew; } // only if not inserted!
|
|
|
|
bool MarkUsedExternalReferences() const;
|
|
|
|
// sorted (via PTRARR) by Index
|
|
// operator== only for sorting
|
|
bool operator ==( const ScConditionalFormat& r ) const { return nKey == r.nKey; }
|
|
bool operator < ( const ScConditionalFormat& r ) const { return nKey < r.nKey; }
|
|
|
|
void startRendering();
|
|
void endRendering();
|
|
};
|
|
|
|
|
|
// List of areas and formats:
|
|
|
|
|
|
class SC_DLLPUBLIC ScConditionalFormatList
|
|
{
|
|
private:
|
|
typedef boost::ptr_set<ScConditionalFormat> ConditionalFormatContainer;
|
|
ConditionalFormatContainer maConditionalFormats;
|
|
|
|
void operator =(ScConditionalFormatList const &) SAL_DELETED_FUNCTION;
|
|
|
|
public:
|
|
ScConditionalFormatList() {}
|
|
ScConditionalFormatList(const ScConditionalFormatList& rList);
|
|
ScConditionalFormatList(ScDocument* pDoc, const ScConditionalFormatList& rList);
|
|
~ScConditionalFormatList() {}
|
|
|
|
void InsertNew( ScConditionalFormat* pNew );
|
|
|
|
/**
|
|
* Checks that all cond formats have a non empty range.
|
|
* Deletes empty cond formats.
|
|
* @return true if all cond formats were valid
|
|
*/
|
|
bool CheckAllEntries();
|
|
|
|
ScConditionalFormat* GetFormat( sal_uInt32 nKey );
|
|
const ScConditionalFormat* GetFormat( sal_uInt32 nKey ) const;
|
|
|
|
void CompileAll();
|
|
void CompileXML();
|
|
void UpdateReference( sc::RefUpdateContext& rCxt );
|
|
void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt );
|
|
void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt );
|
|
void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt );
|
|
|
|
void InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowStart, SCSIZE nSize);
|
|
void InsertCol(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColStart, SCSIZE nSize);
|
|
|
|
void RenameCellStyle( const OUString& rOld, const OUString& rNew );
|
|
void DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
|
|
|
|
void SourceChanged( const ScAddress& rAddr );
|
|
|
|
bool operator==( const ScConditionalFormatList& r ) const; // for Ref-Undo
|
|
|
|
typedef ConditionalFormatContainer::iterator iterator;
|
|
typedef ConditionalFormatContainer::const_iterator const_iterator;
|
|
|
|
iterator begin();
|
|
const_iterator begin() const;
|
|
iterator end();
|
|
const_iterator end() const;
|
|
|
|
size_t size() const;
|
|
|
|
void erase(sal_uLong nIndex);
|
|
|
|
void startRendering();
|
|
void endRendering();
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|