Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/vcl/source/window/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 36 kB image not shown  

Quelle  dockmgr.cxx   Sprache: C

 
/* -*- 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 <tools/time.hxx>
#include <sal/log.hxx>
#include <o3tl/deleter.hxx>

#include <brdwin.hxx>
#include <svdata.hxx>
#include <window.h>

#include <vcl/event.hxx>
#include <vcl/toolkit/floatwin.hxx>
#include <vcl/dockwin.hxx>
#include <vcl/toolbox.hxx>
#include <vcl/svapp.hxx>
#include <vcl/timer.hxx>
#include <vcl/settings.hxx>

#include "impldockingwrapper.hxx"

#define DOCKWIN_FLOATSTYLES         (WB_SIZEABLE | WB_MOVEABLE | WB_CLOSEABLE | WB_STANDALONE)

namespace {

class ImplDockFloatWin2 : public FloatingWindow
{
private:
    ImplDockingWindowWrapper*  mpDockWin;
    sal_uInt64      mnLastTicks;
    Timer           m_aDockTimer;
    Timer           m_aEndDockTimer;
    Point           maDockPos;
    tools::Rectangle       maDockRect;
    bool            mbInMove;
    ImplSVEvent *   mnLastUserEvent;

    DECL_LINK(DockingHdl, void *, void);
    DECL_LINK(DockTimerHdl, Timer *, void);
    DECL_LINK(EndDockTimerHdl, Timer *, void);
public:
    ImplDockFloatWin2( vcl::Window* pParent, WinBits nWinBits,
                      ImplDockingWindowWrapper* pDockingWin );
    virtual ~ImplDockFloatWin2() override;
    virtual void dispose() override;

    virtual void    Move() override;
    virtual void    Resize() override;
    virtual void    TitleButtonClick( TitleButton nButton ) override;
    virtual void    Resizing( Size& rSize ) override;
    virtual bool    Close() override;
};

}

ImplDockFloatWin2::ImplDockFloatWin2( vcl::Window* pParent, WinBits nWinBits,
                                    ImplDockingWindowWrapper* pDockingWin ) :
        FloatingWindow( pParent, nWinBits ),
        mpDockWin( pDockingWin ),
        mnLastTicks( tools::Time::GetSystemTicks() ),
        m_aDockTimer("vcl::ImplDockFloatWin2 m_aDockTimer"),
        m_aEndDockTimer( "vcl::ImplDockFloatWin2 m_aEndDockTimer" ),
        mbInMove( false ),
        mnLastUserEvent( nullptr )
{
    // copy state of DockingWindow
    if ( pDockingWin )
    {
        GetOutDev()->SetSettings( pDockingWin->GetWindow()->GetSettings() );
        Enable( pDockingWin->GetWindow()->IsEnabled(), false );
        EnableInput( pDockingWin->GetWindow()->IsInputEnabled(), false );
        AlwaysEnableInput( pDockingWin->GetWindow()->IsAlwaysEnableInput(), false );
        EnableAlwaysOnTop( pDockingWin->GetWindow()->IsAlwaysOnTopEnabled() );
        SetActivateMode( pDockingWin->GetWindow()->GetActivateMode() );
    }

    SetBackground( GetSettings().GetStyleSettings().GetFaceColor() );

    m_aDockTimer.SetInvokeHandler( LINK( this, ImplDockFloatWin2, DockTimerHdl ) );
    m_aDockTimer.SetPriority( TaskPriority::HIGH_IDLE );
    m_aDockTimer.SetTimeout( 50 );

    m_aEndDockTimer.SetInvokeHandler( LINK( this, ImplDockFloatWin2, EndDockTimerHdl ) );
    m_aEndDockTimer.SetPriority( TaskPriority::HIGH_IDLE );
    m_aEndDockTimer.SetTimeout( 50 );
}

ImplDockFloatWin2::~ImplDockFloatWin2()
{
    disposeOnce();
}

void ImplDockFloatWin2::dispose()
{
    if( mnLastUserEvent )
        Application::RemoveUserEvent( mnLastUserEvent );
    FloatingWindow::dispose();
}

IMPL_LINK_NOARG(ImplDockFloatWin2, DockTimerHdl, Timer *, void)
{
    SAL_WARN_IF( !mpDockWin->IsFloatingMode(), "vcl""docktimer called but not floating" );

    PointerState aState = GetPointerState();

    if( aState.mnState & KEY_MOD1 )
    {
        // i43499 CTRL disables docking now
        mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
        if( aState.mnState & ( MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT ) )
            m_aDockTimer.Start();
    }
    else if( ! ( aState.mnState & ( MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT ) ) )
    {
        mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
        mpDockWin->EndDocking( maDockRect, false );
    }
    else
    {
        mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect, ShowTrackFlags::Big | ShowTrackFlags::TrackWindow );
        m_aDockTimer.Start();
    }
}

IMPL_LINK_NOARG(ImplDockFloatWin2, EndDockTimerHdl, Timer *, void)
{
    SAL_WARN_IF( !mpDockWin->IsFloatingMode(), "vcl""enddocktimer called but not floating" );

    PointerState aState = GetPointerState();
    if( ! ( aState.mnState & ( MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT ) ) )
    {
        mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
        mpDockWin->EndDocking( maDockRect, true );
    }
    else
        m_aEndDockTimer.Start();
}

IMPL_LINK_NOARG(ImplDockFloatWin2, DockingHdl, void*, void)
{
    // called during move of a floating window
    mnLastUserEvent = nullptr;

    vcl::Window *pDockingArea = mpDockWin->GetWindow()->GetParent();
    PointerState aState = pDockingArea->GetPointerState();

    bool bRealMove = true;
    if( GetStyle() & WB_OWNERDRAWDECORATION )
    {
        // for windows with ownerdraw decoration
        // we allow docking only when the window was moved
        // by dragging its caption
        // and ignore move request due to resizing
        vcl::Window *pBorder = GetWindow( GetWindowType::Border );
        if( pBorder != this )
        {
            tools::Rectangle aBorderRect( Point(), pBorder->GetSizePixel() );
            sal_Int32 nLeft, nTop, nRight, nBottom;
            GetBorder( nLeft, nTop, nRight, nBottom );
            // limit borderrect to the caption part only and without the resizing borders
            aBorderRect.SetBottom( aBorderRect.Top() + nTop );
            aBorderRect.AdjustLeft(nLeft );
            aBorderRect.AdjustRight( -nRight );

            PointerState aBorderState = pBorder->GetPointerState();
            bRealMove = aBorderRect.Contains( aBorderState.maPos );
        }
    }

    if( mpDockWin->GetWindow()->IsVisible() &&
        (tools::Time::GetSystemTicks() - mnLastTicks > 500) &&
        ( aState.mnState & ( MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT ) ) &&
        !(aState.mnState & KEY_MOD1) && // i43499 CTRL disables docking now
        bRealMove )
    {
        maDockPos = pDockingArea->OutputToScreenPixel( pDockingArea->AbsoluteScreenToOutputPixel( OutputToAbsoluteScreenPixel( Point() ) ) );
        maDockRect = tools::Rectangle( maDockPos, mpDockWin->GetSizePixel() );

        // mouse pos in screen pixels
        Point aMousePos = pDockingArea->OutputToScreenPixel( aState.maPos );

        if( ! mpDockWin->IsDocking() )
            mpDockWin->StartDocking( aMousePos, maDockRect );

        bool bFloatMode = mpDockWin->Docking( aMousePos, maDockRect );

        if( ! bFloatMode )
        {
            // indicates that the window could be docked at maDockRect
            maDockRect.SetPos( mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->ScreenToOutputPixel(
                 maDockRect.TopLeft() ) );
            mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect, ShowTrackFlags::Big | ShowTrackFlags::TrackWindow );
            m_aEndDockTimer.Stop();
            m_aDockTimer.Invoke();
        }
        else
        {
            mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
            m_aDockTimer.Stop();
            m_aEndDockTimer.Invoke();
        }
    }
    mbInMove = false;
}

void ImplDockFloatWin2::Move()
{
    if( mbInMove )
        return;

    mbInMove = true;
    FloatingWindow::Move();
    mpDockWin->GetWindow()->Move();

    /*
     *  note: the window should only dock if KEY_MOD1 is pressed
     *  and the user releases all mouse buttons. The real problem here
     *  is that we don't get mouse events (at least not on X)
     *  if the mouse is on the decoration. So we have to start an
     *  awkward timer based process that polls the modifier/buttons
     *  to see whether they are in the right condition shortly after the
     *  last Move message.
     */

    if( ! mnLastUserEvent )
        mnLastUserEvent = Application::PostUserEvent( LINK( this, ImplDockFloatWin2, DockingHdl ), nullptr, true );
}

void ImplDockFloatWin2::Resize()
{
    // forwarding of resize only required if we have no borderwindow ( GetWindow() then returns 'this' )
    if( GetWindow( GetWindowType::Border ) == this )
    {
        FloatingWindow::Resize();
        Size aSize( GetSizePixel() );
        mpDockWin->GetWindow()->ImplPosSizeWindow( 0, 0, aSize.Width(), aSize.Height(), PosSizeFlags::PosSize ); // TODO: is this needed ???
    }
}

void ImplDockFloatWin2::TitleButtonClick( TitleButton nButton )
{
    FloatingWindow::TitleButtonClick( nButton );
    mpDockWin->TitleButtonClick( nButton );
}

void ImplDockFloatWin2::Resizing( Size& rSize )
{
    FloatingWindow::Resizing( rSize );
    mpDockWin->Resizing( rSize );
}

bool ImplDockFloatWin2::Close()
{
    return true;
}

DockingManager::DockingManager()
{
}

DockingManager::~DockingManager()
{
}

ImplDockingWindowWrapper* DockingManager::GetDockingWindowWrapper( const vcl::Window *pWindow )
{
    forconst auto& xWrapper : mvDockingWindows )
    {
        if (xWrapper && xWrapper->mpDockingWindow == pWindow)
            return xWrapper.get();
    }
    return nullptr;
}

bool DockingManager::IsDockable( const vcl::Window *pWindow )
{
    ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );

    /*
    if( pWindow->HasDockingHandler() )
        return true;
    */

    return (pWrapper != nullptr);
}

bool DockingManager::IsFloating( const vcl::Window *pWindow )
{
    ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
    if( pWrapper )
        return pWrapper->IsFloatingMode();
    else
        return false;
}

bool DockingManager::IsLocked( const vcl::Window *pWindow )
{
    ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
    return pWrapper && pWrapper->IsLocked();
}

void DockingManager::Lock( const vcl::Window *pWindow )
{
    ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
    if( pWrapper )
        pWrapper->Lock();
}

void DockingManager::Unlock( const vcl::Window *pWindow )
{
    ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
    if( pWrapper )
        pWrapper->Unlock();
}

void DockingManager::SetFloatingMode( const vcl::Window *pWindow, bool bFloating )
{
    ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
    if( pWrapper )
        pWrapper->SetFloatingMode( bFloating );
}

void DockingManager::StartPopupMode( const vcl::Window *pWindow, const tools::Rectangle& rRect, FloatWinPopupFlags nFlags )
{
    ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
    if( pWrapper )
        pWrapper->StartPopupMode( rRect, nFlags );
}

void DockingManager::StartPopupMode( ToolBox *pParentToolBox, const vcl::Window *pWindow, FloatWinPopupFlags nFlags )
{
    ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
    if( pWrapper )
        pWrapper->StartPopupMode( pParentToolBox, nFlags );
}

void DockingManager::StartPopupMode( ToolBox *pParentToolBox, const vcl::Window *pWindow )
{
    StartPopupMode( pParentToolBox, pWindow, FloatWinPopupFlags::AllowTearOff         |
                    FloatWinPopupFlags::AllMouseButtonClose  |
                    FloatWinPopupFlags::NoMouseUpClose );
}

bool DockingManager::IsInPopupMode( const vcl::Window *pWindow )
{
    ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
    return pWrapper && pWrapper->IsInPopupMode();
}

void DockingManager::EndPopupMode( const vcl::Window *pWin )
{
    ImplDockingWindowWrapper *pWrapper = GetDockingWindowWrapper( pWin );
    if( pWrapper && pWrapper->GetFloatingWindow() && static_cast<FloatingWindow*>(pWrapper->GetFloatingWindow())->IsInPopupMode() )
        static_cast<FloatingWindow*>(pWrapper->GetFloatingWindow())->EndPopupMode();
}

SystemWindow* DockingManager::GetFloatingWindow(const vcl::Window *pWin)
{
    ImplDockingWindowWrapper *pWrapper = GetDockingWindowWrapper( pWin );
    if (pWrapper)
        return pWrapper->GetFloatingWindow();
    return nullptr;
}

void DockingManager::SetPopupModeEndHdl( const vcl::Window *pWindow, const Link<FloatingWindow*,void>& rLink )
{
    ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
    if( pWrapper )
        pWrapper->SetPopupModeEndHdl(rLink);
}

void DockingManager::AddWindow( const vcl::Window *pWindow )
{
    ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
    if( pWrapper )
        return;
    mvDockingWindows.emplace_back( new ImplDockingWindowWrapper( pWindow ) );
}

void DockingManager::RemoveWindow( const vcl::Window *pWindow )
{
    forauto it = mvDockingWindows.begin(); it != mvDockingWindows.end(); ++it )
    {
        const auto& xWrapper = *it;
        if (xWrapper && xWrapper->mpDockingWindow == pWindow)
        {
            // deleting wrappers calls set of actions which may want to use
            // wrapper we want to delete - avoid crash using temporary owner
            // while erasing
            auto pTemporaryOwner = std::move(*it);
            mvDockingWindows.erase( it );
            break;
        }
    }
}

void DockingManager::SetPosSizePixel( vcl::Window const *pWindow, tools::Long nX, tools::Long nY,
                                    tools::Long nWidth, tools::Long nHeight,
                                    PosSizeFlags nFlags )
{
    ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
    if( pWrapper )
        pWrapper->setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
}

tools::Rectangle DockingManager::GetPosSizePixel( const vcl::Window *pWindow )
{
    tools::Rectangle aRect;
    ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
    if( pWrapper )
        aRect = tools::Rectangle( pWrapper->GetPosPixel(), pWrapper->GetSizePixel() );

    return aRect;
}

class ImplPopupFloatWin : public FloatingWindow
{
private:
    bool mbToolBox;

public:
    ImplPopupFloatWin( vcl::Window* pParent, bool bToolBox );
    virtual ~ImplPopupFloatWin() override;
    virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessible() override;
};

ImplPopupFloatWin::ImplPopupFloatWin( vcl::Window* pParent, bool bToolBox ) :
    FloatingWindow( pParent, bToolBox ? WB_BORDER | WB_POPUP | WB_SYSTEMWINDOW | WB_NOSHADOW : WB_STDPOPUP ),
    mbToolBox( bToolBox )
{
}

ImplPopupFloatWin::~ImplPopupFloatWin()
{
    disposeOnce();
}

css::uno::Reference< css::accessibility::XAccessible > ImplPopupFloatWin::CreateAccessible()
{
    if ( !mbToolBox )
        return FloatingWindow::CreateAccessible();

    // switch off direct accessibility support for this window

    // this is to avoid appearance of this window as standalone window in the accessibility hierarchy
    // as this window is only used as a helper for subtoolbars that are not teared-off, the parent toolbar
    // has to provide accessibility support (as implemented in the toolkit)
    // so the contained toolbar should appear as child of the corresponding toolbar item of the parent toolbar
    return css::uno::Reference< css::accessibility::XAccessible >();
}

ImplDockingWindowWrapper::ImplDockingWindowWrapper( const vcl::Window *pWindow )
    : mpDockingWindow(const_cast<vcl::Window*>(pWindow))
    , mpFloatWin(nullptr)
    , mpOldBorderWin(nullptr)
    , mpParent(pWindow->GetParent())
    , maMaxOutSize( SHRT_MAX, SHRT_MAX )
    , mnTrackX(0)
    , mnTrackY(0)
    , mnTrackWidth(0)
    , mnTrackHeight(0)
    , mnDockLeft(0)
    , mnDockTop(0)
    , mnDockRight(0)
    , mnDockBottom(0)
    , mnFloatBits(WB_BORDER | WB_CLOSEABLE | WB_SIZEABLE | (pWindow->GetStyle() & DOCKWIN_FLOATSTYLES))
    , mbDockCanceled(false)
    , mbDocking(false)
    , mbLastFloatMode(false)
    , mbDockBtn(false)
    , mbHideBtn(false)
    // must be enabled in Window::Notify to prevent permanent docking during mouse move
    , mbStartDockingEnabled(false)
    , mbLocked(false)
{
    assert(mpDockingWindow);
    DockingWindow *pDockWin = dynamic_cast< DockingWindow* > ( mpDockingWindow.get() );
    if( pDockWin )
        mnFloatBits = pDockWin->GetFloatStyle();
}

ImplDockingWindowWrapper::~ImplDockingWindowWrapper()
{
    if ( IsFloatingMode() )
    {
        GetWindow()->Show( false, ShowFlags::NoFocusChange );
        SetFloatingMode(false);
    }
}

void ImplDockingWindowWrapper::ImplStartDocking( const Point& rPos )
{
    if( !mbStartDockingEnabled )
        return;

    maMouseOff      = rPos;
    mbDocking       = true;
    mbLastFloatMode = IsFloatingMode();

    // calculate FloatingBorder
    VclPtr<FloatingWindow> pWin;
    if ( mpFloatWin )
        pWin = mpFloatWin;
    else
        pWin = VclPtr<ImplDockFloatWin2>::Create( mpParent, mnFloatBits, nullptr );
    pWin->GetBorder( mnDockLeft, mnDockTop, mnDockRight, mnDockBottom );
    if ( !mpFloatWin )
        pWin.disposeAndClear();

    Point   aPos    = GetWindow()->OutputToScreenPixel( Point() );
    Size    aSize   = GetWindow()->GetOutputSizePixel();
    mnTrackX        = aPos.X();
    mnTrackY        = aPos.Y();
    mnTrackWidth    = aSize.Width();
    mnTrackHeight   = aSize.Height();

    if ( mbLastFloatMode )
    {
        maMouseOff.AdjustX(mnDockLeft );
        maMouseOff.AdjustY(mnDockTop );
        mnTrackX        -= mnDockLeft;
        mnTrackY        -= mnDockTop;
        mnTrackWidth    += mnDockLeft+mnDockRight;
        mnTrackHeight   += mnDockTop+mnDockBottom;
    }

    vcl::Window *pDockingArea = GetWindow()->GetParent();
    vcl::Window::PointerState aState = pDockingArea->GetPointerState();

    // mouse pos in screen pixels
    Point aMousePos = pDockingArea->OutputToScreenPixel( aState.maPos );
    Point aDockPos = pDockingArea->AbsoluteScreenToOutputPixel( GetWindow()->OutputToAbsoluteScreenPixel( GetWindow()->GetPosPixel() ) );
    tools::Rectangle aDockRect( aDockPos, GetWindow()->GetSizePixel() );
    StartDocking( aMousePos, aDockRect );

    GetWindow()->ImplUpdateAll();
    GetWindow()->ImplGetFrameWindow()->ImplUpdateAll();

    GetWindow()->StartTracking( StartTrackingFlags::KeyMod );
}

void ImplDockingWindowWrapper::Tracking( const TrackingEvent& rTEvt )
{
    // used during docking of a currently docked window
    if ( !mbDocking )
        return;

    if ( rTEvt.IsTrackingEnded() )
    {
        mbDocking = false;
        GetWindow()->HideTracking();
        if ( rTEvt.IsTrackingCanceled() )
        {
            mbDockCanceled = true;
            EndDocking( tools::Rectangle( Point( mnTrackX, mnTrackY ), Size( mnTrackWidth, mnTrackHeight ) ), mbLastFloatMode );
            mbDockCanceled = false;
        }
        else
            EndDocking( tools::Rectangle( Point( mnTrackX, mnTrackY ), Size( mnTrackWidth, mnTrackHeight ) ), mbLastFloatMode );
    }
    // Docking only upon non-synthetic MouseEvents
    else if ( !rTEvt.GetMouseEvent().IsSynthetic() || rTEvt.GetMouseEvent().IsModifierChanged() )
    {
        Point   aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
        Point   aFrameMousePos = GetWindow()->OutputToScreenPixel( aMousePos );
        Size    aFrameSize = GetWindow()->ImplGetFrameWindow()->GetOutputSizePixel();
        if ( aFrameMousePos.X() < 0 )
            aFrameMousePos.setX( 0 );
        if ( aFrameMousePos.Y() < 0 )
            aFrameMousePos.setY( 0 );
        if ( aFrameMousePos.X() > aFrameSize.Width()-1 )
            aFrameMousePos.setX( aFrameSize.Width()-1 );
        if ( aFrameMousePos.Y() > aFrameSize.Height()-1 )
            aFrameMousePos.setY( aFrameSize.Height()-1 );
        aMousePos = GetWindow()->ScreenToOutputPixel( aFrameMousePos );
        aMousePos.AdjustX( -(maMouseOff.X()) );
        aMousePos.AdjustY( -(maMouseOff.Y()) );
        Point aPos = GetWindow()->OutputToScreenPixel( aMousePos );
        tools::Rectangle aTrackRect( aPos, Size( mnTrackWidth, mnTrackHeight ) );
        tools::Rectangle aCompRect = aTrackRect;
        aPos.AdjustX(maMouseOff.X() );
        aPos.AdjustY(maMouseOff.Y() );

        bool bFloatMode = Docking( aPos, aTrackRect );

        if ( mbLastFloatMode != bFloatMode )
        {
            if ( bFloatMode )
            {
                aTrackRect.AdjustLeft( -mnDockLeft );
                aTrackRect.AdjustTop( -mnDockTop );
                aTrackRect.AdjustRight(mnDockRight );
                aTrackRect.AdjustBottom(mnDockBottom );
            }
            else
            {
                if ( aCompRect == aTrackRect )
                {
                    aTrackRect.AdjustLeft(mnDockLeft );
                    aTrackRect.AdjustTop(mnDockTop );
                    aTrackRect.AdjustRight( -mnDockRight );
                    aTrackRect.AdjustBottom( -mnDockBottom );
                }
            }
            mbLastFloatMode = bFloatMode;
        }

        ShowTrackFlags nTrackStyle;
        if ( bFloatMode )
            nTrackStyle = ShowTrackFlags::Object;
        else
            nTrackStyle = ShowTrackFlags::Big;
        tools::Rectangle aShowTrackRect = aTrackRect;
        aShowTrackRect.SetPos( GetWindow()->ScreenToOutputPixel( aShowTrackRect.TopLeft() ) );

        GetWindow()->ShowTracking( aShowTrackRect, nTrackStyle );

        // calculate mouse offset again, as the rectangle was changed
        maMouseOff.setX( aPos.X() - aTrackRect.Left() );
        maMouseOff.setY( aPos.Y() - aTrackRect.Top() );

        mnTrackX        = aTrackRect.Left();
        mnTrackY        = aTrackRect.Top();
        mnTrackWidth    = aTrackRect.GetWidth();
        mnTrackHeight   = aTrackRect.GetHeight();
    }
}

void ImplDockingWindowWrapper::StartDocking( const Point& rPoint, tools::Rectanglconst & rRect )
{
    DockingData data( rPoint, rRect, IsFloatingMode() );

    GetWindow()->CallEventListeners( VclEventId::WindowStartDocking, &data );
    mbDocking = true;
}

bool ImplDockingWindowWrapper::Docking( const Point& rPoint, tools::Rectangle& ;rRect )
{
    DockingData data( rPoint, rRect, IsFloatingMode() );

    GetWindow()->CallEventListeners( VclEventId::WindowDocking, &data );
    rRect = data.maTrackRect;
    return data.mbFloating;
}

void ImplDockingWindowWrapper::EndDocking( const tools::Rectangle& rRect, bool bFloatMode )
{
    tools::Rectangle aRect( rRect );

    bool bOrigDockCanceled = mbDockCanceled;
    if (bFloatMode && !StyleSettings::GetDockingFloatsSupported())
        mbDockCanceled = true;

    if ( !IsDockingCanceled() )
    {
        bool bShow = false;
        if ( bFloatMode != IsFloatingMode() )
        {
            GetWindow()->Show( false, ShowFlags::NoFocusChange );
            SetFloatingMode( bFloatMode );
            bShow = true;
            if ( bFloatMode )
            {
                // #i44800# always use outputsize - as in all other places
                mpFloatWin->SetOutputSizePixel( aRect.GetSize() );
                mpFloatWin->SetPosPixel( aRect.TopLeft() );
            }
        }
        if ( !bFloatMode )
        {
            Point aPos = aRect.TopLeft();
            aPos = GetWindow()->GetParent()->ScreenToOutputPixel( aPos );
            GetWindow()->SetPosSizePixel( aPos, aRect.GetSize() );
        }

        if ( bShow )
            GetWindow()->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
    }

    EndDockingData data( aRect, IsFloatingMode(), IsDockingCanceled() );
    GetWindow()->CallEventListeners( VclEventId::WindowEndDocking, &data );

    mbDocking = false;

    // must be enabled in Window::Notify to prevent permanent docking during mouse move
    mbStartDockingEnabled = false;

    mbDockCanceled = bOrigDockCanceled;
}

bool ImplDockingWindowWrapper::PrepareToggleFloatingMode()
{
    bool bFloating = true;
    GetWindow()->CallEventListeners( VclEventId::WindowPrepareToggleFloating, &bFloating );
    return bFloating;
}

void ImplDockingWindowWrapper::ToggleFloatingMode()
{
    // notify dockingwindow/toolbox
    // note: this must be done *before* notifying the
    //       listeners to have the toolbox in the proper state
    if( GetWindow()->IsDockingWindow() )
        static_cast<DockingWindow*>(GetWindow())->ToggleFloatingMode();

    // now notify listeners
    GetWindow()->CallEventListeners( VclEventId::WindowToggleFloating );

    // must be enabled in Window::Notify to prevent permanent docking during mouse move
    mbStartDockingEnabled = false;
}

void ImplDockingWindowWrapper::TitleButtonClick( TitleButton nType )
{
    if( nType == TitleButton::Menu )
    {
        ToolBox *pToolBox = dynamic_cast< ToolBox* >( GetWindow() );
        if( pToolBox )
        {
            pToolBox->ExecuteCustomMenu();
        }
    }
    if( nType == TitleButton::Docking )
    {
        SetFloatingMode( !IsFloatingMode() );
    }
}

void ImplDockingWindowWrapper::Resizing( Size& rSize )
{
    // TODO: add virtual Resizing() to class Window, so we can get rid of class DockingWindow
    DockingWindow *pDockingWindow = dynamic_cast< DockingWindow* >( GetWindow() );
    if( pDockingWindow )
        pDockingWindow->Resizing( rSize );
}

void ImplDockingWindowWrapper::ShowMenuTitleButton( bool bVisible )
{
    if ( mpFloatWin )
        mpFloatWin->ShowTitleButton( TitleButton::Menu, bVisible );
}

void ImplDockingWindowWrapper::ImplPreparePopupMode()
{
    VclPtr<vcl::Window> xWindow = GetWindow();
    xWindow->Show( false, ShowFlags::NoFocusChange );

    // prepare reparenting
    vcl::Window* pRealParent = xWindow->GetWindow( GetWindowType::Parent );
    mpOldBorderWin = xWindow->GetWindow( GetWindowType::Border );
    if( mpOldBorderWin.get() == xWindow )
        mpOldBorderWin = nullptr;  // no border window found

    // the new parent for popup mode
    VclPtrInstance<ImplPopupFloatWin> pWin( mpParent, xWindow->GetType() == WindowType::TOOLBOX );
    pWin->SetPopupModeEndHdl( LINK( this, ImplDockingWindowWrapper, PopupModeEnd ) );

    // At least for DockingWindow, GetText() has a side effect of setting deferred
    // properties. This must be done before setting the border window (see below),
    // so that the border width will end up in mpWindowImpl->mnBorderWidth, not in
    // the border window (See DockingWindow::setPosSizeOnContainee() and
    // DockingWindow::GetOptimalSize()).
    pWin->SetText( xWindow->GetText() );
    pWin->SetOutputSizePixel( xWindow->GetSizePixel() );

    xWindow->mpWindowImpl->mpBorderWindow  = nullptr;
    xWindow->mpWindowImpl->mnLeftBorder    = 0;
    xWindow->mpWindowImpl->mnTopBorder     = 0;
    xWindow->mpWindowImpl->mnRightBorder   = 0;
    xWindow->mpWindowImpl->mnBottomBorder  = 0;

    // reparent borderwindow and window
    if ( mpOldBorderWin )
        mpOldBorderWin->SetParent( pWin );
    xWindow->SetParent( pWin );

    // correct border window pointers
    xWindow->mpWindowImpl->mpBorderWindow = pWin;
    pWin->mpWindowImpl->mpClientWindow = xWindow;
    xWindow->mpWindowImpl->mpRealParent = pRealParent;

    // set mpFloatWin not until all window positioning is done !!!
    // (SetPosPixel etc. check for valid mpFloatWin pointer)
    mpFloatWin = pWin;
}

void ImplDockingWindowWrapper::StartPopupMode( ToolBox *pParentToolBox, FloatWinPopupFlags nFlags )
{
    // do nothing if window is floating
    if( IsFloatingMode() )
        return;

    ImplPreparePopupMode();

    // don't allow tearoff, if globally disabled
    if( !StyleSettings::GetDockingFloatsSupported() )
        nFlags &= ~FloatWinPopupFlags::AllowTearOff;

    // if the subtoolbar was opened via keyboard make sure that key events
    // will go into subtoolbar
    if( pParentToolBox->IsKeyEvent() )
        nFlags |= FloatWinPopupFlags::GrabFocus;

    mpFloatWin->StartPopupMode( pParentToolBox, nFlags );
    GetWindow()->Show();
    // grab focus (again) after showing docking window, as e.g. a11y focus
    // events require window to be visible first
    if (nFlags & FloatWinPopupFlags::GrabFocus)
        mpFloatWin->GrabFocus();

    if( pParentToolBox->IsKeyEvent() )
    {
        // send HOME key to subtoolbar in order to select first item
        KeyEvent aEvent( 0, vcl::KeyCode( KEY_HOME ) );
        GetWindow()->KeyInput(aEvent);
    }
}

void ImplDockingWindowWrapper::StartPopupMode( const tools::Rectangle& rRect, FloatWinPopupFlags nFlags )
{
    // do nothing if window is floating
    if( IsFloatingMode() )
        return;

    ImplPreparePopupMode();
    mpFloatWin->StartPopupMode( rRect, nFlags );
    GetWindow()->Show();
    // grab focus (again) after showing docking window, as e.g. a11y focus
    // events require window to be visible first
    if (nFlags & FloatWinPopupFlags::GrabFocus)
        mpFloatWin->GrabFocus();
}

IMPL_LINK_NOARG(ImplDockingWindowWrapper, PopupModeEnd, FloatingWindow*, void)
{
    VclPtr<vcl::Window> xWindow = GetWindow();
    xWindow->Show( false, ShowFlags::NoFocusChange );

    // set parameter for handler before destroying floating window
    EndPopupModeData aData( mpFloatWin->GetWindow( GetWindowType::Border )->GetPosPixel(), mpFloatWin->IsPopupModeTearOff() );

    // before deleting change parent back, so we can delete the floating window alone
    vcl::Window* pRealParent = xWindow->GetWindow( GetWindowType::Parent );
    xWindow->mpWindowImpl->mpBorderWindow = nullptr;
    if ( mpOldBorderWin )
    {
        xWindow->SetParent( mpOldBorderWin );
        static_cast<ImplBorderWindow*>(mpOldBorderWin.get())->GetBorder(
            xWindow->mpWindowImpl->mnLeftBorder, xWindow->mpWindowImpl->mnTopBorder,
            xWindow->mpWindowImpl->mnRightBorder, xWindow->mpWindowImpl->mnBottomBorder );
        mpOldBorderWin->Resize();
    }
    xWindow->mpWindowImpl->mpBorderWindow = mpOldBorderWin;
    xWindow->SetParent( pRealParent );
    xWindow->mpWindowImpl->mpRealParent = pRealParent;

    // take ownership to local variable to protect against maPopupModeEndHdl destroying this object
    auto xFloatWin = std::move(mpFloatWin);
    maPopupModeEndHdl.Call(xFloatWin);
    xFloatWin.disposeAndClear();

    // call handler - which will destroy the window and thus the wrapper as well !
    xWindow->CallEventListeners( VclEventId::WindowEndPopupMode, &aData );
}

bool ImplDockingWindowWrapper::IsInPopupMode() const
{
    if( GetFloatingWindow() )
        return static_cast<FloatingWindow*>(GetFloatingWindow())->IsInPopupMode();
    else
        return false;
}

void ImplDockingWindowWrapper::SetFloatingMode( bool bFloatMode )
{
    // do nothing if window is docked and locked
    if( !IsFloatingMode() && IsLocked() )
        return;

    if ( IsFloatingMode() == bFloatMode )
        return;

    if ( !PrepareToggleFloatingMode() )
        return;

    bool bVisible = GetWindow()->IsVisible();

    if ( bFloatMode )
    {
        GetWindow()->Show( false, ShowFlags::NoFocusChange );

        maDockPos = GetWindow()->GetPosPixel();

        vcl::Window* pRealParent = GetWindow()->GetWindow( GetWindowType::Parent );
        mpOldBorderWin = GetWindow()->GetWindow( GetWindowType::Border );
        if( mpOldBorderWin == mpDockingWindow )
            mpOldBorderWin = nullptr;  // no border window found

        VclPtrInstance<ImplDockFloatWin2> pWin(
                                 mpParent,
                                 mnFloatBits & ( WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE ) ?
                                  mnFloatBits | WB_SYSTEMWINDOW
                                  | WB_OWNERDRAWDECORATION
                                  : mnFloatBits,
                                 this );

        // At least for DockingWindow, GetText() has a side effect of setting deferred
        // properties. This must be done before setting the border window (see below),
        // so that the border width will end up in mpWindowImpl->mnBorderWidth, not in
        // the border window (See DockingWindow::setPosSizeOnContainee() and
        // DockingWindow::GetOptimalSize()).
        pWin->SetText( GetWindow()->GetText() );

        GetWindow()->mpWindowImpl->mpBorderWindow  = nullptr;
        GetWindow()->mpWindowImpl->mnLeftBorder    = 0;
        GetWindow()->mpWindowImpl->mnTopBorder     = 0;
        GetWindow()->mpWindowImpl->mnRightBorder   = 0;
        GetWindow()->mpWindowImpl->mnBottomBorder  = 0;

        // if the parent gets destroyed, we also have to reset the parent of the BorderWindow
        if ( mpOldBorderWin )
            mpOldBorderWin->SetParent( pWin );
        GetWindow()->SetParent( pWin );
        pWin->SetPosPixel( Point() );

        GetWindow()->mpWindowImpl->mpBorderWindow = pWin;
        pWin->mpWindowImpl->mpClientWindow = mpDockingWindow;
        GetWindow()->mpWindowImpl->mpRealParent = pRealParent;

        pWin->SetOutputSizePixel( GetWindow()->GetSizePixel() );
        pWin->SetPosPixel( maFloatPos );
        // pass on DockingData to FloatingWindow
        pWin->ShowTitleButton( TitleButton::Docking, mbDockBtn );
        pWin->ShowTitleButton( TitleButton::Hide, mbHideBtn );
        pWin->SetMinOutputSizePixel( maMinOutSize );
        pWin->SetMaxOutputSizePixel( maMaxOutSize );

        mpFloatWin      = pWin;

        if ( bVisible )
            GetWindow()->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );

        ToggleFloatingMode();
    }
    else
    {
        GetWindow()->Show( false, ShowFlags::NoFocusChange );

        // store FloatingData in FloatingWindow
        maFloatPos      = mpFloatWin->GetPosPixel();
        mbDockBtn       = mpFloatWin->IsTitleButtonVisible( TitleButton::Docking );
        mbHideBtn       = mpFloatWin->IsTitleButtonVisible( TitleButton::Hide );
        maMinOutSize    = mpFloatWin->GetMinOutputSizePixel();
        maMaxOutSize    = mpFloatWin->GetMaxOutputSizePixel();

        vcl::Window* pRealParent = GetWindow()->GetWindow( GetWindowType::Parent ); //mpWindowImpl->mpRealParent;
        GetWindow()->mpWindowImpl->mpBorderWindow = nullptr;
        if ( mpOldBorderWin )
        {
            GetWindow()->SetParent( mpOldBorderWin );
            static_cast<ImplBorderWindow*>(mpOldBorderWin.get())->GetBorder(
                GetWindow()->mpWindowImpl->mnLeftBorder, GetWindow()->mpWindowImpl->mnTopBorder,
                GetWindow()->mpWindowImpl->mnRightBorder, GetWindow()->mpWindowImpl->mnBottomBorder );
            mpOldBorderWin->Resize();
        }
        GetWindow()->mpWindowImpl->mpBorderWindow = mpOldBorderWin;
        GetWindow()->SetParent( pRealParent );
        GetWindow()->mpWindowImpl->mpRealParent = pRealParent;

        mpFloatWin.disposeAndClear();
        GetWindow()->SetPosPixel( maDockPos );

        if ( bVisible )
            GetWindow()->Show();

        ToggleFloatingMode();

    }
}

void ImplDockingWindowWrapper::SetFloatStyle( WinBits nStyle )
{
    mnFloatBits = nStyle;
}


void ImplDockingWindowWrapper::setPosSizePixel( tools::Long nX, tools::Long nY,
                                     tools::Long nWidth, tools::Long nHeight,
                                     PosSizeFlags nFlags )
{
    if ( mpFloatWin )
        mpFloatWin->setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
    else
        GetWindow()->setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
}

Point ImplDockingWindowWrapper::GetPosPixel() const
{
    if ( mpFloatWin )
        return mpFloatWin->GetPosPixel();
    else
        return mpDockingWindow->GetPosPixel();
}

Size ImplDockingWindowWrapper::GetSizePixel() const
{
    if ( mpFloatWin )
        return mpFloatWin->GetSizePixel();
    else
        return mpDockingWindow->GetSizePixel();
}

// old inlines from DockingWindow

void ImplDockingWindowWrapper::SetMinOutputSizePixel( const Size& rSize )
{
    if ( mpFloatWin )
        mpFloatWin->SetMinOutputSizePixel( rSize );
    maMinOutSize = rSize;
}

void ImplDockingWindowWrapper::SetMaxOutputSizePixel( const Size& rSize )
{
    if ( mpFloatWin )
        mpFloatWin->SetMaxOutputSizePixel( rSize );
    maMaxOutSize = rSize;
}

bool ImplDockingWindowWrapper::IsFloatingMode() const
{
    return (mpFloatWin != nullptr);
}

void    ImplDockingWindowWrapper::SetDragArea( const tools::Rectangle& rRect )
{
    maDragArea = rRect;
}


void ImplDockingWindowWrapper::Lock()
{
    mbLocked = true;
    // only toolbars support locking
    ToolBox *pToolBox = dynamic_cast< ToolBox * >( GetWindow() );
    if( pToolBox )
        pToolBox->Lock( mbLocked );
}

void ImplDockingWindowWrapper::Unlock()
{
    mbLocked = false;
    // only toolbars support locking
    ToolBox *pToolBox = dynamic_cast< ToolBox * >( GetWindow() );
    if( pToolBox )
        pToolBox->Lock( mbLocked );
}

SystemWindow* ImplDockingWindowWrapper::GetFloatingWindow() const
{
    return mpFloatWin;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=92 H=97 G=94

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.