📄 etslayout.cpp
字号:
CPaneBase pItem = m_paneItems[i];
if( m_Orientation == HORIZONTAL ) {
// for absolute items subtract their size from available space
if(pItem->modeResize() & ABSOLUTE_HORZ) {
availSpace -= (sizePrimary[i] = pItem->getConstrainHorz(0));
}
// count Greedy items for later
if(!(pItem->modeResize() & ABSOLUTE_HORZ) && !(pItem->modeResize() & RELATIVE_HORZ)) {
nGreedy++;
}
sizeMin[i] = pItem->getMinConstrainHorz();
sizeMax[i] = pItem->getMaxConstrainHorz();
}
else {
// for absolute items subtract their size from available space
if(pItem->modeResize() & ABSOLUTE_VERT) {
availSpace -= (sizePrimary[i] = pItem->getConstrainVert(0));
}
// count Greedy items for later
if(!(pItem->modeResize() & ABSOLUTE_VERT) && !(pItem->modeResize() & RELATIVE_VERT)) {
nGreedy++;
}
sizeMin[i] = pItem->getMinConstrainVert();
sizeMax[i] = pItem->getMaxConstrainVert();
}
}
// Must not be negative !!
availSpace = max(availSpace, 0);
return nGreedy;
}
bool ETSLayoutMgr::Pane::resizeToRelative(int& availSpace, CArray<int,int>& sizePrimary,
CArray<int,int>& sizeMin, CArray<int,int>& sizeMax)
{
// Then all relative items as percentage of left space (as of now after
// all absolute items are subtracted
int availRel = availSpace; // At the beginning all of remaining space is available. We want all
// operation to be relative to the left space at this moment, so we
// save this amount here. Then we safly can lower availSpace
int relDiff = 0; // The cumulated difference between first proposed size and
// eventual maximum/minimum size. This amount has to be
// saved in some other place (i.e. where relativ items/subpane
// are not limited by min/max
int relLeft = 0; // The cumulated amout of space that can be saved by
// shrinking the items/panes up to the minimum
int relCount = 0; // Actually allocated item/subpane's cumulated primary sizes
// of non-limited items/subpanes (these can be modified in fixup)
// needed for equally distribution of differences amoung non-limited
// relative items/subpanes
for(int i=0; i<m_paneItems.GetSize(); ++i) {
CPaneBase pItem = m_paneItems[i];
// For all relative items in primary direction
if( (m_Orientation==HORIZONTAL && pItem->modeResize() & RELATIVE_HORZ)
||
(m_Orientation==VERTICAL && pItem->modeResize() & RELATIVE_VERT) )
{
// minimum item/subpane size in primary direction (pixels)
int nSizeRelMin = sizeMin[i];
// maximum item/subpane size in primary direction (pixels)
int nSizeRelMax = sizeMax[i];
// Relative size in primary direction (pixels)
int nSizeRel = (m_Orientation==HORIZONTAL)
?
(pItem->getConstrainHorz(availRel))
:
(pItem->getConstrainVert(availRel));
if( nSizeRel < nSizeRelMin) {
// The item/pane is shrinked too small!
// We will grow it to it's minimum-size. In order not to modify
// this item later when fixing up set the size to the negative
// minimum size
sizePrimary[i] = -nSizeRelMin;
// As we grew one item/subpane we have to shrink another one.
// We keep count on how much space we needed to grow the item
// to it's minimum size
relDiff += ( nSizeRelMin - nSizeRel );
}
else if( nSizeRelMax != -1 && nSizeRel > nSizeRelMax) {
// if there's a maximum size (nSizeRelMax != -1) and our item/subpane
// is to be resized over that amount correct it. In order not to modify
// this item later when fixing up set the size to the negative
// maximum size
sizePrimary[i] = -nSizeRelMax;
// As we shrinked one item/subpane we have to grow another one.
// We keep count on how much space we needed to grow the item
// to it's maximum size.
relDiff += ( nSizeRelMax - nSizeRel );
}
else {
// this is the normal case: neither are we minimum limited nor maximum
// limited
// As this item/subpane is larger that it's minimum we could later (if
// necessary for fixup) shrink it for the difference amount of pixels
relLeft += ( nSizeRel - nSizeRelMin );
// Set the primary size of this item/pane. Can later be modified by fixup
sizePrimary[i] = nSizeRel;
// Add this item/subpane's primary size to the count of already allocated
// cumulated size of non-limited items/subpanes (these can be modified in fixup)
relCount += nSizeRel;
}
// decrease available space by used space in this step
availSpace -= nSizeRel;
}
}
// We now have the situation that some items/subpanes had to be adjusted for cumulated
// relDiff pixels (positive value means more space taken than indicated by percentage of
// left space). On the other hand we have some items/subpanes which were not limited (in
// their current dimensions) but could be if necessary up to relLeft pixels.
if(relLeft < relDiff && availSpace >= (relDiff-relLeft) ){
// If it's not possible to shrink other (relative) panes in order to distribute the
// difference because the left for shrinking (relLeft) is too small we need to aquire
// more space from the globally left space (if available at all)
availSpace -= (relDiff-relLeft);
relDiff = relLeft;
}
// At this point we should have some space left (at least not be negative with the leftover
// space) and on the other hand there's enough space for the limit-difference to be distributed
ASSERT( availSpace >= 0 && relLeft >= relDiff);
// Fixup Relative:
// Distribute (if anecessary) relDiff on other (not limited) relative items/subpanes
// (if available - if not later just grow the limited panes)
while( relDiff != 0 && relCount >= 0 ) {
// in every iteration there must be some space distributed (of the difference) or it could
// come to endless looping. Save the amount of space actually distributed in this iteration
int relDist = 0;
for(i=0; i<m_paneItems.GetSize(); ++i) {
CPaneBase pItem = m_paneItems[i];
// For all relative items in primary direction which were NOT limited
if( (m_Orientation==HORIZONTAL && (pItem->modeResize() & RELATIVE_HORZ) && sizePrimary[i] > 0)
||
(m_Orientation==VERTICAL && (pItem->modeResize() & RELATIVE_VERT) && sizePrimary[i] > 0) )
{
// keep a flag for termination of this iteration
bool bLast = false;
// the difference should be distributed amoung all non-limited items/subpanes equally.
// nDiff is the amount for the current item/subpane
int nDiff = (relDiff * sizePrimary[i]) / relCount;
// if it's a too small value just add it to the current pane and break iteration
if( abs(relDiff) <= FIXUP_CUTOFF ) {
// take it all in this step
nDiff = relDiff;
// set break flag
bLast = true;
}
// calculate the new size for the current item/subpane
int nNewSize = sizePrimary[i] - nDiff;
if( nNewSize < sizeMin[i] ) {
// oh, we are limited here. Revise our plan:
// Not all of the space could be saved, add the actually possible space
// to the sum
relDist += ( sizePrimary[i] - sizeMin[i] );
// set it to the minimum possible size
sizePrimary[i] = -sizeMin[i];
// as this item/subpane is now limited it's occupied space doesn't count
// for relCount anymore
relCount-= ( sizePrimary[i] );
}
else {
// account the difference of the sizes in relDist and set new size
relDist += ( sizePrimary[i] - nNewSize );
sizePrimary[i] = nNewSize;
// if it's the last one break now
if(bLast)
break;
}
}
}
// Distributed some relDiff-space in every iteration
ASSERT(relDist != 0);
relDiff -= relDist;
}
// Fixup Relative: invert all negative (limited) sized to correct value
for(i=0; i<m_paneItems.GetSize(); ++i) {
CPaneBase pItem = m_paneItems[i];
if( (m_Orientation==HORIZONTAL && (pItem->modeResize() & RELATIVE_HORZ) && sizePrimary[i] < 0)
||
(m_Orientation==VERTICAL && (pItem->modeResize() & RELATIVE_VERT) && sizePrimary[i] < 0) )
{
sizePrimary[i] *= -1;
}
}
return true;
}
bool ETSLayoutMgr::Pane::resizeToGreedy(int& availSpace, int nGreedy, CArray<int,int>& sizePrimary,
CArray<int,int>& sizeMin, CArray<int,int>& sizeMax)
{
// Now resize all Greedy items/subpanes equally among the remaining space
int greedyDiff = 0; // The cumulated difference between first proposed size and
// eventual maximum/minimum size. This amount has to be
// saved in some other place (i.e. where items/subpane
// are not limited by min/max
int greedyLeft = 0; // The cumulated amount of space that can be saved by
// shrinking the items/panes up to the minimum
int greedyCount = 0; // Actually allocated item/subpane's cumulated primary sizes
// of non-limited items/subpanes (these can be modified in fixup)
// needed for equally distribution of differences amoung non-limited
// items/subpanes
for(int i=0; i<m_paneItems.GetSize(); ++i) {
CPaneBase pItem = m_paneItems[i];
if( (m_Orientation==HORIZONTAL
&& !(pItem->modeResize()&ABSOLUTE_HORZ)
&& !(pItem->modeResize()&RELATIVE_HORZ)
)
||
(m_Orientation==VERTICAL
&& !(pItem->modeResize()&ABSOLUTE_VERT)
&& !(pItem->modeResize()&RELATIVE_VERT)
)
)
{
// All greedy items get an equal portion of the left space
int nSize = availSpace / nGreedy;
// minimum item/subpane size in primary direction (pixels)
int nSizeMin = sizeMin[i];
// maximum item/subpane size in primary direction (pixels)
int nSizeMax = sizeMax[i];
// the last gets the all of the remaining space
if( nGreedy == 1 )
nSize = availSpace;
if( nSize < nSizeMin) {
// The item/pane is shrinked too small!
// We will grow it to it's minimum-size. In order not to modify
// this item later when fixing up set the size to the negative
// minimum size
sizePrimary[i] = -nSizeMin;
// As we grew one item/subpane we have to shrink another one.
// We keep count on how much space we needed to grow the item
// to it's minimum size
greedyDiff += ( nSizeMin - nSize );
}
else if( nSizeMax != -1 && nSize > nSizeMax) {
// if there's a maximum size (nSizeRelMax != -1) and our item/subpane
// is to be resized over that amount correct it. In order not to modify
// this item later when fixing up set the size to the negative
// maximum size
sizePrimary[i] = -nSizeMax;
// As we shrinked one item/subpane we have to grow another one.
// We keep count on how much space we needed to grow the item
// to it's maximum size.
greedyDiff += ( nSizeMax - nSize );
}
else {
// this is the normal case: neither are we minimum limited nor maximum
// limited
// As this item/subpane is larger that it's minimum we could later (if
// necessary for fixup) shrink it for the difference amount of pixels
greedyLeft += ( nSize - nSizeMin );
// Set the primary size of this item/pane. Can later be modified by fixup
sizePrimary[i] = nSize;
// Add this item/subpane's primary size to the count of already allocated
// cumulated size of non-limited items/subpanes (these can be modified in fixup)
greedyCount += nSize;
}
// decrease available space by used space in this step
availSpace -= nSize;
// one greedy item/subpane complete
--nGreedy;
}
}
// Fixup Greedy I
// Distribute (if anecessary) greedyDiff on other (not limited) greedy items/subpanes
// (if available - if not later just grow the limited panes)
// at least on not limited item present
bool bAtLeastOne = true;
while( bAtLeastOne && greedyDiff != 0 && greedyCount > 0) {
// in every iteration there must be some space distributed (of the difference) or it could
// come to endless looping. Save the amount of space actually distributed in this iteration
int greedyDist = 0;
// at least on not limited item present
bAtLeastOne = false;
for(i=0; i<m_paneItems.GetSize(); ++i) {
CPaneBase pItem = m_paneItems[i];
if( (m_Orientation==HORIZONTAL
&& !(pItem->modeResize()&ABSOLUTE_HORZ)
&& !(pItem->modeResize()&RELATIVE_HORZ)
&& sizePrimary[i] > 0
)
||
(m_Orientation==VERTICAL
&& !(pItem->modeResize()&ABSOLUTE_VERT)
&& !(pItem->modeResize()&RELATIVE_VERT)
&& sizePrimary[i] > 0
)
)
{
// keep a flag for termination of this iteration
bool bLast = false;
// the difference should be distributed amoung all non-limited items/subpanes equally.
// nDiff is the amount for the current item/subpane
int nDiff = (greedyDiff * sizePrimary[i]) / greedyCount;
// if it's a too small value just add it to the current pane and break iteration
if( abs(greedyDiff) <= FIXUP_CUTOFF || nDiff == 0) {
// take it all in this step
nDiff = greedyDiff;
// set break flag
bLast = true;
}
// calculate the new size for the current item/subpane
int nNewSize = sizePrimary[i] - nDiff;
if( nNewSize < sizeMin[i] ) {
// oh, we are limited here. Revise our plan:
if( sizePrimary[i] != sizeMin[i] )
bAtLeastOne = true;
// Not all of the space could be saved, add the actually possible space
// to the sum
greedyDist += ( sizePrimary[i] - sizeMin[i] );
// set it to the minimum possible size
sizePrimary[i] = sizeMin[i];
// as this item/subpane is now limited it's occupied space doesn't count
// for relCount anymore
greedyCount -= ( sizePrimary[i] );
}
else {
// yes, there is one
bAtLeastOne = true;
// account the difference of the sizes in relDist and set new size
greedyDist += ( sizePrimary[i] - nNewSize );
sizePrimary[i] = nNewSize;
// if it's the last one break now
if(bLast)
break;
}
}
}
// Distributed some greedyDiff-space in every iteration
ASSERT(!bAtLeastOne || greedyDist != 0 || greedyCount<=0);
greedyDiff -= greedyDist;
}
// Fixup Greedy II
if( greedyDiff < 0 ) {
// still difference, some space left
// are there any items which are minimum-limited where we can give more space?
for(i=0; i<m_paneItems.GetSize() && greedyDiff!=0; ++i) {
CPaneBase pItem = m_paneItems[i];
if( (m_Orientation==HORIZONTAL
&& !(pItem->modeResize()&ABSOLUTE_HORZ)
&& !(pItem->modeResize()&RELATIVE_HORZ)
)
||
(m_Orientation==VERTICAL
&& !(pItem->modeResize()&ABSOLUTE_VERT)
&& !(pItem->modeResize()&RELATIVE_VERT)
)
)
{
if( sizePrimary[i] == -sizeMin[i] ) {
// fill this one up as much as possible
if( sizeMax[i] == -1) {
// all fits in
sizePrimary[i] += greedyDiff;
greedyDiff = 0;
}
else {
sizePrimary[i] += -min( -greedyDiff, sizeMax[i]-sizeMin[i]);
greedyDiff -= -min( -greedyDiff, sizeMax[i]-sizeMin[i]);
}
}
}
}
}
// Fixup Greedy III: invert all negative (limited) sized to correct value
for(i=0; i<m_paneItems.GetSize(); ++i) {
CPaneBase pItem = m_paneItems[i];
if( (m_Orientation==HORIZONTAL
&& !(pItem->modeResize() & ABSOLUTE_HORZ)
&& !(pItem->modeResize() & RELATIVE_HORZ)
&& sizePrimary[i] < 0
)
||
(m_Orientation==VERTICAL
&& !(pItem->modeResize() & ABSOLUTE_VERT)
&& !(pItem->modeResize() & RELATIVE_VERT)
&& sizePrimary[i] < 0
)
)
{
if(sizePrimary[i] < 0)
sizePrimary[i] *= -1;
}
}
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -