Mercurial > foo_out_sdl
diff foosdk/sdk/libPPUI/CEditWithButtons.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/CEditWithButtons.cpp Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,196 @@ +#include "stdafx.h" +#include "CEditWithButtons.h" + + +void CEditWithButtons::AddMoreButton(std::function<void()> f) { + AddButton(L"more", f, nullptr, L"\x2026"); +} +void CEditWithButtons::AddClearButton(const wchar_t * clearVal, bool bHandleEsc) { + std::wstring clearValCopy(clearVal); + auto handler = [this, clearValCopy] { + this->SetWindowText(clearValCopy.c_str()); + }; + auto condition = [clearValCopy](const wchar_t * txt) -> bool { + return clearValCopy != txt; + }; + // Present "clear" to accessibility APIs but actually draw a multiplication x sign + AddButton(L"clear", handler, condition, L"\x00D7"); + + if (bHandleEsc) { + this->onEscKey = handler; + } + +} + +void CEditWithButtons::AddButton(const wchar_t * str, handler_t handler, condition_t condition, const wchar_t * drawAlternateText) { + PFC_ASSERT(GetStyle() & WS_CLIPCHILDREN); + Button_t btn; + btn.handler = handler; + btn.title = str; + btn.condition = condition; + btn.visible = EvalCondition(btn, nullptr); + + if (drawAlternateText != nullptr) { + btn.titleDraw = drawAlternateText; + } + + m_buttons.push_back(std::move(btn)); + RefreshButtons(); +} + +CRect CEditWithButtons::RectOfButton(const wchar_t * text) { + for (auto i = m_buttons.begin(); i != m_buttons.end(); ++i) { + if (i->title == text && i->wnd != NULL) { + CRect rc; + if (i->wnd.GetWindowRect(rc)) return rc; + } + } + return CRect(); +} + +void CEditWithButtons::TabCycleButtons(HWND wnd) { + for (auto i = m_buttons.begin(); i != m_buttons.end(); ++i) { + if (i->wnd == wnd) { + if (IsShiftPressed()) { + // back + for (;; ) { + if (i == m_buttons.begin()) { + TabFocusThis(m_hWnd); break; + } else { + --i; + if (i->visible) { + TabFocusThis(i->wnd); + break; + } + } + } + } else { + // forward + for (;; ) { + ++i; + if (i == m_buttons.end()) { + TabFocusThis(m_hWnd); + TabFocusPrevNext(false); + break; + } else { + if (i->visible) { + TabFocusThis(i->wnd); + break; + } + } + } + } + + return; + } + } +} + + +bool CEditWithButtons::ButtonWantTab(HWND wnd) { + if (IsShiftPressed()) return true; + if (m_buttons.size() == 0) return false; // should not be possible + auto last = m_buttons.rbegin(); + if (wnd == last->wnd) return false; // not for last button + return true; +} +bool CEditWithButtons::EvalCondition(Button_t & btn, const wchar_t * newText) { + if (!btn.condition) return true; + if (newText != nullptr) return btn.condition(newText); + TCHAR text[256] = {}; + GetWindowText(text, 256); + text[255] = 0; + return btn.condition(text); +} +void CEditWithButtons::RefreshConditions(const wchar_t * newText) { + bool changed = false; + for (auto i = m_buttons.begin(); i != m_buttons.end(); ++i) { + bool status = EvalCondition(*i, newText); + if (status != i->visible) { + i->visible = status; changed = true; + } + } + if (changed) { + Layout(); + } +} + +void CEditWithButtons::Layout(CSize size, CFontHandle fontSetMe) { + if (m_buttons.size() == 0) return; + + int walk = size.cx; + + HDWP dwp = BeginDeferWindowPos((int)m_buttons.size()); + for (auto iter = m_buttons.rbegin(); iter != m_buttons.rend(); ++iter) { + if (!iter->visible) { + if (::GetFocus() == iter->wnd) { + this->SetFocus(); + } + ::DeferWindowPos(dwp, iter->wnd, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOCOPYBITS); + continue; + } + + if (iter->wnd == NULL) { + auto* b = &iter->wnd; + b->Create(*this, NULL, iter->title.c_str()); + if (iter->titleDraw.length() > 0) b->DrawAlternateText(iter->titleDraw.c_str()); + CFontHandle font = fontSetMe; + if (font == NULL) font = GetFont(); + b->SetFont(font); + b->ClickHandler = iter->handler; + b->CtlColorHandler = [=](CDCHandle dc) -> HBRUSH { + return this->OnColorBtn(dc, NULL); + }; + b->TabCycleHandler = [=](HWND wnd) { + TabCycleButtons(wnd); + }; + b->WantTabCheck = [=](HWND wnd) -> bool { + return ButtonWantTab(wnd); + }; + if (!IsWindowEnabled()) b->EnableWindow(FALSE); + } else if (fontSetMe) { + iter->wnd.SetFont(fontSetMe); + } + + unsigned delta = MeasureButton(*iter); + int left = walk - delta; + + if (iter->wnd != NULL) { + CRect rc; + rc.top = 0; + rc.bottom = size.cy; + rc.left = left; + rc.right = walk; + ::DeferWindowPos(dwp, iter->wnd, NULL, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOCOPYBITS); + } + + walk = left; + } + EndDeferWindowPos(dwp); + this->SetMargins(0, size.cx - walk, EC_RIGHTMARGIN); +} + +unsigned CEditWithButtons::MeasureButton(Button_t const & button) { + if (m_fixedWidthAuto && m_fixedWidth == 0) { + CWindowDC dc(*this); + SelectObjectScope fontScope(dc, GetFont()); + SIZE sz = {}; + WIN32_OP_D( dc.GetTextExtent(L"#", 1, &sz) ); + m_fixedWidth = MulDiv(sz.cx, 3, 2); + } + if (m_fixedWidth != 0) return m_fixedWidth; + + return button.wnd.Measure(); +} + +void CEditWithButtons::OnSetFont(CFontHandle font, BOOL bRedraw) { + (void)bRedraw; + + if ( m_fixedWidthAuto ) m_fixedWidth = 0; // require re-calculation + + DefWindowProc(); + CRect rc; + if (GetClientRect(&rc)) { + Layout(rc.Size(), font); + } +}
