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 "taskpane/PanelId.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,
152                 ::sd::toolpanel::PID_LAYOUT);
153             SfxViewFrame* pFrame = mrViewShell.GetViewFrame();
154             if (pFrame!=NULL && pFrame->GetDispatcher()!=NULL)
155             {
156                 pFrame->GetDispatcher()->Execute (
157                     SID_SHOW_TOOL_PANEL,
158                     SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
159                     &aMakeToolPaneVisible,
160                     &aPanelId,
161                     NULL);
162             }
163             else
164             {
165                 DBG_ASSERT(pFrame!=NULL && pFrame->GetDispatcher()!=NULL,
166                     "ViewShell::Implementation::ProcessModifyPageSlot(): can not get dispatcher");
167             }
168 
169             // We have activated a non-modal control in the task pane.
170             // Because it does not return anything we can not do anything
171             // more right now and have to exit here.
172             break;
173         }
174         else if (pArgs->Count() == 4)
175         {
176             SFX_REQUEST_ARG (rRequest, pNewName, SfxStringItem, ID_VAL_PAGENAME, sal_False);
177             SFX_REQUEST_ARG (rRequest, pNewAutoLayout, SfxUInt32Item, ID_VAL_WHATLAYOUT, sal_False);
178             SFX_REQUEST_ARG (rRequest, pBVisible, SfxBoolItem, ID_VAL_ISPAGEBACK, sal_False);
179             SFX_REQUEST_ARG (rRequest, pBObjsVisible, SfxBoolItem, ID_VAL_ISPAGEOBJ, sal_False);
180             AutoLayout aLayout ((AutoLayout)pNewAutoLayout->GetValue ());
181             if (aLayout >= AUTOLAYOUT__START
182                 && aLayout < AUTOLAYOUT__END)
183             {
184                 aNewName		= pNewName->GetValue ();
185                 aNewAutoLayout = (AutoLayout) pNewAutoLayout->GetValue ();
186                 bBVisible		= pBVisible->GetValue ();
187                 bBObjsVisible	= pBObjsVisible->GetValue ();
188             }
189             else
190             {
191                 StarBASIC::FatalError (SbERR_BAD_PROP_VALUE);
192                 rRequest.Ignore ();
193                 break;
194             }
195             if (ePageKind == PK_HANDOUT)
196             {
197                 bHandoutMode = sal_True;
198                 pHandoutMPage = pDocument->GetMasterSdPage(0, PK_HANDOUT);
199             }
200         }
201         else
202         {
203             StarBASIC::FatalError (SbERR_WRONG_ARGS);
204             rRequest.Ignore ();
205             break;
206         }
207 
208         SdPage* pUndoPage =
209             bHandoutMode ? pHandoutMPage : pCurrentPage;
210 
211         ::svl::IUndoManager* pUndoManager = mrViewShell.GetDocSh()->GetUndoManager();
212         DBG_ASSERT(pUndoManager, "No UNDO MANAGER ?!?");
213 
214 		if( pUndoManager )
215 		{
216 			String aComment( SdResId(STR_UNDO_MODIFY_PAGE) );
217 			pUndoManager->EnterListAction(aComment, aComment);
218 			ModifyPageUndoAction* pAction = new ModifyPageUndoAction(
219 				pDocument, pUndoPage, aNewName, aNewAutoLayout, bBVisible, bBObjsVisible);
220 			pUndoManager->AddUndoAction(pAction);
221 
222 			// Clear the selection because the selectec object may be removed as
223 			// a result of the ssignment of the layout.
224 			mrViewShell.GetDrawView()->UnmarkAll();
225 
226 			if (!bHandoutMode)
227 			{
228 				if (pCurrentPage->GetName() != aNewName)
229 				{
230 					pCurrentPage->SetName(aNewName);
231 
232 					if (ePageKind == PK_STANDARD)
233 					{
234 						sal_uInt16 nPage = (pCurrentPage->GetPageNum()-1) / 2;
235 						SdPage* pNotesPage = pDocument->GetSdPage(nPage, PK_NOTES);
236 						if (pNotesPage != NULL)
237 							pNotesPage->SetName(aNewName);
238 					}
239 				}
240 
241 				pCurrentPage->SetAutoLayout(aNewAutoLayout, sal_True);
242 
243 				aBckgrnd = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), sal_False);
244 				aBckgrndObj = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), sal_False);
245 				aVisibleLayers.Set(aBckgrnd, bBVisible);
246 				aVisibleLayers.Set(aBckgrndObj, bBObjsVisible);
247 				pCurrentPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers);
248 			}
249 			else
250 			{
251 				pHandoutMPage->SetAutoLayout(aNewAutoLayout, sal_True);
252 			}
253 
254 			mrViewShell.GetViewFrame()->GetDispatcher()->Execute(SID_SWITCHPAGE,
255 				SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD);
256 
257 			sal_Bool bSetModified = sal_True;
258 
259 			if (pArgs && pArgs->Count() == 1)
260 			{
261 				bSetModified = (sal_Bool) ((SfxBoolItem&) pArgs->Get(SID_MODIFYPAGE)).GetValue();
262 			}
263 
264 			pUndoManager->AddUndoAction( new UndoAutoLayoutPosAndSize( *pUndoPage ) );
265 			pUndoManager->LeaveListAction();
266 
267 			pDocument->SetChanged(bSetModified);
268         }
269     }
270     while (false);
271 
272     mrViewShell.Cancel();
273     rRequest.Done ();
274 }
275 
276 void ViewShell::Implementation::AssignLayout ( SfxRequest& rRequest, PageKind ePageKind )
277 {
278     const SfxUInt32Item* pWhatPage = static_cast< const SfxUInt32Item*  > ( rRequest.GetArg( ID_VAL_WHATPAGE, sal_False, TYPE(SfxUInt32Item) ) );
279     const SfxUInt32Item* pWhatLayout = static_cast< const SfxUInt32Item*  > ( rRequest.GetArg( ID_VAL_WHATLAYOUT, sal_False, TYPE(SfxUInt32Item) ) );
280 
281     SdDrawDocument* pDocument = mrViewShell.GetDoc();
282 	if( !pDocument )
283 		return;
284 
285     SdPage* pPage = 0;
286     if( pWhatPage )
287     {
288 		pPage = pDocument->GetSdPage(static_cast<sal_uInt16>(pWhatPage->GetValue()), ePageKind);
289     }
290 
291     if( pPage == 0 )
292         pPage = mrViewShell.getCurrentPage();
293 
294     if( pPage )
295     {
296         AutoLayout eLayout = pPage->GetAutoLayout();
297 
298         if( pWhatLayout )
299             eLayout = static_cast< AutoLayout >( pWhatLayout->GetValue() );
300 
301         // Transform the given request into the four argument form that is
302         // understood by ProcessModifyPageSlot().
303         SdrLayerAdmin& rLayerAdmin (mrViewShell.GetViewShellBase().GetDocument()->GetLayerAdmin());
304         sal_uInt8 aBackground (rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), sal_False));
305         sal_uInt8 aBackgroundObject (rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), sal_False));
306 
307         SetOfByte aVisibleLayers;
308 
309 		if( pPage->GetPageKind() == PK_HANDOUT )
310 			aVisibleLayers.SetAll();
311 		else
312 			aVisibleLayers = pPage->TRG_GetMasterPageVisibleLayers();
313 
314 		SfxRequest aRequest (mrViewShell.GetViewShellBase().GetViewFrame(), SID_MODIFYPAGE);
315         aRequest.AppendItem(SfxStringItem (ID_VAL_PAGENAME, pPage->GetName()));
316         aRequest.AppendItem(SfxUInt32Item (ID_VAL_WHATLAYOUT, eLayout));
317         aRequest.AppendItem(SfxBoolItem(ID_VAL_ISPAGEBACK, aVisibleLayers.IsSet(aBackground)));
318         aRequest.AppendItem(SfxBoolItem(ID_VAL_ISPAGEOBJ, aVisibleLayers.IsSet(aBackgroundObject)));
319 
320         // Forward the call with the new arguments.
321         ProcessModifyPageSlot( aRequest, pPage, pPage->GetPageKind());
322     }
323 }
324 
325 
326 
327 
328 sal_uInt16 ViewShell::Implementation::GetViewId (void)
329 {
330     switch (mrViewShell.GetShellType())
331     {
332         case ViewShell::ST_IMPRESS:
333         case ViewShell::ST_NOTES:
334         case ViewShell::ST_HANDOUT:
335             return IMPRESS_FACTORY_ID;
336 
337         case ViewShell::ST_DRAW:
338             return DRAW_FACTORY_ID;
339 
340         case ViewShell::ST_OUTLINE:
341             return OUTLINE_FACTORY_ID;
342 
343         case ViewShell::ST_SLIDE_SORTER:
344             return SLIDE_SORTER_FACTORY_ID;
345 
346         case ViewShell::ST_PRESENTATION:
347             return PRESENTATION_FACTORY_ID;
348 
349         // Since we have to return a view id for every possible shell type
350         // and there is not (yet) a proper ViewShellBase sub class for the
351         // remaining types we chose the Impress factory as a fall back.
352         case ViewShell::ST_TASK_PANE:
353         case ViewShell::ST_NONE:
354         default:
355             return IMPRESS_FACTORY_ID;
356     }
357 }
358 
359 
360 
361 
362 SvxIMapDlg* ViewShell::Implementation::GetImageMapDialog (void)
363 {
364     SvxIMapDlg* pDialog = NULL;
365     SfxChildWindow* pChildWindow = SfxViewFrame::Current()->GetChildWindow(
366         SvxIMapDlgChildWindow::GetChildWindowId());
367     if (pChildWindow != NULL)
368         pDialog = dynamic_cast<SvxIMapDlg*>(pChildWindow->GetWindow());
369     return pDialog;
370 }
371 
372 
373 
374 //===== ToolBarManagerLock ====================================================
375 
376 class ViewShell::Implementation::ToolBarManagerLock::Deleter { public:
377     void operator() (ToolBarManagerLock* pObject) { delete pObject; }
378 };
379 
380 ::boost::shared_ptr<ViewShell::Implementation::ToolBarManagerLock>
381     ViewShell::Implementation::ToolBarManagerLock::Create (
382         const ::boost::shared_ptr<ToolBarManager>& rpManager)
383 {
384     ::boost::shared_ptr<ToolBarManagerLock> pLock (
385         new ViewShell::Implementation::ToolBarManagerLock(rpManager),
386         ViewShell::Implementation::ToolBarManagerLock::Deleter());
387     pLock->mpSelf = pLock;
388     return pLock;
389 }
390 
391 
392 
393 
394 ViewShell::Implementation::ToolBarManagerLock::ToolBarManagerLock (
395     const ::boost::shared_ptr<ToolBarManager>& rpManager)
396     : mpLock(new ToolBarManager::UpdateLock(rpManager)),
397       maTimer()
398 {
399     // Start a timer that will unlock the ToolBarManager update lock when
400     // that is not done explicitly by calling Release().
401     maTimer.SetTimeoutHdl(LINK(this,ToolBarManagerLock,TimeoutCallback));
402     maTimer.SetTimeout(100);
403     maTimer.Start();
404 }
405 
406 
407 
408 
409 IMPL_LINK(ViewShell::Implementation::ToolBarManagerLock,TimeoutCallback,Timer*,EMPTYARG)
410 {
411     // If possible then release the lock now.  Otherwise start the timer
412     // and try again later.
413     if (Application::IsUICaptured())
414     {
415         maTimer.Start();
416     }
417     else
418     {
419         mpSelf.reset();
420     }
421     return 0;
422 }
423 
424 
425 
426 
427 void ViewShell::Implementation::ToolBarManagerLock::Release (bool bForce)
428 {
429     // If possible then release the lock now.  Otherwise try again when the
430     // timer expires.
431     if (bForce || ! Application::IsUICaptured())
432     {
433         mpSelf.reset();
434     }
435 }
436 
437 
438 
439 
440 ViewShell::Implementation::ToolBarManagerLock::~ToolBarManagerLock (void)
441 {
442     mpLock.reset();
443 }
444 
445 } // end of namespace sd
446