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>
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
)
61 , m_bSetOrigSize(false)
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
))
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);
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
);
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
);
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
) ) );
190 if( const SvxBrushItem
* pGraphicItem
= rSet
->GetItemIfSet( SID_ATTR_GRAF_GRAPHIC
, false ) )
193 SfxStringItem
const * it
= rSet
->GetItem(SID_REFERER
);
195 referer
= it
->GetValue();
197 const Graphic
* pGrf
= pGraphicItem
->GetGraphic(referer
);
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() )
209 m_aExampleWN
.SetGraphic( *pGrf
);
210 m_aExampleWN
.SetFrameSize( m_aOrigSize
);
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());
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
);
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() ) );
287 void SvxGrfCropPage::ActivatePage(const SfxItemSet
& rSet
)
290 SfxItemPool
* pPool
= GetItemSet().GetPool();
291 DBG_ASSERT( pPool
, "Where is the pool?" );
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;
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();
327 SfxStringItem
const * it
= rSet
.GetItem(SID_REFERER
);
329 referer
= it
->GetValue();
331 const Graphic
* pGrf
= pBrushItem
->GetGraphic(referer
);
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() );
344 GraphicHasChanged( false );
350 DeactivateRC
SvxGrfCropPage::DeactivatePage(SfxItemSet
*_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),
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) ,
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
) );
407 sal_uInt16 nZoom
= static_cast<sal_uInt16
>( aSize
.Width() * 100 / nWidth
);
408 m_xWidthZoomMF
->set_value(nZoom
, FieldUnit::NONE
);
412 tools::Long nHeight
= m_aOrigSize
.Height() -
413 ( lcl_GetValue(*m_xTopMF
, eUnit
) +
414 lcl_GetValue(*m_xBottomMF
, eUnit
));
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
);
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
);
462 m_aExampleWN
.SetLeft(nLeft
);
463 m_aExampleWN
.SetRight(nRight
);
467 // scale stays, recompute width
468 ZoomHdl(*m_xWidthZoomMF
);
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
);
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
);
497 // scale stays, recompute height
498 ZoomHdl(*m_xHeightZoomMF
);
501 m_aExampleWN
.Invalidate();
502 // size and border changed -> recompute scale
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();
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;
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);
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
)
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() );
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
,
684 sal_Int32 ay
= 0.5 + m_aOrigPixelSize
.Height() /
685 o3tl::convert
<double>(m_aOrigSize
.Height(), o3tl::Length::twip
,
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
)
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
);
719 const MapMode
aMapTwip( MapUnit::MapTwip
);
720 aSize
= rGrf
.GetPrefSize();
721 if( MapUnit::MapPixel
== rGrf
.GetPrefMapMode().GetMapUnit() )
722 aSize
= Application::GetDefaultDevice()->PixelToLogic(aSize
, aMapTwip
);
724 aSize
= OutputDevice::LogicToLogic( aSize
,
725 rGrf
.GetPrefMapMode(), aMapTwip
);
730 /*****************************************************************/
732 SvxCropExample::SvxCropExample()
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
);
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
);
766 ::tools::Rectangle
aRect(
767 Point((aWinSize
.Width() - m_aFrameSize
.Width())/2, (aWinSize
.Height() - m_aFrameSize
.Height())/2),
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
)
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
)
827 m_aMapMode
.SetScaleX(aXScale
);
828 m_aMapMode
.SetScaleY(aXScale
);
833 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */