blob: e072d21afb60273033989e46896375228dcb9d25 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#ifndef _SV_MULTISEL_HXX
#define _SV_MULTISEL_HXX
#include "tools/toolsdllapi.h"
#include <tools/gen.hxx>
#include <tools/list.hxx>
#include <tools/string.hxx>
#include <vector>
#include <set>
//------------------------------------------------------------------
#ifdef _SV_MULTISEL_CXX
DECLARE_LIST( ImpSelList, Range* )
#else
#define ImpSelList List
#endif
#define SFX_ENDOFSELECTION CONTAINER_ENTRY_NOTFOUND
//------------------------------------------------------------------
// ------------------
// - MultiSelection -
// ------------------
class TOOLS_DLLPUBLIC MultiSelection
{
private:
ImpSelList aSels; // array of SV-selections
Range aTotRange; // total range of indexes
sal_uIntPtr nCurSubSel; // index in aSels of current selected index
long nCurIndex; // current selected entry
sal_uIntPtr nSelCount; // number of selected indexes
sal_Bool bInverseCur;// inverse cursor
sal_Bool bCurValid; // are nCurIndex and nCurSubSel valid
sal_Bool bSelectNew; // auto-select newly inserted indexes
#ifdef _SV_MULTISEL_CXX
TOOLS_DLLPRIVATE void ImplClear();
TOOLS_DLLPRIVATE sal_uIntPtr ImplFindSubSelection( long nIndex ) const;
TOOLS_DLLPRIVATE sal_Bool ImplMergeSubSelections( sal_uIntPtr nPos1, sal_uIntPtr nPos2 );
TOOLS_DLLPRIVATE long ImplFwdUnselected();
TOOLS_DLLPRIVATE long ImplBwdUnselected();
#endif
public:
MultiSelection();
MultiSelection( const MultiSelection& rOrig );
MultiSelection( const Range& rRange );
MultiSelection( const UniString& rString,
sal_Unicode cRange = '-',
sal_Unicode cSep = ';' );
~MultiSelection();
MultiSelection& operator= ( const MultiSelection& rOrig );
sal_Bool operator== ( MultiSelection& rOrig );
sal_Bool operator!= ( MultiSelection& rOrig )
{ return !operator==( rOrig ); }
sal_Bool operator !() const
{ return nSelCount == 0; }
void SelectAll( sal_Bool bSelect = sal_True );
sal_Bool Select( long nIndex, sal_Bool bSelect = sal_True );
void Select( const Range& rIndexRange, sal_Bool bSelect = sal_True );
sal_Bool IsSelected( long nIndex ) const;
sal_Bool IsAllSelected() const
{ return nSelCount == sal_uIntPtr(aTotRange.Len()); }
long GetSelectCount() const { return nSelCount; }
void SetTotalRange( const Range& rTotRange );
void Insert( long nIndex, long nCount = 1 );
void Remove( long nIndex );
void Append( long nCount = 1 );
const Range& GetTotalRange() const { return aTotRange; }
sal_Bool IsCurValid() const { return bCurValid; }
long GetCurSelected() const { return nCurIndex; }
long FirstSelected( sal_Bool bInverse = sal_False );
long LastSelected();
long NextSelected();
long PrevSelected();
sal_uIntPtr GetRangeCount() const { return aSels.Count(); }
const Range& GetRange( sal_uIntPtr nRange ) const { return *(const Range*)aSels.GetObject(nRange); }
};
class TOOLS_DLLPUBLIC StringRangeEnumerator
{
struct Range
{
sal_Int32 nFirst;
sal_Int32 nLast;
Range() : nFirst( -1 ), nLast( -1 ) {}
Range( sal_Int32 i_nFirst, sal_Int32 i_nLast ) : nFirst( i_nFirst ), nLast( i_nLast ) {}
};
std::vector< StringRangeEnumerator::Range > maSequence;
sal_Int32 mnCount;
sal_Int32 mnMin;
sal_Int32 mnMax;
sal_Int32 mnOffset;
bool insertRange( sal_Int32 nFirst, sal_Int32 nLast, bool bSequence, bool bMayAdjust );
bool checkValue( sal_Int32, const std::set< sal_Int32 >* i_pPossibleValues = NULL ) const;
public:
class TOOLS_DLLPUBLIC Iterator
{
const StringRangeEnumerator* pEnumerator;
const std::set< sal_Int32 >* pPossibleValues;
sal_Int32 nRangeIndex;
sal_Int32 nCurrent;
friend class StringRangeEnumerator;
Iterator( const StringRangeEnumerator* i_pEnum,
const std::set< sal_Int32 >* i_pPossibleValues,
sal_Int32 i_nRange,
sal_Int32 i_nCurrent )
: pEnumerator( i_pEnum ), pPossibleValues( i_pPossibleValues )
, nRangeIndex( i_nRange ), nCurrent( i_nCurrent ) {}
public:
Iterator() : pEnumerator( NULL ), pPossibleValues( NULL ), nRangeIndex( -1 ), nCurrent( -1 ) {}
Iterator& operator++();
sal_Int32 operator*() const;
bool operator==(const Iterator&) const;
bool operator!=(const Iterator& i_rComp) const
{ return ! (*this == i_rComp); }
};
friend class StringRangeEnumerator::Iterator;
StringRangeEnumerator() : mnCount( 0 ), mnMin( -1 ), mnMax( -1 ), mnOffset( -1 ) {}
StringRangeEnumerator( const rtl::OUString& i_rInput,
sal_Int32 i_nMinNumber = -1,
sal_Int32 i_nMaxNumber = -1,
sal_Int32 i_nLogicalOffset = -1
);
size_t size() const { return size_t(mnCount); }
Iterator begin( const std::set< sal_Int32 >* i_pPossibleValues = NULL ) const;
Iterator end( const std::set< sal_Int32 >* i_pPossibleValues = NULL ) const;
sal_Int32 getMin() const { return mnMin; }
void setMin( sal_Int32 i_nMinValue ) { mnMin = i_nMinValue; }
sal_Int32 getMax() const { return mnMax; }
void setMax( sal_Int32 i_nMaxValue ) { mnMax = i_nMaxValue; }
sal_Int32 getLogicalOffset() const { return mnOffset; }
void setLogicalOffset( sal_Int32 i_nOffset ) { mnOffset = i_nOffset; }
bool setRange( const rtl::OUString& i_rNewRange, bool i_bStrict = false );
bool hasValue( sal_Int32 nValue, const std::set< sal_Int32 >* i_pPossibleValues = NULL ) const;
/**
i_rPageRange: the string to be changed into a sequence of numbers
valid format example "5-3,9,9,7-8" ; instead of ',' ';' or ' ' are allowed as well
o_rPageVector: the output sequence of numbers
i_nLogicalOffset: an offset to be applied to each number in the string before inserting it in the resulting sequence
example: a user enters page numbers from 1 to n (since that is logical)
of course usable page numbers in code would start from 0 and end at n-1
so the logical offset would be -1
i_nMinNumber: the minimum allowed number, a negative number means no minimum check
i_nMaxNumber: the maximum allowed number, a negative number means no maximum check
@returns: true if the input string was valid, o_rPageVector will contain the resulting sequence
false if the input string was invalid, o_rPageVector will be unchanged
behavior:
- only non-negative sequence numbers are allowed
- only non-negative values in the input string are allowed
- the string "-3" will be either
* an error if no minimum is given
* or result in the sequence i_nMinNumber to 3
- the string "3-" will be either
* an error if no maximum is given
* or result in the seqeuence 3 to i_nMaxNumber
- an empty string as input is valid and will result in the range [min,max] if given
or an empty vector, if not
*/
static bool getRangesFromString( const rtl::OUString& i_rPageRange,
std::vector< sal_Int32 >& o_rPageVector,
sal_Int32 i_nMinNumber = -1,
sal_Int32 i_nMaxNumber = -1,
sal_Int32 i_nLogicalOffset = -1,
std::set< sal_Int32 >* i_pPossibleValues = NULL
);
};
#endif // _SV_MULTISEL_HXX