diff options
Diffstat (limited to '')
-rw-r--r-- | basctl/source/dlged/dlged.cxx | 1242 | ||||
-rw-r--r-- | basctl/source/dlged/dlgedclip.cxx | 109 | ||||
-rw-r--r-- | basctl/source/dlged/dlgedfac.cxx | 232 | ||||
-rw-r--r-- | basctl/source/dlged/dlgedfunc.cxx | 548 | ||||
-rw-r--r-- | basctl/source/dlged/dlgedlist.cxx | 80 | ||||
-rw-r--r-- | basctl/source/dlged/dlgedmod.cxx | 36 | ||||
-rw-r--r-- | basctl/source/dlged/dlgedobj.cxx | 1703 | ||||
-rw-r--r-- | basctl/source/dlged/dlgedpage.cxx | 66 | ||||
-rw-r--r-- | basctl/source/dlged/dlgedview.cxx | 184 | ||||
-rw-r--r-- | basctl/source/dlged/managelang.cxx | 318 | ||||
-rw-r--r-- | basctl/source/dlged/propbrw.cxx | 506 |
11 files changed, 5024 insertions, 0 deletions
diff --git a/basctl/source/dlged/dlged.cxx b/basctl/source/dlged/dlged.cxx new file mode 100644 index 000000000..81fa3f14e --- /dev/null +++ b/basctl/source/dlged/dlged.cxx @@ -0,0 +1,1242 @@ +/* -*- 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 <dlged.hxx> +#include <dlgedclip.hxx> +#include <dlgeddef.hxx> +#include <dlgedfac.hxx> +#include <dlgedfunc.hxx> +#include <dlgedmod.hxx> +#include <dlgedobj.hxx> +#include <dlgedpage.hxx> +#include <dlgedview.hxx> +#include <localizationmgr.hxx> +#include <baside3.hxx> + +#include <com/sun/star/awt/Toolkit.hpp> +#include <com/sun/star/awt/UnoControlDialog.hpp> +#include <com/sun/star/resource/StringResource.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/util/NumberFormatsSupplier.hpp> +#include <comphelper/types.hxx> +#include <comphelper/processfactory.hxx> +#include <tools/debug.hxx> +#include <svl/itempool.hxx> +#include <svx/sdrpaintwindow.hxx> +#include <svx/svdpagv.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/print.hxx> +#include <vcl/scrbar.hxx> +#include <vcl/svapp.hxx> +#include <xmlscript/xml_helper.hxx> +#include <xmlscript/xmldlg_imexp.hxx> +#include <osl/diagnose.h> + +namespace basctl +{ + +using namespace comphelper; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::io; + +constexpr OUStringLiteral aResourceResolverPropName = u"ResourceResolver"; +constexpr OUStringLiteral aDecorationPropName = u"Decoration"; + + +// DlgEdHint + + +DlgEdHint::DlgEdHint(Kind eHint) + : eKind(eHint) + , pDlgEdObj(nullptr) +{ +} + +DlgEdHint::DlgEdHint(Kind eHint, DlgEdObj* pObj) + : eKind(eHint) + , pDlgEdObj(pObj) +{ +} + +DlgEdHint::~DlgEdHint() +{ +} + + +// DlgEditor + + +void DlgEditor::ShowDialog() +{ + uno::Reference< uno::XComponentContext > xContext = getProcessComponentContext(); + + // create a dialog + uno::Reference< awt::XUnoControlDialog > xDlg = awt::UnoControlDialog::create( xContext ); + + // clone the dialog model + uno::Reference< util::XCloneable > xC( m_xUnoControlDialogModel, uno::UNO_QUERY ); + uno::Reference< util::XCloneable > xNew = xC->createClone(); + uno::Reference< awt::XControlModel > xDlgMod( xNew, uno::UNO_QUERY ); + + uno::Reference< beans::XPropertySet > xSrcDlgModPropSet( m_xUnoControlDialogModel, uno::UNO_QUERY ); + uno::Reference< beans::XPropertySet > xNewDlgModPropSet( xDlgMod, uno::UNO_QUERY ); + if( xNewDlgModPropSet.is() ) + { + if( xSrcDlgModPropSet.is() ) + { + try + { + Any aResourceResolver = xSrcDlgModPropSet->getPropertyValue( aResourceResolverPropName ); + xNewDlgModPropSet->setPropertyValue( aResourceResolverPropName, aResourceResolver ); + } + catch(const UnknownPropertyException& ) + { + OSL_FAIL( "DlgEditor::ShowDialog(): No ResourceResolver property" ); + } + } + + // Disable decoration + try + { + bool bDecoration = true; + + Any aDecorationAny = xSrcDlgModPropSet->getPropertyValue( aDecorationPropName ); + aDecorationAny >>= bDecoration; + if( !bDecoration ) + { + xNewDlgModPropSet->setPropertyValue( aDecorationPropName, Any( true ) ); + xNewDlgModPropSet->setPropertyValue( "Title", Any( OUString() ) ); + } + } + catch(const UnknownPropertyException& ) + {} + } + + // set the model + xDlg->setModel( xDlgMod ); + + // create a peer + uno::Reference< awt::XToolkit> xToolkit = awt::Toolkit::create( xContext ); + xDlg->createPeer( xToolkit, rWindow.GetComponentInterface() ); + + xDlg->execute(); + + // need to cast because of multiple inheritance + Reference<awt::XControl>(xDlg)->dispose(); +} + + +bool DlgEditor::UnmarkDialog() +{ + SdrObject* pDlgObj = pDlgEdModel->GetPage(0)->GetObj(0); + SdrPageView* pPgView = pDlgEdView->GetSdrPageView(); + + bool bWasMarked = pDlgEdView->IsObjMarked( pDlgObj ); + + if( bWasMarked ) + pDlgEdView->MarkObj( pDlgObj, pPgView, true ); + + return bWasMarked; +} + + +bool DlgEditor::RemarkDialog() +{ + SdrObject* pDlgObj = pDlgEdModel->GetPage(0)->GetObj(0); + SdrPageView* pPgView = pDlgEdView->GetSdrPageView(); + + bool bWasMarked = pDlgEdView->IsObjMarked( pDlgObj ); + + if( !bWasMarked ) + pDlgEdView->MarkObj( pDlgObj, pPgView ); + + return bWasMarked; +} + + +DlgEditor::DlgEditor ( + vcl::Window& rWindow_, DialogWindowLayout& rLayout_, + css::uno::Reference<css::frame::XModel> const& xModel, + css::uno::Reference<css::container::XNameContainer> const & xDialogModel +) + :pHScroll(nullptr) + ,pVScroll(nullptr) + ,pDlgEdModel(new DlgEdModel()) + ,pDlgEdPage(new DlgEdPage(*pDlgEdModel)) + // set clipboard data flavors + ,m_ClipboardDataFlavors{ { /* MimeType */ "application/vnd.sun.xml.dialog", + /* HumanPresentableName */ "Dialog 6.0", + /* DataType */ cppu::UnoType<Sequence< sal_Int8 >>::get() } } + ,m_ClipboardDataFlavorsResource{ m_ClipboardDataFlavors[0], + { /* MimeType */ "application/vnd.sun.xml.dialogwithresource", + /* HumanPresentableName */ "Dialog 8.0", + /* DataType */ cppu::UnoType<Sequence< sal_Int8 >>::get() } } + ,pObjFac(new DlgEdFactory(xModel)) + ,rWindow(rWindow_) + ,pFunc(new DlgEdFuncSelect(*this)) + ,rLayout(rLayout_) + ,eMode( DlgEditor::SELECT ) + ,eActObj( SdrObjKind::BasicDialogPushButton ) + ,bFirstDraw(false) + ,bCreateOK(true) + ,bDialogModelChanged(false) + ,aMarkIdle("basctl DlgEditor Mark") + ,mnPaintGuard(0) + ,m_xDocument( xModel ) +{ + pDlgEdModel->GetItemPool().FreezeIdRanges(); + pDlgEdView.reset(new DlgEdView(*pDlgEdModel, *rWindow_.GetOutDev(), *this)); + pDlgEdModel->SetScaleUnit( MapUnit::Map100thMM ); + + SdrLayerAdmin& rAdmin = pDlgEdModel->GetLayerAdmin(); + rAdmin.NewLayer( rAdmin.GetControlLayerName() ); + rAdmin.NewLayer( "HiddenLayer" ); + + pDlgEdModel->InsertPage(pDlgEdPage); + + aMarkIdle.SetInvokeHandler( LINK( this, DlgEditor, MarkTimeout ) ); + + rWindow.SetMapMode( MapMode( MapUnit::Map100thMM ) ); + pDlgEdPage->SetSize( rWindow.PixelToLogic( Size(DLGED_PAGE_WIDTH_MIN, DLGED_PAGE_HEIGHT_MIN) ) ); + + pDlgEdView->ShowSdrPage(pDlgEdView->GetModel()->GetPage(0)); + pDlgEdView->SetLayerVisible( "HiddenLayer", false ); + pDlgEdView->SetMoveSnapOnlyTopLeft(true); + pDlgEdView->SetWorkArea( tools::Rectangle( Point( 0, 0 ), pDlgEdPage->GetSize() ) ); + + Size aGridSize( 100, 100 ); // 100TH_MM + pDlgEdView->SetGridCoarse( aGridSize ); + pDlgEdView->SetSnapGridWidth(Fraction(aGridSize.Width(), 1), Fraction(aGridSize.Height(), 1)); + pDlgEdView->SetGridSnap( true ); + pDlgEdView->SetGridVisible( false ); + pDlgEdView->SetDragStripes(false); + + pDlgEdView->SetDesignMode(); + + ::comphelper::disposeComponent( m_xControlContainer ); + + SetDialog(xDialogModel); +} + + +DlgEditor::~DlgEditor() +{ + aMarkIdle.Stop(); + + ::comphelper::disposeComponent( m_xControlContainer ); +} + + +Reference< awt::XControlContainer > const & DlgEditor::GetWindowControlContainer() +{ + if (!m_xControlContainer.is()) + m_xControlContainer = VCLUnoHelper::CreateControlContainer(&rWindow); + return m_xControlContainer; +} + + +void DlgEditor::SetScrollBars( ScrollBar* pHS, ScrollBar* pVS ) +{ + pHScroll = pHS; + pVScroll = pVS; + + InitScrollBars(); +} + + +void DlgEditor::InitScrollBars() +{ + DBG_ASSERT( pHScroll, "DlgEditor::InitScrollBars: no horizontal scroll bar!" ); + DBG_ASSERT( pVScroll, "DlgEditor::InitScrollBars: no vertical scroll bar!" ); + if ( !pHScroll || !pVScroll ) + return; + + Size aOutSize = rWindow.GetOutDev()->GetOutputSize(); + Size aPgSize = pDlgEdPage->GetSize(); + + pHScroll->SetRange( Range( 0, aPgSize.Width() )); + pVScroll->SetRange( Range( 0, aPgSize.Height() )); + pHScroll->SetVisibleSize( aOutSize.Width() ); + pVScroll->SetVisibleSize( aOutSize.Height() ); + + pHScroll->SetLineSize( aOutSize.Width() / 10 ); + pVScroll->SetLineSize( aOutSize.Height() / 10 ); + pHScroll->SetPageSize( aOutSize.Width() / 2 ); + pVScroll->SetPageSize( aOutSize.Height() / 2 ); + + DoScroll(); +} + + +void DlgEditor::DoScroll() +{ + if( !pHScroll || !pVScroll ) + return; + + MapMode aMap = rWindow.GetMapMode(); + Point aOrg = aMap.GetOrigin(); + + Size aScrollPos( pHScroll->GetThumbPos(), pVScroll->GetThumbPos() ); + aScrollPos = rWindow.LogicToPixel( aScrollPos ); + aScrollPos = rWindow.PixelToLogic( aScrollPos ); + + tools::Long nX = aScrollPos.Width() + aOrg.X(); + tools::Long nY = aScrollPos.Height() + aOrg.Y(); + + if( !nX && !nY ) + return; + + rWindow.PaintImmediately(); + + // #i31562# + // When scrolling, someone was rescuing the Wallpaper and forced the window scroll to + // be done without background refresh. I do not know why, but that causes the repaint + // problems. Taking that out. + // Wallpaper aOldBackground = rWindow.GetBackground(); + // rWindow.SetBackground(); + + // #i74769# children should be scrolled + rWindow.Scroll( -nX, -nY, ScrollFlags::Children); + aMap.SetOrigin( Point( -aScrollPos.Width(), -aScrollPos.Height() ) ); + rWindow.SetMapMode( aMap ); + rWindow.PaintImmediately(); + + DlgEdHint aHint( DlgEdHint::WINDOWSCROLLED ); + Broadcast( aHint ); +} + + +void DlgEditor::UpdateScrollBars() +{ + MapMode aMap = rWindow.GetMapMode(); + Point aOrg = aMap.GetOrigin(); + + if ( pHScroll ) + pHScroll->SetThumbPos( -aOrg.X() ); + + if ( pVScroll ) + pVScroll->SetThumbPos( -aOrg.Y() ); +} + + +void DlgEditor::SetDialog( const uno::Reference< container::XNameContainer >& xUnoControlDialogModel ) +{ + // set dialog model + m_xUnoControlDialogModel = xUnoControlDialogModel; + + // create dialog form + pDlgEdForm = new DlgEdForm(*pDlgEdModel, *this); + uno::Reference< awt::XControlModel > xDlgMod( m_xUnoControlDialogModel , uno::UNO_QUERY ); + pDlgEdForm->SetUnoControlModel(xDlgMod); + static_cast<DlgEdPage*>(pDlgEdModel->GetPage(0))->SetDlgEdForm( pDlgEdForm ); + pDlgEdModel->GetPage(0)->InsertObject( pDlgEdForm ); + AdjustPageSize(); + pDlgEdForm->SetRectFromProps(); + pDlgEdForm->UpdateTabIndices(); // for backward compatibility + pDlgEdForm->StartListening(); + + // create controls + if ( m_xUnoControlDialogModel.is() ) + { + // get sequence of control names + Sequence< OUString > aNames = m_xUnoControlDialogModel->getElementNames(); + const OUString* pNames = aNames.getConstArray(); + sal_Int32 nCtrls = aNames.getLength(); + + // create a map of tab indices and control names, sorted by tab index + IndexToNameMap aIndexToNameMap; + for ( sal_Int32 i = 0; i < nCtrls; ++i ) + { + // get name + OUString aName( pNames[i] ); + + // get tab index + sal_Int16 nTabIndex = -1; + Any aCtrl = m_xUnoControlDialogModel->getByName( aName ); + Reference< css::beans::XPropertySet > xPSet; + aCtrl >>= xPSet; + if ( xPSet.is() ) + xPSet->getPropertyValue( DLGED_PROP_TABINDEX ) >>= nTabIndex; + + // insert into map + aIndexToNameMap.emplace( nTabIndex, aName ); + } + + // create controls and insert them into drawing page + for (auto const& indexToName : aIndexToNameMap) + { + Any aCtrl = m_xUnoControlDialogModel->getByName( indexToName.second ); + Reference< css::awt::XControlModel > xCtrlModel; + aCtrl >>= xCtrlModel; + DlgEdObj* pCtrlObj = new DlgEdObj(*pDlgEdModel); + pCtrlObj->SetUnoControlModel( xCtrlModel ); + pCtrlObj->SetDlgEdForm( pDlgEdForm ); + pDlgEdForm->AddChild( pCtrlObj ); + pDlgEdModel->GetPage(0)->InsertObject( pCtrlObj ); + pCtrlObj->SetRectFromProps(); + pCtrlObj->UpdateStep(); + pCtrlObj->StartListening(); + } + } + + bFirstDraw = true; + + pDlgEdModel->SetChanged(false); +} + +void DlgEditor::ResetDialog () +{ + DlgEdForm* pOldDlgEdForm = pDlgEdForm; + DlgEdPage* pPage = static_cast<DlgEdPage*>(pDlgEdModel->GetPage(0)); + SdrPageView* pPgView = pDlgEdView->GetSdrPageView(); + bool bWasMarked = pDlgEdView->IsObjMarked( pOldDlgEdForm ); + pDlgEdView->UnmarkAll(); + + // clear SdrObjects with broadcasting + pPage->ClearSdrObjList(); + + pPage->SetDlgEdForm( nullptr ); + SetDialog( m_xUnoControlDialogModel ); + if( bWasMarked ) + pDlgEdView->MarkObj( pDlgEdForm, pPgView ); +} + + +Reference< util::XNumberFormatsSupplier > const & DlgEditor::GetNumberFormatsSupplier() +{ + if ( !m_xSupplier.is() ) + { + Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + Reference< util::XNumberFormatsSupplier > xSupplier( util::NumberFormatsSupplier::createWithDefaultLocale(xContext) ); + + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !m_xSupplier.is() ) + { + m_xSupplier = xSupplier; + } + } + return m_xSupplier; +} + + +void DlgEditor::MouseButtonDown( const MouseEvent& rMEvt ) +{ + rWindow.GrabFocus(); + pFunc->MouseButtonDown( rMEvt ); +} + + +void DlgEditor::MouseButtonUp( const MouseEvent& rMEvt ) +{ + bool bRet = pFunc->MouseButtonUp( rMEvt ); + + if( eMode == DlgEditor::INSERT ) + bCreateOK = bRet; +} + + +void DlgEditor::MouseMove( const MouseEvent& rMEvt ) +{ + pFunc->MouseMove( rMEvt ); +} + + +bool DlgEditor::KeyInput( const KeyEvent& rKEvt ) +{ + return pFunc->KeyInput( rKEvt ); +} + + +void DlgEditor::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +{ + aPaintRect = rRect; + mnPaintGuard++; + + if (bFirstDraw && rWindow.IsVisible() && (rRenderContext.GetOutputSize() != Size())) + { + bFirstDraw = false; + + // get property set + css::uno::Reference<css::beans::XPropertySet> xPSet(pDlgEdForm->GetUnoControlModel(), css::uno::UNO_QUERY); + + if (xPSet.is()) + { + // get dialog size from properties + sal_Int32 nWidth = 0, nHeight = 0; + xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nWidth; + xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nHeight; + + if (nWidth == 0 && nHeight == 0) + { + Size aSize = rRenderContext.PixelToLogic( Size( 400, 300 ) ); + + // align with grid + Size aGridSize_(tools::Long(pDlgEdView->GetSnapGridWidthX()), tools::Long(pDlgEdView->GetSnapGridWidthY())); + aSize.AdjustWidth( -(aSize.Width() % aGridSize_.Width()) ); + aSize.AdjustHeight( -(aSize.Height() % aGridSize_.Height()) ); + + Point aPos; + Size aOutSize = rRenderContext.GetOutputSize(); + aPos.setX( (aOutSize.Width()>>1) - (aSize.Width()>>1) ); + aPos.setY( (aOutSize.Height()>>1) - (aSize.Height()>>1) ); + + // align with grid + aPos.AdjustX( -(aPos.X() % aGridSize_.Width()) ); + aPos.AdjustY( -(aPos.Y() % aGridSize_.Height()) ); + + // don't put in the corner + Point aMinPos = rRenderContext.PixelToLogic( Point( 30, 20 ) ); + if( (aPos.X() < aMinPos.X()) || (aPos.Y() < aMinPos.Y()) ) + { + aPos = aMinPos; + aPos.AdjustX( -(aPos.X() % aGridSize_.Width()) ); + aPos.AdjustY( -(aPos.Y() % aGridSize_.Height()) ); + } + + // set dialog position and size + pDlgEdForm->SetSnapRect( tools::Rectangle( aPos, aSize ) ); + pDlgEdForm->EndListening(false); + pDlgEdForm->SetPropsFromRect(); + pDlgEdForm->GetDlgEditor().SetDialogModelChanged(); + pDlgEdForm->StartListening(); + + // set position and size of controls + if (const size_t nObjCount = pDlgEdPage->GetObjCount()) + { + for (size_t i = 0 ; i < nObjCount ; ++i) + { + if (DlgEdObj* pDlgEdObj = dynamic_cast<DlgEdObj*>(pDlgEdPage->GetObj(i))) + { + if (!dynamic_cast<DlgEdForm*>(pDlgEdObj)) + { + pDlgEdObj->SetRectFromProps(); + } + } + } + } + } + } + } + + // repaint, get PageView and prepare Region + SdrPageView* pPgView = pDlgEdView->GetSdrPageView(); + const vcl::Region aPaintRectRegion(aPaintRect); + + // #i74769# + SdrPaintWindow* pTargetPaintWindow = nullptr; + + // mark repaint start + if (pPgView) + { + pTargetPaintWindow = pPgView->GetView().BeginDrawLayers(&rRenderContext, aPaintRectRegion); + OSL_ENSURE(pTargetPaintWindow, "BeginDrawLayers: Got no SdrPaintWindow (!)"); + } + + // draw background self using wallpaper + // #i79128# ...and use correct OutDev for that + if (pTargetPaintWindow) + { + OutputDevice& rTargetOutDev = pTargetPaintWindow->GetTargetOutputDevice(); + rTargetOutDev.DrawWallpaper(aPaintRect, Wallpaper(COL_WHITE)); + } + + // do paint (unbuffered) and mark repaint end + if (pPgView) + { + // paint of control layer is done in EndDrawLayers anyway... + pPgView->GetView().EndDrawLayers(*pTargetPaintWindow, true); + } + + mnPaintGuard--; +} + + +IMPL_LINK_NOARG(DlgEditor, MarkTimeout, Timer *, void) +{ + rLayout.UpdatePropertyBrowser(); +} + + +void DlgEditor::SetMode (Mode eNewMode ) +{ + if ( eNewMode != eMode ) + { + if ( eNewMode == INSERT ) + pFunc.reset(new DlgEdFuncInsert(*this)); + else + pFunc.reset(new DlgEdFuncSelect(*this)); + + if ( eNewMode == READONLY ) + pDlgEdModel->SetReadOnly( true ); + else + pDlgEdModel->SetReadOnly( false ); + } + + if ( eNewMode == TEST ) + ShowDialog(); + + eMode = eNewMode; +} + + +void DlgEditor::SetInsertObj(SdrObjKind eObj) +{ + eActObj = eObj; + + pDlgEdView->SetCurrentObj( eActObj, SdrInventor::BasicDialog ); +} + +void DlgEditor::CreateDefaultObject() +{ + // create object by factory + SdrObject* pObj = SdrObjFactory::MakeNewObject( + *pDlgEdModel, + pDlgEdView->GetCurrentObjInventor(), + pDlgEdView->GetCurrentObjIdentifier()); + + DlgEdObj* pDlgEdObj = dynamic_cast<DlgEdObj*>(pObj); + if (!pDlgEdObj) + return; + + // set position and size + Size aSize = rWindow.PixelToLogic( Size( 96, 24 ) ); + Point aPoint = pDlgEdForm->GetSnapRect().Center(); + aPoint.AdjustX( -(aSize.Width() / 2) ); + aPoint.AdjustY( -(aSize.Height() / 2) ); + pDlgEdObj->SetSnapRect( tools::Rectangle( aPoint, aSize ) ); + + // set default property values + pDlgEdObj->SetDefaults(); + + // insert object into drawing page + SdrPageView* pPageView = pDlgEdView->GetSdrPageView(); + if (pDlgEdView->InsertObjectAtView(pDlgEdObj, *pPageView)) + { + // start listening + pDlgEdObj->StartListening(); + } +} + +void DlgEditor::Cut() +{ + Copy(); + Delete(); +} + +static void implCopyStreamToByteSequence( const Reference< XInputStream >& xStream, + Sequence< sal_Int8 >& bytes ) +{ + xStream->readBytes( bytes, xStream->available() ); + for (;;) + { + Sequence< sal_Int8 > readBytes; + sal_Int32 nRead = xStream->readBytes( readBytes, 1024 ); + if (! nRead) + break; + + sal_Int32 nPos = bytes.getLength(); + bytes.realloc( nPos + nRead ); + memcpy( bytes.getArray() + nPos, readBytes.getConstArray(), static_cast<sal_uInt32>(nRead) ); + } +} + +void DlgEditor::Copy() +{ + if( !pDlgEdView->AreObjectsMarked() ) + return; + + // stop all drawing actions + pDlgEdView->BrkAction(); + + // create an empty clipboard dialog model + Reference< util::XCloneable > xClone( m_xUnoControlDialogModel, UNO_QUERY ); + Reference< util::XCloneable > xNewClone = xClone->createClone(); + Reference< container::XNameContainer > xClipDialogModel( xNewClone, UNO_QUERY ); + + if ( xClipDialogModel.is() ) + { + Sequence< OUString > aNames = xClipDialogModel->getElementNames(); + const OUString* pNames = aNames.getConstArray(); + sal_uInt32 nCtrls = aNames.getLength(); + + for ( sal_uInt32 n = 0; n < nCtrls; n++ ) + { + xClipDialogModel->removeByName( pNames[n] ); + } + } + + // insert control models of marked objects into clipboard dialog model + const size_t nMark = pDlgEdView->GetMarkedObjectList().GetMarkCount(); + for( size_t i = 0; i < nMark; ++i ) + { + SdrObject* pObj = pDlgEdView->GetMarkedObjectList().GetMark(i)->GetMarkedSdrObj(); + DlgEdObj* pDlgEdObj = dynamic_cast<DlgEdObj*>(pObj); + + if (pDlgEdObj && !dynamic_cast<DlgEdForm*>(pDlgEdObj)) + { + OUString aName; + Reference< beans::XPropertySet > xMarkPSet(pDlgEdObj->GetUnoControlModel(), uno::UNO_QUERY); + if (xMarkPSet.is()) + { + xMarkPSet->getPropertyValue( DLGED_PROP_NAME ) >>= aName; + } + + if ( m_xUnoControlDialogModel.is() && m_xUnoControlDialogModel->hasByName(aName) ) + { + Any aCtrl = m_xUnoControlDialogModel->getByName( aName ); + + // clone control model + Reference< util::XCloneable > xCtrl; + aCtrl >>= xCtrl; + Reference< util::XCloneable > xNewCtrl = xCtrl->createClone(); + Any aNewCtrl; + aNewCtrl <<= xNewCtrl; + + if (xClipDialogModel.is()) + xClipDialogModel->insertByName( aName , aNewCtrl ); + } + } + } + + // export clipboard dialog model to xml + Reference< XComponentContext > xContext( + comphelper::getProcessComponentContext() ); + Reference< XInputStreamProvider > xISP = ::xmlscript::exportDialogModel( xClipDialogModel, xContext, m_xDocument ); + Reference< XInputStream > xStream( xISP->createInputStream() ); + Sequence< sal_Int8 > DialogModelBytes; + implCopyStreamToByteSequence( xStream, DialogModelBytes ); + xStream->closeInput(); + + // set clipboard content + Reference< datatransfer::clipboard::XClipboard > xClipboard = GetWindow().GetClipboard(); + if ( !xClipboard.is() ) + return; + + // With resource? + uno::Reference< beans::XPropertySet > xDialogModelPropSet( m_xUnoControlDialogModel, uno::UNO_QUERY ); + uno::Reference< resource::XStringResourcePersistence > xStringResourcePersistence; + if( xDialogModelPropSet.is() ) + { + try + { + Any aResourceResolver = xDialogModelPropSet->getPropertyValue( aResourceResolverPropName ); + aResourceResolver >>= xStringResourcePersistence; + } + catch(const UnknownPropertyException& ) + {} + } + + rtl::Reference<DlgEdTransferableImpl> pTrans; + if( xStringResourcePersistence.is() ) + { + // With resource, support old and new format + + // Export xClipDialogModel another time with ids replaced by current language string + LocalizationMgr::resetResourceForDialog( xClipDialogModel, xStringResourcePersistence ); + Reference< XInputStreamProvider > xISP2 = ::xmlscript::exportDialogModel( xClipDialogModel, xContext, m_xDocument ); + Reference< XInputStream > xStream2( xISP2->createInputStream() ); + Sequence< sal_Int8 > NoResourceDialogModelBytes; + implCopyStreamToByteSequence( xStream2, NoResourceDialogModelBytes ); + xStream2->closeInput(); + + // Old format contains dialog with replaced ids + Any aNoResourceDialogModelBytesAny; + aNoResourceDialogModelBytesAny <<= NoResourceDialogModelBytes; + + // New format contains dialog and resource + Sequence< sal_Int8 > aResData = xStringResourcePersistence->exportBinary(); + + // Create sequence for combined dialog and resource + sal_Int32 nDialogDataLen = DialogModelBytes.getLength(); + sal_Int32 nResDataLen = aResData.getLength(); + + // Combined data = 4 Bytes 32Bit Offset to begin of resource data, lowest byte first + // + nDialogDataLen bytes dialog data + nResDataLen resource data + sal_Int32 nTotalLen = 4 + nDialogDataLen + nResDataLen; + sal_Int32 nResOffset = 4 + nDialogDataLen; + Sequence< sal_Int8 > aCombinedData( nTotalLen ); + sal_Int8* pCombinedData = aCombinedData.getArray(); + + // Write offset + sal_Int32 n = nResOffset; + for( sal_Int16 i = 0 ; i < 4 ; i++ ) + { + pCombinedData[i] = sal_Int8( n & 0xff ); + n >>= 8; + } + memcpy( pCombinedData + 4, DialogModelBytes.getConstArray(), nDialogDataLen ); + memcpy( pCombinedData + nResOffset, aResData.getConstArray(), nResDataLen ); + + Sequence< Any > aSeqData + { + aNoResourceDialogModelBytesAny, + Any(aCombinedData) + }; + + pTrans = new DlgEdTransferableImpl( m_ClipboardDataFlavorsResource, aSeqData ); + } + else + { + // No resource, support only old format + pTrans = new DlgEdTransferableImpl( m_ClipboardDataFlavors , { Any(DialogModelBytes) } ); + } + SolarMutexReleaser aReleaser; + xClipboard->setContents( pTrans , pTrans ); +} + + +void DlgEditor::Paste() +{ + // stop all drawing actions + pDlgEdView->BrkAction(); + + // unmark all objects + pDlgEdView->UnmarkAll(); + + // get clipboard + Reference< datatransfer::clipboard::XClipboard > xClipboard = GetWindow().GetClipboard(); + if ( !xClipboard.is() ) + return; + + Reference< datatransfer::XTransferable > xTransf; + { + SolarMutexReleaser aReleaser; + // get clipboard content + xTransf = xClipboard->getContents(); + } + if ( !xTransf.is() ) + return; + + // Is target dialog (library) localized? + uno::Reference< beans::XPropertySet > xDialogModelPropSet( m_xUnoControlDialogModel, uno::UNO_QUERY ); + uno::Reference< resource::XStringResourceManager > xStringResourceManager; + if( xDialogModelPropSet.is() ) + { + try + { + Any aResourceResolver = xDialogModelPropSet->getPropertyValue( aResourceResolverPropName ); + aResourceResolver >>= xStringResourceManager; + } + catch(const UnknownPropertyException& ) + {} + } + bool bLocalized = false; + if( xStringResourceManager.is() ) + bLocalized = xStringResourceManager->getLocales().hasElements(); + + if ( !xTransf->isDataFlavorSupported( m_ClipboardDataFlavors[0] ) ) + return; + + // create clipboard dialog model from xml + Reference< XComponentContext > xContext = comphelper::getProcessComponentContext(); + Reference< container::XNameContainer > xClipDialogModel( xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.awt.UnoControlDialogModel", xContext ), uno::UNO_QUERY ); + + bool bSourceIsLocalized = false; + Sequence< sal_Int8 > DialogModelBytes; + Sequence< sal_Int8 > aResData; + if( bLocalized && xTransf->isDataFlavorSupported( m_ClipboardDataFlavorsResource[1] ) ) + { + bSourceIsLocalized = true; + + Any aCombinedDataAny = xTransf->getTransferData( m_ClipboardDataFlavorsResource[1] ); + Sequence< sal_Int8 > aCombinedData; + aCombinedDataAny >>= aCombinedData; + const sal_Int8* pCombinedData = aCombinedData.getConstArray(); + + sal_Int32 nTotalLen = aCombinedData.getLength(); + + // Reading offset + sal_Int32 nResOffset = 0; + sal_Int32 nFactor = 1; + for( sal_Int16 i = 0; i < 4; i++ ) + { + nResOffset += nFactor * sal_uInt8( pCombinedData[i] ); + nFactor *= 256; + } + + sal_Int32 nResDataLen = nTotalLen - nResOffset; + sal_Int32 nDialogDataLen = nTotalLen - nResDataLen - 4; + + DialogModelBytes.realloc( nDialogDataLen ); + memcpy( DialogModelBytes.getArray(), pCombinedData + 4, nDialogDataLen ); + + aResData.realloc( nResDataLen ); + memcpy( aResData.getArray(), pCombinedData + nResOffset, nResDataLen ); + } + else + { + Any aAny = xTransf->getTransferData( m_ClipboardDataFlavors[0] ); + aAny >>= DialogModelBytes; + } + + if ( xClipDialogModel.is() ) + { + Reference<XInputStream> xIn = ::xmlscript::createInputStream( DialogModelBytes.getConstArray(), DialogModelBytes.getLength() ); + ::xmlscript::importDialogModel( xIn , xClipDialogModel, xContext, m_xDocument ); + } + + // get control models from clipboard dialog model + if ( !xClipDialogModel.is() ) + return; + + Sequence< OUString > aNames = xClipDialogModel->getElementNames(); + const OUString* pNames = aNames.getConstArray(); + sal_uInt32 nCtrls = aNames.getLength(); + + Reference< resource::XStringResourcePersistence > xStringResourcePersistence; + if( nCtrls > 0 && bSourceIsLocalized ) + { + xStringResourcePersistence = css::resource::StringResource::create( getProcessComponentContext() ); + xStringResourcePersistence->importBinary( aResData ); + } + for( sal_uInt32 n = 0; n < nCtrls; n++ ) + { + Any aA = xClipDialogModel->getByName( pNames[n] ); + Reference< css::awt::XControlModel > xCM; + aA >>= xCM; + + // clone the control model + Reference< util::XCloneable > xClone( xCM, uno::UNO_QUERY ); + Reference< awt::XControlModel > xCtrlModel( xClone->createClone(), uno::UNO_QUERY ); + + DlgEdObj* pCtrlObj = new DlgEdObj(*pDlgEdModel); + pCtrlObj->SetDlgEdForm(pDlgEdForm); // set parent form + pDlgEdForm->AddChild(pCtrlObj); // add child to parent form + pCtrlObj->SetUnoControlModel( xCtrlModel ); // set control model + + // set new name + OUString aOUniqueName( pCtrlObj->GetUniqueName() ); + Reference< beans::XPropertySet > xPSet( xCtrlModel , UNO_QUERY ); + xPSet->setPropertyValue( DLGED_PROP_NAME, Any(aOUniqueName) ); + + // set tabindex + Sequence< OUString > aNames_ = m_xUnoControlDialogModel->getElementNames(); + xPSet->setPropertyValue( DLGED_PROP_TABINDEX, Any(static_cast<sal_Int16>(aNames_.getLength())) ); + + if( bLocalized ) + { + Any aControlAny; + aControlAny <<= xCtrlModel; + if( bSourceIsLocalized && xStringResourcePersistence.is() ) + { + LocalizationMgr::copyResourcesForPastedEditorObject( this, + aControlAny, aOUniqueName, xStringResourcePersistence ); + } + else + { + LocalizationMgr::setControlResourceIDsForNewEditorObject + ( this, aControlAny, aOUniqueName ); + } + } + + // insert control model in editor dialog model + Any aCtrlModel; + aCtrlModel <<= xCtrlModel; + m_xUnoControlDialogModel->insertByName( aOUniqueName , aCtrlModel ); + + // insert object into drawing page + pDlgEdModel->GetPage(0)->InsertObject( pCtrlObj ); + pCtrlObj->SetRectFromProps(); + pCtrlObj->UpdateStep(); + pDlgEdForm->UpdateTabOrderAndGroups(); + pCtrlObj->StartListening(); // start listening + + // mark object + SdrPageView* pPgView = pDlgEdView->GetSdrPageView(); + pDlgEdView->MarkObj( pCtrlObj, pPgView, false, true); + } + + // center marked objects in dialog editor form + Point aMarkCenter = pDlgEdView->GetMarkedObjRect().Center(); + Point aFormCenter = pDlgEdForm->GetSnapRect().Center(); + Point aPoint = aFormCenter - aMarkCenter; + Size aSize( aPoint.X() , aPoint.Y() ); + pDlgEdView->MoveMarkedObj( aSize ); // update of control model properties (position + size) in NbcMove + pDlgEdView->MarkListHasChanged(); + + // dialog model changed + SetDialogModelChanged(); +} + + +void DlgEditor::Delete() +{ + if( !pDlgEdView->AreObjectsMarked() ) + return; + + // remove control models of marked objects from dialog model + const size_t nMark = pDlgEdView->GetMarkedObjectList().GetMarkCount(); + + for( size_t i = 0; i < nMark; ++i ) + { + SdrObject* pObj = pDlgEdView->GetMarkedObjectList().GetMark(i)->GetMarkedSdrObj(); + DlgEdObj* pDlgEdObj = dynamic_cast<DlgEdObj*>(pObj); + + if ( pDlgEdObj && !dynamic_cast<DlgEdForm*>(pDlgEdObj) ) + { + // get name from property + OUString aName; + uno::Reference< beans::XPropertySet > xPSet(pDlgEdObj->GetUnoControlModel(), uno::UNO_QUERY); + if (xPSet.is()) + { + xPSet->getPropertyValue( DLGED_PROP_NAME ) >>= aName; + } + + // remove control from dialog model + Reference< css::container::XNameAccess > xNameAcc(pDlgEdObj->GetDlgEdForm()->GetUnoControlModel(), UNO_QUERY ); + if ( xNameAcc.is() && xNameAcc->hasByName(aName) ) + { + Reference< css::container::XNameContainer > xCont(xNameAcc, UNO_QUERY ); + if ( xCont.is() ) + { + if( xCont->hasByName( aName ) ) + { + Any aAny = xCont->getByName( aName ); + LocalizationMgr::deleteControlResourceIDsForDeletedEditorObject( this, aAny, aName ); + } + xCont->removeByName( aName ); + } + } + + // remove child from parent form + pDlgEdForm->RemoveChild( pDlgEdObj ); + } + } + + // update tab indices + pDlgEdForm->UpdateTabIndices(); + + pDlgEdView->BrkAction(); + + bool const bDlgMarked = UnmarkDialog(); + pDlgEdView->DeleteMarked(); + if( bDlgMarked ) + RemarkDialog(); +} + + +bool DlgEditor::IsPasteAllowed() +{ + // get clipboard + Reference< datatransfer::clipboard::XClipboard > xClipboard = GetWindow().GetClipboard(); + if ( xClipboard.is() ) + { + Reference< datatransfer::XTransferable > xTransf; + { + SolarMutexReleaser aReleaser; + // get clipboard content + xTransf = xClipboard->getContents(); + } + if (xTransf.is()) + return xTransf->isDataFlavorSupported(m_ClipboardDataFlavors[0]); + } + return false; +} + + +void DlgEditor::ShowProperties() +{ + rLayout.ShowPropertyBrowser(); +} + + +void DlgEditor::UpdatePropertyBrowserDelayed() +{ + aMarkIdle.Start(); +} + + +bool DlgEditor::IsModified() const +{ + return pDlgEdModel->IsChanged() || bDialogModelChanged; +} + + +void DlgEditor::ClearModifyFlag() +{ + pDlgEdModel->SetChanged(false); + bDialogModelChanged = false; +} + + +namespace Print +{ + tools::Long const nLeftMargin = 1700; + tools::Long const nRightMargin = 900; + tools::Long const nTopMargin = 2000; + tools::Long const nBottomMargin = 1000; + tools::Long const nBorder = 300; +} + +static void lcl_PrintHeader( Printer* pPrinter, const OUString& rTitle ) // not working yet +{ + + pPrinter->Push(); + + Size const aSz = pPrinter->GetOutputSize(); + + pPrinter->SetLineColor( COL_BLACK ); + pPrinter->SetFillColor(); + + vcl::Font aFont( pPrinter->GetFont() ); + aFont.SetWeight( WEIGHT_BOLD ); + aFont.SetAlignment( ALIGN_BOTTOM ); + pPrinter->SetFont( aFont ); + + tools::Long const nFontHeight = pPrinter->GetTextHeight(); + + // 1st border => line, 2+3 border = free space + tools::Long const nYTop = Print::nTopMargin - 3*Print::nBorder - nFontHeight; + + tools::Long const nXLeft = Print::nLeftMargin - Print::nBorder; + tools::Long const nXRight = aSz.Width() - Print::nRightMargin + Print::nBorder; + + pPrinter->DrawRect(tools::Rectangle( + Point(nXLeft, nYTop), + Size(nXRight - nXLeft, aSz.Height() - nYTop - Print::nBottomMargin + Print::nBorder) + )); + + tools::Long nY = Print::nTopMargin - 2*Print::nBorder; + Point aPos(Print::nLeftMargin, nY); + pPrinter->DrawText( aPos, rTitle ); + + nY = Print::nTopMargin - Print::nBorder; + pPrinter->DrawLine( Point( nXLeft, nY ), Point( nXRight, nY ) ); + + pPrinter->Pop(); +} + + +void DlgEditor::printPage( sal_Int32 nPage, Printer* pPrinter, const OUString& rTitle ) +{ + if( nPage == 0 ) + Print( pPrinter, rTitle ); +} + + +void DlgEditor::Print( Printer* pPrinter, const OUString& rTitle ) // not working yet +{ + MapMode aOldMap( pPrinter->GetMapMode()); + vcl::Font aOldFont( pPrinter->GetFont() ); + + MapMode aMap( MapUnit::Map100thMM ); + pPrinter->SetMapMode( aMap ); + vcl::Font aFont; + aFont.SetAlignment( ALIGN_BOTTOM ); + aFont.SetFontSize( Size( 0, 360 )); + pPrinter->SetFont( aFont ); + + Size aPaperSz = pPrinter->GetOutputSize(); + aPaperSz.AdjustWidth( -(Print::nLeftMargin + Print::nRightMargin) ); + aPaperSz.AdjustHeight( -(Print::nTopMargin + Print::nBottomMargin) ); + + lcl_PrintHeader( pPrinter, rTitle ); + + BitmapEx aDlgEx; + Size aBmpSz( pPrinter->PixelToLogic( aDlgEx.GetSizePixel() ) ); + double nPaperSzWidth = aPaperSz.Width(); + double nPaperSzHeight = aPaperSz.Height(); + double nBmpSzWidth = aBmpSz.Width(); + double nBmpSzHeight = aBmpSz.Height(); + double nScaleX = nPaperSzWidth / nBmpSzWidth; + double nScaleY = nPaperSzHeight / nBmpSzHeight; + + Size aOutputSz; + if( nBmpSzHeight * nScaleX <= nPaperSzHeight ) + { + aOutputSz.setWidth( static_cast<tools::Long>(nBmpSzWidth * nScaleX) ); + aOutputSz.setHeight( static_cast<tools::Long>(nBmpSzHeight * nScaleX) ); + } + else + { + aOutputSz.setWidth( static_cast<tools::Long>(nBmpSzWidth * nScaleY) ); + aOutputSz.setHeight( static_cast<tools::Long>(nBmpSzHeight * nScaleY) ); + } + + Point aPosOffs( + (aPaperSz.Width() / 2) - (aOutputSz.Width() / 2), + (aPaperSz.Height()/ 2) - (aOutputSz.Height() / 2)); + + aPosOffs.AdjustX(Print::nLeftMargin ); + aPosOffs.AdjustY(Print::nTopMargin ); + + pPrinter->DrawBitmapEx( aPosOffs, aOutputSz, aDlgEx ); + + pPrinter->SetMapMode( aOldMap ); + pPrinter->SetFont( aOldFont ); +} + + +bool DlgEditor::AdjustPageSize() +{ + bool bAdjustedPageSize = false; + Reference< beans::XPropertySet > xPSet( m_xUnoControlDialogModel, UNO_QUERY ); + if ( xPSet.is() ) + { + sal_Int32 nFormXIn = 0, nFormYIn = 0, nFormWidthIn = 0, nFormHeightIn = 0; + xPSet->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nFormXIn; + xPSet->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nFormYIn; + xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nFormWidthIn; + xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nFormHeightIn; + + sal_Int32 nFormX, nFormY, nFormWidth, nFormHeight; + if ( pDlgEdForm && pDlgEdForm->TransformFormToSdrCoordinates( nFormXIn, nFormYIn, nFormWidthIn, nFormHeightIn, nFormX, nFormY, nFormWidth, nFormHeight ) ) + { + Size aPageSizeDelta( 400, 300 ); + aPageSizeDelta = rWindow.PixelToLogic( aPageSizeDelta, MapMode( MapUnit::Map100thMM ) ); + + sal_Int32 nNewPageWidth = nFormX + nFormWidth + aPageSizeDelta.Width(); + sal_Int32 nNewPageHeight = nFormY + nFormHeight + aPageSizeDelta.Height(); + + Size aPageSizeMin( DLGED_PAGE_WIDTH_MIN, DLGED_PAGE_HEIGHT_MIN ); + aPageSizeMin = rWindow.PixelToLogic( aPageSizeMin, MapMode( MapUnit::Map100thMM ) ); + sal_Int32 nPageWidthMin = aPageSizeMin.Width(); + sal_Int32 nPageHeightMin = aPageSizeMin.Height(); + + if ( nNewPageWidth < nPageWidthMin ) + nNewPageWidth = nPageWidthMin; + + if ( nNewPageHeight < nPageHeightMin ) + nNewPageHeight = nPageHeightMin; + + if ( pDlgEdPage ) + { + Size aPageSize = pDlgEdPage->GetSize(); + if ( nNewPageWidth != aPageSize.Width() || nNewPageHeight != aPageSize.Height() ) + { + Size aNewPageSize( nNewPageWidth, nNewPageHeight ); + pDlgEdPage->SetSize( aNewPageSize ); + pDlgEdView->SetWorkArea( tools::Rectangle( Point( 0, 0 ), aNewPageSize ) ); + bAdjustedPageSize = true; + } + } + } + } + + return bAdjustedPageSize; +} + + +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/dlged/dlgedclip.cxx b/basctl/source/dlged/dlgedclip.cxx new file mode 100644 index 000000000..931f10afe --- /dev/null +++ b/basctl/source/dlged/dlgedclip.cxx @@ -0,0 +1,109 @@ +/* -*- 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 <dlgedclip.hxx> +#include <vcl/svapp.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp> +#include <com/sun/star/datatransfer/XMimeContentType.hpp> +#include <com/sun/star/datatransfer/MimeContentTypeFactory.hpp> + +namespace basctl +{ + +using namespace comphelper; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::datatransfer; +using namespace ::com::sun::star::datatransfer::clipboard; +DlgEdTransferableImpl::DlgEdTransferableImpl( const Sequence< DataFlavor >& aSeqFlavors, const Sequence< Any >& aSeqData ) +{ + m_SeqFlavors = aSeqFlavors; + m_SeqData = aSeqData; +} +DlgEdTransferableImpl::~DlgEdTransferableImpl() +{ +} +bool DlgEdTransferableImpl::compareDataFlavors( const DataFlavor& lFlavor, const DataFlavor& rFlavor ) +{ + // compare mime content types + Reference< uno::XComponentContext > xContext = getProcessComponentContext(); + Reference< datatransfer::XMimeContentTypeFactory > + xMCntTypeFactory = MimeContentTypeFactory::create(xContext); + + // compare full media types + Reference< datatransfer::XMimeContentType > xLType = xMCntTypeFactory->createMimeContentType( lFlavor.MimeType ); + Reference< datatransfer::XMimeContentType > xRType = xMCntTypeFactory->createMimeContentType( rFlavor.MimeType ); + + OUString aLFullMediaType = xLType->getFullMediaType(); + OUString aRFullMediaType = xRType->getFullMediaType(); + + bool bRet = aLFullMediaType.equalsIgnoreAsciiCase( aRFullMediaType ); + + return bRet; +} + +// XTransferable +Any SAL_CALL DlgEdTransferableImpl::getTransferData( const DataFlavor& rFlavor ) +{ + const SolarMutexGuard aGuard; + + if ( !isDataFlavorSupported( rFlavor ) ) + throw UnsupportedFlavorException(); + + Any aData; + + for ( sal_Int32 i = 0; i < m_SeqFlavors.getLength(); i++ ) + { + if ( compareDataFlavors( m_SeqFlavors[i] , rFlavor ) ) + { + aData = m_SeqData[i]; + break; + } + } + + return aData; +} +Sequence< DataFlavor > SAL_CALL DlgEdTransferableImpl::getTransferDataFlavors( ) +{ + const SolarMutexGuard aGuard; + + return m_SeqFlavors; +} +sal_Bool SAL_CALL DlgEdTransferableImpl::isDataFlavorSupported( const DataFlavor& rFlavor ) +{ + const SolarMutexGuard aGuard; + + for ( auto const & i : std::as_const(m_SeqFlavors) ) + if ( compareDataFlavors( i, rFlavor ) ) + return true; + return false; +} + +// XClipboardOwner +void SAL_CALL DlgEdTransferableImpl::lostOwnership( const Reference< XClipboard >&, const Reference< XTransferable >& ) +{ + const SolarMutexGuard aGuard; + + m_SeqFlavors = Sequence< DataFlavor >(); + m_SeqData = Sequence< Any >(); +} +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/dlged/dlgedfac.cxx b/basctl/source/dlged/dlgedfac.cxx new file mode 100644 index 000000000..03713c2b9 --- /dev/null +++ b/basctl/source/dlged/dlgedfac.cxx @@ -0,0 +1,232 @@ +/* -*- 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 <dlgedfac.hxx> +#include <dlgedobj.hxx> +#include <dlgeddef.hxx> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/ScrollBarOrientation.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <comphelper/processfactory.hxx> +#include <utility> + +namespace basctl +{ + +using namespace ::com::sun::star; + + +DlgEdFactory::DlgEdFactory( css::uno::Reference< css::frame::XModel > xModel ) : mxModel(std::move( xModel )) +{ + SdrObjFactory::InsertMakeObjectHdl( LINK(this, DlgEdFactory, MakeObject) ); +} + + +DlgEdFactory::~DlgEdFactory() COVERITY_NOEXCEPT_FALSE +{ + SdrObjFactory::RemoveMakeObjectHdl( LINK(this, DlgEdFactory, MakeObject) ); +} + + +IMPL_LINK( DlgEdFactory, MakeObject, SdrObjCreatorParams, aParams, SdrObject* ) +{ + static const uno::Reference<lang::XMultiServiceFactory> xDialogSFact = [] { + uno::Reference<lang::XMultiServiceFactory> xFact; + uno::Reference< uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext(); + uno::Reference< container::XNameContainer > xC( xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.awt.UnoControlDialogModel", xContext ), uno::UNO_QUERY ); + if( xC.is() ) + { + uno::Reference< lang::XMultiServiceFactory > xModFact( xC, uno::UNO_QUERY ); + xFact = xModFact; + } + return xFact; + }(); + + SdrObject* pNewObj = nullptr; + if( (aParams.nInventor == SdrInventor::BasicDialog) && + (aParams.nObjIdentifier >= SdrObjKind::BasicDialogPushButton) && + (aParams.nObjIdentifier <= SdrObjKind::BasicDialogFormHorizontalScroll) ) + { + switch( aParams.nObjIdentifier ) + { + case SdrObjKind::BasicDialogPushButton: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlButtonModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogRadioButton: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlRadioButtonModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogFormRadio: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.form.component.RadioButton", xDialogSFact ); + static_cast< DlgEdObj* >( pNewObj )->MakeDataAware( mxModel ); + break; + case SdrObjKind::BasicDialogCheckbox: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlCheckBoxModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogFormCheck: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.form.component.CheckBox", xDialogSFact ); + static_cast< DlgEdObj* >( pNewObj )->MakeDataAware( mxModel ); + break; + case SdrObjKind::BasicDialogListbox: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlListBoxModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogFormList: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.form.component.ListBox", xDialogSFact ); + static_cast< DlgEdObj* >( pNewObj )->MakeDataAware( mxModel ); + break; + case SdrObjKind::BasicDialogFormCombo: + case SdrObjKind::BasicDialogCombobox: + { + DlgEdObj* pNew = nullptr; + if ( aParams.nObjIdentifier == SdrObjKind::BasicDialogCombobox ) + pNew = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlComboBoxModel", xDialogSFact ); + else + { + pNew = new DlgEdObj(aParams.rSdrModel, "com.sun.star.form.component.ComboBox", xDialogSFact ); + pNew->MakeDataAware( mxModel ); + } + pNewObj = pNew; + try + { + uno::Reference< beans::XPropertySet > xPSet(pNew->GetUnoControlModel(), uno::UNO_QUERY); + if (xPSet.is()) + { + xPSet->setPropertyValue( DLGED_PROP_DROPDOWN, uno::Any(true)); + } + } + catch(...) + { + } + } + break; + case SdrObjKind::BasicDialogGroupBox: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlGroupBoxModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogEdit: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlEditModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogFixedText: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlFixedTextModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogImageControl: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlImageControlModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogProgressbar: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlProgressBarModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogHorizontalScrollbar: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlScrollBarModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogFormHorizontalScroll: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.form.component.ScrollBar", xDialogSFact ); + static_cast< DlgEdObj* >( pNewObj )->MakeDataAware( mxModel ); + break; + case SdrObjKind::BasicDialogFormVerticalScroll: + case SdrObjKind::BasicDialogVerticalScrollbar: + { + DlgEdObj* pNew = nullptr; + if ( aParams.nObjIdentifier == SdrObjKind::BasicDialogVerticalScrollbar ) + pNew = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlScrollBarModel", xDialogSFact ); + else + { + pNew = new DlgEdObj(aParams.rSdrModel, "com.sun.star.form.component.ScrollBar", xDialogSFact ); + pNew->MakeDataAware( mxModel ); + } + pNewObj = pNew; + // set vertical orientation + try + { + uno::Reference< beans::XPropertySet > xPSet(pNew->GetUnoControlModel(), uno::UNO_QUERY); + if (xPSet.is()) + { + xPSet->setPropertyValue( DLGED_PROP_ORIENTATION, uno::Any(sal_Int32(css::awt::ScrollBarOrientation::VERTICAL)) ); + } + } + catch(...) + { + } + } break; + case SdrObjKind::BasicDialogHorizontalFixedLine: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlFixedLineModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogVerticalFixedLine: + { + DlgEdObj* pNew = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlFixedLineModel", xDialogSFact ); + pNewObj = pNew; + // set vertical orientation + try + { + uno::Reference< beans::XPropertySet > xPSet(pNew->GetUnoControlModel(), uno::UNO_QUERY); + if (xPSet.is()) + { + xPSet->setPropertyValue( DLGED_PROP_ORIENTATION, uno::Any(sal_Int32(1)) ); + } + } + catch(...) + { + } + } break; + case SdrObjKind::BasicDialogDateField: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlDateFieldModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogTimeField: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlTimeFieldModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogNumericField: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlNumericFieldModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogCurencyField: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlCurrencyFieldModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogFormattedField: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlFormattedFieldModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogPatternField: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlPatternFieldModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogFileControl: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlFileControlModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogSpinButton: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlSpinButtonModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogFormSpin: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.form.component.SpinButton", xDialogSFact ); + static_cast< DlgEdObj* >( pNewObj )->MakeDataAware( mxModel ); + break; + case SdrObjKind::BasicDialogTreeControl: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.tree.TreeControlModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogGridControl: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.grid.UnoControlGridModel", xDialogSFact ); + break; + case SdrObjKind::BasicDialogHyperlinkControl: + pNewObj = new DlgEdObj(aParams.rSdrModel, "com.sun.star.awt.UnoControlFixedHyperlinkModel", xDialogSFact ); + break; + default: + break; + + } + } + return pNewObj; +} + +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/dlged/dlgedfunc.cxx b/basctl/source/dlged/dlgedfunc.cxx new file mode 100644 index 000000000..c43b22c8e --- /dev/null +++ b/basctl/source/dlged/dlgedfunc.cxx @@ -0,0 +1,548 @@ +/* -*- 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 <vcl/scrbar.hxx> +#include <svx/svdview.hxx> +#include <dlgedfunc.hxx> +#include <dlged.hxx> +#include <dlgedview.hxx> +#include <vcl/seleng.hxx> + +namespace basctl +{ + +IMPL_LINK_NOARG( DlgEdFunc, ScrollTimeout, Timer *, void ) +{ + vcl::Window& rWindow = rParent.GetWindow(); + Point aPos = rWindow.ScreenToOutputPixel( rWindow.GetPointerPosPixel() ); + aPos = rWindow.PixelToLogic( aPos ); + ForceScroll( aPos ); +} + +void DlgEdFunc::ForceScroll( const Point& rPos ) +{ + aScrollTimer.Stop(); + + vcl::Window& rWindow = rParent.GetWindow(); + + static const Point aDefPoint; + tools::Rectangle aOutRect( aDefPoint, rWindow.GetOutputSizePixel() ); + aOutRect = rWindow.PixelToLogic( aOutRect ); + + ScrollBar* pHScroll = rParent.GetHScroll(); + ScrollBar* pVScroll = rParent.GetVScroll(); + tools::Long nDeltaX = pHScroll->GetLineSize(); + tools::Long nDeltaY = pVScroll->GetLineSize(); + + if( !aOutRect.Contains( rPos ) ) + { + if( rPos.X() < aOutRect.Left() ) + nDeltaX = -nDeltaX; + else if( rPos.X() <= aOutRect.Right() ) + nDeltaX = 0; + + if( rPos.Y() < aOutRect.Top() ) + nDeltaY = -nDeltaY; + else if( rPos.Y() <= aOutRect.Bottom() ) + nDeltaY = 0; + + if( nDeltaX ) + pHScroll->SetThumbPos( pHScroll->GetThumbPos() + nDeltaX ); + if( nDeltaY ) + pVScroll->SetThumbPos( pVScroll->GetThumbPos() + nDeltaY ); + + if( nDeltaX ) + rParent.DoScroll(); + if( nDeltaY ) + rParent.DoScroll(); + } + + aScrollTimer.Start(); +} + +DlgEdFunc::DlgEdFunc (DlgEditor& rParent_) : + rParent(rParent_), aScrollTimer("basctl DlgEdFunc aScrollTimer") +{ + aScrollTimer.SetInvokeHandler( LINK( this, DlgEdFunc, ScrollTimeout ) ); + aScrollTimer.SetTimeout( SELENG_AUTOREPEAT_INTERVAL ); +} + +DlgEdFunc::~DlgEdFunc() +{ +} + +void DlgEdFunc::MouseButtonDown( const MouseEvent& ) +{ +} + +bool DlgEdFunc::MouseButtonUp( const MouseEvent& ) +{ + aScrollTimer.Stop(); + return true; +} + +void DlgEdFunc::MouseMove( const MouseEvent& ) +{ +} + +bool DlgEdFunc::KeyInput( const KeyEvent& rKEvt ) +{ + bool bReturn = false; + + SdrView& rView = rParent.GetView(); + vcl::Window& rWindow = rParent.GetWindow(); + + vcl::KeyCode aCode = rKEvt.GetKeyCode(); + sal_uInt16 nCode = aCode.GetCode(); + + switch ( nCode ) + { + case KEY_ESCAPE: + { + if ( rView.IsAction() ) + { + rView.BrkAction(); + bReturn = true; + } + else if ( rView.AreObjectsMarked() ) + { + const SdrHdlList& rHdlList = rView.GetHdlList(); + SdrHdl* pHdl = rHdlList.GetFocusHdl(); + if ( pHdl ) + const_cast<SdrHdlList&>(rHdlList).ResetFocusHdl(); + else + rView.UnmarkAll(); + + bReturn = true; + } + } + break; + case KEY_TAB: + { + if ( !aCode.IsMod1() && !aCode.IsMod2() ) + { + // mark next object + if ( !rView.MarkNextObj( !aCode.IsShift() ) ) + { + // if no next object, mark first/last + rView.UnmarkAllObj(); + rView.MarkNextObj( !aCode.IsShift() ); + } + + if ( rView.AreObjectsMarked() ) + rView.MakeVisible( rView.GetAllMarkedRect(), rWindow ); + + bReturn = true; + } + else if ( aCode.IsMod1() ) + { + // selected handle + const SdrHdlList& rHdlList = rView.GetHdlList(); + const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl( !aCode.IsShift() ); + + // guarantee visibility of focused handle + if (SdrHdl* pHdl = rHdlList.GetFocusHdl()) + { + Point aHdlPosition( pHdl->GetPos() ); + tools::Rectangle aVisRect( aHdlPosition - Point( 100, 100 ), Size( 200, 200 ) ); + rView.MakeVisible( aVisRect, rWindow ); + } + + bReturn = true; + } + } + break; + case KEY_UP: + case KEY_DOWN: + case KEY_LEFT: + case KEY_RIGHT: + { + tools::Long nX = 0; + tools::Long nY = 0; + + if ( nCode == KEY_UP ) + { + // scroll up + nX = 0; + nY = -1; + } + else if ( nCode == KEY_DOWN ) + { + // scroll down + nX = 0; + nY = 1; + } + else if ( nCode == KEY_LEFT ) + { + // scroll left + nX = -1; + nY = 0; + } + else if ( nCode == KEY_RIGHT ) + { + // scroll right + nX = 1; + nY = 0; + } + + if ( rView.AreObjectsMarked() && !aCode.IsMod1() ) + { + if ( aCode.IsMod2() ) + { + // move in 1 pixel distance + Size aPixelSize = rWindow.PixelToLogic(Size(1, 1)); + nX *= aPixelSize.Width(); + nY *= aPixelSize.Height(); + } + else + { + // move in 1 mm distance + nX *= 100; + nY *= 100; + } + + const SdrHdlList& rHdlList = rView.GetHdlList(); + SdrHdl* pHdl = rHdlList.GetFocusHdl(); + + if ( pHdl == nullptr ) + { + // no handle selected + if ( rView.IsMoveAllowed() ) + { + // restrict movement to work area + const tools::Rectangle& rWorkArea = rView.GetWorkArea(); + + if ( !rWorkArea.IsEmpty() ) + { + tools::Rectangle aMarkRect( rView.GetMarkedObjRect() ); + aMarkRect.Move( nX, nY ); + + if ( !rWorkArea.Contains( aMarkRect ) ) + { + if ( aMarkRect.Left() < rWorkArea.Left() ) + nX += rWorkArea.Left() - aMarkRect.Left(); + + if ( aMarkRect.Right() > rWorkArea.Right() ) + nX -= aMarkRect.Right() - rWorkArea.Right(); + + if ( aMarkRect.Top() < rWorkArea.Top() ) + nY += rWorkArea.Top() - aMarkRect.Top(); + + if ( aMarkRect.Bottom() > rWorkArea.Bottom() ) + nY -= aMarkRect.Bottom() - rWorkArea.Bottom(); + } + } + + if ( nX != 0 || nY != 0 ) + { + rView.MoveAllMarked( Size( nX, nY ) ); + rView.MakeVisible( rView.GetAllMarkedRect(), rWindow ); + } + } + } + else if (nX || nY) + { + Point aStartPoint(pHdl->GetPos()); + Point aEndPoint(pHdl->GetPos() + Point(nX, nY)); + const SdrDragStat& rDragStat = rView.GetDragStat(); + + // start dragging + rView.BegDragObj(aStartPoint, nullptr, pHdl, 0); + + if (rView.IsDragObj()) + { + bool const bWasNoSnap = rDragStat.IsNoSnap(); + bool const bWasSnapEnabled = rView.IsSnapEnabled(); + + // switch snapping off + if (!bWasNoSnap) + const_cast<SdrDragStat&>(rDragStat).SetNoSnap(); + if (bWasSnapEnabled) + rView.SetSnapEnabled(false); + + rView.MovAction(aEndPoint); + rView.EndDragObj(); + + // restore snap + if (!bWasNoSnap) + const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap); + if (bWasSnapEnabled) + rView.SetSnapEnabled(bWasSnapEnabled); + } + + // make moved handle visible + tools::Rectangle aVisRect(aEndPoint - Point(100, 100), Size(200, 200)); + rView.MakeVisible(aVisRect, rWindow); + } + } + else + { + // scroll page + ScrollBar* pScrollBar = ( nX != 0 ) ? rParent.GetHScroll() : rParent.GetVScroll(); + if ( pScrollBar ) + { + tools::Long nRangeMin = pScrollBar->GetRangeMin(); + tools::Long nRangeMax = pScrollBar->GetRangeMax(); + tools::Long nThumbPos = pScrollBar->GetThumbPos() + ( ( nX != 0 ) ? nX : nY ) * pScrollBar->GetLineSize(); + if ( nThumbPos < nRangeMin ) + nThumbPos = nRangeMin; + if ( nThumbPos > nRangeMax ) + nThumbPos = nRangeMax; + pScrollBar->SetThumbPos( nThumbPos ); + rParent.DoScroll(); + } + } + + bReturn = true; + } + break; + default: + { + } + break; + } + + if ( bReturn ) + rWindow.ReleaseMouse(); + + return bReturn; +} + +DlgEdFuncInsert::DlgEdFuncInsert (DlgEditor& rParent_) : + DlgEdFunc(rParent_) +{ + rParent.GetView().SetCreateMode(); +} + +DlgEdFuncInsert::~DlgEdFuncInsert() +{ + rParent.GetView().SetEditMode(); +} + +void DlgEdFuncInsert::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if( !rMEvt.IsLeft() ) + return; + + SdrView& rView = rParent.GetView(); + vcl::Window& rWindow = rParent.GetWindow(); + rView.SetActualWin(rWindow.GetOutDev()); + + Point aPos = rWindow.PixelToLogic( rMEvt.GetPosPixel() ); + sal_uInt16 nHitLog = static_cast<sal_uInt16>(rWindow.PixelToLogic(Size(3, 0)).Width()); + sal_uInt16 nDrgLog = static_cast<sal_uInt16>(rWindow.PixelToLogic(Size(3, 0)).Width()); + + rWindow.CaptureMouse(); + + if ( rMEvt.IsLeft() && rMEvt.GetClicks() == 1 ) + { + SdrHdl* pHdl = rView.PickHandle(aPos); + + // if selected object was hit, drag object + if ( pHdl!=nullptr || rView.IsMarkedHit(aPos, nHitLog) ) + rView.BegDragObj(aPos, nullptr, pHdl, nDrgLog); + else if ( rView.AreObjectsMarked() ) + rView.UnmarkAll(); + + // if no action, create object + if ( !rView.IsAction() ) + rView.BegCreateObj(aPos); + } + else if ( rMEvt.IsLeft() && rMEvt.GetClicks() == 2 ) + { + // if object was hit, show property browser + if ( rView.IsMarkedHit(aPos, nHitLog) && rParent.GetMode() != DlgEditor::READONLY ) + rParent.ShowProperties(); + } +} + +bool DlgEdFuncInsert::MouseButtonUp( const MouseEvent& rMEvt ) +{ + DlgEdFunc::MouseButtonUp( rMEvt ); + + SdrView& rView = rParent.GetView(); + vcl::Window& rWindow = rParent.GetWindow(); + rView.SetActualWin(rWindow.GetOutDev()); + + rWindow.ReleaseMouse(); + + // object creation active? + if ( rView.IsCreateObj() ) + { + rView.EndCreateObj(SdrCreateCmd::ForceEnd); + + if ( !rView.AreObjectsMarked() ) + { + sal_uInt16 nHitLog = static_cast<sal_uInt16>(rWindow.PixelToLogic(Size(3, 0)).Width()); + Point aPos( rWindow.PixelToLogic( rMEvt.GetPosPixel() ) ); + rView.MarkObj(aPos, nHitLog); + } + + return rView.AreObjectsMarked(); + } + else + { + if ( rView.IsDragObj() ) + rView.EndDragObj( rMEvt.IsMod1() ); + return true; + } +} + +void DlgEdFuncInsert::MouseMove( const MouseEvent& rMEvt ) +{ + SdrView& rView = rParent.GetView(); + vcl::Window& rWindow = rParent.GetWindow(); + rView.SetActualWin(rWindow.GetOutDev()); + + Point aPos = rWindow.PixelToLogic(rMEvt.GetPosPixel()); + sal_uInt16 nHitLog = static_cast<sal_uInt16>(rWindow.PixelToLogic(Size(3, 0)).Width()); + + if (rView.IsAction()) + { + ForceScroll(aPos); + rView.MovAction(aPos); + } + + rWindow.SetPointer( rView.GetPreferredPointer( aPos, rWindow.GetOutDev(), nHitLog ) ); +} + +DlgEdFuncSelect::DlgEdFuncSelect (DlgEditor& rParent_) : + DlgEdFunc(rParent_) +{ +} + +DlgEdFuncSelect::~DlgEdFuncSelect() +{ +} + +void DlgEdFuncSelect::MouseButtonDown( const MouseEvent& rMEvt ) +{ + // get view from parent + SdrView& rView = rParent.GetView(); + vcl::Window& rWindow = rParent.GetWindow(); + rView.SetActualWin(rWindow.GetOutDev()); + + sal_uInt16 nDrgLog = static_cast<sal_uInt16>(rWindow.PixelToLogic(Size(3, 0)).Width()); + sal_uInt16 nHitLog = static_cast<sal_uInt16>(rWindow.PixelToLogic(Size(3, 0)).Width()); + Point aMDPos = rWindow.PixelToLogic(rMEvt.GetPosPixel()); + + if ( rMEvt.IsLeft() && rMEvt.GetClicks() == 1 ) + { + SdrHdl* pHdl = rView.PickHandle(aMDPos); + + // hit selected object? + if ( pHdl!=nullptr || rView.IsMarkedHit(aMDPos, nHitLog) ) + { + rView.BegDragObj(aMDPos, nullptr, pHdl, nDrgLog); + } + else + { + // if not multi selection, unmark all + if ( !rMEvt.IsShift() ) + rView.UnmarkAll(); + else + { + SdrPageView* pPV; + SdrObject* pObj = rView.PickObj(aMDPos, nHitLog, pPV); + if (pObj) + { + //if (dynamic_cast<DlgEdForm*>(pObj)) + // rView.UnmarkAll(); + //else + // rParent.UnmarkDialog(); + } + } + + if ( rView.MarkObj(aMDPos, nHitLog) ) + { + // drag object + pHdl = rView.PickHandle(aMDPos); + rView.BegDragObj(aMDPos, nullptr, pHdl, nDrgLog); + } + else + { + // select object + rView.BegMarkObj(aMDPos); + } + } + } + else if ( rMEvt.IsLeft() && rMEvt.GetClicks() == 2 ) + { + // if object was hit, show property browser + if ( rView.IsMarkedHit(aMDPos, nHitLog) && rParent.GetMode() != DlgEditor::READONLY ) + rParent.ShowProperties(); + } +} + +bool DlgEdFuncSelect::MouseButtonUp( const MouseEvent& rMEvt ) +{ + DlgEdFunc::MouseButtonUp( rMEvt ); + + // get view from parent + SdrView& rView = rParent.GetView(); + vcl::Window& rWindow = rParent.GetWindow(); + rView.SetActualWin(rWindow.GetOutDev()); + + Point aPnt = rWindow.PixelToLogic(rMEvt.GetPosPixel()); + sal_uInt16 nHitLog = static_cast<sal_uInt16>(rWindow.PixelToLogic(Size(3, 0)).Width()); + + if ( rMEvt.IsLeft() ) + { + if (rView.IsDragObj()) + { + // object was dragged + rView.EndDragObj( rMEvt.IsMod1() ); + rView.ForceMarkedToAnotherPage(); + } + else if (rView.IsAction()) + { + rView.EndAction(); + } + } + + rWindow.SetPointer( rView.GetPreferredPointer( aPnt, rWindow.GetOutDev(), nHitLog ) ); + rWindow.ReleaseMouse(); + + return true; +} + +void DlgEdFuncSelect::MouseMove( const MouseEvent& rMEvt ) +{ + SdrView& rView = rParent.GetView(); + vcl::Window& rWindow = rParent.GetWindow(); + rView.SetActualWin(rWindow.GetOutDev()); + + Point aPnt = rWindow.PixelToLogic(rMEvt.GetPosPixel()); + sal_uInt16 nHitLog = static_cast<sal_uInt16>(rWindow.PixelToLogic(Size(3, 0)).Width()); + + if ( rView.IsAction() ) + { + Point aPix = rMEvt.GetPosPixel(); + Point aPnt_ = rWindow.PixelToLogic(aPix); + + ForceScroll(aPnt_); + rView.MovAction(aPnt_); + } + + rWindow.SetPointer( rView.GetPreferredPointer( aPnt, rWindow.GetOutDev(), nHitLog ) ); +} + +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/dlged/dlgedlist.cxx b/basctl/source/dlged/dlgedlist.cxx new file mode 100644 index 000000000..6b9cebfe8 --- /dev/null +++ b/basctl/source/dlged/dlgedlist.cxx @@ -0,0 +1,80 @@ +/* -*- 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 <dlgedlist.hxx> +#include <dlgedobj.hxx> + +namespace basctl +{ + +// DlgEdPropListenerImpl +DlgEdPropListenerImpl::DlgEdPropListenerImpl (DlgEdObj& rObj) : + rDlgEdObj(rObj) +{ +} + +DlgEdPropListenerImpl::~DlgEdPropListenerImpl() +{ +} + +// XEventListener +void SAL_CALL DlgEdPropListenerImpl::disposing( const css::lang::EventObject& ) +{ +} + +// XPropertyChangeListener +void SAL_CALL DlgEdPropListenerImpl::propertyChange( const css::beans::PropertyChangeEvent& evt ) +{ + rDlgEdObj._propertyChange( evt ); +} + +// DlgEdEvtContListenerImpl +DlgEdEvtContListenerImpl::DlgEdEvtContListenerImpl (DlgEdObj& rObj) : + rDlgEdObj(rObj) +{ +} + +DlgEdEvtContListenerImpl::~DlgEdEvtContListenerImpl() +{ +} + +// XEventListener +void SAL_CALL DlgEdEvtContListenerImpl::disposing( const css::lang::EventObject& ) +{ +} + +// XContainerListener +void SAL_CALL DlgEdEvtContListenerImpl::elementInserted(const css::container::ContainerEvent& /*Event*/) +{ + rDlgEdObj._elementInserted(); +} + +void SAL_CALL DlgEdEvtContListenerImpl::elementReplaced(const css::container::ContainerEvent& /*Event*/) +{ + rDlgEdObj._elementReplaced(); +} + +void SAL_CALL DlgEdEvtContListenerImpl::elementRemoved(const css::container::ContainerEvent& /*Event*/) +{ + rDlgEdObj._elementRemoved(); +} + +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/dlged/dlgedmod.cxx b/basctl/source/dlged/dlgedmod.cxx new file mode 100644 index 000000000..017e4b16c --- /dev/null +++ b/basctl/source/dlged/dlgedmod.cxx @@ -0,0 +1,36 @@ +/* -*- 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 <dlgedmod.hxx> +#include <dlgedpage.hxx> + +namespace basctl +{ +DlgEdModel::DlgEdModel() {} + +DlgEdModel::~DlgEdModel() {} + +rtl::Reference<SdrPage> DlgEdModel::AllocPage(bool bMasterPage) +{ + return new DlgEdPage(*this, bMasterPage); +} + +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/dlged/dlgedobj.cxx b/basctl/source/dlged/dlgedobj.cxx new file mode 100644 index 000000000..1d89210b7 --- /dev/null +++ b/basctl/source/dlged/dlgedobj.cxx @@ -0,0 +1,1703 @@ +/* -*- 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 <sal/config.h> +#include <sal/log.hxx> + +#include <cassert> + +#include <dlged.hxx> +#include <dlgeddef.hxx> +#include <dlgedlist.hxx> +#include <dlgedobj.hxx> +#include <dlgedpage.hxx> +#include <dlgedview.hxx> +#include <localizationmgr.hxx> +#include <strings.hxx> + +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/form/binding/XBindableValue.hpp> +#include <com/sun/star/form/binding/XValueBinding.hpp> +#include <com/sun/star/form/binding/XListEntrySink.hpp> +#include <com/sun/star/awt/XUnoControlContainer.hpp> +#include <com/sun/star/awt/XVclContainerPeer.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/script/XScriptEventsSupplier.hpp> +#include <com/sun/star/table/CellAddress.hpp> +#include <cppuhelper/exc_hlp.hxx> +#include <o3tl/functional.hxx> +#include <svx/svdpagv.hxx> +#include <unotools/sharedunocomponent.hxx> +#include <vcl/svapp.hxx> +#include <tools/debug.hxx> + +namespace basctl +{ + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::script; + + +DlgEditor& DlgEdObj::GetDialogEditor () +{ + if (DlgEdForm* pFormThis = dynamic_cast<DlgEdForm*>(this)) + return pFormThis->GetDlgEditor(); + else + return pDlgEdForm->GetDlgEditor(); +} + +DlgEdObj::DlgEdObj(SdrModel& rSdrModel) +: SdrUnoObj(rSdrModel, OUString()) + ,bIsListening(false) + ,pDlgEdForm( nullptr ) +{ +} + +DlgEdObj::DlgEdObj(SdrModel& rSdrModel, DlgEdObj const & rSource) +: SdrUnoObj(rSdrModel, rSource) + ,bIsListening(false) +{ + // set parent form + pDlgEdForm = rSource.pDlgEdForm; + + // add child to parent form + pDlgEdForm->AddChild( this ); + + Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY ); + if ( xPSet.is() ) + { + // set new name + OUString aOUniqueName( GetUniqueName() ); + Any aUniqueName; + aUniqueName <<= aOUniqueName; + xPSet->setPropertyValue( DLGED_PROP_NAME, aUniqueName ); + + Reference< container::XNameContainer > xCont( GetDlgEdForm()->GetUnoControlModel() , UNO_QUERY ); + if ( xCont.is() ) + { + // set tabindex + Sequence< OUString > aNames = xCont->getElementNames(); + xPSet->setPropertyValue( DLGED_PROP_TABINDEX, Any(static_cast<sal_Int16>(aNames.getLength())) ); + + // insert control model in dialog model + Reference< awt::XControlModel > xCtrl( xPSet , UNO_QUERY ); + xCont->insertByName( aOUniqueName, Any(xCtrl) ); + + pDlgEdForm->UpdateTabOrderAndGroups(); + } + } + + // start listening + StartListening(); +} + +DlgEdObj::DlgEdObj( + SdrModel& rSdrModel, + const OUString& rModelName, + const css::uno::Reference< css::lang::XMultiServiceFactory >& rxSFac) +: SdrUnoObj(rSdrModel, rModelName, rxSFac) + ,bIsListening(false) + ,pDlgEdForm( nullptr ) +{ +} + +DlgEdObj::~DlgEdObj() +{ + if ( isListening() ) + EndListening(true); +} + +namespace +{ + /* returns the DlgEdForm which the given DlgEdObj belongs to + (which might in fact be the object itself) + + Failure to obtain the form will be reported with an assertion in the non-product + version. + */ + bool lcl_getDlgEdForm( DlgEdObj* _pObject, DlgEdForm*& _out_pDlgEdForm ) + { + _out_pDlgEdForm = dynamic_cast< DlgEdForm* >( _pObject ); + if ( !_out_pDlgEdForm ) + _out_pDlgEdForm = _pObject->GetDlgEdForm(); + DBG_ASSERT( _out_pDlgEdForm, "lcl_getDlgEdForm: no form!" ); + return ( _out_pDlgEdForm != nullptr ); + } +} + +uno::Reference< awt::XControl > DlgEdObj::GetControl() const +{ + uno::Reference< awt::XControl > xControl; + if (DlgEdForm const* pForm = GetDlgEdForm()) + { + DlgEditor const& rEditor = pForm->GetDlgEditor(); + xControl = GetUnoControl(rEditor.GetView(), *rEditor.GetWindow().GetOutDev()); + } + return xControl; +} + +bool DlgEdObj::TransformSdrToControlCoordinates( + sal_Int32 nXIn, sal_Int32 nYIn, sal_Int32 nWidthIn, sal_Int32 nHeightIn, + sal_Int32& nXOut, sal_Int32& nYOut, sal_Int32& nWidthOut, sal_Int32& nHeightOut ) +{ + // input position and size + Size aPos( nXIn, nYIn ); + Size aSize( nWidthIn, nHeightIn ); + + // form position + DlgEdForm* pForm = nullptr; + if ( !lcl_getDlgEdForm( this, pForm ) ) + return false; + tools::Rectangle aFormRect = pForm->GetSnapRect(); + Size aFormPos( aFormRect.Left(), aFormRect.Top() ); + + // convert 100th_mm to pixel + OutputDevice* pDevice = Application::GetDefaultDevice(); + DBG_ASSERT( pDevice, "DlgEdObj::TransformSdrToControlCoordinates: missing default device!" ); + if ( !pDevice ) + return false; + aPos = pDevice->LogicToPixel( aPos, MapMode( MapUnit::Map100thMM ) ); + aSize = pDevice->LogicToPixel( aSize, MapMode( MapUnit::Map100thMM ) ); + aFormPos = pDevice->LogicToPixel( aFormPos, MapMode( MapUnit::Map100thMM ) ); + + // subtract form position + aPos.AdjustWidth( -(aFormPos.Width()) ); + aPos.AdjustHeight( -(aFormPos.Height()) ); + + // take window borders into account + Reference< beans::XPropertySet > xPSetForm( pForm->GetUnoControlModel(), UNO_QUERY ); + DBG_ASSERT( xPSetForm.is(), "DlgEdObj::TransformFormToSdrCoordinates: no form property set!" ); + if ( !xPSetForm.is() ) + return false; + bool bDecoration = true; + xPSetForm->getPropertyValue( DLGED_PROP_DECORATION ) >>= bDecoration; + if( bDecoration ) + { + awt::DeviceInfo aDeviceInfo = pForm->getDeviceInfo(); + aPos.AdjustWidth( -(aDeviceInfo.LeftInset) ); + aPos.AdjustHeight( -(aDeviceInfo.TopInset) ); + } + + // convert pixel to logic units + aPos = pDevice->PixelToLogic(aPos, MapMode(MapUnit::MapAppFont)); + aSize = pDevice->PixelToLogic(aSize, MapMode(MapUnit::MapAppFont)); + + // set out parameters + nXOut = aPos.Width(); + nYOut = aPos.Height(); + nWidthOut = aSize.Width(); + nHeightOut = aSize.Height(); + + return true; +} + +bool DlgEdObj::TransformSdrToFormCoordinates( + sal_Int32 nXIn, sal_Int32 nYIn, sal_Int32 nWidthIn, sal_Int32 nHeightIn, + sal_Int32& nXOut, sal_Int32& nYOut, sal_Int32& nWidthOut, sal_Int32& nHeightOut ) +{ + // input position and size + Size aPos( nXIn, nYIn ); + Size aSize( nWidthIn, nHeightIn ); + + // convert 100th_mm to pixel + OutputDevice* pDevice = Application::GetDefaultDevice(); + DBG_ASSERT( pDevice, "DlgEdObj::TransformSdrToFormCoordinates: missing default device!" ); + if ( !pDevice ) + return false; + aPos = pDevice->LogicToPixel( aPos, MapMode( MapUnit::Map100thMM ) ); + aSize = pDevice->LogicToPixel( aSize, MapMode( MapUnit::Map100thMM ) ); + + // take window borders into account + DlgEdForm* pForm = nullptr; + if ( !lcl_getDlgEdForm( this, pForm ) ) + return false; + + // take window borders into account + Reference< beans::XPropertySet > xPSetForm( pForm->GetUnoControlModel(), UNO_QUERY ); + DBG_ASSERT( xPSetForm.is(), "DlgEdObj::TransformFormToSdrCoordinates: no form property set!" ); + if ( !xPSetForm.is() ) + return false; + bool bDecoration = true; + xPSetForm->getPropertyValue( DLGED_PROP_DECORATION ) >>= bDecoration; + if( bDecoration ) + { + awt::DeviceInfo aDeviceInfo = pForm->getDeviceInfo(); + aSize.AdjustWidth( -(aDeviceInfo.LeftInset + aDeviceInfo.RightInset) ); + aSize.AdjustHeight( -(aDeviceInfo.TopInset + aDeviceInfo.BottomInset) ); + } + // convert pixel to logic units + aPos = pDevice->PixelToLogic(aPos, MapMode(MapUnit::MapAppFont)); + aSize = pDevice->PixelToLogic(aSize, MapMode(MapUnit::MapAppFont)); + + // set out parameters + nXOut = aPos.Width(); + nYOut = aPos.Height(); + nWidthOut = aSize.Width(); + nHeightOut = aSize.Height(); + + return true; +} + +bool DlgEdObj::TransformControlToSdrCoordinates( + sal_Int32 nXIn, sal_Int32 nYIn, sal_Int32 nWidthIn, sal_Int32 nHeightIn, + sal_Int32& nXOut, sal_Int32& nYOut, sal_Int32& nWidthOut, sal_Int32& nHeightOut ) +{ + // input position and size + Size aPos( nXIn, nYIn ); + Size aSize( nWidthIn, nHeightIn ); + + // form position + DlgEdForm* pForm = nullptr; + if ( !lcl_getDlgEdForm( this, pForm ) ) + return false; + + Reference< beans::XPropertySet > xPSetForm( pForm->GetUnoControlModel(), UNO_QUERY ); + DBG_ASSERT( xPSetForm.is(), "DlgEdObj::TransformControlToSdrCoordinates: no form property set!" ); + if ( !xPSetForm.is() ) + return false; + sal_Int32 nFormX = 0, nFormY = 0; + xPSetForm->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nFormX; + xPSetForm->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nFormY; + Size aFormPos( nFormX, nFormY ); + + // convert logic units to pixel + OutputDevice* pDevice = Application::GetDefaultDevice(); + DBG_ASSERT( pDevice, "DlgEdObj::TransformControlToSdrCoordinates: missing default device!" ); + if ( !pDevice ) + return false; + aPos = pDevice->LogicToPixel(aPos, MapMode(MapUnit::MapAppFont)); + aSize = pDevice->LogicToPixel(aSize, MapMode(MapUnit::MapAppFont)); + aFormPos = pDevice->LogicToPixel(aFormPos, MapMode(MapUnit::MapAppFont)); + + // add form position + aPos.AdjustWidth(aFormPos.Width() ); + aPos.AdjustHeight(aFormPos.Height() ); + + // take window borders into account + bool bDecoration = true; + xPSetForm->getPropertyValue( DLGED_PROP_DECORATION ) >>= bDecoration; + if( bDecoration ) + { + awt::DeviceInfo aDeviceInfo = pForm->getDeviceInfo(); + aPos.AdjustWidth(aDeviceInfo.LeftInset ); + aPos.AdjustHeight(aDeviceInfo.TopInset ); + } + + // convert pixel to 100th_mm + aPos = pDevice->PixelToLogic( aPos, MapMode( MapUnit::Map100thMM ) ); + aSize = pDevice->PixelToLogic( aSize, MapMode( MapUnit::Map100thMM ) ); + + // set out parameters + nXOut = aPos.Width(); + nYOut = aPos.Height(); + nWidthOut = aSize.Width(); + nHeightOut = aSize.Height(); + + return true; +} + +bool DlgEdObj::TransformFormToSdrCoordinates( + sal_Int32 nXIn, sal_Int32 nYIn, sal_Int32 nWidthIn, sal_Int32 nHeightIn, + sal_Int32& nXOut, sal_Int32& nYOut, sal_Int32& nWidthOut, sal_Int32& nHeightOut ) +{ + // input position and size + Size aPos( nXIn, nYIn ); + Size aSize( nWidthIn, nHeightIn ); + + // convert logic units to pixel + OutputDevice* pDevice = Application::GetDefaultDevice(); + DBG_ASSERT( pDevice, "DlgEdObj::TransformFormToSdrCoordinates: missing default device!" ); + if ( !pDevice ) + return false; + + // take window borders into account + DlgEdForm* pForm = nullptr; + if ( !lcl_getDlgEdForm( this, pForm ) ) + return false; + + aPos = pDevice->LogicToPixel(aPos, MapMode(MapUnit::MapAppFont)); + aSize = pDevice->LogicToPixel(aSize, MapMode(MapUnit::MapAppFont)); + + // take window borders into account + Reference< beans::XPropertySet > xPSetForm( pForm->GetUnoControlModel(), UNO_QUERY ); + DBG_ASSERT( xPSetForm.is(), "DlgEdObj::TransformFormToSdrCoordinates: no form property set!" ); + if ( !xPSetForm.is() ) + return false; + bool bDecoration = true; + xPSetForm->getPropertyValue( DLGED_PROP_DECORATION ) >>= bDecoration; + if( bDecoration ) + { + awt::DeviceInfo aDeviceInfo = pForm->getDeviceInfo(); + aSize.AdjustWidth(aDeviceInfo.LeftInset + aDeviceInfo.RightInset ); + aSize.AdjustHeight(aDeviceInfo.TopInset + aDeviceInfo.BottomInset ); + } + + // convert pixel to 100th_mm + aPos = pDevice->PixelToLogic( aPos, MapMode( MapUnit::Map100thMM ) ); + aSize = pDevice->PixelToLogic( aSize, MapMode( MapUnit::Map100thMM ) ); + + // set out parameters + nXOut = aPos.Width(); + nYOut = aPos.Height(); + nWidthOut = aSize.Width(); + nHeightOut = aSize.Height(); + + return true; +} + +void DlgEdObj::SetRectFromProps() +{ + // get control position and size from properties + Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY ); + if ( !xPSet.is() ) + return; + + sal_Int32 nXIn = 0, nYIn = 0, nWidthIn = 0, nHeightIn = 0; + xPSet->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nXIn; + xPSet->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nYIn; + xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nWidthIn; + xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nHeightIn; + + // transform coordinates + sal_Int32 nXOut, nYOut, nWidthOut, nHeightOut; + if ( TransformControlToSdrCoordinates( nXIn, nYIn, nWidthIn, nHeightIn, nXOut, nYOut, nWidthOut, nHeightOut ) ) + { + // set rectangle position and size + Point aPoint( nXOut, nYOut ); + Size aSize( nWidthOut, nHeightOut ); + SetSnapRect( tools::Rectangle( aPoint, aSize ) ); + } +} + +void DlgEdObj::SetPropsFromRect() +{ + // get control position and size from rectangle + tools::Rectangle aRect_ = GetSnapRect(); + sal_Int32 nXIn = aRect_.Left(); + sal_Int32 nYIn = aRect_.Top(); + sal_Int32 nWidthIn = aRect_.GetWidth(); + sal_Int32 nHeightIn = aRect_.GetHeight(); + + // transform coordinates + sal_Int32 nXOut, nYOut, nWidthOut, nHeightOut; + if ( TransformSdrToControlCoordinates( nXIn, nYIn, nWidthIn, nHeightIn, nXOut, nYOut, nWidthOut, nHeightOut ) ) + { + // set properties + Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY ); + if ( xPSet.is() ) + { + xPSet->setPropertyValue( DLGED_PROP_POSITIONX, Any(nXOut) ); + xPSet->setPropertyValue( DLGED_PROP_POSITIONY, Any(nYOut) ); + xPSet->setPropertyValue( DLGED_PROP_WIDTH, Any(nWidthOut) ); + xPSet->setPropertyValue( DLGED_PROP_HEIGHT, Any(nHeightOut) ); + } + } +} + +void DlgEdObj::PositionAndSizeChange( const beans::PropertyChangeEvent& evt ) +{ + DBG_ASSERT( pDlgEdForm, "DlgEdObj::PositionAndSizeChange: no form!" ); + DlgEdPage& rPage = pDlgEdForm->GetDlgEditor().GetPage(); + { + Size aPageSize = rPage.GetSize(); + sal_Int32 nPageWidthIn = aPageSize.Width(); + sal_Int32 nPageHeightIn = aPageSize.Height(); + sal_Int32 nPageX, nPageY, nPageWidth, nPageHeight; + if ( TransformSdrToControlCoordinates( 0/*nPageXIn*/, 0/*nPageYIn*/, nPageWidthIn, nPageHeightIn, nPageX, nPageY, nPageWidth, nPageHeight ) ) + { + Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY ); + if ( xPSet.is() ) + { + sal_Int32 nX = 0, nY = 0, nWidth = 0, nHeight = 0; + xPSet->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nX; + xPSet->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nY; + xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nWidth; + xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nHeight; + + sal_Int32 nValue = 0; + evt.NewValue >>= nValue; + sal_Int32 nNewValue = nValue; + + if ( evt.PropertyName == DLGED_PROP_POSITIONX ) + { + if ( nNewValue + nWidth > nPageX + nPageWidth ) + nNewValue = nPageX + nPageWidth - nWidth; + if ( nNewValue < nPageX ) + nNewValue = nPageX; + } + else if ( evt.PropertyName == DLGED_PROP_POSITIONY ) + { + if ( nNewValue + nHeight > nPageY + nPageHeight ) + nNewValue = nPageY + nPageHeight - nHeight; + if ( nNewValue < nPageY ) + nNewValue = nPageY; + } + else if ( evt.PropertyName == DLGED_PROP_WIDTH ) + { + if ( nX + nNewValue > nPageX + nPageWidth ) + nNewValue = nPageX + nPageWidth - nX; + if ( nNewValue < 1 ) + nNewValue = 1; + } + else if ( evt.PropertyName == DLGED_PROP_HEIGHT ) + { + if ( nY + nNewValue > nPageY + nPageHeight ) + nNewValue = nPageY + nPageHeight - nY; + if ( nNewValue < 1 ) + nNewValue = 1; + } + + if ( nNewValue != nValue ) + { + EndListening( false ); + xPSet->setPropertyValue( evt.PropertyName, Any(nNewValue) ); + StartListening(); + } + } + } + } + + SetRectFromProps(); +} + +void DlgEdObj::NameChange( const css::beans::PropertyChangeEvent& evt ) +{ + // get old name + OUString aOldName; + evt.OldValue >>= aOldName; + + // get new name + OUString aNewName; + evt.NewValue >>= aNewName; + + if ( aNewName == aOldName ) + return; + + Reference< container::XNameAccess > xNameAcc((GetDlgEdForm()->GetUnoControlModel()), UNO_QUERY); + if ( !(xNameAcc.is() && xNameAcc->hasByName(aOldName)) ) + return; + + if (!xNameAcc->hasByName(aNewName) && !aNewName.isEmpty()) + { + // remove the control by the old name and insert the control by the new name in the container + Reference< container::XNameContainer > xCont(xNameAcc, UNO_QUERY ); + if ( xCont.is() ) + { + Reference< awt::XControlModel > xCtrl = GetUnoControlModel(); + Any aAny; + aAny <<= xCtrl; + xCont->removeByName( aOldName ); + xCont->insertByName( aNewName , aAny ); + + LocalizationMgr::renameControlResourceIDsForEditorObject( + &GetDialogEditor(), aAny, aNewName + ); + } + } + else + { + // set old name property + EndListening(false); + Reference< beans::XPropertySet > xPSet(GetUnoControlModel(), UNO_QUERY); + xPSet->setPropertyValue( DLGED_PROP_NAME, Any(aOldName) ); + StartListening(); + } +} + +sal_Int32 DlgEdObj::GetStep() const +{ + // get step property + sal_Int32 nStep = 0; + uno::Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), uno::UNO_QUERY ); + if (xPSet.is()) + { + xPSet->getPropertyValue( DLGED_PROP_STEP ) >>= nStep; + } + return nStep; +} + +void DlgEdObj::UpdateStep() +{ + sal_Int32 nCurStep = GetDlgEdForm()->GetStep(); + sal_Int32 nStep = GetStep(); + + SdrLayerAdmin& rLayerAdmin(getSdrModelFromSdrObject().GetLayerAdmin()); + SdrLayerID nHiddenLayerId = rLayerAdmin.GetLayerID( "HiddenLayer" ); + SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID( rLayerAdmin.GetControlLayerName() ); + + if( nCurStep ) + { + if ( nStep && (nStep != nCurStep) ) + { + SetLayer( nHiddenLayerId ); + } + else + { + SetLayer( nControlLayerId ); + } + } + else + { + SetLayer( nControlLayerId ); + } +} + +void DlgEdObj::TabIndexChange( const beans::PropertyChangeEvent& evt ) +{ + DlgEdForm* pForm = GetDlgEdForm(); + if ( !pForm ) + return; + + // stop listening with all children + std::vector<DlgEdObj*> aChildList = pForm->GetChildren(); + for (auto const& child : aChildList) + { + child->EndListening( false ); + } + + Reference< container::XNameAccess > xNameAcc( pForm->GetUnoControlModel() , UNO_QUERY ); + if ( xNameAcc.is() ) + { + // get sequence of control names + Sequence< OUString > aNames = xNameAcc->getElementNames(); + const OUString* pNames = aNames.getConstArray(); + sal_Int32 nCtrls = aNames.getLength(); + + // create a map of tab indices and control names, sorted by tab index + IndexToNameMap aIndexToNameMap; + for ( sal_Int32 i = 0; i < nCtrls; ++i ) + { + // get control name + OUString aName( pNames[i] ); + + // get tab index + sal_Int16 nTabIndex = -1; + Any aCtrl = xNameAcc->getByName( aName ); + Reference< beans::XPropertySet > xPSet; + aCtrl >>= xPSet; + if ( xPSet.is() && xPSet == Reference< beans::XPropertySet >( evt.Source, UNO_QUERY ) ) + evt.OldValue >>= nTabIndex; + else if ( xPSet.is() ) + xPSet->getPropertyValue( DLGED_PROP_TABINDEX ) >>= nTabIndex; + + // insert into map + aIndexToNameMap.emplace( nTabIndex, aName ); + } + + // create a helper list of control names, sorted by tab index + std::vector< OUString > aNameList( aIndexToNameMap.size() ); + std::transform( + aIndexToNameMap.begin(), aIndexToNameMap.end(), + aNameList.begin(), + ::o3tl::select2nd< IndexToNameMap::value_type >( ) + ); + + // check tab index + sal_Int16 nOldTabIndex = 0; + evt.OldValue >>= nOldTabIndex; + sal_Int16 nNewTabIndex = 0; + evt.NewValue >>= nNewTabIndex; + if ( nNewTabIndex < 0 ) + nNewTabIndex = 0; + else if ( nNewTabIndex > nCtrls - 1 ) + nNewTabIndex = sal::static_int_cast<sal_Int16>( nCtrls - 1 ); + + // reorder helper list + OUString aCtrlName = aNameList[nOldTabIndex]; + aNameList.erase( aNameList.begin() + nOldTabIndex ); + aNameList.insert( aNameList.begin() + nNewTabIndex , aCtrlName ); + + // set new tab indices + for ( sal_Int32 i = 0; i < nCtrls; ++i ) + { + Any aCtrl = xNameAcc->getByName( aNameList[i] ); + Reference< beans::XPropertySet > xPSet; + aCtrl >>= xPSet; + if ( xPSet.is() ) + { + assert(i >= SAL_MIN_INT16); + if (i > SAL_MAX_INT16) + { + SAL_WARN("basctl", "tab " << i << " > SAL_MAX_INT16"); + continue; + } + xPSet->setPropertyValue( DLGED_PROP_TABINDEX, Any(static_cast<sal_Int16>(i)) ); + } + } + + // reorder objects in drawing page + getSdrModelFromSdrObject().GetPage(0)->SetObjectOrdNum( nOldTabIndex + 1, nNewTabIndex + 1 ); + + pForm->UpdateTabOrderAndGroups(); + } + + // start listening with all children + for (auto const& child : aChildList) + { + child->StartListening(); + } +} + +bool DlgEdObj::supportsService( OUString const & serviceName ) const +{ + bool bSupports = false; + + Reference< lang::XServiceInfo > xServiceInfo( GetUnoControlModel() , UNO_QUERY ); + // TODO: cache xServiceInfo as member? + if ( xServiceInfo.is() ) + bSupports = xServiceInfo->supportsService( serviceName ); + + return bSupports; +} + +OUString DlgEdObj::GetDefaultName() const +{ + OUString sResId; + OUString aDefaultName; + if ( supportsService( "com.sun.star.awt.UnoControlDialogModel" ) ) + { + sResId = RID_STR_CLASS_DIALOG; + } + else if ( supportsService( "com.sun.star.awt.UnoControlButtonModel" ) ) + { + sResId = RID_STR_CLASS_BUTTON; + } + else if ( supportsService( "com.sun.star.awt.UnoControlRadioButtonModel" ) ) + { + sResId = RID_STR_CLASS_RADIOBUTTON; + } + else if ( supportsService( "com.sun.star.awt.UnoControlCheckBoxModel" ) ) + { + sResId = RID_STR_CLASS_CHECKBOX; + } + else if ( supportsService( "com.sun.star.awt.UnoControlListBoxModel" ) ) + { + sResId = RID_STR_CLASS_LISTBOX; + } + else if ( supportsService( "com.sun.star.awt.UnoControlComboBoxModel" ) ) + { + sResId = RID_STR_CLASS_COMBOBOX; + } + else if ( supportsService( "com.sun.star.awt.UnoControlGroupBoxModel" ) ) + { + sResId = RID_STR_CLASS_GROUPBOX; + } + else if ( supportsService( "com.sun.star.awt.UnoControlEditModel" ) ) + { + sResId = RID_STR_CLASS_EDIT; + } + else if ( supportsService( "com.sun.star.awt.UnoControlFixedTextModel" ) ) + { + sResId = RID_STR_CLASS_FIXEDTEXT; + } + else if ( supportsService( "com.sun.star.awt.UnoControlImageControlModel" ) ) + { + sResId = RID_STR_CLASS_IMAGECONTROL; + } + else if ( supportsService( "com.sun.star.awt.UnoControlProgressBarModel" ) ) + { + sResId = RID_STR_CLASS_PROGRESSBAR; + } + else if ( supportsService( "com.sun.star.awt.UnoControlScrollBarModel" ) ) + { + sResId = RID_STR_CLASS_SCROLLBAR; + } + else if ( supportsService( "com.sun.star.awt.UnoControlFixedLineModel" ) ) + { + sResId = RID_STR_CLASS_FIXEDLINE; + } + else if ( supportsService( "com.sun.star.awt.UnoControlDateFieldModel" ) ) + { + sResId = RID_STR_CLASS_DATEFIELD; + } + else if ( supportsService( "com.sun.star.awt.UnoControlTimeFieldModel" ) ) + { + sResId = RID_STR_CLASS_TIMEFIELD; + } + else if ( supportsService( "com.sun.star.awt.UnoControlNumericFieldModel" ) ) + { + sResId = RID_STR_CLASS_NUMERICFIELD; + } + else if ( supportsService( "com.sun.star.awt.UnoControlCurrencyFieldModel" ) ) + { + sResId = RID_STR_CLASS_CURRENCYFIELD; + } + else if ( supportsService( "com.sun.star.awt.UnoControlFormattedFieldModel" ) ) + { + sResId = RID_STR_CLASS_FORMATTEDFIELD; + } + else if ( supportsService( "com.sun.star.awt.UnoControlPatternFieldModel" ) ) + { + sResId = RID_STR_CLASS_PATTERNFIELD; + } + else if ( supportsService( "com.sun.star.awt.UnoControlFileControlModel" ) ) + { + sResId = RID_STR_CLASS_FILECONTROL; + } + else if ( supportsService( "com.sun.star.awt.tree.TreeControlModel" ) ) + { + sResId = RID_STR_CLASS_TREECONTROL; + } + else if ( supportsService( "com.sun.star.awt.grid.UnoControlGridModel" ) ) + { + sResId = RID_STR_CLASS_GRIDCONTROL; + } + else if ( supportsService( "com.sun.star.awt.UnoControlFixedHyperlinkModel" ) ) + { + sResId = RID_STR_CLASS_HYPERLINKCONTROL; + } + else if ( supportsService( "com.sun.star.awt.UnoControlSpinButtonModel" ) ) + { + sResId = RID_STR_CLASS_SPINCONTROL; + } + else + { + sResId = RID_STR_CLASS_CONTROL; + } + + if (!sResId.isEmpty()) + aDefaultName = sResId; + + return aDefaultName; +} + +OUString DlgEdObj::GetUniqueName() const +{ + OUString aUniqueName; + uno::Reference< container::XNameAccess > xNameAcc((GetDlgEdForm()->GetUnoControlModel()), uno::UNO_QUERY); + + if ( xNameAcc.is() ) + { + sal_Int32 n = 0; + OUString aDefaultName = GetDefaultName(); + + do + { + aUniqueName = aDefaultName + OUString::number(++n); + } while (xNameAcc->hasByName(aUniqueName)); + } + + return aUniqueName; +} + +SdrInventor DlgEdObj::GetObjInventor() const +{ + return SdrInventor::BasicDialog; +} + +SdrObjKind DlgEdObj::GetObjIdentifier() const +{ + if ( supportsService( "com.sun.star.awt.UnoControlDialogModel" )) + { + return SdrObjKind::BasicDialogDialog; + } + else if ( supportsService( "com.sun.star.awt.UnoControlButtonModel" )) + { + return SdrObjKind::BasicDialogPushButton; + } + else if ( supportsService( "com.sun.star.awt.UnoControlRadioButtonModel" )) + { + return SdrObjKind::BasicDialogRadioButton; + } + else if ( supportsService( "com.sun.star.awt.UnoControlCheckBoxModel" )) + { + return SdrObjKind::BasicDialogCheckbox; + } + else if ( supportsService( "com.sun.star.awt.UnoControlListBoxModel" )) + { + return SdrObjKind::BasicDialogListbox; + } + else if ( supportsService( "com.sun.star.awt.UnoControlComboBoxModel" )) + { + return SdrObjKind::BasicDialogCombobox; + } + else if ( supportsService( "com.sun.star.awt.UnoControlGroupBoxModel" )) + { + return SdrObjKind::BasicDialogGroupBox; + } + else if ( supportsService( "com.sun.star.awt.UnoControlEditModel" )) + { + return SdrObjKind::BasicDialogEdit; + } + else if ( supportsService( "com.sun.star.awt.UnoControlFixedTextModel" )) + { + return SdrObjKind::BasicDialogFixedText; + } + else if ( supportsService( "com.sun.star.awt.UnoControlImageControlModel" )) + { + return SdrObjKind::BasicDialogImageControl; + } + else if ( supportsService( "com.sun.star.awt.UnoControlProgressBarModel" )) + { + return SdrObjKind::BasicDialogProgressbar; + } + else if ( supportsService( "com.sun.star.awt.UnoControlScrollBarModel" )) + { + return SdrObjKind::BasicDialogHorizontalScrollbar; + } + else if ( supportsService( "com.sun.star.awt.UnoControlFixedLineModel" )) + { + return SdrObjKind::BasicDialogHorizontalFixedLine; + } + else if ( supportsService( "com.sun.star.awt.UnoControlDateFieldModel" )) + { + return SdrObjKind::BasicDialogDateField; + } + else if ( supportsService( "com.sun.star.awt.UnoControlTimeFieldModel" )) + { + return SdrObjKind::BasicDialogTimeField; + } + else if ( supportsService( "com.sun.star.awt.UnoControlNumericFieldModel" )) + { + return SdrObjKind::BasicDialogNumericField; + } + else if ( supportsService( "com.sun.star.awt.UnoControlCurrencyFieldModel" )) + { + return SdrObjKind::BasicDialogCurencyField; + } + else if ( supportsService( "com.sun.star.awt.UnoControlFormattedFieldModel" )) + { + return SdrObjKind::BasicDialogFormattedField; + } + else if ( supportsService( "com.sun.star.awt.UnoControlPatternFieldModel" )) + { + return SdrObjKind::BasicDialogPatternField; + } + else if ( supportsService( "com.sun.star.awt.UnoControlFileControlModel" )) + { + return SdrObjKind::BasicDialogFileControl; + } + else if ( supportsService( "com.sun.star.awt.tree.TreeControlModel" )) + { + return SdrObjKind::BasicDialogTreeControl; + } + else if ( supportsService( "com.sun.star.awt.grid.UnoControlGridModel" )) + { + return SdrObjKind::BasicDialogGridControl; + } + else if ( supportsService( "com.sun.star.awt.UnoControlFixedHyperlinkModel" )) + { + return SdrObjKind::BasicDialogHyperlinkControl; + } + else + { + return SdrObjKind::BasicDialogControl; + } +} + +DlgEdObj* DlgEdObj::CloneSdrObject(SdrModel& rTargetModel) const +{ + return new DlgEdObj(rTargetModel, *this); +} + +SdrObjectUniquePtr DlgEdObj::getFullDragClone() const +{ + // no need to really add the clone for dragging, it's a temporary + // object + return SdrObjectUniquePtr(new SdrUnoObj(getSdrModelFromSdrObject(), *this)); +} + +void DlgEdObj::NbcMove( const Size& rSize ) +{ + SdrUnoObj::NbcMove( rSize ); + + // stop listening + EndListening(false); + + // set geometry properties + SetPropsFromRect(); + + // start listening + StartListening(); + + // dialog model changed + GetDlgEdForm()->GetDlgEditor().SetDialogModelChanged(); +} + +void DlgEdObj::NbcResize(const Point& rRef, const Fraction& xFract, const Fraction& yFract) +{ + SdrUnoObj::NbcResize( rRef, xFract, yFract ); + + // stop listening + EndListening(false); + + // set geometry properties + SetPropsFromRect(); + + // start listening + StartListening(); + + // dialog model changed + GetDlgEdForm()->GetDlgEditor().SetDialogModelChanged(); +} + +bool DlgEdObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) +{ + bool bResult = SdrUnoObj::EndCreate(rStat, eCmd); + + // tdf#120674 after interactive creation, the SdrObject (this) has no SdrPage yet + // due to not being inserted. Usually this should be handled in a ::handlePageChange + // implementation. For historical reasons, the SdrPage (which is the DlgEdPage) was + // already set. For now, get it from the SdrDragStat and use it to access and set + // the local pDlgEdForm + if(nullptr == pDlgEdForm && nullptr != rStat.GetPageView()) + { + const DlgEdPage* pDlgEdPage(dynamic_cast<const DlgEdPage*>(rStat.GetPageView()->GetPage())); + + if(nullptr != pDlgEdPage) + { + // set parent form + pDlgEdForm = pDlgEdPage->GetDlgEdForm(); + } + } + + SetDefaults(); + StartListening(); + + return bResult; +} + +void DlgEdObj::SetDefaults() +{ + if ( !pDlgEdForm ) + return; + + // add child to parent form + pDlgEdForm->AddChild( this ); + + Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY ); + if ( xPSet.is() ) + { + // get unique name + OUString aOUniqueName( GetUniqueName() ); + + // set name property + xPSet->setPropertyValue( DLGED_PROP_NAME, Any(aOUniqueName) ); + + // set labels + if ( supportsService( "com.sun.star.awt.UnoControlButtonModel" ) || + supportsService( "com.sun.star.awt.UnoControlRadioButtonModel" ) || + supportsService( "com.sun.star.awt.UnoControlCheckBoxModel" ) || + supportsService( "com.sun.star.awt.UnoControlGroupBoxModel" ) || + supportsService( "com.sun.star.awt.UnoControlFixedTextModel" ) ) + { + xPSet->setPropertyValue( DLGED_PROP_LABEL, Any(aOUniqueName) ); + } + + // set number formats supplier for formatted field + if ( supportsService( "com.sun.star.awt.UnoControlFormattedFieldModel" ) ) + { + Reference< util::XNumberFormatsSupplier > xSupplier = GetDlgEdForm()->GetDlgEditor().GetNumberFormatsSupplier(); + if ( xSupplier.is() ) + { + xPSet->setPropertyValue( DLGED_PROP_FORMATSSUPPLIER, Any(xSupplier) ); + } + } + + // set geometry properties + SetPropsFromRect(); + + Reference< container::XNameContainer > xCont( GetDlgEdForm()->GetUnoControlModel() , UNO_QUERY ); + if ( xCont.is() ) + { + // set tabindex + Sequence< OUString > aNames = xCont->getElementNames(); + uno::Any aTabIndex; + aTabIndex <<= static_cast<sal_Int16>(aNames.getLength()); + xPSet->setPropertyValue( DLGED_PROP_TABINDEX, aTabIndex ); + + // set step + Reference< beans::XPropertySet > xPSetForm( xCont, UNO_QUERY ); + if ( xPSetForm.is() ) + { + Any aStep = xPSetForm->getPropertyValue( DLGED_PROP_STEP ); + xPSet->setPropertyValue( DLGED_PROP_STEP, aStep ); + } + + // insert control model in dialog model + Reference< awt::XControlModel > xCtrl( xPSet , UNO_QUERY ); + Any aAny; + aAny <<= xCtrl; + xCont->insertByName( aOUniqueName , aAny ); + + LocalizationMgr::setControlResourceIDsForNewEditorObject( + &GetDialogEditor(), aAny, aOUniqueName + ); + + pDlgEdForm->UpdateTabOrderAndGroups(); + } + } + + // dialog model changed + pDlgEdForm->GetDlgEditor().SetDialogModelChanged(); +} + +void DlgEdObj::StartListening() +{ + DBG_ASSERT(!isListening(), "DlgEdObj::StartListening: already listening!"); + + if (isListening()) + return; + + bIsListening = true; + + // XPropertyChangeListener + Reference< XPropertySet > xControlModel( GetUnoControlModel() , UNO_QUERY ); + if (!m_xPropertyChangeListener.is() && xControlModel.is()) + { + // create listener + m_xPropertyChangeListener = new DlgEdPropListenerImpl(*this); + + // register listener to properties + xControlModel->addPropertyChangeListener( OUString() , m_xPropertyChangeListener ); + } + + // XContainerListener + Reference< XScriptEventsSupplier > xEventsSupplier( GetUnoControlModel() , UNO_QUERY ); + if( !m_xContainerListener.is() && xEventsSupplier.is() ) + { + // create listener + m_xContainerListener = new DlgEdEvtContListenerImpl(*this); + + // register listener to script event container + Reference< XNameContainer > xEventCont = xEventsSupplier->getEvents(); + DBG_ASSERT(xEventCont.is(), "DlgEdObj::StartListening: control model has no script event container!"); + Reference< XContainer > xCont( xEventCont , UNO_QUERY ); + if (xCont.is()) + xCont->addContainerListener( m_xContainerListener ); + } +} + +void DlgEdObj::EndListening(bool bRemoveListener) +{ + DBG_ASSERT(isListening(), "DlgEdObj::EndListening: not listening currently!"); + + if (!isListening()) + return; + + bIsListening = false; + + if (!bRemoveListener) + return; + + // XPropertyChangeListener + Reference< XPropertySet > xControlModel(GetUnoControlModel(), UNO_QUERY); + if ( m_xPropertyChangeListener.is() && xControlModel.is() ) + { + // remove listener + xControlModel->removePropertyChangeListener( OUString() , m_xPropertyChangeListener ); + } + m_xPropertyChangeListener.clear(); + + // XContainerListener + Reference< XScriptEventsSupplier > xEventsSupplier( GetUnoControlModel() , UNO_QUERY ); + if( m_xContainerListener.is() && xEventsSupplier.is() ) + { + // remove listener + Reference< XNameContainer > xEventCont = xEventsSupplier->getEvents(); + DBG_ASSERT(xEventCont.is(), "DlgEdObj::EndListening: control model has no script event container!"); + Reference< XContainer > xCont( xEventCont , UNO_QUERY ); + if (xCont.is()) + xCont->removeContainerListener( m_xContainerListener ); + } + m_xContainerListener.clear(); +} + +void DlgEdObj::_propertyChange( const css::beans::PropertyChangeEvent& evt ) +{ + if (!isListening()) + return; + + DlgEdForm* pRealDlgEdForm = dynamic_cast<DlgEdForm*>(this); + if (!pRealDlgEdForm) + pRealDlgEdForm = GetDlgEdForm(); + if (!pRealDlgEdForm) + return; + DlgEditor& rDlgEditor = pRealDlgEdForm->GetDlgEditor(); + if (rDlgEditor.isInPaint()) + return; + + // dialog model changed + rDlgEditor.SetDialogModelChanged(); + + // update position and size + if ( evt.PropertyName == DLGED_PROP_POSITIONX || evt.PropertyName == DLGED_PROP_POSITIONY || + evt.PropertyName == DLGED_PROP_WIDTH || evt.PropertyName == DLGED_PROP_HEIGHT || + evt.PropertyName == DLGED_PROP_DECORATION ) + { + PositionAndSizeChange( evt ); + + if ( evt.PropertyName == DLGED_PROP_DECORATION ) + GetDialogEditor().ResetDialog(); + } + // change name of control in dialog model + else if ( evt.PropertyName == DLGED_PROP_NAME ) + { + if (!dynamic_cast<DlgEdForm*>(this)) + { + try + { + NameChange(evt); + } + catch (container::NoSuchElementException const&) + { + css::uno::Any anyEx = cppu::getCaughtException(); + throw lang::WrappedTargetRuntimeException("", nullptr, + anyEx); + } + } + } + // update step + else if ( evt.PropertyName == DLGED_PROP_STEP ) + { + UpdateStep(); + } + // change tabindex + else if ( evt.PropertyName == DLGED_PROP_TABINDEX ) + { + if (!dynamic_cast<DlgEdForm*>(this)) + TabIndexChange(evt); + } +} + +void DlgEdObj::_elementInserted() +{ + if (isListening()) + { + // dialog model changed + GetDialogEditor().SetDialogModelChanged(); + } +} + +void DlgEdObj::_elementReplaced() +{ + if (isListening()) + { + // dialog model changed + GetDialogEditor().SetDialogModelChanged(); + } +} + +void DlgEdObj::_elementRemoved() +{ + if (isListening()) + { + // dialog model changed + GetDialogEditor().SetDialogModelChanged(); + } +} + +void DlgEdObj::SetLayer(SdrLayerID nLayer) +{ + SdrLayerID nOldLayer = GetLayer(); + + if ( nLayer != nOldLayer ) + { + SdrUnoObj::SetLayer( nLayer ); + + DlgEdHint aHint( DlgEdHint::LAYERCHANGED, this ); + GetDlgEdForm()->GetDlgEditor().Broadcast( aHint ); + } +} + +DlgEdForm::DlgEdForm( + SdrModel& rSdrModel, + DlgEditor& rDlgEditor_) +: DlgEdObj(rSdrModel), + rDlgEditor(rDlgEditor_) +{ +} + +DlgEdForm::~DlgEdForm() +{ +} + +void DlgEdForm::SetRectFromProps() +{ + // get form position and size from properties + Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY ); + if ( !xPSet.is() ) + return; + + sal_Int32 nXIn = 0, nYIn = 0, nWidthIn = 0, nHeightIn = 0; + xPSet->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nXIn; + xPSet->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nYIn; + xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nWidthIn; + xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nHeightIn; + + // transform coordinates + sal_Int32 nXOut, nYOut, nWidthOut, nHeightOut; + if ( TransformFormToSdrCoordinates( nXIn, nYIn, nWidthIn, nHeightIn, nXOut, nYOut, nWidthOut, nHeightOut ) ) + { + // set rectangle position and size + Point aPoint( nXOut, nYOut ); + Size aSize( nWidthOut, nHeightOut ); + SetSnapRect( tools::Rectangle( aPoint, aSize ) ); + } +} + +void DlgEdForm::SetPropsFromRect() +{ + // get form position and size from rectangle + tools::Rectangle aRect_ = GetSnapRect(); + sal_Int32 nXIn = aRect_.Left(); + sal_Int32 nYIn = aRect_.Top(); + sal_Int32 nWidthIn = aRect_.GetWidth(); + sal_Int32 nHeightIn = aRect_.GetHeight(); + + // transform coordinates + sal_Int32 nXOut, nYOut, nWidthOut, nHeightOut; + if ( TransformSdrToFormCoordinates( nXIn, nYIn, nWidthIn, nHeightIn, nXOut, nYOut, nWidthOut, nHeightOut ) ) + { + // set properties + Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY ); + if ( xPSet.is() ) + { + xPSet->setPropertyValue( DLGED_PROP_POSITIONX, Any(nXOut) ); + xPSet->setPropertyValue( DLGED_PROP_POSITIONY, Any(nYOut) ); + xPSet->setPropertyValue( DLGED_PROP_WIDTH, Any(nWidthOut) ); + xPSet->setPropertyValue( DLGED_PROP_HEIGHT, Any(nHeightOut) ); + } + } +} + +void DlgEdForm::AddChild( DlgEdObj* pDlgEdObj ) +{ + pChildren.push_back( pDlgEdObj ); +} + +void DlgEdForm::RemoveChild( DlgEdObj* pDlgEdObj ) +{ + pChildren.erase( std::remove( pChildren.begin() , pChildren.end() , pDlgEdObj ) ); +} + +void DlgEdForm::PositionAndSizeChange( const beans::PropertyChangeEvent& evt ) +{ + DlgEditor& rEditor = GetDlgEditor(); + DlgEdPage& rPage = rEditor.GetPage(); + + sal_Int32 nPageXIn = 0; + sal_Int32 nPageYIn = 0; + Size aPageSize = rPage.GetSize(); + sal_Int32 nPageWidthIn = aPageSize.Width(); + sal_Int32 nPageHeightIn = aPageSize.Height(); + sal_Int32 nPageX, nPageY, nPageWidth, nPageHeight; + if ( TransformSdrToFormCoordinates( nPageXIn, nPageYIn, nPageWidthIn, nPageHeightIn, nPageX, nPageY, nPageWidth, nPageHeight ) ) + { + Reference< beans::XPropertySet > xPSetForm( GetUnoControlModel(), UNO_QUERY ); + if ( xPSetForm.is() ) + { + sal_Int32 nValue = 0; + evt.NewValue >>= nValue; + sal_Int32 nNewValue = nValue; + + if ( evt.PropertyName == DLGED_PROP_POSITIONX ) + { + if ( nNewValue < nPageX ) + nNewValue = nPageX; + } + else if ( evt.PropertyName == DLGED_PROP_POSITIONY ) + { + if ( nNewValue < nPageY ) + nNewValue = nPageY; + } + else if ( evt.PropertyName == DLGED_PROP_WIDTH ) + { + if ( nNewValue < 1 ) + nNewValue = 1; + } + else if ( evt.PropertyName == DLGED_PROP_HEIGHT ) + { + if ( nNewValue < 1 ) + nNewValue = 1; + } + + if ( nNewValue != nValue ) + { + EndListening( false ); + xPSetForm->setPropertyValue( evt.PropertyName, Any(nNewValue) ); + StartListening(); + } + } + } + + bool bAdjustedPageSize = rEditor.AdjustPageSize(); + SetRectFromProps(); + std::vector<DlgEdObj*> const& aChildList = GetChildren(); + + if ( bAdjustedPageSize ) + { + rEditor.InitScrollBars(); + aPageSize = rPage.GetSize(); + nPageWidthIn = aPageSize.Width(); + nPageHeightIn = aPageSize.Height(); + if ( TransformSdrToControlCoordinates( nPageXIn, nPageYIn, nPageWidthIn, nPageHeightIn, nPageX, nPageY, nPageWidth, nPageHeight ) ) + { + for (auto const& child : aChildList) + { + Reference< beans::XPropertySet > xPSet( child->GetUnoControlModel(), UNO_QUERY ); + if ( xPSet.is() ) + { + sal_Int32 nX = 0, nY = 0, nWidth = 0, nHeight = 0; + xPSet->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nX; + xPSet->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nY; + xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nWidth; + xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nHeight; + + sal_Int32 nNewX = nX; + if ( nX + nWidth > nPageX + nPageWidth ) + { + nNewX = nPageX + nPageWidth - nWidth; + if ( nNewX < nPageX ) + nNewX = nPageX; + } + if ( nNewX != nX ) + { + EndListening( false ); + xPSet->setPropertyValue( DLGED_PROP_POSITIONX, Any(nNewX) ); + StartListening(); + } + + sal_Int32 nNewY = nY; + if ( nY + nHeight > nPageY + nPageHeight ) + { + nNewY = nPageY + nPageHeight - nHeight; + if ( nNewY < nPageY ) + nNewY = nPageY; + } + if ( nNewY != nY ) + { + EndListening( false ); + xPSet->setPropertyValue( DLGED_PROP_POSITIONY, Any(nNewY) ); + StartListening(); + } + } + } + } + } + + for (auto const& child : aChildList) + child->SetRectFromProps(); +} + +void DlgEdForm::UpdateStep() +{ + SdrPage* pSdrPage = getSdrPageFromSdrObject(); + + if ( pSdrPage ) + { + const size_t nObjCount = pSdrPage->GetObjCount(); + for ( size_t i = 0 ; i < nObjCount ; i++ ) + { + DlgEdObj* pDlgEdObj = dynamic_cast<DlgEdObj*>(pSdrPage->GetObj(i)); + if (pDlgEdObj && !dynamic_cast<DlgEdForm*>(pDlgEdObj)) + pDlgEdObj->UpdateStep(); + } + } +} + +void DlgEdForm::UpdateTabIndices() +{ + // stop listening with all children + for (auto const& child : pChildren) + { + child->EndListening( false ); + } + + Reference< css::container::XNameAccess > xNameAcc( GetUnoControlModel() , UNO_QUERY ); + if ( xNameAcc.is() ) + { + // get sequence of control names + Sequence< OUString > aNames = xNameAcc->getElementNames(); + const OUString* pNames = aNames.getConstArray(); + sal_Int32 nCtrls = aNames.getLength(); + + // create a map of tab indices and control names, sorted by tab index + IndexToNameMap aIndexToNameMap; + for ( sal_Int32 i = 0; i < nCtrls; ++i ) + { + // get name + OUString aName( pNames[i] ); + + // get tab index + sal_Int16 nTabIndex = -1; + Any aCtrl = xNameAcc->getByName( aName ); + Reference< css::beans::XPropertySet > xPSet; + aCtrl >>= xPSet; + if ( xPSet.is() ) + xPSet->getPropertyValue( DLGED_PROP_TABINDEX ) >>= nTabIndex; + + // insert into map + aIndexToNameMap.emplace( nTabIndex, aName ); + } + + // set new tab indices + sal_Int16 nNewTabIndex = 0; + for (auto const& indexToName : aIndexToNameMap) + { + Any aCtrl = xNameAcc->getByName( indexToName.second ); + Reference< beans::XPropertySet > xPSet; + aCtrl >>= xPSet; + if ( xPSet.is() ) + { + xPSet->setPropertyValue( DLGED_PROP_TABINDEX, Any(nNewTabIndex) ); + nNewTabIndex++; + } + } + + UpdateTabOrderAndGroups(); + } + + // start listening with all children + for (auto const& child : pChildren) + { + child->StartListening(); + } +} + +void DlgEdForm::UpdateTabOrder() +{ + // When the tabindex of a control model changes, the dialog control is + // notified about those changes. Due to #109067# (bad performance of + // dialog editor) the dialog control doesn't activate the tab order + // in design mode. When the dialog editor has reordered all + // tabindices, this method allows to activate the taborder afterwards. + + Reference< awt::XUnoControlContainer > xCont( GetControl(), UNO_QUERY ); + if ( xCont.is() ) + { + Sequence< Reference< awt::XTabController > > aSeqTabCtrls = xCont->getTabControllers(); + const Reference< awt::XTabController >* pTabCtrls = aSeqTabCtrls.getConstArray(); + sal_Int32 nCount = aSeqTabCtrls.getLength(); + for ( sal_Int32 i = 0; i < nCount; ++i ) + pTabCtrls[i]->activateTabOrder(); + } +} + +void DlgEdForm::UpdateGroups() +{ + // The grouping of radio buttons in a dialog is done by vcl. + // In the dialog editor we have two views (=controls) for one + // radio button model. One control is owned by the dialog control, + // but not visible in design mode. The other control is owned by + // the drawing layer object. Whereas the grouping of the first + // control is done by vcl, the grouping of the control in the + // drawing layer has to be done here. + + Reference< awt::XTabControllerModel > xTabModel( GetUnoControlModel() , UNO_QUERY ); + if ( !xTabModel.is() ) + return; + + // create a global list of controls that belong to the dialog + std::vector<DlgEdObj*> aChildList = GetChildren(); + sal_uInt32 nSize = aChildList.size(); + Sequence< Reference< awt::XControl > > aSeqControls( nSize ); + for ( sal_uInt32 i = 0; i < nSize; ++i ) + aSeqControls.getArray()[i] = aChildList[i]->GetControl(); + + sal_Int32 nGroupCount = xTabModel->getGroupCount(); + for ( sal_Int32 nGroup = 0; nGroup < nGroupCount; ++nGroup ) + { + // get a list of control models that belong to this group + OUString aName; + Sequence< Reference< awt::XControlModel > > aSeqModels; + xTabModel->getGroup( nGroup, aSeqModels, aName ); + const Reference< awt::XControlModel >* pModels = aSeqModels.getConstArray(); + sal_Int32 nModelCount = aSeqModels.getLength(); + + // create a list of peers that belong to this group + Sequence< Reference< awt::XWindow > > aSeqPeers( nModelCount ); + for ( sal_Int32 nModel = 0; nModel < nModelCount; ++nModel ) + { + // for each control model find the corresponding control in the global list + const Reference< awt::XControl >* pControls = aSeqControls.getConstArray(); + sal_Int32 nControlCount = aSeqControls.getLength(); + for ( sal_Int32 nControl = 0; nControl < nControlCount; ++nControl ) + { + const Reference< awt::XControl > xCtrl( pControls[nControl] ); + if ( xCtrl.is() ) + { + Reference< awt::XControlModel > xCtrlModel( xCtrl->getModel() ); + if ( xCtrlModel.get() == pModels[nModel].get() ) + { + // get the control peer and insert into the list of peers + aSeqPeers.getArray()[ nModel ].set( xCtrl->getPeer(), UNO_QUERY ); + break; + } + } + } + } + + // set the group at the dialog peer + Reference< awt::XControl > xDlg = GetControl(); + if ( xDlg.is() ) + { + Reference< awt::XVclContainerPeer > xDlgPeer( xDlg->getPeer(), UNO_QUERY ); + if ( xDlgPeer.is() ) + xDlgPeer->setGroup( aSeqPeers ); + } + } +} + +void DlgEdForm::UpdateTabOrderAndGroups() +{ + UpdateTabOrder(); + UpdateGroups(); +} + +void DlgEdForm::NbcMove( const Size& rSize ) +{ + SdrUnoObj::NbcMove( rSize ); + + // set geometry properties of form + EndListening(false); + SetPropsFromRect(); + StartListening(); + + // set geometry properties of all children + for (auto const& child : pChildren) + { + child->EndListening(false); + child->SetPropsFromRect(); + child->StartListening(); + } + + // dialog model changed + GetDlgEditor().SetDialogModelChanged(); +} + +void DlgEdForm::NbcResize(const Point& rRef, const Fraction& xFract, const Fraction& yFract) +{ + SdrUnoObj::NbcResize( rRef, xFract, yFract ); + + // set geometry properties of form + EndListening(false); + SetPropsFromRect(); + StartListening(); + + // set geometry properties of all children + for (auto const& child : pChildren) + { + child->EndListening(false); + child->SetPropsFromRect(); + child->StartListening(); + } + + // dialog model changed + GetDlgEditor().SetDialogModelChanged(); +} + +bool DlgEdForm::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) +{ + bool bResult = SdrUnoObj::EndCreate(rStat, eCmd); + + // stop listening + EndListening(false); + + // set geometry properties + SetPropsFromRect(); + + // dialog model changed + GetDlgEditor().SetDialogModelChanged(); + + // start listening + StartListening(); + + return bResult; +} + +awt::DeviceInfo DlgEdForm::getDeviceInfo() const +{ + awt::DeviceInfo aDeviceInfo; + + DlgEditor& rEditor = GetDlgEditor(); + vcl::Window& rWindow = rEditor.GetWindow(); + + // obtain an XControl + ::utl::SharedUNOComponent< awt::XControl > xDialogControl; // ensures auto-disposal, if needed + xDialogControl.reset( GetControl(), ::utl::SharedUNOComponent< awt::XControl >::NoTakeOwnership ); + if ( !xDialogControl.is() ) + { + // don't create a temporary control all the time, this method here is called + // way too often. Instead, use a cached DeviceInfo. + // #i74065# + if ( !!mpDeviceInfo ) + return *mpDeviceInfo; + + Reference< awt::XControlContainer > xEditorControlContainer( rEditor.GetWindowControlContainer() ); + xDialogControl.reset( + GetTemporaryControlForWindow(rWindow, xEditorControlContainer), + utl::SharedUNOComponent< awt::XControl >::TakeOwnership + ); + } + + Reference< awt::XDevice > xDialogDevice; + if ( xDialogControl.is() ) + xDialogDevice.set( xDialogControl->getPeer(), UNO_QUERY ); + DBG_ASSERT( xDialogDevice.is(), "DlgEdForm::getDeviceInfo: no device!" ); + if ( xDialogDevice.is() ) + aDeviceInfo = xDialogDevice->getInfo(); + + mpDeviceInfo = aDeviceInfo; + + return aDeviceInfo; +} +void DlgEdObj::MakeDataAware( const Reference< frame::XModel >& xModel ) +{ + // Need to flesh this out, currently we will only support data-aware controls for calc + // and only handle a subset of functionality e.g. linked-cell and cell range data source. Of course later + // we need to disambiguate for writer ( and others ? ) and also support the generic form (db) bindings + // we need some more work in xmlscript to be able to handle that + Reference< lang::XMultiServiceFactory > xFac( xModel, UNO_QUERY ); + Reference< form::binding::XBindableValue > xBindable( GetUnoControlModel(), UNO_QUERY ); + Reference< form::binding::XListEntrySink > xListEntrySink( GetUnoControlModel(), UNO_QUERY ); + if ( !xFac.is() ) + return; + + css::table::CellAddress aApiAddress; + + //tdf#90361 CellValueBinding and CellRangeListSource are unusable + //without being initialized, so use createInstanceWithArguments with a + //dummy BoundCell instead of createInstance. This at least results in + //the dialog editor not falling. + css::beans::NamedValue aValue; + aValue.Name = "BoundCell"; + aValue.Value <<= aApiAddress; + + Sequence< Any > aArgs{ Any(aValue) }; + + if ( xBindable.is() ) + { + Reference< form::binding::XValueBinding > xBinding( xFac->createInstanceWithArguments( "com.sun.star.table.CellValueBinding", aArgs ), UNO_QUERY ); + xBindable->setValueBinding( xBinding ); + } + if ( xListEntrySink.is() ) + { + Reference< form::binding::XListEntrySource > xSource( xFac->createInstanceWithArguments( "com.sun.star.table.CellRangeListSource", aArgs ), UNO_QUERY ); + xListEntrySink->setListEntrySource( xSource ); + } +} +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/dlged/dlgedpage.cxx b/basctl/source/dlged/dlgedpage.cxx new file mode 100644 index 000000000..760f88527 --- /dev/null +++ b/basctl/source/dlged/dlgedpage.cxx @@ -0,0 +1,66 @@ +/* -*- 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 <dlgedpage.hxx> +#include <dlged.hxx> +#include <dlgedmod.hxx> +#include <dlgedobj.hxx> + +namespace basctl +{ + + +DlgEdPage::DlgEdPage(DlgEdModel& rModel, bool bMasterPage) +: SdrPage(rModel, bMasterPage) + ,pDlgEdForm(nullptr) +{ +} + +DlgEdPage::~DlgEdPage() +{ + // clear SdrObjects with broadcasting + ClearSdrObjList(); +} + +rtl::Reference<SdrPage> DlgEdPage::CloneSdrPage(SdrModel& rTargetModel) const +{ + DlgEdModel& rDlgEdModel(static_cast< DlgEdModel& >(rTargetModel)); + rtl::Reference<DlgEdPage> pClonedDlgEdPage = + new DlgEdPage( + rDlgEdModel, + IsMasterPage()); + pClonedDlgEdPage->SdrPage::lateInit(*this); + return pClonedDlgEdPage; +} + + +SdrObject* DlgEdPage::SetObjectOrdNum(size_t nOldObjNum, size_t nNewObjNum) +{ + SdrObject* pObj = SdrPage::SetObjectOrdNum( nOldObjNum, nNewObjNum ); + + DlgEdHint aHint( DlgEdHint::OBJORDERCHANGED ); + if ( pDlgEdForm ) + pDlgEdForm->GetDlgEditor().Broadcast( aHint ); + + return pObj; +} + +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/dlged/dlgedview.cxx b/basctl/source/dlged/dlgedview.cxx new file mode 100644 index 000000000..d6c67b7e9 --- /dev/null +++ b/basctl/source/dlged/dlgedview.cxx @@ -0,0 +1,184 @@ +/* -*- 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 <dlgedview.hxx> +#include <dlged.hxx> +#include <dlgedpage.hxx> + +#include <vcl/canvastools.hxx> +#include <vcl/scrbar.hxx> + +#include <dlgedobj.hxx> + +namespace basctl +{ + +DlgEdView::DlgEdView( + SdrModel& rSdrModel, + OutputDevice& rOut, + DlgEditor& rEditor) +: SdrView(rSdrModel, &rOut), + rDlgEditor(rEditor) +{ + SetBufferedOutputAllowed(true); + SetBufferedOverlayAllowed(true); +} + +DlgEdView::~DlgEdView() +{ +} + +void DlgEdView::MarkListHasChanged() +{ + SdrView::MarkListHasChanged(); + + DlgEdHint aHint( DlgEdHint::SELECTIONCHANGED ); + rDlgEditor.Broadcast( aHint ); + rDlgEditor.UpdatePropertyBrowserDelayed(); +} + +void DlgEdView::MakeVisible( const tools::Rectangle& rRect, vcl::Window& rWin ) +{ + // visible area + MapMode aMap( rWin.GetMapMode() ); + Point aOrg( aMap.GetOrigin() ); + Size aVisSize( rWin.GetOutDev()->GetOutputSize() ); + tools::Rectangle RectTmp( Point(-aOrg.X(),-aOrg.Y()), aVisSize ); + tools::Rectangle aVisRect( RectTmp ); + + // check, if rectangle is inside visible area + if ( aVisRect.Contains( rRect ) ) + return; + + // calculate scroll distance; the rectangle must be inside the visible area + sal_Int32 nScrollX = 0, nScrollY = 0; + + sal_Int32 nVisLeft = aVisRect.Left(); + sal_Int32 nVisRight = aVisRect.Right(); + sal_Int32 nVisTop = aVisRect.Top(); + sal_Int32 nVisBottom = aVisRect.Bottom(); + + sal_Int32 nDeltaX = rDlgEditor.GetHScroll()->GetLineSize(); + sal_Int32 nDeltaY = rDlgEditor.GetVScroll()->GetLineSize(); + + while ( rRect.Right() > nVisRight + nScrollX ) + nScrollX += nDeltaX; + + while ( rRect.Left() < nVisLeft + nScrollX ) + nScrollX -= nDeltaX; + + while ( rRect.Bottom() > nVisBottom + nScrollY ) + nScrollY += nDeltaY; + + while ( rRect.Top() < nVisTop + nScrollY ) + nScrollY -= nDeltaY; + + // don't scroll beyond the page size + Size aPageSize = rDlgEditor.GetPage().GetSize(); + sal_Int32 nPageWidth = aPageSize.Width(); + sal_Int32 nPageHeight = aPageSize.Height(); + + if ( nVisRight + nScrollX > nPageWidth ) + nScrollX = nPageWidth - nVisRight; + + if ( nVisLeft + nScrollX < 0 ) + nScrollX = -nVisLeft; + + if ( nVisBottom + nScrollY > nPageHeight ) + nScrollY = nPageHeight - nVisBottom; + + if ( nVisTop + nScrollY < 0 ) + nScrollY = -nVisTop; + + // scroll window + rWin.PaintImmediately(); + rWin.Scroll( -nScrollX, -nScrollY ); + aMap.SetOrigin( Point( aOrg.X() - nScrollX, aOrg.Y() - nScrollY ) ); + rWin.SetMapMode( aMap ); + rWin.Invalidate(); + + // update scroll bars + rDlgEditor.UpdateScrollBars(); + + DlgEdHint aHint( DlgEdHint::WINDOWSCROLLED ); + rDlgEditor.Broadcast( aHint ); +} + +static SdrObject* impLocalHitCorrection(SdrObject* pRetval, const Point& rPnt, sal_uInt16 nTol) +{ + DlgEdObj* pDlgEdObj = dynamic_cast< DlgEdObj* >(pRetval); + + if(pDlgEdObj) + { + bool bExcludeInner(false); + + if(dynamic_cast< DlgEdForm* >(pRetval) != nullptr) + { + // from DlgEdForm::CheckHit; exclude inner for DlgEdForm + bExcludeInner = true; + } + else if(pDlgEdObj->supportsService("com.sun.star.awt.UnoControlGroupBoxModel")) + { + // from DlgEdObj::CheckHit; exclude inner for group shapes + bExcludeInner = true; + } + + if(bExcludeInner) + { + // use direct model data; it's a DlgEdObj, so GetLastBoundRect() + // will access aOutRect directly + const tools::Rectangle aOuterRectangle(pDlgEdObj->GetLastBoundRect()); + + if(!aOuterRectangle.IsEmpty()) + { + basegfx::B2DRange aOuterRange = vcl::unotools::b2DRectangleFromRectangle(aOuterRectangle); + + if(nTol) + { + aOuterRange.grow(-1.0 * nTol); + } + + if(aOuterRange.isInside(basegfx::B2DPoint(rPnt.X(), rPnt.Y()))) + { + pRetval = nullptr; + } + } + } + } + + return pRetval; +} + +SdrObject* DlgEdView::CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, SdrSearchOptions nOptions, const SdrLayerIDSet* pMVisLay) const +{ + // call parent + SdrObject* pRetval = SdrView::CheckSingleSdrObjectHit(rPnt, nTol, pObj, pPV, nOptions, pMVisLay); + + if(pRetval) + { + // check hit object locally + pRetval = impLocalHitCorrection(pRetval, rPnt, nTol); + } + + return pRetval; +} + +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/dlged/managelang.cxx b/basctl/source/dlged/managelang.cxx new file mode 100644 index 000000000..69f366ed6 --- /dev/null +++ b/basctl/source/dlged/managelang.cxx @@ -0,0 +1,318 @@ +/* -*- 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 <basidesh.hxx> +#include <basobj.hxx> +#include <iderdll.hxx> +#include <iderid.hxx> +#include <localizationmgr.hxx> +#include <managelang.hxx> + +#include <strings.hrc> + +#include <comphelper/sequence.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/sfxsids.hrc> +#include <svtools/langtab.hxx> +#include <svx/langbox.hxx> +#include <utility> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <vcl/settings.hxx> +#include <tools/debug.hxx> + +namespace basctl +{ + +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::resource; +using namespace ::com::sun::star::uno; + +bool localesAreEqual( const Locale& rLocaleLeft, const Locale& rLocaleRight ) +{ + bool bRet = ( rLocaleLeft.Language == rLocaleRight.Language && + rLocaleLeft.Country == rLocaleRight.Country && + rLocaleLeft.Variant == rLocaleRight.Variant ); + return bRet; +} + +ManageLanguageDialog::ManageLanguageDialog(weld::Window* pParent, std::shared_ptr<LocalizationMgr> xLMgr) + : GenericDialogController(pParent, "modules/BasicIDE/ui/managelanguages.ui", "ManageLanguagesDialog") + , m_xLocalizationMgr(std::move(xLMgr)) + , m_sDefLangStr(IDEResId(RID_STR_DEF_LANG)) + , m_sCreateLangStr(IDEResId(RID_STR_CREATE_LANG)) + , m_xLanguageLB(m_xBuilder->weld_tree_view("treeview")) + , m_xAddPB(m_xBuilder->weld_button("add")) + , m_xDeletePB(m_xBuilder->weld_button("delete")) + , m_xMakeDefPB(m_xBuilder->weld_button("default")) +{ + m_xLanguageLB->set_size_request(m_xLanguageLB->get_approximate_digit_width() * 42, + m_xLanguageLB->get_height_rows(10)); + + Init(); + FillLanguageBox(); + SelectHdl( *m_xLanguageLB ); +} + +ManageLanguageDialog::~ManageLanguageDialog() +{ + ClearLanguageBox(); +} + +void ManageLanguageDialog::Init() +{ + // get current IDE + Shell* pShell = GetShell(); + const OUString& sLibName = pShell->GetCurLibName(); + // set dialog title with library name + OUString sText = m_xDialog->get_title(); + sText = sText.replaceAll("$1", sLibName); + m_xDialog->set_title(sText); + // set handler + m_xAddPB->connect_clicked( LINK( this, ManageLanguageDialog, AddHdl ) ); + m_xDeletePB->connect_clicked( LINK( this, ManageLanguageDialog, DeleteHdl ) ); + m_xMakeDefPB->connect_clicked( LINK( this, ManageLanguageDialog, MakeDefHdl ) ); + m_xLanguageLB->connect_changed( LINK( this, ManageLanguageDialog, SelectHdl ) ); + + m_xLanguageLB->set_selection_mode(SelectionMode::Multiple); +} + +void ManageLanguageDialog::FillLanguageBox() +{ + DBG_ASSERT( m_xLocalizationMgr, "ManageLanguageDialog::FillLanguageBox(): no localization manager" ); + + if ( m_xLocalizationMgr->isLibraryLocalized() ) + { + Locale aDefaultLocale = m_xLocalizationMgr->getStringResourceManager()->getDefaultLocale(); + Sequence< Locale > aLocaleSeq = m_xLocalizationMgr->getStringResourceManager()->getLocales(); + const Locale* pLocale = aLocaleSeq.getConstArray(); + sal_Int32 i, nCount = aLocaleSeq.getLength(); + for ( i = 0; i < nCount; ++i ) + { + bool bIsDefault = localesAreEqual( aDefaultLocale, pLocale[i] ); + LanguageType eLangType = LanguageTag::convertToLanguageType( pLocale[i] ); + OUString sLanguage = SvtLanguageTable::GetLanguageString( eLangType ); + if ( bIsDefault ) + { + sLanguage += " " + m_sDefLangStr; + } + LanguageEntry* pEntry = new LanguageEntry(pLocale[i], bIsDefault); + m_xLanguageLB->append(weld::toId(pEntry), sLanguage); + } + } + else + m_xLanguageLB->append_text(m_sCreateLangStr); +} + +void ManageLanguageDialog::ClearLanguageBox() +{ + const sal_Int32 nCount = m_xLanguageLB->n_children(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + LanguageEntry* pEntry = weld::fromId<LanguageEntry*>(m_xLanguageLB->get_id(i)); + delete pEntry; + } + m_xLanguageLB->clear(); +} + +IMPL_LINK_NOARG(ManageLanguageDialog, AddHdl, weld::Button&, void) +{ + auto xDlg = std::make_shared<SetDefaultLanguageDialog>(m_xDialog.get(), m_xLocalizationMgr); + weld::DialogController::runAsync(xDlg, [xDlg,this](sal_Int32 nResult) + { + if (!nResult ) + return; + // add new locales + Sequence< Locale > aLocaleSeq = xDlg->GetLocales(); + m_xLocalizationMgr->handleAddLocales( aLocaleSeq ); + // update listbox + ClearLanguageBox(); + FillLanguageBox(); + + if (SfxBindings* pBindings = GetBindingsPtr()) + pBindings->Invalidate( SID_BASICIDE_CURRENT_LANG ); + }); +} + +IMPL_LINK_NOARG(ManageLanguageDialog, DeleteHdl, weld::Button&, void) +{ + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xDialog.get(), "modules/BasicIDE/ui/deletelangdialog.ui")); + std::unique_ptr<weld::MessageDialog> xQBox(xBuilder->weld_message_dialog("DeleteLangDialog")); + if (xQBox->run() != RET_OK) + return; + + std::vector<int> aSelection = m_xLanguageLB->get_selected_rows(); + int nCount = aSelection.size(); + int nPos = m_xLanguageLB->get_selected_index(); + // remove locales + Sequence< Locale > aLocaleSeq( nCount ); + auto aLocaleSeqRange = asNonConstRange(aLocaleSeq); + for (int i = 0; i < nCount; ++i) + { + const sal_Int32 nSelPos = aSelection[i]; + LanguageEntry* pEntry = weld::fromId<LanguageEntry*>(m_xLanguageLB->get_id(nSelPos)); + if ( pEntry ) + aLocaleSeqRange[i] = pEntry->m_aLocale; + } + m_xLocalizationMgr->handleRemoveLocales( aLocaleSeq ); + // update listbox + ClearLanguageBox(); + FillLanguageBox(); + // reset selection + nCount = m_xLanguageLB->n_children(); + if (nCount <= nPos) + nPos = nCount - 1; + m_xLanguageLB->select(nPos); + SelectHdl( *m_xLanguageLB ); +} + +IMPL_LINK_NOARG(ManageLanguageDialog, MakeDefHdl, weld::Button&, void) +{ + const sal_Int32 nPos = m_xLanguageLB->get_selected_index(); + LanguageEntry* pSelectEntry = weld::fromId<LanguageEntry*>(m_xLanguageLB->get_id(nPos)); + if (pSelectEntry && !pSelectEntry->m_bIsDefault) + { + // set new default entry + m_xLocalizationMgr->handleSetDefaultLocale( pSelectEntry->m_aLocale ); + // update Listbox + ClearLanguageBox(); + FillLanguageBox(); + // reset selection + m_xLanguageLB->select(nPos); + SelectHdl( *m_xLanguageLB ); + } +} + +IMPL_LINK_NOARG(ManageLanguageDialog, SelectHdl, weld::TreeView&, void) +{ + const sal_Int32 nCount = m_xLanguageLB->n_children(); + bool bEmpty = ( !nCount || + m_xLanguageLB->find_text(m_sCreateLangStr) != -1 ); + bool bSelect = ( m_xLanguageLB->get_selected_index() != -1 ); + bool bEnable = !bEmpty && bSelect; + + m_xDeletePB->set_sensitive(bEnable); + m_xMakeDefPB->set_sensitive(bEnable && nCount > 1 && m_xLanguageLB->count_selected_rows() == 1); +} + +// class SetDefaultLanguageDialog ----------------------------------------------- + +SetDefaultLanguageDialog::SetDefaultLanguageDialog(weld::Window* pParent, std::shared_ptr<LocalizationMgr> xLMgr) + : GenericDialogController(pParent, "modules/BasicIDE/ui/defaultlanguage.ui", "DefaultLanguageDialog") + , m_xLocalizationMgr(std::move(xLMgr)) + , m_xLanguageFT(m_xBuilder->weld_label("defaultlabel")) + , m_xLanguageLB(m_xBuilder->weld_tree_view("entries")) + , m_xCheckLangFT(m_xBuilder->weld_label("checkedlabel")) + , m_xCheckLangLB(m_xBuilder->weld_tree_view("checkedentries")) + , m_xDefinedFT(m_xBuilder->weld_label("defined")) + , m_xAddedFT(m_xBuilder->weld_label("added")) + , m_xAltTitle(m_xBuilder->weld_label("alttitle")) + , m_xLanguageCB(new SvxLanguageBox(m_xBuilder->weld_combo_box("hidden"))) +{ + m_xLanguageLB->set_size_request(-1, m_xLanguageLB->get_height_rows(10)); + m_xCheckLangLB->set_size_request(-1, m_xCheckLangLB->get_height_rows(10)); + m_xCheckLangLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + + if (m_xLocalizationMgr->isLibraryLocalized()) + { + // change to "Add Interface Language" mode + m_xLanguageLB->hide(); + m_xCheckLangLB->show(); + m_xDialog->set_title(m_xAltTitle->get_label()); + m_xLanguageFT->hide(); + m_xCheckLangFT->show(); + m_xDefinedFT->hide(); + m_xAddedFT->show(); + } + + FillLanguageBox(); +} + +SetDefaultLanguageDialog::~SetDefaultLanguageDialog() +{ +} + +void SetDefaultLanguageDialog::FillLanguageBox() +{ + // fill list with all languages + m_xLanguageCB->SetLanguageList(SvxLanguageListFlags::ALL, false); + + if (m_xLocalizationMgr->isLibraryLocalized()) + { + // remove the already localized languages + Sequence< Locale > aLocaleSeq = m_xLocalizationMgr->getStringResourceManager()->getLocales(); + const Locale* pLocale = aLocaleSeq.getConstArray(); + const sal_Int32 nCountLoc = aLocaleSeq.getLength(); + for ( sal_Int32 i = 0; i < nCountLoc; ++i ) + m_xLanguageCB->remove_id(LanguageTag::convertToLanguageType(pLocale[i])); + + // fill checklistbox if not in default mode + const sal_Int32 nCountLang = m_xLanguageCB->get_count(); + for (sal_Int32 j = 0; j < nCountLang; ++j) + { + LanguageType eLang = m_xLanguageCB->get_id(j); + m_xCheckLangLB->append(); + const int nRow = m_xCheckLangLB->n_children() - 1; + m_xCheckLangLB->set_toggle(nRow, TRISTATE_FALSE); + m_xCheckLangLB->set_text(nRow, m_xLanguageCB->get_text(j), 0); + m_xCheckLangLB->set_id(nRow, OUString::number(eLang.get())); + } + m_xLanguageCB.reset(); + m_xLanguageLB.reset(); + } + else + { + const sal_Int32 nCountLang = m_xLanguageCB->get_count(); + for (sal_Int32 j = 0; j < nCountLang; ++j) + { + LanguageType eLang = m_xLanguageCB->get_id(j); + m_xLanguageLB->append(OUString::number(eLang.get()), m_xLanguageCB->get_text(j)); + } + m_xLanguageCB.reset(); + + // preselect current UI language + m_xLanguageLB->select_id(OUString::number(Application::GetSettings().GetUILanguageTag().getLanguageType().get())); + } +} + +Sequence< Locale > SetDefaultLanguageDialog::GetLocales() const +{ + bool bNotLocalized = !m_xLocalizationMgr->isLibraryLocalized(); + if (bNotLocalized) + { + LanguageType eType(m_xLanguageLB->get_selected_id().toUInt32()); + return {LanguageTag(eType).getLocale()}; + } + std::vector<Locale> aLocaleSeq; + const sal_Int32 nCount = m_xCheckLangLB->n_children(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + if (m_xCheckLangLB->get_toggle(i) == TRISTATE_TRUE) + { + LanguageType eType(m_xCheckLangLB->get_id(i).toUInt32()); + aLocaleSeq.push_back(LanguageTag::convertToLocale(eType)); + } + } + return comphelper::containerToSequence(aLocaleSeq); +} + +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/dlged/propbrw.cxx b/basctl/source/dlged/propbrw.cxx new file mode 100644 index 000000000..d7ab2ee63 --- /dev/null +++ b/basctl/source/dlged/propbrw.cxx @@ -0,0 +1,506 @@ +/* -*- 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 <propbrw.hxx> +#include <basidesh.hxx> +#include <dlgedobj.hxx> +#include <iderid.hxx> +#include <baside3.hxx> +#include <strings.hrc> + +#include <strings.hxx> + +#include <com/sun/star/frame/Frame.hpp> +#include <com/sun/star/inspection/XObjectInspector.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <comphelper/types.hxx> +#include <comphelper/processfactory.hxx> +#include <cppuhelper/component_context.hxx> +#include <tools/debug.hxx> +#include <svx/svditer.hxx> +#include <svx/svdview.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <tools/diagnose_ex.h> +#include <vcl/layout.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/weld.hxx> + +#include <memory> + +namespace basctl +{ + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::comphelper; + + +void PropBrw::Update( const SfxViewShell* pShell ) +{ + Shell const* pIdeShell = dynamic_cast<Shell const*>(pShell); + OSL_ENSURE( pIdeShell || !pShell, "PropBrw::Update: invalid shell!" ); + if (pIdeShell) + ImplUpdate(pIdeShell->GetCurrentDocument(), pIdeShell->GetCurDlgView()); + else if (pShell) + ImplUpdate(nullptr, pShell->GetDrawView()); + else + ImplUpdate(nullptr, nullptr); +} + + +namespace +{ + +const tools::Long STD_WIN_SIZE_X = 300; +const tools::Long STD_WIN_SIZE_Y = 350; + +const tools::Long STD_MIN_SIZE_X = 250; +const tools::Long STD_MIN_SIZE_Y = 250; + +const tools::Long WIN_BORDER = 2; + +} // namespace + +PropBrw::PropBrw (DialogWindowLayout& rLayout_): + DockingWindow(&rLayout_), + m_xContentArea(VclPtr<VclVBox>::Create(this)), + m_bInitialStateChange(true), + m_xContextDocument(SfxViewShell::Current() ? SfxViewShell::Current()->GetCurrentDocument() : Reference<XModel>()), + pView(nullptr) +{ + Size aPropWinSize(STD_WIN_SIZE_X,STD_WIN_SIZE_Y); + SetMinOutputSizePixel(Size(STD_MIN_SIZE_X,STD_MIN_SIZE_Y)); + SetOutputSizePixel(aPropWinSize); + + // turn off WB_CLIPCHILDREN otherwise the bg won't extend "under" + // transparent children of the widget + m_xContentArea->SetControlBackground(m_xContentArea->GetSettings().GetStyleSettings().GetWindowColor()); + m_xContentArea->SetBackground(m_xContentArea->GetControlBackground()); + m_xContentArea->SetStyle(m_xContentArea->GetStyle() & ~WB_CLIPCHILDREN); + m_xContentArea->Show(); + + try + { + // create a frame wrapper for myself + m_xMeAsFrame = frame::Frame::create( comphelper::getProcessComponentContext() ); + m_xMeAsFrame->initialize(VCLUnoHelper::GetInterface(m_xContentArea)); + m_xMeAsFrame->setName( "form property browser" ); // change name! + } + catch (const Exception&) + { + OSL_FAIL("PropBrw::PropBrw: could not create/initialize my frame!"); + m_xMeAsFrame.clear(); + } + + ImplReCreateController(); +} + + +void PropBrw::ImplReCreateController() +{ + OSL_PRECOND( m_xMeAsFrame.is(), "PropBrw::ImplCreateController: no frame for myself!" ); + if ( !m_xMeAsFrame.is() ) + return; + + if ( m_xBrowserController.is() ) + ImplDestroyController(); + + try + { + Reference< XComponentContext > xOwnContext = comphelper::getProcessComponentContext(); + + // a ComponentContext for the + ::cppu::ContextEntry_Init aHandlerContextInfo[] = + { + ::cppu::ContextEntry_Init( "DialogParentWindow", Any(VCLUnoHelper::GetInterface(this))), + ::cppu::ContextEntry_Init( "ContextDocument", Any( m_xContextDocument ) ) + }; + Reference< XComponentContext > xInspectorContext( + ::cppu::createComponentContext( aHandlerContextInfo, std::size( aHandlerContextInfo ), xOwnContext ) ); + + // create a property browser controller + Reference< XMultiComponentFactory > xFactory( xInspectorContext->getServiceManager(), UNO_SET_THROW ); + static constexpr OUStringLiteral s_sControllerServiceName = u"com.sun.star.awt.PropertyBrowserController"; + m_xBrowserController.set( xFactory->createInstanceWithContext( s_sControllerServiceName, xInspectorContext ), UNO_QUERY ); + if ( !m_xBrowserController.is() ) + { + vcl::Window* pWin = GetParent(); + ShowServiceNotAvailableError(pWin ? pWin->GetFrameWeld() : nullptr, s_sControllerServiceName, true); + } + else + { + Reference< XController > xAsXController( m_xBrowserController, UNO_QUERY ); + DBG_ASSERT(xAsXController.is(), "PropBrw::PropBrw: invalid controller object!"); + if (!xAsXController.is()) + { + ::comphelper::disposeComponent(m_xBrowserController); + m_xBrowserController.clear(); + } + else + { + xAsXController->attachFrame( Reference<XFrame>(m_xMeAsFrame,UNO_QUERY_THROW) ); + } + } + + Point aPropWinPos( WIN_BORDER, WIN_BORDER ); + Size aPropWinSize(STD_WIN_SIZE_X,STD_WIN_SIZE_Y); + aPropWinSize.AdjustWidth( -(2*WIN_BORDER) ); + aPropWinSize.AdjustHeight( -(2*WIN_BORDER) ); + + VclContainer::setLayoutAllocation(*m_xContentArea, aPropWinPos, aPropWinSize); + m_xContentArea->Show(); + } + catch (const Exception&) + { + OSL_FAIL("PropBrw::PropBrw: could not create/initialize the browser controller!"); + try + { + ::comphelper::disposeComponent(m_xBrowserController); + } + catch(const Exception&) + { + } + + m_xBrowserController.clear(); + } + Resize(); +} + +PropBrw::~PropBrw() +{ + disposeOnce(); +} + +void PropBrw::dispose() +{ + if ( m_xBrowserController.is() ) + ImplDestroyController(); + m_xContentArea.disposeAndClear(); + DockingWindow::dispose(); +} + + +void PropBrw::ImplDestroyController() +{ + implSetNewObject( Reference< XPropertySet >() ); + + if ( m_xMeAsFrame.is() ) + m_xMeAsFrame->setComponent( nullptr, nullptr ); + + Reference< XController > xAsXController( m_xBrowserController, UNO_QUERY ); + if ( xAsXController.is() ) + xAsXController->attachFrame( nullptr ); + + try + { + ::comphelper::disposeComponent( m_xBrowserController ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("basctl"); + } + + m_xBrowserController.clear(); +} + +bool PropBrw::Close() +{ + ImplDestroyController(); + + return DockingWindow::Close(); +} + +Sequence< Reference< XInterface > > + PropBrw::CreateMultiSelectionSequence( const SdrMarkList& _rMarkList ) +{ + Sequence< Reference< XInterface > > aSeq; + InterfaceArray aInterfaces; + + const size_t nMarkCount = _rMarkList.GetMarkCount(); + for( size_t i = 0 ; i < nMarkCount ; ++i ) + { + SdrObject* pCurrent = _rMarkList.GetMark(i)->GetMarkedSdrObj(); + + std::unique_ptr<SdrObjListIter> pGroupIterator; + if (pCurrent->IsGroupObject()) + { + pGroupIterator.reset(new SdrObjListIter(pCurrent->GetSubList())); + pCurrent = pGroupIterator->IsMore() ? pGroupIterator->Next() : nullptr; + } + + while (pCurrent) + { + if (DlgEdObj* pDlgEdObj = dynamic_cast<DlgEdObj*>(pCurrent)) + { + Reference< XInterface > xControlInterface(pDlgEdObj->GetUnoControlModel(), UNO_QUERY); + if (xControlInterface.is()) + aInterfaces.push_back(xControlInterface); + } + + // next element + pCurrent = pGroupIterator && pGroupIterator->IsMore() ? pGroupIterator->Next() : nullptr; + } + } + + sal_Int32 nCount = aInterfaces.size(); + aSeq.realloc( nCount ); + Reference< XInterface >* pInterfaces = aSeq.getArray(); + for( sal_Int32 i = 0 ; i < nCount ; i++ ) + pInterfaces[i] = aInterfaces[i]; + + return aSeq; +} + + +void PropBrw::implSetNewObjectSequence + ( const Sequence< Reference< XInterface > >& _rObjectSeq ) +{ + Reference< inspection::XObjectInspector > xObjectInspector(m_xBrowserController, UNO_QUERY); + if ( xObjectInspector.is() ) + { + xObjectInspector->inspect( _rObjectSeq ); + + OUString aText = IDEResId(RID_STR_BRWTITLE_PROPERTIES) + + IDEResId(RID_STR_BRWTITLE_MULTISELECT); + SetText( aText ); + } +} + + +void PropBrw::implSetNewObject( const Reference< XPropertySet >& _rxObject ) +{ + if ( m_xBrowserController.is() ) + { + m_xBrowserController->setPropertyValue( "IntrospectedObject", + Any( _rxObject ) + ); + + // set the new title according to the selected object + SetText( GetHeadlineName( _rxObject ) ); + } +} + + +OUString PropBrw::GetHeadlineName( const Reference< XPropertySet >& _rxObject ) +{ + OUString aName; + Reference< lang::XServiceInfo > xServiceInfo( _rxObject, UNO_QUERY ); + + if (xServiceInfo.is()) // single selection + { + OUString sResId; + aName = IDEResId(RID_STR_BRWTITLE_PROPERTIES); + + if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlDialogModel" ) ) + { + sResId = RID_STR_CLASS_DIALOG; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlButtonModel" ) ) + { + sResId = RID_STR_CLASS_BUTTON; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlRadioButtonModel" ) ) + { + sResId = RID_STR_CLASS_RADIOBUTTON; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlCheckBoxModel" ) ) + { + sResId = RID_STR_CLASS_CHECKBOX; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlListBoxModel" ) ) + { + sResId = RID_STR_CLASS_LISTBOX; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlComboBoxModel" ) ) + { + sResId = RID_STR_CLASS_COMBOBOX; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlGroupBoxModel" ) ) + { + sResId = RID_STR_CLASS_GROUPBOX; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlEditModel" ) ) + { + sResId = RID_STR_CLASS_EDIT; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlFixedTextModel" ) ) + { + sResId = RID_STR_CLASS_FIXEDTEXT; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlImageControlModel" ) ) + { + sResId = RID_STR_CLASS_IMAGECONTROL; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlProgressBarModel" ) ) + { + sResId = RID_STR_CLASS_PROGRESSBAR; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlScrollBarModel" ) ) + { + sResId = RID_STR_CLASS_SCROLLBAR; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlFixedLineModel" ) ) + { + sResId = RID_STR_CLASS_FIXEDLINE; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlDateFieldModel" ) ) + { + sResId = RID_STR_CLASS_DATEFIELD; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlTimeFieldModel" ) ) + { + sResId = RID_STR_CLASS_TIMEFIELD; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlNumericFieldModel" ) ) + { + sResId = RID_STR_CLASS_NUMERICFIELD; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlCurrencyFieldModel" ) ) + { + sResId = RID_STR_CLASS_CURRENCYFIELD; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlFormattedFieldModel" ) ) + { + sResId = RID_STR_CLASS_FORMATTEDFIELD; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlPatternFieldModel" ) ) + { + sResId = RID_STR_CLASS_PATTERNFIELD; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlFileControlModel" ) ) + { + sResId = RID_STR_CLASS_FILECONTROL; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.tree.TreeControlModel" ) ) + { + sResId = RID_STR_CLASS_TREECONTROL; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.grid.UnoControlGridModel" ) ) + { + sResId = RID_STR_CLASS_GRIDCONTROL; + } + else if ( xServiceInfo->supportsService( "com.sun.star.awt.UnoControlFixedHyperlinkModel" ) ) + { + sResId = RID_STR_CLASS_HYPERLINKCONTROL; + } + else + { + sResId = RID_STR_CLASS_CONTROL; + } + + if (!sResId.isEmpty()) + { + aName += sResId; + } + } + else if (!_rxObject.is()) // no properties + { + aName = IDEResId(RID_STR_BRWTITLE_NO_PROPERTIES); + } + + return aName; +} + +void PropBrw::ImplUpdate( const Reference< XModel >& _rxContextDocument, SdrView* pNewView ) +{ + Reference< XModel > xContextDocument( _rxContextDocument ); + + // if we should simply "empty" ourself, assume the context document didn't change + if ( !pNewView ) + { + OSL_ENSURE( !_rxContextDocument.is(), "PropBrw::ImplUpdate: no view, but a document?!" ); + xContextDocument = m_xContextDocument; + } + + if ( xContextDocument != m_xContextDocument ) + { + m_xContextDocument = xContextDocument; + ImplReCreateController(); + } + + try + { + if ( pView ) + { + EndListening( *(pView->GetModel()) ); + pView = nullptr; + } + + if ( !pNewView ) + return; + + pView = pNewView; + + // set focus on initialization + if ( m_bInitialStateChange ) + { + m_xContentArea->GrabFocus(); + m_bInitialStateChange = false; + } + + const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); + const size_t nMarkCount = rMarkList.GetMarkCount(); + + if ( nMarkCount == 0 ) + { + EndListening( *(pView->GetModel()) ); + pView = nullptr; + implSetNewObject( nullptr ); + return; + } + + Reference< XPropertySet > xNewObject; + Sequence< Reference< XInterface > > aNewObjects; + if ( nMarkCount == 1 ) + { + if (DlgEdObj* pDlgEdObj = dynamic_cast<DlgEdObj*>(rMarkList.GetMark(0)->GetMarkedSdrObj())) + { + if ( pDlgEdObj->IsGroupObject() ) // group object + aNewObjects = CreateMultiSelectionSequence( rMarkList ); + else // single selection + xNewObject.set(pDlgEdObj->GetUnoControlModel(), css::uno::UNO_QUERY); + } + } + else if ( nMarkCount > 1 ) // multiple selection + { + aNewObjects = CreateMultiSelectionSequence( rMarkList ); + } + + if ( aNewObjects.hasElements() ) + implSetNewObjectSequence( aNewObjects ); + else + implSetNewObject( xNewObject ); + + StartListening( *(pView->GetModel()) ); + } + catch ( const PropertyVetoException& ) { /* silence */ } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("basctl"); + } +} + +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |