1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
44 constexpr auto CM_1_TO_TWIP
= o3tl::convert(1, o3tl::Length::cm
, o3tl::Length::twip
); // 567
47 static int lcl_GetValue(const weld::MetricSpinButton
& rMetric
, FieldUnit eUnit
)
49 return rMetric
.denormalize(rMetric
.get_value(eUnit
));
52 /*--------------------------------------------------------------------
53 description: crop graphic
54 --------------------------------------------------------------------*/
56 SvxGrfCropPage::SvxGrfCropPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
&rSet
)
57 : SfxTabPage(pPage
, pController
, "cui/ui/croppage.ui", "CropPage", &rSet
)
60 , m_bSetOrigSize(false)
62 , m_xCropFrame(m_xBuilder
->weld_widget("cropframe"))
63 , m_xZoomConstRB(m_xBuilder
->weld_radio_button("keepscale"))
64 , m_xSizeConstRB(m_xBuilder
->weld_radio_button("keepsize"))
65 , m_xLeftMF(m_xBuilder
->weld_metric_spin_button("left", FieldUnit::CM
))
66 , m_xRightMF(m_xBuilder
->weld_metric_spin_button("right", FieldUnit::CM
))
67 , m_xTopMF(m_xBuilder
->weld_metric_spin_button("top", FieldUnit::CM
))
68 , m_xBottomMF(m_xBuilder
->weld_metric_spin_button("bottom", FieldUnit::CM
))
69 , m_xScaleFrame(m_xBuilder
->weld_widget("scaleframe"))
70 , m_xWidthZoomMF(m_xBuilder
->weld_metric_spin_button("widthzoom", FieldUnit::PERCENT
))
71 , m_xHeightZoomMF(m_xBuilder
->weld_metric_spin_button("heightzoom", FieldUnit::PERCENT
))
72 , m_xSizeFrame(m_xBuilder
->weld_widget("sizeframe"))
73 , m_xWidthMF(m_xBuilder
->weld_metric_spin_button("width", FieldUnit::CM
))
74 , m_xHeightMF(m_xBuilder
->weld_metric_spin_button("height", FieldUnit::CM
))
75 , m_xOrigSizeGrid(m_xBuilder
->weld_widget("origsizegrid"))
76 , m_xOrigSizeFT(m_xBuilder
->weld_label("origsizeft"))
77 , m_xOrigSizePB(m_xBuilder
->weld_button("origsize"))
78 , m_xExampleWN(new weld::CustomWeld(*m_xBuilder
, "preview", m_aExampleWN
))
82 // set the correct metric
83 const FieldUnit eMetric
= GetModuleFieldUnit( rSet
);
85 SetFieldUnit( *m_xWidthMF
, eMetric
);
86 SetFieldUnit( *m_xHeightMF
, eMetric
);
87 SetFieldUnit( *m_xLeftMF
, eMetric
);
88 SetFieldUnit( *m_xRightMF
, eMetric
);
89 SetFieldUnit( *m_xTopMF
, eMetric
);
90 SetFieldUnit( *m_xBottomMF
, eMetric
);
92 Link
<weld::MetricSpinButton
&,void> aLk
= LINK(this, SvxGrfCropPage
, SizeHdl
);
93 m_xWidthMF
->connect_value_changed( aLk
);
94 m_xHeightMF
->connect_value_changed( aLk
);
96 aLk
= LINK(this, SvxGrfCropPage
, ZoomHdl
);
97 m_xWidthZoomMF
->connect_value_changed( aLk
);
98 m_xHeightZoomMF
->connect_value_changed( aLk
);
100 aLk
= LINK(this, SvxGrfCropPage
, CropModifyHdl
);
101 m_xLeftMF
->connect_value_changed( aLk
);
102 m_xRightMF
->connect_value_changed( aLk
);
103 m_xTopMF
->connect_value_changed( aLk
);
104 m_xBottomMF
->connect_value_changed( aLk
);
106 m_xOrigSizePB
->connect_clicked(LINK(this, SvxGrfCropPage
, OrigSizeHdl
));
109 SvxGrfCropPage::~SvxGrfCropPage()
111 m_xExampleWN
.reset();
114 std::unique_ptr
<SfxTabPage
> SvxGrfCropPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
*rSet
)
116 return std::make_unique
<SvxGrfCropPage
>(pPage
, pController
, *rSet
);
119 void SvxGrfCropPage::Reset( const SfxItemSet
*rSet
)
121 const SfxPoolItem
* pItem
;
122 const SfxItemPool
& rPool
= *rSet
->GetPool();
124 if(SfxItemState::SET
== rSet
->GetItemState( rPool
.GetWhich(
125 SID_ATTR_GRAF_KEEP_ZOOM
), true, &pItem
))
127 if( static_cast<const SfxBoolItem
*>(pItem
)->GetValue() )
128 m_xZoomConstRB
->set_active(true);
130 m_xSizeConstRB
->set_active(true);
131 m_xZoomConstRB
->save_state();
134 sal_uInt16 nW
= rPool
.GetWhich( SID_ATTR_GRAF_CROP
);
135 if( SfxItemState::SET
== rSet
->GetItemState( nW
, true, &pItem
))
137 FieldUnit eUnit
= MapToFieldUnit( rSet
->GetPool()->GetMetric( nW
));
139 const SvxGrfCrop
* pCrop
= static_cast<const SvxGrfCrop
*>(pItem
);
141 m_aExampleWN
.SetLeft(pCrop
->GetLeft());
142 m_aExampleWN
.SetRight(pCrop
->GetRight());
143 m_aExampleWN
.SetTop(pCrop
->GetTop());
144 m_aExampleWN
.SetBottom(pCrop
->GetBottom());
146 m_xLeftMF
->set_value( m_xLeftMF
->normalize( pCrop
->GetLeft()), eUnit
);
147 m_xRightMF
->set_value( m_xRightMF
->normalize( pCrop
->GetRight()), eUnit
);
148 m_xTopMF
->set_value( m_xTopMF
->normalize( pCrop
->GetTop()), eUnit
);
149 m_xBottomMF
->set_value( m_xBottomMF
->normalize( pCrop
->GetBottom()), eUnit
);
153 m_xLeftMF
->set_value(0, FieldUnit::NONE
);
154 m_xRightMF
->set_value(0, FieldUnit::NONE
);
155 m_xTopMF
->set_value(0, FieldUnit::NONE
);
156 m_xBottomMF
->set_value(0, FieldUnit::NONE
);
159 m_xLeftMF
->save_value();
160 m_xRightMF
->save_value();
161 m_xTopMF
->save_value();
162 m_xBottomMF
->save_value();
164 nW
= rPool
.GetWhich( SID_ATTR_PAGE_SIZE
);
165 if ( SfxItemState::SET
== rSet
->GetItemState( nW
, false, &pItem
) )
167 // orientation and size from the PageItem
168 FieldUnit eUnit
= MapToFieldUnit( rSet
->GetPool()->GetMetric( nW
));
170 m_aPageSize
= static_cast<const SvxSizeItem
*>(pItem
)->GetSize();
172 auto nMin
= m_xWidthMF
->normalize( 23 );
173 auto nMax
= m_xHeightMF
->normalize(m_aPageSize
.Height());
174 m_xHeightMF
->set_range(nMin
, nMax
, eUnit
);
175 nMax
= m_xWidthMF
->normalize(m_aPageSize
.Width());
176 m_xWidthMF
->set_range(nMin
, nMax
, eUnit
);
180 m_aPageSize
= OutputDevice::LogicToLogic(
181 Size( CM_1_TO_TWIP
, CM_1_TO_TWIP
),
182 MapMode( MapUnit::MapTwip
),
183 MapMode( rSet
->GetPool()->GetMetric( nW
) ) );
187 if( const SvxBrushItem
* pGraphicItem
= rSet
->GetItemIfSet( SID_ATTR_GRAF_GRAPHIC
, false ) )
190 SfxStringItem
const * it
= rSet
->GetItem(SID_REFERER
);
192 referer
= it
->GetValue();
194 const Graphic
* pGrf
= pGraphicItem
->GetGraphic(referer
);
197 m_aOrigSize
= GetGrfOrigSize( *pGrf
);
198 if (pGrf
->GetType() == GraphicType::Bitmap
&& m_aOrigSize
.Width() && m_aOrigSize
.Height())
200 m_aOrigPixelSize
= pGrf
->GetSizePixel();
203 if( m_aOrigSize
.Width() && m_aOrigSize
.Height() )
206 m_aExampleWN
.SetGraphic( *pGrf
);
207 m_aExampleWN
.SetFrameSize( m_aOrigSize
);
210 if( !pGraphicItem
->GetGraphicLink().isEmpty() )
211 m_aGraphicName
= pGraphicItem
->GetGraphicLink();
216 GraphicHasChanged( bFound
);
217 ActivatePage( *rSet
);
220 bool SvxGrfCropPage::FillItemSet(SfxItemSet
*rSet
)
222 const SfxItemPool
& rPool
= *rSet
->GetPool();
223 bool bModified
= false;
224 if( m_xWidthMF
->get_value_changed_from_saved() ||
225 m_xHeightMF
->get_value_changed_from_saved() )
227 constexpr TypedWhichId
<SvxSizeItem
> nW
= SID_ATTR_GRAF_FRMSIZE
;
228 FieldUnit eUnit
= MapToFieldUnit( rSet
->GetPool()->GetMetric( nW
));
230 std::shared_ptr
<SvxSizeItem
> aSz(std::make_shared
<SvxSizeItem
>(nW
));
232 // size could already have been set from another page
233 const SfxItemSet
* pExSet
= GetDialogExampleSet();
234 const SvxSizeItem
* pSizeItem
= nullptr;
235 if( pExSet
&& (pSizeItem
= pExSet
->GetItemIfSet( nW
, false )) )
237 aSz
.reset(pSizeItem
->Clone());
241 aSz
.reset(GetItemSet().Get(nW
).Clone());
244 Size
aTmpSz( aSz
->GetSize() );
245 if( m_xWidthMF
->get_value_changed_from_saved() )
246 aTmpSz
.setWidth( lcl_GetValue( *m_xWidthMF
, eUnit
) );
247 if( m_xHeightMF
->get_value_changed_from_saved() )
248 aTmpSz
.setHeight( lcl_GetValue( *m_xHeightMF
, eUnit
) );
249 aSz
->SetSize( aTmpSz
);
250 m_xWidthMF
->save_value();
251 m_xHeightMF
->save_value();
253 bModified
|= nullptr != rSet
->Put( *aSz
);
257 bModified
|= nullptr != rSet
->Put( SvxSizeItem( rPool
.GetWhich(
258 SID_ATTR_GRAF_FRMSIZE_PERCENT
), Size( 0, 0 )) );
261 if( m_xLeftMF
->get_value_changed_from_saved() || m_xRightMF
->get_value_changed_from_saved() ||
262 m_xTopMF
->get_value_changed_from_saved() || m_xBottomMF
->get_value_changed_from_saved() )
264 sal_uInt16 nW
= rPool
.GetWhich( SID_ATTR_GRAF_CROP
);
265 FieldUnit eUnit
= MapToFieldUnit( rSet
->GetPool()->GetMetric( nW
));
266 std::unique_ptr
<SvxGrfCrop
> pNew(static_cast<SvxGrfCrop
*>(rSet
->Get( nW
).Clone()));
268 pNew
->SetLeft( lcl_GetValue( *m_xLeftMF
, eUnit
) );
269 pNew
->SetRight( lcl_GetValue( *m_xRightMF
, eUnit
) );
270 pNew
->SetTop( lcl_GetValue( *m_xTopMF
, eUnit
) );
271 pNew
->SetBottom( lcl_GetValue( *m_xBottomMF
, eUnit
) );
272 bModified
|= nullptr != rSet
->Put( std::move(pNew
) );
275 if( m_xZoomConstRB
->get_state_changed_from_saved() )
277 bModified
|= nullptr != rSet
->Put( SfxBoolItem( rPool
.GetWhich(
278 SID_ATTR_GRAF_KEEP_ZOOM
), m_xZoomConstRB
->get_active() ) );
284 void SvxGrfCropPage::ActivatePage(const SfxItemSet
& rSet
)
287 SfxItemPool
* pPool
= GetItemSet().GetPool();
288 DBG_ASSERT( pPool
, "Where is the pool?" );
291 auto& aProperties
= getAdditionalProperties();
292 auto aIterator
= aProperties
.find("PreferredDPI");
293 if (aIterator
!= aProperties
.end())
294 m_aPreferredDPI
= aIterator
->second
.get
<sal_Int32
>();
296 m_bSetOrigSize
= false;
300 if( const SvxSizeItem
* pFrmSizeItem
= rSet
.GetItemIfSet( SID_ATTR_GRAF_FRMSIZE
, false ) )
301 aSize
= pFrmSizeItem
->GetSize();
303 m_nOldWidth
= aSize
.Width();
304 m_nOldHeight
= aSize
.Height();
306 auto nWidth
= m_xWidthMF
->normalize(m_nOldWidth
);
307 auto nHeight
= m_xHeightMF
->normalize(m_nOldHeight
);
309 if (nWidth
!= m_xWidthMF
->get_value(FieldUnit::TWIP
))
310 m_xWidthMF
->set_value(nWidth
, FieldUnit::TWIP
);
311 m_xWidthMF
->save_value();
313 if (nHeight
!= m_xHeightMF
->get_value(FieldUnit::TWIP
))
314 m_xHeightMF
->set_value(nHeight
, FieldUnit::TWIP
);
315 m_xHeightMF
->save_value();
317 if( const SvxBrushItem
* pBrushItem
= rSet
.GetItemIfSet( SID_ATTR_GRAF_GRAPHIC
, false ) )
319 if( !pBrushItem
->GetGraphicLink().isEmpty() &&
320 m_aGraphicName
!= pBrushItem
->GetGraphicLink() )
321 m_aGraphicName
= pBrushItem
->GetGraphicLink();
324 SfxStringItem
const * it
= rSet
.GetItem(SID_REFERER
);
326 referer
= it
->GetValue();
328 const Graphic
* pGrf
= pBrushItem
->GetGraphic(referer
);
331 m_aExampleWN
.SetGraphic( *pGrf
);
332 m_aOrigSize
= GetGrfOrigSize( *pGrf
);
333 if (pGrf
->GetType() == GraphicType::Bitmap
&& m_aOrigSize
.Width() > 1 && m_aOrigSize
.Height() > 1) {
334 m_aOrigPixelSize
= pGrf
->GetSizePixel();
336 m_aExampleWN
.SetFrameSize(m_aOrigSize
);
337 GraphicHasChanged( m_aOrigSize
.Width() && m_aOrigSize
.Height() );
341 GraphicHasChanged( false );
347 DeactivateRC
SvxGrfCropPage::DeactivatePage(SfxItemSet
*_pSet
)
350 FillItemSet( _pSet
);
351 return DeactivateRC::LeavePage
;
354 /*--------------------------------------------------------------------
355 description: scale changed, adjust size
356 --------------------------------------------------------------------*/
358 IMPL_LINK( SvxGrfCropPage
, ZoomHdl
, weld::MetricSpinButton
&, rField
, void )
360 SfxItemPool
* pPool
= GetItemSet().GetPool();
361 DBG_ASSERT( pPool
, "Where is the pool?" );
362 FieldUnit eUnit
= MapToFieldUnit( pPool
->GetMetric( pPool
->GetWhich(
363 SID_ATTR_GRAF_CROP
) ) );
365 if (&rField
== m_xWidthZoomMF
.get())
367 tools::Long nLRBorders
= lcl_GetValue(*m_xLeftMF
, eUnit
)
368 +lcl_GetValue(*m_xRightMF
, eUnit
);
369 m_xWidthMF
->set_value( m_xWidthMF
->normalize(
370 ((m_aOrigSize
.Width() - nLRBorders
) * rField
.get_value(FieldUnit::NONE
))/100),
375 tools::Long nULBorders
= lcl_GetValue(*m_xTopMF
, eUnit
)
376 +lcl_GetValue(*m_xBottomMF
, eUnit
);
377 m_xHeightMF
->set_value( m_xHeightMF
->normalize(
378 ((m_aOrigSize
.Height() - nULBorders
) * rField
.get_value(FieldUnit::NONE
))/100) ,
383 /*--------------------------------------------------------------------
384 description: change size, adjust scale
385 --------------------------------------------------------------------*/
387 IMPL_LINK( SvxGrfCropPage
, SizeHdl
, weld::MetricSpinButton
&, rField
, void )
389 SfxItemPool
* pPool
= GetItemSet().GetPool();
390 DBG_ASSERT( pPool
, "Where is the pool?" );
391 FieldUnit eUnit
= MapToFieldUnit( pPool
->GetMetric( pPool
->GetWhich(
392 SID_ATTR_GRAF_CROP
) ) );
394 Size
aSize( lcl_GetValue(*m_xWidthMF
, eUnit
),
395 lcl_GetValue(*m_xHeightMF
, eUnit
) );
397 if(&rField
== m_xWidthMF
.get())
399 tools::Long nWidth
= m_aOrigSize
.Width() -
400 ( lcl_GetValue(*m_xLeftMF
, eUnit
) +
401 lcl_GetValue(*m_xRightMF
, eUnit
) );
404 sal_uInt16 nZoom
= static_cast<sal_uInt16
>( aSize
.Width() * 100 / nWidth
);
405 m_xWidthZoomMF
->set_value(nZoom
, FieldUnit::NONE
);
409 tools::Long nHeight
= m_aOrigSize
.Height() -
410 ( lcl_GetValue(*m_xTopMF
, eUnit
) +
411 lcl_GetValue(*m_xBottomMF
, eUnit
));
414 sal_uInt16 nZoom
= static_cast<sal_uInt16
>( aSize
.Height() * 100 / nHeight
);
415 m_xHeightZoomMF
->set_value(nZoom
, FieldUnit::NONE
);
419 /*--------------------------------------------------------------------
420 description: evaluate border
421 --------------------------------------------------------------------*/
423 IMPL_LINK( SvxGrfCropPage
, CropModifyHdl
, weld::MetricSpinButton
&, rField
, void )
425 SfxItemPool
* pPool
= GetItemSet().GetPool();
426 DBG_ASSERT( pPool
, "Where is the pool?" );
427 FieldUnit eUnit
= MapToFieldUnit( pPool
->GetMetric( pPool
->GetWhich(
428 SID_ATTR_GRAF_CROP
) ) );
430 bool bZoom
= m_xZoomConstRB
->get_active();
431 if (&rField
== m_xLeftMF
.get() || &rField
== m_xRightMF
.get())
433 tools::Long nLeft
= lcl_GetValue( *m_xLeftMF
, eUnit
);
434 tools::Long nRight
= lcl_GetValue( *m_xRightMF
, eUnit
);
435 tools::Long nWidthZoom
= static_cast<tools::Long
>(m_xWidthZoomMF
->get_value(FieldUnit::NONE
));
436 if (bZoom
&& nWidthZoom
!= 0 && ( ( ( m_aOrigSize
.Width() - (nLeft
+ nRight
)) * nWidthZoom
)
437 / 100 >= m_aPageSize
.Width() ) )
439 if (&rField
== m_xLeftMF
.get())
441 nLeft
= m_aOrigSize
.Width() -
442 ( m_aPageSize
.Width() * 100 / nWidthZoom
+ nRight
);
443 m_xLeftMF
->set_value( m_xLeftMF
->normalize( nLeft
), eUnit
);
447 nRight
= m_aOrigSize
.Width() -
448 ( m_aPageSize
.Width() * 100 / nWidthZoom
+ nLeft
);
449 m_xRightMF
->set_value( m_xRightMF
->normalize( nRight
), eUnit
);
452 if (AllSettings::GetLayoutRTL())
454 m_aExampleWN
.SetLeft(nRight
);
455 m_aExampleWN
.SetRight(nLeft
);
459 m_aExampleWN
.SetLeft(nLeft
);
460 m_aExampleWN
.SetRight(nRight
);
464 // scale stays, recompute width
465 ZoomHdl(*m_xWidthZoomMF
);
470 tools::Long nTop
= lcl_GetValue( *m_xTopMF
, eUnit
);
471 tools::Long nBottom
= lcl_GetValue( *m_xBottomMF
, eUnit
);
472 tools::Long nHeightZoom
= static_cast<tools::Long
>(m_xHeightZoomMF
->get_value(FieldUnit::NONE
));
473 if(bZoom
&& ( ( ( m_aOrigSize
.Height() - (nTop
+ nBottom
)) * nHeightZoom
)
474 / 100 >= m_aPageSize
.Height()))
476 assert(nHeightZoom
&& "div-by-zero");
477 if(&rField
== m_xTopMF
.get())
479 nTop
= m_aOrigSize
.Height() -
480 ( m_aPageSize
.Height() * 100 / nHeightZoom
+ nBottom
);
481 m_xTopMF
->set_value( m_xWidthMF
->normalize( nTop
), eUnit
);
485 nBottom
= m_aOrigSize
.Height() -
486 ( m_aPageSize
.Height() * 100 / nHeightZoom
+ nTop
);
487 m_xBottomMF
->set_value( m_xWidthMF
->normalize( nBottom
), eUnit
);
490 m_aExampleWN
.SetTop( nTop
);
491 m_aExampleWN
.SetBottom( nBottom
);
494 // scale stays, recompute height
495 ZoomHdl(*m_xHeightZoomMF
);
498 m_aExampleWN
.Invalidate();
499 // size and border changed -> recompute scale
504 /*--------------------------------------------------------------------
505 description: set original size
506 --------------------------------------------------------------------*/
508 IMPL_LINK_NOARG(SvxGrfCropPage
, OrigSizeHdl
, weld::Button
&, void)
510 SfxItemPool
* pPool
= GetItemSet().GetPool();
511 DBG_ASSERT( pPool
, "Where is the pool?" );
512 FieldUnit eUnit
= MapToFieldUnit( pPool
->GetMetric( pPool
->GetWhich(
513 SID_ATTR_GRAF_CROP
) ) );
515 tools::Long nWidth
= m_aOrigSize
.Width() -
516 lcl_GetValue( *m_xLeftMF
, eUnit
) -
517 lcl_GetValue( *m_xRightMF
, eUnit
);
518 m_xWidthMF
->set_value( m_xWidthMF
->normalize( nWidth
), eUnit
);
519 tools::Long nHeight
= m_aOrigSize
.Height() -
520 lcl_GetValue( *m_xTopMF
, eUnit
) -
521 lcl_GetValue( *m_xBottomMF
, eUnit
);
522 m_xHeightMF
->set_value( m_xHeightMF
->normalize( nHeight
), eUnit
);
523 m_xWidthZoomMF
->set_value(100, FieldUnit::NONE
);
524 m_xHeightZoomMF
->set_value(100, FieldUnit::NONE
);
525 m_bSetOrigSize
= true;
527 /*--------------------------------------------------------------------
528 description: compute scale
529 --------------------------------------------------------------------*/
531 void SvxGrfCropPage::CalcZoom()
533 SfxItemPool
* pPool
= GetItemSet().GetPool();
534 DBG_ASSERT( pPool
, "Where is the pool?" );
535 FieldUnit eUnit
= MapToFieldUnit( pPool
->GetMetric( pPool
->GetWhich(
536 SID_ATTR_GRAF_CROP
) ) );
538 tools::Long nWidth
= lcl_GetValue( *m_xWidthMF
, eUnit
);
539 tools::Long nHeight
= lcl_GetValue( *m_xHeightMF
, eUnit
);
540 tools::Long nLRBorders
= lcl_GetValue( *m_xLeftMF
, eUnit
) +
541 lcl_GetValue( *m_xRightMF
, eUnit
);
542 tools::Long nULBorders
= lcl_GetValue( *m_xTopMF
, eUnit
) +
543 lcl_GetValue( *m_xBottomMF
, eUnit
);
544 sal_uInt16 nZoom
= 0;
546 if( (nDen
= m_aOrigSize
.Width() - nLRBorders
) > 0)
547 nZoom
= static_cast<sal_uInt16
>((( nWidth
* 1000 / nDen
)+5)/10);
548 m_xWidthZoomMF
->set_value(nZoom
, FieldUnit::NONE
);
549 if( (nDen
= m_aOrigSize
.Height() - nULBorders
) > 0)
550 nZoom
= static_cast<sal_uInt16
>((( nHeight
* 1000 / nDen
)+5)/10);
553 m_xHeightZoomMF
->set_value(nZoom
, FieldUnit::NONE
);
556 /*--------------------------------------------------------------------
557 description: set minimum/maximum values for the margins
558 --------------------------------------------------------------------*/
560 void SvxGrfCropPage::CalcMinMaxBorder()
562 SfxItemPool
* pPool
= GetItemSet().GetPool();
563 DBG_ASSERT( pPool
, "Where is the pool?" );
564 FieldUnit eUnit
= MapToFieldUnit( pPool
->GetMetric( pPool
->GetWhich(
565 SID_ATTR_GRAF_CROP
) ) );
566 tools::Long nR
= lcl_GetValue(*m_xRightMF
, eUnit
);
567 tools::Long nMinWidth
= (m_aOrigSize
.Width() * 10) /11;
568 tools::Long nMin
= nMinWidth
- (nR
>= 0 ? nR
: 0);
569 m_xLeftMF
->set_max( m_xLeftMF
->normalize(nMin
), eUnit
);
571 tools::Long nL
= lcl_GetValue(*m_xLeftMF
, eUnit
);
572 nMin
= nMinWidth
- (nL
>= 0 ? nL
: 0);
573 m_xRightMF
->set_max( m_xRightMF
->normalize(nMin
), eUnit
);
575 tools::Long nUp
= lcl_GetValue( *m_xTopMF
, eUnit
);
576 tools::Long nMinHeight
= (m_aOrigSize
.Height() * 10) /11;
577 nMin
= nMinHeight
- (nUp
>= 0 ? nUp
: 0);
578 m_xBottomMF
->set_max( m_xBottomMF
->normalize(nMin
), eUnit
);
580 tools::Long nLow
= lcl_GetValue(*m_xBottomMF
, eUnit
);
581 nMin
= nMinHeight
- (nLow
>= 0 ? nLow
: 0);
582 m_xTopMF
->set_max( m_xTopMF
->normalize(nMin
), eUnit
);
584 /*--------------------------------------------------------------------
585 description: set spinsize to 1/20 of the original size,
586 fill FixedText with the original size
587 --------------------------------------------------------------------*/
589 void SvxGrfCropPage::GraphicHasChanged( bool bFound
)
593 SfxItemPool
* pPool
= GetItemSet().GetPool();
594 DBG_ASSERT( pPool
, "Where is the pool?" );
595 FieldUnit eUnit
= MapToFieldUnit( pPool
->GetMetric( pPool
->GetWhich(
596 SID_ATTR_GRAF_CROP
) ));
598 sal_Int64 nSpin
= m_xLeftMF
->normalize(m_aOrigSize
.Width()) / 20;
599 nSpin
= vcl::ConvertValue( nSpin
, m_aOrigSize
.Width(), 0,
600 eUnit
, m_xLeftMF
->get_unit());
602 // if the margin is too big, it is set to 1/3 on both pages
603 tools::Long nR
= lcl_GetValue( *m_xRightMF
, eUnit
);
604 tools::Long nL
= lcl_GetValue( *m_xLeftMF
, eUnit
);
605 if((nL
+ nR
) < - m_aOrigSize
.Width())
607 tools::Long nVal
= m_aOrigSize
.Width() / -3;
608 m_xRightMF
->set_value( m_xRightMF
->normalize( nVal
), eUnit
);
609 m_xLeftMF
->set_value( m_xLeftMF
->normalize( nVal
), eUnit
);
610 m_aExampleWN
.SetLeft(nVal
);
611 m_aExampleWN
.SetRight(nVal
);
613 tools::Long nUp
= lcl_GetValue(*m_xTopMF
, eUnit
);
614 tools::Long nLow
= lcl_GetValue(*m_xBottomMF
, eUnit
);
615 if((nUp
+ nLow
) < - m_aOrigSize
.Height())
617 tools::Long nVal
= m_aOrigSize
.Height() / -3;
618 m_xTopMF
->set_value( m_xTopMF
->normalize( nVal
), eUnit
);
619 m_xBottomMF
->set_value( m_xBottomMF
->normalize( nVal
), eUnit
);
620 m_aExampleWN
.SetTop(nVal
);
621 m_aExampleWN
.SetBottom(nVal
);
624 m_xLeftMF
->set_increments(nSpin
, nSpin
* 10, FieldUnit::NONE
);
625 m_xRightMF
->set_increments(nSpin
, nSpin
* 10, FieldUnit::NONE
);
626 nSpin
= m_xTopMF
->normalize(m_aOrigSize
.Height()) / 20;
627 nSpin
= vcl::ConvertValue( nSpin
, m_aOrigSize
.Width(), 0,
628 eUnit
, m_xLeftMF
->get_unit() );
629 m_xTopMF
->set_increments(nSpin
, nSpin
* 10, FieldUnit::NONE
);
630 m_xBottomMF
->set_increments(nSpin
, nSpin
* 10, FieldUnit::NONE
);
632 // display original size
633 const FieldUnit eMetric
= GetModuleFieldUnit( GetItemSet() );
637 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/spinbox.ui"));
638 std::unique_ptr
<weld::Dialog
> xTopLevel(xBuilder
->weld_dialog("SpinDialog"));
639 std::unique_ptr
<weld::MetricSpinButton
> xFld(xBuilder
->weld_metric_spin_button("spin", FieldUnit::CM
));
640 SetFieldUnit( *xFld
, eMetric
);
641 xFld
->set_digits(m_xWidthMF
->get_digits());
642 xFld
->set_max(INT_MAX
- 1, FieldUnit::NONE
);
644 xFld
->set_value(xFld
->normalize(m_aOrigSize
.Width()), eUnit
);
645 sTemp
= xFld
->get_text();
646 xFld
->set_value(xFld
->normalize(m_aOrigSize
.Height()), eUnit
);
647 // multiplication sign (U+00D7)
648 sTemp
+= u
"\u00D7" + xFld
->get_text();
651 if ( m_aOrigPixelSize
.Width() && m_aOrigPixelSize
.Height() ) {
652 sal_Int32 ax
= 0.5 + m_aOrigPixelSize
.Width() /
653 o3tl::convert
<double>(m_aOrigSize
.Width(), o3tl::Length::twip
,
655 sal_Int32 ay
= 0.5 + m_aOrigPixelSize
.Height() /
656 o3tl::convert
<double>(m_aOrigSize
.Height(), o3tl::Length::twip
,
658 OUString sPPI
= OUString::number(ax
);
659 if (abs(ax
- ay
) > 1) {
660 sPPI
+= u
"\u00D7" + OUString::number(ay
);
662 sTemp
+= " " + CuiResId(RID_CUISTR_PPI
).replaceAll("%1", sPPI
);
664 sTemp
+= "\n" + OUString::number(m_aOrigPixelSize
.Width()) + u
"\u00D7" + OUString::number(m_aOrigPixelSize
.Height()) + " px";
665 m_xOrigSizeFT
->set_label(sTemp
);
668 m_xCropFrame
->set_sensitive(bFound
);
669 m_xScaleFrame
->set_sensitive(bFound
);
670 m_xSizeFrame
->set_sensitive(bFound
);
671 m_xOrigSizeGrid
->set_sensitive(bFound
);
672 m_xZoomConstRB
->set_sensitive(bFound
);
675 Size
SvxGrfCropPage::GetGrfOrigSize(const Graphic
& rGrf
)
679 if (m_aPreferredDPI
> 0)
681 Size aPixelSize
= rGrf
.GetSizePixel();
682 double fWidth
= aPixelSize
.Width() / double(m_aPreferredDPI
);
683 double fHeight
= aPixelSize
.Height() / double(m_aPreferredDPI
);
684 fWidth
= o3tl::convert(fWidth
, o3tl::Length::in
, o3tl::Length::twip
);
685 fHeight
= o3tl::convert(fHeight
, o3tl::Length::in
, o3tl::Length::twip
);
686 aSize
= Size(fWidth
, fHeight
);
690 const MapMode
aMapTwip( MapUnit::MapTwip
);
691 aSize
= rGrf
.GetPrefSize();
692 if( MapUnit::MapPixel
== rGrf
.GetPrefMapMode().GetMapUnit() )
693 aSize
= Application::GetDefaultDevice()->PixelToLogic(aSize
, aMapTwip
);
695 aSize
= OutputDevice::LogicToLogic( aSize
,
696 rGrf
.GetPrefMapMode(), aMapTwip
);
701 /*****************************************************************/
703 SvxCropExample::SvxCropExample()
705 , m_aBottomRight(0, 0)
709 void SvxCropExample::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
711 CustomWidgetController::SetDrawingArea(pDrawingArea
);
712 OutputDevice
& rDevice
= pDrawingArea
->get_ref_device();
713 Size
aSize(rDevice
.LogicToPixel(Size(78, 78), MapMode(MapUnit::MapAppFont
)));
714 pDrawingArea
->set_size_request(aSize
.Width(), aSize
.Height());
716 m_aMapMode
= rDevice
.GetMapMode();
717 m_aFrameSize
= OutputDevice::LogicToLogic(
718 Size(CM_1_TO_TWIP
/ 2, CM_1_TO_TWIP
/ 2),
719 MapMode(MapUnit::MapTwip
), m_aMapMode
);
722 void SvxCropExample::Paint(vcl::RenderContext
& rRenderContext
, const ::tools::Rectangle
&)
724 rRenderContext
.Push(vcl::PushFlags::MAPMODE
);
725 rRenderContext
.SetMapMode(m_aMapMode
);
728 const Size
aWinSize(rRenderContext
.PixelToLogic(GetOutputSizePixel()));
729 rRenderContext
.SetLineColor();
730 rRenderContext
.SetFillColor(rRenderContext
.GetSettings().GetStyleSettings().GetWindowColor());
731 rRenderContext
.DrawRect(::tools::Rectangle(Point(), aWinSize
));
733 // use AA, the Graphic may be a metafile/svg and would then look ugly
734 rRenderContext
.SetAntialiasing(AntialiasingFlags::Enable
);
737 ::tools::Rectangle
aRect(
738 Point((aWinSize
.Width() - m_aFrameSize
.Width())/2, (aWinSize
.Height() - m_aFrameSize
.Height())/2),
740 m_aGrf
.Draw(rRenderContext
, aRect
.TopLeft(), aRect
.GetSize());
742 // Remove one more case that uses XOR paint (RasterOp::Invert).
743 // Get colors and logic DashLength from settings, use equal to
744 // PolygonMarkerPrimitive2D, may be changed to that primitive later.
745 // Use this to guarantee good visibility - that was the purpose of
746 // the former used XOR paint.
747 const Color
aColA(SvtOptionsDrawinglayer::GetStripeColorA().getBColor());
748 const Color
aColB(SvtOptionsDrawinglayer::GetStripeColorB().getBColor());
749 const double fStripeLength(SvtOptionsDrawinglayer::GetStripeLength());
750 const basegfx::B2DVector
aDashVector(rRenderContext
.GetInverseViewTransformation() * basegfx::B2DVector(fStripeLength
, 0.0));
751 const double fLogicDashLength(aDashVector
.getX());
753 // apply current crop settings
754 aRect
.AdjustLeft(m_aTopLeft
.Y());
755 aRect
.AdjustTop(m_aTopLeft
.X());
756 aRect
.AdjustRight(-m_aBottomRight
.Y());
757 aRect
.AdjustBottom(-m_aBottomRight
.X());
759 // apply dash with direct paint callbacks
760 basegfx::utils::applyLineDashing(
761 basegfx::utils::createPolygonFromRect(
762 basegfx::B2DRange(aRect
.Left(), aRect
.Top(), aRect
.Right(), aRect
.Bottom())),
763 std::vector
< double >(2, fLogicDashLength
),
764 [&aColA
,&rRenderContext
](const basegfx::B2DPolygon
& rSnippet
)
766 rRenderContext
.SetLineColor(aColA
);
767 rRenderContext
.DrawPolyLine(rSnippet
);
769 [&aColB
,&rRenderContext
](const basegfx::B2DPolygon
& rSnippet
)
771 rRenderContext
.SetLineColor(aColB
);
772 rRenderContext
.DrawPolyLine(rSnippet
);
774 2.0 * fLogicDashLength
);
776 rRenderContext
.Pop();
779 void SvxCropExample::Resize()
781 SetFrameSize(m_aFrameSize
);
784 void SvxCropExample::SetFrameSize( const Size
& rSz
)
787 if (!m_aFrameSize
.Width())
788 m_aFrameSize
.setWidth( 1 );
789 if (!m_aFrameSize
.Height())
790 m_aFrameSize
.setHeight( 1 );
791 Size
aWinSize( GetOutputSizePixel() );
792 Fraction
aXScale( aWinSize
.Width() * 4, m_aFrameSize
.Width() * 5 );
793 Fraction
aYScale( aWinSize
.Height() * 4, m_aFrameSize
.Height() * 5 );
795 if( aYScale
< aXScale
)
798 m_aMapMode
.SetScaleX(aXScale
);
799 m_aMapMode
.SetScaleY(aXScale
);
804 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */