summaryrefslogtreecommitdiffstats
path: root/vcl/source/window/brdwin.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/window/brdwin.cxx')
-rw-r--r--vcl/source/window/brdwin.cxx2080
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: */