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"
26 #include <svx/svxids.hrc>
27 #include <sfx2/dispatch.hxx>
28 #include <sfx2/bindings.hxx>
29 #include <sfx2/lokhelper.hxx>
30 #include <sfx2/module.hxx>
31 #include <sfx2/viewsh.hxx>
32 #include <sfx2/objsh.hxx>
33 #include <sfx2/viewfrm.hxx>
34 #include <sfx2/weldutils.hxx>
35 #include <svx/dialcontrol.hxx>
36 #include <svx/dlgutil.hxx>
37 #include <svx/rectenum.hxx>
39 #include <unotools/viewoptions.hxx>
40 #include <vcl/canvastools.hxx>
41 #include <vcl/virdev.hxx>
42 #include <vcl/svapp.hxx>
43 #include <svl/aeitem.hxx>
44 #include <svl/intitem.hxx>
45 #include <svx/svdpagv.hxx>
46 #include <svx/svdview.hxx>
47 #include <svx/transfrmhelper.hxx>
48 
49 #include <svtools/unitconv.hxx>
50 #include <comphelper/lok.hxx>
51 
52 using namespace css;
53 using namespace css::uno;
54 
55 const char USERITEM_NAME[] = "FitItem";
56 
57 namespace svx::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, true),
65  mxFtPosX(m_xBuilder->weld_label("horizontallabel")),
66  mxMtrPosX(m_xBuilder->weld_metric_spin_button("horizontalpos", FieldUnit::CM)),
67  mxFtPosY(m_xBuilder->weld_label("verticallabel")),
68  mxMtrPosY(m_xBuilder->weld_metric_spin_button("verticalpos", FieldUnit::CM)),
69  mxFtWidth(m_xBuilder->weld_label("widthlabel")),
70  mxMtrWidth(m_xBuilder->weld_metric_spin_button("selectwidth", FieldUnit::CM)),
71  mxFtHeight(m_xBuilder->weld_label("heightlabel")),
72  mxMtrHeight(m_xBuilder->weld_metric_spin_button("selectheight", FieldUnit::CM)),
73  mxCbxScale(m_xBuilder->weld_check_button("ratio")),
74  mxFtAngle(m_xBuilder->weld_label("rotationlabel")),
75  mxMtrAngle(m_xBuilder->weld_metric_spin_button("rotation", FieldUnit::DEGREE)),
76  mxCtrlDial(new DialControl(m_xBuilder->weld_scrolled_window("anglepreview"))),
77  mxDial(new weld::CustomWeld(*m_xBuilder, "orientationcontrol", *mxCtrlDial)),
78  mxFtFlip(m_xBuilder->weld_label("fliplabel")),
79  mxFlipTbx(m_xBuilder->weld_toolbar("selectrotationtype")),
80  mxFlipDispatch(new ToolbarUnoDispatcher(*mxFlipTbx, rxFrame)),
81  mxArrangeTbx(m_xBuilder->weld_toolbar("arrangetoolbar")),
82  mxArrangeDispatch(new ToolbarUnoDispatcher(*mxArrangeTbx, rxFrame)),
83  mxBtnEditChart(m_xBuilder->weld_button("btnEditChart")),
84  maRect(),
85  mpView(nullptr),
86  mlOldWidth(1),
87  mlOldHeight(1),
88  mlRotX(0),
89  mlRotY(0),
90  maUIScale(),
91  mePoolUnit(),
92  meDlgUnit(FieldUnit::INCH), // #i124409# init with fallback default
93  maTransfPosXControl(SID_ATTR_TRANSFORM_POS_X, *pBindings, *this),
94  maTransfPosYControl(SID_ATTR_TRANSFORM_POS_Y, *pBindings, *this),
95  maTransfWidthControl(SID_ATTR_TRANSFORM_WIDTH, *pBindings, *this),
96  maTransfHeightControl(SID_ATTR_TRANSFORM_HEIGHT, *pBindings, *this),
97  maSvxAngleControl( SID_ATTR_TRANSFORM_ANGLE, *pBindings, *this),
98  maRotXControl(SID_ATTR_TRANSFORM_ROT_X, *pBindings, *this),
99  maRotYControl(SID_ATTR_TRANSFORM_ROT_Y, *pBindings, *this),
100  maProPosControl(SID_ATTR_TRANSFORM_PROTECT_POS, *pBindings, *this),
101  maProSizeControl(SID_ATTR_TRANSFORM_PROTECT_SIZE, *pBindings, *this),
102  maAutoWidthControl(SID_ATTR_TRANSFORM_AUTOWIDTH, *pBindings, *this),
103  maAutoHeightControl(SID_ATTR_TRANSFORM_AUTOHEIGHT, *pBindings, *this),
104  m_aMetricCtl(SID_ATTR_METRIC, *pBindings, *this),
105  maContext(),
106  mpBindings(pBindings),
107  mbSizeProtected(false),
108  mbPositionProtected(false),
109  mbAutoWidth(false),
110  mbAutoHeight(false),
111  mbAdjustEnabled(false),
112  mxSidebar(rxSidebar)
113 {
114  Initialize();
115 
116  mpBindings->Update( SID_ATTR_METRIC );
117  mpBindings->Update( SID_ATTR_TRANSFORM_WIDTH );
118  mpBindings->Update( SID_ATTR_TRANSFORM_HEIGHT );
119  mpBindings->Update( SID_ATTR_TRANSFORM_PROTECT_SIZE );
120 }
121 
123 {
124  disposeOnce();
125 }
126 
128 {
129  mxFtPosX.reset();
130  mxMtrPosX.reset();
131  mxFtPosY.reset();
132  mxMtrPosY.reset();
133  mxFtWidth.reset();
134  mxMtrWidth.reset();
135  mxFtHeight.reset();
136  mxMtrHeight.reset();
137  mxCbxScale.reset();
138  mxFtAngle.reset();
139  mxMtrAngle.reset();
140  mxDial.reset();
141  mxCtrlDial.reset();
142  mxFtFlip.reset();
143  mxFlipDispatch.reset();
144  mxFlipTbx.reset();
145  mxArrangeDispatch.reset();
146  mxArrangeTbx.reset();
147  mxBtnEditChart.reset();
148 
153 
162 
164 }
165 
166 
167 namespace
168 {
169  bool hasText(const SdrView& rSdrView)
170  {
171  const SdrMarkList& rMarkList = rSdrView.GetMarkedObjectList();
172 
173  if(1 == rMarkList.GetMarkCount())
174  {
175  const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
176  const SdrObjKind eKind(static_cast<SdrObjKind>(pObj->GetObjIdentifier()));
177 
178  if((pObj->GetObjInventor() == SdrInventor::Default) && (OBJ_TEXT == eKind || OBJ_TITLETEXT == eKind || OBJ_OUTLINETEXT == eKind))
179  {
180  const SdrTextObj* pSdrTextObj = dynamic_cast< const SdrTextObj* >(pObj);
181 
182  if(pSdrTextObj && pSdrTextObj->HasText())
183  {
184  return true;
185  }
186  }
187  }
188 
189  return false;
190  }
191 } // end of anonymous namespace
192 
193 
195 {
196  //Position : Horizontal / Vertical
197  mxMtrPosX->connect_value_changed( LINK( this, PosSizePropertyPanel, ChangePosXHdl ) );
198  mxMtrPosY->connect_value_changed( LINK( this, PosSizePropertyPanel, ChangePosYHdl ) );
199 
200  //Size : Width / Height
201  mxMtrWidth->connect_value_changed( LINK( this, PosSizePropertyPanel, ChangeWidthHdl ) );
202  mxMtrHeight->connect_value_changed( LINK( this, PosSizePropertyPanel, ChangeHeightHdl ) );
203 
204  //Size : Keep ratio
205  mxCbxScale->connect_toggled( LINK( this, PosSizePropertyPanel, ClickAutoHdl ) );
206 
207  //rotation control
208  mxCtrlDial->SetLinkedField(mxMtrAngle.get());
209  mxCtrlDial->SetModifyHdl(LINK( this, PosSizePropertyPanel, RotationHdl));
210 
211  //use same logic as DialControl_Impl::SetSize
212  weld::DrawingArea* pDrawingArea = mxCtrlDial->GetDrawingArea();
213  int nDim = (std::min<int>(pDrawingArea->get_approximate_digit_width() * 6,
214  pDrawingArea->get_text_height() * 3) - 1) | 1;
215  Size aSize(nDim, nDim);
216  pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
217  mxCtrlDial->Init(aSize);
218 
219  mxBtnEditChart->connect_clicked( LINK( this, PosSizePropertyPanel, ClickChartEditHdl ) );
220 
222  if ( pCurSh )
223  mpView = pCurSh->GetDrawView();
224  else
225  mpView = nullptr;
226 
227  if ( mpView != nullptr )
228  {
230  mbAdjustEnabled = hasText(*mpView);
231  }
232 
234 }
235 
237  vcl::Window* pParent,
238  const css::uno::Reference<css::frame::XFrame>& rxFrame,
239  SfxBindings* pBindings,
240  const css::uno::Reference<css::ui::XSidebar>& rxSidebar)
241 {
242  if (pParent == nullptr)
243  throw lang::IllegalArgumentException("no parent Window given to PosSizePropertyPanel::Create", nullptr, 0);
244  if ( ! rxFrame.is())
245  throw lang::IllegalArgumentException("no XFrame given to PosSizePropertyPanel::Create", nullptr, 1);
246  if (pBindings == nullptr)
247  throw lang::IllegalArgumentException("no SfxBindings given to PosSizePropertyPanel::Create", nullptr, 2);
248 
250  pParent,
251  rxFrame,
252  pBindings,
253  rxSidebar);
254 }
255 
256 
258  const DataChangedEvent& /*rEvent*/)
259 {
260 }
261 
263  const vcl::EnumContext& rContext)
264 {
265  if (maContext == rContext)
266  {
267  // Nothing to do.
268  return;
269  }
270 
271  maContext = rContext;
272 
273  bool bShowPosition = false;
274  bool bShowAngle = false;
275  bool bShowFlip = false;
276  bool bShowEditChart = false;
277 
279  {
280  case CombinedEnumContext(Application::WriterVariants, Context::Draw):
281  bShowAngle = true;
282  bShowFlip = true;
283  break;
284 
285  case CombinedEnumContext(Application::WriterVariants, Context::Graphic):
286  bShowFlip = true;
287  bShowAngle = true; // RotGrfFlyFrame: Writer FlyFrames for Graphics now support angle
288  break;
289 
290  case CombinedEnumContext(Application::Calc, Context::Draw):
291  case CombinedEnumContext(Application::Calc, Context::DrawLine):
292  case CombinedEnumContext(Application::Calc, Context::Graphic):
293  case CombinedEnumContext(Application::DrawImpress, Context::Draw):
294  case CombinedEnumContext(Application::DrawImpress, Context::DrawLine):
295  case CombinedEnumContext(Application::DrawImpress, Context::TextObject):
296  case CombinedEnumContext(Application::DrawImpress, Context::Graphic):
297  bShowPosition = true;
298  bShowAngle = true;
299  bShowFlip = true;
300  break;
301 
302  case CombinedEnumContext(Application::WriterVariants, Context::OLE):
303  bShowEditChart = true;
304  break;
305 
306  case CombinedEnumContext(Application::Calc, Context::OLE):
307  case CombinedEnumContext(Application::DrawImpress, Context::OLE):
308  bShowPosition = true;
309  bShowEditChart = true;
310  break;
311 
312  case CombinedEnumContext(Application::Calc, Context::Chart):
313  case CombinedEnumContext(Application::Calc, Context::Form):
314  case CombinedEnumContext(Application::Calc, Context::Media):
315  case CombinedEnumContext(Application::Calc, Context::MultiObject):
316  case CombinedEnumContext(Application::DrawImpress, Context::Media):
317  case CombinedEnumContext(Application::DrawImpress, Context::Form):
318  case CombinedEnumContext(Application::DrawImpress, Context::ThreeDObject):
319  case CombinedEnumContext(Application::DrawImpress, Context::MultiObject):
320  bShowPosition = true;
321  break;
322  }
323 
324  // Position
325  mxFtPosX->set_visible(bShowPosition);
326  mxMtrPosX->set_visible(bShowPosition);
327  mxFtPosY->set_visible(bShowPosition);
328  mxMtrPosY->set_visible(bShowPosition);
329 
330  // Rotation
331  mxFtAngle->set_visible(bShowAngle);
332  mxMtrAngle->set_visible(bShowAngle);
333  mxCtrlDial->set_visible(bShowAngle);
334 
335  // Flip
336  mxFtFlip->set_visible(bShowFlip);
337  mxFlipTbx->set_visible(bShowFlip);
338 
339  // Edit Chart
340  mxBtnEditChart->set_visible(bShowEditChart);
341 
342  if (mxSidebar.is())
343  mxSidebar->requestLayout();
344 }
345 
346 
348 {
349  if( mxCbxScale->get_active() &&
350  mxCbxScale->get_sensitive() )
351  {
352  long nHeight = static_cast<long>( (static_cast<double>(mlOldHeight) * static_cast<double>(mxMtrWidth->get_value(FieldUnit::NONE))) / static_cast<double>(mlOldWidth) );
353  if( nHeight <= mxMtrHeight->get_max( FieldUnit::NONE ) )
354  {
355  mxMtrHeight->set_value( nHeight, FieldUnit::NONE );
356  }
357  else
358  {
359  nHeight = static_cast<long>(mxMtrHeight->get_max( FieldUnit::NONE ));
360  mxMtrHeight->set_value(nHeight, FieldUnit::NONE);
361  const long nWidth = static_cast<long>( (static_cast<double>(mlOldWidth) * static_cast<double>(nHeight)) / static_cast<double>(mlOldHeight) );
362  mxMtrWidth->set_value( nWidth, FieldUnit::NONE );
363  }
364  }
365  executeSize();
366 }
367 
368 
370 {
371  if( mxCbxScale->get_active() &&
372  mxCbxScale->get_sensitive() )
373  {
374  long nWidth = static_cast<long>( (static_cast<double>(mlOldWidth) * static_cast<double>(mxMtrHeight->get_value(FieldUnit::NONE))) / static_cast<double>(mlOldHeight) );
375  if( nWidth <= mxMtrWidth->get_max( FieldUnit::NONE ) )
376  {
377  mxMtrWidth->set_value( nWidth, FieldUnit::NONE );
378  }
379  else
380  {
381  nWidth = static_cast<long>(mxMtrWidth->get_max( FieldUnit::NONE ));
382  mxMtrWidth->set_value( nWidth, FieldUnit::NONE );
383  const long nHeight = static_cast<long>( (static_cast<double>(mlOldHeight) * static_cast<double>(nWidth)) / static_cast<double>(mlOldWidth) );
384  mxMtrHeight->set_value( nHeight, FieldUnit::NONE );
385  }
386  }
387  executeSize();
388 }
389 
390 
392 {
393  if ( mxMtrPosX->get_value_changed_from_saved())
394  {
395  long lX = GetCoreValue( *mxMtrPosX, mePoolUnit );
396 
397  Fraction aUIScale = mpView->GetModel()->GetUIScale();
398  lX = long( lX * aUIScale );
399 
400  SfxInt32Item aPosXItem( SID_ATTR_TRANSFORM_POS_X,static_cast<sal_uInt32>(lX));
401 
402  GetBindings()->GetDispatcher()->ExecuteList(
403  SID_ATTR_TRANSFORM, SfxCallMode::RECORD, { &aPosXItem });
404  }
405 }
406 
408 {
409  if ( mxMtrPosY->get_value_changed_from_saved() )
410  {
411  long lY = GetCoreValue( *mxMtrPosY, mePoolUnit );
412 
413  Fraction aUIScale = mpView->GetModel()->GetUIScale();
414  lY = long( lY * aUIScale );
415 
416  SfxInt32Item aPosYItem( SID_ATTR_TRANSFORM_POS_Y,static_cast<sal_uInt32>(lY));
417 
418  GetBindings()->GetDispatcher()->ExecuteList(
419  SID_ATTR_TRANSFORM, SfxCallMode::RECORD, { &aPosYItem });
420  }
421 }
422 
424 {
425  if ( mxCbxScale->get_active() )
426  {
427  mlOldWidth = std::max(GetCoreValue(*mxMtrWidth, mePoolUnit), 1);
428  mlOldHeight = std::max(GetCoreValue(*mxMtrHeight, mePoolUnit), 1);
429  }
430 
431  // mxCbxScale must synchronized with that on Position and Size tabpage on Shape Properties dialog
432  SvtViewOptions aPageOpt(EViewType::TabPage, "cui/ui/possizetabpage/PositionAndSize");
433  aPageOpt.SetUserItem( USERITEM_NAME, css::uno::makeAny( OUString::number( int(mxCbxScale->get_active()) ) ) );
434 }
435 
437 {
438  sal_Int32 nTmp = mxCtrlDial->GetRotation();
439 
440  // #i123993# Need to take UIScale into account when executing rotations
441  const double fUIScale(mpView && mpView->GetModel() ? double(mpView->GetModel()->GetUIScale()) : 1.0);
442  SfxInt32Item aAngleItem( SID_ATTR_TRANSFORM_ANGLE,static_cast<sal_uInt32>(nTmp));
443  SfxInt32Item aRotXItem( SID_ATTR_TRANSFORM_ROT_X, basegfx::fround(mlRotX * fUIScale));
444  SfxInt32Item aRotYItem( SID_ATTR_TRANSFORM_ROT_Y, basegfx::fround(mlRotY * fUIScale));
445 
446  GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM,
447  SfxCallMode::RECORD, { &aAngleItem, &aRotXItem, &aRotYItem });
448 }
449 
451 {
453  if ( pCurSh)
454  {
455  pCurSh->DoVerb( -1 );
456  }
457 }
458 
459 namespace
460 {
461  void limitWidth(weld::MetricSpinButton& rMetricSpinButton)
462  {
463  // space is limited in the sidebar, so limit MetricSpinButtons to a width of 7 digits
464  const int nMaxDigits = 7;
465 
466  weld::SpinButton& rSpinButton = rMetricSpinButton.get_widget();
467  rSpinButton.set_width_chars(std::min(rSpinButton.get_width_chars(), nMaxDigits));
468  }
469 }
470 
472  sal_uInt16 nSID,
473  SfxItemState eState,
474  const SfxPoolItem* pState)
475 {
476  mxFtAngle->set_sensitive(true);
477  mxMtrAngle->set_sensitive(true);
478  mxDial->set_sensitive(true);
479  mxFtFlip->set_sensitive(true);
480  mxFlipTbx->set_sensitive(true);
481 
482  const SfxUInt32Item* pWidthItem;
483  const SfxUInt32Item* pHeightItem;
484 
486  if ( pCurSh )
487  mpView = pCurSh->GetDrawView();
488  else
489  mpView = nullptr;
490 
491  if ( mpView == nullptr )
492  return;
493 
494  mbAdjustEnabled = hasText(*mpView);
495 
496  // Pool unit and dialog unit may have changed, make sure that we
497  // have the current values.
499 
500  switch (nSID)
501  {
502  case SID_ATTR_TRANSFORM_WIDTH:
503  if ( SfxItemState::DEFAULT == eState )
504  {
505  pWidthItem = dynamic_cast< const SfxUInt32Item* >(pState);
506 
507  if(pWidthItem)
508  {
509  long lOldWidth1 = long( pWidthItem->GetValue() / maUIScale );
510  SetFieldUnit( *mxMtrWidth, meDlgUnit, true );
511  SetMetricValue( *mxMtrWidth, lOldWidth1, mePoolUnit );
512  limitWidth(*mxMtrWidth);
513  mlOldWidth = lOldWidth1;
514  mxMtrWidth->save_value();
515  break;
516  }
517  }
518 
519  mxMtrWidth->set_text( "" );
520  break;
521 
522  case SID_ATTR_TRANSFORM_HEIGHT:
523  if ( SfxItemState::DEFAULT == eState )
524  {
525  pHeightItem = dynamic_cast< const SfxUInt32Item* >(pState);
526 
527  if(pHeightItem)
528  {
529  long nTmp = long( pHeightItem->GetValue() / maUIScale);
532  limitWidth(*mxMtrHeight);
533  mlOldHeight = nTmp;
534  mxMtrHeight->save_value();
535  break;
536  }
537  }
538 
539  mxMtrHeight->set_text( "");
540  break;
541 
542  case SID_ATTR_TRANSFORM_POS_X:
543  if(SfxItemState::DEFAULT == eState)
544  {
545  const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState);
546 
547  if(pItem)
548  {
549  long nTmp = long(pItem->GetValue() / maUIScale);
550  SetFieldUnit( *mxMtrPosX, meDlgUnit, true );
552  limitWidth(*mxMtrPosX);
553  mxMtrPosX->save_value();
554  break;
555  }
556  }
557 
558  mxMtrPosX->set_text( "" );
559  break;
560 
561  case SID_ATTR_TRANSFORM_POS_Y:
562  if(SfxItemState::DEFAULT == eState)
563  {
564  const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState);
565 
566  if(pItem)
567  {
568  long nTmp = long(pItem->GetValue() / maUIScale);
569  SetFieldUnit( *mxMtrPosY, meDlgUnit, true );
571  limitWidth(*mxMtrPosY);
572  mxMtrPosY->save_value();
573  break;
574  }
575  }
576 
577  mxMtrPosY->set_text( "" );
578  break;
579 
580  case SID_ATTR_TRANSFORM_ROT_X:
581  if (SfxItemState::DEFAULT == eState)
582  {
583  const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState);
584 
585  if(pItem)
586  {
587  mlRotX = pItem->GetValue();
588  mlRotX = long( mlRotX / maUIScale );
589  }
590  }
591  break;
592 
593  case SID_ATTR_TRANSFORM_ROT_Y:
594  if (SfxItemState::DEFAULT == eState)
595  {
596  const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState);
597 
598  if(pItem)
599  {
600  mlRotY = pItem->GetValue();
601  mlRotY = long( mlRotY / maUIScale );
602  }
603  }
604  break;
605 
606  case SID_ATTR_TRANSFORM_PROTECT_POS:
607  if(SfxItemState::DEFAULT == eState)
608  {
609  const SfxBoolItem* pItem = dynamic_cast< const SfxBoolItem* >(pState);
610 
611  if(pItem)
612  {
613  // record the state of position protect
614  mbPositionProtected = pItem->GetValue();
615  break;
616  }
617  }
618 
619  mbPositionProtected = false;
620  break;
621 
622  case SID_ATTR_TRANSFORM_PROTECT_SIZE:
623  if(SfxItemState::DEFAULT == eState)
624  {
625  const SfxBoolItem* pItem = dynamic_cast< const SfxBoolItem* >(pState);
626 
627  if(pItem)
628  {
629  // record the state of size protect
630  mbSizeProtected = pItem->GetValue();
631  break;
632  }
633  }
634 
635  mbSizeProtected = false;
636  break;
637 
638  case SID_ATTR_TRANSFORM_AUTOWIDTH:
639  if(SfxItemState::DEFAULT == eState)
640  {
641  const SfxBoolItem* pItem = dynamic_cast< const SfxBoolItem* >(pState);
642 
643  if(pItem)
644  {
645  mbAutoWidth = pItem->GetValue();
646  }
647  }
648  break;
649 
650  case SID_ATTR_TRANSFORM_AUTOHEIGHT:
651  if(SfxItemState::DEFAULT == eState)
652  {
653  const SfxBoolItem* pItem = dynamic_cast< const SfxBoolItem* >(pState);
654 
655  if(pItem)
656  {
657  mbAutoHeight = pItem->GetValue();
658  }
659  }
660  break;
661 
662  case SID_ATTR_TRANSFORM_ANGLE:
663  if (eState >= SfxItemState::DEFAULT)
664  {
665  const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState);
666 
667  if(pItem)
668  {
669  long nTmp = pItem->GetValue();
670  nTmp = nTmp < 0 ? 36000+nTmp : nTmp;
671 
672  mxMtrAngle->set_value(nTmp, FieldUnit::DEGREE);
673  mxCtrlDial->SetRotation(nTmp);
674 
675  break;
676  }
677  }
678 
679  mxMtrAngle->set_text( "" );
680  mxCtrlDial->SetRotation( 0 );
681  break;
682 
683  case SID_ATTR_METRIC:
684  MetricState( eState, pState );
685  UpdateUIScale();
686  break;
687 
688  default:
689  break;
690  }
691 
692  const sal_Int32 nCombinedContext(maContext.GetCombinedContext_DI());
693  const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
694 
695  switch (rMarkList.GetMarkCount())
696  {
697  case 0:
698  break;
699 
700  case 1:
701  {
702  const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
703  const SdrObjKind eKind(static_cast<SdrObjKind>(pObj->GetObjIdentifier()));
704 
705  if(((nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::Draw)
706  || nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::TextObject)
707  ) && OBJ_EDGE == eKind)
708  || OBJ_CAPTION == eKind)
709  {
710  mxFtAngle->set_sensitive(false);
711  mxMtrAngle->set_sensitive(false);
712  mxDial->set_sensitive(false);
713  mxFlipTbx->set_sensitive(false);
714  mxFtFlip->set_sensitive(false);
715  }
716  break;
717  }
718 
719  default:
720  {
721  sal_uInt16 nMarkObj = 0;
722  bool isNoEdge = true;
723 
724  while(isNoEdge && rMarkList.GetMark(nMarkObj))
725  {
726  const SdrObject* pObj = rMarkList.GetMark(nMarkObj)->GetMarkedSdrObj();
727  const SdrObjKind eKind(static_cast<SdrObjKind>(pObj->GetObjIdentifier()));
728 
729  if(((nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::Draw)
730  || nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::TextObject)
731  ) && OBJ_EDGE == eKind)
732  || OBJ_CAPTION == eKind)
733  {
734  isNoEdge = false;
735  break;
736  }
737  nMarkObj++;
738  }
739 
740  if(!isNoEdge)
741  {
742  mxFtAngle->set_sensitive(false);
743  mxMtrAngle->set_sensitive(false);
744  mxDial->set_sensitive(false);
745  mxFlipTbx->set_sensitive(false);
746  mxFtFlip->set_sensitive(false);
747  }
748  break;
749  }
750  }
751 
752  if(nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::TextObject))
753  {
754  mxFlipTbx->set_sensitive(false);
755  mxFtFlip->set_sensitive(false);
756  }
757 
758  DisableControls();
759 
760  // mxCbxScale must synchronized with that on Position and Size tabpage on Shape Properties dialog
761  SvtViewOptions aPageOpt(EViewType::TabPage, "cui/ui/possizetabpage/PositionAndSize");
762  OUString sUserData;
763  css::uno::Any aUserItem = aPageOpt.GetUserItem( USERITEM_NAME );
764  OUString aTemp;
765  if ( aUserItem >>= aTemp )
766  sUserData = aTemp;
767  mxCbxScale->set_active(static_cast<bool>(sUserData.toInt32()));
768 }
769 
770 
772 {
773  if ( !mxMtrWidth->get_value_changed_from_saved() && !mxMtrHeight->get_value_changed_from_saved())
774  return;
775 
776  Fraction aUIScale = mpView->GetModel()->GetUIScale();
777 
778  // get Width
779  double nWidth = static_cast<double>(mxMtrWidth->get_value(FieldUnit::MM_100TH));
780  long lWidth = long(nWidth * static_cast<double>(aUIScale));
781  lWidth = OutputDevice::LogicToLogic( lWidth, MapUnit::Map100thMM, mePoolUnit );
782  lWidth = static_cast<long>(mxMtrWidth->denormalize( lWidth ));
783 
784  // get Height
785  double nHeight = static_cast<double>(mxMtrHeight->get_value(FieldUnit::MM_100TH));
786  long lHeight = long(nHeight * static_cast<double>(aUIScale));
787  lHeight = OutputDevice::LogicToLogic( lHeight, MapUnit::Map100thMM, mePoolUnit );
788  lHeight = static_cast<long>(mxMtrHeight->denormalize( lHeight ));
789 
790  // put Width & Height to itemset
791  SfxUInt32Item aWidthItem( SID_ATTR_TRANSFORM_WIDTH, static_cast<sal_uInt32>(lWidth));
792  SfxUInt32Item aHeightItem( SID_ATTR_TRANSFORM_HEIGHT, static_cast<sal_uInt32>(lHeight));
793  SfxUInt16Item aPointItem (SID_ATTR_TRANSFORM_SIZE_POINT, sal_uInt16(RectPoint::LT));
794  const sal_Int32 nCombinedContext(maContext.GetCombinedContext_DI());
795 
796  if( nCombinedContext == CombinedEnumContext(Application::WriterVariants, Context::Graphic)
797  || nCombinedContext == CombinedEnumContext(Application::WriterVariants, Context::OLE)
798  )
799  {
800  GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM,
801  SfxCallMode::RECORD, { &aWidthItem, &aHeightItem, &aPointItem });
802  }
803  else
804  {
805  if ( (mxMtrWidth->get_value_changed_from_saved()) && (mxMtrHeight->get_value_changed_from_saved()))
806  GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM,
807  SfxCallMode::RECORD, { &aWidthItem, &aHeightItem, &aPointItem });
808  else if( mxMtrWidth->get_value_changed_from_saved())
809  GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM,
810  SfxCallMode::RECORD, { &aWidthItem, &aPointItem });
811  else if ( mxMtrHeight->get_value_changed_from_saved())
812  GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM,
813  SfxCallMode::RECORD, { &aHeightItem, &aPointItem });
814  }
815 }
816 
818 {
819  bool bPosXBlank = false;
820  bool bPosYBlank = false;
821  bool bWidthBlank = false;
822  bool bHeightBlank = false;
823 
824  // #i124409# use the given Item to get the correct UI unit and initialize it
825  // and the Fields using it
826  meDlgUnit = GetCurrentUnit(eState,pState);
827 
828  if (mxMtrPosX->get_text().isEmpty())
829  bPosXBlank = true;
830  SetFieldUnit( *mxMtrPosX, meDlgUnit, true );
831  if(bPosXBlank)
832  mxMtrPosX->set_text(OUString());
833 
834  if (mxMtrPosY->get_text().isEmpty())
835  bPosYBlank = true;
836  SetFieldUnit( *mxMtrPosY, meDlgUnit, true );
837  if(bPosYBlank)
838  mxMtrPosY->set_text(OUString());
840 
841  if (mxMtrWidth->get_text().isEmpty())
842  bWidthBlank = true;
843  SetFieldUnit( *mxMtrWidth, meDlgUnit, true );
844  if(bWidthBlank)
845  mxMtrWidth->set_text(OUString());
846 
847  if (mxMtrHeight->get_text().isEmpty())
848  bHeightBlank = true;
850  if(bHeightBlank)
851  mxMtrHeight->set_text(OUString());
852 }
853 
854 
856 {
857  FieldUnit eUnit = FieldUnit::NONE;
858 
859  if ( pState && eState >= SfxItemState::DEFAULT )
860  {
861  eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pState)->GetValue());
862  }
863  else
864  {
866  SfxObjectShell* pSh = nullptr;
867  if ( pFrame )
868  pSh = pFrame->GetObjectShell();
869  if ( pSh )
870  {
871  SfxModule* pModule = pSh->GetModule();
872  if ( pModule )
873  {
874  const SfxPoolItem* pItem = pModule->GetItem( SID_ATTR_METRIC );
875  if ( pItem )
876  eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pItem)->GetValue());
877  }
878  else
879  {
880  SAL_WARN("svx.sidebar", "GetModuleFieldUnit(): no module found");
881  }
882  }
883  }
884 
885  return eUnit;
886 }
887 
888 
890 {
891  if( mbPositionProtected )
892  {
893  // the position is protected("Position protect" option in modal dialog is checked),
894  // disable all the Position controls in sidebar
895  mxFtPosX->set_sensitive(false);
896  mxMtrPosX->set_sensitive(false);
897  mxFtPosY->set_sensitive(false);
898  mxMtrPosY->set_sensitive(false);
899  mxFtAngle->set_sensitive(false);
900  mxMtrAngle->set_sensitive(false);
901  mxDial->set_sensitive(false);
902  mxFtFlip->set_sensitive(false);
903  mxFlipTbx->set_sensitive(false);
904 
905  mxFtWidth->set_sensitive(false);
906  mxMtrWidth->set_sensitive(false);
907  mxFtHeight->set_sensitive(false);
908  mxMtrHeight->set_sensitive(false);
909  mxCbxScale->set_sensitive(false);
910  }
911  else
912  {
913  mxFtPosX->set_sensitive(true);
914  mxMtrPosX->set_sensitive(true);
915  mxFtPosY->set_sensitive(true);
916  mxMtrPosY->set_sensitive(true);
917 
918  if( mbSizeProtected )
919  {
920  mxFtWidth->set_sensitive(false);
921  mxMtrWidth->set_sensitive(false);
922  mxFtHeight->set_sensitive(false);
923  mxMtrHeight->set_sensitive(false);
924  mxCbxScale->set_sensitive(false);
925  }
926  else
927  {
928  if( mbAdjustEnabled )
929  {
930  if( mbAutoWidth )
931  {
932  mxFtWidth->set_sensitive(false);
933  mxMtrWidth->set_sensitive(false);
934  mxCbxScale->set_sensitive(false);
935  }
936  else
937  {
938  mxFtWidth->set_sensitive(true);
939  mxMtrWidth->set_sensitive(true);
940  }
941  if( mbAutoHeight )
942  {
943  mxFtHeight->set_sensitive(false);
944  mxMtrHeight->set_sensitive(false);
945  mxCbxScale->set_sensitive(false);
946  }
947  else
948  {
949  mxFtHeight->set_sensitive(true);
950  mxMtrHeight->set_sensitive(true);
951  }
952  if( !mbAutoWidth && !mbAutoHeight )
953  mxCbxScale->set_sensitive(true);
954  }
955  else
956  {
957  mxFtWidth->set_sensitive(true);
958  mxMtrWidth->set_sensitive(true);
959  mxFtHeight->set_sensitive(true);
960  mxMtrHeight->set_sensitive(true);
961  mxCbxScale->set_sensitive(true);
962  }
963  }
964  }
965 }
966 
968 {
970  if (!pPV)
971  return;
973  pPV->LogicToPagePos(aTmpRect);
975 
976  tools::Rectangle aTmpRect2(mpView->GetWorkArea());
977  pPV->LogicToPagePos(aTmpRect2);
979 
980  const Fraction aUIScale(mpView->GetModel()->GetUIScale());
982  TransfrmHelper::ScaleRect( maRect, aUIScale );
983 
984  const sal_uInt16 nDigits(mxMtrPosX->get_digits());
987 
988  double fLeft(maWorkArea.getMinX());
989  double fTop(maWorkArea.getMinY());
990  double fRight(maWorkArea.getMaxX());
991  double fBottom(maWorkArea.getMaxY());
992 
993  // seems that sidebar defaults to top left reference point
994  // and there's no way to set it to something else
995  fRight -= maRect.getWidth();
996  fBottom -= maRect.getHeight();
997 
998  const double fMaxLong(static_cast<double>(MetricField::ConvertValue( LONG_MAX, 0, MapUnit::Map100thMM, meDlgUnit ) - 1));
999  fLeft = std::clamp(fLeft, -fMaxLong, fMaxLong);
1000  fRight = std::clamp(fRight, -fMaxLong, fMaxLong);
1001  fTop = std::clamp(fTop, - fMaxLong, fMaxLong);
1002  fBottom = std::clamp(fBottom, -fMaxLong, fMaxLong);
1003 
1004  mxMtrPosX->set_range(basegfx::fround64(fLeft), basegfx::fround64(fRight), FieldUnit::NONE);
1005  limitWidth(*mxMtrPosX);
1006  mxMtrPosY->set_range(basegfx::fround64(fTop), basegfx::fround64(fBottom), FieldUnit::NONE);
1007  limitWidth(*mxMtrPosY);
1008 
1009  double fMaxWidth = maWorkArea.getWidth() - (maRect.getWidth() - fLeft);
1010  double fMaxHeight = maWorkArea.getHeight() - (maRect.getHeight() - fTop);
1011  mxMtrWidth->set_max(basegfx::fround64(fMaxWidth*100), FieldUnit::NONE);
1012  limitWidth(*mxMtrWidth);
1013  mxMtrHeight->set_max(basegfx::fround64(fMaxHeight*100), FieldUnit::NONE);
1014  limitWidth(*mxMtrHeight);
1015 }
1016 
1018 {
1019  const Fraction aUIScale (mpView->GetModel()->GetUIScale());
1020  if (maUIScale != aUIScale)
1021  {
1022  // UI scale has changed.
1023 
1024  // Remember the new UI scale.
1025  maUIScale = aUIScale;
1026 
1027  // The content of the position and size boxes is only updated when item changes are notified.
1028  // Request such notifications without changing the actual item values.
1029  GetBindings()->Invalidate(SID_ATTR_TRANSFORM_POS_X, true);
1030  GetBindings()->Invalidate(SID_ATTR_TRANSFORM_POS_Y, true);
1031  GetBindings()->Invalidate(SID_ATTR_TRANSFORM_WIDTH, true);
1032  GetBindings()->Invalidate(SID_ATTR_TRANSFORM_HEIGHT, true);
1033  }
1034 }
1035 
1036 
1037 } // end of namespace svx::sidebar
1038 
1039 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool GetValue() const
long Width() const
void SetUserItem(const OUString &sName, const css::uno::Any &aValue)
std::unique_ptr< weld::MetricSpinButton > mxMtrAngle
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
IMPL_LINK_NOARG(AreaPropertyPanelBase, ToolbarHdl_Impl, const OString &, void)
::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:25
double getHeight() const
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
long Height() const
This control allows to input a rotation angle, visualized by a dial.
Definition: dialcontrol.hxx:75
periodic cubic Spline (ni)
Definition: svdobj.hxx:133
std::unique_ptr< ToolbarUnoDispatcher > mxFlipDispatch
std::unique_ptr< weld::MetricSpinButton > mxMtrHeight
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
virtual int get_width_chars() const =0
std::unique_ptr< weld::MetricSpinButton > mxMtrWidth
virtual void set_width_chars(int nChars)=0
void Invalidate(sal_uInt16 nId)
weld::SpinButton & get_widget()
virtual SfxObjectShell * GetObjectShell() override
double getMaxX() const
virtual bool HasText() const override
Definition: svdotxat.cxx:429
SfxModule * GetModule() const
void LogicToPagePos(Point &rPnt) const
Definition: svdpagv.hxx:210
::sfx2::sidebar::ControllerItem m_aMetricCtl
double getWidth() const
connector object
Definition: svdobj.hxx:139
::sfx2::sidebar::ControllerItem maTransfWidthControl
virtual void NotifyItemUpdate(const sal_uInt16 nSId, const SfxItemState eState, const SfxPoolItem *pState) override
static SfxViewShell * Current()
std::unique_ptr< ToolbarUnoDispatcher > mxArrangeDispatch
double getMaxY() const
std::unique_ptr< weld::Toolbar > mxFlipTbx
B2IRange fround(const B2DRange &rRange)
sal_Int32 GetCombinedContext_DI() const
css::uno::Reference< css::ui::XSidebar > mxSidebar
SdrObject * GetMarkedSdrObj() const
Definition: svdmark.hxx:67
std::unique_ptr< weld::Label > mxFtWidth
const SfxPoolItem * GetItem(sal_uInt16 nSlotId) const
::sfx2::sidebar::ControllerItem maRotYControl
std::unique_ptr< weld::CheckButton > mxCbxScale
virtual sal_uInt16 GetObjIdentifier() const
Definition: svdobj.cxx:585
static void ScaleRect(basegfx::B2DRange &rRange, const Fraction &rUIScale)
std::unique_ptr< weld::Label > mxFtHeight
const SdrMarkList & GetMarkedObjectList() const
Definition: svdmrkv.hxx:243
int GetCoreValue(const weld::MetricSpinButton &rField, MapUnit eUnit)
std::unique_ptr< weld::MetricSpinButton > mxMtrPosX
virtual void DataChanged(const DataChangedEvent &rEvent) override
static FieldUnit GetCurrentUnit(SfxItemState eState, const SfxPoolItem *pState)
std::unique_ptr< weld::Label > mxFtPosY
std::unique_ptr< weld::Label > mxFtPosX
::sfx2::sidebar::ControllerItem maTransfPosYControl
void SetMetricValue(weld::MetricSpinButton &rField, int nCoreValue, MapUnit eUnit)
Abstract DrawObject.
Definition: svdobj.hxx:312
::sfx2::sidebar::ControllerItem maProSizeControl
const tools::Rectangle & GetAllMarkedRect() const
Definition: svdmrkv.hxx:410
const long LONG_MAX
virtual SdrInventor GetObjInventor() const
Definition: svdobj.cxx:580
basegfx::B2DRange b2DRectangleFromRectangle(const ::tools::Rectangle &rRect)
void Update(sal_uInt16 nId)
virtual void dispose() override
Definition: PanelLayout.cxx:52
const Fraction & GetUIScale() const
Definition: svdmodel.hxx:383
TitleText, special text object for StarDraw.
Definition: svdobj.hxx:135
std::unique_ptr< weld::CustomWeld > mxDial
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
std::unique_ptr< weld::MetricSpinButton > mxMtrPosY
virtual int get_text_height() const =0
static VclPtr< reference_type > Create(Arg &&...arg)
virtual ErrCode DoVerb(long nVerb)
std::unique_ptr< weld::Button > mxBtnEditChart
std::unique_ptr< svx::DialControl > mxCtrlDial
css::uno::Any GetUserItem(const OUString &sName) const
UnoViewSharedPtr mpView
::sfx2::sidebar::ControllerItem maRotXControl
virtual SdrView * GetDrawView() const
SdrPageView * GetSdrPageView() const
Definition: svdpntv.hxx:310
std::unique_ptr< weld::Label > mxFtFlip
sal_uInt32 GetValue() const
SfxDispatcher * GetDispatcher() const
#define SAL_WARN(area, stream)
double getMinX() const
::sfx2::sidebar::ControllerItem maAutoWidthControl
IMPL_STATIC_LINK_NOARG(PosSizePropertyPanel, ClickChartEditHdl, weld::Button &, void)
std::unique_ptr< weld::Label > mxFtAngle
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)
std::unique_ptr< weld::Toolbar > mxArrangeTbx
virtual void set_size_request(int nWidth, int nHeight)=0
sal_Int64 fround64(double fVal)
SdrModel * GetModel() const
Definition: svdpntv.hxx:271
const tools::Rectangle & GetWorkArea() const
Definition: svddrgv.hxx:213
text object
Definition: svdobj.hxx:134
virtual float get_approximate_digit_width() const =0
::sfx2::sidebar::ControllerItem maTransfHeightControl
#define CombinedEnumContext(a, e)