1301 lines
40 KiB
C++
1301 lines
40 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <vcl/headbar.hxx>
|
|
#include <rtl/ustrbuf.hxx>
|
|
#include <tools/debug.hxx>
|
|
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/help.hxx>
|
|
#include <vcl/image.hxx>
|
|
#include <vcl/salnativewidgets.hxx>
|
|
#include <vcl/settings.hxx>
|
|
#include <vcl/commandevent.hxx>
|
|
#include <vcl/event.hxx>
|
|
#include <vcl/ptrstyle.hxx>
|
|
|
|
#include <com/sun/star/accessibility/XAccessible.hpp>
|
|
|
|
class ImplHeadItem
|
|
{
|
|
public:
|
|
sal_uInt16 mnId;
|
|
HeaderBarItemBits mnBits;
|
|
tools::Long mnSize;
|
|
OString maHelpId;
|
|
Image maImage;
|
|
OUString maOutText;
|
|
OUString maText;
|
|
OUString maHelpText;
|
|
};
|
|
|
|
#define HEAD_ARROWSIZE1 4
|
|
#define HEAD_ARROWSIZE2 7
|
|
|
|
#define HEADERBAR_TEXTOFF 2
|
|
#define HEADERBAR_ARROWOFF 5
|
|
#define HEADERBAR_SPLITOFF 3
|
|
|
|
#define HEADERBAR_DRAGOUTOFF 15
|
|
|
|
#define HEAD_HITTEST_ITEM (sal_uInt16(0x0001))
|
|
#define HEAD_HITTEST_DIVIDER (sal_uInt16(0x0002))
|
|
|
|
void HeaderBar::ImplInit( WinBits nWinStyle )
|
|
{
|
|
mnBorderOff1 = 0;
|
|
mnBorderOff2 = 0;
|
|
mnOffset = 0;
|
|
mnDX = 0;
|
|
mnDY = 0;
|
|
mnDragSize = 0;
|
|
mnStartPos = 0;
|
|
mnDragPos = 0;
|
|
mnMouseOff = 0;
|
|
mnCurItemId = 0;
|
|
mnItemDragPos = HEADERBAR_ITEM_NOTFOUND;
|
|
mbDrag = false;
|
|
mbItemDrag = false;
|
|
mbOutDrag = false;
|
|
mbItemMode = false;
|
|
|
|
// evaluate StyleBits
|
|
if ( nWinStyle & WB_DRAG )
|
|
mbDragable = true;
|
|
else
|
|
mbDragable = false;
|
|
if ( nWinStyle & WB_BUTTONSTYLE )
|
|
mbButtonStyle = true;
|
|
else
|
|
mbButtonStyle = false;
|
|
if ( nWinStyle & WB_BORDER )
|
|
{
|
|
mnBorderOff1 = 1;
|
|
mnBorderOff2 = 1;
|
|
}
|
|
else
|
|
{
|
|
if ( nWinStyle & WB_BOTTOMBORDER )
|
|
mnBorderOff2 = 1;
|
|
}
|
|
|
|
ImplInitSettings( true, true, true );
|
|
}
|
|
|
|
HeaderBar::HeaderBar(vcl::Window* pParent, WinBits nWinStyle)
|
|
: Window(pParent, nWinStyle & WB_3DLOOK)
|
|
{
|
|
SetType(WindowType::HEADERBAR);
|
|
ImplInit(nWinStyle);
|
|
SetSizePixel( CalcWindowSizePixel() );
|
|
}
|
|
|
|
Size HeaderBar::GetOptimalSize() const
|
|
{
|
|
return CalcWindowSizePixel();
|
|
}
|
|
|
|
HeaderBar::~HeaderBar() = default;
|
|
|
|
void HeaderBar::ApplySettings(vcl::RenderContext& rRenderContext)
|
|
{
|
|
const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
|
|
|
|
ApplyControlFont(rRenderContext, rStyleSettings.GetToolFont());
|
|
|
|
ApplyControlForeground(rRenderContext, rStyleSettings.GetButtonTextColor());
|
|
SetTextFillColor();
|
|
|
|
ApplyControlBackground(rRenderContext, rStyleSettings.GetFaceColor());
|
|
}
|
|
|
|
void HeaderBar::ImplInitSettings(bool bFont, bool bForeground, bool bBackground)
|
|
{
|
|
const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
|
|
|
|
if (bFont)
|
|
ApplyControlFont(*GetOutDev(), rStyleSettings.GetToolFont());
|
|
|
|
if (bForeground || bFont)
|
|
{
|
|
ApplyControlForeground(*GetOutDev(), rStyleSettings.GetButtonTextColor());
|
|
SetTextFillColor();
|
|
}
|
|
|
|
if (bBackground)
|
|
ApplyControlBackground(*GetOutDev(), rStyleSettings.GetFaceColor());
|
|
}
|
|
|
|
tools::Long HeaderBar::ImplGetItemPos( sal_uInt16 nPos ) const
|
|
{
|
|
tools::Long nX = -mnOffset;
|
|
for ( size_t i = 0; i < nPos; i++ )
|
|
nX += mvItemList[ i ]->mnSize;
|
|
return nX;
|
|
}
|
|
|
|
tools::Rectangle HeaderBar::ImplGetItemRect( sal_uInt16 nPos ) const
|
|
{
|
|
tools::Rectangle aRect( ImplGetItemPos( nPos ), 0, 0, mnDY-1 );
|
|
aRect.SetRight( aRect.Left() + mvItemList[ nPos ]->mnSize - 1 );
|
|
// check for overflow on various systems
|
|
if ( aRect.Right() > 16000 )
|
|
aRect.SetRight( 16000 );
|
|
return aRect;
|
|
}
|
|
|
|
sal_uInt16 HeaderBar::ImplDoHitTest( const Point& rPos,
|
|
tools::Long& nMouseOff, sal_uInt16& nPos ) const
|
|
{
|
|
size_t nCount = static_cast<sal_uInt16>(mvItemList.size());
|
|
bool bLastFixed = true;
|
|
tools::Long nX = -mnOffset;
|
|
|
|
for ( size_t i = 0; i < nCount; i++ )
|
|
{
|
|
auto& pItem = mvItemList[ i ];
|
|
|
|
if ( rPos.X() < (nX+pItem->mnSize) )
|
|
{
|
|
sal_uInt16 nMode;
|
|
|
|
if ( !bLastFixed && (rPos.X() < (nX+HEADERBAR_SPLITOFF)) )
|
|
{
|
|
nMode = HEAD_HITTEST_DIVIDER;
|
|
nPos = i-1;
|
|
nMouseOff = rPos.X()-nX+1;
|
|
}
|
|
else
|
|
{
|
|
nPos = i;
|
|
|
|
if ( rPos.X() >= (nX+pItem->mnSize-HEADERBAR_SPLITOFF) )
|
|
{
|
|
nMode = HEAD_HITTEST_DIVIDER;
|
|
nMouseOff = rPos.X()-(nX+pItem->mnSize);
|
|
}
|
|
else
|
|
{
|
|
nMode = HEAD_HITTEST_ITEM;
|
|
nMouseOff = rPos.X()-nX;
|
|
}
|
|
}
|
|
|
|
return nMode;
|
|
}
|
|
|
|
bLastFixed = false;
|
|
|
|
nX += pItem->mnSize;
|
|
}
|
|
|
|
if ( !bLastFixed )
|
|
{
|
|
auto& pItem = mvItemList[ nCount-1 ];
|
|
if ( (pItem->mnSize < 4) && (rPos.X() < (nX+HEADERBAR_SPLITOFF)) )
|
|
{
|
|
nPos = nCount-1;
|
|
nMouseOff = rPos.X()-nX+1;
|
|
return HEAD_HITTEST_DIVIDER;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void HeaderBar::ImplInvertDrag( sal_uInt16 nStartPos, sal_uInt16 nEndPos )
|
|
{
|
|
tools::Rectangle aRect1 = ImplGetItemRect( nStartPos );
|
|
tools::Rectangle aRect2 = ImplGetItemRect( nEndPos );
|
|
Point aStartPos = aRect1.Center();
|
|
Point aEndPos = aStartPos;
|
|
tools::Rectangle aStartRect( aStartPos.X()-2, aStartPos.Y()-2,
|
|
aStartPos.X()+2, aStartPos.Y()+2 );
|
|
|
|
if ( nEndPos > nStartPos )
|
|
{
|
|
aStartPos.AdjustX(3 );
|
|
aEndPos.setX( aRect2.Right()-6 );
|
|
}
|
|
else
|
|
{
|
|
aStartPos.AdjustX( -3 );
|
|
aEndPos.setX( aRect2.Left()+6 );
|
|
}
|
|
|
|
GetOutDev()->SetRasterOp( RasterOp::Invert );
|
|
GetOutDev()->DrawRect( aStartRect );
|
|
GetOutDev()->DrawLine( aStartPos, aEndPos );
|
|
if ( nEndPos > nStartPos )
|
|
{
|
|
GetOutDev()->DrawLine( Point( aEndPos.X()+1, aEndPos.Y()-3 ),
|
|
Point( aEndPos.X()+1, aEndPos.Y()+3 ) );
|
|
GetOutDev()->DrawLine( Point( aEndPos.X()+2, aEndPos.Y()-2 ),
|
|
Point( aEndPos.X()+2, aEndPos.Y()+2 ) );
|
|
GetOutDev()->DrawLine( Point( aEndPos.X()+3, aEndPos.Y()-1 ),
|
|
Point( aEndPos.X()+3, aEndPos.Y()+1 ) );
|
|
GetOutDev()->DrawPixel( Point( aEndPos.X()+4, aEndPos.Y() ) );
|
|
}
|
|
else
|
|
{
|
|
GetOutDev()->DrawLine( Point( aEndPos.X()-1, aEndPos.Y()-3 ),
|
|
Point( aEndPos.X()-1, aEndPos.Y()+3 ) );
|
|
GetOutDev()->DrawLine( Point( aEndPos.X()-2, aEndPos.Y()-2 ),
|
|
Point( aEndPos.X()-2, aEndPos.Y()+2 ) );
|
|
GetOutDev()->DrawLine( Point( aEndPos.X()-3, aEndPos.Y()-1 ),
|
|
Point( aEndPos.X()-3, aEndPos.Y()+1 ) );
|
|
GetOutDev()->DrawPixel( Point( aEndPos.X()-4, aEndPos.Y() ) );
|
|
}
|
|
GetOutDev()->SetRasterOp( RasterOp::OverPaint );
|
|
}
|
|
|
|
void HeaderBar::ImplDrawItem(vcl::RenderContext& rRenderContext, sal_uInt16 nPos, bool bHigh,
|
|
const tools::Rectangle& rItemRect, const tools::Rectangle* pRect )
|
|
{
|
|
ImplControlValue aControlValue(0);
|
|
tools::Rectangle aCtrlRegion;
|
|
ControlState nState(ControlState::NONE);
|
|
|
|
tools::Rectangle aRect = rItemRect;
|
|
|
|
// do not display if there is no space
|
|
if (aRect.GetWidth() <= 1)
|
|
return;
|
|
|
|
// check of rectangle is visible
|
|
if (pRect)
|
|
{
|
|
if (aRect.Right() < pRect->Left())
|
|
return;
|
|
else if (aRect.Left() > pRect->Right())
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (aRect.Right() < 0)
|
|
return;
|
|
else if (aRect.Left() > mnDX)
|
|
return;
|
|
}
|
|
|
|
auto& pItem = mvItemList[nPos];
|
|
HeaderBarItemBits nBits = pItem->mnBits;
|
|
const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
|
|
|
|
if (rRenderContext.IsNativeControlSupported(ControlType::WindowBackground, ControlPart::Entire))
|
|
{
|
|
aCtrlRegion = aRect;
|
|
rRenderContext.DrawNativeControl(ControlType::WindowBackground, ControlPart::Entire,
|
|
aCtrlRegion, nState, aControlValue, OUString());
|
|
|
|
}
|
|
else
|
|
{
|
|
// do not draw border
|
|
aRect.AdjustTop(mnBorderOff1 );
|
|
aRect.AdjustBottom( -mnBorderOff2 );
|
|
|
|
// delete background
|
|
if ( !pRect )
|
|
{
|
|
rRenderContext.DrawWallpaper(aRect, rRenderContext.GetBackground());
|
|
}
|
|
}
|
|
|
|
Color aSelectionTextColor(COL_TRANSPARENT);
|
|
|
|
if (rRenderContext.IsNativeControlSupported(ControlType::ListHeader, ControlPart::Button))
|
|
{
|
|
aCtrlRegion = aRect;
|
|
aControlValue.setTristateVal(ButtonValue::On);
|
|
nState |= ControlState::ENABLED;
|
|
if (bHigh)
|
|
nState |= ControlState::PRESSED;
|
|
rRenderContext.DrawNativeControl(ControlType::ListHeader, ControlPart::Button,
|
|
aCtrlRegion, nState, aControlValue, OUString());
|
|
}
|
|
else
|
|
{
|
|
// draw separation line
|
|
rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
|
|
rRenderContext.DrawLine(Point(aRect.Right(), aRect.Top()), Point(aRect.Right(), aRect.Bottom()));
|
|
|
|
// draw ButtonStyle
|
|
// avoid 3D borders
|
|
if (bHigh)
|
|
vcl::RenderTools::DrawSelectionBackground(rRenderContext, *this, aRect, 1, true, false, false, &aSelectionTextColor);
|
|
else if (!mbButtonStyle || (nBits & HeaderBarItemBits::FLAT))
|
|
vcl::RenderTools::DrawSelectionBackground(rRenderContext, *this, aRect, 0, true, false, false, &aSelectionTextColor);
|
|
}
|
|
|
|
// do not draw if there is no space
|
|
if (aRect.GetWidth() < 1)
|
|
return;
|
|
|
|
// calculate size and position and draw content
|
|
pItem->maOutText = pItem->maText;
|
|
Size aImageSize = pItem->maImage.GetSizePixel();
|
|
Size aTxtSize(rRenderContext.GetTextWidth(pItem->maOutText), 0);
|
|
if (!pItem->maOutText.isEmpty())
|
|
aTxtSize.setHeight( rRenderContext.GetTextHeight() );
|
|
tools::Long nArrowWidth = 0;
|
|
if (nBits & (HeaderBarItemBits::UPARROW | HeaderBarItemBits::DOWNARROW))
|
|
nArrowWidth = HEAD_ARROWSIZE2 + HEADERBAR_ARROWOFF;
|
|
|
|
// do not draw if there is not enough space for the image
|
|
tools::Long nTestHeight = aImageSize.Height();
|
|
if (!(nBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE)))
|
|
nTestHeight += aTxtSize.Height();
|
|
if ((aImageSize.Width() > aRect.GetWidth()) || (nTestHeight > aRect.GetHeight()))
|
|
{
|
|
aImageSize.setWidth( 0 );
|
|
aImageSize.setHeight( 0 );
|
|
}
|
|
|
|
// cut text to correct length
|
|
bool bLeftText = false;
|
|
tools::Long nMaxTxtWidth = aRect.GetWidth() - (HEADERBAR_TEXTOFF * 2) - nArrowWidth;
|
|
if (nBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE))
|
|
nMaxTxtWidth -= aImageSize.Width();
|
|
tools::Long nTxtWidth = aTxtSize.Width();
|
|
if (nTxtWidth > nMaxTxtWidth)
|
|
{
|
|
bLeftText = true;
|
|
OUStringBuffer aBuf(pItem->maOutText + "...");
|
|
do
|
|
{
|
|
aBuf.remove(aBuf.getLength() - 3 - 1, 1);
|
|
nTxtWidth = rRenderContext.GetTextWidth(aBuf.toString());
|
|
}
|
|
while ((nTxtWidth > nMaxTxtWidth) && (aBuf.getLength() > 3));
|
|
pItem->maOutText = aBuf.makeStringAndClear();
|
|
if (pItem->maOutText.getLength() == 3)
|
|
{
|
|
nTxtWidth = 0;
|
|
pItem->maOutText.clear();
|
|
}
|
|
}
|
|
|
|
// calculate text/imageposition
|
|
tools::Long nTxtPos;
|
|
if (!bLeftText && (nBits & HeaderBarItemBits::RIGHT))
|
|
{
|
|
nTxtPos = aRect.Right() - nTxtWidth - HEADERBAR_TEXTOFF;
|
|
if (nBits & HeaderBarItemBits::RIGHTIMAGE)
|
|
nTxtPos -= aImageSize.Width();
|
|
}
|
|
else if (!bLeftText && (nBits & HeaderBarItemBits::CENTER))
|
|
{
|
|
tools::Long nTempWidth = nTxtWidth;
|
|
if (nBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE))
|
|
nTempWidth += aImageSize.Width();
|
|
nTxtPos = aRect.Left() + (aRect.GetWidth() - nTempWidth) / 2;
|
|
if (nBits & HeaderBarItemBits::LEFTIMAGE)
|
|
nTxtPos += aImageSize.Width();
|
|
if (nArrowWidth)
|
|
{
|
|
if (nTxtPos + nTxtWidth + nArrowWidth >= aRect.Right())
|
|
{
|
|
nTxtPos = aRect.Left() + HEADERBAR_TEXTOFF;
|
|
if (nBits & HeaderBarItemBits::LEFTIMAGE)
|
|
nTxtPos += aImageSize.Width();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nTxtPos = aRect.Left() + HEADERBAR_TEXTOFF;
|
|
if (nBits & HeaderBarItemBits::LEFTIMAGE)
|
|
nTxtPos += aImageSize.Width();
|
|
if (nBits & HeaderBarItemBits::RIGHT)
|
|
nTxtPos += nArrowWidth;
|
|
}
|
|
|
|
// calculate text/imageposition
|
|
tools::Long nTxtPosY = 0;
|
|
if (!pItem->maOutText.isEmpty() || (nArrowWidth && aTxtSize.Height()))
|
|
{
|
|
tools::Long nTempHeight = aTxtSize.Height();
|
|
nTempHeight += aImageSize.Height();
|
|
nTxtPosY = aRect.Top()+((aRect.GetHeight()-nTempHeight)/2);
|
|
if (!(nBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE)))
|
|
nTxtPosY += aImageSize.Height();
|
|
}
|
|
|
|
// display text
|
|
if (!pItem->maOutText.isEmpty())
|
|
{
|
|
if (aSelectionTextColor != COL_TRANSPARENT)
|
|
{
|
|
rRenderContext.Push(vcl::PushFlags::TEXTCOLOR);
|
|
rRenderContext.SetTextColor(aSelectionTextColor);
|
|
}
|
|
if (IsEnabled())
|
|
rRenderContext.DrawText(Point(nTxtPos, nTxtPosY), pItem->maOutText);
|
|
else
|
|
rRenderContext.DrawCtrlText(Point(nTxtPos, nTxtPosY), pItem->maOutText, 0, pItem->maOutText.getLength(), DrawTextFlags::Disable);
|
|
if (aSelectionTextColor != COL_TRANSPARENT)
|
|
rRenderContext.Pop();
|
|
}
|
|
|
|
// calculate the position and draw image if it is available
|
|
tools::Long nImagePosY = 0;
|
|
if (aImageSize.Width() && aImageSize.Height())
|
|
{
|
|
tools::Long nImagePos = nTxtPos;
|
|
if (nBits & HeaderBarItemBits::LEFTIMAGE)
|
|
{
|
|
nImagePos -= aImageSize.Width();
|
|
if (nBits & HeaderBarItemBits::RIGHT)
|
|
nImagePos -= nArrowWidth;
|
|
}
|
|
else if (nBits & HeaderBarItemBits::RIGHTIMAGE)
|
|
{
|
|
nImagePos += nTxtWidth;
|
|
if (!(nBits & HeaderBarItemBits::RIGHT))
|
|
nImagePos += nArrowWidth;
|
|
}
|
|
else
|
|
{
|
|
if (nBits & HeaderBarItemBits::RIGHT )
|
|
nImagePos = aRect.Right()-aImageSize.Width();
|
|
else if (nBits & HeaderBarItemBits::CENTER)
|
|
nImagePos = aRect.Left() + (aRect.GetWidth() - aImageSize.Width()) / 2;
|
|
else
|
|
nImagePos = aRect.Left() + HEADERBAR_TEXTOFF;
|
|
}
|
|
|
|
tools::Long nTempHeight = aImageSize.Height();
|
|
if (!(nBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE)))
|
|
nTempHeight += aTxtSize.Height();
|
|
nImagePosY = aRect.Top() + ((aRect.GetHeight() - nTempHeight) / 2);
|
|
|
|
if (nImagePos + aImageSize.Width() <= aRect.Right())
|
|
{
|
|
DrawImageFlags nStyle = DrawImageFlags::NONE;
|
|
if (!IsEnabled())
|
|
nStyle |= DrawImageFlags::Disable;
|
|
rRenderContext.DrawImage(Point(nImagePos, nImagePosY), pItem->maImage, nStyle);
|
|
}
|
|
}
|
|
|
|
if (!(nBits & (HeaderBarItemBits::UPARROW | HeaderBarItemBits::DOWNARROW)))
|
|
return;
|
|
|
|
tools::Long nArrowX = nTxtPos;
|
|
if (nBits & HeaderBarItemBits::RIGHT)
|
|
nArrowX -= nArrowWidth;
|
|
else
|
|
nArrowX += nTxtWidth + HEADERBAR_ARROWOFF;
|
|
if (!(nBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE)) && pItem->maText.isEmpty())
|
|
{
|
|
if (nBits & HeaderBarItemBits::RIGHT)
|
|
nArrowX -= aImageSize.Width();
|
|
else
|
|
nArrowX += aImageSize.Width();
|
|
}
|
|
|
|
// is there enough space to draw the item?
|
|
bool bDraw = true;
|
|
if (nArrowX < aRect.Left() + HEADERBAR_TEXTOFF)
|
|
bDraw = false;
|
|
else if (nArrowX + HEAD_ARROWSIZE2 > aRect.Right())
|
|
bDraw = false;
|
|
|
|
if (!bDraw)
|
|
return;
|
|
|
|
if (rRenderContext.IsNativeControlSupported(ControlType::ListHeader, ControlPart::Arrow))
|
|
{
|
|
aCtrlRegion = tools::Rectangle(Point(nArrowX, aRect.Top()), Size(nArrowWidth, aRect.GetHeight()));
|
|
// control value passes 1 if arrow points down, 0 otherwise
|
|
aControlValue.setNumericVal((nBits & HeaderBarItemBits::DOWNARROW) ? 1 : 0);
|
|
nState |= ControlState::ENABLED;
|
|
if (bHigh)
|
|
nState |= ControlState::PRESSED;
|
|
rRenderContext.DrawNativeControl(ControlType::ListHeader, ControlPart::Arrow, aCtrlRegion,
|
|
nState, aControlValue, OUString());
|
|
}
|
|
else
|
|
{
|
|
tools::Long nArrowY;
|
|
if (aTxtSize.Height())
|
|
nArrowY = nTxtPosY + (aTxtSize.Height() / 2);
|
|
else if (aImageSize.Width() && aImageSize.Height())
|
|
nArrowY = nImagePosY + (aImageSize.Height() / 2);
|
|
else
|
|
nArrowY = aRect.Top() + ((aRect.GetHeight() - HEAD_ARROWSIZE2) / 2);
|
|
nArrowY -= HEAD_ARROWSIZE1 - 1;
|
|
if (nBits & HeaderBarItemBits::DOWNARROW)
|
|
{
|
|
rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
|
|
rRenderContext.DrawLine(Point(nArrowX, nArrowY),
|
|
Point(nArrowX + HEAD_ARROWSIZE2, nArrowY));
|
|
rRenderContext.DrawLine(Point(nArrowX, nArrowY),
|
|
Point(nArrowX + HEAD_ARROWSIZE1, nArrowY + HEAD_ARROWSIZE2));
|
|
rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
|
|
rRenderContext.DrawLine(Point(nArrowX + HEAD_ARROWSIZE1, nArrowY + HEAD_ARROWSIZE2),
|
|
Point(nArrowX + HEAD_ARROWSIZE2, nArrowY));
|
|
}
|
|
else
|
|
{
|
|
rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
|
|
rRenderContext.DrawLine(Point(nArrowX, nArrowY + HEAD_ARROWSIZE2),
|
|
Point(nArrowX + HEAD_ARROWSIZE1, nArrowY));
|
|
rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
|
|
rRenderContext.DrawLine(Point(nArrowX, nArrowY + HEAD_ARROWSIZE2),
|
|
Point(nArrowX + HEAD_ARROWSIZE2, nArrowY + HEAD_ARROWSIZE2));
|
|
rRenderContext.DrawLine(Point(nArrowX + HEAD_ARROWSIZE2, nArrowY + HEAD_ARROWSIZE2),
|
|
Point(nArrowX + HEAD_ARROWSIZE1, nArrowY));
|
|
}
|
|
}
|
|
}
|
|
|
|
void HeaderBar::ImplDrawItem(vcl::RenderContext& rRenderContext, sal_uInt16 nPos,
|
|
bool bHigh, const tools::Rectangle* pRect )
|
|
{
|
|
tools::Rectangle aRect = ImplGetItemRect(nPos);
|
|
ImplDrawItem(rRenderContext, nPos, bHigh, aRect, pRect );
|
|
}
|
|
|
|
void HeaderBar::ImplUpdate(sal_uInt16 nPos, bool bEnd)
|
|
{
|
|
if (!(IsVisible() && IsUpdateMode()))
|
|
return;
|
|
|
|
tools::Rectangle aRect;
|
|
size_t nItemCount = mvItemList.size();
|
|
if (nPos < nItemCount)
|
|
aRect = ImplGetItemRect(nPos);
|
|
else
|
|
{
|
|
aRect.SetBottom( mnDY - 1 );
|
|
if (nItemCount)
|
|
aRect.SetLeft( ImplGetItemRect(nItemCount - 1).Right() );
|
|
}
|
|
if (bEnd)
|
|
aRect.SetRight( mnDX - 1 );
|
|
aRect.AdjustTop(mnBorderOff1 );
|
|
aRect.AdjustBottom( -mnBorderOff2 );
|
|
Invalidate(aRect);
|
|
}
|
|
|
|
void HeaderBar::ImplStartDrag( const Point& rMousePos, bool bCommand )
|
|
{
|
|
sal_uInt16 nPos;
|
|
sal_uInt16 nHitTest = ImplDoHitTest( rMousePos, mnMouseOff, nPos );
|
|
if ( !nHitTest )
|
|
return;
|
|
|
|
mbDrag = false;
|
|
auto& pItem = mvItemList[ nPos ];
|
|
if ( nHitTest & HEAD_HITTEST_DIVIDER )
|
|
mbDrag = true;
|
|
else
|
|
{
|
|
if ( ((pItem->mnBits & HeaderBarItemBits::CLICKABLE) && !(pItem->mnBits & HeaderBarItemBits::FLAT)) ||
|
|
mbDragable )
|
|
{
|
|
mbItemMode = true;
|
|
mbDrag = true;
|
|
if ( bCommand )
|
|
{
|
|
if ( mbDragable )
|
|
mbItemDrag = true;
|
|
else
|
|
{
|
|
mbItemMode = false;
|
|
mbDrag = false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !bCommand )
|
|
{
|
|
mnCurItemId = pItem->mnId;
|
|
Select();
|
|
mnCurItemId = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( mbDrag )
|
|
{
|
|
mbOutDrag = false;
|
|
mnCurItemId = pItem->mnId;
|
|
mnItemDragPos = nPos;
|
|
StartTracking();
|
|
mnStartPos = rMousePos.X()-mnMouseOff;
|
|
mnDragPos = mnStartPos;
|
|
maStartDragHdl.Call( this );
|
|
if (mbItemMode)
|
|
Invalidate();
|
|
else
|
|
{
|
|
tools::Rectangle aSizeRect( mnDragPos, 0, mnDragPos, mnDragSize+mnDY );
|
|
ShowTracking( aSizeRect, ShowTrackFlags::Split );
|
|
}
|
|
}
|
|
else
|
|
mnMouseOff = 0;
|
|
}
|
|
|
|
void HeaderBar::ImplDrag( const Point& rMousePos )
|
|
{
|
|
sal_uInt16 nPos = GetItemPos( mnCurItemId );
|
|
|
|
mnDragPos = rMousePos.X()-mnMouseOff;
|
|
if ( mbItemMode )
|
|
{
|
|
bool bNewOutDrag;
|
|
|
|
tools::Rectangle aItemRect = ImplGetItemRect( nPos );
|
|
bNewOutDrag = !aItemRect.Contains( rMousePos );
|
|
|
|
// if needed switch on ItemDrag
|
|
if ( bNewOutDrag && mbDragable && !mbItemDrag )
|
|
{
|
|
if ( (rMousePos.Y() >= aItemRect.Top()) && (rMousePos.Y() <= aItemRect.Bottom()) )
|
|
{
|
|
mbItemDrag = true;
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
sal_uInt16 nOldItemDragPos = mnItemDragPos;
|
|
if ( mbItemDrag )
|
|
{
|
|
bNewOutDrag = (rMousePos.Y() < -HEADERBAR_DRAGOUTOFF) || (rMousePos.Y() > mnDY+HEADERBAR_DRAGOUTOFF);
|
|
|
|
if ( bNewOutDrag )
|
|
mnItemDragPos = HEADERBAR_ITEM_NOTFOUND;
|
|
else
|
|
{
|
|
sal_uInt16 nTempId = GetItemId( Point( rMousePos.X(), 2 ) );
|
|
if ( nTempId )
|
|
mnItemDragPos = GetItemPos( nTempId );
|
|
else
|
|
{
|
|
if ( rMousePos.X() <= 0 )
|
|
mnItemDragPos = 0;
|
|
else
|
|
mnItemDragPos = GetItemCount()-1;
|
|
}
|
|
}
|
|
|
|
if ( (mnItemDragPos != nOldItemDragPos) &&
|
|
(nOldItemDragPos != nPos) &&
|
|
(nOldItemDragPos != HEADERBAR_ITEM_NOTFOUND) )
|
|
{
|
|
ImplInvertDrag( nPos, nOldItemDragPos );
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
if ( bNewOutDrag != mbOutDrag )
|
|
Invalidate();
|
|
|
|
if ( mbItemDrag )
|
|
{
|
|
if ( (mnItemDragPos != nOldItemDragPos) &&
|
|
(mnItemDragPos != nPos) &&
|
|
(mnItemDragPos != HEADERBAR_ITEM_NOTFOUND) )
|
|
{
|
|
Invalidate();
|
|
ImplInvertDrag( nPos, mnItemDragPos );
|
|
}
|
|
}
|
|
|
|
mbOutDrag = bNewOutDrag;
|
|
}
|
|
else
|
|
{
|
|
tools::Rectangle aItemRect = ImplGetItemRect( nPos );
|
|
if ( mnDragPos < aItemRect.Left() )
|
|
mnDragPos = aItemRect.Left();
|
|
if ( (mnDragPos < 0) || (mnDragPos > mnDX-1) )
|
|
HideTracking();
|
|
else
|
|
{
|
|
tools::Rectangle aSizeRect( mnDragPos, 0, mnDragPos, mnDragSize+mnDY );
|
|
ShowTracking( aSizeRect, ShowTrackFlags::Split );
|
|
}
|
|
}
|
|
}
|
|
|
|
void HeaderBar::ImplEndDrag( bool bCancel )
|
|
{
|
|
HideTracking();
|
|
|
|
if ( bCancel || mbOutDrag )
|
|
{
|
|
if ( mbItemMode && (!mbOutDrag || mbItemDrag) )
|
|
{
|
|
Invalidate();
|
|
}
|
|
|
|
mnCurItemId = 0;
|
|
}
|
|
else
|
|
{
|
|
sal_uInt16 nPos = GetItemPos( mnCurItemId );
|
|
if ( mbItemMode )
|
|
{
|
|
if ( mbItemDrag )
|
|
{
|
|
SetPointer( PointerStyle::Arrow );
|
|
if ( (mnItemDragPos != nPos) &&
|
|
(mnItemDragPos != HEADERBAR_ITEM_NOTFOUND) )
|
|
{
|
|
ImplInvertDrag( nPos, mnItemDragPos );
|
|
MoveItem( mnCurItemId, mnItemDragPos );
|
|
}
|
|
else
|
|
Invalidate();
|
|
}
|
|
else
|
|
{
|
|
Select();
|
|
ImplUpdate( nPos );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tools::Long nDelta = mnDragPos - mnStartPos;
|
|
if ( nDelta )
|
|
{
|
|
auto& pItem = mvItemList[ nPos ];
|
|
pItem->mnSize += nDelta;
|
|
ImplUpdate( nPos, true );
|
|
}
|
|
}
|
|
}
|
|
|
|
mbDrag = false;
|
|
EndDrag();
|
|
mnCurItemId = 0;
|
|
mnItemDragPos = HEADERBAR_ITEM_NOTFOUND;
|
|
mbOutDrag = false;
|
|
mbItemMode = false;
|
|
mbItemDrag = false;
|
|
}
|
|
|
|
void HeaderBar::MouseButtonDown( const MouseEvent& rMEvt )
|
|
{
|
|
if ( !rMEvt.IsLeft() )
|
|
return;
|
|
|
|
if ( rMEvt.GetClicks() == 2 )
|
|
{
|
|
tools::Long nTemp;
|
|
sal_uInt16 nPos;
|
|
sal_uInt16 nHitTest = ImplDoHitTest( rMEvt.GetPosPixel(), nTemp, nPos );
|
|
if ( nHitTest )
|
|
{
|
|
auto& pItem = mvItemList[ nPos ];
|
|
if ( nHitTest & HEAD_HITTEST_DIVIDER )
|
|
mbItemMode = false;
|
|
else
|
|
mbItemMode = true;
|
|
mnCurItemId = pItem->mnId;
|
|
DoubleClick();
|
|
mbItemMode = false;
|
|
mnCurItemId = 0;
|
|
}
|
|
}
|
|
else
|
|
ImplStartDrag( rMEvt.GetPosPixel(), false );
|
|
}
|
|
|
|
void HeaderBar::MouseMove( const MouseEvent& rMEvt )
|
|
{
|
|
tools::Long nTemp1;
|
|
sal_uInt16 nTemp2;
|
|
PointerStyle eStyle = PointerStyle::Arrow;
|
|
sal_uInt16 nHitTest = ImplDoHitTest( rMEvt.GetPosPixel(), nTemp1, nTemp2 );
|
|
|
|
if ( nHitTest & HEAD_HITTEST_DIVIDER )
|
|
eStyle = PointerStyle::HSizeBar;
|
|
SetPointer( eStyle );
|
|
}
|
|
|
|
void HeaderBar::Tracking( const TrackingEvent& rTEvt )
|
|
{
|
|
Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
|
|
|
|
if ( rTEvt.IsTrackingEnded() )
|
|
ImplEndDrag( rTEvt.IsTrackingCanceled() );
|
|
else
|
|
ImplDrag( aMousePos );
|
|
}
|
|
|
|
void HeaderBar::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
|
|
{
|
|
if (mnBorderOff1 || mnBorderOff2)
|
|
{
|
|
rRenderContext.SetLineColor(rRenderContext.GetSettings().GetStyleSettings().GetDarkShadowColor());
|
|
if (mnBorderOff1)
|
|
rRenderContext.DrawLine(Point(0, 0), Point(mnDX - 1, 0));
|
|
if (mnBorderOff2)
|
|
rRenderContext.DrawLine(Point(0, mnDY - 1), Point(mnDX - 1, mnDY - 1));
|
|
// #i40393# draw left and right border, if WB_BORDER was set in ImplInit()
|
|
if (mnBorderOff1 && mnBorderOff2)
|
|
{
|
|
rRenderContext.DrawLine(Point(0, 0), Point(0, mnDY - 1));
|
|
rRenderContext.DrawLine(Point(mnDX - 1, 0), Point(mnDX - 1, mnDY - 1));
|
|
}
|
|
}
|
|
|
|
sal_uInt16 nCurItemPos;
|
|
if (mbDrag)
|
|
nCurItemPos = GetItemPos(mnCurItemId);
|
|
else
|
|
nCurItemPos = HEADERBAR_ITEM_NOTFOUND;
|
|
sal_uInt16 nItemCount = static_cast<sal_uInt16>(mvItemList.size());
|
|
for (sal_uInt16 i = 0; i < nItemCount; i++)
|
|
ImplDrawItem(rRenderContext, i, (i == nCurItemPos), &rRect);
|
|
}
|
|
|
|
void HeaderBar::Draw( OutputDevice* pDev, const Point& rPos,
|
|
SystemTextColorFlags nFlags )
|
|
{
|
|
Point aPos = pDev->LogicToPixel( rPos );
|
|
Size aSize = GetSizePixel();
|
|
tools::Rectangle aRect( aPos, aSize );
|
|
vcl::Font aFont = GetDrawPixelFont( pDev );
|
|
|
|
pDev->Push();
|
|
pDev->SetMapMode();
|
|
pDev->SetFont( aFont );
|
|
if ( nFlags & SystemTextColorFlags::Mono )
|
|
pDev->SetTextColor( COL_BLACK );
|
|
else
|
|
pDev->SetTextColor( GetTextColor() );
|
|
pDev->SetTextFillColor();
|
|
|
|
// draw background
|
|
{
|
|
pDev->DrawWallpaper( aRect, GetBackground() );
|
|
if ( mnBorderOff1 || mnBorderOff2 )
|
|
{
|
|
pDev->SetLineColor( GetSettings().GetStyleSettings().GetDarkShadowColor() );
|
|
if ( mnBorderOff1 )
|
|
pDev->DrawLine( aRect.TopLeft(), Point( aRect.Right(), aRect.Top() ) );
|
|
if ( mnBorderOff2 )
|
|
pDev->DrawLine( Point( aRect.Left(), aRect.Bottom() ), Point( aRect.Right(), aRect.Bottom() ) );
|
|
// #i40393# draw left and right border, if WB_BORDER was set in ImplInit()
|
|
if ( mnBorderOff1 && mnBorderOff2 )
|
|
{
|
|
pDev->DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom() ) );
|
|
pDev->DrawLine( Point( aRect.Right(), aRect.Top() ), Point( aRect.Right(), aRect.Bottom() ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
tools::Rectangle aItemRect( aRect );
|
|
size_t nItemCount = mvItemList.size();
|
|
for ( size_t i = 0; i < nItemCount; i++ )
|
|
{
|
|
aItemRect.SetLeft( aRect.Left()+ImplGetItemPos( i ) );
|
|
aItemRect.SetRight( aItemRect.Left() + mvItemList[ i ]->mnSize - 1 );
|
|
// check for overflow on some systems
|
|
if ( aItemRect.Right() > 16000 )
|
|
aItemRect.SetRight( 16000 );
|
|
vcl::Region aRegion( aRect );
|
|
pDev->SetClipRegion( aRegion );
|
|
ImplDrawItem(*pDev, i, false, aItemRect, &aRect );
|
|
pDev->SetClipRegion();
|
|
}
|
|
|
|
pDev->Pop();
|
|
}
|
|
|
|
void HeaderBar::Resize()
|
|
{
|
|
Size aSize = GetOutputSizePixel();
|
|
if ( IsVisible() && (mnDY != aSize.Height()) )
|
|
Invalidate();
|
|
mnDX = aSize.Width();
|
|
mnDY = aSize.Height();
|
|
}
|
|
|
|
void HeaderBar::Command( const CommandEvent& rCEvt )
|
|
{
|
|
if ( rCEvt.IsMouseEvent() && (rCEvt.GetCommand() == CommandEventId::StartDrag) && !mbDrag )
|
|
{
|
|
ImplStartDrag( rCEvt.GetMousePosPixel(), true );
|
|
return;
|
|
}
|
|
|
|
Window::Command( rCEvt );
|
|
}
|
|
|
|
void HeaderBar::RequestHelp( const HelpEvent& rHEvt )
|
|
{
|
|
sal_uInt16 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
|
|
if ( nItemId )
|
|
{
|
|
if ( rHEvt.GetMode() & (HelpEventMode::QUICK | HelpEventMode::BALLOON) )
|
|
{
|
|
tools::Rectangle aItemRect = GetItemRect( nItemId );
|
|
Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
|
|
aItemRect.SetLeft( aPt.X() );
|
|
aItemRect.SetTop( aPt.Y() );
|
|
aPt = OutputToScreenPixel( aItemRect.BottomRight() );
|
|
aItemRect.SetRight( aPt.X() );
|
|
aItemRect.SetBottom( aPt.Y() );
|
|
|
|
OUString aStr = GetHelpText( nItemId );
|
|
if ( aStr.isEmpty() || !(rHEvt.GetMode() & HelpEventMode::BALLOON) )
|
|
{
|
|
auto& pItem = mvItemList[ GetItemPos( nItemId ) ];
|
|
// Quick-help is only displayed if the text is not fully visible.
|
|
// Otherwise we display Helptext only if the items do not contain text
|
|
if ( pItem->maOutText != pItem->maText )
|
|
aStr = pItem->maText;
|
|
else if (!pItem->maText.isEmpty())
|
|
aStr.clear();
|
|
}
|
|
|
|
if (!aStr.isEmpty())
|
|
{
|
|
if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
|
|
Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
|
|
else
|
|
Help::ShowQuickHelp( this, aItemRect, aStr );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
Window::RequestHelp( rHEvt );
|
|
}
|
|
|
|
void HeaderBar::StateChanged( StateChangedType nType )
|
|
{
|
|
Window::StateChanged( nType );
|
|
|
|
if ( nType == StateChangedType::Enable )
|
|
Invalidate();
|
|
else if ( (nType == StateChangedType::Zoom) ||
|
|
(nType == StateChangedType::ControlFont) )
|
|
{
|
|
ImplInitSettings( true, false, false );
|
|
Invalidate();
|
|
}
|
|
else if ( nType == StateChangedType::ControlForeground )
|
|
{
|
|
ImplInitSettings( false, true, false );
|
|
Invalidate();
|
|
}
|
|
else if ( nType == StateChangedType::ControlBackground )
|
|
{
|
|
ImplInitSettings( false, false, true );
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
void HeaderBar::DataChanged( const DataChangedEvent& rDCEvt )
|
|
{
|
|
Window::DataChanged( rDCEvt );
|
|
|
|
if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
|
|
(rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
|
|
((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
|
|
(rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
|
|
{
|
|
ImplInitSettings( true, true, true );
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
void HeaderBar::EndDrag()
|
|
{
|
|
maEndDragHdl.Call( this );
|
|
}
|
|
|
|
void HeaderBar::Select()
|
|
{
|
|
maSelectHdl.Call( this );
|
|
}
|
|
|
|
void HeaderBar::DoubleClick()
|
|
{
|
|
}
|
|
|
|
void HeaderBar::InsertItem( sal_uInt16 nItemId, const OUString& rText,
|
|
tools::Long nSize, HeaderBarItemBits nBits, sal_uInt16 nPos )
|
|
{
|
|
DBG_ASSERT( nItemId, "HeaderBar::InsertItem(): ItemId == 0" );
|
|
DBG_ASSERT( GetItemPos( nItemId ) == HEADERBAR_ITEM_NOTFOUND,
|
|
"HeaderBar::InsertItem(): ItemId already exists" );
|
|
|
|
// create item and insert in the list
|
|
std::unique_ptr<ImplHeadItem> pItem(new ImplHeadItem);
|
|
pItem->mnId = nItemId;
|
|
pItem->mnBits = nBits;
|
|
pItem->mnSize = nSize;
|
|
pItem->maText = rText;
|
|
if ( nPos < mvItemList.size() ) {
|
|
auto it = mvItemList.begin();
|
|
it += nPos;
|
|
mvItemList.insert( it, std::move(pItem) );
|
|
} else {
|
|
mvItemList.push_back( std::move(pItem) );
|
|
}
|
|
|
|
// update display
|
|
ImplUpdate( nPos, true );
|
|
}
|
|
|
|
void HeaderBar::RemoveItem( sal_uInt16 nItemId )
|
|
{
|
|
sal_uInt16 nPos = GetItemPos( nItemId );
|
|
if ( nPos != HEADERBAR_ITEM_NOTFOUND )
|
|
{
|
|
if ( nPos < mvItemList.size() ) {
|
|
auto it = mvItemList.begin();
|
|
it += nPos;
|
|
mvItemList.erase( it );
|
|
}
|
|
}
|
|
}
|
|
|
|
void HeaderBar::MoveItem( sal_uInt16 nItemId, sal_uInt16 nNewPos )
|
|
{
|
|
sal_uInt16 nPos = GetItemPos( nItemId );
|
|
if ( nPos == HEADERBAR_ITEM_NOTFOUND )
|
|
return;
|
|
|
|
if ( nPos == nNewPos )
|
|
return;
|
|
|
|
auto it = mvItemList.begin();
|
|
it += nPos;
|
|
std::unique_ptr<ImplHeadItem> pItem = std::move(*it);
|
|
mvItemList.erase( it );
|
|
if ( nNewPos < nPos )
|
|
nPos = nNewPos;
|
|
it = mvItemList.begin();
|
|
it += nNewPos;
|
|
mvItemList.insert( it, std::move(pItem) );
|
|
ImplUpdate( nPos, true);
|
|
}
|
|
|
|
void HeaderBar::Clear()
|
|
{
|
|
// delete all items
|
|
mvItemList.clear();
|
|
|
|
ImplUpdate( 0, true );
|
|
}
|
|
|
|
void HeaderBar::SetOffset( tools::Long nNewOffset )
|
|
{
|
|
// tdf#129856 (see also #i40393#) invalidate old left and right border area if WB_BORDER was set in ImplInit()
|
|
if (mnBorderOff1 && mnBorderOff2)
|
|
{
|
|
Invalidate(tools::Rectangle(0, 0, 1, mnDY));
|
|
Invalidate(tools::Rectangle(mnDX - 1, 0, mnDX, mnDY));
|
|
}
|
|
|
|
// move area
|
|
tools::Rectangle aRect( 0, mnBorderOff1, mnDX-1, mnDY-mnBorderOff1-mnBorderOff2 );
|
|
tools::Long nDelta = mnOffset-nNewOffset;
|
|
mnOffset = nNewOffset;
|
|
Scroll( nDelta, 0, aRect );
|
|
}
|
|
|
|
sal_uInt16 HeaderBar::GetItemCount() const
|
|
{
|
|
return static_cast<sal_uInt16>(mvItemList.size());
|
|
}
|
|
|
|
sal_uInt16 HeaderBar::GetItemPos( sal_uInt16 nItemId ) const
|
|
{
|
|
for ( size_t i = 0, n = mvItemList.size(); i < n; ++i ) {
|
|
auto& pItem = mvItemList[ i ];
|
|
if ( pItem->mnId == nItemId )
|
|
return static_cast<sal_uInt16>(i);
|
|
}
|
|
return HEADERBAR_ITEM_NOTFOUND;
|
|
}
|
|
|
|
sal_uInt16 HeaderBar::GetItemId( sal_uInt16 nPos ) const
|
|
{
|
|
ImplHeadItem* pItem = (nPos < mvItemList.size() ) ? mvItemList[ nPos ].get() : nullptr;
|
|
if ( pItem )
|
|
return pItem->mnId;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
sal_uInt16 HeaderBar::GetItemId( const Point& rPos ) const
|
|
{
|
|
for ( size_t i = 0, n = mvItemList.size(); i < n; ++i ) {
|
|
if ( ImplGetItemRect( i ).Contains( rPos ) ) {
|
|
return GetItemId( i );
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
tools::Rectangle HeaderBar::GetItemRect( sal_uInt16 nItemId ) const
|
|
{
|
|
tools::Rectangle aRect;
|
|
sal_uInt16 nPos = GetItemPos( nItemId );
|
|
if ( nPos != HEADERBAR_ITEM_NOTFOUND )
|
|
aRect = ImplGetItemRect( nPos );
|
|
return aRect;
|
|
}
|
|
|
|
void HeaderBar::SetItemSize( sal_uInt16 nItemId, tools::Long nNewSize )
|
|
{
|
|
sal_uInt16 nPos = GetItemPos( nItemId );
|
|
if ( nPos != HEADERBAR_ITEM_NOTFOUND )
|
|
{
|
|
auto& pItem = mvItemList[ nPos ];
|
|
if ( pItem->mnSize != nNewSize )
|
|
{
|
|
pItem->mnSize = nNewSize;
|
|
ImplUpdate( nPos, true );
|
|
}
|
|
}
|
|
}
|
|
|
|
tools::Long HeaderBar::GetItemSize( sal_uInt16 nItemId ) const
|
|
{
|
|
sal_uInt16 nPos = GetItemPos( nItemId );
|
|
if ( nPos != HEADERBAR_ITEM_NOTFOUND )
|
|
return mvItemList[ nPos ]->mnSize;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
void HeaderBar::SetItemBits( sal_uInt16 nItemId, HeaderBarItemBits nNewBits )
|
|
{
|
|
sal_uInt16 nPos = GetItemPos( nItemId );
|
|
if ( nPos != HEADERBAR_ITEM_NOTFOUND )
|
|
{
|
|
auto& pItem = mvItemList[ nPos ];
|
|
if ( pItem->mnBits != nNewBits )
|
|
{
|
|
pItem->mnBits = nNewBits;
|
|
ImplUpdate( nPos );
|
|
}
|
|
}
|
|
}
|
|
|
|
HeaderBarItemBits HeaderBar::GetItemBits( sal_uInt16 nItemId ) const
|
|
{
|
|
sal_uInt16 nPos = GetItemPos( nItemId );
|
|
if ( nPos != HEADERBAR_ITEM_NOTFOUND )
|
|
return mvItemList[ nPos ]->mnBits;
|
|
else
|
|
return HeaderBarItemBits::NONE;
|
|
}
|
|
|
|
void HeaderBar::SetItemText( sal_uInt16 nItemId, const OUString& rText )
|
|
{
|
|
sal_uInt16 nPos = GetItemPos( nItemId );
|
|
if ( nPos != HEADERBAR_ITEM_NOTFOUND )
|
|
{
|
|
mvItemList[ nPos ]->maText = rText;
|
|
ImplUpdate( nPos );
|
|
}
|
|
}
|
|
|
|
const OUString & HeaderBar::GetItemText( sal_uInt16 nItemId ) const
|
|
{
|
|
sal_uInt16 nPos = GetItemPos( nItemId );
|
|
if ( nPos != HEADERBAR_ITEM_NOTFOUND )
|
|
return mvItemList[ nPos ]->maText;
|
|
return EMPTY_OUSTRING;
|
|
}
|
|
|
|
OUString HeaderBar::GetHelpText( sal_uInt16 nItemId ) const
|
|
{
|
|
sal_uInt16 nPos = GetItemPos( nItemId );
|
|
if ( nPos != HEADERBAR_ITEM_NOTFOUND )
|
|
{
|
|
auto& pItem = mvItemList[ nPos ];
|
|
if ( pItem->maHelpText.isEmpty() && !pItem->maHelpId.isEmpty() )
|
|
{
|
|
Help* pHelp = Application::GetHelp();
|
|
if ( pHelp )
|
|
pItem->maHelpText = pHelp->GetHelpText( OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ) );
|
|
}
|
|
|
|
return pItem->maHelpText;
|
|
}
|
|
|
|
return OUString();
|
|
}
|
|
|
|
Size HeaderBar::CalcWindowSizePixel() const
|
|
{
|
|
tools::Long nMaxImageSize = 0;
|
|
Size aSize( 0, GetTextHeight() );
|
|
|
|
for (auto& pItem : mvItemList)
|
|
{
|
|
// take image size into account
|
|
tools::Long nImageHeight = pItem->maImage.GetSizePixel().Height();
|
|
if ( !(pItem->mnBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE)) && !pItem->maText.isEmpty() )
|
|
nImageHeight += aSize.Height();
|
|
if ( nImageHeight > nMaxImageSize )
|
|
nMaxImageSize = nImageHeight;
|
|
|
|
// add width
|
|
aSize.AdjustWidth(pItem->mnSize );
|
|
}
|
|
|
|
if ( nMaxImageSize > aSize.Height() )
|
|
aSize.setHeight( nMaxImageSize );
|
|
|
|
// add border
|
|
if ( mbButtonStyle )
|
|
aSize.AdjustHeight(4 );
|
|
else
|
|
aSize.AdjustHeight(2 );
|
|
aSize.AdjustHeight(mnBorderOff1+mnBorderOff2 );
|
|
|
|
return aSize;
|
|
}
|
|
|
|
css::uno::Reference< css::accessibility::XAccessible > HeaderBar::CreateAccessible()
|
|
{
|
|
if ( !mxAccessible.is() )
|
|
{
|
|
maCreateAccessibleHdl.Call( this );
|
|
|
|
if ( !mxAccessible.is() )
|
|
mxAccessible = Window::CreateAccessible();
|
|
}
|
|
|
|
return mxAccessible;
|
|
}
|
|
|
|
void HeaderBar::SetAccessible( const css::uno::Reference< css::accessibility::XAccessible >& _xAccessible )
|
|
{
|
|
mxAccessible = _xAccessible;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|