1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <fucopy.hxx>
21 #include <sfx2/progress.hxx>
22 #include <svl/intitem.hxx>
23 
24 #include <sdattr.hrc>
25 #include <sdresid.hxx>
26 #include <strings.hrc>
27 #include <ViewShell.hxx>
28 #include <View.hxx>
29 #include <drawdoc.hxx>
30 #include <DrawDocShell.hxx>
31 #include <svx/svdobj.hxx>
32 #include <svx/xcolit.hxx>
33 #include <svx/xflclit.hxx>
34 #include <svx/xdef.hxx>
35 #include <svx/xfillit0.hxx>
36 #include <sfx2/request.hxx>
37 #include <sdabstdlg.hxx>
38 #include <memory>
39 
40 using namespace com::sun::star;
41 
42 namespace sd {
43 
44 
FuCopy(ViewShell * pViewSh,::sd::Window * pWin,::sd::View * pView,SdDrawDocument * pDoc,SfxRequest & rReq)45 FuCopy::FuCopy (
46     ViewShell* pViewSh,
47     ::sd::Window* pWin,
48     ::sd::View* pView,
49     SdDrawDocument* pDoc,
50     SfxRequest& rReq)
51     : FuPoor(pViewSh, pWin, pView, pDoc, rReq)
52 {
53 }
54 
Create(ViewShell * pViewSh,::sd::Window * pWin,::sd::View * pView,SdDrawDocument * pDoc,SfxRequest & rReq)55 rtl::Reference<FuPoor> FuCopy::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq )
56 {
57     rtl::Reference<FuPoor> xFunc( new FuCopy( pViewSh, pWin, pView, pDoc, rReq ) );
58     xFunc->DoExecute(rReq);
59     return xFunc;
60 }
61 
DoExecute(SfxRequest & rReq)62 void FuCopy::DoExecute( SfxRequest& rReq )
63 {
64     if( !mpView->AreObjectsMarked() )
65         return;
66 
67     // Undo
68     OUString aString = mpView->GetDescriptionOfMarkedObjects() +
69         " " + SdResId( STR_UNDO_COPYOBJECTS );
70     mpView->BegUndo( aString );
71 
72     const SfxItemSet* pArgs = rReq.GetArgs();
73 
74     if( !pArgs )
75     {
76         SfxItemSet aSet( mpViewShell->GetPool(),
77                             svl::Items<ATTR_COPY_START, ATTR_COPY_END>{} );
78 
79         // indicate color attribute
80         SfxItemSet aAttr( mpDoc->GetPool() );
81         mpView->GetAttributes( aAttr );
82         const SfxPoolItem*  pPoolItem = nullptr;
83 
84         if( SfxItemState::SET == aAttr.GetItemState( XATTR_FILLSTYLE, true, &pPoolItem ) )
85         {
86             drawing::FillStyle eStyle = static_cast<const XFillStyleItem*>(pPoolItem)->GetValue();
87 
88             if( eStyle == drawing::FillStyle_SOLID &&
89                 SfxItemState::SET == aAttr.GetItemState( XATTR_FILLCOLOR, true, &pPoolItem ) )
90             {
91                 const XFillColorItem* pItem = static_cast<const XFillColorItem*>(pPoolItem);
92                 XColorItem aXColorItem( ATTR_COPY_START_COLOR, pItem->GetName(),
93                                                     pItem->GetColorValue() );
94                 aSet.Put( aXColorItem );
95 
96             }
97         }
98 
99         SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create();
100         ScopedVclPtr<AbstractCopyDlg> pDlg(pFact->CreateCopyDlg(mpViewShell->GetFrameWeld(), aSet, mpView ));
101 
102         sal_uInt16 nResult = pDlg->Execute();
103 
104         switch( nResult )
105         {
106             case RET_OK:
107                 pDlg->GetAttr( aSet );
108                 rReq.Done( aSet );
109                 pArgs = rReq.GetArgs();
110             break;
111 
112             default:
113             {
114                 pDlg.disposeAndClear();
115                 mpView->EndUndo();
116                 return; // Cancel
117             }
118         }
119     }
120 
121     ::tools::Rectangle           aRect;
122     sal_Int32               lWidth = 0, lHeight = 0, lSizeX = 0, lSizeY = 0, lAngle = 0;
123     sal_uInt16              nNumber = 0;
124     Color               aStartColor, aEndColor;
125     bool                bColor = false;
126     const SfxPoolItem*  pPoolItem = nullptr;
127 
128     // Count
129     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_NUMBER, true, &pPoolItem ) )
130         nNumber = static_cast<const SfxUInt16Item*>( pPoolItem )->GetValue();
131 
132     // translation
133     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_MOVE_X, true, &pPoolItem ) )
134         lSizeX = static_cast<const SfxInt32Item*>( pPoolItem )->GetValue();
135     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_MOVE_Y, true, &pPoolItem ) )
136         lSizeY = static_cast<const SfxInt32Item*>( pPoolItem )->GetValue();
137     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_ANGLE, true, &pPoolItem ) )
138         lAngle = static_cast<const SfxInt32Item*>( pPoolItem )->GetValue();
139 
140     // scale
141     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_WIDTH, true, &pPoolItem ) )
142         lWidth = static_cast<const SfxInt32Item*>( pPoolItem )->GetValue();
143     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_HEIGHT, true, &pPoolItem ) )
144         lHeight = static_cast<const SfxInt32Item*>( pPoolItem )->GetValue();
145 
146     // start/end color
147     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_START_COLOR, true, &pPoolItem ) )
148     {
149         aStartColor = static_cast<const XColorItem*>( pPoolItem )->GetColorValue();
150         bColor = true;
151     }
152     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_END_COLOR, true, &pPoolItem ) )
153     {
154         aEndColor = static_cast<const XColorItem*>( pPoolItem )->GetColorValue();
155         if( aStartColor == aEndColor )
156             bColor = false;
157     }
158     else
159         bColor = false;
160 
161     // remove handles
162     //HMHmpView->HideMarkHdl();
163 
164     std::unique_ptr<SfxProgress> pProgress;
165     bool            bWaiting = false;
166 
167     if( nNumber > 1 )
168     {
169         OUString aStr = SdResId( STR_OBJECTS ) +
170             " " + SdResId( STR_UNDO_COPYOBJECTS );
171 
172         pProgress.reset(new SfxProgress( mpDocSh, aStr, nNumber ));
173         mpDocSh->SetWaitCursor( true );
174         bWaiting = true;
175     }
176 
177     const SdrMarkList   aMarkList( mpView->GetMarkedObjectList() );
178     const size_t nMarkCount = aMarkList.GetMarkCount();
179     SdrObject*          pObj = nullptr;
180 
181     // calculate number of possible copies
182     aRect = mpView->GetAllMarkedRect();
183 
184     if( lWidth < 0 )
185     {
186         long nTmp = ( aRect.Right() - aRect.Left() ) / -lWidth;
187         nNumber = static_cast<sal_uInt16>(std::min( nTmp, static_cast<long>(nNumber) ));
188     }
189 
190     if( lHeight < 0 )
191     {
192         long nTmp = ( aRect.Bottom() - aRect.Top() ) / -lHeight;
193         nNumber = static_cast<sal_uInt16>(std::min( nTmp, static_cast<long>(nNumber) ));
194     }
195 
196     for( sal_uInt16 i = 1; i <= nNumber; i++ )
197     {
198         if( pProgress )
199             pProgress->SetState( i );
200 
201         aRect = mpView->GetAllMarkedRect();
202 
203         if( ( 1 == i ) && bColor )
204         {
205             SfxItemSet aNewSet( mpViewShell->GetPool(), svl::Items<XATTR_FILLSTYLE, XATTR_FILLCOLOR>{} );
206             aNewSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
207             aNewSet.Put( XFillColorItem( OUString(), aStartColor ) );
208             mpView->SetAttributes( aNewSet );
209         }
210 
211         // make a copy of selected objects
212         mpView->CopyMarked();
213 
214         // get newly selected objects
215         SdrMarkList aCopyMarkList( mpView->GetMarkedObjectList() );
216         const size_t nCopyMarkCount = aMarkList.GetMarkCount();
217 
218         // set protection flags at marked copies to null
219         for( size_t j = 0; j < nCopyMarkCount; ++j )
220         {
221             pObj = aCopyMarkList.GetMark( j )->GetMarkedSdrObj();
222 
223             if( pObj )
224             {
225                 pObj->SetMoveProtect( false );
226                 pObj->SetResizeProtect( false );
227             }
228         }
229 
230         Fraction aWidth( aRect.Right() - aRect.Left() + lWidth, aRect.Right() - aRect.Left() );
231         Fraction aHeight( aRect.Bottom() - aRect.Top() + lHeight, aRect.Bottom() - aRect.Top() );
232 
233         if( mpView->IsResizeAllowed() )
234             mpView->ResizeAllMarked( aRect.TopLeft(), aWidth, aHeight );
235 
236         if( mpView->IsRotateAllowed() )
237             mpView->RotateAllMarked( aRect.Center(), lAngle );
238 
239         if( mpView->IsMoveAllowed() )
240             mpView->MoveAllMarked( Size( lSizeX, lSizeY ) );
241 
242         // set protection flags at marked copies to original values
243         if( nMarkCount == nCopyMarkCount )
244         {
245             for( size_t j = 0; j < nMarkCount; ++j )
246             {
247                 SdrObject* pSrcObj = aMarkList.GetMark( j )->GetMarkedSdrObj();
248                 SdrObject* pDstObj = aCopyMarkList.GetMark( j )->GetMarkedSdrObj();
249 
250                 if( pSrcObj && pDstObj &&
251                     ( pSrcObj->GetObjInventor() == pDstObj->GetObjInventor() ) &&
252                     ( pSrcObj->GetObjIdentifier() == pDstObj->GetObjIdentifier() ) )
253                 {
254                     pDstObj->SetMoveProtect( pSrcObj->IsMoveProtect() );
255                     pDstObj->SetResizeProtect( pSrcObj->IsResizeProtect() );
256                 }
257             }
258         }
259 
260         if( bColor )
261         {
262             // probably room for optimizations, but may can lead to rounding errors
263             sal_uInt8 nRed = aStartColor.GetRed() + static_cast<sal_uInt8>( ( static_cast<long>(aEndColor.GetRed()) - static_cast<long>(aStartColor.GetRed()) ) * static_cast<long>(i) / static_cast<long>(nNumber)  );
264             sal_uInt8 nGreen = aStartColor.GetGreen() + static_cast<sal_uInt8>( ( static_cast<long>(aEndColor.GetGreen()) - static_cast<long>(aStartColor.GetGreen()) ) *  static_cast<long>(i) / static_cast<long>(nNumber) );
265             sal_uInt8 nBlue = aStartColor.GetBlue() + static_cast<sal_uInt8>( ( static_cast<long>(aEndColor.GetBlue()) - static_cast<long>(aStartColor.GetBlue()) ) * static_cast<long>(i) / static_cast<long>(nNumber) );
266             Color aNewColor( nRed, nGreen, nBlue );
267             SfxItemSet aNewSet( mpViewShell->GetPool(), svl::Items<XATTR_FILLSTYLE, XATTR_FILLCOLOR>{} );
268             aNewSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
269             aNewSet.Put( XFillColorItem( OUString(), aNewColor ) );
270             mpView->SetAttributes( aNewSet );
271         }
272     }
273 
274     pProgress.reset();
275 
276     if ( bWaiting )
277         mpDocSh->SetWaitCursor( false );
278 
279     // show handles
280     mpView->AdjustMarkHdl(); //HMH sal_True );
281     //HMHpView->ShowMarkHdl();
282 
283     mpView->EndUndo();
284 }
285 
286 } // end of namespace
287 
288 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
289