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 #include "precompiled_sd.hxx"
25 
26 #include "controller/SlsInsertionIndicatorHandler.hxx"
27 #include "controller/SlsProperties.hxx"
28 #include "view/SlideSorterView.hxx"
29 #include "view/SlsLayouter.hxx"
30 #include "view/SlsInsertionIndicatorOverlay.hxx"
31 #include "model/SlideSorterModel.hxx"
32 #include "model/SlsPageEnumerationProvider.hxx"
33 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
34 
35 #include "SlideSorter.hxx"
36 
37 using namespace ::com::sun::star::datatransfer::dnd::DNDConstants;
38 
39 namespace sd { namespace slidesorter { namespace controller {
40 
41 
InsertionIndicatorHandler(SlideSorter & rSlideSorter)42 InsertionIndicatorHandler::InsertionIndicatorHandler (SlideSorter& rSlideSorter)
43     : mrSlideSorter(rSlideSorter),
44       mpInsertAnimator(),
45       mpInsertionIndicatorOverlay(new view::InsertionIndicatorOverlay(rSlideSorter)),
46       maInsertPosition(),
47       meMode(MoveMode),
48       mbIsActive(false),
49       mbIsReadOnly(mrSlideSorter.GetModel().IsReadOnly()),
50       mbIsOverSourceView(true),
51       maIconSize(0,0),
52       mbIsForcedShow(false)
53 {
54 }
55 
56 
57 
58 
~InsertionIndicatorHandler(void)59 InsertionIndicatorHandler::~InsertionIndicatorHandler (void)
60 {
61 }
62 
63 
64 
65 
Start(const bool bIsOverSourceView)66 void InsertionIndicatorHandler::Start (const bool bIsOverSourceView)
67 {
68     if (mbIsActive)
69     {
70         OSL_ASSERT(!mbIsActive);
71     }
72 
73     mbIsReadOnly = mrSlideSorter.GetModel().IsReadOnly();
74     if (mbIsReadOnly)
75         return;
76 
77     mbIsActive = true;
78     mbIsOverSourceView = bIsOverSourceView;
79 }
80 
81 
82 
83 
End(const controller::Animator::AnimationMode eMode)84 void InsertionIndicatorHandler::End (const controller::Animator::AnimationMode eMode)
85 {
86     if (mbIsForcedShow ||  ! mbIsActive || mbIsReadOnly)
87         return;
88 
89     GetInsertAnimator()->Reset(eMode);
90 
91     mbIsActive = false;
92     //    maInsertPosition = view::InsertPosition();
93     meMode = UnknownMode;
94 
95     mpInsertionIndicatorOverlay->Hide();
96     mpInsertionIndicatorOverlay.reset(new view::InsertionIndicatorOverlay(mrSlideSorter));
97 }
98 
99 
100 
101 
ForceShow(void)102 void InsertionIndicatorHandler::ForceShow (void)
103 {
104     mbIsForcedShow = true;
105 }
106 
107 
108 
109 
ForceEnd(void)110 void InsertionIndicatorHandler::ForceEnd (void)
111 {
112     mbIsForcedShow = false;
113     End(Animator::AM_Immediate);
114 }
115 
116 
117 
118 
UpdateIndicatorIcon(const SdTransferable * pTransferable)119 void InsertionIndicatorHandler::UpdateIndicatorIcon (const SdTransferable* pTransferable)
120 {
121     mpInsertionIndicatorOverlay->Create(pTransferable);
122     maIconSize = mpInsertionIndicatorOverlay->GetSize();
123 }
124 
125 
126 
127 
GetModeFromDndAction(const sal_Int8 nDndAction)128 InsertionIndicatorHandler::Mode InsertionIndicatorHandler::GetModeFromDndAction (
129     const sal_Int8 nDndAction)
130 {
131     if ((nDndAction & ACTION_MOVE) != 0)
132         return MoveMode;
133     else if ((nDndAction & ACTION_COPY) != 0)
134         return CopyMode;
135     else
136         return UnknownMode;
137 }
138 
139 
140 
141 
UpdatePosition(const Point & rMouseModelPosition,const Mode eMode)142 void InsertionIndicatorHandler::UpdatePosition (
143     const Point& rMouseModelPosition,
144     const Mode eMode)
145 {
146     if ( ! mbIsActive)
147         return;
148 
149     if (mbIsReadOnly)
150         return;
151 
152     SetPosition(rMouseModelPosition, eMode);
153 }
154 
155 
156 
157 
UpdatePosition(const Point & rMouseModelPosition,const sal_Int8 nDndAction)158 void InsertionIndicatorHandler::UpdatePosition (
159     const Point& rMouseModelPosition,
160     const sal_Int8 nDndAction)
161 {
162     UpdatePosition(rMouseModelPosition, GetModeFromDndAction(nDndAction));
163 }
164 
165 
166 
167 
IsActive(void) const168 bool InsertionIndicatorHandler::IsActive (void) const
169 {
170     return mbIsActive;
171 }
172 
173 
174 
175 
GetInsertionPageIndex(void) const176 sal_Int32 InsertionIndicatorHandler::GetInsertionPageIndex (void) const
177 {
178     if (mbIsReadOnly)
179         return -1;
180     else
181         return maInsertPosition.GetIndex();
182 }
183 
184 
185 
186 
SetPosition(const Point & rPoint,const Mode eMode)187 void InsertionIndicatorHandler::SetPosition (
188     const Point& rPoint,
189     const Mode eMode)
190 {
191     view::Layouter& rLayouter (mrSlideSorter.GetView().GetLayouter());
192 
193     const view::InsertPosition aInsertPosition (rLayouter.GetInsertPosition(
194         rPoint,
195         maIconSize,
196         mrSlideSorter.GetModel()));
197 
198     static sal_Int32 TargetIndex (1);
199     if (aInsertPosition.GetIndex() == TargetIndex)
200     {
201         const view::InsertPosition aPosition (rLayouter.GetInsertPosition(
202             rPoint,
203             maIconSize,
204             mrSlideSorter.GetModel()));
205         const view::InsertPosition aPosition2 (rLayouter.GetInsertPosition(
206             rPoint,
207             maIconSize,
208             mrSlideSorter.GetModel()));
209     }
210 
211     if (maInsertPosition != aInsertPosition
212         || meMode != eMode
213         //        || ! mpInsertionIndicatorOverlay->IsVisible()
214         )
215     {
216         maInsertPosition = aInsertPosition;
217         meMode = eMode;
218         mbIsInsertionTrivial = IsInsertionTrivial(maInsertPosition.GetIndex(), eMode);
219         if (maInsertPosition.GetIndex()>=0 && ! mbIsInsertionTrivial)
220         {
221             mpInsertionIndicatorOverlay->SetLocation(maInsertPosition.GetLocation());
222 
223             GetInsertAnimator()->SetInsertPosition(maInsertPosition);
224             mpInsertionIndicatorOverlay->Show();
225         }
226         else
227         {
228             GetInsertAnimator()->Reset(Animator::AM_Animated);
229             mpInsertionIndicatorOverlay->Hide();
230         }
231     }
232 }
233 
234 
235 
236 
GetInsertAnimator(void)237 ::boost::shared_ptr<view::InsertAnimator> InsertionIndicatorHandler::GetInsertAnimator (void)
238 {
239     if ( ! mpInsertAnimator)
240         mpInsertAnimator.reset(new view::InsertAnimator(mrSlideSorter));
241     return mpInsertAnimator;
242 }
243 
244 
245 
246 
IsInsertionTrivial(const sal_Int32 nInsertionIndex,const Mode eMode) const247 bool InsertionIndicatorHandler::IsInsertionTrivial (
248     const sal_Int32 nInsertionIndex,
249     const Mode eMode) const
250 {
251     if (eMode == CopyMode)
252         return false;
253     else if (eMode == UnknownMode)
254         return true;
255 
256     if ( ! mbIsOverSourceView)
257         return false;
258 
259     // Iterate over all selected pages and check whether there are
260     // holes.  While we do this we remember the indices of the first and
261     // last selected page as preparation for the next step.
262     sal_Int32 nCurrentIndex = -1;
263     sal_Int32 nFirstIndex = -1;
264     sal_Int32 nLastIndex = -1;
265     model::PageEnumeration aSelectedPages (
266         model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
267             mrSlideSorter.GetModel()));
268     while (aSelectedPages.HasMoreElements())
269     {
270         model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
271 
272         // Get the page number and compare it to the last one.
273         const sal_Int32 nPageNumber (pDescriptor->GetPageIndex());
274         if (nCurrentIndex>=0 && nPageNumber>(nCurrentIndex+1))
275             return false;
276         else
277             nCurrentIndex = nPageNumber;
278 
279         // Remember indices of the first and last page of the selection.
280         if (nFirstIndex == -1)
281             nFirstIndex = nPageNumber;
282         nLastIndex = nPageNumber;
283     }
284 
285     // When we come here then the selection has no holes.  We still have
286     // to check that the insertion position is not directly in front or
287     // directly behind the selection and thus moving the selection there
288     // would not change the model.
289     if (nInsertionIndex<nFirstIndex || nInsertionIndex>(nLastIndex+1))
290         return false;
291 
292     return true;
293 }
294 
295 
296 
297 
IsInsertionTrivial(const sal_Int8 nDndAction)298 bool InsertionIndicatorHandler::IsInsertionTrivial (const sal_Int8 nDndAction)
299 {
300     return IsInsertionTrivial(GetInsertionPageIndex(), GetModeFromDndAction(nDndAction));
301 }
302 
303 
304 
305 
306 //===== InsertionIndicatorHandler::ForceShowContext ===========================
307 
ForceShowContext(const::boost::shared_ptr<InsertionIndicatorHandler> & rpHandler)308 InsertionIndicatorHandler::ForceShowContext::ForceShowContext (
309     const ::boost::shared_ptr<InsertionIndicatorHandler>& rpHandler)
310     : mpHandler(rpHandler)
311 {
312     mpHandler->ForceShow();
313 }
314 
315 
316 
317 
~ForceShowContext(void)318 InsertionIndicatorHandler::ForceShowContext::~ForceShowContext (void)
319 {
320     mpHandler->ForceEnd();
321 }
322 
323 } } } // end of namespace ::sd::slidesorter::controller
324