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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sd.hxx"
26 
27 #include "ViewShellImplementation.hxx"
28 
29 #include "sdpage.hxx"
30 #include "drawdoc.hxx"
31 #include "sdresid.hxx"
32 #include "glob.hrc"
33 #include "app.hrc"
34 #include "strings.hrc"
35 #include "strings.hrc"
36 #include "helpids.h"
37 #include "sdattr.hxx"
38 #include "sdabstdlg.hxx"
39 #include "unmodpg.hxx"
40 #include "Window.hxx"
41 #include "optsitem.hxx"
42 #include "DrawDocShell.hxx"
43 #include "DrawController.hxx"
44 #include "FactoryIds.hxx"
45 #include "slideshow.hxx"
46 #include "ViewShellBase.hxx"
47 #include "FrameView.hxx"
48 #include "DrawViewShell.hxx"
49 #include "ViewShellHint.hxx"
50 #include "SidebarPanelId.hxx"
51 #include "framework/FrameworkHelper.hxx"
52 
53 #include <sfx2/bindings.hxx>
54 #include <sfx2/dispatch.hxx>
55 #include <sfx2/request.hxx>
56 #include <svl/aeitem.hxx>
57 #include <svx/imapdlg.hxx>
58 #include <vcl/msgbox.hxx>
59 #include <basic/sbstar.hxx>
60 #include "undo/undoobjects.hxx"
61 
62 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
63 
64 using namespace ::com::sun::star::uno;
65 using namespace ::com::sun::star::drawing::framework;
66 using ::sd::framework::FrameworkHelper;
67 
68 namespace sd {
69 
70 ViewShell::Implementation::Implementation (ViewShell& rViewShell)
71     : mbIsShowingUIControls(false),
72       mbIsMainViewShell(false),
73       mbIsInitialized(false),
74       mbArrangeActive(false),
75       mpSubShellFactory(),
76       mpUpdateLockForMouse(),
77       mrViewShell(rViewShell)
78 {
79 }
80 
81 
82 
83 
84 ViewShell::Implementation::~Implementation (void)
85 {
86     if ( ! mpUpdateLockForMouse.expired())
87     {
88         ::boost::shared_ptr<ToolBarManagerLock> pLock(mpUpdateLockForMouse);
89         if (pLock.get() != NULL)
90         {
91             // Force the ToolBarManagerLock to be released even when the
92             // IsUICaptured() returns <TRUE/>.
93             pLock->Release(true);
94         }
95     }
96 }
97 
98 
99 
100 
101 void ViewShell::Implementation::ProcessModifyPageSlot (
102     SfxRequest& rRequest,
103     SdPage* pCurrentPage,
104     PageKind ePageKind)
105 {
106     SdDrawDocument* pDocument = mrViewShell.GetDoc();
107     SdrLayerAdmin& rLayerAdmin = pDocument->GetLayerAdmin();
108     sal_uInt8 aBckgrnd = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), sal_False);
109     sal_uInt8 aBckgrndObj = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), sal_False);
110     SetOfByte aVisibleLayers;
111     sal_Bool bHandoutMode = sal_False;
112     SdPage* pHandoutMPage = NULL;
113     String aNewName;
114 
115     // #95981#
116     String aOldName;
117 
118     AutoLayout aNewAutoLayout;
119 
120     sal_Bool bBVisible;
121     sal_Bool bBObjsVisible;
122     const SfxItemSet* pArgs = rRequest.GetArgs();
123 
124     if (pCurrentPage != NULL && pCurrentPage->TRG_HasMasterPage())
125         aVisibleLayers = pCurrentPage->TRG_GetMasterPageVisibleLayers();
126     else
127         aVisibleLayers.SetAll();
128 
129     do
130     {
131         if (pCurrentPage == NULL)
132             break;
133 
134         if (!pArgs || pArgs->Count() == 1 || pArgs->Count() == 2 )
135         {
136             if (pArgs && pArgs->Count() == 2)
137             {
138                 // We have been called with a request that contains two
139                 // arguments.  One was used as preselected layout in a
140                 // dialog.  We could select that layout in the
141                 // layout panel instead.
142                 /*
143                     SFX_REQUEST_ARG (rRequest, pNewAutoLayout, SfxUInt32Item, ID_VAL_WHATLAYOUT, sal_False);
144                     eNewAutoLayout = (AutoLayout) pNewAutoLayout->GetValue
145                     ();
146                 */
147             }
148 
149             // Make the layout menu visible in the tool pane.
150             SfxBoolItem aMakeToolPaneVisible (ID_VAL_ISVISIBLE, sal_True);
151             SfxUInt32Item aPanelId (ID_VAL_PANEL_INDEX, sidebar::PID_LAYOUT);
152             SfxViewFrame* pFrame = mrViewShell.GetViewFrame();
153             if (pFrame!=NULL && pFrame->GetDispatcher()!=NULL)
154             {
155                 pFrame->GetDispatcher()->Execute (
156                     SID_SHOW_TOOL_PANEL,
157                     SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
158                     &aMakeToolPaneVisible,
159                     &aPanelId,
160                     NULL);
161             }
162             else
163             {
164                 DBG_ASSERT(pFrame!=NULL && pFrame->GetDispatcher()!=NULL,
165                     "ViewShell::Implementation::ProcessModifyPageSlot(): can not get dispatcher");
166             }
167 
168             // We have activated a non-modal control in the task pane.
169             // Because it does not return anything we can not do anything
170             // more right now and have to exit here.
171             break;
172         }
173         else if (pArgs->Count() == 4)
174         {
175             SFX_REQUEST_ARG (rRequest, pNewName, SfxStringItem, ID_VAL_PAGENAME, sal_False);
176             SFX_REQUEST_ARG (rRequest, pNewAutoLayout, SfxUInt32Item, ID_VAL_WHATLAYOUT, sal_False);
177             SFX_REQUEST_ARG (rRequest, pBVisible, SfxBoolItem, ID_VAL_ISPAGEBACK, sal_False);
178             SFX_REQUEST_ARG (rRequest, pBObjsVisible, SfxBoolItem, ID_VAL_ISPAGEOBJ, sal_False);
179             AutoLayout aLayout ((AutoLayout)pNewAutoLayout->GetValue ());
180             if (aLayout >= AUTOLAYOUT__START
181                 && aLayout < AUTOLAYOUT__END)
182             {
183                 aNewName		= pNewName->GetValue ();
184                 aNewAutoLayout = (AutoLayout) pNewAutoLayout->GetValue ();
185                 bBVisible		= pBVisible->GetValue ();
186                 bBObjsVisible	= pBObjsVisible->GetValue ();
187             }
188             else
189             {
190                 StarBASIC::FatalError (SbERR_BAD_PROP_VALUE);
191                 rRequest.Ignore ();
192                 break;
193             }
194             if (ePageKind == PK_HANDOUT)
195             {
196                 bHandoutMode = sal_True;
197                 pHandoutMPage = pDocument->GetMasterSdPage(0, PK_HANDOUT);
198             }
199         }
200         else
201         {
202             StarBASIC::FatalError (SbERR_WRONG_ARGS);
203             rRequest.Ignore ();
204             break;
205         }
206 
207         SdPage* pUndoPage =
208             bHandoutMode ? pHandoutMPage : pCurrentPage;
209 
210         ::svl::IUndoManager* pUndoManager = mrViewShell.GetDocSh()->GetUndoManager();
211         DBG_ASSERT(pUndoManager, "No UNDO MANAGER ?!?");
212 
213 		if( pUndoManager )
214 		{
215 			String aComment( SdResId(STR_UNDO_MODIFY_PAGE) );
216 			pUndoManager->EnterListAction(aComment, aComment);
217 			ModifyPageUndoAction* pAction = new ModifyPageUndoAction(
218 				pDocument, pUndoPage, aNewName, aNewAutoLayout, bBVisible, bBObjsVisible);
219 			pUndoManager->AddUndoAction(pAction);
220 
221 			// Clear the selection because the selectec object may be removed as
222 			// a result of the ssignment of the layout.
223 			mrViewShell.GetDrawView()->UnmarkAll();
224 
225 			if (!bHandoutMode)
226 			{
227 				if (pCurrentPage->GetName() != aNewName)
228 				{
229 					pCurrentPage->SetName(aNewName);
230 
231 					if (ePageKind == PK_STANDARD)
232 					{
233 						sal_uInt16 nPage = (pCurrentPage->GetPageNum()-1) / 2;
234 						SdPage* pNotesPage = pDocument->GetSdPage(nPage, PK_NOTES);
235 						if (pNotesPage != NULL)
236 							pNotesPage->SetName(aNewName);
237 					}
238 				}
239 
240 				pCurrentPage->SetAutoLayout(aNewAutoLayout, sal_True);
241 
242 				aBckgrnd = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), sal_False);
243 				aBckgrndObj = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), sal_False);
244 				aVisibleLayers.Set(aBckgrnd, bBVisible);
245 				aVisibleLayers.Set(aBckgrndObj, bBObjsVisible);
246 				pCurrentPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers);
247 			}
248 			else
249 			{
250 				pHandoutMPage->SetAutoLayout(aNewAutoLayout, sal_True);
251 			}
252 
253 			mrViewShell.GetViewFrame()->GetDispatcher()->Execute(SID_SWITCHPAGE,
254 				SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD);
255 
256 			sal_Bool bSetModified = sal_True;
257 
258 			if (pArgs && pArgs->Count() == 1)
259 			{
260 				bSetModified = (sal_Bool) ((SfxBoolItem&) pArgs->Get(SID_MODIFYPAGE)).GetValue();
261 			}
262 
263 			pUndoManager->AddUndoAction( new UndoAutoLayoutPosAndSize( *pUndoPage ) );
264 			pUndoManager->LeaveListAction();
265 
266 			pDocument->SetChanged(bSetModified);
267         }
268     }
269     while (false);
270 
271     mrViewShell.Cancel();
272     rRequest.Done ();
273 }
274 
275 void ViewShell::Implementation::AssignLayout ( SfxRequest& rRequest, PageKind ePageKind )
276 {
277     const SfxUInt32Item* pWhatPage = static_cast< const SfxUInt32Item*  > ( rRequest.GetArg( ID_VAL_WHATPAGE, sal_False, TYPE(SfxUInt32Item) ) );
278     const SfxUInt32Item* pWhatLayout = static_cast< const SfxUInt32Item*  > ( rRequest.GetArg( ID_VAL_WHATLAYOUT, sal_False, TYPE(SfxUInt32Item) ) );
279 
280     SdDrawDocument* pDocument = mrViewShell.GetDoc();
281 	if( !pDocument )
282 		return;
283 
284     SdPage* pPage = 0;
285     if( pWhatPage )
286     {
287 		pPage = pDocument->GetSdPage(static_cast<sal_uInt16>(pWhatPage->GetValue()), ePageKind);
288     }
289 
290     if( pPage == 0 )
291         pPage = mrViewShell.getCurrentPage();
292 
293     if( pPage )
294     {
295         AutoLayout eLayout = pPage->GetAutoLayout();
296 
297         if( pWhatLayout )
298             eLayout = static_cast< AutoLayout >( pWhatLayout->GetValue() );
299 
300         // Transform the given request into the four argument form that is
301         // understood by ProcessModifyPageSlot().
302         SdrLayerAdmin& rLayerAdmin (mrViewShell.GetViewShellBase().GetDocument()->GetLayerAdmin());
303         sal_uInt8 aBackground (rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), sal_False));
304         sal_uInt8 aBackgroundObject (rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), sal_False));
305 
306         SetOfByte aVisibleLayers;
307 
308 		if( pPage->GetPageKind() == PK_HANDOUT )
309 			aVisibleLayers.SetAll();
310 		else
311 			aVisibleLayers = pPage->TRG_GetMasterPageVisibleLayers();
312 
313 		SfxRequest aRequest (mrViewShell.GetViewShellBase().GetViewFrame(), SID_MODIFYPAGE);
314         aRequest.AppendItem(SfxStringItem (ID_VAL_PAGENAME, pPage->GetName()));
315         aRequest.AppendItem(SfxUInt32Item (ID_VAL_WHATLAYOUT, eLayout));
316         aRequest.AppendItem(SfxBoolItem(ID_VAL_ISPAGEBACK, aVisibleLayers.IsSet(aBackground)));
317         aRequest.AppendItem(SfxBoolItem(ID_VAL_ISPAGEOBJ, aVisibleLayers.IsSet(aBackgroundObject)));
318 
319         // Forward the call with the new arguments.
320         ProcessModifyPageSlot( aRequest, pPage, pPage->GetPageKind());
321     }
322 }
323 
324 
325 
326 
327 sal_uInt16 ViewShell::Implementation::GetViewId (void)
328 {
329     switch (mrViewShell.GetShellType())
330     {
331         case ViewShell::ST_IMPRESS:
332         case ViewShell::ST_NOTES:
333         case ViewShell::ST_HANDOUT:
334             return IMPRESS_FACTORY_ID;
335 
336         case ViewShell::ST_DRAW:
337             return DRAW_FACTORY_ID;
338 
339         case ViewShell::ST_OUTLINE:
340             return OUTLINE_FACTORY_ID;
341 
342         case ViewShell::ST_SLIDE_SORTER:
343             return SLIDE_SORTER_FACTORY_ID;
344 
345         case ViewShell::ST_PRESENTATION:
346             return PRESENTATION_FACTORY_ID;
347 
348         // Since we have to return a view id for every possible shell type
349         // and there is not (yet) a proper ViewShellBase sub class for the
350         // remaining types we chose the Impress factory as a fall back.
351         case ViewShell::ST_SIDEBAR:
352         case ViewShell::ST_NONE:
353         default:
354             return IMPRESS_FACTORY_ID;
355     }
356 }
357 
358 
359 
360 
361 SvxIMapDlg* ViewShell::Implementation::GetImageMapDialog (void)
362 {
363     SvxIMapDlg* pDialog = NULL;
364     SfxChildWindow* pChildWindow = SfxViewFrame::Current()->GetChildWindow(
365         SvxIMapDlgChildWindow::GetChildWindowId());
366     if (pChildWindow != NULL)
367         pDialog = dynamic_cast<SvxIMapDlg*>(pChildWindow->GetWindow());
368     return pDialog;
369 }
370 
371 
372 
373 //===== ToolBarManagerLock ====================================================
374 
375 class ViewShell::Implementation::ToolBarManagerLock::Deleter { public:
376     void operator() (ToolBarManagerLock* pObject) { delete pObject; }
377 };
378 
379 ::boost::shared_ptr<ViewShell::Implementation::ToolBarManagerLock>
380     ViewShell::Implementation::ToolBarManagerLock::Create (
381         const ::boost::shared_ptr<ToolBarManager>& rpManager)
382 {
383     ::boost::shared_ptr<ToolBarManagerLock> pLock (
384         new ViewShell::Implementation::ToolBarManagerLock(rpManager),
385         ViewShell::Implementation::ToolBarManagerLock::Deleter());
386     pLock->mpSelf = pLock;
387     return pLock;
388 }
389 
390 
391 
392 
393 ViewShell::Implementation::ToolBarManagerLock::ToolBarManagerLock (
394     const ::boost::shared_ptr<ToolBarManager>& rpManager)
395     : mpLock(new ToolBarManager::UpdateLock(rpManager)),
396       maTimer()
397 {
398     // Start a timer that will unlock the ToolBarManager update lock when
399     // that is not done explicitly by calling Release().
400     maTimer.SetTimeoutHdl(LINK(this,ToolBarManagerLock,TimeoutCallback));
401     maTimer.SetTimeout(100);
402     maTimer.Start();
403 }
404 
405 
406 
407 
408 IMPL_LINK(ViewShell::Implementation::ToolBarManagerLock,TimeoutCallback,Timer*,EMPTYARG)
409 {
410     // If possible then release the lock now.  Otherwise start the timer
411     // and try again later.
412     if (Application::IsUICaptured())
413     {
414         maTimer.Start();
415     }
416     else
417     {
418         mpSelf.reset();
419     }
420     return 0;
421 }
422 
423 
424 
425 
426 void ViewShell::Implementation::ToolBarManagerLock::Release (bool bForce)
427 {
428     // If possible then release the lock now.  Otherwise try again when the
429     // timer expires.
430     if (bForce || ! Application::IsUICaptured())
431     {
432         mpSelf.reset();
433     }
434 }
435 
436 
437 
438 
439 ViewShell::Implementation::ToolBarManagerLock::~ToolBarManagerLock (void)
440 {
441     mpLock.reset();
442 }
443 
444 } // end of namespace sd
445