xref: /trunk/main/sc/source/ui/app/seltrans.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 // INCLUDE ---------------------------------------------------------------
32 
33 
34 
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/beans/XPropertySetInfo.hpp>
37 #include <com/sun/star/form/FormButtonType.hpp>
38 
39 #include <tools/urlobj.hxx>
40 #include <sfx2/docfile.hxx>
41 #include <svx/fmglob.hxx>
42 #include <svx/svdograf.hxx>
43 #include <svx/svdouno.hxx>
44 
45 #include "seltrans.hxx"
46 #include "transobj.hxx"
47 #include "drwtrans.hxx"
48 #include "scmod.hxx"
49 #include "dbfunc.hxx"   // for CopyToClip
50 #include "docsh.hxx"
51 #include "drawview.hxx"
52 #include "drwlayer.hxx"
53 
54 using namespace com::sun::star;
55 
56 // -----------------------------------------------------------------------
57 
58 sal_Bool lcl_IsURLButton( SdrObject* pObject )
59 {
60     sal_Bool bRet = sal_False;
61 
62     SdrUnoObj* pUnoCtrl = PTR_CAST(SdrUnoObj, pObject);
63     if (pUnoCtrl && FmFormInventor == pUnoCtrl->GetObjInventor())
64     {
65         uno::Reference<awt::XControlModel> xControlModel = pUnoCtrl->GetUnoControlModel();
66         DBG_ASSERT( xControlModel.is(), "uno control without model" );
67         if ( xControlModel.is() )
68         {
69             uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY );
70             uno::Reference< beans::XPropertySetInfo > xInfo = xPropSet->getPropertySetInfo();
71 
72             rtl::OUString sPropButtonType = rtl::OUString::createFromAscii( "ButtonType" );
73             if(xInfo->hasPropertyByName( sPropButtonType ))
74             {
75                 uno::Any aAny = xPropSet->getPropertyValue( sPropButtonType );
76                 form::FormButtonType eTmp;
77                 if ( (aAny >>= eTmp) && eTmp == form::FormButtonType_URL )
78                     bRet = sal_True;
79             }
80         }
81     }
82 
83     return bRet;
84 }
85 
86 // static
87 
88 ScSelectionTransferObj* ScSelectionTransferObj::CreateFromView( ScTabView* pView )
89 {
90     ScSelectionTransferObj* pRet = NULL;
91 
92     if ( pView )
93     {
94         ScSelectionTransferMode eMode = SC_SELTRANS_INVALID;
95 
96         SdrView* pSdrView = pView->GetSdrView();
97         if ( pSdrView )
98         {
99             //  handle selection on drawing layer
100             const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
101             sal_uLong nMarkCount = rMarkList.GetMarkCount();
102             if ( nMarkCount )
103             {
104                 if ( nMarkCount == 1 )
105                 {
106                     SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
107                     sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier();
108 
109                     if ( nSdrObjKind == OBJ_GRAF )
110                     {
111                         if ( ((SdrGrafObj*)pObj)->GetGraphic().GetType() == GRAPHIC_BITMAP )
112                             eMode = SC_SELTRANS_DRAW_BITMAP;
113                         else
114                             eMode = SC_SELTRANS_DRAW_GRAPHIC;
115                     }
116                     else if ( nSdrObjKind == OBJ_OLE2 )
117                         eMode = SC_SELTRANS_DRAW_OLE;
118                     else if ( lcl_IsURLButton( pObj ) )
119                         eMode = SC_SELTRANS_DRAW_BOOKMARK;
120                 }
121 
122                 if ( eMode == SC_SELTRANS_INVALID )
123                     eMode = SC_SELTRANS_DRAW_OTHER;     // something selected but no special selection
124             }
125         }
126         if ( eMode == SC_SELTRANS_INVALID )             // no drawing object selected
127         {
128             ScRange aRange;
129             ScViewData* pViewData = pView->GetViewData();
130             const ScMarkData& rMark = pViewData->GetMarkData();
131             //  allow MultiMarked because GetSimpleArea may be able to merge into a simple range
132             //  (GetSimpleArea modifies a local copy of MarkData)
133             // Also allow simple filtered area.
134             ScMarkType eMarkType;
135             if ( ( rMark.IsMarked() || rMark.IsMultiMarked() ) &&
136                     (((eMarkType = pViewData->GetSimpleArea( aRange )) == SC_MARK_SIMPLE) ||
137                      (eMarkType == SC_MARK_SIMPLE_FILTERED)) )
138             {
139                 //  only for "real" selection, cursor alone isn't used
140                 if ( aRange.aStart == aRange.aEnd )
141                     eMode = SC_SELTRANS_CELL;
142                 else
143                     eMode = SC_SELTRANS_CELLS;
144             }
145         }
146 
147         if ( eMode != SC_SELTRANS_INVALID )
148             pRet = new ScSelectionTransferObj( pView, eMode );
149     }
150 
151     return pRet;
152 }
153 
154 
155 ScSelectionTransferObj::ScSelectionTransferObj( ScTabView* pSource, ScSelectionTransferMode eNewMode ) :
156     pView( pSource ),
157     eMode( eNewMode ),
158     pCellData( NULL ),
159     pDrawData( NULL )
160 {
161     //! store range for StillValid
162 }
163 
164 ScSelectionTransferObj::~ScSelectionTransferObj()
165 {
166     ScModule* pScMod = SC_MOD();
167     if ( pScMod->GetSelectionTransfer() == this )
168     {
169         //  this is reached when the object wasn't really copied to the selection
170         //  (CopyToSelection has no effect under Windows)
171 
172         ForgetView();
173         pScMod->SetSelectionTransfer( NULL );
174     }
175 
176     DBG_ASSERT( !pView, "ScSelectionTransferObj dtor: ForgetView not called" );
177 }
178 
179 sal_Bool ScSelectionTransferObj::StillValid()
180 {
181     //! check if view still has same cell selection
182     //! (but return sal_False if data has changed inbetween)
183     return sal_False;
184 }
185 
186 void ScSelectionTransferObj::ForgetView()
187 {
188     pView = NULL;
189     eMode = SC_SELTRANS_INVALID;
190 
191     if (pCellData)
192     {
193         pCellData->release();
194         pCellData = NULL;
195     }
196     if (pDrawData)
197     {
198         pDrawData->release();
199         pDrawData = NULL;
200     }
201 }
202 
203 void ScSelectionTransferObj::AddSupportedFormats()
204 {
205     //  AddSupportedFormats must work without actually creating the
206     //  "real" transfer object
207 
208     switch (eMode)
209     {
210         case SC_SELTRANS_CELL:
211         case SC_SELTRANS_CELLS:
212             //  same formats as in ScTransferObj::AddSupportedFormats
213             AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE );
214             AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
215             AddFormat( SOT_FORMAT_GDIMETAFILE );
216             AddFormat( SOT_FORMAT_BITMAP );
217             AddFormat( SOT_FORMATSTR_ID_HTML );
218             AddFormat( SOT_FORMATSTR_ID_SYLK );
219             AddFormat( SOT_FORMATSTR_ID_LINK );
220             AddFormat( SOT_FORMATSTR_ID_DIF );
221             AddFormat( SOT_FORMAT_STRING );
222             AddFormat( SOT_FORMAT_RTF );
223             if ( eMode == SC_SELTRANS_CELL )
224                 AddFormat( SOT_FORMATSTR_ID_EDITENGINE );
225             break;
226 
227         // different graphic formats as in ScDrawTransferObj::AddSupportedFormats:
228 
229         case SC_SELTRANS_DRAW_BITMAP:
230             AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
231             AddFormat( SOT_FORMATSTR_ID_SVXB );
232             AddFormat( SOT_FORMAT_BITMAP );
233             AddFormat( SOT_FORMAT_GDIMETAFILE );
234             break;
235 
236         case SC_SELTRANS_DRAW_GRAPHIC:
237             AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
238             AddFormat( SOT_FORMATSTR_ID_SVXB );
239             AddFormat( SOT_FORMAT_GDIMETAFILE );
240             AddFormat( SOT_FORMAT_BITMAP );
241             break;
242 
243         case SC_SELTRANS_DRAW_BOOKMARK:
244             AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
245             AddFormat( SOT_FORMATSTR_ID_SOLK );
246             AddFormat( SOT_FORMAT_STRING );
247             AddFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR );
248             AddFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK );
249             AddFormat( SOT_FORMATSTR_ID_DRAWING );
250             break;
251 
252         case SC_SELTRANS_DRAW_OLE:
253             AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE );
254             AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
255             AddFormat( SOT_FORMAT_GDIMETAFILE );
256             break;
257 
258         case SC_SELTRANS_DRAW_OTHER:
259             //  other drawing objects
260             AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE );
261             AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
262             AddFormat( SOT_FORMATSTR_ID_DRAWING );
263             AddFormat( SOT_FORMAT_BITMAP );
264             AddFormat( SOT_FORMAT_GDIMETAFILE );
265             break;
266 
267         default:
268         {
269             // added to avoid warnings
270         }
271     }
272 }
273 
274 void ScSelectionTransferObj::CreateCellData()
275 {
276     DBG_ASSERT( !pCellData, "CreateCellData twice" );
277     if ( pView )
278     {
279         ScViewData* pViewData = pView->GetViewData();
280         ScMarkData aNewMark( pViewData->GetMarkData() );    // use local copy for MarkToSimple
281         aNewMark.MarkToSimple();
282 
283         //  similar to ScViewFunctionSet::BeginDrag
284         if ( aNewMark.IsMarked() && !aNewMark.IsMultiMarked() )
285         {
286             ScDocShell* pDocSh = pViewData->GetDocShell();
287 
288             ScRange aSelRange;
289             aNewMark.GetMarkArea( aSelRange );
290             ScDocShellRef aDragShellRef;
291             if ( pDocSh->GetDocument()->HasOLEObjectsInArea( aSelRange, &aNewMark ) )
292             {
293                 aDragShellRef = new ScDocShell;     // DocShell needs a Ref immediately
294                 aDragShellRef->DoInitNew(NULL);
295             }
296             ScDrawLayer::SetGlobalDrawPersist(aDragShellRef);
297 
298             ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
299             // bApi = sal_True -> no error mesages
300             // #i18364# bStopEdit = sal_False -> don't end edit mode
301             // (this may be called from pasting into the edit line)
302             sal_Bool bCopied = pViewData->GetView()->CopyToClip( pClipDoc, sal_False, sal_True, sal_True, sal_False );
303 
304             ScDrawLayer::SetGlobalDrawPersist(NULL);
305 
306             if ( bCopied )
307             {
308                 TransferableObjectDescriptor aObjDesc;
309                 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
310                 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
311                 // maSize is set in ScTransferObj ctor
312 
313                 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
314                 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
315 
316                 // SetDragHandlePos is not used - there is no mouse position
317                 //? pTransferObj->SetVisibleTab( nTab );
318 
319                 SfxObjectShellRef aPersistRef( aDragShellRef );
320                 pTransferObj->SetDrawPersist( aPersistRef );    // keep persist for ole objects alive
321 
322                 pTransferObj->SetDragSource( pDocSh, aNewMark );
323 
324                 pCellData = pTransferObj;
325                 pCellData->acquire();       // keep ref count up - released in ForgetView
326             }
327             else
328                 delete pClipDoc;
329         }
330     }
331     DBG_ASSERT( pCellData, "can't create CellData" );
332 }
333 
334 //! make static member of ScDrawView
335 extern void lcl_CheckOle( const SdrMarkList& rMarkList, sal_Bool& rAnyOle, sal_Bool& rOneOle );
336 
337 void ScSelectionTransferObj::CreateDrawData()
338 {
339     DBG_ASSERT( !pDrawData, "CreateDrawData twice" );
340     if ( pView )
341     {
342         //  similar to ScDrawView::BeginDrag
343 
344         ScDrawView* pDrawView = pView->GetScDrawView();
345         if ( pDrawView )
346         {
347             sal_Bool bAnyOle, bOneOle;
348             const SdrMarkList& rMarkList = pDrawView->GetMarkedObjectList();
349             lcl_CheckOle( rMarkList, bAnyOle, bOneOle );
350 
351             //---------------------------------------------------------
352             ScDocShellRef aDragShellRef;
353             if (bAnyOle)
354             {
355                 aDragShellRef = new ScDocShell;     // ohne Ref lebt die DocShell nicht !!!
356                 aDragShellRef->DoInitNew(NULL);
357             }
358             //---------------------------------------------------------
359 
360             ScDrawLayer::SetGlobalDrawPersist(aDragShellRef);
361             SdrModel* pModel = pDrawView->GetAllMarkedModel();
362             ScDrawLayer::SetGlobalDrawPersist(NULL);
363 
364             ScViewData* pViewData = pView->GetViewData();
365             ScDocShell* pDocSh = pViewData->GetDocShell();
366 
367             TransferableObjectDescriptor aObjDesc;
368             pDocSh->FillTransferableObjectDescriptor( aObjDesc );
369             aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
370             // maSize is set in ScDrawTransferObj ctor
371 
372             ScDrawTransferObj* pTransferObj = new ScDrawTransferObj( pModel, pDocSh, aObjDesc );
373             uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
374 
375             SfxObjectShellRef aPersistRef( aDragShellRef );
376             pTransferObj->SetDrawPersist( aPersistRef );    // keep persist for ole objects alive
377             pTransferObj->SetDragSource( pDrawView );       // copies selection
378 
379             pDrawData = pTransferObj;
380             pDrawData->acquire();       // keep ref count up - released in ForgetView
381         }
382     }
383     DBG_ASSERT( pDrawData, "can't create DrawData" );
384 }
385 
386 ScTransferObj* ScSelectionTransferObj::GetCellData()
387 {
388     if ( !pCellData && ( eMode == SC_SELTRANS_CELL || eMode == SC_SELTRANS_CELLS ) )
389         CreateCellData();
390     return pCellData;
391 }
392 
393 ScDrawTransferObj* ScSelectionTransferObj::GetDrawData()
394 {
395     if ( !pDrawData && ( eMode == SC_SELTRANS_DRAW_BITMAP || eMode == SC_SELTRANS_DRAW_GRAPHIC ||
396                          eMode == SC_SELTRANS_DRAW_BOOKMARK || eMode == SC_SELTRANS_DRAW_OLE ||
397                          eMode == SC_SELTRANS_DRAW_OTHER ) )
398         CreateDrawData();
399     return pDrawData;
400 }
401 
402 sal_Bool ScSelectionTransferObj::GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor )
403 {
404     sal_Bool bOK = sal_False;
405 
406     uno::Reference<datatransfer::XTransferable> xSource;
407     switch (eMode)
408     {
409         case SC_SELTRANS_CELL:
410         case SC_SELTRANS_CELLS:
411             xSource = GetCellData();
412             break;
413         case SC_SELTRANS_DRAW_BITMAP:
414         case SC_SELTRANS_DRAW_GRAPHIC:
415         case SC_SELTRANS_DRAW_BOOKMARK:
416         case SC_SELTRANS_DRAW_OLE:
417         case SC_SELTRANS_DRAW_OTHER:
418             xSource = GetDrawData();
419             break;
420         default:
421         {
422             // added to avoid warnings
423         }
424     }
425 
426     if ( xSource.is() )
427     {
428         TransferableDataHelper aHelper( xSource );
429         uno::Any aAny = aHelper.GetAny( rFlavor );
430         bOK = SetAny( aAny, rFlavor );
431     }
432 
433     return bOK;
434 }
435 
436 void ScSelectionTransferObj::ObjectReleased()
437 {
438     //  called when another selection is set from outside
439 
440     ForgetView();
441 
442     ScModule* pScMod = SC_MOD();
443     if ( pScMod->GetSelectionTransfer() == this )
444         pScMod->SetSelectionTransfer( NULL );
445 
446     TransferableHelper::ObjectReleased();
447 }
448 
449 
450