...following up on 314f15bff0
"Extend
loplugin:external to warn about enums".
Cases where free functions were moved into an unnamed namespace along with a
class, to not break ADL, are in:
filter/source/svg/svgexport.cxx
sc/source/filter/excel/xelink.cxx
sc/source/filter/excel/xilink.cxx
svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx
All other free functions mentioning moved classes appear to be harmless and not
give rise to (silent, even) ADL breakage. (One remaining TODO in
compilerplugins/clang/external.cxx is that derived classes are not covered by
computeAffectedTypes, even though they could also be affected by ADL-breakage---
but don't seem to be in any acutal case across the code base.)
For friend declarations using elaborate type specifiers, like
class C1 {};
class C2 { friend class C1; };
* If C2 (but not C1) is moved into an unnamed namespace, the friend declaration
must be changed to not use an elaborate type specifier (i.e., "friend C1;"; see
C++17 [namespace.memdef]/3: "If the name in a friend declaration is neither
qualified nor a template-id and the declaration is a function or an
elaborated-type-specifier, the lookup to determine whether the entity has been
previously declared shall not consider any scopes outside the innermost
enclosing namespace.")
* If C1 (but not C2) is moved into an unnamed namespace, the friend declaration
must be changed too, see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71882>
"elaborated-type-specifier friend not looked up in unnamed namespace".
Apart from that, to keep changes simple and mostly mechanical (which should help
avoid regressions), out-of-line definitions of class members have been left in
the enclosing (named) namespace. But explicit specializations of class
templates had to be moved into the unnamed namespace to appease
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92598> "explicit specialization of
template from unnamed namespace using unqualified-id in enclosing namespace".
Also, accompanying declarations (of e.g. typedefs or static variables) that
could arguably be moved into the unnamed namespace too have been left alone.
And in some cases, mention of affected types in blacklists in other loplugins
needed to be adapted.
And sc/qa/unit/mark_test.cxx uses a hack of including other .cxx, one of which
is sc/source/core/data/segmenttree.cxx where e.g. ScFlatUInt16SegmentsImpl is
not moved into an unnamed namespace (because it is declared in
sc/inc/segmenttree.hxx), but its base ScFlatSegmentsImpl is. GCC warns about
such combinations with enabled-by-default -Wsubobject-linkage, but "The compiler
doesn’t give this warning for types defined in the main .C file, as those are
unlikely to have multiple definitions."
(<https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc/Warning-Options.html>) The
warned-about classes also don't have multiple definitions in the given test, so
disable the warning when including the .cxx.
Change-Id: Ib694094c0d8168be68f8fe90dfd0acbb66a3f1e4
Reviewed-on: https://gerrit.libreoffice.org/83239
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2810 lines
82 KiB
C++
2810 lines
82 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 <string.h>
|
|
|
|
#include <sal/log.hxx>
|
|
|
|
#include <vcl/event.hxx>
|
|
#include <vcl/wall.hxx>
|
|
#include <vcl/help.hxx>
|
|
#include <vcl/splitwin.hxx>
|
|
#include <vcl/settings.hxx>
|
|
#include <vcl/ptrstyle.hxx>
|
|
|
|
#include <svdata.hxx>
|
|
#include <strings.hrc>
|
|
|
|
|
|
#define SPLITWIN_SPLITSIZE 4
|
|
#define SPLITWIN_SPLITSIZEEX 4
|
|
#define SPLITWIN_SPLITSIZEEXLN 7
|
|
#define SPLITWIN_SPLITSIZEAUTOHIDE 72
|
|
#define SPLITWIN_SPLITSIZEFADE 72
|
|
|
|
#define SPLIT_HORZ (sal_uInt16(0x0001))
|
|
#define SPLIT_VERT (sal_uInt16(0x0002))
|
|
#define SPLIT_WINDOW (sal_uInt16(0x0004))
|
|
#define SPLIT_NOSPLIT (sal_uInt16(0x8000))
|
|
|
|
namespace {
|
|
|
|
class ImplSplitItem
|
|
{
|
|
public:
|
|
ImplSplitItem();
|
|
|
|
long mnSize;
|
|
long mnPixSize;
|
|
long mnLeft;
|
|
long mnTop;
|
|
long mnWidth;
|
|
long mnHeight;
|
|
long mnSplitPos;
|
|
long mnSplitSize;
|
|
long mnOldSplitPos;
|
|
long mnOldSplitSize;
|
|
long mnOldWidth;
|
|
long mnOldHeight;
|
|
std::unique_ptr<ImplSplitSet> mpSet;
|
|
VclPtr<vcl::Window> mpWindow;
|
|
VclPtr<vcl::Window> mpOrgParent;
|
|
sal_uInt16 mnId;
|
|
SplitWindowItemFlags mnBits;
|
|
bool mbFixed;
|
|
bool mbSubSize;
|
|
/// Minimal width or height of the item. -1 means no restriction.
|
|
long mnMinSize;
|
|
/// Maximal width or height of the item. -1 means no restriction.
|
|
long mnMaxSize;
|
|
};
|
|
|
|
}
|
|
|
|
class ImplSplitSet
|
|
{
|
|
public:
|
|
ImplSplitSet();
|
|
~ImplSplitSet();
|
|
|
|
std::vector< ImplSplitItem > mvItems;
|
|
std::unique_ptr<Wallpaper> mpWallpaper;
|
|
long mnLastSize;
|
|
long mnSplitSize;
|
|
sal_uInt16 mnId;
|
|
bool mbCalcPix;
|
|
};
|
|
|
|
ImplSplitItem::ImplSplitItem()
|
|
: mnSize(0)
|
|
, mnPixSize(0)
|
|
, mnLeft(0)
|
|
, mnTop(0)
|
|
, mnWidth(0)
|
|
, mnHeight(0)
|
|
, mnSplitPos(0)
|
|
, mnSplitSize(0)
|
|
, mnOldSplitPos(0)
|
|
, mnOldSplitSize(0)
|
|
, mnOldWidth(0)
|
|
, mnOldHeight(0)
|
|
, mnId(0)
|
|
, mnBits(SplitWindowItemFlags::NONE)
|
|
, mbFixed(false)
|
|
, mbSubSize(false)
|
|
, mnMinSize(-1)
|
|
, mnMaxSize(-1)
|
|
{
|
|
}
|
|
|
|
ImplSplitSet::ImplSplitSet() :
|
|
mnLastSize( 0 ),
|
|
mnSplitSize( SPLITWIN_SPLITSIZE ),
|
|
mnId( 0 ),
|
|
mbCalcPix( true )
|
|
{
|
|
}
|
|
|
|
ImplSplitSet::~ImplSplitSet()
|
|
{
|
|
mpWallpaper.reset();
|
|
}
|
|
|
|
/** Check whether the given size is inside the valid range defined by
|
|
[rItem.mnMinSize,rItem.mnMaxSize]. When it is not inside it then return
|
|
the upper or lower bound, respectively. Otherwise return the given size
|
|
unmodified.
|
|
Note that either mnMinSize and/or mnMaxSize can be -1 in which case the
|
|
size has not lower or upper bound.
|
|
*/
|
|
namespace {
|
|
long ValidateSize (const long nSize, const ImplSplitItem & rItem)
|
|
{
|
|
if (rItem.mnMinSize>=0 && nSize<rItem.mnMinSize)
|
|
return rItem.mnMinSize;
|
|
else if (rItem.mnMaxSize>0 && nSize>rItem.mnMaxSize)
|
|
return rItem.mnMaxSize;
|
|
else
|
|
return nSize;
|
|
}
|
|
}
|
|
|
|
static void ImplCalcBorder( WindowAlign eAlign,
|
|
long& rLeft, long& rTop,
|
|
long& rRight, long& rBottom )
|
|
{
|
|
switch ( eAlign )
|
|
{
|
|
case WindowAlign::Top:
|
|
rLeft = 2;
|
|
rTop = 2;
|
|
rRight = 2;
|
|
rBottom = 0;
|
|
break;
|
|
case WindowAlign::Left:
|
|
rLeft = 0;
|
|
rTop = 2;
|
|
rRight = 2;
|
|
rBottom = 2;
|
|
break;
|
|
case WindowAlign::Bottom:
|
|
rLeft = 2;
|
|
rTop = 0;
|
|
rRight = 2;
|
|
rBottom = 2;
|
|
break;
|
|
default:
|
|
rLeft = 0;
|
|
rTop = 2;
|
|
rRight = 2;
|
|
rBottom = 2;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void SplitWindow::ImplDrawBorder(vcl::RenderContext& rRenderContext)
|
|
{
|
|
const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
|
|
long nDX = mnDX;
|
|
long nDY = mnDY;
|
|
|
|
switch (meAlign)
|
|
{
|
|
case WindowAlign::Bottom:
|
|
rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
|
|
rRenderContext.DrawLine(Point(0, 0), Point(nDX - 1, 0));
|
|
rRenderContext.DrawLine(Point(0, nDY - 2), Point(nDX - 1, nDY - 2));
|
|
|
|
rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
|
|
rRenderContext.DrawLine(Point(0, 1), Point(nDX - 1, 1));
|
|
rRenderContext.DrawLine(Point(0, nDY - 1), Point(nDX - 1, nDY - 1));
|
|
break;
|
|
case WindowAlign::Top:
|
|
rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
|
|
rRenderContext.DrawLine(Point(0, nDY - 2), Point(nDX - 1, nDY - 2));
|
|
rRenderContext.DrawLine(Point(0, 0), Point(nDX - 1, 0));
|
|
|
|
rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
|
|
rRenderContext.DrawLine(Point(0, nDY - 1), Point(nDX - 1, nDY - 1));
|
|
rRenderContext.DrawLine(Point(0, 1), Point(nDX - 1, 1));
|
|
break;
|
|
case WindowAlign::Left:
|
|
rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
|
|
rRenderContext.DrawLine(Point(nDX - 2, 0), Point(nDX - 2, nDY - 2));
|
|
rRenderContext.DrawLine(Point(0, 0), Point(nDX - 1, 0));
|
|
rRenderContext.DrawLine(Point(0, nDY - 2), Point(nDX - 2, nDY - 2));
|
|
|
|
rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
|
|
rRenderContext.DrawLine(Point(nDX - 1, 0), Point(nDX - 1, nDY - 1));
|
|
rRenderContext.DrawLine(Point(0, 1), Point(nDX - 3, 1));
|
|
rRenderContext.DrawLine(Point(0, nDY - 1), Point(nDX - 2, nDY - 1));
|
|
break;
|
|
default:
|
|
rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
|
|
rRenderContext.DrawLine(Point(0, 0), Point( 0, nDY - 2));
|
|
rRenderContext.DrawLine(Point(0, 0), Point( nDX - 1, 0));
|
|
rRenderContext.DrawLine(Point(0, nDY - 2), Point(nDX - 1, nDY - 2));
|
|
|
|
rRenderContext.SetLineColor( rStyleSettings.GetLightColor());
|
|
rRenderContext.DrawLine(Point(1, 1), Point(1, nDY - 3));
|
|
rRenderContext.DrawLine(Point(1, 1), Point(nDX - 1, 1));
|
|
rRenderContext.DrawLine(Point(0, nDY - 1), Point(nDX - 1, nDY - 1));
|
|
}
|
|
}
|
|
|
|
void SplitWindow::ImplDrawBorderLine(vcl::RenderContext& rRenderContext)
|
|
{
|
|
if (mbFadeOut)
|
|
{
|
|
const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
|
|
long nDX = mnDX;
|
|
long nDY = mnDY;
|
|
|
|
switch (meAlign)
|
|
{
|
|
case WindowAlign::Left:
|
|
rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
|
|
rRenderContext.DrawLine( Point( nDX-SPLITWIN_SPLITSIZEEXLN-1, 1 ), Point( nDX-SPLITWIN_SPLITSIZEEXLN-1, nDY-2 ) );
|
|
|
|
rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
|
|
rRenderContext.DrawLine( Point( nDX-SPLITWIN_SPLITSIZEEXLN, 1 ), Point( nDX-SPLITWIN_SPLITSIZEEXLN, nDY-3 ) );
|
|
break;
|
|
case WindowAlign::Right:
|
|
rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
|
|
rRenderContext.DrawLine( Point( SPLITWIN_SPLITSIZEEXLN-1, 0 ), Point( SPLITWIN_SPLITSIZEEXLN-1, nDY-2 ) );
|
|
|
|
rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
|
|
rRenderContext.DrawLine( Point( SPLITWIN_SPLITSIZEEXLN, 1 ), Point( SPLITWIN_SPLITSIZEEXLN, nDY-3 ) );
|
|
break;
|
|
case WindowAlign::Top:
|
|
rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
|
|
rRenderContext.DrawLine( Point( 0, nDY-SPLITWIN_SPLITSIZEEXLN-1 ), Point( nDX-1, nDY-SPLITWIN_SPLITSIZEEXLN-1 ) );
|
|
|
|
rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
|
|
rRenderContext.DrawLine( Point( 0, nDY-SPLITWIN_SPLITSIZEEXLN ), Point( nDX-1, nDY-SPLITWIN_SPLITSIZEEXLN ) );
|
|
break;
|
|
case WindowAlign::Bottom:
|
|
rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
|
|
rRenderContext.DrawLine( Point( 0, 5 ), Point( nDX-1, 5 ) );
|
|
|
|
rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
|
|
rRenderContext.DrawLine( Point( 0, SPLITWIN_SPLITSIZEEXLN ), Point( nDX-1, SPLITWIN_SPLITSIZEEXLN ) );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static ImplSplitSet* ImplFindSet( ImplSplitSet* pSet, sal_uInt16 nId )
|
|
{
|
|
if ( pSet->mnId == nId )
|
|
return pSet;
|
|
|
|
std::vector< ImplSplitItem >& rItems = pSet->mvItems;
|
|
|
|
for ( const auto& rItem : rItems )
|
|
{
|
|
if ( rItem.mnId == nId )
|
|
return rItem.mpSet.get();
|
|
}
|
|
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
if ( rItem.mpSet )
|
|
{
|
|
ImplSplitSet* pFindSet = ImplFindSet( rItem.mpSet.get(), nId );
|
|
if ( pFindSet )
|
|
return pFindSet;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
static ImplSplitSet* ImplFindItem( ImplSplitSet* pSet, sal_uInt16 nId, sal_uInt16& rPos )
|
|
{
|
|
size_t nItems = pSet->mvItems.size();
|
|
std::vector< ImplSplitItem >& rItems = pSet->mvItems;
|
|
|
|
for ( size_t i = 0; i < nItems; i++ )
|
|
{
|
|
if ( rItems[i].mnId == nId )
|
|
{
|
|
rPos = i;
|
|
return pSet;
|
|
}
|
|
}
|
|
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
if ( rItem.mpSet )
|
|
{
|
|
ImplSplitSet* pFindSet = ImplFindItem( rItem.mpSet.get(), nId, rPos );
|
|
if ( pFindSet )
|
|
return pFindSet;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
static sal_uInt16 ImplFindItem( ImplSplitSet* pSet, vcl::Window* pWindow )
|
|
{
|
|
std::vector< ImplSplitItem >& rItems = pSet->mvItems;
|
|
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
if ( rItem.mpWindow == pWindow )
|
|
return rItem.mnId;
|
|
else
|
|
{
|
|
if ( rItem.mpSet )
|
|
{
|
|
sal_uInt16 nId = ImplFindItem( rItem.mpSet.get(), pWindow );
|
|
if ( nId )
|
|
return nId;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static sal_uInt16 ImplFindItem( ImplSplitSet* pSet, const Point& rPos,
|
|
bool bRows, bool bDown = true )
|
|
{
|
|
std::vector< ImplSplitItem >& rItems = pSet->mvItems;
|
|
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
if ( rItem.mnWidth && rItem.mnHeight )
|
|
{
|
|
Point aPoint( rItem.mnLeft, rItem.mnTop );
|
|
Size aSize( rItem.mnWidth, rItem.mnHeight );
|
|
tools::Rectangle aRect( aPoint, aSize );
|
|
if ( bRows )
|
|
{
|
|
if ( bDown )
|
|
aRect.AdjustBottom(pSet->mnSplitSize );
|
|
else
|
|
aRect.AdjustTop( -(pSet->mnSplitSize) );
|
|
}
|
|
else
|
|
{
|
|
if ( bDown )
|
|
aRect.AdjustRight(pSet->mnSplitSize );
|
|
else
|
|
aRect.AdjustLeft( -(pSet->mnSplitSize) );
|
|
}
|
|
|
|
if ( aRect.IsInside( rPos ) )
|
|
{
|
|
if ( rItem.mpSet && !rItem.mpSet->mvItems.empty() )
|
|
{
|
|
return ImplFindItem( rItem.mpSet.get(), rPos,
|
|
!(rItem.mnBits & SplitWindowItemFlags::ColSet) );
|
|
}
|
|
else
|
|
return rItem.mnId;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void ImplCalcSet( ImplSplitSet* pSet,
|
|
long nSetLeft, long nSetTop,
|
|
long nSetWidth, long nSetHeight,
|
|
bool bRows, bool bDown = true )
|
|
{
|
|
if ( pSet->mvItems.empty() )
|
|
return;
|
|
|
|
sal_uInt16 nMins;
|
|
sal_uInt16 nCalcItems;
|
|
size_t nItems = pSet->mvItems.size();
|
|
sal_uInt16 nAbsItems;
|
|
long nCalcSize;
|
|
long nPos;
|
|
long nMaxPos;
|
|
std::vector< ImplSplitItem >& rItems = pSet->mvItems;
|
|
bool bEmpty;
|
|
|
|
// calculate sizes
|
|
if ( bRows )
|
|
nCalcSize = nSetHeight;
|
|
else
|
|
nCalcSize = nSetWidth;
|
|
nCalcSize -= (rItems.size()-1)*pSet->mnSplitSize;
|
|
if ( pSet->mbCalcPix || (pSet->mnLastSize != nCalcSize) )
|
|
{
|
|
long nPercentFactor = 10;
|
|
long nRelCount = 0;
|
|
long nPercent = 0;
|
|
long nRelPercent = 0;
|
|
long nAbsSize = 0;
|
|
long nCurSize = 0;
|
|
for ( const auto& rItem : rItems )
|
|
{
|
|
if ( rItem.mnBits & SplitWindowItemFlags::RelativeSize )
|
|
nRelCount += rItem.mnSize;
|
|
else if ( rItem.mnBits & SplitWindowItemFlags::PercentSize )
|
|
nPercent += rItem.mnSize;
|
|
else
|
|
nAbsSize += rItem.mnSize;
|
|
}
|
|
// map relative values to percentages (percentage here one tenth of a percent)
|
|
nPercent *= nPercentFactor;
|
|
if ( nRelCount )
|
|
{
|
|
long nRelPercentBase = 1000;
|
|
while ( (nRelCount > nRelPercentBase) && (nPercentFactor < 100000) )
|
|
{
|
|
nRelPercentBase *= 10;
|
|
nPercentFactor *= 10;
|
|
}
|
|
if ( nPercent < nRelPercentBase )
|
|
{
|
|
nRelPercent = (nRelPercentBase-nPercent)/nRelCount;
|
|
nPercent += nRelPercent*nRelCount;
|
|
}
|
|
else
|
|
nRelPercent = 0;
|
|
}
|
|
if ( !nPercent )
|
|
nPercent = 1;
|
|
long nSizeDelta = nCalcSize-nAbsSize;
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
if ( rItem.mnBits & SplitWindowItemFlags::RelativeSize )
|
|
{
|
|
if ( nSizeDelta <= 0 )
|
|
rItem.mnPixSize = 0;
|
|
else
|
|
rItem.mnPixSize = (nSizeDelta*rItem.mnSize*nRelPercent)/nPercent;
|
|
}
|
|
else if ( rItem.mnBits & SplitWindowItemFlags::PercentSize )
|
|
{
|
|
if ( nSizeDelta <= 0 )
|
|
rItem.mnPixSize = 0;
|
|
else
|
|
rItem.mnPixSize = (nSizeDelta*rItem.mnSize*nPercentFactor)/nPercent;
|
|
}
|
|
else
|
|
rItem.mnPixSize = rItem.mnSize;
|
|
nCurSize += rItem.mnPixSize;
|
|
}
|
|
|
|
pSet->mbCalcPix = false;
|
|
pSet->mnLastSize = nCalcSize;
|
|
|
|
// adapt window
|
|
nSizeDelta = nCalcSize-nCurSize;
|
|
if ( nSizeDelta )
|
|
{
|
|
nAbsItems = 0;
|
|
long nSizeWinSize = 0;
|
|
|
|
// first resize absolute items relative
|
|
for ( const auto& rItem : rItems )
|
|
{
|
|
if ( !(rItem.mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize)) )
|
|
{
|
|
nAbsItems++;
|
|
nSizeWinSize += rItem.mnPixSize;
|
|
}
|
|
}
|
|
// do not compensate rounding errors here
|
|
if ( (nAbsItems < static_cast<sal_uInt16>(std::abs( nSizeDelta ))) && nSizeWinSize )
|
|
{
|
|
long nNewSizeWinSize = 0;
|
|
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
if ( !(rItem.mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize)) )
|
|
{
|
|
rItem.mnPixSize += (nSizeDelta*rItem.mnPixSize)/nSizeWinSize;
|
|
nNewSizeWinSize += rItem.mnPixSize;
|
|
}
|
|
}
|
|
|
|
nSizeDelta -= nNewSizeWinSize-nSizeWinSize;
|
|
}
|
|
|
|
// compensate rounding errors now
|
|
sal_uInt16 j = 0;
|
|
nMins = 0;
|
|
while ( nSizeDelta && (nItems != nMins) )
|
|
{
|
|
// determine which items we can calculate
|
|
nCalcItems = 0;
|
|
while ( !nCalcItems )
|
|
{
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
rItem.mbSubSize = false;
|
|
|
|
if ( j >= 2 )
|
|
rItem.mbSubSize = true;
|
|
else
|
|
{
|
|
if ( (nSizeDelta > 0) || rItem.mnPixSize )
|
|
{
|
|
if ( j >= 1 )
|
|
rItem.mbSubSize = true;
|
|
else
|
|
{
|
|
if ( (j == 0) && (rItem.mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize)) )
|
|
rItem.mbSubSize = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( rItem.mbSubSize )
|
|
nCalcItems++;
|
|
}
|
|
|
|
j++;
|
|
}
|
|
|
|
// subtract size of individual items
|
|
long nErrorSum = nSizeDelta % nCalcItems;
|
|
long nCurSizeDelta = nSizeDelta / nCalcItems;
|
|
nMins = 0;
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
if ( rItem.mbSubSize )
|
|
{
|
|
long* pSize = &(rItem.mnPixSize);
|
|
long nTempErr;
|
|
|
|
if ( nErrorSum )
|
|
{
|
|
if ( nErrorSum < 0 )
|
|
nTempErr = -1;
|
|
else
|
|
nTempErr = 1;
|
|
}
|
|
else
|
|
nTempErr = 0;
|
|
|
|
if ( (*pSize+nCurSizeDelta+nTempErr) <= 0 )
|
|
{
|
|
long nTemp = *pSize;
|
|
if ( nTemp )
|
|
{
|
|
*pSize -= nTemp;
|
|
nSizeDelta += nTemp;
|
|
}
|
|
nMins++;
|
|
}
|
|
else
|
|
{
|
|
*pSize += nCurSizeDelta;
|
|
nSizeDelta -= nCurSizeDelta;
|
|
if ( nTempErr && (*pSize || (nTempErr > 0)) )
|
|
{
|
|
*pSize += nTempErr;
|
|
nSizeDelta -= nTempErr;
|
|
nErrorSum -= nTempErr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// calculate maximum size
|
|
if ( bRows )
|
|
{
|
|
nPos = nSetTop;
|
|
if ( !bDown )
|
|
nMaxPos = nSetTop-nSetHeight;
|
|
else
|
|
nMaxPos = nSetTop+nSetHeight;
|
|
}
|
|
else
|
|
{
|
|
nPos = nSetLeft;
|
|
if ( !bDown )
|
|
nMaxPos = nSetLeft-nSetWidth;
|
|
else
|
|
nMaxPos = nSetLeft+nSetWidth;
|
|
}
|
|
|
|
// order windows and adept values
|
|
for ( size_t i = 0; i < nItems; i++ )
|
|
{
|
|
rItems[i].mnOldSplitPos = rItems[i].mnSplitPos;
|
|
rItems[i].mnOldSplitSize = rItems[i].mnSplitSize;
|
|
rItems[i].mnOldWidth = rItems[i].mnWidth;
|
|
rItems[i].mnOldHeight = rItems[i].mnHeight;
|
|
|
|
bEmpty = false;
|
|
if ( bDown )
|
|
{
|
|
if ( nPos+rItems[i].mnPixSize > nMaxPos )
|
|
bEmpty = true;
|
|
}
|
|
else
|
|
{
|
|
nPos -= rItems[i].mnPixSize;
|
|
if ( nPos < nMaxPos )
|
|
bEmpty = true;
|
|
}
|
|
|
|
if ( bEmpty )
|
|
{
|
|
rItems[i].mnWidth = 0;
|
|
rItems[i].mnHeight = 0;
|
|
rItems[i].mnSplitSize = 0;
|
|
}
|
|
else
|
|
{
|
|
if ( bRows )
|
|
{
|
|
rItems[i].mnLeft = nSetLeft;
|
|
rItems[i].mnTop = nPos;
|
|
rItems[i].mnWidth = nSetWidth;
|
|
rItems[i].mnHeight = rItems[i].mnPixSize;
|
|
}
|
|
else
|
|
{
|
|
rItems[i].mnLeft = nPos;
|
|
rItems[i].mnTop = nSetTop;
|
|
rItems[i].mnWidth = rItems[i].mnPixSize;
|
|
rItems[i].mnHeight = nSetHeight;
|
|
}
|
|
|
|
if ( i > nItems-1 )
|
|
rItems[i].mnSplitSize = 0;
|
|
else
|
|
{
|
|
rItems[i].mnSplitSize = pSet->mnSplitSize;
|
|
if ( bDown )
|
|
{
|
|
rItems[i].mnSplitPos = nPos+rItems[i].mnPixSize;
|
|
if ( rItems[i].mnSplitPos+rItems[i].mnSplitSize > nMaxPos )
|
|
rItems[i].mnSplitSize = nMaxPos-rItems[i].mnSplitPos;
|
|
}
|
|
else
|
|
{
|
|
rItems[i].mnSplitPos = nPos-pSet->mnSplitSize;
|
|
if ( rItems[i].mnSplitPos < nMaxPos )
|
|
rItems[i].mnSplitSize = rItems[i].mnSplitPos+pSet->mnSplitSize-nMaxPos;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !bDown )
|
|
nPos -= pSet->mnSplitSize;
|
|
else
|
|
nPos += rItems[i].mnPixSize+pSet->mnSplitSize;
|
|
}
|
|
|
|
// calculate Sub-Set's
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
if ( rItem.mpSet && rItem.mnWidth && rItem.mnHeight )
|
|
{
|
|
ImplCalcSet( rItem.mpSet.get(),
|
|
rItem.mnLeft, rItem.mnTop,
|
|
rItem.mnWidth, rItem.mnHeight,
|
|
!(rItem.mnBits & SplitWindowItemFlags::ColSet) );
|
|
}
|
|
}
|
|
|
|
// set fixed
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
rItem.mbFixed = false;
|
|
if ( rItem.mnBits & SplitWindowItemFlags::Fixed )
|
|
rItem.mbFixed = true;
|
|
else
|
|
{
|
|
// this item is also fixed if Child-Set is available,
|
|
// if a child is fixed
|
|
if ( rItem.mpSet )
|
|
{
|
|
for ( auto const & j: rItem.mpSet->mvItems )
|
|
{
|
|
if ( j.mbFixed )
|
|
{
|
|
rItem.mbFixed = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SplitWindow::ImplCalcSet2( SplitWindow* pWindow, ImplSplitSet* pSet, bool bHide,
|
|
bool bRows )
|
|
{
|
|
std::vector< ImplSplitItem >& rItems = pSet->mvItems;
|
|
|
|
if ( pWindow->IsReallyVisible() && pWindow->IsUpdateMode() && pWindow->mbInvalidate )
|
|
{
|
|
for ( const auto& rItem : rItems )
|
|
{
|
|
if ( rItem.mnSplitSize )
|
|
{
|
|
// invalidate all, if applicable or only a small part
|
|
if ( (rItem.mnOldSplitPos != rItem.mnSplitPos) ||
|
|
(rItem.mnOldSplitSize != rItem.mnSplitSize) ||
|
|
(rItem.mnOldWidth != rItem.mnWidth) ||
|
|
(rItem.mnOldHeight != rItem.mnHeight) )
|
|
{
|
|
tools::Rectangle aRect;
|
|
|
|
// invalidate old rectangle
|
|
if ( bRows )
|
|
{
|
|
aRect.SetLeft( rItem.mnLeft );
|
|
aRect.SetRight( rItem.mnLeft+rItem.mnOldWidth-1 );
|
|
aRect.SetTop( rItem.mnOldSplitPos );
|
|
aRect.SetBottom( aRect.Top() + rItem.mnOldSplitSize );
|
|
}
|
|
else
|
|
{
|
|
aRect.SetTop( rItem.mnTop );
|
|
aRect.SetBottom( rItem.mnTop+rItem.mnOldHeight-1 );
|
|
aRect.SetLeft( rItem.mnOldSplitPos );
|
|
aRect.SetRight( aRect.Left() + rItem.mnOldSplitSize );
|
|
}
|
|
pWindow->Invalidate( aRect );
|
|
// invalidate new rectangle
|
|
if ( bRows )
|
|
{
|
|
aRect.SetLeft( rItem.mnLeft );
|
|
aRect.SetRight( rItem.mnLeft+rItem.mnWidth-1 );
|
|
aRect.SetTop( rItem.mnSplitPos );
|
|
aRect.SetBottom( aRect.Top() + rItem.mnSplitSize );
|
|
}
|
|
else
|
|
{
|
|
aRect.SetTop( rItem.mnTop );
|
|
aRect.SetBottom( rItem.mnTop+rItem.mnHeight-1 );
|
|
aRect.SetLeft( rItem.mnSplitPos );
|
|
aRect.SetRight( aRect.Left() + rItem.mnSplitSize );
|
|
}
|
|
pWindow->Invalidate( aRect );
|
|
|
|
// invalidate complete set, as these areas
|
|
// are not cluttered by windows
|
|
if ( rItem.mpSet && rItem.mpSet->mvItems.empty() )
|
|
{
|
|
aRect.SetLeft( rItem.mnLeft );
|
|
aRect.SetTop( rItem.mnTop );
|
|
aRect.SetRight( rItem.mnLeft+rItem.mnWidth-1 );
|
|
aRect.SetBottom( rItem.mnTop+rItem.mnHeight-1 );
|
|
pWindow->Invalidate( aRect );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// position windows
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
if ( rItem.mpSet )
|
|
{
|
|
bool bTempHide = bHide;
|
|
if ( !rItem.mnWidth || !rItem.mnHeight )
|
|
bTempHide = true;
|
|
ImplCalcSet2( pWindow, rItem.mpSet.get(), bTempHide,
|
|
!(rItem.mnBits & SplitWindowItemFlags::ColSet) );
|
|
}
|
|
else
|
|
{
|
|
if ( rItem.mnWidth && rItem.mnHeight && !bHide )
|
|
{
|
|
Point aPos( rItem.mnLeft, rItem.mnTop );
|
|
Size aSize( rItem.mnWidth, rItem.mnHeight );
|
|
rItem.mpWindow->SetPosSizePixel( aPos, aSize );
|
|
}
|
|
else
|
|
rItem.mpWindow->Hide();
|
|
}
|
|
}
|
|
|
|
// show windows and reset flag
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
if ( rItem.mpWindow && rItem.mnWidth && rItem.mnHeight && !bHide )
|
|
rItem.mpWindow->Show();
|
|
}
|
|
}
|
|
|
|
static void ImplCalcLogSize( std::vector< ImplSplitItem > & rItems, size_t nItems )
|
|
{
|
|
// update original sizes
|
|
size_t i;
|
|
long nRelSize = 0;
|
|
long nPerSize = 0;
|
|
|
|
for ( i = 0; i < nItems; i++ )
|
|
{
|
|
if ( rItems[i].mnBits & SplitWindowItemFlags::RelativeSize )
|
|
nRelSize += rItems[i].mnPixSize;
|
|
else if ( rItems[i].mnBits & SplitWindowItemFlags::PercentSize )
|
|
nPerSize += rItems[i].mnPixSize;
|
|
}
|
|
nPerSize += nRelSize;
|
|
for ( i = 0; i < nItems; i++ )
|
|
{
|
|
if ( rItems[i].mnBits & SplitWindowItemFlags::RelativeSize )
|
|
{
|
|
if ( nRelSize )
|
|
rItems[i].mnSize = (rItems[i].mnPixSize+(nRelSize/2))/nRelSize;
|
|
else
|
|
rItems[i].mnSize = 1;
|
|
}
|
|
else if ( rItems[i].mnBits & SplitWindowItemFlags::PercentSize )
|
|
{
|
|
if ( nPerSize )
|
|
rItems[i].mnSize = (rItems[i].mnPixSize*100)/nPerSize;
|
|
else
|
|
rItems[i].mnSize = 1;
|
|
}
|
|
else
|
|
rItems[i].mnSize = rItems[i].mnPixSize;
|
|
}
|
|
}
|
|
|
|
void SplitWindow::ImplDrawBack(vcl::RenderContext& rRenderContext, ImplSplitSet* pSet)
|
|
{
|
|
std::vector< ImplSplitItem >& rItems = pSet->mvItems;
|
|
|
|
for ( const auto& rItem : rItems )
|
|
{
|
|
pSet = rItem.mpSet.get();
|
|
if (pSet && pSet->mpWallpaper)
|
|
{
|
|
Point aPoint(rItem.mnLeft, rItem.mnTop);
|
|
Size aSize(rItem.mnWidth, rItem.mnHeight);
|
|
tools::Rectangle aRect(aPoint, aSize);
|
|
rRenderContext.DrawWallpaper(aRect, *pSet->mpWallpaper);
|
|
}
|
|
}
|
|
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
if (rItem.mpSet)
|
|
ImplDrawBack(rRenderContext, rItem.mpSet.get());
|
|
}
|
|
}
|
|
|
|
static void ImplDrawSplit(vcl::RenderContext& rRenderContext, ImplSplitSet* pSet, bool bRows, bool bDown)
|
|
{
|
|
if (pSet->mvItems.empty())
|
|
return;
|
|
|
|
size_t nItems = pSet->mvItems.size();
|
|
long nPos;
|
|
long nTop;
|
|
long nBottom;
|
|
std::vector< ImplSplitItem >& rItems = pSet->mvItems;
|
|
const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
|
|
|
|
for (size_t i = 0; i < nItems-1; i++)
|
|
{
|
|
if (rItems[i].mnSplitSize)
|
|
{
|
|
nPos = rItems[i].mnSplitPos;
|
|
|
|
long nItemSplitSize = rItems[i].mnSplitSize;
|
|
long nSplitSize = pSet->mnSplitSize;
|
|
if (bRows)
|
|
{
|
|
nTop = rItems[i].mnLeft;
|
|
nBottom = rItems[i].mnLeft+rItems[i].mnWidth-1;
|
|
|
|
if (bDown || (nItemSplitSize >= nSplitSize))
|
|
{
|
|
rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
|
|
rRenderContext.DrawLine(Point(nTop, nPos + 1), Point(nBottom, nPos + 1));
|
|
}
|
|
nPos += nSplitSize-2;
|
|
if ((!bDown && (nItemSplitSize >= 2)) ||
|
|
(bDown && (nItemSplitSize >= nSplitSize - 1)))
|
|
{
|
|
rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
|
|
rRenderContext.DrawLine(Point(nTop, nPos), Point(nBottom, nPos));
|
|
}
|
|
nPos++;
|
|
if (!bDown || (nItemSplitSize >= nSplitSize))
|
|
{
|
|
rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
|
|
rRenderContext.DrawLine(Point(nTop, nPos), Point(nBottom, nPos));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nTop = rItems[i].mnTop;
|
|
nBottom = rItems[i].mnTop+pSet->mvItems[i].mnHeight-1;
|
|
|
|
if (bDown || (nItemSplitSize >= nSplitSize))
|
|
{
|
|
rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
|
|
rRenderContext.DrawLine(Point(nPos + 1, nTop), Point(nPos+1, nBottom));
|
|
}
|
|
nPos += pSet->mnSplitSize - 2;
|
|
if ((!bDown && (nItemSplitSize >= 2)) ||
|
|
(bDown && (nItemSplitSize >= nSplitSize - 1)))
|
|
{
|
|
rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
|
|
rRenderContext.DrawLine(Point(nPos, nTop), Point(nPos, nBottom));
|
|
}
|
|
nPos++;
|
|
if (!bDown || (nItemSplitSize >= nSplitSize))
|
|
{
|
|
rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
|
|
rRenderContext.DrawLine(Point(nPos, nTop), Point(nPos, nBottom));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
if (rItem.mpSet && rItem.mnWidth && rItem.mnHeight)
|
|
{
|
|
ImplDrawSplit(rRenderContext, rItem.mpSet.get(), !(rItem.mnBits & SplitWindowItemFlags::ColSet), true/*bDown*/);
|
|
}
|
|
}
|
|
}
|
|
|
|
sal_uInt16 SplitWindow::ImplTestSplit( ImplSplitSet* pSet, const Point& rPos,
|
|
long& rMouseOff, ImplSplitSet** ppFoundSet, sal_uInt16& rFoundPos,
|
|
bool bRows )
|
|
{
|
|
if ( pSet->mvItems.empty() )
|
|
return 0;
|
|
|
|
sal_uInt16 nSplitTest;
|
|
size_t nItems = pSet->mvItems.size();
|
|
long nMPos1;
|
|
long nMPos2;
|
|
long nPos;
|
|
long nTop;
|
|
long nBottom;
|
|
std::vector< ImplSplitItem >& rItems = pSet->mvItems;
|
|
|
|
if ( bRows )
|
|
{
|
|
nMPos1 = rPos.X();
|
|
nMPos2 = rPos.Y();
|
|
}
|
|
else
|
|
{
|
|
nMPos1 = rPos.Y();
|
|
nMPos2 = rPos.X();
|
|
}
|
|
|
|
for ( size_t i = 0; i < nItems-1; i++ )
|
|
{
|
|
if ( rItems[i].mnSplitSize )
|
|
{
|
|
if ( bRows )
|
|
{
|
|
nTop = rItems[i].mnLeft;
|
|
nBottom = rItems[i].mnLeft+rItems[i].mnWidth-1;
|
|
}
|
|
else
|
|
{
|
|
nTop = rItems[i].mnTop;
|
|
nBottom = rItems[i].mnTop+rItems[i].mnHeight-1;
|
|
}
|
|
nPos = rItems[i].mnSplitPos;
|
|
|
|
if ( (nMPos1 >= nTop) && (nMPos1 <= nBottom) &&
|
|
(nMPos2 >= nPos) && (nMPos2 <= nPos+rItems[i].mnSplitSize) )
|
|
{
|
|
if ( !rItems[i].mbFixed && !rItems[i+1].mbFixed )
|
|
{
|
|
rMouseOff = nMPos2-nPos;
|
|
*ppFoundSet = pSet;
|
|
rFoundPos = i;
|
|
if ( bRows )
|
|
return SPLIT_VERT;
|
|
else
|
|
return SPLIT_HORZ;
|
|
}
|
|
else
|
|
return SPLIT_NOSPLIT;
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( auto& rItem : rItems )
|
|
{
|
|
if ( rItem.mpSet )
|
|
{
|
|
nSplitTest = ImplTestSplit( rItem.mpSet.get(), rPos,
|
|
rMouseOff, ppFoundSet, rFoundPos,
|
|
!(rItem.mnBits & SplitWindowItemFlags::ColSet) );
|
|
if ( nSplitTest )
|
|
return nSplitTest;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
sal_uInt16 SplitWindow::ImplTestSplit( const SplitWindow* pWindow, const Point& rPos,
|
|
long& rMouseOff, ImplSplitSet** ppFoundSet, sal_uInt16& rFoundPos )
|
|
{
|
|
// Resizable SplitWindow should be treated different
|
|
if ( pWindow->mnWinStyle & WB_SIZEABLE )
|
|
{
|
|
long nTPos;
|
|
long nPos;
|
|
long nBorder;
|
|
|
|
if ( pWindow->mbHorz )
|
|
{
|
|
if ( pWindow->mbBottomRight )
|
|
{
|
|
nBorder = pWindow->mnBottomBorder;
|
|
nPos = 0;
|
|
}
|
|
else
|
|
{
|
|
nBorder = pWindow->mnTopBorder;
|
|
nPos = pWindow->mnDY-nBorder;
|
|
}
|
|
nTPos = rPos.Y();
|
|
}
|
|
else
|
|
{
|
|
if ( pWindow->mbBottomRight )
|
|
{
|
|
nBorder = pWindow->mnRightBorder;
|
|
nPos = 0;
|
|
}
|
|
else
|
|
{
|
|
nBorder = pWindow->mnLeftBorder;
|
|
nPos = pWindow->mnDX-nBorder;
|
|
}
|
|
nTPos = rPos.X();
|
|
}
|
|
long nSplitSize = pWindow->mpMainSet->mnSplitSize-2;
|
|
if (pWindow->mbFadeOut)
|
|
nSplitSize += SPLITWIN_SPLITSIZEEXLN;
|
|
if ( !pWindow->mbBottomRight )
|
|
nPos -= nSplitSize;
|
|
if ( (nTPos >= nPos) && (nTPos <= nPos+nSplitSize+nBorder) )
|
|
{
|
|
rMouseOff = nTPos-nPos;
|
|
*ppFoundSet = pWindow->mpMainSet.get();
|
|
if ( !pWindow->mpMainSet->mvItems.empty() )
|
|
rFoundPos = pWindow->mpMainSet->mvItems.size() - 1;
|
|
else
|
|
rFoundPos = 0;
|
|
if ( pWindow->mbHorz )
|
|
return SPLIT_VERT | SPLIT_WINDOW;
|
|
else
|
|
return SPLIT_HORZ | SPLIT_WINDOW;
|
|
}
|
|
}
|
|
|
|
return ImplTestSplit( pWindow->mpMainSet.get(), rPos, rMouseOff, ppFoundSet, rFoundPos,
|
|
pWindow->mbHorz );
|
|
}
|
|
|
|
void SplitWindow::ImplDrawSplitTracking(const Point& rPos)
|
|
{
|
|
tools::Rectangle aRect;
|
|
|
|
if (mnSplitTest & SPLIT_HORZ)
|
|
{
|
|
aRect.SetTop( maDragRect.Top() );
|
|
aRect.SetBottom( maDragRect.Bottom() );
|
|
aRect.SetLeft( rPos.X() );
|
|
aRect.SetRight( aRect.Left() + mpSplitSet->mnSplitSize - 1 );
|
|
if (!(mnWinStyle & WB_NOSPLITDRAW))
|
|
aRect.AdjustRight( -1 );
|
|
if ((mnSplitTest & SPLIT_WINDOW) && mbFadeOut)
|
|
{
|
|
aRect.AdjustLeft(SPLITWIN_SPLITSIZEEXLN );
|
|
aRect.AdjustRight(SPLITWIN_SPLITSIZEEXLN );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aRect.SetLeft( maDragRect.Left() );
|
|
aRect.SetRight( maDragRect.Right() );
|
|
aRect.SetTop( rPos.Y() );
|
|
aRect.SetBottom( aRect.Top() + mpSplitSet->mnSplitSize - 1 );
|
|
if (!(mnWinStyle & WB_NOSPLITDRAW))
|
|
aRect.AdjustBottom( -1 );
|
|
if ((mnSplitTest & SPLIT_WINDOW) && mbFadeOut)
|
|
{
|
|
aRect.AdjustTop(SPLITWIN_SPLITSIZEEXLN );
|
|
aRect.AdjustBottom(SPLITWIN_SPLITSIZEEXLN );
|
|
}
|
|
}
|
|
ShowTracking(aRect, ShowTrackFlags::Split);
|
|
}
|
|
|
|
void SplitWindow::ImplInit( vcl::Window* pParent, WinBits nStyle )
|
|
{
|
|
mpMainSet.reset(new ImplSplitSet());
|
|
mpBaseSet = mpMainSet.get();
|
|
mpSplitSet = nullptr;
|
|
mpLastSizes = nullptr;
|
|
mnDX = 0;
|
|
mnDY = 0;
|
|
mnLeftBorder = 0;
|
|
mnTopBorder = 0;
|
|
mnRightBorder = 0;
|
|
mnBottomBorder = 0;
|
|
mnMaxSize = 0;
|
|
mnMouseOff = 0;
|
|
meAlign = WindowAlign::Top;
|
|
mnWinStyle = nStyle;
|
|
mnSplitTest = 0;
|
|
mnSplitPos = 0;
|
|
mnMouseModifier = 0;
|
|
mnMStartPos = 0;
|
|
mnMSplitPos = 0;
|
|
mbDragFull = false;
|
|
mbHorz = true;
|
|
mbBottomRight = false;
|
|
mbCalc = false;
|
|
mbRecalc = true;
|
|
mbInvalidate = true;
|
|
mbFadeIn = false;
|
|
mbFadeOut = false;
|
|
mbFadeInDown = false;
|
|
mbFadeOutDown = false;
|
|
mbFadeInPressed = false;
|
|
mbFadeOutPressed = false;
|
|
mbFadeNoButtonMode = false;
|
|
|
|
if ( nStyle & WB_NOSPLITDRAW )
|
|
{
|
|
mpMainSet->mnSplitSize -= 2;
|
|
mbInvalidate = false;
|
|
}
|
|
|
|
if ( nStyle & WB_BORDER )
|
|
{
|
|
ImplCalcBorder( meAlign, mnLeftBorder, mnTopBorder,
|
|
mnRightBorder, mnBottomBorder );
|
|
}
|
|
else
|
|
{
|
|
mnLeftBorder = 0;
|
|
mnTopBorder = 0;
|
|
mnRightBorder = 0;
|
|
mnBottomBorder = 0;
|
|
}
|
|
|
|
DockingWindow::ImplInit( pParent, (nStyle | WB_CLIPCHILDREN) & ~(WB_BORDER | WB_SIZEABLE) );
|
|
|
|
ImplInitSettings();
|
|
}
|
|
|
|
void SplitWindow::ImplInitSettings()
|
|
{
|
|
// If MainSet has a Wallpaper, this is the background,
|
|
// otherwise it is the standard colour
|
|
if ( mpMainSet->mpWallpaper )
|
|
SetBackground( *mpMainSet->mpWallpaper );
|
|
else
|
|
{
|
|
const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
|
|
|
|
Color aColor;
|
|
if ( IsControlBackground() )
|
|
aColor = GetControlBackground();
|
|
else if ( Window::GetStyle() & WB_3DLOOK )
|
|
aColor = rStyleSettings.GetFaceColor();
|
|
else
|
|
aColor = rStyleSettings.GetWindowColor();
|
|
SetBackground( aColor );
|
|
}
|
|
}
|
|
|
|
SplitWindow::SplitWindow( vcl::Window* pParent, WinBits nStyle ) :
|
|
DockingWindow( WindowType::SPLITWINDOW )
|
|
{
|
|
ImplInit( pParent, nStyle );
|
|
DockingWindow::SetIdleDebugName( "vcl::SplitWindow maLayoutIdle" );
|
|
}
|
|
|
|
SplitWindow::~SplitWindow()
|
|
{
|
|
disposeOnce();
|
|
}
|
|
|
|
void SplitWindow::dispose()
|
|
{
|
|
// delete Sets
|
|
mpMainSet.reset();
|
|
DockingWindow::dispose();
|
|
}
|
|
|
|
void SplitWindow::ImplSetWindowSize( long nDelta )
|
|
{
|
|
if ( !nDelta )
|
|
return;
|
|
|
|
Size aSize = GetSizePixel();
|
|
switch ( meAlign )
|
|
{
|
|
case WindowAlign::Top:
|
|
aSize.AdjustHeight(nDelta );
|
|
SetSizePixel( aSize );
|
|
break;
|
|
case WindowAlign::Bottom:
|
|
{
|
|
maDragRect.AdjustTop(nDelta );
|
|
Point aPos = GetPosPixel();
|
|
aPos.AdjustY( -nDelta );
|
|
aSize.AdjustHeight(nDelta );
|
|
SetPosSizePixel( aPos, aSize );
|
|
break;
|
|
}
|
|
case WindowAlign::Left:
|
|
aSize.AdjustWidth(nDelta );
|
|
SetSizePixel( aSize );
|
|
break;
|
|
case WindowAlign::Right:
|
|
default:
|
|
{
|
|
maDragRect.AdjustLeft(nDelta );
|
|
Point aPos = GetPosPixel();
|
|
aPos.AdjustX( -nDelta );
|
|
aSize.AdjustWidth(nDelta );
|
|
SetPosSizePixel( aPos, aSize );
|
|
break;
|
|
}
|
|
}
|
|
|
|
SplitResize();
|
|
}
|
|
|
|
Size SplitWindow::CalcLayoutSizePixel( const Size& aNewSize )
|
|
{
|
|
Size aSize( aNewSize );
|
|
long nSplitSize = mpMainSet->mnSplitSize-2;
|
|
|
|
if (mbFadeOut)
|
|
nSplitSize += SPLITWIN_SPLITSIZEEXLN;
|
|
|
|
// if the window is sizeable and if it does not contain a relative window,
|
|
// the size is determined according to MainSet
|
|
if ( mnWinStyle & WB_SIZEABLE )
|
|
{
|
|
long nCalcSize = 0;
|
|
std::vector< ImplSplitItem* >::size_type i;
|
|
|
|
for ( i = 0; i < mpMainSet->mvItems.size(); i++ )
|
|
{
|
|
if ( mpMainSet->mvItems[i].mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize) )
|
|
break;
|
|
else
|
|
nCalcSize += mpMainSet->mvItems[i].mnSize;
|
|
}
|
|
|
|
if ( i == mpMainSet->mvItems.size() )
|
|
{
|
|
long nDelta = 0;
|
|
long nCurSize;
|
|
|
|
if ( mbHorz )
|
|
nCurSize = aNewSize.Height()-mnTopBorder-mnBottomBorder;
|
|
else
|
|
nCurSize = aNewSize.Width()-mnLeftBorder-mnRightBorder;
|
|
nCurSize -= nSplitSize;
|
|
nCurSize -= (mpMainSet->mvItems.size()-1)*mpMainSet->mnSplitSize;
|
|
|
|
nDelta = nCalcSize-nCurSize;
|
|
if ( !nDelta )
|
|
return aSize;
|
|
|
|
switch ( meAlign )
|
|
{
|
|
case WindowAlign::Top:
|
|
aSize.AdjustHeight(nDelta );
|
|
break;
|
|
case WindowAlign::Bottom:
|
|
aSize.AdjustHeight(nDelta );
|
|
break;
|
|
case WindowAlign::Left:
|
|
aSize.AdjustWidth(nDelta );
|
|
break;
|
|
case WindowAlign::Right:
|
|
default:
|
|
aSize.AdjustWidth(nDelta );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return aSize;
|
|
}
|
|
|
|
void SplitWindow::ImplCalcLayout()
|
|
{
|
|
if ( !mbCalc || !mbRecalc || mpMainSet->mvItems.empty() )
|
|
return;
|
|
|
|
long nSplitSize = mpMainSet->mnSplitSize-2;
|
|
if (mbFadeOut)
|
|
nSplitSize += SPLITWIN_SPLITSIZEEXLN;
|
|
|
|
// if the window is sizeable and if it does not contain a relative window,
|
|
// the size is determined according to MainSet
|
|
if ( mnWinStyle & WB_SIZEABLE )
|
|
{
|
|
long nCalcSize = 0;
|
|
std::vector<ImplSplitItem *>::size_type i;
|
|
|
|
for ( i = 0; i < mpMainSet->mvItems.size(); i++ )
|
|
{
|
|
if ( mpMainSet->mvItems[i].mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize) )
|
|
break;
|
|
else
|
|
nCalcSize += mpMainSet->mvItems[i].mnSize;
|
|
}
|
|
|
|
if ( i == mpMainSet->mvItems.size() )
|
|
{
|
|
long nCurSize;
|
|
if ( mbHorz )
|
|
nCurSize = mnDY-mnTopBorder-mnBottomBorder;
|
|
else
|
|
nCurSize = mnDX-mnLeftBorder-mnRightBorder;
|
|
nCurSize -= nSplitSize;
|
|
nCurSize -= (mpMainSet->mvItems.size()-1)*mpMainSet->mnSplitSize;
|
|
|
|
mbRecalc = false;
|
|
ImplSetWindowSize( nCalcSize-nCurSize );
|
|
mbRecalc = true;
|
|
}
|
|
}
|
|
|
|
if ( (mnDX <= 0) || (mnDY <= 0) )
|
|
return;
|
|
|
|
// pre-calculate sizes/position
|
|
long nL;
|
|
long nT;
|
|
long nW;
|
|
long nH;
|
|
|
|
if ( mbHorz )
|
|
{
|
|
if ( mbBottomRight )
|
|
nT = mnDY-mnBottomBorder;
|
|
else
|
|
nT = mnTopBorder;
|
|
nL = mnLeftBorder;
|
|
}
|
|
else
|
|
{
|
|
if ( mbBottomRight )
|
|
nL = mnDX-mnRightBorder;
|
|
else
|
|
nL = mnLeftBorder;
|
|
nT = mnTopBorder;
|
|
}
|
|
nW = mnDX-mnLeftBorder-mnRightBorder;
|
|
nH = mnDY-mnTopBorder-mnBottomBorder;
|
|
if ( mnWinStyle & WB_SIZEABLE )
|
|
{
|
|
if ( mbHorz )
|
|
nH -= nSplitSize;
|
|
else
|
|
nW -= nSplitSize;
|
|
}
|
|
|
|
// calculate sets recursive
|
|
ImplCalcSet( mpMainSet.get(), nL, nT, nW, nH, mbHorz, !mbBottomRight );
|
|
ImplCalcSet2( this, mpMainSet.get(), false, mbHorz );
|
|
mbCalc = false;
|
|
}
|
|
|
|
void SplitWindow::ImplUpdate()
|
|
{
|
|
mbCalc = true;
|
|
|
|
if ( IsReallyShown() && IsUpdateMode() && mbRecalc )
|
|
{
|
|
if ( !mpMainSet->mvItems.empty() )
|
|
ImplCalcLayout();
|
|
else
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
void SplitWindow::ImplSplitMousePos( Point& rMousePos )
|
|
{
|
|
if ( mnSplitTest & SPLIT_HORZ )
|
|
{
|
|
rMousePos.AdjustX( -mnMouseOff );
|
|
if ( rMousePos.X() < maDragRect.Left() )
|
|
rMousePos.setX( maDragRect.Left() );
|
|
else if ( rMousePos.X()+mpSplitSet->mnSplitSize+1 > maDragRect.Right() )
|
|
rMousePos.setX( maDragRect.Right()-mpSplitSet->mnSplitSize+1 );
|
|
// store in screen coordinates due to FullDrag
|
|
mnMSplitPos = OutputToScreenPixel( rMousePos ).X();
|
|
}
|
|
else
|
|
{
|
|
rMousePos.AdjustY( -mnMouseOff );
|
|
if ( rMousePos.Y() < maDragRect.Top() )
|
|
rMousePos.setY( maDragRect.Top() );
|
|
else if ( rMousePos.Y()+mpSplitSet->mnSplitSize+1 > maDragRect.Bottom() )
|
|
rMousePos.setY( maDragRect.Bottom()-mpSplitSet->mnSplitSize+1 );
|
|
mnMSplitPos = OutputToScreenPixel( rMousePos ).Y();
|
|
}
|
|
}
|
|
|
|
void SplitWindow::ImplGetButtonRect( tools::Rectangle& rRect, bool bTest ) const
|
|
{
|
|
long nSplitSize = mpMainSet->mnSplitSize-1;
|
|
if (mbFadeOut || mbFadeIn)
|
|
nSplitSize += SPLITWIN_SPLITSIZEEX;
|
|
|
|
long nButtonSize = 0;
|
|
if ( mbFadeIn )
|
|
nButtonSize += SPLITWIN_SPLITSIZEFADE+1;
|
|
if ( mbFadeOut )
|
|
nButtonSize += SPLITWIN_SPLITSIZEFADE+1;
|
|
long nCenterEx = 0;
|
|
if ( mbHorz )
|
|
nCenterEx += ((mnDX-mnLeftBorder-mnRightBorder)-nButtonSize)/2;
|
|
else
|
|
nCenterEx += ((mnDY-mnTopBorder-mnBottomBorder)-nButtonSize)/2;
|
|
long nEx = 0;
|
|
if ( nCenterEx > 0 )
|
|
nEx += nCenterEx;
|
|
|
|
switch ( meAlign )
|
|
{
|
|
case WindowAlign::Top:
|
|
rRect.SetLeft( mnLeftBorder+nEx );
|
|
rRect.SetTop( mnDY-mnBottomBorder-nSplitSize );
|
|
rRect.SetRight( rRect.Left()+SPLITWIN_SPLITSIZEAUTOHIDE );
|
|
rRect.SetBottom( mnDY-mnBottomBorder-1 );
|
|
if ( bTest )
|
|
{
|
|
rRect.AdjustTop( -mnTopBorder );
|
|
rRect.AdjustBottom(mnBottomBorder );
|
|
}
|
|
break;
|
|
case WindowAlign::Bottom:
|
|
rRect.SetLeft( mnLeftBorder+nEx );
|
|
rRect.SetTop( mnTopBorder );
|
|
rRect.SetRight( rRect.Left()+SPLITWIN_SPLITSIZEAUTOHIDE );
|
|
rRect.SetBottom( mnTopBorder+nSplitSize-1 );
|
|
if ( bTest )
|
|
{
|
|
rRect.AdjustTop( -mnTopBorder );
|
|
rRect.AdjustBottom(mnBottomBorder );
|
|
}
|
|
break;
|
|
case WindowAlign::Left:
|
|
rRect.SetLeft( mnDX-mnRightBorder-nSplitSize );
|
|
rRect.SetTop( mnTopBorder+nEx );
|
|
rRect.SetRight( mnDX-mnRightBorder-1 );
|
|
rRect.SetBottom( rRect.Top()+SPLITWIN_SPLITSIZEAUTOHIDE );
|
|
if ( bTest )
|
|
{
|
|
rRect.AdjustLeft( -mnLeftBorder );
|
|
rRect.AdjustRight(mnRightBorder );
|
|
}
|
|
break;
|
|
case WindowAlign::Right:
|
|
rRect.SetLeft( mnLeftBorder );
|
|
rRect.SetTop( mnTopBorder+nEx );
|
|
rRect.SetRight( mnLeftBorder+nSplitSize-1 );
|
|
rRect.SetBottom( rRect.Top()+SPLITWIN_SPLITSIZEAUTOHIDE );
|
|
if ( bTest )
|
|
{
|
|
rRect.AdjustLeft( -mnLeftBorder );
|
|
rRect.AdjustRight(mnRightBorder );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void SplitWindow::ImplGetFadeInRect( tools::Rectangle& rRect, bool bTest ) const
|
|
{
|
|
tools::Rectangle aRect;
|
|
|
|
if ( mbFadeIn )
|
|
ImplGetButtonRect( aRect, bTest );
|
|
|
|
rRect = aRect;
|
|
}
|
|
|
|
void SplitWindow::ImplGetFadeOutRect( tools::Rectangle& rRect ) const
|
|
{
|
|
tools::Rectangle aRect;
|
|
|
|
if ( mbFadeOut )
|
|
ImplGetButtonRect( aRect, false );
|
|
|
|
rRect = aRect;
|
|
}
|
|
|
|
void SplitWindow::ImplDrawGrip(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, bool bHorizontal, bool bLeft)
|
|
{
|
|
const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
|
|
|
|
Color aColor;
|
|
|
|
if (rRect.IsInside(GetPointerPosPixel()))
|
|
{
|
|
vcl::RenderTools::DrawSelectionBackground(rRenderContext, *this, rRect, 2, false, false, false);
|
|
|
|
aColor = rStyleSettings.GetDarkShadowColor();
|
|
}
|
|
else
|
|
{
|
|
rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
|
|
rRenderContext.SetFillColor(rStyleSettings.GetDarkShadowColor());
|
|
|
|
rRenderContext.DrawRect(rRect);
|
|
|
|
aColor = rStyleSettings.GetFaceColor();
|
|
}
|
|
|
|
AntialiasingFlags nAA = rRenderContext.GetAntialiasing();
|
|
rRenderContext.SetAntialiasing(nAA | AntialiasingFlags::PixelSnapHairline | AntialiasingFlags::EnableB2dDraw);
|
|
|
|
long nWidth = rRect.getWidth();
|
|
long nWidthHalf = nWidth / 2;
|
|
long nHeight = rRect.getHeight();
|
|
long nHeightHalf = nHeight / 2;
|
|
|
|
long nLeft = rRect.Left();
|
|
long nRight = rRect.Right();
|
|
long nTop = rRect.Top();
|
|
long nBottom = rRect.Bottom();
|
|
long nMargin = 1;
|
|
|
|
rRenderContext.SetLineColor(aColor);
|
|
rRenderContext.SetFillColor(aColor);
|
|
|
|
tools::Polygon aPoly(3);
|
|
|
|
if (bHorizontal)
|
|
{
|
|
long nCenter = nLeft + nWidthHalf;
|
|
|
|
if (bLeft)
|
|
{
|
|
aPoly.SetPoint(Point(nCenter, nTop + nMargin), 0);
|
|
aPoly.SetPoint(Point(nCenter - nHeightHalf, nBottom - nMargin), 1);
|
|
aPoly.SetPoint(Point(nCenter - nHeightHalf, nBottom - nMargin), 2);
|
|
}
|
|
else
|
|
{
|
|
aPoly.SetPoint(Point(nCenter, nBottom - nMargin), 0);
|
|
aPoly.SetPoint(Point(nCenter - nHeightHalf, nTop + nMargin), 1);
|
|
aPoly.SetPoint(Point(nCenter + nHeightHalf, nTop + nMargin), 2);
|
|
}
|
|
rRenderContext.DrawPolygon(aPoly);
|
|
}
|
|
else
|
|
{
|
|
long nCenter = nTop + nHeightHalf;
|
|
|
|
if (bLeft)
|
|
{
|
|
aPoly.SetPoint(Point(nLeft + nMargin, nCenter), 0);
|
|
aPoly.SetPoint(Point(nRight - nMargin, nCenter - nWidthHalf), 1);
|
|
aPoly.SetPoint(Point(nRight - nMargin, nCenter + nWidthHalf), 2);
|
|
}
|
|
else
|
|
{
|
|
aPoly.SetPoint(Point(nRight - nMargin, nCenter), 0);
|
|
aPoly.SetPoint(Point(nLeft + nMargin, nCenter - nWidthHalf), 1);
|
|
aPoly.SetPoint(Point(nLeft + nMargin, nCenter + nWidthHalf), 2);
|
|
}
|
|
rRenderContext.DrawPolygon(aPoly);
|
|
}
|
|
|
|
rRenderContext.SetAntialiasing(nAA);
|
|
}
|
|
|
|
void SplitWindow::ImplDrawFadeIn(vcl::RenderContext& rRenderContext)
|
|
{
|
|
if (mbFadeIn)
|
|
{
|
|
tools::Rectangle aTempRect;
|
|
ImplGetFadeInRect(aTempRect);
|
|
|
|
bool bLeft = true;
|
|
switch (meAlign)
|
|
{
|
|
case WindowAlign::Top:
|
|
case WindowAlign::Left:
|
|
bLeft = false;
|
|
break;
|
|
case WindowAlign::Bottom:
|
|
case WindowAlign::Right:
|
|
default:
|
|
bLeft = true;
|
|
break;
|
|
}
|
|
|
|
ImplDrawGrip(rRenderContext, aTempRect, (meAlign == WindowAlign::Top) || (meAlign == WindowAlign::Bottom), bLeft);
|
|
}
|
|
}
|
|
|
|
void SplitWindow::ImplDrawFadeOut(vcl::RenderContext& rRenderContext)
|
|
{
|
|
if (mbFadeOut)
|
|
{
|
|
tools::Rectangle aTempRect;
|
|
ImplGetFadeOutRect(aTempRect);
|
|
|
|
bool bLeft = true;
|
|
switch (meAlign)
|
|
{
|
|
case WindowAlign::Bottom:
|
|
case WindowAlign::Right:
|
|
bLeft = false;
|
|
break;
|
|
case WindowAlign::Top:
|
|
case WindowAlign::Left:
|
|
default:
|
|
bLeft = true;
|
|
break;
|
|
}
|
|
|
|
ImplDrawGrip(rRenderContext, aTempRect, (meAlign == WindowAlign::Top) || (meAlign == WindowAlign::Bottom), bLeft);
|
|
}
|
|
}
|
|
|
|
void SplitWindow::ImplStartSplit( const MouseEvent& rMEvt )
|
|
{
|
|
Point aMousePosPixel = rMEvt.GetPosPixel();
|
|
mnSplitTest = ImplTestSplit( this, aMousePosPixel, mnMouseOff, &mpSplitSet, mnSplitPos );
|
|
|
|
if ( !mnSplitTest || (mnSplitTest & SPLIT_NOSPLIT) )
|
|
return;
|
|
|
|
ImplSplitItem* pSplitItem;
|
|
long nCurMaxSize;
|
|
bool bPropSmaller;
|
|
|
|
mnMouseModifier = rMEvt.GetModifier();
|
|
bPropSmaller = (mnMouseModifier & KEY_SHIFT) && (static_cast<sal_uInt16>(mnSplitPos+1) < mpSplitSet->mvItems.size());
|
|
|
|
// here we can set the maximum size
|
|
StartSplit();
|
|
|
|
if ( mnMaxSize )
|
|
nCurMaxSize = mnMaxSize;
|
|
else
|
|
{
|
|
Size aSize = GetParent()->GetOutputSizePixel();
|
|
if ( mbHorz )
|
|
nCurMaxSize = aSize.Height();
|
|
else
|
|
nCurMaxSize = aSize.Width();
|
|
}
|
|
|
|
if ( !mpSplitSet->mvItems.empty() )
|
|
{
|
|
bool bDown = true;
|
|
if ( (mpSplitSet == mpMainSet.get()) && mbBottomRight )
|
|
bDown = false;
|
|
|
|
pSplitItem = &mpSplitSet->mvItems[mnSplitPos];
|
|
maDragRect.SetLeft( pSplitItem->mnLeft );
|
|
maDragRect.SetTop( pSplitItem->mnTop );
|
|
maDragRect.SetRight( pSplitItem->mnLeft+pSplitItem->mnWidth-1 );
|
|
maDragRect.SetBottom( pSplitItem->mnTop+pSplitItem->mnHeight-1 );
|
|
|
|
if ( mnSplitTest & SPLIT_HORZ )
|
|
{
|
|
if ( bDown )
|
|
maDragRect.AdjustRight(mpSplitSet->mnSplitSize );
|
|
else
|
|
maDragRect.AdjustLeft( -(mpSplitSet->mnSplitSize) );
|
|
}
|
|
else
|
|
{
|
|
if ( bDown )
|
|
maDragRect.AdjustBottom(mpSplitSet->mnSplitSize );
|
|
else
|
|
maDragRect.AdjustTop( -(mpSplitSet->mnSplitSize) );
|
|
}
|
|
|
|
if ( mnSplitPos )
|
|
{
|
|
long nTemp = mnSplitPos;
|
|
while ( nTemp )
|
|
{
|
|
pSplitItem = &mpSplitSet->mvItems[nTemp-1];
|
|
if ( pSplitItem->mbFixed )
|
|
break;
|
|
else
|
|
{
|
|
if ( mnSplitTest & SPLIT_HORZ )
|
|
{
|
|
if ( bDown )
|
|
maDragRect.AdjustLeft( -(pSplitItem->mnPixSize) );
|
|
else
|
|
maDragRect.AdjustRight(pSplitItem->mnPixSize );
|
|
}
|
|
else
|
|
{
|
|
if ( bDown )
|
|
maDragRect.AdjustTop( -(pSplitItem->mnPixSize) );
|
|
else
|
|
maDragRect.AdjustBottom(pSplitItem->mnPixSize );
|
|
}
|
|
}
|
|
nTemp--;
|
|
}
|
|
}
|
|
|
|
if ( (mpSplitSet == mpMainSet.get()) && (mnWinStyle & WB_SIZEABLE) && !bPropSmaller )
|
|
{
|
|
if ( bDown )
|
|
{
|
|
if ( mbHorz )
|
|
maDragRect.AdjustBottom(nCurMaxSize-mnDY-mnTopBorder );
|
|
else
|
|
maDragRect.AdjustRight(nCurMaxSize-mnDX-mnLeftBorder );
|
|
}
|
|
else
|
|
{
|
|
if ( mbHorz )
|
|
maDragRect.AdjustTop( -(nCurMaxSize-mnDY-mnBottomBorder) );
|
|
else
|
|
maDragRect.AdjustLeft( -(nCurMaxSize-mnDX-mnRightBorder) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::vector<ImplSplitItem *>::size_type nTemp = mnSplitPos+1;
|
|
while ( nTemp < mpSplitSet->mvItems.size() )
|
|
{
|
|
pSplitItem = &mpSplitSet->mvItems[nTemp];
|
|
if ( pSplitItem->mbFixed )
|
|
break;
|
|
else
|
|
{
|
|
if ( mnSplitTest & SPLIT_HORZ )
|
|
{
|
|
if ( bDown )
|
|
maDragRect.AdjustRight(pSplitItem->mnPixSize );
|
|
else
|
|
maDragRect.AdjustLeft( -(pSplitItem->mnPixSize) );
|
|
}
|
|
else
|
|
{
|
|
if ( bDown )
|
|
maDragRect.AdjustBottom(pSplitItem->mnPixSize );
|
|
else
|
|
maDragRect.AdjustTop( -(pSplitItem->mnPixSize) );
|
|
}
|
|
}
|
|
nTemp++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
maDragRect.SetLeft( mnLeftBorder );
|
|
maDragRect.SetTop( mnTopBorder );
|
|
maDragRect.SetRight( mnDX-mnRightBorder-1 );
|
|
maDragRect.SetBottom( mnDY-mnBottomBorder-1 );
|
|
if ( mbHorz )
|
|
{
|
|
if ( mbBottomRight )
|
|
maDragRect.AdjustTop( -(nCurMaxSize-mnDY-mnBottomBorder) );
|
|
else
|
|
maDragRect.AdjustBottom(nCurMaxSize-mnDY-mnTopBorder );
|
|
}
|
|
else
|
|
{
|
|
if ( mbBottomRight )
|
|
maDragRect.AdjustLeft( -(nCurMaxSize-mnDX-mnRightBorder) );
|
|
else
|
|
maDragRect.AdjustRight(nCurMaxSize-mnDX-mnLeftBorder );
|
|
}
|
|
}
|
|
|
|
StartTracking();
|
|
|
|
mbDragFull = bool(GetSettings().GetStyleSettings().GetDragFullOptions() & DragFullOptions::Split);
|
|
|
|
ImplSplitMousePos( aMousePosPixel );
|
|
|
|
if (!mbDragFull)
|
|
{
|
|
ImplDrawSplitTracking(aMousePosPixel);
|
|
}
|
|
else
|
|
{
|
|
std::vector< ImplSplitItem >& rItems = mpSplitSet->mvItems;
|
|
sal_uInt16 nItems = mpSplitSet->mvItems.size();
|
|
mpLastSizes = new long[nItems*2];
|
|
for ( sal_uInt16 i = 0; i < nItems; i++ )
|
|
{
|
|
mpLastSizes[i*2] = rItems[i].mnSize;
|
|
mpLastSizes[i*2+1] = rItems[i].mnPixSize;
|
|
}
|
|
}
|
|
mnMStartPos = mnMSplitPos;
|
|
|
|
PointerStyle eStyle = PointerStyle::Arrow;
|
|
if ( mnSplitTest & SPLIT_HORZ )
|
|
eStyle = PointerStyle::HSplit;
|
|
else if ( mnSplitTest & SPLIT_VERT )
|
|
eStyle = PointerStyle::VSplit;
|
|
|
|
SetPointer( eStyle );
|
|
}
|
|
|
|
void SplitWindow::StartSplit()
|
|
{
|
|
}
|
|
|
|
void SplitWindow::Split()
|
|
{
|
|
maSplitHdl.Call( this );
|
|
}
|
|
|
|
void SplitWindow::SplitResize()
|
|
{
|
|
}
|
|
|
|
void SplitWindow::FadeIn()
|
|
{
|
|
}
|
|
|
|
void SplitWindow::FadeOut()
|
|
{
|
|
}
|
|
|
|
void SplitWindow::MouseButtonDown( const MouseEvent& rMEvt )
|
|
{
|
|
if ( !rMEvt.IsLeft() || rMEvt.IsMod2() )
|
|
{
|
|
DockingWindow::MouseButtonDown( rMEvt );
|
|
return;
|
|
}
|
|
|
|
Point aMousePosPixel = rMEvt.GetPosPixel();
|
|
tools::Rectangle aTestRect;
|
|
|
|
mbFadeNoButtonMode = false;
|
|
|
|
ImplGetFadeOutRect( aTestRect );
|
|
if ( aTestRect.IsInside( aMousePosPixel ) )
|
|
{
|
|
mbFadeOutDown = true;
|
|
mbFadeOutPressed = true;
|
|
Invalidate();
|
|
}
|
|
else
|
|
{
|
|
ImplGetFadeInRect( aTestRect, true );
|
|
if ( aTestRect.IsInside( aMousePosPixel ) )
|
|
{
|
|
mbFadeInDown = true;
|
|
mbFadeInPressed = true;
|
|
Invalidate();
|
|
}
|
|
else if ( !aTestRect.IsEmpty() && !(mnWinStyle & WB_SIZEABLE) )
|
|
{
|
|
mbFadeNoButtonMode = true;
|
|
FadeIn();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( mbFadeInDown || mbFadeOutDown )
|
|
StartTracking();
|
|
else
|
|
ImplStartSplit( rMEvt );
|
|
}
|
|
|
|
void SplitWindow::MouseMove( const MouseEvent& rMEvt )
|
|
{
|
|
if ( IsTracking() )
|
|
return;
|
|
|
|
Point aPos = rMEvt.GetPosPixel();
|
|
long nTemp;
|
|
ImplSplitSet* pTempSplitSet;
|
|
sal_uInt16 nTempSplitPos;
|
|
sal_uInt16 nSplitTest = ImplTestSplit( this, aPos, nTemp, &pTempSplitSet, nTempSplitPos );
|
|
PointerStyle eStyle = PointerStyle::Arrow;
|
|
tools::Rectangle aFadeInRect;
|
|
tools::Rectangle aFadeOutRect;
|
|
|
|
ImplGetFadeInRect( aFadeInRect );
|
|
ImplGetFadeOutRect( aFadeOutRect );
|
|
if ( !aFadeInRect.IsInside( aPos ) &&
|
|
!aFadeOutRect.IsInside( aPos ) )
|
|
{
|
|
if ( nSplitTest && !(nSplitTest & SPLIT_NOSPLIT) )
|
|
{
|
|
if ( nSplitTest & SPLIT_HORZ )
|
|
eStyle = PointerStyle::HSplit;
|
|
else if ( nSplitTest & SPLIT_VERT )
|
|
eStyle = PointerStyle::VSplit;
|
|
}
|
|
}
|
|
|
|
SetPointer( eStyle );
|
|
}
|
|
|
|
void SplitWindow::Tracking( const TrackingEvent& rTEvt )
|
|
{
|
|
Point aMousePosPixel = rTEvt.GetMouseEvent().GetPosPixel();
|
|
|
|
if ( mbFadeInDown )
|
|
{
|
|
if ( rTEvt.IsTrackingEnded() )
|
|
{
|
|
mbFadeInDown = false;
|
|
if ( mbFadeInPressed )
|
|
{
|
|
mbFadeInPressed = false;
|
|
Invalidate();
|
|
|
|
if ( !rTEvt.IsTrackingCanceled() )
|
|
FadeIn();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tools::Rectangle aTestRect;
|
|
ImplGetFadeInRect( aTestRect, true );
|
|
bool bNewPressed = aTestRect.IsInside( aMousePosPixel );
|
|
if ( bNewPressed != mbFadeInPressed )
|
|
{
|
|
mbFadeInPressed = bNewPressed;
|
|
Invalidate();
|
|
}
|
|
}
|
|
}
|
|
else if ( mbFadeOutDown )
|
|
{
|
|
if ( rTEvt.IsTrackingEnded() )
|
|
{
|
|
mbFadeOutDown = false;
|
|
if ( mbFadeOutPressed )
|
|
{
|
|
mbFadeOutPressed = false;
|
|
Invalidate();
|
|
|
|
if ( !rTEvt.IsTrackingCanceled() )
|
|
FadeOut();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tools::Rectangle aTestRect;
|
|
ImplGetFadeOutRect( aTestRect );
|
|
bool bNewPressed = aTestRect.IsInside( aMousePosPixel );
|
|
if ( !bNewPressed )
|
|
{
|
|
mbFadeOutPressed = bNewPressed;
|
|
Invalidate();
|
|
|
|
// We need a mouseevent with a position inside the button for the
|
|
// ImplStartSplit function!
|
|
MouseEvent aOrgMEvt = rTEvt.GetMouseEvent();
|
|
MouseEvent aNewMEvt( aTestRect.Center(), aOrgMEvt.GetClicks(),
|
|
aOrgMEvt.GetMode(), aOrgMEvt.GetButtons(),
|
|
aOrgMEvt.GetModifier() );
|
|
|
|
ImplStartSplit( aNewMEvt );
|
|
mbFadeOutDown = false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ImplSplitMousePos( aMousePosPixel );
|
|
bool bSplit = true;
|
|
if ( mbDragFull )
|
|
{
|
|
if ( rTEvt.IsTrackingEnded() )
|
|
{
|
|
if ( rTEvt.IsTrackingCanceled() )
|
|
{
|
|
std::vector< ImplSplitItem >& rItems = mpSplitSet->mvItems;
|
|
size_t nItems = rItems.size();
|
|
for ( size_t i = 0; i < nItems; i++ )
|
|
{
|
|
rItems[i].mnSize = mpLastSizes[i*2];
|
|
rItems[i].mnPixSize = mpLastSizes[i*2+1];
|
|
}
|
|
ImplUpdate();
|
|
Split();
|
|
}
|
|
bSplit = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( rTEvt.IsTrackingEnded() )
|
|
{
|
|
HideTracking();
|
|
bSplit = !rTEvt.IsTrackingCanceled();
|
|
}
|
|
else
|
|
{
|
|
ImplDrawSplitTracking(aMousePosPixel);
|
|
bSplit = false;
|
|
}
|
|
}
|
|
|
|
if ( bSplit )
|
|
{
|
|
bool bPropSmaller = (mnMouseModifier & KEY_SHIFT) != 0;
|
|
bool bPropGreater = (mnMouseModifier & KEY_MOD1) != 0;
|
|
long nDelta = mnMSplitPos-mnMStartPos;
|
|
|
|
if ( (mnSplitTest & SPLIT_WINDOW) && mpMainSet->mvItems.empty() )
|
|
{
|
|
if ( (mpSplitSet == mpMainSet.get()) && mbBottomRight )
|
|
nDelta *= -1;
|
|
ImplSetWindowSize( nDelta );
|
|
}
|
|
else
|
|
{
|
|
long nNewSize = mpSplitSet->mvItems[mnSplitPos].mnPixSize;
|
|
if ( (mpSplitSet == mpMainSet.get()) && mbBottomRight )
|
|
nNewSize -= nDelta;
|
|
else
|
|
nNewSize += nDelta;
|
|
SplitItem( mpSplitSet->mvItems[mnSplitPos].mnId, nNewSize,
|
|
bPropSmaller, bPropGreater );
|
|
}
|
|
|
|
Split();
|
|
|
|
if ( mbDragFull )
|
|
{
|
|
Update();
|
|
mnMStartPos = mnMSplitPos;
|
|
}
|
|
}
|
|
|
|
if ( rTEvt.IsTrackingEnded() )
|
|
{
|
|
delete [] mpLastSizes;
|
|
mpLastSizes = nullptr;
|
|
mpSplitSet = nullptr;
|
|
mnMouseOff = 0;
|
|
mnMStartPos = 0;
|
|
mnMSplitPos = 0;
|
|
mnMouseModifier = 0;
|
|
mnSplitTest = 0;
|
|
mnSplitPos = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SplitWindow::PreNotify( NotifyEvent& rNEvt )
|
|
{
|
|
const MouseEvent* pMouseEvt = nullptr;
|
|
|
|
if( (rNEvt.GetType() == MouseNotifyEvent::MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != nullptr )
|
|
{
|
|
if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
|
|
{
|
|
// trigger redraw if mouse over state has changed
|
|
tools::Rectangle aFadeInRect;
|
|
tools::Rectangle aFadeOutRect;
|
|
ImplGetFadeInRect( aFadeInRect );
|
|
ImplGetFadeOutRect( aFadeOutRect );
|
|
|
|
if ( aFadeInRect.IsInside( GetPointerPosPixel() ) != aFadeInRect.IsInside( GetLastPointerPosPixel() ) )
|
|
Invalidate( aFadeInRect );
|
|
if ( aFadeOutRect.IsInside( GetPointerPosPixel() ) != aFadeOutRect.IsInside( GetLastPointerPosPixel() ) )
|
|
Invalidate( aFadeOutRect );
|
|
|
|
if( pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() )
|
|
{
|
|
Invalidate( aFadeInRect );
|
|
Invalidate( aFadeOutRect );
|
|
}
|
|
}
|
|
}
|
|
return Window::PreNotify( rNEvt );
|
|
}
|
|
|
|
void SplitWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
|
|
{
|
|
if (mnWinStyle & WB_BORDER)
|
|
ImplDrawBorder(rRenderContext);
|
|
|
|
ImplDrawBorderLine(rRenderContext);
|
|
ImplDrawFadeOut(rRenderContext);
|
|
ImplDrawFadeIn(rRenderContext);
|
|
|
|
// draw FrameSet-backgrounds
|
|
ImplDrawBack(rRenderContext, mpMainSet.get());
|
|
|
|
// draw splitter
|
|
if (!(mnWinStyle & WB_NOSPLITDRAW))
|
|
{
|
|
ImplDrawSplit(rRenderContext, mpMainSet.get(), mbHorz, !mbBottomRight);
|
|
}
|
|
}
|
|
|
|
void SplitWindow::Resize()
|
|
{
|
|
Size aSize = GetOutputSizePixel();
|
|
mnDX = aSize.Width();
|
|
mnDY = aSize.Height();
|
|
|
|
ImplUpdate();
|
|
Invalidate();
|
|
}
|
|
|
|
void SplitWindow::RequestHelp( const HelpEvent& rHEvt )
|
|
{
|
|
// no keyboard help for splitwin
|
|
if ( rHEvt.GetMode() & (HelpEventMode::BALLOON | HelpEventMode::QUICK) && !rHEvt.KeyboardActivated() )
|
|
{
|
|
Point aMousePosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
|
|
tools::Rectangle aHelpRect;
|
|
const char* pHelpResId = nullptr;
|
|
|
|
ImplGetFadeInRect( aHelpRect, true );
|
|
if ( aHelpRect.IsInside( aMousePosPixel ) )
|
|
pHelpResId = SV_HELPTEXT_FADEIN;
|
|
else
|
|
{
|
|
ImplGetFadeOutRect( aHelpRect );
|
|
if ( aHelpRect.IsInside( aMousePosPixel ) )
|
|
pHelpResId = SV_HELPTEXT_FADEOUT;
|
|
}
|
|
|
|
// get rectangle
|
|
if (pHelpResId)
|
|
{
|
|
Point aPt = OutputToScreenPixel( aHelpRect.TopLeft() );
|
|
aHelpRect.SetLeft( aPt.X() );
|
|
aHelpRect.SetTop( aPt.Y() );
|
|
aPt = OutputToScreenPixel( aHelpRect.BottomRight() );
|
|
aHelpRect.SetRight( aPt.X() );
|
|
aHelpRect.SetBottom( aPt.Y() );
|
|
|
|
// get and draw text
|
|
OUString aStr = VclResId(pHelpResId);
|
|
if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
|
|
Help::ShowBalloon( this, aHelpRect.Center(), aHelpRect, aStr );
|
|
else
|
|
Help::ShowQuickHelp( this, aHelpRect, aStr );
|
|
return;
|
|
}
|
|
}
|
|
|
|
DockingWindow::RequestHelp( rHEvt );
|
|
}
|
|
|
|
void SplitWindow::StateChanged( StateChangedType nType )
|
|
{
|
|
switch ( nType )
|
|
{
|
|
case StateChangedType::InitShow:
|
|
if ( IsUpdateMode() )
|
|
ImplCalcLayout();
|
|
break;
|
|
case StateChangedType::UpdateMode:
|
|
if ( IsUpdateMode() && IsReallyShown() )
|
|
ImplCalcLayout();
|
|
break;
|
|
case StateChangedType::ControlBackground:
|
|
ImplInitSettings();
|
|
Invalidate();
|
|
break;
|
|
default:;
|
|
}
|
|
|
|
DockingWindow::StateChanged( nType );
|
|
}
|
|
|
|
void SplitWindow::DataChanged( const DataChangedEvent& rDCEvt )
|
|
{
|
|
if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
|
|
(rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
|
|
{
|
|
ImplInitSettings();
|
|
Invalidate();
|
|
}
|
|
else
|
|
DockingWindow::DataChanged( rDCEvt );
|
|
}
|
|
|
|
void SplitWindow::InsertItem( sal_uInt16 nId, vcl::Window* pWindow, long nSize,
|
|
sal_uInt16 nPos, sal_uInt16 nIntoSetId,
|
|
SplitWindowItemFlags nBits )
|
|
{
|
|
#ifdef DBG_UTIL
|
|
sal_uInt16 nDbgDummy;
|
|
SAL_WARN_IF( ImplFindItem( mpMainSet.get(), nId, nDbgDummy ), "vcl", "SplitWindow::InsertItem() - Id already exists" );
|
|
#endif
|
|
|
|
// Size has to be at least 1.
|
|
if ( nSize < 1 )
|
|
nSize = 1;
|
|
|
|
ImplSplitSet* pSet = ImplFindSet( mpMainSet.get(), nIntoSetId );
|
|
#ifdef DBG_UTIL
|
|
SAL_WARN_IF( !pSet, "vcl", "SplitWindow::InsertItem() - Set not exists" );
|
|
#endif
|
|
if(!pSet)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Don't insert further than the end
|
|
if ( nPos > pSet->mvItems.size() )
|
|
nPos = pSet->mvItems.size();
|
|
|
|
// Insert in set
|
|
pSet->mvItems.emplace( pSet->mvItems.begin() + nPos );
|
|
|
|
// init new item
|
|
ImplSplitItem & aItem = pSet->mvItems[nPos];
|
|
aItem.mnSize = nSize;
|
|
aItem.mnPixSize = 0;
|
|
aItem.mnId = nId;
|
|
aItem.mnBits = nBits;
|
|
aItem.mnMinSize=-1;
|
|
aItem.mnMaxSize=-1;
|
|
|
|
if ( pWindow )
|
|
{
|
|
// New VclPtr reference
|
|
aItem.mpWindow = pWindow;
|
|
aItem.mpOrgParent = pWindow->GetParent();
|
|
|
|
// Attach window to SplitWindow.
|
|
pWindow->Hide();
|
|
pWindow->SetParent( this );
|
|
}
|
|
else
|
|
{
|
|
ImplSplitSet * pNewSet = new ImplSplitSet();
|
|
pNewSet->mnId = nId;
|
|
pNewSet->mnSplitSize = pSet->mnSplitSize;
|
|
|
|
aItem.mpSet.reset(pNewSet);
|
|
}
|
|
|
|
pSet->mbCalcPix = true;
|
|
|
|
ImplUpdate();
|
|
}
|
|
|
|
void SplitWindow::InsertItem( sal_uInt16 nId, long nSize,
|
|
sal_uInt16 nPos, sal_uInt16 nIntoSetId,
|
|
SplitWindowItemFlags nBits )
|
|
{
|
|
InsertItem( nId, nullptr, nSize, nPos, nIntoSetId, nBits );
|
|
}
|
|
|
|
void SplitWindow::RemoveItem( sal_uInt16 nId )
|
|
{
|
|
#ifdef DBG_UTIL
|
|
sal_uInt16 nDbgDummy;
|
|
SAL_WARN_IF( !ImplFindItem( mpMainSet.get(), nId, nDbgDummy ), "vcl", "SplitWindow::RemoveItem() - Id not found" );
|
|
#endif
|
|
|
|
// search set
|
|
sal_uInt16 nPos;
|
|
ImplSplitSet* pSet = ImplFindItem( mpMainSet.get(), nId, nPos );
|
|
|
|
if (!pSet)
|
|
return;
|
|
|
|
ImplSplitItem* pItem = &pSet->mvItems[nPos];
|
|
VclPtr<vcl::Window> pWindow = pItem->mpWindow;
|
|
VclPtr<vcl::Window> pOrgParent = pItem->mpOrgParent;
|
|
|
|
// delete set if required
|
|
if ( !pWindow )
|
|
pItem->mpSet.reset();
|
|
|
|
// remove item
|
|
pSet->mbCalcPix = true;
|
|
pSet->mvItems.erase( pSet->mvItems.begin() + nPos );
|
|
|
|
ImplUpdate();
|
|
|
|
// to have the least amounts of paints delete window only here
|
|
if ( pWindow )
|
|
{
|
|
// restore window
|
|
pWindow->Hide();
|
|
pWindow->SetParent( pOrgParent );
|
|
}
|
|
|
|
// Clear and delete
|
|
pWindow.clear();
|
|
pOrgParent.clear();
|
|
}
|
|
|
|
void SplitWindow::Clear()
|
|
{
|
|
// create Main-Set again
|
|
mpMainSet.reset(new ImplSplitSet());
|
|
if ( mnWinStyle & WB_NOSPLITDRAW )
|
|
mpMainSet->mnSplitSize -= 2;
|
|
mpBaseSet = mpMainSet.get();
|
|
|
|
// and invalidate again
|
|
ImplUpdate();
|
|
}
|
|
|
|
void SplitWindow::SplitItem( sal_uInt16 nId, long nNewSize,
|
|
bool bPropSmall, bool bPropGreat )
|
|
{
|
|
sal_uInt16 nPos;
|
|
ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
|
|
|
|
if (!pSet)
|
|
return;
|
|
|
|
size_t nItems = pSet->mvItems.size();
|
|
std::vector< ImplSplitItem >& rItems = pSet->mvItems;
|
|
|
|
// When there is an explicit minimum or maximum size then move nNewSize
|
|
// into that range (when it is not yet already in it.)
|
|
nNewSize = ValidateSize(nNewSize, rItems[nPos]);
|
|
|
|
if ( mbCalc )
|
|
{
|
|
rItems[nPos].mnSize = nNewSize;
|
|
return;
|
|
}
|
|
|
|
long nDelta = nNewSize-rItems[nPos].mnPixSize;
|
|
if ( !nDelta )
|
|
return;
|
|
|
|
// calculate area, which could be affected by splitting
|
|
sal_uInt16 nMin = 0;
|
|
sal_uInt16 nMax = nItems;
|
|
for (size_t i = 0; i < nItems; ++i)
|
|
{
|
|
if ( rItems[i].mbFixed )
|
|
{
|
|
if ( i < nPos )
|
|
nMin = i+1;
|
|
else
|
|
nMax = i;
|
|
}
|
|
}
|
|
|
|
// treat TopSet different if the window is sizeable
|
|
bool bSmall = true;
|
|
bool bGreat = true;
|
|
if ( (pSet == mpMainSet.get()) && (mnWinStyle & WB_SIZEABLE) )
|
|
{
|
|
if ( nPos < pSet->mvItems.size()-1 )
|
|
{
|
|
if ( !((bPropSmall && bPropGreat) ||
|
|
((nDelta > 0) && bPropSmall) ||
|
|
((nDelta < 0) && bPropGreat)) )
|
|
{
|
|
if ( nDelta < 0 )
|
|
bGreat = false;
|
|
else
|
|
bSmall = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( nDelta < 0 )
|
|
bGreat = false;
|
|
else
|
|
bSmall = false;
|
|
}
|
|
}
|
|
else if ( nPos >= nMax )
|
|
{
|
|
bSmall = false;
|
|
bGreat = false;
|
|
}
|
|
else if ( nPos && (nPos >= pSet->mvItems.size()-1) )
|
|
{
|
|
nPos--;
|
|
nDelta *= -1;
|
|
bool bTemp = bPropSmall;
|
|
bPropSmall = bPropGreat;
|
|
bPropGreat = bTemp;
|
|
}
|
|
|
|
sal_uInt16 n;
|
|
// now splitt the windows
|
|
if ( nDelta < 0 )
|
|
{
|
|
if ( bGreat )
|
|
{
|
|
if ( bPropGreat )
|
|
{
|
|
long nTempDelta = nDelta;
|
|
do
|
|
{
|
|
n = nPos+1;
|
|
do
|
|
{
|
|
if ( nTempDelta )
|
|
{
|
|
rItems[n].mnPixSize++;
|
|
nTempDelta++;
|
|
}
|
|
n++;
|
|
}
|
|
while ( n < nMax );
|
|
}
|
|
while ( nTempDelta );
|
|
}
|
|
else
|
|
rItems[nPos+1].mnPixSize -= nDelta;
|
|
}
|
|
|
|
if ( bSmall )
|
|
{
|
|
if ( bPropSmall )
|
|
{
|
|
do
|
|
{
|
|
n = nPos+1;
|
|
do
|
|
{
|
|
if ( nDelta && rItems[n-1].mnPixSize )
|
|
{
|
|
rItems[n-1].mnPixSize--;
|
|
nDelta++;
|
|
}
|
|
|
|
n--;
|
|
}
|
|
while ( n > nMin );
|
|
}
|
|
while ( nDelta );
|
|
}
|
|
else
|
|
{
|
|
n = nPos+1;
|
|
do
|
|
{
|
|
if ( rItems[n-1].mnPixSize+nDelta < 0 )
|
|
{
|
|
nDelta += rItems[n-1].mnPixSize;
|
|
rItems[n-1].mnPixSize = 0;
|
|
}
|
|
else
|
|
{
|
|
rItems[n-1].mnPixSize += nDelta;
|
|
break;
|
|
}
|
|
n--;
|
|
}
|
|
while ( n > nMin );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( bGreat )
|
|
{
|
|
if ( bPropGreat )
|
|
{
|
|
long nTempDelta = nDelta;
|
|
do
|
|
{
|
|
n = nPos+1;
|
|
do
|
|
{
|
|
if ( nTempDelta )
|
|
{
|
|
rItems[n-1].mnPixSize++;
|
|
nTempDelta--;
|
|
}
|
|
n--;
|
|
}
|
|
while ( n > nMin );
|
|
}
|
|
while ( nTempDelta );
|
|
}
|
|
else
|
|
rItems[nPos].mnPixSize += nDelta;
|
|
}
|
|
|
|
if ( bSmall )
|
|
{
|
|
if ( bPropSmall )
|
|
{
|
|
do
|
|
{
|
|
n = nPos+1;
|
|
do
|
|
{
|
|
if ( nDelta && rItems[n].mnPixSize )
|
|
{
|
|
rItems[n].mnPixSize--;
|
|
nDelta--;
|
|
}
|
|
|
|
n++;
|
|
}
|
|
while ( n < nMax );
|
|
}
|
|
while ( nDelta );
|
|
}
|
|
else
|
|
{
|
|
n = nPos+1;
|
|
do
|
|
{
|
|
if ( rItems[n].mnPixSize-nDelta < 0 )
|
|
{
|
|
nDelta -= rItems[n].mnPixSize;
|
|
rItems[n].mnPixSize = 0;
|
|
}
|
|
else
|
|
{
|
|
rItems[n].mnPixSize -= nDelta;
|
|
break;
|
|
}
|
|
n++;
|
|
}
|
|
while ( n < nMax );
|
|
}
|
|
}
|
|
}
|
|
|
|
// update original sizes
|
|
ImplCalcLogSize( rItems, nItems );
|
|
|
|
ImplUpdate();
|
|
}
|
|
|
|
void SplitWindow::SetItemSize( sal_uInt16 nId, long nNewSize )
|
|
{
|
|
sal_uInt16 nPos;
|
|
ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
|
|
ImplSplitItem* pItem;
|
|
|
|
if ( !pSet )
|
|
return;
|
|
|
|
// check if size is changed
|
|
pItem = &pSet->mvItems[nPos];
|
|
if ( pItem->mnSize != nNewSize )
|
|
{
|
|
// set new size and re-calculate
|
|
pItem->mnSize = nNewSize;
|
|
pSet->mbCalcPix = true;
|
|
ImplUpdate();
|
|
}
|
|
}
|
|
|
|
long SplitWindow::GetItemSize( sal_uInt16 nId ) const
|
|
{
|
|
sal_uInt16 nPos;
|
|
ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
|
|
|
|
if ( pSet )
|
|
return pSet->mvItems[nPos].mnSize;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
long SplitWindow::GetItemSize( sal_uInt16 nId, SplitWindowItemFlags nBits ) const
|
|
{
|
|
sal_uInt16 nPos;
|
|
ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
|
|
|
|
if ( pSet )
|
|
{
|
|
if ( nBits == pSet->mvItems[nPos].mnBits )
|
|
return pSet->mvItems[nPos].mnSize;
|
|
else
|
|
{
|
|
const_cast<SplitWindow*>(this)->ImplCalcLayout();
|
|
|
|
long nRelSize = 0;
|
|
long nPerSize = 0;
|
|
size_t nItems;
|
|
SplitWindowItemFlags nTempBits;
|
|
nItems = pSet->mvItems.size();
|
|
std::vector< ImplSplitItem >& rItems = pSet->mvItems;
|
|
for ( size_t i = 0; i < nItems; i++ )
|
|
{
|
|
if ( i == nPos )
|
|
nTempBits = nBits;
|
|
else
|
|
nTempBits = rItems[i].mnBits;
|
|
if ( nTempBits & SplitWindowItemFlags::RelativeSize )
|
|
nRelSize += rItems[i].mnPixSize;
|
|
else if ( nTempBits & SplitWindowItemFlags::PercentSize )
|
|
nPerSize += rItems[i].mnPixSize;
|
|
}
|
|
nPerSize += nRelSize;
|
|
if ( nBits & SplitWindowItemFlags::RelativeSize )
|
|
{
|
|
if ( nRelSize )
|
|
return (rItems[nPos].mnPixSize+(nRelSize/2))/nRelSize;
|
|
else
|
|
return 1;
|
|
}
|
|
else if ( nBits & SplitWindowItemFlags::PercentSize )
|
|
{
|
|
if ( nPerSize )
|
|
return (rItems[nPos].mnPixSize*100)/nPerSize;
|
|
else
|
|
return 1;
|
|
}
|
|
else
|
|
return rItems[nPos].mnPixSize;
|
|
}
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
void SplitWindow::SetItemSizeRange (sal_uInt16 nId, const Range& rRange)
|
|
{
|
|
sal_uInt16 nPos;
|
|
ImplSplitSet* pSet = ImplFindItem(mpBaseSet, nId, nPos);
|
|
|
|
if (pSet != nullptr)
|
|
{
|
|
pSet->mvItems[nPos].mnMinSize = rRange.Min();
|
|
pSet->mvItems[nPos].mnMaxSize = rRange.Max();
|
|
}
|
|
}
|
|
|
|
sal_uInt16 SplitWindow::GetSet( sal_uInt16 nId ) const
|
|
{
|
|
sal_uInt16 nPos;
|
|
ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
|
|
|
|
if ( pSet )
|
|
return pSet->mnId;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
bool SplitWindow::IsItemValid( sal_uInt16 nId ) const
|
|
{
|
|
sal_uInt16 nPos;
|
|
ImplSplitSet* pSet = mpBaseSet ? ImplFindItem(mpBaseSet, nId, nPos) : nullptr;
|
|
|
|
return pSet != nullptr;
|
|
}
|
|
|
|
sal_uInt16 SplitWindow::GetItemId( vcl::Window* pWindow ) const
|
|
{
|
|
return ImplFindItem( mpBaseSet, pWindow );
|
|
}
|
|
|
|
sal_uInt16 SplitWindow::GetItemId( const Point& rPos ) const
|
|
{
|
|
return ImplFindItem( mpBaseSet, rPos, mbHorz, !mbBottomRight );
|
|
}
|
|
|
|
sal_uInt16 SplitWindow::GetItemPos( sal_uInt16 nId, sal_uInt16 nSetId ) const
|
|
{
|
|
ImplSplitSet* pSet = ImplFindSet( mpBaseSet, nSetId );
|
|
sal_uInt16 nPos = SPLITWINDOW_ITEM_NOTFOUND;
|
|
|
|
if ( pSet )
|
|
{
|
|
for ( size_t i = 0; i < pSet->mvItems.size(); i++ )
|
|
{
|
|
if ( pSet->mvItems[i].mnId == nId )
|
|
{
|
|
nPos = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return nPos;
|
|
}
|
|
|
|
sal_uInt16 SplitWindow::GetItemId( sal_uInt16 nPos ) const
|
|
{
|
|
ImplSplitSet* pSet = ImplFindSet( mpBaseSet, 0/*nSetId*/ );
|
|
if ( pSet && (nPos < pSet->mvItems.size()) )
|
|
return pSet->mvItems[nPos].mnId;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
sal_uInt16 SplitWindow::GetItemCount( sal_uInt16 nSetId ) const
|
|
{
|
|
ImplSplitSet* pSet = ImplFindSet( mpBaseSet, nSetId );
|
|
if ( pSet )
|
|
return pSet->mvItems.size();
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
void SplitWindow::ImplNewAlign()
|
|
{
|
|
switch ( meAlign )
|
|
{
|
|
case WindowAlign::Top:
|
|
mbHorz = true;
|
|
mbBottomRight = false;
|
|
break;
|
|
case WindowAlign::Bottom:
|
|
mbHorz = true;
|
|
mbBottomRight = true;
|
|
break;
|
|
case WindowAlign::Left:
|
|
mbHorz = false;
|
|
mbBottomRight = false;
|
|
break;
|
|
case WindowAlign::Right:
|
|
mbHorz = false;
|
|
mbBottomRight = true;
|
|
break;
|
|
}
|
|
|
|
if ( mnWinStyle & WB_BORDER )
|
|
{
|
|
ImplCalcBorder( meAlign, mnLeftBorder, mnTopBorder,
|
|
mnRightBorder, mnBottomBorder );
|
|
}
|
|
|
|
if ( IsReallyVisible() && IsUpdateMode() )
|
|
Invalidate();
|
|
ImplUpdate();
|
|
}
|
|
|
|
void SplitWindow::SetAlign( WindowAlign eNewAlign )
|
|
{
|
|
if ( meAlign != eNewAlign )
|
|
{
|
|
meAlign = eNewAlign;
|
|
ImplNewAlign();
|
|
}
|
|
}
|
|
|
|
void SplitWindow::ShowFadeInHideButton()
|
|
{
|
|
mbFadeIn = true;
|
|
ImplUpdate();
|
|
}
|
|
|
|
void SplitWindow::ShowFadeOutButton()
|
|
{
|
|
mbFadeOut = true;
|
|
ImplUpdate();
|
|
}
|
|
|
|
long SplitWindow::GetFadeInSize() const
|
|
{
|
|
long n = 0;
|
|
|
|
if ( mbHorz )
|
|
n = mnTopBorder+mnBottomBorder;
|
|
else
|
|
n = mnLeftBorder+mnRightBorder;
|
|
|
|
return n+SPLITWIN_SPLITSIZE+SPLITWIN_SPLITSIZEEX-2;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|