1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 #ifndef INCLUDED_TOOLS_MULTISEL_HXX
20 #define INCLUDED_TOOLS_MULTISEL_HXX
21 
22 #include <tools/toolsdllapi.h>
23 #include <tools/gen.hxx>
24 #include <rtl/ustring.hxx>
25 
26 #include <vector>
27 #include <o3tl/sorted_vector.hxx>
28 
29 #define SFX_ENDOFSELECTION      (-1)
30 
31 class SAL_WARN_UNUSED TOOLS_DLLPUBLIC MultiSelection
32 {
33 private:
34     std::vector< Range >
35                     aSels;      // array of SV-selections
36     Range           aTotRange;  // total range of indexes
37     sal_Int32       nCurSubSel; // index in aSels of current selected index
38     sal_Int32       nCurIndex;  // current selected entry
39     sal_Int32       nSelCount;  // number of selected indexes
40     bool            bCurValid;  // are nCurIndex and nCurSubSel valid
41 
42     TOOLS_DLLPRIVATE void           ImplClear();
43     TOOLS_DLLPRIVATE sal_Int32      ImplFindSubSelection( sal_Int32 nIndex ) const;
44     TOOLS_DLLPRIVATE void           ImplMergeSubSelections( sal_Int32 nPos1, sal_Int32 nPos2 );
45 
46 public:
47                     MultiSelection();
48                     MultiSelection( const MultiSelection& rOrig );
49                     MultiSelection( const Range& rRange );
50                     ~MultiSelection();
51 
52     MultiSelection& operator= ( const MultiSelection& rOrig );
53 
54     void            SelectAll( bool bSelect = true );
55     bool            Select( sal_Int32 nIndex, bool bSelect = true );
56     void            Select( const Range& rIndexRange, bool bSelect = true );
57     bool            IsSelected( sal_Int32 nIndex ) const;
IsAllSelected() const58     bool            IsAllSelected() const
59                         { return nSelCount == aTotRange.Len(); }
GetSelectCount() const60     sal_Int32       GetSelectCount() const { return nSelCount; }
61 
62     void            SetTotalRange( const Range& rTotRange );
63     void            Insert( sal_Int32 nIndex, sal_Int32 nCount = 1 );
64     void            Remove( sal_Int32 nIndex );
65     void            Reset();
66 
GetTotalRange() const67     const Range&    GetTotalRange() const { return aTotRange; }
68     sal_Int32       FirstSelected();
69     sal_Int32       LastSelected();
70     sal_Int32       NextSelected();
71 
GetRangeCount() const72     sal_Int32       GetRangeCount() const { return aSels.size(); }
GetRange(sal_Int32 nRange) const73     const Range&    GetRange( sal_Int32 nRange ) const { return aSels[nRange]; }
74 };
75 
76 class SAL_WARN_UNUSED TOOLS_DLLPUBLIC StringRangeEnumerator
77 {
78     struct Range
79     {
80         sal_Int32   nFirst;
81         sal_Int32   nLast;
82 
RangeStringRangeEnumerator::Range83         Range( sal_Int32 i_nFirst, sal_Int32 i_nLast ) : nFirst( i_nFirst ), nLast( i_nLast ) {}
84     };
85     std::vector< StringRangeEnumerator::Range >            maSequence;
86     sal_Int32                                              mnCount;
87     sal_Int32                                              mnMin;
88     sal_Int32                                              mnMax;
89     sal_Int32                                              mnOffset;
90     bool                                                   mbValidInput;
91 
92     bool setRange( const OUString& i_rNewRange );
93     bool insertRange( sal_Int32 nFirst, sal_Int32 nLast, bool bSequence );
94     void insertJoinedRanges( const std::vector< sal_Int32 >& rNumbers );
95     bool checkValue( sal_Int32, const o3tl::sorted_vector< sal_Int32 >* i_pPossibleValues = nullptr ) const;
96 public:
97     class TOOLS_DLLPUBLIC Iterator
98     {
99         const StringRangeEnumerator*      pEnumerator;
100         const o3tl::sorted_vector< sal_Int32 >* pPossibleValues;
101         sal_Int32                         nRangeIndex;
102         sal_Int32                         nCurrent;
103 
104         friend class StringRangeEnumerator;
Iterator(const StringRangeEnumerator * i_pEnum,const o3tl::sorted_vector<sal_Int32> * i_pPossibleValues,sal_Int32 i_nRange,sal_Int32 i_nCurrent)105         Iterator( const StringRangeEnumerator* i_pEnum,
106                   const o3tl::sorted_vector< sal_Int32 >* i_pPossibleValues,
107                   sal_Int32 i_nRange,
108                   sal_Int32 i_nCurrent )
109         : pEnumerator( i_pEnum ), pPossibleValues( i_pPossibleValues )
110         , nRangeIndex( i_nRange ), nCurrent( i_nCurrent ) {}
111 
112     public:
113         Iterator& operator++();
operator *() const114         sal_Int32 operator*() const { return nCurrent;}
115         bool operator==(const Iterator&) const;
operator !=(const Iterator & i_rComp) const116         bool operator!=(const Iterator& i_rComp) const
117         { return ! (*this == i_rComp); }
118     };
119 
120     friend class StringRangeEnumerator::Iterator;
121 
122     StringRangeEnumerator( const OUString& i_rInput,
123                            sal_Int32 i_nMinNumber,
124                            sal_Int32 i_nMaxNumber,
125                            sal_Int32 i_nLogicalOffset = -1
126                            );
127 
size() const128     sal_Int32 size() const { return mnCount; }
129     Iterator begin( const o3tl::sorted_vector< sal_Int32 >* i_pPossibleValues = nullptr ) const;
130     Iterator end( const o3tl::sorted_vector< sal_Int32 >* i_pPossibleValues = nullptr ) const;
131 
132     bool hasValue( sal_Int32 nValue, const o3tl::sorted_vector< sal_Int32 >* i_pPossibleValues = nullptr ) const;
133 
134     /**
135     i_rPageRange:     the string to be changed into a sequence of numbers
136                       valid format example "5-3,9,9,7-8" ; instead of ',' ';' or ' ' are allowed as well
137     o_rPageVector:    the output sequence of numbers
138     i_nLogicalOffset: an offset to be applied to each number in the string before inserting it in the resulting sequence
139                       example: a user enters page numbers from 1 to n (since that is logical)
140                                of course usable page numbers in code would start from 0 and end at n-1
141                                so the logical offset would be -1
142     i_nMinNumber:     the minimum allowed number
143     i_nMaxNumber:     the maximum allowed number
144 
145     @returns: true if the input string was valid, o_rPageVector will contain the resulting sequence
146               false if the input string was invalid, o_rPageVector will contain
147                     the sequence that parser is able to extract
148 
149     behavior:
150     - only non-negative sequence numbers are allowed
151     - only non-negative values in the input string are allowed
152     - the string "-3" means the sequence i_nMinNumber to 3
153     - the string "3-" means the sequence 3 to i_nMaxNumber
154     - the string "-" means the sequence i_nMinNumber to i_nMaxNumber
155     - single number that doesn't fit in [i_nMinNumber,i_nMaxNumber] will be ignored
156     - range that doesn't fit in [i_nMinNumber,i_nMaxNumber] will be adjusted
157     */
158     static bool getRangesFromString( const OUString& i_rPageRange,
159                                      std::vector< sal_Int32 >& o_rPageVector,
160                                      sal_Int32 i_nMinNumber,
161                                      sal_Int32 i_nMaxNumber,
162                                      sal_Int32 i_nLogicalOffset = -1,
163                                      o3tl::sorted_vector< sal_Int32 > const * i_pPossibleValues = nullptr
164                                     );
165 };
166 
167 #endif
168 
169 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
170