xref: /aoo41x/main/tools/inc/tools/multisel.hxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #ifndef _SV_MULTISEL_HXX
28 #define _SV_MULTISEL_HXX
29 
30 #include "tools/toolsdllapi.h"
31 #include <tools/gen.hxx>
32 #include <tools/list.hxx>
33 #include <tools/string.hxx>
34 
35 #include <vector>
36 #include <set>
37 
38 //------------------------------------------------------------------
39 
40 #ifdef _SV_MULTISEL_CXX
41 DECLARE_LIST( ImpSelList, Range* )
42 #else
43 #define ImpSelList List
44 #endif
45 
46 #define SFX_ENDOFSELECTION		CONTAINER_ENTRY_NOTFOUND
47 
48 //------------------------------------------------------------------
49 
50 // ------------------
51 // - MultiSelection -
52 // ------------------
53 
54 class TOOLS_DLLPUBLIC MultiSelection
55 {
56 private:
57 	ImpSelList		aSels;		// array of SV-selections
58 	Range			aTotRange;	// total range of indexes
59 	sal_uIntPtr			nCurSubSel; // index in aSels of current selected index
60 	long			nCurIndex;	// current selected entry
61 	sal_uIntPtr			nSelCount;	// number of selected indexes
62 	sal_Bool			bInverseCur;// inverse cursor
63 	sal_Bool			bCurValid;	// are nCurIndex and nCurSubSel valid
64 	sal_Bool			bSelectNew; // auto-select newly inserted indexes
65 
66 #ifdef _SV_MULTISEL_CXX
67 	TOOLS_DLLPRIVATE void			ImplClear();
68 	TOOLS_DLLPRIVATE sal_uIntPtr			ImplFindSubSelection( long nIndex ) const;
69 	TOOLS_DLLPRIVATE sal_Bool			ImplMergeSubSelections( sal_uIntPtr nPos1, sal_uIntPtr nPos2 );
70 	TOOLS_DLLPRIVATE long			ImplFwdUnselected();
71 	TOOLS_DLLPRIVATE long			ImplBwdUnselected();
72 #endif
73 
74 public:
75 					MultiSelection();
76 					MultiSelection( const MultiSelection& rOrig );
77 					MultiSelection( const Range& rRange );
78 					MultiSelection( const UniString& rString,
79 									sal_Unicode cRange = '-',
80 									sal_Unicode cSep = ';' );
81 					~MultiSelection();
82 
83 	MultiSelection& operator= ( const MultiSelection& rOrig );
84 	sal_Bool			operator== ( MultiSelection& rOrig );
85 	sal_Bool			operator!= ( MultiSelection& rOrig )
86 						{ return !operator==( rOrig ); }
87 	sal_Bool			operator !() const
88 						{ return nSelCount == 0; }
89 
90 	void			SelectAll( sal_Bool bSelect = sal_True );
91 	sal_Bool			Select( long nIndex, sal_Bool bSelect = sal_True );
92 	void			Select( const Range& rIndexRange, sal_Bool bSelect = sal_True );
93 	sal_Bool			IsSelected( long nIndex ) const;
94 	sal_Bool			IsAllSelected() const
95 						{ return nSelCount == sal_uIntPtr(aTotRange.Len()); }
96 	long			GetSelectCount() const { return nSelCount; }
97 
98 	void			SetTotalRange( const Range& rTotRange );
99 	void			Insert( long nIndex, long nCount = 1 );
100 	void			Remove( long nIndex );
101 	void			Append( long nCount = 1 );
102 
103 	const Range&	GetTotalRange() const { return aTotRange; }
104 	sal_Bool			IsCurValid() const { return bCurValid; }
105 	long			GetCurSelected() const { return nCurIndex; }
106 	long			FirstSelected( sal_Bool bInverse = sal_False );
107 	long			LastSelected();
108 	long			NextSelected();
109 	long			PrevSelected();
110 
111 	sal_uIntPtr			GetRangeCount() const { return aSels.Count(); }
112 	const Range&	GetRange( sal_uIntPtr nRange ) const { return *(const Range*)aSels.GetObject(nRange); }
113 };
114 
115 class TOOLS_DLLPUBLIC StringRangeEnumerator
116 {
117     struct Range
118     {
119         sal_Int32   nFirst;
120         sal_Int32   nLast;
121 
122         Range() : nFirst( -1 ), nLast( -1 ) {}
123         Range( sal_Int32 i_nFirst, sal_Int32 i_nLast ) : nFirst( i_nFirst ), nLast( i_nLast ) {}
124     };
125     std::vector< StringRangeEnumerator::Range >            maSequence;
126     sal_Int32                                              mnCount;
127     sal_Int32                                              mnMin;
128     sal_Int32                                              mnMax;
129     sal_Int32                                              mnOffset;
130 
131     bool insertRange( sal_Int32 nFirst, sal_Int32 nLast, bool bSequence, bool bMayAdjust );
132     bool checkValue( sal_Int32, const std::set< sal_Int32 >* i_pPossibleValues = NULL ) const;
133 public:
134     class TOOLS_DLLPUBLIC Iterator
135     {
136         const StringRangeEnumerator*      pEnumerator;
137         const std::set< sal_Int32 >*      pPossibleValues;
138         sal_Int32                         nRangeIndex;
139         sal_Int32                         nCurrent;
140 
141         friend class StringRangeEnumerator;
142         Iterator( const StringRangeEnumerator* i_pEnum,
143                   const std::set< sal_Int32 >* i_pPossibleValues,
144                   sal_Int32 i_nRange,
145                   sal_Int32 i_nCurrent )
146         : pEnumerator( i_pEnum ), pPossibleValues( i_pPossibleValues )
147         , nRangeIndex( i_nRange ), nCurrent( i_nCurrent ) {}
148     public:
149         Iterator() : pEnumerator( NULL ), pPossibleValues( NULL ), nRangeIndex( -1 ), nCurrent( -1 ) {}
150         Iterator& operator++();
151         sal_Int32 operator*() const;
152         bool operator==(const Iterator&) const;
153         bool operator!=(const Iterator& i_rComp) const
154         { return ! (*this == i_rComp); }
155     };
156 
157     friend class StringRangeEnumerator::Iterator;
158 
159     StringRangeEnumerator() : mnCount( 0 ), mnMin( -1 ), mnMax( -1 ), mnOffset( -1 ) {}
160     StringRangeEnumerator( const rtl::OUString& i_rInput,
161                            sal_Int32 i_nMinNumber = -1,
162                            sal_Int32 i_nMaxNumber = -1,
163                            sal_Int32 i_nLogicalOffset = -1
164                            );
165 
166     size_t size() const { return size_t(mnCount); }
167     Iterator begin( const std::set< sal_Int32 >* i_pPossibleValues = NULL ) const;
168     Iterator end( const std::set< sal_Int32 >* i_pPossibleValues = NULL ) const;
169 
170     sal_Int32 getMin() const { return mnMin; }
171     void setMin( sal_Int32 i_nMinValue ) { mnMin = i_nMinValue; }
172     sal_Int32 getMax() const { return mnMax; }
173     void setMax( sal_Int32 i_nMaxValue ) { mnMax = i_nMaxValue; }
174     sal_Int32 getLogicalOffset() const { return mnOffset; }
175     void setLogicalOffset( sal_Int32 i_nOffset ) { mnOffset = i_nOffset; }
176 
177     bool setRange( const rtl::OUString& i_rNewRange, bool i_bStrict = false );
178     bool hasValue( sal_Int32 nValue, const std::set< sal_Int32 >* i_pPossibleValues = NULL ) const;
179 
180 
181     /**
182     i_rPageRange:     the string to be changed into a sequence of numbers
183                       valid format example "5-3,9,9,7-8" ; instead of ',' ';' or ' ' are allowed as well
184     o_rPageVector:    the output sequence of numbers
185     i_nLogicalOffset: an offset to be applied to each number in the string before inserting it in the resulting sequence
186                       example: a user enters page numbers from 1 to n (since that is logical)
187                                of course usable page numbers in code would start from 0 and end at n-1
188                                so the logical offset would be -1
189     i_nMinNumber:     the minimum allowed number, a negative number means no minimum check
190     i_nMaxNumber:     the maximum allowed number, a negative number means no maximum check
191 
192     @returns: true if the input string was valid, o_rPageVector will contain the resulting sequence
193               false if the input string was invalid, o_rPageVector will be unchanged
194 
195     behavior:
196     - only non-negative sequence numbers are allowed
197     - only non-negative values in the input string are allowed
198     - the string "-3" will be either
199       * an error if no minimum is given
200       * or result in the sequence i_nMinNumber to 3
201     - the string "3-" will be either
202       * an error if no maximum is given
203       * or result in the seqeuence 3 to i_nMaxNumber
204     - an empty string as input is valid and will result in the range [min,max] if given
205       or an empty vector, if not
206     */
207     static bool getRangesFromString( const rtl::OUString& i_rPageRange,
208                                      std::vector< sal_Int32 >& o_rPageVector,
209                                      sal_Int32 i_nMinNumber = -1,
210                                      sal_Int32 i_nMaxNumber = -1,
211                                      sal_Int32 i_nLogicalOffset = -1,
212                                      std::set< sal_Int32 >* i_pPossibleValues = NULL
213                                     );
214 };
215 
216 #endif	// _SV_MULTISEL_HXX
217