/* -*- 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 #include "mmlayoutpage.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace osl; using namespace svt; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::text; using namespace ::com::sun::star::frame; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::view; #define DEFAULT_LEFT_DISTANCE (MM50*5) // 2,5 cm #define DEFAULT_TOP_DISTANCE (MM50*11) // 5,5 cm #define GREETING_TOP_DISTANCE (MM50*25) //12,5 cm #define DEFAULT_ADDRESS_WIDTH (MM50*15)// 7,5 cm #define DEFAULT_ADDRESS_HEIGHT (MM50*7) // 3,5cm SwMailMergeLayoutPage::SwMailMergeLayoutPage(weld::Container* pPage, SwMailMergeWizard* pWizard) : vcl::OWizardPage(pPage, pWizard, "modules/swriter/ui/mmlayoutpage.ui", "MMLayoutPage") , m_pExampleWrtShell(nullptr) , m_pAddressBlockFormat(nullptr) , m_bIsGreetingInserted(false) , m_pWizard(pWizard) , m_xPosition(m_xBuilder->weld_container("addresspos")) , m_xAlignToBodyCB(m_xBuilder->weld_check_button("align")) , m_xLeftFT(m_xBuilder->weld_label("leftft")) , m_xLeftMF(m_xBuilder->weld_metric_spin_button("left", FieldUnit::CM)) , m_xTopMF(m_xBuilder->weld_metric_spin_button("top", FieldUnit::CM)) , m_xGreetingLine(m_xBuilder->weld_container("greetingspos")) , m_xUpPB(m_xBuilder->weld_button("up")) , m_xDownPB(m_xBuilder->weld_button("down")) , m_xZoomLB(m_xBuilder->weld_combo_box("zoom")) { std::shared_ptr pSfxFlt = SwDocShell::Factory().GetFilterContainer()-> GetFilter4FilterName("writer8", SfxFilterFlags::EXPORT); //save the current document into a temporary file { //temp file needs its own block //creating with extension is not supported by a static method :-( OUString const sExt( comphelper::string::stripStart(pSfxFlt->GetDefaultExtension(),'*')); utl::TempFile aTempFile( OUString(), true, &sExt ); m_sExampleURL = aTempFile.GetURL(); aTempFile.EnableKillingFile(); } SwView* pView = m_pWizard->GetSwView(); uno::Sequence< beans::PropertyValue > aValues(2); beans::PropertyValue* pValues = aValues.getArray(); pValues[0].Name = "FilterName"; pValues[0].Value <<= pSfxFlt->GetFilterName(); // Don't save embedded data set! It would steal it from current document. pValues[1].Name = "NoEmbDataSet"; pValues[1].Value <<= true; uno::Reference< frame::XStorable > xStore( pView->GetDocShell()->GetModel(), uno::UNO_QUERY); xStore->storeToURL( m_sExampleURL, aValues ); Link aLink(LINK(this, SwMailMergeLayoutPage, PreviewLoadedHdl_Impl)); m_xExampleFrame.reset(new SwOneExampleFrame(EX_SHOW_DEFAULT_PAGE, &aLink, &m_sExampleURL)); m_xExampleContainerWIN.reset(new weld::CustomWeld(*m_xBuilder, "example", *m_xExampleFrame)); Size aSize = m_xExampleFrame->GetDrawingArea()->get_ref_device().LogicToPixel( Size(124, 159), MapMode(MapUnit::MapAppFont)); m_xExampleFrame->set_size_request(aSize.Width(), aSize.Height()); m_xExampleContainerWIN->hide(); m_xLeftMF->set_value(m_xLeftMF->normalize(DEFAULT_LEFT_DISTANCE), FieldUnit::TWIP); m_xTopMF->set_value(m_xTopMF->normalize(DEFAULT_TOP_DISTANCE), FieldUnit::TWIP); const LanguageTag& rLang = Application::GetSettings().GetUILanguageTag(); m_xZoomLB->append_text(unicode::formatPercent(50, rLang)); m_xZoomLB->append_text(unicode::formatPercent(75, rLang)); m_xZoomLB->append_text(unicode::formatPercent(100, rLang)); m_xZoomLB->set_active(0); //page size m_xZoomLB->connect_changed(LINK(this, SwMailMergeLayoutPage, ZoomHdl_Impl)); Link aFrameHdl = LINK(this, SwMailMergeLayoutPage, ChangeAddressHdl_Impl); m_xLeftMF->connect_value_changed(aFrameHdl); m_xTopMF->connect_value_changed(aFrameHdl); FieldUnit eFieldUnit = ::GetDfltMetric(false); ::SetFieldUnit( *m_xLeftMF, eFieldUnit ); ::SetFieldUnit( *m_xTopMF, eFieldUnit ); Link aUpDownHdl = LINK(this, SwMailMergeLayoutPage, GreetingsHdl_Impl ); m_xUpPB->connect_clicked(aUpDownHdl); m_xDownPB->connect_clicked(aUpDownHdl); m_xAlignToBodyCB->connect_toggled(LINK(this, SwMailMergeLayoutPage, AlignToTextHdl_Impl)); m_xAlignToBodyCB->set_active(true); } SwMailMergeLayoutPage::~SwMailMergeLayoutPage() { File::remove( m_sExampleURL ); } void SwMailMergeLayoutPage::Activate() { SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem(); bool bGreetingLine = rConfigItem.IsGreetingLine(false) && !rConfigItem.IsGreetingInserted(); bool bAddressBlock = rConfigItem.IsAddressBlock() && !rConfigItem.IsAddressInserted(); m_xPosition->set_sensitive(bAddressBlock); AlignToTextHdl_Impl(*m_xAlignToBodyCB); m_xGreetingLine->set_sensitive(bGreetingLine); //check if greeting and/or address frame have to be inserted/removed if(m_pExampleWrtShell) // initially there's nothing to check { if(!rConfigItem.IsGreetingInserted() && m_bIsGreetingInserted != bGreetingLine ) { if( m_bIsGreetingInserted ) { m_pExampleWrtShell->DelFullPara(); m_bIsGreetingInserted = false; } else { InsertGreeting(*m_pExampleWrtShell, m_pWizard->GetConfigItem(), true); m_bIsGreetingInserted = true; } } if(!rConfigItem.IsAddressInserted() && rConfigItem.IsAddressBlock() != ( nullptr != m_pAddressBlockFormat )) { if( m_pAddressBlockFormat ) { m_pExampleWrtShell->Push(); m_pExampleWrtShell->GotoFly( m_pAddressBlockFormat->GetName() ); m_pExampleWrtShell->DelRight(); m_pAddressBlockFormat = nullptr; m_pExampleWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent); } else { long nLeft = static_cast< long >(m_xLeftMF->denormalize(m_xLeftMF->get_value(FieldUnit::TWIP))); long nTop = static_cast< long >(m_xTopMF->denormalize(m_xTopMF->get_value(FieldUnit::TWIP))); m_pAddressBlockFormat = InsertAddressFrame( *m_pExampleWrtShell, m_pWizard->GetConfigItem(), Point(nLeft, nTop), m_xAlignToBodyCB->get_active(), true); } } m_xExampleFrame->Invalidate(); } } bool SwMailMergeLayoutPage::commitPage(::vcl::WizardTypes::CommitPageReason eReason) { //now insert the frame and the greeting SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem(); if (eReason == ::vcl::WizardTypes::eTravelForward || eReason == ::vcl::WizardTypes::eFinish) { long nLeft = static_cast< long >(m_xLeftMF->denormalize(m_xLeftMF->get_value(FieldUnit::TWIP))); long nTop = static_cast< long >(m_xTopMF->denormalize(m_xTopMF->get_value(FieldUnit::TWIP))); InsertAddressAndGreeting( m_pWizard->GetSwView(), rConfigItem, Point(nLeft, nTop), m_xAlignToBodyCB->get_active()); } return true; } SwFrameFormat* SwMailMergeLayoutPage::InsertAddressAndGreeting(SwView const * pView, SwMailMergeConfigItem& rConfigItem, const Point& rAddressPosition, bool bAlignToBody) { SwFrameFormat* pAddressBlockFormat = nullptr; pView->GetWrtShell().StartUndo(SwUndoId::INSERT); if(rConfigItem.IsAddressBlock() && !rConfigItem.IsAddressInserted()) { //insert the frame Point aAddressPosition(DEFAULT_LEFT_DISTANCE, DEFAULT_TOP_DISTANCE); if(rAddressPosition.X() > 0 && rAddressPosition.Y() > 0) aAddressPosition = rAddressPosition; pAddressBlockFormat = InsertAddressFrame( pView->GetWrtShell(), rConfigItem, aAddressPosition, bAlignToBody, false); rConfigItem.SetAddressInserted(); } //now the greeting if(rConfigItem.IsGreetingLine(false) && !rConfigItem.IsGreetingInserted()) { InsertGreeting( pView->GetWrtShell(), rConfigItem, false); rConfigItem.SetGreetingInserted(); } pView->GetWrtShell().EndUndo(SwUndoId::INSERT); return pAddressBlockFormat; } SwFrameFormat* SwMailMergeLayoutPage::InsertAddressFrame( SwWrtShell& rShell, SwMailMergeConfigItem const & rConfigItem, const Point& rDestination, bool bAlignLeft, bool bExample) { // insert the address block and the greeting line SfxItemSet aSet( rShell.GetAttrPool(), svl::Items< RES_FRM_SIZE, RES_FRM_SIZE, RES_SURROUND, RES_ANCHOR, RES_BOX, RES_BOX>{} ); aSet.Put(SwFormatAnchor(RndStdIds::FLY_AT_PAGE, 1)); if(bAlignLeft) aSet.Put(SwFormatHoriOrient( 0, text::HoriOrientation::NONE, text::RelOrientation::PAGE_PRINT_AREA )); else aSet.Put(SwFormatHoriOrient( rDestination.X(), text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME )); aSet.Put(SwFormatVertOrient( rDestination.Y(), text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME )); aSet.Put(SwFormatFrameSize( SwFrameSize::Minimum, DEFAULT_ADDRESS_WIDTH, DEFAULT_ADDRESS_HEIGHT )); // the example gets a border around the frame, the real document doesn't get one if(!bExample) aSet.Put(SvxBoxItem( RES_BOX )); aSet.Put(SwFormatSurround( css::text::WrapTextMode_NONE )); rShell.NewFlyFrame(aSet, true ); SwFrameFormat* pRet = rShell.GetFlyFrameFormat(); OSL_ENSURE( pRet, "Fly not inserted" ); rShell.UnSelectFrame(); const Sequence< OUString> aBlocks = rConfigItem.GetAddressBlocks(); if(bExample) { rShell.Insert(aBlocks[0]); } else { //the placeholders should be replaced by the appropriate fields SwFieldMgr aFieldMgr(&rShell); //create a database string source.command.commandtype.column const SwDBData& rData = rConfigItem.GetCurrentDBData(); OUString sDBName(rData.sDataSource + OUStringChar(DB_DELIM) + rData.sCommand + OUStringChar(DB_DELIM)); const OUString sDatabaseConditionPrefix(sDBName.replace(DB_DELIM, '.')); sDBName += OUString::number(rData.nCommandType) + OUStringChar(DB_DELIM); // if only the country is in an address line the // paragraph has to be hidden depending on the // IsIncludeCountry()/GetExcludeCountry() settings bool bIncludeCountry = rConfigItem.IsIncludeCountry(); bool bHideEmptyParagraphs = rConfigItem.IsHideEmptyParagraphs(); const OUString rExcludeCountry = rConfigItem.GetExcludeCountry(); bool bSpecialReplacementForCountry = (!bIncludeCountry || !rExcludeCountry.isEmpty()); const std::vector>& rHeaders = rConfigItem.GetDefaultAddressHeaders(); Sequence< OUString> aAssignment = rConfigItem.GetColumnAssignment( rConfigItem.GetCurrentDBData() ); const OUString* pAssignment = aAssignment.getConstArray(); const OUString sCountryColumn( (aAssignment.getLength() > MM_PART_COUNTRY && !aAssignment[MM_PART_COUNTRY].isEmpty()) ? aAssignment[MM_PART_COUNTRY] : rHeaders[MM_PART_COUNTRY].first); OUString sHideParagraphsExpression; SwAddressIterator aIter(aBlocks[0]); while(aIter.HasMore()) { SwMergeAddressItem aItem = aIter.Next(); if(aItem.bIsColumn) { OUString sConvertedColumn = aItem.sText; auto nSize = std::min(static_cast(rHeaders.size()), static_cast(aAssignment.getLength())); for(sal_uInt32 nColumn = 0; nColumn < nSize; ++nColumn) { if (rHeaders[nColumn].first == aItem.sText && !pAssignment[nColumn].isEmpty()) { sConvertedColumn = pAssignment[nColumn]; break; } } const OUString sDB(sDBName + sConvertedColumn); if(!sHideParagraphsExpression.isEmpty()) sHideParagraphsExpression += " AND "; sHideParagraphsExpression += "![" + sDatabaseConditionPrefix + sConvertedColumn + "]"; if( bSpecialReplacementForCountry && sCountryColumn == sConvertedColumn ) { // now insert a hidden paragraph field if( !rExcludeCountry.isEmpty() ) { const OUString sExpression("[" + sDatabaseConditionPrefix + sCountryColumn + "]"); SwInsertField_Data aData(SwFieldTypesEnum::ConditionalText, 0, sExpression + " != \"" + rExcludeCountry + "\"", sExpression, 0, &rShell ); aFieldMgr.InsertField( aData ); } else { SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, "", "", 0, &rShell ); aFieldMgr.InsertField( aData ); } } else { SwInsertField_Data aData(SwFieldTypesEnum::Database, 0, sDB, OUString(), 0, &rShell); aFieldMgr.InsertField( aData ); } } else if(!aItem.bIsReturn) { rShell.Insert(aItem.sText); } else { if(bHideEmptyParagraphs) { SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sHideParagraphsExpression, OUString(), 0, &rShell); aFieldMgr.InsertField( aData ); } sHideParagraphsExpression.clear(); //now add a new paragraph rShell.SplitNode(); } } if(bHideEmptyParagraphs && !sHideParagraphsExpression.isEmpty()) { SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sHideParagraphsExpression, OUString(), 0, &rShell); aFieldMgr.InsertField( aData ); } } return pRet; } void SwMailMergeLayoutPage::InsertGreeting(SwWrtShell& rShell, SwMailMergeConfigItem const & rConfigItem, bool bExample) { //set the cursor to the desired position - if no text content is here then //new paragraphs are inserted const SwRect& rPageRect = rShell.GetAnyCurRect(CurRectType::Page); const Point aGreetingPos( DEFAULT_LEFT_DISTANCE + rPageRect.Left(), GREETING_TOP_DISTANCE ); const bool bRet = rShell.SetShadowCursorPos( aGreetingPos, SwFillMode::TabSpace ); if(!bRet) { //there's already text at the desired position //go to start of the doc, directly! rShell.SttEndDoc(true); //and go by paragraph until the position is reached long nYPos = rShell.GetCharRect().Top(); while(nYPos < GREETING_TOP_DISTANCE) { if(!rShell.FwdPara()) break; nYPos = rShell.GetCharRect().Top(); } //text needs to be appended while(nYPos < GREETING_TOP_DISTANCE) { if(!rShell.AppendTextNode()) break; nYPos = rShell.GetCharRect().Top(); } } else { //we may end up inside of a paragraph if the left margin is not at DEFAULT_LEFT_DISTANCE rShell.MovePara(GoCurrPara, fnParaStart); } bool bSplitNode = !rShell.IsEndPara(); sal_Int32 nMoves = rConfigItem.GetGreetingMoves(); if( !bExample && 0 != nMoves ) { if(nMoves < 0) { rShell.MoveParagraph( nMoves ); } else while(nMoves) { bool bMoved = rShell.MoveParagraph(); if(!bMoved) { //insert a new paragraph before the greeting line rShell.SplitNode(); } --nMoves; } } //now insert the greeting text - if we have any? const bool bIndividual = rConfigItem.IsIndividualGreeting(false); if(bIndividual) { //lock expression fields - prevents hiding of the paragraph to insert into rShell.LockExpFields(); if(bExample) { for(sal_Int8 eGender = SwMailMergeConfigItem::FEMALE; eGender <= SwMailMergeConfigItem::NEUTRAL; ++eGender) { Sequence< OUString > aEntries = rConfigItem.GetGreetings(static_cast(eGender)); sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(static_cast(eGender)); if( nCurrent >= 0 && nCurrent < aEntries.getLength()) { // Greeting rShell.Insert(aEntries[nCurrent]); break; } } } else { SwFieldMgr aFieldMgr(&rShell); //three paragraphs, each with an appropriate hidden paragraph field //are to be inserted //name of the gender column const OUString sGenderColumn = rConfigItem.GetAssignedColumn(MM_PART_GENDER); const OUString sNameColumn = rConfigItem.GetAssignedColumn(MM_PART_LASTNAME); const OUString& rFemaleGenderValue = rConfigItem.GetFemaleGenderValue(); bool bHideEmptyParagraphs = rConfigItem.IsHideEmptyParagraphs(); const SwDBData& rData = rConfigItem.GetCurrentDBData(); const OUString sCommonBase(rData.sDataSource + "." + rData.sCommand + "."); const OUString sConditionBase("[" + sCommonBase + sGenderColumn + "]"); const OUString sNameColumnBase("[" + sCommonBase + sNameColumn + "]"); const OUString sDBName(rData.sDataSource + OUStringChar(DB_DELIM) + rData.sCommand + OUStringChar(DB_DELIM) + OUString::number(rData.nCommandType) + OUStringChar(DB_DELIM)); // Female: [database.sGenderColumn] != "rFemaleGenderValue" && [database.NameColumn] // Male: [database.sGenderColumn] == "rFemaleGenderValue" && [database.rGenderColumn] // Neutral: [database.sNameColumn] OSL_ENSURE(!sGenderColumn.isEmpty() && !rFemaleGenderValue.isEmpty(), "gender settings not available - how to form the condition?"); //column used as lastname for(sal_Int8 eGender = SwMailMergeConfigItem::FEMALE; eGender <= SwMailMergeConfigItem::NEUTRAL; ++eGender) { Sequence< OUString> aEntries = rConfigItem.GetGreetings(static_cast(eGender)); sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(static_cast(eGender)); if( nCurrent >= 0 && nCurrent < aEntries.getLength()) { const OUString sGreeting = aEntries[nCurrent]; OUString sCondition; OUString sHideParagraphsExpression; switch(eGender) { case SwMailMergeConfigItem::FEMALE: sCondition = sConditionBase + " != \"" + rFemaleGenderValue + "\" OR NOT " + sNameColumnBase; sHideParagraphsExpression = "!" + sNameColumnBase; break; case SwMailMergeConfigItem::MALE: sCondition = sConditionBase + " == \"" + rFemaleGenderValue + "\" OR NOT " + sNameColumnBase; break; case SwMailMergeConfigItem::NEUTRAL: sCondition = sNameColumnBase; break; } if(bHideEmptyParagraphs && !sHideParagraphsExpression.isEmpty()) { OUString sComplete = "(" + sCondition + ") OR (" + sHideParagraphsExpression + ")"; SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sComplete, OUString(), 0, &rShell); aFieldMgr.InsertField( aData ); } else { SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sCondition, OUString(), 0, &rShell); aFieldMgr.InsertField( aData ); } //now the text has to be inserted const std::vector>& rHeaders = rConfigItem.GetDefaultAddressHeaders(); Sequence< OUString> aAssignment = rConfigItem.GetColumnAssignment( rConfigItem.GetCurrentDBData() ); const OUString* pAssignment = aAssignment.getConstArray(); SwAddressIterator aIter(sGreeting); while(aIter.HasMore()) { SwMergeAddressItem aItem = aIter.Next(); if(aItem.bIsColumn) { OUString sConvertedColumn = aItem.sText; auto nSize = std::min(static_cast(rHeaders.size()), static_cast(aAssignment.getLength())); for(sal_uInt32 nColumn = 0; nColumn < nSize; ++nColumn) { if (rHeaders[nColumn].first == aItem.sText && !pAssignment[nColumn].isEmpty()) { sConvertedColumn = pAssignment[nColumn]; break; } } SwInsertField_Data aData(SwFieldTypesEnum::Database, 0, sDBName + sConvertedColumn, OUString(), 0, &rShell); aFieldMgr.InsertField( aData ); } else { rShell.Insert(aItem.sText); } } //now add a new paragraph rShell.SplitNode(); } } } rShell.UnlockExpFields(); } else { Sequence< OUString> aEntries = rConfigItem.GetGreetings(SwMailMergeConfigItem::NEUTRAL); sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(SwMailMergeConfigItem::NEUTRAL); // Greeting rShell.Insert(( nCurrent >= 0 && nCurrent < aEntries.getLength() ) ? aEntries[nCurrent] : OUString()); } // now insert a new paragraph here if necessary if(bSplitNode) { rShell.Push(); rShell.SplitNode(); rShell.Pop(SwCursorShell::PopMode::DeleteCurrent); } //put the cursor to the start of the paragraph rShell.SttPara(); OSL_ENSURE(nullptr == rShell.GetTableFormat(), "What to do with a table here?"); } IMPL_LINK_NOARG(SwMailMergeLayoutPage, PreviewLoadedHdl_Impl, SwOneExampleFrame&, void) { m_xExampleContainerWIN->show(); Reference< XModel > & xModel = m_xExampleFrame->GetModel(); //now the ViewOptions should be set properly Reference< XViewSettingsSupplier > xSettings(xModel->getCurrentController(), UNO_QUERY); m_xViewProperties = xSettings->getViewSettings(); auto pXDoc = comphelper::getUnoTunnelImplementation(xModel); SwDocShell* pDocShell = pXDoc->GetDocShell(); m_pExampleWrtShell = pDocShell->GetWrtShell(); OSL_ENSURE(m_pExampleWrtShell, "No SwWrtShell found!"); if(!m_pExampleWrtShell) return; SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem(); if(rConfigItem.IsAddressBlock()) { m_pAddressBlockFormat = InsertAddressFrame( *m_pExampleWrtShell, rConfigItem, Point(DEFAULT_LEFT_DISTANCE, DEFAULT_TOP_DISTANCE), m_xAlignToBodyCB->get_active(), true); } if(rConfigItem.IsGreetingLine(false)) { InsertGreeting(*m_pExampleWrtShell, rConfigItem, true); m_bIsGreetingInserted = true; } ZoomHdl_Impl(*m_xZoomLB); const SwFormatFrameSize& rPageSize = m_pExampleWrtShell->GetPageDesc( m_pExampleWrtShell->GetCurPageDesc()).GetMaster().GetFrameSize(); m_xLeftMF->set_max(rPageSize.GetWidth() - DEFAULT_LEFT_DISTANCE, FieldUnit::NONE); m_xTopMF->set_max(rPageSize.GetHeight() - DEFAULT_TOP_DISTANCE, FieldUnit::NONE); } IMPL_LINK(SwMailMergeLayoutPage, ZoomHdl_Impl, weld::ComboBox&, rBox, void) { if (m_pExampleWrtShell) { sal_Int16 eType = DocumentZoomType::BY_VALUE; short nZoom = 50; switch (rBox.get_active()) { case 0 : eType = DocumentZoomType::ENTIRE_PAGE; break; case 1 : nZoom = 50; break; case 2 : nZoom = 75; break; case 3 : nZoom = 100; break; } Any aZoom; aZoom <<= eType; m_xViewProperties->setPropertyValue(UNO_NAME_ZOOM_TYPE, aZoom); aZoom <<= nZoom; m_xViewProperties->setPropertyValue(UNO_NAME_ZOOM_VALUE, aZoom); m_xExampleFrame->Invalidate(); } } IMPL_LINK_NOARG(SwMailMergeLayoutPage, ChangeAddressHdl_Impl, weld::MetricSpinButton&, void) { if(m_pExampleWrtShell && m_pAddressBlockFormat) { long nLeft = static_cast< long >(m_xLeftMF->denormalize(m_xLeftMF->get_value(FieldUnit::TWIP))); long nTop = static_cast< long >(m_xTopMF->denormalize(m_xTopMF->get_value(FieldUnit::TWIP))); SfxItemSet aSet( m_pExampleWrtShell->GetAttrPool(), svl::Items{}); if (m_xAlignToBodyCB->get_active()) aSet.Put(SwFormatHoriOrient( 0, text::HoriOrientation::NONE, text::RelOrientation::PAGE_PRINT_AREA )); else aSet.Put(SwFormatHoriOrient( nLeft, text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME )); aSet.Put(SwFormatVertOrient( nTop, text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME )); m_pExampleWrtShell->GetDoc()->SetFlyFrameAttr( *m_pAddressBlockFormat, aSet ); m_xExampleFrame->Invalidate(); } } IMPL_LINK(SwMailMergeLayoutPage, GreetingsHdl_Impl, weld::Button&, rButton, void) { bool bDown = &rButton == m_xDownPB.get(); bool bMoved = m_pExampleWrtShell->MoveParagraph( bDown ? 1 : -1 ); if (bMoved || bDown) m_pWizard->GetConfigItem().MoveGreeting(bDown ? 1 : -1 ); if(!bMoved && bDown) { //insert a new paragraph before the greeting line m_pExampleWrtShell->SplitNode(); } m_xExampleFrame->Invalidate(); } IMPL_LINK(SwMailMergeLayoutPage, AlignToTextHdl_Impl, weld::ToggleButton&, rBox, void) { bool bCheck = rBox.get_active() && rBox.get_sensitive(); m_xLeftFT->set_sensitive(!bCheck); m_xLeftMF->set_sensitive(!bCheck); ChangeAddressHdl_Impl( *m_xLeftMF ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */