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