workaround segfault in compiler on macos-clang-intel
[LibreOffice.git] / cui / source / tabpages / grfpage.cxx
blob688e03cf5d7e7c6851c10fc2dfeef5a5489f620d
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 <memory>
21 #include <svl/eitem.hxx>
22 #include <svl/stritem.hxx>
23 #include <dialmgr.hxx>
24 #include <svx/dlgutil.hxx>
25 #include <editeng/sizeitem.hxx>
26 #include <editeng/brushitem.hxx>
27 #include <grfpage.hxx>
28 #include <svx/grfcrop.hxx>
29 #include <rtl/ustring.hxx>
30 #include <tools/debug.hxx>
31 #include <tools/fract.hxx>
32 #include <svx/svxids.hrc>
33 #include <strings.hrc>
34 #include <vcl/fieldvalues.hxx>
35 #include <vcl/outdev.hxx>
36 #include <vcl/settings.hxx>
37 #include <vcl/svapp.hxx>
38 #include <svtools/unitconv.hxx>
39 #include <svtools/optionsdrawinglayer.hxx>
40 #include <basegfx/matrix/b2dhommatrix.hxx>
41 #include <basegfx/polygon/b2dpolygontools.hxx>
42 #include <o3tl/unit_conversion.hxx>
43 #include <officecfg/Office/Common.hxx>
45 constexpr auto CM_1_TO_TWIP = o3tl::convert(1, o3tl::Length::cm, o3tl::Length::twip); // 567
48 static int lcl_GetValue(const weld::MetricSpinButton& rMetric, FieldUnit eUnit)
50 return rMetric.denormalize(rMetric.get_value(eUnit));
53 /*--------------------------------------------------------------------
54 description: crop graphic
55 --------------------------------------------------------------------*/
57 SvxGrfCropPage::SvxGrfCropPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet)
58 : SfxTabPage(pPage, pController, u"cui/ui/croppage.ui"_ustr, u"CropPage"_ustr, &rSet)
59 , m_nOldWidth(0)
60 , m_nOldHeight(0)
61 , m_bSetOrigSize(false)
62 , m_aPreferredDPI(0)
63 , m_xCropFrame(m_xBuilder->weld_widget(u"cropframe"_ustr))
64 , m_xZoomConstRB(m_xBuilder->weld_radio_button(u"keepscale"_ustr))
65 , m_xSizeConstRB(m_xBuilder->weld_radio_button(u"keepsize"_ustr))
66 , m_xLeftMF(m_xBuilder->weld_metric_spin_button(u"left"_ustr, FieldUnit::CM))
67 , m_xRightMF(m_xBuilder->weld_metric_spin_button(u"right"_ustr, FieldUnit::CM))
68 , m_xTopMF(m_xBuilder->weld_metric_spin_button(u"top"_ustr, FieldUnit::CM))
69 , m_xBottomMF(m_xBuilder->weld_metric_spin_button(u"bottom"_ustr, FieldUnit::CM))
70 , m_xScaleFrame(m_xBuilder->weld_widget(u"scaleframe"_ustr))
71 , m_xWidthZoomMF(m_xBuilder->weld_metric_spin_button(u"widthzoom"_ustr, FieldUnit::PERCENT))
72 , m_xHeightZoomMF(m_xBuilder->weld_metric_spin_button(u"heightzoom"_ustr, FieldUnit::PERCENT))
73 , m_xSizeFrame(m_xBuilder->weld_widget(u"sizeframe"_ustr))
74 , m_xWidthMF(m_xBuilder->weld_metric_spin_button(u"width"_ustr, FieldUnit::CM))
75 , m_xHeightMF(m_xBuilder->weld_metric_spin_button(u"height"_ustr, FieldUnit::CM))
76 , m_xOrigSizeGrid(m_xBuilder->weld_widget(u"origsizegrid"_ustr))
77 , m_xOrigSizeFT(m_xBuilder->weld_label(u"origsizeft"_ustr))
78 , m_xOrigSizePB(m_xBuilder->weld_button(u"origsize"_ustr))
79 , m_xUncropPB(m_xBuilder->weld_button(u"uncrop"_ustr))
80 , m_xExampleWN(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, m_aExampleWN))
82 SetExchangeSupport();
84 // set the correct metric
85 const FieldUnit eMetric = GetModuleFieldUnit( rSet );
87 SetFieldUnit( *m_xWidthMF, eMetric );
88 SetFieldUnit( *m_xHeightMF, eMetric );
89 SetFieldUnit( *m_xLeftMF, eMetric );
90 SetFieldUnit( *m_xRightMF, eMetric );
91 SetFieldUnit( *m_xTopMF , eMetric );
92 SetFieldUnit( *m_xBottomMF, eMetric );
94 Link<weld::MetricSpinButton&,void> aLk = LINK(this, SvxGrfCropPage, SizeHdl);
95 m_xWidthMF->connect_value_changed( aLk );
96 m_xHeightMF->connect_value_changed( aLk );
98 aLk = LINK(this, SvxGrfCropPage, ZoomHdl);
99 m_xWidthZoomMF->connect_value_changed( aLk );
100 m_xHeightZoomMF->connect_value_changed( aLk );
102 aLk = LINK(this, SvxGrfCropPage, CropModifyHdl);
103 m_xLeftMF->connect_value_changed( aLk );
104 m_xRightMF->connect_value_changed( aLk );
105 m_xTopMF->connect_value_changed( aLk );
106 m_xBottomMF->connect_value_changed( aLk );
108 m_xOrigSizePB->connect_clicked(LINK(this, SvxGrfCropPage, OrigSizeHdl));
109 m_xUncropPB->connect_clicked(LINK(this, SvxGrfCropPage, UncropHdl));
112 SvxGrfCropPage::~SvxGrfCropPage()
114 m_xExampleWN.reset();
117 std::unique_ptr<SfxTabPage> SvxGrfCropPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet)
119 return std::make_unique<SvxGrfCropPage>(pPage, pController, *rSet);
122 void SvxGrfCropPage::Reset( const SfxItemSet *rSet )
124 const SfxPoolItem* pItem;
125 const SfxItemPool& rPool = *rSet->GetPool();
127 if(SfxItemState::SET == rSet->GetItemState( rPool.GetWhichIDFromSlotID(
128 SID_ATTR_GRAF_KEEP_ZOOM ), true, &pItem ))
130 if( static_cast<const SfxBoolItem*>(pItem)->GetValue() )
131 m_xZoomConstRB->set_active(true);
132 else
133 m_xSizeConstRB->set_active(true);
134 m_xZoomConstRB->save_state();
137 sal_uInt16 nW = rPool.GetWhichIDFromSlotID( SID_ATTR_GRAF_CROP );
138 if( SfxItemState::SET == rSet->GetItemState( nW, true, &pItem))
140 FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW ));
142 const SvxGrfCrop* pCrop = static_cast<const SvxGrfCrop*>(pItem);
144 m_aExampleWN.SetLeft(pCrop->GetLeft());
145 m_aExampleWN.SetRight(pCrop->GetRight());
146 m_aExampleWN.SetTop(pCrop->GetTop());
147 m_aExampleWN.SetBottom(pCrop->GetBottom());
149 m_xLeftMF->set_value( m_xLeftMF->normalize( pCrop->GetLeft()), eUnit );
150 m_xRightMF->set_value( m_xRightMF->normalize( pCrop->GetRight()), eUnit );
151 m_xTopMF->set_value( m_xTopMF->normalize( pCrop->GetTop()), eUnit );
152 m_xBottomMF->set_value( m_xBottomMF->normalize( pCrop->GetBottom()), eUnit );
154 else
156 m_xLeftMF->set_value(0, FieldUnit::NONE);
157 m_xRightMF->set_value(0, FieldUnit::NONE);
158 m_xTopMF->set_value(0, FieldUnit::NONE);
159 m_xBottomMF->set_value(0, FieldUnit::NONE);
162 m_xLeftMF->save_value();
163 m_xRightMF->save_value();
164 m_xTopMF->save_value();
165 m_xBottomMF->save_value();
167 nW = rPool.GetWhichIDFromSlotID( SID_ATTR_PAGE_SIZE );
168 if ( SfxItemState::SET == rSet->GetItemState( nW, false, &pItem ) )
170 // orientation and size from the PageItem
171 FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW ));
173 m_aPageSize = static_cast<const SvxSizeItem*>(pItem)->GetSize();
175 auto nMin = m_xWidthMF->normalize( 23 );
176 auto nMax = m_xHeightMF->normalize(m_aPageSize.Height());
177 m_xHeightMF->set_range(nMin, nMax, eUnit);
178 nMax = m_xWidthMF->normalize(m_aPageSize.Width());
179 m_xWidthMF->set_range(nMin, nMax, eUnit);
181 else
183 m_aPageSize = OutputDevice::LogicToLogic(
184 Size( CM_1_TO_TWIP, CM_1_TO_TWIP ),
185 MapMode( MapUnit::MapTwip ),
186 MapMode( rSet->GetPool()->GetMetric( nW ) ) );
189 bool bFound = false;
190 if( const SvxBrushItem* pGraphicItem = rSet->GetItemIfSet( SID_ATTR_GRAF_GRAPHIC, false ) )
192 OUString referer;
193 SfxStringItem const * it = rSet->GetItem(SID_REFERER);
194 if (it != nullptr) {
195 referer = it->GetValue();
197 const Graphic* pGrf = pGraphicItem->GetGraphic(referer);
198 if( pGrf )
200 m_aOrigSize = GetGrfOrigSize( *pGrf );
201 if (pGrf->GetType() == GraphicType::Bitmap && m_aOrigSize.Width() && m_aOrigSize.Height())
203 m_aOrigPixelSize = pGrf->GetSizePixel();
206 if( m_aOrigSize.Width() && m_aOrigSize.Height() )
208 CalcMinMaxBorder();
209 m_aExampleWN.SetGraphic( *pGrf );
210 m_aExampleWN.SetFrameSize( m_aOrigSize );
212 bFound = true;
213 if( !pGraphicItem->GetGraphicLink().isEmpty() )
214 m_aGraphicName = pGraphicItem->GetGraphicLink();
219 GraphicHasChanged( bFound );
220 ActivatePage( *rSet );
223 bool SvxGrfCropPage::FillItemSet(SfxItemSet *rSet)
225 const SfxItemPool& rPool = *rSet->GetPool();
226 bool bModified = false;
227 if( m_xWidthMF->get_value_changed_from_saved() ||
228 m_xHeightMF->get_value_changed_from_saved() )
230 constexpr TypedWhichId<SvxSizeItem> nW = SID_ATTR_GRAF_FRMSIZE;
231 FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW ));
233 std::shared_ptr<SvxSizeItem> aSz(std::make_shared<SvxSizeItem>(nW));
235 // size could already have been set from another page
236 const SfxItemSet* pExSet = GetDialogExampleSet();
237 const SvxSizeItem* pSizeItem = nullptr;
238 if( pExSet && (pSizeItem = pExSet->GetItemIfSet( nW, false )) )
240 aSz.reset(pSizeItem->Clone());
242 else
244 aSz.reset(GetItemSet().Get(nW).Clone());
247 Size aTmpSz( aSz->GetSize() );
248 if( m_xWidthMF->get_value_changed_from_saved() )
249 aTmpSz.setWidth( lcl_GetValue( *m_xWidthMF, eUnit ) );
250 if( m_xHeightMF->get_value_changed_from_saved() )
251 aTmpSz.setHeight( lcl_GetValue( *m_xHeightMF, eUnit ) );
252 aSz->SetSize( aTmpSz );
253 m_xWidthMF->save_value();
254 m_xHeightMF->save_value();
256 bModified |= nullptr != rSet->Put( *aSz );
258 if (m_bSetOrigSize)
260 bModified |= nullptr != rSet->Put( SvxSizeItem( rPool.GetWhichIDFromSlotID(
261 SID_ATTR_GRAF_FRMSIZE_PERCENT ), Size( 0, 0 )) );
264 if( m_xLeftMF->get_value_changed_from_saved() || m_xRightMF->get_value_changed_from_saved() ||
265 m_xTopMF->get_value_changed_from_saved() || m_xBottomMF->get_value_changed_from_saved() )
267 sal_uInt16 nW = rPool.GetWhichIDFromSlotID( SID_ATTR_GRAF_CROP );
268 FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW ));
269 std::unique_ptr<SvxGrfCrop> pNew(static_cast<SvxGrfCrop*>(rSet->Get( nW ).Clone()));
271 pNew->SetLeft( lcl_GetValue( *m_xLeftMF, eUnit ) );
272 pNew->SetRight( lcl_GetValue( *m_xRightMF, eUnit ) );
273 pNew->SetTop( lcl_GetValue( *m_xTopMF, eUnit ) );
274 pNew->SetBottom( lcl_GetValue( *m_xBottomMF, eUnit ) );
275 bModified |= nullptr != rSet->Put( std::move(pNew) );
278 if( m_xZoomConstRB->get_state_changed_from_saved() )
280 bModified |= nullptr != rSet->Put( SfxBoolItem( rPool.GetWhichIDFromSlotID(
281 SID_ATTR_GRAF_KEEP_ZOOM), m_xZoomConstRB->get_active() ) );
284 return bModified;
287 void SvxGrfCropPage::ActivatePage(const SfxItemSet& rSet)
289 #ifdef DBG_UTIL
290 SfxItemPool* pPool = GetItemSet().GetPool();
291 DBG_ASSERT( pPool, "Where is the pool?" );
292 #endif
294 auto& aProperties = getAdditionalProperties();
295 auto aIterator = aProperties.find(u"PreferredDPI"_ustr);
296 if (aIterator != aProperties.end())
297 m_aPreferredDPI = aIterator->second.get<sal_Int32>();
299 m_bSetOrigSize = false;
301 // Size
302 Size aSize;
303 if( const SvxSizeItem* pFrmSizeItem = rSet.GetItemIfSet( SID_ATTR_GRAF_FRMSIZE, false ) )
304 aSize = pFrmSizeItem->GetSize();
306 m_nOldWidth = aSize.Width();
307 m_nOldHeight = aSize.Height();
309 auto nWidth = m_xWidthMF->normalize(m_nOldWidth);
310 auto nHeight = m_xHeightMF->normalize(m_nOldHeight);
312 if (nWidth != m_xWidthMF->get_value(FieldUnit::TWIP))
313 m_xWidthMF->set_value(nWidth, FieldUnit::TWIP);
314 m_xWidthMF->save_value();
316 if (nHeight != m_xHeightMF->get_value(FieldUnit::TWIP))
317 m_xHeightMF->set_value(nHeight, FieldUnit::TWIP);
318 m_xHeightMF->save_value();
320 if( const SvxBrushItem* pBrushItem = rSet.GetItemIfSet( SID_ATTR_GRAF_GRAPHIC, false ) )
322 if( !pBrushItem->GetGraphicLink().isEmpty() &&
323 m_aGraphicName != pBrushItem->GetGraphicLink() )
324 m_aGraphicName = pBrushItem->GetGraphicLink();
326 OUString referer;
327 SfxStringItem const * it = rSet.GetItem(SID_REFERER);
328 if (it != nullptr) {
329 referer = it->GetValue();
331 const Graphic* pGrf = pBrushItem->GetGraphic(referer);
332 if( pGrf )
334 m_aExampleWN.SetGraphic( *pGrf );
335 m_aOrigSize = GetGrfOrigSize( *pGrf );
336 if (pGrf->GetType() == GraphicType::Bitmap && m_aOrigSize.Width() > 1 && m_aOrigSize.Height() > 1) {
337 m_aOrigPixelSize = pGrf->GetSizePixel();
339 m_aExampleWN.SetFrameSize(m_aOrigSize);
340 GraphicHasChanged( m_aOrigSize.Width() && m_aOrigSize.Height() );
341 CalcMinMaxBorder();
343 else
344 GraphicHasChanged( false );
347 CalcZoom();
350 DeactivateRC SvxGrfCropPage::DeactivatePage(SfxItemSet *_pSet)
352 if ( _pSet )
353 FillItemSet( _pSet );
354 return DeactivateRC::LeavePage;
357 /*--------------------------------------------------------------------
358 description: scale changed, adjust size
359 --------------------------------------------------------------------*/
361 IMPL_LINK( SvxGrfCropPage, ZoomHdl, weld::MetricSpinButton&, rField, void )
363 SfxItemPool* pPool = GetItemSet().GetPool();
364 assert(pPool && "Where is the pool?");
365 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhichIDFromSlotID(
366 SID_ATTR_GRAF_CROP ) ) );
368 if (&rField == m_xWidthZoomMF.get())
370 tools::Long nLRBorders = lcl_GetValue(*m_xLeftMF, eUnit)
371 +lcl_GetValue(*m_xRightMF, eUnit);
372 m_xWidthMF->set_value( m_xWidthMF->normalize(
373 ((m_aOrigSize.Width() - nLRBorders) * rField.get_value(FieldUnit::NONE))/100),
374 eUnit);
376 else
378 tools::Long nULBorders = lcl_GetValue(*m_xTopMF, eUnit)
379 +lcl_GetValue(*m_xBottomMF, eUnit);
380 m_xHeightMF->set_value( m_xHeightMF->normalize(
381 ((m_aOrigSize.Height() - nULBorders ) * rField.get_value(FieldUnit::NONE))/100) ,
382 eUnit );
386 /*--------------------------------------------------------------------
387 description: change size, adjust scale
388 --------------------------------------------------------------------*/
390 IMPL_LINK( SvxGrfCropPage, SizeHdl, weld::MetricSpinButton&, rField, void )
392 SfxItemPool* pPool = GetItemSet().GetPool();
393 assert(pPool && "Where is the pool?");
394 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhichIDFromSlotID(
395 SID_ATTR_GRAF_CROP ) ) );
397 Size aSize( lcl_GetValue(*m_xWidthMF, eUnit),
398 lcl_GetValue(*m_xHeightMF, eUnit) );
400 if(&rField == m_xWidthMF.get())
402 tools::Long nWidth = m_aOrigSize.Width() -
403 ( lcl_GetValue(*m_xLeftMF, eUnit) +
404 lcl_GetValue(*m_xRightMF, eUnit) );
405 if(!nWidth)
406 nWidth++;
407 sal_uInt16 nZoom = static_cast<sal_uInt16>( aSize.Width() * 100 / nWidth);
408 m_xWidthZoomMF->set_value(nZoom, FieldUnit::NONE);
410 else
412 tools::Long nHeight = m_aOrigSize.Height() -
413 ( lcl_GetValue(*m_xTopMF, eUnit) +
414 lcl_GetValue(*m_xBottomMF, eUnit));
415 if(!nHeight)
416 nHeight++;
417 sal_uInt16 nZoom = static_cast<sal_uInt16>( aSize.Height() * 100 / nHeight);
418 m_xHeightZoomMF->set_value(nZoom, FieldUnit::NONE);
422 /*--------------------------------------------------------------------
423 description: evaluate border
424 --------------------------------------------------------------------*/
426 IMPL_LINK( SvxGrfCropPage, CropModifyHdl, weld::MetricSpinButton&, rField, void )
428 SfxItemPool* pPool = GetItemSet().GetPool();
429 assert(pPool && "Where is the pool?");
430 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhichIDFromSlotID(
431 SID_ATTR_GRAF_CROP ) ) );
433 bool bZoom = m_xZoomConstRB->get_active();
434 if (&rField == m_xLeftMF.get() || &rField == m_xRightMF.get())
436 tools::Long nLeft = lcl_GetValue( *m_xLeftMF, eUnit );
437 tools::Long nRight = lcl_GetValue( *m_xRightMF, eUnit );
438 tools::Long nWidthZoom = static_cast<tools::Long>(m_xWidthZoomMF->get_value(FieldUnit::NONE));
439 if (bZoom && nWidthZoom != 0 && ( ( ( m_aOrigSize.Width() - (nLeft + nRight )) * nWidthZoom )
440 / 100 >= m_aPageSize.Width() ) )
442 if (&rField == m_xLeftMF.get())
444 nLeft = m_aOrigSize.Width() -
445 ( m_aPageSize.Width() * 100 / nWidthZoom + nRight );
446 m_xLeftMF->set_value( m_xLeftMF->normalize( nLeft ), eUnit );
448 else
450 nRight = m_aOrigSize.Width() -
451 ( m_aPageSize.Width() * 100 / nWidthZoom + nLeft );
452 m_xRightMF->set_value( m_xRightMF->normalize( nRight ), eUnit );
455 if (AllSettings::GetLayoutRTL())
457 m_aExampleWN.SetLeft(nRight);
458 m_aExampleWN.SetRight(nLeft);
460 else
462 m_aExampleWN.SetLeft(nLeft);
463 m_aExampleWN.SetRight(nRight);
465 if(bZoom)
467 // scale stays, recompute width
468 ZoomHdl(*m_xWidthZoomMF);
471 else
473 tools::Long nTop = lcl_GetValue( *m_xTopMF, eUnit );
474 tools::Long nBottom = lcl_GetValue( *m_xBottomMF, eUnit );
475 tools::Long nHeightZoom = static_cast<tools::Long>(m_xHeightZoomMF->get_value(FieldUnit::NONE));
476 if(bZoom && ( ( ( m_aOrigSize.Height() - (nTop + nBottom )) * nHeightZoom)
477 / 100 >= m_aPageSize.Height()))
479 assert(nHeightZoom && "div-by-zero");
480 if(&rField == m_xTopMF.get())
482 nTop = m_aOrigSize.Height() -
483 ( m_aPageSize.Height() * 100 / nHeightZoom + nBottom);
484 m_xTopMF->set_value( m_xWidthMF->normalize( nTop ), eUnit );
486 else
488 nBottom = m_aOrigSize.Height() -
489 ( m_aPageSize.Height() * 100 / nHeightZoom + nTop);
490 m_xBottomMF->set_value( m_xWidthMF->normalize( nBottom ), eUnit );
493 m_aExampleWN.SetTop( nTop );
494 m_aExampleWN.SetBottom( nBottom );
495 if(bZoom)
497 // scale stays, recompute height
498 ZoomHdl(*m_xHeightZoomMF);
501 m_aExampleWN.Invalidate();
502 // size and border changed -> recompute scale
503 if(!bZoom)
504 CalcZoom();
505 CalcMinMaxBorder();
507 /*--------------------------------------------------------------------
508 description: set original size
509 --------------------------------------------------------------------*/
511 IMPL_LINK_NOARG(SvxGrfCropPage, OrigSizeHdl, weld::Button&, void)
513 SfxItemPool* pPool = GetItemSet().GetPool();
514 assert(pPool && "Where is the pool?");
515 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhichIDFromSlotID(
516 SID_ATTR_GRAF_CROP ) ) );
518 tools::Long nWidth = m_aOrigSize.Width() -
519 lcl_GetValue( *m_xLeftMF, eUnit ) -
520 lcl_GetValue( *m_xRightMF, eUnit );
521 m_xWidthMF->set_value( m_xWidthMF->normalize( nWidth ), eUnit );
522 tools::Long nHeight = m_aOrigSize.Height() -
523 lcl_GetValue( *m_xTopMF, eUnit ) -
524 lcl_GetValue( *m_xBottomMF, eUnit );
525 m_xHeightMF->set_value( m_xHeightMF->normalize( nHeight ), eUnit );
526 m_xWidthZoomMF->set_value(100, FieldUnit::NONE);
527 m_xHeightZoomMF->set_value(100, FieldUnit::NONE);
528 m_bSetOrigSize = true;
531 /*--------------------------------------------------------------------
532 description: reset crop
533 --------------------------------------------------------------------*/
535 IMPL_LINK_NOARG(SvxGrfCropPage, UncropHdl, weld::Button&, void)
537 SfxItemPool* pPool = GetItemSet().GetPool();
538 DBG_ASSERT( pPool, "Where is the pool?" );
540 m_xLeftMF->set_value(0, FieldUnit::NONE);
541 m_xRightMF->set_value(0, FieldUnit::NONE);
542 m_xTopMF->set_value(0, FieldUnit::NONE);
543 m_xBottomMF->set_value(0, FieldUnit::NONE);
545 m_aExampleWN.SetLeft(0);
546 m_aExampleWN.SetRight(0);
547 m_aExampleWN.SetTop(0);
548 m_aExampleWN.SetBottom(0);
550 m_aExampleWN.Invalidate();
551 CalcMinMaxBorder();
556 /*--------------------------------------------------------------------
557 description: compute scale
558 --------------------------------------------------------------------*/
560 void SvxGrfCropPage::CalcZoom()
562 SfxItemPool* pPool = GetItemSet().GetPool();
563 assert(pPool && "Where is the pool?");
564 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhichIDFromSlotID(
565 SID_ATTR_GRAF_CROP ) ) );
567 tools::Long nWidth = lcl_GetValue( *m_xWidthMF, eUnit );
568 tools::Long nHeight = lcl_GetValue( *m_xHeightMF, eUnit );
569 tools::Long nLRBorders = lcl_GetValue( *m_xLeftMF, eUnit ) +
570 lcl_GetValue( *m_xRightMF, eUnit );
571 tools::Long nULBorders = lcl_GetValue( *m_xTopMF, eUnit ) +
572 lcl_GetValue( *m_xBottomMF, eUnit );
573 sal_uInt16 nZoom = 0;
574 tools::Long nDen;
575 if( (nDen = m_aOrigSize.Width() - nLRBorders) > 0)
576 nZoom = static_cast<sal_uInt16>((( nWidth * 1000 / nDen )+5)/10);
577 m_xWidthZoomMF->set_value(nZoom, FieldUnit::NONE);
578 if( (nDen = m_aOrigSize.Height() - nULBorders) > 0)
579 nZoom = static_cast<sal_uInt16>((( nHeight * 1000 / nDen )+5)/10);
580 else
581 nZoom = 0;
582 m_xHeightZoomMF->set_value(nZoom, FieldUnit::NONE);
585 /*--------------------------------------------------------------------
586 description: set minimum/maximum values for the margins
587 --------------------------------------------------------------------*/
589 void SvxGrfCropPage::CalcMinMaxBorder()
591 SfxItemPool* pPool = GetItemSet().GetPool();
592 assert(pPool && "Where is the pool?");
593 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhichIDFromSlotID(
594 SID_ATTR_GRAF_CROP ) ) );
595 tools::Long nR = lcl_GetValue(*m_xRightMF, eUnit );
596 tools::Long nMinWidth = (m_aOrigSize.Width() * 10) /11;
597 tools::Long nMin = nMinWidth - (nR >= 0 ? nR : 0);
598 m_xLeftMF->set_max( m_xLeftMF->normalize(nMin), eUnit );
600 tools::Long nL = lcl_GetValue(*m_xLeftMF, eUnit );
601 nMin = nMinWidth - (nL >= 0 ? nL : 0);
602 m_xRightMF->set_max( m_xRightMF->normalize(nMin), eUnit );
604 tools::Long nUp = lcl_GetValue( *m_xTopMF, eUnit );
605 tools::Long nMinHeight = (m_aOrigSize.Height() * 10) /11;
606 nMin = nMinHeight - (nUp >= 0 ? nUp : 0);
607 m_xBottomMF->set_max( m_xBottomMF->normalize(nMin), eUnit );
609 tools::Long nLow = lcl_GetValue(*m_xBottomMF, eUnit );
610 nMin = nMinHeight - (nLow >= 0 ? nLow : 0);
611 m_xTopMF->set_max( m_xTopMF->normalize(nMin), eUnit );
613 /*--------------------------------------------------------------------
614 description: set spinsize to 1/20 of the original size,
615 fill FixedText with the original size
616 --------------------------------------------------------------------*/
618 void SvxGrfCropPage::GraphicHasChanged( bool bFound )
620 if( bFound )
622 SfxItemPool* pPool = GetItemSet().GetPool();
623 assert(pPool && "Where is the pool?");
624 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhichIDFromSlotID(
625 SID_ATTR_GRAF_CROP ) ));
627 sal_Int64 nSpin = m_xLeftMF->normalize(m_aOrigSize.Width()) / 20;
628 nSpin = vcl::ConvertValue( nSpin, m_aOrigSize.Width(), 0,
629 eUnit, m_xLeftMF->get_unit());
631 // if the margin is too big, it is set to 1/3 on both pages
632 tools::Long nR = lcl_GetValue( *m_xRightMF, eUnit );
633 tools::Long nL = lcl_GetValue( *m_xLeftMF, eUnit );
634 if((nL + nR) < - m_aOrigSize.Width())
636 tools::Long nVal = m_aOrigSize.Width() / -3;
637 m_xRightMF->set_value( m_xRightMF->normalize( nVal ), eUnit );
638 m_xLeftMF->set_value( m_xLeftMF->normalize( nVal ), eUnit );
639 m_aExampleWN.SetLeft(nVal);
640 m_aExampleWN.SetRight(nVal);
642 tools::Long nUp = lcl_GetValue(*m_xTopMF, eUnit );
643 tools::Long nLow = lcl_GetValue(*m_xBottomMF, eUnit );
644 if((nUp + nLow) < - m_aOrigSize.Height())
646 tools::Long nVal = m_aOrigSize.Height() / -3;
647 m_xTopMF->set_value( m_xTopMF->normalize( nVal ), eUnit );
648 m_xBottomMF->set_value( m_xBottomMF->normalize( nVal ), eUnit );
649 m_aExampleWN.SetTop(nVal);
650 m_aExampleWN.SetBottom(nVal);
653 m_xLeftMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE);
654 m_xRightMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE);
655 nSpin = m_xTopMF->normalize(m_aOrigSize.Height()) / 20;
656 nSpin = vcl::ConvertValue( nSpin, m_aOrigSize.Width(), 0,
657 eUnit, m_xLeftMF->get_unit() );
658 m_xTopMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE);
659 m_xBottomMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE);
661 // display original size
662 const FieldUnit eMetric = GetModuleFieldUnit( GetItemSet() );
664 OUString sTemp;
666 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), u"cui/ui/spinbox.ui"_ustr));
667 std::unique_ptr<weld::Dialog> xTopLevel(xBuilder->weld_dialog(u"SpinDialog"_ustr));
668 std::unique_ptr<weld::MetricSpinButton> xFld(xBuilder->weld_metric_spin_button(u"spin"_ustr, FieldUnit::CM));
669 SetFieldUnit( *xFld, eMetric );
670 xFld->set_digits(m_xWidthMF->get_digits());
671 xFld->set_max(INT_MAX - 1, FieldUnit::NONE);
673 xFld->set_value(xFld->normalize(m_aOrigSize.Width()), eUnit);
674 sTemp = xFld->get_text();
675 xFld->set_value(xFld->normalize(m_aOrigSize.Height()), eUnit);
676 // multiplication sign (U+00D7)
677 sTemp += u"\u00D7" + xFld->get_text();
680 if ( m_aOrigPixelSize.Width() && m_aOrigPixelSize.Height() ) {
681 sal_Int32 ax = 0.5 + m_aOrigPixelSize.Width() /
682 o3tl::convert<double>(m_aOrigSize.Width(), o3tl::Length::twip,
683 o3tl::Length::in);
684 sal_Int32 ay = 0.5 + m_aOrigPixelSize.Height() /
685 o3tl::convert<double>(m_aOrigSize.Height(), o3tl::Length::twip,
686 o3tl::Length::in);
687 OUString sPPI = OUString::number(ax);
688 if (abs(ax - ay) > 1) {
689 sPPI += u"\u00D7" + OUString::number(ay);
691 sTemp += " " + CuiResId(RID_CUISTR_PPI).replaceAll("%1", sPPI);
693 sTemp += "\n" + OUString::number(m_aOrigPixelSize.Width()) + u"\u00D7" + OUString::number(m_aOrigPixelSize.Height()) + " px";
694 m_xOrigSizeFT->set_label(sTemp);
697 m_xCropFrame->set_sensitive(bFound);
698 m_xScaleFrame->set_sensitive(bFound);
699 m_xSizeFrame->set_sensitive(bFound);
700 m_xOrigSizeGrid->set_sensitive(bFound);
701 m_xZoomConstRB->set_sensitive(bFound);
704 Size SvxGrfCropPage::GetGrfOrigSize(const Graphic& rGrf)
706 Size aSize;
708 if (m_aPreferredDPI > 0)
710 Size aPixelSize = rGrf.GetSizePixel();
711 double fWidth = aPixelSize.Width() / double(m_aPreferredDPI);
712 double fHeight = aPixelSize.Height() / double(m_aPreferredDPI);
713 fWidth = o3tl::convert(fWidth, o3tl::Length::in, o3tl::Length::twip);
714 fHeight = o3tl::convert(fHeight, o3tl::Length::in, o3tl::Length::twip);
715 aSize = Size(fWidth, fHeight);
717 else
719 const MapMode aMapTwip( MapUnit::MapTwip );
720 aSize = rGrf.GetPrefSize();
721 if( MapUnit::MapPixel == rGrf.GetPrefMapMode().GetMapUnit() )
722 aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMapTwip);
723 else
724 aSize = OutputDevice::LogicToLogic( aSize,
725 rGrf.GetPrefMapMode(), aMapTwip );
727 return aSize;
730 /*****************************************************************/
732 SvxCropExample::SvxCropExample()
733 : m_aTopLeft(0, 0)
734 , m_aBottomRight(0, 0)
738 void SvxCropExample::SetDrawingArea(weld::DrawingArea* pDrawingArea)
740 CustomWidgetController::SetDrawingArea(pDrawingArea);
741 OutputDevice& rDevice = pDrawingArea->get_ref_device();
742 Size aSize(rDevice.LogicToPixel(Size(78, 78), MapMode(MapUnit::MapAppFont)));
743 pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
745 m_aMapMode = rDevice.GetMapMode();
746 m_aFrameSize = OutputDevice::LogicToLogic(
747 Size(CM_1_TO_TWIP / 2, CM_1_TO_TWIP / 2),
748 MapMode(MapUnit::MapTwip), m_aMapMode);
751 void SvxCropExample::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&)
753 rRenderContext.Push(vcl::PushFlags::MAPMODE);
754 rRenderContext.SetMapMode(m_aMapMode);
756 // Win BG
757 const Size aWinSize(rRenderContext.PixelToLogic(GetOutputSizePixel()));
758 rRenderContext.SetLineColor();
759 rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetWindowColor());
760 rRenderContext.DrawRect(::tools::Rectangle(Point(), aWinSize));
762 // use AA, the Graphic may be a metafile/svg and would then look ugly
763 rRenderContext.SetAntialiasing(AntialiasingFlags::Enable);
765 // draw Graphic
766 ::tools::Rectangle aRect(
767 Point((aWinSize.Width() - m_aFrameSize.Width())/2, (aWinSize.Height() - m_aFrameSize.Height())/2),
768 m_aFrameSize);
769 m_aGrf.Draw(rRenderContext, aRect.TopLeft(), aRect.GetSize());
771 // Remove one more case that uses XOR paint (RasterOp::Invert).
772 // Get colors and logic DashLength from settings, use equal to
773 // PolygonMarkerPrimitive2D, may be changed to that primitive later.
774 // Use this to guarantee good visibility - that was the purpose of
775 // the former used XOR paint.
776 const Color aColA(SvtOptionsDrawinglayer::GetStripeColorA().getBColor());
777 const Color aColB(SvtOptionsDrawinglayer::GetStripeColorB().getBColor());
778 const double fStripeLength(officecfg::Office::Common::Drawinglayer::StripeLength::get());
779 const basegfx::B2DVector aDashVector(rRenderContext.GetInverseViewTransformation() * basegfx::B2DVector(fStripeLength, 0.0));
780 const double fLogicDashLength(aDashVector.getX());
782 // apply current crop settings
783 aRect.AdjustLeft(m_aTopLeft.Y());
784 aRect.AdjustTop(m_aTopLeft.X());
785 aRect.AdjustRight(-m_aBottomRight.Y());
786 aRect.AdjustBottom(-m_aBottomRight.X());
788 // apply dash with direct paint callbacks
789 basegfx::utils::applyLineDashing(
790 basegfx::utils::createPolygonFromRect(
791 basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom())),
792 std::vector< double >(2, fLogicDashLength),
793 [&aColA,&rRenderContext](const basegfx::B2DPolygon& rSnippet)
795 rRenderContext.SetLineColor(aColA);
796 rRenderContext.DrawPolyLine(rSnippet);
798 [&aColB,&rRenderContext](const basegfx::B2DPolygon& rSnippet)
800 rRenderContext.SetLineColor(aColB);
801 rRenderContext.DrawPolyLine(rSnippet);
803 2.0 * fLogicDashLength);
805 rRenderContext.Pop();
808 void SvxCropExample::Resize()
810 SetFrameSize(m_aFrameSize);
813 void SvxCropExample::SetFrameSize( const Size& rSz )
815 m_aFrameSize = rSz;
816 if (!m_aFrameSize.Width())
817 m_aFrameSize.setWidth( 1 );
818 if (!m_aFrameSize.Height())
819 m_aFrameSize.setHeight( 1 );
820 Size aWinSize( GetOutputSizePixel() );
821 Fraction aXScale( aWinSize.Width() * 4, m_aFrameSize.Width() * 5 );
822 Fraction aYScale( aWinSize.Height() * 4, m_aFrameSize.Height() * 5 );
824 if( aYScale < aXScale )
825 aXScale = aYScale;
827 m_aMapMode.SetScaleX(aXScale);
828 m_aMapMode.SetScaleY(aXScale);
830 Invalidate();
833 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */