/* -*- 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 .
*/
// called by Window when resized void Layout::Resize()
{ if (IsVisible())
ArrangeWindows();
}
// ArrangeWindows() -- arranges the child windows void Layout::ArrangeWindows ()
{ // prevent recursion via OnFirstSize() -> Add() -> ArrangeWindows() staticbool bInArrangeWindows = false; if (bInArrangeWindows) return;
bInArrangeWindows = true;
Size const aSize = GetOutputSizePixel();
tools::Longconst nWidth = aSize.Width(), nHeight = aSize.Height(); if (nWidth && nHeight) // non-empty size
{ // On first call the derived classes initializes the sizes of the // docking windows. This cannot be done at construction because // the Layout has empty size at that point. if (bFirstSize)
{
bFirstSize = false;
OnFirstSize(nWidth, nHeight); // virtual
}
// Remove() -- removes a window from the side (if contains) void Layout::SplittedSide::Remove (DockingWindow* pWin)
{ // contains?
std::vector<Item>::size_type iWin; for (iWin = 0; iWin != vItems.size(); ++iWin) if (vItems[iWin].pWin == pWin) break; if (iWin == vItems.size()) return; // remove
vItems[iWin].pSplit.disposeAndClear();
vItems[iWin].pWin.reset();
vItems.erase(vItems.begin() + iWin); // if that was the first one, remove the first splitter line if (iWin == 0 && !vItems.empty())
vItems.front().pSplit.reset();
}
// creating a Point or a Size object // The coordinate order depends on bVertical (reversed if true). inline Size Layout::SplittedSide::MakeSize (tools::Long A, tools::Long B) const
{ return bVertical ? Size(B, A) : Size(A, B);
} inline Point Layout::SplittedSide::MakePoint (tools::Long A, tools::Long B) const
{ return bVertical ? Point(B, A) : Point(A, B);
}
// IsDocking() -- is this window currently docking in the strip? bool Layout::SplittedSide::IsDocking (DockingWindow const& rWin)
{ return rWin.IsVisible() && !rWin.IsFloatingMode();
}
// IsEmpty() -- are there no windows docked in this strip? bool Layout::SplittedSide::IsEmpty () const
{ for (autoconst & i: vItems) if (IsDocking(*i.pWin)) returnfalse; returntrue;
}
// GetSize() -- returns the width or height of the strip (depending on the direction)
tools::Long Layout::SplittedSide::GetSize () const
{ return IsEmpty() ? 0 : nSize;
}
// Arrange() -- arranges the docking windows // rRect: the available space void Layout::SplittedSide::ArrangeIn (tools::Rectangle const& rRect)
{ // saving the rectangle
aRect = rRect;
// the length of the side
tools::Longconst nLength = bVertical ? aRect.GetSize().Height() : aRect.GetSize().Width();
tools::Longconst nOtherSize = bVertical ? aRect.GetSize().Width() : aRect.GetSize().Height(); // bVertical ? horizontal position : vertical position
tools::Longconst nPos1 = (bVertical ? aRect.Left() : aRect.Top()) +
(bLower ? 0 : nOtherSize - (nSize - nSplitThickness)); // bVertical ? vertical position : horizontal position
tools::Longconst nPos2 = bVertical ? aRect.Top() : aRect.Left();
// main line boolconst bEmpty = IsEmpty(); // shown if any of the windows is docked if (!bEmpty)
{
aSplitter->Show(); // split position
aSplitter->SetSplitPosPixel((bLower ? nSize : nPos1) - nSplitThickness); // the actual position and size
aSplitter->SetPosSizePixel(
MakePoint(nPos2, aSplitter->GetSplitPosPixel()),
MakeSize(nLength, nSplitThickness)
); // dragging rectangle
aSplitter->SetDragRectPixel(aRect);
} else
aSplitter->Hide();
// positioning separator lines and windows bool bPrevDocking = false; // is the previous window docked?
tools::Long nStartPos = 0; // window position in the strip
std::vector<Item>::size_type iLastWin = vItems.size(); // index of last docking window in the strip
for (std::vector<Item>::size_type i = 0; i != vItems.size(); ++i)
{ // window
DockingWindow& rWin = *vItems[i].pWin; boolconst bDocking = IsDocking(rWin); if (bDocking)
iLastWin = i; // sizing window
rWin.ResizeIfDocking(
MakePoint(nPos2 + nStartPos, nPos1),
MakeSize(vItems[i].nEndPos - nStartPos, nSize - nSplitThickness)
); // splitting line before the window if (i > 0)
{
Splitter& rSplit = *vItems[i].pSplit; // If neither of two adjacent windows are docked, // the splitting line is hidden. // If this window is docking but the previous isn't, // then the splitting line is also hidden, because this window // will occupy the space of the previous. if (bPrevDocking)
{
rSplit.Show(); // the actual position and size of the line
rSplit.SetPosSizePixel(
MakePoint(nPos2 + nStartPos - nSplitThickness, nPos1),
MakeSize(nSplitThickness, nSize - nSplitThickness)
); // the dragging rectangle
rSplit.SetDragRectPixel(tools::Rectangle(
MakePoint(nPos2, nPos1),
MakeSize(nLength, nSize - nSplitThickness)
));
} else
rSplit.Hide();
} // next
bPrevDocking = bDocking; if (bDocking)
nStartPos = vItems[i].nEndPos + nSplitThickness; // We only set nStartPos if this window is docking, because otherwise // the next window will occupy also the space of this window.
}
// filling the remaining space with the last docking window if (bEmpty || vItems[iLastWin].nEndPos == nLength) return;
Item& rItem = vItems[iLastWin];
Size aSize = rItem.pWin->GetDockingSize(); if (bVertical)
aSize.AdjustHeight( nLength - rItem.nEndPos ); else
aSize.AdjustWidth( nLength - rItem.nEndPos );
rItem.pWin->ResizeIfDocking(aSize); // and hiding the split line after the window if (iLastWin + 1 < vItems.size())
vItems[iLastWin + 1].pSplit->Hide();
}
IMPL_LINK(Layout::SplittedSide, SplitHdl, Splitter*, pSplitter, void)
{ // checking margins
CheckMarginsFor(pSplitter); // changing stored sizes if (pSplitter == aSplitter.get())
{ // nSize if (bLower)
nSize = pSplitter->GetSplitPosPixel(); else
nSize = (bVertical ? aRect.Right() : aRect.Bottom()) + 1 - pSplitter->GetSplitPosPixel();
} else
{ // Item::nStartPos, Item::nLength for (size_t i = 1; i < vItems.size(); ++i)
{ if (vItems[i].pSplit.get() == pSplitter)
{ // before the line
vItems[i - 1].nEndPos = pSplitter->GetSplitPosPixel(); // after the line
vItems[i].nStartPos = pSplitter->GetSplitPosPixel() + nSplitThickness;
}
}
} // arranging windows
rLayout.ArrangeWindows();
}
void Layout::SplittedSide::CheckMarginsFor (Splitter* pSplitter)
{ // The splitter line cannot be closer to the edges than nMargin pixels. static tools::Longconst nMargin = 16; // Checking margins:
tools::Longconst nLength = pSplitter->IsHorizontal() ?
aRect.GetWidth() : aRect.GetHeight(); if (!nLength) return;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.