Mercurial > foo_out_sdl
comparison foosdk/sdk/libPPUI/CListControl-Cells.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 |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #include "stdafx.h" | |
| 2 #include "CListControl.h" | |
| 3 #include "CListControlHeaderImpl.h" | |
| 4 #include "CListControl-Cells.h" | |
| 5 #include "PaintUtils.h" | |
| 6 #include "GDIUtils.h" | |
| 7 #include <vsstyle.h> | |
| 8 #include "InPlaceEdit.h" | |
| 9 #include "DarkMode.h" | |
| 10 | |
| 11 #define PRETEND_CLASSIC_THEME 0 | |
| 12 | |
| 13 | |
| 14 #if PRETEND_CLASSIC_THEME | |
| 15 #define IsThemePartDefined(A,B,C) false | |
| 16 #endif | |
| 17 | |
| 18 LONG CListCell::AccRole() { | |
| 19 return ROLE_SYSTEM_LISTITEM; | |
| 20 } | |
| 21 | |
| 22 void RenderCheckbox( HTHEME theme, CDCHandle dc, CRect rcCheckBox, unsigned stateFlags, bool bRadio ) { | |
| 23 | |
| 24 const int part = bRadio ? BP_RADIOBUTTON : BP_CHECKBOX; | |
| 25 | |
| 26 const bool bDisabled = (stateFlags & CListCell::cellState_disabled) != 0; | |
| 27 const bool bPressed = (stateFlags & CListCell::cellState_pressed ) != 0; | |
| 28 const bool bHot = ( stateFlags & CListCell::cellState_hot ) != 0; | |
| 29 | |
| 30 if (theme != NULL && IsThemePartDefined(theme, part, 0)) { | |
| 31 int state = 0; | |
| 32 if (bDisabled) { | |
| 33 state = bPressed ? CBS_CHECKEDDISABLED : CBS_UNCHECKEDDISABLED; | |
| 34 } else if ( bHot ) { | |
| 35 state = bPressed ? CBS_CHECKEDHOT : CBS_UNCHECKEDHOT; | |
| 36 } else { | |
| 37 state = bPressed ? CBS_CHECKEDNORMAL : CBS_UNCHECKEDNORMAL; | |
| 38 } | |
| 39 | |
| 40 CSize size; | |
| 41 if (SUCCEEDED(GetThemePartSize(theme, dc, part, state, rcCheckBox, TS_TRUE, &size))) { | |
| 42 if (size.cx <= rcCheckBox.Width() && size.cy <= rcCheckBox.Height()) { | |
| 43 CRect rc = rcCheckBox; | |
| 44 rc.left += ( rc.Width() - size.cx ) / 2; | |
| 45 rc.top += ( rc.Height() - size.cy ) / 2; | |
| 46 rc.right = rc.left + size.cx; | |
| 47 rc.bottom = rc.top + size.cy; | |
| 48 DrawThemeBackground(theme, dc, part, state, rc, &rc); | |
| 49 return; | |
| 50 } | |
| 51 } | |
| 52 } | |
| 53 | |
| 54 auto DPI = QueryContextDPI(dc); | |
| 55 CSize size(MulDiv(13, DPI.cx, 96), MulDiv(13, DPI.cy, 96)); | |
| 56 CSize sizeBig = rcCheckBox.Size(); | |
| 57 if (sizeBig.cx >= size.cx && sizeBig.cy >= size.cy) { | |
| 58 CPoint center = rcCheckBox.CenterPoint(); | |
| 59 rcCheckBox.left = center.x - size.cx / 2; rcCheckBox.right = rcCheckBox.left + size.cx; | |
| 60 rcCheckBox.top = center.y - size.cy / 2; rcCheckBox.bottom = rcCheckBox.top + size.cy; | |
| 61 } | |
| 62 | |
| 63 int stateEx = bRadio ? DFCS_BUTTONRADIO : DFCS_BUTTONCHECK; | |
| 64 if ( bPressed ) stateEx |= DFCS_CHECKED; | |
| 65 if ( bDisabled ) stateEx |= DFCS_INACTIVE; | |
| 66 else if ( bHot ) stateEx |= DFCS_HOT; | |
| 67 DrawFrameControl(dc, rcCheckBox, DFC_BUTTON, stateEx); | |
| 68 } | |
| 69 | |
| 70 void RenderButton( HTHEME theme, CDCHandle dc, CRect rcButton, CRect rcUpdate, uint32_t cellState ) { | |
| 71 | |
| 72 const int part = BP_PUSHBUTTON; | |
| 73 | |
| 74 enum { | |
| 75 stNormal = PBS_NORMAL, | |
| 76 stHot = PBS_HOT, | |
| 77 stDisabled = PBS_DISABLED, | |
| 78 stPressed = PBS_PRESSED, | |
| 79 }; | |
| 80 | |
| 81 int state = 0; | |
| 82 if (cellState & CListCell::cellState_disabled) state = stDisabled; | |
| 83 if ( cellState & CListCell::cellState_pressed ) state = stPressed; | |
| 84 else if ( cellState & CListCell::cellState_hot ) state = stHot; | |
| 85 else state = stNormal; | |
| 86 | |
| 87 CRect rcClient = rcButton; | |
| 88 | |
| 89 if (theme != NULL && IsThemePartDefined(theme, part, 0)) { | |
| 90 DrawThemeBackground(theme, dc, part, state, rcClient, &rcUpdate); | |
| 91 } else { | |
| 92 int stateEx = DFCS_BUTTONPUSH; | |
| 93 switch (state) { | |
| 94 case stPressed: stateEx |= DFCS_PUSHED; break; | |
| 95 case stDisabled: stateEx |= DFCS_INACTIVE; break; | |
| 96 } | |
| 97 DrawFrameControl(dc, rcClient, DFC_BUTTON, stateEx); | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 bool CListCell::ApplyTextStyle( LOGFONT & font, double scale, uint32_t ) { | |
| 102 if ( scale != 1.0 ) { | |
| 103 font.lfHeight = pfc::rint32( font.lfHeight * scale ); | |
| 104 return true; | |
| 105 } else { | |
| 106 return false; | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 void CListCell_Text::DrawContent( DrawContentArg_t const & arg ) { | |
| 111 const auto fgWas = arg.dc.GetTextColor(); | |
| 112 CDCHandle dc = arg.dc; | |
| 113 if ((arg.cellState & cellState_disabled) != 0 && arg.allowColors) { | |
| 114 dc.SetTextColor(DarkMode::GetSysColor(COLOR_GRAYTEXT, arg.darkMode)); | |
| 115 } | |
| 116 | |
| 117 CRect clip = arg.rcText; | |
| 118 | |
| 119 if (arg.imageRenderer && clip.Width() > clip.Height() ) { | |
| 120 CRect rcImage = clip; rcImage.right = rcImage.left + clip.Height(); | |
| 121 arg.imageRenderer(dc, rcImage); | |
| 122 clip.left = rcImage.right; | |
| 123 } | |
| 124 | |
| 125 const t_uint32 format = PaintUtils::DrawText_TranslateHeaderAlignment(arg.hdrFormat); | |
| 126 dc.DrawText( arg.text, (int)wcslen(arg.text), clip, format | DT_NOPREFIX | DT_END_ELLIPSIS | DT_SINGLELINE | DT_VCENTER ); | |
| 127 | |
| 128 dc.SetTextColor(fgWas); | |
| 129 } | |
| 130 | |
| 131 void CListCell_TextColors::DrawContent( DrawContentArg_t const & arg ) { | |
| 132 CDCHandle dc = arg.dc; | |
| 133 | |
| 134 CRect clip = arg.rcText; | |
| 135 | |
| 136 const uint32_t fgWas = dc.GetTextColor(); | |
| 137 | |
| 138 const t_uint32 format = PaintUtils::DrawText_TranslateHeaderAlignment(arg.hdrFormat); | |
| 139 const t_uint32 bk = dc.GetBkColor(); | |
| 140 const t_uint32 fg = fgWas; | |
| 141 const t_uint32 hl = (arg.allowColors ? arg.colorHighlight : fg); | |
| 142 const t_uint32 colors[3] = { PaintUtils::BlendColor(bk, fg, 33), fg, hl }; | |
| 143 | |
| 144 PaintUtils::TextOutColorsEx(dc, arg.text, clip, format, colors); | |
| 145 | |
| 146 dc.SetTextColor(fgWas); | |
| 147 } | |
| 148 | |
| 149 void CListCell_MultiText::DrawContent( DrawContentArg_t const & arg ) { | |
| 150 CDCHandle dc = arg.dc; | |
| 151 | |
| 152 const int textLen = (int) wcslen( arg.text ); | |
| 153 | |
| 154 CRect clip = arg.rcText; | |
| 155 | |
| 156 const t_uint32 format = PaintUtils::DrawText_TranslateHeaderAlignment(arg.hdrFormat) | DT_NOPREFIX | DT_VCENTER ; | |
| 157 | |
| 158 CRect rcDraw = clip; | |
| 159 dc.DrawText(arg.text, textLen, rcDraw, format | DT_CALCRECT); | |
| 160 auto txSize = rcDraw.Size(); | |
| 161 rcDraw = clip; | |
| 162 if ( txSize.cy < rcDraw.Height() ) { | |
| 163 int sub = rcDraw.Height() - txSize.cy; | |
| 164 rcDraw.top += sub/2; | |
| 165 rcDraw.bottom = rcDraw.top + txSize.cy; | |
| 166 } | |
| 167 dc.DrawText(arg.text, textLen, rcDraw, format); | |
| 168 } | |
| 169 | |
| 170 bool CListCell_Hyperlink::ApplyTextStyle( LOGFONT & font, double scale, uint32_t state ) { | |
| 171 bool rv = __super::ApplyTextStyle(font, scale, state); | |
| 172 | |
| 173 if ( state & cellState_hot ) { | |
| 174 font.lfUnderline = TRUE; | |
| 175 rv = true; | |
| 176 } | |
| 177 | |
| 178 return rv; | |
| 179 } | |
| 180 | |
| 181 HCURSOR CListCell_Hyperlink::HotCursor() { | |
| 182 return LoadCursor(NULL, IDC_HAND); | |
| 183 } | |
| 184 | |
| 185 LONG CListCell_Hyperlink::AccRole() { | |
| 186 return ROLE_SYSTEM_LINK; | |
| 187 } | |
| 188 | |
| 189 void CListCell_Hyperlink::DrawContent( DrawContentArg_t const & arg ) { | |
| 190 | |
| 191 CDCHandle dc = arg.dc; | |
| 192 | |
| 193 const uint32_t fgWas = dc.GetTextColor(); | |
| 194 | |
| 195 const t_uint32 format = PaintUtils::DrawText_TranslateHeaderAlignment(arg.hdrFormat); | |
| 196 if (arg.allowColors) dc.SetTextColor( arg.colorHighlight ); | |
| 197 // const t_uint32 bk = dc.GetBkColor(); | |
| 198 | |
| 199 CRect rc = arg.rcText; | |
| 200 dc.DrawText(arg.text, (int) wcslen(arg.text), rc, format | DT_NOPREFIX | DT_END_ELLIPSIS | DT_SINGLELINE | DT_VCENTER ); | |
| 201 | |
| 202 dc.SetTextColor(fgWas); | |
| 203 } | |
| 204 | |
| 205 LONG CListCell_Button::AccRole() { | |
| 206 return ROLE_SYSTEM_PUSHBUTTON; | |
| 207 } | |
| 208 | |
| 209 void CListCell_Button::DrawContent( DrawContentArg_t const & arg ) { | |
| 210 | |
| 211 CDCHandle dc = arg.dc; | |
| 212 | |
| 213 const bool bPressed = (arg.cellState & cellState_pressed) != 0; | |
| 214 const bool bHot = (arg.cellState & cellState_hot) != 0; | |
| 215 | |
| 216 | |
| 217 if ( !m_lite || bHot || bPressed ) { | |
| 218 RenderButton( arg.theme, dc, arg.rcHot, arg.rcHot, arg.cellState ); | |
| 219 } | |
| 220 | |
| 221 CRect clip = arg.rcText; | |
| 222 | |
| 223 dc.DrawText(arg.text, (int) wcslen(arg.text), clip, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_CENTER); | |
| 224 } | |
| 225 | |
| 226 bool CListCell_ButtonGlyph::ApplyTextStyle( LOGFONT & font, double scale, uint32_t state ) { | |
| 227 return __super::ApplyTextStyle(font, scale * 1.3, state); | |
| 228 } | |
| 229 | |
| 230 static CRect CheckBoxRect(CRect rc) { | |
| 231 if (rc.Width() > rc.Height()) { | |
| 232 rc.right = rc.left + rc.Height(); | |
| 233 } | |
| 234 return rc; | |
| 235 } | |
| 236 | |
| 237 LONG CListCell_Checkbox::AccRole() { | |
| 238 return m_radio ? ROLE_SYSTEM_RADIOBUTTON : ROLE_SYSTEM_CHECKBUTTON; | |
| 239 } | |
| 240 | |
| 241 CRect CListCell_Checkbox::HotRect( CRect rc ) { | |
| 242 return CheckBoxRect( rc ); | |
| 243 } | |
| 244 | |
| 245 void CListCell_Checkbox::DrawContent( DrawContentArg_t const & arg ) { | |
| 246 | |
| 247 CDCHandle dc = arg.dc; | |
| 248 | |
| 249 // const bool bPressed = (arg.cellState & cellState_pressed) != 0; | |
| 250 // const bool bHot = (arg.cellState & cellState_hot) != 0; | |
| 251 | |
| 252 | |
| 253 // CRect clip = arg.rcText; | |
| 254 | |
| 255 const uint32_t fgWas = dc.GetTextColor(); | |
| 256 | |
| 257 if (arg.subItemRect.Width() > arg.subItemRect.Height() ) { | |
| 258 CRect rcCheckbox = arg.subItemRect; | |
| 259 rcCheckbox.right = rcCheckbox.left + rcCheckbox.Height(); | |
| 260 RenderCheckbox(arg.theme, dc, rcCheckbox, arg.cellState, m_radio ); | |
| 261 CRect rcText = arg.subItemRect; | |
| 262 rcText.left = rcCheckbox.right; | |
| 263 if (arg.cellState & cellState_disabled) { | |
| 264 dc.SetTextColor(GetSysColor(COLOR_GRAYTEXT)); | |
| 265 } | |
| 266 | |
| 267 if (arg.imageRenderer && rcText.Width() > rcText.Height()) { | |
| 268 CRect rcImage = rcText; rcImage.right = rcImage.left + rcImage.Height(); | |
| 269 arg.imageRenderer(dc, rcImage); | |
| 270 rcText.left = rcImage.right; | |
| 271 } | |
| 272 | |
| 273 dc.DrawText(arg.text, (int) wcslen(arg.text), rcText, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_LEFT); | |
| 274 } else { | |
| 275 RenderCheckbox(arg.theme, dc, arg.subItemRect, arg.cellState, m_radio ); | |
| 276 } | |
| 277 | |
| 278 dc.SetTextColor(fgWas); | |
| 279 } | |
| 280 | |
| 281 void CListCell_Text_FixedColor::DrawContent(DrawContentArg_t const & arg) { | |
| 282 if (arg.allowColors) { | |
| 283 SetTextColorScope scope(arg.dc, m_col); | |
| 284 __super::DrawContent(arg); | |
| 285 } else { | |
| 286 __super::DrawContent(arg); | |
| 287 } | |
| 288 } | |
| 289 | |
| 290 uint32_t CListCell_Combo::EditFlags() { | |
| 291 return InPlaceEdit::KFlagCombo; | |
| 292 } | |
| 293 | |
| 294 void CListCell_Combo::DrawContent(DrawContentArg_t const & arg) { | |
| 295 CDCHandle dc = arg.dc; | |
| 296 | |
| 297 const bool bDisabled = (arg.cellState & CListCell::cellState_disabled) != 0; | |
| 298 const bool bPressed = (arg.cellState & cellState_pressed) != 0; | |
| 299 const bool bHot = (arg.cellState & cellState_hot) != 0; | |
| 300 | |
| 301 const int part = CP_DROPDOWNBUTTONRIGHT; | |
| 302 | |
| 303 const HTHEME theme = arg.theme; | |
| 304 | |
| 305 const int w = MulDiv(16, GetDeviceCaps(dc, LOGPIXELSX), 96); | |
| 306 CRect rcText = arg.rcText; | |
| 307 if (theme != NULL && IsThemePartDefined(theme, part, 0)) { | |
| 308 int state = CBXSR_NORMAL; | |
| 309 if (bDisabled) { | |
| 310 state = CBXSR_DISABLED; | |
| 311 } else if (bPressed) { | |
| 312 state = CBXSR_PRESSED; | |
| 313 } else if (bHot) { | |
| 314 state = CBXSR_HOT; | |
| 315 } | |
| 316 | |
| 317 CSize size; | |
| 318 CRect rcCombo = arg.subItemRect; | |
| 319 if (w < rcCombo.Width()) { | |
| 320 rcCombo.left = rcCombo.right - w; | |
| 321 DrawThemeBackground(theme, dc, part, state, rcCombo, &rcCombo); | |
| 322 if (rcCombo.left < rcText.right ) rcText.right = rcCombo.left; | |
| 323 } | |
| 324 } else { | |
| 325 CRect rcCombo = arg.subItemRect; | |
| 326 if (w < rcCombo.Width()) { | |
| 327 rcCombo.left = rcCombo.right - w; | |
| 328 if (rcCombo.left < rcText.right) rcText.right = rcCombo.left; | |
| 329 | |
| 330 if (bHot) { | |
| 331 DrawFrameControl(dc, rcCombo, DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_HOT); | |
| 332 } | |
| 333 dc.DrawText(L"˅", 1, rcCombo, DT_VCENTER | DT_CENTER | DT_SINGLELINE); | |
| 334 } | |
| 335 | |
| 336 } | |
| 337 | |
| 338 DrawContentArg_t arg2 = arg; | |
| 339 arg2.rcText = rcText; | |
| 340 PFC_SINGLETON(CListCell_Text).DrawContent(arg2); | |
| 341 } | |
| 342 | |
| 343 LONG CListCell_Combo::AccRole() { | |
| 344 return ROLE_SYSTEM_DROPLIST; | |
| 345 } |
