1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <sal/config.h>
21 #include <sal/log.hxx>
22
23 #include <cassert>
24
25 #include <dlged.hxx>
26 #include <dlgeddef.hxx>
27 #include <dlgedlist.hxx>
28 #include <dlgedobj.hxx>
29 #include <dlgedpage.hxx>
30 #include <dlgedview.hxx>
31 #include <localizationmgr.hxx>
32 #include <strings.hxx>
33
34 #include <com/sun/star/beans/NamedValue.hpp>
35 #include <com/sun/star/form/binding/XBindableValue.hpp>
36 #include <com/sun/star/form/binding/XValueBinding.hpp>
37 #include <com/sun/star/form/binding/XListEntrySink.hpp>
38 #include <com/sun/star/awt/XUnoControlContainer.hpp>
39 #include <com/sun/star/awt/XVclContainerPeer.hpp>
40 #include <com/sun/star/container/XContainer.hpp>
41 #include <com/sun/star/lang/XServiceInfo.hpp>
42 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
43 #include <com/sun/star/script/XScriptEventsSupplier.hpp>
44 #include <com/sun/star/table/CellAddress.hpp>
45 #include <cppuhelper/exc_hlp.hxx>
46 #include <o3tl/functional.hxx>
47 #include <svx/svdpagv.hxx>
48 #include <unotools/sharedunocomponent.hxx>
49 #include <vcl/svapp.hxx>
50 #include <tools/debug.hxx>
51
52 namespace basctl
53 {
54
55 using namespace ::com::sun::star;
56 using namespace ::com::sun::star::uno;
57 using namespace ::com::sun::star::beans;
58 using namespace ::com::sun::star::container;
59 using namespace ::com::sun::star::script;
60
61
GetDialogEditor()62 DlgEditor& DlgEdObj::GetDialogEditor ()
63 {
64 if (DlgEdForm* pFormThis = dynamic_cast<DlgEdForm*>(this))
65 return pFormThis->GetDlgEditor();
66 else
67 return pDlgEdForm->GetDlgEditor();
68 }
69
DlgEdObj(SdrModel & rSdrModel)70 DlgEdObj::DlgEdObj(SdrModel& rSdrModel)
71 : SdrUnoObj(rSdrModel, OUString())
72 ,bIsListening(false)
73 ,pDlgEdForm( nullptr )
74 {
75 }
76
DlgEdObj(SdrModel & rSdrModel,DlgEdObj const & rSource)77 DlgEdObj::DlgEdObj(SdrModel& rSdrModel, DlgEdObj const & rSource)
78 : SdrUnoObj(rSdrModel, rSource)
79 ,bIsListening(false)
80 {
81 // set parent form
82 pDlgEdForm = rSource.pDlgEdForm;
83
84 // add child to parent form
85 pDlgEdForm->AddChild( this );
86
87 Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
88 if ( xPSet.is() )
89 {
90 // set new name
91 OUString aOUniqueName( GetUniqueName() );
92 Any aUniqueName;
93 aUniqueName <<= aOUniqueName;
94 xPSet->setPropertyValue( DLGED_PROP_NAME, aUniqueName );
95
96 Reference< container::XNameContainer > xCont( GetDlgEdForm()->GetUnoControlModel() , UNO_QUERY );
97 if ( xCont.is() )
98 {
99 // set tabindex
100 Sequence< OUString > aNames = xCont->getElementNames();
101 xPSet->setPropertyValue( DLGED_PROP_TABINDEX, Any(static_cast<sal_Int16>(aNames.getLength())) );
102
103 // insert control model in dialog model
104 Reference< awt::XControlModel > xCtrl( xPSet , UNO_QUERY );
105 xCont->insertByName( aOUniqueName, Any(xCtrl) );
106
107 pDlgEdForm->UpdateTabOrderAndGroups();
108 }
109 }
110
111 // start listening
112 StartListening();
113 }
114
DlgEdObj(SdrModel & rSdrModel,const OUString & rModelName,const css::uno::Reference<css::lang::XMultiServiceFactory> & rxSFac)115 DlgEdObj::DlgEdObj(
116 SdrModel& rSdrModel,
117 const OUString& rModelName,
118 const css::uno::Reference< css::lang::XMultiServiceFactory >& rxSFac)
119 : SdrUnoObj(rSdrModel, rModelName, rxSFac)
120 ,bIsListening(false)
121 ,pDlgEdForm( nullptr )
122 {
123 }
124
~DlgEdObj()125 DlgEdObj::~DlgEdObj()
126 {
127 if ( isListening() )
128 EndListening(true);
129 }
130
131 namespace
132 {
133 /* returns the DlgEdForm which the given DlgEdObj belongs to
134 (which might in fact be the object itself)
135
136 Failure to obtain the form will be reported with an assertion in the non-product
137 version.
138 */
lcl_getDlgEdForm(DlgEdObj * _pObject,DlgEdForm * & _out_pDlgEdForm)139 bool lcl_getDlgEdForm( DlgEdObj* _pObject, DlgEdForm*& _out_pDlgEdForm )
140 {
141 _out_pDlgEdForm = dynamic_cast< DlgEdForm* >( _pObject );
142 if ( !_out_pDlgEdForm )
143 _out_pDlgEdForm = _pObject->GetDlgEdForm();
144 DBG_ASSERT( _out_pDlgEdForm, "lcl_getDlgEdForm: no form!" );
145 return ( _out_pDlgEdForm != nullptr );
146 }
147 }
148
GetControl() const149 uno::Reference< awt::XControl > DlgEdObj::GetControl() const
150 {
151 uno::Reference< awt::XControl > xControl;
152 if (DlgEdForm const* pForm = GetDlgEdForm())
153 {
154 DlgEditor const& rEditor = pForm->GetDlgEditor();
155 xControl = GetUnoControl(rEditor.GetView(), *rEditor.GetWindow().GetOutDev());
156 }
157 return xControl;
158 }
159
TransformSdrToControlCoordinates(sal_Int32 nXIn,sal_Int32 nYIn,sal_Int32 nWidthIn,sal_Int32 nHeightIn,sal_Int32 & nXOut,sal_Int32 & nYOut,sal_Int32 & nWidthOut,sal_Int32 & nHeightOut)160 bool DlgEdObj::TransformSdrToControlCoordinates(
161 sal_Int32 nXIn, sal_Int32 nYIn, sal_Int32 nWidthIn, sal_Int32 nHeightIn,
162 sal_Int32& nXOut, sal_Int32& nYOut, sal_Int32& nWidthOut, sal_Int32& nHeightOut )
163 {
164 // input position and size
165 Size aPos( nXIn, nYIn );
166 Size aSize( nWidthIn, nHeightIn );
167
168 // form position
169 DlgEdForm* pForm = nullptr;
170 if ( !lcl_getDlgEdForm( this, pForm ) )
171 return false;
172 tools::Rectangle aFormRect = pForm->GetSnapRect();
173 Size aFormPos( aFormRect.Left(), aFormRect.Top() );
174
175 // convert 100th_mm to pixel
176 OutputDevice* pDevice = Application::GetDefaultDevice();
177 DBG_ASSERT( pDevice, "DlgEdObj::TransformSdrToControlCoordinates: missing default device!" );
178 if ( !pDevice )
179 return false;
180 aPos = pDevice->LogicToPixel( aPos, MapMode( MapUnit::Map100thMM ) );
181 aSize = pDevice->LogicToPixel( aSize, MapMode( MapUnit::Map100thMM ) );
182 aFormPos = pDevice->LogicToPixel( aFormPos, MapMode( MapUnit::Map100thMM ) );
183
184 // subtract form position
185 aPos.AdjustWidth( -(aFormPos.Width()) );
186 aPos.AdjustHeight( -(aFormPos.Height()) );
187
188 // take window borders into account
189 Reference< beans::XPropertySet > xPSetForm( pForm->GetUnoControlModel(), UNO_QUERY );
190 DBG_ASSERT( xPSetForm.is(), "DlgEdObj::TransformFormToSdrCoordinates: no form property set!" );
191 if ( !xPSetForm.is() )
192 return false;
193 bool bDecoration = true;
194 xPSetForm->getPropertyValue( DLGED_PROP_DECORATION ) >>= bDecoration;
195 if( bDecoration )
196 {
197 awt::DeviceInfo aDeviceInfo = pForm->getDeviceInfo();
198 aPos.AdjustWidth( -(aDeviceInfo.LeftInset) );
199 aPos.AdjustHeight( -(aDeviceInfo.TopInset) );
200 }
201
202 // convert pixel to logic units
203 aPos = pDevice->PixelToLogic(aPos, MapMode(MapUnit::MapAppFont));
204 aSize = pDevice->PixelToLogic(aSize, MapMode(MapUnit::MapAppFont));
205
206 // set out parameters
207 nXOut = aPos.Width();
208 nYOut = aPos.Height();
209 nWidthOut = aSize.Width();
210 nHeightOut = aSize.Height();
211
212 return true;
213 }
214
TransformSdrToFormCoordinates(sal_Int32 nXIn,sal_Int32 nYIn,sal_Int32 nWidthIn,sal_Int32 nHeightIn,sal_Int32 & nXOut,sal_Int32 & nYOut,sal_Int32 & nWidthOut,sal_Int32 & nHeightOut)215 bool DlgEdObj::TransformSdrToFormCoordinates(
216 sal_Int32 nXIn, sal_Int32 nYIn, sal_Int32 nWidthIn, sal_Int32 nHeightIn,
217 sal_Int32& nXOut, sal_Int32& nYOut, sal_Int32& nWidthOut, sal_Int32& nHeightOut )
218 {
219 // input position and size
220 Size aPos( nXIn, nYIn );
221 Size aSize( nWidthIn, nHeightIn );
222
223 // convert 100th_mm to pixel
224 OutputDevice* pDevice = Application::GetDefaultDevice();
225 DBG_ASSERT( pDevice, "DlgEdObj::TransformSdrToFormCoordinates: missing default device!" );
226 if ( !pDevice )
227 return false;
228 aPos = pDevice->LogicToPixel( aPos, MapMode( MapUnit::Map100thMM ) );
229 aSize = pDevice->LogicToPixel( aSize, MapMode( MapUnit::Map100thMM ) );
230
231 // take window borders into account
232 DlgEdForm* pForm = nullptr;
233 if ( !lcl_getDlgEdForm( this, pForm ) )
234 return false;
235
236 // take window borders into account
237 Reference< beans::XPropertySet > xPSetForm( pForm->GetUnoControlModel(), UNO_QUERY );
238 DBG_ASSERT( xPSetForm.is(), "DlgEdObj::TransformFormToSdrCoordinates: no form property set!" );
239 if ( !xPSetForm.is() )
240 return false;
241 bool bDecoration = true;
242 xPSetForm->getPropertyValue( DLGED_PROP_DECORATION ) >>= bDecoration;
243 if( bDecoration )
244 {
245 awt::DeviceInfo aDeviceInfo = pForm->getDeviceInfo();
246 aSize.AdjustWidth( -(aDeviceInfo.LeftInset + aDeviceInfo.RightInset) );
247 aSize.AdjustHeight( -(aDeviceInfo.TopInset + aDeviceInfo.BottomInset) );
248 }
249 // convert pixel to logic units
250 aPos = pDevice->PixelToLogic(aPos, MapMode(MapUnit::MapAppFont));
251 aSize = pDevice->PixelToLogic(aSize, MapMode(MapUnit::MapAppFont));
252
253 // set out parameters
254 nXOut = aPos.Width();
255 nYOut = aPos.Height();
256 nWidthOut = aSize.Width();
257 nHeightOut = aSize.Height();
258
259 return true;
260 }
261
TransformControlToSdrCoordinates(sal_Int32 nXIn,sal_Int32 nYIn,sal_Int32 nWidthIn,sal_Int32 nHeightIn,sal_Int32 & nXOut,sal_Int32 & nYOut,sal_Int32 & nWidthOut,sal_Int32 & nHeightOut)262 bool DlgEdObj::TransformControlToSdrCoordinates(
263 sal_Int32 nXIn, sal_Int32 nYIn, sal_Int32 nWidthIn, sal_Int32 nHeightIn,
264 sal_Int32& nXOut, sal_Int32& nYOut, sal_Int32& nWidthOut, sal_Int32& nHeightOut )
265 {
266 // input position and size
267 Size aPos( nXIn, nYIn );
268 Size aSize( nWidthIn, nHeightIn );
269
270 // form position
271 DlgEdForm* pForm = nullptr;
272 if ( !lcl_getDlgEdForm( this, pForm ) )
273 return false;
274
275 Reference< beans::XPropertySet > xPSetForm( pForm->GetUnoControlModel(), UNO_QUERY );
276 DBG_ASSERT( xPSetForm.is(), "DlgEdObj::TransformControlToSdrCoordinates: no form property set!" );
277 if ( !xPSetForm.is() )
278 return false;
279 sal_Int32 nFormX = 0, nFormY = 0;
280 xPSetForm->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nFormX;
281 xPSetForm->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nFormY;
282 Size aFormPos( nFormX, nFormY );
283
284 // convert logic units to pixel
285 OutputDevice* pDevice = Application::GetDefaultDevice();
286 DBG_ASSERT( pDevice, "DlgEdObj::TransformControlToSdrCoordinates: missing default device!" );
287 if ( !pDevice )
288 return false;
289 aPos = pDevice->LogicToPixel(aPos, MapMode(MapUnit::MapAppFont));
290 aSize = pDevice->LogicToPixel(aSize, MapMode(MapUnit::MapAppFont));
291 aFormPos = pDevice->LogicToPixel(aFormPos, MapMode(MapUnit::MapAppFont));
292
293 // add form position
294 aPos.AdjustWidth(aFormPos.Width() );
295 aPos.AdjustHeight(aFormPos.Height() );
296
297 // take window borders into account
298 bool bDecoration = true;
299 xPSetForm->getPropertyValue( DLGED_PROP_DECORATION ) >>= bDecoration;
300 if( bDecoration )
301 {
302 awt::DeviceInfo aDeviceInfo = pForm->getDeviceInfo();
303 aPos.AdjustWidth(aDeviceInfo.LeftInset );
304 aPos.AdjustHeight(aDeviceInfo.TopInset );
305 }
306
307 // convert pixel to 100th_mm
308 aPos = pDevice->PixelToLogic( aPos, MapMode( MapUnit::Map100thMM ) );
309 aSize = pDevice->PixelToLogic( aSize, MapMode( MapUnit::Map100thMM ) );
310
311 // set out parameters
312 nXOut = aPos.Width();
313 nYOut = aPos.Height();
314 nWidthOut = aSize.Width();
315 nHeightOut = aSize.Height();
316
317 return true;
318 }
319
TransformFormToSdrCoordinates(sal_Int32 nXIn,sal_Int32 nYIn,sal_Int32 nWidthIn,sal_Int32 nHeightIn,sal_Int32 & nXOut,sal_Int32 & nYOut,sal_Int32 & nWidthOut,sal_Int32 & nHeightOut)320 bool DlgEdObj::TransformFormToSdrCoordinates(
321 sal_Int32 nXIn, sal_Int32 nYIn, sal_Int32 nWidthIn, sal_Int32 nHeightIn,
322 sal_Int32& nXOut, sal_Int32& nYOut, sal_Int32& nWidthOut, sal_Int32& nHeightOut )
323 {
324 // input position and size
325 Size aPos( nXIn, nYIn );
326 Size aSize( nWidthIn, nHeightIn );
327
328 // convert logic units to pixel
329 OutputDevice* pDevice = Application::GetDefaultDevice();
330 DBG_ASSERT( pDevice, "DlgEdObj::TransformFormToSdrCoordinates: missing default device!" );
331 if ( !pDevice )
332 return false;
333
334 // take window borders into account
335 DlgEdForm* pForm = nullptr;
336 if ( !lcl_getDlgEdForm( this, pForm ) )
337 return false;
338
339 aPos = pDevice->LogicToPixel(aPos, MapMode(MapUnit::MapAppFont));
340 aSize = pDevice->LogicToPixel(aSize, MapMode(MapUnit::MapAppFont));
341
342 // take window borders into account
343 Reference< beans::XPropertySet > xPSetForm( pForm->GetUnoControlModel(), UNO_QUERY );
344 DBG_ASSERT( xPSetForm.is(), "DlgEdObj::TransformFormToSdrCoordinates: no form property set!" );
345 if ( !xPSetForm.is() )
346 return false;
347 bool bDecoration = true;
348 xPSetForm->getPropertyValue( DLGED_PROP_DECORATION ) >>= bDecoration;
349 if( bDecoration )
350 {
351 awt::DeviceInfo aDeviceInfo = pForm->getDeviceInfo();
352 aSize.AdjustWidth(aDeviceInfo.LeftInset + aDeviceInfo.RightInset );
353 aSize.AdjustHeight(aDeviceInfo.TopInset + aDeviceInfo.BottomInset );
354 }
355
356 // convert pixel to 100th_mm
357 aPos = pDevice->PixelToLogic( aPos, MapMode( MapUnit::Map100thMM ) );
358 aSize = pDevice->PixelToLogic( aSize, MapMode( MapUnit::Map100thMM ) );
359
360 // set out parameters
361 nXOut = aPos.Width();
362 nYOut = aPos.Height();
363 nWidthOut = aSize.Width();
364 nHeightOut = aSize.Height();
365
366 return true;
367 }
368
SetRectFromProps()369 void DlgEdObj::SetRectFromProps()
370 {
371 // get control position and size from properties
372 Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
373 if ( !xPSet.is() )
374 return;
375
376 sal_Int32 nXIn = 0, nYIn = 0, nWidthIn = 0, nHeightIn = 0;
377 xPSet->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nXIn;
378 xPSet->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nYIn;
379 xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nWidthIn;
380 xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nHeightIn;
381
382 // transform coordinates
383 sal_Int32 nXOut, nYOut, nWidthOut, nHeightOut;
384 if ( TransformControlToSdrCoordinates( nXIn, nYIn, nWidthIn, nHeightIn, nXOut, nYOut, nWidthOut, nHeightOut ) )
385 {
386 // set rectangle position and size
387 Point aPoint( nXOut, nYOut );
388 Size aSize( nWidthOut, nHeightOut );
389 SetSnapRect( tools::Rectangle( aPoint, aSize ) );
390 }
391 }
392
SetPropsFromRect()393 void DlgEdObj::SetPropsFromRect()
394 {
395 // get control position and size from rectangle
396 tools::Rectangle aRect_ = GetSnapRect();
397 sal_Int32 nXIn = aRect_.Left();
398 sal_Int32 nYIn = aRect_.Top();
399 sal_Int32 nWidthIn = aRect_.GetWidth();
400 sal_Int32 nHeightIn = aRect_.GetHeight();
401
402 // transform coordinates
403 sal_Int32 nXOut, nYOut, nWidthOut, nHeightOut;
404 if ( TransformSdrToControlCoordinates( nXIn, nYIn, nWidthIn, nHeightIn, nXOut, nYOut, nWidthOut, nHeightOut ) )
405 {
406 // set properties
407 Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
408 if ( xPSet.is() )
409 {
410 xPSet->setPropertyValue( DLGED_PROP_POSITIONX, Any(nXOut) );
411 xPSet->setPropertyValue( DLGED_PROP_POSITIONY, Any(nYOut) );
412 xPSet->setPropertyValue( DLGED_PROP_WIDTH, Any(nWidthOut) );
413 xPSet->setPropertyValue( DLGED_PROP_HEIGHT, Any(nHeightOut) );
414 }
415 }
416 }
417
PositionAndSizeChange(const beans::PropertyChangeEvent & evt)418 void DlgEdObj::PositionAndSizeChange( const beans::PropertyChangeEvent& evt )
419 {
420 DBG_ASSERT( pDlgEdForm, "DlgEdObj::PositionAndSizeChange: no form!" );
421 DlgEdPage& rPage = pDlgEdForm->GetDlgEditor().GetPage();
422 {
423 Size aPageSize = rPage.GetSize();
424 sal_Int32 nPageWidthIn = aPageSize.Width();
425 sal_Int32 nPageHeightIn = aPageSize.Height();
426 sal_Int32 nPageX, nPageY, nPageWidth, nPageHeight;
427 if ( TransformSdrToControlCoordinates( 0/*nPageXIn*/, 0/*nPageYIn*/, nPageWidthIn, nPageHeightIn, nPageX, nPageY, nPageWidth, nPageHeight ) )
428 {
429 Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
430 if ( xPSet.is() )
431 {
432 sal_Int32 nX = 0, nY = 0, nWidth = 0, nHeight = 0;
433 xPSet->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nX;
434 xPSet->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nY;
435 xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nWidth;
436 xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nHeight;
437
438 sal_Int32 nValue = 0;
439 evt.NewValue >>= nValue;
440 sal_Int32 nNewValue = nValue;
441
442 if ( evt.PropertyName == DLGED_PROP_POSITIONX )
443 {
444 if ( nNewValue + nWidth > nPageX + nPageWidth )
445 nNewValue = nPageX + nPageWidth - nWidth;
446 if ( nNewValue < nPageX )
447 nNewValue = nPageX;
448 }
449 else if ( evt.PropertyName == DLGED_PROP_POSITIONY )
450 {
451 if ( nNewValue + nHeight > nPageY + nPageHeight )
452 nNewValue = nPageY + nPageHeight - nHeight;
453 if ( nNewValue < nPageY )
454 nNewValue = nPageY;
455 }
456 else if ( evt.PropertyName == DLGED_PROP_WIDTH )
457 {
458 if ( nX + nNewValue > nPageX + nPageWidth )
459 nNewValue = nPageX + nPageWidth - nX;
460 if ( nNewValue < 1 )
461 nNewValue = 1;
462 }
463 else if ( evt.PropertyName == DLGED_PROP_HEIGHT )
464 {
465 if ( nY + nNewValue > nPageY + nPageHeight )
466 nNewValue = nPageY + nPageHeight - nY;
467 if ( nNewValue < 1 )
468 nNewValue = 1;
469 }
470
471 if ( nNewValue != nValue )
472 {
473 EndListening( false );
474 xPSet->setPropertyValue( evt.PropertyName, Any(nNewValue) );
475 StartListening();
476 }
477 }
478 }
479 }
480
481 SetRectFromProps();
482 }
483
NameChange(const css::beans::PropertyChangeEvent & evt)484 void DlgEdObj::NameChange( const css::beans::PropertyChangeEvent& evt )
485 {
486 // get old name
487 OUString aOldName;
488 evt.OldValue >>= aOldName;
489
490 // get new name
491 OUString aNewName;
492 evt.NewValue >>= aNewName;
493
494 if ( aNewName == aOldName )
495 return;
496
497 Reference< container::XNameAccess > xNameAcc((GetDlgEdForm()->GetUnoControlModel()), UNO_QUERY);
498 if ( !(xNameAcc.is() && xNameAcc->hasByName(aOldName)) )
499 return;
500
501 if (!xNameAcc->hasByName(aNewName) && !aNewName.isEmpty())
502 {
503 // remove the control by the old name and insert the control by the new name in the container
504 Reference< container::XNameContainer > xCont(xNameAcc, UNO_QUERY );
505 if ( xCont.is() )
506 {
507 Reference< awt::XControlModel > xCtrl = GetUnoControlModel();
508 Any aAny;
509 aAny <<= xCtrl;
510 xCont->removeByName( aOldName );
511 xCont->insertByName( aNewName , aAny );
512
513 LocalizationMgr::renameControlResourceIDsForEditorObject(
514 &GetDialogEditor(), aAny, aNewName
515 );
516 }
517 }
518 else
519 {
520 // set old name property
521 EndListening(false);
522 Reference< beans::XPropertySet > xPSet(GetUnoControlModel(), UNO_QUERY);
523 xPSet->setPropertyValue( DLGED_PROP_NAME, Any(aOldName) );
524 StartListening();
525 }
526 }
527
GetStep() const528 sal_Int32 DlgEdObj::GetStep() const
529 {
530 // get step property
531 sal_Int32 nStep = 0;
532 uno::Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), uno::UNO_QUERY );
533 if (xPSet.is())
534 {
535 xPSet->getPropertyValue( DLGED_PROP_STEP ) >>= nStep;
536 }
537 return nStep;
538 }
539
UpdateStep()540 void DlgEdObj::UpdateStep()
541 {
542 sal_Int32 nCurStep = GetDlgEdForm()->GetStep();
543 sal_Int32 nStep = GetStep();
544
545 SdrLayerAdmin& rLayerAdmin(getSdrModelFromSdrObject().GetLayerAdmin());
546 SdrLayerID nHiddenLayerId = rLayerAdmin.GetLayerID( "HiddenLayer" );
547 SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID( rLayerAdmin.GetControlLayerName() );
548
549 if( nCurStep )
550 {
551 if ( nStep && (nStep != nCurStep) )
552 {
553 SetLayer( nHiddenLayerId );
554 }
555 else
556 {
557 SetLayer( nControlLayerId );
558 }
559 }
560 else
561 {
562 SetLayer( nControlLayerId );
563 }
564 }
565
TabIndexChange(const beans::PropertyChangeEvent & evt)566 void DlgEdObj::TabIndexChange( const beans::PropertyChangeEvent& evt )
567 {
568 DlgEdForm* pForm = GetDlgEdForm();
569 if ( !pForm )
570 return;
571
572 // stop listening with all children
573 std::vector<DlgEdObj*> aChildList = pForm->GetChildren();
574 for (auto const& child : aChildList)
575 {
576 child->EndListening( false );
577 }
578
579 Reference< container::XNameAccess > xNameAcc( pForm->GetUnoControlModel() , UNO_QUERY );
580 if ( xNameAcc.is() )
581 {
582 // get sequence of control names
583 Sequence< OUString > aNames = xNameAcc->getElementNames();
584 const OUString* pNames = aNames.getConstArray();
585 sal_Int32 nCtrls = aNames.getLength();
586
587 // create a map of tab indices and control names, sorted by tab index
588 IndexToNameMap aIndexToNameMap;
589 for ( sal_Int32 i = 0; i < nCtrls; ++i )
590 {
591 // get control name
592 OUString aName( pNames[i] );
593
594 // get tab index
595 sal_Int16 nTabIndex = -1;
596 Any aCtrl = xNameAcc->getByName( aName );
597 Reference< beans::XPropertySet > xPSet;
598 aCtrl >>= xPSet;
599 if ( xPSet.is() && xPSet == Reference< beans::XPropertySet >( evt.Source, UNO_QUERY ) )
600 evt.OldValue >>= nTabIndex;
601 else if ( xPSet.is() )
602 xPSet->getPropertyValue( DLGED_PROP_TABINDEX ) >>= nTabIndex;
603
604 // insert into map
605 aIndexToNameMap.emplace( nTabIndex, aName );
606 }
607
608 // create a helper list of control names, sorted by tab index
609 std::vector< OUString > aNameList( aIndexToNameMap.size() );
610 std::transform(
611 aIndexToNameMap.begin(), aIndexToNameMap.end(),
612 aNameList.begin(),
613 ::o3tl::select2nd< IndexToNameMap::value_type >( )
614 );
615
616 // check tab index
617 sal_Int16 nOldTabIndex = 0;
618 evt.OldValue >>= nOldTabIndex;
619 sal_Int16 nNewTabIndex = 0;
620 evt.NewValue >>= nNewTabIndex;
621 if ( nNewTabIndex < 0 )
622 nNewTabIndex = 0;
623 else if ( nNewTabIndex > nCtrls - 1 )
624 nNewTabIndex = sal::static_int_cast<sal_Int16>( nCtrls - 1 );
625
626 // reorder helper list
627 OUString aCtrlName = aNameList[nOldTabIndex];
628 aNameList.erase( aNameList.begin() + nOldTabIndex );
629 aNameList.insert( aNameList.begin() + nNewTabIndex , aCtrlName );
630
631 // set new tab indices
632 for ( sal_Int32 i = 0; i < nCtrls; ++i )
633 {
634 Any aCtrl = xNameAcc->getByName( aNameList[i] );
635 Reference< beans::XPropertySet > xPSet;
636 aCtrl >>= xPSet;
637 if ( xPSet.is() )
638 {
639 assert(i >= SAL_MIN_INT16);
640 if (i > SAL_MAX_INT16)
641 {
642 SAL_WARN("basctl", "tab " << i << " > SAL_MAX_INT16");
643 continue;
644 }
645 xPSet->setPropertyValue( DLGED_PROP_TABINDEX, Any(static_cast<sal_Int16>(i)) );
646 }
647 }
648
649 // reorder objects in drawing page
650 getSdrModelFromSdrObject().GetPage(0)->SetObjectOrdNum( nOldTabIndex + 1, nNewTabIndex + 1 );
651
652 pForm->UpdateTabOrderAndGroups();
653 }
654
655 // start listening with all children
656 for (auto const& child : aChildList)
657 {
658 child->StartListening();
659 }
660 }
661
supportsService(OUString const & serviceName) const662 bool DlgEdObj::supportsService( OUString const & serviceName ) const
663 {
664 bool bSupports = false;
665
666 Reference< lang::XServiceInfo > xServiceInfo( GetUnoControlModel() , UNO_QUERY );
667 // TODO: cache xServiceInfo as member?
668 if ( xServiceInfo.is() )
669 bSupports = xServiceInfo->supportsService( serviceName );
670
671 return bSupports;
672 }
673
GetDefaultName() const674 OUString DlgEdObj::GetDefaultName() const
675 {
676 OUString sResId;
677 OUString aDefaultName;
678 if ( supportsService( "com.sun.star.awt.UnoControlDialogModel" ) )
679 {
680 sResId = RID_STR_CLASS_DIALOG;
681 }
682 else if ( supportsService( "com.sun.star.awt.UnoControlButtonModel" ) )
683 {
684 sResId = RID_STR_CLASS_BUTTON;
685 }
686 else if ( supportsService( "com.sun.star.awt.UnoControlRadioButtonModel" ) )
687 {
688 sResId = RID_STR_CLASS_RADIOBUTTON;
689 }
690 else if ( supportsService( "com.sun.star.awt.UnoControlCheckBoxModel" ) )
691 {
692 sResId = RID_STR_CLASS_CHECKBOX;
693 }
694 else if ( supportsService( "com.sun.star.awt.UnoControlListBoxModel" ) )
695 {
696 sResId = RID_STR_CLASS_LISTBOX;
697 }
698 else if ( supportsService( "com.sun.star.awt.UnoControlComboBoxModel" ) )
699 {
700 sResId = RID_STR_CLASS_COMBOBOX;
701 }
702 else if ( supportsService( "com.sun.star.awt.UnoControlGroupBoxModel" ) )
703 {
704 sResId = RID_STR_CLASS_GROUPBOX;
705 }
706 else if ( supportsService( "com.sun.star.awt.UnoControlEditModel" ) )
707 {
708 sResId = RID_STR_CLASS_EDIT;
709 }
710 else if ( supportsService( "com.sun.star.awt.UnoControlFixedTextModel" ) )
711 {
712 sResId = RID_STR_CLASS_FIXEDTEXT;
713 }
714 else if ( supportsService( "com.sun.star.awt.UnoControlImageControlModel" ) )
715 {
716 sResId = RID_STR_CLASS_IMAGECONTROL;
717 }
718 else if ( supportsService( "com.sun.star.awt.UnoControlProgressBarModel" ) )
719 {
720 sResId = RID_STR_CLASS_PROGRESSBAR;
721 }
722 else if ( supportsService( "com.sun.star.awt.UnoControlScrollBarModel" ) )
723 {
724 sResId = RID_STR_CLASS_SCROLLBAR;
725 }
726 else if ( supportsService( "com.sun.star.awt.UnoControlFixedLineModel" ) )
727 {
728 sResId = RID_STR_CLASS_FIXEDLINE;
729 }
730 else if ( supportsService( "com.sun.star.awt.UnoControlDateFieldModel" ) )
731 {
732 sResId = RID_STR_CLASS_DATEFIELD;
733 }
734 else if ( supportsService( "com.sun.star.awt.UnoControlTimeFieldModel" ) )
735 {
736 sResId = RID_STR_CLASS_TIMEFIELD;
737 }
738 else if ( supportsService( "com.sun.star.awt.UnoControlNumericFieldModel" ) )
739 {
740 sResId = RID_STR_CLASS_NUMERICFIELD;
741 }
742 else if ( supportsService( "com.sun.star.awt.UnoControlCurrencyFieldModel" ) )
743 {
744 sResId = RID_STR_CLASS_CURRENCYFIELD;
745 }
746 else if ( supportsService( "com.sun.star.awt.UnoControlFormattedFieldModel" ) )
747 {
748 sResId = RID_STR_CLASS_FORMATTEDFIELD;
749 }
750 else if ( supportsService( "com.sun.star.awt.UnoControlPatternFieldModel" ) )
751 {
752 sResId = RID_STR_CLASS_PATTERNFIELD;
753 }
754 else if ( supportsService( "com.sun.star.awt.UnoControlFileControlModel" ) )
755 {
756 sResId = RID_STR_CLASS_FILECONTROL;
757 }
758 else if ( supportsService( "com.sun.star.awt.tree.TreeControlModel" ) )
759 {
760 sResId = RID_STR_CLASS_TREECONTROL;
761 }
762 else if ( supportsService( "com.sun.star.awt.grid.UnoControlGridModel" ) )
763 {
764 sResId = RID_STR_CLASS_GRIDCONTROL;
765 }
766 else if ( supportsService( "com.sun.star.awt.UnoControlFixedHyperlinkModel" ) )
767 {
768 sResId = RID_STR_CLASS_HYPERLINKCONTROL;
769 }
770 else if ( supportsService( "com.sun.star.awt.UnoControlSpinButtonModel" ) )
771 {
772 sResId = RID_STR_CLASS_SPINCONTROL;
773 }
774 else
775 {
776 sResId = RID_STR_CLASS_CONTROL;
777 }
778
779 if (!sResId.isEmpty())
780 aDefaultName = sResId;
781
782 return aDefaultName;
783 }
784
GetUniqueName() const785 OUString DlgEdObj::GetUniqueName() const
786 {
787 OUString aUniqueName;
788 uno::Reference< container::XNameAccess > xNameAcc((GetDlgEdForm()->GetUnoControlModel()), uno::UNO_QUERY);
789
790 if ( xNameAcc.is() )
791 {
792 sal_Int32 n = 0;
793 OUString aDefaultName = GetDefaultName();
794
795 do
796 {
797 aUniqueName = aDefaultName + OUString::number(++n);
798 } while (xNameAcc->hasByName(aUniqueName));
799 }
800
801 return aUniqueName;
802 }
803
GetObjInventor() const804 SdrInventor DlgEdObj::GetObjInventor() const
805 {
806 return SdrInventor::BasicDialog;
807 }
808
GetObjIdentifier() const809 SdrObjKind DlgEdObj::GetObjIdentifier() const
810 {
811 if ( supportsService( "com.sun.star.awt.UnoControlDialogModel" ))
812 {
813 return OBJ_DLG_DIALOG;
814 }
815 else if ( supportsService( "com.sun.star.awt.UnoControlButtonModel" ))
816 {
817 return OBJ_DLG_PUSHBUTTON;
818 }
819 else if ( supportsService( "com.sun.star.awt.UnoControlRadioButtonModel" ))
820 {
821 return OBJ_DLG_RADIOBUTTON;
822 }
823 else if ( supportsService( "com.sun.star.awt.UnoControlCheckBoxModel" ))
824 {
825 return OBJ_DLG_CHECKBOX;
826 }
827 else if ( supportsService( "com.sun.star.awt.UnoControlListBoxModel" ))
828 {
829 return OBJ_DLG_LISTBOX;
830 }
831 else if ( supportsService( "com.sun.star.awt.UnoControlComboBoxModel" ))
832 {
833 return OBJ_DLG_COMBOBOX;
834 }
835 else if ( supportsService( "com.sun.star.awt.UnoControlGroupBoxModel" ))
836 {
837 return OBJ_DLG_GROUPBOX;
838 }
839 else if ( supportsService( "com.sun.star.awt.UnoControlEditModel" ))
840 {
841 return OBJ_DLG_EDIT;
842 }
843 else if ( supportsService( "com.sun.star.awt.UnoControlFixedTextModel" ))
844 {
845 return OBJ_DLG_FIXEDTEXT;
846 }
847 else if ( supportsService( "com.sun.star.awt.UnoControlImageControlModel" ))
848 {
849 return OBJ_DLG_IMAGECONTROL;
850 }
851 else if ( supportsService( "com.sun.star.awt.UnoControlProgressBarModel" ))
852 {
853 return OBJ_DLG_PROGRESSBAR;
854 }
855 else if ( supportsService( "com.sun.star.awt.UnoControlScrollBarModel" ))
856 {
857 return OBJ_DLG_HSCROLLBAR;
858 }
859 else if ( supportsService( "com.sun.star.awt.UnoControlFixedLineModel" ))
860 {
861 return OBJ_DLG_HFIXEDLINE;
862 }
863 else if ( supportsService( "com.sun.star.awt.UnoControlDateFieldModel" ))
864 {
865 return OBJ_DLG_DATEFIELD;
866 }
867 else if ( supportsService( "com.sun.star.awt.UnoControlTimeFieldModel" ))
868 {
869 return OBJ_DLG_TIMEFIELD;
870 }
871 else if ( supportsService( "com.sun.star.awt.UnoControlNumericFieldModel" ))
872 {
873 return OBJ_DLG_NUMERICFIELD;
874 }
875 else if ( supportsService( "com.sun.star.awt.UnoControlCurrencyFieldModel" ))
876 {
877 return OBJ_DLG_CURRENCYFIELD;
878 }
879 else if ( supportsService( "com.sun.star.awt.UnoControlFormattedFieldModel" ))
880 {
881 return OBJ_DLG_FORMATTEDFIELD;
882 }
883 else if ( supportsService( "com.sun.star.awt.UnoControlPatternFieldModel" ))
884 {
885 return OBJ_DLG_PATTERNFIELD;
886 }
887 else if ( supportsService( "com.sun.star.awt.UnoControlFileControlModel" ))
888 {
889 return OBJ_DLG_FILECONTROL;
890 }
891 else if ( supportsService( "com.sun.star.awt.tree.TreeControlModel" ))
892 {
893 return OBJ_DLG_TREECONTROL;
894 }
895 else if ( supportsService( "com.sun.star.awt.grid.UnoControlGridModel" ))
896 {
897 return OBJ_DLG_GRIDCONTROL;
898 }
899 else if ( supportsService( "com.sun.star.awt.UnoControlFixedHyperlinkModel" ))
900 {
901 return OBJ_DLG_HYPERLINKCONTROL;
902 }
903 else
904 {
905 return OBJ_DLG_CONTROL;
906 }
907 }
908
CloneSdrObject(SdrModel & rTargetModel) const909 DlgEdObj* DlgEdObj::CloneSdrObject(SdrModel& rTargetModel) const
910 {
911 return new DlgEdObj(rTargetModel, *this);
912 }
913
getFullDragClone() const914 SdrObjectUniquePtr DlgEdObj::getFullDragClone() const
915 {
916 // no need to really add the clone for dragging, it's a temporary
917 // object
918 return SdrObjectUniquePtr(new SdrUnoObj(getSdrModelFromSdrObject(), *this));
919 }
920
NbcMove(const Size & rSize)921 void DlgEdObj::NbcMove( const Size& rSize )
922 {
923 SdrUnoObj::NbcMove( rSize );
924
925 // stop listening
926 EndListening(false);
927
928 // set geometry properties
929 SetPropsFromRect();
930
931 // start listening
932 StartListening();
933
934 // dialog model changed
935 GetDlgEdForm()->GetDlgEditor().SetDialogModelChanged();
936 }
937
NbcResize(const Point & rRef,const Fraction & xFract,const Fraction & yFract)938 void DlgEdObj::NbcResize(const Point& rRef, const Fraction& xFract, const Fraction& yFract)
939 {
940 SdrUnoObj::NbcResize( rRef, xFract, yFract );
941
942 // stop listening
943 EndListening(false);
944
945 // set geometry properties
946 SetPropsFromRect();
947
948 // start listening
949 StartListening();
950
951 // dialog model changed
952 GetDlgEdForm()->GetDlgEditor().SetDialogModelChanged();
953 }
954
EndCreate(SdrDragStat & rStat,SdrCreateCmd eCmd)955 bool DlgEdObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
956 {
957 bool bResult = SdrUnoObj::EndCreate(rStat, eCmd);
958
959 // tdf#120674 after interactive creation, the SdrObject (this) has no SdrPage yet
960 // due to not being inserted. Usually this should be handled in a ::handlePageChange
961 // implementation. For historical reasons, the SdrPage (which is the DlgEdPage) was
962 // already set. For now, get it from the SdrDragStat and use it to access and set
963 // the local pDlgEdForm
964 if(nullptr == pDlgEdForm && nullptr != rStat.GetPageView())
965 {
966 const DlgEdPage* pDlgEdPage(dynamic_cast<const DlgEdPage*>(rStat.GetPageView()->GetPage()));
967
968 if(nullptr != pDlgEdPage)
969 {
970 // set parent form
971 pDlgEdForm = pDlgEdPage->GetDlgEdForm();
972 }
973 }
974
975 SetDefaults();
976 StartListening();
977
978 return bResult;
979 }
980
SetDefaults()981 void DlgEdObj::SetDefaults()
982 {
983 if ( !pDlgEdForm )
984 return;
985
986 // add child to parent form
987 pDlgEdForm->AddChild( this );
988
989 Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
990 if ( xPSet.is() )
991 {
992 // get unique name
993 OUString aOUniqueName( GetUniqueName() );
994
995 // set name property
996 xPSet->setPropertyValue( DLGED_PROP_NAME, Any(aOUniqueName) );
997
998 // set labels
999 if ( supportsService( "com.sun.star.awt.UnoControlButtonModel" ) ||
1000 supportsService( "com.sun.star.awt.UnoControlRadioButtonModel" ) ||
1001 supportsService( "com.sun.star.awt.UnoControlCheckBoxModel" ) ||
1002 supportsService( "com.sun.star.awt.UnoControlGroupBoxModel" ) ||
1003 supportsService( "com.sun.star.awt.UnoControlFixedTextModel" ) )
1004 {
1005 xPSet->setPropertyValue( DLGED_PROP_LABEL, Any(aOUniqueName) );
1006 }
1007
1008 // set number formats supplier for formatted field
1009 if ( supportsService( "com.sun.star.awt.UnoControlFormattedFieldModel" ) )
1010 {
1011 Reference< util::XNumberFormatsSupplier > xSupplier = GetDlgEdForm()->GetDlgEditor().GetNumberFormatsSupplier();
1012 if ( xSupplier.is() )
1013 {
1014 xPSet->setPropertyValue( DLGED_PROP_FORMATSSUPPLIER, Any(xSupplier) );
1015 }
1016 }
1017
1018 // set geometry properties
1019 SetPropsFromRect();
1020
1021 Reference< container::XNameContainer > xCont( GetDlgEdForm()->GetUnoControlModel() , UNO_QUERY );
1022 if ( xCont.is() )
1023 {
1024 // set tabindex
1025 Sequence< OUString > aNames = xCont->getElementNames();
1026 uno::Any aTabIndex;
1027 aTabIndex <<= static_cast<sal_Int16>(aNames.getLength());
1028 xPSet->setPropertyValue( DLGED_PROP_TABINDEX, aTabIndex );
1029
1030 // set step
1031 Reference< beans::XPropertySet > xPSetForm( xCont, UNO_QUERY );
1032 if ( xPSetForm.is() )
1033 {
1034 Any aStep = xPSetForm->getPropertyValue( DLGED_PROP_STEP );
1035 xPSet->setPropertyValue( DLGED_PROP_STEP, aStep );
1036 }
1037
1038 // insert control model in dialog model
1039 Reference< awt::XControlModel > xCtrl( xPSet , UNO_QUERY );
1040 Any aAny;
1041 aAny <<= xCtrl;
1042 xCont->insertByName( aOUniqueName , aAny );
1043
1044 LocalizationMgr::setControlResourceIDsForNewEditorObject(
1045 &GetDialogEditor(), aAny, aOUniqueName
1046 );
1047
1048 pDlgEdForm->UpdateTabOrderAndGroups();
1049 }
1050 }
1051
1052 // dialog model changed
1053 pDlgEdForm->GetDlgEditor().SetDialogModelChanged();
1054 }
1055
StartListening()1056 void DlgEdObj::StartListening()
1057 {
1058 DBG_ASSERT(!isListening(), "DlgEdObj::StartListening: already listening!");
1059
1060 if (isListening())
1061 return;
1062
1063 bIsListening = true;
1064
1065 // XPropertyChangeListener
1066 Reference< XPropertySet > xControlModel( GetUnoControlModel() , UNO_QUERY );
1067 if (!m_xPropertyChangeListener.is() && xControlModel.is())
1068 {
1069 // create listener
1070 m_xPropertyChangeListener = new DlgEdPropListenerImpl(*this);
1071
1072 // register listener to properties
1073 xControlModel->addPropertyChangeListener( OUString() , m_xPropertyChangeListener );
1074 }
1075
1076 // XContainerListener
1077 Reference< XScriptEventsSupplier > xEventsSupplier( GetUnoControlModel() , UNO_QUERY );
1078 if( !m_xContainerListener.is() && xEventsSupplier.is() )
1079 {
1080 // create listener
1081 m_xContainerListener = new DlgEdEvtContListenerImpl(*this);
1082
1083 // register listener to script event container
1084 Reference< XNameContainer > xEventCont = xEventsSupplier->getEvents();
1085 DBG_ASSERT(xEventCont.is(), "DlgEdObj::StartListening: control model has no script event container!");
1086 Reference< XContainer > xCont( xEventCont , UNO_QUERY );
1087 if (xCont.is())
1088 xCont->addContainerListener( m_xContainerListener );
1089 }
1090 }
1091
EndListening(bool bRemoveListener)1092 void DlgEdObj::EndListening(bool bRemoveListener)
1093 {
1094 DBG_ASSERT(isListening(), "DlgEdObj::EndListening: not listening currently!");
1095
1096 if (!isListening())
1097 return;
1098
1099 bIsListening = false;
1100
1101 if (!bRemoveListener)
1102 return;
1103
1104 // XPropertyChangeListener
1105 Reference< XPropertySet > xControlModel(GetUnoControlModel(), UNO_QUERY);
1106 if ( m_xPropertyChangeListener.is() && xControlModel.is() )
1107 {
1108 // remove listener
1109 xControlModel->removePropertyChangeListener( OUString() , m_xPropertyChangeListener );
1110 }
1111 m_xPropertyChangeListener.clear();
1112
1113 // XContainerListener
1114 Reference< XScriptEventsSupplier > xEventsSupplier( GetUnoControlModel() , UNO_QUERY );
1115 if( m_xContainerListener.is() && xEventsSupplier.is() )
1116 {
1117 // remove listener
1118 Reference< XNameContainer > xEventCont = xEventsSupplier->getEvents();
1119 DBG_ASSERT(xEventCont.is(), "DlgEdObj::EndListening: control model has no script event container!");
1120 Reference< XContainer > xCont( xEventCont , UNO_QUERY );
1121 if (xCont.is())
1122 xCont->removeContainerListener( m_xContainerListener );
1123 }
1124 m_xContainerListener.clear();
1125 }
1126
_propertyChange(const css::beans::PropertyChangeEvent & evt)1127 void DlgEdObj::_propertyChange( const css::beans::PropertyChangeEvent& evt )
1128 {
1129 if (!isListening())
1130 return;
1131
1132 DlgEdForm* pRealDlgEdForm = dynamic_cast<DlgEdForm*>(this);
1133 if (!pRealDlgEdForm)
1134 pRealDlgEdForm = GetDlgEdForm();
1135 if (!pRealDlgEdForm)
1136 return;
1137 DlgEditor& rDlgEditor = pRealDlgEdForm->GetDlgEditor();
1138 if (rDlgEditor.isInPaint())
1139 return;
1140
1141 // dialog model changed
1142 rDlgEditor.SetDialogModelChanged();
1143
1144 // update position and size
1145 if ( evt.PropertyName == DLGED_PROP_POSITIONX || evt.PropertyName == DLGED_PROP_POSITIONY ||
1146 evt.PropertyName == DLGED_PROP_WIDTH || evt.PropertyName == DLGED_PROP_HEIGHT ||
1147 evt.PropertyName == DLGED_PROP_DECORATION )
1148 {
1149 PositionAndSizeChange( evt );
1150
1151 if ( evt.PropertyName == DLGED_PROP_DECORATION )
1152 GetDialogEditor().ResetDialog();
1153 }
1154 // change name of control in dialog model
1155 else if ( evt.PropertyName == DLGED_PROP_NAME )
1156 {
1157 if (!dynamic_cast<DlgEdForm*>(this))
1158 {
1159 try
1160 {
1161 NameChange(evt);
1162 }
1163 catch (container::NoSuchElementException const&)
1164 {
1165 css::uno::Any anyEx = cppu::getCaughtException();
1166 throw lang::WrappedTargetRuntimeException("", nullptr,
1167 anyEx);
1168 }
1169 }
1170 }
1171 // update step
1172 else if ( evt.PropertyName == DLGED_PROP_STEP )
1173 {
1174 UpdateStep();
1175 }
1176 // change tabindex
1177 else if ( evt.PropertyName == DLGED_PROP_TABINDEX )
1178 {
1179 if (!dynamic_cast<DlgEdForm*>(this))
1180 TabIndexChange(evt);
1181 }
1182 }
1183
_elementInserted()1184 void DlgEdObj::_elementInserted()
1185 {
1186 if (isListening())
1187 {
1188 // dialog model changed
1189 GetDialogEditor().SetDialogModelChanged();
1190 }
1191 }
1192
_elementReplaced()1193 void DlgEdObj::_elementReplaced()
1194 {
1195 if (isListening())
1196 {
1197 // dialog model changed
1198 GetDialogEditor().SetDialogModelChanged();
1199 }
1200 }
1201
_elementRemoved()1202 void DlgEdObj::_elementRemoved()
1203 {
1204 if (isListening())
1205 {
1206 // dialog model changed
1207 GetDialogEditor().SetDialogModelChanged();
1208 }
1209 }
1210
SetLayer(SdrLayerID nLayer)1211 void DlgEdObj::SetLayer(SdrLayerID nLayer)
1212 {
1213 SdrLayerID nOldLayer = GetLayer();
1214
1215 if ( nLayer != nOldLayer )
1216 {
1217 SdrUnoObj::SetLayer( nLayer );
1218
1219 DlgEdHint aHint( DlgEdHint::LAYERCHANGED, this );
1220 GetDlgEdForm()->GetDlgEditor().Broadcast( aHint );
1221 }
1222 }
1223
DlgEdForm(SdrModel & rSdrModel,DlgEditor & rDlgEditor_)1224 DlgEdForm::DlgEdForm(
1225 SdrModel& rSdrModel,
1226 DlgEditor& rDlgEditor_)
1227 : DlgEdObj(rSdrModel),
1228 rDlgEditor(rDlgEditor_)
1229 {
1230 }
1231
~DlgEdForm()1232 DlgEdForm::~DlgEdForm()
1233 {
1234 }
1235
SetRectFromProps()1236 void DlgEdForm::SetRectFromProps()
1237 {
1238 // get form position and size from properties
1239 Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
1240 if ( !xPSet.is() )
1241 return;
1242
1243 sal_Int32 nXIn = 0, nYIn = 0, nWidthIn = 0, nHeightIn = 0;
1244 xPSet->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nXIn;
1245 xPSet->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nYIn;
1246 xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nWidthIn;
1247 xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nHeightIn;
1248
1249 // transform coordinates
1250 sal_Int32 nXOut, nYOut, nWidthOut, nHeightOut;
1251 if ( TransformFormToSdrCoordinates( nXIn, nYIn, nWidthIn, nHeightIn, nXOut, nYOut, nWidthOut, nHeightOut ) )
1252 {
1253 // set rectangle position and size
1254 Point aPoint( nXOut, nYOut );
1255 Size aSize( nWidthOut, nHeightOut );
1256 SetSnapRect( tools::Rectangle( aPoint, aSize ) );
1257 }
1258 }
1259
SetPropsFromRect()1260 void DlgEdForm::SetPropsFromRect()
1261 {
1262 // get form position and size from rectangle
1263 tools::Rectangle aRect_ = GetSnapRect();
1264 sal_Int32 nXIn = aRect_.Left();
1265 sal_Int32 nYIn = aRect_.Top();
1266 sal_Int32 nWidthIn = aRect_.GetWidth();
1267 sal_Int32 nHeightIn = aRect_.GetHeight();
1268
1269 // transform coordinates
1270 sal_Int32 nXOut, nYOut, nWidthOut, nHeightOut;
1271 if ( TransformSdrToFormCoordinates( nXIn, nYIn, nWidthIn, nHeightIn, nXOut, nYOut, nWidthOut, nHeightOut ) )
1272 {
1273 // set properties
1274 Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
1275 if ( xPSet.is() )
1276 {
1277 xPSet->setPropertyValue( DLGED_PROP_POSITIONX, Any(nXOut) );
1278 xPSet->setPropertyValue( DLGED_PROP_POSITIONY, Any(nYOut) );
1279 xPSet->setPropertyValue( DLGED_PROP_WIDTH, Any(nWidthOut) );
1280 xPSet->setPropertyValue( DLGED_PROP_HEIGHT, Any(nHeightOut) );
1281 }
1282 }
1283 }
1284
AddChild(DlgEdObj * pDlgEdObj)1285 void DlgEdForm::AddChild( DlgEdObj* pDlgEdObj )
1286 {
1287 pChildren.push_back( pDlgEdObj );
1288 }
1289
RemoveChild(DlgEdObj * pDlgEdObj)1290 void DlgEdForm::RemoveChild( DlgEdObj* pDlgEdObj )
1291 {
1292 pChildren.erase( std::remove( pChildren.begin() , pChildren.end() , pDlgEdObj ) );
1293 }
1294
PositionAndSizeChange(const beans::PropertyChangeEvent & evt)1295 void DlgEdForm::PositionAndSizeChange( const beans::PropertyChangeEvent& evt )
1296 {
1297 DlgEditor& rEditor = GetDlgEditor();
1298 DlgEdPage& rPage = rEditor.GetPage();
1299
1300 sal_Int32 nPageXIn = 0;
1301 sal_Int32 nPageYIn = 0;
1302 Size aPageSize = rPage.GetSize();
1303 sal_Int32 nPageWidthIn = aPageSize.Width();
1304 sal_Int32 nPageHeightIn = aPageSize.Height();
1305 sal_Int32 nPageX, nPageY, nPageWidth, nPageHeight;
1306 if ( TransformSdrToFormCoordinates( nPageXIn, nPageYIn, nPageWidthIn, nPageHeightIn, nPageX, nPageY, nPageWidth, nPageHeight ) )
1307 {
1308 Reference< beans::XPropertySet > xPSetForm( GetUnoControlModel(), UNO_QUERY );
1309 if ( xPSetForm.is() )
1310 {
1311 sal_Int32 nValue = 0;
1312 evt.NewValue >>= nValue;
1313 sal_Int32 nNewValue = nValue;
1314
1315 if ( evt.PropertyName == DLGED_PROP_POSITIONX )
1316 {
1317 if ( nNewValue < nPageX )
1318 nNewValue = nPageX;
1319 }
1320 else if ( evt.PropertyName == DLGED_PROP_POSITIONY )
1321 {
1322 if ( nNewValue < nPageY )
1323 nNewValue = nPageY;
1324 }
1325 else if ( evt.PropertyName == DLGED_PROP_WIDTH )
1326 {
1327 if ( nNewValue < 1 )
1328 nNewValue = 1;
1329 }
1330 else if ( evt.PropertyName == DLGED_PROP_HEIGHT )
1331 {
1332 if ( nNewValue < 1 )
1333 nNewValue = 1;
1334 }
1335
1336 if ( nNewValue != nValue )
1337 {
1338 EndListening( false );
1339 xPSetForm->setPropertyValue( evt.PropertyName, Any(nNewValue) );
1340 StartListening();
1341 }
1342 }
1343 }
1344
1345 bool bAdjustedPageSize = rEditor.AdjustPageSize();
1346 SetRectFromProps();
1347 std::vector<DlgEdObj*> const& aChildList = GetChildren();
1348
1349 if ( bAdjustedPageSize )
1350 {
1351 rEditor.InitScrollBars();
1352 aPageSize = rPage.GetSize();
1353 nPageWidthIn = aPageSize.Width();
1354 nPageHeightIn = aPageSize.Height();
1355 if ( TransformSdrToControlCoordinates( nPageXIn, nPageYIn, nPageWidthIn, nPageHeightIn, nPageX, nPageY, nPageWidth, nPageHeight ) )
1356 {
1357 for (auto const& child : aChildList)
1358 {
1359 Reference< beans::XPropertySet > xPSet( child->GetUnoControlModel(), UNO_QUERY );
1360 if ( xPSet.is() )
1361 {
1362 sal_Int32 nX = 0, nY = 0, nWidth = 0, nHeight = 0;
1363 xPSet->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nX;
1364 xPSet->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nY;
1365 xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nWidth;
1366 xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nHeight;
1367
1368 sal_Int32 nNewX = nX;
1369 if ( nX + nWidth > nPageX + nPageWidth )
1370 {
1371 nNewX = nPageX + nPageWidth - nWidth;
1372 if ( nNewX < nPageX )
1373 nNewX = nPageX;
1374 }
1375 if ( nNewX != nX )
1376 {
1377 EndListening( false );
1378 xPSet->setPropertyValue( DLGED_PROP_POSITIONX, Any(nNewX) );
1379 StartListening();
1380 }
1381
1382 sal_Int32 nNewY = nY;
1383 if ( nY + nHeight > nPageY + nPageHeight )
1384 {
1385 nNewY = nPageY + nPageHeight - nHeight;
1386 if ( nNewY < nPageY )
1387 nNewY = nPageY;
1388 }
1389 if ( nNewY != nY )
1390 {
1391 EndListening( false );
1392 xPSet->setPropertyValue( DLGED_PROP_POSITIONY, Any(nNewY) );
1393 StartListening();
1394 }
1395 }
1396 }
1397 }
1398 }
1399
1400 for (auto const& child : aChildList)
1401 child->SetRectFromProps();
1402 }
1403
UpdateStep()1404 void DlgEdForm::UpdateStep()
1405 {
1406 SdrPage* pSdrPage = getSdrPageFromSdrObject();
1407
1408 if ( pSdrPage )
1409 {
1410 const size_t nObjCount = pSdrPage->GetObjCount();
1411 for ( size_t i = 0 ; i < nObjCount ; i++ )
1412 {
1413 DlgEdObj* pDlgEdObj = dynamic_cast<DlgEdObj*>(pSdrPage->GetObj(i));
1414 if (pDlgEdObj && !dynamic_cast<DlgEdForm*>(pDlgEdObj))
1415 pDlgEdObj->UpdateStep();
1416 }
1417 }
1418 }
1419
UpdateTabIndices()1420 void DlgEdForm::UpdateTabIndices()
1421 {
1422 // stop listening with all children
1423 for (auto const& child : pChildren)
1424 {
1425 child->EndListening( false );
1426 }
1427
1428 Reference< css::container::XNameAccess > xNameAcc( GetUnoControlModel() , UNO_QUERY );
1429 if ( xNameAcc.is() )
1430 {
1431 // get sequence of control names
1432 Sequence< OUString > aNames = xNameAcc->getElementNames();
1433 const OUString* pNames = aNames.getConstArray();
1434 sal_Int32 nCtrls = aNames.getLength();
1435
1436 // create a map of tab indices and control names, sorted by tab index
1437 IndexToNameMap aIndexToNameMap;
1438 for ( sal_Int32 i = 0; i < nCtrls; ++i )
1439 {
1440 // get name
1441 OUString aName( pNames[i] );
1442
1443 // get tab index
1444 sal_Int16 nTabIndex = -1;
1445 Any aCtrl = xNameAcc->getByName( aName );
1446 Reference< css::beans::XPropertySet > xPSet;
1447 aCtrl >>= xPSet;
1448 if ( xPSet.is() )
1449 xPSet->getPropertyValue( DLGED_PROP_TABINDEX ) >>= nTabIndex;
1450
1451 // insert into map
1452 aIndexToNameMap.emplace( nTabIndex, aName );
1453 }
1454
1455 // set new tab indices
1456 sal_Int16 nNewTabIndex = 0;
1457 for (auto const& indexToName : aIndexToNameMap)
1458 {
1459 Any aCtrl = xNameAcc->getByName( indexToName.second );
1460 Reference< beans::XPropertySet > xPSet;
1461 aCtrl >>= xPSet;
1462 if ( xPSet.is() )
1463 {
1464 xPSet->setPropertyValue( DLGED_PROP_TABINDEX, Any(nNewTabIndex) );
1465 nNewTabIndex++;
1466 }
1467 }
1468
1469 UpdateTabOrderAndGroups();
1470 }
1471
1472 // start listening with all children
1473 for (auto const& child : pChildren)
1474 {
1475 child->StartListening();
1476 }
1477 }
1478
UpdateTabOrder()1479 void DlgEdForm::UpdateTabOrder()
1480 {
1481 // When the tabindex of a control model changes, the dialog control is
1482 // notified about those changes. Due to #109067# (bad performance of
1483 // dialog editor) the dialog control doesn't activate the tab order
1484 // in design mode. When the dialog editor has reordered all
1485 // tabindices, this method allows to activate the taborder afterwards.
1486
1487 Reference< awt::XUnoControlContainer > xCont( GetControl(), UNO_QUERY );
1488 if ( xCont.is() )
1489 {
1490 Sequence< Reference< awt::XTabController > > aSeqTabCtrls = xCont->getTabControllers();
1491 const Reference< awt::XTabController >* pTabCtrls = aSeqTabCtrls.getConstArray();
1492 sal_Int32 nCount = aSeqTabCtrls.getLength();
1493 for ( sal_Int32 i = 0; i < nCount; ++i )
1494 pTabCtrls[i]->activateTabOrder();
1495 }
1496 }
1497
UpdateGroups()1498 void DlgEdForm::UpdateGroups()
1499 {
1500 // The grouping of radio buttons in a dialog is done by vcl.
1501 // In the dialog editor we have two views (=controls) for one
1502 // radio button model. One control is owned by the dialog control,
1503 // but not visible in design mode. The other control is owned by
1504 // the drawing layer object. Whereas the grouping of the first
1505 // control is done by vcl, the grouping of the control in the
1506 // drawing layer has to be done here.
1507
1508 Reference< awt::XTabControllerModel > xTabModel( GetUnoControlModel() , UNO_QUERY );
1509 if ( !xTabModel.is() )
1510 return;
1511
1512 // create a global list of controls that belong to the dialog
1513 std::vector<DlgEdObj*> aChildList = GetChildren();
1514 sal_uInt32 nSize = aChildList.size();
1515 Sequence< Reference< awt::XControl > > aSeqControls( nSize );
1516 for ( sal_uInt32 i = 0; i < nSize; ++i )
1517 aSeqControls.getArray()[i] = aChildList[i]->GetControl();
1518
1519 sal_Int32 nGroupCount = xTabModel->getGroupCount();
1520 for ( sal_Int32 nGroup = 0; nGroup < nGroupCount; ++nGroup )
1521 {
1522 // get a list of control models that belong to this group
1523 OUString aName;
1524 Sequence< Reference< awt::XControlModel > > aSeqModels;
1525 xTabModel->getGroup( nGroup, aSeqModels, aName );
1526 const Reference< awt::XControlModel >* pModels = aSeqModels.getConstArray();
1527 sal_Int32 nModelCount = aSeqModels.getLength();
1528
1529 // create a list of peers that belong to this group
1530 Sequence< Reference< awt::XWindow > > aSeqPeers( nModelCount );
1531 for ( sal_Int32 nModel = 0; nModel < nModelCount; ++nModel )
1532 {
1533 // for each control model find the corresponding control in the global list
1534 const Reference< awt::XControl >* pControls = aSeqControls.getConstArray();
1535 sal_Int32 nControlCount = aSeqControls.getLength();
1536 for ( sal_Int32 nControl = 0; nControl < nControlCount; ++nControl )
1537 {
1538 const Reference< awt::XControl > xCtrl( pControls[nControl] );
1539 if ( xCtrl.is() )
1540 {
1541 Reference< awt::XControlModel > xCtrlModel( xCtrl->getModel() );
1542 if ( xCtrlModel.get() == pModels[nModel].get() )
1543 {
1544 // get the control peer and insert into the list of peers
1545 aSeqPeers.getArray()[ nModel ].set( xCtrl->getPeer(), UNO_QUERY );
1546 break;
1547 }
1548 }
1549 }
1550 }
1551
1552 // set the group at the dialog peer
1553 Reference< awt::XControl > xDlg = GetControl();
1554 if ( xDlg.is() )
1555 {
1556 Reference< awt::XVclContainerPeer > xDlgPeer( xDlg->getPeer(), UNO_QUERY );
1557 if ( xDlgPeer.is() )
1558 xDlgPeer->setGroup( aSeqPeers );
1559 }
1560 }
1561 }
1562
UpdateTabOrderAndGroups()1563 void DlgEdForm::UpdateTabOrderAndGroups()
1564 {
1565 UpdateTabOrder();
1566 UpdateGroups();
1567 }
1568
NbcMove(const Size & rSize)1569 void DlgEdForm::NbcMove( const Size& rSize )
1570 {
1571 SdrUnoObj::NbcMove( rSize );
1572
1573 // set geometry properties of form
1574 EndListening(false);
1575 SetPropsFromRect();
1576 StartListening();
1577
1578 // set geometry properties of all children
1579 for (auto const& child : pChildren)
1580 {
1581 child->EndListening(false);
1582 child->SetPropsFromRect();
1583 child->StartListening();
1584 }
1585
1586 // dialog model changed
1587 GetDlgEditor().SetDialogModelChanged();
1588 }
1589
NbcResize(const Point & rRef,const Fraction & xFract,const Fraction & yFract)1590 void DlgEdForm::NbcResize(const Point& rRef, const Fraction& xFract, const Fraction& yFract)
1591 {
1592 SdrUnoObj::NbcResize( rRef, xFract, yFract );
1593
1594 // set geometry properties of form
1595 EndListening(false);
1596 SetPropsFromRect();
1597 StartListening();
1598
1599 // set geometry properties of all children
1600 for (auto const& child : pChildren)
1601 {
1602 child->EndListening(false);
1603 child->SetPropsFromRect();
1604 child->StartListening();
1605 }
1606
1607 // dialog model changed
1608 GetDlgEditor().SetDialogModelChanged();
1609 }
1610
EndCreate(SdrDragStat & rStat,SdrCreateCmd eCmd)1611 bool DlgEdForm::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
1612 {
1613 bool bResult = SdrUnoObj::EndCreate(rStat, eCmd);
1614
1615 // stop listening
1616 EndListening(false);
1617
1618 // set geometry properties
1619 SetPropsFromRect();
1620
1621 // dialog model changed
1622 GetDlgEditor().SetDialogModelChanged();
1623
1624 // start listening
1625 StartListening();
1626
1627 return bResult;
1628 }
1629
getDeviceInfo() const1630 awt::DeviceInfo DlgEdForm::getDeviceInfo() const
1631 {
1632 awt::DeviceInfo aDeviceInfo;
1633
1634 DlgEditor& rEditor = GetDlgEditor();
1635 vcl::Window& rWindow = rEditor.GetWindow();
1636
1637 // obtain an XControl
1638 ::utl::SharedUNOComponent< awt::XControl > xDialogControl; // ensures auto-disposal, if needed
1639 xDialogControl.reset( GetControl(), ::utl::SharedUNOComponent< awt::XControl >::NoTakeOwnership );
1640 if ( !xDialogControl.is() )
1641 {
1642 // don't create a temporary control all the time, this method here is called
1643 // way too often. Instead, use a cached DeviceInfo.
1644 // #i74065#
1645 if ( !!mpDeviceInfo )
1646 return *mpDeviceInfo;
1647
1648 Reference< awt::XControlContainer > xEditorControlContainer( rEditor.GetWindowControlContainer() );
1649 xDialogControl.reset(
1650 GetTemporaryControlForWindow(rWindow, xEditorControlContainer),
1651 utl::SharedUNOComponent< awt::XControl >::TakeOwnership
1652 );
1653 }
1654
1655 Reference< awt::XDevice > xDialogDevice;
1656 if ( xDialogControl.is() )
1657 xDialogDevice.set( xDialogControl->getPeer(), UNO_QUERY );
1658 DBG_ASSERT( xDialogDevice.is(), "DlgEdForm::getDeviceInfo: no device!" );
1659 if ( xDialogDevice.is() )
1660 aDeviceInfo = xDialogDevice->getInfo();
1661
1662 mpDeviceInfo = aDeviceInfo;
1663
1664 return aDeviceInfo;
1665 }
MakeDataAware(const Reference<frame::XModel> & xModel)1666 void DlgEdObj::MakeDataAware( const Reference< frame::XModel >& xModel )
1667 {
1668 // Need to flesh this out, currently we will only support data-aware controls for calc
1669 // and only handle a subset of functionality e.g. linked-cell and cell range data source. Of course later
1670 // we need to disambiguate for writer ( and others ? ) and also support the generic form (db) bindings
1671 // we need some more work in xmlscript to be able to handle that
1672 Reference< lang::XMultiServiceFactory > xFac( xModel, UNO_QUERY );
1673 Reference< form::binding::XBindableValue > xBindable( GetUnoControlModel(), UNO_QUERY );
1674 Reference< form::binding::XListEntrySink > xListEntrySink( GetUnoControlModel(), UNO_QUERY );
1675 if ( !xFac.is() )
1676 return;
1677
1678 css::table::CellAddress aApiAddress;
1679
1680 //tdf#90361 CellValueBinding and CellRangeListSource are unusable
1681 //without being initialized, so use createInstanceWithArguments with a
1682 //dummy BoundCell instead of createInstance. This at least results in
1683 //the dialog editor not falling.
1684 css::beans::NamedValue aValue;
1685 aValue.Name = "BoundCell";
1686 aValue.Value <<= aApiAddress;
1687
1688 Sequence< Any > aArgs( 1 );
1689 aArgs[ 0 ] <<= aValue;
1690
1691 if ( xBindable.is() )
1692 {
1693 Reference< form::binding::XValueBinding > xBinding( xFac->createInstanceWithArguments( "com.sun.star.table.CellValueBinding", aArgs ), UNO_QUERY );
1694 xBindable->setValueBinding( xBinding );
1695 }
1696 if ( xListEntrySink.is() )
1697 {
1698 Reference< form::binding::XListEntrySource > xSource( xFac->createInstanceWithArguments( "com.sun.star.table.CellRangeListSource", aArgs ), UNO_QUERY );
1699 xListEntrySink->setListEntrySource( xSource );
1700 }
1701 }
1702 } // namespace basctl
1703
1704 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1705