diff --git a/far/dialog.cpp b/far/dialog.cpp index 7991b02fe5..01bbe1d87b 100644 --- a/far/dialog.cpp +++ b/far/dialog.cpp @@ -2032,8 +2032,8 @@ void Dialog::ShowDialog(size_t ID) if (Item.ListPtr) { // Перед отрисовкой спросим об изменении цветовых атрибутов - FarColor RealColors[std::to_underlying(vmenu_colors::COUNT)]{}; - FarDialogItemColors ListColors{ sizeof(ListColors), 0, std::to_underlying(vmenu_colors::COUNT), RealColors }; + vmenu_colors_t RealColors{}; + FarDialogItemColors ListColors{ sizeof(ListColors), 0, RealColors.size(), RealColors.data()}; Item.ListPtr->GetColors(&ListColors); if (DlgProc(DN_CTLCOLORDLGLIST,I,&ListColors)) @@ -3865,8 +3865,8 @@ int Dialog::SelectFromComboBox(DialogItemEx& CurItem, DlgEdit& EditLine) DlgProc(DN_DROPDOWNOPENED, m_FocusPos, ToPtr(1)); SetComboBoxPos(&CurItem); // Перед отрисовкой спросим об изменении цветовых атрибутов - FarColor RealColors[std::to_underlying(vmenu_colors::COUNT)]{}; - FarDialogItemColors ListColors{ sizeof(ListColors), 0, std::to_underlying(vmenu_colors::COUNT), RealColors }; + vmenu_colors_t RealColors{}; + FarDialogItemColors ListColors{ sizeof(ListColors), 0, RealColors.size(), RealColors.data()}; ComboBox->SetColors(nullptr); ComboBox->GetColors(&ListColors); diff --git a/far/vmenu.cpp b/far/vmenu.cpp index f1246cf402..4673858560 100644 --- a/far/vmenu.cpp +++ b/far/vmenu.cpp @@ -189,7 +189,7 @@ void MarkupSliceBoundaries(std::pair Segment, std::ranges::input_range { assert(Segment.first < Segment.second); - for (const auto Slice : Slices) + for (const auto& Slice : Slices) { if (Slice.first >= Slice.second) continue; @@ -2033,70 +2033,45 @@ void VMenu::Hide() SetMenuFlags(VMENU_UPDATEREQUIRED); } -void VMenu::DisplayObject() +namespace { - const auto Parent = GetDialog(); - if (Parent && !Parent->IsRedrawEnabled()) return; - ClearFlags(VMENU_UPDATEREQUIRED); - - if (CheckFlags(VMENU_REFILTERREQUIRED)!=0) - { - if (bFilterEnabled) - { - RestoreFilteredItems(); - if (!strFilter.empty()) - FilterStringUpdated(); - } - ClearFlags(VMENU_REFILTERREQUIRED); - } - - HideCursor(); + // Indices in the color array + enum class color_indices + { + Body = 0, // background + Box = 1, // border + Title = 2, // title - top and bottom + Text = 3, // item text + Highlight = 4, // hot key + Separator = 5, // separator + Selected = 6, // selected + HSelect = 7, // selected - HotKey + ScrollBar = 8, // scrollBar + Disabled = 9, // disabled + Arrows =10, // '«' & '»' normal + ArrowsSelect =11, // '«' & '»' selected + ArrowsDisabled =12, // '«' & '»' disabled + Grayed =13, // grayed + SelGrayed =14, // selected grayed + + COUNT // always the last - array dimension + }; - const auto BoxType{ CalculateBoxType() }; + static_assert(std::tuple_size_v == std::to_underlying(color_indices::COUNT)); - if (!CheckFlags(VMENU_LISTBOX) && !SaveScr) + [[nodiscard]] const FarColor& GetColor(const vmenu_colors_t& VMenuColors, color_indices ColorIndex) noexcept { - if (!CheckFlags(VMENU_DISABLEDRAWBACKGROUND) && !(BoxType==SHORT_DOUBLE_BOX || BoxType==SHORT_SINGLE_BOX)) - SaveScr = std::make_unique(rectangle{ m_Where.left - 2, m_Where.top - 1, m_Where.right + 4, m_Where.bottom + 2 }); - else - SaveScr = std::make_unique(rectangle{ m_Where.left, m_Where.top, m_Where.right + 2, m_Where.bottom + 1 }); + return VMenuColors[std::to_underlying(ColorIndex)]; } - if (!CheckFlags(VMENU_DISABLEDRAWBACKGROUND) && !CheckFlags(VMENU_LISTBOX)) + void SetColor(const vmenu_colors_t& VMenuColors, color_indices ColorIndex) { - // BUGBUG, dead code -- 2023-07-08 MZK: I've got here when pressed hotkey of "Select search area" combobox on "find file" dialog. - // It may be related to the CheckFlags(VMENU_DISABLEDRAWBACKGROUND) part of the condition only. Need to investigate. - - if (BoxType==SHORT_DOUBLE_BOX || BoxType==SHORT_SINGLE_BOX) - { - SetScreen(m_Where, L' ', GetColor(vmenu_colors::Body)); - Box(m_Where, GetColor(vmenu_colors::Box), BoxType); - } - else - { - if (BoxType!=NO_BOX) - SetScreen({ m_Where.left - 2, m_Where.top - 1, m_Where.right + 2, m_Where.bottom + 1 }, L' ', GetColor(vmenu_colors::Body)); - else - SetScreen(m_Where, L' ', GetColor(vmenu_colors::Body)); - - if (BoxType!=NO_BOX) - Box(m_Where, GetColor(vmenu_colors::Box), BoxType); - } - - //SetMenuFlags(VMENU_DISABLEDRAWBACKGROUND); + ::SetColor(GetColor(VMenuColors, ColorIndex)); } - if (!CheckFlags(VMENU_LISTBOX)) - DrawTitles(); - - DrawMenu(); -} - -namespace -{ struct item_color_indicies { - vmenu_colors Normal, Highlighted, HScroller; + color_indices Normal, Highlighted, HScroller; item_color_indicies(const MenuItemEx& CurItem) { @@ -2106,38 +2081,38 @@ namespace if (Disabled) { - Normal = vmenu_colors::Disabled; - Highlighted = vmenu_colors::Disabled; - HScroller = vmenu_colors::ArrowsDisabled; + Normal = color_indices::Disabled; + Highlighted = color_indices::Disabled; + HScroller = color_indices::ArrowsDisabled; return; } if (Selected) { - Normal = Grayed ? vmenu_colors::SelGrayed : vmenu_colors::Selected; - Highlighted = Grayed ? vmenu_colors::SelGrayed : vmenu_colors::HSelect; - HScroller = vmenu_colors::ArrowsSelect; + Normal = Grayed ? color_indices::SelGrayed : color_indices::Selected; + Highlighted = Grayed ? color_indices::SelGrayed : color_indices::HSelect; + HScroller = color_indices::ArrowsSelect; return; } - Normal = Grayed ? vmenu_colors::Grayed : vmenu_colors::Text; - Highlighted = Grayed ? vmenu_colors::Grayed : vmenu_colors::Highlight; - HScroller = vmenu_colors::Arrows; + Normal = Grayed ? color_indices::Grayed : color_indices::Text; + Highlighted = Grayed ? color_indices::Grayed : color_indices::Highlight; + HScroller = color_indices::Arrows; } }; - std::tuple GetItemCheckMark(const MenuItemEx& CurItem, item_color_indicies ColorIndices) noexcept + std::tuple GetItemCheckMark(const MenuItemEx& CurItem, item_color_indicies ColorIndices) noexcept { return { ColorIndices.Normal, !(CurItem.Flags & LIF_CHECKED) - ? L' ' - : !(CurItem.Flags & 0x0000FFFF) ? L'√' : static_cast(CurItem.Flags & 0x0000FFFF) + ? L' ' + : !(CurItem.Flags & 0x0000FFFF) ? L'√' : static_cast(CurItem.Flags & 0x0000FFFF) }; } - std::tuple GetItemSubMenu(const MenuItemEx& CurItem, item_color_indicies ColorIndices) noexcept + std::tuple GetItemSubMenu(const MenuItemEx& CurItem, item_color_indicies ColorIndices) noexcept { return { @@ -2146,7 +2121,7 @@ namespace }; } - std::tuple GetItemLeftHScroll(const bool NeedLeftHScroll, item_color_indicies ColorIndices) noexcept + std::tuple GetItemLeftHScroll(const bool NeedLeftHScroll, item_color_indicies ColorIndices) noexcept { return { @@ -2155,7 +2130,7 @@ namespace }; } - std::tuple GetItemRightHScroll(const bool NeedRightHScroll, item_color_indicies ColorIndices) noexcept + std::tuple GetItemRightHScroll(const bool NeedRightHScroll, item_color_indicies ColorIndices) noexcept { return { @@ -2165,6 +2140,65 @@ namespace } } +void VMenu::DisplayObject() +{ + const auto Parent = GetDialog(); + if (Parent && !Parent->IsRedrawEnabled()) return; + ClearFlags(VMENU_UPDATEREQUIRED); + + if (CheckFlags(VMENU_REFILTERREQUIRED)!=0) + { + if (bFilterEnabled) + { + RestoreFilteredItems(); + if (!strFilter.empty()) + FilterStringUpdated(); + } + ClearFlags(VMENU_REFILTERREQUIRED); + } + + HideCursor(); + + const auto BoxType{ CalculateBoxType() }; + + if (!CheckFlags(VMENU_LISTBOX) && !SaveScr) + { + if (!CheckFlags(VMENU_DISABLEDRAWBACKGROUND) && !(BoxType==SHORT_DOUBLE_BOX || BoxType==SHORT_SINGLE_BOX)) + SaveScr = std::make_unique(rectangle{ m_Where.left - 2, m_Where.top - 1, m_Where.right + 4, m_Where.bottom + 2 }); + else + SaveScr = std::make_unique(rectangle{ m_Where.left, m_Where.top, m_Where.right + 2, m_Where.bottom + 1 }); + } + + if (!CheckFlags(VMENU_DISABLEDRAWBACKGROUND) && !CheckFlags(VMENU_LISTBOX)) + { + // BUGBUG, dead code -- 2023-07-08 MZK: I've got here when pressed hotkey of "Select search area" combobox on "find file" dialog. + // It may be related to the CheckFlags(VMENU_DISABLEDRAWBACKGROUND) part of the condition only. Need to investigate. + + if (BoxType==SHORT_DOUBLE_BOX || BoxType==SHORT_SINGLE_BOX) + { + SetScreen(m_Where, L' ', GetColor(Colors, color_indices::Body)); + Box(m_Where, GetColor(Colors, color_indices::Box), BoxType); + } + else + { + if (BoxType!=NO_BOX) + SetScreen({ m_Where.left - 2, m_Where.top - 1, m_Where.right + 2, m_Where.bottom + 1 }, L' ', GetColor(Colors, color_indices::Body)); + else + SetScreen(m_Where, L' ', GetColor(Colors, color_indices::Body)); + + if (BoxType!=NO_BOX) + Box(m_Where, GetColor(Colors, color_indices::Box), BoxType); + } + + //SetMenuFlags(VMENU_DISABLEDRAWBACKGROUND); + } + + if (!CheckFlags(VMENU_LISTBOX)) + DrawTitles(); + + DrawMenu(); +} + void VMenu::DrawMenu() { const auto BoxType{ CalculateBoxType() }; @@ -2177,13 +2211,14 @@ void VMenu::DrawMenu() } // 2023-12-09 MZK: Do we need this? Why? - if (CheckFlags(VMENU_LISTBOX)) + // 2023-12-28 MZK: OK, at least combo box maybe refreshed without DisplayObject(); then vertical borders are garbled by separators. + if (CheckFlags(VMENU_LISTBOX | VMENU_COMBOBOX)) { if (!GetShowItemCount()) - SetScreen(m_Where, L' ', GetColor(vmenu_colors::Body)); + SetScreen(m_Where, L' ', GetColor(Colors, color_indices::Body)); if (BoxType!=NO_BOX) - Box(m_Where, GetColor(vmenu_colors::Box), BoxType); + Box(m_Where, GetColor(Colors, color_indices::Box), BoxType); DrawTitles(); } @@ -2208,7 +2243,7 @@ void VMenu::DrawMenu() if (I >= static_cast(Items.size())) { GotoXY(ClientRect.left, Y); - SetColor(vmenu_colors::Text); + SetColor(Colors, color_indices::Text); Text(BlankLine); continue; } @@ -2230,7 +2265,7 @@ void VMenu::DrawMenu() if (Layout.Scrollbar) { - SetColor(vmenu_colors::ScrollBar); + SetColor(Colors, color_indices::ScrollBar); ScrollBar(Layout.Scrollbar.value(), ClientRect.top, ClientRect.height(), VisualTopPos, GetShowItemCount()); } } @@ -2270,7 +2305,7 @@ void VMenu::DrawTitles() const WidthTitle = MaxTitleLength - 1; GotoXY(m_Where.left + (m_Where.width() - 2 - WidthTitle) / 2, m_Where.top); - SetColor(vmenu_colors::Title); + SetColor(Colors, color_indices::Title); Text(concat(L' ', string_view(strDisplayTitle).substr(0, WidthTitle), L' ')); } @@ -2283,7 +2318,7 @@ void VMenu::DrawTitles() const WidthTitle = MaxTitleLength - 1; GotoXY(m_Where.left + (m_Where.width() - 2 - WidthTitle) / 2, m_Where.bottom); - SetColor(vmenu_colors::Title); + SetColor(Colors, color_indices::Title); Text(concat(L' ', string_view(strBottomTitle).substr(0, WidthTitle), L' ')); } @@ -2343,7 +2378,7 @@ void VMenu::DrawSeparator(const size_t CurItemIndex, const int BoxType, const in ConnectSeparator(CurItemIndex, separator, BoxType); ApplySeparatorName(Items[CurItemIndex], separator); - SetColor(vmenu_colors::Separator); + SetColor(Colors, color_indices::Separator); GotoXY(m_Where.left, Y); Text(separator); } @@ -2394,7 +2429,7 @@ void VMenu::ApplySeparatorName(const MenuItemEx& CurItem, string& separator) con separator[NamePos + NameWidth] = L' '; } -void VMenu::DrawRegularItem(const MenuItemEx& CurItem, const item_layout& Layout, const int Y, std::vector& HighlightMarkup, string_view BlankLine) const +void VMenu::DrawRegularItem(const MenuItemEx& CurItem, const item_layout& Layout, const int Y, std::vector& HighlightMarkup, const string_view BlankLine) const { if (!Layout.Text) return; @@ -2436,19 +2471,19 @@ void VMenu::DrawRegularItem(const MenuItemEx& CurItem, const item_layout& Layout GotoXY(TextBegin, Y); for (const auto SliceEnd : HighlightMarkup) { - SetColor(CurColorIndex); + SetColor(Colors, CurColorIndex); Text(string_view{ ItemTextToDisplay.begin() + CurPos, ItemTextToDisplay.begin() + SliceEnd }); std::swap(CurColorIndex, AltColorIndex); CurPos = SliceEnd; } - SetColor(ColorIndices.Normal); + SetColor(Colors, ColorIndices.Normal); Text(BlankLine.substr(0, TextBegin + TextWidth - WhereX())); - const auto DrawDecorator = [&](const int X, std::tuple ColorAndChar) + const auto DrawDecorator = [&](const int X, std::tuple ColorAndChar) { GotoXY(X, Y); - SetColor(std::get(ColorAndChar)); + SetColor(Colors, std::get(ColorAndChar)); Text(std::get(ColorAndChar)); }; @@ -2669,7 +2704,7 @@ void VMenu::SetColors(const FarDialogItemColors *ColorsIn) { if (ColorsIn) { - std::copy_n(ColorsIn->Colors, std::min(std::size(Colors), ColorsIn->ColorsCount), Colors); + std::ranges::copy_n(ColorsIn->Colors, std::min(Colors.size(), ColorsIn->ColorsCount), Colors.begin()); } else { @@ -2678,11 +2713,11 @@ void VMenu::SetColors(const FarDialogItemColors *ColorsIn) if (CheckFlags(VMENU_DISABLED)) { - std::fill_n(Colors, std::to_underlying(vmenu_colors::COUNT), colors::PaletteColorToFarColor(StyleMenu? COL_WARNDIALOGDISABLED : COL_DIALOGDISABLED)); + std::ranges::fill(Colors, colors::PaletteColorToFarColor(StyleMenu? COL_WARNDIALOGDISABLED : COL_DIALOGDISABLED)); } else { - static const PaletteColors StdColor[2][3][std::to_underlying(vmenu_colors::COUNT)]= + static const PaletteColors StdColor[2][3][std::tuple_size_v] = { // Not VMENU_WARNDIALOG { @@ -2801,19 +2836,19 @@ void VMenu::SetColors(const FarDialogItemColors *ColorsIn) } }; - std::ranges::transform(StdColor[StyleMenu][TypeMenu], Colors, colors::PaletteColorToFarColor); + std::ranges::transform(StdColor[StyleMenu][TypeMenu], Colors.begin(), colors::PaletteColorToFarColor); } } } void VMenu::GetColors(FarDialogItemColors *ColorsOut) { - std::copy_n(Colors, std::min(std::size(Colors), ColorsOut->ColorsCount), ColorsOut->Colors); + std::ranges::copy_n(Colors.begin(), std::min(Colors.size(), ColorsOut->ColorsCount), ColorsOut->Colors); } void VMenu::SetOneColor(int Index, PaletteColors Color) { - if (Index < static_cast(std::size(Colors))) + if (0 <= Index && static_cast(Index) < Colors.size()) Colors[Index] = colors::PaletteColorToFarColor(Color); } @@ -3048,11 +3083,6 @@ size_t VMenu::CalculateMaxLineWidth() const return Text ? Text.value().second : 0; } -void VMenu::SetColor(vmenu_colors ColorIndex) const -{ - ::SetColor(GetColor(ColorIndex)); -} - size_t VMenu::Text(string_view const Str) const { return ::Text(Str, m_Where.width() - (WhereX() - m_Where.left)); diff --git a/far/vmenu.hpp b/far/vmenu.hpp index c12df1946c..712df91a5d 100644 --- a/far/vmenu.hpp +++ b/far/vmenu.hpp @@ -52,27 +52,11 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //---------------------------------------------------------------------------- -// Цветовые атрибуты - индексы в массиве цветов -enum class vmenu_colors -{ - Body = 0, // подложка - Box = 1, // рамка - Title = 2, // заголовок - верхний и нижний - Text = 3, // Текст пункта - Highlight = 4, // HotKey - Separator = 5, // separator - Selected = 6, // Выбранный - HSelect = 7, // Выбранный - HotKey - ScrollBar = 8, // ScrollBar - Disabled = 9, // Disabled - Arrows =10, // '<' & '>' обычные - ArrowsSelect =11, // '<' & '>' выбранные - ArrowsDisabled =12, // '<' & '>' Disabled - Grayed =13, // "серый" - SelGrayed =14, // выбранный "серый" - - COUNT, // всегда последняя - размерность массива -}; +class window; +class Dialog; +class SaveScreen; + +using vmenu_colors_t = std::array; enum VMENU_FLAGS { @@ -100,10 +84,6 @@ enum VMENU_FLAGS VMENU_COMBOBOXEVENTMOUSE = 31_bit, // посылать события мыши в диалоговую проц. для открытого комбобокса }; -class window; -class Dialog; -class SaveScreen; - struct menu_item { string Name; @@ -331,8 +311,6 @@ class VMenu final: public Modal void UpdateSelectPos(); void EnableFilter(bool Enable); - [[nodiscard]] const FarColor& GetColor(vmenu_colors ColorIndex) const noexcept { return Colors[std::to_underlying(ColorIndex)]; } - void SetColor(vmenu_colors ColorIndex) const; size_t Text(string_view Str) const; size_t Text(wchar_t Char) const; @@ -358,7 +336,7 @@ class VMenu final: public Modal std::vector Items; intptr_t ItemHiddenCount{}; intptr_t ItemSubMenusCount{}; - FarColor Colors[std::to_underlying(vmenu_colors::COUNT)]{}; + vmenu_colors_t Colors{}; bool bRightBtnPressed{}; UUID MenuId; };