2025-11-28 00:35:46 +09:00

253 lines
5.6 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
#include "stdafx.h"
#include "dock.h"
#include <assert.h>
CDock::CArea::CArea(AREA_MOVE_TYPE Type)
{
ZeroMemory(this, sizeof(CArea));
m_MoveType = Type;
}
CDock::CDock()
: m_StockLeft(MOVE_NO)
, m_StockRight(MOVE_NO)
, m_StockTop(MOVE_NO)
, m_StockBottom(MOVE_NO)
{
}
CDock::~CDock()
{
RemoveAllAreas();
}
DWORD CDock::GetAreaCount()
{
return (DWORD) m_Areas.GetCount();
}
CDock::CArea* CDock::GetArea(DWORD n)
{
if(n >= m_Areas.GetCount())
{
return NULL;
}
return m_Areas.GetAt(n);
}
CDock::CArea* CDock::AddArea(AREA_MOVE_TYPE Type)
{
CArea* pArea;
pArea = new CArea(Type);
if(NULL != pArea)
{
m_Areas.Add(pArea);
}
return pArea;
}
CDock::CArea* CDock::GetStockArea(STOCK_AREA AreaType)
{
switch(AreaType)
{
case STOCK_AREA_LEFT: return &m_StockLeft;
case STOCK_AREA_RIGHT: return &m_StockRight;
case STOCK_AREA_TOP: return &m_StockTop;
case STOCK_AREA_BOTTOM: return &m_StockBottom;
}
return NULL;
}
void CDock::RemoveAllAreas()
{
DWORD n;
CArea* pArea;
for(n = 0; n < m_Areas.GetCount(); n++)
{
pArea = m_Areas.GetAt(n);
delete pArea;
}
m_Areas.RemoveAll();
}
void CDock::UpdateDock()
{
RECT rect;
GetClientRect(&rect);
ResizeDock(rect.right - rect.top, rect.bottom - rect.top);
}
void CDock::MoveSplitter(CWindow* pSplitter, LONG x, LONG y)
{
// Find the splitter area and move it to the new position
for(size_t i = 0; i < m_Areas.GetCount(); i++)
{
CArea* pArea = m_Areas.GetAt(i);
if(pArea->m_pWindow == pSplitter)
{
if(pArea->m_MoveType == MOVE_HOR)
{
LONG newY = pArea->m_rc.top + y;
pArea->m_posFixed.top = double(newY) / m_nHeight;
}
else
{
LONG newX = pArea->m_rc.left + x;
pArea->m_posFixed.left = double(newX) / m_nWidth;
}
}
}
UpdateDock();
}
void CDock::ResizeDock(long nWidth, long nHeight)
{
DWORD n;
CArea * pArea;
DWORD nCurIter;
m_nHeight = nHeight;
m_nWidth = nWidth;
// cleanup resize iteration
// update fixed position
for(n = 0; n < m_Areas.GetCount(); n++)
{
pArea = m_Areas.GetAt(n);
pArea->m_nResizeIter = 1;
if(pArea->m_posFixed.left != 0.0)
{
pArea->m_rc.left = LONG(m_nWidth * pArea->m_posFixed.left);
pArea->m_rc.right = LONG(pArea->m_rc.left + pArea->m_posFixed.width);
}
if(pArea->m_posFixed.top != 0.0)
{
pArea->m_rc.top = LONG(m_nHeight * pArea->m_posFixed.top);
pArea->m_rc.bottom = LONG(pArea->m_rc.top + pArea->m_posFixed.height);
}
}
// resize stock panes
m_StockLeft.m_rc.bottom = nHeight;
m_StockRight.m_rc.left = m_StockRight.m_rc.right = nWidth;
m_StockRight.m_rc.bottom = nHeight;
m_StockTop.m_rc.right = nWidth;
m_StockBottom.m_rc.right = nWidth;
m_StockBottom.m_rc.bottom = m_StockBottom.m_rc.top = nHeight;
// run through all panes and resize
for(nCurIter = 0; nCurIter < 100; nCurIter++)
{
for(n = 0; n < m_Areas.GetCount(); n++)
{
pArea = m_Areas.GetAt(n);
if(pArea->m_nResizeIter >= nCurIter)
{
// we can resize if we already resized all attached
if(CanResize(pArea))
{
ResizePane(pArea);
}
else
{
pArea->m_nResizeIter = nCurIter+1;
}
}
}
}
// update position for all windows
for(n = 0; n < m_Areas.GetCount(); n++)
{
pArea = m_Areas.GetAt(n);
if(pArea->m_pWindow)
{
pArea->m_pWindow->SetWindowPos(HWND_BOTTOM, &(pArea->m_rc), SWP_NOZORDER);
}
}
}
void CDock::ResizePane(CDock::CArea* pArea)
{
if(pArea->m_Attach.pLeft)
{
pArea->m_rc.left = pArea->m_Attach.pLeft->m_rc.right;
}
if(pArea->m_Attach.pRight)
{
pArea->m_rc.right = pArea->m_Attach.pRight->m_rc.left;
}
if(pArea->m_Attach.pTop)
{
pArea->m_rc.top = pArea->m_Attach.pTop->m_rc.bottom;
}
if(pArea->m_Attach.pBottom)
{
pArea->m_rc.bottom = pArea->m_Attach.pBottom->m_rc.top;
}
}
BOOL CDock::CanResize(CDock::CArea* pArea)
{
if(pArea->m_Attach.pLeft && pArea->m_Attach.pLeft->m_nResizeIter >= pArea->m_nResizeIter)
{
return FALSE;
}
if(pArea->m_Attach.pRight && pArea->m_Attach.pRight->m_nResizeIter >= pArea->m_nResizeIter)
{
return FALSE;
}
if(pArea->m_Attach.pTop && pArea->m_Attach.pTop->m_nResizeIter >= pArea->m_nResizeIter)
{
return FALSE;
}
if(pArea->m_Attach.pBottom && pArea->m_Attach.pBottom->m_nResizeIter >= pArea->m_nResizeIter)
{
return FALSE;
}
return TRUE;
}
LRESULT CDock::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
bHandled = TRUE;
return 0;
}
LRESULT CDock::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
ResizeDock(LOWORD(lParam), HIWORD(lParam));
bHandled = TRUE;
return 0;
}