Bump version to 6.4.7.2.M8
[LibreOffice.git] / svx / source / dialog / dlgctl3d.cxx
blob8d73639261a5509f9ac936f690dd991af756644a
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/def3d.hxx>
22 #include <svx/dlgctl3d.hxx>
23 #include <svx/strings.hrc>
24 #include <svx/view3d.hxx>
25 #include <svx/fmmodel.hxx>
26 #include <svl/itempool.hxx>
27 #include <svx/fmpage.hxx>
28 #include <svx/sphere3d.hxx>
29 #include <svx/cube3d.hxx>
30 #include <svx/scene3d.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/builderfactory.hxx>
33 #include <svx/helperhittest3d.hxx>
34 #include <basegfx/polygon/b2dpolygontools.hxx>
35 #include <svx/polygn3d.hxx>
36 #include <svx/xfillit0.hxx>
37 #include <svx/xflclit.hxx>
38 #include <svx/xlineit0.hxx>
39 #include <svx/xlnclit.hxx>
40 #include <svx/xlnwtit.hxx>
41 #include <helpids.h>
42 #include <algorithm>
43 #include <svx/dialmgr.hxx>
44 #include <tools/helpers.hxx>
45 #include <vcl/settings.hxx>
47 using namespace com::sun::star;
49 Svx3DPreviewControl::Svx3DPreviewControl(vcl::Window* pParent, WinBits nStyle)
50 : Control(pParent, nStyle),
51 mpFmPage(nullptr),
52 mpScene(nullptr),
53 mp3DObj(nullptr),
54 mnObjectType(SvxPreviewObjectType::SPHERE)
56 Construct();
58 // do not paint background self, DrawingLayer paints this buffered and as page
59 SetControlBackground();
60 SetBackground();
63 Size Svx3DPreviewControl::GetOptimalSize() const
65 return LogicToPixel(Size(80, 100), MapMode(MapUnit::MapAppFont));
68 VCL_BUILDER_FACTORY(Svx3DPreviewControl)
70 Svx3DPreviewControl::~Svx3DPreviewControl()
72 disposeOnce();
75 void Svx3DPreviewControl::dispose()
77 mp3DView.reset();
78 mpModel.reset();
79 Control::dispose();
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(MapMode(MapUnit::Map100thMM));
89 // Model
90 mpModel.reset(new FmFormModel());
91 mpModel->GetItemPool().FreezeIdRanges();
93 // Page
94 mpFmPage = new FmFormPage( *mpModel );
95 mpModel->InsertPage( mpFmPage, 0 );
97 // 3D View
98 mp3DView.reset(new E3dView(*mpModel, this ));
99 mp3DView->SetBufferedOutputAllowed(true);
100 mp3DView->SetBufferedOverlayAllowed(true);
102 // 3D Scene
103 mpScene = new E3dScene(*mpModel);
105 // initially create object
106 SetObjectType(SvxPreviewObjectType::SPHERE);
108 // camera and perspective
109 Camera3D rCamera = 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);
124 mpScene->SetCamera( rCamera );
125 mpFmPage->InsertObject( mpScene );
127 basegfx::B3DHomMatrix aRotation;
128 aRotation.rotate(DEG2RAD( 25 ), 0.0, 0.0);
129 aRotation.rotate(0.0, DEG2RAD( 40 ), 0.0);
130 mpScene->SetTransform(aRotation * mpScene->GetTransform());
132 // invalidate SnapRects of objects
133 mpScene->SetRectsDirty();
135 SfxItemSet aSet( mpModel->GetItemPool(),
136 svl::Items<XATTR_LINESTYLE, XATTR_LINESTYLE,
137 XATTR_FILL_FIRST, XATTR_FILLBITMAP>{} );
138 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
139 aSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
140 aSet.Put( XFillColorItem( "", COL_WHITE ) );
142 mpScene->SetMergedItemSet(aSet);
144 // PageView
145 SdrPageView* pPageView = mp3DView->ShowSdrPage( mpFmPage );
146 mp3DView->hideMarkHandles();
148 // mark scene
149 mp3DView->MarkObj( mpScene, pPageView );
152 void Svx3DPreviewControl::Resize()
154 // size of page
155 Size aSize( GetSizePixel() );
156 aSize = PixelToLogic( aSize );
157 mpFmPage->SetSize( aSize );
159 // set size
160 Size aObjSize( aSize.Width()*5/6, aSize.Height()*5/6 );
161 Point aObjPoint( (aSize.Width() - aObjSize.Width()) / 2,
162 (aSize.Height() - aObjSize.Height()) / 2);
163 tools::Rectangle aRect( aObjPoint, aObjSize);
164 mpScene->SetSnapRect( aRect );
167 void Svx3DPreviewControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
169 mp3DView->CompleteRedraw(&rRenderContext, vcl::Region(rRect));
172 void Svx3DPreviewControl::MouseButtonDown(const MouseEvent& rMEvt)
174 Control::MouseButtonDown(rMEvt);
176 if( rMEvt.IsShift() && rMEvt.IsMod1() )
178 if(SvxPreviewObjectType::SPHERE == GetObjectType())
180 SetObjectType(SvxPreviewObjectType::CUBE);
182 else
184 SetObjectType(SvxPreviewObjectType::SPHERE);
189 void Svx3DPreviewControl::SetObjectType(SvxPreviewObjectType nType)
191 if( mnObjectType != nType || !mp3DObj)
193 SfxItemSet aSet(mpModel->GetItemPool(), svl::Items<SDRATTR_START, SDRATTR_END>{});
194 mnObjectType = nType;
196 if( mp3DObj )
198 aSet.Put(mp3DObj->GetMergedItemSet());
199 mpScene->RemoveObject( mp3DObj->GetOrdNum() );
200 // always use SdrObject::Free(...) for SdrObjects (!)
201 SdrObject* pTemp(mp3DObj);
202 SdrObject::Free(pTemp);
205 switch( nType )
207 case SvxPreviewObjectType::SPHERE:
209 mp3DObj = new E3dSphereObj(
210 *mpModel,
211 mp3DView->Get3DDefaultAttributes(),
212 basegfx::B3DPoint( 0, 0, 0 ),
213 basegfx::B3DVector( 5000, 5000, 5000 ));
215 break;
217 case SvxPreviewObjectType::CUBE:
219 mp3DObj = new E3dCubeObj(
220 *mpModel,
221 mp3DView->Get3DDefaultAttributes(),
222 basegfx::B3DPoint( -2500, -2500, -2500 ),
223 basegfx::B3DVector( 5000, 5000, 5000 ));
225 break;
228 if (mp3DObj)
230 mpScene->InsertObject( mp3DObj );
231 mp3DObj->SetMergedItemSet(aSet);
234 Resize();
238 SfxItemSet const & Svx3DPreviewControl::Get3DAttributes() const
240 return mp3DObj->GetMergedItemSet();
243 void Svx3DPreviewControl::Set3DAttributes( const SfxItemSet& rAttr )
245 mp3DObj->SetMergedItemSet(rAttr, true);
246 Resize();
249 PreviewControl3D::PreviewControl3D()
250 : mpFmPage(nullptr)
251 , mpScene(nullptr)
252 , mp3DObj(nullptr)
253 , mnObjectType(SvxPreviewObjectType::SPHERE)
257 void PreviewControl3D::SetDrawingArea(weld::DrawingArea* pDrawingArea)
259 Size aSize(pDrawingArea->get_ref_device().LogicToPixel(Size(80, 100), MapMode(MapUnit::MapAppFont)));
260 pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
261 CustomWidgetController::SetDrawingArea(pDrawingArea);
262 SetOutputSizePixel(aSize);
264 Construct();
267 PreviewControl3D::~PreviewControl3D()
269 mp3DView.reset();
270 mpModel.reset();
273 void PreviewControl3D::Construct()
275 // Do never mirror the preview window. This explicitly includes right
276 // to left writing environments.
277 EnableRTL (false);
278 OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
279 rDevice.SetMapMode(MapMode(MapUnit::Map100thMM));
281 // Model
282 mpModel.reset(new FmFormModel());
283 mpModel->GetItemPool().FreezeIdRanges();
285 // Page
286 mpFmPage = new FmFormPage( *mpModel );
287 mpModel->InsertPage( mpFmPage, 0 );
289 // 3D View
290 mp3DView.reset(new E3dView(*mpModel, &rDevice));
291 mp3DView->SetBufferedOutputAllowed(true);
292 mp3DView->SetBufferedOverlayAllowed(true);
294 // 3D Scene
295 mpScene = new E3dScene(*mpModel);
297 // initially create object
298 SetObjectType(SvxPreviewObjectType::SPHERE);
300 // camera and perspective
301 Camera3D rCamera = mpScene->GetCamera();
302 const basegfx::B3DRange& rVolume = mpScene->GetBoundVolume();
303 double fW = rVolume.getWidth();
304 double fH = rVolume.getHeight();
305 double fCamZ = rVolume.getMaxZ() + ((fW + fH) / 2.0);
307 rCamera.SetAutoAdjustProjection(false);
308 rCamera.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
309 basegfx::B3DPoint aLookAt;
310 double fDefaultCamPosZ = mp3DView->GetDefaultCamPosZ();
311 basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
312 rCamera.SetPosAndLookAt(aCamPos, aLookAt);
313 double fDefaultCamFocal = mp3DView->GetDefaultCamFocal();
314 rCamera.SetFocalLength(fDefaultCamFocal);
316 mpScene->SetCamera( rCamera );
317 mpFmPage->InsertObject( mpScene );
319 basegfx::B3DHomMatrix aRotation;
320 aRotation.rotate(DEG2RAD( 25 ), 0.0, 0.0);
321 aRotation.rotate(0.0, DEG2RAD( 40 ), 0.0);
322 mpScene->SetTransform(aRotation * mpScene->GetTransform());
324 // invalidate SnapRects of objects
325 mpScene->SetRectsDirty();
327 SfxItemSet aSet( mpModel->GetItemPool(),
328 svl::Items<XATTR_LINESTYLE, XATTR_LINESTYLE,
329 XATTR_FILL_FIRST, XATTR_FILLBITMAP>{} );
330 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
331 aSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
332 aSet.Put( XFillColorItem( "", COL_WHITE ) );
334 mpScene->SetMergedItemSet(aSet);
336 // PageView
337 SdrPageView* pPageView = mp3DView->ShowSdrPage( mpFmPage );
338 mp3DView->hideMarkHandles();
340 // mark scene
341 mp3DView->MarkObj( mpScene, pPageView );
344 void PreviewControl3D::Resize()
346 // size of page
347 Size aSize(GetOutputSizePixel());
348 aSize = GetDrawingArea()->get_ref_device().PixelToLogic(aSize);
349 mpFmPage->SetSize(aSize);
351 // set size
352 Size aObjSize( aSize.Width()*5/6, aSize.Height()*5/6 );
353 Point aObjPoint( (aSize.Width() - aObjSize.Width()) / 2,
354 (aSize.Height() - aObjSize.Height()) / 2);
355 tools::Rectangle aRect( aObjPoint, aObjSize);
356 mpScene->SetSnapRect( aRect );
359 void PreviewControl3D::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
361 mp3DView->CompleteRedraw(&rRenderContext, vcl::Region(rRect));
364 bool PreviewControl3D::MouseButtonDown(const MouseEvent& rMEvt)
366 if (rMEvt.IsShift() && rMEvt.IsMod1())
368 if(SvxPreviewObjectType::SPHERE == GetObjectType())
370 SetObjectType(SvxPreviewObjectType::CUBE);
372 else
374 SetObjectType(SvxPreviewObjectType::SPHERE);
377 return false;
380 void PreviewControl3D::SetObjectType(SvxPreviewObjectType nType)
382 if( mnObjectType != nType || !mp3DObj)
384 SfxItemSet aSet(mpModel->GetItemPool(), svl::Items<SDRATTR_START, SDRATTR_END>{});
385 mnObjectType = nType;
387 if( mp3DObj )
389 aSet.Put(mp3DObj->GetMergedItemSet());
390 mpScene->RemoveObject( mp3DObj->GetOrdNum() );
391 // always use SdrObject::Free(...) for SdrObjects (!)
392 SdrObject* pTemp(mp3DObj);
393 SdrObject::Free(pTemp);
396 switch( nType )
398 case SvxPreviewObjectType::SPHERE:
400 mp3DObj = new E3dSphereObj(
401 *mpModel,
402 mp3DView->Get3DDefaultAttributes(),
403 basegfx::B3DPoint( 0, 0, 0 ),
404 basegfx::B3DVector( 5000, 5000, 5000 ));
406 break;
408 case SvxPreviewObjectType::CUBE:
410 mp3DObj = new E3dCubeObj(
411 *mpModel,
412 mp3DView->Get3DDefaultAttributes(),
413 basegfx::B3DPoint( -2500, -2500, -2500 ),
414 basegfx::B3DVector( 5000, 5000, 5000 ));
416 break;
419 if (mp3DObj)
421 mpScene->InsertObject( mp3DObj );
422 mp3DObj->SetMergedItemSet(aSet);
425 Invalidate();
429 SfxItemSet const & PreviewControl3D::Get3DAttributes() const
431 return mp3DObj->GetMergedItemSet();
434 void PreviewControl3D::Set3DAttributes( const SfxItemSet& rAttr )
436 mp3DObj->SetMergedItemSet(rAttr, true);
437 Resize();
440 #define RADIUS_LAMP_PREVIEW_SIZE (4500.0)
441 #define RADIUS_LAMP_SMALL (600.0)
442 #define RADIUS_LAMP_BIG (1000.0)
443 #define NO_LIGHT_SELECTED (0xffffffff)
444 #define MAX_NUMBER_LIGHTS (8)
446 static const sal_Int32 g_nInteractionStartDistance = 5 * 5 * 2;
448 Svx3DLightControl::Svx3DLightControl(vcl::Window* pParent, WinBits nStyle)
449 : Svx3DPreviewControl(pParent, nStyle),
450 maChangeCallback(),
451 maSelectionChangeCallback(),
452 maSelectedLight(NO_LIGHT_SELECTED),
453 mpExpansionObject(nullptr),
454 mpLampBottomObject(nullptr),
455 mpLampShaftObject(nullptr),
456 maLightObjects(MAX_NUMBER_LIGHTS, nullptr),
457 mfRotateX(-20.0),
458 mfRotateY(45.0),
459 mfRotateZ(0.0),
460 maActionStartPoint(),
461 mfSaveActionStartHor(0.0),
462 mfSaveActionStartVer(0.0),
463 mfSaveActionStartRotZ(0.0),
464 mbMouseMoved(false),
465 mbGeometrySelected(false)
467 Construct2();
470 void Svx3DLightControl::Construct2()
473 // hide all page stuff, use control background (normally gray)
474 const Color aDialogColor(Application::GetSettings().GetStyleSettings().GetDialogColor());
475 mp3DView->SetPageVisible(false);
476 mp3DView->SetApplicationBackgroundColor(aDialogColor);
477 mp3DView->SetApplicationDocumentColor(aDialogColor);
481 // create invisible expansion object
482 const double fMaxExpansion(RADIUS_LAMP_BIG + RADIUS_LAMP_PREVIEW_SIZE);
483 mpExpansionObject = new E3dCubeObj(
484 *mpModel,
485 mp3DView->Get3DDefaultAttributes(),
486 basegfx::B3DPoint(-fMaxExpansion, -fMaxExpansion, -fMaxExpansion),
487 basegfx::B3DVector(2.0 * fMaxExpansion, 2.0 * fMaxExpansion, 2.0 * fMaxExpansion));
488 mpScene->InsertObject( mpExpansionObject );
489 SfxItemSet aSet(mpModel->GetItemPool());
490 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
491 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
492 mpExpansionObject->SetMergedItemSet(aSet);
496 // create lamp control object (Yellow lined object)
497 // base circle
498 const basegfx::B2DPolygon a2DCircle(basegfx::utils::createPolygonFromCircle(basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE));
499 basegfx::B3DPolygon a3DCircle(basegfx::utils::createB3DPolygonFromB2DPolygon(a2DCircle));
500 basegfx::B3DHomMatrix aTransform;
502 aTransform.rotate(F_PI2, 0.0, 0.0);
503 aTransform.translate(0.0, -RADIUS_LAMP_PREVIEW_SIZE, 0.0);
504 a3DCircle.transform(aTransform);
506 // create object for it
507 mpLampBottomObject = new E3dPolygonObj(
508 *mpModel,
509 basegfx::B3DPolyPolygon(a3DCircle));
510 mpScene->InsertObject( mpLampBottomObject );
512 // half circle with stand
513 basegfx::B2DPolygon a2DHalfCircle;
514 a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, 0.0));
515 a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, -RADIUS_LAMP_PREVIEW_SIZE));
516 a2DHalfCircle.append(basegfx::utils::createPolygonFromEllipseSegment(
517 basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE, RADIUS_LAMP_PREVIEW_SIZE, F_2PI - F_PI2, F_PI2));
518 basegfx::B3DPolygon a3DHalfCircle(basegfx::utils::createB3DPolygonFromB2DPolygon(a2DHalfCircle));
520 // create object for it
521 mpLampShaftObject = new E3dPolygonObj(
522 *mpModel,
523 basegfx::B3DPolyPolygon(a3DHalfCircle));
524 mpScene->InsertObject( mpLampShaftObject );
526 // initially invisible
527 SfxItemSet aSet(mpModel->GetItemPool());
528 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
529 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
531 mpLampBottomObject->SetMergedItemSet(aSet);
532 mpLampShaftObject->SetMergedItemSet(aSet);
536 // change camera settings
537 Camera3D rCamera = mpScene->GetCamera();
538 const basegfx::B3DRange& rVolume = mpScene->GetBoundVolume();
539 double fW = rVolume.getWidth();
540 double fH = rVolume.getHeight();
541 double fCamZ = rVolume.getMaxZ() + ((fW + fH) / 2.0);
543 rCamera.SetAutoAdjustProjection(false);
544 rCamera.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
545 basegfx::B3DPoint aLookAt;
546 double fDefaultCamPosZ = mp3DView->GetDefaultCamPosZ();
547 basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
548 rCamera.SetPosAndLookAt(aCamPos, aLookAt);
549 double fDefaultCamFocal = mp3DView->GetDefaultCamFocal();
550 rCamera.SetFocalLength(fDefaultCamFocal);
552 mpScene->SetCamera( rCamera );
554 basegfx::B3DHomMatrix aNeutral;
555 mpScene->SetTransform(aNeutral);
558 // invalidate SnapRects of objects
559 mpScene->SetRectsDirty();
562 void Svx3DLightControl::ConstructLightObjects()
564 for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
566 // get rid of possible existing light object
567 if(maLightObjects[a])
569 mpScene->RemoveObject(maLightObjects[a]->GetOrdNum());
570 // always use SdrObject::Free(...) for SdrObjects (!)
571 SdrObject* pTemp(maLightObjects[a]);
572 SdrObject::Free(pTemp);
573 maLightObjects[a] = nullptr;
576 if(GetLightOnOff(a))
578 const bool bIsSelectedLight(a == maSelectedLight);
579 basegfx::B3DVector aDirection(GetLightDirection(a));
580 aDirection.normalize();
581 aDirection *= RADIUS_LAMP_PREVIEW_SIZE;
583 const double fLampSize(bIsSelectedLight ? RADIUS_LAMP_BIG : RADIUS_LAMP_SMALL);
584 E3dObject* pNewLight = new E3dSphereObj(
585 *mpModel,
586 mp3DView->Get3DDefaultAttributes(),
587 basegfx::B3DPoint( 0, 0, 0 ),
588 basegfx::B3DVector( fLampSize, fLampSize, fLampSize));
589 mpScene->InsertObject(pNewLight);
591 basegfx::B3DHomMatrix aTransform;
592 aTransform.translate(aDirection.getX(), aDirection.getY(), aDirection.getZ());
593 pNewLight->SetTransform(aTransform);
595 SfxItemSet aSet(mpModel->GetItemPool());
596 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
597 aSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
598 aSet.Put( XFillColorItem(OUString(), GetLightColor(a)));
599 pNewLight->SetMergedItemSet(aSet);
601 maLightObjects[a] = pNewLight;
606 void Svx3DLightControl::AdaptToSelectedLight()
608 if(NO_LIGHT_SELECTED == maSelectedLight)
610 // make mpLampBottomObject/mpLampShaftObject invisible
611 SfxItemSet aSet(mpModel->GetItemPool());
612 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
613 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
614 mpLampBottomObject->SetMergedItemSet(aSet);
615 mpLampShaftObject->SetMergedItemSet(aSet);
617 else
619 basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
620 aDirection.normalize();
622 // make mpLampBottomObject/mpLampShaftObject visible (yellow hairline)
623 SfxItemSet aSet(mpModel->GetItemPool());
624 aSet.Put( XLineStyleItem( drawing::LineStyle_SOLID ) );
625 aSet.Put( XLineColorItem(OUString(), COL_YELLOW));
626 aSet.Put( XLineWidthItem(0));
627 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
628 mpLampBottomObject->SetMergedItemSet(aSet);
629 mpLampShaftObject->SetMergedItemSet(aSet);
631 // adapt transformation of mpLampShaftObject
632 basegfx::B3DHomMatrix aTransform;
633 double fRotateY(0.0);
635 if(!basegfx::fTools::equalZero(aDirection.getZ()) || !basegfx::fTools::equalZero(aDirection.getX()))
637 fRotateY = atan2(-aDirection.getZ(), aDirection.getX());
640 aTransform.rotate(0.0, fRotateY, 0.0);
641 mpLampShaftObject->SetTransform(aTransform);
643 // adapt transformation of selected light
644 E3dObject* pSelectedLight = maLightObjects[sal_Int32(maSelectedLight)];
646 if(pSelectedLight)
648 aTransform.identity();
649 aTransform.translate(
650 aDirection.getX() * RADIUS_LAMP_PREVIEW_SIZE,
651 aDirection.getY() * RADIUS_LAMP_PREVIEW_SIZE,
652 aDirection.getZ() * RADIUS_LAMP_PREVIEW_SIZE);
653 pSelectedLight->SetTransform(aTransform);
658 void Svx3DLightControl::TrySelection(Point aPosPixel)
660 if(mpScene)
662 const Point aPosLogic(PixelToLogic(aPosPixel));
663 const basegfx::B2DPoint aPoint(aPosLogic.X(), aPosLogic.Y());
664 std::vector< const E3dCompoundObject* > aResult;
665 getAllHit3DObjectsSortedFrontToBack(aPoint, *mpScene, aResult);
667 if(!aResult.empty())
669 // exclude expansion object which will be part of
670 // the hits. It's invisible, but for HitTest, it's included
671 const E3dCompoundObject* pResult = nullptr;
673 for(auto const & b: aResult)
675 if(b && b != mpExpansionObject)
677 pResult = b;
678 break;
682 if(pResult == mp3DObj)
684 if(!mbGeometrySelected)
686 mbGeometrySelected = true;
687 maSelectedLight = NO_LIGHT_SELECTED;
688 ConstructLightObjects();
689 AdaptToSelectedLight();
690 Invalidate();
692 if(maSelectionChangeCallback.IsSet())
694 maSelectionChangeCallback.Call(this);
698 else
700 sal_uInt32 aNewSelectedLight(NO_LIGHT_SELECTED);
702 for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
704 if(maLightObjects[a] && maLightObjects[a] == pResult)
706 aNewSelectedLight = a;
710 if(aNewSelectedLight != maSelectedLight)
712 SelectLight(aNewSelectedLight);
714 if(maSelectionChangeCallback.IsSet())
716 maSelectionChangeCallback.Call(this);
724 void Svx3DLightControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
726 Svx3DPreviewControl::Paint(rRenderContext, rRect);
729 void Svx3DLightControl::MouseButtonDown( const MouseEvent& rMEvt )
731 bool bCallParent(true);
733 // switch state
734 if(rMEvt.IsLeft())
736 if(IsSelectionValid() || mbGeometrySelected)
738 mbMouseMoved = false;
739 bCallParent = false;
740 maActionStartPoint = rMEvt.GetPosPixel();
741 StartTracking();
743 else
745 // Single click without moving much trying to do a selection
746 TrySelection(rMEvt.GetPosPixel());
747 bCallParent = false;
751 // call parent
752 if(bCallParent)
754 Svx3DPreviewControl::MouseButtonDown(rMEvt);
758 void Svx3DLightControl::Tracking( const TrackingEvent& rTEvt )
760 if(rTEvt.IsTrackingEnded())
762 if(rTEvt.IsTrackingCanceled())
764 if(mbMouseMoved)
766 // interrupt tracking
767 mbMouseMoved = false;
769 if(mbGeometrySelected)
771 SetRotation(mfSaveActionStartVer, mfSaveActionStartHor, mfSaveActionStartRotZ);
773 else
775 SetPosition(mfSaveActionStartHor, mfSaveActionStartVer);
778 if(maChangeCallback.IsSet())
780 maChangeCallback.Call(this);
784 else
786 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
788 if(mbMouseMoved)
790 // was change interactively
792 else
794 // simple click without much movement, try selection
795 TrySelection(rMEvt.GetPosPixel());
799 else
801 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
802 Point aDeltaPos = rMEvt.GetPosPixel() - maActionStartPoint;
804 if(!mbMouseMoved)
806 if(sal_Int32(aDeltaPos.X() * aDeltaPos.X() + aDeltaPos.Y() * aDeltaPos.Y()) > g_nInteractionStartDistance)
808 if(mbGeometrySelected)
810 GetRotation(mfSaveActionStartVer, mfSaveActionStartHor, mfSaveActionStartRotZ);
812 else
814 // interaction start, save values
815 GetPosition(mfSaveActionStartHor, mfSaveActionStartVer);
818 mbMouseMoved = true;
822 if(mbMouseMoved)
824 if(mbGeometrySelected)
826 double fNewRotX = mfSaveActionStartVer - basegfx::deg2rad(aDeltaPos.Y());
827 double fNewRotY = mfSaveActionStartHor + basegfx::deg2rad(aDeltaPos.X());
829 // cut horizontal
830 while(fNewRotY < 0.0)
832 fNewRotY += F_2PI;
835 while(fNewRotY >= F_2PI)
837 fNewRotY -= F_2PI;
840 // cut vertical
841 if(fNewRotX < -F_PI2)
843 fNewRotX = -F_PI2;
846 if(fNewRotX > F_PI2)
848 fNewRotX = F_PI2;
851 SetRotation(fNewRotX, fNewRotY, mfSaveActionStartRotZ);
853 if(maChangeCallback.IsSet())
855 maChangeCallback.Call(this);
858 else
860 // interaction in progress
861 double fNewPosHor = mfSaveActionStartHor + static_cast<double>(aDeltaPos.X());
862 double fNewPosVer = mfSaveActionStartVer - static_cast<double>(aDeltaPos.Y());
864 // cut horizontal
865 fNewPosHor = NormAngle360(fNewPosHor);
867 // cut vertical
868 if(fNewPosVer < -90.0)
870 fNewPosVer = -90.0;
873 if(fNewPosVer > 90.0)
875 fNewPosVer = 90.0;
878 SetPosition(fNewPosHor, fNewPosVer);
880 if(maChangeCallback.IsSet())
882 maChangeCallback.Call(this);
889 void Svx3DLightControl::Resize()
891 // set size of page
892 const Size aSize(PixelToLogic(GetSizePixel()));
893 mpFmPage->SetSize(aSize);
895 // set position and size of scene
896 mpScene->SetSnapRect(tools::Rectangle(Point(0, 0), aSize));
899 void Svx3DLightControl::SetObjectType(SvxPreviewObjectType nType)
901 // call parent
902 Svx3DPreviewControl::SetObjectType(nType);
904 // apply object rotation
905 if(mp3DObj)
907 basegfx::B3DHomMatrix aObjectRotation;
908 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
909 mp3DObj->SetTransform(aObjectRotation);
913 bool Svx3DLightControl::IsSelectionValid()
915 return (NO_LIGHT_SELECTED != maSelectedLight) && GetLightOnOff(maSelectedLight);
918 void Svx3DLightControl::GetPosition(double& rHor, double& rVer)
920 if(IsSelectionValid())
922 basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
923 aDirection.normalize();
924 rHor = basegfx::rad2deg(atan2(-aDirection.getX(), -aDirection.getZ()) + F_PI); // 0..360.0
925 rVer = basegfx::rad2deg(atan2(aDirection.getY(), aDirection.getXZLength())); // -90.0..90.0
927 if(IsGeometrySelected())
929 rHor = basegfx::rad2deg(mfRotateY); // 0..360.0
930 rVer = basegfx::rad2deg(mfRotateX); // -90.0..90.0
934 void Svx3DLightControl::SetPosition(double fHor, double fVer)
936 if(IsSelectionValid())
938 // set selected light's direction
939 fHor = basegfx::deg2rad(fHor) - F_PI; // -PI..PI
940 fVer = basegfx::deg2rad(fVer); // -PI2..PI2
941 basegfx::B3DVector aDirection(cos(fVer) * -sin(fHor), sin(fVer), cos(fVer) * -cos(fHor));
942 aDirection.normalize();
944 if(!aDirection.equal(GetLightDirection(maSelectedLight)))
946 // set changed light direction at SdrScene
947 SfxItemSet aSet(mpModel->GetItemPool());
949 switch(maSelectedLight)
951 case 0: aSet.Put(makeSvx3DLightDirection1Item(aDirection)); break;
952 case 1: aSet.Put(makeSvx3DLightDirection2Item(aDirection)); break;
953 case 2: aSet.Put(makeSvx3DLightDirection3Item(aDirection)); break;
954 case 3: aSet.Put(makeSvx3DLightDirection4Item(aDirection)); break;
955 case 4: aSet.Put(makeSvx3DLightDirection5Item(aDirection)); break;
956 case 5: aSet.Put(makeSvx3DLightDirection6Item(aDirection)); break;
957 case 6: aSet.Put(makeSvx3DLightDirection7Item(aDirection)); break;
958 default:
959 case 7: aSet.Put(makeSvx3DLightDirection8Item(aDirection)); break;
962 mpScene->SetMergedItemSet(aSet);
964 // correct 3D light's and LampFrame's geometries
965 AdaptToSelectedLight();
966 Invalidate();
969 if(IsGeometrySelected())
971 if(mfRotateX != fVer || mfRotateY != fHor)
973 mfRotateX = basegfx::deg2rad(fVer);
974 mfRotateY = basegfx::deg2rad(fHor);
976 if(mp3DObj)
978 basegfx::B3DHomMatrix aObjectRotation;
979 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
980 mp3DObj->SetTransform(aObjectRotation);
982 Invalidate();
988 void Svx3DLightControl::SetRotation(double fRotX, double fRotY, double fRotZ)
990 if(IsGeometrySelected())
992 if(fRotX != mfRotateX || fRotY != mfRotateY || fRotZ != mfRotateZ)
994 mfRotateX = fRotX;
995 mfRotateY = fRotY;
996 mfRotateZ = fRotZ;
998 if(mp3DObj)
1000 basegfx::B3DHomMatrix aObjectRotation;
1001 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
1002 mp3DObj->SetTransform(aObjectRotation);
1004 Invalidate();
1010 void Svx3DLightControl::GetRotation(double& rRotX, double& rRotY, double& rRotZ)
1012 rRotX = mfRotateX;
1013 rRotY = mfRotateY;
1014 rRotZ = mfRotateZ;
1017 void Svx3DLightControl::Set3DAttributes( const SfxItemSet& rAttr )
1019 // call parent
1020 Svx3DPreviewControl::Set3DAttributes(rAttr);
1022 if(maSelectedLight != NO_LIGHT_SELECTED && !GetLightOnOff(maSelectedLight))
1024 // selected light is no more active, select new one
1025 maSelectedLight = NO_LIGHT_SELECTED;
1028 // local updates
1029 ConstructLightObjects();
1030 AdaptToSelectedLight();
1031 Invalidate();
1034 void Svx3DLightControl::SelectLight(sal_uInt32 nLightNumber)
1036 if(nLightNumber > 7)
1038 nLightNumber = NO_LIGHT_SELECTED;
1041 if(NO_LIGHT_SELECTED != nLightNumber)
1043 if(!GetLightOnOff(nLightNumber))
1045 nLightNumber = NO_LIGHT_SELECTED;
1049 if(nLightNumber != maSelectedLight)
1051 maSelectedLight = nLightNumber;
1052 mbGeometrySelected = false;
1053 ConstructLightObjects();
1054 AdaptToSelectedLight();
1055 Invalidate();
1059 bool Svx3DLightControl::GetLightOnOff(sal_uInt32 nNum) const
1061 if(nNum <= 7)
1063 const SfxItemSet aLightItemSet(Get3DAttributes());
1065 switch(nNum)
1067 case 0 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_1).GetValue();
1068 case 1 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_2).GetValue();
1069 case 2 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_3).GetValue();
1070 case 3 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_4).GetValue();
1071 case 4 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_5).GetValue();
1072 case 5 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_6).GetValue();
1073 case 6 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_7).GetValue();
1074 case 7 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_8).GetValue();
1078 return false;
1081 Color Svx3DLightControl::GetLightColor(sal_uInt32 nNum) const
1083 if(nNum <= 7)
1085 const SfxItemSet aLightItemSet(Get3DAttributes());
1087 switch(nNum)
1089 case 0 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1).GetValue();
1090 case 1 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2).GetValue();
1091 case 2 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3).GetValue();
1092 case 3 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4).GetValue();
1093 case 4 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5).GetValue();
1094 case 5 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6).GetValue();
1095 case 6 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7).GetValue();
1096 case 7 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8).GetValue();
1100 return COL_BLACK;
1103 basegfx::B3DVector Svx3DLightControl::GetLightDirection(sal_uInt32 nNum) const
1105 if(nNum <= 7)
1107 const SfxItemSet aLightItemSet(Get3DAttributes());
1109 switch(nNum)
1111 case 0 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1).GetValue();
1112 case 1 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2).GetValue();
1113 case 2 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3).GetValue();
1114 case 3 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4).GetValue();
1115 case 4 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5).GetValue();
1116 case 5 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6).GetValue();
1117 case 6 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7).GetValue();
1118 case 7 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8).GetValue();
1122 return basegfx::B3DVector();
1125 LightControl3D::LightControl3D()
1126 : maChangeCallback(),
1127 maSelectionChangeCallback(),
1128 maSelectedLight(NO_LIGHT_SELECTED),
1129 mpExpansionObject(nullptr),
1130 mpLampBottomObject(nullptr),
1131 mpLampShaftObject(nullptr),
1132 maLightObjects(MAX_NUMBER_LIGHTS, nullptr),
1133 mfRotateX(-20.0),
1134 mfRotateY(45.0),
1135 mfRotateZ(0.0),
1136 maActionStartPoint(),
1137 mfSaveActionStartHor(0.0),
1138 mfSaveActionStartVer(0.0),
1139 mfSaveActionStartRotZ(0.0),
1140 mbMouseMoved(false),
1141 mbMouseCaptured(false),
1142 mbGeometrySelected(false)
1146 void LightControl3D::SetDrawingArea(weld::DrawingArea* pDrawingArea)
1148 PreviewControl3D::SetDrawingArea(pDrawingArea);
1149 Construct2();
1152 void LightControl3D::Construct2()
1155 // hide all page stuff, use control background (normally gray)
1156 const Color aDialogColor(Application::GetSettings().GetStyleSettings().GetDialogColor());
1157 mp3DView->SetPageVisible(false);
1158 mp3DView->SetApplicationBackgroundColor(aDialogColor);
1159 mp3DView->SetApplicationDocumentColor(aDialogColor);
1163 // create invisible expansion object
1164 const double fMaxExpansion(RADIUS_LAMP_BIG + RADIUS_LAMP_PREVIEW_SIZE);
1165 mpExpansionObject = new E3dCubeObj(
1166 *mpModel,
1167 mp3DView->Get3DDefaultAttributes(),
1168 basegfx::B3DPoint(-fMaxExpansion, -fMaxExpansion, -fMaxExpansion),
1169 basegfx::B3DVector(2.0 * fMaxExpansion, 2.0 * fMaxExpansion, 2.0 * fMaxExpansion));
1170 mpScene->InsertObject( mpExpansionObject );
1171 SfxItemSet aSet(mpModel->GetItemPool());
1172 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
1173 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
1174 mpExpansionObject->SetMergedItemSet(aSet);
1178 // create lamp control object (Yellow lined object)
1179 // base circle
1180 const basegfx::B2DPolygon a2DCircle(basegfx::utils::createPolygonFromCircle(basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE));
1181 basegfx::B3DPolygon a3DCircle(basegfx::utils::createB3DPolygonFromB2DPolygon(a2DCircle));
1182 basegfx::B3DHomMatrix aTransform;
1184 aTransform.rotate(F_PI2, 0.0, 0.0);
1185 aTransform.translate(0.0, -RADIUS_LAMP_PREVIEW_SIZE, 0.0);
1186 a3DCircle.transform(aTransform);
1188 // create object for it
1189 mpLampBottomObject = new E3dPolygonObj(
1190 *mpModel,
1191 basegfx::B3DPolyPolygon(a3DCircle));
1192 mpScene->InsertObject( mpLampBottomObject );
1194 // half circle with stand
1195 basegfx::B2DPolygon a2DHalfCircle;
1196 a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, 0.0));
1197 a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, -RADIUS_LAMP_PREVIEW_SIZE));
1198 a2DHalfCircle.append(basegfx::utils::createPolygonFromEllipseSegment(
1199 basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE, RADIUS_LAMP_PREVIEW_SIZE, F_2PI - F_PI2, F_PI2));
1200 basegfx::B3DPolygon a3DHalfCircle(basegfx::utils::createB3DPolygonFromB2DPolygon(a2DHalfCircle));
1202 // create object for it
1203 mpLampShaftObject = new E3dPolygonObj(
1204 *mpModel,
1205 basegfx::B3DPolyPolygon(a3DHalfCircle));
1206 mpScene->InsertObject( mpLampShaftObject );
1208 // initially invisible
1209 SfxItemSet aSet(mpModel->GetItemPool());
1210 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
1211 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
1213 mpLampBottomObject->SetMergedItemSet(aSet);
1214 mpLampShaftObject->SetMergedItemSet(aSet);
1218 // change camera settings
1219 Camera3D rCamera = mpScene->GetCamera();
1220 const basegfx::B3DRange& rVolume = mpScene->GetBoundVolume();
1221 double fW = rVolume.getWidth();
1222 double fH = rVolume.getHeight();
1223 double fCamZ = rVolume.getMaxZ() + ((fW + fH) / 2.0);
1225 rCamera.SetAutoAdjustProjection(false);
1226 rCamera.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
1227 basegfx::B3DPoint aLookAt;
1228 double fDefaultCamPosZ = mp3DView->GetDefaultCamPosZ();
1229 basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
1230 rCamera.SetPosAndLookAt(aCamPos, aLookAt);
1231 double fDefaultCamFocal = mp3DView->GetDefaultCamFocal();
1232 rCamera.SetFocalLength(fDefaultCamFocal);
1234 mpScene->SetCamera( rCamera );
1236 basegfx::B3DHomMatrix aNeutral;
1237 mpScene->SetTransform(aNeutral);
1240 // invalidate SnapRects of objects
1241 mpScene->SetRectsDirty();
1244 void LightControl3D::ConstructLightObjects()
1246 for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
1248 // get rid of possible existing light object
1249 if(maLightObjects[a])
1251 mpScene->RemoveObject(maLightObjects[a]->GetOrdNum());
1252 // always use SdrObject::Free(...) for SdrObjects (!)
1253 SdrObject* pTemp(maLightObjects[a]);
1254 SdrObject::Free(pTemp);
1255 maLightObjects[a] = nullptr;
1258 if(GetLightOnOff(a))
1260 const bool bIsSelectedLight(a == maSelectedLight);
1261 basegfx::B3DVector aDirection(GetLightDirection(a));
1262 aDirection.normalize();
1263 aDirection *= RADIUS_LAMP_PREVIEW_SIZE;
1265 const double fLampSize(bIsSelectedLight ? RADIUS_LAMP_BIG : RADIUS_LAMP_SMALL);
1266 E3dObject* pNewLight = new E3dSphereObj(
1267 *mpModel,
1268 mp3DView->Get3DDefaultAttributes(),
1269 basegfx::B3DPoint( 0, 0, 0 ),
1270 basegfx::B3DVector( fLampSize, fLampSize, fLampSize));
1271 mpScene->InsertObject(pNewLight);
1273 basegfx::B3DHomMatrix aTransform;
1274 aTransform.translate(aDirection.getX(), aDirection.getY(), aDirection.getZ());
1275 pNewLight->SetTransform(aTransform);
1277 SfxItemSet aSet(mpModel->GetItemPool());
1278 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
1279 aSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
1280 aSet.Put( XFillColorItem(OUString(), GetLightColor(a)));
1281 pNewLight->SetMergedItemSet(aSet);
1283 maLightObjects[a] = pNewLight;
1288 void LightControl3D::AdaptToSelectedLight()
1290 if(NO_LIGHT_SELECTED == maSelectedLight)
1292 // make mpLampBottomObject/mpLampShaftObject invisible
1293 SfxItemSet aSet(mpModel->GetItemPool());
1294 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
1295 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
1296 mpLampBottomObject->SetMergedItemSet(aSet);
1297 mpLampShaftObject->SetMergedItemSet(aSet);
1299 else
1301 basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
1302 aDirection.normalize();
1304 // make mpLampBottomObject/mpLampShaftObject visible (yellow hairline)
1305 SfxItemSet aSet(mpModel->GetItemPool());
1306 aSet.Put( XLineStyleItem( drawing::LineStyle_SOLID ) );
1307 aSet.Put( XLineColorItem(OUString(), COL_YELLOW));
1308 aSet.Put( XLineWidthItem(0));
1309 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
1310 mpLampBottomObject->SetMergedItemSet(aSet);
1311 mpLampShaftObject->SetMergedItemSet(aSet);
1313 // adapt transformation of mpLampShaftObject
1314 basegfx::B3DHomMatrix aTransform;
1315 double fRotateY(0.0);
1317 if(!basegfx::fTools::equalZero(aDirection.getZ()) || !basegfx::fTools::equalZero(aDirection.getX()))
1319 fRotateY = atan2(-aDirection.getZ(), aDirection.getX());
1322 aTransform.rotate(0.0, fRotateY, 0.0);
1323 mpLampShaftObject->SetTransform(aTransform);
1325 // adapt transformation of selected light
1326 E3dObject* pSelectedLight = maLightObjects[sal_Int32(maSelectedLight)];
1328 if(pSelectedLight)
1330 aTransform.identity();
1331 aTransform.translate(
1332 aDirection.getX() * RADIUS_LAMP_PREVIEW_SIZE,
1333 aDirection.getY() * RADIUS_LAMP_PREVIEW_SIZE,
1334 aDirection.getZ() * RADIUS_LAMP_PREVIEW_SIZE);
1335 pSelectedLight->SetTransform(aTransform);
1340 void LightControl3D::TrySelection(Point aPosPixel)
1342 if(mpScene)
1344 const Point aPosLogic(GetDrawingArea()->get_ref_device().PixelToLogic(aPosPixel));
1345 const basegfx::B2DPoint aPoint(aPosLogic.X(), aPosLogic.Y());
1346 std::vector< const E3dCompoundObject* > aResult;
1347 getAllHit3DObjectsSortedFrontToBack(aPoint, *mpScene, aResult);
1349 if(!aResult.empty())
1351 // exclude expansion object which will be part of
1352 // the hits. It's invisible, but for HitTest, it's included
1353 const E3dCompoundObject* pResult = nullptr;
1355 for(auto const & b: aResult)
1357 if(b && b != mpExpansionObject)
1359 pResult = b;
1360 break;
1364 if(pResult == mp3DObj)
1366 if(!mbGeometrySelected)
1368 mbGeometrySelected = true;
1369 maSelectedLight = NO_LIGHT_SELECTED;
1370 ConstructLightObjects();
1371 AdaptToSelectedLight();
1372 Invalidate();
1374 if(maSelectionChangeCallback.IsSet())
1376 maSelectionChangeCallback.Call(this);
1380 else
1382 sal_uInt32 aNewSelectedLight(NO_LIGHT_SELECTED);
1384 for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
1386 if(maLightObjects[a] && maLightObjects[a] == pResult)
1388 aNewSelectedLight = a;
1392 if(aNewSelectedLight != maSelectedLight)
1394 SelectLight(aNewSelectedLight);
1396 if(maSelectionChangeCallback.IsSet())
1398 maSelectionChangeCallback.Call(this);
1406 void LightControl3D::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
1408 PreviewControl3D::Paint(rRenderContext, rRect);
1411 tools::Rectangle LightControl3D::GetFocusRect()
1413 if (!HasFocus())
1414 return tools::Rectangle();
1415 Size aFocusSize = GetOutputSizePixel();
1416 aFocusSize.AdjustWidth( -4 );
1417 aFocusSize.AdjustHeight( -4 );
1418 return tools::Rectangle(Point(2, 2), aFocusSize);
1421 bool LightControl3D::MouseButtonDown( const MouseEvent& rMEvt )
1423 bool bCallParent(true);
1425 // switch state
1426 if(rMEvt.IsLeft())
1428 if(IsSelectionValid() || mbGeometrySelected)
1430 mbMouseMoved = false;
1431 bCallParent = false;
1432 maActionStartPoint = rMEvt.GetPosPixel();
1433 CaptureMouse();
1434 mbMouseCaptured = true;
1436 else
1438 // Single click without moving much trying to do a selection
1439 TrySelection(rMEvt.GetPosPixel());
1440 bCallParent = false;
1444 // call parent
1445 if (bCallParent)
1446 return PreviewControl3D::MouseButtonDown(rMEvt);
1447 return true;
1450 bool LightControl3D::MouseMove(const MouseEvent& rMEvt)
1452 if (!mbMouseCaptured)
1453 return false;
1455 Point aDeltaPos = rMEvt.GetPosPixel() - maActionStartPoint;
1457 if(!mbMouseMoved)
1459 if(sal_Int32(aDeltaPos.X() * aDeltaPos.X() + aDeltaPos.Y() * aDeltaPos.Y()) > g_nInteractionStartDistance)
1461 if(mbGeometrySelected)
1463 GetRotation(mfSaveActionStartVer, mfSaveActionStartHor, mfSaveActionStartRotZ);
1465 else
1467 // interaction start, save values
1468 GetPosition(mfSaveActionStartHor, mfSaveActionStartVer);
1471 mbMouseMoved = true;
1475 if(mbMouseMoved)
1477 if(mbGeometrySelected)
1479 double fNewRotX = mfSaveActionStartVer - basegfx::deg2rad(aDeltaPos.Y());
1480 double fNewRotY = mfSaveActionStartHor + basegfx::deg2rad(aDeltaPos.X());
1482 // cut horizontal
1483 while(fNewRotY < 0.0)
1485 fNewRotY += F_2PI;
1488 while(fNewRotY >= F_2PI)
1490 fNewRotY -= F_2PI;
1493 // cut vertical
1494 if(fNewRotX < -F_PI2)
1496 fNewRotX = -F_PI2;
1499 if(fNewRotX > F_PI2)
1501 fNewRotX = F_PI2;
1504 SetRotation(fNewRotX, fNewRotY, mfSaveActionStartRotZ);
1506 if(maChangeCallback.IsSet())
1508 maChangeCallback.Call(this);
1511 else
1513 // interaction in progress
1514 double fNewPosHor = mfSaveActionStartHor + static_cast<double>(aDeltaPos.X());
1515 double fNewPosVer = mfSaveActionStartVer - static_cast<double>(aDeltaPos.Y());
1517 // cut horizontal
1518 fNewPosHor = NormAngle360(fNewPosHor);
1520 // cut vertical
1521 if(fNewPosVer < -90.0)
1523 fNewPosVer = -90.0;
1526 if(fNewPosVer > 90.0)
1528 fNewPosVer = 90.0;
1531 SetPosition(fNewPosHor, fNewPosVer);
1533 if(maChangeCallback.IsSet())
1535 maChangeCallback.Call(this);
1539 return true;
1542 bool LightControl3D::MouseButtonUp(const MouseEvent& rMEvt)
1544 if (!mbMouseCaptured)
1545 return false;
1546 ReleaseMouse();
1547 mbMouseCaptured = false;
1549 if (mbMouseMoved)
1551 // was change interactively
1553 else
1555 // simple click without much movement, try selection
1556 TrySelection(rMEvt.GetPosPixel());
1559 return true;
1562 void LightControl3D::Resize()
1564 // set size of page
1565 const Size aSize(GetDrawingArea()->get_ref_device().PixelToLogic(GetOutputSizePixel()));
1566 mpFmPage->SetSize(aSize);
1568 // set position and size of scene
1569 mpScene->SetSnapRect(tools::Rectangle(Point(0, 0), aSize));
1572 void LightControl3D::SetObjectType(SvxPreviewObjectType nType)
1574 // call parent
1575 PreviewControl3D::SetObjectType(nType);
1577 // apply object rotation
1578 if(mp3DObj)
1580 basegfx::B3DHomMatrix aObjectRotation;
1581 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
1582 mp3DObj->SetTransform(aObjectRotation);
1586 bool LightControl3D::IsSelectionValid()
1588 return (NO_LIGHT_SELECTED != maSelectedLight) && GetLightOnOff(maSelectedLight);
1591 void LightControl3D::GetPosition(double& rHor, double& rVer)
1593 if(IsSelectionValid())
1595 basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
1596 aDirection.normalize();
1597 rHor = basegfx::rad2deg(atan2(-aDirection.getX(), -aDirection.getZ()) + F_PI); // 0..360.0
1598 rVer = basegfx::rad2deg(atan2(aDirection.getY(), aDirection.getXZLength())); // -90.0..90.0
1600 if(IsGeometrySelected())
1602 rHor = basegfx::rad2deg(mfRotateY); // 0..360.0
1603 rVer = basegfx::rad2deg(mfRotateX); // -90.0..90.0
1607 void LightControl3D::SetPosition(double fHor, double fVer)
1609 if(IsSelectionValid())
1611 // set selected light's direction
1612 fHor = basegfx::deg2rad(fHor) - F_PI; // -PI..PI
1613 fVer = basegfx::deg2rad(fVer); // -PI2..PI2
1614 basegfx::B3DVector aDirection(cos(fVer) * -sin(fHor), sin(fVer), cos(fVer) * -cos(fHor));
1615 aDirection.normalize();
1617 if(!aDirection.equal(GetLightDirection(maSelectedLight)))
1619 // set changed light direction at SdrScene
1620 SfxItemSet aSet(mpModel->GetItemPool());
1622 switch(maSelectedLight)
1624 case 0: aSet.Put(makeSvx3DLightDirection1Item(aDirection)); break;
1625 case 1: aSet.Put(makeSvx3DLightDirection2Item(aDirection)); break;
1626 case 2: aSet.Put(makeSvx3DLightDirection3Item(aDirection)); break;
1627 case 3: aSet.Put(makeSvx3DLightDirection4Item(aDirection)); break;
1628 case 4: aSet.Put(makeSvx3DLightDirection5Item(aDirection)); break;
1629 case 5: aSet.Put(makeSvx3DLightDirection6Item(aDirection)); break;
1630 case 6: aSet.Put(makeSvx3DLightDirection7Item(aDirection)); break;
1631 default:
1632 case 7: aSet.Put(makeSvx3DLightDirection8Item(aDirection)); break;
1635 mpScene->SetMergedItemSet(aSet);
1637 // correct 3D light's and LampFrame's geometries
1638 AdaptToSelectedLight();
1639 Invalidate();
1642 if(IsGeometrySelected())
1644 if(mfRotateX != fVer || mfRotateY != fHor)
1646 mfRotateX = basegfx::deg2rad(fVer);
1647 mfRotateY = basegfx::deg2rad(fHor);
1649 if(mp3DObj)
1651 basegfx::B3DHomMatrix aObjectRotation;
1652 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
1653 mp3DObj->SetTransform(aObjectRotation);
1655 Invalidate();
1661 void LightControl3D::SetRotation(double fRotX, double fRotY, double fRotZ)
1663 if(IsGeometrySelected())
1665 if(fRotX != mfRotateX || fRotY != mfRotateY || fRotZ != mfRotateZ)
1667 mfRotateX = fRotX;
1668 mfRotateY = fRotY;
1669 mfRotateZ = fRotZ;
1671 if(mp3DObj)
1673 basegfx::B3DHomMatrix aObjectRotation;
1674 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
1675 mp3DObj->SetTransform(aObjectRotation);
1677 Invalidate();
1683 void LightControl3D::GetRotation(double& rRotX, double& rRotY, double& rRotZ)
1685 rRotX = mfRotateX;
1686 rRotY = mfRotateY;
1687 rRotZ = mfRotateZ;
1690 void LightControl3D::Set3DAttributes( const SfxItemSet& rAttr )
1692 // call parent
1693 PreviewControl3D::Set3DAttributes(rAttr);
1695 if(maSelectedLight != NO_LIGHT_SELECTED && !GetLightOnOff(maSelectedLight))
1697 // selected light is no more active, select new one
1698 maSelectedLight = NO_LIGHT_SELECTED;
1701 // local updates
1702 ConstructLightObjects();
1703 AdaptToSelectedLight();
1704 Invalidate();
1707 void LightControl3D::SelectLight(sal_uInt32 nLightNumber)
1709 if(nLightNumber > 7)
1711 nLightNumber = NO_LIGHT_SELECTED;
1714 if(NO_LIGHT_SELECTED != nLightNumber)
1716 if(!GetLightOnOff(nLightNumber))
1718 nLightNumber = NO_LIGHT_SELECTED;
1722 if(nLightNumber != maSelectedLight)
1724 maSelectedLight = nLightNumber;
1725 mbGeometrySelected = false;
1726 ConstructLightObjects();
1727 AdaptToSelectedLight();
1728 Invalidate();
1732 bool LightControl3D::GetLightOnOff(sal_uInt32 nNum) const
1734 if(nNum <= 7)
1736 const SfxItemSet aLightItemSet(Get3DAttributes());
1738 switch(nNum)
1740 case 0 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_1).GetValue();
1741 case 1 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_2).GetValue();
1742 case 2 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_3).GetValue();
1743 case 3 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_4).GetValue();
1744 case 4 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_5).GetValue();
1745 case 5 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_6).GetValue();
1746 case 6 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_7).GetValue();
1747 case 7 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_8).GetValue();
1751 return false;
1754 Color LightControl3D::GetLightColor(sal_uInt32 nNum) const
1756 if(nNum <= 7)
1758 const SfxItemSet aLightItemSet(Get3DAttributes());
1760 switch(nNum)
1762 case 0 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1).GetValue();
1763 case 1 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2).GetValue();
1764 case 2 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3).GetValue();
1765 case 3 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4).GetValue();
1766 case 4 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5).GetValue();
1767 case 5 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6).GetValue();
1768 case 6 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7).GetValue();
1769 case 7 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8).GetValue();
1773 return COL_BLACK;
1776 basegfx::B3DVector LightControl3D::GetLightDirection(sal_uInt32 nNum) const
1778 if(nNum <= 7)
1780 const SfxItemSet aLightItemSet(Get3DAttributes());
1782 switch(nNum)
1784 case 0 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1).GetValue();
1785 case 1 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2).GetValue();
1786 case 2 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3).GetValue();
1787 case 3 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4).GetValue();
1788 case 4 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5).GetValue();
1789 case 5 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6).GetValue();
1790 case 6 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7).GetValue();
1791 case 7 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8).GetValue();
1795 return basegfx::B3DVector();
1798 SvxLightCtl3D::SvxLightCtl3D( vcl::Window* pParent)
1799 : Control(pParent, WB_BORDER | WB_TABSTOP),
1800 maLightControl(VclPtr<Svx3DLightControl>::Create(this, 0)),
1801 maHorScroller(VclPtr<ScrollBar>::Create(this, WB_HORZ | WB_DRAG)),
1802 maVerScroller(VclPtr<ScrollBar>::Create(this, WB_VERT | WB_DRAG)),
1803 maSwitcher(VclPtr<PushButton>::Create(this, 0))
1805 // init members
1806 Init();
1809 Size SvxLightCtl3D::GetOptimalSize() const
1811 return LogicToPixel(Size(80, 100), MapMode(MapUnit::MapAppFont));
1814 VCL_BUILDER_FACTORY(SvxLightCtl3D)
1816 void SvxLightCtl3D::Init()
1818 // #i58240# set HelpIDs for scrollbars and switcher
1819 maHorScroller->SetHelpId(HID_CTRL3D_HSCROLL);
1820 maVerScroller->SetHelpId(HID_CTRL3D_VSCROLL);
1821 maSwitcher->SetHelpId(HID_CTRL3D_SWITCHER);
1822 maSwitcher->SetAccessibleName(SvxResId(STR_SWITCH));
1824 // Light preview
1825 maLightControl->Show();
1826 maLightControl->SetChangeCallback( LINK(this, SvxLightCtl3D, InternalInteractiveChange) );
1827 maLightControl->SetSelectionChangeCallback( LINK(this, SvxLightCtl3D, InternalSelectionChange) );
1829 // Horiz Scrollbar
1830 maHorScroller->Show();
1831 maHorScroller->SetRange(Range(0, 36000));
1832 maHorScroller->SetLineSize(100);
1833 maHorScroller->SetPageSize(1000);
1834 maHorScroller->SetScrollHdl( LINK(this, SvxLightCtl3D, ScrollBarMove) );
1836 // Vert Scrollbar
1837 maVerScroller->Show();
1838 maVerScroller->SetRange(Range(0, 18000));
1839 maVerScroller->SetLineSize(100);
1840 maVerScroller->SetPageSize(1000);
1841 maVerScroller->SetScrollHdl( LINK(this, SvxLightCtl3D, ScrollBarMove) );
1843 // Switch Button
1844 maSwitcher->Show();
1845 maSwitcher->SetClickHdl( LINK(this, SvxLightCtl3D, ButtonPress) );
1847 // check selection
1848 CheckSelection();
1850 // new layout
1851 NewLayout();
1854 SvxLightCtl3D::~SvxLightCtl3D()
1856 disposeOnce();
1859 void SvxLightCtl3D::dispose()
1861 maLightControl.disposeAndClear();
1862 maHorScroller.disposeAndClear();
1863 maVerScroller.disposeAndClear();
1864 maSwitcher.disposeAndClear();
1865 Control::dispose();
1868 void SvxLightCtl3D::Resize()
1870 // call parent
1871 Control::Resize();
1873 // new layout
1874 NewLayout();
1877 void SvxLightCtl3D::NewLayout()
1879 // Layout members
1880 const Size aSize(GetOutputSizePixel());
1881 const sal_Int32 nScrollSize(maHorScroller->GetSizePixel().Height());
1883 // Preview control
1884 Point aPoint(0, 0);
1885 Size aDestSize(aSize.Width() - nScrollSize, aSize.Height() - nScrollSize);
1886 maLightControl->SetPosSizePixel(aPoint, aDestSize);
1888 // hor scrollbar
1889 aPoint.setY( aSize.Height() - nScrollSize );
1890 aDestSize.setHeight( nScrollSize );
1891 maHorScroller->SetPosSizePixel(aPoint, aDestSize);
1893 // vert scrollbar
1894 aPoint.setX( aSize.Width() - nScrollSize );
1895 aPoint.setY( 0 );
1896 aDestSize.setWidth( nScrollSize );
1897 aDestSize.setHeight( aSize.Height() - nScrollSize );
1898 maVerScroller->SetPosSizePixel(aPoint, aDestSize);
1900 // button
1901 aPoint.setY( aSize.Height() - nScrollSize );
1902 aDestSize.setHeight( nScrollSize );
1903 maSwitcher->SetPosSizePixel(aPoint, aDestSize);
1906 void SvxLightCtl3D::CheckSelection()
1908 const bool bSelectionValid(maLightControl->IsSelectionValid() || maLightControl->IsGeometrySelected());
1909 maHorScroller->Enable(bSelectionValid);
1910 maVerScroller->Enable(bSelectionValid);
1912 if(bSelectionValid)
1914 double fHor(0.0), fVer(0.0);
1915 maLightControl->GetPosition(fHor, fVer);
1916 maHorScroller->SetThumbPos( sal_Int32(fHor * 100.0) );
1917 maVerScroller->SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
1921 void SvxLightCtl3D::move( double fDeltaHor, double fDeltaVer )
1923 double fHor(0.0), fVer(0.0);
1925 maLightControl->GetPosition(fHor, fVer);
1926 fHor += fDeltaHor;
1927 fVer += fDeltaVer;
1929 if( fVer > 90.0 )
1930 return;
1932 if ( fVer < -90.0 )
1933 return;
1935 maLightControl->SetPosition(fHor, fVer);
1936 maHorScroller->SetThumbPos( sal_Int32(fHor * 100.0) );
1937 maVerScroller->SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
1940 void SvxLightCtl3D::KeyInput( const KeyEvent& rKEvt )
1942 const vcl::KeyCode aCode(rKEvt.GetKeyCode());
1944 if( aCode.GetModifier() )
1946 Control::KeyInput( rKEvt );
1947 return;
1950 switch ( aCode.GetCode() )
1952 case KEY_SPACE:
1954 break;
1956 case KEY_LEFT:
1958 move( -4.0, 0.0 ); // #i58242# changed move direction in X
1959 break;
1961 case KEY_RIGHT:
1963 move( 4.0, 0.0 ); // #i58242# changed move direction in X
1964 break;
1966 case KEY_UP:
1968 move( 0.0, 4.0 );
1969 break;
1971 case KEY_DOWN:
1973 move( 0.0, -4.0 );
1974 break;
1976 case KEY_PAGEUP:
1978 sal_Int32 nLight(maLightControl->GetSelectedLight() - 1);
1980 while((nLight >= 0) && !maLightControl->GetLightOnOff(nLight))
1982 nLight--;
1985 if(nLight < 0)
1987 nLight = 7;
1989 while((nLight >= 0) && !maLightControl->GetLightOnOff(nLight))
1991 nLight--;
1995 if(nLight >= 0)
1997 maLightControl->SelectLight(nLight);
1998 CheckSelection();
2000 if(maUserSelectionChangeCallback.IsSet())
2002 maUserSelectionChangeCallback.Call(this);
2006 break;
2008 case KEY_PAGEDOWN:
2010 sal_Int32 nLight(maLightControl->GetSelectedLight() - 1);
2012 while(nLight <= 7 && !maLightControl->GetLightOnOff(nLight))
2014 nLight++;
2017 if(nLight > 7)
2019 nLight = 0;
2021 while(nLight <= 7 && !maLightControl->GetLightOnOff(nLight))
2023 nLight++;
2027 if(nLight <= 7)
2029 maLightControl->SelectLight(nLight);
2030 CheckSelection();
2032 if(maUserSelectionChangeCallback.IsSet())
2034 maUserSelectionChangeCallback.Call(this);
2038 break;
2040 default:
2042 Control::KeyInput( rKEvt );
2043 break;
2048 void SvxLightCtl3D::GetFocus()
2050 Control::GetFocus();
2052 if(HasFocus() && IsEnabled())
2054 CheckSelection();
2056 Size aFocusSize = maLightControl->GetOutputSizePixel();
2058 aFocusSize.AdjustWidth( -4 );
2059 aFocusSize.AdjustHeight( -4 );
2061 tools::Rectangle aFocusRect( Point( 2, 2 ), aFocusSize );
2063 aFocusRect = maLightControl->PixelToLogic( aFocusRect );
2065 maLightControl->ShowFocus( aFocusRect );
2069 void SvxLightCtl3D::LoseFocus()
2071 Control::LoseFocus();
2073 maLightControl->HideFocus();
2076 IMPL_LINK_NOARG(SvxLightCtl3D, ScrollBarMove, ScrollBar*, void)
2078 const sal_Int32 nHor(maHorScroller->GetThumbPos());
2079 const sal_Int32 nVer(maVerScroller->GetThumbPos());
2081 maLightControl->SetPosition(
2082 static_cast<double>(nHor) / 100.0,
2083 static_cast<double>((18000 - nVer) - 9000) / 100.0);
2086 IMPL_LINK_NOARG(SvxLightCtl3D, ButtonPress, Button*, void)
2088 if(SvxPreviewObjectType::SPHERE == GetSvx3DLightControl().GetObjectType())
2090 GetSvx3DLightControl().SetObjectType(SvxPreviewObjectType::CUBE);
2092 else
2094 GetSvx3DLightControl().SetObjectType(SvxPreviewObjectType::SPHERE);
2098 IMPL_LINK_NOARG(SvxLightCtl3D, InternalInteractiveChange, Svx3DLightControl*, void)
2100 double fHor(0.0), fVer(0.0);
2102 maLightControl->GetPosition(fHor, fVer);
2103 maHorScroller->SetThumbPos( sal_Int32(fHor * 100.0) );
2104 maVerScroller->SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
2107 IMPL_LINK_NOARG(SvxLightCtl3D, InternalSelectionChange, Svx3DLightControl*, void)
2109 CheckSelection();
2111 if(maUserSelectionChangeCallback.IsSet())
2113 maUserSelectionChangeCallback.Call(this);
2117 LightCtl3D::LightCtl3D(LightControl3D& rLightControl, weld::Scale& rHori,
2118 weld::Scale& rVert, weld::Button& rSwitcher)
2119 : mrLightControl(rLightControl)
2120 , mrHorScroller(rHori)
2121 , mrVerScroller(rVert)
2122 , mrSwitcher(rSwitcher)
2124 // init members
2125 Init();
2128 void LightCtl3D::Init()
2130 Size aSize(mrLightControl.GetDrawingArea()->get_ref_device().LogicToPixel(Size(80, 100), MapMode(MapUnit::MapAppFont)));
2131 mrLightControl.set_size_request(aSize.Width(), aSize.Height());
2133 // #i58240# set HelpIDs for scrollbars and switcher
2134 mrHorScroller.set_help_id(HID_CTRL3D_HSCROLL);
2135 mrVerScroller.set_help_id(HID_CTRL3D_VSCROLL);
2136 mrSwitcher.set_help_id(HID_CTRL3D_SWITCHER);
2137 mrSwitcher.set_accessible_name(SvxResId(STR_SWITCH));
2139 // Light preview
2140 mrLightControl.Show();
2141 mrLightControl.SetChangeCallback( LINK(this, LightCtl3D, InternalInteractiveChange) );
2142 mrLightControl.SetSelectionChangeCallback( LINK(this, LightCtl3D, InternalSelectionChange) );
2144 // Horiz Scrollbar
2145 mrHorScroller.show();
2146 mrHorScroller.set_range(0, 36000);
2147 mrHorScroller.connect_value_changed( LINK(this, LightCtl3D, ScrollBarMove) );
2149 // Vert Scrollbar
2150 mrVerScroller.show();
2151 mrVerScroller.set_range(0, 18000);
2152 mrVerScroller.connect_value_changed( LINK(this, LightCtl3D, ScrollBarMove) );
2154 // Switch Button
2155 mrSwitcher.show();
2156 mrSwitcher.connect_clicked( LINK(this, LightCtl3D, ButtonPress) );
2158 weld::DrawingArea* pArea = mrLightControl.GetDrawingArea();
2159 pArea->connect_key_press(Link<const KeyEvent&, bool>()); //acknowledge we first remove the old one
2160 pArea->connect_key_press(LINK(this, LightCtl3D, KeyInput));
2162 pArea->connect_focus_in(Link<weld::Widget&, void>()); //acknowledge we first remove the old one
2163 pArea->connect_focus_in(LINK(this, LightCtl3D, FocusIn));
2165 // check selection
2166 CheckSelection();
2169 LightCtl3D::~LightCtl3D()
2173 void LightCtl3D::CheckSelection()
2175 const bool bSelectionValid(mrLightControl.IsSelectionValid() || mrLightControl.IsGeometrySelected());
2176 mrHorScroller.set_sensitive(bSelectionValid);
2177 mrVerScroller.set_sensitive(bSelectionValid);
2179 if (bSelectionValid)
2181 double fHor(0.0), fVer(0.0);
2182 mrLightControl.GetPosition(fHor, fVer);
2183 mrHorScroller.set_value( sal_Int32(fHor * 100.0) );
2184 mrVerScroller.set_value( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
2188 void LightCtl3D::move( double fDeltaHor, double fDeltaVer )
2190 double fHor(0.0), fVer(0.0);
2192 mrLightControl.GetPosition(fHor, fVer);
2193 fHor += fDeltaHor;
2194 fVer += fDeltaVer;
2196 if( fVer > 90.0 )
2197 return;
2199 if ( fVer < -90.0 )
2200 return;
2202 mrLightControl.SetPosition(fHor, fVer);
2203 mrHorScroller.set_value( sal_Int32(fHor * 100.0) );
2204 mrVerScroller.set_value( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
2206 if(maUserInteractiveChangeCallback.IsSet())
2208 maUserInteractiveChangeCallback.Call(this);
2212 IMPL_LINK(LightCtl3D, KeyInput, const KeyEvent&, rKEvt, bool)
2214 const vcl::KeyCode aCode(rKEvt.GetKeyCode());
2216 if (aCode.GetModifier())
2217 return false;
2219 bool bHandled = true;
2221 switch ( aCode.GetCode() )
2223 case KEY_SPACE:
2225 break;
2227 case KEY_LEFT:
2229 move( -4.0, 0.0 ); // #i58242# changed move direction in X
2230 break;
2232 case KEY_RIGHT:
2234 move( 4.0, 0.0 ); // #i58242# changed move direction in X
2235 break;
2237 case KEY_UP:
2239 move( 0.0, 4.0 );
2240 break;
2242 case KEY_DOWN:
2244 move( 0.0, -4.0 );
2245 break;
2247 case KEY_PAGEUP:
2249 sal_Int32 nLight(mrLightControl.GetSelectedLight() - 1);
2251 while((nLight >= 0) && !mrLightControl.GetLightOnOff(nLight))
2253 nLight--;
2256 if(nLight < 0)
2258 nLight = 7;
2260 while((nLight >= 0) && !mrLightControl.GetLightOnOff(nLight))
2262 nLight--;
2266 if(nLight >= 0)
2268 mrLightControl.SelectLight(nLight);
2269 CheckSelection();
2271 if(maUserSelectionChangeCallback.IsSet())
2273 maUserSelectionChangeCallback.Call(this);
2277 break;
2279 case KEY_PAGEDOWN:
2281 sal_Int32 nLight(mrLightControl.GetSelectedLight() - 1);
2283 while(nLight <= 7 && !mrLightControl.GetLightOnOff(nLight))
2285 nLight++;
2288 if(nLight > 7)
2290 nLight = 0;
2292 while(nLight <= 7 && !mrLightControl.GetLightOnOff(nLight))
2294 nLight++;
2298 if(nLight <= 7)
2300 mrLightControl.SelectLight(nLight);
2301 CheckSelection();
2303 if(maUserSelectionChangeCallback.IsSet())
2305 maUserSelectionChangeCallback.Call(this);
2309 break;
2311 default:
2313 bHandled = false;
2314 break;
2317 return bHandled;
2320 IMPL_LINK_NOARG(LightCtl3D, FocusIn, weld::Widget&, void)
2322 if (mrLightControl.IsEnabled())
2324 CheckSelection();
2328 IMPL_LINK_NOARG(LightCtl3D, ScrollBarMove, weld::Scale&, void)
2330 const sal_Int32 nHor(mrHorScroller.get_value());
2331 const sal_Int32 nVer(mrVerScroller.get_value());
2333 mrLightControl.SetPosition(
2334 static_cast<double>(nHor) / 100.0,
2335 static_cast<double>((18000 - nVer) - 9000) / 100.0);
2337 if (maUserInteractiveChangeCallback.IsSet())
2339 maUserInteractiveChangeCallback.Call(this);
2343 IMPL_LINK_NOARG(LightCtl3D, ButtonPress, weld::Button&, void)
2345 if(SvxPreviewObjectType::SPHERE == GetSvx3DLightControl().GetObjectType())
2347 GetSvx3DLightControl().SetObjectType(SvxPreviewObjectType::CUBE);
2349 else
2351 GetSvx3DLightControl().SetObjectType(SvxPreviewObjectType::SPHERE);
2355 IMPL_LINK_NOARG(LightCtl3D, InternalInteractiveChange, LightControl3D*, void)
2357 double fHor(0.0), fVer(0.0);
2359 mrLightControl.GetPosition(fHor, fVer);
2360 mrHorScroller.set_value( sal_Int32(fHor * 100.0) );
2361 mrVerScroller.set_value( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
2363 if(maUserInteractiveChangeCallback.IsSet())
2365 maUserInteractiveChangeCallback.Call(this);
2369 IMPL_LINK_NOARG(LightCtl3D, InternalSelectionChange, LightControl3D*, void)
2371 CheckSelection();
2373 if(maUserSelectionChangeCallback.IsSet())
2375 maUserSelectionChangeCallback.Call(this);
2379 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */