372 lines
9.3 KiB
C++
372 lines
9.3 KiB
C++
// ==========================================================================
|
|
// Class Implementation : COXDockTabCtrl
|
|
// ==========================================================================
|
|
|
|
// Source file : OXDockTabCtrl.cpp
|
|
|
|
// Version: 9.3
|
|
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "OXDockTabCtrl.h"
|
|
#include "OXCoolToolBar.h"
|
|
#include "OXSizeCtrlBar.h"
|
|
#include "OXSizeDockBar.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COXDockTabCtrl
|
|
|
|
COXDockTabCtrl::COXDockTabCtrl(COXSizeDockBar* pSizeDockBar)
|
|
{
|
|
m_pSizeDockBar = pSizeDockBar;
|
|
m_pLastSelectedBar = NULL;
|
|
}
|
|
|
|
COXDockTabCtrl::~COXDockTabCtrl()
|
|
{
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(COXDockTabCtrl, COXSkinnedTabCtrl)
|
|
//{{AFX_MSG_MAP(COXDockTabCtrl)
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_NOTIFY_REFLECT(TCN_SELCHANGE, OnSelChange)
|
|
ON_WM_CREATE()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
void COXDockTabCtrl::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
m_ptLButtonDown = point;
|
|
COXSkinnedTabCtrl::OnLButtonDown(nFlags, point);
|
|
}
|
|
|
|
void COXDockTabCtrl::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
// In order to start dragging the left button must be down and the current point
|
|
// must be at least 3 pixels away from the point where the button was pressed
|
|
if ((nFlags & MK_LBUTTON) &&
|
|
(abs(point.x - m_ptLButtonDown.x) > 3 || abs(point.y - m_ptLButtonDown.y) > 3))
|
|
{
|
|
TCHITTESTINFO thti;
|
|
thti.pt = point;
|
|
int iIndex = HitTest(&thti);
|
|
|
|
if (iIndex != -1)
|
|
{
|
|
CControlBar* pBar = GetBar(iIndex);
|
|
|
|
// Handle COXCoolToolBar
|
|
COXCoolToolBar* pToolBar = DYNAMIC_DOWNCAST(COXCoolToolBar, pBar);
|
|
if (pToolBar)
|
|
{
|
|
// We have a toolbar
|
|
pToolBar->SaveMouseOffset(CPoint(0, 0));
|
|
pToolBar->SetCapture();
|
|
pToolBar->m_bDragging = true;
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEALL));
|
|
return;
|
|
}
|
|
|
|
// Handle COXSizeControlBar
|
|
COXSizeControlBar* pControlBar = DYNAMIC_DOWNCAST(COXSizeControlBar, pBar);
|
|
if (pControlBar)
|
|
{
|
|
// We have a docking window
|
|
pControlBar->SaveMouseOffset(CPoint(0, 0));
|
|
pControlBar->SetCapture();
|
|
pControlBar->m_bDragging = true;
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEALL));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
COXSkinnedTabCtrl::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
void COXDockTabCtrl::OnSelChange(NMHDR* /*pNMHDR*/, LRESULT* pResult)
|
|
{
|
|
// TODO: Add your control notification handler code here
|
|
|
|
ShowSelectedTab();
|
|
*pResult = 0;
|
|
}
|
|
|
|
// Inserts the given control bar as a new tab
|
|
void COXDockTabCtrl::InsertTab(CControlBar* pBar, int iIndex, BOOL bShowSelectedTab)
|
|
{
|
|
// If this is the only control bar in the dock bar do nothing
|
|
int iSizeControlBarCount = m_pSizeDockBar->GetSizeControlBarCount(pBar);
|
|
if (iSizeControlBarCount == 0)
|
|
return;
|
|
|
|
// Add a tab for all other size control bars that are docked but not tabbed
|
|
|
|
int i = 0;
|
|
for (i = 0; i < m_pSizeDockBar->m_arrBars.GetSize(); i++)
|
|
{
|
|
COXSizeControlBar* pSizeBar = DYNAMIC_DOWNCAST(COXSizeControlBar, m_pSizeDockBar->GetDockedControlBar(i));
|
|
if (pSizeBar != NULL && pSizeBar != pBar && FindTab(pSizeBar) == -1)
|
|
{
|
|
CString strTextOther;
|
|
pSizeBar->GetWindowText(strTextOther);
|
|
|
|
TCITEM tciOther;
|
|
tciOther.mask = TCIF_TEXT | TCIF_PARAM;
|
|
tciOther.pszText = strTextOther.GetBuffer(strTextOther.GetLength());
|
|
tciOther.lParam = (LPARAM) pSizeBar;
|
|
|
|
//Check added for visibility so that hidden control
|
|
//bars don't get shown - Nish - Feb 15th 2005
|
|
if(pSizeBar->IsWindowVisible())
|
|
InsertItem(0, &tciOther);
|
|
}
|
|
}
|
|
|
|
// Insert this control bar to the tab control
|
|
CString strText;
|
|
pBar->GetWindowText(strText);
|
|
|
|
TCITEM tci;
|
|
tci.mask = TCIF_TEXT | TCIF_PARAM;
|
|
tci.pszText = strText.GetBuffer(strText.GetLength());
|
|
tci.lParam = (LPARAM) pBar;
|
|
|
|
InsertItem(iIndex, &tci);
|
|
SetCurSel(iIndex);
|
|
|
|
// Reshresh the tab control
|
|
m_pSizeDockBar->PositionTabCtrl();
|
|
|
|
if (bShowSelectedTab)
|
|
ShowSelectedTab();
|
|
else
|
|
{
|
|
int iSelected = GetCurSel();
|
|
for (i = 0; i < GetItemCount(); i++)
|
|
{
|
|
CControlBar* pBar = GetBar(i);
|
|
if (iSelected != i)
|
|
pBar->GetDockingFrame()->ShowControlBar(pBar, FALSE, TRUE); // hide
|
|
}
|
|
}
|
|
}
|
|
|
|
void COXDockTabCtrl::ShowSelectedTab()
|
|
{
|
|
int iSelected = GetCurSel();
|
|
|
|
// Show first
|
|
for (int i = 0; i < GetItemCount(); i++)
|
|
{
|
|
CControlBar* pBar = GetBar(i);
|
|
if (iSelected == i)
|
|
{
|
|
pBar->GetDockingFrame()->ShowControlBar(pBar, TRUE, TRUE); // show
|
|
}
|
|
else
|
|
{
|
|
pBar->GetDockingFrame()->ShowControlBar(pBar, FALSE, TRUE); // hide
|
|
}
|
|
}
|
|
|
|
CRect rect;
|
|
m_pSizeDockBar->GetClientRect(rect);
|
|
|
|
CControlBar* pBar = GetBar(iSelected);
|
|
if (pBar != NULL)
|
|
{
|
|
COXSizeControlBar* pSizeBar = DYNAMIC_DOWNCAST(COXSizeControlBar, pBar);
|
|
if (m_pSizeDockBar->IsBarHorizontal())
|
|
{
|
|
if (m_pLastSelectedBar != NULL)
|
|
{
|
|
pSizeBar->m_HorzDockSize.cx = m_pLastSelectedBar->m_HorzDockSize.cx;
|
|
}
|
|
m_pLastSelectedBar = pSizeBar;
|
|
}
|
|
else // vertical
|
|
{
|
|
CFrameWnd* pMF = (CFrameWnd*) GetParentFrame();//AfxGetMainWnd();
|
|
if (pMF != NULL)
|
|
{
|
|
if (pMF->GetControlBar(AFX_IDW_DOCKBAR_LEFT) == m_pSizeDockBar)
|
|
rect.right -= 3;
|
|
|
|
if (pMF->GetControlBar(AFX_IDW_DOCKBAR_RIGHT) == m_pSizeDockBar)
|
|
rect.left += 4;
|
|
}
|
|
|
|
rect.bottom -= m_pSizeDockBar->GetTabHeight();
|
|
|
|
pBar->MoveWindow(rect, TRUE);
|
|
|
|
COXSizeControlBar* pSizeBar = DYNAMIC_DOWNCAST(COXSizeControlBar, pBar);
|
|
if (pSizeBar)
|
|
{
|
|
pSizeBar->m_VertDockSize.cx = rect.Width();
|
|
pSizeBar->m_VertDockSize.cy = rect.Height() + 5;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void COXDockTabCtrl::RemoveTab(CControlBar* pBar)
|
|
{
|
|
// If there are not tabs just exit
|
|
if (GetItemCount() == 0)
|
|
return;
|
|
|
|
// If there is only one other tab left we need to remove it as well
|
|
if (m_pSizeDockBar->GetSizeControlBarCount(pBar) == 1)
|
|
{
|
|
COXSizeControlBar* pOther = m_pSizeDockBar->GetFirstDockedSizeControlBar(pBar);
|
|
|
|
int iOtherIndex = FindTab(pOther);
|
|
DeleteItem(iOtherIndex);
|
|
pOther->GetDockingFrame()->ShowControlBar(pOther, TRUE, TRUE);
|
|
}
|
|
|
|
// Remove this tab
|
|
int iIndex = FindTab(pBar);
|
|
DeleteItem(iIndex);
|
|
|
|
if (GetItemCount() > 1)
|
|
{
|
|
// Set the current selection to the previous tab
|
|
if (iIndex != 0)
|
|
SetCurSel(iIndex - 1);
|
|
else
|
|
SetCurSel(0);
|
|
ShowSelectedTab();
|
|
}
|
|
}
|
|
|
|
// This function searched the tab control for the given control bar and returns its
|
|
// index or -1 if not found.
|
|
int COXDockTabCtrl::FindTab(CControlBar* pBar)
|
|
{
|
|
for (int i = 0; i < GetItemCount(); i++)
|
|
{
|
|
TCITEM tci;
|
|
tci.mask = TCIF_PARAM;
|
|
GetItem(i, &tci);
|
|
|
|
if (tci.lParam == (LPARAM) pBar)
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// If the point is over the tab control this function returns the index where
|
|
// the new tab should be inserted. If the point is not over the tab control it
|
|
// returns -1
|
|
int COXDockTabCtrl::HitTestTabControl(CPoint point, CControlBar* /*pBar*/)
|
|
{
|
|
// Deterine the rectangle of the buttons
|
|
|
|
CRect rectTabButtons;
|
|
m_pSizeDockBar->GetWindowRect(rectTabButtons);
|
|
rectTabButtons.top = rectTabButtons.bottom - 48;
|
|
|
|
if (rectTabButtons.PtInRect(point))
|
|
{
|
|
// Determine the actual button
|
|
TCHITTESTINFO thti;
|
|
ScreenToClient(&point);
|
|
thti.pt = point;
|
|
int iIndex = HitTest(&thti);
|
|
if (iIndex == -1)
|
|
return 0;
|
|
|
|
return iIndex;
|
|
}
|
|
|
|
// If there are more when 1 tabs already the test area should cover the entire dock window
|
|
// and the new tab should be inserted at the end
|
|
// int iTabCount = GetItemCount();
|
|
// if (iTabCount > 0)
|
|
// {
|
|
// CRect rectDockBar;
|
|
// m_pSizeDockBar->GetWindowRect(rectDockBar);
|
|
// rectDockBar.InflateRect(20, 20);
|
|
// if (rectDockBar.PtInRect(point))
|
|
// return iTabCount;
|
|
// }
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Moves the tab from the old position to the new position
|
|
void COXDockTabCtrl::RepositionTabs(int iOldIndex, int iNewIndex, CPoint point)
|
|
{
|
|
// To avoid flashing only reposition if the mouse cursor is behind the midpoint
|
|
// of the next or previous item
|
|
|
|
CRect rectNew;
|
|
GetItemRect(iNewIndex, rectNew);
|
|
ScreenToClient(&point);
|
|
if (iOldIndex < iNewIndex)
|
|
{
|
|
// The new tab is to the right
|
|
if (point.x < rectNew.CenterPoint().x)
|
|
return; // the mouse cursor is not far enough to the right
|
|
}
|
|
else
|
|
{
|
|
// The new tab is to the left
|
|
if (point.x > rectNew.CenterPoint().x)
|
|
return; // the mouse cursor is not far enough to the left
|
|
}
|
|
|
|
TCHAR szBuffer[256];
|
|
|
|
TCITEM tci;
|
|
tci.mask = TCIF_TEXT | TCIF_PARAM;
|
|
tci.pszText = szBuffer;
|
|
tci.cchTextMax = 256;
|
|
GetItem(iOldIndex, &tci);
|
|
|
|
DeleteItem(iOldIndex);
|
|
InsertItem(iNewIndex, &tci);
|
|
}
|
|
|
|
CControlBar* COXDockTabCtrl::GetBar(int iIndex)
|
|
{
|
|
TCITEM tci;
|
|
tci.mask = TCIF_PARAM;
|
|
GetItem(iIndex, &tci);
|
|
|
|
return (CControlBar*) tci.lParam;
|
|
}
|
|
|
|
int COXDockTabCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
if (COXSkinnedTabCtrl::OnCreate(lpCreateStruct) == -1)
|
|
return -1;
|
|
|
|
m_font.CreatePointFont(80, _T("MS Sans Serif"));
|
|
|
|
SetFont(&m_font);
|
|
|
|
SetPadding(CSize(12, 4));
|
|
|
|
return 0;
|
|
}
|