From b8146d3bc3aba3fb58d86f4d985b88863b5d19a3 Mon Sep 17 00:00:00 2001 From: "Michael Z. Kadaner" Date: Sun, 9 Jul 2023 17:30:10 -0700 Subject: [PATCH] Work in progress --- far/vmenu.cpp | 49 +++++++++++++++++++++---------------------------- far/vmenu.hpp | 1 + 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/far/vmenu.cpp b/far/vmenu.cpp index 0d085eb937..2aa918ab7e 100644 --- a/far/vmenu.cpp +++ b/far/vmenu.cpp @@ -2013,7 +2013,7 @@ void VMenu::DisplayObject() if (!CheckFlags(VMENU_DISABLEDRAWBACKGROUND) && !CheckFlags(VMENU_LISTBOX)) { - // BUGBUG, dead code + // BUGBUG, dead code -- 2023-07-08 MZK: Is it though? I've got here when pressed hotkey of "Select search area" combobox on "find file" dialog. if (m_BoxType==SHORT_DOUBLE_BOX || m_BoxType==SHORT_SINGLE_BOX) { @@ -2086,6 +2086,14 @@ void VMenu::DrawTitles() const } } +rectangle VMenu::GetClientRect() const noexcept +{ + if (m_BoxType == NO_BOX) + return m_Where; + + return { m_Where.left + 1, m_Where.top + 1, m_Where.right - 1, m_Where.bottom - 1 }; +} + void VMenu::ShowMenu() { const auto ServiceAreaSize = GetServiceAreaSize(); @@ -2097,12 +2105,11 @@ void VMenu::ShowMenu() return; } + // 2023-07-09 MZK: Do we need this? Why? if (CheckFlags(VMENU_LISTBOX)) { if (!GetShowItemCount()) - { SetScreen(m_Where, L' ', Colors[VMenuColorBody]); - } if (m_BoxType!=NO_BOX) Box(m_Where, Colors[VMenuColorBox], m_BoxType); @@ -2113,32 +2120,16 @@ void VMenu::ShowMenu() if (GetShowItemCount() <= 0) return; - wchar_t BoxChar[2]{}; - - switch (m_BoxType) - { - case NO_BOX: - *BoxChar=L' '; - break; - - case SINGLE_BOX: - case SHORT_SINGLE_BOX: - *BoxChar=BoxSymbols[BS_V1]; - break; - - case DOUBLE_BOX: - case SHORT_DOUBLE_BOX: - *BoxChar=BoxSymbols[BS_V2]; - break; - } - if (CheckFlags(VMENU_AUTOHIGHLIGHT)) AssignHighlights(CheckFlags(VMENU_REVERSEHIGHLIGHT)); + const auto ClientRect{ GetClientRect() }; + int VisualSelectPos = GetVisualPos(SelectPos); int VisualTopPos = GetVisualPos(TopPos); // коррекция Top`а + // 2023-07-09 MZK: What is it? Should it be ClientRect.height() instead of m_Where.height()? if (VisualTopPos+GetShowItemCount() >= m_Where.height() - 1 && VisualSelectPos == GetShowItemCount()-1) { VisualTopPos--; @@ -2147,11 +2138,11 @@ void VMenu::ShowMenu() VisualTopPos=0; } - VisualTopPos = std::min(VisualTopPos, GetShowItemCount() - (m_Where.height() - 2 - (m_BoxType == NO_BOX ? 2 : 0))); + VisualTopPos = std::min(VisualTopPos, GetShowItemCount() - (ClientRect.height() - 4)); - if (VisualSelectPos > VisualTopPos + (m_Where.height() - 1 - (m_BoxType == NO_BOX? 0 : 2))) + if (VisualSelectPos > VisualTopPos + (ClientRect.height() - 1)) { - VisualTopPos = VisualSelectPos - (m_Where.height() - 1 - (m_BoxType == NO_BOX? 0 : 2)); + VisualTopPos = VisualSelectPos - (ClientRect.height() - 1); } if (VisualSelectPos < VisualTopPos) @@ -2170,10 +2161,10 @@ void VMenu::ShowMenu() if (TopPos<0) TopPos=0; - for (int Y = m_Where.top + (m_BoxType == NO_BOX? 0 : 1), I = TopPos; Y < m_Where.bottom + (m_BoxType == NO_BOX? 1 : 0); ++Y, ++I) - { - GotoXY(m_Where.left, Y); + string LineBuffer(MaxLineWidth, L' '); + for (int Y = ClientRect.top, I = TopPos; Y <= ClientRect.bottom; ++Y, ++I) + { if (I < static_cast(Items.size())) { if (!ItemIsVisible(Items[I])) @@ -2182,6 +2173,7 @@ void VMenu::ShowMenu() continue; } + GotoXY(m_Where.left, Y); if (Items[I].Flags&LIF_SEPARATOR) { int SepWidth = m_Where.width(); @@ -2391,6 +2383,7 @@ void VMenu::ShowMenu() } else { + GotoXY(m_Where.left, Y); if (m_BoxType!=NO_BOX) { SetColor(Colors[VMenuColorBox]); diff --git a/far/vmenu.hpp b/far/vmenu.hpp index 386dd2d3b5..633f2b68c2 100644 --- a/far/vmenu.hpp +++ b/far/vmenu.hpp @@ -320,6 +320,7 @@ class VMenu final: public Modal //корректировка текущей позиции и флагов SELECTED void UpdateSelectPos(); void EnableFilter(bool Enable); + rectangle GetClientRect()const noexcept; size_t Text(string_view Str) const; size_t Text(wchar_t Char) const;