Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / svx / source / dialog / dlgctl3d.cxx
bloba1e20bf28a05165709df3259c431c40f96c9c202
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <svx/dlgctl3d.hxx>
22 #include <svx/dialogs.hrc>
23 #include <svx/view3d.hxx>
24 #include <svx/fmmodel.hxx>
25 #include <svl/itempool.hxx>
26 #include <svx/fmpage.hxx>
27 #include <svx/polysc3d.hxx>
28 #include <svx/sphere3d.hxx>
29 #include <svx/cube3d.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/builder.hxx>
32 #include <svx/helperhittest3d.hxx>
33 #include <basegfx/polygon/b2dpolygontools.hxx>
34 #include <polygn3d.hxx>
35 #include <svx/xlnclit.hxx>
36 #include <svx/xlnwtit.hxx>
37 #include "helpid.hrc"
38 #include <algorithm>
39 #include <svx/dialmgr.hxx>
40 #include <vcl/settings.hxx>
44 Svx3DPreviewControl::Svx3DPreviewControl(Window* pParent, const ResId& rResId)
45 : Control(pParent, rResId),
46 mpModel(0),
47 mpFmPage(0),
48 mp3DView(0),
49 mpScene(0),
50 mp3DObj(0),
51 mnObjectType(PREVIEW_OBJECTTYPE_SPHERE)
53 Construct();
55 // do not paint background self, DrawingLayer paints this buffered and as page
56 SetControlBackground();
57 SetBackground();
60 Svx3DPreviewControl::Svx3DPreviewControl(Window* pParent, WinBits nStyle)
61 : Control(pParent, nStyle),
62 mpModel(0),
63 mpFmPage(0),
64 mp3DView(0),
65 mpScene(0),
66 mp3DObj(0),
67 mnObjectType(PREVIEW_OBJECTTYPE_SPHERE)
69 Construct();
71 // do not paint background self, DrawingLayer paints this buffered and as page
72 SetControlBackground();
73 SetBackground();
76 Svx3DPreviewControl::~Svx3DPreviewControl()
78 delete mp3DView;
79 delete mpModel;
82 void Svx3DPreviewControl::Construct()
84 // Do never mirror the preview window. This explicitly includes right
85 // to left writing environments.
86 EnableRTL (false);
87 SetMapMode( MAP_100TH_MM );
89 // Model
90 mpModel = new FmFormModel();
91 mpModel->GetItemPool().FreezeIdRanges();
93 // Page
94 mpFmPage = new FmFormPage( *mpModel );
95 mpModel->InsertPage( mpFmPage, 0 );
97 // 3D View
98 mp3DView = new E3dView( mpModel, this );
99 mp3DView->SetBufferedOutputAllowed(true);
100 mp3DView->SetBufferedOverlayAllowed(true);
102 // 3D Scene
103 mpScene = new E3dPolyScene(mp3DView->Get3DDefaultAttributes());
105 // initially create object
106 SetObjectType(PREVIEW_OBJECTTYPE_SPHERE);
108 // camera and perspective
109 Camera3D& rCamera = (Camera3D&) mpScene->GetCamera();
110 const basegfx::B3DRange& rVolume = mpScene->GetBoundVolume();
111 double fW = rVolume.getWidth();
112 double fH = rVolume.getHeight();
113 double fCamZ = rVolume.getMaxZ() + ((fW + fH) / 2.0);
115 rCamera.SetAutoAdjustProjection(false);
116 rCamera.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
117 basegfx::B3DPoint aLookAt;
118 double fDefaultCamPosZ = mp3DView->GetDefaultCamPosZ();
119 basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
120 rCamera.SetPosAndLookAt(aCamPos, aLookAt);
121 double fDefaultCamFocal = mp3DView->GetDefaultCamFocal();
122 rCamera.SetFocalLength(fDefaultCamFocal);
123 rCamera.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ), aLookAt, fDefaultCamFocal);
125 mpScene->SetCamera( rCamera );
126 mpFmPage->InsertObject( mpScene );
128 basegfx::B3DHomMatrix aRotation;
129 aRotation.rotate(DEG2RAD( 25 ), 0.0, 0.0);
130 aRotation.rotate(0.0, DEG2RAD( 40 ), 0.0);
131 mpScene->SetTransform(aRotation * mpScene->GetTransform());
133 // invalidate SnapRects of objects
134 mpScene->SetRectsDirty();
136 SfxItemSet aSet( mpModel->GetItemPool(),
137 XATTR_LINESTYLE, XATTR_LINESTYLE,
138 XATTR_FILL_FIRST, XATTR_FILLBITMAP,
139 0, 0 );
140 aSet.Put( XLineStyleItem( XLINE_NONE ) );
141 aSet.Put( XFillStyleItem( XFILL_SOLID ) );
142 aSet.Put( XFillColorItem( "", Color( COL_WHITE ) ) );
144 mpScene->SetMergedItemSet(aSet);
146 // PageView
147 SdrPageView* pPageView = mp3DView->ShowSdrPage( mpFmPage );
148 mp3DView->hideMarkHandles();
150 // mark scene
151 mp3DView->MarkObj( mpScene, pPageView );
154 void Svx3DPreviewControl::Resize()
156 // size of page
157 Size aSize( GetSizePixel() );
158 aSize = PixelToLogic( aSize );
159 mpFmPage->SetSize( aSize );
161 // set size
162 Size aObjSize( aSize.Width()*5/6, aSize.Height()*5/6 );
163 Point aObjPoint( (aSize.Width() - aObjSize.Width()) / 2,
164 (aSize.Height() - aObjSize.Height()) / 2);
165 Rectangle aRect( aObjPoint, aObjSize);
166 mpScene->SetSnapRect( aRect );
169 void Svx3DPreviewControl::Paint(const Rectangle& rRect)
171 mp3DView->CompleteRedraw(this, Region(rRect));
174 void Svx3DPreviewControl::MouseButtonDown(const MouseEvent& rMEvt)
176 Control::MouseButtonDown(rMEvt);
178 if( rMEvt.IsShift() && rMEvt.IsMod1() )
180 if(PREVIEW_OBJECTTYPE_SPHERE == GetObjectType())
182 SetObjectType(PREVIEW_OBJECTTYPE_CUBE);
184 else
186 SetObjectType(PREVIEW_OBJECTTYPE_SPHERE);
191 void Svx3DPreviewControl::SetObjectType(sal_uInt16 nType)
193 if( mnObjectType != nType || !mp3DObj)
195 SfxItemSet aSet(mpModel->GetItemPool(), SDRATTR_START, SDRATTR_END, 0, 0);
196 mnObjectType = nType;
198 if( mp3DObj )
200 aSet.Put(mp3DObj->GetMergedItemSet());
201 mpScene->Remove3DObj( mp3DObj );
202 delete mp3DObj;
203 mp3DObj = NULL;
206 switch( nType )
208 case PREVIEW_OBJECTTYPE_SPHERE:
210 mp3DObj = new E3dSphereObj(
211 mp3DView->Get3DDefaultAttributes(),
212 basegfx::B3DPoint( 0, 0, 0 ),
213 basegfx::B3DVector( 5000, 5000, 5000 ));
215 break;
217 case PREVIEW_OBJECTTYPE_CUBE:
219 mp3DObj = new E3dCubeObj(
220 mp3DView->Get3DDefaultAttributes(),
221 basegfx::B3DPoint( -2500, -2500, -2500 ),
222 basegfx::B3DVector( 5000, 5000, 5000 ));
224 break;
227 mpScene->Insert3DObj( mp3DObj );
228 mp3DObj->SetMergedItemSet(aSet);
230 Resize();
234 SfxItemSet Svx3DPreviewControl::Get3DAttributes() const
236 return mp3DObj->GetMergedItemSet();
239 void Svx3DPreviewControl::Set3DAttributes( const SfxItemSet& rAttr )
241 mp3DObj->SetMergedItemSet(rAttr, true);
242 Resize();
247 #define RADIUS_LAMP_PREVIEW_SIZE (4500.0)
248 #define RADIUS_LAMP_SMALL (600.0)
249 #define RADIUS_LAMP_BIG (1000.0)
250 #define NO_LIGHT_SELECTED (0xffffffff)
251 #define MAX_NUMBER_LIGHTS (8)
253 Svx3DLightControl::Svx3DLightControl(Window* pParent, WinBits nStyle)
254 : Svx3DPreviewControl(pParent, nStyle),
255 maUserInteractiveChangeCallback(),
256 maUserSelectionChangeCallback(),
257 maChangeCallback(),
258 maSelectionChangeCallback(),
259 maSelectedLight(NO_LIGHT_SELECTED),
260 mpExpansionObject(0),
261 mpLampBottomObject(0),
262 mpLampShaftObject(0),
263 maLightObjects(MAX_NUMBER_LIGHTS, (E3dObject*)0),
264 mfRotateX(-20.0),
265 mfRotateY(45.0),
266 mfRotateZ(0.0),
267 maActionStartPoint(),
268 mnInteractionStartDistance(5 * 5 * 2),
269 mfSaveActionStartHor(0.0),
270 mfSaveActionStartVer(0.0),
271 mfSaveActionStartRotZ(0.0),
272 mbMouseMoved(false),
273 mbGeometrySelected(false)
275 Construct2();
278 Svx3DLightControl::~Svx3DLightControl()
280 // SdrObjects like mpExpansionObject and mpLampBottomObject/mpLampShaftObject get deleted
281 // with deletion of the DrawingLayer and model
284 void Svx3DLightControl::Construct2()
287 // hide all page stuff, use control background (normally gray)
288 const Color aDialogColor(Application::GetSettings().GetStyleSettings().GetDialogColor());
289 mp3DView->SetPageVisible(false);
290 mp3DView->SetApplicationBackgroundColor(aDialogColor);
291 mp3DView->SetApplicationDocumentColor(aDialogColor);
295 // create invisible expansion object
296 const double fMaxExpansion(RADIUS_LAMP_BIG + RADIUS_LAMP_PREVIEW_SIZE);
297 mpExpansionObject = new E3dCubeObj(
298 mp3DView->Get3DDefaultAttributes(),
299 basegfx::B3DPoint(-fMaxExpansion, -fMaxExpansion, -fMaxExpansion),
300 basegfx::B3DVector(2.0 * fMaxExpansion, 2.0 * fMaxExpansion, 2.0 * fMaxExpansion));
301 mpScene->Insert3DObj( mpExpansionObject );
302 SfxItemSet aSet(mpModel->GetItemPool());
303 aSet.Put( XLineStyleItem( XLINE_NONE ) );
304 aSet.Put( XFillStyleItem( XFILL_NONE ) );
305 mpExpansionObject->SetMergedItemSet(aSet);
309 // create lamp control object (Yellow lined object)
310 // base circle
311 const basegfx::B2DPolygon a2DCircle(basegfx::tools::createPolygonFromCircle(basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE));
312 basegfx::B3DPolygon a3DCircle(basegfx::tools::createB3DPolygonFromB2DPolygon(a2DCircle));
313 basegfx::B3DHomMatrix aTransform;
315 aTransform.rotate(F_PI2, 0.0, 0.0);
316 aTransform.translate(0.0, -RADIUS_LAMP_PREVIEW_SIZE, 0.0);
317 a3DCircle.transform(aTransform);
319 // create object for it
320 mpLampBottomObject = new E3dPolygonObj(
321 mp3DView->Get3DDefaultAttributes(),
322 basegfx::B3DPolyPolygon(a3DCircle),
323 true);
324 mpScene->Insert3DObj( mpLampBottomObject );
326 // half circle with stand
327 basegfx::B2DPolygon a2DHalfCircle;
328 a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, 0.0));
329 a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, -RADIUS_LAMP_PREVIEW_SIZE));
330 a2DHalfCircle.append(basegfx::tools::createPolygonFromEllipseSegment(
331 basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE, RADIUS_LAMP_PREVIEW_SIZE, F_2PI - F_PI2, F_PI2));
332 basegfx::B3DPolygon a3DHalfCircle(basegfx::tools::createB3DPolygonFromB2DPolygon(a2DHalfCircle));
334 // create object for it
335 mpLampShaftObject = new E3dPolygonObj(
336 mp3DView->Get3DDefaultAttributes(),
337 basegfx::B3DPolyPolygon(a3DHalfCircle),
338 true);
339 mpScene->Insert3DObj( mpLampShaftObject );
341 // initially invisible
342 SfxItemSet aSet(mpModel->GetItemPool());
343 aSet.Put( XLineStyleItem( XLINE_NONE ) );
344 aSet.Put( XFillStyleItem( XFILL_NONE ) );
346 mpLampBottomObject->SetMergedItemSet(aSet);
347 mpLampShaftObject->SetMergedItemSet(aSet);
351 // change camera settings
352 Camera3D& rCamera = (Camera3D&) mpScene->GetCamera();
353 const basegfx::B3DRange& rVolume = mpScene->GetBoundVolume();
354 double fW = rVolume.getWidth();
355 double fH = rVolume.getHeight();
356 double fCamZ = rVolume.getMaxZ() + ((fW + fH) / 2.0);
358 rCamera.SetAutoAdjustProjection(false);
359 rCamera.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
360 basegfx::B3DPoint aLookAt;
361 double fDefaultCamPosZ = mp3DView->GetDefaultCamPosZ();
362 basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
363 rCamera.SetPosAndLookAt(aCamPos, aLookAt);
364 double fDefaultCamFocal = mp3DView->GetDefaultCamFocal();
365 rCamera.SetFocalLength(fDefaultCamFocal);
366 rCamera.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ), aLookAt, fDefaultCamFocal);
368 mpScene->SetCamera( rCamera );
370 basegfx::B3DHomMatrix aNeutral;
371 mpScene->SetTransform(aNeutral);
374 // invalidate SnapRects of objects
375 mpScene->SetRectsDirty();
378 void Svx3DLightControl::ConstructLightObjects()
380 for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
382 // get rid of possible existing light object
383 if(maLightObjects[a])
385 mpScene->Remove3DObj(maLightObjects[a]);
386 delete maLightObjects[a];
387 maLightObjects[a] = 0;
390 if(GetLightOnOff(a))
392 const bool bIsSelectedLight(a == maSelectedLight);
393 basegfx::B3DVector aDirection(GetLightDirection(a));
394 aDirection.normalize();
395 aDirection *= RADIUS_LAMP_PREVIEW_SIZE;
397 const double fLampSize(bIsSelectedLight ? RADIUS_LAMP_BIG : RADIUS_LAMP_SMALL);
398 E3dObject* pNewLight = new E3dSphereObj(
399 mp3DView->Get3DDefaultAttributes(),
400 basegfx::B3DPoint( 0, 0, 0 ),
401 basegfx::B3DVector( fLampSize, fLampSize, fLampSize));
402 mpScene->Insert3DObj(pNewLight);
404 basegfx::B3DHomMatrix aTransform;
405 aTransform.translate(aDirection.getX(), aDirection.getY(), aDirection.getZ());
406 pNewLight->SetTransform(aTransform);
408 SfxItemSet aSet(mpModel->GetItemPool());
409 aSet.Put( XLineStyleItem( XLINE_NONE ) );
410 aSet.Put( XFillStyleItem( XFILL_SOLID ) );
411 aSet.Put( XFillColorItem(OUString(), GetLightColor(a)));
412 pNewLight->SetMergedItemSet(aSet);
414 maLightObjects[a] = pNewLight;
419 void Svx3DLightControl::AdaptToSelectedLight()
421 if(NO_LIGHT_SELECTED == maSelectedLight)
423 // make mpLampBottomObject/mpLampShaftObject invisible
424 SfxItemSet aSet(mpModel->GetItemPool());
425 aSet.Put( XLineStyleItem( XLINE_NONE ) );
426 aSet.Put( XFillStyleItem( XFILL_NONE ) );
427 mpLampBottomObject->SetMergedItemSet(aSet);
428 mpLampShaftObject->SetMergedItemSet(aSet);
430 else
432 basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
433 aDirection.normalize();
435 // make mpLampBottomObject/mpLampShaftObject visible (yellow hairline)
436 SfxItemSet aSet(mpModel->GetItemPool());
437 aSet.Put( XLineStyleItem( XLINE_SOLID ) );
438 aSet.Put( XLineColorItem(OUString(), COL_YELLOW));
439 aSet.Put( XLineWidthItem(0));
440 aSet.Put( XFillStyleItem( XFILL_NONE ) );
441 mpLampBottomObject->SetMergedItemSet(aSet);
442 mpLampShaftObject->SetMergedItemSet(aSet);
444 // adapt transformation of mpLampShaftObject
445 basegfx::B3DHomMatrix aTransform;
446 double fRotateY(0.0);
448 if(!basegfx::fTools::equalZero(aDirection.getZ()) || !basegfx::fTools::equalZero(aDirection.getX()))
450 fRotateY = atan2(-aDirection.getZ(), aDirection.getX());
453 aTransform.rotate(0.0, fRotateY, 0.0);
454 mpLampShaftObject->SetTransform(aTransform);
456 // adapt transformation of selected light
457 E3dObject* pSelectedLight = maLightObjects[sal_Int32(maSelectedLight)];
459 if(pSelectedLight)
461 aTransform.identity();
462 aTransform.translate(
463 aDirection.getX() * RADIUS_LAMP_PREVIEW_SIZE,
464 aDirection.getY() * RADIUS_LAMP_PREVIEW_SIZE,
465 aDirection.getZ() * RADIUS_LAMP_PREVIEW_SIZE);
466 pSelectedLight->SetTransform(aTransform);
471 void Svx3DLightControl::TrySelection(Point aPosPixel)
473 if(mpScene)
475 const Point aPosLogic(PixelToLogic(aPosPixel));
476 const basegfx::B2DPoint aPoint(aPosLogic.X(), aPosLogic.Y());
477 std::vector< const E3dCompoundObject* > aResult;
478 getAllHit3DObjectsSortedFrontToBack(aPoint, *mpScene, aResult);
480 if(!aResult.empty())
482 // exclude expansion object which will be part of
483 // the hits. It's invisible, but for HitTest, it's included
484 const E3dCompoundObject* pResult = 0;
486 for(sal_uInt32 b(0); !pResult && b < aResult.size(); b++)
488 if(aResult[b] && aResult[b] != mpExpansionObject)
490 pResult = aResult[b];
494 if(pResult == mp3DObj)
496 if(!mbGeometrySelected)
498 mbGeometrySelected = true;
499 maSelectedLight = NO_LIGHT_SELECTED;
500 ConstructLightObjects();
501 AdaptToSelectedLight();
502 Invalidate();
504 if(maSelectionChangeCallback.IsSet())
506 maSelectionChangeCallback.Call(this);
510 else
512 sal_uInt32 aNewSelectedLight(NO_LIGHT_SELECTED);
514 for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
516 if(maLightObjects[a] && maLightObjects[a] == pResult)
518 aNewSelectedLight = a;
522 if(aNewSelectedLight != maSelectedLight)
524 SelectLight(aNewSelectedLight);
526 if(maSelectionChangeCallback.IsSet())
528 maSelectionChangeCallback.Call(this);
536 void Svx3DLightControl::Paint(const Rectangle& rRect)
538 Svx3DPreviewControl::Paint(rRect);
541 void Svx3DLightControl::MouseButtonDown( const MouseEvent& rMEvt )
543 bool bCallParent(true);
545 // switch state
546 if(rMEvt.IsLeft())
548 if(IsSelectionValid() || mbGeometrySelected)
550 mbMouseMoved = false;
551 bCallParent = false;
552 maActionStartPoint = rMEvt.GetPosPixel();
553 StartTracking();
555 else
557 // Single click without moving much trying to do a selection
558 TrySelection(rMEvt.GetPosPixel());
559 bCallParent = false;
563 // call parent
564 if(bCallParent)
566 Svx3DPreviewControl::MouseButtonDown(rMEvt);
570 void Svx3DLightControl::Tracking( const TrackingEvent& rTEvt )
572 if(rTEvt.IsTrackingEnded())
574 if(rTEvt.IsTrackingCanceled())
576 if(mbMouseMoved)
578 // interrupt tracking
579 mbMouseMoved = false;
581 if(mbGeometrySelected)
583 SetRotation(mfSaveActionStartVer, mfSaveActionStartHor, mfSaveActionStartRotZ);
585 else
587 SetPosition(mfSaveActionStartHor, mfSaveActionStartVer);
590 if(maChangeCallback.IsSet())
592 maChangeCallback.Call(this);
596 else
598 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
600 if(mbMouseMoved)
602 // was change dinteractively
604 else
606 // simple click without much movement, try selection
607 TrySelection(rMEvt.GetPosPixel());
611 else
613 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
614 Point aDeltaPos = rMEvt.GetPosPixel() - maActionStartPoint;
616 if(!mbMouseMoved)
618 if(sal_Int32(aDeltaPos.X() * aDeltaPos.X() + aDeltaPos.Y() * aDeltaPos.Y()) > mnInteractionStartDistance)
620 if(mbGeometrySelected)
622 GetRotation(mfSaveActionStartVer, mfSaveActionStartHor, mfSaveActionStartRotZ);
624 else
626 // intercation start, save values
627 GetPosition(mfSaveActionStartHor, mfSaveActionStartVer);
630 mbMouseMoved = true;
634 if(mbMouseMoved)
636 if(mbGeometrySelected)
638 double fNewRotX = mfSaveActionStartVer - ((double)aDeltaPos.Y() * F_PI180);
639 double fNewRotY = mfSaveActionStartHor + ((double)aDeltaPos.X() * F_PI180);
641 // cut horizontal
642 while(fNewRotY < 0.0)
644 fNewRotY += F_2PI;
647 while(fNewRotY >= F_2PI)
649 fNewRotY -= F_2PI;
652 // cut vertical
653 if(fNewRotX < -F_PI2)
655 fNewRotX = -F_PI2;
658 if(fNewRotX > F_PI2)
660 fNewRotX = F_PI2;
663 SetRotation(fNewRotX, fNewRotY, mfSaveActionStartRotZ);
665 if(maChangeCallback.IsSet())
667 maChangeCallback.Call(this);
670 else
672 // interaction in progress
673 double fNewPosHor = mfSaveActionStartHor + ((double)aDeltaPos.X());
674 double fNewPosVer = mfSaveActionStartVer - ((double)aDeltaPos.Y());
676 // cut horizontal
677 while(fNewPosHor < 0.0)
679 fNewPosHor += 360.0;
682 while(fNewPosHor >= 360.0)
684 fNewPosHor -= 360.0;
687 // cut vertical
688 if(fNewPosVer < -90.0)
690 fNewPosVer = -90.0;
693 if(fNewPosVer > 90.0)
695 fNewPosVer = 90.0;
698 SetPosition(fNewPosHor, fNewPosVer);
700 if(maChangeCallback.IsSet())
702 maChangeCallback.Call(this);
709 void Svx3DLightControl::Resize()
711 // set size of page
712 const Size aSize(PixelToLogic(GetSizePixel()));
713 mpFmPage->SetSize(aSize);
715 // set position and size of scene
716 mpScene->SetSnapRect(Rectangle(Point(0, 0), aSize));
719 void Svx3DLightControl::SetObjectType(sal_uInt16 nType)
721 // call parent
722 Svx3DPreviewControl::SetObjectType(nType);
724 // apply object rotation
725 if(mp3DObj)
727 basegfx::B3DHomMatrix aObjectRotation;
728 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
729 mp3DObj->SetTransform(aObjectRotation);
733 bool Svx3DLightControl::IsSelectionValid()
735 if((NO_LIGHT_SELECTED != maSelectedLight) && (GetLightOnOff(maSelectedLight)))
737 return true;
740 return false;
743 void Svx3DLightControl::GetPosition(double& rHor, double& rVer)
745 if(IsSelectionValid())
747 basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
748 aDirection.normalize();
749 rHor = atan2(-aDirection.getX(), -aDirection.getZ()) + F_PI; // 0..2PI
750 rVer = atan2(aDirection.getY(), aDirection.getXZLength()); // -PI2..PI2
751 rHor /= F_PI180; // 0..360.0
752 rVer /= F_PI180; // -90.0..90.0
754 if(IsGeometrySelected())
756 rHor = mfRotateY / F_PI180; // 0..360.0
757 rVer = mfRotateX / F_PI180; // -90.0..90.0
761 void Svx3DLightControl::SetPosition(double fHor, double fVer)
763 if(IsSelectionValid())
765 // set selected light's direction
766 fHor = (fHor * F_PI180) - F_PI; // -PI..PI
767 fVer *= F_PI180; // -PI2..PI2
768 basegfx::B3DVector aDirection(cos(fVer) * -sin(fHor), sin(fVer), cos(fVer) * -cos(fHor));
769 aDirection.normalize();
771 if(!aDirection.equal(GetLightDirection(maSelectedLight)))
773 // set changed light direction at SdrScene
774 SfxItemSet aSet(mpModel->GetItemPool());
776 switch(maSelectedLight)
778 case 0: aSet.Put(Svx3DLightDirection1Item(aDirection)); break;
779 case 1: aSet.Put(Svx3DLightDirection2Item(aDirection)); break;
780 case 2: aSet.Put(Svx3DLightDirection3Item(aDirection)); break;
781 case 3: aSet.Put(Svx3DLightDirection4Item(aDirection)); break;
782 case 4: aSet.Put(Svx3DLightDirection5Item(aDirection)); break;
783 case 5: aSet.Put(Svx3DLightDirection6Item(aDirection)); break;
784 case 6: aSet.Put(Svx3DLightDirection7Item(aDirection)); break;
785 default:
786 case 7: aSet.Put(Svx3DLightDirection8Item(aDirection)); break;
789 mpScene->SetMergedItemSet(aSet);
791 // correct 3D light's and LampFrame's geometries
792 AdaptToSelectedLight();
793 Invalidate();
796 if(IsGeometrySelected())
798 if(mfRotateX != fVer || mfRotateY != fHor)
800 mfRotateX = fVer * F_PI180;
801 mfRotateY = fHor * F_PI180;
803 if(mp3DObj)
805 basegfx::B3DHomMatrix aObjectRotation;
806 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
807 mp3DObj->SetTransform(aObjectRotation);
809 Invalidate();
815 void Svx3DLightControl::SetRotation(double fRotX, double fRotY, double fRotZ)
817 if(IsGeometrySelected())
819 if(fRotX != mfRotateX || fRotY != mfRotateY || fRotZ != mfRotateZ)
821 mfRotateX = fRotX;
822 mfRotateY = fRotY;
823 mfRotateZ = fRotZ;
825 if(mp3DObj)
827 basegfx::B3DHomMatrix aObjectRotation;
828 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
829 mp3DObj->SetTransform(aObjectRotation);
831 Invalidate();
837 void Svx3DLightControl::GetRotation(double& rRotX, double& rRotY, double& rRotZ)
839 rRotX = mfRotateX;
840 rRotY = mfRotateY;
841 rRotZ = mfRotateZ;
844 void Svx3DLightControl::Set3DAttributes( const SfxItemSet& rAttr )
846 // call parent
847 Svx3DPreviewControl::Set3DAttributes(rAttr);
849 if(maSelectedLight != NO_LIGHT_SELECTED && !GetLightOnOff(maSelectedLight))
851 // selected light is no more active, select new one
852 maSelectedLight = NO_LIGHT_SELECTED;
855 // local updates
856 ConstructLightObjects();
857 AdaptToSelectedLight();
858 Invalidate();
861 void Svx3DLightControl::SelectLight(sal_uInt32 nLightNumber)
863 if(nLightNumber > 7)
865 nLightNumber = NO_LIGHT_SELECTED;
868 if(NO_LIGHT_SELECTED != nLightNumber)
870 if(!GetLightOnOff(nLightNumber))
872 nLightNumber = NO_LIGHT_SELECTED;
876 if(nLightNumber != maSelectedLight)
878 maSelectedLight = nLightNumber;
879 mbGeometrySelected = false;
880 ConstructLightObjects();
881 AdaptToSelectedLight();
882 Invalidate();
886 bool Svx3DLightControl::GetLightOnOff(sal_uInt32 nNum) const
888 if(nNum <= 7)
890 const SfxItemSet aLightItemSet(Get3DAttributes());
892 switch(nNum)
894 case 0 : return ((const Svx3DLightOnOff1Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_1)).GetValue();
895 case 1 : return ((const Svx3DLightOnOff2Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_2)).GetValue();
896 case 2 : return ((const Svx3DLightOnOff3Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_3)).GetValue();
897 case 3 : return ((const Svx3DLightOnOff4Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_4)).GetValue();
898 case 4 : return ((const Svx3DLightOnOff5Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_5)).GetValue();
899 case 5 : return ((const Svx3DLightOnOff6Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_6)).GetValue();
900 case 6 : return ((const Svx3DLightOnOff7Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_7)).GetValue();
901 case 7 : return ((const Svx3DLightOnOff8Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_8)).GetValue();
905 return false;
908 Color Svx3DLightControl::GetLightColor(sal_uInt32 nNum) const
910 if(nNum <= 7)
912 const SfxItemSet aLightItemSet(Get3DAttributes());
914 switch(nNum)
916 case 0 : return ((const Svx3DLightcolor1Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1)).GetValue();
917 case 1 : return ((const Svx3DLightcolor2Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2)).GetValue();
918 case 2 : return ((const Svx3DLightcolor3Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3)).GetValue();
919 case 3 : return ((const Svx3DLightcolor4Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4)).GetValue();
920 case 4 : return ((const Svx3DLightcolor5Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5)).GetValue();
921 case 5 : return ((const Svx3DLightcolor6Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6)).GetValue();
922 case 6 : return ((const Svx3DLightcolor7Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7)).GetValue();
923 case 7 : return ((const Svx3DLightcolor8Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8)).GetValue();
927 return Color(COL_BLACK);
930 basegfx::B3DVector Svx3DLightControl::GetLightDirection(sal_uInt32 nNum) const
932 if(nNum <= 7)
934 const SfxItemSet aLightItemSet(Get3DAttributes());
936 switch(nNum)
938 case 0 : return ((const Svx3DLightDirection1Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1)).GetValue();
939 case 1 : return ((const Svx3DLightDirection2Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2)).GetValue();
940 case 2 : return ((const Svx3DLightDirection3Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3)).GetValue();
941 case 3 : return ((const Svx3DLightDirection4Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4)).GetValue();
942 case 4 : return ((const Svx3DLightDirection5Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5)).GetValue();
943 case 5 : return ((const Svx3DLightDirection6Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6)).GetValue();
944 case 6 : return ((const Svx3DLightDirection7Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7)).GetValue();
945 case 7 : return ((const Svx3DLightDirection8Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8)).GetValue();
949 return basegfx::B3DVector();
954 SvxLightCtl3D::SvxLightCtl3D( Window* pParent, const ResId& rResId)
955 : Control(pParent, rResId),
956 maLightControl(this, 0),
957 maHorScroller(this, WB_HORZ | WB_DRAG),
958 maVerScroller(this, WB_VERT | WB_DRAG),
959 maSwitcher(this, 0)
961 // init members
962 Init();
965 SvxLightCtl3D::SvxLightCtl3D( Window* pParent)
966 : Control(pParent, WB_BORDER | WB_TABSTOP),
967 maLightControl(this, 0),
968 maHorScroller(this, WB_HORZ | WB_DRAG),
969 maVerScroller(this, WB_VERT | WB_DRAG),
970 maSwitcher(this, 0)
972 // init members
973 Init();
976 Size SvxLightCtl3D::GetOptimalSize() const
978 return LogicToPixel(Size(80, 100), MAP_APPFONT);
981 extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeSvxLightCtl3D(Window *pParent, VclBuilder::stringmap &)
983 return new SvxLightCtl3D(pParent);
987 void SvxLightCtl3D::Init()
989 // #i58240# set HelpIDs for scrollbars and switcher
990 maHorScroller.SetHelpId(HID_CTRL3D_HSCROLL);
991 maVerScroller.SetHelpId(HID_CTRL3D_VSCROLL);
992 maSwitcher.SetHelpId(HID_CTRL3D_SWITCHER);
993 maSwitcher.SetAccessibleName(SVX_RESSTR(STR_SWITCH));
995 // Light preview
996 maLightControl.Show();
997 maLightControl.SetChangeCallback( LINK(this, SvxLightCtl3D, InternalInteractiveChange) );
998 maLightControl.SetSelectionChangeCallback( LINK(this, SvxLightCtl3D, InternalSelectionChange) );
1000 // Horiz Scrollbar
1001 maHorScroller.Show();
1002 maHorScroller.SetRange(Range(0, 36000));
1003 maHorScroller.SetLineSize(100);
1004 maHorScroller.SetPageSize(1000);
1005 maHorScroller.SetScrollHdl( LINK(this, SvxLightCtl3D, ScrollBarMove) );
1007 // Vert Scrollbar
1008 maVerScroller.Show();
1009 maVerScroller.SetRange(Range(0, 18000));
1010 maVerScroller.SetLineSize(100);
1011 maVerScroller.SetPageSize(1000);
1012 maVerScroller.SetScrollHdl( LINK(this, SvxLightCtl3D, ScrollBarMove) );
1014 // Switch Button
1015 maSwitcher.Show();
1016 maSwitcher.SetClickHdl( LINK(this, SvxLightCtl3D, ButtonPress) );
1018 // check selection
1019 CheckSelection();
1021 // new layout
1022 NewLayout();
1025 SvxLightCtl3D::~SvxLightCtl3D()
1029 void SvxLightCtl3D::Resize()
1031 // call parent
1032 Control::Resize();
1034 // new layout
1035 NewLayout();
1038 void SvxLightCtl3D::NewLayout()
1040 // Layout members
1041 const Size aSize(GetOutputSizePixel());
1042 const sal_Int32 nScrollSize(maHorScroller.GetSizePixel().Height());
1044 // Preview control
1045 Point aPoint(0, 0);
1046 Size aDestSize(aSize.Width() - nScrollSize, aSize.Height() - nScrollSize);
1047 maLightControl.SetPosSizePixel(aPoint, aDestSize);
1049 // hor scrollbar
1050 aPoint.Y() = aSize.Height() - nScrollSize;
1051 aDestSize.Height() = nScrollSize;
1052 maHorScroller.SetPosSizePixel(aPoint, aDestSize);
1054 // vert scrollbar
1055 aPoint.X() = aSize.Width() - nScrollSize;
1056 aPoint.Y() = 0;
1057 aDestSize.Width() = nScrollSize;
1058 aDestSize.Height() = aSize.Height() - nScrollSize;
1059 maVerScroller.SetPosSizePixel(aPoint, aDestSize);
1061 // button
1062 aPoint.Y() = aSize.Height() - nScrollSize;
1063 aDestSize.Height() = nScrollSize;
1064 maSwitcher.SetPosSizePixel(aPoint, aDestSize);
1067 void SvxLightCtl3D::CheckSelection()
1069 const bool bSelectionValid(maLightControl.IsSelectionValid() || maLightControl.IsGeometrySelected());
1070 maHorScroller.Enable(bSelectionValid);
1071 maVerScroller.Enable(bSelectionValid);
1073 if(bSelectionValid)
1075 double fHor, fVer;
1076 maLightControl.GetPosition(fHor, fVer);
1077 maHorScroller.SetThumbPos( sal_Int32(fHor * 100.0) );
1078 maVerScroller.SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
1082 void SvxLightCtl3D::move( double fDeltaHor, double fDeltaVer )
1084 double fHor, fVer;
1086 maLightControl.GetPosition(fHor, fVer);
1087 fHor += fDeltaHor;
1088 fVer += fDeltaVer;
1090 if( fVer > 90.0 )
1091 return;
1093 if ( fVer < -90.0 )
1094 return;
1096 maLightControl.SetPosition(fHor, fVer);
1097 maHorScroller.SetThumbPos( sal_Int32(fHor * 100.0) );
1098 maVerScroller.SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
1100 if(maUserInteractiveChangeCallback.IsSet())
1102 maUserInteractiveChangeCallback.Call(this);
1106 void SvxLightCtl3D::KeyInput( const KeyEvent& rKEvt )
1108 const KeyCode aCode(rKEvt.GetKeyCode());
1110 if( aCode.GetModifier() )
1112 Control::KeyInput( rKEvt );
1113 return;
1116 switch ( aCode.GetCode() )
1118 case KEY_SPACE:
1120 break;
1122 case KEY_LEFT:
1124 move( -4.0, 0.0 ); // #i58242# changed move direction in X
1125 break;
1127 case KEY_RIGHT:
1129 move( 4.0, 0.0 ); // #i58242# changed move direction in X
1130 break;
1132 case KEY_UP:
1134 move( 0.0, 4.0 );
1135 break;
1137 case KEY_DOWN:
1139 move( 0.0, -4.0 );
1140 break;
1142 case KEY_PAGEUP:
1144 sal_Int32 nLight(maLightControl.GetSelectedLight() - 1);
1146 while((nLight >= 0) && !maLightControl.GetLightOnOff(nLight))
1148 nLight--;
1151 if(nLight < 0)
1153 nLight = 7;
1155 while((nLight >= 0) && !maLightControl.GetLightOnOff(nLight))
1157 nLight--;
1161 if(nLight >= 0)
1163 maLightControl.SelectLight(nLight);
1164 CheckSelection();
1166 if(maUserSelectionChangeCallback.IsSet())
1168 maUserSelectionChangeCallback.Call(this);
1172 break;
1174 case KEY_PAGEDOWN:
1176 sal_Int32 nLight(maLightControl.GetSelectedLight() - 1);
1178 while(nLight <= 7 && !maLightControl.GetLightOnOff(nLight))
1180 nLight++;
1183 if(nLight > 7)
1185 nLight = 0;
1187 while(nLight <= 7 && !maLightControl.GetLightOnOff(nLight))
1189 nLight++;
1193 if(nLight <= 7)
1195 maLightControl.SelectLight(nLight);
1196 CheckSelection();
1198 if(maUserSelectionChangeCallback.IsSet())
1200 maUserSelectionChangeCallback.Call(this);
1204 break;
1206 default:
1208 Control::KeyInput( rKEvt );
1209 break;
1214 void SvxLightCtl3D::GetFocus()
1216 Control::GetFocus();
1218 if(HasFocus() && IsEnabled())
1220 CheckSelection();
1222 Size aFocusSize = maLightControl.GetOutputSizePixel();
1224 aFocusSize.Width() -= 4;
1225 aFocusSize.Height() -= 4;
1227 Rectangle aFocusRect( Point( 2, 2 ), aFocusSize );
1229 aFocusRect = maLightControl.PixelToLogic( aFocusRect );
1231 maLightControl.ShowFocus( aFocusRect );
1235 void SvxLightCtl3D::LoseFocus()
1237 Control::LoseFocus();
1239 maLightControl.HideFocus();
1242 IMPL_LINK_NOARG(SvxLightCtl3D, ScrollBarMove)
1244 const sal_Int32 nHor(maHorScroller.GetThumbPos());
1245 const sal_Int32 nVer(maVerScroller.GetThumbPos());
1247 maLightControl.SetPosition(
1248 ((double)nHor) / 100.0,
1249 ((double)((18000 - nVer) - 9000)) / 100.0);
1251 if(maUserInteractiveChangeCallback.IsSet())
1253 maUserInteractiveChangeCallback.Call(this);
1256 return 0;
1259 IMPL_LINK_NOARG(SvxLightCtl3D, ButtonPress)
1261 if(PREVIEW_OBJECTTYPE_SPHERE == GetSvx3DLightControl().GetObjectType())
1263 GetSvx3DLightControl().SetObjectType(PREVIEW_OBJECTTYPE_CUBE);
1265 else
1267 GetSvx3DLightControl().SetObjectType(PREVIEW_OBJECTTYPE_SPHERE);
1270 return 0;
1273 IMPL_LINK_NOARG(SvxLightCtl3D, InternalInteractiveChange)
1275 double fHor, fVer;
1277 maLightControl.GetPosition(fHor, fVer);
1278 maHorScroller.SetThumbPos( sal_Int32(fHor * 100.0) );
1279 maVerScroller.SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
1281 if(maUserInteractiveChangeCallback.IsSet())
1283 maUserInteractiveChangeCallback.Call(this);
1286 return 0;
1289 IMPL_LINK_NOARG(SvxLightCtl3D, InternalSelectionChange)
1291 CheckSelection();
1293 if(maUserSelectionChangeCallback.IsSet())
1295 maUserSelectionChangeCallback.Call(this);
1298 return 0;
1301 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */