summaryrefslogtreecommitdiffstats
path: root/cui/source/tabpages/grfpage.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /cui/source/tabpages/grfpage.cxx
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'cui/source/tabpages/grfpage.cxx')
-rw-r--r--cui/source/tabpages/grfpage.cxx785
1 files changed, 785 insertions, 0 deletions
diff --git a/cui/source/tabpages/grfpage.cxx b/cui/source/tabpages/grfpage.cxx
new file mode 100644
index 000000000..7f334e2f1
--- /dev/null
+++ b/cui/source/tabpages/grfpage.cxx
@@ -0,0 +1,785 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <dialmgr.hxx>
+#include <svx/dlgutil.hxx>
+#include <editeng/sizeitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <grfpage.hxx>
+#include <svx/grfcrop.hxx>
+#include <rtl/ustring.hxx>
+#include <tools/debug.hxx>
+#include <tools/fract.hxx>
+#include <svx/svxids.hrc>
+#include <strings.hrc>
+#include <vcl/fieldvalues.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <svtools/unitconv.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+
+#define CM_1_TO_TWIP 567
+#define TWIP_TO_INCH 1440
+
+
+static int lcl_GetValue(const weld::MetricSpinButton& rMetric, FieldUnit eUnit)
+{
+ return rMetric.denormalize(rMetric.get_value(eUnit));
+}
+
+/*--------------------------------------------------------------------
+ description: crop graphic
+ --------------------------------------------------------------------*/
+
+SvxGrfCropPage::SvxGrfCropPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet)
+ : SfxTabPage(pPage, pController, "cui/ui/croppage.ui", "CropPage", &rSet)
+ , nOldWidth(0)
+ , nOldHeight(0)
+ , bSetOrigSize(false)
+ , m_xCropFrame(m_xBuilder->weld_widget("cropframe"))
+ , m_xZoomConstRB(m_xBuilder->weld_radio_button("keepscale"))
+ , m_xSizeConstRB(m_xBuilder->weld_radio_button("keepsize"))
+ , m_xLeftMF(m_xBuilder->weld_metric_spin_button("left", FieldUnit::CM))
+ , m_xRightMF(m_xBuilder->weld_metric_spin_button("right", FieldUnit::CM))
+ , m_xTopMF(m_xBuilder->weld_metric_spin_button("top", FieldUnit::CM))
+ , m_xBottomMF(m_xBuilder->weld_metric_spin_button("bottom", FieldUnit::CM))
+ , m_xScaleFrame(m_xBuilder->weld_widget("scaleframe"))
+ , m_xWidthZoomMF(m_xBuilder->weld_metric_spin_button("widthzoom", FieldUnit::PERCENT))
+ , m_xHeightZoomMF(m_xBuilder->weld_metric_spin_button("heightzoom", FieldUnit::PERCENT))
+ , m_xSizeFrame(m_xBuilder->weld_widget("sizeframe"))
+ , m_xWidthMF(m_xBuilder->weld_metric_spin_button("width", FieldUnit::CM))
+ , m_xHeightMF(m_xBuilder->weld_metric_spin_button("height", FieldUnit::CM))
+ , m_xOrigSizeGrid(m_xBuilder->weld_widget("origsizegrid"))
+ , m_xOrigSizeFT(m_xBuilder->weld_label("origsizeft"))
+ , m_xOrigSizePB(m_xBuilder->weld_button("origsize"))
+ , m_xExampleWN(new weld::CustomWeld(*m_xBuilder, "preview", m_aExampleWN))
+{
+ SetExchangeSupport();
+
+ // set the correct metric
+ const FieldUnit eMetric = GetModuleFieldUnit( rSet );
+
+ SetFieldUnit( *m_xWidthMF, eMetric );
+ SetFieldUnit( *m_xHeightMF, eMetric );
+ SetFieldUnit( *m_xLeftMF, eMetric );
+ SetFieldUnit( *m_xRightMF, eMetric );
+ SetFieldUnit( *m_xTopMF , eMetric );
+ SetFieldUnit( *m_xBottomMF, eMetric );
+
+ Link<weld::MetricSpinButton&,void> aLk = LINK(this, SvxGrfCropPage, SizeHdl);
+ m_xWidthMF->connect_value_changed( aLk );
+ m_xHeightMF->connect_value_changed( aLk );
+
+ aLk = LINK(this, SvxGrfCropPage, ZoomHdl);
+ m_xWidthZoomMF->connect_value_changed( aLk );
+ m_xHeightZoomMF->connect_value_changed( aLk );
+
+ aLk = LINK(this, SvxGrfCropPage, CropModifyHdl);
+ m_xLeftMF->connect_value_changed( aLk );
+ m_xRightMF->connect_value_changed( aLk );
+ m_xTopMF->connect_value_changed( aLk );
+ m_xBottomMF->connect_value_changed( aLk );
+
+ m_xOrigSizePB->connect_clicked(LINK(this, SvxGrfCropPage, OrigSizeHdl));
+}
+
+SvxGrfCropPage::~SvxGrfCropPage()
+{
+ m_xExampleWN.reset();
+}
+
+std::unique_ptr<SfxTabPage> SvxGrfCropPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet)
+{
+ return std::make_unique<SvxGrfCropPage>(pPage, pController, *rSet);
+}
+
+void SvxGrfCropPage::Reset( const SfxItemSet *rSet )
+{
+ const SfxPoolItem* pItem;
+ const SfxItemPool& rPool = *rSet->GetPool();
+
+ if(SfxItemState::SET == rSet->GetItemState( rPool.GetWhich(
+ SID_ATTR_GRAF_KEEP_ZOOM ), true, &pItem ))
+ {
+ if( static_cast<const SfxBoolItem*>(pItem)->GetValue() )
+ m_xZoomConstRB->set_active(true);
+ else
+ m_xSizeConstRB->set_active(true);
+ m_xZoomConstRB->save_state();
+ }
+
+ sal_uInt16 nW = rPool.GetWhich( SID_ATTR_GRAF_CROP );
+ if( SfxItemState::SET == rSet->GetItemState( nW, true, &pItem))
+ {
+ FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW ));
+
+ const SvxGrfCrop* pCrop = static_cast<const SvxGrfCrop*>(pItem);
+
+ m_aExampleWN.SetLeft(pCrop->GetLeft());
+ m_aExampleWN.SetRight(pCrop->GetRight());
+ m_aExampleWN.SetTop(pCrop->GetTop());
+ m_aExampleWN.SetBottom(pCrop->GetBottom());
+
+ m_xLeftMF->set_value( m_xLeftMF->normalize( pCrop->GetLeft()), eUnit );
+ m_xRightMF->set_value( m_xRightMF->normalize( pCrop->GetRight()), eUnit );
+ m_xTopMF->set_value( m_xTopMF->normalize( pCrop->GetTop()), eUnit );
+ m_xBottomMF->set_value( m_xBottomMF->normalize( pCrop->GetBottom()), eUnit );
+ }
+ else
+ {
+ m_xLeftMF->set_value(0, FieldUnit::NONE);
+ m_xRightMF->set_value(0, FieldUnit::NONE);
+ m_xTopMF->set_value(0, FieldUnit::NONE);
+ m_xBottomMF->set_value(0, FieldUnit::NONE);
+ }
+
+ m_xLeftMF->save_value();
+ m_xRightMF->save_value();
+ m_xTopMF->save_value();
+ m_xBottomMF->save_value();
+
+ nW = rPool.GetWhich( SID_ATTR_PAGE_SIZE );
+ if ( SfxItemState::SET == rSet->GetItemState( nW, false, &pItem ) )
+ {
+ // orientation and size from the PageItem
+ FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW ));
+
+ aPageSize = static_cast<const SvxSizeItem*>(pItem)->GetSize();
+
+ auto nMin = m_xWidthMF->normalize( 23 );
+ auto nMax = m_xHeightMF->normalize(aPageSize.Height());
+ m_xHeightMF->set_range(nMin, nMax, eUnit);
+ nMax = m_xWidthMF->normalize(aPageSize.Width());
+ m_xWidthMF->set_range(nMin, nMax, eUnit);
+ }
+ else
+ {
+ aPageSize = OutputDevice::LogicToLogic(
+ Size( CM_1_TO_TWIP, CM_1_TO_TWIP ),
+ MapMode( MapUnit::MapTwip ),
+ MapMode( rSet->GetPool()->GetMetric( nW ) ) );
+ }
+
+ bool bFound = false;
+ if( SfxItemState::SET == rSet->GetItemState( SID_ATTR_GRAF_GRAPHIC, false, &pItem ) )
+ {
+ OUString referer;
+ SfxStringItem const * it = static_cast<SfxStringItem const *>(
+ rSet->GetItem(SID_REFERER));
+ if (it != nullptr) {
+ referer = it->GetValue();
+ }
+ const Graphic* pGrf = static_cast<const SvxBrushItem*>(pItem)->GetGraphic(referer);
+ if( pGrf )
+ {
+ aOrigSize = GetGrfOrigSize( *pGrf );
+ if (pGrf->GetType() == GraphicType::Bitmap && aOrigSize.Width() && aOrigSize.Height())
+ {
+ aOrigPixelSize = pGrf->GetSizePixel();
+ }
+
+ if( aOrigSize.Width() && aOrigSize.Height() )
+ {
+ CalcMinMaxBorder();
+ m_aExampleWN.SetGraphic( *pGrf );
+ m_aExampleWN.SetFrameSize( aOrigSize );
+
+ bFound = true;
+ if( !static_cast<const SvxBrushItem*>(pItem)->GetGraphicLink().isEmpty() )
+ aGraphicName = static_cast<const SvxBrushItem*>(pItem)->GetGraphicLink();
+ }
+ }
+ }
+
+ GraphicHasChanged( bFound );
+ ActivatePage( *rSet );
+}
+
+bool SvxGrfCropPage::FillItemSet(SfxItemSet *rSet)
+{
+ const SfxItemPool& rPool = *rSet->GetPool();
+ bool bModified = false;
+ if( m_xWidthMF->get_value_changed_from_saved() ||
+ m_xHeightMF->get_value_changed_from_saved() )
+ {
+ sal_uInt16 nW = rPool.GetWhich( SID_ATTR_GRAF_FRMSIZE );
+ FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW ));
+
+ std::shared_ptr<SvxSizeItem> aSz(std::make_shared<SvxSizeItem>(nW));
+
+ // size could already have been set from another page
+ const SfxItemSet* pExSet = GetDialogExampleSet();
+ const SfxPoolItem* pItem = nullptr;
+ if( pExSet && SfxItemState::SET ==pExSet->GetItemState( nW, false, &pItem ) )
+ {
+ aSz.reset(static_cast< SvxSizeItem*>(pItem->Clone()));
+ }
+ else
+ {
+ aSz.reset(static_cast< SvxSizeItem*>(GetItemSet().Get(nW).Clone()));
+ }
+
+ Size aTmpSz( aSz->GetSize() );
+ if( m_xWidthMF->get_value_changed_from_saved() )
+ aTmpSz.setWidth( lcl_GetValue( *m_xWidthMF, eUnit ) );
+ if( m_xHeightMF->get_value_changed_from_saved() )
+ aTmpSz.setHeight( lcl_GetValue( *m_xHeightMF, eUnit ) );
+ aSz->SetSize( aTmpSz );
+ m_xWidthMF->save_value();
+ m_xHeightMF->save_value();
+
+ bModified |= nullptr != rSet->Put( *aSz );
+
+ if( bSetOrigSize )
+ {
+ bModified |= nullptr != rSet->Put( SvxSizeItem( rPool.GetWhich(
+ SID_ATTR_GRAF_FRMSIZE_PERCENT ), Size( 0, 0 )) );
+ }
+ }
+ if( m_xLeftMF->get_value_changed_from_saved() || m_xRightMF->get_value_changed_from_saved() ||
+ m_xTopMF->get_value_changed_from_saved() || m_xBottomMF->get_value_changed_from_saved() )
+ {
+ sal_uInt16 nW = rPool.GetWhich( SID_ATTR_GRAF_CROP );
+ FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW ));
+ std::unique_ptr<SvxGrfCrop> pNew(static_cast<SvxGrfCrop*>(rSet->Get( nW ).Clone()));
+
+ pNew->SetLeft( lcl_GetValue( *m_xLeftMF, eUnit ) );
+ pNew->SetRight( lcl_GetValue( *m_xRightMF, eUnit ) );
+ pNew->SetTop( lcl_GetValue( *m_xTopMF, eUnit ) );
+ pNew->SetBottom( lcl_GetValue( *m_xBottomMF, eUnit ) );
+ bModified |= nullptr != rSet->Put( *pNew );
+ }
+
+ if( m_xZoomConstRB->get_state_changed_from_saved() )
+ {
+ bModified |= nullptr != rSet->Put( SfxBoolItem( rPool.GetWhich(
+ SID_ATTR_GRAF_KEEP_ZOOM), m_xZoomConstRB->get_active() ) );
+ }
+
+ return bModified;
+}
+
+void SvxGrfCropPage::ActivatePage(const SfxItemSet& rSet)
+{
+#ifdef DBG_UTIL
+ SfxItemPool* pPool = GetItemSet().GetPool();
+ DBG_ASSERT( pPool, "Where is the pool?" );
+#endif
+
+ bSetOrigSize = false;
+
+ // Size
+ Size aSize;
+ const SfxPoolItem* pItem;
+ if( SfxItemState::SET == rSet.GetItemState( SID_ATTR_GRAF_FRMSIZE, false, &pItem ) )
+ aSize = static_cast<const SvxSizeItem*>(pItem)->GetSize();
+
+ nOldWidth = aSize.Width();
+ nOldHeight = aSize.Height();
+
+ auto nWidth = m_xWidthMF->normalize(nOldWidth);
+ auto nHeight = m_xHeightMF->normalize(nOldHeight);
+
+ if (nWidth != m_xWidthMF->get_value(FieldUnit::TWIP))
+ m_xWidthMF->set_value(nWidth, FieldUnit::TWIP);
+ m_xWidthMF->save_value();
+
+ if (nHeight != m_xHeightMF->get_value(FieldUnit::TWIP))
+ m_xHeightMF->set_value(nHeight, FieldUnit::TWIP);
+ m_xHeightMF->save_value();
+
+ if( SfxItemState::SET == rSet.GetItemState( SID_ATTR_GRAF_GRAPHIC, false, &pItem ) )
+ {
+ const SvxBrushItem& rBrush = *static_cast<const SvxBrushItem*>(pItem);
+ if( !rBrush.GetGraphicLink().isEmpty() &&
+ aGraphicName != rBrush.GetGraphicLink() )
+ aGraphicName = rBrush.GetGraphicLink();
+
+ OUString referer;
+ SfxStringItem const * it = static_cast<SfxStringItem const *>(
+ rSet.GetItem(SID_REFERER));
+ if (it != nullptr) {
+ referer = it->GetValue();
+ }
+ const Graphic* pGrf = rBrush.GetGraphic(referer);
+ if( pGrf )
+ {
+ m_aExampleWN.SetGraphic( *pGrf );
+ aOrigSize = GetGrfOrigSize( *pGrf );
+ if (pGrf->GetType() == GraphicType::Bitmap && aOrigSize.Width() > 1 && aOrigSize.Height() > 1) {
+ aOrigPixelSize = pGrf->GetSizePixel();
+ }
+ m_aExampleWN.SetFrameSize(aOrigSize);
+ GraphicHasChanged( aOrigSize.Width() && aOrigSize.Height() );
+ CalcMinMaxBorder();
+ }
+ else
+ GraphicHasChanged( false );
+ }
+
+ CalcZoom();
+}
+
+DeactivateRC SvxGrfCropPage::DeactivatePage(SfxItemSet *_pSet)
+{
+ if ( _pSet )
+ FillItemSet( _pSet );
+ return DeactivateRC::LeavePage;
+}
+
+/*--------------------------------------------------------------------
+ description: scale changed, adjust size
+ --------------------------------------------------------------------*/
+
+IMPL_LINK( SvxGrfCropPage, ZoomHdl, weld::MetricSpinButton&, rField, void )
+{
+ SfxItemPool* pPool = GetItemSet().GetPool();
+ DBG_ASSERT( pPool, "Where is the pool?" );
+ FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
+ SID_ATTR_GRAF_CROP ) ) );
+
+ if (&rField == m_xWidthZoomMF.get())
+ {
+ long nLRBorders = lcl_GetValue(*m_xLeftMF, eUnit)
+ +lcl_GetValue(*m_xRightMF, eUnit);
+ m_xWidthMF->set_value( m_xWidthMF->normalize(
+ ((aOrigSize.Width() - nLRBorders) * rField.get_value(FieldUnit::NONE))/100),
+ eUnit);
+ }
+ else
+ {
+ long nULBorders = lcl_GetValue(*m_xTopMF, eUnit)
+ +lcl_GetValue(*m_xBottomMF, eUnit);
+ m_xHeightMF->set_value( m_xHeightMF->normalize(
+ ((aOrigSize.Height() - nULBorders ) * rField.get_value(FieldUnit::NONE))/100) ,
+ eUnit );
+ }
+}
+
+/*--------------------------------------------------------------------
+ description: change size, adjust scale
+ --------------------------------------------------------------------*/
+
+IMPL_LINK( SvxGrfCropPage, SizeHdl, weld::MetricSpinButton&, rField, void )
+{
+ SfxItemPool* pPool = GetItemSet().GetPool();
+ DBG_ASSERT( pPool, "Where is the pool?" );
+ FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
+ SID_ATTR_GRAF_CROP ) ) );
+
+ Size aSize( lcl_GetValue(*m_xWidthMF, eUnit),
+ lcl_GetValue(*m_xHeightMF, eUnit) );
+
+ if(&rField == m_xWidthMF.get())
+ {
+ long nWidth = aOrigSize.Width() -
+ ( lcl_GetValue(*m_xLeftMF, eUnit) +
+ lcl_GetValue(*m_xRightMF, eUnit) );
+ if(!nWidth)
+ nWidth++;
+ sal_uInt16 nZoom = static_cast<sal_uInt16>( aSize.Width() * 100 / nWidth);
+ m_xWidthZoomMF->set_value(nZoom, FieldUnit::NONE);
+ }
+ else
+ {
+ long nHeight = aOrigSize.Height() -
+ ( lcl_GetValue(*m_xTopMF, eUnit) +
+ lcl_GetValue(*m_xBottomMF, eUnit));
+ if(!nHeight)
+ nHeight++;
+ sal_uInt16 nZoom = static_cast<sal_uInt16>( aSize.Height() * 100 / nHeight);
+ m_xHeightZoomMF->set_value(nZoom, FieldUnit::NONE);
+ }
+}
+
+/*--------------------------------------------------------------------
+ description: evaluate border
+ --------------------------------------------------------------------*/
+
+IMPL_LINK( SvxGrfCropPage, CropModifyHdl, weld::MetricSpinButton&, rField, void )
+{
+ SfxItemPool* pPool = GetItemSet().GetPool();
+ DBG_ASSERT( pPool, "Where is the pool?" );
+ FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
+ SID_ATTR_GRAF_CROP ) ) );
+
+ bool bZoom = m_xZoomConstRB->get_active();
+ if (&rField == m_xLeftMF.get() || &rField == m_xRightMF.get())
+ {
+ long nLeft = lcl_GetValue( *m_xLeftMF, eUnit );
+ long nRight = lcl_GetValue( *m_xRightMF, eUnit );
+ long nWidthZoom = static_cast<long>(m_xWidthZoomMF->get_value(FieldUnit::NONE));
+ if (bZoom && nWidthZoom != 0 && ( ( ( aOrigSize.Width() - (nLeft + nRight )) * nWidthZoom )
+ / 100 >= aPageSize.Width() ) )
+ {
+ if (&rField == m_xLeftMF.get())
+ {
+ nLeft = aOrigSize.Width() -
+ ( aPageSize.Width() * 100 / nWidthZoom + nRight );
+ m_xLeftMF->set_value( m_xLeftMF->normalize( nLeft ), eUnit );
+ }
+ else
+ {
+ nRight = aOrigSize.Width() -
+ ( aPageSize.Width() * 100 / nWidthZoom + nLeft );
+ m_xRightMF->set_value( m_xRightMF->normalize( nRight ), eUnit );
+ }
+ }
+ if (AllSettings::GetLayoutRTL())
+ {
+ m_aExampleWN.SetLeft(nRight);
+ m_aExampleWN.SetRight(nLeft);
+ }
+ else
+ {
+ m_aExampleWN.SetLeft(nLeft);
+ m_aExampleWN.SetRight(nRight);
+ }
+ if(bZoom)
+ {
+ // scale stays, recompute width
+ ZoomHdl(*m_xWidthZoomMF);
+ }
+ }
+ else
+ {
+ long nTop = lcl_GetValue( *m_xTopMF, eUnit );
+ long nBottom = lcl_GetValue( *m_xBottomMF, eUnit );
+ long nHeightZoom = static_cast<long>(m_xHeightZoomMF->get_value(FieldUnit::NONE));
+ if(bZoom && ( ( ( aOrigSize.Height() - (nTop + nBottom )) * nHeightZoom)
+ / 100 >= aPageSize.Height()))
+ {
+ assert(nHeightZoom && "div-by-zero");
+ if(&rField == m_xTopMF.get())
+ {
+ nTop = aOrigSize.Height() -
+ ( aPageSize.Height() * 100 / nHeightZoom + nBottom);
+ m_xTopMF->set_value( m_xWidthMF->normalize( nTop ), eUnit );
+ }
+ else
+ {
+ nBottom = aOrigSize.Height() -
+ ( aPageSize.Height() * 100 / nHeightZoom + nTop);
+ m_xBottomMF->set_value( m_xWidthMF->normalize( nBottom ), eUnit );
+ }
+ }
+ m_aExampleWN.SetTop( nTop );
+ m_aExampleWN.SetBottom( nBottom );
+ if(bZoom)
+ {
+ // scale stays, recompute height
+ ZoomHdl(*m_xHeightZoomMF);
+ }
+ }
+ m_aExampleWN.Invalidate();
+ // size and border changed -> recompute scale
+ if(!bZoom)
+ CalcZoom();
+ CalcMinMaxBorder();
+}
+/*--------------------------------------------------------------------
+ description: set original size
+ --------------------------------------------------------------------*/
+
+IMPL_LINK_NOARG(SvxGrfCropPage, OrigSizeHdl, weld::Button&, void)
+{
+ SfxItemPool* pPool = GetItemSet().GetPool();
+ DBG_ASSERT( pPool, "Where is the pool?" );
+ FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
+ SID_ATTR_GRAF_CROP ) ) );
+
+ long nWidth = aOrigSize.Width() -
+ lcl_GetValue( *m_xLeftMF, eUnit ) -
+ lcl_GetValue( *m_xRightMF, eUnit );
+ m_xWidthMF->set_value( m_xWidthMF->normalize( nWidth ), eUnit );
+ long nHeight = aOrigSize.Height() -
+ lcl_GetValue( *m_xTopMF, eUnit ) -
+ lcl_GetValue( *m_xBottomMF, eUnit );
+ m_xHeightMF->set_value( m_xHeightMF->normalize( nHeight ), eUnit );
+ m_xWidthZoomMF->set_value(100, FieldUnit::NONE);
+ m_xHeightZoomMF->set_value(100, FieldUnit::NONE);
+ bSetOrigSize = true;
+}
+/*--------------------------------------------------------------------
+ description: compute scale
+ --------------------------------------------------------------------*/
+
+void SvxGrfCropPage::CalcZoom()
+{
+ SfxItemPool* pPool = GetItemSet().GetPool();
+ DBG_ASSERT( pPool, "Where is the pool?" );
+ FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
+ SID_ATTR_GRAF_CROP ) ) );
+
+ long nWidth = lcl_GetValue( *m_xWidthMF, eUnit );
+ long nHeight = lcl_GetValue( *m_xHeightMF, eUnit );
+ long nLRBorders = lcl_GetValue( *m_xLeftMF, eUnit ) +
+ lcl_GetValue( *m_xRightMF, eUnit );
+ long nULBorders = lcl_GetValue( *m_xTopMF, eUnit ) +
+ lcl_GetValue( *m_xBottomMF, eUnit );
+ sal_uInt16 nZoom = 0;
+ long nDen;
+ if( (nDen = aOrigSize.Width() - nLRBorders) > 0)
+ nZoom = static_cast<sal_uInt16>((( nWidth * 1000 / nDen )+5)/10);
+ m_xWidthZoomMF->set_value(nZoom, FieldUnit::NONE);
+ if( (nDen = aOrigSize.Height() - nULBorders) > 0)
+ nZoom = static_cast<sal_uInt16>((( nHeight * 1000 / nDen )+5)/10);
+ else
+ nZoom = 0;
+ m_xHeightZoomMF->set_value(nZoom, FieldUnit::NONE);
+}
+
+/*--------------------------------------------------------------------
+ description: set minimum/maximum values for the margins
+ --------------------------------------------------------------------*/
+
+void SvxGrfCropPage::CalcMinMaxBorder()
+{
+ SfxItemPool* pPool = GetItemSet().GetPool();
+ DBG_ASSERT( pPool, "Where is the pool?" );
+ FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
+ SID_ATTR_GRAF_CROP ) ) );
+ long nR = lcl_GetValue(*m_xRightMF, eUnit );
+ long nMinWidth = (aOrigSize.Width() * 10) /11;
+ long nMin = nMinWidth - (nR >= 0 ? nR : 0);
+ m_xLeftMF->set_max( m_xLeftMF->normalize(nMin), eUnit );
+
+ long nL = lcl_GetValue(*m_xLeftMF, eUnit );
+ nMin = nMinWidth - (nL >= 0 ? nL : 0);
+ m_xRightMF->set_max( m_xRightMF->normalize(nMin), eUnit );
+
+ long nUp = lcl_GetValue( *m_xTopMF, eUnit );
+ long nMinHeight = (aOrigSize.Height() * 10) /11;
+ nMin = nMinHeight - (nUp >= 0 ? nUp : 0);
+ m_xBottomMF->set_max( m_xBottomMF->normalize(nMin), eUnit );
+
+ long nLow = lcl_GetValue(*m_xBottomMF, eUnit );
+ nMin = nMinHeight - (nLow >= 0 ? nLow : 0);
+ m_xTopMF->set_max( m_xTopMF->normalize(nMin), eUnit );
+}
+/*--------------------------------------------------------------------
+ description: set spinsize to 1/20 of the original size,
+ fill FixedText with the original size
+ --------------------------------------------------------------------*/
+
+void SvxGrfCropPage::GraphicHasChanged( bool bFound )
+{
+ if( bFound )
+ {
+ SfxItemPool* pPool = GetItemSet().GetPool();
+ DBG_ASSERT( pPool, "Where is the pool?" );
+ FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich(
+ SID_ATTR_GRAF_CROP ) ));
+
+ sal_Int64 nSpin = m_xLeftMF->normalize(aOrigSize.Width()) / 20;
+ nSpin = vcl::ConvertValue( nSpin, aOrigSize.Width(), 0,
+ eUnit, m_xLeftMF->get_unit());
+
+ // if the margin is too big, it is set to 1/3 on both pages
+ long nR = lcl_GetValue( *m_xRightMF, eUnit );
+ long nL = lcl_GetValue( *m_xLeftMF, eUnit );
+ if((nL + nR) < - aOrigSize.Width())
+ {
+ long nVal = aOrigSize.Width() / -3;
+ m_xRightMF->set_value( m_xRightMF->normalize( nVal ), eUnit );
+ m_xLeftMF->set_value( m_xLeftMF->normalize( nVal ), eUnit );
+ m_aExampleWN.SetLeft(nVal);
+ m_aExampleWN.SetRight(nVal);
+ }
+ long nUp = lcl_GetValue(*m_xTopMF, eUnit );
+ long nLow = lcl_GetValue(*m_xBottomMF, eUnit );
+ if((nUp + nLow) < - aOrigSize.Height())
+ {
+ long nVal = aOrigSize.Height() / -3;
+ m_xTopMF->set_value( m_xTopMF->normalize( nVal ), eUnit );
+ m_xBottomMF->set_value( m_xBottomMF->normalize( nVal ), eUnit );
+ m_aExampleWN.SetTop(nVal);
+ m_aExampleWN.SetBottom(nVal);
+ }
+
+ m_xLeftMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE);
+ m_xRightMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE);
+ nSpin = m_xTopMF->normalize(aOrigSize.Height()) / 20;
+ nSpin = vcl::ConvertValue( nSpin, aOrigSize.Width(), 0,
+ eUnit, m_xLeftMF->get_unit() );
+ m_xTopMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE);
+ m_xBottomMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE);
+
+ // display original size
+ const FieldUnit eMetric = GetModuleFieldUnit( GetItemSet() );
+
+ OUString sTemp;
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/spinbox.ui"));
+ std::unique_ptr<weld::MetricSpinButton> xFld(xBuilder->weld_metric_spin_button("spin", FieldUnit::CM));
+ SetFieldUnit( *xFld, eMetric );
+ xFld->set_digits(m_xWidthMF->get_digits());
+ xFld->set_max(INT_MAX - 1, FieldUnit::NONE);
+
+ xFld->set_value(xFld->normalize(aOrigSize.Width()), eUnit);
+ sTemp = xFld->get_text();
+ xFld->set_value(xFld->normalize(aOrigSize.Height()), eUnit);
+ // multiplication sign (U+00D7)
+ sTemp += u"\u00D7" + xFld->get_text();
+ }
+
+ if ( aOrigPixelSize.Width() && aOrigPixelSize.Height() ) {
+ sal_Int32 ax = sal_Int32(floor(static_cast<float>(aOrigPixelSize.Width()) /
+ (static_cast<float>(aOrigSize.Width())/TWIP_TO_INCH)+0.5));
+ sal_Int32 ay = sal_Int32(floor(static_cast<float>(aOrigPixelSize.Height()) /
+ (static_cast<float>(aOrigSize.Height())/TWIP_TO_INCH)+0.5));
+ sTemp += " " + CuiResId( RID_SVXSTR_PPI );
+ OUString sPPI = OUString::number(ax);
+ if (abs(ax - ay) > 1) {
+ sPPI += u"\u00D7" + OUString::number(ay);
+ }
+ sTemp = sTemp.replaceAll("%1", sPPI);
+ }
+ m_xOrigSizeFT->set_label(sTemp);
+ }
+
+ m_xCropFrame->set_sensitive(bFound);
+ m_xScaleFrame->set_sensitive(bFound);
+ m_xSizeFrame->set_sensitive(bFound);
+ m_xOrigSizeGrid->set_sensitive(bFound);
+ m_xZoomConstRB->set_sensitive(bFound);
+}
+
+Size SvxGrfCropPage::GetGrfOrigSize(const Graphic& rGrf)
+{
+ const MapMode aMapTwip( MapUnit::MapTwip );
+ Size aSize( rGrf.GetPrefSize() );
+ if( MapUnit::MapPixel == rGrf.GetPrefMapMode().GetMapUnit() )
+ aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMapTwip);
+ else
+ aSize = OutputDevice::LogicToLogic( aSize,
+ rGrf.GetPrefMapMode(), aMapTwip );
+ return aSize;
+}
+
+/*****************************************************************/
+
+SvxCropExample::SvxCropExample()
+ : m_aTopLeft(0, 0)
+ , m_aBottomRight(0, 0)
+{
+}
+
+void SvxCropExample::SetDrawingArea(weld::DrawingArea* pDrawingArea)
+{
+ CustomWidgetController::SetDrawingArea(pDrawingArea);
+ OutputDevice& rDevice = pDrawingArea->get_ref_device();
+ Size aSize(rDevice.LogicToPixel(Size(78, 78), MapMode(MapUnit::MapAppFont)));
+ pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
+
+ m_aMapMode = rDevice.GetMapMode();
+ m_aFrameSize = OutputDevice::LogicToLogic(
+ Size(CM_1_TO_TWIP / 2, CM_1_TO_TWIP / 2),
+ MapMode(MapUnit::MapTwip), m_aMapMode);
+}
+
+void SvxCropExample::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&)
+{
+ rRenderContext.Push(PushFlags::MAPMODE);
+ rRenderContext.SetMapMode(m_aMapMode);
+
+ // Win BG
+ const Size aWinSize(rRenderContext.PixelToLogic(GetOutputSizePixel()));
+ rRenderContext.SetLineColor();
+ rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetWindowColor());
+ rRenderContext.DrawRect(::tools::Rectangle(Point(), aWinSize));
+
+ // use AA, the Graphic may be a metafile/svg and would then look ugly
+ rRenderContext.SetAntialiasing(AntialiasingFlags::EnableB2dDraw);
+
+ // draw Graphic
+ ::tools::Rectangle aRect(
+ Point((aWinSize.Width() - m_aFrameSize.Width())/2, (aWinSize.Height() - m_aFrameSize.Height())/2),
+ m_aFrameSize);
+ m_aGrf.Draw(&rRenderContext, aRect.TopLeft(), aRect.GetSize());
+
+ // Remove one more case that uses XOR paint (RasterOp::Invert).
+ // Get colors and logic DashLength from settings, use equal to
+ // PolygonMarkerPrimitive2D, may be changed to that primitive later.
+ // Use this to guarantee good visibility - that was the purpose of
+ // the former used XOR paint.
+ const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
+ const Color aColA(aSvtOptionsDrawinglayer.GetStripeColorA().getBColor());
+ const Color aColB(aSvtOptionsDrawinglayer.GetStripeColorB().getBColor());
+ const double fStripeLength(aSvtOptionsDrawinglayer.GetStripeLength());
+ const basegfx::B2DVector aDashVector(rRenderContext.GetInverseViewTransformation() * basegfx::B2DVector(fStripeLength, 0.0));
+ const double fLogicDashLength(aDashVector.getX());
+
+ // apply current crop settings
+ aRect.AdjustLeft(m_aTopLeft.Y());
+ aRect.AdjustTop(m_aTopLeft.X());
+ aRect.AdjustRight(-m_aBottomRight.Y());
+ aRect.AdjustBottom(-m_aBottomRight.X());
+
+ // apply dash with direct paint callbacks
+ basegfx::utils::applyLineDashing(
+ basegfx::utils::createPolygonFromRect(
+ basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom())),
+ std::vector< double >(2, fLogicDashLength),
+ [&aColA,&rRenderContext](const basegfx::B2DPolygon& rSnippet)
+ {
+ rRenderContext.SetLineColor(aColA);
+ rRenderContext.DrawPolyLine(rSnippet);
+ },
+ [&aColB,&rRenderContext](const basegfx::B2DPolygon& rSnippet)
+ {
+ rRenderContext.SetLineColor(aColB);
+ rRenderContext.DrawPolyLine(rSnippet);
+ },
+ 2.0 * fLogicDashLength);
+
+ rRenderContext.Pop();
+}
+
+void SvxCropExample::Resize()
+{
+ SetFrameSize(m_aFrameSize);
+}
+
+void SvxCropExample::SetFrameSize( const Size& rSz )
+{
+ m_aFrameSize = rSz;
+ if (!m_aFrameSize.Width())
+ m_aFrameSize.setWidth( 1 );
+ if (!m_aFrameSize.Height())
+ m_aFrameSize.setHeight( 1 );
+ Size aWinSize( GetOutputSizePixel() );
+ Fraction aXScale( aWinSize.Width() * 4, m_aFrameSize.Width() * 5 );
+ Fraction aYScale( aWinSize.Height() * 4, m_aFrameSize.Height() * 5 );
+
+ if( aYScale < aXScale )
+ aXScale = aYScale;
+
+ m_aMapMode.SetScaleX(aXScale);
+ m_aMapMode.SetScaleY(aXScale);
+
+ Invalidate();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */