diff options
Diffstat (limited to 'vcl/source/window/brdwin.cxx')
-rw-r--r-- | vcl/source/window/brdwin.cxx | 2080 |
1 files changed, 2080 insertions, 0 deletions
diff --git a/vcl/source/window/brdwin.cxx b/vcl/source/window/brdwin.cxx new file mode 100644 index 000000000..8be4de5d8 --- /dev/null +++ b/vcl/source/window/brdwin.cxx @@ -0,0 +1,2080 @@ +/* -*- 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 <strings.hrc> +#include <svdata.hxx> +#include <brdwin.hxx> +#include <window.h> + +#include <vcl/textrectinfo.hxx> +#include <vcl/event.hxx> +#include <vcl/decoview.hxx> +#include <vcl/syswin.hxx> +#include <vcl/dockwin.hxx> +#include <vcl/floatwin.hxx> +#include <vcl/help.hxx> +#include <vcl/edit.hxx> +#include <vcl/settings.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/ptrstyle.hxx> + +using namespace ::com::sun::star::uno; + +// useful caption height for title bar buttons +#define MIN_CAPTION_HEIGHT 18 + +namespace vcl { + +void Window::ImplCalcSymbolRect( tools::Rectangle& rRect ) +{ + // Add border, not shown in the non-default representation, + // as we want to use it for small buttons + rRect.AdjustLeft( -1 ); + rRect.AdjustTop( -1 ); + rRect.AdjustRight( 1 ); + rRect.AdjustBottom( 1 ); + + // we leave 5% room between the symbol and the button border + long nExtraWidth = ((rRect.GetWidth()*50)+500)/1000; + long nExtraHeight = ((rRect.GetHeight()*50)+500)/1000; + rRect.AdjustLeft(nExtraWidth ); + rRect.AdjustRight( -nExtraWidth ); + rRect.AdjustTop(nExtraHeight ); + rRect.AdjustBottom( -nExtraHeight ); +} + +} /* namespace vcl */ + +static void ImplDrawBrdWinSymbol( vcl::RenderContext* pDev, + const tools::Rectangle& rRect, SymbolType eSymbol ) +{ + // we leave 5% room between the symbol and the button border + DecorationView aDecoView( pDev ); + tools::Rectangle aTempRect = rRect; + vcl::Window::ImplCalcSymbolRect( aTempRect ); + aDecoView.DrawSymbol( aTempRect, eSymbol, + pDev->GetSettings().GetStyleSettings().GetButtonTextColor() ); +} + +static void ImplDrawBrdWinSymbolButton( vcl::RenderContext* pDev, + const tools::Rectangle& rRect, + SymbolType eSymbol, DrawButtonFlags nState ) +{ + bool bMouseOver(nState & DrawButtonFlags::Highlight); + nState &= ~DrawButtonFlags::Highlight; + + tools::Rectangle aTempRect; + vcl::Window *pWin = dynamic_cast< vcl::Window* >(pDev); + if( pWin ) + { + if( bMouseOver ) + { + // provide a bright background for selection effect + pDev->SetFillColor( pDev->GetSettings().GetStyleSettings().GetWindowColor() ); + pDev->SetLineColor(); + pDev->DrawRect( rRect ); + pWin->DrawSelectionBackground( rRect, 2, bool(nState & DrawButtonFlags::Pressed), + true ); + } + aTempRect = rRect; + aTempRect.AdjustLeft(3 ); + aTempRect.AdjustRight( -4 ); + aTempRect.AdjustTop(3 ); + aTempRect.AdjustBottom( -4 ); + } + else + { + DecorationView aDecoView( pDev ); + aTempRect = aDecoView.DrawButton( rRect, nState|DrawButtonFlags::Flat ); + } + ImplDrawBrdWinSymbol( pDev, aTempRect, eSymbol ); +} + + +ImplBorderWindowView::~ImplBorderWindowView() +{ +} + +bool ImplBorderWindowView::MouseMove( const MouseEvent& ) +{ + return false; +} + +bool ImplBorderWindowView::MouseButtonDown( const MouseEvent& ) +{ + return false; +} + +bool ImplBorderWindowView::Tracking( const TrackingEvent& ) +{ + return false; +} + +OUString ImplBorderWindowView::RequestHelp( const Point&, tools::Rectangle& ) +{ + return OUString(); +} + +tools::Rectangle ImplBorderWindowView::GetMenuRect() const +{ + return tools::Rectangle(); +} + +void ImplBorderWindowView::ImplInitTitle(ImplBorderFrameData* pData) +{ + ImplBorderWindow* pBorderWindow = pData->mpBorderWindow; + + if ( !(pBorderWindow->GetStyle() & (WB_MOVEABLE | WB_POPUP)) || + (pData->mnTitleType == BorderWindowTitleType::NONE) ) + { + pData->mnTitleType = BorderWindowTitleType::NONE; + pData->mnTitleHeight = 0; + } + else + { + const StyleSettings& rStyleSettings = pData->mpOutDev->GetSettings().GetStyleSettings(); + if (pData->mnTitleType == BorderWindowTitleType::Tearoff) + pData->mnTitleHeight = ToolBox::ImplGetDragWidth(*pData->mpBorderWindow, false) + 2; + else + { + if (pData->mnTitleType == BorderWindowTitleType::Small) + { + pBorderWindow->SetPointFont(*pBorderWindow, rStyleSettings.GetFloatTitleFont() ); + pData->mnTitleHeight = rStyleSettings.GetFloatTitleHeight(); + } + else // pData->mnTitleType == BorderWindowTitleType::Normal + { + // FIXME RenderContext + pBorderWindow->SetPointFont(*pBorderWindow, rStyleSettings.GetTitleFont()); + pData->mnTitleHeight = rStyleSettings.GetTitleHeight(); + } + long nTextHeight = pBorderWindow->GetTextHeight(); + if (nTextHeight > pData->mnTitleHeight) + pData->mnTitleHeight = nTextHeight; + } + } +} + +BorderWindowHitTest ImplBorderWindowView::ImplHitTest( ImplBorderFrameData const * pData, const Point& rPos ) +{ + ImplBorderWindow* pBorderWindow = pData->mpBorderWindow; + + if ( pData->maTitleRect.IsInside( rPos ) ) + { + if ( pData->maCloseRect.IsInside( rPos ) ) + return BorderWindowHitTest::Close; + else if ( pData->maRollRect.IsInside( rPos ) ) + return BorderWindowHitTest::Roll; + else if ( pData->maMenuRect.IsInside( rPos ) ) + return BorderWindowHitTest::Menu; + else if ( pData->maDockRect.IsInside( rPos ) ) + return BorderWindowHitTest::Dock; + else if ( pData->maHideRect.IsInside( rPos ) ) + return BorderWindowHitTest::Hide; + else if ( pData->maHelpRect.IsInside( rPos ) ) + return BorderWindowHitTest::Help; + else + return BorderWindowHitTest::Title; + } + + if ( (pBorderWindow->GetStyle() & WB_SIZEABLE) && + !pBorderWindow->mbRollUp ) + { + long nSizeWidth = pData->mnNoTitleTop+pData->mnTitleHeight; + if ( nSizeWidth < 16 ) + nSizeWidth = 16; + + // no corner resize for floating toolbars, which would lead to jumps while formatting + // setting nSizeWidth = 0 will only return pure left,top,right,bottom + if( pBorderWindow->GetStyle() & (WB_OWNERDRAWDECORATION | WB_POPUP) ) + nSizeWidth = 0; + + if ( rPos.X() < pData->mnLeftBorder ) + { + if ( rPos.Y() < nSizeWidth ) + return BorderWindowHitTest::TopLeft; + else if ( rPos.Y() >= pData->mnHeight-nSizeWidth ) + return BorderWindowHitTest::BottomLeft; + else + return BorderWindowHitTest::Left; + } + else if ( rPos.X() >= pData->mnWidth-pData->mnRightBorder ) + { + if ( rPos.Y() < nSizeWidth ) + return BorderWindowHitTest::TopRight; + else if ( rPos.Y() >= pData->mnHeight-nSizeWidth ) + return BorderWindowHitTest::BottomRight; + else + return BorderWindowHitTest::Right; + } + else if ( rPos.Y() < pData->mnNoTitleTop ) + { + if ( rPos.X() < nSizeWidth ) + return BorderWindowHitTest::TopLeft; + else if ( rPos.X() >= pData->mnWidth-nSizeWidth ) + return BorderWindowHitTest::TopRight; + else + return BorderWindowHitTest::Top; + } + else if ( rPos.Y() >= pData->mnHeight-pData->mnBottomBorder ) + { + if ( rPos.X() < nSizeWidth ) + return BorderWindowHitTest::BottomLeft; + else if ( rPos.X() >= pData->mnWidth-nSizeWidth ) + return BorderWindowHitTest::BottomRight; + else + return BorderWindowHitTest::Bottom; + } + } + + return BorderWindowHitTest::NONE; +} + +void ImplBorderWindowView::ImplMouseMove( ImplBorderFrameData* pData, const MouseEvent& rMEvt ) +{ + DrawButtonFlags oldCloseState = pData->mnCloseState; + DrawButtonFlags oldMenuState = pData->mnMenuState; + pData->mnCloseState &= ~DrawButtonFlags::Highlight; + pData->mnMenuState &= ~DrawButtonFlags::Highlight; + + Point aMousePos = rMEvt.GetPosPixel(); + BorderWindowHitTest nHitTest = ImplHitTest( pData, aMousePos ); + PointerStyle ePtrStyle = PointerStyle::Arrow; + if ( nHitTest & BorderWindowHitTest::Left ) + ePtrStyle = PointerStyle::WindowWSize; + else if ( nHitTest & BorderWindowHitTest::Right ) + ePtrStyle = PointerStyle::WindowESize; + else if ( nHitTest & BorderWindowHitTest::Top ) + ePtrStyle = PointerStyle::WindowNSize; + else if ( nHitTest & BorderWindowHitTest::Bottom ) + ePtrStyle = PointerStyle::WindowSSize; + else if ( nHitTest & BorderWindowHitTest::TopLeft ) + ePtrStyle = PointerStyle::WindowNWSize; + else if ( nHitTest & BorderWindowHitTest::BottomRight ) + ePtrStyle = PointerStyle::WindowSESize; + else if ( nHitTest & BorderWindowHitTest::TopRight ) + ePtrStyle = PointerStyle::WindowNESize; + else if ( nHitTest & BorderWindowHitTest::BottomLeft ) + ePtrStyle = PointerStyle::WindowSWSize; + else if ( nHitTest & BorderWindowHitTest::Close ) + pData->mnCloseState |= DrawButtonFlags::Highlight; + else if ( nHitTest & BorderWindowHitTest::Menu ) + pData->mnMenuState |= DrawButtonFlags::Highlight; + else if ( nHitTest & BorderWindowHitTest::Title && + pData->mnTitleType == BorderWindowTitleType::Tearoff && !rMEvt.IsLeaveWindow() ) + ePtrStyle = PointerStyle::Move; + pData->mpBorderWindow->SetPointer( ePtrStyle ); + + if( pData->mnCloseState != oldCloseState ) + pData->mpBorderWindow->Invalidate( pData->maCloseRect ); + if( pData->mnMenuState != oldMenuState ) + pData->mpBorderWindow->Invalidate( pData->maMenuRect ); +} + +OUString ImplBorderWindowView::ImplRequestHelp( ImplBorderFrameData const * pData, + const Point& rPos, + tools::Rectangle& rHelpRect ) +{ + const char* pHelpId = nullptr; + OUString aHelpStr; + BorderWindowHitTest nHitTest = ImplHitTest( pData, rPos ); + if ( nHitTest != BorderWindowHitTest::NONE ) + { + if ( nHitTest & BorderWindowHitTest::Close ) + { + pHelpId = SV_HELPTEXT_CLOSE; + rHelpRect = pData->maCloseRect; + } + else if ( nHitTest & BorderWindowHitTest::Roll ) + { + if ( pData->mpBorderWindow->mbRollUp ) + pHelpId = SV_HELPTEXT_ROLLDOWN; + else + pHelpId = SV_HELPTEXT_ROLLUP; + rHelpRect = pData->maRollRect; + } + else if ( nHitTest & BorderWindowHitTest::Dock ) + { + pHelpId = SV_HELPTEXT_MAXIMIZE; + rHelpRect = pData->maDockRect; + } + else if ( nHitTest & BorderWindowHitTest::Hide ) + { + pHelpId = SV_HELPTEXT_MINIMIZE; + rHelpRect = pData->maHideRect; + } + else if ( nHitTest & BorderWindowHitTest::Help ) + { + pHelpId = SV_HELPTEXT_HELP; + rHelpRect = pData->maHelpRect; + } + else if ( nHitTest & BorderWindowHitTest::Title ) + { + if( !pData->maTitleRect.IsEmpty() ) + { + // tooltip only if title truncated + if( pData->mbTitleClipped ) + { + rHelpRect = pData->maTitleRect; + // no help id, use window title as help string + aHelpStr = pData->mpBorderWindow->GetText(); + } + } + } + } + + if (pHelpId) + aHelpStr = VclResId(pHelpId); + + return aHelpStr; +} + +long ImplBorderWindowView::ImplCalcTitleWidth( const ImplBorderFrameData* pData ) +{ + // title is not visible therefore no width + if ( !pData->mnTitleHeight ) + return 0; + + ImplBorderWindow* pBorderWindow = pData->mpBorderWindow; + long nTitleWidth = pBorderWindow->GetTextWidth( pBorderWindow->GetText() )+6; + nTitleWidth += pData->maCloseRect.GetWidth(); + nTitleWidth += pData->maRollRect.GetWidth(); + nTitleWidth += pData->maDockRect.GetWidth(); + nTitleWidth += pData->maMenuRect.GetWidth(); + nTitleWidth += pData->maHideRect.GetWidth(); + nTitleWidth += pData->maHelpRect.GetWidth(); + nTitleWidth += pData->mnLeftBorder+pData->mnRightBorder; + return nTitleWidth; +} + + +ImplNoBorderWindowView::ImplNoBorderWindowView() +{ +} + +void ImplNoBorderWindowView::Init( OutputDevice*, long, long ) +{ +} + +void ImplNoBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder, + sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const +{ + rLeftBorder = 0; + rTopBorder = 0; + rRightBorder = 0; + rBottomBorder = 0; +} + +long ImplNoBorderWindowView::CalcTitleWidth() const +{ + return 0; +} + +void ImplNoBorderWindowView::DrawWindow(vcl::RenderContext&, const Point*) +{ +} + +ImplSmallBorderWindowView::ImplSmallBorderWindowView( ImplBorderWindow* pBorderWindow ) + : mpBorderWindow(pBorderWindow) + , mpOutDev(nullptr) + , mnWidth(0) + , mnHeight(0) + , mnLeftBorder(0) + , mnTopBorder(0) + , mnRightBorder(0) + , mnBottomBorder(0) + , mbNWFBorder(false) +{ +} + +void ImplSmallBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight ) +{ + mpOutDev = pDev; + mnWidth = nWidth; + mnHeight = nHeight; + mbNWFBorder = false; + + vcl::Window *pWin = nullptr, *pCtrl = nullptr; + if (mpOutDev->GetOutDevType() == OUTDEV_WINDOW) + pWin = static_cast<vcl::Window*>(mpOutDev.get()); + + if (pWin) + pCtrl = mpBorderWindow->GetWindow(GetWindowType::Client); + + long nOrigLeftBorder = mnLeftBorder; + long nOrigTopBorder = mnTopBorder; + long nOrigRightBorder = mnRightBorder; + long nOrigBottomBorder = mnBottomBorder; + + WindowBorderStyle nBorderStyle = mpBorderWindow->GetBorderStyle(); + if ( nBorderStyle & WindowBorderStyle::NOBORDER ) + { + mnLeftBorder = 0; + mnTopBorder = 0; + mnRightBorder = 0; + mnBottomBorder = 0; + } + else + { + // FIXME: this is currently only on macOS, check with other + // platforms + if( ImplGetSVData()->maNWFData.mbNoFocusRects && !( nBorderStyle & WindowBorderStyle::NWF ) ) + { + // for native widget drawing we must find out what + // control this border belongs to + ControlType aCtrlType = ControlType::Generic; + if (pCtrl) + { + switch( pCtrl->GetType() ) + { + case WindowType::LISTBOX: + if( pCtrl->GetStyle() & WB_DROPDOWN ) + { + aCtrlType = ControlType::Listbox; + mbNWFBorder = true; + } + break; + case WindowType::COMBOBOX: + if( pCtrl->GetStyle() & WB_DROPDOWN ) + { + aCtrlType = ControlType::Combobox; + mbNWFBorder = true; + } + break; + case WindowType::MULTILINEEDIT: + aCtrlType = ControlType::MultilineEditbox; + mbNWFBorder = true; + break; + case WindowType::EDIT: + case WindowType::PATTERNFIELD: + case WindowType::METRICFIELD: + case WindowType::CURRENCYFIELD: + case WindowType::DATEFIELD: + case WindowType::TIMEFIELD: + case WindowType::LONGCURRENCYFIELD: + case WindowType::NUMERICFIELD: + case WindowType::SPINFIELD: + case WindowType::FORMATTEDFIELD: + case WindowType::CALCINPUTLINE: + mbNWFBorder = true; + if (pCtrl->GetStyle() & WB_SPIN) + aCtrlType = ControlType::Spinbox; + else + aCtrlType = ControlType::Editbox; + break; + default: + break; + } + } + if( mbNWFBorder ) + { + ImplControlValue aControlValue; + Size aMinSize( mnWidth - mnLeftBorder - mnRightBorder, mnHeight - mnTopBorder - mnBottomBorder ); + if( aMinSize.Width() < 10 ) aMinSize.setWidth( 10 ); + if( aMinSize.Height() < 10 ) aMinSize.setHeight( 10 ); + tools::Rectangle aCtrlRegion( Point(mnLeftBorder, mnTopBorder), aMinSize ); + tools::Rectangle aBounds, aContent; + if( pWin->GetNativeControlRegion( aCtrlType, ControlPart::Entire, aCtrlRegion, + ControlState::ENABLED, aControlValue, + aBounds, aContent ) ) + { + mnLeftBorder = aContent.Left() - aBounds.Left(); + mnRightBorder = aBounds.Right() - aContent.Right(); + mnTopBorder = aContent.Top() - aBounds.Top(); + mnBottomBorder = aBounds.Bottom() - aContent.Bottom(); + if( mnWidth && mnHeight ) + { + + mpBorderWindow->SetPaintTransparent( true ); + mpBorderWindow->SetBackground(); + pCtrl->SetPaintTransparent( true ); + + vcl::Window* pCompoundParent = nullptr; + if( pWin->GetParent() && pWin->GetParent()->IsCompoundControl() ) + pCompoundParent = pWin->GetParent(); + + if( pCompoundParent ) + pCompoundParent->SetPaintTransparent( true ); + + if( mnWidth < aBounds.GetWidth() || mnHeight < aBounds.GetHeight() ) + { + if( ! pCompoundParent ) // compound controls have to fix themselves + { + Point aPos( mpBorderWindow->GetPosPixel() ); + if( mnWidth < aBounds.GetWidth() ) + aPos.AdjustX( -((aBounds.GetWidth() - mnWidth) / 2) ); + if( mnHeight < aBounds.GetHeight() ) + aPos.AdjustY( -((aBounds.GetHeight() - mnHeight) / 2) ); + mpBorderWindow->SetPosSizePixel( aPos, aBounds.GetSize() ); + } + } + } + } + else + mbNWFBorder = false; + } + } + + if( ! mbNWFBorder ) + { + DrawFrameStyle nStyle = DrawFrameStyle::NONE; + DrawFrameFlags nFlags = DrawFrameFlags::NoDraw; + // move border outside if border was converted or if the BorderWindow is a frame window, + if ( mpBorderWindow->mbSmallOutBorder ) + nStyle = DrawFrameStyle::DoubleOut; + else if ( nBorderStyle & WindowBorderStyle::NWF ) + nStyle = DrawFrameStyle::NWF; + else + nStyle = DrawFrameStyle::DoubleIn; + if ( nBorderStyle & WindowBorderStyle::MONO ) + nFlags |= DrawFrameFlags::Mono; + + DecorationView aDecoView( mpOutDev ); + tools::Rectangle aRect( 0, 0, 10, 10 ); + tools::Rectangle aCalcRect = aDecoView.DrawFrame( aRect, nStyle, nFlags ); + mnLeftBorder = aCalcRect.Left(); + mnTopBorder = aCalcRect.Top(); + mnRightBorder = aRect.Right()-aCalcRect.Right(); + mnBottomBorder = aRect.Bottom()-aCalcRect.Bottom(); + } + } + + if (pCtrl) + { + //fdo#57090 If the borders have changed, then trigger a queue_resize on + //the bordered window, which will resync its borders at that point + if (nOrigLeftBorder != mnLeftBorder || + nOrigTopBorder != mnTopBorder || + nOrigRightBorder != mnRightBorder || + nOrigBottomBorder != mnBottomBorder) + { + pCtrl->queue_resize(); + } + } +} + +void ImplSmallBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder, + sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const +{ + rLeftBorder = mnLeftBorder; + rTopBorder = mnTopBorder; + rRightBorder = mnRightBorder; + rBottomBorder = mnBottomBorder; +} + +long ImplSmallBorderWindowView::CalcTitleWidth() const +{ + return 0; +} + +void ImplSmallBorderWindowView::DrawWindow(vcl::RenderContext& rRenderContext, const Point*) +{ + WindowBorderStyle nBorderStyle = mpBorderWindow->GetBorderStyle(); + if (nBorderStyle & WindowBorderStyle::NOBORDER) + return; + + bool bNativeOK = false; + // for native widget drawing we must find out what + // control this border belongs to + vcl::Window* pCtrl = mpBorderWindow->GetWindow(GetWindowType::Client); + + ControlType aCtrlType = ControlType::Generic; + ControlPart aCtrlPart = ControlPart::Entire; + if (pCtrl) + { + switch (pCtrl->GetType()) + { + case WindowType::MULTILINEEDIT: + aCtrlType = ControlType::MultilineEditbox; + break; + case WindowType::EDIT: + case WindowType::PATTERNFIELD: + case WindowType::METRICFIELD: + case WindowType::CURRENCYFIELD: + case WindowType::DATEFIELD: + case WindowType::TIMEFIELD: + case WindowType::LONGCURRENCYFIELD: + case WindowType::NUMERICFIELD: + case WindowType::SPINFIELD: + case WindowType::FORMATTEDFIELD: + case WindowType::CALCINPUTLINE: + if (pCtrl->GetStyle() & WB_SPIN) + aCtrlType = ControlType::Spinbox; + else + aCtrlType = ControlType::Editbox; + break; + + case WindowType::LISTBOX: + case WindowType::MULTILISTBOX: + case WindowType::TREELISTBOX: + aCtrlType = ControlType::Listbox; + if (pCtrl->GetStyle() & WB_DROPDOWN) + aCtrlPart = ControlPart::Entire; + else + aCtrlPart = ControlPart::ListboxWindow; + break; + + case WindowType::LISTBOXWINDOW: + aCtrlType = ControlType::Listbox; + aCtrlPart = ControlPart::ListboxWindow; + break; + + case WindowType::COMBOBOX: + case WindowType::PATTERNBOX: + case WindowType::NUMERICBOX: + case WindowType::METRICBOX: + case WindowType::CURRENCYBOX: + case WindowType::DATEBOX: + case WindowType::TIMEBOX: + case WindowType::LONGCURRENCYBOX: + if (pCtrl->GetStyle() & WB_DROPDOWN) + { + aCtrlType = ControlType::Combobox; + aCtrlPart = ControlPart::Entire; + } + else + { + aCtrlType = ControlType::Listbox; + aCtrlPart = ControlPart::ListboxWindow; + } + break; + + default: + break; + } + } + + if (aCtrlType != ControlType::Generic && pCtrl->IsNativeControlSupported(aCtrlType, aCtrlPart)) + { + ImplControlValue aControlValue; + ControlState nState = ControlState::ENABLED; + + if (!mpBorderWindow->IsEnabled()) + nState &= ~ControlState::ENABLED; + if (mpBorderWindow->HasFocus()) + nState |= ControlState::FOCUSED; + else if(mbNWFBorder) + { + // FIXME: this is currently only on macOS, see if other platforms can profit + + // FIXME: for macOS focus rings all controls need to support GetNativeControlRegion + // for the dropdown style + if (pCtrl->HasFocus() || pCtrl->HasChildPathFocus()) + nState |= ControlState::FOCUSED; + } + + bool bMouseOver = false; + vcl::Window *pCtrlChild = pCtrl->GetWindow(GetWindowType::FirstChild); + while(pCtrlChild) + { + bMouseOver = pCtrlChild->IsMouseOver(); + if (bMouseOver) + break; + pCtrlChild = pCtrlChild->GetWindow(GetWindowType::Next); + } + + if (bMouseOver) + nState |= ControlState::ROLLOVER; + + Point aPoint; + tools::Rectangle aCtrlRegion(aPoint, Size(mnWidth, mnHeight)); + + tools::Rectangle aBoundingRgn(aPoint, Size(mnWidth, mnHeight)); + tools::Rectangle aContentRgn(aCtrlRegion); + if (!ImplGetSVData()->maNWFData.mbCanDrawWidgetAnySize && + rRenderContext.GetNativeControlRegion(aCtrlType, aCtrlPart, aCtrlRegion, + nState, aControlValue, + aBoundingRgn, aContentRgn)) + { + aCtrlRegion=aContentRgn; + } + + Color aBackgroundColor = COL_AUTO; + if (pCtrl->IsControlBackground()) + aBackgroundColor = pCtrl->GetBackgroundColor(); + bNativeOK = rRenderContext.DrawNativeControl(aCtrlType, aCtrlPart, aCtrlRegion, nState, aControlValue, OUString(), aBackgroundColor); + + // if the native theme draws the spinbuttons in one call, make sure the proper settings + // are passed, this might force a redraw though... (TODO: improve) + if ((aCtrlType == ControlType::Spinbox) && !pCtrl->IsNativeControlSupported(ControlType::Spinbox, ControlPart::ButtonUp)) + { + Edit* pEdit = static_cast<Edit*>(pCtrl)->GetSubEdit(); + if (pEdit && !pEdit->SupportsDoubleBuffering()) + pCtrl->Paint(*pCtrl, tools::Rectangle()); // make sure the buttons are also drawn as they might overwrite the border + } + } + + if (bNativeOK) + return; + + DrawFrameStyle nStyle = DrawFrameStyle::NONE; + DrawFrameFlags nFlags = DrawFrameFlags::NONE; + // move border outside if border was converted or if the border window is a frame window, + if (mpBorderWindow->mbSmallOutBorder) + nStyle = DrawFrameStyle::DoubleOut; + else if (nBorderStyle & WindowBorderStyle::NWF) + nStyle = DrawFrameStyle::NWF; + else + nStyle = DrawFrameStyle::DoubleIn; + if (nBorderStyle & WindowBorderStyle::MONO) + nFlags |= DrawFrameFlags::Mono; + if (nBorderStyle & WindowBorderStyle::MENU) + nFlags |= DrawFrameFlags::Menu; + // tell DrawFrame that we're drawing a window border of a frame window to avoid round corners + if (mpBorderWindow == mpBorderWindow->ImplGetFrameWindow()) + nFlags |= DrawFrameFlags::WindowBorder; + + DecorationView aDecoView(&rRenderContext); + tools::Rectangle aInRect(Point(), Size(mnWidth, mnHeight)); + aDecoView.DrawFrame(aInRect, nStyle, nFlags); +} + + +ImplStdBorderWindowView::ImplStdBorderWindowView( ImplBorderWindow* pBorderWindow ) +{ + maFrameData.mpBorderWindow = pBorderWindow; + maFrameData.mbDragFull = false; + maFrameData.mnHitTest = BorderWindowHitTest::NONE; + maFrameData.mnCloseState = DrawButtonFlags::NONE; + maFrameData.mnRollState = DrawButtonFlags::NONE; + maFrameData.mnDockState = DrawButtonFlags::NONE; + maFrameData.mnMenuState = DrawButtonFlags::NONE; + maFrameData.mnHideState = DrawButtonFlags::NONE; + maFrameData.mnHelpState = DrawButtonFlags::NONE; + maFrameData.mbTitleClipped = false; +} + +ImplStdBorderWindowView::~ImplStdBorderWindowView() +{ +} + +bool ImplStdBorderWindowView::MouseMove( const MouseEvent& rMEvt ) +{ + ImplMouseMove( &maFrameData, rMEvt ); + return true; +} + +bool ImplStdBorderWindowView::MouseButtonDown( const MouseEvent& rMEvt ) +{ + ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow; + + if ( rMEvt.IsLeft() || rMEvt.IsRight() ) + { + maFrameData.maMouseOff = rMEvt.GetPosPixel(); + maFrameData.mnHitTest = ImplHitTest( &maFrameData, maFrameData.maMouseOff ); + if ( maFrameData.mnHitTest != BorderWindowHitTest::NONE ) + { + DragFullOptions nDragFullTest = DragFullOptions::NONE; + bool bTracking = true; + bool bHitTest = true; + + if ( maFrameData.mnHitTest & BorderWindowHitTest::Close ) + { + maFrameData.mnCloseState |= DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + else if ( maFrameData.mnHitTest & BorderWindowHitTest::Roll ) + { + maFrameData.mnRollState |= DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + else if ( maFrameData.mnHitTest & BorderWindowHitTest::Dock ) + { + maFrameData.mnDockState |= DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + else if ( maFrameData.mnHitTest & BorderWindowHitTest::Menu ) + { + maFrameData.mnMenuState |= DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + + // call handler already on mouse down + if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() ) + { + SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow()); + pClientWindow->TitleButtonClick( TitleButton::Menu ); + } + } + else if ( maFrameData.mnHitTest & BorderWindowHitTest::Hide ) + { + maFrameData.mnHideState |= DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + else if ( maFrameData.mnHitTest & BorderWindowHitTest::Help ) + { + maFrameData.mnHelpState |= DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + else + { + if ( rMEvt.GetClicks() == 1 ) + { + Point aPos = pBorderWindow->GetPosPixel(); + Size aSize = pBorderWindow->GetOutputSizePixel(); + maFrameData.mnTrackX = aPos.X(); + maFrameData.mnTrackY = aPos.Y(); + maFrameData.mnTrackWidth = aSize.Width(); + maFrameData.mnTrackHeight = aSize.Height(); + + if (maFrameData.mnHitTest & BorderWindowHitTest::Title) + nDragFullTest = DragFullOptions::WindowMove; + else + nDragFullTest = DragFullOptions::WindowSize; + } + else + { + bTracking = false; + + if ( (maFrameData.mnHitTest & BorderWindowHitTest::Title) && + ((rMEvt.GetClicks() % 2) == 0) ) + { + maFrameData.mnHitTest = BorderWindowHitTest::NONE; + bHitTest = false; + + if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() ) + { + SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow()); + // always perform docking on double click, no button required + pClientWindow->TitleButtonClick( TitleButton::Docking ); + } + } + } + } + + if ( bTracking ) + { + maFrameData.mbDragFull = false; + if ( nDragFullTest != DragFullOptions::NONE ) + maFrameData.mbDragFull = true; // always fulldrag for proper docking, ignore system settings + pBorderWindow->StartTracking(); + } + else if ( bHitTest ) + maFrameData.mnHitTest = BorderWindowHitTest::NONE; + } + } + + return true; +} + +bool ImplStdBorderWindowView::Tracking( const TrackingEvent& rTEvt ) +{ + ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow; + + if ( rTEvt.IsTrackingEnded() ) + { + BorderWindowHitTest nHitTest = maFrameData.mnHitTest; + maFrameData.mnHitTest = BorderWindowHitTest::NONE; + + if ( nHitTest & BorderWindowHitTest::Close ) + { + if ( maFrameData.mnCloseState & DrawButtonFlags::Pressed ) + { + maFrameData.mnCloseState &= ~DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + + // do not call a Click-Handler when aborting + if ( !rTEvt.IsTrackingCanceled() ) + { + // dispatch to correct window type (why is Close() not virtual ??? ) + // TODO: make Close() virtual + VclPtr<vcl::Window> pWin = pBorderWindow->ImplGetClientWindow()->ImplGetWindow(); + SystemWindow *pSysWin = dynamic_cast<SystemWindow* >(pWin.get()); + DockingWindow *pDockWin = dynamic_cast<DockingWindow*>(pWin.get()); + if ( pSysWin ) + pSysWin->Close(); + else if ( pDockWin ) + pDockWin->Close(); + } + } + } + else if ( nHitTest & BorderWindowHitTest::Roll ) + { + if ( maFrameData.mnRollState & DrawButtonFlags::Pressed ) + { + maFrameData.mnRollState &= ~DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + + // do not call a Click-Handler when aborting + if ( !rTEvt.IsTrackingCanceled() ) + { + if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() ) + { + SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow()); + if ( pClientWindow->IsRollUp() ) + pClientWindow->RollDown(); + else + pClientWindow->RollUp(); + } + } + } + } + else if ( nHitTest & BorderWindowHitTest::Dock ) + { + if ( maFrameData.mnDockState & DrawButtonFlags::Pressed ) + { + maFrameData.mnDockState &= ~DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + + // do not call a Click-Handler when aborting + if ( !rTEvt.IsTrackingCanceled() ) + { + if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() ) + { + SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow()); + pClientWindow->TitleButtonClick( TitleButton::Docking ); + } + } + } + } + else if ( nHitTest & BorderWindowHitTest::Menu ) + { + if ( maFrameData.mnMenuState & DrawButtonFlags::Pressed ) + { + maFrameData.mnMenuState &= ~DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + + // handler already called on mouse down + } + } + else if ( nHitTest & BorderWindowHitTest::Hide ) + { + if ( maFrameData.mnHideState & DrawButtonFlags::Pressed ) + { + maFrameData.mnHideState &= ~DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + + // do not call a Click-Handler when aborting + if ( !rTEvt.IsTrackingCanceled() ) + { + if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() ) + { + SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow()); + pClientWindow->TitleButtonClick( TitleButton::Hide ); + } + } + } + } + else if ( nHitTest & BorderWindowHitTest::Help ) + { + if ( maFrameData.mnHelpState & DrawButtonFlags::Pressed ) + { + maFrameData.mnHelpState &= ~DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + } + else + { + if ( maFrameData.mbDragFull ) + { + // restore old state when aborting + if ( rTEvt.IsTrackingCanceled() ) + pBorderWindow->SetPosSizePixel( Point( maFrameData.mnTrackX, maFrameData.mnTrackY ), Size( maFrameData.mnTrackWidth, maFrameData.mnTrackHeight ) ); + } + else + { + pBorderWindow->HideTracking(); + if ( !rTEvt.IsTrackingCanceled() ) + pBorderWindow->SetPosSizePixel( Point( maFrameData.mnTrackX, maFrameData.mnTrackY ), Size( maFrameData.mnTrackWidth, maFrameData.mnTrackHeight ) ); + } + + if ( !rTEvt.IsTrackingCanceled() ) + { + if ( pBorderWindow->ImplGetClientWindow()->ImplIsFloatingWindow() ) + { + if ( static_cast<FloatingWindow*>(pBorderWindow->ImplGetClientWindow())->IsInPopupMode() ) + static_cast<FloatingWindow*>(pBorderWindow->ImplGetClientWindow())->EndPopupMode( FloatWinPopupEndFlags::TearOff ); + } + } + } + } + else if ( !rTEvt.GetMouseEvent().IsSynthetic() ) + { + Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel(); + + if ( maFrameData.mnHitTest & BorderWindowHitTest::Close ) + { + if ( maFrameData.maCloseRect.IsInside( aMousePos ) ) + { + if ( !(maFrameData.mnCloseState & DrawButtonFlags::Pressed) ) + { + maFrameData.mnCloseState |= DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + } + else + { + if ( maFrameData.mnCloseState & DrawButtonFlags::Pressed ) + { + maFrameData.mnCloseState &= ~DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + } + } + else if ( maFrameData.mnHitTest & BorderWindowHitTest::Roll ) + { + if ( maFrameData.maRollRect.IsInside( aMousePos ) ) + { + if ( !(maFrameData.mnRollState & DrawButtonFlags::Pressed) ) + { + maFrameData.mnRollState |= DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + } + else + { + if ( maFrameData.mnRollState & DrawButtonFlags::Pressed ) + { + maFrameData.mnRollState &= ~DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + } + } + else if ( maFrameData.mnHitTest & BorderWindowHitTest::Dock ) + { + if ( maFrameData.maDockRect.IsInside( aMousePos ) ) + { + if ( !(maFrameData.mnDockState & DrawButtonFlags::Pressed) ) + { + maFrameData.mnDockState |= DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + } + else + { + if ( maFrameData.mnDockState & DrawButtonFlags::Pressed ) + { + maFrameData.mnDockState &= ~DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + } + } + else if ( maFrameData.mnHitTest & BorderWindowHitTest::Menu ) + { + if ( maFrameData.maMenuRect.IsInside( aMousePos ) ) + { + if ( !(maFrameData.mnMenuState & DrawButtonFlags::Pressed) ) + { + maFrameData.mnMenuState |= DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + } + else + { + if ( maFrameData.mnMenuState & DrawButtonFlags::Pressed ) + { + maFrameData.mnMenuState &= ~DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + } + } + else if ( maFrameData.mnHitTest & BorderWindowHitTest::Hide ) + { + if ( maFrameData.maHideRect.IsInside( aMousePos ) ) + { + if ( !(maFrameData.mnHideState & DrawButtonFlags::Pressed) ) + { + maFrameData.mnHideState |= DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + } + else + { + if ( maFrameData.mnHideState & DrawButtonFlags::Pressed ) + { + maFrameData.mnHideState &= ~DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + } + } + else if ( maFrameData.mnHitTest & BorderWindowHitTest::Help ) + { + if ( maFrameData.maHelpRect.IsInside( aMousePos ) ) + { + if ( !(maFrameData.mnHelpState & DrawButtonFlags::Pressed) ) + { + maFrameData.mnHelpState |= DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + } + else + { + if ( maFrameData.mnHelpState & DrawButtonFlags::Pressed ) + { + maFrameData.mnHelpState &= ~DrawButtonFlags::Pressed; + pBorderWindow->InvalidateBorder(); + } + } + } + else + { + aMousePos.AdjustX( -(maFrameData.maMouseOff.X()) ); + aMousePos.AdjustY( -(maFrameData.maMouseOff.Y()) ); + + if ( maFrameData.mnHitTest & BorderWindowHitTest::Title ) + { + maFrameData.mpBorderWindow->SetPointer( PointerStyle::Move ); + + Point aPos = pBorderWindow->GetPosPixel(); + aPos.AdjustX(aMousePos.X() ); + aPos.AdjustY(aMousePos.Y() ); + if ( maFrameData.mbDragFull ) + { + pBorderWindow->SetPosPixel( aPos ); + pBorderWindow->ImplUpdateAll(); + pBorderWindow->ImplGetFrameWindow()->ImplUpdateAll(); + } + else + { + maFrameData.mnTrackX = aPos.X(); + maFrameData.mnTrackY = aPos.Y(); + pBorderWindow->ShowTracking( tools::Rectangle( pBorderWindow->ScreenToOutputPixel( aPos ), pBorderWindow->GetOutputSizePixel() ), ShowTrackFlags::Big ); + } + } + else + { + Point aOldPos = pBorderWindow->GetPosPixel(); + Size aSize = pBorderWindow->GetSizePixel(); + tools::Rectangle aNewRect( aOldPos, aSize ); + long nOldWidth = aSize.Width(); + long nOldHeight = aSize.Height(); + long nBorderWidth = maFrameData.mnLeftBorder+maFrameData.mnRightBorder; + long nBorderHeight = maFrameData.mnTopBorder+maFrameData.mnBottomBorder; + long nMinWidth = pBorderWindow->mnMinWidth+nBorderWidth; + long nMinHeight = pBorderWindow->mnMinHeight+nBorderHeight; + long nMinWidth2 = nBorderWidth; + long nMaxWidth = pBorderWindow->mnMaxWidth+nBorderWidth; + long nMaxHeight = pBorderWindow->mnMaxHeight+nBorderHeight; + + if ( maFrameData.mnTitleHeight ) + { + nMinWidth2 += 4; + + if ( pBorderWindow->GetStyle() & WB_CLOSEABLE ) + nMinWidth2 += maFrameData.maCloseRect.GetWidth(); + } + if ( nMinWidth2 > nMinWidth ) + nMinWidth = nMinWidth2; + if ( maFrameData.mnHitTest & (BorderWindowHitTest::Left | BorderWindowHitTest::TopLeft | BorderWindowHitTest::BottomLeft) ) + { + aNewRect.AdjustLeft(aMousePos.X() ); + if ( aNewRect.GetWidth() < nMinWidth ) + aNewRect.SetLeft( aNewRect.Right()-nMinWidth+1 ); + else if ( aNewRect.GetWidth() > nMaxWidth ) + aNewRect.SetLeft( aNewRect.Right()-nMaxWidth+1 ); + } + else if ( maFrameData.mnHitTest & (BorderWindowHitTest::Right | BorderWindowHitTest::TopRight | BorderWindowHitTest::BottomRight) ) + { + aNewRect.AdjustRight(aMousePos.X() ); + if ( aNewRect.GetWidth() < nMinWidth ) + aNewRect.SetRight( aNewRect.Left()+nMinWidth+1 ); + else if ( aNewRect.GetWidth() > nMaxWidth ) + aNewRect.SetRight( aNewRect.Left()+nMaxWidth+1 ); + } + if ( maFrameData.mnHitTest & (BorderWindowHitTest::Top | BorderWindowHitTest::TopLeft | BorderWindowHitTest::TopRight) ) + { + aNewRect.AdjustTop(aMousePos.Y() ); + if ( aNewRect.GetHeight() < nMinHeight ) + aNewRect.SetTop( aNewRect.Bottom()-nMinHeight+1 ); + else if ( aNewRect.GetHeight() > nMaxHeight ) + aNewRect.SetTop( aNewRect.Bottom()-nMaxHeight+1 ); + } + else if ( maFrameData.mnHitTest & (BorderWindowHitTest::Bottom | BorderWindowHitTest::BottomLeft | BorderWindowHitTest::BottomRight) ) + { + aNewRect.AdjustBottom(aMousePos.Y() ); + if ( aNewRect.GetHeight() < nMinHeight ) + aNewRect.SetBottom( aNewRect.Top()+nMinHeight+1 ); + else if ( aNewRect.GetHeight() > nMaxHeight ) + aNewRect.SetBottom( aNewRect.Top()+nMaxHeight+1 ); + } + + // call Resizing-Handler for SystemWindows + if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() ) + { + // adjust size for Resizing-call + aSize = aNewRect.GetSize(); + aSize.AdjustWidth( -nBorderWidth ); + aSize.AdjustHeight( -nBorderHeight ); + static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow())->Resizing( aSize ); + aSize.AdjustWidth(nBorderWidth ); + aSize.AdjustHeight(nBorderHeight ); + if ( aSize.Width() < nMinWidth ) + aSize.setWidth( nMinWidth ); + if ( aSize.Height() < nMinHeight ) + aSize.setHeight( nMinHeight ); + if ( aSize.Width() > nMaxWidth ) + aSize.setWidth( nMaxWidth ); + if ( aSize.Height() > nMaxHeight ) + aSize.setHeight( nMaxHeight ); + if ( maFrameData.mnHitTest & (BorderWindowHitTest::Left | BorderWindowHitTest::TopLeft | BorderWindowHitTest::BottomLeft) ) + aNewRect.SetLeft( aNewRect.Right()-aSize.Width()+1 ); + else + aNewRect.SetRight( aNewRect.Left()+aSize.Width()-1 ); + if ( maFrameData.mnHitTest & (BorderWindowHitTest::Top | BorderWindowHitTest::TopLeft | BorderWindowHitTest::TopRight) ) + aNewRect.SetTop( aNewRect.Bottom()-aSize.Height()+1 ); + else + aNewRect.SetBottom( aNewRect.Top()+aSize.Height()-1 ); + } + + if ( maFrameData.mbDragFull ) + { + // no move (only resize) if position did not change + if( aOldPos != aNewRect.TopLeft() ) + pBorderWindow->setPosSizePixel( aNewRect.Left(), aNewRect.Top(), + aNewRect.GetWidth(), aNewRect.GetHeight() ); + else + pBorderWindow->setPosSizePixel( aNewRect.Left(), aNewRect.Top(), + aNewRect.GetWidth(), aNewRect.GetHeight(), PosSizeFlags::Size ); + + pBorderWindow->ImplUpdateAll(); + pBorderWindow->ImplGetFrameWindow()->ImplUpdateAll(); + if ( maFrameData.mnHitTest & (BorderWindowHitTest::Right | BorderWindowHitTest::TopRight | BorderWindowHitTest::BottomRight) ) + maFrameData.maMouseOff.AdjustX(aNewRect.GetWidth()-nOldWidth ); + if ( maFrameData.mnHitTest & (BorderWindowHitTest::Bottom | BorderWindowHitTest::BottomLeft | BorderWindowHitTest::BottomRight) ) + maFrameData.maMouseOff.AdjustY(aNewRect.GetHeight()-nOldHeight ); + } + else + { + maFrameData.mnTrackX = aNewRect.Left(); + maFrameData.mnTrackY = aNewRect.Top(); + maFrameData.mnTrackWidth = aNewRect.GetWidth(); + maFrameData.mnTrackHeight = aNewRect.GetHeight(); + pBorderWindow->ShowTracking( tools::Rectangle( pBorderWindow->ScreenToOutputPixel( aNewRect.TopLeft() ), aNewRect.GetSize() ), ShowTrackFlags::Big ); + } + } + } + } + + return true; +} + +OUString ImplStdBorderWindowView::RequestHelp( const Point& rPos, tools::Rectangle& rHelpRect ) +{ + return ImplRequestHelp( &maFrameData, rPos, rHelpRect ); +} + +tools::Rectangle ImplStdBorderWindowView::GetMenuRect() const +{ + return maFrameData.maMenuRect; +} + +void ImplStdBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight ) +{ + ImplBorderFrameData* pData = &maFrameData; + ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow; + const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings(); + DecorationView aDecoView( pDev ); + tools::Rectangle aRect( 0, 0, 10, 10 ); + tools::Rectangle aCalcRect = aDecoView.DrawFrame( aRect, DrawFrameStyle::DoubleOut, DrawFrameFlags::NoDraw ); + + pData->mpOutDev = pDev; + pData->mnWidth = nWidth; + pData->mnHeight = nHeight; + + pData->mnTitleType = pBorderWindow->mnTitleType; + + if ( !(pBorderWindow->GetStyle() & (WB_MOVEABLE | WB_POPUP)) || (pData->mnTitleType == BorderWindowTitleType::NONE) ) + pData->mnBorderSize = 0; + else if ( pData->mnTitleType == BorderWindowTitleType::Tearoff ) + pData->mnBorderSize = 0; + else + pData->mnBorderSize = StyleSettings::GetBorderSize(); + pData->mnLeftBorder = aCalcRect.Left(); + pData->mnTopBorder = aCalcRect.Top(); + pData->mnRightBorder = aRect.Right()-aCalcRect.Right(); + pData->mnBottomBorder = aRect.Bottom()-aCalcRect.Bottom(); + pData->mnLeftBorder += pData->mnBorderSize; + pData->mnTopBorder += pData->mnBorderSize; + pData->mnRightBorder += pData->mnBorderSize; + pData->mnBottomBorder += pData->mnBorderSize; + pData->mnNoTitleTop = pData->mnTopBorder; + + ImplInitTitle(&maFrameData); + if (pData->mnTitleHeight) + { + // to improve symbol display force a minimum title height + if (pData->mnTitleType != BorderWindowTitleType::Tearoff && + pData->mnTitleHeight < MIN_CAPTION_HEIGHT) + pData->mnTitleHeight = MIN_CAPTION_HEIGHT; + + // set a proper background for drawing + // highlighted buttons in the title + pBorderWindow->SetBackground( rStyleSettings.GetFaceColor() ); + + pData->maTitleRect.SetLeft( pData->mnLeftBorder ); + pData->maTitleRect.SetRight( nWidth-pData->mnRightBorder-1 ); + pData->maTitleRect.SetTop( pData->mnTopBorder ); + pData->maTitleRect.SetBottom( pData->maTitleRect.Top()+pData->mnTitleHeight-1 ); + + if ( pData->mnTitleType & (BorderWindowTitleType::Normal | BorderWindowTitleType::Small) ) + { + long nRight = pData->maTitleRect.Right() - 3; + long const nItemTop = pData->maTitleRect.Top() + 2; + long const nItemBottom = pData->maTitleRect.Bottom() - 2; + + auto addSquareOnRight = [&nRight, nItemTop, nItemBottom]( + tools::Rectangle & rect, long gap) + { + rect.SetTop( nItemTop ); + rect.SetBottom( nItemBottom ); + rect.SetRight( nRight ); + rect.SetLeft( rect.Right() - rect.GetHeight() + 1 ); + nRight -= rect.GetWidth() + gap; + }; + + if ( pBorderWindow->GetStyle() & WB_CLOSEABLE ) + { + addSquareOnRight(pData->maCloseRect, 3); + } + + if ( pBorderWindow->mbMenuBtn ) + { + addSquareOnRight(pData->maMenuRect, 0); + } + + if ( pBorderWindow->mbDockBtn ) + { + addSquareOnRight(pData->maDockRect, 0); + } + + if ( pBorderWindow->mbHideBtn ) + { + addSquareOnRight(pData->maHideRect, 0); + } + + if ( pBorderWindow->GetStyle() & WB_ROLLABLE ) + { + addSquareOnRight(pData->maRollRect, 0); + } + } + else + { + pData->maCloseRect.SetEmpty(); + pData->maDockRect.SetEmpty(); + pData->maMenuRect.SetEmpty(); + pData->maHideRect.SetEmpty(); + pData->maRollRect.SetEmpty(); + pData->maHelpRect.SetEmpty(); + } + + pData->mnTopBorder += pData->mnTitleHeight; + } + else + { + pData->maTitleRect.SetEmpty(); + pData->maCloseRect.SetEmpty(); + pData->maDockRect.SetEmpty(); + pData->maMenuRect.SetEmpty(); + pData->maHideRect.SetEmpty(); + pData->maRollRect.SetEmpty(); + pData->maHelpRect.SetEmpty(); + } +} + +void ImplStdBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder, + sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const +{ + rLeftBorder = maFrameData.mnLeftBorder; + rTopBorder = maFrameData.mnTopBorder; + rRightBorder = maFrameData.mnRightBorder; + rBottomBorder = maFrameData.mnBottomBorder; +} + +long ImplStdBorderWindowView::CalcTitleWidth() const +{ + return ImplCalcTitleWidth( &maFrameData ); +} + +void ImplStdBorderWindowView::DrawWindow(vcl::RenderContext& rRenderContext, const Point* pOffset) +{ + ImplBorderFrameData* pData = &maFrameData; + ImplBorderWindow* pBorderWindow = pData->mpBorderWindow; + Point aTmpPoint = pOffset ? *pOffset : Point(); + tools::Rectangle aInRect( aTmpPoint, Size( pData->mnWidth, pData->mnHeight ) ); + const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); + Color aFaceColor(rStyleSettings.GetFaceColor()); + Color aFrameColor(aFaceColor); + + aFrameColor.DecreaseContrast(sal_uInt8(0.5 * 255)); + + // Draw Frame + vcl::Region oldClipRgn(rRenderContext.GetClipRegion()); + + // for popups, don't draw part of the frame + if (!(pData->mnTitleType & (BorderWindowTitleType::Normal | BorderWindowTitleType::Small))) + { + FloatingWindow* pWin = dynamic_cast<FloatingWindow*>(pData->mpBorderWindow->GetWindow(GetWindowType::Client)); + if (pWin) + { + vcl::Region aClipRgn(aInRect); + tools::Rectangle aItemClipRect(pWin->ImplGetItemEdgeClipRect()); + if (!aItemClipRect.IsEmpty()) + { + aItemClipRect.SetPos(pData->mpBorderWindow->AbsoluteScreenToOutputPixel(aItemClipRect.TopLeft())); + aClipRgn.Exclude(aItemClipRect); + rRenderContext.SetClipRegion(aClipRgn); + } + } + } + + // single line frame + rRenderContext.SetLineColor(aFrameColor); + rRenderContext.SetFillColor(); + rRenderContext.DrawRect(aInRect); + aInRect.AdjustLeft( 1 ); + aInRect.AdjustRight( -1 ); + aInRect.AdjustTop( 1 ); + aInRect.AdjustBottom( -1 ); + + // restore + if (!(pData->mnTitleType & (BorderWindowTitleType::Normal | BorderWindowTitleType::Small))) + rRenderContext.SetClipRegion(oldClipRgn); + + // Draw Border + rRenderContext.SetLineColor(); + long nBorderSize = pData->mnBorderSize; + if (nBorderSize) + { + rRenderContext.SetFillColor(rStyleSettings.GetFaceColor()); + rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Left(), aInRect.Top()), + Size(aInRect.GetWidth(), nBorderSize))); + rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Left(), aInRect.Top() + nBorderSize), + Size(nBorderSize, aInRect.GetHeight() - nBorderSize))); + rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Left(), aInRect.Bottom() - nBorderSize + 1), + Size(aInRect.GetWidth(), nBorderSize))); + rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Right()-nBorderSize + 1, aInRect.Top() + nBorderSize), + Size(nBorderSize, aInRect.GetHeight() - nBorderSize))); + } + + // Draw Title + if (!pData->maTitleRect.IsEmpty()) + { + aInRect = pData->maTitleRect; + + // use no gradient anymore, just a static titlecolor + if (pData->mnTitleType == BorderWindowTitleType::Tearoff) + rRenderContext.SetFillColor(rStyleSettings.GetFaceGradientColor()); + else if (pData->mnTitleType == BorderWindowTitleType::Popup) + rRenderContext.SetFillColor(aFaceColor); + else + rRenderContext.SetFillColor(aFrameColor); + + rRenderContext.SetTextColor(rStyleSettings.GetButtonTextColor()); + tools::Rectangle aTitleRect(pData->maTitleRect); + if(pOffset) + aTitleRect.Move(pOffset->X(), pOffset->Y()); + rRenderContext.DrawRect(aTitleRect); + + if (pData->mnTitleType != BorderWindowTitleType::Tearoff) + { + aInRect.AdjustLeft(2 ); + aInRect.AdjustRight( -2 ); + + if (!pData->maHelpRect.IsEmpty()) + aInRect.SetRight( pData->maHelpRect.Left() - 2 ); + else if (!pData->maRollRect.IsEmpty()) + aInRect.SetRight( pData->maRollRect.Left() - 2 ); + else if (!pData->maHideRect.IsEmpty()) + aInRect.SetRight( pData->maHideRect.Left() - 2 ); + else if (!pData->maDockRect.IsEmpty()) + aInRect.SetRight( pData->maDockRect.Left() - 2 ); + else if (!pData->maMenuRect.IsEmpty()) + aInRect.SetRight( pData->maMenuRect.Left() - 2 ); + else if (!pData->maCloseRect.IsEmpty()) + aInRect.SetRight( pData->maCloseRect.Left() - 2 ); + + if (pOffset) + aInRect.Move(pOffset->X(), pOffset->Y()); + + DrawTextFlags nTextStyle = DrawTextFlags::Left | DrawTextFlags::VCenter | DrawTextFlags::EndEllipsis | DrawTextFlags::Clip; + + // must show tooltip ? + TextRectInfo aInfo; + rRenderContext.GetTextRect(aInRect, pBorderWindow->GetText(), nTextStyle, &aInfo); + pData->mbTitleClipped = aInfo.IsEllipses(); + + rRenderContext.DrawText(aInRect, pBorderWindow->GetText(), nTextStyle); + } + else + { + ToolBox::ImplDrawGrip(rRenderContext, aTitleRect, ToolBox::ImplGetDragWidth(rRenderContext, false), + WindowAlign::Left, false); + } + } + + if (!pData->maCloseRect.IsEmpty()) + { + tools::Rectangle aSymbolRect(pData->maCloseRect); + if (pOffset) + aSymbolRect.Move(pOffset->X(), pOffset->Y()); + ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::CLOSE, pData->mnCloseState); + } + if (!pData->maDockRect.IsEmpty()) + { + tools::Rectangle aSymbolRect(pData->maDockRect); + if (pOffset) + aSymbolRect.Move(pOffset->X(), pOffset->Y()); + ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::DOCK, pData->mnDockState); + } + if (!pData->maMenuRect.IsEmpty()) + { + tools::Rectangle aSymbolRect(pData->maMenuRect); + if (pOffset) + aSymbolRect.Move(pOffset->X(), pOffset->Y()); + ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::MENU, pData->mnMenuState); + } + if (!pData->maHideRect.IsEmpty()) + { + tools::Rectangle aSymbolRect(pData->maHideRect); + if (pOffset) + aSymbolRect.Move(pOffset->X(), pOffset->Y()); + ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::HIDE, pData->mnHideState); + } + if (!pData->maRollRect.IsEmpty()) + { + SymbolType eType; + if (pBorderWindow->mbRollUp) + eType = SymbolType::ROLLDOWN; + else + eType = SymbolType::ROLLUP; + tools::Rectangle aSymbolRect(pData->maRollRect); + if (pOffset) + aSymbolRect.Move(pOffset->X(), pOffset->Y()); + ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, eType, pData->mnRollState); + } + + if (!pData->maHelpRect.IsEmpty()) + { + tools::Rectangle aSymbolRect(pData->maHelpRect); + if (pOffset) + aSymbolRect.Move(pOffset->X(), pOffset->Y()); + ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::HELP, pData->mnHelpState); + } +} + +void ImplBorderWindow::ImplInit( vcl::Window* pParent, + WinBits nStyle, BorderWindowStyle nTypeStyle, + SystemParentData* pSystemParentData + ) +{ + // remove all unwanted WindowBits + WinBits nOrgStyle = nStyle; + WinBits nTestStyle = (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE | WB_DIALOGCONTROL | WB_NODIALOGCONTROL | WB_SYSTEMFLOATWIN | WB_INTROWIN | WB_DEFAULTWIN | WB_TOOLTIPWIN | WB_NOSHADOW | WB_OWNERDRAWDECORATION | WB_SYSTEMCHILDWINDOW | WB_POPUP); + if ( nTypeStyle & BorderWindowStyle::App ) + nTestStyle |= WB_APP; + nStyle &= nTestStyle; + + mpWindowImpl->mbBorderWin = true; + mbSmallOutBorder = false; + if ( nTypeStyle & BorderWindowStyle::Frame ) + { + if( nStyle & WB_SYSTEMCHILDWINDOW ) + { + mpWindowImpl->mbOverlapWin = true; + mpWindowImpl->mbFrame = true; + mbFrameBorder = false; + } + else if( nStyle & (WB_OWNERDRAWDECORATION | WB_POPUP) ) + { + mpWindowImpl->mbOverlapWin = true; + mpWindowImpl->mbFrame = true; + mbFrameBorder = (nOrgStyle & WB_NOBORDER) == 0; + } + else + { + mpWindowImpl->mbOverlapWin = true; + mpWindowImpl->mbFrame = true; + mbFrameBorder = false; + // closeable windows may have a border as well, eg. system floating windows without caption + if ( (nOrgStyle & (WB_BORDER | WB_NOBORDER | WB_MOVEABLE | WB_SIZEABLE/* | WB_CLOSEABLE*/)) == WB_BORDER ) + mbSmallOutBorder = true; + } + } + else if ( nTypeStyle & BorderWindowStyle::Overlap ) + { + mpWindowImpl->mbOverlapWin = true; + mbFrameBorder = true; + } + else + mbFrameBorder = false; + + if ( nTypeStyle & BorderWindowStyle::Float ) + mbFloatWindow = true; + else + mbFloatWindow = false; + + Window::ImplInit( pParent, nStyle, pSystemParentData ); + SetBackground(); + SetTextFillColor(); + + mpMenuBarWindow = nullptr; + mnMinWidth = 0; + mnMinHeight = 0; + mnMaxWidth = SHRT_MAX; + mnMaxHeight = SHRT_MAX; + mnOrgMenuHeight = 0; + mbRollUp = false; + mbMenuHide = false; + mbDockBtn = false; + mbMenuBtn = false; + mbHideBtn = false; + mbDisplayActive = IsActive(); + + if ( nTypeStyle & BorderWindowStyle::Float ) + mnTitleType = BorderWindowTitleType::Small; + else + mnTitleType = BorderWindowTitleType::Normal; + mnBorderStyle = WindowBorderStyle::NORMAL; + InitView(); +} + +ImplBorderWindow::ImplBorderWindow( vcl::Window* pParent, + SystemParentData* pSystemParentData, + WinBits nStyle, BorderWindowStyle nTypeStyle + ) : Window( WindowType::BORDERWINDOW ) +{ + ImplInit( pParent, nStyle, nTypeStyle, pSystemParentData ); +} + +ImplBorderWindow::ImplBorderWindow( vcl::Window* pParent, WinBits nStyle , + BorderWindowStyle nTypeStyle ) : + Window( WindowType::BORDERWINDOW ) +{ + ImplInit( pParent, nStyle, nTypeStyle, nullptr ); +} + +ImplBorderWindow::~ImplBorderWindow() +{ + disposeOnce(); +} + +void ImplBorderWindow::dispose() +{ + mpBorderView.reset(); + mpMenuBarWindow.clear(); + mpNotebookBar.disposeAndClear(); + vcl::Window::dispose(); +} + +void ImplBorderWindow::MouseMove( const MouseEvent& rMEvt ) +{ + if (mpBorderView) + mpBorderView->MouseMove( rMEvt ); +} + +void ImplBorderWindow::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if (mpBorderView) + mpBorderView->MouseButtonDown( rMEvt ); +} + +void ImplBorderWindow::Tracking( const TrackingEvent& rTEvt ) +{ + if (mpBorderView) + mpBorderView->Tracking( rTEvt ); +} + +void ImplBorderWindow::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& ) +{ + if (mpBorderView) + mpBorderView->DrawWindow(rRenderContext); +} + +void ImplBorderWindow::Draw( OutputDevice* pOutDev, const Point& rPos ) +{ + if (mpBorderView) + mpBorderView->DrawWindow(*pOutDev, &rPos); +} + +void ImplBorderWindow::Activate() +{ + SetDisplayActive( true ); + Window::Activate(); +} + +void ImplBorderWindow::Deactivate() +{ + // remove active windows from the ruler, also ignore the Deactivate + // if a menu becomes active + if (GetActivateMode() != ActivateModeFlags::NONE && !ImplGetSVData()->mpWinData->mbNoDeactivate) + SetDisplayActive( false ); + Window::Deactivate(); +} + +void ImplBorderWindow::RequestHelp( const HelpEvent& rHEvt ) +{ + // no keyboard help for border window + if ( rHEvt.GetMode() & (HelpEventMode::BALLOON | HelpEventMode::QUICK) && !rHEvt.KeyboardActivated() ) + { + Point aMousePosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() ); + tools::Rectangle aHelpRect; + OUString aHelpStr( mpBorderView->RequestHelp( aMousePosPixel, aHelpRect ) ); + + // retrieve rectangle + if ( !aHelpStr.isEmpty() ) + { + aHelpRect.SetPos( OutputToScreenPixel( aHelpRect.TopLeft() ) ); + if ( rHEvt.GetMode() & HelpEventMode::BALLOON ) + Help::ShowBalloon( this, aHelpRect.Center(), aHelpRect, aHelpStr ); + else + Help::ShowQuickHelp( this, aHelpRect, aHelpStr ); + return; + } + } + + Window::RequestHelp( rHEvt ); +} + +void ImplBorderWindow::Resize() +{ + Size aSize = GetOutputSizePixel(); + + if ( !mbRollUp ) + { + vcl::Window* pClientWindow = ImplGetClientWindow(); + + sal_Int32 nLeftBorder; + sal_Int32 nTopBorder; + sal_Int32 nRightBorder; + sal_Int32 nBottomBorder; + mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder ); + + if (mpMenuBarWindow) + { + long nMenuHeight = mpMenuBarWindow->GetSizePixel().Height(); + if ( mbMenuHide ) + { + if ( nMenuHeight ) + mnOrgMenuHeight = nMenuHeight; + nMenuHeight = 0; + } + else + { + if ( !nMenuHeight ) + nMenuHeight = mnOrgMenuHeight; + } + mpMenuBarWindow->setPosSizePixel( + nLeftBorder, nTopBorder, + aSize.Width()-nLeftBorder-nRightBorder, + nMenuHeight); + + // shift the notebookbar down accordingly + nTopBorder += nMenuHeight; + } + + if (mpNotebookBar) + { + long nNotebookBarHeight = mpNotebookBar->GetSizePixel().Height(); + + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + const BitmapEx& aPersona = rStyleSettings.GetPersonaHeader(); + // since size of notebookbar changes, to make common persona for menubar + // and notebookbar persona should be set again with changed coordinates + if (!aPersona.IsEmpty()) + { + Wallpaper aWallpaper(aPersona); + aWallpaper.SetStyle(WallpaperStyle::TopRight); + aWallpaper.SetRect(tools::Rectangle(Point(0, -nTopBorder), + Size(aSize.Width() - nLeftBorder - nRightBorder, + nNotebookBarHeight + nTopBorder))); + mpNotebookBar->SetBackground(aWallpaper); + } + + mpNotebookBar->setPosSizePixel( + nLeftBorder, nTopBorder, + aSize.Width() - nLeftBorder - nRightBorder, + nNotebookBarHeight); + } + + GetBorder( pClientWindow->mpWindowImpl->mnLeftBorder, pClientWindow->mpWindowImpl->mnTopBorder, + pClientWindow->mpWindowImpl->mnRightBorder, pClientWindow->mpWindowImpl->mnBottomBorder ); + pClientWindow->ImplPosSizeWindow( pClientWindow->mpWindowImpl->mnLeftBorder, + pClientWindow->mpWindowImpl->mnTopBorder, + aSize.Width()-pClientWindow->mpWindowImpl->mnLeftBorder-pClientWindow->mpWindowImpl->mnRightBorder, + aSize.Height()-pClientWindow->mpWindowImpl->mnTopBorder-pClientWindow->mpWindowImpl->mnBottomBorder, + PosSizeFlags::X | PosSizeFlags::Y | + PosSizeFlags::Width | PosSizeFlags::Height ); + } + + // UpdateView + mpBorderView->Init( this, aSize.Width(), aSize.Height() ); + InvalidateBorder(); + + Window::Resize(); +} + +void ImplBorderWindow::StateChanged( StateChangedType nType ) +{ + if ( (nType == StateChangedType::Text) || + (nType == StateChangedType::Data) ) + { + if (IsReallyVisible() && mbFrameBorder) + InvalidateBorder(); + } + + Window::StateChanged( nType ); +} + +void ImplBorderWindow::DataChanged( const DataChangedEvent& rDCEvt ) +{ + if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) || + (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) || + ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) ) + { + if ( !mpWindowImpl->mbFrame || (GetStyle() & (WB_OWNERDRAWDECORATION | WB_POPUP)) ) + UpdateView( true, ImplGetWindow()->GetOutputSizePixel() ); + } + + Window::DataChanged( rDCEvt ); +} + +void ImplBorderWindow::InitView() +{ + if ( mbSmallOutBorder ) + mpBorderView.reset(new ImplSmallBorderWindowView( this )); + else if ( mpWindowImpl->mbFrame ) + { + if( mbFrameBorder ) + mpBorderView.reset(new ImplStdBorderWindowView( this )); + else + mpBorderView.reset(new ImplNoBorderWindowView); + } + else if ( !mbFrameBorder ) + mpBorderView.reset(new ImplSmallBorderWindowView( this )); + else + mpBorderView.reset(new ImplStdBorderWindowView( this )); + Size aSize = GetOutputSizePixel(); + mpBorderView->Init( this, aSize.Width(), aSize.Height() ); +} + +void ImplBorderWindow::UpdateView( bool bNewView, const Size& rNewOutSize ) +{ + sal_Int32 nLeftBorder; + sal_Int32 nTopBorder; + sal_Int32 nRightBorder; + sal_Int32 nBottomBorder; + Size aOldSize = GetSizePixel(); + Size aOutputSize = rNewOutSize; + + if ( bNewView ) + { + mpBorderView.reset(); + InitView(); + } + else + { + Size aSize = aOutputSize; + mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder ); + aSize.AdjustWidth(nLeftBorder+nRightBorder ); + aSize.AdjustHeight(nTopBorder+nBottomBorder ); + mpBorderView->Init( this, aSize.Width(), aSize.Height() ); + } + + vcl::Window* pClientWindow = ImplGetClientWindow(); + if ( pClientWindow ) + { + GetBorder( pClientWindow->mpWindowImpl->mnLeftBorder, pClientWindow->mpWindowImpl->mnTopBorder, + pClientWindow->mpWindowImpl->mnRightBorder, pClientWindow->mpWindowImpl->mnBottomBorder ); + } + GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder ); + if ( aOldSize.Width() || aOldSize.Height() ) + { + aOutputSize.AdjustWidth(nLeftBorder+nRightBorder ); + aOutputSize.AdjustHeight(nTopBorder+nBottomBorder ); + if ( aOutputSize == GetSizePixel() ) + InvalidateBorder(); + else + SetSizePixel( aOutputSize ); + } +} + +void ImplBorderWindow::InvalidateBorder() +{ + if ( IsReallyVisible() ) + { + // invalidate only if we have a border + sal_Int32 nLeftBorder; + sal_Int32 nTopBorder; + sal_Int32 nRightBorder; + sal_Int32 nBottomBorder; + mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder ); + if ( nLeftBorder || nTopBorder || nRightBorder || nBottomBorder ) + { + tools::Rectangle aWinRect( Point( 0, 0 ), GetOutputSizePixel() ); + vcl::Region aRegion( aWinRect ); + aWinRect.AdjustLeft(nLeftBorder ); + aWinRect.AdjustTop(nTopBorder ); + aWinRect.AdjustRight( -nRightBorder ); + aWinRect.AdjustBottom( -nBottomBorder ); + // no output area anymore, now invalidate all + if ( (aWinRect.Right() < aWinRect.Left()) || + (aWinRect.Bottom() < aWinRect.Top()) ) + Invalidate( InvalidateFlags::NoChildren ); + else + { + aRegion.Exclude( aWinRect ); + Invalidate( aRegion, InvalidateFlags::NoChildren ); + } + } + } +} + +void ImplBorderWindow::SetDisplayActive( bool bActive ) +{ + if ( mbDisplayActive != bActive ) + { + mbDisplayActive = bActive; + if ( mbFrameBorder ) + InvalidateBorder(); + } +} + +void ImplBorderWindow::SetTitleType( BorderWindowTitleType nTitleType, const Size& rSize ) +{ + mnTitleType = nTitleType; + UpdateView( false, rSize ); +} + +void ImplBorderWindow::SetBorderStyle( WindowBorderStyle nStyle ) +{ + if ( !mbFrameBorder && (mnBorderStyle != nStyle) ) + { + mnBorderStyle = nStyle; + UpdateView( false, ImplGetWindow()->GetOutputSizePixel() ); + } +} + +void ImplBorderWindow::SetRollUp( bool bRollUp, const Size& rSize ) +{ + mbRollUp = bRollUp; + UpdateView( false, rSize ); +} + +void ImplBorderWindow::SetCloseButton() +{ + SetStyle( GetStyle() | WB_CLOSEABLE ); + Size aSize = GetOutputSizePixel(); + mpBorderView->Init( this, aSize.Width(), aSize.Height() ); + InvalidateBorder(); +} + +void ImplBorderWindow::SetDockButton( bool bDockButton ) +{ + mbDockBtn = bDockButton; + Size aSize = GetOutputSizePixel(); + mpBorderView->Init( this, aSize.Width(), aSize.Height() ); + InvalidateBorder(); +} + +void ImplBorderWindow::SetHideButton( bool bHideButton ) +{ + mbHideBtn = bHideButton; + Size aSize = GetOutputSizePixel(); + mpBorderView->Init( this, aSize.Width(), aSize.Height() ); + InvalidateBorder(); +} + +void ImplBorderWindow::SetMenuButton( bool bMenuButton ) +{ + mbMenuBtn = bMenuButton; + Size aSize = GetOutputSizePixel(); + mpBorderView->Init( this, aSize.Width(), aSize.Height() ); + InvalidateBorder(); +} + +void ImplBorderWindow::UpdateMenuHeight() +{ + Resize(); +} + +void ImplBorderWindow::SetMenuBarWindow( vcl::Window* pWindow ) +{ + mpMenuBarWindow = pWindow; + UpdateMenuHeight(); + if ( pWindow ) + pWindow->Show(); +} + +void ImplBorderWindow::SetMenuBarMode( bool bHide ) +{ + mbMenuHide = bHide; + UpdateMenuHeight(); +} + +void ImplBorderWindow::SetNotebookBar(const OUString& rUIXMLDescription, + const css::uno::Reference<css::frame::XFrame>& rFrame, + const NotebookBarAddonsItem& aNotebookBarAddonsItem) +{ + if (mpNotebookBar) + mpNotebookBar.disposeAndClear(); + mpNotebookBar = VclPtr<NotebookBar>::Create(this, "NotebookBar", rUIXMLDescription, rFrame, + aNotebookBarAddonsItem); + Resize(); +} + +void ImplBorderWindow::CloseNotebookBar() +{ + if (mpNotebookBar) + mpNotebookBar.disposeAndClear(); + mpNotebookBar = nullptr; + Resize(); +} + +void ImplBorderWindow::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder, + sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const +{ + mpBorderView->GetBorder(rLeftBorder, rTopBorder, rRightBorder, rBottomBorder); + + if (mpMenuBarWindow && !mbMenuHide) + rTopBorder += mpMenuBarWindow->GetSizePixel().Height(); + + if (mpNotebookBar && mpNotebookBar->IsVisible()) + rTopBorder += mpNotebookBar->GetSizePixel().Height(); +} + +long ImplBorderWindow::CalcTitleWidth() const +{ + return mpBorderView->CalcTitleWidth(); +} + +tools::Rectangle ImplBorderWindow::GetMenuRect() const +{ + return mpBorderView->GetMenuRect(); +} + +Size ImplBorderWindow::GetOptimalSize() const +{ + const vcl::Window* pClientWindow = ImplGetClientWindow(); + if (pClientWindow) + return pClientWindow->GetOptimalSize(); + return Size(mnMinWidth, mnMinHeight); +} + +void ImplBorderWindow::queue_resize(StateChangedType eReason) +{ + //if we are floating, then we don't want to inform our parent that it needs + //to calculate a new layout allocation. Because while we are a child + //of our parent we are not embedded into the parent so it doesn't care + //about us. + if (mbFloatWindow) + return; + vcl::Window::queue_resize(eReason); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |