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 <svx/sdangitm.hxx>
37 #include <sfx2/request.hxx>
38 #include <sdabstdlg.hxx>
39 #include <memory>
40 
41 using namespace com::sun::star;
42 
43 namespace sd {
44 
45 
FuCopy(ViewShell * pViewSh,::sd::Window * pWin,::sd::View * pView,SdDrawDocument * pDoc,SfxRequest & rReq)46 FuCopy::FuCopy (
47     ViewShell* pViewSh,
48     ::sd::Window* pWin,
49     ::sd::View* pView,
50     SdDrawDocument* pDoc,
51     SfxRequest& rReq)
52     : FuPoor(pViewSh, pWin, pView, pDoc, rReq)
53 {
54 }
55 
Create(ViewShell * pViewSh,::sd::Window * pWin,::sd::View * pView,SdDrawDocument * pDoc,SfxRequest & rReq)56 rtl::Reference<FuPoor> FuCopy::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq )
57 {
58     rtl::Reference<FuPoor> xFunc( new FuCopy( pViewSh, pWin, pView, pDoc, rReq ) );
59     xFunc->DoExecute(rReq);
60     return xFunc;
61 }
62 
DoExecute(SfxRequest & rReq)63 void FuCopy::DoExecute( SfxRequest& rReq )
64 {
65     if( !mpView->AreObjectsMarked() )
66         return;
67 
68     // Undo
69     OUString aString = mpView->GetDescriptionOfMarkedObjects() +
70         " " + SdResId( STR_UNDO_COPYOBJECTS );
71     mpView->BegUndo( aString );
72 
73     const SfxItemSet* pArgs = rReq.GetArgs();
74 
75     if( !pArgs )
76     {
77         SfxItemSet aSet( mpViewShell->GetPool(),
78                             svl::Items<ATTR_COPY_START, ATTR_COPY_END>{} );
79 
80         // indicate color attribute
81         SfxItemSet aAttr( mpDoc->GetPool() );
82         mpView->GetAttributes( aAttr );
83         const SfxPoolItem*  pPoolItem = nullptr;
84 
85         if( SfxItemState::SET == aAttr.GetItemState( XATTR_FILLSTYLE, true, &pPoolItem ) )
86         {
87             drawing::FillStyle eStyle = static_cast<const XFillStyleItem*>(pPoolItem)->GetValue();
88 
89             if( eStyle == drawing::FillStyle_SOLID &&
90                 SfxItemState::SET == aAttr.GetItemState( XATTR_FILLCOLOR, true, &pPoolItem ) )
91             {
92                 const XFillColorItem* pItem = static_cast<const XFillColorItem*>(pPoolItem);
93                 XColorItem aXColorItem( ATTR_COPY_START_COLOR, pItem->GetName(),
94                                                     pItem->GetColorValue() );
95                 aSet.Put( aXColorItem );
96 
97             }
98         }
99 
100         SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create();
101         ScopedVclPtr<AbstractCopyDlg> pDlg(pFact->CreateCopyDlg(mpViewShell->GetFrameWeld(), aSet, mpView ));
102 
103         sal_uInt16 nResult = pDlg->Execute();
104 
105         switch( nResult )
106         {
107             case RET_OK:
108                 pDlg->GetAttr( aSet );
109                 rReq.Done( aSet );
110                 pArgs = rReq.GetArgs();
111             break;
112 
113             default:
114             {
115                 pDlg.disposeAndClear();
116                 mpView->EndUndo();
117                 return; // Cancel
118             }
119         }
120     }
121 
122     ::tools::Rectangle           aRect;
123     sal_Int32               lWidth = 0, lHeight = 0, lSizeX = 0, lSizeY = 0;
124     Degree100           lAngle(0);
125     sal_uInt16              nNumber = 0;
126     Color               aStartColor, aEndColor;
127     bool                bColor = false;
128     const SfxPoolItem*  pPoolItem = nullptr;
129 
130     // Count
131     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_NUMBER, true, &pPoolItem ) )
132         nNumber = static_cast<const SfxUInt16Item*>( pPoolItem )->GetValue();
133 
134     // translation
135     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_MOVE_X, true, &pPoolItem ) )
136         lSizeX = static_cast<const SfxInt32Item*>( pPoolItem )->GetValue();
137     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_MOVE_Y, true, &pPoolItem ) )
138         lSizeY = static_cast<const SfxInt32Item*>( pPoolItem )->GetValue();
139     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_ANGLE, true, &pPoolItem ) )
140         lAngle = static_cast<const SdrAngleItem*>( pPoolItem )->GetValue();
141 
142     // scale
143     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_WIDTH, true, &pPoolItem ) )
144         lWidth = static_cast<const SfxInt32Item*>( pPoolItem )->GetValue();
145     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_HEIGHT, true, &pPoolItem ) )
146         lHeight = static_cast<const SfxInt32Item*>( pPoolItem )->GetValue();
147 
148     // start/end color
149     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_START_COLOR, true, &pPoolItem ) )
150     {
151         aStartColor = static_cast<const XColorItem*>( pPoolItem )->GetColorValue();
152         bColor = true;
153     }
154     if( pArgs && SfxItemState::SET == pArgs->GetItemState( ATTR_COPY_END_COLOR, true, &pPoolItem ) )
155     {
156         aEndColor = static_cast<const XColorItem*>( pPoolItem )->GetColorValue();
157         if( aStartColor == aEndColor )
158             bColor = false;
159     }
160     else
161         bColor = false;
162 
163     // remove handles
164     //HMHmpView->HideMarkHdl();
165 
166     std::unique_ptr<SfxProgress> pProgress;
167     bool            bWaiting = false;
168 
169     if( nNumber > 1 )
170     {
171         OUString aStr = SdResId( STR_OBJECTS ) +
172             " " + SdResId( STR_UNDO_COPYOBJECTS );
173 
174         pProgress.reset(new SfxProgress( mpDocSh, aStr, nNumber ));
175         mpDocSh->SetWaitCursor( true );
176         bWaiting = true;
177     }
178 
179     const SdrMarkList   aMarkList( mpView->GetMarkedObjectList() );
180     const size_t nMarkCount = aMarkList.GetMarkCount();
181     SdrObject*          pObj = nullptr;
182 
183     // calculate number of possible copies
184     aRect = mpView->GetAllMarkedRect();
185 
186     if( lWidth < 0 )
187     {
188         ::tools::Long nTmp = ( aRect.Right() - aRect.Left() ) / -lWidth;
189         nNumber = static_cast<sal_uInt16>(std::min( nTmp, static_cast<::tools::Long>(nNumber) ));
190     }
191 
192     if( lHeight < 0 )
193     {
194         ::tools::Long nTmp = ( aRect.Bottom() - aRect.Top() ) / -lHeight;
195         nNumber = static_cast<sal_uInt16>(std::min( nTmp, static_cast<::tools::Long>(nNumber) ));
196     }
197 
198     for( sal_uInt16 i = 1; i <= nNumber; i++ )
199     {
200         if( pProgress )
201             pProgress->SetState( i );
202 
203         aRect = mpView->GetAllMarkedRect();
204 
205         if( ( 1 == i ) && bColor )
206         {
207             SfxItemSet aNewSet( mpViewShell->GetPool(), svl::Items<XATTR_FILLSTYLE, XATTR_FILLCOLOR>{} );
208             aNewSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
209             aNewSet.Put( XFillColorItem( OUString(), aStartColor ) );
210             mpView->SetAttributes( aNewSet );
211         }
212 
213         // make a copy of selected objects
214         mpView->CopyMarked();
215 
216         // get newly selected objects
217         SdrMarkList aCopyMarkList( mpView->GetMarkedObjectList() );
218         const size_t nCopyMarkCount = aMarkList.GetMarkCount();
219 
220         // set protection flags at marked copies to null
221         for( size_t j = 0; j < nCopyMarkCount; ++j )
222         {
223             pObj = aCopyMarkList.GetMark( j )->GetMarkedSdrObj();
224 
225             if( pObj )
226             {
227                 pObj->SetMoveProtect( false );
228                 pObj->SetResizeProtect( false );
229             }
230         }
231 
232         Fraction aWidth( aRect.Right() - aRect.Left() + lWidth, aRect.Right() - aRect.Left() );
233         Fraction aHeight( aRect.Bottom() - aRect.Top() + lHeight, aRect.Bottom() - aRect.Top() );
234 
235         if( mpView->IsResizeAllowed() )
236             mpView->ResizeAllMarked( aRect.TopLeft(), aWidth, aHeight );
237 
238         if( mpView->IsRotateAllowed() )
239             mpView->RotateAllMarked( aRect.Center(), lAngle );
240 
241         if( mpView->IsMoveAllowed() )
242             mpView->MoveAllMarked( Size( lSizeX, lSizeY ) );
243 
244         // set protection flags at marked copies to original values
245         if( nMarkCount == nCopyMarkCount )
246         {
247             for( size_t j = 0; j < nMarkCount; ++j )
248             {
249                 SdrObject* pSrcObj = aMarkList.GetMark( j )->GetMarkedSdrObj();
250                 SdrObject* pDstObj = aCopyMarkList.GetMark( j )->GetMarkedSdrObj();
251 
252                 if( pSrcObj && pDstObj &&
253                     ( pSrcObj->GetObjInventor() == pDstObj->GetObjInventor() ) &&
254                     ( pSrcObj->GetObjIdentifier() == pDstObj->GetObjIdentifier() ) )
255                 {
256                     pDstObj->SetMoveProtect( pSrcObj->IsMoveProtect() );
257                     pDstObj->SetResizeProtect( pSrcObj->IsResizeProtect() );
258                 }
259             }
260         }
261 
262         if( bColor )
263         {
264             // probably room for optimizations, but may can lead to rounding errors
265             sal_uInt8 nRed = aStartColor.GetRed() + static_cast<sal_uInt8>( ( static_cast<::tools::Long>(aEndColor.GetRed()) - static_cast<::tools::Long>(aStartColor.GetRed()) ) * static_cast<::tools::Long>(i) / static_cast<::tools::Long>(nNumber)  );
266             sal_uInt8 nGreen = aStartColor.GetGreen() + static_cast<sal_uInt8>( ( static_cast<::tools::Long>(aEndColor.GetGreen()) - static_cast<::tools::Long>(aStartColor.GetGreen()) ) *  static_cast<::tools::Long>(i) / static_cast<::tools::Long>(nNumber) );
267             sal_uInt8 nBlue = aStartColor.GetBlue() + static_cast<sal_uInt8>( ( static_cast<::tools::Long>(aEndColor.GetBlue()) - static_cast<::tools::Long>(aStartColor.GetBlue()) ) * static_cast<::tools::Long>(i) / static_cast<::tools::Long>(nNumber) );
268             Color aNewColor( nRed, nGreen, nBlue );
269             SfxItemSet aNewSet( mpViewShell->GetPool(), svl::Items<XATTR_FILLSTYLE, XATTR_FILLCOLOR>{} );
270             aNewSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
271             aNewSet.Put( XFillColorItem( OUString(), aNewColor ) );
272             mpView->SetAttributes( aNewSet );
273         }
274     }
275 
276     pProgress.reset();
277 
278     if ( bWaiting )
279         mpDocSh->SetWaitCursor( false );
280 
281     // show handles
282     mpView->AdjustMarkHdl(); //HMH sal_True );
283     //HMHpView->ShowMarkHdl();
284 
285     mpView->EndUndo();
286 }
287 
288 } // end of namespace
289 
290 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
291