Mercurial > foo_out_sdl
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #include "stdafx.h" | |
| 2 #include "CEditWithButtons.h" | |
| 3 | |
| 4 | |
| 5 void CEditWithButtons::AddMoreButton(std::function<void()> f) { | |
| 6 AddButton(L"more", f, nullptr, L"\x2026"); | |
| 7 } | |
| 8 void CEditWithButtons::AddClearButton(const wchar_t * clearVal, bool bHandleEsc) { | |
| 9 std::wstring clearValCopy(clearVal); | |
| 10 auto handler = [this, clearValCopy] { | |
| 11 this->SetWindowText(clearValCopy.c_str()); | |
| 12 }; | |
| 13 auto condition = [clearValCopy](const wchar_t * txt) -> bool { | |
| 14 return clearValCopy != txt; | |
| 15 }; | |
| 16 // Present "clear" to accessibility APIs but actually draw a multiplication x sign | |
| 17 AddButton(L"clear", handler, condition, L"\x00D7"); | |
| 18 | |
| 19 if (bHandleEsc) { | |
| 20 this->onEscKey = handler; | |
| 21 } | |
| 22 | |
| 23 } | |
| 24 | |
| 25 void CEditWithButtons::AddButton(const wchar_t * str, handler_t handler, condition_t condition, const wchar_t * drawAlternateText) { | |
| 26 PFC_ASSERT(GetStyle() & WS_CLIPCHILDREN); | |
| 27 Button_t btn; | |
| 28 btn.handler = handler; | |
| 29 btn.title = str; | |
| 30 btn.condition = condition; | |
| 31 btn.visible = EvalCondition(btn, nullptr); | |
| 32 | |
| 33 if (drawAlternateText != nullptr) { | |
| 34 btn.titleDraw = drawAlternateText; | |
| 35 } | |
| 36 | |
| 37 m_buttons.push_back(std::move(btn)); | |
| 38 RefreshButtons(); | |
| 39 } | |
| 40 | |
| 41 CRect CEditWithButtons::RectOfButton(const wchar_t * text) { | |
| 42 for (auto i = m_buttons.begin(); i != m_buttons.end(); ++i) { | |
| 43 if (i->title == text && i->wnd != NULL) { | |
| 44 CRect rc; | |
| 45 if (i->wnd.GetWindowRect(rc)) return rc; | |
| 46 } | |
| 47 } | |
| 48 return CRect(); | |
| 49 } | |
| 50 | |
| 51 void CEditWithButtons::TabCycleButtons(HWND wnd) { | |
| 52 for (auto i = m_buttons.begin(); i != m_buttons.end(); ++i) { | |
| 53 if (i->wnd == wnd) { | |
| 54 if (IsShiftPressed()) { | |
| 55 // back | |
| 56 for (;; ) { | |
| 57 if (i == m_buttons.begin()) { | |
| 58 TabFocusThis(m_hWnd); break; | |
| 59 } else { | |
| 60 --i; | |
| 61 if (i->visible) { | |
| 62 TabFocusThis(i->wnd); | |
| 63 break; | |
| 64 } | |
| 65 } | |
| 66 } | |
| 67 } else { | |
| 68 // forward | |
| 69 for (;; ) { | |
| 70 ++i; | |
| 71 if (i == m_buttons.end()) { | |
| 72 TabFocusThis(m_hWnd); | |
| 73 TabFocusPrevNext(false); | |
| 74 break; | |
| 75 } else { | |
| 76 if (i->visible) { | |
| 77 TabFocusThis(i->wnd); | |
| 78 break; | |
| 79 } | |
| 80 } | |
| 81 } | |
| 82 } | |
| 83 | |
| 84 return; | |
| 85 } | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 | |
| 90 bool CEditWithButtons::ButtonWantTab(HWND wnd) { | |
| 91 if (IsShiftPressed()) return true; | |
| 92 if (m_buttons.size() == 0) return false; // should not be possible | |
| 93 auto last = m_buttons.rbegin(); | |
| 94 if (wnd == last->wnd) return false; // not for last button | |
| 95 return true; | |
| 96 } | |
| 97 bool CEditWithButtons::EvalCondition(Button_t & btn, const wchar_t * newText) { | |
| 98 if (!btn.condition) return true; | |
| 99 if (newText != nullptr) return btn.condition(newText); | |
| 100 TCHAR text[256] = {}; | |
| 101 GetWindowText(text, 256); | |
| 102 text[255] = 0; | |
| 103 return btn.condition(text); | |
| 104 } | |
| 105 void CEditWithButtons::RefreshConditions(const wchar_t * newText) { | |
| 106 bool changed = false; | |
| 107 for (auto i = m_buttons.begin(); i != m_buttons.end(); ++i) { | |
| 108 bool status = EvalCondition(*i, newText); | |
| 109 if (status != i->visible) { | |
| 110 i->visible = status; changed = true; | |
| 111 } | |
| 112 } | |
| 113 if (changed) { | |
| 114 Layout(); | |
| 115 } | |
| 116 } | |
| 117 | |
| 118 void CEditWithButtons::Layout(CSize size, CFontHandle fontSetMe) { | |
| 119 if (m_buttons.size() == 0) return; | |
| 120 | |
| 121 int walk = size.cx; | |
| 122 | |
| 123 HDWP dwp = BeginDeferWindowPos((int)m_buttons.size()); | |
| 124 for (auto iter = m_buttons.rbegin(); iter != m_buttons.rend(); ++iter) { | |
| 125 if (!iter->visible) { | |
| 126 if (::GetFocus() == iter->wnd) { | |
| 127 this->SetFocus(); | |
| 128 } | |
| 129 ::DeferWindowPos(dwp, iter->wnd, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOCOPYBITS); | |
| 130 continue; | |
| 131 } | |
| 132 | |
| 133 if (iter->wnd == NULL) { | |
| 134 auto* b = &iter->wnd; | |
| 135 b->Create(*this, NULL, iter->title.c_str()); | |
| 136 if (iter->titleDraw.length() > 0) b->DrawAlternateText(iter->titleDraw.c_str()); | |
| 137 CFontHandle font = fontSetMe; | |
| 138 if (font == NULL) font = GetFont(); | |
| 139 b->SetFont(font); | |
| 140 b->ClickHandler = iter->handler; | |
| 141 b->CtlColorHandler = [=](CDCHandle dc) -> HBRUSH { | |
| 142 return this->OnColorBtn(dc, NULL); | |
| 143 }; | |
| 144 b->TabCycleHandler = [=](HWND wnd) { | |
| 145 TabCycleButtons(wnd); | |
| 146 }; | |
| 147 b->WantTabCheck = [=](HWND wnd) -> bool { | |
| 148 return ButtonWantTab(wnd); | |
| 149 }; | |
| 150 if (!IsWindowEnabled()) b->EnableWindow(FALSE); | |
| 151 } else if (fontSetMe) { | |
| 152 iter->wnd.SetFont(fontSetMe); | |
| 153 } | |
| 154 | |
| 155 unsigned delta = MeasureButton(*iter); | |
| 156 int left = walk - delta; | |
| 157 | |
| 158 if (iter->wnd != NULL) { | |
| 159 CRect rc; | |
| 160 rc.top = 0; | |
| 161 rc.bottom = size.cy; | |
| 162 rc.left = left; | |
| 163 rc.right = walk; | |
| 164 ::DeferWindowPos(dwp, iter->wnd, NULL, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOCOPYBITS); | |
| 165 } | |
| 166 | |
| 167 walk = left; | |
| 168 } | |
| 169 EndDeferWindowPos(dwp); | |
| 170 this->SetMargins(0, size.cx - walk, EC_RIGHTMARGIN); | |
| 171 } | |
| 172 | |
| 173 unsigned CEditWithButtons::MeasureButton(Button_t const & button) { | |
| 174 if (m_fixedWidthAuto && m_fixedWidth == 0) { | |
| 175 CWindowDC dc(*this); | |
| 176 SelectObjectScope fontScope(dc, GetFont()); | |
| 177 SIZE sz = {}; | |
| 178 WIN32_OP_D( dc.GetTextExtent(L"#", 1, &sz) ); | |
| 179 m_fixedWidth = MulDiv(sz.cx, 3, 2); | |
| 180 } | |
| 181 if (m_fixedWidth != 0) return m_fixedWidth; | |
| 182 | |
| 183 return button.wnd.Measure(); | |
| 184 } | |
| 185 | |
| 186 void CEditWithButtons::OnSetFont(CFontHandle font, BOOL bRedraw) { | |
| 187 (void)bRedraw; | |
| 188 | |
| 189 if ( m_fixedWidthAuto ) m_fixedWidth = 0; // require re-calculation | |
| 190 | |
| 191 DefWindowProc(); | |
| 192 CRect rc; | |
| 193 if (GetClientRect(&rc)) { | |
| 194 Layout(rc.Size(), font); | |
| 195 } | |
| 196 } |
