LibreOffice Module svx (master)  1
PosSizePropertyPanel.cxx
Go to the documentation of this file.
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 
22 #include <algorithm>
23 
25 #include "PosSizePropertyPanel.hxx"
27 #include <svx/svxids.hrc>
28 #include <sfx2/dispatch.hxx>
29 #include <sfx2/bindings.hxx>
30 #include <sfx2/module.hxx>
31 #include <sfx2/viewsh.hxx>
32 #include <sfx2/objsh.hxx>
33 #include <sfx2/viewfrm.hxx>
34 #include <svx/dlgutil.hxx>
36 #include <unotools/viewoptions.hxx>
37 #include <vcl/button.hxx>
38 #include <vcl/canvastools.hxx>
39 #include <vcl/virdev.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/field.hxx>
42 #include <vcl/fixed.hxx>
43 #include <vcl/toolbox.hxx>
44 #include <svl/aeitem.hxx>
45 #include <svl/intitem.hxx>
46 #include <svx/svdpagv.hxx>
47 #include <svx/svdview.hxx>
48 #include <svx/transfrmhelper.hxx>
49 
50 #include <svtools/unitconv.hxx>
51 
52 using namespace css;
53 using namespace css::uno;
54 
55 const char USERITEM_NAME[] = "FitItem";
56 
57 namespace svx { namespace sidebar {
58 
59 PosSizePropertyPanel::PosSizePropertyPanel(
60  vcl::Window* pParent,
61  const css::uno::Reference<css::frame::XFrame>& rxFrame,
62  SfxBindings* pBindings,
63  const css::uno::Reference<css::ui::XSidebar>& rxSidebar)
64 : PanelLayout(pParent, "PosSizePropertyPanel", "svx/ui/sidebarpossize.ui", rxFrame),
65  maRect(),
66  mpView(nullptr),
67  mlOldWidth(1),
68  mlOldHeight(1),
69  mlRotX(0),
70  mlRotY(0),
71  maUIScale(),
72  mePoolUnit(),
73  meDlgUnit(FieldUnit::INCH), // #i124409# init with fallback default
74  maTransfPosXControl(SID_ATTR_TRANSFORM_POS_X, *pBindings, *this),
75  maTransfPosYControl(SID_ATTR_TRANSFORM_POS_Y, *pBindings, *this),
76  maTransfWidthControl(SID_ATTR_TRANSFORM_WIDTH, *pBindings, *this),
77  maTransfHeightControl(SID_ATTR_TRANSFORM_HEIGHT, *pBindings, *this),
78  maSvxAngleControl( SID_ATTR_TRANSFORM_ANGLE, *pBindings, *this),
79  maRotXControl(SID_ATTR_TRANSFORM_ROT_X, *pBindings, *this),
80  maRotYControl(SID_ATTR_TRANSFORM_ROT_Y, *pBindings, *this),
81  maProPosControl(SID_ATTR_TRANSFORM_PROTECT_POS, *pBindings, *this),
82  maProSizeControl(SID_ATTR_TRANSFORM_PROTECT_SIZE, *pBindings, *this),
83  maAutoWidthControl(SID_ATTR_TRANSFORM_AUTOWIDTH, *pBindings, *this),
84  maAutoHeightControl(SID_ATTR_TRANSFORM_AUTOHEIGHT, *pBindings, *this),
85  m_aMetricCtl(SID_ATTR_METRIC, *pBindings, *this),
86  maContext(),
87  mpBindings(pBindings),
88  mbSizeProtected(false),
89  mbPositionProtected(false),
90  mbAutoWidth(false),
91  mbAutoHeight(false),
92  mbAdjustEnabled(false),
93  mxSidebar(rxSidebar)
94 {
95  get( mpFtPosX, "horizontallabel" );
96  get( mpMtrPosX, "horizontalpos" );
97  get( mpFtPosY, "verticallabel" );
98  get( mpMtrPosY, "verticalpos" );
99  get( mpFtWidth, "widthlabel" );
100  get( mpMtrWidth, "selectwidth" );
101  get( mpFtHeight, "heightlabel" );
102  get( mpMtrHeight, "selectheight" );
103  get( mpCbxScale, "ratio" );
104  get( mpFtAngle, "rotationlabel" );
105  get( mpMtrAngle, "rotation" );
106  get( mpDial, "orientationcontrol" );
107  get( mpFtFlip, "fliplabel" );
108  get( mpFlipTbx, "selectrotationtype" );
109  Initialize();
110 
111  mpBindings->Update( SID_ATTR_TRANSFORM_WIDTH );
112  mpBindings->Update( SID_ATTR_TRANSFORM_HEIGHT );
113  mpBindings->Update( SID_ATTR_TRANSFORM_PROTECT_SIZE );
114  mpBindings->Update( SID_ATTR_METRIC );
115 }
116 
118 {
119  disposeOnce();
120 }
121 
123 {
124  mpFtPosX.clear();
125  mpMtrPosX.clear();
126  mpFtPosY.clear();
127  mpMtrPosY.clear();
128  mpFtWidth.clear();
129  mpMtrWidth.clear();
130  mpFtHeight.clear();
131  mpMtrHeight.clear();
132  mpCbxScale.clear();
133  mpFtAngle.clear();
134  mpMtrAngle.clear();
135  mpDial.clear();
136  mpFtFlip.clear();
137  mpFlipTbx.clear();
138 
143 
152 
154 }
155 
156 
157 namespace
158 {
159  bool hasText(const SdrView& rSdrView)
160  {
161  const SdrMarkList& rMarkList = rSdrView.GetMarkedObjectList();
162 
163  if(1 == rMarkList.GetMarkCount())
164  {
165  const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
166  const SdrObjKind eKind(static_cast<SdrObjKind>(pObj->GetObjIdentifier()));
167 
168  if((pObj->GetObjInventor() == SdrInventor::Default) && (OBJ_TEXT == eKind || OBJ_TITLETEXT == eKind || OBJ_OUTLINETEXT == eKind))
169  {
170  const SdrTextObj* pSdrTextObj = dynamic_cast< const SdrTextObj* >(pObj);
171 
172  if(pSdrTextObj && pSdrTextObj->HasText())
173  {
174  return true;
175  }
176  }
177  }
178 
179  return false;
180  }
181 } // end of anonymous namespace
182 
183 
185 {
186  //Position : Horizontal / Vertical
187  mpMtrPosX->SetModifyHdl( LINK( this, PosSizePropertyPanel, ChangePosXHdl ) );
188  mpMtrPosY->SetModifyHdl( LINK( this, PosSizePropertyPanel, ChangePosYHdl ) );
189 
190  //Size : Width / Height
191  mpMtrWidth->SetModifyHdl( LINK( this, PosSizePropertyPanel, ChangeWidthHdl ) );
192  mpMtrHeight->SetModifyHdl( LINK( this, PosSizePropertyPanel, ChangeHeightHdl ) );
193 
194  //Size : Keep ratio
195  mpCbxScale->SetClickHdl( LINK( this, PosSizePropertyPanel, ClickAutoHdl ) );
196 
197  //rotation:
198  mpMtrAngle->SetModifyHdl(LINK( this, PosSizePropertyPanel, AngleModifiedHdl));
199  mpMtrAngle->EnableAutocomplete( false );
200 
201  //rotation control
202  mpDial->SetModifyHdl(LINK( this, PosSizePropertyPanel, RotationHdl));
203 
204  //flip:
205  mpFlipTbx->SetSelectHdl( LINK( this, PosSizePropertyPanel, FlipHdl) );
206 
207  mpMtrAngle->InsertValue(0, FieldUnit::CUSTOM);
208  mpMtrAngle->InsertValue(4500, FieldUnit::CUSTOM);
209  mpMtrAngle->InsertValue(9000, FieldUnit::CUSTOM);
210  mpMtrAngle->InsertValue(13500, FieldUnit::CUSTOM);
211  mpMtrAngle->InsertValue(18000, FieldUnit::CUSTOM);
212  mpMtrAngle->InsertValue(22500, FieldUnit::CUSTOM);
213  mpMtrAngle->InsertValue(27000, FieldUnit::CUSTOM);
214  mpMtrAngle->InsertValue(31500, FieldUnit::CUSTOM);
216 
218  if ( pCurSh )
219  mpView = pCurSh->GetDrawView();
220  else
221  mpView = nullptr;
222 
223  if ( mpView != nullptr )
224  {
226  mbAdjustEnabled = hasText(*mpView);
227  }
228 
230 }
231 
233  vcl::Window* pParent,
234  const css::uno::Reference<css::frame::XFrame>& rxFrame,
235  SfxBindings* pBindings,
236  const css::uno::Reference<css::ui::XSidebar>& rxSidebar)
237 {
238  if (pParent == nullptr)
239  throw lang::IllegalArgumentException("no parent Window given to PosSizePropertyPanel::Create", nullptr, 0);
240  if ( ! rxFrame.is())
241  throw lang::IllegalArgumentException("no XFrame given to PosSizePropertyPanel::Create", nullptr, 1);
242  if (pBindings == nullptr)
243  throw lang::IllegalArgumentException("no SfxBindings given to PosSizePropertyPanel::Create", nullptr, 2);
244 
246  pParent,
247  rxFrame,
248  pBindings,
249  rxSidebar);
250 }
251 
252 
254  const DataChangedEvent& /*rEvent*/)
255 {
256 }
257 
259  const vcl::EnumContext& rContext)
260 {
261  if (maContext == rContext)
262  {
263  // Nothing to do.
264  return;
265  }
266 
267  maContext = rContext;
268 
269  bool bShowPosition = false;
270  bool bShowAngle = false;
271  bool bShowFlip = false;
272 
274  {
275  case CombinedEnumContext(Application::WriterVariants, Context::Draw):
276  bShowAngle = true;
277  bShowFlip = true;
278  break;
279 
280  case CombinedEnumContext(Application::WriterVariants, Context::Graphic):
281  bShowFlip = true;
282  bShowAngle = true; // RotGrfFlyFrame: Writer FlyFrames for Graphics now support angle
283  break;
284 
285  case CombinedEnumContext(Application::Calc, Context::Draw):
286  case CombinedEnumContext(Application::Calc, Context::DrawLine):
287  case CombinedEnumContext(Application::Calc, Context::Graphic):
288  case CombinedEnumContext(Application::DrawImpress, Context::Draw):
289  case CombinedEnumContext(Application::DrawImpress, Context::DrawLine):
290  case CombinedEnumContext(Application::DrawImpress, Context::TextObject):
291  case CombinedEnumContext(Application::DrawImpress, Context::Graphic):
292  bShowPosition = true;
293  bShowAngle = true;
294  bShowFlip = true;
295  break;
296 
297  case CombinedEnumContext(Application::Calc, Context::Chart):
298  case CombinedEnumContext(Application::Calc, Context::Form):
299  case CombinedEnumContext(Application::Calc, Context::Media):
300  case CombinedEnumContext(Application::Calc, Context::OLE):
301  case CombinedEnumContext(Application::Calc, Context::MultiObject):
302  case CombinedEnumContext(Application::DrawImpress, Context::Media):
303  case CombinedEnumContext(Application::DrawImpress, Context::Form):
304  case CombinedEnumContext(Application::DrawImpress, Context::OLE):
305  case CombinedEnumContext(Application::DrawImpress, Context::ThreeDObject):
306  case CombinedEnumContext(Application::DrawImpress, Context::MultiObject):
307  bShowPosition = true;
308  break;
309  }
310 
311  // Position
312  mpFtPosX->Show(bShowPosition);
313  mpMtrPosX->Show(bShowPosition);
314  mpFtPosY->Show(bShowPosition);
315  mpMtrPosY->Show(bShowPosition);
316 
317  // Rotation
318  mpFtAngle->Show(bShowAngle);
319  mpMtrAngle->Show(bShowAngle);
320  mpDial->Show(bShowAngle);
321 
322  // Flip
323  mpFtFlip->Show(bShowFlip);
324  mpFlipTbx->Show(bShowFlip);
325 
326  if (mxSidebar.is())
327  mxSidebar->requestLayout();
328 }
329 
330 
331 IMPL_LINK_NOARG( PosSizePropertyPanel, ChangeWidthHdl, Edit&, void )
332 {
333  if( mpCbxScale->IsChecked() &&
334  mpCbxScale->IsEnabled() )
335  {
336  long nHeight = static_cast<long>( (static_cast<double>(mlOldHeight) * static_cast<double>(mpMtrWidth->GetValue())) / static_cast<double>(mlOldWidth) );
337  if( nHeight <= mpMtrHeight->GetMax( FieldUnit::NONE ) )
338  {
339  mpMtrHeight->SetUserValue( nHeight, FieldUnit::NONE );
340  }
341  else
342  {
343  nHeight = static_cast<long>(mpMtrHeight->GetMax( FieldUnit::NONE ));
344  mpMtrHeight->SetUserValue( nHeight );
345  const long nWidth = static_cast<long>( (static_cast<double>(mlOldWidth) * static_cast<double>(nHeight)) / static_cast<double>(mlOldHeight) );
346  mpMtrWidth->SetUserValue( nWidth, FieldUnit::NONE );
347  }
348  }
349  executeSize();
350 }
351 
352 
353 IMPL_LINK_NOARG( PosSizePropertyPanel, ChangeHeightHdl, Edit&, void )
354 {
355  if( mpCbxScale->IsChecked() &&
356  mpCbxScale->IsEnabled() )
357  {
358  long nWidth = static_cast<long>( (static_cast<double>(mlOldWidth) * static_cast<double>(mpMtrHeight->GetValue())) / static_cast<double>(mlOldHeight) );
359  if( nWidth <= mpMtrWidth->GetMax( FieldUnit::NONE ) )
360  {
361  mpMtrWidth->SetUserValue( nWidth, FieldUnit::NONE );
362  }
363  else
364  {
365  nWidth = static_cast<long>(mpMtrWidth->GetMax( FieldUnit::NONE ));
366  mpMtrWidth->SetUserValue( nWidth );
367  const long nHeight = static_cast<long>( (static_cast<double>(mlOldHeight) * static_cast<double>(nWidth)) / static_cast<double>(mlOldWidth) );
368  mpMtrHeight->SetUserValue( nHeight, FieldUnit::NONE );
369  }
370  }
371  executeSize();
372 }
373 
374 
375 IMPL_LINK_NOARG( PosSizePropertyPanel, ChangePosXHdl, Edit&, void )
376 {
377  if ( mpMtrPosX->IsValueModified())
378  {
379  long lX = GetCoreValue( *mpMtrPosX, mePoolUnit );
380 
381  Fraction aUIScale = mpView->GetModel()->GetUIScale();
382  lX = long( lX * aUIScale );
383 
384  SfxInt32Item aPosXItem( SID_ATTR_TRANSFORM_POS_X,static_cast<sal_uInt32>(lX));
385 
386  GetBindings()->GetDispatcher()->ExecuteList(
387  SID_ATTR_TRANSFORM, SfxCallMode::RECORD, { &aPosXItem });
388  }
389 }
390 
391 
392 IMPL_LINK_NOARG( PosSizePropertyPanel, ChangePosYHdl, Edit&, void )
393 {
394  if ( mpMtrPosY->IsValueModified() )
395  {
396  long lY = GetCoreValue( *mpMtrPosY, mePoolUnit );
397 
398  Fraction aUIScale = mpView->GetModel()->GetUIScale();
399  lY = long( lY * aUIScale );
400 
401  SfxInt32Item aPosYItem( SID_ATTR_TRANSFORM_POS_Y,static_cast<sal_uInt32>(lY));
402 
403  GetBindings()->GetDispatcher()->ExecuteList(
404  SID_ATTR_TRANSFORM, SfxCallMode::RECORD, { &aPosYItem });
405  }
406 }
407 
408 
410 {
411  if ( mpCbxScale->IsChecked() )
412  {
413  mlOldWidth = std::max( GetCoreValue( *mpMtrWidth, mePoolUnit ), 1L );
414  mlOldHeight = std::max( GetCoreValue( *mpMtrHeight, mePoolUnit ), 1L );
415  }
416 
417  // mpCbxScale must synchronized with that on Position and Size tabpage on Shape Properties dialog
418  SvtViewOptions aPageOpt(EViewType::TabPage, "cui/ui/possizetabpage/PositionAndSize");
419  aPageOpt.SetUserItem( USERITEM_NAME, css::uno::makeAny( OUString::number( int(mpCbxScale->IsChecked()) ) ) );
420 }
421 
422 
423 IMPL_LINK_NOARG( PosSizePropertyPanel, AngleModifiedHdl, Edit&, void )
424 {
425  OUString sTmp = mpMtrAngle->GetText();
426  if (sTmp.isEmpty())
427  return;
428  sal_Unicode nChar = sTmp[0];
429  if( nChar == '-' )
430  {
431  if (sTmp.getLength() < 2)
432  return;
433  nChar = sTmp[1];
434  }
435 
436  if( (nChar < '0') || (nChar > '9') )
437  return;
438 
440 
441  // Do not check that the entire string was parsed up to its end, there may
442  // be a degree symbol following the number. Note that this also means that
443  // the number recognized just stops at any non-matching character.
444  /* TODO: we could check for the degree symbol stop if there are no other
445  * cases with different symbol characters in any language? */
446  rtl_math_ConversionStatus eStatus;
447  double fTmp = rLocaleWrapper.stringToDouble( sTmp, false, &eStatus, nullptr);
448  if (eStatus != rtl_math_ConversionStatus_Ok)
449  return;
450 
451  while (fTmp < 0)
452  fTmp += 360;
453 
454  sal_Int64 nTmp = fTmp*100;
455 
456  // #i123993# Need to take UIScale into account when executing rotations
457  const double fUIScale(mpView && mpView->GetModel() ? double(mpView->GetModel()->GetUIScale()) : 1.0);
458  SfxInt32Item aAngleItem( SID_ATTR_TRANSFORM_ANGLE,static_cast<sal_uInt32>(nTmp));
459  SfxInt32Item aRotXItem( SID_ATTR_TRANSFORM_ROT_X, basegfx::fround(mlRotX * fUIScale));
460  SfxInt32Item aRotYItem( SID_ATTR_TRANSFORM_ROT_Y, basegfx::fround(mlRotY * fUIScale));
461 
462  GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM,
463  SfxCallMode::RECORD, { &aAngleItem, &aRotXItem, &aRotYItem });
464 }
465 
466 
468 {
469  sal_Int32 nTmp = mpDial->GetRotation();
470 
471  // #i123993# Need to take UIScale into account when executing rotations
472  const double fUIScale(mpView && mpView->GetModel() ? double(mpView->GetModel()->GetUIScale()) : 1.0);
473  SfxInt32Item aAngleItem( SID_ATTR_TRANSFORM_ANGLE,static_cast<sal_uInt32>(nTmp));
474  SfxInt32Item aRotXItem( SID_ATTR_TRANSFORM_ROT_X, basegfx::fround(mlRotX * fUIScale));
475  SfxInt32Item aRotYItem( SID_ATTR_TRANSFORM_ROT_Y, basegfx::fround(mlRotY * fUIScale));
476 
477  GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM,
478  SfxCallMode::RECORD, { &aAngleItem, &aRotXItem, &aRotYItem });
479 }
480 
481 
482 IMPL_LINK( PosSizePropertyPanel, FlipHdl, ToolBox*, pBox, void )
483 {
484  const OUString aCommand(pBox->GetItemCommand(pBox->GetCurItemId()));
485 
486  if(aCommand == ".uno:FlipHorizontal")
487  {
488  SfxVoidItem aHoriItem(SID_FLIP_HORIZONTAL);
489  GetBindings()->GetDispatcher()->ExecuteList(SID_FLIP_HORIZONTAL,
490  SfxCallMode::RECORD, { &aHoriItem });
491  }
492  else if(aCommand == ".uno:FlipVertical")
493  {
494  SfxVoidItem aVertItem(SID_FLIP_VERTICAL);
495  GetBindings()->GetDispatcher()->ExecuteList(SID_FLIP_VERTICAL,
496  SfxCallMode::RECORD, { &aVertItem });
497  }
498 }
499 
500 
502  sal_uInt16 nSID,
503  SfxItemState eState,
504  const SfxPoolItem* pState)
505 {
506  mpFtAngle->Enable();
507  mpMtrAngle->Enable();
508  mpDial->Enable();
509  mpFtFlip->Enable();
510  mpFlipTbx->Enable();
511 
512  const SfxUInt32Item* pWidthItem;
513  const SfxUInt32Item* pHeightItem;
514 
516  if ( pCurSh )
517  mpView = pCurSh->GetDrawView();
518  else
519  mpView = nullptr;
520 
521  if ( mpView == nullptr )
522  return;
523 
524  mbAdjustEnabled = hasText(*mpView);
525 
526  // Pool unit and dialog unit may have changed, make sure that we
527  // have the current values.
529 
530  switch (nSID)
531  {
532  case SID_ATTR_TRANSFORM_WIDTH:
533  if ( SfxItemState::DEFAULT == eState )
534  {
535  pWidthItem = dynamic_cast< const SfxUInt32Item* >(pState);
536 
537  if(pWidthItem)
538  {
539  long lOldWidth1 = long( pWidthItem->GetValue() / maUIScale );
540  SetFieldUnit( *mpMtrWidth, meDlgUnit, true );
541  SetMetricValue( *mpMtrWidth, lOldWidth1, mePoolUnit );
542  mlOldWidth = lOldWidth1;
543  break;
544  }
545  }
546 
547  mpMtrWidth->SetText( "" );
548  break;
549 
550  case SID_ATTR_TRANSFORM_HEIGHT:
551  if ( SfxItemState::DEFAULT == eState )
552  {
553  pHeightItem = dynamic_cast< const SfxUInt32Item* >(pState);
554 
555  if(pHeightItem)
556  {
557  long nTmp = long( pHeightItem->GetValue() / maUIScale);
560  mlOldHeight = nTmp;
561  break;
562  }
563  }
564 
565  mpMtrHeight->SetText( "");
566  break;
567 
568  case SID_ATTR_TRANSFORM_POS_X:
569  if(SfxItemState::DEFAULT == eState)
570  {
571  const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState);
572 
573  if(pItem)
574  {
575  long nTmp = long(pItem->GetValue() / maUIScale);
576  SetFieldUnit( *mpMtrPosX, meDlgUnit, true );
578  break;
579  }
580  }
581 
582  mpMtrPosX->SetText( "" );
583  break;
584 
585  case SID_ATTR_TRANSFORM_POS_Y:
586  if(SfxItemState::DEFAULT == eState)
587  {
588  const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState);
589 
590  if(pItem)
591  {
592  long nTmp = long(pItem->GetValue() / maUIScale);
593  SetFieldUnit( *mpMtrPosY, meDlgUnit, true );
595  break;
596  }
597  }
598 
599  mpMtrPosY->SetText( "" );
600  break;
601 
602  case SID_ATTR_TRANSFORM_ROT_X:
603  if (SfxItemState::DEFAULT == eState)
604  {
605  const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState);
606 
607  if(pItem)
608  {
609  mlRotX = pItem->GetValue();
610  mlRotX = long( mlRotX / maUIScale );
611  }
612  }
613  break;
614 
615  case SID_ATTR_TRANSFORM_ROT_Y:
616  if (SfxItemState::DEFAULT == eState)
617  {
618  const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState);
619 
620  if(pItem)
621  {
622  mlRotY = pItem->GetValue();
623  mlRotY = long( mlRotY / maUIScale );
624  }
625  }
626  break;
627 
628  case SID_ATTR_TRANSFORM_PROTECT_POS:
629  if(SfxItemState::DEFAULT == eState)
630  {
631  const SfxBoolItem* pItem = dynamic_cast< const SfxBoolItem* >(pState);
632 
633  if(pItem)
634  {
635  // record the state of position protect
636  mbPositionProtected = pItem->GetValue();
637  break;
638  }
639  }
640 
641  mbPositionProtected = false;
642  break;
643 
644  case SID_ATTR_TRANSFORM_PROTECT_SIZE:
645  if(SfxItemState::DEFAULT == eState)
646  {
647  const SfxBoolItem* pItem = dynamic_cast< const SfxBoolItem* >(pState);
648 
649  if(pItem)
650  {
651  // record the state of size protect
652  mbSizeProtected = pItem->GetValue();
653  break;
654  }
655  }
656 
657  mbSizeProtected = false;
658  break;
659 
660  case SID_ATTR_TRANSFORM_AUTOWIDTH:
661  if(SfxItemState::DEFAULT == eState)
662  {
663  const SfxBoolItem* pItem = dynamic_cast< const SfxBoolItem* >(pState);
664 
665  if(pItem)
666  {
667  mbAutoWidth = pItem->GetValue();
668  }
669  }
670  break;
671 
672  case SID_ATTR_TRANSFORM_AUTOHEIGHT:
673  if(SfxItemState::DEFAULT == eState)
674  {
675  const SfxBoolItem* pItem = dynamic_cast< const SfxBoolItem* >(pState);
676 
677  if(pItem)
678  {
679  mbAutoHeight = pItem->GetValue();
680  }
681  }
682  break;
683 
684  case SID_ATTR_TRANSFORM_ANGLE:
685  if (eState >= SfxItemState::DEFAULT)
686  {
687  const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState);
688 
689  if(pItem)
690  {
691  long nTmp = pItem->GetValue();
692  nTmp = nTmp < 0 ? 36000+nTmp : nTmp;
693 
694  mpMtrAngle->SetValue( nTmp );
695  mpDial->SetRotation( nTmp );
696 
697  switch(nTmp)
698  {
699  case 0:
701  break;
702  case 4500:
704  break;
705  case 9000:
707  break;
708  case 13500:
710  break;
711  case 18000:
713  break;
714  case 22500:
716  break;
717  case 27000:
719  break;
720  case 315000:
722  break;
723  }
724 
725  break;
726  }
727  }
728 
729  mpMtrAngle->SetText( "" );
730  mpDial->SetRotation( 0 );
731  break;
732 
733  case SID_ATTR_METRIC:
734  MetricState( eState, pState );
735  UpdateUIScale();
736  break;
737 
738  default:
739  break;
740  }
741 
742  const sal_Int32 nCombinedContext(maContext.GetCombinedContext_DI());
743  const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
744 
745  switch (rMarkList.GetMarkCount())
746  {
747  case 0:
748  break;
749 
750  case 1:
751  {
752  const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
753  const SdrObjKind eKind(static_cast<SdrObjKind>(pObj->GetObjIdentifier()));
754 
755  if(((nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::Draw)
756  || nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::TextObject)
757  ) && OBJ_EDGE == eKind)
758  || OBJ_CAPTION == eKind)
759  {
760  mpFtAngle->Disable();
761  mpMtrAngle->Disable();
762  mpDial->Disable();
763  mpFlipTbx->Disable();
764  mpFtFlip->Disable();
765  }
766  break;
767  }
768 
769  default:
770  {
771  sal_uInt16 nMarkObj = 0;
772  bool isNoEdge = true;
773 
774  while(isNoEdge && rMarkList.GetMark(nMarkObj))
775  {
776  const SdrObject* pObj = rMarkList.GetMark(nMarkObj)->GetMarkedSdrObj();
777  const SdrObjKind eKind(static_cast<SdrObjKind>(pObj->GetObjIdentifier()));
778 
779  if(((nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::Draw)
780  || nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::TextObject)
781  ) && OBJ_EDGE == eKind)
782  || OBJ_CAPTION == eKind)
783  {
784  isNoEdge = false;
785  break;
786  }
787  nMarkObj++;
788  }
789 
790  if(!isNoEdge)
791  {
792  mpFtAngle->Disable();
793  mpMtrAngle->Disable();
794  mpDial->Disable();
795  mpFlipTbx->Disable();
796  mpFtFlip->Disable();
797  }
798  break;
799  }
800  }
801 
802  if(nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::TextObject))
803  {
804  mpFlipTbx->Disable();
805  mpFtFlip->Disable();
806  }
807 
808  DisableControls();
809 
810  // mpCbxScale must synchronized with that on Position and Size tabpage on Shape Properties dialog
811  SvtViewOptions aPageOpt(EViewType::TabPage, "cui/ui/possizetabpage/PositionAndSize");
812  OUString sUserData;
813  css::uno::Any aUserItem = aPageOpt.GetUserItem( USERITEM_NAME );
814  OUString aTemp;
815  if ( aUserItem >>= aTemp )
816  sUserData = aTemp;
817  mpCbxScale->Check( static_cast<bool>(sUserData.toInt32()) );
818 }
819 
820 
822 {
824  return;
825 
826  Fraction aUIScale = mpView->GetModel()->GetUIScale();
827 
828  // get Width
829  double nWidth = static_cast<double>(mpMtrWidth->GetValue( meDlgUnit ));
830  nWidth = MetricField::ConvertDoubleValue( nWidth, mpMtrWidth->GetBaseValue(), mpMtrWidth->GetDecimalDigits(), meDlgUnit, FieldUnit::MM_100TH );
831  long lWidth = static_cast<long>(nWidth * static_cast<double>(aUIScale));
832  lWidth = OutputDevice::LogicToLogic( lWidth, MapUnit::Map100thMM, mePoolUnit );
833  lWidth = static_cast<long>(mpMtrWidth->Denormalize( lWidth ));
834 
835  // get Height
836  double nHeight = static_cast<double>(mpMtrHeight->GetValue( meDlgUnit ));
837  nHeight = MetricField::ConvertDoubleValue( nHeight, mpMtrHeight->GetBaseValue(), mpMtrHeight->GetDecimalDigits(), meDlgUnit, FieldUnit::MM_100TH );
838  long lHeight = static_cast<long>(nHeight * static_cast<double>(aUIScale));
839  lHeight = OutputDevice::LogicToLogic( lHeight, MapUnit::Map100thMM, mePoolUnit );
840  lHeight = static_cast<long>(mpMtrWidth->Denormalize( lHeight ));
841 
842  // put Width & Height to itemset
843  SfxUInt32Item aWidthItem( SID_ATTR_TRANSFORM_WIDTH, static_cast<sal_uInt32>(lWidth));
844  SfxUInt32Item aHeightItem( SID_ATTR_TRANSFORM_HEIGHT, static_cast<sal_uInt32>(lHeight));
845  SfxUInt16Item aPointItem (SID_ATTR_TRANSFORM_SIZE_POINT, sal_uInt16(RectPoint::LT));
846  const sal_Int32 nCombinedContext(maContext.GetCombinedContext_DI());
847 
848  if( nCombinedContext == CombinedEnumContext(Application::WriterVariants, Context::Graphic)
849  || nCombinedContext == CombinedEnumContext(Application::WriterVariants, Context::OLE)
850  )
851  {
852  GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM,
853  SfxCallMode::RECORD, { &aWidthItem, &aHeightItem, &aPointItem });
854  }
855  else
856  {
858  GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM,
859  SfxCallMode::RECORD, { &aWidthItem, &aHeightItem, &aPointItem });
860  else if( mpMtrWidth->IsValueModified())
861  GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM,
862  SfxCallMode::RECORD, { &aWidthItem, &aPointItem });
863  else if ( mpMtrHeight->IsValueModified())
864  GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM,
865  SfxCallMode::RECORD, { &aHeightItem, &aPointItem });
866  }
867 }
868 
869 
871 {
872  bool bPosXBlank = false;
873  bool bPosYBlank = false;
874  bool bWidthBlank = false;
875  bool bHeightBlank = false;
876 
877  // #i124409# use the given Item to get the correct UI unit and initialize it
878  // and the Fields using it
879  meDlgUnit = GetCurrentUnit(eState,pState);
880 
881  if (mpMtrPosX->GetText().isEmpty())
882  bPosXBlank = true;
883  SetFieldUnit( *mpMtrPosX, meDlgUnit, true );
884  if(bPosXBlank)
885  mpMtrPosX->SetText(OUString());
886 
887  if (mpMtrPosY->GetText().isEmpty())
888  bPosYBlank = true;
889  SetFieldUnit( *mpMtrPosY, meDlgUnit, true );
890  if(bPosYBlank)
891  mpMtrPosY->SetText(OUString());
893 
894  if (mpMtrWidth->GetText().isEmpty())
895  bWidthBlank = true;
896  SetFieldUnit( *mpMtrWidth, meDlgUnit, true );
897  if(bWidthBlank)
898  mpMtrWidth->SetText(OUString());
899 
900  if (mpMtrHeight->GetText().isEmpty())
901  bHeightBlank = true;
903  if(bHeightBlank)
904  mpMtrHeight->SetText(OUString());
905 }
906 
907 
909 {
910  FieldUnit eUnit = FieldUnit::NONE;
911 
912  if ( pState && eState >= SfxItemState::DEFAULT )
913  {
914  eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pState)->GetValue());
915  }
916  else
917  {
919  SfxObjectShell* pSh = nullptr;
920  if ( pFrame )
921  pSh = pFrame->GetObjectShell();
922  if ( pSh )
923  {
924  SfxModule* pModule = pSh->GetModule();
925  if ( pModule )
926  {
927  const SfxPoolItem* pItem = pModule->GetItem( SID_ATTR_METRIC );
928  if ( pItem )
929  eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pItem)->GetValue());
930  }
931  else
932  {
933  SAL_WARN("svx.sidebar", "GetModuleFieldUnit(): no module found");
934  }
935  }
936  }
937 
938  return eUnit;
939 }
940 
941 
943 {
944  if( mbPositionProtected )
945  {
946  // the position is protected("Position protect" option in modal dialog is checked),
947  // disable all the Position controls in sidebar
948  mpFtPosX->Disable();
949  mpMtrPosX->Disable();
950  mpFtPosY->Disable();
951  mpMtrPosY->Disable();
952  mpFtAngle->Disable();
953  mpMtrAngle->Disable();
954  mpDial->Disable();
955  mpFtFlip->Disable();
956  mpFlipTbx->Disable();
957 
958  mpFtWidth->Disable();
959  mpMtrWidth->Disable();
960  mpFtHeight->Disable();
961  mpMtrHeight->Disable();
962  mpCbxScale->Disable();
963  }
964  else
965  {
966  mpFtPosX->Enable();
967  mpMtrPosX->Enable();
968  mpFtPosY->Enable();
969  mpMtrPosY->Enable();
970 
971  //mpFtAngle->Enable();
972  //mpMtrAngle->Enable();
973  //mpDial->Enable();
974  //mpFtFlip->Enable();
975  //mpFlipTbx->Enable();
976 
977  if( mbSizeProtected )
978  {
979  mpFtWidth->Disable();
980  mpMtrWidth->Disable();
981  mpFtHeight->Disable();
982  mpMtrHeight->Disable();
983  mpCbxScale->Disable();
984  }
985  else
986  {
987  if( mbAdjustEnabled )
988  {
989  if( mbAutoWidth )
990  {
991  mpFtWidth->Disable();
992  mpMtrWidth->Disable();
993  mpCbxScale->Disable();
994  }
995  else
996  {
997  mpFtWidth->Enable();
998  mpMtrWidth->Enable();
999  }
1000  if( mbAutoHeight )
1001  {
1002  mpFtHeight->Disable();
1003  mpMtrHeight->Disable();
1004  mpCbxScale->Disable();
1005  }
1006  else
1007  {
1008  mpFtHeight->Enable();
1009  mpMtrHeight->Enable();
1010  }
1011  if( !mbAutoWidth && !mbAutoHeight )
1012  mpCbxScale->Enable();
1013  }
1014  else
1015  {
1016  mpFtWidth->Enable();
1017  mpMtrWidth->Enable();
1018  mpFtHeight->Enable();
1019  mpMtrHeight->Enable();
1020  mpCbxScale->Enable();
1021  }
1022  }
1023  }
1024 }
1025 
1027 {
1028  SdrPageView* pPV = mpView->GetSdrPageView();
1029  if (!pPV)
1030  return;
1032  pPV->LogicToPagePos(aTmpRect);
1034 
1035  tools::Rectangle aTmpRect2(mpView->GetWorkArea());
1036  pPV->LogicToPagePos(aTmpRect2);
1038 
1039  const Fraction aUIScale(mpView->GetModel()->GetUIScale());
1041  TransfrmHelper::ScaleRect( maRect, aUIScale );
1042 
1043  const sal_uInt16 nDigits(mpMtrPosX->GetDecimalDigits());
1046 
1047  double fLeft(maWorkArea.getMinX());
1048  double fTop(maWorkArea.getMinY());
1049  double fRight(maWorkArea.getMaxX());
1050  double fBottom(maWorkArea.getMaxY());
1051 
1052  // seems that sidebar defaults to top left reference point
1053  // and there's no way to set it to something else
1054  fRight -= maRect.getWidth();
1055  fBottom -= maRect.getHeight();
1056 
1057  const double fMaxLong(static_cast<double>(MetricField::ConvertValue( LONG_MAX, 0, MapUnit::Map100thMM, meDlgUnit ) - 1));
1058  fLeft = std::clamp(fLeft, -fMaxLong, fMaxLong);
1059  fRight = std::clamp(fRight, -fMaxLong, fMaxLong);
1060  fTop = std::clamp(fTop, - fMaxLong, fMaxLong);
1061  fBottom = std::clamp(fBottom, -fMaxLong, fMaxLong);
1062 
1069  mpMtrPosY->SetMax(basegfx::fround64(fBottom));
1070  mpMtrPosY->SetLast(basegfx::fround64(fBottom));
1071 
1072  double fMaxWidth = maWorkArea.getWidth() - (maRect.getWidth() - fLeft);
1073  double fMaxHeight = maWorkArea.getHeight() - (maRect.getHeight() - fTop);
1074  mpMtrWidth->SetMax(basegfx::fround64(fMaxWidth*100));
1075  mpMtrWidth->SetLast(basegfx::fround64(fMaxWidth*100));
1076  mpMtrHeight->SetMax(basegfx::fround64(fMaxHeight*100));
1077  mpMtrHeight->SetLast(basegfx::fround64(fMaxHeight*100));
1078 }
1079 
1081 {
1082  const Fraction aUIScale (mpView->GetModel()->GetUIScale());
1083  if (maUIScale != aUIScale)
1084  {
1085  // UI scale has changed.
1086 
1087  // Remember the new UI scale.
1088  maUIScale = aUIScale;
1089 
1090  // The content of the position and size boxes is only updated when item changes are notified.
1091  // Request such notifications without changing the actual item values.
1092  GetBindings()->Invalidate(SID_ATTR_TRANSFORM_POS_X, true);
1093  GetBindings()->Invalidate(SID_ATTR_TRANSFORM_POS_Y, true);
1094  GetBindings()->Invalidate(SID_ATTR_TRANSFORM_WIDTH, true);
1095  GetBindings()->Invalidate(SID_ATTR_TRANSFORM_HEIGHT, true);
1096  }
1097 }
1098 
1099 
1100 } } // end of namespace svx::sidebar
1101 
1102 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool GetValue() const
void SetUserItem(const OUString &sName, const css::uno::Any &aValue)
void SetFieldUnit(weld::MetricSpinButton &rField, FieldUnit eUnit, bool bAll)
sal_Int32 GetValue() const
const char USERITEM_NAME[]
void UpdateUIScale()
Check if the UI scale has changed and handle such a change.
const SfxPoolItem * ExecuteList(sal_uInt16 nSlot, SfxCallMode nCall, std::initializer_list< SfxPoolItem const * > args, std::initializer_list< SfxPoolItem const * > internalargs=std::initializer_list< SfxPoolItem const * >())
FieldUnit
::sfx2::sidebar::ControllerItem maAutoHeightControl
size_t GetMarkCount() const
Definition: svdmark.hxx:179
SlideShowContext maContext
::sfx2::sidebar::ControllerItem maProPosControl
This class is the base for the Widget Layout-based sidebar panels.
Definition: PanelLayout.hxx:24
double getHeight() const
void SetClickHdl(const Link< Button *, void > &rLink)
void MetricState(SfxItemState eState, const SfxPoolItem *pState)
::sfx2::sidebar::ControllerItem maTransfPosXControl
std::string GetValue
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
void SetMin(sal_Int64 nNewMin, FieldUnit eInUnit)
This control allows to input a rotation angle, visualized by a dial.
Definition: dialcontrol.hxx:77
periodic cubic Spline (ni)
Definition: svdobj.hxx:133
void SetFirst(sal_Int64 nNewFirst, FieldUnit eInUnit)
static const AllSettings & GetSettings()
virtual void HandleContextChange(const vcl::EnumContext &rContext) override
MapUnit GetCoreMetric() const
::sfx2::sidebar::ControllerItem maSvxAngleControl
SdrMark * GetMark(size_t nNum) const
Definition: svdmark.cxx:234
OLE object.
Definition: svdobj.hxx:138
void SetMax(sal_Int64 nNewMax, FieldUnit eInUnit)
void Invalidate(sal_uInt16 nId)
IMPL_LINK(AreaPropertyPanelBase, ClickTrGrHdl_Impl, ToolBox *, pToolBox, void)
virtual SfxObjectShell * GetObjectShell() override
bool IsValueModified() const
double stringToDouble(const OUString &rString, bool bUseGroupSep, rtl_math_ConversionStatus *pStatus, sal_Int32 *pParseEnd) const
double getMaxX() const
virtual bool HasText() const override
Definition: svdotxat.cxx:429
SfxModule * GetModule() const
sal_uInt16 sal_Unicode
void LogicToPagePos(Point &rPnt) const
Definition: svdpagv.hxx:212
::sfx2::sidebar::ControllerItem m_aMetricCtl
double getWidth() const
connector object
Definition: svdobj.hxx:139
::sfx2::sidebar::ControllerItem maTransfWidthControl
virtual void SetModifyHdl(const Link< Edit &, void > &rLink)
void Enable(bool bEnable=true, bool bChild=true)
sal_Int64 GetBaseValue() const
virtual void NotifyItemUpdate(const sal_uInt16 nSId, const SfxItemState eState, const SfxPoolItem *pState) override
sal_uInt16 GetDecimalDigits() const
static SfxViewShell * Current()
double getMaxY() const
void AdaptDropDownLineCountToMaximum()
B2IRange fround(const B2DRange &rRange)
sal_Int32 GetCombinedContext_DI() const
css::uno::Reference< css::ui::XSidebar > mxSidebar
SdrObject * GetMarkedSdrObj() const
Definition: svdmark.hxx:67
const SfxPoolItem * GetItem(sal_uInt16 nSlotId) const
::sfx2::sidebar::ControllerItem maRotYControl
virtual sal_uInt16 GetObjIdentifier() const
Definition: svdobj.cxx:585
static void ScaleRect(basegfx::B2DRange &rRange, const Fraction &rUIScale)
const SdrMarkList & GetMarkedObjectList() const
Definition: svdmrkv.hxx:243
int GetCoreValue(const weld::MetricSpinButton &rField, MapUnit eUnit)
virtual OUString GetText() const override
virtual void DataChanged(const DataChangedEvent &rEvent) override
void InsertValue(sal_Int64 nValue, FieldUnit eInUnit=FieldUnit::NONE, sal_Int32 nPos=COMBOBOX_APPEND)
static FieldUnit GetCurrentUnit(SfxItemState eState, const SfxPoolItem *pState)
const LocaleDataWrapper & GetLocaleDataWrapper(LanguageType nLang)
void Check(bool bCheck=true)
void SetSelectHdl(const Link< ToolBox *, void > &rLink)
::sfx2::sidebar::ControllerItem maTransfPosYControl
void SetMetricValue(weld::MetricSpinButton &rField, int nCoreValue, MapUnit eUnit)
Abstract DrawObject.
Definition: svdobj.hxx:312
::sfx2::sidebar::ControllerItem maProSizeControl
sal_Int64 Denormalize(sal_Int64 nValue) const
IMPL_LINK_NOARG(GalleryControl, SplitHdl, Splitter *, void)
const tools::Rectangle & GetAllMarkedRect() const
Definition: svdmrkv.hxx:410
const long LONG_MAX
void Disable(bool bChild=true)
virtual SdrInventor GetObjInventor() const
Definition: svdobj.cxx:580
void SetLast(sal_Int64 nNewLast, FieldUnit eInUnit)
void EnableAutocomplete(bool bEnable, bool bMatchCase=false)
basegfx::B2DRange b2DRectangleFromRectangle(const ::tools::Rectangle &rRect)
void Update(sal_uInt16 nId)
virtual void dispose() override
Definition: PanelLayout.cxx:45
const Fraction & GetUIScale() const
Definition: svdmodel.hxx:383
TitleText, special text object for StarDraw.
Definition: svdobj.hxx:135
double getMinY() const
static SfxViewFrame * Current()
SfxItemState
SdrObjKind
Definition: svdobj.hxx:116
static void ConvertRect(basegfx::B2DRange &rRange, const sal_uInt16 nDigits, const MapUnit ePoolUnit, const FieldUnit eDlgUnit)
static sal_Int64 ConvertValue(sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
virtual void dispose() override
static VclPtr< reference_type > Create(Arg &&...arg)
css::uno::Any GetUserItem(const OUString &sName) const
virtual void SetValue(sal_Int64 nNewValue, FieldUnit eInUnit)
UnoViewSharedPtr mpView
::sfx2::sidebar::ControllerItem maRotXControl
virtual SdrView * GetDrawView() const
SdrPageView * GetSdrPageView() const
Definition: svdpntv.hxx:317
VclPtr< SidebarDialControl > mpDial
sal_uInt32 GetValue() const
SfxDispatcher * GetDispatcher() const
#define SAL_WARN(area, stream)
static double ConvertDoubleValue(double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
OUString aCommand
double getMinX() const
::sfx2::sidebar::ControllerItem maAutoWidthControl
void SelectEntryPos(sal_Int32 nPos, bool bSelect=true)
virtual void SetText(const OUString &rStr) override
static VclPtr< vcl::Window > Create(vcl::Window *pParent, const css::uno::Reference< css::frame::XFrame > &rxFrame, SfxBindings *pBindings, const css::uno::Reference< css::ui::XSidebar > &rxSidebar)
sal_Int64 GetValue(FieldUnit eOutUnit) const
sal_Int64 fround64(double fVal)
virtual void SetText(const OUString &rStr) override
SdrModel * GetModel() const
Definition: svdpntv.hxx:278
const tools::Rectangle & GetWorkArea() const
Definition: svddrgv.hxx:213
text object
Definition: svdobj.hxx:134
::sfx2::sidebar::ControllerItem maTransfHeightControl
#define CombinedEnumContext(a, e)
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)