diff foosdk/sdk/libPPUI/CListControlTruncationTooltipImpl.cpp @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/foosdk/sdk/libPPUI/CListControlTruncationTooltipImpl.cpp	Mon Jan 05 02:15:46 2026 -0500
@@ -0,0 +1,219 @@
+#include "stdafx.h"
+#include "CListControl.h"
+#include "PaintUtils.h"
+#include "DarkMode.h"
+
+LRESULT CListControlTruncationTooltipImpl::OnTTShow(int,LPNMHDR,BOOL&) {
+	SetTimer(KTooltipTimer,KTooltipTimerDelay);
+	return 0;
+}
+LRESULT CListControlTruncationTooltipImpl::OnTTPop(int,LPNMHDR,BOOL&) {
+	KillTimer(KTooltipTimer);
+	return 0;
+}
+LRESULT CListControlTruncationTooltipImpl::OnTTGetDispInfo(int,LPNMHDR p_hdr,BOOL&) {
+	LPNMTTDISPINFO info = (LPNMTTDISPINFO)p_hdr;
+
+	info->lpszText = const_cast<TCHAR*>(this->m_tooltipText.get_ptr());
+	info->hinst = 0;
+	info->uFlags = 0;
+		
+	return 0;
+}
+
+LRESULT CListControlTruncationTooltipImpl::OnDestroyPassThru(UINT,WPARAM,LPARAM,BOOL& bHandled) {
+	if (m_tooltip.m_hWnd != NULL) m_tooltip.DestroyWindow();
+	KillTimer(KTooltipTimer);
+	bHandled = FALSE; return 0;
+}
+
+CListControlTruncationTooltipImpl::CListControlTruncationTooltipImpl() 
+	: m_toolinfo()
+	, m_tooltipRect(0,0,0,0)
+{
+}
+
+
+
+void CListControlTruncationTooltipImpl::TooltipRemove() {
+	m_tooltipRect = CRect(0,0,0,0);
+	if (m_tooltip.m_hWnd != NULL) {
+		m_tooltip.TrackActivate(&m_toolinfo,FALSE);
+	}
+}
+
+void CListControlTruncationTooltipImpl::TooltipRemoveCheck() {
+	CPoint pt; ;
+	if (GetCursorPos(&pt) && ScreenToClient(&pt)) {
+		TooltipRemoveCheck( MAKELPARAM( pt.x, pt.y ) );
+	}
+}
+void CListControlTruncationTooltipImpl::TooltipRemoveCheck(LPARAM pos) {
+	if (!m_tooltipRect.IsRectEmpty()) {
+		CPoint pt(pos);
+		if (!GetClientRectHook().PtInRect(pt)) {
+			TooltipRemove();
+		} else {
+			ClientToScreen(&pt);
+			if (!m_tooltipRect.PtInRect(pt)) {
+				TooltipRemove();
+			}
+		}
+	}
+}
+
+LRESULT CListControlTruncationTooltipImpl::OnTimer(UINT,WPARAM wp,LPARAM,BOOL& bHandled) {
+	switch(wp) {
+		case KTooltipTimer:
+			TooltipRemoveCheck();
+			return 0;
+		default:
+			bHandled = FALSE;
+			return 0;
+	}
+}
+
+LRESULT CListControlTruncationTooltipImpl::OnMouseMovePassThru(UINT,WPARAM,LPARAM lp,BOOL& bHandled) {
+	TooltipRemoveCheck(lp);
+	{
+		TRACKMOUSEEVENT ev = {sizeof(ev)};
+		ev.dwFlags = TME_HOVER;
+		ev.hwndTrack = *this;
+		ev.dwHoverTime = HOVER_DEFAULT;
+		TrackMouseEvent(&ev);
+	}
+	bHandled = FALSE;
+	return 0;
+}
+
+
+bool CListControlTruncationTooltipImpl::IsRectPartiallyObscuredAbs(CRect const & r) const {
+	const CRect cl = GetVisibleRectAbs();
+	return r.right > cl.right || r.top < cl.top || r.bottom > cl.bottom;
+}
+
+bool CListControlTruncationTooltipImpl::IsRectFullyVisibleAbs(CRect const & r) {
+	const CRect cl = GetVisibleRectAbs();
+	return r.left >= cl.left && r.right <= cl.right && r.top >= cl.top && r.bottom <= cl.bottom;
+}
+
+bool CListControlTruncationTooltipImpl::GetTooltipData(CPoint pt, pfc::string_base & outText, CRect & outRC, CFontHandle & outFont) const {
+	t_size item;
+	if (ItemFromPointAbs(pt, item)) {
+		PFC_ASSERT(item < GetItemCount());
+		const CRect itemRectAbs = this->GetItemRectAbs(item);
+		/*if (this->IsHeaderEnabled()) */{
+			t_uint32 cbase = 0;
+			auto orderArray = this->GetColumnOrderArray();
+			for (t_size _cwalk = 0; _cwalk < orderArray.size(); ++_cwalk) {
+				const t_size cwalk = orderArray[_cwalk];
+				//const TColumnRuntime & col = m_columns[cwalk];
+
+				const t_uint32 width = GetSubItemWidth(cwalk);
+				if ((t_uint32)pt.x < cbase + width) {
+					t_uint32 estWidth = GetOptimalSubItemWidthSimple(item, cwalk);
+					CRect rc = itemRectAbs; rc.left = cbase; rc.right = cbase + estWidth;
+					if (estWidth > width || (IsRectPartiallyObscuredAbs(rc) && rc.PtInRect(pt))) {
+						pfc::string_formatter label, ccTemp;
+						if (GetSubItemText(item, cwalk, label)) {
+							PaintUtils::TextOutColors_StripCodes(ccTemp, label);
+							outFont = GetFont(); outRC = rc; outText = ccTemp;
+							return true;
+						}
+					}
+					break;
+				}
+				cbase += width;
+			}
+		}
+	} else if (GroupHeaderFromPointAbs2(pt, item)) {
+		CRect rc;
+		if (GetGroupHeaderRectAbs2(item, rc) && rc.PtInRect(pt)) {
+			const t_uint32 estWidth = GetOptimalGroupHeaderWidth2( item );
+			CRect rcText = rc; rcText.right = rcText.left + estWidth;
+			if (estWidth > (t_uint32)rc.Width() || (IsRectPartiallyObscuredAbs(rcText) && rcText.PtInRect(pt))) {
+				pfc::string_formatter label;
+				if (GetGroupHeaderText2(item, label)) {
+					outFont = GetGroupHeaderFont(); outRC = rc; outText = label; 
+					return true;
+				}
+			}
+		}
+	}
+	return false;
+}
+LRESULT CListControlTruncationTooltipImpl::OnHover(UINT,WPARAM wp,LPARAM lp,BOOL&) {
+	if (!m_tooltipRect.IsRectEmpty()) {
+		return 0;
+	}
+	if (wp & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON)) return 0;
+	
+	const CPoint pt = PointClientToAbs(CPoint(lp));
+
+	CFontHandle font;
+	CRect rc;
+	pfc::string8 text;
+	if ( this->GetTooltipData(pt, text, rc, font) ) {
+		this->m_tooltipFont = font;
+		// Gets stuck if the text is very long!
+		if (text.length() < 4096) {
+			TooltipActivateAbs(text, rc);
+		}
+	}
+	return 0;
+}
+
+void CListControlTruncationTooltipImpl::TooltipActivateAbs(const char * label, const CRect & rect)  {
+	CRect temp = RectAbsToClient(rect);
+	ClientToScreen(temp);
+	TooltipActivate(label,temp);
+}
+void CListControlTruncationTooltipImpl::TooltipActivate(const char * label, const CRect & rect) {
+	if (rect.IsRectEmpty()) return;
+	if (m_tooltip.m_hWnd == NULL) {
+		try {
+			InitTooltip();
+		} catch(std::exception const & e) {
+			(void) e;
+			// console::complain("Tooltip initialization failure", e);
+			return;
+		}
+	}
+	
+	m_tooltipText.convert( EscapeTooltipText( label ) );
+
+	m_tooltipRect = rect;
+
+	TooltipUpdateFont();
+	m_tooltip.TrackPosition(rect.left,rect.top);
+	m_tooltip.TrackActivate(&m_toolinfo,TRUE);
+}
+
+void CListControlTruncationTooltipImpl::TooltipUpdateFont() {
+	if (m_tooltip.m_hWnd != NULL) {
+		if (m_tooltipFont) {
+			m_tooltip.SetFont(m_tooltipFont);
+		}
+	}
+}
+
+void CListControlTruncationTooltipImpl::InitTooltip() {
+	m_tooltipRect = CRect(0,0,0,0);
+	WIN32_OP( m_tooltip.Create(NULL,NULL,NULL,WS_POPUP,WS_EX_TRANSPARENT) );
+	m_toolinfo.cbSize = sizeof(m_toolinfo);
+	m_toolinfo.uFlags = TTF_TRACK | TTF_IDISHWND | TTF_ABSOLUTE | TTF_TRANSPARENT;
+	m_toolinfo.hwnd = *this;
+	m_toolinfo.uId = 0;
+	m_toolinfo.lpszText = LPSTR_TEXTCALLBACK;
+	m_toolinfo.hinst = GetThisModuleHandle();
+	WIN32_OP_D( m_tooltip.AddTool(&m_toolinfo) );
+
+	if ( GetDarkMode() ) DarkMode::ApplyDarkThemeCtrl(m_tooltip, true );
+}
+
+void CListControlTruncationTooltipImpl::RefreshDarkMode() {
+	__super::RefreshDarkMode();
+	if (m_tooltip) {
+		DarkMode::ApplyDarkThemeCtrl(m_tooltip, GetDarkMode()  );
+	}
+}