Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / cui / source / tabpages / transfrm.cxx
blobc67d69da6026c88c9078c3f1ec8c2d152f151949
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <algorithm>
24 #include <svx/EnhancedCustomShape2d.hxx>
25 #include <svx/svdundo.hxx>
26 #include <svx/svdview.hxx>
27 #include <svx/svdobj.hxx>
28 #include <svx/svdpagv.hxx>
29 #include <svx/svdoashp.hxx>
30 #include <svx/sderitm.hxx>
31 #include <svx/svxids.hrc>
32 #include <svx/transfrmhelper.hxx>
33 #include <svtools/unitconv.hxx>
35 #include <transfrm.hxx>
36 #include <svx/dlgutil.hxx>
37 #include <svx/anchorid.hxx>
38 #include <svl/rectitem.hxx>
39 #include <svl/aeitem.hxx>
40 #include <swpossizetabpage.hxx>
41 #include <vcl/canvastools.hxx>
43 // static ----------------------------------------------------------------
45 const sal_uInt16 SvxPositionSizeTabPage::pPosSizeRanges[] =
47 SID_ATTR_TRANSFORM_POS_X,
48 SID_ATTR_TRANSFORM_POS_Y,
49 SID_ATTR_TRANSFORM_PROTECT_POS,
50 SID_ATTR_TRANSFORM_PROTECT_POS,
51 SID_ATTR_TRANSFORM_INTERN,
52 SID_ATTR_TRANSFORM_INTERN,
53 SID_ATTR_TRANSFORM_ANCHOR,
54 SID_ATTR_TRANSFORM_VERT_ORIENT,
55 SID_ATTR_TRANSFORM_WIDTH,
56 SID_ATTR_TRANSFORM_SIZE_POINT,
57 SID_ATTR_TRANSFORM_PROTECT_POS,
58 SID_ATTR_TRANSFORM_INTERN,
59 SID_ATTR_TRANSFORM_AUTOWIDTH,
60 SID_ATTR_TRANSFORM_AUTOHEIGHT,
64 const sal_uInt16 SvxAngleTabPage::pAngleRanges[] =
66 SID_ATTR_TRANSFORM_ROT_X,
67 SID_ATTR_TRANSFORM_ANGLE,
68 SID_ATTR_TRANSFORM_INTERN,
69 SID_ATTR_TRANSFORM_INTERN,
73 const sal_uInt16 SvxSlantTabPage::pSlantRanges[] =
75 SDRATTR_ECKENRADIUS,
76 SDRATTR_ECKENRADIUS,
77 SID_ATTR_TRANSFORM_SHEAR,
78 SID_ATTR_TRANSFORM_SHEAR_VERTICAL,
79 SID_ATTR_TRANSFORM_INTERN,
80 SID_ATTR_TRANSFORM_INTERN,
84 /*************************************************************************
86 |* constructor of the tab dialog: adds the pages to the dialog
88 \************************************************************************/
90 SvxTransformTabDialog::SvxTransformTabDialog(weld::Window* pParent, const SfxItemSet* pAttr,
91 const SdrView* pSdrView, SvxAnchorIds nAnchorTypes)
92 : SfxTabDialogController(pParent, "cui/ui/positionsizedialog.ui", "PositionAndSizeDialog", pAttr)
93 , pView(pSdrView)
94 , nAnchorCtrls(nAnchorTypes)
96 DBG_ASSERT(pView, "no valid view (!)");
98 //different positioning page in Writer
99 if(nAnchorCtrls & (SvxAnchorIds::Paragraph | SvxAnchorIds::Character | SvxAnchorIds::Page | SvxAnchorIds::Fly))
101 AddTabPage("RID_SVXPAGE_SWPOSSIZE", SvxSwPosSizeTabPage::Create, SvxSwPosSizeTabPage::GetRanges);
102 RemoveTabPage("RID_SVXPAGE_POSITION_SIZE");
104 else
106 AddTabPage("RID_SVXPAGE_POSITION_SIZE", SvxPositionSizeTabPage::Create, SvxPositionSizeTabPage::GetRanges);
107 RemoveTabPage("RID_SVXPAGE_SWPOSSIZE");
110 AddTabPage("RID_SVXPAGE_ANGLE", SvxAngleTabPage::Create, SvxAngleTabPage::GetRanges);
111 AddTabPage("RID_SVXPAGE_SLANT", SvxSlantTabPage::Create, SvxSlantTabPage::GetRanges);
115 void SvxTransformTabDialog::PageCreated(const OString& rId, SfxTabPage &rPage)
117 if (rId == "RID_SVXPAGE_POSITION_SIZE")
119 SvxPositionSizeTabPage& rSvxPos = static_cast<SvxPositionSizeTabPage&>(rPage);
120 rSvxPos.SetView(pView);
121 rSvxPos.Construct();
123 if(nAnchorCtrls & SvxAnchorIds::NoResize)
125 rSvxPos.DisableResize();
128 if(nAnchorCtrls & SvxAnchorIds::NoProtect)
130 rSvxPos.DisableProtect();
131 rSvxPos.UpdateControlStates();
134 else if (rId == "RID_SVXPAGE_SWPOSSIZE")
136 SvxSwPosSizeTabPage& rSwPos = static_cast<SvxSwPosSizeTabPage&>(rPage);
138 rSwPos.EnableAnchorTypes(nAnchorCtrls);
139 rSwPos.SetValidateFramePosLink(aValidateLink);
140 rSwPos.SetView(pView);
142 else if (rId == "RID_SVXPAGE_ANGLE")
144 SvxAngleTabPage& rSvxAng = static_cast<SvxAngleTabPage&>(rPage);
146 rSvxAng.SetView( pView );
147 rSvxAng.Construct();
149 else if (rId == "RID_SVXPAGE_SLANT")
151 SvxSlantTabPage& rSvxSlnt = static_cast<SvxSlantTabPage&>(rPage);
153 rSvxSlnt.SetView( pView );
154 rSvxSlnt.Construct();
158 void SvxTransformTabDialog::SetValidateFramePosLink(const Link<SvxSwFrameValidation&,void>& rLink)
160 aValidateLink = rLink;
163 /*************************************************************************
165 |* dialog for changing the positions of the rotation
166 |* angle and the rotation angle of the graphic objects
168 \************************************************************************/
169 SvxAngleTabPage::SvxAngleTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
170 : SvxTabPage(pPage, pController, "cui/ui/rotationtabpage.ui", "Rotation", rInAttrs)
171 , rOutAttrs(rInAttrs)
172 , pView(nullptr)
173 , eDlgUnit(FieldUnit::NONE)
174 , m_aCtlRect(this)
175 , m_xFlPosition(m_xBuilder->weld_widget("FL_POSITION"))
176 , m_xMtrPosX(m_xBuilder->weld_metric_spin_button("MTR_FLD_POS_X", FieldUnit::CM))
177 , m_xMtrPosY(m_xBuilder->weld_metric_spin_button("MTR_FLD_POS_Y", FieldUnit::CM))
178 , m_xCtlRect(new weld::CustomWeld(*m_xBuilder, "CTL_RECT", m_aCtlRect))
179 , m_xFlAngle(m_xBuilder->weld_widget("FL_ANGLE"))
180 , m_xNfAngle(m_xBuilder->weld_spin_button("NF_ANGLE"))
181 , m_xCtlAngle(new weld::CustomWeld(*m_xBuilder, "CTL_ANGLE", m_aCtlAngle))
183 // calculate PoolUnit
184 SfxItemPool* pPool = rOutAttrs.GetPool();
185 DBG_ASSERT( pPool, "no pool (!)" );
186 ePoolUnit = pPool->GetMetric(SID_ATTR_TRANSFORM_POS_X);
188 m_aCtlAngle.SetLinkedField(m_xNfAngle.get(), 2);
191 SvxAngleTabPage::~SvxAngleTabPage()
195 void SvxAngleTabPage::Construct()
197 DBG_ASSERT(pView, "No valid view (!)");
198 eDlgUnit = GetModuleFieldUnit(GetItemSet());
199 SetFieldUnit(*m_xMtrPosX, eDlgUnit, true);
200 SetFieldUnit(*m_xMtrPosY, eDlgUnit, true);
202 if (FieldUnit::MILE == eDlgUnit || FieldUnit::KM == eDlgUnit)
204 m_xMtrPosX->set_digits(3);
205 m_xMtrPosY->set_digits(3);
208 { // #i75273#
209 ::tools::Rectangle aTempRect(pView->GetAllMarkedRect());
210 pView->GetSdrPageView()->LogicToPagePos(aTempRect);
211 maRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect);
214 // Take anchor into account (Writer)
215 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
217 if(rMarkList.GetMarkCount())
219 const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
220 maAnchor = basegfx::B2DPoint(pObj->GetAnchorPos().X(), pObj->GetAnchorPos().Y());
222 if(!maAnchor.equalZero()) // -> Writer
224 maRange = basegfx::B2DRange(maRange.getMinimum() - maAnchor, maRange.getMaximum() - maAnchor);
228 // take scale into account
229 const Fraction aUIScale(pView->GetModel()->GetUIScale());
230 TransfrmHelper::ScaleRect(maRange, aUIScale);
232 // take UI units into account
233 sal_uInt16 nDigits(m_xMtrPosX->get_digits());
234 TransfrmHelper::ConvertRect(maRange, nDigits, ePoolUnit, eDlgUnit);
236 if(!pView->IsRotateAllowed())
238 m_xFlPosition->set_sensitive(false);
239 m_xFlAngle->set_sensitive(false);
243 bool SvxAngleTabPage::FillItemSet(SfxItemSet* rSet)
245 bool bModified = false;
247 if (m_aCtlAngle.IsValueModified() || m_xMtrPosX->get_value_changed_from_saved() || m_xMtrPosY->get_value_changed_from_saved())
249 const double fUIScale(double(pView->GetModel()->GetUIScale()));
250 const double fTmpX((GetCoreValue(*m_xMtrPosX, ePoolUnit) + maAnchor.getX()) * fUIScale);
251 const double fTmpY((GetCoreValue(*m_xMtrPosY, ePoolUnit) + maAnchor.getY()) * fUIScale);
253 rSet->Put(SfxInt32Item(GetWhich(SID_ATTR_TRANSFORM_ANGLE), m_aCtlAngle.GetRotation()));
254 rSet->Put(SfxInt32Item(GetWhich(SID_ATTR_TRANSFORM_ROT_X), basegfx::fround(fTmpX)));
255 rSet->Put(SfxInt32Item(GetWhich(SID_ATTR_TRANSFORM_ROT_Y), basegfx::fround(fTmpY)));
257 bModified = true;
260 return bModified;
264 void SvxAngleTabPage::Reset(const SfxItemSet* rAttrs)
266 const double fUIScale(double(pView->GetModel()->GetUIScale()));
268 const SfxPoolItem* pItem = GetItem( *rAttrs, SID_ATTR_TRANSFORM_ROT_X );
269 if(pItem)
271 const double fTmp((static_cast<double>(static_cast<const SfxInt32Item*>(pItem)->GetValue()) - maAnchor.getX()) / fUIScale);
272 SetMetricValue(*m_xMtrPosX, basegfx::fround(fTmp), ePoolUnit);
274 else
276 m_xMtrPosX->set_text(OUString());
279 pItem = GetItem(*rAttrs, SID_ATTR_TRANSFORM_ROT_Y);
280 if(pItem)
282 const double fTmp((static_cast<double>(static_cast<const SfxInt32Item*>(pItem)->GetValue()) - maAnchor.getY()) / fUIScale);
283 SetMetricValue(*m_xMtrPosY, basegfx::fround(fTmp), ePoolUnit);
285 else
287 m_xMtrPosY->set_text(OUString());
290 pItem = GetItem( *rAttrs, SID_ATTR_TRANSFORM_ANGLE );
291 if(pItem)
293 m_aCtlAngle.SetRotation(static_cast<const SfxInt32Item*>(pItem)->GetValue());
295 else
297 m_aCtlAngle.SetRotation(0);
299 m_aCtlAngle.SaveValue();
300 m_xMtrPosX->save_value();
301 m_xMtrPosY->save_value();
304 std::unique_ptr<SfxTabPage> SvxAngleTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
306 return std::make_unique<SvxAngleTabPage>(pPage, pController, *rSet);
309 void SvxAngleTabPage::ActivatePage(const SfxItemSet& rSet)
311 SfxBoolItem const * bPosProtect = nullptr;
312 if(SfxItemState::SET == rSet.GetItemState( GetWhich(SID_ATTR_TRANSFORM_PROTECT_POS ) , false, reinterpret_cast<SfxPoolItem const **>(&bPosProtect) ))
314 m_xFlPosition->set_sensitive(!bPosProtect->GetValue());
315 m_xFlAngle->set_sensitive(!bPosProtect->GetValue());
319 DeactivateRC SvxAngleTabPage::DeactivatePage( SfxItemSet* _pSet )
321 if(_pSet)
323 FillItemSet(_pSet);
326 return DeactivateRC::LeavePage;
329 void SvxAngleTabPage::PointChanged(weld::DrawingArea* pDrawingArea, RectPoint eRP)
331 if (pDrawingArea == m_aCtlRect.GetDrawingArea())
333 switch(eRP)
335 case RectPoint::LT:
337 m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE );
338 m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE );
339 break;
341 case RectPoint::MT:
343 m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE );
344 m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE );
345 break;
347 case RectPoint::RT:
349 m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE );
350 m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE );
351 break;
353 case RectPoint::LM:
355 m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE );
356 m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE );
357 break;
359 case RectPoint::MM:
361 m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE );
362 m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE );
363 break;
365 case RectPoint::RM:
367 m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE );
368 m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE );
369 break;
371 case RectPoint::LB:
373 m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE );
374 m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE );
375 break;
377 case RectPoint::MB:
379 m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE );
380 m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE );
381 break;
383 case RectPoint::RB:
385 m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE );
386 m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE );
387 break;
393 /*************************************************************************
395 |* dialog for changing slant and corner radius
397 \************************************************************************/
398 SvxSlantTabPage::SvxSlantTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
399 : SfxTabPage(pPage, pController, "cui/ui/slantcornertabpage.ui", "SlantAndCornerRadius", &rInAttrs)
400 , rOutAttrs(rInAttrs)
401 , pView(nullptr)
402 , eDlgUnit(FieldUnit::NONE)
403 , m_xFlRadius(m_xBuilder->weld_widget("FL_RADIUS"))
404 , m_xMtrRadius(m_xBuilder->weld_metric_spin_button("MTR_FLD_RADIUS", FieldUnit::CM))
405 , m_xFlAngle(m_xBuilder->weld_widget("FL_SLANT"))
406 , m_xMtrAngle(m_xBuilder->weld_metric_spin_button("MTR_FLD_ANGLE", FieldUnit::DEGREE))
408 for (int i = 0; i < 2; ++i)
410 m_aControlGroups[i] = m_xBuilder->weld_widget("controlgroups" + OString::number(i+1));
411 m_aControlGroupX[i] = m_xBuilder->weld_widget("controlgroupx" + OString::number(i+1));
412 m_aControlX[i] = m_xBuilder->weld_metric_spin_button("controlx" + OString::number(i+1), FieldUnit::CM);
413 m_aControlGroupY[i] = m_xBuilder->weld_widget("controlgroupy" + OString::number(i+1));
414 m_aControlY[i] = m_xBuilder->weld_metric_spin_button("controly" + OString::number(i+1), FieldUnit::CM);
417 // this page needs ExchangeSupport
418 SetExchangeSupport();
420 // evaluate PoolUnit
421 SfxItemPool* pPool = rOutAttrs.GetPool();
422 assert(pPool && "no pool (!)");
423 ePoolUnit = pPool->GetMetric( SID_ATTR_TRANSFORM_POS_X );
426 SvxSlantTabPage::~SvxSlantTabPage()
430 void SvxSlantTabPage::Construct()
432 // get the range
433 DBG_ASSERT(pView, "no valid view (!)");
434 eDlgUnit = GetModuleFieldUnit(GetItemSet());
435 SetFieldUnit(*m_xMtrRadius, eDlgUnit, true);
436 for (int i = 0; i < 2; ++i)
438 SetFieldUnit(*m_aControlX[i], eDlgUnit, true);
439 SetFieldUnit(*m_aControlY[i], eDlgUnit, true);
442 { // #i75273#
443 ::tools::Rectangle aTempRect(pView->GetAllMarkedRect());
444 pView->GetSdrPageView()->LogicToPagePos(aTempRect);
448 bool SvxSlantTabPage::FillItemSet(SfxItemSet* rAttrs)
450 bool bModified = false;
452 if (m_xMtrRadius->get_value_changed_from_saved())
454 Fraction aUIScale = pView->GetModel()->GetUIScale();
455 long nTmp = long(GetCoreValue(*m_xMtrRadius, ePoolUnit) * aUIScale);
457 rAttrs->Put( makeSdrEckenradiusItem( nTmp ) );
458 bModified = true;
461 if (m_xMtrAngle->get_value_changed_from_saved())
463 sal_Int32 nValue = static_cast<sal_Int32>(m_xMtrAngle->get_value(FieldUnit::NONE));
464 rAttrs->Put( SfxInt32Item( SID_ATTR_TRANSFORM_SHEAR, nValue ) );
465 bModified = true;
468 if( bModified )
470 // set reference points
471 ::tools::Rectangle aObjectRect(pView->GetAllMarkedRect());
472 pView->GetSdrPageView()->LogicToPagePos(aObjectRect);
473 Point aPt = aObjectRect.Center();
475 rAttrs->Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_X, aPt.X()));
476 rAttrs->Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_Y, aPt.Y()));
477 rAttrs->Put( SfxBoolItem( SID_ATTR_TRANSFORM_SHEAR_VERTICAL, false ) );
480 bool bControlPointsChanged = false;
481 for (int i = 0; i < 2; ++i)
483 bControlPointsChanged |= (m_aControlX[i]->get_value_changed_from_saved() ||
484 m_aControlY[i]->get_value_changed_from_saved());
487 if (!bControlPointsChanged)
488 return bModified;
490 bool bSelectionIsSdrObjCustomShape(false);
492 while(true)
494 if(nullptr == pView)
496 break;
499 if(0 == pView->GetMarkedObjectList().GetMarkCount())
501 break;
504 SdrObject* pCandidate(pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj());
506 if(nullptr == pCandidate)
508 break;
511 if(nullptr == dynamic_cast< SdrObjCustomShape* >(pCandidate))
513 break;
516 bSelectionIsSdrObjCustomShape = true;
517 break;
520 if(bSelectionIsSdrObjCustomShape)
522 SdrObjCustomShape& rSdrObjCustomShape(
523 static_cast< SdrObjCustomShape& >(
524 *pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj()));
525 SdrModel& rModel(rSdrObjCustomShape.getSdrModelFromSdrObject());
526 std::unique_ptr<SdrUndoAction> pUndo;
527 if (rModel.IsUndoEnabled())
528 pUndo = rModel.GetSdrUndoFactory().CreateUndoAttrObject(rSdrObjCustomShape);
530 if(pUndo)
532 rModel.BegUndo(pUndo->GetComment());
535 EnhancedCustomShape2d aShape(rSdrObjCustomShape);
536 ::tools::Rectangle aLogicRect = aShape.GetLogicRect();
538 for (int i = 0; i < 2; ++i)
540 if (m_aControlX[i]->get_value_changed_from_saved() || m_aControlY[i]->get_value_changed_from_saved())
542 Point aNewPosition(GetCoreValue(*m_aControlX[i], ePoolUnit),
543 GetCoreValue(*m_aControlY[i], ePoolUnit));
544 aNewPosition.Move(aLogicRect.Left(), aLogicRect.Top());
546 css::awt::Point aPosition;
547 aPosition.X = aNewPosition.X();
548 aPosition.Y = aNewPosition.Y();
550 aShape.SetHandleControllerPosition(i, aPosition);
554 rSdrObjCustomShape.SetChanged();
555 rSdrObjCustomShape.BroadcastObjectChange();
556 bModified = true;
558 if (pUndo)
560 rModel.AddUndo(std::move(pUndo));
561 rModel.EndUndo();
565 return bModified;
568 void SvxSlantTabPage::Reset(const SfxItemSet* rAttrs)
570 // if the view has selected objects, items with SfxItemState::DEFAULT need to be disabled
571 const SfxPoolItem* pItem;
573 // corner radius
574 if(!pView->IsEdgeRadiusAllowed())
576 m_xMtrRadius->set_text("");
577 m_xFlRadius->set_sensitive(false);
579 else
581 pItem = GetItem( *rAttrs, SDRATTR_ECKENRADIUS );
583 if( pItem )
585 const double fUIScale(double(pView->GetModel()->GetUIScale()));
586 const double fTmp(static_cast<double>(static_cast<const SdrMetricItem*>(pItem)->GetValue()) / fUIScale);
587 SetMetricValue(*m_xMtrRadius, basegfx::fround(fTmp), ePoolUnit);
589 else
591 m_xMtrRadius->set_text("");
595 m_xMtrRadius->save_value();
597 // slant: angle
598 if( !pView->IsShearAllowed() )
600 m_xMtrAngle->set_text( "" );
601 m_xFlAngle->set_sensitive(false);
603 else
605 pItem = GetItem( *rAttrs, SID_ATTR_TRANSFORM_SHEAR );
607 if( pItem )
609 m_xMtrAngle->set_value(static_cast<const SfxInt32Item*>(pItem)->GetValue(), FieldUnit::NONE);
611 else
613 m_xMtrAngle->set_text("");
617 m_xMtrAngle->save_value();
619 bool bSelectionIsSdrObjCustomShape(false);
621 while(true)
623 if(1 != pView->GetMarkedObjectList().GetMarkCount())
625 break;
628 SdrObject* pCandidate(pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj());
630 if(nullptr == pCandidate)
632 break;
635 if(nullptr == dynamic_cast< SdrObjCustomShape* >(pCandidate))
637 break;
640 bSelectionIsSdrObjCustomShape = true;
641 break;
644 if(bSelectionIsSdrObjCustomShape)
646 SdrObjCustomShape& rSdrObjCustomShape(
647 static_cast< SdrObjCustomShape& >(
648 *pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj()));
650 //save geometry
651 SdrCustomShapeGeometryItem aInitialGeometry(rSdrObjCustomShape.GetMergedItem(SDRATTR_CUSTOMSHAPE_GEOMETRY));
652 EnhancedCustomShape2d aShape(rSdrObjCustomShape);
654 for (int i = 0; i < 2; ++i)
656 Point aInitialPosition;
657 if (!aShape.GetHandlePosition(i, aInitialPosition))
658 break;
659 m_aControlGroups[i]->set_sensitive(true);
660 css::awt::Point aPosition;
662 aPosition.X = SAL_MAX_INT32/2;
663 aPosition.Y = SAL_MAX_INT32/2;
664 aShape.SetHandleControllerPosition(i, aPosition);
665 Point aMaxPosition;
666 aShape.GetHandlePosition(i, aMaxPosition);
668 aPosition.X = SAL_MIN_INT32/2;
669 aPosition.Y = SAL_MIN_INT32/2;
670 aShape.SetHandleControllerPosition(i, aPosition);
671 Point aMinPosition;
672 aShape.GetHandlePosition(i, aMinPosition);
674 ::tools::Rectangle aLogicRect = aShape.GetLogicRect();
675 aInitialPosition.Move(-aLogicRect.Left(), -aLogicRect.Top());
676 aMaxPosition.Move(-aLogicRect.Left(), -aLogicRect.Top());
677 aMinPosition.Move(-aLogicRect.Left(), -aLogicRect.Top());
679 SetMetricValue(*m_aControlX[i], aInitialPosition.X(), ePoolUnit);
680 SetMetricValue(*m_aControlY[i], aInitialPosition.Y(), ePoolUnit);
682 if (aMaxPosition.X() == aMinPosition.X())
683 m_aControlGroupX[i]->set_sensitive(false);
684 else
685 m_aControlX[i]->set_range(aMinPosition.X(), aMaxPosition.X(), FieldUnit::MM);
686 if (aMaxPosition.Y() == aMinPosition.Y())
687 m_aControlGroupY[i]->set_sensitive(false);
688 else
689 m_aControlY[i]->set_range(aMinPosition.Y(), aMaxPosition.Y(), FieldUnit::MM);
692 //restore geometry
693 rSdrObjCustomShape.SetMergedItem(aInitialGeometry);
696 for (int i = 0; i < 2; ++i)
698 m_aControlX[i]->save_value();
699 m_aControlY[i]->save_value();
703 std::unique_ptr<SfxTabPage> SvxSlantTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs)
705 return std::make_unique<SvxSlantTabPage>(pPage, pController, *rOutAttrs);
708 void SvxSlantTabPage::ActivatePage( const SfxItemSet& rSet )
710 SfxBoolItem const * bPosProtect = nullptr;
711 if(SfxItemState::SET == rSet.GetItemState( GetWhich(SID_ATTR_TRANSFORM_PROTECT_POS ) , false, reinterpret_cast<SfxPoolItem const **>(&bPosProtect) ))
713 m_xFlAngle->set_sensitive(!bPosProtect->GetValue());
715 SfxBoolItem const * bSizeProtect = nullptr;
716 if(SfxItemState::SET == rSet.GetItemState( GetWhich(SID_ATTR_TRANSFORM_PROTECT_SIZE ) , false, reinterpret_cast<SfxPoolItem const **>(&bSizeProtect) ))
718 m_xFlAngle->set_sensitive(!bSizeProtect->GetValue());
723 DeactivateRC SvxSlantTabPage::DeactivatePage( SfxItemSet* _pSet )
725 if(_pSet)
727 FillItemSet(_pSet);
730 return DeactivateRC::LeavePage;
734 /*************************************************************************
736 |* Dialog for changing position and size of graphic objects
738 \************************************************************************/
739 SvxPositionSizeTabPage::SvxPositionSizeTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
740 : SvxTabPage(pPage, pController, "cui/ui/possizetabpage.ui", "PositionAndSize", rInAttrs)
741 , mrOutAttrs(rInAttrs)
742 , mpView(nullptr)
743 , meDlgUnit(FieldUnit::NONE)
744 , mnProtectSizeState(TRISTATE_FALSE)
745 , mbPageDisabled(false)
746 , mbProtectDisabled(false)
747 , mbSizeDisabled(false)
748 , mbAdjustDisabled(true)
749 , mbIgnoreAutoGrowWidth(true)
750 , mbIgnoreAutoGrowHeight(true)
751 , mfOldWidth(0.0)
752 , mfOldHeight(0.0)
753 , m_aCtlPos(this)
754 , m_aCtlSize(this)
755 , m_xFlPosition(m_xBuilder->weld_widget("FL_POSITION"))
756 , m_xMtrPosX(m_xBuilder->weld_metric_spin_button("MTR_FLD_POS_X", FieldUnit::CM))
757 , m_xMtrPosY(m_xBuilder->weld_metric_spin_button("MTR_FLD_POS_Y", FieldUnit::CM))
758 , m_xCtlPos(new weld::CustomWeld(*m_xBuilder, "CTL_POSRECT", m_aCtlPos))
759 , m_xFlSize(m_xBuilder->weld_widget("FL_SIZE"))
760 , m_xFtWidth(m_xBuilder->weld_label("FT_WIDTH"))
761 , m_xMtrWidth(m_xBuilder->weld_metric_spin_button("MTR_FLD_WIDTH", FieldUnit::CM))
762 , m_xFtHeight(m_xBuilder->weld_label("FT_HEIGHT"))
763 , m_xMtrHeight(m_xBuilder->weld_metric_spin_button("MTR_FLD_HEIGHT", FieldUnit::CM))
764 , m_xCbxScale(m_xBuilder->weld_check_button("CBX_SCALE"))
765 , m_xCtlSize(new weld::CustomWeld(*m_xBuilder, "CTL_SIZERECT", m_aCtlSize))
766 , m_xFlProtect(m_xBuilder->weld_widget("FL_PROTECT"))
767 , m_xTsbPosProtect(m_xBuilder->weld_check_button("TSB_POSPROTECT"))
768 , m_xTsbSizeProtect(m_xBuilder->weld_check_button("TSB_SIZEPROTECT"))
769 , m_xFlAdjust(m_xBuilder->weld_widget("FL_ADJUST"))
770 , m_xTsbAutoGrowWidth(m_xBuilder->weld_check_button("TSB_AUTOGROW_WIDTH"))
771 , m_xTsbAutoGrowHeight(m_xBuilder->weld_check_button("TSB_AUTOGROW_HEIGHT"))
773 // this page needs ExchangeSupport
774 SetExchangeSupport();
776 // evaluate PoolUnit
777 SfxItemPool* pPool = mrOutAttrs.GetPool();
778 DBG_ASSERT( pPool, "no pool (!)" );
779 mePoolUnit = pPool->GetMetric( SID_ATTR_TRANSFORM_POS_X );
781 m_aCtlPos.SetActualRP(RectPoint::LT);
782 m_aCtlSize.SetActualRP(RectPoint::LT);
783 meRP = RectPoint::LT; // see above
785 m_xMtrWidth->connect_value_changed( LINK( this, SvxPositionSizeTabPage, ChangeWidthHdl ) );
786 m_xMtrHeight->connect_value_changed( LINK( this, SvxPositionSizeTabPage, ChangeHeightHdl ) );
787 m_xCbxScale->connect_toggled( LINK( this, SvxPositionSizeTabPage, ClickAutoHdl ) );
789 m_xFlAdjust->set_sensitive(false);
791 // #i2379# disable controls when protected
792 m_xTsbPosProtect->connect_toggled( LINK( this, SvxPositionSizeTabPage, ChangePosProtectHdl ) );
793 m_xTsbSizeProtect->connect_toggled( LINK( this, SvxPositionSizeTabPage, ChangeSizeProtectHdl ) );
796 SvxPositionSizeTabPage::~SvxPositionSizeTabPage()
800 void SvxPositionSizeTabPage::Construct()
802 // get range and work area
803 DBG_ASSERT( mpView, "no valid view (!)" );
804 meDlgUnit = GetModuleFieldUnit( GetItemSet() );
805 SetFieldUnit( *m_xMtrPosX, meDlgUnit, true );
806 SetFieldUnit( *m_xMtrPosY, meDlgUnit, true );
807 SetFieldUnit( *m_xMtrWidth, meDlgUnit, true );
808 SetFieldUnit( *m_xMtrHeight, meDlgUnit, true );
810 if(FieldUnit::MILE == meDlgUnit || FieldUnit::KM == meDlgUnit)
812 m_xMtrPosX->set_digits( 3 );
813 m_xMtrPosY->set_digits( 3 );
814 m_xMtrWidth->set_digits( 3 );
815 m_xMtrHeight->set_digits( 3 );
818 { // #i75273#
819 ::tools::Rectangle aTempRect(mpView->GetAllMarkedRect());
820 mpView->GetSdrPageView()->LogicToPagePos(aTempRect);
821 maRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect);
824 { // #i75273#
825 ::tools::Rectangle aTempRect(mpView->GetWorkArea());
826 mpView->GetSdrPageView()->LogicToPagePos(aTempRect);
827 maWorkRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect);
830 // take anchor into account (Writer)
831 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
833 if(rMarkList.GetMarkCount())
835 const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
836 maAnchor = basegfx::B2DPoint(pObj->GetAnchorPos().X(), pObj->GetAnchorPos().Y());
838 if(!maAnchor.equalZero()) // -> Writer
840 for(size_t i = 1; i < rMarkList.GetMarkCount(); ++i)
842 pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
844 if(maAnchor != basegfx::B2DPoint(pObj->GetAnchorPos().X(), pObj->GetAnchorPos().Y()))
846 // different anchor positions
847 m_xMtrPosX->set_text("");
848 m_xMtrPosY->set_text("");
849 mbPageDisabled = true;
850 return;
854 // translate ranges about anchor
855 maRange = basegfx::B2DRange(maRange.getMinimum() - maAnchor, maRange.getMaximum() - maAnchor);
856 maWorkRange = basegfx::B2DRange(maWorkRange.getMinimum() - maAnchor, maWorkRange.getMaximum() - maAnchor);
860 // this should happen via SID_ATTR_TRANSFORM_AUTOSIZE
861 if(1 == rMarkList.GetMarkCount())
863 const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
864 const SdrObjKind eKind(static_cast<SdrObjKind>(pObj->GetObjIdentifier()));
866 if((pObj->GetObjInventor() == SdrInventor::Default) &&
867 (OBJ_TEXT == eKind || OBJ_TITLETEXT == eKind || OBJ_OUTLINETEXT == eKind) &&
868 pObj->HasText())
870 mbAdjustDisabled = false;
872 m_xFlAdjust->set_sensitive(true);
874 m_xTsbAutoGrowWidth->connect_toggled( LINK( this, SvxPositionSizeTabPage, ClickSizeProtectHdl ) );
875 m_xTsbAutoGrowHeight->connect_toggled( LINK( this, SvxPositionSizeTabPage, ClickSizeProtectHdl ) );
877 // is used as flag to evaluate if its selectable
878 mbIgnoreAutoGrowWidth = false;
879 mbIgnoreAutoGrowHeight = false;
883 // take scale into account
884 const Fraction aUIScale(mpView->GetModel()->GetUIScale());
885 TransfrmHelper::ScaleRect( maWorkRange, aUIScale );
886 TransfrmHelper::ScaleRect( maRange, aUIScale );
888 // take UI units into account
889 const sal_uInt16 nDigits(m_xMtrPosX->get_digits());
890 TransfrmHelper::ConvertRect( maWorkRange, nDigits, mePoolUnit, meDlgUnit );
891 TransfrmHelper::ConvertRect( maRange, nDigits, mePoolUnit, meDlgUnit );
893 SetMinMaxPosition();
897 bool SvxPositionSizeTabPage::FillItemSet( SfxItemSet* rOutAttrs )
899 bool bModified(false);
901 if ( m_xMtrWidth->has_focus() )
903 ChangeWidthHdl( *m_xMtrWidth );
906 if ( m_xMtrHeight->has_focus() )
908 ChangeHeightHdl( *m_xMtrHeight );
911 if( !mbPageDisabled )
913 if (m_xMtrPosX->get_value_changed_from_saved() || m_xMtrPosY->get_value_changed_from_saved())
915 const double fUIScale(double(mpView->GetModel()->GetUIScale()));
916 double fX((GetCoreValue( *m_xMtrPosX, mePoolUnit ) + maAnchor.getX()) * fUIScale);
917 double fY((GetCoreValue( *m_xMtrPosY, mePoolUnit ) + maAnchor.getY()) * fUIScale);
919 { // #i75273#
920 ::tools::Rectangle aTempRect(mpView->GetAllMarkedRect());
921 mpView->GetSdrPageView()->LogicToPagePos(aTempRect);
922 maRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect);
925 // #101581# GetTopLeftPosition(...) needs coordinates after UI scaling, in real PagePositions
926 GetTopLeftPosition(fX, fY, maRange);
928 rOutAttrs->Put(SfxInt32Item(GetWhich(SID_ATTR_TRANSFORM_POS_X), basegfx::fround(fX)));
929 rOutAttrs->Put(SfxInt32Item(GetWhich(SID_ATTR_TRANSFORM_POS_Y), basegfx::fround(fY)));
931 bModified = true;
934 if (m_xTsbPosProtect->get_state_changed_from_saved())
936 if( m_xTsbPosProtect->get_inconsistent() )
938 rOutAttrs->InvalidateItem( SID_ATTR_TRANSFORM_PROTECT_POS );
940 else
942 rOutAttrs->Put(
943 SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_PROTECT_POS ),
944 m_xTsbPosProtect->get_active() ) );
947 bModified = true;
951 if (m_xMtrWidth->get_value_changed_from_saved() || m_xMtrHeight->get_value_changed_from_saved())
953 Fraction aUIScale = mpView->GetModel()->GetUIScale();
955 // get Width
956 double nWidth = static_cast<double>(m_xMtrWidth->get_value(FieldUnit::MM_100TH));
957 long lWidth = long(nWidth * static_cast<double>(aUIScale));
958 lWidth = OutputDevice::LogicToLogic( lWidth, MapUnit::Map100thMM, mePoolUnit );
959 lWidth = static_cast<long>(m_xMtrWidth->denormalize( lWidth ));
961 // get Height
962 double nHeight = static_cast<double>(m_xMtrHeight->get_value(FieldUnit::MM_100TH));
963 long lHeight = long(nHeight * static_cast<double>(aUIScale));
964 lHeight = OutputDevice::LogicToLogic( lHeight, MapUnit::Map100thMM, mePoolUnit );
965 lHeight = static_cast<long>(m_xMtrHeight->denormalize( lHeight ));
967 // put Width & Height to itemset
968 rOutAttrs->Put( SfxUInt32Item( GetWhich( SID_ATTR_TRANSFORM_WIDTH ), static_cast<sal_uInt32>(lWidth) ) );
969 rOutAttrs->Put( SfxUInt32Item( GetWhich( SID_ATTR_TRANSFORM_HEIGHT ), static_cast<sal_uInt32>(lHeight) ) );
970 rOutAttrs->Put( SfxUInt16Item( GetWhich( SID_ATTR_TRANSFORM_SIZE_POINT ), sal::static_int_cast< sal_uInt16 >( meRP ) ) );
971 bModified = true;
974 if (m_xTsbSizeProtect->get_state_changed_from_saved())
976 if ( m_xTsbSizeProtect->get_inconsistent() )
977 rOutAttrs->InvalidateItem( SID_ATTR_TRANSFORM_PROTECT_SIZE );
978 else
979 rOutAttrs->Put(
980 SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_PROTECT_SIZE ),
981 m_xTsbSizeProtect->get_active() ) );
982 bModified = true;
985 if (m_xTsbAutoGrowWidth->get_state_changed_from_saved())
987 if (!mbIgnoreAutoGrowWidth)
989 if( m_xTsbAutoGrowWidth->get_inconsistent() )
990 rOutAttrs->InvalidateItem( SID_ATTR_TRANSFORM_AUTOWIDTH );
991 else
992 rOutAttrs->Put(
993 SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_AUTOWIDTH ),
994 m_xTsbAutoGrowWidth->get_active() ) );
996 bModified = true;
999 if (m_xTsbAutoGrowHeight->get_state_changed_from_saved())
1001 if (!mbIgnoreAutoGrowHeight)
1003 if (m_xTsbAutoGrowHeight->get_inconsistent())
1005 rOutAttrs->InvalidateItem( SID_ATTR_TRANSFORM_AUTOHEIGHT );
1007 else
1009 rOutAttrs->Put(
1010 SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_AUTOHEIGHT ),
1011 m_xTsbAutoGrowHeight->get_active() ) );
1014 bModified = true;
1017 return bModified;
1020 void SvxPositionSizeTabPage::Reset( const SfxItemSet* )
1022 const SfxPoolItem* pItem;
1023 const double fUIScale(double(mpView->GetModel()->GetUIScale()));
1025 if ( !mbPageDisabled )
1027 pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_POS_X );
1028 if ( pItem )
1030 const double fTmp((static_cast<const SfxInt32Item*>(pItem)->GetValue() - maAnchor.getX()) / fUIScale);
1031 SetMetricValue(*m_xMtrPosX, basegfx::fround(fTmp), mePoolUnit);
1034 pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_POS_Y );
1035 if ( pItem )
1037 const double fTmp((static_cast<const SfxInt32Item*>(pItem)->GetValue() - maAnchor.getY()) / fUIScale);
1038 SetMetricValue(*m_xMtrPosY, basegfx::fround(fTmp), mePoolUnit);
1041 pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_PROTECT_POS );
1042 if ( pItem )
1044 bool bProtected = static_cast<const SfxBoolItem*>( pItem )->GetValue();
1045 m_xTsbPosProtect->set_active(bProtected);
1047 else
1049 m_xTsbPosProtect->set_inconsistent(true);
1052 m_xTsbPosProtect->save_state();
1053 m_aCtlPos.Reset();
1055 // #i2379# Disable controls for protected objects
1056 ChangePosProtectHdl(*m_xTsbPosProtect);
1059 { // #i75273# set width
1060 pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_WIDTH );
1061 mfOldWidth = std::max( pItem ? static_cast<double>(static_cast<const SfxUInt32Item*>(pItem)->GetValue()) : 0.0, 1.0 );
1062 double fTmpWidth((OutputDevice::LogicToLogic(static_cast<sal_Int32>(mfOldWidth), mePoolUnit, MapUnit::Map100thMM)) / fUIScale);
1063 if (m_xMtrWidth->get_digits())
1064 fTmpWidth *= pow(10.0, m_xMtrWidth->get_digits());
1065 m_xMtrWidth->set_value(static_cast<int>(fTmpWidth), FieldUnit::MM_100TH);
1068 { // #i75273# set height
1069 pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_HEIGHT );
1070 mfOldHeight = std::max( pItem ? static_cast<double>(static_cast<const SfxUInt32Item*>(pItem)->GetValue()) : 0.0, 1.0 );
1071 double fTmpHeight((OutputDevice::LogicToLogic(static_cast<sal_Int32>(mfOldHeight), mePoolUnit, MapUnit::Map100thMM)) / fUIScale);
1072 if (m_xMtrHeight->get_digits())
1073 fTmpHeight *= pow(10.0, m_xMtrHeight->get_digits());
1074 m_xMtrHeight->set_value(static_cast<int>(fTmpHeight), FieldUnit::MM_100TH);
1077 pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_PROTECT_SIZE );
1078 if ( pItem )
1080 m_xTsbSizeProtect->set_active(static_cast<const SfxBoolItem*>(pItem)->GetValue());
1082 else
1083 m_xTsbSizeProtect->set_inconsistent(true);
1085 pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_AUTOWIDTH );
1086 if ( pItem )
1088 m_xTsbAutoGrowWidth->set_active(static_cast<const SfxBoolItem*>( pItem )->GetValue());
1090 else
1091 m_xTsbAutoGrowWidth->set_inconsistent(true);
1093 pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_AUTOHEIGHT );
1094 if ( pItem )
1096 m_xTsbAutoGrowHeight->set_active(static_cast<const SfxBoolItem*>( pItem )->GetValue());
1098 else
1099 m_xTsbAutoGrowHeight->set_inconsistent(true);
1101 // Is matching set?
1102 OUString aStr = GetUserData();
1103 m_xCbxScale->set_active(aStr.toInt32() != 0);
1105 m_xMtrPosX->save_value();
1106 m_xMtrPosY->save_value();
1107 m_xMtrWidth->save_value();
1108 m_xMtrHeight->save_value();
1110 m_xTsbSizeProtect->save_state();
1111 m_xTsbAutoGrowWidth->save_state();
1112 m_xTsbAutoGrowHeight->save_state();
1113 ClickSizeProtectHdl(*m_xTsbAutoGrowHeight);
1115 // #i2379# Disable controls for protected objects
1116 ChangeSizeProtectHdl(*m_xTsbSizeProtect);
1119 std::unique_ptr<SfxTabPage> SvxPositionSizeTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs)
1121 return std::make_unique<SvxPositionSizeTabPage>(pPage, pController, *rOutAttrs);
1124 void SvxPositionSizeTabPage::ActivatePage( const SfxItemSet& rSet )
1126 SfxRectangleItem const * pRectItem = nullptr;
1128 if( SfxItemState::SET == rSet.GetItemState( GetWhich( SID_ATTR_TRANSFORM_INTERN ) , false, reinterpret_cast<SfxPoolItem const **>(&pRectItem) ) )
1130 { // #i75273#
1131 const ::tools::Rectangle aTempRect(pRectItem->GetValue());
1132 maRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect);
1135 SetMinMaxPosition();
1140 DeactivateRC SvxPositionSizeTabPage::DeactivatePage( SfxItemSet* _pSet )
1142 if( _pSet )
1144 double fX(static_cast<double>(m_xMtrPosX->get_value(FieldUnit::NONE)));
1145 double fY(static_cast<double>(m_xMtrPosY->get_value(FieldUnit::NONE)));
1147 GetTopLeftPosition(fX, fY, maRange);
1148 const ::tools::Rectangle aOutRectangle(
1149 basegfx::fround(fX), basegfx::fround(fY),
1150 basegfx::fround(fX + maRange.getWidth()), basegfx::fround(fY + maRange.getHeight()));
1151 _pSet->Put(SfxRectangleItem(SID_ATTR_TRANSFORM_INTERN, aOutRectangle));
1152 _pSet->Put(SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_PROTECT_POS ),
1153 m_xTsbPosProtect->get_state() == TRISTATE_TRUE ));
1154 _pSet->Put(SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_PROTECT_SIZE ),
1155 m_xTsbSizeProtect->get_state() == TRISTATE_TRUE ));
1156 FillItemSet(_pSet);
1159 return DeactivateRC::LeavePage;
1163 IMPL_LINK_NOARG(SvxPositionSizeTabPage, ChangePosProtectHdl, weld::ToggleButton&, void)
1165 // #106572# Remember user's last choice
1166 m_xTsbSizeProtect->set_state(m_xTsbPosProtect->get_state() == TRISTATE_TRUE ? TRISTATE_TRUE : mnProtectSizeState);
1167 UpdateControlStates();
1171 void SvxPositionSizeTabPage::UpdateControlStates()
1173 const bool bPosProtect = m_xTsbPosProtect->get_state() == TRISTATE_TRUE;
1174 const bool bSizeProtect = m_xTsbSizeProtect->get_state() == TRISTATE_TRUE;
1175 const bool bHeightChecked = !mbIgnoreAutoGrowHeight && (m_xTsbAutoGrowHeight->get_active());
1176 const bool bWidthChecked = !mbIgnoreAutoGrowWidth && (m_xTsbAutoGrowWidth->get_active());
1178 m_xFlPosition->set_sensitive(!bPosProtect && !mbPageDisabled);
1180 m_xTsbPosProtect->set_sensitive( !mbProtectDisabled && !mbPageDisabled );
1182 m_xFlSize->set_sensitive( !mbSizeDisabled && !bSizeProtect );
1184 m_xFtWidth->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bWidthChecked );
1185 m_xMtrWidth->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bWidthChecked );
1187 m_xFtHeight->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bHeightChecked );
1188 m_xMtrHeight->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bHeightChecked );
1190 m_xCbxScale->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bHeightChecked && !bWidthChecked );
1191 m_xCtlSize->set_sensitive( !mbSizeDisabled && !bSizeProtect && (!bHeightChecked || !bWidthChecked) );
1193 m_xFlProtect->set_sensitive( !mbProtectDisabled );
1194 m_xTsbSizeProtect->set_sensitive( !mbProtectDisabled && !bPosProtect );
1196 m_xFlAdjust->set_sensitive( !mbSizeDisabled && !bSizeProtect && !mbAdjustDisabled );
1198 m_aCtlSize.Invalidate();
1199 m_aCtlPos.Invalidate();
1202 IMPL_LINK_NOARG(SvxPositionSizeTabPage, ChangeSizeProtectHdl, weld::ToggleButton&, void)
1204 if (m_xTsbSizeProtect->get_sensitive())
1206 // #106572# Remember user's last choice
1208 // Note: this works only as long as the dialog is open. When
1209 // the user closes the dialog, there is no way to remember
1210 // whether size was enabled or disabled before pos protect was
1211 // clicked. Thus, if pos protect is selected, the dialog is
1212 // closed and reopened again, unchecking pos protect will
1213 // always uncheck size protect, too. That's life.
1214 mnProtectSizeState = m_xTsbSizeProtect->get_state();
1217 UpdateControlStates();
1220 void SvxPositionSizeTabPage::SetMinMaxPosition()
1222 // position
1223 double fLeft(maWorkRange.getMinX());
1224 double fTop(maWorkRange.getMinY());
1225 double fRight(maWorkRange.getMaxX());
1226 double fBottom(maWorkRange.getMaxY());
1228 switch (m_aCtlPos.GetActualRP())
1230 case RectPoint::LT:
1232 fRight -= maRange.getWidth();
1233 fBottom -= maRange.getHeight();
1234 break;
1236 case RectPoint::MT:
1238 fLeft += maRange.getWidth() / 2.0;
1239 fRight -= maRange.getWidth() / 2.0;
1240 fBottom -= maRange.getHeight();
1241 break;
1243 case RectPoint::RT:
1245 fLeft += maRange.getWidth();
1246 fBottom -= maRange.getHeight();
1247 break;
1249 case RectPoint::LM:
1251 fRight -= maRange.getWidth();
1252 fTop += maRange.getHeight() / 2.0;
1253 fBottom -= maRange.getHeight() / 2.0;
1254 break;
1256 case RectPoint::MM:
1258 fLeft += maRange.getWidth() / 2.0;
1259 fRight -= maRange.getWidth() / 2.0;
1260 fTop += maRange.getHeight() / 2.0;
1261 fBottom -= maRange.getHeight() / 2.0;
1262 break;
1264 case RectPoint::RM:
1266 fLeft += maRange.getWidth();
1267 fTop += maRange.getHeight() / 2.0;
1268 fBottom -= maRange.getHeight() / 2.0;
1269 break;
1271 case RectPoint::LB:
1273 fRight -= maRange.getWidth();
1274 fTop += maRange.getHeight();
1275 break;
1277 case RectPoint::MB:
1279 fLeft += maRange.getWidth() / 2.0;
1280 fRight -= maRange.getWidth() / 2.0;
1281 fTop += maRange.getHeight();
1282 break;
1284 case RectPoint::RB:
1286 fLeft += maRange.getWidth();
1287 fTop += maRange.getHeight();
1288 break;
1292 const double fMaxLong(static_cast<double>(MetricField::ConvertValue( LONG_MAX, 0, MapUnit::Map100thMM, meDlgUnit ) - 1));
1293 fLeft = std::clamp(fLeft, -fMaxLong, fMaxLong);
1294 fRight = std::clamp(fRight, -fMaxLong, fMaxLong);
1295 fTop = std::clamp(fTop, - fMaxLong, fMaxLong);
1296 fBottom = std::clamp(fBottom, -fMaxLong, fMaxLong);
1298 // #i75273# normalizing when setting the min/max values was wrong, removed
1299 m_xMtrPosX->set_range(basegfx::fround64(fLeft), basegfx::fround64(fRight), FieldUnit::NONE);
1300 m_xMtrPosY->set_range(basegfx::fround64(fTop), basegfx::fround64(fBottom), FieldUnit::NONE);
1302 // size
1303 fLeft = maWorkRange.getMinX();
1304 fTop = maWorkRange.getMinY();
1305 fRight = maWorkRange.getMaxX();
1306 fBottom = maWorkRange.getMaxY();
1307 double fNewX(0);
1308 double fNewY(0);
1310 switch (m_aCtlSize.GetActualRP())
1312 case RectPoint::LT:
1314 fNewX = maWorkRange.getWidth() - ( maRange.getMinX() - fLeft );
1315 fNewY = maWorkRange.getHeight() - ( maRange.getMinY() - fTop );
1316 break;
1318 case RectPoint::MT:
1320 fNewX = std::min( maRange.getCenter().getX() - fLeft, fRight - maRange.getCenter().getX() ) * 2.0;
1321 fNewY = maWorkRange.getHeight() - ( maRange.getMinY() - fTop );
1322 break;
1324 case RectPoint::RT:
1326 fNewX = maWorkRange.getWidth() - ( fRight - maRange.getMaxX() );
1327 fNewY = maWorkRange.getHeight() - ( maRange.getMinY() - fTop );
1328 break;
1330 case RectPoint::LM:
1332 fNewX = maWorkRange.getWidth() - ( maRange.getMinX() - fLeft );
1333 fNewY = std::min( maRange.getCenter().getY() - fTop, fBottom - maRange.getCenter().getY() ) * 2.0;
1334 break;
1336 case RectPoint::MM:
1338 const double f1(maRange.getCenter().getX() - fLeft);
1339 const double f2(fRight - maRange.getCenter().getX());
1340 const double f3(std::min(f1, f2));
1341 const double f4(maRange.getCenter().getY() - fTop);
1342 const double f5(fBottom - maRange.getCenter().getY());
1343 const double f6(std::min(f4, f5));
1345 fNewX = f3 * 2.0;
1346 fNewY = f6 * 3.0;
1348 break;
1350 case RectPoint::RM:
1352 fNewX = maWorkRange.getWidth() - ( fRight - maRange.getMaxX() );
1353 fNewY = std::min( maRange.getCenter().getY() - fTop, fBottom - maRange.getCenter().getY() ) * 2.0;
1354 break;
1356 case RectPoint::LB:
1358 fNewX = maWorkRange.getWidth() - ( maRange.getMinX() - fLeft );
1359 fNewY = maWorkRange.getHeight() - ( fBottom - maRange.getMaxY() );
1360 break;
1362 case RectPoint::MB:
1364 fNewX = std::min( maRange.getCenter().getX() - fLeft, fRight - maRange.getCenter().getX() ) * 2.0;
1365 fNewY = maWorkRange.getHeight() - ( maRange.getMaxY() - fBottom );
1366 break;
1368 case RectPoint::RB:
1370 fNewX = maWorkRange.getWidth() - ( fRight - maRange.getMaxX() );
1371 fNewY = maWorkRange.getHeight() - ( fBottom - maRange.getMaxY() );
1372 break;
1376 // #i75273# normalizing when setting the min/max values was wrong, removed
1377 m_xMtrWidth->set_max(basegfx::fround64(fNewX), FieldUnit::NONE);
1378 m_xMtrHeight->set_max(basegfx::fround64(fNewY), FieldUnit::NONE);
1381 void SvxPositionSizeTabPage::GetTopLeftPosition(double& rfX, double& rfY, const basegfx::B2DRange& rRange)
1383 switch (m_aCtlPos.GetActualRP())
1385 case RectPoint::LT:
1387 break;
1389 case RectPoint::MT:
1391 rfX -= rRange.getCenter().getX() - rRange.getMinX();
1392 break;
1394 case RectPoint::RT:
1396 rfX -= rRange.getWidth();
1397 break;
1399 case RectPoint::LM:
1401 rfY -= rRange.getCenter().getY() - rRange.getMinY();
1402 break;
1404 case RectPoint::MM:
1406 rfX -= rRange.getCenter().getX() - rRange.getMinX();
1407 rfY -= rRange.getCenter().getY() - rRange.getMinY();
1408 break;
1410 case RectPoint::RM:
1412 rfX -= rRange.getWidth();
1413 rfY -= rRange.getCenter().getY() - rRange.getMinY();
1414 break;
1416 case RectPoint::LB:
1418 rfY -= rRange.getHeight();
1419 break;
1421 case RectPoint::MB:
1423 rfX -= rRange.getCenter().getX() - rRange.getMinX();
1424 rfY -= rRange.getHeight();
1425 break;
1427 case RectPoint::RB:
1429 rfX -= rRange.getWidth();
1430 rfY -= rRange.getHeight();
1431 break;
1436 void SvxPositionSizeTabPage::PointChanged(weld::DrawingArea* pDrawingArea, RectPoint eRP)
1438 if (pDrawingArea == m_aCtlPos.GetDrawingArea())
1440 SetMinMaxPosition();
1441 switch( eRP )
1443 case RectPoint::LT:
1445 m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE );
1446 m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE );
1447 break;
1449 case RectPoint::MT:
1451 m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE );
1452 m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE );
1453 break;
1455 case RectPoint::RT:
1457 m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE );
1458 m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE );
1459 break;
1461 case RectPoint::LM:
1463 m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE );
1464 m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE );
1465 break;
1467 case RectPoint::MM:
1469 m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE );
1470 m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE );
1471 break;
1473 case RectPoint::RM:
1475 m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE );
1476 m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE );
1477 break;
1479 case RectPoint::LB:
1481 m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE );
1482 m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE );
1483 break;
1485 case RectPoint::MB:
1487 m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE );
1488 m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE );
1489 break;
1491 case RectPoint::RB:
1493 m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE );
1494 m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE );
1495 break;
1499 else
1501 meRP = eRP;
1502 SetMinMaxPosition();
1506 void SvxPositionSizeTabPage::DisableResize()
1508 mbSizeDisabled = true;
1512 void SvxPositionSizeTabPage::DisableProtect()
1514 mbProtectDisabled = true;
1518 IMPL_LINK_NOARG(SvxPositionSizeTabPage, ChangeWidthHdl, weld::MetricSpinButton&, void)
1520 if( m_xCbxScale->get_active() && m_xCbxScale->get_sensitive() )
1522 sal_Int64 nHeight(basegfx::fround64((mfOldHeight * static_cast<double>(m_xMtrWidth->get_value(FieldUnit::NONE))) / mfOldWidth));
1523 int nMin, nMax;
1524 m_xMtrHeight->get_range(nMin, nMax, FieldUnit::NONE);
1526 if (nHeight <= nMax)
1528 m_xMtrHeight->set_value(nHeight, FieldUnit::NONE);
1530 else
1532 nHeight = nMax;
1533 m_xMtrHeight->set_value(nHeight, FieldUnit::NONE);
1535 const sal_Int64 nWidth(basegfx::fround64((mfOldWidth * static_cast<double>(nHeight)) / mfOldHeight));
1536 m_xMtrWidth->set_value(nWidth, FieldUnit::NONE);
1541 IMPL_LINK_NOARG(SvxPositionSizeTabPage, ChangeHeightHdl, weld::MetricSpinButton&, void)
1543 if( m_xCbxScale->get_active() && m_xCbxScale->get_sensitive() )
1545 sal_Int64 nWidth(basegfx::fround64((mfOldWidth * static_cast<double>(m_xMtrHeight->get_value(FieldUnit::NONE))) / mfOldHeight));
1546 int nMin, nMax;
1547 m_xMtrWidth->get_range(nMin, nMax, FieldUnit::NONE);
1549 if (nWidth <= nMax)
1551 m_xMtrWidth->set_value(nWidth, FieldUnit::NONE);
1553 else
1555 nWidth = nMax;
1556 m_xMtrWidth->set_value(nWidth, FieldUnit::NONE);
1558 const sal_Int64 nHeight(basegfx::fround64((mfOldHeight * static_cast<double>(nWidth)) / mfOldWidth));
1559 m_xMtrHeight->set_value(nHeight, FieldUnit::NONE);
1564 IMPL_LINK_NOARG(SvxPositionSizeTabPage, ClickSizeProtectHdl, weld::ToggleButton&, void)
1566 UpdateControlStates();
1569 IMPL_LINK_NOARG(SvxPositionSizeTabPage, ClickAutoHdl, weld::ToggleButton&, void)
1571 if (m_xCbxScale->get_active())
1573 mfOldWidth = std::max( static_cast<double>(GetCoreValue( *m_xMtrWidth, mePoolUnit )), 1.0 );
1574 mfOldHeight = std::max( static_cast<double>(GetCoreValue( *m_xMtrHeight, mePoolUnit )), 1.0 );
1578 void SvxPositionSizeTabPage::FillUserData()
1580 // matching is saved in the Ini-file
1581 OUString aStr = m_xCbxScale->get_active() ? OUString("1") : OUString("0");
1582 SetUserData( aStr );
1585 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */