diff --git a/neo/engine/tools/radiant/CamWnd.cpp b/neo/engine/tools/radiant/CamWnd.cpp index 72c03cd3..9e4058d7 100644 --- a/neo/engine/tools/radiant/CamWnd.cpp +++ b/neo/engine/tools/radiant/CamWnd.cpp @@ -1003,7 +1003,9 @@ static const char* CAMWND_PROP_REBUILD_MODE = "QER_CamWnd_RebuildMode"; static const char* CAMWND_PROP_ENTITY_MODE = "QER_CamWnd_EntityMode"; static const char* CAMWND_PROP_FILTER_MASK = "QER_CamWnd_FilterMask"; +#define CAMWND_CAPTION_HEIGHT 30 #define CAMWND_MENU_HEIGHT 22 +#define CAMWND_TOPBAR_HEIGHT (CAMWND_CAPTION_HEIGHT + CAMWND_MENU_HEIGHT) #define CAMWND_MENU_CHILD_ID 62000 #define CAMWND_MENU_CMD_REALTIME_LIGHTING 62100 #define CAMWND_MENU_CMD_SHOW_WORLD 62101 @@ -1026,7 +1028,7 @@ static const char* CAMWND_PROP_FILTER_MASK = "QER_CamWnd_FilterMask"; static LRESULT CALLBACK CamWnd_MenuBarProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static int CamWnd_GetMenuHeight() { - return CAMWND_MENU_HEIGHT; + return CAMWND_TOPBAR_HEIGHT; } static int CamWnd_GetIntProp(HWND hWnd, const char* name, int defaultValue = 0) { @@ -1092,8 +1094,8 @@ static void CamWnd_RequestRedraw(CCamWnd* cam) { static void CamWnd_GetMenuItemRect(HWND hWnd, int item, RECT& rect) { GetClientRect(hWnd, &rect); - rect.top = 1; - rect.bottom = CAMWND_MENU_HEIGHT - 1; + rect.top = CAMWND_CAPTION_HEIGHT + 1; + rect.bottom = CAMWND_TOPBAR_HEIGHT - 1; if (item == 0) { rect.left = 4; @@ -1317,7 +1319,7 @@ static HWND CamWnd_EnsureMenuBar(CCamWnd* cam) { 0, 0, rect.Width(), - CAMWND_MENU_HEIGHT, + CAMWND_TOPBAR_HEIGHT, cam->GetSafeHwnd(), (HMENU)CAMWND_MENU_CHILD_ID, AfxGetInstanceHandle(), @@ -1343,7 +1345,7 @@ static void CamWnd_LayoutMenuBar(CCamWnd* cam) { CRect rect; cam->GetClientRect(rect); - MoveWindow(hBar, 0, 0, rect.Width(), CAMWND_MENU_HEIGHT, TRUE); + MoveWindow(hBar, 0, 0, rect.Width(), CAMWND_TOPBAR_HEIGHT, TRUE); } static void CamWnd_DestroyMenuBar(CCamWnd* cam) { @@ -1581,6 +1583,39 @@ static bool CamWnd_MenuFilterBrush(CCamWnd* cam, brush_t* brush) { return false; } + +static COLORREF CamWnd_LerpColor(COLORREF a, COLORREF b, float t) { + const int ar = GetRValue(a); + const int ag = GetGValue(a); + const int ab = GetBValue(a); + const int br = GetRValue(b); + const int bg = GetGValue(b); + const int bb = GetBValue(b); + + const int r = ar + (int)((br - ar) * t); + const int g = ag + (int)((bg - ag) * t); + const int bl = ab + (int)((bb - ab) * t); + return RGB(r, g, bl); +} + +static void CamWnd_FillHorizontalGradient(HDC hDC, const RECT& rect, COLORREF leftColor, COLORREF rightColor) { + const int width = rect.right - rect.left; + if (width <= 0) { + return; + } + + for (int x = 0; x < width; x++) { + const float t = (width > 1) ? ((float)x / (float)(width - 1)) : 0.0f; + const COLORREF color = CamWnd_LerpColor(leftColor, rightColor, t); + HPEN pen = CreatePen(PS_SOLID, 1, color); + HPEN oldPen = (HPEN)SelectObject(hDC, pen); + MoveToEx(hDC, rect.left + x, rect.top, NULL); + LineTo(hDC, rect.left + x, rect.bottom); + SelectObject(hDC, oldPen); + DeleteObject(pen); + } +} + static LRESULT CALLBACK CamWnd_MenuBarProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_ERASEBKGND: @@ -1615,10 +1650,25 @@ static LRESULT CALLBACK CamWnd_MenuBarProc(HWND hWnd, UINT uMsg, WPARAM wParam, RECT rect; GetClientRect(hWnd, &rect); - FillRect(hDC, &rect, (HBRUSH)(COLOR_BTNFACE + 1)); + RECT captionRect = rect; + captionRect.top = 0; + captionRect.bottom = CAMWND_CAPTION_HEIGHT; + + RECT menuRect = rect; + menuRect.top = CAMWND_CAPTION_HEIGHT; + menuRect.bottom = CAMWND_TOPBAR_HEIGHT; + + CamWnd_FillHorizontalGradient(hDC, captionRect, RGB(24, 82, 150), RGB(92, 96, 104)); + FillRect(hDC, &menuRect, (HBRUSH)(COLOR_BTNFACE + 1)); + + RECT dividerRect = rect; + dividerRect.top = CAMWND_CAPTION_HEIGHT - 1; + dividerRect.bottom = CAMWND_CAPTION_HEIGHT; + FillRect(hDC, ÷rRect, (HBRUSH)(COLOR_3DSHADOW + 1)); RECT lineRect = rect; - lineRect.top = CAMWND_MENU_HEIGHT - 1; + lineRect.top = CAMWND_TOPBAR_HEIGHT - 1; + lineRect.bottom = CAMWND_TOPBAR_HEIGHT; FillRect(hDC, &lineRect, (HBRUSH)(COLOR_3DSHADOW + 1)); HFONT font = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0); @@ -1628,6 +1678,13 @@ static LRESULT CALLBACK CamWnd_MenuBarProc(HWND hWnd, UINT uMsg, WPARAM wParam, } SetBkMode(hDC, TRANSPARENT); + + RECT captionTextRect = captionRect; + captionTextRect.left += 8; + captionTextRect.right -= 8; + SetTextColor(hDC, RGB(235, 242, 255)); + DrawText(hDC, "Viewport", -1, &captionTextRect, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS); + SetTextColor(hDC, GetSysColor(COLOR_BTNTEXT)); RECT itemRect; diff --git a/neo/engine/tools/radiant/TabsDlg.cpp b/neo/engine/tools/radiant/TabsDlg.cpp index bf88f1aa..6c848622 100644 --- a/neo/engine/tools/radiant/TabsDlg.cpp +++ b/neo/engine/tools/radiant/TabsDlg.cpp @@ -2,9 +2,9 @@ =========================================================================== IceTech GPL Source Code -Copyright (C) 2026 Justin Marshall +Copyright (C) 2026 Justin Marshall -This file is part of the IceTech GPL Source Code (?IceTech Source Code?). +This file is part of the IceTech GPL Source Code (?IceTech Source Code?). IceTech Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,10 +31,384 @@ If you have questions concerning this license or the applicable additional terms #include "QE3.H" #include "TabsDlg.h" + + +/* +======================== +Tabs dialog top caption + +Draws a non-layout-changing caption at the top of the tab dialog. This is an +overlay child window, so it does not move the tab control, docked children, or +floating/docking logic. The caption text follows the currently selected tab. +======================== +*/ +static const char* TABSDLG_TOP_CAPTION_CLASS = "QER_TabsDlgTopCaption"; +static const char* TABSDLG_TOP_CAPTION_STATE_PROP = "QER_TabsDlgTopCaptionState"; +static const char* TABSDLG_TAB_NOTIFY_STATE_PROP = "QER_TabsDlgTabNotifyState"; +static const int TABSDLG_TOP_CAPTION_HEIGHT = 28; +static const int TABSDLG_TOP_CAPTION_CHILD_ID = 64010; + +struct tabsDlgTopCaptionState_t { + WNDPROC oldProc; + HWND captionWnd; +}; + +struct tabsDlgTabNotifyState_t { + WNDPROC oldProc; + HWND parentWnd; +}; + +static LRESULT CALLBACK TabsDlg_TopCaptionProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +static LRESULT CALLBACK TabsDlg_ParentProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +static LRESULT CALLBACK TabsDlg_TabNotifyProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +static WNDPROC TabsDlg_GetWindowProc(HWND hWnd) { +#ifdef _WIN64 + return (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC); +#else + return (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC); +#endif +} + +static void TabsDlg_SetWindowProc(HWND hWnd, WNDPROC proc) { +#ifdef _WIN64 + SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)proc); +#else + SetWindowLong(hWnd, GWL_WNDPROC, (LONG)proc); +#endif +} + +static COLORREF TabsDlg_LerpColor(COLORREF a, COLORREF b, float t) { + const int ar = GetRValue(a); + const int ag = GetGValue(a); + const int ab = GetBValue(a); + + const int br = GetRValue(b); + const int bg = GetGValue(b); + const int bb = GetBValue(b); + + const int r = ar + (int)((br - ar) * t); + const int g = ag + (int)((bg - ag) * t); + const int bl = ab + (int)((bb - ab) * t); + + return RGB(r, g, bl); +} + +static void TabsDlg_FillHorizontalGradient(HDC hDC, const RECT& rect, COLORREF leftColor, COLORREF rightColor) { + const int width = rect.right - rect.left; + if (width <= 0) { + return; + } + + for (int x = 0; x < width; x++) { + const float t = (width > 1) ? ((float)x / (float)(width - 1)) : 0.0f; + const COLORREF color = TabsDlg_LerpColor(leftColor, rightColor, t); + + HPEN pen = CreatePen(PS_SOLID, 1, color); + HPEN oldPen = (HPEN)SelectObject(hDC, pen); + + MoveToEx(hDC, rect.left + x, rect.top, NULL); + LineTo(hDC, rect.left + x, rect.bottom); + + SelectObject(hDC, oldPen); + DeleteObject(pen); + } +} + +static tabsDlgTopCaptionState_t* TabsDlg_GetTopCaptionState(HWND hWnd) { + return (tabsDlgTopCaptionState_t*)GetProp(hWnd, TABSDLG_TOP_CAPTION_STATE_PROP); +} + +static tabsDlgTabNotifyState_t* TabsDlg_GetTabNotifyState(HWND hTabs) { + return (tabsDlgTabNotifyState_t*)GetProp(hTabs, TABSDLG_TAB_NOTIFY_STATE_PROP); +} + +static HWND TabsDlg_GetTabControl(HWND hWnd) { + HWND hTabs = GetDlgItem(hWnd, IDC_TAB_INSPECTOR); + return IsWindow(hTabs) ? hTabs : NULL; +} + +static CString TabsDlg_GetCurrentTopCaption(HWND hWnd) { + HWND hTabs = TabsDlg_GetTabControl(hWnd); + if (!hTabs) { + return "Viewport"; + } + + int curSel = TabCtrl_GetCurSel(hTabs); + if (curSel < 0 && TabCtrl_GetItemCount(hTabs) > 0) { + curSel = 0; + } + + if (curSel >= 0) { + char text[256]; + text[0] = '\0'; + + TCITEM item; + memset(&item, 0, sizeof(item)); + item.mask = TCIF_TEXT; + item.pszText = text; + item.cchTextMax = sizeof(text); + + if (TabCtrl_GetItem(hTabs, curSel, &item) && text[0] != '\0') { + return text; + } + } + + return "Viewport"; +} + +static void TabsDlg_RegisterTopCaptionClass() { + static bool registered = false; + if (registered) { + return; + } + + WNDCLASS wc; + memset(&wc, 0, sizeof(wc)); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = TabsDlg_TopCaptionProc; + wc.hInstance = AfxGetInstanceHandle(); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszClassName = TABSDLG_TOP_CAPTION_CLASS; + AfxRegisterClass(&wc); + registered = true; +} + +static void TabsDlg_DrawTopCaption(HWND hCaption, HDC hDC) { + HWND hParent = GetParent(hCaption); + RECT rect; + GetClientRect(hCaption, &rect); + + TabsDlg_FillHorizontalGradient( + hDC, + rect, + RGB(24, 82, 150), + RGB(92, 96, 104) + ); + + RECT dividerRect = rect; + dividerRect.top = rect.bottom - 1; + dividerRect.bottom = rect.bottom; + FillRect(hDC, ÷rRect, (HBRUSH)(COLOR_3DSHADOW + 1)); + + HFONT font = (HFONT)GetStockObject(DEFAULT_GUI_FONT); + HFONT oldFont = NULL; + if (font) { + oldFont = (HFONT)SelectObject(hDC, font); + } + + SetBkMode(hDC, TRANSPARENT); + SetTextColor(hDC, RGB(235, 242, 255)); + + RECT textRect = rect; + textRect.left += 8; + textRect.right -= 8; + + CString caption = TabsDlg_GetCurrentTopCaption(hParent); + DrawText( + hDC, + caption, + -1, + &textRect, + DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS + ); + + if (oldFont) { + SelectObject(hDC, oldFont); + } +} + +static LRESULT CALLBACK TabsDlg_TopCaptionProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch (uMsg) { + case WM_ERASEBKGND: + return 1; + + case WM_SETCURSOR: + SetCursor(LoadCursor(NULL, IDC_ARROW)); + return TRUE; + + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hDC = BeginPaint(hWnd, &ps); + TabsDlg_DrawTopCaption(hWnd, hDC); + EndPaint(hWnd, &ps); + return 0; + } + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + +static void TabsDlg_LayoutTopCaption(HWND hWnd) { + tabsDlgTopCaptionState_t* state = TabsDlg_GetTopCaptionState(hWnd); + if (!state || !IsWindow(state->captionWnd)) { + return; + } + + RECT clientRect; + GetClientRect(hWnd, &clientRect); + int width = clientRect.right - clientRect.left; + if (width < 1) { + width = 1; + } + + SetWindowPos( + state->captionWnd, + HWND_TOP, + 0, + 0, + width, + TABSDLG_TOP_CAPTION_HEIGHT, + SWP_NOACTIVATE | SWP_SHOWWINDOW + ); +} + +static void TabsDlg_RefreshTopCaption(HWND hWnd) { + tabsDlgTopCaptionState_t* state = TabsDlg_GetTopCaptionState(hWnd); + if (!state || !IsWindow(state->captionWnd)) { + return; + } + + TabsDlg_LayoutTopCaption(hWnd); + InvalidateRect(state->captionWnd, NULL, FALSE); + UpdateWindow(state->captionWnd); +} + +static void TabsDlg_UninstallTabNotify(HWND hTabs) { + tabsDlgTabNotifyState_t* state = TabsDlg_GetTabNotifyState(hTabs); + if (!state) { + return; + } + + TabsDlg_SetWindowProc(hTabs, state->oldProc); + RemoveProp(hTabs, TABSDLG_TAB_NOTIFY_STATE_PROP); + delete state; +} + +static LRESULT CALLBACK TabsDlg_TabNotifyProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + tabsDlgTabNotifyState_t* state = TabsDlg_GetTabNotifyState(hWnd); + WNDPROC oldProc = state ? state->oldProc : NULL; + HWND parentWnd = state ? state->parentWnd : GetParent(hWnd); + + switch (uMsg) { + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_KEYDOWN: + case WM_KEYUP: + case TCM_SETCURSEL: + case TCM_SETCURFOCUS: + { + LRESULT result = oldProc ? CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam) : DefWindowProc(hWnd, uMsg, wParam, lParam); + TabsDlg_RefreshTopCaption(parentWnd); + return result; + } + + case WM_NCDESTROY: + { + TabsDlg_UninstallTabNotify(hWnd); + return oldProc ? CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam) : DefWindowProc(hWnd, uMsg, wParam, lParam); + } + } + + return oldProc ? CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam) : DefWindowProc(hWnd, uMsg, wParam, lParam); +} + +static void TabsDlg_InstallTabNotify(HWND hWnd) { + HWND hTabs = TabsDlg_GetTabControl(hWnd); + if (!hTabs || TabsDlg_GetTabNotifyState(hTabs)) { + return; + } + + tabsDlgTabNotifyState_t* state = new tabsDlgTabNotifyState_t; + state->oldProc = TabsDlg_GetWindowProc(hTabs); + state->parentWnd = hWnd; + SetProp(hTabs, TABSDLG_TAB_NOTIFY_STATE_PROP, (HANDLE)state); + TabsDlg_SetWindowProc(hTabs, TabsDlg_TabNotifyProc); +} + +static LRESULT CALLBACK TabsDlg_ParentProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + tabsDlgTopCaptionState_t* state = TabsDlg_GetTopCaptionState(hWnd); + WNDPROC oldProc = state ? state->oldProc : NULL; + + switch (uMsg) { + case WM_SIZE: + case WM_WINDOWPOSCHANGED: + { + LRESULT result = oldProc ? CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam) : DefWindowProc(hWnd, uMsg, wParam, lParam); + TabsDlg_LayoutTopCaption(hWnd); + return result; + } + + case WM_NCDESTROY: + { + HWND hTabs = TabsDlg_GetTabControl(hWnd); + if (hTabs) { + TabsDlg_UninstallTabNotify(hTabs); + } + + HWND hCaption = state ? state->captionWnd : NULL; + if (IsWindow(hCaption)) { + DestroyWindow(hCaption); + } + + if (oldProc) { + TabsDlg_SetWindowProc(hWnd, oldProc); + } + RemoveProp(hWnd, TABSDLG_TOP_CAPTION_STATE_PROP); + if (state) { + delete state; + } + + return oldProc ? CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam) : DefWindowProc(hWnd, uMsg, wParam, lParam); + } + } + + return oldProc ? CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam) : DefWindowProc(hWnd, uMsg, wParam, lParam); +} + +static void TabsDlg_InstallTopCaption(HWND hWnd) { + if (!IsWindow(hWnd)) { + return; + } + + tabsDlgTopCaptionState_t* state = TabsDlg_GetTopCaptionState(hWnd); + if (!state) { + TabsDlg_RegisterTopCaptionClass(); + + state = new tabsDlgTopCaptionState_t; + memset(state, 0, sizeof(*state)); + state->oldProc = TabsDlg_GetWindowProc(hWnd); + SetProp(hWnd, TABSDLG_TOP_CAPTION_STATE_PROP, (HANDLE)state); + TabsDlg_SetWindowProc(hWnd, TabsDlg_ParentProc); + } + + if (!IsWindow(state->captionWnd)) { + state->captionWnd = CreateWindowEx( + 0, + TABSDLG_TOP_CAPTION_CLASS, + "", + WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, + 0, + 0, + 1, + TABSDLG_TOP_CAPTION_HEIGHT, + hWnd, + (HMENU)TABSDLG_TOP_CAPTION_CHILD_ID, + AfxGetInstanceHandle(), + NULL); + } + + TabsDlg_InstallTabNotify(hWnd); + TabsDlg_LayoutTopCaption(hWnd); + TabsDlg_RefreshTopCaption(hWnd); +} + // CTabsDlg dialog //IMPLEMENT_DYNAMIC ( CTabsDlg , CDialog ) -CTabsDlg::CTabsDlg(UINT ID , CWnd* pParent /*=NULL*/) +CTabsDlg::CTabsDlg(UINT ID, CWnd* pParent /*=NULL*/) : CDialog(ID, pParent) { m_DragTabActive = false; @@ -61,127 +435,135 @@ BOOL CTabsDlg::OnInitDialog() { CDialog::OnInitDialog(); + TabsDlg_InstallTopCaption(GetSafeHwnd()); + return TRUE; // return TRUE unless you set the focus to a control } -void CTabsDlg::OnTcnSelchange(NMHDR *pNMHDR, LRESULT *pResult) +void CTabsDlg::OnTcnSelchange(NMHDR* pNMHDR, LRESULT* pResult) { - int ID = TabCtrl_GetCurSel ( pNMHDR->hwndFrom ); + int ID = TabCtrl_GetCurSel(pNMHDR->hwndFrom); - if ( ID >= 0 ) + if (ID >= 0) { TCITEM item; item.mask = TCIF_PARAM; - ShowAllWindows ( FALSE ); - TabCtrl_GetItem (m_Tabs.GetSafeHwnd() , ID , &item); + ShowAllWindows(FALSE); + TabCtrl_GetItem(m_Tabs.GetSafeHwnd(), ID, &item); DockedWindowInfo* info = (DockedWindowInfo*)item.lParam; - ASSERT ( info ); + ASSERT(info); info->m_TabControlIndex = ID; info->m_Window->ShowWindow(TRUE); + TabsDlg_RefreshTopCaption(GetSafeHwnd()); } } -void CTabsDlg::DockWindow ( int ID , bool dock ) +void CTabsDlg::DockWindow(int ID, bool dock) { DockedWindowInfo* info = NULL; - m_Windows.Lookup ( (WORD)ID , (void*&)info ); + m_Windows.Lookup((WORD)ID, (void*&)info); - ASSERT ( info ); - ASSERT ( m_Tabs.GetSafeHwnd() ); - - ShowAllWindows ( FALSE ); + ASSERT(info); + ASSERT(m_Tabs.GetSafeHwnd()); - if ( !dock ) - { + ShowAllWindows(FALSE); + + if (!dock) + { //make a containing window and assign the dialog to it CRect rect; - CString classname = AfxRegisterWndClass ( CS_DBLCLKS , 0 , 0 , 0 ); + CString classname = AfxRegisterWndClass(CS_DBLCLKS, 0, 0, 0); info->m_State = DockedWindowInfo::FLOATING; info->m_Window->GetWindowRect(rect); - info->m_Container.CreateEx ( WS_EX_TOOLWINDOW , classname , info->m_Title , WS_THICKFRAME | WS_SYSMENU | WS_POPUP | WS_CAPTION, rect , this , 0 ); - info->m_Window->SetParent ( &info->m_Container ); + info->m_Container.CreateEx(WS_EX_TOOLWINDOW, classname, info->m_Title, WS_THICKFRAME | WS_SYSMENU | WS_POPUP | WS_CAPTION, rect, this, 0); + info->m_Window->SetParent(&info->m_Container); info->m_Window->ShowWindow(TRUE); info->m_Container.SetDockManager(this); info->m_Container.ShowWindow(TRUE); - info->m_Container.SetDialog ( info->m_Window , info->m_ID ); + info->m_Container.SetDialog(info->m_Window, info->m_ID); - if (info->m_TabControlIndex >= 0 ) + if (info->m_TabControlIndex >= 0) { - m_Tabs.DeleteItem( info->m_TabControlIndex ); - } + m_Tabs.DeleteItem(info->m_TabControlIndex); + } - if ( m_Tabs.GetItemCount() > 0 ) + if (m_Tabs.GetItemCount() > 0) { - m_Tabs.SetCurFocus( 0 ); - } + m_Tabs.SetCurFocus(0); + } CString placementName = info->m_Title + "Placement"; - LoadWindowPlacement(info->m_Container , placementName); + LoadWindowPlacement(info->m_Container, placementName); } else - { - info->m_State = DockedWindowInfo::DOCKED; - - info->m_TabControlIndex = m_Tabs.InsertItem( TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM , 0 , info->m_Title , info->m_ImageID , (LPARAM)info); + { + info->m_State = DockedWindowInfo::DOCKED; - info->m_Window->SetParent ( this ); - info->m_Window->ShowWindow (TRUE); - - info->m_Container.SetDockManager( NULL ); //so it doesn't try to call back and redock this window - info->m_Container.DestroyWindow (); + info->m_TabControlIndex = m_Tabs.InsertItem(TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM, 0, info->m_Title, info->m_ImageID, (LPARAM)info); + + info->m_Window->SetParent(this); + info->m_Window->ShowWindow(TRUE); + + info->m_Container.SetDockManager(NULL); //so it doesn't try to call back and redock this window + info->m_Container.DestroyWindow(); CRect rect; - GetWindowRect ( rect ); + GetWindowRect(rect); //stupid hack to get the window reitself properly - rect.DeflateRect(0,0,0,1); - MoveWindow(rect); - rect.InflateRect(0,0,0,1); - MoveWindow(rect); + rect.DeflateRect(0, 0, 0, 1); + MoveWindow(rect); + rect.InflateRect(0, 0, 0, 1); + MoveWindow(rect); } - UpdateTabControlIndices (); - FocusWindow ( ID ); + UpdateTabControlIndices(); + FocusWindow(ID); - if ( info->m_DockCallback ) + TabsDlg_InstallTopCaption(GetSafeHwnd()); + TabsDlg_RefreshTopCaption(GetSafeHwnd()); + + if (info->m_DockCallback) { - info->m_DockCallback ( dock , info->m_ID , info->m_Window ); + info->m_DockCallback(dock, info->m_ID, info->m_Window); } - SaveWindowPlacement (); + SaveWindowPlacement(); } -int CTabsDlg::PreTranslateMessage ( MSG* msg ) +int CTabsDlg::PreTranslateMessage(MSG* msg) { - if ( msg->message == WM_LBUTTONDBLCLK && msg->hwnd == m_Tabs.GetSafeHwnd() ) + if (msg->message == WM_LBUTTONDBLCLK && msg->hwnd == m_Tabs.GetSafeHwnd()) { - HandleUndock (); + HandleUndock(); return TRUE; } //steal lbutton clicks for the main dialog too, but let the tabs do their default thing as well - if ( msg->message == WM_LBUTTONDOWN && msg->hwnd == m_Tabs.GetSafeHwnd()) { - m_Tabs.SendMessage ( msg->message , msg->wParam , msg->lParam ); + if (msg->message == WM_LBUTTONDOWN && msg->hwnd == m_Tabs.GetSafeHwnd()) { + m_Tabs.SendMessage(msg->message, msg->wParam, msg->lParam); m_DragTabActive = true; + TabsDlg_RefreshTopCaption(GetSafeHwnd()); } - else if ( msg->message == WM_LBUTTONUP && msg->hwnd == m_Tabs.GetSafeHwnd()) { - m_Tabs.SendMessage ( msg->message , msg->wParam , msg->lParam ); + else if (msg->message == WM_LBUTTONUP && msg->hwnd == m_Tabs.GetSafeHwnd()) { + m_Tabs.SendMessage(msg->message, msg->wParam, msg->lParam); m_DragTabActive = false; + TabsDlg_RefreshTopCaption(GetSafeHwnd()); } return CDialog::PreTranslateMessage(msg); } -bool CTabsDlg::RectWithinDockManager ( CRect& rect ) +bool CTabsDlg::RectWithinDockManager(CRect& rect) { - CRect tabsRect,intersectionRect; + CRect tabsRect, intersectionRect; - m_Tabs.GetWindowRect ( tabsRect ); - intersectionRect.IntersectRect( tabsRect , rect ); + m_Tabs.GetWindowRect(tabsRect); + intersectionRect.IntersectRect(tabsRect, rect); return !(intersectionRect.IsRectEmpty()); } @@ -192,9 +574,9 @@ void CTabsDlg::OnLButtonDown(UINT nFlags, CPoint point) } void CTabsDlg::OnLButtonUp(UINT nFlags, CPoint point) -{ - if ( m_DragTabActive && ((abs ( point.x - m_DragDownPoint.x ) > 50) || (abs ( point.y - m_DragDownPoint.y ) > 50))) - { +{ + if (m_DragTabActive && ((abs(point.x - m_DragDownPoint.x) > 50) || (abs(point.y - m_DragDownPoint.y) > 50))) + { HandleUndock(); m_DragTabActive = false; } @@ -202,19 +584,19 @@ void CTabsDlg::OnLButtonUp(UINT nFlags, CPoint point) } -void CTabsDlg::HandleUndock () +void CTabsDlg::HandleUndock() { TCITEM item; item.mask = TCIF_PARAM; - int curSel = TabCtrl_GetCurSel ( m_Tabs.GetSafeHwnd()); + int curSel = TabCtrl_GetCurSel(m_Tabs.GetSafeHwnd()); - TabCtrl_GetItem (m_Tabs.GetSafeHwnd() , curSel , &item); + TabCtrl_GetItem(m_Tabs.GetSafeHwnd(), curSel, &item); DockedWindowInfo* info = (DockedWindowInfo*)item.lParam; - ASSERT ( info ); + ASSERT(info); - DockWindow ( info->m_ID , false ); + DockWindow(info->m_ID, false); } void CTabsDlg::OnMouseMove(UINT nFlags, CPoint point) @@ -223,69 +605,74 @@ void CTabsDlg::OnMouseMove(UINT nFlags, CPoint point) } -void CTabsDlg::AddDockedWindow ( CWnd* wnd , int ID , int imageID , const CString& title , bool dock , pfnOnDockEvent dockCallback ) +void CTabsDlg::AddDockedWindow(CWnd* wnd, int ID, int imageID, const CString& title, bool dock, pfnOnDockEvent dockCallback) { DockedWindowInfo* info = NULL; - m_Windows.Lookup( (WORD)ID , (void*&)info); + m_Windows.Lookup((WORD)ID, (void*&)info); - ASSERT ( wnd ); - ASSERT ( info == NULL ); + ASSERT(wnd); + ASSERT(info == NULL); - info = new DockedWindowInfo ( wnd , ID , imageID , title , dockCallback); + dock = true; - m_Windows.SetAt ( (WORD)ID , info ); - DockWindow ( ID , dock ); + info = new DockedWindowInfo(wnd, ID, imageID, title, dockCallback); - UpdateTabControlIndices (); + m_Windows.SetAt((WORD)ID, info); + DockWindow(ID, dock); + + UpdateTabControlIndices(); + TabsDlg_RefreshTopCaption(GetSafeHwnd()); } -void CTabsDlg::ShowAllWindows ( bool show ) +void CTabsDlg::ShowAllWindows(bool show) { POSITION pos; WORD ID; DockedWindowInfo* info = NULL; - for( pos = m_Windows.GetStartPosition(); pos != NULL ; ) + for (pos = m_Windows.GetStartPosition(); pos != NULL; ) { - m_Windows.GetNextAssoc( pos, ID, (void*&)info ); - ASSERT ( info->m_Window ); - if ( info->m_State == DockedWindowInfo::DOCKED ) + m_Windows.GetNextAssoc(pos, ID, (void*&)info); + ASSERT(info->m_Window); + if (info->m_State == DockedWindowInfo::DOCKED) { - info->m_Window->ShowWindow( show ); - } + info->m_Window->ShowWindow(show); + } } } -void CTabsDlg::FocusWindow ( int ID ) +void CTabsDlg::FocusWindow(int ID) { DockedWindowInfo* info = NULL; - m_Windows.Lookup( (WORD)ID , (void*&)info); + m_Windows.Lookup((WORD)ID, (void*&)info); - ASSERT ( info ); - ASSERT ( info->m_Window ); - - if ( info->m_State == DockedWindowInfo::DOCKED ) + ASSERT(info); + ASSERT(info->m_Window); + + if (info->m_State == DockedWindowInfo::DOCKED) { - TabCtrl_SetCurFocus ( m_Tabs.GetSafeHwnd() , info->m_TabControlIndex ); + TabCtrl_SetCurFocus(m_Tabs.GetSafeHwnd(), info->m_TabControlIndex); } else { info->m_Container.SetFocus(); } + + TabsDlg_RefreshTopCaption(GetSafeHwnd()); } -void CTabsDlg::UpdateTabControlIndices () -{ +void CTabsDlg::UpdateTabControlIndices() +{ TCITEM item; item.mask = TCIF_PARAM; DockedWindowInfo* info = NULL; int itemCount = m_Tabs.GetItemCount(); - - for ( int i = 0 ; i < itemCount ; i ++ ) + + for (int i = 0; i < itemCount; i++) { - if ( !m_Tabs.GetItem( i , &item ) ) + if (!m_Tabs.GetItem(i, &item)) { - Sys_Error ( "UpdateTabControlIndices(): GetItem failed!\n" ); + Sys_Error("UpdateTabControlIndices(): GetItem failed!\n"); } info = (DockedWindowInfo*)item.lParam; @@ -299,32 +686,32 @@ void CTabsDlg::OnDestroy() DockedWindowInfo* info = NULL; - for ( int i = 0 ; i < m_Tabs.GetItemCount() ; i ++ ) + for (int i = 0; i < m_Tabs.GetItemCount(); i++) { - m_Tabs.GetItem( i , &item ); + m_Tabs.GetItem(i, &item); info = (DockedWindowInfo*)item.lParam; - ASSERT( info ); + ASSERT(info); delete info; - } + } CDialog::OnDestroy(); } -bool CTabsDlg::IsDocked ( CWnd* wnd ) +bool CTabsDlg::IsDocked(CWnd* wnd) { bool docked = false; DockedWindowInfo* info = NULL; - CString placementName; + CString placementName; POSITION pos; WORD wID; - for( pos = m_Windows.GetStartPosition(); pos != NULL ; ) + for (pos = m_Windows.GetStartPosition(); pos != NULL; ) { - m_Windows.GetNextAssoc( pos, wID, (void*&)info ); + m_Windows.GetNextAssoc(pos, wID, (void*&)info); - if ( info->m_Window == wnd ) { + if (info->m_Window == wnd) { docked = (info->m_State == DockedWindowInfo::DOCKED); break; } @@ -332,21 +719,21 @@ bool CTabsDlg::IsDocked ( CWnd* wnd ) return docked; } -void CTabsDlg::SaveWindowPlacement( int ID ) +void CTabsDlg::SaveWindowPlacement(int ID) { DockedWindowInfo* info = NULL; - - CString placementName; + + CString placementName; POSITION pos; WORD wID = ID; - for( pos = m_Windows.GetStartPosition(); pos != NULL ; ) + for (pos = m_Windows.GetStartPosition(); pos != NULL; ) { - m_Windows.GetNextAssoc( pos, wID, (void*&)info ); + m_Windows.GetNextAssoc(pos, wID, (void*&)info); - if ( (info->m_State == DockedWindowInfo::FLOATING) && ((ID == -1) || (ID == info->m_ID))) { + if ((info->m_State == DockedWindowInfo::FLOATING) && ((ID == -1) || (ID == info->m_ID))) { placementName = info->m_Title + "Placement"; - ::SaveWindowPlacement(info->m_Container.GetSafeHwnd() , placementName); + ::SaveWindowPlacement(info->m_Container.GetSafeHwnd(), placementName); } } } \ No newline at end of file