diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /toolkit/source/hatchwindow | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/source/hatchwindow')
-rw-r--r-- | toolkit/source/hatchwindow/documentcloser.cxx | 228 | ||||
-rw-r--r-- | toolkit/source/hatchwindow/hatchwindow.cxx | 200 | ||||
-rw-r--r-- | toolkit/source/hatchwindow/hatchwindow.hxx | 69 | ||||
-rw-r--r-- | toolkit/source/hatchwindow/hatchwindowfactory.cxx | 89 | ||||
-rw-r--r-- | toolkit/source/hatchwindow/ipwin.cxx | 623 | ||||
-rw-r--r-- | toolkit/source/hatchwindow/ipwin.hxx | 92 |
6 files changed, 1301 insertions, 0 deletions
diff --git a/toolkit/source/hatchwindow/documentcloser.cxx b/toolkit/source/hatchwindow/documentcloser.cxx new file mode 100644 index 000000000..b83825cdf --- /dev/null +++ b/toolkit/source/hatchwindow/documentcloser.cxx @@ -0,0 +1,228 @@ +/* -*- 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 <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> +#include <cppuhelper/implbase.hxx> +#include <comphelper/interfacecontainer4.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <vcl/svapp.hxx> +#include <vcl/dialoghelper.hxx> +#include <vcl/window.hxx> +#include <tools/link.hxx> +#include <toolkit/helper/vclunohelper.hxx> + +using namespace ::com::sun::star; + +namespace { + +// the service is implemented as a wrapper to be able to die by refcount +// the disposing mechanics is required for java related scenarios +class ODocumentCloser : public ::cppu::WeakImplHelper< css::lang::XComponent, + css::lang::XServiceInfo > +{ + std::mutex m_aMutex; + css::uno::Reference< css::frame::XFrame > m_xFrame; + ::comphelper::OInterfaceContainerHelper4<lang::XEventListener> m_aListenersContainer; // list of listeners + + bool m_bDisposed; + +public: + explicit ODocumentCloser(const css::uno::Sequence< css::uno::Any >& aArguments); + +// XComponent + virtual void SAL_CALL dispose() override; + virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override; + virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override; + +// XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +class MainThreadFrameCloserRequest +{ + uno::Reference< frame::XFrame > m_xFrame; + + public: + explicit MainThreadFrameCloserRequest( const uno::Reference< frame::XFrame >& xFrame ) + : m_xFrame( xFrame ) + {} + + DECL_STATIC_LINK( MainThreadFrameCloserRequest, worker, void*, void ); + + static void Start( MainThreadFrameCloserRequest* pRequest ); +}; + + +void MainThreadFrameCloserRequest::Start( MainThreadFrameCloserRequest* pMTRequest ) +{ + if ( pMTRequest ) + { + if ( Application::IsMainThread() ) + { + // this is the main thread + worker( nullptr, pMTRequest ); + } + else + Application::PostUserEvent( LINK( nullptr, MainThreadFrameCloserRequest, worker ), pMTRequest ); + } +} + + +IMPL_STATIC_LINK( MainThreadFrameCloserRequest, worker, void*, p, void ) +{ + MainThreadFrameCloserRequest* pMTRequest = static_cast<MainThreadFrameCloserRequest*>(p); + if ( !pMTRequest ) + return; + + if ( pMTRequest->m_xFrame.is() ) + { + // this is the main thread, the solar mutex must be locked + SolarMutexGuard aGuard; + + try + { + uno::Reference< awt::XWindow > xWindow = pMTRequest->m_xFrame->getContainerWindow(); + uno::Reference< awt::XVclWindowPeer > xWinPeer( xWindow, uno::UNO_QUERY_THROW ); + + xWindow->setVisible( false ); + + // reparent the window + xWinPeer->setProperty( "PluginParent", uno::Any( sal_Int64(0) ) ); + + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow ); + if (pWindow) + vcl::EndAllDialogs(pWindow); + } + catch( uno::Exception& ) + { + // ignore all the errors + } + + try + { + uno::Reference< util::XCloseable > xCloseable( pMTRequest->m_xFrame, uno::UNO_QUERY_THROW ); + xCloseable->close( true ); + } + catch( uno::Exception& ) + { + // ignore all the errors + } + } + + delete pMTRequest; +} + +ODocumentCloser::ODocumentCloser(const css::uno::Sequence< css::uno::Any >& aArguments) +: m_bDisposed( false ) +{ + std::unique_lock aGuard( m_aMutex ); + if ( !m_refCount ) + throw uno::RuntimeException(); // the object must be refcounted already! + + sal_Int32 nLen = aArguments.getLength(); + if ( nLen != 1 ) + throw lang::IllegalArgumentException( + "Wrong count of parameters!", + uno::Reference< uno::XInterface >(), + 0 ); + + if ( !( aArguments[0] >>= m_xFrame ) || !m_xFrame.is() ) + throw lang::IllegalArgumentException( + "Nonempty reference is expected as the first argument!", + uno::Reference< uno::XInterface >(), + 0 ); +} + + +// XComponent + +void SAL_CALL ODocumentCloser::dispose() +{ + std::unique_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) ); + m_aListenersContainer.disposeAndClear( aGuard, aSource ); + + // TODO: trigger a main thread execution to close the frame + if ( m_xFrame.is() ) + { + // the created object will be deleted after thread execution + MainThreadFrameCloserRequest* pCloser = new MainThreadFrameCloserRequest( m_xFrame ); + MainThreadFrameCloserRequest::Start( pCloser ); + } + + m_bDisposed = true; +} + + +void SAL_CALL ODocumentCloser::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) +{ + std::unique_lock aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + m_aListenersContainer.addInterface( aGuard, xListener ); +} + + +void SAL_CALL ODocumentCloser::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) +{ + std::unique_lock aGuard( m_aMutex ); + m_aListenersContainer.removeInterface( aGuard, xListener ); +} + +// XServiceInfo +OUString SAL_CALL ODocumentCloser::getImplementationName( ) +{ + return "com.sun.star.comp.embed.DocumentCloser"; +} + +sal_Bool SAL_CALL ODocumentCloser::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL ODocumentCloser::getSupportedServiceNames() +{ + return { "com.sun.star.embed.DocumentCloser" }; +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_embed_DocumentCloser_get_implementation( + SAL_UNUSED_PARAMETER css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &arguments) +{ + return cppu::acquire(new ODocumentCloser(arguments)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/hatchwindow/hatchwindow.cxx b/toolkit/source/hatchwindow/hatchwindow.cxx new file mode 100644 index 000000000..31b017d77 --- /dev/null +++ b/toolkit/source/hatchwindow/hatchwindow.cxx @@ -0,0 +1,200 @@ +/* -*- 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 <com/sun/star/embed/XHatchWindowController.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include "hatchwindow.hxx" +#include "ipwin.hxx" + +#include <toolkit/helper/convert.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <osl/diagnose.h> +#include <vcl/svapp.hxx> + +using namespace ::com::sun::star; + +VCLXHatchWindow::VCLXHatchWindow() +: pHatchWindow(nullptr) +{ +} + +VCLXHatchWindow::~VCLXHatchWindow() +{ +} + +void VCLXHatchWindow::initializeWindow( const uno::Reference< awt::XWindowPeer >& xParent, + const awt::Rectangle& aBounds, + const awt::Size& aSize ) +{ + SolarMutexGuard aGuard; + + VclPtr<vcl::Window> pParent; + VCLXWindow* pParentComponent = comphelper::getFromUnoTunnel<VCLXWindow>( xParent ); + + if ( pParentComponent ) + pParent = pParentComponent->GetWindow(); + + OSL_ENSURE( pParent, "No parent window is provided!" ); + if ( !pParent ) + throw lang::IllegalArgumentException(); // TODO + + pHatchWindow = VclPtr<SvResizeWindow>::Create( pParent, this ); + pHatchWindow->setPosSizePixel( aBounds.X, aBounds.Y, aBounds.Width, aBounds.Height ); + aHatchBorderSize = aSize; + pHatchWindow->SetHatchBorderPixel( Size( aSize.Width, aSize.Height ) ); + + SetWindow( pHatchWindow ); + pHatchWindow->SetComponentInterface( this ); + + //pHatchWindow->Show(); +} + +void VCLXHatchWindow::QueryObjAreaPixel( tools::Rectangle & aRect ) +{ + if ( !m_xController.is() ) + return; + + awt::Rectangle aUnoRequestRect = AWTRectangle( aRect ); + + try { + awt::Rectangle aUnoResultRect = m_xController->calcAdjustedRectangle( aUnoRequestRect ); + aRect = VCLRectangle( aUnoResultRect ); + } + catch( uno::Exception& ) + { + OSL_FAIL( "Can't adjust rectangle size!" ); + } +} + +void VCLXHatchWindow::RequestObjAreaPixel( const tools::Rectangle & aRect ) +{ + if ( m_xController.is() ) + { + awt::Rectangle aUnoRequestRect = AWTRectangle( aRect ); + + try { + m_xController->requestPositioning( aUnoRequestRect ); + } + catch( uno::Exception& ) + { + OSL_FAIL( "Can't request resizing!" ); + } + } +} + +void VCLXHatchWindow::InplaceDeactivate() +{ + if ( m_xController.is() ) + { + // TODO: communicate with controller + } +} + + +uno::Any SAL_CALL VCLXHatchWindow::queryInterface( const uno::Type & rType ) +{ + // Attention: + // Don't use mutex or guard in this method!!! Is a method of XInterface. + + uno::Any aReturn( ::cppu::queryInterface( rType, + static_cast< embed::XHatchWindow* >( this ) ) ); + + if ( aReturn.hasValue() ) + { + return aReturn ; + } + + return VCLXWindow::queryInterface( rType ) ; +} + +void SAL_CALL VCLXHatchWindow::acquire() + noexcept +{ + VCLXWindow::acquire(); +} + +void SAL_CALL VCLXHatchWindow::release() + noexcept +{ + VCLXWindow::release(); +} + +uno::Sequence< uno::Type > SAL_CALL VCLXHatchWindow::getTypes() +{ + static cppu::OTypeCollection aTypeCollection(cppu::UnoType<embed::XHatchWindow>::get(), + VCLXWindow::getTypes()); + + return aTypeCollection.getTypes(); +} + +uno::Sequence< sal_Int8 > SAL_CALL VCLXHatchWindow::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +css::awt::Size SAL_CALL VCLXHatchWindow::getHatchBorderSize() +{ + return aHatchBorderSize; +} + +void SAL_CALL VCLXHatchWindow::setHatchBorderSize( const css::awt::Size& _hatchbordersize ) +{ + if ( pHatchWindow ) + { + aHatchBorderSize = _hatchbordersize; + pHatchWindow->SetHatchBorderPixel( Size( aHatchBorderSize.Width, aHatchBorderSize.Height ) ); + } +} + +void SAL_CALL VCLXHatchWindow::setController( const uno::Reference< embed::XHatchWindowController >& xController ) +{ + m_xController = xController; +} + +void SAL_CALL VCLXHatchWindow::dispose() +{ + pHatchWindow.clear(); + VCLXWindow::dispose(); +} + +void SAL_CALL VCLXHatchWindow::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) +{ + VCLXWindow::addEventListener( xListener ); +} + +void SAL_CALL VCLXHatchWindow::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) +{ + VCLXWindow::removeEventListener( xListener ); +} + +void VCLXHatchWindow::Activated() +{ + if ( m_xController.is() ) + m_xController->activated(); +} + +void VCLXHatchWindow::Deactivated() +{ + if ( m_xController.is() ) + m_xController->deactivated(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/hatchwindow/hatchwindow.hxx b/toolkit/source/hatchwindow/hatchwindow.hxx new file mode 100644 index 000000000..52e91d12e --- /dev/null +++ b/toolkit/source/hatchwindow/hatchwindow.hxx @@ -0,0 +1,69 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/embed/XHatchWindow.hpp> + +#include <toolkit/awt/vclxwindow.hxx> + +class SvResizeWindow; +class VCLXHatchWindow : public css::embed::XHatchWindow, + public VCLXWindow +{ + css::uno::Reference< css::embed::XHatchWindowController > m_xController; + css::awt::Size aHatchBorderSize; + VclPtr<SvResizeWindow> pHatchWindow; + +public: + VCLXHatchWindow(); + virtual ~VCLXHatchWindow() override; + + void initializeWindow( const css::uno::Reference< css::awt::XWindowPeer >& xParent, + const css::awt::Rectangle& aBounds, + const css::awt::Size& aSize ); + + void QueryObjAreaPixel( tools::Rectangle & ); + void RequestObjAreaPixel( const tools::Rectangle & ); + void InplaceDeactivate(); + void Activated(); + void Deactivated(); + + // XInterface + css::uno::Any SAL_CALL queryInterface( const css::uno::Type& rType ) override; + void SAL_CALL acquire() noexcept override; + void SAL_CALL release() noexcept override; + + // XTypeProvider + css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override; + css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override; + + // XHatchWindow + virtual void SAL_CALL setController( const css::uno::Reference< css::embed::XHatchWindowController >& xController ) override; + virtual css::awt::Size SAL_CALL getHatchBorderSize() override; + virtual void SAL_CALL setHatchBorderSize( const css::awt::Size& _hatchbordersize ) override; + + // XComponent + virtual void SAL_CALL dispose() override; + virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override; + virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override; +}; + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/hatchwindow/hatchwindowfactory.cxx b/toolkit/source/hatchwindow/hatchwindowfactory.cxx new file mode 100644 index 000000000..3e50db64e --- /dev/null +++ b/toolkit/source/hatchwindow/hatchwindowfactory.cxx @@ -0,0 +1,89 @@ +/* -*- 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 <com/sun/star/embed/XHatchWindowFactory.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <vcl/svapp.hxx> + +#include "hatchwindow.hxx" + +using namespace ::com::sun::star; + +namespace { + +class OHatchWindowFactory : public ::cppu::WeakImplHelper< + embed::XHatchWindowFactory, + lang::XServiceInfo > +{ +public: + OHatchWindowFactory() {} + + // XHatchWindowFactory + virtual uno::Reference< embed::XHatchWindow > SAL_CALL createHatchWindowInstance( const uno::Reference< awt::XWindowPeer >& xParent, const awt::Rectangle& aBounds, const awt::Size& aSize ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +uno::Reference< embed::XHatchWindow > SAL_CALL OHatchWindowFactory::createHatchWindowInstance( + const uno::Reference< awt::XWindowPeer >& xParent, + const awt::Rectangle& aBounds, + const awt::Size& aHandlerSize ) +{ + if ( !xParent.is() ) + throw lang::IllegalArgumentException(); // TODO + + SolarMutexGuard aGuard; + rtl::Reference<VCLXHatchWindow> pResult = new VCLXHatchWindow(); + pResult->initializeWindow( xParent, aBounds, aHandlerSize ); + return pResult; +} + +OUString SAL_CALL OHatchWindowFactory::getImplementationName() +{ + return "com.sun.star.comp.embed.HatchWindowFactory"; +} + +sal_Bool SAL_CALL OHatchWindowFactory::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL OHatchWindowFactory::getSupportedServiceNames() +{ + return { "com.sun.star.embed.HatchWindowFactory", "com.sun.star.comp.embed.HatchWindowFactory" }; +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_embed_HatchWindowFactory_get_implementation( + css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new OHatchWindowFactory); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/hatchwindow/ipwin.cxx b/toolkit/source/hatchwindow/ipwin.cxx new file mode 100644 index 000000000..227d0a661 --- /dev/null +++ b/toolkit/source/hatchwindow/ipwin.cxx @@ -0,0 +1,623 @@ +/* -*- 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 <com/sun/star/accessibility/AccessibleRole.hpp> + +#include <osl/diagnose.h> +#include <vcl/event.hxx> +#include <vcl/settings.hxx> +#include <vcl/ptrstyle.hxx> + +#include "ipwin.hxx" +#include "hatchwindow.hxx" + +/************************************************************************/ +/************************************************************************* +|* SvResizeHelper::SvResizeHelper() +|* +|* Description +*************************************************************************/ +SvResizeHelper::SvResizeHelper() + : aBorder( 5, 5 ) + , nGrab( -1 ) +{ +} + +/************************************************************************* +|* SvResizeHelper::FillHandleRects() +|* +|* Description: the eight handles to magnify +*************************************************************************/ +std::array<tools::Rectangle,8> SvResizeHelper::FillHandleRectsPixel() const +{ + std::array<tools::Rectangle,8> aRects; + + // only because of EMPTY_RECT + Point aBottomRight = aOuter.BottomRight(); + + // upper left + aRects[ 0 ] = tools::Rectangle( aOuter.TopLeft(), aBorder ); + // upper middle + aRects[ 1 ] = tools::Rectangle( Point( aOuter.Center().X() - aBorder.Width() / 2, + aOuter.Top() ), + aBorder ); + // upper right + aRects[ 2 ] = tools::Rectangle( Point( aBottomRight.X() - aBorder.Width() +1, + aOuter.Top() ), + aBorder ); + // middle right + aRects[ 3 ] = tools::Rectangle( Point( aBottomRight.X() - aBorder.Width() +1, + aOuter.Center().Y() - aBorder.Height() / 2 ), + aBorder ); + // lower right + aRects[ 4 ] = tools::Rectangle( Point( aBottomRight.X() - aBorder.Width() +1, + aBottomRight.Y() - aBorder.Height() +1 ), + aBorder ); + // lower middle + aRects[ 5 ] = tools::Rectangle( Point( aOuter.Center().X() - aBorder.Width() / 2, + aBottomRight.Y() - aBorder.Height() +1), + aBorder ); + // lower left + aRects[ 6 ] = tools::Rectangle( Point( aOuter.Left(), + aBottomRight.Y() - aBorder.Height() +1), + aBorder ); + // middle left + aRects[ 7 ] = tools::Rectangle( Point( aOuter.Left(), + aOuter.Center().Y() - aBorder.Height() / 2 ), + aBorder ); + return aRects; +} + +/************************************************************************* +|* SvResizeHelper::FillMoveRectsPixel() +|* +|* Description: the four edges are calculated +*************************************************************************/ +std::array<tools::Rectangle,4> SvResizeHelper::FillMoveRectsPixel() const +{ + std::array<tools::Rectangle,4> aRects; + + // upper + aRects[ 0 ] = aOuter; + aRects[ 0 ].SetBottom( aRects[ 0 ].Top() + aBorder.Height() -1 ); + // right + aRects[ 1 ] = aOuter; + if (!aOuter.IsWidthEmpty()) + aRects[ 1 ].SetLeft( aRects[ 1 ].Right() - aBorder.Width() -1 ); + // lower + aRects[ 2 ] = aOuter; + if (!aOuter.IsHeightEmpty()) + aRects[ 2 ].SetTop( aRects[ 2 ].Bottom() - aBorder.Height() -1 ); + // left + aRects[ 3 ] = aOuter; + aRects[ 3 ].SetRight( aRects[ 3 ].Left() + aBorder.Width() -1 ); + + return aRects; +} + +/************************************************************************* +|* SvResizeHelper::Draw() +|* +|* Description +*************************************************************************/ +void SvResizeHelper::Draw(vcl::RenderContext& rRenderContext) +{ + rRenderContext.Push(); + rRenderContext.SetMapMode( MapMode() ); + + rRenderContext.SetFillColor( COL_LIGHTGRAY ); + rRenderContext.SetLineColor(); + + std::array<tools::Rectangle,4> aMoveRects = FillMoveRectsPixel(); + sal_uInt16 i; + for (i = 0; i < 4; i++) + rRenderContext.DrawRect(aMoveRects[i]); + // draw handles + rRenderContext.SetFillColor(Color()); // black + std::array<tools::Rectangle,8> aRects = FillHandleRectsPixel(); + for (i = 0; i < 8; i++) + rRenderContext.DrawRect( aRects[ i ] ); + rRenderContext.Pop(); +} + +/************************************************************************* +|* SvResizeHelper::InvalidateBorder() +|* +|* Description +*************************************************************************/ +void SvResizeHelper::InvalidateBorder( vcl::Window * pWin ) +{ + std::array<tools::Rectangle,4> aMoveRects = FillMoveRectsPixel(); + for(const auto & rMoveRect : aMoveRects) + pWin->Invalidate( rMoveRect ); +} + +/************************************************************************* +|* SvResizeHelper::SelectBegin() +|* +|* Description +*************************************************************************/ +bool SvResizeHelper::SelectBegin( vcl::Window * pWin, const Point & rPos ) +{ + if( -1 == nGrab ) + { + nGrab = SelectMove( pWin, rPos ); + if( -1 != nGrab ) + { + aSelPos = rPos; // store start position + pWin->CaptureMouse(); + return true; + } + } + return false; +} + +/************************************************************************* +|* SvResizeHelper::SelectMove() +|* +|* Description +*************************************************************************/ +short SvResizeHelper::SelectMove( vcl::Window * pWin, const Point & rPos ) +{ + if( -1 == nGrab ) + { + std::array<tools::Rectangle,8> aRects = FillHandleRectsPixel(); + for( sal_uInt16 i = 0; i < 8; i++ ) + if( aRects[ i ].Contains( rPos ) ) + return i; + // Move-Rect overlaps Handles + std::array<tools::Rectangle,4> aMoveRects = FillMoveRectsPixel(); + for(const auto & rMoveRect : aMoveRects) + if( rMoveRect.Contains( rPos ) ) + return 8; + } + else + { + tools::Rectangle aRect( GetTrackRectPixel( rPos ) ); + aRect.SetSize( pWin->PixelToLogic( aRect.GetSize() ) ); + aRect.SetPos( pWin->PixelToLogic( aRect.TopLeft() ) ); + pWin->ShowTracking( aRect ); + } + return nGrab; +} + +Point SvResizeHelper::GetTrackPosPixel( const tools::Rectangle & rRect ) const +{ + // not important how the rectangle is returned, it is important + // which handle has been touched + Point aPos; + tools::Rectangle aRect( rRect ); + aRect.Justify(); + // only because of EMPTY_RECT + Point aBR = aOuter.BottomRight(); + Point aTR = aOuter.TopRight(); + Point aBL = aOuter.BottomLeft(); + bool bRTL = AllSettings::GetLayoutRTL(); + switch( nGrab ) + { + case 0: + // FIXME: disable it for RTL because it's wrong calculations + if( bRTL ) + break; + aPos = aRect.TopLeft() - aOuter.TopLeft(); + break; + case 1: + aPos.setY( aRect.Top() - aOuter.Top() ); + break; + case 2: + // FIXME: disable it for RTL because it's wrong calculations + if( bRTL ) + break; + aPos = aRect.TopRight() - aTR; + break; + case 3: + if( bRTL ) + aPos.setX( aRect.Left() - aTR.X() ); + else + aPos.setX( aRect.Right() - aTR.X() ); + break; + case 4: + // FIXME: disable it for RTL because it's wrong calculations + if( bRTL ) + break; + aPos = aRect.BottomRight() - aBR; + break; + case 5: + aPos.setY( aRect.Bottom() - aBR.Y() ); + break; + case 6: + // FIXME: disable it for RTL because it's wrong calculations + if( bRTL ) + break; + aPos = aRect.BottomLeft() - aBL; + break; + case 7: + if( bRTL ) + aPos.setX( aRect.Right() + aOuter.Right() - aOuter.Right() ); + else + aPos.setX( aRect.Left() - aOuter.Left() ); + break; + case 8: + aPos = aRect.TopLeft() - aOuter.TopLeft(); + break; + } + return aPos + aSelPos; +} + +/************************************************************************* +|* SvResizeHelper::GetTrackRectPixel() +|* +|* Description +*************************************************************************/ +tools::Rectangle SvResizeHelper::GetTrackRectPixel( const Point & rTrackPos ) const +{ + tools::Rectangle aTrackRect; + if( -1 != nGrab ) + { + Point aDiff = rTrackPos - aSelPos; + aTrackRect = aOuter; + Point aBR = aOuter.BottomRight(); + bool bRTL = AllSettings::GetLayoutRTL(); + switch( nGrab ) + { + case 0: + aTrackRect.AdjustTop(aDiff.Y() ); + // ugly solution for resizing OLE objects in RTL + if( bRTL ) + aTrackRect.SetRight( aBR.X() - aDiff.X() ); + else + aTrackRect.AdjustLeft(aDiff.X() ); + break; + case 1: + aTrackRect.AdjustTop(aDiff.Y() ); + break; + case 2: + aTrackRect.AdjustTop(aDiff.Y() ); + // ugly solution for resizing OLE objects in RTL + if( bRTL ) + aTrackRect.AdjustLeft( -(aDiff.X()) ); + else + aTrackRect.SetRight( aBR.X() + aDiff.X() ); + break; + case 3: + // ugly solution for resizing OLE objects in RTL + if( bRTL ) + aTrackRect.AdjustLeft( -(aDiff.X()) ); + else + aTrackRect.SetRight( aBR.X() + aDiff.X() ); + break; + case 4: + aTrackRect.SetBottom( aBR.Y() + aDiff.Y() ); + // ugly solution for resizing OLE objects in RTL + if( bRTL ) + aTrackRect.AdjustLeft( -(aDiff.X()) ); + else + aTrackRect.SetRight( aBR.X() + aDiff.X() ); + break; + case 5: + aTrackRect.SetBottom( aBR.Y() + aDiff.Y() ); + break; + case 6: + aTrackRect.SetBottom( aBR.Y() + aDiff.Y() ); + // ugly solution for resizing OLE objects in RTL + if( bRTL ) + aTrackRect.SetRight( aBR.X() - aDiff.X() ); + else + aTrackRect.AdjustLeft(aDiff.X() ); + break; + case 7: + // ugly solution for resizing OLE objects in RTL + if( bRTL ) + aTrackRect.SetRight( aBR.X() - aDiff.X() ); + else + aTrackRect.AdjustLeft(aDiff.X() ); + break; + case 8: + if( bRTL ) + aDiff.setX( -aDiff.X() ); // workaround for move in RTL mode + aTrackRect.SetPos( aTrackRect.TopLeft() + aDiff ); + break; + } + } + return aTrackRect; +} + +void SvResizeHelper::ValidateRect( tools::Rectangle & rValidate ) const +{ + switch( nGrab ) + { + case 0: + if( rValidate.Top() > rValidate.Bottom() ) + rValidate.SetTop( rValidate.Bottom() ); + if( rValidate.Left() > rValidate.Right() ) + rValidate.SetLeft( rValidate.Right() ); + break; + case 1: + if( rValidate.Top() > rValidate.Bottom() ) + rValidate.SetTop( rValidate.Bottom() ); + break; + case 2: + if( rValidate.Top() > rValidate.Bottom() ) + rValidate.SetTop( rValidate.Bottom() ); + if( rValidate.Left() > rValidate.Right() ) + rValidate.SetRight( rValidate.Left() ); + break; + case 3: + if( rValidate.Left() > rValidate.Right() ) + rValidate.SetRight( rValidate.Left() ); + break; + case 4: + if( rValidate.Top() > rValidate.Bottom() ) + rValidate.SetBottom( rValidate.Top() ); + if( rValidate.Left() > rValidate.Right() ) + rValidate.SetRight( rValidate.Left() ); + break; + case 5: + if( rValidate.Top() > rValidate.Bottom() ) + rValidate.SetBottom( rValidate.Top() ); + break; + case 6: + if( rValidate.Top() > rValidate.Bottom() ) + rValidate.SetBottom( rValidate.Top() ); + if( rValidate.Left() > rValidate.Right() ) + rValidate.SetLeft( rValidate.Right() ); + break; + case 7: + if( rValidate.Left() > rValidate.Right() ) + rValidate.SetLeft( rValidate.Right() ); + break; + } + + // Mindestgr"osse 5 x 5 + if( rValidate.Left() + 5 > rValidate.Right() ) + rValidate.SetRight( rValidate.Left() + 5 ); + if( rValidate.Top() + 5 > rValidate.Bottom() ) + rValidate.SetBottom( rValidate.Top() + 5 ); +} + +/************************************************************************* +|* SvResizeHelper::SelectRelease() +|* +|* Description +*************************************************************************/ +bool SvResizeHelper::SelectRelease( vcl::Window * pWin, const Point & rPos, + tools::Rectangle & rOutPosSize ) +{ + if( -1 != nGrab ) + { + rOutPosSize = GetTrackRectPixel( rPos ); + rOutPosSize.Justify(); + nGrab = -1; + pWin->ReleaseMouse(); + pWin->HideTracking(); + return true; + } + return false; +} + +/************************************************************************* +|* SvResizeHelper::Release() +|* +|* Description +*************************************************************************/ +void SvResizeHelper::Release( vcl::Window * pWin ) +{ + if( nGrab != -1 ) + { + pWin->ReleaseMouse(); + pWin->HideTracking(); + nGrab = -1; + } +} + +/************************************************************************* +|* SvResizeWindow::SvResizeWindow() +|* +|* Description +*************************************************************************/ +SvResizeWindow::SvResizeWindow +( + vcl::Window * pParent, + VCLXHatchWindow* pWrapper +) + : Window( pParent, WB_CLIPCHILDREN ) + , m_aOldPointer(PointerStyle::Arrow) + , m_nMoveGrab( -1 ) + , m_bActive( false ) + , m_pWrapper( pWrapper ) +{ + OSL_ENSURE( pParent != nullptr && pWrapper != nullptr, "Wrong initialization of hatch window!" ); + SetBackground(); + SetAccessibleRole( css::accessibility::AccessibleRole::EMBEDDED_OBJECT ); + m_aResizer.SetOuterRectPixel( tools::Rectangle( Point(), GetOutputSizePixel() ) ); +} + +/************************************************************************* +|* SvResizeWindow::SetHatchBorderPixel() +|* +|* Description +*************************************************************************/ +void SvResizeWindow::SetHatchBorderPixel( const Size & rSize ) +{ + m_aResizer.SetBorderPixel( rSize ); +} + +/************************************************************************* +|* SvResizeWindow::SelectMouse() +|* +|* Description +*************************************************************************/ +void SvResizeWindow::SelectMouse( const Point & rPos ) +{ + short nGrab = m_aResizer.SelectMove( this, rPos ); + if( nGrab >= 4 ) + nGrab -= 4; + if( m_nMoveGrab == nGrab ) + return; + + // Pointer did change + if( -1 == nGrab ) + SetPointer( m_aOldPointer ); + else + { + PointerStyle aStyle = PointerStyle::Move; + if( nGrab == 3 ) + aStyle = PointerStyle::ESize; + else if( nGrab == 2 ) + aStyle = PointerStyle::NESize; + else if( nGrab == 1 ) + aStyle = PointerStyle::SSize; + else if( nGrab == 0 ) + aStyle = PointerStyle::SESize; + if( m_nMoveGrab == -1 ) // the first time + { + m_aOldPointer = GetPointer(); + SetPointer( aStyle ); + } + else + SetPointer( aStyle ); + } + m_nMoveGrab = nGrab; +} + +/************************************************************************* +|* SvResizeWindow::MouseButtonDown() +|* +|* Description +*************************************************************************/ +void SvResizeWindow::MouseButtonDown( const MouseEvent & rEvt ) +{ + if( m_aResizer.SelectBegin( this, rEvt.GetPosPixel() ) ) + SelectMouse( rEvt.GetPosPixel() ); +} + +/************************************************************************* +|* SvResizeWindow::MouseMove() +|* +|* Description +*************************************************************************/ +void SvResizeWindow::MouseMove( const MouseEvent & rEvt ) +{ + if( m_aResizer.GetGrab() == -1 ) + SelectMouse( rEvt.GetPosPixel() ); + else + { + tools::Rectangle aRect( m_aResizer.GetTrackRectPixel( rEvt.GetPosPixel() ) ); + Point aDiff = GetPosPixel(); + aRect.SetPos( aRect.TopLeft() + aDiff ); + m_aResizer.ValidateRect( aRect ); + + m_pWrapper->QueryObjAreaPixel( aRect ); + aRect.SetPos( aRect.TopLeft() - aDiff ); + Point aPos = m_aResizer.GetTrackPosPixel( aRect ); + + SelectMouse( aPos ); + } +} + +/************************************************************************* +|* SvResizeWindow::MouseButtonUp() +|* +|* Description +*************************************************************************/ +void SvResizeWindow::MouseButtonUp( const MouseEvent & rEvt ) +{ + if( m_aResizer.GetGrab() == -1 ) + return; + + tools::Rectangle aRect( m_aResizer.GetTrackRectPixel( rEvt.GetPosPixel() ) ); + Point aDiff = GetPosPixel(); + aRect.SetPos( aRect.TopLeft() + aDiff ); + // aRect -= GetAllBorderPixel(); + m_aResizer.ValidateRect( aRect ); + + m_pWrapper->QueryObjAreaPixel( aRect ); + + tools::Rectangle aOutRect; + if( m_aResizer.SelectRelease( this, rEvt.GetPosPixel(), aOutRect ) ) + { + m_nMoveGrab = -1; + SetPointer( m_aOldPointer ); + m_pWrapper->RequestObjAreaPixel( aRect ); + } +} + +/************************************************************************* +|* SvResizeWindow::KeyEvent() +|* +|* Description +*************************************************************************/ +void SvResizeWindow::KeyInput( const KeyEvent & rEvt ) +{ + if( rEvt.GetKeyCode().GetCode() == KEY_ESCAPE ) + { + m_aResizer.Release( this ); + m_pWrapper->InplaceDeactivate(); + } +} + +/************************************************************************* +|* SvResizeWindow::Resize() +|* +|* Description +*************************************************************************/ +void SvResizeWindow::Resize() +{ + m_aResizer.InvalidateBorder( this ); // old area + m_aResizer.SetOuterRectPixel( tools::Rectangle( Point(), GetOutputSizePixel() ) ); + m_aResizer.InvalidateBorder( this ); // new area +} + +/************************************************************************* +|* SvResizeWindow::Paint() +|* +|* Description +*************************************************************************/ +void SvResizeWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle & /*rRect*/ ) +{ + m_aResizer.Draw(rRenderContext); +} + +bool SvResizeWindow::PreNotify( NotifyEvent& rEvt ) +{ + if ( rEvt.GetType() == MouseNotifyEvent::GETFOCUS && !m_bActive ) + { + m_bActive = true; + m_pWrapper->Activated(); + } + + return Window::PreNotify(rEvt); +} + +bool SvResizeWindow::EventNotify( NotifyEvent& rEvt ) +{ + if ( rEvt.GetType() == MouseNotifyEvent::LOSEFOCUS && m_bActive ) + { + bool bHasFocus = HasChildPathFocus(true); + if ( !bHasFocus ) + { + m_bActive = false; + m_pWrapper->Deactivated(); + } + } + + return Window::EventNotify(rEvt); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/hatchwindow/ipwin.hxx b/toolkit/source/hatchwindow/ipwin.hxx new file mode 100644 index 000000000..72567ce26 --- /dev/null +++ b/toolkit/source/hatchwindow/ipwin.hxx @@ -0,0 +1,92 @@ +/* -*- 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 . + */ + +#pragma once + +#include <tools/gen.hxx> +#include <vcl/window.hxx> +#include <array> + +/********************** SvResizeHelper *********************************** +*************************************************************************/ +class SvResizeHelper +{ + Size aBorder; + tools::Rectangle aOuter; + short nGrab; // -1 no Grab, 0 - 7, 8 = Move, see FillHandle... + Point aSelPos; +public: + SvResizeHelper(); + + short GetGrab() const + { + return nGrab; + } + void SetBorderPixel(const Size & rBorderP) + { + aBorder = rBorderP; + } + void SetOuterRectPixel(const tools::Rectangle& rRect) + { + aOuter = rRect; + } + // Clockwise, start at upper left + + std::array<tools::Rectangle,8> FillHandleRectsPixel() const; + std::array<tools::Rectangle,4> FillMoveRectsPixel() const; + void Draw(vcl::RenderContext& rRenderContext); + void InvalidateBorder( vcl::Window * ); + bool SelectBegin( vcl::Window *, const Point & rPos ); + short SelectMove( vcl::Window * pWin, const Point & rPos ); + Point GetTrackPosPixel( const tools::Rectangle & rRect ) const; + tools::Rectangle GetTrackRectPixel( const Point & rTrackPos ) const; + void ValidateRect( tools::Rectangle & rValidate ) const; + bool SelectRelease( vcl::Window *, const Point & rPos, tools::Rectangle & rOutPosSize ); + void Release( vcl::Window * pWin ); +}; + +/********************** SvResizeWindow *********************************** +*************************************************************************/ +class VCLXHatchWindow; +class SvResizeWindow : public vcl::Window +{ + PointerStyle m_aOldPointer; + short m_nMoveGrab; // last pointer type + SvResizeHelper m_aResizer; + bool m_bActive; + + VCLXHatchWindow* m_pWrapper; +public: + SvResizeWindow( vcl::Window* pParent, VCLXHatchWindow* pWrapper ); + + void SetHatchBorderPixel( const Size & rSize ); + + void SelectMouse( const Point & rPos ); + virtual void MouseButtonUp( const MouseEvent & rEvt ) override; + virtual void MouseMove( const MouseEvent & rEvt ) override; + virtual void MouseButtonDown( const MouseEvent & rEvt ) override; + virtual void KeyInput( const KeyEvent & rEvt ) override; + virtual void Resize() override; + virtual void Paint( vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle & ) override; + virtual bool EventNotify( NotifyEvent& rNEvt ) override; + virtual bool PreNotify( NotifyEvent& rNEvt ) override; +}; + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |