xref: /trunk/main/sd/source/ui/func/fuconbez.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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_sd.hxx"
30 
31 #include <com/sun/star/presentation/EffectNodeType.hpp>
32 
33 #include "fuconbez.hxx"
34 #include <svl/aeitem.hxx>
35 #include <svx/svdopath.hxx>
36 #include <svl/intitem.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include <svx/svdobj.hxx>
39 #include <sfx2/bindings.hxx>
40 #include <sfx2/request.hxx>
41 #include <sfx2/viewfrm.hxx>
42 
43 
44 #include <svx/svxids.hrc>
45 #include <svx/svdpagv.hxx>
46 
47 #include "app.hrc"
48 #include "ViewShell.hxx"
49 #include "ViewShellBase.hxx"
50 #include "View.hxx"
51 #include "Window.hxx"
52 #include "ToolBarManager.hxx"
53 #include "drawdoc.hxx"
54 #include "res_bmp.hrc"
55 #include <basegfx/polygon/b2dpolygon.hxx>
56 #include <basegfx/polygon/b2dpolygontools.hxx>
57 
58 #include "CustomAnimationEffect.hxx"
59 
60 using namespace ::com::sun::star::uno;
61 
62 namespace sd {
63 
64 TYPEINIT1( FuConstructBezierPolygon, FuConstruct );
65 
66 
67 /*************************************************************************
68 |*
69 |* Konstruktor
70 |*
71 \************************************************************************/
72 
73 FuConstructBezierPolygon::FuConstructBezierPolygon (
74     ViewShell* pViewSh,
75     ::sd::Window* pWin,
76     ::sd::View* pView,
77     SdDrawDocument* pDoc,
78     SfxRequest& rReq)
79     : FuConstruct(pViewSh, pWin, pView, pDoc, rReq),
80       nEditMode(SID_BEZIER_MOVE)
81 {
82 }
83 
84 FunctionReference FuConstructBezierPolygon::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq, bool bPermanent )
85 {
86     FuConstructBezierPolygon* pFunc;
87     FunctionReference xFunc( pFunc = new FuConstructBezierPolygon( pViewSh, pWin, pView, pDoc, rReq ) );
88     xFunc->DoExecute(rReq);
89     pFunc->SetPermanent(bPermanent);
90     return xFunc;
91 }
92 
93 void FuConstructBezierPolygon::DoExecute( SfxRequest& rReq )
94 {
95     FuConstruct::DoExecute( rReq );
96 
97     const SfxItemSet* pArgs = rReq.GetArgs();
98     if( pArgs )
99     {
100         const SfxPoolItem*  pPoolItem = NULL;
101         if( SFX_ITEM_SET == pArgs->GetItemState( SID_ADD_MOTION_PATH, sal_True, &pPoolItem ) )
102             maTargets = ( ( const SfxUnoAnyItem* ) pPoolItem )->GetValue();
103     }
104 }
105 
106 /*************************************************************************
107 |*
108 |* MouseButtonDown-event
109 |*
110 \************************************************************************/
111 
112 sal_Bool FuConstructBezierPolygon::MouseButtonDown(const MouseEvent& rMEvt)
113 {
114     sal_Bool bReturn = FuConstruct::MouseButtonDown(rMEvt);
115 
116     SdrViewEvent aVEvt;
117     SdrHitKind eHit = mpView->PickAnything(rMEvt, SDRMOUSEBUTTONDOWN, aVEvt);
118 
119     if (eHit == SDRHIT_HANDLE || rMEvt.IsMod1())
120     {
121         mpView->SetEditMode(SDREDITMODE_EDIT);
122     }
123     else
124     {
125         mpView->SetEditMode(SDREDITMODE_CREATE);
126     }
127 
128     if (aVEvt.eEvent == SDREVENT_BEGTEXTEDIT)
129     {
130         // Texteingabe hier nicht zulassen
131         aVEvt.eEvent = SDREVENT_BEGDRAGOBJ;
132         mpView->EnableExtendedMouseEventDispatcher(sal_False);
133     }
134     else
135     {
136         mpView->EnableExtendedMouseEventDispatcher(sal_True);
137     }
138 
139     if (eHit == SDRHIT_MARKEDOBJECT && nEditMode == SID_BEZIER_INSERT)
140     {
141         /******************************************************************
142         * Klebepunkt einfuegen
143         ******************************************************************/
144         mpView->BegInsObjPoint(aMDPos, rMEvt.IsMod1());
145     }
146     else
147     {
148         mpView->MouseButtonDown(rMEvt, mpWindow);
149 
150         SdrObject* pObj = mpView->GetCreateObj();
151 
152         if (pObj)
153         {
154             SfxItemSet aAttr(mpDoc->GetPool());
155             SetStyleSheet(aAttr, pObj);
156             pObj->SetMergedItemSet(aAttr);
157         }
158     }
159 
160     return(bReturn);
161 }
162 
163 /*************************************************************************
164 |*
165 |* MouseMove-event
166 |*
167 \************************************************************************/
168 
169 sal_Bool FuConstructBezierPolygon::MouseMove(const MouseEvent& rMEvt)
170 {
171     sal_Bool bReturn = FuConstruct::MouseMove(rMEvt);
172     return(bReturn);
173 }
174 
175 /*************************************************************************
176 |*
177 |* MouseButtonUp-event
178 |*
179 \************************************************************************/
180 
181 sal_Bool FuConstructBezierPolygon::MouseButtonUp(const MouseEvent& rMEvt )
182 {
183     sal_Bool bReturn = sal_False;
184     sal_Bool bCreated = sal_False;
185 
186     SdrViewEvent aVEvt;
187     mpView->PickAnything(rMEvt, SDRMOUSEBUTTONUP, aVEvt);
188 
189     sal_uLong nCount = mpView->GetSdrPageView()->GetObjList()->GetObjCount();
190 
191     if (mpView->IsInsObjPoint())
192     {
193         mpView->EndInsObjPoint(SDRCREATE_FORCEEND);
194     }
195     else
196     {
197         mpView->MouseButtonUp(rMEvt, mpWindow);
198     }
199 
200     if (aVEvt.eEvent == SDREVENT_ENDCREATE)
201     {
202         bReturn = sal_True;
203 
204         if (nCount == (mpView->GetSdrPageView()->GetObjList()->GetObjCount() - 1))
205         {
206             bCreated = sal_True;
207         }
208 
209         // Trick, um FuDraw::DoubleClick nicht auszuloesen
210         bMBDown = sal_False;
211 
212     }
213 
214     bReturn = FuConstruct::MouseButtonUp(rMEvt) || bReturn;
215 
216     bool bDeleted = false;
217     if( bCreated && maTargets.hasValue() )
218     {
219         SdrPathObj* pPathObj = dynamic_cast< SdrPathObj* >( mpView->GetSdrPageView()->GetObjList()->GetObj( nCount ) );
220         SdPage* pPage = dynamic_cast< SdPage* >( pPathObj ? pPathObj->GetPage() : 0 );
221         if( pPage )
222         {
223             boost::shared_ptr< sd::MainSequence > pMainSequence( pPage->getMainSequence() );
224             if( pMainSequence.get() )
225             {
226                 Sequence< Any > aTargets;
227                 maTargets >>= aTargets;
228 
229                 sal_Int32 nTCount = aTargets.getLength();
230                 if( nTCount > 1 )
231                 {
232                     const Any* pTarget = aTargets.getConstArray();
233                     double fDuration = 0.0;
234                     *pTarget++ >>= fDuration;
235                     bool bFirst = true;
236                     while( --nTCount )
237                     {
238                         CustomAnimationEffectPtr pCreated( pMainSequence->append( *pPathObj, *pTarget++, fDuration ) );
239                         if( bFirst )
240                             bFirst = false;
241                         else
242                             pCreated->setNodeType( ::com::sun::star::presentation::EffectNodeType::WITH_PREVIOUS );
243                     }
244                 }
245             }
246         }
247         mpView->DeleteMarked();
248         bDeleted = true;
249     }
250 
251     if ((!bPermanent && bCreated) || bDeleted)
252     {
253         mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SFX_CALLMODE_ASYNCHRON);
254     }
255 
256     return(bReturn);
257 }
258 
259 /*************************************************************************
260 |*
261 |* Tastaturereignisse bearbeiten
262 |*
263 |* Wird ein KeyEvent bearbeitet, so ist der Return-Wert sal_True, andernfalls
264 |* sal_False.
265 |*
266 \************************************************************************/
267 
268 sal_Bool FuConstructBezierPolygon::KeyInput(const KeyEvent& rKEvt)
269 {
270     sal_Bool bReturn = FuConstruct::KeyInput(rKEvt);
271 
272     return(bReturn);
273 }
274 
275 /*************************************************************************
276 |*
277 |* Function aktivieren
278 |*
279 \************************************************************************/
280 
281 void FuConstructBezierPolygon::Activate()
282 {
283     mpView->EnableExtendedMouseEventDispatcher(sal_True);
284 
285     SdrObjKind eKind;
286 
287     switch (nSlotId)
288     {
289         case SID_DRAW_POLYGON_NOFILL:
290         case SID_DRAW_XPOLYGON_NOFILL:
291         {
292             eKind = OBJ_PLIN;
293         }
294         break;
295 
296         case SID_DRAW_POLYGON:
297         case SID_DRAW_XPOLYGON:
298         {
299             eKind = OBJ_POLY;
300         }
301         break;
302 
303         case SID_DRAW_BEZIER_NOFILL:
304         {
305             eKind = OBJ_PATHLINE;
306         }
307         break;
308 
309         case SID_DRAW_BEZIER_FILL:
310         {
311             eKind = OBJ_PATHFILL;
312         }
313         break;
314 
315         case SID_DRAW_FREELINE_NOFILL:
316         {
317             eKind = OBJ_FREELINE;
318         }
319         break;
320 
321         case SID_DRAW_FREELINE:
322         {
323             eKind = OBJ_FREEFILL;
324         }
325         break;
326 
327         default:
328         {
329             eKind = OBJ_PATHLINE;
330         }
331         break;
332     }
333 
334     mpView->SetCurrentObj((sal_uInt16)eKind);
335 
336     FuConstruct::Activate();
337 }
338 
339 /*************************************************************************
340 |*
341 |* Function deaktivieren
342 |*
343 \************************************************************************/
344 
345 void FuConstructBezierPolygon::Deactivate()
346 {
347     mpView->EnableExtendedMouseEventDispatcher(sal_False);
348 
349     FuConstruct::Deactivate();
350 }
351 
352 
353 /*************************************************************************
354 |*
355 |* Selektion hat sich geaendert
356 |*
357 \************************************************************************/
358 
359 void FuConstructBezierPolygon::SelectionHasChanged()
360 {
361     FuDraw::SelectionHasChanged();
362 
363     mpViewShell->GetViewShellBase().GetToolBarManager()->SelectionHasChanged(
364         *mpViewShell,
365         *mpView);
366 }
367 
368 
369 
370 /*************************************************************************
371 |*
372 |* Aktuellen Bezier-Editmodus setzen
373 |*
374 \************************************************************************/
375 
376 void FuConstructBezierPolygon::SetEditMode(sal_uInt16 nMode)
377 {
378     nEditMode = nMode;
379     ForcePointer();
380 
381     SfxBindings& rBindings = mpViewShell->GetViewFrame()->GetBindings();
382     rBindings.Invalidate(SID_BEZIER_MOVE);
383     rBindings.Invalidate(SID_BEZIER_INSERT);
384 }
385 
386 // #97016#
387 SdrObject* FuConstructBezierPolygon::CreateDefaultObject(const sal_uInt16 nID, const Rectangle& rRectangle)
388 {
389     // case SID_DRAW_POLYGON:
390     // case SID_DRAW_POLYGON_NOFILL:
391     // case SID_DRAW_XPOLYGON:
392     // case SID_DRAW_XPOLYGON_NOFILL:
393     // case SID_DRAW_FREELINE:
394     // case SID_DRAW_FREELINE_NOFILL:
395     // case SID_DRAW_BEZIER_FILL:          // BASIC
396     // case SID_DRAW_BEZIER_NOFILL:        // BASIC
397 
398     SdrObject* pObj = SdrObjFactory::MakeNewObject(
399         mpView->GetCurrentObjInventor(), mpView->GetCurrentObjIdentifier(),
400         0L, mpDoc);
401 
402     if(pObj)
403     {
404         if(pObj->ISA(SdrPathObj))
405         {
406             basegfx::B2DPolyPolygon aPoly;
407 
408             switch(nID)
409             {
410                 case SID_DRAW_BEZIER_FILL:
411                 {
412                     const sal_Int32 nWdt(rRectangle.GetWidth() / 2);
413                     const sal_Int32 nHgt(rRectangle.GetHeight() / 2);
414                     const basegfx::B2DPolygon aInnerPoly(basegfx::tools::createPolygonFromEllipse(basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Center().Y()), nWdt, nHgt));
415 
416                     aPoly.append(aInnerPoly);
417                     break;
418                 }
419                 case SID_DRAW_BEZIER_NOFILL:
420                 {
421                     basegfx::B2DPolygon aInnerPoly;
422 
423                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom()));
424 
425                     const basegfx::B2DPoint aCenterBottom(rRectangle.Center().X(), rRectangle.Bottom());
426                     aInnerPoly.appendBezierSegment(
427                         aCenterBottom,
428                         aCenterBottom,
429                         basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Center().Y()));
430 
431                     const basegfx::B2DPoint aCenterTop(rRectangle.Center().X(), rRectangle.Top());
432                     aInnerPoly.appendBezierSegment(
433                         aCenterTop,
434                         aCenterTop,
435                         basegfx::B2DPoint(rRectangle.Right(), rRectangle.Top()));
436 
437                     aPoly.append(aInnerPoly);
438                     break;
439                 }
440                 case SID_DRAW_FREELINE:
441                 case SID_DRAW_FREELINE_NOFILL:
442                 {
443                     basegfx::B2DPolygon aInnerPoly;
444 
445                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom()));
446 
447                     aInnerPoly.appendBezierSegment(
448                         basegfx::B2DPoint(rRectangle.Left(), rRectangle.Top()),
449                         basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Top()),
450                         basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Center().Y()));
451 
452                     aInnerPoly.appendBezierSegment(
453                         basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Bottom()),
454                         basegfx::B2DPoint(rRectangle.Right(), rRectangle.Bottom()),
455                         basegfx::B2DPoint(rRectangle.Right(), rRectangle.Top()));
456 
457                     if(SID_DRAW_FREELINE == nID)
458                     {
459                         aInnerPoly.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Bottom()));
460                     }
461                     else
462                     {
463                         aInnerPoly.setClosed(true);
464                     }
465 
466                     aPoly.append(aInnerPoly);
467                     break;
468                 }
469                 case SID_DRAW_XPOLYGON:
470                 case SID_DRAW_XPOLYGON_NOFILL:
471                 {
472                     basegfx::B2DPolygon aInnerPoly;
473 
474                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom()));
475                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Top()));
476                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Top()));
477                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Center().Y()));
478                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Center().Y()));
479                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Bottom()));
480 
481                     if(SID_DRAW_XPOLYGON_NOFILL == nID)
482                     {
483                         aInnerPoly.append(basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Bottom()));
484                     }
485                     else
486                     {
487                         aInnerPoly.setClosed(true);
488                     }
489 
490                     aPoly.append(aInnerPoly);
491                     break;
492                 }
493                 case SID_DRAW_POLYGON:
494                 case SID_DRAW_POLYGON_NOFILL:
495                 {
496                     basegfx::B2DPolygon aInnerPoly;
497                     const sal_Int32 nWdt(rRectangle.GetWidth());
498                     const sal_Int32 nHgt(rRectangle.GetHeight());
499 
500                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom()));
501                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + (nWdt * 30) / 100, rRectangle.Top() + (nHgt * 70) / 100));
502                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Top() + (nHgt * 15) / 100));
503                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + (nWdt * 65) / 100, rRectangle.Top()));
504                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + nWdt, rRectangle.Top() + (nHgt * 30) / 100));
505                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + (nWdt * 80) / 100, rRectangle.Top() + (nHgt * 50) / 100));
506                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + (nWdt * 80) / 100, rRectangle.Top() + (nHgt * 75) / 100));
507                     aInnerPoly.append(basegfx::B2DPoint(rRectangle.Bottom(), rRectangle.Right()));
508 
509                     if(SID_DRAW_POLYGON_NOFILL == nID)
510                     {
511                         aInnerPoly.append(basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Bottom()));
512                     }
513                     else
514                     {
515                         aInnerPoly.setClosed(true);
516                     }
517 
518                     aPoly.append(aInnerPoly);
519                     break;
520                 }
521             }
522 
523             ((SdrPathObj*)pObj)->SetPathPoly(aPoly);
524         }
525         else
526         {
527             DBG_ERROR("Object is NO path object");
528         }
529 
530         pObj->SetLogicRect(rRectangle);
531     }
532 
533     return pObj;
534 }
535 
536 } // end of namespace sd
537 
538 // eof
539