From f3d44bc057201407373012b7f682881bda7b3d98 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Wed, 23 May 2012 07:44:30 +0000 Subject: some includes restored, mir_full.sln updated, some renaming of folders and projects git-svn-id: http://svn.miranda-ng.org/main/trunk@140 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Tabsrmm/src/sidebar.cpp | 1232 --------------------------------------- 1 file changed, 1232 deletions(-) delete mode 100644 plugins/Tabsrmm/src/sidebar.cpp (limited to 'plugins/Tabsrmm/src/sidebar.cpp') diff --git a/plugins/Tabsrmm/src/sidebar.cpp b/plugins/Tabsrmm/src/sidebar.cpp deleted file mode 100644 index 85dbf3e6c3..0000000000 --- a/plugins/Tabsrmm/src/sidebar.cpp +++ /dev/null @@ -1,1232 +0,0 @@ -/* - * astyle --force-indent=tab=4 --brackets=linux --indent-switches - * --pad=oper --one-line=keep-blocks --unpad=paren - * - * Miranda IM: the free IM client for Microsoft* Windows* - * - * Copyright 2000-2009 Miranda ICQ/IM project, - * all portions of this codebase are copyrighted to the people - * listed in contributors.txt. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * you should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * part of tabSRMM messaging plugin for Miranda. - * - * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors - * - * $Id: sidebar.cpp 12647 2010-09-09 22:17:49Z silvercircle $ - * - * the contact switch bar on the left (or right) side - * - */ - -#include "commonheaders.h" - -extern int TSAPI TBStateConvert2Flat(int state); -extern int TSAPI RBStateConvert2Flat(int state); -extern void TSAPI FillTabBackground(const HDC hdc, int iStateId, const TWindowData* dat, RECT* rc); - -TSideBarLayout CSideBar::m_layouts[CSideBar::NR_LAYOUTS] = { - { - _T("Like tabs, vertical text orientation"), - 26, 30, - SIDEBARLAYOUT_DYNHEIGHT | SIDEBARLAYOUT_VERTICALORIENTATION, - CSideBar::m_DefaultContentRenderer, - CSideBar::m_DefaultBackgroundRenderer, - NULL, - NULL, - SIDEBARLAYOUT_VERTICAL - }, - { - _T("Compact layout, horizontal buttons"), - 100, 24, - 0, - CSideBar::m_DefaultContentRenderer, - CSideBar::m_DefaultBackgroundRenderer, - NULL, - NULL, - SIDEBARLAYOUT_NORMAL - }, - { - _T("Advanced layout with avatars"), - 140, 40, - SIDEBARLAYOUT_NOCLOSEBUTTONS, - CSideBar::m_AdvancedContentRenderer, - CSideBar::m_DefaultBackgroundRenderer, - NULL, - NULL, - SIDEBARLAYOUT_NORMAL - }, - { - _T("Advanced with avatars, vertical orientation"), - 40, 40, - SIDEBARLAYOUT_DYNHEIGHT | SIDEBARLAYOUT_VERTICALORIENTATION | SIDEBARLAYOUT_NOCLOSEBUTTONS, - CSideBar::m_AdvancedContentRenderer, - CSideBar::m_DefaultBackgroundRenderer, - CSideBar::m_measureAdvancedVertical, - NULL, - SIDEBARLAYOUT_VERTICAL - } -}; - -CSideBarButton::CSideBarButton(const TWindowData *dat, CSideBar *sideBar) -{ - m_dat = dat; - m_id = reinterpret_cast(dat->hContact); // set the control id - m_sideBar = sideBar; - _create(); -} - -CSideBarButton::CSideBarButton(const UINT id, CSideBar *sideBar) -{ - m_dat = 0; - m_id = id; - m_sideBar = sideBar; - _create(); -} - -/** - * Internal method to create the button item and configure the associated button control - */ -void CSideBarButton::_create() -{ - m_hwnd = 0; - m_isTopAligned = true; - m_sz.cx = m_sz.cy = 0; - - m_hwnd = ::CreateWindowEx(0, _T("TSButtonClass"), _T(""), WS_CHILD | WS_TABSTOP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, - 0, 0, 40, 40, m_sideBar->getScrollWnd(), reinterpret_cast(m_id), g_hInst, NULL); - - if(m_hwnd) { - ::SendMessage(m_hwnd, BUTTONSETASSIDEBARBUTTON, 0, (LPARAM)this); - ::SendMessage(m_hwnd, BUTTONSETASFLATBTN, 1, 1); - ::SendMessage(m_hwnd, BUTTONSETASFLATBTN + 10, 1, 1); - ::SendMessage(m_hwnd, BUTTONSETASFLATBTN + 12, 0, (LPARAM)m_sideBar->getContainer()); - m_buttonControl = (MButtonCtrl *)::GetWindowLongPtr(m_hwnd, 0); - } - else - delete this; - - if(m_id == IDC_SIDEBARUP || m_id == IDC_SIDEBARDOWN) - ::SetParent(m_hwnd, m_sideBar->getContainer()->hwnd); -} - -CSideBarButton::~CSideBarButton() -{ - if(m_hwnd) { - ::SendMessage(m_hwnd, BUTTONSETASSIDEBARBUTTON, 0, 0); // make sure, the button will no longer call us back - ::DestroyWindow(m_hwnd); - } -} - -void CSideBarButton::Show(const int showCmd) const -{ - ::ShowWindow(m_hwnd, showCmd); -} - -/** - * Measure the metrics for the current item. The side bar layouting will call this - * whenever a layout with a dynamic height is active). For fixed dimension layouts, - * m_elementWidth and m_elementHeight will be used. - * - * @return SIZE&: reference to the item's size member. The caller may use cx and cy values - * to determine further layouting actions. - */ -const SIZE& CSideBarButton::measureItem() -{ - SIZE sz; - - if(m_sideBarLayout->pfnMeasureItem) - m_sideBarLayout->pfnMeasureItem(this); // use the current layout's function, if available, else use default - else { - HDC dc = ::GetDC(m_hwnd); - TCHAR tszLabel[255]; - - HFONT oldFont = reinterpret_cast(::SelectObject(dc, ::GetStockObject(DEFAULT_GUI_FONT))); - - mir_sntprintf(tszLabel, 255, _T("%s"), m_dat->newtitle); - ::GetTextExtentPoint32(dc, tszLabel, lstrlen(tszLabel), &sz); - - sz.cx += 28; - if(m_dat->pContainer->dwFlagsEx & TCF_CLOSEBUTTON) - sz.cx += 20; - - if(m_sideBarLayout->dwFlags & CSideBar::SIDEBARLAYOUT_VERTICALORIENTATION) - m_sz.cy = sz.cx; - else - m_sz.cx = sz.cx; - - ::SelectObject(dc, oldFont); - ::ReleaseDC(m_hwnd, dc); - } - return(m_sz); -} -/** - * Render the button item. Callback from the button window procedure - * - * @param ctl MButtonCtrl *: pointer to the private button data structure - * @param hdc HDC: device context for painting - */ -void CSideBarButton::RenderThis(const HDC hdc) const -{ - RECT rc; - LONG cx, cy; - HDC hdcMem = 0; - bool fVertical = (m_sideBarLayout->dwFlags & CSideBar::SIDEBARLAYOUT_VERTICALORIENTATION) ? true : false; - HBITMAP hbmMem, hbmOld; - HANDLE hbp = 0; - - ::GetClientRect(m_hwnd, &rc); - - if(m_id == IDC_SIDEBARUP || m_id == IDC_SIDEBARDOWN) - fVertical = false; - - if(fVertical) { - cx = rc.bottom; - cy = rc.right; - } - else { - cx = rc.right; - cy = rc.bottom; - } - - hdcMem = ::CreateCompatibleDC(hdc); - - if(fVertical) { - RECT rcFlipped = {0,0,cx,cy}; - hbmMem = CSkin::CreateAeroCompatibleBitmap(rcFlipped, hdcMem); - rc = rcFlipped; - } - else - hbmMem = CSkin::CreateAeroCompatibleBitmap(rc, hdcMem); - - hbmOld = reinterpret_cast(::SelectObject(hdcMem, hbmMem)); - - HFONT hFontOld = reinterpret_cast(::SelectObject(hdcMem, ::GetStockObject(DEFAULT_GUI_FONT))); - - m_sideBarLayout->pfnBackgroundRenderer(hdcMem, &rc, this); - m_sideBarLayout->pfnContentRenderer(hdcMem, &rc, this); - - ::SelectObject(hdcMem, hFontOld); - - /* - * for vertical tabs, we did draw to a rotated rectangle, so we now must rotate the - * final bitmap back to it's original orientation - */ - - if(fVertical) { - ::SelectObject(hdcMem, hbmOld); - - FIBITMAP *fib = FIF->FI_CreateDIBFromHBITMAP(hbmMem); - FIBITMAP *fib_new = FIF->FI_RotateClassic(fib, 90.0f); - FIF->FI_Unload(fib); - ::DeleteObject(hbmMem); - hbmMem = FIF->FI_CreateHBITMAPFromDIB(fib_new); - FIF->FI_Unload(fib_new); - hbmOld =reinterpret_cast(::SelectObject(hdcMem, hbmMem)); - ::BitBlt(hdc, 0, 0, cy, cx, hdcMem, 0, 0, SRCCOPY); - ::SelectObject(hdcMem, hbmOld); - ::DeleteObject(hbmMem); - ::DeleteDC(hdcMem); - } - else { - ::BitBlt(hdc, 0, 0, cx, cy, hdcMem, 0, 0, SRCCOPY); - ::SelectObject(hdcMem, hbmOld); - ::DeleteObject(hbmMem); - ::DeleteDC(hdcMem); - } - return; -} - -/** - * render basic button content like nickname and icon. Used for the basic layouts - * only. Pretty much the same code as used for the tabs. - * - * @param hdc : target device context - * @param rcItem : rectangle to render into - */ -void CSideBarButton::renderIconAndNick(const HDC hdc, const RECT *rcItem) const -{ - HICON hIcon; - RECT rc = *rcItem; - DWORD dwTextFlags = DT_SINGLELINE | DT_VCENTER; - int stateId = m_buttonControl->stateId; - int iSize = 16; - const TContainerData *pContainer = m_sideBar->getContainer(); - - if(m_dat && pContainer) { - hIcon = m_dat->cache->getIcon(iSize); - - if (m_dat->mayFlashTab == FALSE || (m_dat->mayFlashTab == TRUE && m_dat->bTabFlash != 0) || !(pContainer->dwFlagsEx & TCF_FLASHICON)) { - DWORD ix = rc.left + 4; - DWORD iy = (rc.bottom + rc.top - iSize) / 2; - if (m_dat->dwFlagsEx & MWF_SHOW_ISIDLE && PluginConfig.m_IdleDetect) - CSkin::DrawDimmedIcon(hdc, ix, iy, iSize, iSize, hIcon, 180); - else - ::DrawIconEx(hdc, ix, iy, hIcon, iSize, iSize, 0, NULL, DI_NORMAL | DI_COMPAT); - } - - rc.left += (iSize + 7); - - /* - * draw the close button if enabled - */ - if(m_sideBar->getContainer()->dwFlagsEx & TCF_CLOSEBUTTON) { - if(m_sideBar->getHoveredClose() != this) - CSkin::m_default_bf.SourceConstantAlpha = 150; - - CMimAPI::m_MyAlphaBlend(hdc, rc.right - 20, (rc.bottom + rc.top - 16) / 2, 16, 16, CSkin::m_tabCloseHDC, - 0, 0, 16, 16, CSkin::m_default_bf); - - rc.right -= 19; - CSkin::m_default_bf.SourceConstantAlpha = 255; - } - - ::SetBkMode(hdc, TRANSPARENT); - - if (m_dat->mayFlashTab == FALSE || (m_dat->mayFlashTab == TRUE && m_dat->bTabFlash != 0) || !(pContainer->dwFlagsEx & TCF_FLASHLABEL)) { - bool fIsActive = (m_sideBar->getActiveItem() == this ? true : false); - COLORREF clr = 0; - dwTextFlags |= DT_WORD_ELLIPSIS; - - if (fIsActive || stateId == PBS_PRESSED) - clr = PluginConfig.tabConfig.colors[1]; - else if (stateId == PBS_HOT) - clr = PluginConfig.tabConfig.colors[3]; - else - clr = PluginConfig.tabConfig.colors[0]; - - CSkin::RenderText(hdc, m_buttonControl->hThemeButton, m_dat->newtitle, &rc, dwTextFlags, CSkin::m_glowSize, clr); - } - } -} - -/** - * test if we have the mouse pointer over our close button. - * @return: 1 if the pointer is inside the button's rect, -1 otherwise - */ -int CSideBarButton::testCloseButton() const -{ - if(m_id == IDC_SIDEBARUP || m_id == IDC_SIDEBARDOWN) // scroller buttons don't have a close button - return(-1); - - if(m_sideBar->getContainer()->dwFlagsEx & TCF_CLOSEBUTTON && !(getLayout()->dwFlags & CSideBar::SIDEBARLAYOUT_NOCLOSEBUTTONS)) { - POINT pt; - ::GetCursorPos(&pt); - ::ScreenToClient(m_hwnd, &pt); - RECT rc; - - ::GetClientRect(m_hwnd, &rc); - if(getLayout()->dwFlags & CSideBar::SIDEBARLAYOUT_VERTICALORIENTATION) { - rc.bottom = rc.top + 18; rc.top += 2; - rc.left += 2; rc.right -= 2; - if(::PtInRect(&rc, pt)) - return(1); - } - else { - rc.bottom -= 4; rc.top += 4; - rc.right -= 3; rc.left = rc.right - 16; - if(::PtInRect(&rc, pt)) - return(1); - } - } - return(-1); -} -/** - * call back from the button window procedure. Activate my session - */ -void CSideBarButton::activateSession() const -{ - if(m_dat) - ::SendMessage(m_dat->hwnd, DM_ACTIVATEME, 0, 0); // the child window will activate itself -} - -/** - * show the context menu (same as on tabs - */ -void CSideBarButton::invokeContextMenu() -{ - const TContainerData* pContainer = m_sideBar->getContainer(); - - if(pContainer) { - TSideBarNotify tsn = {0}; - tsn.nmHdr.code = NM_RCLICK; - tsn.nmHdr.idFrom = 5000; - tsn.nmHdr.hwndFrom = ::GetDlgItem(pContainer->hwnd, 5000); - tsn.dat = m_dat; - ::SendMessage(pContainer->hwnd, WM_NOTIFY, 0, reinterpret_cast(&tsn)); - } -} - -CSideBar::CSideBar(TContainerData *pContainer) -{ - m_pContainer = pContainer; - m_up = m_down = 0; - m_hwndScrollWnd = 0; - m_buttonlist.clear(); - m_activeItem = 0; - m_isVisible = true; - - Init(true); -} - -CSideBar::~CSideBar() -{ - destroyScroller(); - m_buttonlist.clear(); - - if(m_hwndScrollWnd) - ::DestroyWindow(m_hwndScrollWnd); -} - -void CSideBar::Init(const bool fForce) -{ - m_iTopButtons = m_iBottomButtons = 0; - m_topHeight = m_bottomHeight = 0; - m_firstVisibleOffset = 0; - m_totalItemHeight = 0; - - m_uLayout = (m_pContainer->dwFlagsEx & 0xff000000) >> 24; - m_uLayout = ((m_uLayout >= 0 && m_uLayout < NR_LAYOUTS) ? m_uLayout : 0); - - m_currentLayout = &m_layouts[m_uLayout]; - - m_dwFlags = m_currentLayout->dwFlags; - - m_dwFlags = (m_pContainer->dwFlagsEx & TCF_SBARLEFT ? m_dwFlags | SIDEBARORIENTATION_LEFT : m_dwFlags & ~SIDEBARORIENTATION_LEFT); - m_dwFlags = (m_pContainer->dwFlagsEx & TCF_SBARRIGHT ? m_dwFlags | SIDEBARORIENTATION_RIGHT : m_dwFlags & ~SIDEBARORIENTATION_RIGHT); - - if(m_pContainer->dwFlags & CNT_SIDEBAR) { - if(m_hwndScrollWnd == 0) - m_hwndScrollWnd = ::CreateWindowEx(0, _T("TS_SideBarClass"), _T(""), WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE | WS_CHILD, - 0, 0, m_width, 40, m_pContainer->hwnd, reinterpret_cast(5000), g_hInst, this); - - m_isActive = true; - m_isVisible = m_isActive ? m_isVisible : true; - createScroller(); - m_elementHeight = m_currentLayout->height; - m_elementWidth = m_currentLayout->width; - m_width = m_elementWidth + 4; - populateAll(); - if(m_activeItem) - setActiveItem(m_activeItem); - } - else { - destroyScroller(); - m_width = 0; - m_isActive = m_isVisible = false; - m_activeItem = 0; - - removeAll(); - if(m_hwndScrollWnd) - ::DestroyWindow(m_hwndScrollWnd); - m_hwndScrollWnd = 0; - } -} - -/** - * sets visibility status for the sidebar. An invisible sidebar (collapsed - * by the button in the message dialog) will remain active, it will, however - * not do any drawing or other things that are only visually important. - * - * @param fNewVisible : set the new visibility status - */ -void CSideBar::setVisible(bool fNewVisible) -{ - m_isVisible = fNewVisible; - - /* - * only needed on hiding. Layout() will do it when showing it - */ - - if(!m_isVisible) - showAll(SW_HIDE); - else { - m_up->Show(SW_SHOW); - m_down->Show(SW_SHOW); - } -} - -/** - * Create both scrollbar buttons which can be used to scroll the switchbar - * up and down. - */ -void CSideBar::createScroller() -{ - if(m_up == 0) - m_up = new CSideBarButton(IDC_SIDEBARUP, this); - if(m_down == 0) - m_down = new CSideBarButton(IDC_SIDEBARDOWN, this); - - m_up->setLayout(m_currentLayout); - m_down->setLayout(m_currentLayout); -} - -/** - * Destroy the scroller buttons. - */ -void CSideBar::destroyScroller() -{ - if(m_up) { - delete m_up; - m_up = 0; - } - if(m_down) { - delete m_down; - m_down = 0; - } -} - -/** - * remove all buttons from the current list - * Does not remove the sessions. This is basically only used when switching - * from a sidebar to a tabbed interface - */ -void CSideBar::removeAll() -{ - ButtonIterator item = m_buttonlist.begin(); - - while(item != m_buttonlist.end()) { - delete *item; - item++; - } - m_buttonlist.clear(); -} - -/** - * popuplate the side bar with all sessions inside the current window. Information - * is gathered from the tab control, which remains active (but invisible) when the - * switch bar is in use. - * - * This is needed when the user switches from tabs to a switchbar layout while a - * window is open. - */ -void CSideBar::populateAll() -{ - HWND hwndTab = ::GetDlgItem(m_pContainer->hwnd, IDC_MSGTABS); - - if(hwndTab) { - int iItems = (int)TabCtrl_GetItemCount(hwndTab); - TCITEM item = {0}; - - item.mask = TCIF_PARAM; - std::vector::iterator b_item; - - m_iTopButtons = 0; - - for(int i = 0; i < iItems; i++) { - TabCtrl_GetItem(hwndTab, i, &item); - if(item.lParam && ::IsWindow((HWND)item.lParam)) { - TWindowData *dat = (TWindowData *)::GetWindowLongPtr((HWND)item.lParam, GWLP_USERDATA); - if(dat) { - if((b_item = findSession(dat)) == m_buttonlist.end()) - addSession(dat, i); - else { - (*b_item)->setLayout(m_currentLayout); - if(m_dwFlags & SIDEBARLAYOUT_VERTICALORIENTATION) { - (*b_item)->measureItem(); - m_topHeight += ((*b_item)->getHeight() + 1); - } - else - m_topHeight += (m_elementHeight + 1); - } - } - } - } - } -} -/** - * Add a new session to the switchbar. - * - * @param dat _MessageWindowData *: session data for a client session. Must be fully initialized - * (that is, it can only be used after WM_INITIALOG completed). - * position: -1 = append, otherwise insert it at the given position - */ -void CSideBar::addSession(const TWindowData *dat, int position) -{ - if(!m_isActive) - return; - - CSideBarButton *item = new CSideBarButton(dat, this); - - item->setLayout(m_currentLayout); - - if(m_dwFlags & SIDEBARLAYOUT_DYNHEIGHT) { - SIZE sz = item->measureItem(); - m_topHeight += (sz.cy + 1); - } - else - m_topHeight += (m_elementHeight + 1); - - m_iTopButtons++; - if(position == -1 || (size_t)position >= m_buttonlist.size()) - m_buttonlist.push_back(item); - else { - ButtonIterator it = m_buttonlist.begin() + position; - m_buttonlist.insert(it, item); - } - SendDlgItemMessage(dat->hwnd, dat->bType == SESSIONTYPE_IM ? IDC_TOGGLESIDEBAR : IDC_CHAT_TOGGLESIDEBAR, BM_SETIMAGE, IMAGE_ICON, - (LPARAM)(m_dwFlags & SIDEBARORIENTATION_LEFT ? PluginConfig.g_buttonBarIcons[ICON_DEFAULT_LEFT] : PluginConfig.g_buttonBarIcons[ICON_DEFAULT_RIGHT])); - - Invalidate(); -} - -/** - * Remove a new session from the switchbar. - * - * @param dat _MessageWindowData *: session data for a client session. - */ -HRESULT CSideBar::removeSession(const TWindowData *dat) -{ - if(dat) { - std::vector::iterator item = findSession(dat); - - if(item != m_buttonlist.end()) { - m_iTopButtons--; - if(m_dwFlags & SIDEBARLAYOUT_DYNHEIGHT) { - SIZE sz = (*item)->getSize(); - m_topHeight -= (sz.cy + 1); - } - else - m_topHeight -= (m_elementHeight + 1); - delete *item; - m_buttonlist.erase(item); - Invalidate(); - return(S_OK); - } - } - return(S_FALSE); -} - -/** - * make sure the given item is visible in a scrolled switch bar - * - * @param item CSideBarButtonItem*: the item which must be visible in the switch bar - */ -void CSideBar::scrollIntoView(const CSideBarButton *item) -{ - LONG spaceUsed = 0, itemHeight; - bool fNeedLayout = false; - - if(!m_isActive) - return; - - if(item == 0) - item = m_activeItem; - - ButtonIterator it = m_buttonlist.begin(); - - while(it != m_buttonlist.end()) { - itemHeight = (*it)->getHeight(); - spaceUsed += (itemHeight + 1); - if(*it == item ) - break; - it++; - } - - RECT rc; - GetClientRect(m_hwndScrollWnd, &rc); - - if(m_topHeight <= rc.bottom) { - m_firstVisibleOffset = 0; - Layout(); - return; - } - if(it == m_buttonlist.end() || (it == m_buttonlist.begin() && m_firstVisibleOffset == 0)) { - Layout(); - return; // do nothing for the first item and .end() should not really happen - } - - if(spaceUsed <= rc.bottom && spaceUsed - (itemHeight + 1) >= m_firstVisibleOffset) { - Layout(); - return; // item fully visible, do nothing - } - - /* - * button partially or not at all visible at the top - */ - if(spaceUsed < m_firstVisibleOffset || spaceUsed - (itemHeight + 1) < m_firstVisibleOffset) { - m_firstVisibleOffset = spaceUsed - (itemHeight + 1); - fNeedLayout = true; - } else { - if(spaceUsed > rc.bottom) { // partially or not at all visible at the bottom - fNeedLayout = true; - m_firstVisibleOffset = spaceUsed - rc.bottom; - } - } - - //if(fNeedLayout) - Layout(); -} -/** - * Invalidate the button associated with the given session. - * - * @param dat _MessageWindowData*: Session data - */ -void CSideBar::updateSession(const TWindowData *dat) -{ - if(!m_isVisible || !m_isActive) - return; - - ButtonIterator item = findSession(dat); - if(item != m_buttonlist.end()) { - if(m_dwFlags & SIDEBARLAYOUT_DYNHEIGHT) { - LONG oldHeight = (*item)->getHeight(); - m_topHeight -= (oldHeight + 1); - SIZE sz = (*item)->measureItem(); - m_topHeight += (sz.cy + 1); - if(sz.cy != oldHeight) { - Invalidate(); - ::InvalidateRect((*item)->getHwnd(), NULL, TRUE); - } - else - ::InvalidateRect((*item)->getHwnd(), NULL, FALSE); - } - else - ::InvalidateRect((*item)->getHwnd(), NULL, FALSE); - } -} - -/** - * Sets the active session item - * called from the global update handler in msgdialog/group room window - * on every tab activation to ensure consistency - * - * @param dat _MessageWindowData*: session data - * - * @return The previously active item (that can be zero) - */ -const CSideBarButton* CSideBar::setActiveItem(const TWindowData *dat) -{ - ButtonIterator item = findSession(dat); - if(item != m_buttonlist.end()) { - return(setActiveItem(*item)); - } - return(0); -} - -/** - * Layout the buttons within the available space... ensure that buttons are - * set to invisible if there is not enough space. Also, update the state of - * the scroller buttons - * - * @param rc RECT*:the window rectangle - * - * @param fOnlyCalc bool: if false (default), window positions will be updated, otherwise, - * the method will only calculate the layout parameters. A final call to - * Layout() with the parameter set to false is required to perform the - * position update. - */ -void CSideBar::Layout(const RECT *rc, bool fOnlyCalc) -{ - if(!m_isVisible) - return; - - RECT rcWnd; - - rc = &rcWnd; - ::GetClientRect(m_hwndScrollWnd, &rcWnd); - - if(m_currentLayout->pfnLayout) { - m_currentLayout->pfnLayout(this, const_cast(rc)); - return; - } - - HDWP hdwp = ::BeginDeferWindowPos(1); - - int topCount = 0, bottomCount = 0; - size_t i = 0, j = 0; - BOOL topEnabled = FALSE, bottomEnabled = FALSE; - HWND hwnd; - LONG spaceUsed = 0; - DWORD dwFlags = SWP_NOZORDER|SWP_NOACTIVATE; - LONG iSpaceAvail = rc->bottom; - - m_firstVisibleOffset = max(0, m_firstVisibleOffset); - - ButtonIterator item = m_buttonlist.begin(); - - m_totalItemHeight = 0; - - LONG height = m_elementHeight; - - while (item != m_buttonlist.end()) { - hwnd = (*item)->getHwnd(); - - if(m_dwFlags & SIDEBARLAYOUT_DYNHEIGHT) - height = (*item)->getHeight(); - - if(spaceUsed > iSpaceAvail || m_totalItemHeight + height < m_firstVisibleOffset) { - ::ShowWindow(hwnd, SW_HIDE); - item++; - m_totalItemHeight += (height + 1); - continue; - } - - if ((*item)->isTopAligned()) { - if(m_totalItemHeight <= m_firstVisibleOffset) { // partially visible - if(!fOnlyCalc) - hdwp = ::DeferWindowPos(hdwp, hwnd, 0, 2, -(m_firstVisibleOffset - m_totalItemHeight), - m_elementWidth, height, SWP_SHOWWINDOW | dwFlags); - spaceUsed += ((height + 1) - (m_firstVisibleOffset - m_totalItemHeight)); - m_totalItemHeight += (height + 1); - } - else { - if(!fOnlyCalc) - hdwp = ::DeferWindowPos(hdwp, hwnd, 0, 2, spaceUsed, - m_elementWidth, height, SWP_SHOWWINDOW | dwFlags); - spaceUsed += (height + 1); - m_totalItemHeight += (height + 1); - } - }/* - else { - }*/ - item++; - } - topEnabled = m_firstVisibleOffset > 0; - bottomEnabled = (m_totalItemHeight - m_firstVisibleOffset > rc->bottom); - ::EndDeferWindowPos(hdwp); - - //_DebugTraceA("layout: total %d, used: %d, first visible: %d", m_totalItemHeight, spaceUsed, m_firstVisibleOffset); - if(!fOnlyCalc) { - RECT rcContainer; - ::GetClientRect(m_pContainer->hwnd, &rcContainer); - - LONG dx = m_dwFlags & SIDEBARORIENTATION_LEFT ? m_pContainer->tBorder_outer_left : - rcContainer.right - m_pContainer->tBorder_outer_right - (m_elementWidth + 4); - - ::SetWindowPos(m_up->getHwnd(), 0, dx, m_pContainer->tBorder_outer_top + m_pContainer->MenuBar->getHeight(), - m_elementWidth + 4, 14, dwFlags | SWP_SHOWWINDOW); - ::SetWindowPos(m_down->getHwnd(), 0, dx, (rcContainer.bottom - 14 - m_pContainer->statusBarHeight - 1), - m_elementWidth + 4, 14, dwFlags | SWP_SHOWWINDOW); - ::EnableWindow(m_up->getHwnd(), topEnabled); - ::EnableWindow(m_down->getHwnd(), bottomEnabled); - ::InvalidateRect(m_up->getHwnd(), NULL, FALSE); - ::InvalidateRect(m_down->getHwnd(), NULL, FALSE); - } -} - -inline void CSideBar::Invalidate() -{ - Layout(0); -} - -void CSideBar::showAll(int showCmd) -{ - ::ShowWindow(m_up->getHwnd(), showCmd); - ::ShowWindow(m_down->getHwnd(), showCmd); - - std::vector::iterator item = m_buttonlist.begin(); - - while(item != m_buttonlist.end()) - ::ShowWindow((*item++)->getHwnd(), showCmd); -} - -/** - * Helper function: find a button item associated to the given - * session data - * - * @param dat _MessageWindowData*: session information - * - * @return CSideBarButtonItem*: pointer to the found item. Zero, if none was found - */ -ButtonIterator CSideBar::findSession(const TWindowData *dat) -{ - if(dat) { - std::vector::iterator item = m_buttonlist.begin(); - - if(m_buttonlist.size() > 0) { - while(item != m_buttonlist.end()) { - if((*item)->getDat() == dat) - return(item); - item++; - } - } - } - return(m_buttonlist.end()); -} - -/** - * Helper function: find a button item associated to the given - * contact handle - * - * @param hContact HANDLE: contact's handle to look for - * - * @return CSideBarButtonItem*: pointer to the found item. Zero, if none was found - */ -ButtonIterator CSideBar::findSession(const HANDLE hContact) -{ - if(hContact) { - std::vector::iterator item = m_buttonlist.begin(); - - if(m_buttonlist.size() > 0) { - while(item != m_buttonlist.end()) { - if((*item)->getContactHandle() == hContact) - return(item); - item++; - } - } - } - return(m_buttonlist.end()); -} - -void CSideBar::processScrollerButtons(UINT commandID) -{ - if(!m_isActive || m_down == 0) - return; - - if(commandID == IDC_SIDEBARDOWN && ::IsWindowEnabled(m_down->getHwnd())) - m_firstVisibleOffset += 10; - else if(commandID == IDC_SIDEBARUP && ::IsWindowEnabled(m_up->getHwnd())) - m_firstVisibleOffset = max(0, m_firstVisibleOffset - 10); - - Layout(0); -} - -void CSideBar::resizeScrollWnd(LONG x, LONG y, LONG width, LONG height) const -{ - if(!m_isVisible || !m_isActive) { - ::ShowWindow(m_hwndScrollWnd, SW_HIDE); - return; - } - ::SetWindowPos(m_hwndScrollWnd, 0, x, y + 15, m_width, height - 30, - SWP_NOCOPYBITS | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOSENDCHANGING | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS); -} - -void CSideBar::invalidateButton(const TWindowData* dat) -{ - if(m_isActive && m_isVisible) { - ButtonIterator it = findSession(dat); - - if(it != this->m_buttonlist.end()) - RedrawWindow((*it)->m_buttonControl->hwnd, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW); - } -} - -/** - * the window procedure for the sidebar container window (the window which - * acts as a parent for the actual buttons). itself, this window is a child - * of the container window. - */ -LRESULT CALLBACK CSideBar::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch(msg) { - case WM_SIZE: - return(TRUE); - case WM_ERASEBKGND: { - HDC hdc = (HDC)wParam; - RECT rc; - ::GetClientRect(hwnd, &rc); - if (CSkin::m_skinEnabled) { - CSkinItem *item = &SkinItems[ID_EXTBKSIDEBARBG]; - - if(item->IGNORED) - CSkin::SkinDrawBG(hwnd, m_pContainer->hwnd, m_pContainer, &rc, hdc); - else - CSkin::DrawItem(hdc, &rc, item); - } - else if (M->isAero() || M->isVSThemed()) { - HDC hdcMem; - HANDLE hbp = 0; - HBITMAP hbm, hbmOld; - - if(CMimAPI::m_haveBufferedPaint) - hbp = CSkin::InitiateBufferedPaint(hdc, rc, hdcMem); - else { - hdcMem = ::CreateCompatibleDC(hdc); - hbm = CSkin::CreateAeroCompatibleBitmap(rc, hdcMem); - hbmOld = reinterpret_cast(::SelectObject(hdcMem, hbm)); - } - - if(M->isAero()) - ::FillRect(hdcMem, &rc, CSkin::m_BrushBack); - else - CSkin::FillBack(hdcMem, &rc); - - if(hbp) - CSkin::FinalizeBufferedPaint(hbp, &rc); - else { - ::BitBlt(hdc, 0, 0, rc.right, rc.bottom, hdcMem, 0, 0, SRCCOPY); - ::SelectObject(hdcMem, hbmOld); - ::DeleteObject(hbm); - ::DeleteDC(hdcMem); - } - } - else - ::FillRect(hdc, &rc, ::GetSysColorBrush(COLOR_3DFACE)); - return(1); - } - default: - break; - } - return(DefWindowProc(hwnd, msg, wParam, lParam)); -} - -LRESULT CALLBACK CSideBar::wndProcStub(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - CSideBar *sideBar = (CSideBar *)::GetWindowLongPtr(hwnd, GWLP_USERDATA); - - if(sideBar) - return(sideBar->wndProc(hwnd, msg, wParam, lParam)); - - switch(msg) { - case WM_NCCREATE: { - CREATESTRUCT *cs = (CREATESTRUCT *)lParam; - ::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)cs->lpCreateParams); - return(TRUE); - } - default: - break; - } - return(::DefWindowProc(hwnd, msg, wParam, lParam)); -} -/** - * paints the background for a switchbar item. It can paint aero, visual styles, skins or - * classic buttons (depending on os and current plugin settings). - * - * @param hdc HDC: target device context - * @param rc RECT*: target rectangle - * @param stateId the state identifier (normal, pressed, hot, disabled etc.) - */ -void __fastcall CSideBar::m_DefaultBackgroundRenderer(const HDC hdc, const RECT *rc, - const CSideBarButton *item) -{ - UINT id = item->getID(); - int stateId = item->m_buttonControl->stateId; - bool fIsActiveItem = (item->m_sideBar->getActiveItem() == item); - - if(CSkin::m_skinEnabled) { - TContainerData* pContainer = const_cast(item->m_sideBar->getContainer()); - int id = stateId == PBS_PRESSED || fIsActiveItem ? ID_EXTBKBUTTONSPRESSED : (stateId == PBS_HOT ? ID_EXTBKBUTTONSMOUSEOVER : ID_EXTBKBUTTONSNPRESSED); - CSkinItem* skinItem = &SkinItems[id]; - HWND hwnd; - - if(id == IDC_SIDEBARUP) - hwnd = item->m_sideBar->getScrollUp()->m_buttonControl->hwnd; - else if(id == IDC_SIDEBARDOWN) - hwnd = item->m_sideBar->getScrollDown()->m_buttonControl->hwnd; - else - hwnd = item->m_buttonControl->hwnd; - - CSkin::SkinDrawBG(hwnd, pContainer->hwnd, pContainer, const_cast(rc), hdc); - CSkin::DrawItem(hdc, rc, skinItem); - } - else if(M->isAero() || PluginConfig.m_fillColor) { - if(id == IDC_SIDEBARUP || id == IDC_SIDEBARDOWN) { - if(M->isAero()) - ::FillRect(hdc, const_cast(rc), CSkin::m_BrushBack); - else - CSkin::FillBack(hdc, const_cast(rc)); - - if(stateId == PBS_HOT || stateId == PBS_PRESSED) - DrawAlpha(hdc, const_cast(rc), 0xf0f0f0, 70, 0x000000, 0, 9, - 31, 4, 0); - else - DrawAlpha(hdc, const_cast(rc), 0xf0f0f0, 30, 0x707070, 0, 9, - 31, 4, 0); - } - else { - if(PluginConfig.m_fillColor) - FillTabBackground(hdc, stateId, item->getDat(), const_cast(rc)); - - CSkin::m_switchBarItem->setAlphaFormat(AC_SRC_ALPHA, - (stateId == PBS_HOT && !fIsActiveItem) ? 250 : (fIsActiveItem || stateId == PBS_PRESSED ? 250 : 230)); - CSkin::m_switchBarItem->Render(hdc, rc, true); - if(stateId == PBS_HOT || stateId == PBS_PRESSED || fIsActiveItem) { - RECT rcGlow = *rc; - rcGlow.top += 1; - rcGlow.bottom -= 2; - - CSkin::m_tabGlowTop->setAlphaFormat(AC_SRC_ALPHA, (stateId == PBS_PRESSED || fIsActiveItem) ? 180 : 100); - CSkin::m_tabGlowTop->Render(hdc, &rcGlow, true); - } - } - } - else if(M->isVSThemed()) { - RECT *rcDraw = const_cast(rc); - if(id == IDC_SIDEBARUP || id == IDC_SIDEBARDOWN) { - ::FillRect(hdc, rc, stateId == PBS_HOT ? ::GetSysColorBrush(COLOR_HOTLIGHT) : ::GetSysColorBrush(COLOR_3DFACE)); - ::InflateRect(rcDraw, -2, 0); - ::DrawEdge(hdc, rcDraw, EDGE_ETCHED, BF_SOFT|BF_RECT|BF_FLAT); - } - else { - CSkin::FillBack(hdc, rcDraw); - - if(CMimAPI::m_pfnIsThemeBackgroundPartiallyTransparent(item->m_buttonControl->hThemeToolbar, TP_BUTTON, stateId)) - CMimAPI::m_pfnDrawThemeParentBackground(item->getHwnd(), hdc, rcDraw); - - if(M->isAero() || PluginConfig.m_WinVerMajor >= 6) { - stateId = (fIsActiveItem ? PBS_PRESSED : PBS_HOT); - CMimAPI::m_pfnDrawThemeBackground(item->m_buttonControl->hThemeToolbar, hdc, 8, RBStateConvert2Flat(stateId), rcDraw, rcDraw); - } - else { - stateId = (fIsActiveItem ? PBS_PRESSED : PBS_HOT); - CMimAPI::m_pfnDrawThemeBackground(item->m_buttonControl->hThemeToolbar, hdc, TP_BUTTON, TBStateConvert2Flat(stateId), rcDraw, rcDraw); - } - } - } - else { - RECT *rcDraw = const_cast(rc); - if(!(id == IDC_SIDEBARUP || id == IDC_SIDEBARDOWN)) { - HBRUSH br = (stateId == PBS_HOT && !fIsActiveItem) ? ::GetSysColorBrush(COLOR_BTNSHADOW) : (fIsActiveItem || stateId == PBS_PRESSED ? ::GetSysColorBrush(COLOR_HOTLIGHT) : ::GetSysColorBrush(COLOR_3DFACE)); - ::FillRect(hdc, rc, br); - ::DrawEdge(hdc, rcDraw, (stateId == PBS_HOT && !fIsActiveItem) ? EDGE_ETCHED : (fIsActiveItem || stateId == PBS_PRESSED) ? EDGE_BUMP : EDGE_ETCHED, BF_RECT | BF_SOFT | BF_FLAT); - } - else { - ::FillRect(hdc, rc, stateId == PBS_HOT ? ::GetSysColorBrush(COLOR_HOTLIGHT) : ::GetSysColorBrush(COLOR_3DFACE)); - ::InflateRect(rcDraw, -2, 0); - ::DrawEdge(hdc, rcDraw, EDGE_ETCHED, BF_SOFT|BF_RECT|BF_FLAT); - } - } -} - -void __fastcall CSideBar::m_DefaultContentRenderer(const HDC hdc, const RECT *rcBox, - const CSideBarButton *item) -{ - UINT id = item->getID(); - const TWindowData* dat = item->getDat(); - int stateID = item->m_buttonControl->stateId; - - LONG cx = rcBox->right - rcBox->left; - LONG cy = rcBox->bottom - rcBox->top; - - if(id == IDC_SIDEBARUP || id == IDC_SIDEBARDOWN) { - ::DrawIconEx(hdc, (rcBox->left + rcBox->right) / 2 - 8, (rcBox->top + rcBox->bottom) / 2 - 8, id == IDC_SIDEBARUP ? PluginConfig.g_buttonBarIcons[26] : PluginConfig.g_buttonBarIcons[16], - 16, 16, 0, 0, DI_NORMAL); - if(!M->isAero() && stateID == PBS_HOT) - ::DrawEdge(hdc, const_cast(rcBox), BDR_INNER, BF_RECT | BF_SOFT | BF_FLAT); - } - else if(dat) - item->renderIconAndNick(hdc, rcBox); -} - -/** - * content renderer for the advanced side bar button layout. includes - * avatars - */ -void __fastcall CSideBar::m_AdvancedContentRenderer(const HDC hdc, const RECT *rcBox, - const CSideBarButton *item) -{ - UINT id = item->getID(); - const TWindowData* dat = item->getDat(); - int stateID = item->m_buttonControl->stateId; - - LONG cx = rcBox->right - rcBox->left; - LONG cy = rcBox->bottom - rcBox->top; - SIZE szFirstLine, szSecondLine; - - if(id == IDC_SIDEBARUP || id == IDC_SIDEBARDOWN) - m_DefaultContentRenderer(hdc, rcBox, item); - else if(dat) { - RECT rc = *rcBox; - - if(dat->ace && dat->ace->hbmPic) { // we have an avatar - double dNewHeight, dNewWidth; - LONG maxHeight = cy - 8; - bool fFree = false; - - Utils::scaleAvatarHeightLimited(dat->ace->hbmPic, dNewWidth, dNewHeight, maxHeight); - - HBITMAP hbmResized = CSkin::ResizeBitmap(dat->ace->hbmPic, dNewWidth, dNewHeight, fFree); - HDC dc = CreateCompatibleDC(hdc); - HBITMAP hbmOld = reinterpret_cast(::SelectObject(dc, hbmResized)); - - LONG xOff = (cx - maxHeight) + (maxHeight - (LONG)dNewWidth) / 2 - 4; - LONG yOff = (cy - (LONG)dNewHeight) / 2; - - CMimAPI::m_MyAlphaBlend(hdc, xOff, yOff, (LONG)dNewWidth, (LONG)dNewHeight, dc, 0, 0, (LONG)dNewWidth, (LONG)dNewHeight, CSkin::m_default_bf); - ::SelectObject(dc, hbmOld); - if(hbmResized != dat->ace->hbmPic) - ::DeleteObject(hbmResized); - ::DeleteDC(dc); - rc.right -= (maxHeight + 6); - } - - /* - * calculate metrics based on font configuration. Determine if we have enough - * space for both lines - */ - - rc.left += 3; - HFONT hOldFont = reinterpret_cast(::SelectObject(hdc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_NICK])); - ::GetTextExtentPoint32A(hdc, "A", 1, &szFirstLine); - ::SelectObject(hdc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_STATUS]); - ::GetTextExtentPoint32A(hdc, "A", 1, &szSecondLine); - szSecondLine.cy = max(szSecondLine.cy, 18); - - LONG required = szFirstLine.cy + szSecondLine.cy; - bool fSecondLine = (required < cy ? true : false); - - DWORD dtFlags = DT_SINGLELINE | DT_WORD_ELLIPSIS | DT_END_ELLIPSIS | (!fSecondLine ? DT_VCENTER : 0); - - ::SelectObject(hdc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_NICK]); - rc.top++; - ::SetBkMode(hdc, TRANSPARENT); - CSkin::RenderText(hdc, dat->hThemeIP, dat->cache->getNick(), &rc, - dtFlags, CSkin::m_glowSize, CInfoPanel::m_ipConfig.clrs[IPFONTID_NICK]); - - if(fSecondLine) { - int iSize; - HICON hIcon = dat->cache->getIcon(iSize); - - /* - * TODO support larger icons at a later time. This side bar button - * could use 32x32 icons as well. - */ - - rc.top = rc.bottom - szSecondLine.cy - 2; - ::DrawIconEx(hdc, rc.left, rc.top + (rc.bottom - rc.top) / 2 - 8, hIcon, 16, 16, 0, 0, DI_NORMAL); - rc.left += 18; - ::SelectObject(hdc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_STATUS]); - CSkin::RenderText(hdc, dat->hThemeIP, dat->szStatus, &rc, - dtFlags | DT_VCENTER, CSkin::m_glowSize, CInfoPanel::m_ipConfig.clrs[IPFONTID_STATUS]); - } - ::SelectObject(hdc, hOldFont); - } -} - -/** - * measure callback for the advanced sidebar button layout (vertical mode - * with variable height buttons) - */ -const SIZE& __fastcall CSideBar::m_measureAdvancedVertical(CSideBarButton* item) -{ - const TWindowData* dat = item->getDat(); - - SIZE sz = {0}; - - if(dat) { - SIZE szFirstLine, szSecondLine; - - if(dat->ace && dat->ace->hbmPic) - sz.cy = item->getLayout()->width; - - HDC dc = ::GetDC(dat->hwnd); - - HFONT hOldFont = reinterpret_cast(::SelectObject(dc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_NICK])); - ::GetTextExtentPoint32(dc, dat->cache->getNick(), lstrlen(dat->cache->getNick()), &szFirstLine); - ::SelectObject(dc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_STATUS]); - ::GetTextExtentPoint32(dc, dat->szStatus, lstrlen(dat->szStatus), &szSecondLine); - ::SelectObject(dc, hOldFont); - ReleaseDC(dat->hwnd, dc); - - szSecondLine.cx += 18; // icon space - - sz.cy += max(szFirstLine.cx + 4, szSecondLine.cx + 4); - sz.cy += 2; - } - item->setSize(sz); - return(item->getSize()); -} -- cgit v1.2.3