1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef SD_SLIDESORTER_PAGE_SELECTOR_HXX
25 #define SD_SLIDESORTER_PAGE_SELECTOR_HXX
26 
27 #include "model/SlsSharedPageDescriptor.hxx"
28 
29 #include <com/sun/star/drawing/XDrawPage.hpp>
30 #include <vector>
31 #include <memory>
32 #include <boost/noncopyable.hpp>
33 
34 
35 class SdPage;
36 
37 namespace sd { namespace slidesorter {
38 class SlideSorter;
39 } }
40 
41 namespace sd { namespace slidesorter { namespace model {
42 class SlideSorterModel;
43 } } }
44 
45 namespace sd { namespace slidesorter { namespace view {
46 class SlideSorterView;
47 } } }
48 
49 namespace sd { namespace slidesorter { namespace controller {
50 
51 class SlideSorterController;
52 
53 
54 /** A sub-controller that handles page selection of the slide browser.
55     Selecting a page does not make it the current page (of the main view)
56     automatically as this would not be desired in a multi selection.  This
57     has to be done explicitly by calling the
58     CurrentSlideManager::SetCurrentSlide() method.
59 
60     Indices of pages relate always to the number of all pages in the model
61     (as returned by GetPageCount()) not just the selected pages.
62 */
63 class PageSelector : private ::boost::noncopyable
64 {
65 public:
66     PageSelector (SlideSorter& rSlideSorter);
67 
68     void SelectAllPages (void);
69     void DeselectAllPages (void);
70 
71     /** Update the selection state of all page descriptors to be the same as
72         that of the corresponding pages of the SdPage objects and issue
73         redraw requests where necessary.
74     */
75     void GetCoreSelection (void);
76 
77     /** Update the selection state of the SdPage objects to be the same as
78         that of the corresponding page descriptors.
79     */
80     void SetCoreSelection (void);
81 
82     /** Select the specified descriptor.  The selection state of the other
83         descriptors is not affected.
84     */
85     void SelectPage (int nPageIndex);
86     /** Select the descriptor that is associated with the given page.  The
87         selection state of the other descriptors is not affected.
88     */
89     void SelectPage (const SdPage* pPage);
90     /** Select the specified descriptor.  The selection state of the other
91         descriptors is not affected.
92     */
93     void SelectPage (const model::SharedPageDescriptor& rpDescriptor);
94 
95     /** Return whether the specified page is selected.  This convenience
96         method is a substitute for
97         SlideSorterModel::GetPageDescriptor(i)->IsSelected() is included
98         here to make this class more self contained.
99     */
100     bool IsPageSelected (int nPageIndex);
101 
102     /** Deselect the descriptor that is associated with the given page.
103         @param bUpdateCurrentPage
104             When <TRUE/> then the current page is updated to the first slide
105             of the remaining selection.
106     */
107     void DeselectPage (
108         int nPageIndex,
109         const bool bUpdateCurrentPage = true);
110     void DeselectPage (
111         const SdPage* pPage,
112         const bool bUpdateCurrentPage = true);
113     void DeselectPage (
114         const model::SharedPageDescriptor& rpDescriptor,
115         const bool bUpdateCurrentPage = true);
116 
117     /** This convenience method returns the same number of pages that
118         SlideSorterModel.GetPageCount() returns.  It is included here so
119         that it is self contained for iterating over all pages to select or
120         deselect them.
121     */
122     int GetPageCount (void) const;
123     int GetSelectedPageCount (void) const;
124 
125     /** Return the anchor for a range selection.  This usually is the first
126         selected page after all pages have been deselected.
127         @return
128             The returned anchor may be NULL.
129     */
130     model::SharedPageDescriptor GetSelectionAnchor (void) const;
131 
132 
133     typedef ::std::vector<SdPage*> PageSelection;
134 
135     /** Return an object that describes the current selection.  The caller
136         can use that object to later restore the selection.
137         @return
138             The object returned describes the selection via indices.  So
139             even if pages are exchanged a later call to SetPageSelection()
140             is valid.
141     */
142     ::boost::shared_ptr<PageSelection> GetPageSelection (void) const;
143 
144     /** Restore a page selection according to the given selection object.
145         @param rSelection
146             Typically obtained by calling GetPageSelection() this object
147             is used to restore the selection.  If pages were exchanged since
148             the last call to GetPageSelection() it is still valid to call
149             this method with the selection.  When pages have been inserted
150             or removed the result may be unexpected.
151         @param bUpdateCurrentPage
152             When <TRUE/> (the default value) then after setting the
153             selection update the current page to the first page of the
154             selection.
155             When called from within UpdateCurrentPage() then this flag is
156             used to prevent a recursion loop.
157     */
158     void SetPageSelection (
159         const ::boost::shared_ptr<PageSelection>& rSelection,
160         const bool bUpdateCurrentPage = true);
161 
162     /** Call this method after the model has changed to set the number
163         of selected pages.
164     */
165     void CountSelectedPages (void);
166 
167     /** Use the UpdateLock whenever you do a complex selection, i.e. call
168         more than one method in a row.  An active lock prevents intermediate
169         changes of the current slide.
170     */
171     class UpdateLock
172     {
173     public:
174         UpdateLock (SlideSorter& rSlideSorter);
175         UpdateLock (PageSelector& rPageSelector);
176         ~UpdateLock (void);
177         void Release (void);
178     private:
179         PageSelector* mpSelector;
180     };
181 
182     class BroadcastLock
183     {
184     public:
185         BroadcastLock (SlideSorter& rSlideSorter);
186         BroadcastLock (PageSelector& rPageSelector);
187         ~BroadcastLock (void);
188     private:
189         PageSelector& mrSelector;
190     };
191 
192 private:
193     model::SlideSorterModel& mrModel;
194     SlideSorter& mrSlideSorter;
195     SlideSorterController& mrController;
196     int mnSelectedPageCount;
197     int mnBroadcastDisableLevel;
198     bool mbSelectionChangeBroadcastPending;
199     model::SharedPageDescriptor mpMostRecentlySelectedPage;
200     /// Anchor for a range selection.
201     model::SharedPageDescriptor mpSelectionAnchor;
202     model::SharedPageDescriptor mpCurrentPage;
203     sal_Int32 mnUpdateLockCount;
204     bool mbIsUpdateCurrentPagePending;
205 
206     /** Enable the broadcasting of selection change events.  This calls the
207         SlideSorterController::SelectionHasChanged() method to do the actual
208         work.  When EnableBroadcasting has been called as many times as
209         DisableBroadcasting() was called before and the selection has been
210         changed in the mean time, this change will be broadcasted.
211     */
212     void EnableBroadcasting (void);
213 
214     /** Disable the broadcasting of selection change events.  Subsequent
215         changes of the selection will set a flag that triggers the sending
216         of events when EnableBroadcasting() is called.
217     */
218     void DisableBroadcasting (void);
219 
220     void UpdateCurrentPage (const bool bUpdateOnlyWhenPending = false);
221 
222     void CheckConsistency (void) const;
223 };
224 
225 } } } // end of namespace ::sd::slidesorter::controller
226 
227 #endif
228