xref: /trunk/main/svx/source/dialog/dlgctl3d.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_svx.hxx"
30 
31 #include <svx/dlgctl3d.hxx>
32 #include <svx/dialogs.hrc>
33 #include <svx/view3d.hxx>
34 #include <svx/fmmodel.hxx>
35 #include <svl/itempool.hxx>
36 #include <svx/fmpage.hxx>
37 #include <svx/polysc3d.hxx>
38 #include <svx/sphere3d.hxx>
39 #include <svx/cube3d.hxx>
40 #include <vcl/svapp.hxx>
41 #include <svx/helperhittest3d.hxx>
42 #include <basegfx/polygon/b2dpolygontools.hxx>
43 #include <svx/polygn3d.hxx>
44 #include <svx/xlnclit.hxx>
45 #include <svx/xlnwtit.hxx>
46 #include "helpid.hrc"
47 #include <algorithm>
48 #include <svx/dialmgr.hxx>
49 
50 //////////////////////////////////////////////////////////////////////////////
51 
52 Svx3DPreviewControl::Svx3DPreviewControl(Window* pParent, const ResId& rResId)
53 :   Control(pParent, rResId),
54     mpModel(0),
55     mpFmPage(0),
56     mp3DView(0),
57     mpScene(0),
58     mp3DObj(0),
59     mnObjectType(PREVIEW_OBJECTTYPE_SPHERE)
60 {
61     Construct();
62 
63     // do not paint background self, DrawingLayer paints this buffered and as page
64     SetControlBackground();
65     SetBackground();
66 }
67 
68 Svx3DPreviewControl::Svx3DPreviewControl(Window* pParent, WinBits nStyle)
69 :   Control(pParent, nStyle),
70     mpModel(0),
71     mpFmPage(0),
72     mp3DView(0),
73     mpScene(0),
74     mp3DObj(0),
75     mnObjectType(PREVIEW_OBJECTTYPE_SPHERE)
76 {
77     Construct();
78 
79     // do not paint background self, DrawingLayer paints this buffered and as page
80     SetControlBackground();
81     SetBackground();
82 }
83 
84 Svx3DPreviewControl::~Svx3DPreviewControl()
85 {
86     delete mp3DView;
87     delete mpModel;
88 }
89 
90 void Svx3DPreviewControl::Construct()
91 {
92     // Do never mirror the preview window.  This explicitly includes right
93     // to left writing environments.
94     EnableRTL (sal_False);
95     SetMapMode( MAP_100TH_MM );
96 
97     // Model
98     mpModel = new FmFormModel();
99     mpModel->GetItemPool().FreezeIdRanges();
100 
101     // Page
102     mpFmPage = new FmFormPage( *mpModel, NULL );
103     mpModel->InsertPage( mpFmPage, 0 );
104 
105     // 3D View
106     mp3DView = new E3dView( mpModel, this );
107     mp3DView->SetBufferedOutputAllowed(true);
108     mp3DView->SetBufferedOverlayAllowed(true);
109 
110     // 3D Scene
111     mpScene = new E3dPolyScene(mp3DView->Get3DDefaultAttributes());
112 
113     // initially create object
114     SetObjectType(PREVIEW_OBJECTTYPE_SPHERE);
115 
116     // camera and perspective
117     Camera3D& rCamera  = (Camera3D&) mpScene->GetCamera();
118     const basegfx::B3DRange& rVolume = mpScene->GetBoundVolume();
119     double fW = rVolume.getWidth();
120     double fH = rVolume.getHeight();
121     double fCamZ = rVolume.getMaxZ() + ((fW + fH) / 2.0);
122 
123     rCamera.SetAutoAdjustProjection(sal_False);
124     rCamera.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
125     basegfx::B3DPoint aLookAt;
126     double fDefaultCamPosZ = mp3DView->GetDefaultCamPosZ();
127     basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
128     rCamera.SetPosAndLookAt(aCamPos, aLookAt);
129     double fDefaultCamFocal = mp3DView->GetDefaultCamFocal();
130     rCamera.SetFocalLength(fDefaultCamFocal);
131     rCamera.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ), aLookAt, fDefaultCamFocal);
132 
133     mpScene->SetCamera( rCamera );
134     mpFmPage->InsertObject( mpScene );
135 
136     basegfx::B3DHomMatrix aRotation;
137     aRotation.rotate(DEG2RAD( 25 ), 0.0, 0.0);
138     aRotation.rotate(0.0, DEG2RAD( 40 ), 0.0);
139     mpScene->SetTransform(aRotation * mpScene->GetTransform());
140 
141     // invalidate SnapRects of objects
142     mpScene->SetRectsDirty();
143 
144     SfxItemSet aSet( mpModel->GetItemPool(),
145         XATTR_LINESTYLE, XATTR_LINESTYLE,
146         XATTR_FILL_FIRST, XATTR_FILLBITMAP,
147         0, 0 );
148     aSet.Put( XLineStyleItem( XLINE_NONE ) );
149     aSet.Put( XFillStyleItem( XFILL_SOLID ) );
150     aSet.Put( XFillColorItem( String(), Color( COL_WHITE ) ) );
151 
152     mpScene->SetMergedItemSet(aSet);
153 
154     // PageView
155     SdrPageView* pPageView = mp3DView->ShowSdrPage( mpFmPage );
156     mp3DView->hideMarkHandles();
157 
158     // mark scene
159     mp3DView->MarkObj( mpScene, pPageView );
160 }
161 
162 void Svx3DPreviewControl::Resize()
163 {
164     // size of page
165     Size aSize( GetSizePixel() );
166     aSize = PixelToLogic( aSize );
167     mpFmPage->SetSize( aSize );
168 
169     // set size
170     Size aObjSize( aSize.Width()*5/6, aSize.Height()*5/6 );
171     Point aObjPoint( (aSize.Width() - aObjSize.Width()) / 2,
172         (aSize.Height() - aObjSize.Height()) / 2);
173     Rectangle aRect( aObjPoint, aObjSize);
174     mpScene->SetSnapRect( aRect );
175 }
176 
177 void Svx3DPreviewControl::Paint(const Rectangle& rRect)
178 {
179     mp3DView->CompleteRedraw(this, Region(rRect));
180 }
181 
182 void Svx3DPreviewControl::MouseButtonDown(const MouseEvent& rMEvt)
183 {
184     Control::MouseButtonDown(rMEvt);
185 
186     if( rMEvt.IsShift() && rMEvt.IsMod1() )
187     {
188         if(PREVIEW_OBJECTTYPE_SPHERE == GetObjectType())
189         {
190             SetObjectType(PREVIEW_OBJECTTYPE_CUBE);
191         }
192         else
193         {
194             SetObjectType(PREVIEW_OBJECTTYPE_SPHERE);
195         }
196     }
197 }
198 
199 void Svx3DPreviewControl::SetObjectType(sal_uInt16 nType)
200 {
201     if( mnObjectType != nType || !mp3DObj)
202     {
203         SfxItemSet aSet(mpModel->GetItemPool(), SDRATTR_START, SDRATTR_END, 0, 0);
204         mnObjectType = nType;
205 
206         if( mp3DObj )
207         {
208             aSet.Put(mp3DObj->GetMergedItemSet());
209             mpScene->Remove3DObj( mp3DObj );
210             delete mp3DObj;
211             mp3DObj = NULL;
212         }
213 
214         switch( nType )
215         {
216             case PREVIEW_OBJECTTYPE_SPHERE:
217             {
218                 mp3DObj = new E3dSphereObj(
219                     mp3DView->Get3DDefaultAttributes(),
220                     basegfx::B3DPoint( 0, 0, 0 ),
221                     basegfx::B3DVector( 5000, 5000, 5000 ));
222             }
223             break;
224 
225             case PREVIEW_OBJECTTYPE_CUBE:
226             {
227                 mp3DObj = new E3dCubeObj(
228                     mp3DView->Get3DDefaultAttributes(),
229                     basegfx::B3DPoint( -2500, -2500, -2500 ),
230                     basegfx::B3DVector( 5000, 5000, 5000 ));
231             }
232             break;
233         }
234 
235         mpScene->Insert3DObj( mp3DObj );
236         mp3DObj->SetMergedItemSet(aSet);
237 
238         Resize();
239     }
240 }
241 
242 SfxItemSet Svx3DPreviewControl::Get3DAttributes() const
243 {
244     return mp3DObj->GetMergedItemSet();
245 }
246 
247 void Svx3DPreviewControl::Set3DAttributes( const SfxItemSet& rAttr )
248 {
249     mp3DObj->SetMergedItemSet(rAttr, true);
250     Resize();
251 }
252 
253 //////////////////////////////////////////////////////////////////////////////
254 
255 #define RADIUS_LAMP_PREVIEW_SIZE    (4500.0)
256 #define RADIUS_LAMP_SMALL           (600.0)
257 #define RADIUS_LAMP_BIG             (1000.0)
258 #define NO_LIGHT_SELECTED           (0xffffffff)
259 #define MAX_NUMBER_LIGHTS              (8)
260 
261 Svx3DLightControl::Svx3DLightControl(Window* pParent, const ResId& rResId)
262 :   Svx3DPreviewControl(pParent, rResId),
263     maUserInteractiveChangeCallback(),
264     maUserSelectionChangeCallback(),
265     maChangeCallback(),
266     maSelectionChangeCallback(),
267     maSelectedLight(NO_LIGHT_SELECTED),
268     mpExpansionObject(0),
269     mpLampBottomObject(0),
270     mpLampShaftObject(0),
271     maLightObjects(MAX_NUMBER_LIGHTS, (E3dObject*)0),
272     mfRotateX(-20.0),
273     mfRotateY(45.0),
274     mfRotateZ(0.0),
275     maActionStartPoint(),
276     mnInteractionStartDistance(5 * 5 * 2),
277     mfSaveActionStartHor(0.0),
278     mfSaveActionStartVer(0.0),
279     mfSaveActionStartRotZ(0.0),
280     mbMouseMoved(false),
281     mbGeometrySelected(false)
282 {
283     Construct2();
284 }
285 
286 Svx3DLightControl::Svx3DLightControl(Window* pParent, WinBits nStyle)
287 :   Svx3DPreviewControl(pParent, nStyle),
288     maUserInteractiveChangeCallback(),
289     maUserSelectionChangeCallback(),
290     maChangeCallback(),
291     maSelectionChangeCallback(),
292     maSelectedLight(NO_LIGHT_SELECTED),
293     mpExpansionObject(0),
294     mpLampBottomObject(0),
295     mpLampShaftObject(0),
296     maLightObjects(MAX_NUMBER_LIGHTS, (E3dObject*)0),
297     mfRotateX(-20.0),
298     mfRotateY(45.0),
299     mfRotateZ(0.0),
300     maActionStartPoint(),
301     mnInteractionStartDistance(5 * 5 * 2),
302     mfSaveActionStartHor(0.0),
303     mfSaveActionStartVer(0.0),
304     mfSaveActionStartRotZ(0.0),
305     mbMouseMoved(false),
306     mbGeometrySelected(false)
307 {
308     Construct2();
309 }
310 
311 Svx3DLightControl::~Svx3DLightControl()
312 {
313     // SdrObjects like mpExpansionObject and mpLampBottomObject/mpLampShaftObject get deleted
314     // with deletion of the DrawingLayer and model
315 }
316 
317 void Svx3DLightControl::Construct2()
318 {
319     {
320         // hide all page stuff, use control background (normally gray)
321         const Color aDialogColor(Application::GetSettings().GetStyleSettings().GetDialogColor());
322         mp3DView->SetPageVisible(false);
323         mp3DView->SetApplicationBackgroundColor(aDialogColor);
324         mp3DView->SetApplicationDocumentColor(aDialogColor);
325     }
326 
327     {
328         // create invisible expansion object
329         const double fMaxExpansion(RADIUS_LAMP_BIG + RADIUS_LAMP_PREVIEW_SIZE);
330         mpExpansionObject = new E3dCubeObj(
331             mp3DView->Get3DDefaultAttributes(),
332             basegfx::B3DPoint(-fMaxExpansion, -fMaxExpansion, -fMaxExpansion),
333             basegfx::B3DVector(2.0 * fMaxExpansion, 2.0 * fMaxExpansion, 2.0 * fMaxExpansion));
334         mpScene->Insert3DObj( mpExpansionObject );
335         SfxItemSet aSet(mpModel->GetItemPool());
336         aSet.Put( XLineStyleItem( XLINE_NONE ) );
337         aSet.Put( XFillStyleItem( XFILL_NONE ) );
338         mpExpansionObject->SetMergedItemSet(aSet);
339     }
340 
341     {
342         // create lamp control object (Yellow lined object)
343         // base circle
344         const basegfx::B2DPolygon a2DCircle(basegfx::tools::createPolygonFromCircle(basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE));
345         basegfx::B3DPolygon a3DCircle(basegfx::tools::createB3DPolygonFromB2DPolygon(a2DCircle));
346         basegfx::B3DHomMatrix aTransform;
347 
348         aTransform.rotate(F_PI2, 0.0, 0.0);
349         aTransform.translate(0.0, -RADIUS_LAMP_PREVIEW_SIZE, 0.0);
350         a3DCircle.transform(aTransform);
351 
352         // create object for it
353         mpLampBottomObject = new E3dPolygonObj(
354             mp3DView->Get3DDefaultAttributes(),
355             basegfx::B3DPolyPolygon(a3DCircle),
356             true);
357         mpScene->Insert3DObj( mpLampBottomObject );
358 
359         // half circle with stand
360         basegfx::B2DPolygon a2DHalfCircle;
361         a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, 0.0));
362         a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, -RADIUS_LAMP_PREVIEW_SIZE));
363         a2DHalfCircle.append(basegfx::tools::createPolygonFromEllipseSegment(
364             basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE, RADIUS_LAMP_PREVIEW_SIZE, F_2PI - F_PI2, F_PI2));
365         basegfx::B3DPolygon a3DHalfCircle(basegfx::tools::createB3DPolygonFromB2DPolygon(a2DHalfCircle));
366 
367         // create object for it
368         mpLampShaftObject = new E3dPolygonObj(
369             mp3DView->Get3DDefaultAttributes(),
370             basegfx::B3DPolyPolygon(a3DHalfCircle),
371             true);
372         mpScene->Insert3DObj( mpLampShaftObject );
373 
374         // initially invisible
375         SfxItemSet aSet(mpModel->GetItemPool());
376         aSet.Put( XLineStyleItem( XLINE_NONE ) );
377         aSet.Put( XFillStyleItem( XFILL_NONE ) );
378 
379         mpLampBottomObject->SetMergedItemSet(aSet);
380         mpLampShaftObject->SetMergedItemSet(aSet);
381     }
382 
383     {
384         // change camera settings
385         Camera3D& rCamera  = (Camera3D&) mpScene->GetCamera();
386         const basegfx::B3DRange& rVolume = mpScene->GetBoundVolume();
387         double fW = rVolume.getWidth();
388         double fH = rVolume.getHeight();
389         double fCamZ = rVolume.getMaxZ() + ((fW + fH) / 2.0);
390 
391         rCamera.SetAutoAdjustProjection(sal_False);
392         rCamera.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
393         basegfx::B3DPoint aLookAt;
394         double fDefaultCamPosZ = mp3DView->GetDefaultCamPosZ();
395         basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
396         rCamera.SetPosAndLookAt(aCamPos, aLookAt);
397         double fDefaultCamFocal = mp3DView->GetDefaultCamFocal();
398         rCamera.SetFocalLength(fDefaultCamFocal);
399         rCamera.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ), aLookAt, fDefaultCamFocal);
400 
401         mpScene->SetCamera( rCamera );
402 
403         basegfx::B3DHomMatrix aNeutral;
404         mpScene->SetTransform(aNeutral);
405     }
406 
407     // invalidate SnapRects of objects
408     mpScene->SetRectsDirty();
409 }
410 
411 void Svx3DLightControl::ConstructLightObjects()
412 {
413     for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
414     {
415         // get rid of evtl. existing light object
416         if(maLightObjects[a])
417         {
418             mpScene->Remove3DObj(maLightObjects[a]);
419             delete maLightObjects[a];
420             maLightObjects[a] = 0;
421         }
422 
423         if(GetLightOnOff(a))
424         {
425             const bool bIsSelectedLight(a == maSelectedLight);
426             basegfx::B3DVector aDirection(GetLightDirection(a));
427             aDirection.normalize();
428             aDirection *= RADIUS_LAMP_PREVIEW_SIZE;
429 
430             const double fLampSize(bIsSelectedLight ? RADIUS_LAMP_BIG : RADIUS_LAMP_SMALL);
431             E3dObject* pNewLight = new E3dSphereObj(
432                 mp3DView->Get3DDefaultAttributes(),
433                 basegfx::B3DPoint( 0, 0, 0 ),
434                 basegfx::B3DVector( fLampSize, fLampSize, fLampSize));
435             mpScene->Insert3DObj(pNewLight);
436 
437             basegfx::B3DHomMatrix aTransform;
438             aTransform.translate(aDirection.getX(), aDirection.getY(), aDirection.getZ());
439             pNewLight->SetTransform(aTransform);
440 
441             SfxItemSet aSet(mpModel->GetItemPool());
442             aSet.Put( XLineStyleItem( XLINE_NONE ) );
443             aSet.Put( XFillStyleItem( XFILL_SOLID ) );
444             aSet.Put( XFillColorItem(String(), GetLightColor(a)));
445             pNewLight->SetMergedItemSet(aSet);
446 
447             maLightObjects[a] = pNewLight;
448         }
449     }
450 }
451 
452 void Svx3DLightControl::AdaptToSelectedLight()
453 {
454     if(NO_LIGHT_SELECTED == maSelectedLight)
455     {
456         // make mpLampBottomObject/mpLampShaftObject invisible
457         SfxItemSet aSet(mpModel->GetItemPool());
458         aSet.Put( XLineStyleItem( XLINE_NONE ) );
459         aSet.Put( XFillStyleItem( XFILL_NONE ) );
460         mpLampBottomObject->SetMergedItemSet(aSet);
461         mpLampShaftObject->SetMergedItemSet(aSet);
462     }
463     else
464     {
465         basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
466         aDirection.normalize();
467 
468         // make mpLampBottomObject/mpLampShaftObject visible (yellow hairline)
469         SfxItemSet aSet(mpModel->GetItemPool());
470         aSet.Put( XLineStyleItem( XLINE_SOLID ) );
471         aSet.Put( XLineColorItem(String(), COL_YELLOW));
472         aSet.Put( XLineWidthItem(0));
473         aSet.Put( XFillStyleItem( XFILL_NONE ) );
474         mpLampBottomObject->SetMergedItemSet(aSet);
475         mpLampShaftObject->SetMergedItemSet(aSet);
476 
477         // adapt transformation of mpLampShaftObject
478         basegfx::B3DHomMatrix aTransform;
479         double fRotateY(0.0);
480 
481         if(!basegfx::fTools::equalZero(aDirection.getZ()) || !basegfx::fTools::equalZero(aDirection.getX()))
482         {
483             fRotateY = atan2(-aDirection.getZ(), aDirection.getX());
484         }
485 
486         aTransform.rotate(0.0, fRotateY, 0.0);
487         mpLampShaftObject->SetTransform(aTransform);
488 
489         // adapt transformation of selected light
490         E3dObject* pSelectedLight = maLightObjects[sal_Int32(maSelectedLight)];
491 
492         if(pSelectedLight)
493         {
494             aTransform.identity();
495             aTransform.translate(
496                 aDirection.getX() * RADIUS_LAMP_PREVIEW_SIZE,
497                 aDirection.getY() * RADIUS_LAMP_PREVIEW_SIZE,
498                 aDirection.getZ() * RADIUS_LAMP_PREVIEW_SIZE);
499             pSelectedLight->SetTransform(aTransform);
500         }
501     }
502 }
503 
504 void Svx3DLightControl::TrySelection(Point aPosPixel)
505 {
506     if(mpScene)
507     {
508         const Point aPosLogic(PixelToLogic(aPosPixel));
509         const basegfx::B2DPoint aPoint(aPosLogic.X(), aPosLogic.Y());
510         std::vector< const E3dCompoundObject* > aResult;
511         getAllHit3DObjectsSortedFrontToBack(aPoint, *mpScene, aResult);
512 
513         if(!aResult.empty())
514         {
515             // exclude expansion object which will be part of
516             // the hits. It's invisible, but for HitTest, it's included
517             const E3dCompoundObject* pResult = 0;
518 
519             for(sal_uInt32 b(0); !pResult && b < aResult.size(); b++)
520             {
521                 if(aResult[b] && aResult[b] != mpExpansionObject)
522                 {
523                     pResult = aResult[b];
524                 }
525             }
526 
527             if(pResult == mp3DObj)
528             {
529                 if(!mbGeometrySelected)
530                 {
531                     mbGeometrySelected = true;
532                     maSelectedLight = NO_LIGHT_SELECTED;
533                     ConstructLightObjects();
534                     AdaptToSelectedLight();
535                     Invalidate();
536 
537                     if(maSelectionChangeCallback.IsSet())
538                     {
539                         maSelectionChangeCallback.Call(this);
540                     }
541                 }
542             }
543             else
544             {
545                 sal_uInt32 aNewSelectedLight(NO_LIGHT_SELECTED);
546 
547                 for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
548                 {
549                     if(maLightObjects[a] && maLightObjects[a] == pResult)
550                     {
551                         aNewSelectedLight = a;
552                     }
553                 }
554 
555                 if(aNewSelectedLight != maSelectedLight)
556                 {
557                     SelectLight(aNewSelectedLight);
558 
559                     if(maSelectionChangeCallback.IsSet())
560                     {
561                         maSelectionChangeCallback.Call(this);
562                     }
563                 }
564             }
565         }
566     }
567 }
568 
569 void Svx3DLightControl::Paint(const Rectangle& rRect)
570 {
571     Svx3DPreviewControl::Paint(rRect);
572 }
573 
574 void Svx3DLightControl::MouseButtonDown( const MouseEvent& rMEvt )
575 {
576     bool bCallParent(true);
577 
578     // switch state
579     if(rMEvt.IsLeft())
580     {
581         if(IsSelectionValid() || mbGeometrySelected)
582         {
583             mbMouseMoved = false;
584             bCallParent = false;
585             maActionStartPoint = rMEvt.GetPosPixel();
586             StartTracking();
587         }
588         else
589         {
590             // Einfacher Click ohne viel Bewegen, versuche eine
591             // Selektion
592             TrySelection(rMEvt.GetPosPixel());
593             bCallParent = false;
594         }
595     }
596 
597     // call parent
598     if(bCallParent)
599     {
600         Svx3DPreviewControl::MouseButtonDown(rMEvt);
601     }
602 }
603 
604 void Svx3DLightControl::Tracking( const TrackingEvent& rTEvt )
605 {
606     if(rTEvt.IsTrackingEnded())
607     {
608         if(rTEvt.IsTrackingCanceled())
609         {
610             if(mbMouseMoved)
611             {
612                 // interrupt tracking
613                 mbMouseMoved = false;
614 
615                 if(mbGeometrySelected)
616                 {
617                     SetRotation(mfSaveActionStartVer, mfSaveActionStartHor, mfSaveActionStartRotZ);
618                 }
619                 else
620                 {
621                     SetPosition(mfSaveActionStartHor, mfSaveActionStartVer);
622                 }
623 
624                 if(maChangeCallback.IsSet())
625                 {
626                     maChangeCallback.Call(this);
627                 }
628             }
629         }
630         else
631         {
632             const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
633 
634             if(mbMouseMoved)
635             {
636                 // was change dinteractively
637             }
638             else
639             {
640                 // simple click without much movement, try selection
641                 TrySelection(rMEvt.GetPosPixel());
642             }
643         }
644     }
645     else
646     {
647         const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
648         Point aDeltaPos = rMEvt.GetPosPixel() - maActionStartPoint;
649 
650         if(!mbMouseMoved)
651         {
652             if(sal_Int32(aDeltaPos.X() * aDeltaPos.X() + aDeltaPos.Y() * aDeltaPos.Y()) > mnInteractionStartDistance)
653             {
654                 if(mbGeometrySelected)
655                 {
656                     GetRotation(mfSaveActionStartVer, mfSaveActionStartHor, mfSaveActionStartRotZ);
657                 }
658                 else
659                 {
660                     // intercation start, save values
661                     GetPosition(mfSaveActionStartHor, mfSaveActionStartVer);
662                 }
663 
664                 mbMouseMoved = true;
665             }
666         }
667 
668         if(mbMouseMoved)
669         {
670             if(mbGeometrySelected)
671             {
672                 double fNewRotX = mfSaveActionStartVer - ((double)aDeltaPos.Y() * F_PI180);
673                 double fNewRotY = mfSaveActionStartHor + ((double)aDeltaPos.X() * F_PI180);
674 
675                 // cut horizontal
676                 while(fNewRotY < 0.0)
677                 {
678                     fNewRotY += F_2PI;
679                 }
680 
681                 while(fNewRotY >= F_2PI)
682                 {
683                     fNewRotY -= F_2PI;
684                 }
685 
686                 // cut vertical
687                 if(fNewRotX < -F_PI2)
688                 {
689                     fNewRotX = -F_PI2;
690                 }
691 
692                 if(fNewRotX > F_PI2)
693                 {
694                     fNewRotX = F_PI2;
695                 }
696 
697                 SetRotation(fNewRotX, fNewRotY, mfSaveActionStartRotZ);
698 
699                 if(maChangeCallback.IsSet())
700                 {
701                     maChangeCallback.Call(this);
702                 }
703             }
704             else
705             {
706                 // interaction in progress
707                 double fNewPosHor = mfSaveActionStartHor + ((double)aDeltaPos.X());
708                 double fNewPosVer = mfSaveActionStartVer - ((double)aDeltaPos.Y());
709 
710                 // cut horizontal
711                 while(fNewPosHor < 0.0)
712                 {
713                     fNewPosHor += 360.0;
714                 }
715 
716                 while(fNewPosHor >= 360.0)
717                 {
718                     fNewPosHor -= 360.0;
719                 }
720 
721                 // cut vertical
722                 if(fNewPosVer < -90.0)
723                 {
724                     fNewPosVer = -90.0;
725                 }
726 
727                 if(fNewPosVer > 90.0)
728                 {
729                     fNewPosVer = 90.0;
730                 }
731 
732                 SetPosition(fNewPosHor, fNewPosVer);
733 
734                 if(maChangeCallback.IsSet())
735                 {
736                     maChangeCallback.Call(this);
737                 }
738             }
739         }
740     }
741 }
742 
743 void Svx3DLightControl::Resize()
744 {
745     // set size of page
746     const Size aSize(PixelToLogic(GetSizePixel()));
747     mpFmPage->SetSize(aSize);
748 
749     // set position and size of scene
750     mpScene->SetSnapRect(Rectangle(Point(0, 0), aSize));
751 }
752 
753 void Svx3DLightControl::SetObjectType(sal_uInt16 nType)
754 {
755     // call parent
756     Svx3DPreviewControl::SetObjectType(nType);
757 
758     // apply object rotation
759     if(mp3DObj)
760     {
761         basegfx::B3DHomMatrix aObjectRotation;
762         aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
763         mp3DObj->SetTransform(aObjectRotation);
764     }
765 }
766 
767 bool Svx3DLightControl::IsSelectionValid()
768 {
769     if((NO_LIGHT_SELECTED != maSelectedLight) && (GetLightOnOff(maSelectedLight)))
770     {
771         return true;
772     }
773 
774     return false;
775 }
776 
777 void Svx3DLightControl::GetPosition(double& rHor, double& rVer)
778 {
779     if(IsSelectionValid())
780     {
781         basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
782         aDirection.normalize();
783         rHor = atan2(-aDirection.getX(), -aDirection.getZ()) + F_PI; // 0..2PI
784         rVer = atan2(aDirection.getY(), aDirection.getXZLength()); // -PI2..PI2
785         rHor /= F_PI180; // 0..360.0
786         rVer /= F_PI180; // -90.0..90.0
787     }
788     if(IsGeometrySelected())
789     {
790         rHor = mfRotateY / F_PI180; // 0..360.0
791         rVer = mfRotateX / F_PI180; // -90.0..90.0
792     }
793 }
794 
795 void Svx3DLightControl::SetPosition(double fHor, double fVer)
796 {
797     if(IsSelectionValid())
798     {
799         // set selected light's direction
800         fHor = (fHor * F_PI180) - F_PI; // -PI..PI
801         fVer *= F_PI180; // -PI2..PI2
802         basegfx::B3DVector aDirection(cos(fVer) * -sin(fHor), sin(fVer), cos(fVer) * -cos(fHor));
803         aDirection.normalize();
804 
805         if(!aDirection.equal(GetLightDirection(maSelectedLight)))
806         {
807             // set changed light direction at SdrScene
808             SfxItemSet aSet(mpModel->GetItemPool());
809 
810             switch(maSelectedLight)
811             {
812                 case 0: aSet.Put(Svx3DLightDirection1Item(aDirection)); break;
813                 case 1: aSet.Put(Svx3DLightDirection2Item(aDirection)); break;
814                 case 2: aSet.Put(Svx3DLightDirection3Item(aDirection)); break;
815                 case 3: aSet.Put(Svx3DLightDirection4Item(aDirection)); break;
816                 case 4: aSet.Put(Svx3DLightDirection5Item(aDirection)); break;
817                 case 5: aSet.Put(Svx3DLightDirection6Item(aDirection)); break;
818                 case 6: aSet.Put(Svx3DLightDirection7Item(aDirection)); break;
819                 default:
820                 case 7: aSet.Put(Svx3DLightDirection8Item(aDirection)); break;
821             }
822 
823             mpScene->SetMergedItemSet(aSet);
824 
825             // correct 3D light's and LampFrame's geometries
826             AdaptToSelectedLight();
827             Invalidate();
828         }
829     }
830     if(IsGeometrySelected())
831     {
832         if(mfRotateX != fVer || mfRotateY != fHor)
833         {
834             mfRotateX = fVer * F_PI180;
835             mfRotateY = fHor * F_PI180;
836 
837             if(mp3DObj)
838             {
839                 basegfx::B3DHomMatrix aObjectRotation;
840                 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
841                 mp3DObj->SetTransform(aObjectRotation);
842 
843                 Invalidate();
844             }
845         }
846     }
847 }
848 
849 void Svx3DLightControl::SetRotation(double fRotX, double fRotY, double fRotZ)
850 {
851     if(IsGeometrySelected())
852     {
853         if(fRotX != mfRotateX || fRotY != mfRotateY || fRotZ != mfRotateZ)
854         {
855             mfRotateX = fRotX;
856             mfRotateY = fRotY;
857             mfRotateZ = fRotZ;
858 
859             if(mp3DObj)
860             {
861                 basegfx::B3DHomMatrix aObjectRotation;
862                 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
863                 mp3DObj->SetTransform(aObjectRotation);
864 
865                 Invalidate();
866             }
867         }
868     }
869 }
870 
871 void Svx3DLightControl::GetRotation(double& rRotX, double& rRotY, double& rRotZ)
872 {
873     rRotX = mfRotateX;
874     rRotY = mfRotateY;
875     rRotZ = mfRotateZ;
876 }
877 
878 void Svx3DLightControl::Set3DAttributes( const SfxItemSet& rAttr )
879 {
880     // call parent
881     Svx3DPreviewControl::Set3DAttributes(rAttr);
882 
883     if(maSelectedLight != NO_LIGHT_SELECTED && !GetLightOnOff(maSelectedLight))
884     {
885         // selected light is no more active, select new one
886         maSelectedLight = NO_LIGHT_SELECTED;
887     }
888 
889     // local updates
890     ConstructLightObjects();
891     AdaptToSelectedLight();
892     Invalidate();
893 }
894 
895 void Svx3DLightControl::SelectLight(sal_uInt32 nLightNumber)
896 {
897     if(nLightNumber > 7)
898     {
899         nLightNumber = NO_LIGHT_SELECTED;
900     }
901 
902     if(NO_LIGHT_SELECTED != nLightNumber)
903     {
904         if(!GetLightOnOff(nLightNumber))
905         {
906             nLightNumber = NO_LIGHT_SELECTED;
907         }
908     }
909 
910     if(nLightNumber != maSelectedLight)
911     {
912         maSelectedLight = nLightNumber;
913         mbGeometrySelected = false;
914         ConstructLightObjects();
915         AdaptToSelectedLight();
916         Invalidate();
917     }
918 }
919 
920 bool Svx3DLightControl::GetLightOnOff(sal_uInt32 nNum) const
921 {
922     if(nNum <= 7)
923     {
924         const SfxItemSet aLightItemSet(Get3DAttributes());
925 
926         switch(nNum)
927         {
928             case 0 : return ((const Svx3DLightOnOff1Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_1)).GetValue();
929             case 1 : return ((const Svx3DLightOnOff2Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_2)).GetValue();
930             case 2 : return ((const Svx3DLightOnOff3Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_3)).GetValue();
931             case 3 : return ((const Svx3DLightOnOff4Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_4)).GetValue();
932             case 4 : return ((const Svx3DLightOnOff5Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_5)).GetValue();
933             case 5 : return ((const Svx3DLightOnOff6Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_6)).GetValue();
934             case 6 : return ((const Svx3DLightOnOff7Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_7)).GetValue();
935             case 7 : return ((const Svx3DLightOnOff8Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_8)).GetValue();
936         }
937     }
938 
939     return false;
940 }
941 
942 Color Svx3DLightControl::GetLightColor(sal_uInt32 nNum) const
943 {
944     if(nNum <= 7)
945     {
946         const SfxItemSet aLightItemSet(Get3DAttributes());
947 
948         switch(nNum)
949         {
950             case 0 : return ((const Svx3DLightcolor1Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1)).GetValue();
951             case 1 : return ((const Svx3DLightcolor2Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2)).GetValue();
952             case 2 : return ((const Svx3DLightcolor3Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3)).GetValue();
953             case 3 : return ((const Svx3DLightcolor4Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4)).GetValue();
954             case 4 : return ((const Svx3DLightcolor5Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5)).GetValue();
955             case 5 : return ((const Svx3DLightcolor6Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6)).GetValue();
956             case 6 : return ((const Svx3DLightcolor7Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7)).GetValue();
957             case 7 : return ((const Svx3DLightcolor8Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8)).GetValue();
958         }
959     }
960 
961     return Color(COL_BLACK);
962 }
963 
964 basegfx::B3DVector Svx3DLightControl::GetLightDirection(sal_uInt32 nNum) const
965 {
966     if(nNum <= 7)
967     {
968         const SfxItemSet aLightItemSet(Get3DAttributes());
969 
970         switch(nNum)
971         {
972             case 0 : return ((const Svx3DLightDirection1Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1)).GetValue();
973             case 1 : return ((const Svx3DLightDirection2Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2)).GetValue();
974             case 2 : return ((const Svx3DLightDirection3Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3)).GetValue();
975             case 3 : return ((const Svx3DLightDirection4Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4)).GetValue();
976             case 4 : return ((const Svx3DLightDirection5Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5)).GetValue();
977             case 5 : return ((const Svx3DLightDirection6Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6)).GetValue();
978             case 6 : return ((const Svx3DLightDirection7Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7)).GetValue();
979             case 7 : return ((const Svx3DLightDirection8Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8)).GetValue();
980         }
981     }
982 
983     return basegfx::B3DVector();
984 }
985 
986 //////////////////////////////////////////////////////////////////////////////
987 
988 SvxLightCtl3D::SvxLightCtl3D( Window* pParent, const ResId& rResId)
989 :   Control(pParent, rResId),
990     maLightControl(this, 0),
991     maHorScroller(this, WB_HORZ | WB_DRAG),
992     maVerScroller(this, WB_VERT | WB_DRAG),
993     maSwitcher(this, 0)
994 {
995     // init members
996     Init();
997 }
998 
999 SvxLightCtl3D::SvxLightCtl3D( Window* pParent, WinBits nStyle )
1000 :   Control(pParent, nStyle),
1001     maLightControl(this, 0),
1002     maHorScroller(this, WB_HORZ | WB_DRAG),
1003     maVerScroller(this, WB_VERT | WB_DRAG),
1004     maSwitcher(this, 0)
1005 {
1006     // init members
1007     Init();
1008 }
1009 
1010 void SvxLightCtl3D::Init()
1011 {
1012     // #i58240# set HelpIDs for scrollbars and switcher
1013     maHorScroller.SetHelpId(HID_CTRL3D_HSCROLL);
1014     maVerScroller.SetHelpId(HID_CTRL3D_VSCROLL);
1015     maSwitcher.SetHelpId(HID_CTRL3D_SWITCHER);
1016     maSwitcher.SetAccessibleName(String(SVX_RES(STR_SWITCH)));
1017 
1018     // Light preview
1019     maLightControl.Show();
1020     maLightControl.SetChangeCallback( LINK(this, SvxLightCtl3D, InternalInteractiveChange) );
1021     maLightControl.SetSelectionChangeCallback( LINK(this, SvxLightCtl3D, InternalSelectionChange) );
1022 
1023     // Horiz Scrollbar
1024     maHorScroller.Show();
1025     maHorScroller.SetRange(Range(0, 36000));
1026     maHorScroller.SetLineSize(100);
1027     maHorScroller.SetPageSize(1000);
1028     maHorScroller.SetScrollHdl( LINK(this, SvxLightCtl3D, ScrollBarMove) );
1029 
1030     // Vert Scrollbar
1031     maVerScroller.Show();
1032     maVerScroller.SetRange(Range(0, 18000));
1033     maVerScroller.SetLineSize(100);
1034     maVerScroller.SetPageSize(1000);
1035     maVerScroller.SetScrollHdl( LINK(this, SvxLightCtl3D, ScrollBarMove) );
1036 
1037     // Switch Button
1038     maSwitcher.Show();
1039     maSwitcher.SetClickHdl( LINK(this, SvxLightCtl3D, ButtonPress) );
1040 
1041     // check selection
1042     CheckSelection();
1043 
1044     // new layout
1045     NewLayout();
1046 }
1047 
1048 SvxLightCtl3D::~SvxLightCtl3D()
1049 {
1050 }
1051 
1052 void SvxLightCtl3D::Resize()
1053 {
1054     // call parent
1055     Control::Resize();
1056 
1057     // new layout
1058     NewLayout();
1059 }
1060 
1061 void SvxLightCtl3D::NewLayout()
1062 {
1063     // Layout members
1064     const Size aSize(GetOutputSizePixel());
1065     const sal_Int32 nScrollSize(maHorScroller.GetSizePixel().Height());
1066 
1067     // Preview control
1068     Point aPoint(0, 0);
1069     Size aDestSize(aSize.Width() - nScrollSize, aSize.Height() - nScrollSize);
1070     maLightControl.SetPosSizePixel(aPoint, aDestSize);
1071 
1072     // hor scrollbar
1073     aPoint.Y() = aSize.Height() - nScrollSize;
1074     aDestSize.Height() = nScrollSize;
1075     maHorScroller.SetPosSizePixel(aPoint, aDestSize);
1076 
1077     // vert scrollbar
1078     aPoint.X() = aSize.Width() - nScrollSize;
1079     aPoint.Y() = 0;
1080     aDestSize.Width() = nScrollSize;
1081     aDestSize.Height() = aSize.Height() - nScrollSize;
1082     maVerScroller.SetPosSizePixel(aPoint, aDestSize);
1083 
1084     // button
1085     aPoint.Y() = aSize.Height() - nScrollSize;
1086     aDestSize.Height() = nScrollSize;
1087     maSwitcher.SetPosSizePixel(aPoint, aDestSize);
1088 }
1089 
1090 void SvxLightCtl3D::CheckSelection()
1091 {
1092     const bool bSelectionValid(maLightControl.IsSelectionValid() || maLightControl.IsGeometrySelected());
1093     maHorScroller.Enable(bSelectionValid);
1094     maVerScroller.Enable(bSelectionValid);
1095 
1096     if(bSelectionValid)
1097     {
1098         double fHor, fVer;
1099         maLightControl.GetPosition(fHor, fVer);
1100         maHorScroller.SetThumbPos( sal_Int32(fHor * 100.0) );
1101         maVerScroller.SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
1102     }
1103 }
1104 
1105 void SvxLightCtl3D::move( double fDeltaHor, double fDeltaVer )
1106 {
1107     double fHor, fVer;
1108 
1109     maLightControl.GetPosition(fHor, fVer);
1110     fHor += fDeltaHor;
1111     fVer += fDeltaVer;
1112 
1113     if( fVer > 90.0 )
1114         return;
1115 
1116     if ( fVer < -90.0 )
1117         return;
1118 
1119     maLightControl.SetPosition(fHor, fVer);
1120     maHorScroller.SetThumbPos( sal_Int32(fHor * 100.0) );
1121     maVerScroller.SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
1122 
1123     if(maUserInteractiveChangeCallback.IsSet())
1124     {
1125         maUserInteractiveChangeCallback.Call(this);
1126     }
1127 }
1128 
1129 void SvxLightCtl3D::KeyInput( const KeyEvent& rKEvt )
1130 {
1131     const KeyCode aCode(rKEvt.GetKeyCode());
1132 
1133     if( aCode.GetModifier() )
1134     {
1135         Control::KeyInput( rKEvt );
1136         return;
1137     }
1138 
1139     switch ( aCode.GetCode() )
1140     {
1141         case KEY_SPACE:
1142         {
1143             break;
1144         }
1145         case KEY_LEFT:
1146         {
1147             move(  -4.0,  0.0 ); // #i58242# changed move direction in X
1148             break;
1149         }
1150         case KEY_RIGHT:
1151         {
1152             move( 4.0,  0.0 ); // #i58242# changed move direction in X
1153             break;
1154         }
1155         case KEY_UP:
1156         {
1157             move(  0.0,  4.0 );
1158             break;
1159         }
1160         case KEY_DOWN:
1161         {
1162             move(  0.0, -4.0 );
1163             break;
1164         }
1165         case KEY_PAGEUP:
1166         {
1167             sal_Int32 nLight(maLightControl.GetSelectedLight() - 1);
1168 
1169             while((nLight >= 0) && !maLightControl.GetLightOnOff(nLight))
1170             {
1171                 nLight--;
1172             }
1173 
1174             if(nLight < 0)
1175             {
1176                 nLight = 7;
1177 
1178                 while((nLight >= 0) && !maLightControl.GetLightOnOff(nLight))
1179                 {
1180                     nLight--;
1181                 }
1182             }
1183 
1184             if(nLight >= 0)
1185             {
1186                 maLightControl.SelectLight(nLight);
1187                 CheckSelection();
1188 
1189                 if(maUserSelectionChangeCallback.IsSet())
1190                 {
1191                     maUserSelectionChangeCallback.Call(this);
1192                 }
1193             }
1194 
1195             break;
1196         }
1197         case KEY_PAGEDOWN:
1198         {
1199             sal_Int32 nLight(maLightControl.GetSelectedLight() - 1);
1200 
1201             while(nLight <= 7 && !maLightControl.GetLightOnOff(nLight))
1202             {
1203                 nLight++;
1204             }
1205 
1206             if(nLight > 7)
1207             {
1208                 nLight = 0;
1209 
1210                 while(nLight <= 7 && !maLightControl.GetLightOnOff(nLight))
1211                 {
1212                     nLight++;
1213                 }
1214             }
1215 
1216             if(nLight <= 7)
1217             {
1218                 maLightControl.SelectLight(nLight);
1219                 CheckSelection();
1220 
1221                 if(maUserSelectionChangeCallback.IsSet())
1222                 {
1223                     maUserSelectionChangeCallback.Call(this);
1224                 }
1225             }
1226 
1227             break;
1228         }
1229         default:
1230         {
1231             Control::KeyInput( rKEvt );
1232             break;
1233         }
1234     }
1235 }
1236 
1237 void SvxLightCtl3D::GetFocus()
1238 {
1239     Control::GetFocus();
1240 
1241     if(HasFocus() && IsEnabled())
1242     {
1243         CheckSelection();
1244 
1245         Size aFocusSize = maLightControl.GetOutputSizePixel();
1246 
1247         aFocusSize.Width() -= 4;
1248         aFocusSize.Height() -= 4;
1249 
1250         Rectangle aFocusRect( Point( 2, 2 ), aFocusSize );
1251 
1252         aFocusRect = maLightControl.PixelToLogic( aFocusRect );
1253 
1254         maLightControl.ShowFocus( aFocusRect );
1255     }
1256 }
1257 
1258 void SvxLightCtl3D::LoseFocus()
1259 {
1260     Control::LoseFocus();
1261 
1262     maLightControl.HideFocus();
1263 }
1264 
1265 IMPL_LINK( SvxLightCtl3D, ScrollBarMove, void*, EMPTYARG)
1266 {
1267     const sal_Int32 nHor(maHorScroller.GetThumbPos());
1268     const sal_Int32 nVer(maVerScroller.GetThumbPos());
1269 
1270     maLightControl.SetPosition(
1271         ((double)nHor) / 100.0,
1272         ((double)((18000 - nVer) - 9000)) / 100.0);
1273 
1274     if(maUserInteractiveChangeCallback.IsSet())
1275     {
1276         maUserInteractiveChangeCallback.Call(this);
1277     }
1278 
1279     return 0;
1280 }
1281 
1282 IMPL_LINK( SvxLightCtl3D, ButtonPress, void*, EMPTYARG)
1283 {
1284     if(PREVIEW_OBJECTTYPE_SPHERE == GetSvx3DLightControl().GetObjectType())
1285     {
1286         GetSvx3DLightControl().SetObjectType(PREVIEW_OBJECTTYPE_CUBE);
1287     }
1288     else
1289     {
1290         GetSvx3DLightControl().SetObjectType(PREVIEW_OBJECTTYPE_SPHERE);
1291     }
1292 
1293     return 0;
1294 }
1295 
1296 IMPL_LINK( SvxLightCtl3D, InternalInteractiveChange, void*, EMPTYARG)
1297 {
1298     double fHor, fVer;
1299 
1300     maLightControl.GetPosition(fHor, fVer);
1301     maHorScroller.SetThumbPos( sal_Int32(fHor * 100.0) );
1302     maVerScroller.SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
1303 
1304     if(maUserInteractiveChangeCallback.IsSet())
1305     {
1306         maUserInteractiveChangeCallback.Call(this);
1307     }
1308 
1309     return 0;
1310 }
1311 
1312 IMPL_LINK( SvxLightCtl3D, InternalSelectionChange, void*, EMPTYARG)
1313 {
1314     CheckSelection();
1315 
1316     if(maUserSelectionChangeCallback.IsSet())
1317     {
1318         maUserSelectionChangeCallback.Call(this);
1319     }
1320 
1321     return 0;
1322 }
1323 
1324 //////////////////////////////////////////////////////////////////////////////
1325 // eof
1326