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 <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/settings.hxx>
36 #include <vcl/svapp.hxx>
37 #include <svtools/unitconv.hxx>
38 #include <svtools/optionsdrawinglayer.hxx>
39 #include <basegfx/matrix/b2dhommatrix.hxx>
40 #include <basegfx/polygon/b2dpolygontools.hxx>
41 #include <o3tl/unit_conversion.hxx>
42
43 constexpr auto CM_1_TO_TWIP = o3tl::convert(1, o3tl::Length::cm, o3tl::Length::twip); // 567
44
45
lcl_GetValue(const weld::MetricSpinButton & rMetric,FieldUnit eUnit)46 static int lcl_GetValue(const weld::MetricSpinButton& rMetric, FieldUnit eUnit)
47 {
48 return rMetric.denormalize(rMetric.get_value(eUnit));
49 }
50
51 /*--------------------------------------------------------------------
52 description: crop graphic
53 --------------------------------------------------------------------*/
54
SvxGrfCropPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)55 SvxGrfCropPage::SvxGrfCropPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet)
56 : SfxTabPage(pPage, pController, "cui/ui/croppage.ui", "CropPage", &rSet)
57 , nOldWidth(0)
58 , nOldHeight(0)
59 , bSetOrigSize(false)
60 , m_xCropFrame(m_xBuilder->weld_widget("cropframe"))
61 , m_xZoomConstRB(m_xBuilder->weld_radio_button("keepscale"))
62 , m_xSizeConstRB(m_xBuilder->weld_radio_button("keepsize"))
63 , m_xLeftMF(m_xBuilder->weld_metric_spin_button("left", FieldUnit::CM))
64 , m_xRightMF(m_xBuilder->weld_metric_spin_button("right", FieldUnit::CM))
65 , m_xTopMF(m_xBuilder->weld_metric_spin_button("top", FieldUnit::CM))
66 , m_xBottomMF(m_xBuilder->weld_metric_spin_button("bottom", FieldUnit::CM))
67 , m_xScaleFrame(m_xBuilder->weld_widget("scaleframe"))
68 , m_xWidthZoomMF(m_xBuilder->weld_metric_spin_button("widthzoom", FieldUnit::PERCENT))
69 , m_xHeightZoomMF(m_xBuilder->weld_metric_spin_button("heightzoom", FieldUnit::PERCENT))
70 , m_xSizeFrame(m_xBuilder->weld_widget("sizeframe"))
71 , m_xWidthMF(m_xBuilder->weld_metric_spin_button("width", FieldUnit::CM))
72 , m_xHeightMF(m_xBuilder->weld_metric_spin_button("height", FieldUnit::CM))
73 , m_xOrigSizeGrid(m_xBuilder->weld_widget("origsizegrid"))
74 , m_xOrigSizeFT(m_xBuilder->weld_label("origsizeft"))
75 , m_xOrigSizePB(m_xBuilder->weld_button("origsize"))
76 , m_xExampleWN(new weld::CustomWeld(*m_xBuilder, "preview", m_aExampleWN))
77 {
78 SetExchangeSupport();
79
80 // set the correct metric
81 const FieldUnit eMetric = GetModuleFieldUnit( rSet );
82
83 SetFieldUnit( *m_xWidthMF, eMetric );
84 SetFieldUnit( *m_xHeightMF, eMetric );
85 SetFieldUnit( *m_xLeftMF, eMetric );
86 SetFieldUnit( *m_xRightMF, eMetric );
87 SetFieldUnit( *m_xTopMF , eMetric );
88 SetFieldUnit( *m_xBottomMF, eMetric );
89
90 Link<weld::MetricSpinButton&,void> aLk = LINK(this, SvxGrfCropPage, SizeHdl);
91 m_xWidthMF->connect_value_changed( aLk );
92 m_xHeightMF->connect_value_changed( aLk );
93
94 aLk = LINK(this, SvxGrfCropPage, ZoomHdl);
95 m_xWidthZoomMF->connect_value_changed( aLk );
96 m_xHeightZoomMF->connect_value_changed( aLk );
97
98 aLk = LINK(this, SvxGrfCropPage, CropModifyHdl);
99 m_xLeftMF->connect_value_changed( aLk );
100 m_xRightMF->connect_value_changed( aLk );
101 m_xTopMF->connect_value_changed( aLk );
102 m_xBottomMF->connect_value_changed( aLk );
103
104 m_xOrigSizePB->connect_clicked(LINK(this, SvxGrfCropPage, OrigSizeHdl));
105 }
106
~SvxGrfCropPage()107 SvxGrfCropPage::~SvxGrfCropPage()
108 {
109 m_xExampleWN.reset();
110 }
111
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)112 std::unique_ptr<SfxTabPage> SvxGrfCropPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet)
113 {
114 return std::make_unique<SvxGrfCropPage>(pPage, pController, *rSet);
115 }
116
Reset(const SfxItemSet * rSet)117 void SvxGrfCropPage::Reset( const SfxItemSet *rSet )
118 {
119 const SfxPoolItem* pItem;
120 const SfxItemPool& rPool = *rSet->GetPool();
121
122 if(SfxItemState::SET == rSet->GetItemState( rPool.GetWhich(
123 SID_ATTR_GRAF_KEEP_ZOOM ), true, &pItem ))
124 {
125 if( static_cast<const SfxBoolItem*>(pItem)->GetValue() )
126 m_xZoomConstRB->set_active(true);
127 else
128 m_xSizeConstRB->set_active(true);
129 m_xZoomConstRB->save_state();
130 }
131
132 sal_uInt16 nW = rPool.GetWhich( SID_ATTR_GRAF_CROP );
133 if( SfxItemState::SET == rSet->GetItemState( nW, true, &pItem))
134 {
135 FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW ));
136
137 const SvxGrfCrop* pCrop = static_cast<const SvxGrfCrop*>(pItem);
138
139 m_aExampleWN.SetLeft(pCrop->GetLeft());
140 m_aExampleWN.SetRight(pCrop->GetRight());
141 m_aExampleWN.SetTop(pCrop->GetTop());
142 m_aExampleWN.SetBottom(pCrop->GetBottom());
143
144 m_xLeftMF->set_value( m_xLeftMF->normalize( pCrop->GetLeft()), eUnit );
145 m_xRightMF->set_value( m_xRightMF->normalize( pCrop->GetRight()), eUnit );
146 m_xTopMF->set_value( m_xTopMF->normalize( pCrop->GetTop()), eUnit );
147 m_xBottomMF->set_value( m_xBottomMF->normalize( pCrop->GetBottom()), eUnit );
148 }
149 else
150 {
151 m_xLeftMF->set_value(0, FieldUnit::NONE);
152 m_xRightMF->set_value(0, FieldUnit::NONE);
153 m_xTopMF->set_value(0, FieldUnit::NONE);
154 m_xBottomMF->set_value(0, FieldUnit::NONE);
155 }
156
157 m_xLeftMF->save_value();
158 m_xRightMF->save_value();
159 m_xTopMF->save_value();
160 m_xBottomMF->save_value();
161
162 nW = rPool.GetWhich( SID_ATTR_PAGE_SIZE );
163 if ( SfxItemState::SET == rSet->GetItemState( nW, false, &pItem ) )
164 {
165 // orientation and size from the PageItem
166 FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW ));
167
168 aPageSize = static_cast<const SvxSizeItem*>(pItem)->GetSize();
169
170 auto nMin = m_xWidthMF->normalize( 23 );
171 auto nMax = m_xHeightMF->normalize(aPageSize.Height());
172 m_xHeightMF->set_range(nMin, nMax, eUnit);
173 nMax = m_xWidthMF->normalize(aPageSize.Width());
174 m_xWidthMF->set_range(nMin, nMax, eUnit);
175 }
176 else
177 {
178 aPageSize = OutputDevice::LogicToLogic(
179 Size( CM_1_TO_TWIP, CM_1_TO_TWIP ),
180 MapMode( MapUnit::MapTwip ),
181 MapMode( rSet->GetPool()->GetMetric( nW ) ) );
182 }
183
184 bool bFound = false;
185 if( SfxItemState::SET == rSet->GetItemState( SID_ATTR_GRAF_GRAPHIC, false, &pItem ) )
186 {
187 OUString referer;
188 SfxStringItem const * it = static_cast<SfxStringItem const *>(
189 rSet->GetItem(SID_REFERER));
190 if (it != nullptr) {
191 referer = it->GetValue();
192 }
193 const Graphic* pGrf = static_cast<const SvxBrushItem*>(pItem)->GetGraphic(referer);
194 if( pGrf )
195 {
196 aOrigSize = GetGrfOrigSize( *pGrf );
197 if (pGrf->GetType() == GraphicType::Bitmap && aOrigSize.Width() && aOrigSize.Height())
198 {
199 aOrigPixelSize = pGrf->GetSizePixel();
200 }
201
202 if( aOrigSize.Width() && aOrigSize.Height() )
203 {
204 CalcMinMaxBorder();
205 m_aExampleWN.SetGraphic( *pGrf );
206 m_aExampleWN.SetFrameSize( aOrigSize );
207
208 bFound = true;
209 if( !static_cast<const SvxBrushItem*>(pItem)->GetGraphicLink().isEmpty() )
210 aGraphicName = static_cast<const SvxBrushItem*>(pItem)->GetGraphicLink();
211 }
212 }
213 }
214
215 GraphicHasChanged( bFound );
216 ActivatePage( *rSet );
217 }
218
FillItemSet(SfxItemSet * rSet)219 bool SvxGrfCropPage::FillItemSet(SfxItemSet *rSet)
220 {
221 const SfxItemPool& rPool = *rSet->GetPool();
222 bool bModified = false;
223 if( m_xWidthMF->get_value_changed_from_saved() ||
224 m_xHeightMF->get_value_changed_from_saved() )
225 {
226 sal_uInt16 nW = rPool.GetWhich( SID_ATTR_GRAF_FRMSIZE );
227 FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW ));
228
229 std::shared_ptr<SvxSizeItem> aSz(std::make_shared<SvxSizeItem>(nW));
230
231 // size could already have been set from another page
232 const SfxItemSet* pExSet = GetDialogExampleSet();
233 const SfxPoolItem* pItem = nullptr;
234 if( pExSet && SfxItemState::SET ==pExSet->GetItemState( nW, false, &pItem ) )
235 {
236 aSz.reset(static_cast< SvxSizeItem*>(pItem->Clone()));
237 }
238 else
239 {
240 aSz.reset(static_cast< SvxSizeItem*>(GetItemSet().Get(nW).Clone()));
241 }
242
243 Size aTmpSz( aSz->GetSize() );
244 if( m_xWidthMF->get_value_changed_from_saved() )
245 aTmpSz.setWidth( lcl_GetValue( *m_xWidthMF, eUnit ) );
246 if( m_xHeightMF->get_value_changed_from_saved() )
247 aTmpSz.setHeight( lcl_GetValue( *m_xHeightMF, eUnit ) );
248 aSz->SetSize( aTmpSz );
249 m_xWidthMF->save_value();
250 m_xHeightMF->save_value();
251
252 bModified |= nullptr != rSet->Put( *aSz );
253
254 if( bSetOrigSize )
255 {
256 bModified |= nullptr != rSet->Put( SvxSizeItem( rPool.GetWhich(
257 SID_ATTR_GRAF_FRMSIZE_PERCENT ), Size( 0, 0 )) );
258 }
259 }
260 if( m_xLeftMF->get_value_changed_from_saved() || m_xRightMF->get_value_changed_from_saved() ||
261 m_xTopMF->get_value_changed_from_saved() || m_xBottomMF->get_value_changed_from_saved() )
262 {
263 sal_uInt16 nW = rPool.GetWhich( SID_ATTR_GRAF_CROP );
264 FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW ));
265 std::unique_ptr<SvxGrfCrop> pNew(static_cast<SvxGrfCrop*>(rSet->Get( nW ).Clone()));
266
267 pNew->SetLeft( lcl_GetValue( *m_xLeftMF, eUnit ) );
268 pNew->SetRight( lcl_GetValue( *m_xRightMF, eUnit ) );
269 pNew->SetTop( lcl_GetValue( *m_xTopMF, eUnit ) );
270 pNew->SetBottom( lcl_GetValue( *m_xBottomMF, eUnit ) );
271 bModified |= nullptr != rSet->Put( *pNew );
272 }
273
274 if( m_xZoomConstRB->get_state_changed_from_saved() )
275 {
276 bModified |= nullptr != rSet->Put( SfxBoolItem( rPool.GetWhich(
277 SID_ATTR_GRAF_KEEP_ZOOM), m_xZoomConstRB->get_active() ) );
278 }
279
280 return bModified;
281 }
282
ActivatePage(const SfxItemSet & rSet)283 void SvxGrfCropPage::ActivatePage(const SfxItemSet& rSet)
284 {
285 #ifdef DBG_UTIL
286 SfxItemPool* pPool = GetItemSet().GetPool();
287 DBG_ASSERT( pPool, "Where is the pool?" );
288 #endif
289
290 bSetOrigSize = false;
291
292 // Size
293 Size aSize;
294 const SfxPoolItem* pItem;
295 if( SfxItemState::SET == rSet.GetItemState( SID_ATTR_GRAF_FRMSIZE, false, &pItem ) )
296 aSize = static_cast<const SvxSizeItem*>(pItem)->GetSize();
297
298 nOldWidth = aSize.Width();
299 nOldHeight = aSize.Height();
300
301 auto nWidth = m_xWidthMF->normalize(nOldWidth);
302 auto nHeight = m_xHeightMF->normalize(nOldHeight);
303
304 if (nWidth != m_xWidthMF->get_value(FieldUnit::TWIP))
305 m_xWidthMF->set_value(nWidth, FieldUnit::TWIP);
306 m_xWidthMF->save_value();
307
308 if (nHeight != m_xHeightMF->get_value(FieldUnit::TWIP))
309 m_xHeightMF->set_value(nHeight, FieldUnit::TWIP);
310 m_xHeightMF->save_value();
311
312 if( SfxItemState::SET == rSet.GetItemState( SID_ATTR_GRAF_GRAPHIC, false, &pItem ) )
313 {
314 const SvxBrushItem& rBrush = *static_cast<const SvxBrushItem*>(pItem);
315 if( !rBrush.GetGraphicLink().isEmpty() &&
316 aGraphicName != rBrush.GetGraphicLink() )
317 aGraphicName = rBrush.GetGraphicLink();
318
319 OUString referer;
320 SfxStringItem const * it = static_cast<SfxStringItem const *>(
321 rSet.GetItem(SID_REFERER));
322 if (it != nullptr) {
323 referer = it->GetValue();
324 }
325 const Graphic* pGrf = rBrush.GetGraphic(referer);
326 if( pGrf )
327 {
328 m_aExampleWN.SetGraphic( *pGrf );
329 aOrigSize = GetGrfOrigSize( *pGrf );
330 if (pGrf->GetType() == GraphicType::Bitmap && aOrigSize.Width() > 1 && aOrigSize.Height() > 1) {
331 aOrigPixelSize = pGrf->GetSizePixel();
332 }
333 m_aExampleWN.SetFrameSize(aOrigSize);
334 GraphicHasChanged( aOrigSize.Width() && aOrigSize.Height() );
335 CalcMinMaxBorder();
336 }
337 else
338 GraphicHasChanged( false );
339 }
340
341 CalcZoom();
342 }
343
DeactivatePage(SfxItemSet * _pSet)344 DeactivateRC SvxGrfCropPage::DeactivatePage(SfxItemSet *_pSet)
345 {
346 if ( _pSet )
347 FillItemSet( _pSet );
348 return DeactivateRC::LeavePage;
349 }
350
351 /*--------------------------------------------------------------------
352 description: scale changed, adjust size
353 --------------------------------------------------------------------*/
354
IMPL_LINK(SvxGrfCropPage,ZoomHdl,weld::MetricSpinButton &,rField,void)355 IMPL_LINK( SvxGrfCropPage, ZoomHdl, weld::MetricSpinButton&, rField, void )
356 {
357 SfxItemPool* pPool = GetItemSet().GetPool();
358 DBG_ASSERT( pPool, "Where is the pool?" );
359 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
360 SID_ATTR_GRAF_CROP ) ) );
361
362 if (&rField == m_xWidthZoomMF.get())
363 {
364 tools::Long nLRBorders = lcl_GetValue(*m_xLeftMF, eUnit)
365 +lcl_GetValue(*m_xRightMF, eUnit);
366 m_xWidthMF->set_value( m_xWidthMF->normalize(
367 ((aOrigSize.Width() - nLRBorders) * rField.get_value(FieldUnit::NONE))/100),
368 eUnit);
369 }
370 else
371 {
372 tools::Long nULBorders = lcl_GetValue(*m_xTopMF, eUnit)
373 +lcl_GetValue(*m_xBottomMF, eUnit);
374 m_xHeightMF->set_value( m_xHeightMF->normalize(
375 ((aOrigSize.Height() - nULBorders ) * rField.get_value(FieldUnit::NONE))/100) ,
376 eUnit );
377 }
378 }
379
380 /*--------------------------------------------------------------------
381 description: change size, adjust scale
382 --------------------------------------------------------------------*/
383
IMPL_LINK(SvxGrfCropPage,SizeHdl,weld::MetricSpinButton &,rField,void)384 IMPL_LINK( SvxGrfCropPage, SizeHdl, weld::MetricSpinButton&, rField, void )
385 {
386 SfxItemPool* pPool = GetItemSet().GetPool();
387 DBG_ASSERT( pPool, "Where is the pool?" );
388 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
389 SID_ATTR_GRAF_CROP ) ) );
390
391 Size aSize( lcl_GetValue(*m_xWidthMF, eUnit),
392 lcl_GetValue(*m_xHeightMF, eUnit) );
393
394 if(&rField == m_xWidthMF.get())
395 {
396 tools::Long nWidth = aOrigSize.Width() -
397 ( lcl_GetValue(*m_xLeftMF, eUnit) +
398 lcl_GetValue(*m_xRightMF, eUnit) );
399 if(!nWidth)
400 nWidth++;
401 sal_uInt16 nZoom = static_cast<sal_uInt16>( aSize.Width() * 100 / nWidth);
402 m_xWidthZoomMF->set_value(nZoom, FieldUnit::NONE);
403 }
404 else
405 {
406 tools::Long nHeight = aOrigSize.Height() -
407 ( lcl_GetValue(*m_xTopMF, eUnit) +
408 lcl_GetValue(*m_xBottomMF, eUnit));
409 if(!nHeight)
410 nHeight++;
411 sal_uInt16 nZoom = static_cast<sal_uInt16>( aSize.Height() * 100 / nHeight);
412 m_xHeightZoomMF->set_value(nZoom, FieldUnit::NONE);
413 }
414 }
415
416 /*--------------------------------------------------------------------
417 description: evaluate border
418 --------------------------------------------------------------------*/
419
IMPL_LINK(SvxGrfCropPage,CropModifyHdl,weld::MetricSpinButton &,rField,void)420 IMPL_LINK( SvxGrfCropPage, CropModifyHdl, weld::MetricSpinButton&, rField, void )
421 {
422 SfxItemPool* pPool = GetItemSet().GetPool();
423 DBG_ASSERT( pPool, "Where is the pool?" );
424 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
425 SID_ATTR_GRAF_CROP ) ) );
426
427 bool bZoom = m_xZoomConstRB->get_active();
428 if (&rField == m_xLeftMF.get() || &rField == m_xRightMF.get())
429 {
430 tools::Long nLeft = lcl_GetValue( *m_xLeftMF, eUnit );
431 tools::Long nRight = lcl_GetValue( *m_xRightMF, eUnit );
432 tools::Long nWidthZoom = static_cast<tools::Long>(m_xWidthZoomMF->get_value(FieldUnit::NONE));
433 if (bZoom && nWidthZoom != 0 && ( ( ( aOrigSize.Width() - (nLeft + nRight )) * nWidthZoom )
434 / 100 >= aPageSize.Width() ) )
435 {
436 if (&rField == m_xLeftMF.get())
437 {
438 nLeft = aOrigSize.Width() -
439 ( aPageSize.Width() * 100 / nWidthZoom + nRight );
440 m_xLeftMF->set_value( m_xLeftMF->normalize( nLeft ), eUnit );
441 }
442 else
443 {
444 nRight = aOrigSize.Width() -
445 ( aPageSize.Width() * 100 / nWidthZoom + nLeft );
446 m_xRightMF->set_value( m_xRightMF->normalize( nRight ), eUnit );
447 }
448 }
449 if (AllSettings::GetLayoutRTL())
450 {
451 m_aExampleWN.SetLeft(nRight);
452 m_aExampleWN.SetRight(nLeft);
453 }
454 else
455 {
456 m_aExampleWN.SetLeft(nLeft);
457 m_aExampleWN.SetRight(nRight);
458 }
459 if(bZoom)
460 {
461 // scale stays, recompute width
462 ZoomHdl(*m_xWidthZoomMF);
463 }
464 }
465 else
466 {
467 tools::Long nTop = lcl_GetValue( *m_xTopMF, eUnit );
468 tools::Long nBottom = lcl_GetValue( *m_xBottomMF, eUnit );
469 tools::Long nHeightZoom = static_cast<tools::Long>(m_xHeightZoomMF->get_value(FieldUnit::NONE));
470 if(bZoom && ( ( ( aOrigSize.Height() - (nTop + nBottom )) * nHeightZoom)
471 / 100 >= aPageSize.Height()))
472 {
473 assert(nHeightZoom && "div-by-zero");
474 if(&rField == m_xTopMF.get())
475 {
476 nTop = aOrigSize.Height() -
477 ( aPageSize.Height() * 100 / nHeightZoom + nBottom);
478 m_xTopMF->set_value( m_xWidthMF->normalize( nTop ), eUnit );
479 }
480 else
481 {
482 nBottom = aOrigSize.Height() -
483 ( aPageSize.Height() * 100 / nHeightZoom + nTop);
484 m_xBottomMF->set_value( m_xWidthMF->normalize( nBottom ), eUnit );
485 }
486 }
487 m_aExampleWN.SetTop( nTop );
488 m_aExampleWN.SetBottom( nBottom );
489 if(bZoom)
490 {
491 // scale stays, recompute height
492 ZoomHdl(*m_xHeightZoomMF);
493 }
494 }
495 m_aExampleWN.Invalidate();
496 // size and border changed -> recompute scale
497 if(!bZoom)
498 CalcZoom();
499 CalcMinMaxBorder();
500 }
501 /*--------------------------------------------------------------------
502 description: set original size
503 --------------------------------------------------------------------*/
504
IMPL_LINK_NOARG(SvxGrfCropPage,OrigSizeHdl,weld::Button &,void)505 IMPL_LINK_NOARG(SvxGrfCropPage, OrigSizeHdl, weld::Button&, void)
506 {
507 SfxItemPool* pPool = GetItemSet().GetPool();
508 DBG_ASSERT( pPool, "Where is the pool?" );
509 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
510 SID_ATTR_GRAF_CROP ) ) );
511
512 tools::Long nWidth = aOrigSize.Width() -
513 lcl_GetValue( *m_xLeftMF, eUnit ) -
514 lcl_GetValue( *m_xRightMF, eUnit );
515 m_xWidthMF->set_value( m_xWidthMF->normalize( nWidth ), eUnit );
516 tools::Long nHeight = aOrigSize.Height() -
517 lcl_GetValue( *m_xTopMF, eUnit ) -
518 lcl_GetValue( *m_xBottomMF, eUnit );
519 m_xHeightMF->set_value( m_xHeightMF->normalize( nHeight ), eUnit );
520 m_xWidthZoomMF->set_value(100, FieldUnit::NONE);
521 m_xHeightZoomMF->set_value(100, FieldUnit::NONE);
522 bSetOrigSize = true;
523 }
524 /*--------------------------------------------------------------------
525 description: compute scale
526 --------------------------------------------------------------------*/
527
CalcZoom()528 void SvxGrfCropPage::CalcZoom()
529 {
530 SfxItemPool* pPool = GetItemSet().GetPool();
531 DBG_ASSERT( pPool, "Where is the pool?" );
532 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
533 SID_ATTR_GRAF_CROP ) ) );
534
535 tools::Long nWidth = lcl_GetValue( *m_xWidthMF, eUnit );
536 tools::Long nHeight = lcl_GetValue( *m_xHeightMF, eUnit );
537 tools::Long nLRBorders = lcl_GetValue( *m_xLeftMF, eUnit ) +
538 lcl_GetValue( *m_xRightMF, eUnit );
539 tools::Long nULBorders = lcl_GetValue( *m_xTopMF, eUnit ) +
540 lcl_GetValue( *m_xBottomMF, eUnit );
541 sal_uInt16 nZoom = 0;
542 tools::Long nDen;
543 if( (nDen = aOrigSize.Width() - nLRBorders) > 0)
544 nZoom = static_cast<sal_uInt16>((( nWidth * 1000 / nDen )+5)/10);
545 m_xWidthZoomMF->set_value(nZoom, FieldUnit::NONE);
546 if( (nDen = aOrigSize.Height() - nULBorders) > 0)
547 nZoom = static_cast<sal_uInt16>((( nHeight * 1000 / nDen )+5)/10);
548 else
549 nZoom = 0;
550 m_xHeightZoomMF->set_value(nZoom, FieldUnit::NONE);
551 }
552
553 /*--------------------------------------------------------------------
554 description: set minimum/maximum values for the margins
555 --------------------------------------------------------------------*/
556
CalcMinMaxBorder()557 void SvxGrfCropPage::CalcMinMaxBorder()
558 {
559 SfxItemPool* pPool = GetItemSet().GetPool();
560 DBG_ASSERT( pPool, "Where is the pool?" );
561 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
562 SID_ATTR_GRAF_CROP ) ) );
563 tools::Long nR = lcl_GetValue(*m_xRightMF, eUnit );
564 tools::Long nMinWidth = (aOrigSize.Width() * 10) /11;
565 tools::Long nMin = nMinWidth - (nR >= 0 ? nR : 0);
566 m_xLeftMF->set_max( m_xLeftMF->normalize(nMin), eUnit );
567
568 tools::Long nL = lcl_GetValue(*m_xLeftMF, eUnit );
569 nMin = nMinWidth - (nL >= 0 ? nL : 0);
570 m_xRightMF->set_max( m_xRightMF->normalize(nMin), eUnit );
571
572 tools::Long nUp = lcl_GetValue( *m_xTopMF, eUnit );
573 tools::Long nMinHeight = (aOrigSize.Height() * 10) /11;
574 nMin = nMinHeight - (nUp >= 0 ? nUp : 0);
575 m_xBottomMF->set_max( m_xBottomMF->normalize(nMin), eUnit );
576
577 tools::Long nLow = lcl_GetValue(*m_xBottomMF, eUnit );
578 nMin = nMinHeight - (nLow >= 0 ? nLow : 0);
579 m_xTopMF->set_max( m_xTopMF->normalize(nMin), eUnit );
580 }
581 /*--------------------------------------------------------------------
582 description: set spinsize to 1/20 of the original size,
583 fill FixedText with the original size
584 --------------------------------------------------------------------*/
585
GraphicHasChanged(bool bFound)586 void SvxGrfCropPage::GraphicHasChanged( bool bFound )
587 {
588 if( bFound )
589 {
590 SfxItemPool* pPool = GetItemSet().GetPool();
591 DBG_ASSERT( pPool, "Where is the pool?" );
592 FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
593 SID_ATTR_GRAF_CROP ) ));
594
595 sal_Int64 nSpin = m_xLeftMF->normalize(aOrigSize.Width()) / 20;
596 nSpin = vcl::ConvertValue( nSpin, aOrigSize.Width(), 0,
597 eUnit, m_xLeftMF->get_unit());
598
599 // if the margin is too big, it is set to 1/3 on both pages
600 tools::Long nR = lcl_GetValue( *m_xRightMF, eUnit );
601 tools::Long nL = lcl_GetValue( *m_xLeftMF, eUnit );
602 if((nL + nR) < - aOrigSize.Width())
603 {
604 tools::Long nVal = aOrigSize.Width() / -3;
605 m_xRightMF->set_value( m_xRightMF->normalize( nVal ), eUnit );
606 m_xLeftMF->set_value( m_xLeftMF->normalize( nVal ), eUnit );
607 m_aExampleWN.SetLeft(nVal);
608 m_aExampleWN.SetRight(nVal);
609 }
610 tools::Long nUp = lcl_GetValue(*m_xTopMF, eUnit );
611 tools::Long nLow = lcl_GetValue(*m_xBottomMF, eUnit );
612 if((nUp + nLow) < - aOrigSize.Height())
613 {
614 tools::Long nVal = aOrigSize.Height() / -3;
615 m_xTopMF->set_value( m_xTopMF->normalize( nVal ), eUnit );
616 m_xBottomMF->set_value( m_xBottomMF->normalize( nVal ), eUnit );
617 m_aExampleWN.SetTop(nVal);
618 m_aExampleWN.SetBottom(nVal);
619 }
620
621 m_xLeftMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE);
622 m_xRightMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE);
623 nSpin = m_xTopMF->normalize(aOrigSize.Height()) / 20;
624 nSpin = vcl::ConvertValue( nSpin, aOrigSize.Width(), 0,
625 eUnit, m_xLeftMF->get_unit() );
626 m_xTopMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE);
627 m_xBottomMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE);
628
629 // display original size
630 const FieldUnit eMetric = GetModuleFieldUnit( GetItemSet() );
631
632 OUString sTemp;
633 {
634 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/spinbox.ui"));
635 std::unique_ptr<weld::Dialog> xTopLevel(xBuilder->weld_dialog("SpinDialog"));
636 std::unique_ptr<weld::MetricSpinButton> xFld(xBuilder->weld_metric_spin_button("spin", FieldUnit::CM));
637 SetFieldUnit( *xFld, eMetric );
638 xFld->set_digits(m_xWidthMF->get_digits());
639 xFld->set_max(INT_MAX - 1, FieldUnit::NONE);
640
641 xFld->set_value(xFld->normalize(aOrigSize.Width()), eUnit);
642 sTemp = xFld->get_text();
643 xFld->set_value(xFld->normalize(aOrigSize.Height()), eUnit);
644 // multiplication sign (U+00D7)
645 sTemp += u"\u00D7" + xFld->get_text();
646 }
647
648 if ( aOrigPixelSize.Width() && aOrigPixelSize.Height() ) {
649 sal_Int32 ax = 0.5 + aOrigPixelSize.Width() /
650 o3tl::convert<double>(aOrigSize.Width(), o3tl::Length::twip,
651 o3tl::Length::in);
652 sal_Int32 ay = 0.5 + aOrigPixelSize.Height() /
653 o3tl::convert<double>(aOrigSize.Height(), o3tl::Length::twip,
654 o3tl::Length::in);
655 OUString sPPI = OUString::number(ax);
656 if (abs(ax - ay) > 1) {
657 sPPI += u"\u00D7" + OUString::number(ay);
658 }
659 sTemp += " " + CuiResId(RID_SVXSTR_PPI).replaceAll("%1", sPPI);
660 }
661 m_xOrigSizeFT->set_label(sTemp);
662 }
663
664 m_xCropFrame->set_sensitive(bFound);
665 m_xScaleFrame->set_sensitive(bFound);
666 m_xSizeFrame->set_sensitive(bFound);
667 m_xOrigSizeGrid->set_sensitive(bFound);
668 m_xZoomConstRB->set_sensitive(bFound);
669 }
670
GetGrfOrigSize(const Graphic & rGrf)671 Size SvxGrfCropPage::GetGrfOrigSize(const Graphic& rGrf)
672 {
673 const MapMode aMapTwip( MapUnit::MapTwip );
674 Size aSize( rGrf.GetPrefSize() );
675 if( MapUnit::MapPixel == rGrf.GetPrefMapMode().GetMapUnit() )
676 aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMapTwip);
677 else
678 aSize = OutputDevice::LogicToLogic( aSize,
679 rGrf.GetPrefMapMode(), aMapTwip );
680 return aSize;
681 }
682
683 /*****************************************************************/
684
SvxCropExample()685 SvxCropExample::SvxCropExample()
686 : m_aTopLeft(0, 0)
687 , m_aBottomRight(0, 0)
688 {
689 }
690
SetDrawingArea(weld::DrawingArea * pDrawingArea)691 void SvxCropExample::SetDrawingArea(weld::DrawingArea* pDrawingArea)
692 {
693 CustomWidgetController::SetDrawingArea(pDrawingArea);
694 OutputDevice& rDevice = pDrawingArea->get_ref_device();
695 Size aSize(rDevice.LogicToPixel(Size(78, 78), MapMode(MapUnit::MapAppFont)));
696 pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
697
698 m_aMapMode = rDevice.GetMapMode();
699 m_aFrameSize = OutputDevice::LogicToLogic(
700 Size(CM_1_TO_TWIP / 2, CM_1_TO_TWIP / 2),
701 MapMode(MapUnit::MapTwip), m_aMapMode);
702 }
703
Paint(vcl::RenderContext & rRenderContext,const::tools::Rectangle &)704 void SvxCropExample::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&)
705 {
706 rRenderContext.Push(PushFlags::MAPMODE);
707 rRenderContext.SetMapMode(m_aMapMode);
708
709 // Win BG
710 const Size aWinSize(rRenderContext.PixelToLogic(GetOutputSizePixel()));
711 rRenderContext.SetLineColor();
712 rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetWindowColor());
713 rRenderContext.DrawRect(::tools::Rectangle(Point(), aWinSize));
714
715 // use AA, the Graphic may be a metafile/svg and would then look ugly
716 rRenderContext.SetAntialiasing(AntialiasingFlags::Enable);
717
718 // draw Graphic
719 ::tools::Rectangle aRect(
720 Point((aWinSize.Width() - m_aFrameSize.Width())/2, (aWinSize.Height() - m_aFrameSize.Height())/2),
721 m_aFrameSize);
722 m_aGrf.Draw(rRenderContext, aRect.TopLeft(), aRect.GetSize());
723
724 // Remove one more case that uses XOR paint (RasterOp::Invert).
725 // Get colors and logic DashLength from settings, use equal to
726 // PolygonMarkerPrimitive2D, may be changed to that primitive later.
727 // Use this to guarantee good visibility - that was the purpose of
728 // the former used XOR paint.
729 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
730 const Color aColA(aSvtOptionsDrawinglayer.GetStripeColorA().getBColor());
731 const Color aColB(aSvtOptionsDrawinglayer.GetStripeColorB().getBColor());
732 const double fStripeLength(aSvtOptionsDrawinglayer.GetStripeLength());
733 const basegfx::B2DVector aDashVector(rRenderContext.GetInverseViewTransformation() * basegfx::B2DVector(fStripeLength, 0.0));
734 const double fLogicDashLength(aDashVector.getX());
735
736 // apply current crop settings
737 aRect.AdjustLeft(m_aTopLeft.Y());
738 aRect.AdjustTop(m_aTopLeft.X());
739 aRect.AdjustRight(-m_aBottomRight.Y());
740 aRect.AdjustBottom(-m_aBottomRight.X());
741
742 // apply dash with direct paint callbacks
743 basegfx::utils::applyLineDashing(
744 basegfx::utils::createPolygonFromRect(
745 basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom())),
746 std::vector< double >(2, fLogicDashLength),
747 [&aColA,&rRenderContext](const basegfx::B2DPolygon& rSnippet)
748 {
749 rRenderContext.SetLineColor(aColA);
750 rRenderContext.DrawPolyLine(rSnippet);
751 },
752 [&aColB,&rRenderContext](const basegfx::B2DPolygon& rSnippet)
753 {
754 rRenderContext.SetLineColor(aColB);
755 rRenderContext.DrawPolyLine(rSnippet);
756 },
757 2.0 * fLogicDashLength);
758
759 rRenderContext.Pop();
760 }
761
Resize()762 void SvxCropExample::Resize()
763 {
764 SetFrameSize(m_aFrameSize);
765 }
766
SetFrameSize(const Size & rSz)767 void SvxCropExample::SetFrameSize( const Size& rSz )
768 {
769 m_aFrameSize = rSz;
770 if (!m_aFrameSize.Width())
771 m_aFrameSize.setWidth( 1 );
772 if (!m_aFrameSize.Height())
773 m_aFrameSize.setHeight( 1 );
774 Size aWinSize( GetOutputSizePixel() );
775 Fraction aXScale( aWinSize.Width() * 4, m_aFrameSize.Width() * 5 );
776 Fraction aYScale( aWinSize.Height() * 4, m_aFrameSize.Height() * 5 );
777
778 if( aYScale < aXScale )
779 aXScale = aYScale;
780
781 m_aMapMode.SetScaleX(aXScale);
782 m_aMapMode.SetScaleY(aXScale);
783
784 Invalidate();
785 }
786
787 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
788