Skip to content

Commit

Permalink
Need further unification???
Browse files Browse the repository at this point in the history
  • Loading branch information
MKadaner committed Jan 19, 2024
1 parent bf7f436 commit 6bb1bbb
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 147 deletions.
257 changes: 111 additions & 146 deletions far/vmenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,6 @@ struct menu_layout
}
};

// TBD: Remove it
// Must be in the TU scope because it is forward-declared in VMenu.hpp
enum class item_hscroll_policy
{
cling_to_edge,
bound,
bound_stick_to_left
};

namespace
{
MenuItemEx far_list_to_menu_item(const FarListItem& FItem)
Expand Down Expand Up @@ -291,6 +282,13 @@ namespace
return !(Item.Flags & (LIF_HIDDEN | LIF_FILTERED));
}

enum class item_hscroll_policy
{
cling_to_edge,
bound,
bound_stick_to_left
};

std::pair<int, int> item_hpos_limits(const item_hscroll_policy Policy, const int ItemLength, const int TextAreaWidth) noexcept
{
assert(ItemLength > 0);
Expand Down Expand Up @@ -361,6 +359,33 @@ namespace
bool were_right_items() { return MinRightOffset != NonValue; }
};

int get_item_smart_hpos(const int NewHPos, const int ItemLength, const int TextAreaWidth)
{
return NewHPos >= 0 ? NewHPos : TextAreaWidth - ItemLength + NewHPos + 1;
}

bool set_item_hpos(
MenuItemEx& Item,
std::regular_invocable<int /*ItemLength*/> auto const GetNewHPos,
const bool ShowAmpersand,
const int TextAreaWidth,
const item_hscroll_policy Policy)
{
if (Item.Flags & LIF_SEPARATOR) return false;

const auto ItemLength{ static_cast<int>(ShowAmpersand ? visual_string_length(Item.Name) : HiStrlen(Item.Name)) };
if (ItemLength <= 0) return false;

const auto HPosLimits{ item_hpos_limits(Policy, ItemLength, TextAreaWidth) };
const auto ClampedHPos = std::clamp(GetNewHPos(ItemLength), HPosLimits.first, HPosLimits.second);

if (Item.HPos == ClampedHPos)
return false;

Item.HPos = ClampedHPos;
return true;
}

int adjust_en_bloc_shift(const int Shift, const int EnBlocHScrollDiscriminator, const int TextAreaWidth)
{
assert(TextAreaWidth > 0);
Expand All @@ -374,23 +399,32 @@ namespace
return Shift;
}

bool set_item_hpos(MenuItemEx& Item, std::regular_invocable<int /*ItemLength*/> auto const GetNewHPos, const bool ShowAmpersand, const int TextAreaWidth, const item_hscroll_policy Policy)
auto set_all_items_en_bloc_hpos(
std::vector<MenuItemEx>& Items,
std::regular_invocable<const MenuItemEx&> auto const GetNewHPos,
const bool ShowAmpersand)
{
const auto ItemLength{ static_cast<int>(ShowAmpersand ? visual_string_length(Item.Name) : HiStrlen(Item.Name)) };
bool NeedRedraw{};
list_hpos_discriminator Discriminator;

// TBD: (TextAreaWidth <= 0) not needed?
if (ItemLength <= 0 || TextAreaWidth <= 0) return false;
for (auto& Item : Items)
{
if (Item.Flags & LIF_SEPARATOR) continue;

if (Item.Flags & LIF_SEPARATOR) return false;
const auto ItemLength{ static_cast<int>(ShowAmpersand ? visual_string_length(Item.Name) : HiStrlen(Item.Name)) };
if (ItemLength <= 0) continue;

const auto HPosLimits{ item_hpos_limits(Policy, ItemLength, TextAreaWidth) };
const auto ClampedHPos = std::clamp(GetNewHPos(ItemLength), HPosLimits.first, HPosLimits.second);
const auto NewHPos{ GetNewHPos(Item) };

if (Item.HPos == ClampedHPos)
return false;
Discriminator.accumulate(NewHPos, ItemLength);

Item.HPos = ClampedHPos;
return true;
if (Item.HPos == NewHPos) continue;

Item.HPos = NewHPos;
NeedRedraw = true;
}

return std::tuple{ NeedRedraw, Discriminator.classify() };
}

// Indices in the color array
Expand Down Expand Up @@ -2141,16 +2175,6 @@ int VMenu::VisualPosToReal(int VPos) const
return ItemIterator != Items.cend()? ItemIterator - Items.cbegin() : -1;
}



/*
* TBD: Remove
HScrollEnBlocMode
? item_hscroll_policy::unbound
: CheckFlags(VMENU_ENABLEALIGNANNOTATIONS) ? item_hscroll_policy::cling_to_edge : item_hscroll_policy::bound_stick_to_left))
*/


bool VMenu::SetAllItemsSmartHPos(const int NewHPos)
{
const auto TextAreaWidth{ CalculateTextAreaWidth() };
Expand All @@ -2167,7 +2191,7 @@ bool VMenu::SetAllItemsSmartHPos(const int NewHPos)
{
if (set_item_hpos(
Item,
[=](int ItemLength) { return NewHPos >= 0 ? NewHPos : TextAreaWidth - ItemLength + NewHPos + 1; },
[=](int ItemLength) { return get_item_smart_hpos(NewHPos, ItemLength, TextAreaWidth); },
CheckFlags(VMENU_SHOWAMPERSAND),
TextAreaWidth,
Policy))
Expand All @@ -2180,6 +2204,28 @@ bool VMenu::SetAllItemsSmartHPos(const int NewHPos)
return NeedRedraw;
}

bool VMenu::ShiftAllItemsHPosLimited(const int Shift, const int TextAreaWidth)
{
const auto Policy{ CheckFlags(VMENU_ENABLEALIGNANNOTATIONS) ? item_hscroll_policy::cling_to_edge : item_hscroll_policy::bound_stick_to_left };

bool NeedRedraw{};

for (auto& Item : Items)
{
if (set_item_hpos(
Item,
[&](int) { return Item.HPos + Shift; },
CheckFlags(VMENU_SHOWAMPERSAND),
TextAreaWidth,
Policy))
{
NeedRedraw = true;
}
}

return NeedRedraw;
}

bool VMenu::SetCurItemSmartHPos(const int NewHPos)
{
const auto TextAreaWidth{ CalculateTextAreaWidth() };
Expand All @@ -2189,30 +2235,18 @@ bool VMenu::SetCurItemSmartHPos(const int NewHPos)

auto& Item{ Items[SelectPos] };

if (!set_item_hpos(
if (set_item_hpos(
Item,
[=](int ItemLength) { return NewHPos >= 0 ? NewHPos : TextAreaWidth - ItemLength + NewHPos + 1; },
[=](int ItemLength) { return get_item_smart_hpos(NewHPos, ItemLength, TextAreaWidth); },
CheckFlags(VMENU_SHOWAMPERSAND),
TextAreaWidth,
Policy))
{
return false;
SetMenuFlags(VMENU_UPDATEREQUIRED);
return true;
}

SetMenuFlags(VMENU_UPDATEREQUIRED);
return true;
}

bool VMenu::ShiftAllItemsHPos(const int Shift)
{
const auto TextAreaWidth{ CalculateTextAreaWidth() };
if (TextAreaWidth <= 0) return false;

const auto ShiftAllItemsHPosFunc{ EnBlocHScrollMode ? &VMenu::ShiftAllItemsHPosEnBlock : &VMenu::ShiftAllItemsHPosLimited };
if (!(this->*ShiftAllItemsHPosFunc)(Shift, TextAreaWidth)) return false;

SetMenuFlags(VMENU_UPDATEREQUIRED);
return true;
return false;
}

bool VMenu::ShiftCurItemHPos(const int Shift)
Expand All @@ -2224,11 +2258,18 @@ bool VMenu::ShiftCurItemHPos(const int Shift)

auto& Item{ Items[SelectPos] };

if (!set_item_hpos(Item, [&](int) { return Item.HPos + Shift; }, CheckFlags(VMENU_SHOWAMPERSAND), TextAreaWidth, Policy))
return false;
if (set_item_hpos(
Item,
[&](int) { return Item.HPos + Shift; },
CheckFlags(VMENU_SHOWAMPERSAND),
TextAreaWidth,
Policy))
{
SetMenuFlags(VMENU_UPDATEREQUIRED);
return true;
}

SetMenuFlags(VMENU_UPDATEREQUIRED);
return true;
return false;
}

bool VMenu::AlignAnnotations()
Expand All @@ -2237,28 +2278,13 @@ bool VMenu::AlignAnnotations()
if (TextAreaWidth <= 0 || TextAreaWidth + 2 <= 0) return false;
const auto AlignPos{ (TextAreaWidth + 2) / 4 };

bool NeedRedraw{};
list_hpos_discriminator Discriminator;

for (auto& Item : Items)
{
if (Item.Flags & LIF_SEPARATOR) continue;

const auto ItemLength{ static_cast<int>(CheckFlags(VMENU_SHOWAMPERSAND) ? visual_string_length(Item.Name) : HiStrlen(Item.Name)) };
if (ItemLength <= 0) continue;

const auto NewHPos{ Item.Annotations.empty() ? 0 : AlignPos - Item.Annotations.front().first };

Discriminator.accumulate(NewHPos, ItemLength);

if (Item.HPos == NewHPos) continue;

Item.HPos = NewHPos;
NeedRedraw = true;
}
const auto[NeedRedraw, HScrollDiscriminator] = set_all_items_en_bloc_hpos(
Items,
[=](const auto& Item) { return Item.Annotations.empty() ? 0 : AlignPos - Item.Annotations.front().first; },
CheckFlags(VMENU_SHOWAMPERSAND));

EnBlocHScrollMode = true;
EnBlocHScrollDiscriminator = Discriminator.classify();
EnBlocHScrollDiscriminator = HScrollDiscriminator;

if (NeedRedraw) SetMenuFlags(VMENU_UPDATEREQUIRED);
return NeedRedraw;
Expand All @@ -2271,91 +2297,30 @@ bool VMenu::ShiftAllItemsHPosEnBlock(const int Shift, const int TextAreaWidth)
: Shift;
if (!AdjustedShift) return false;

bool NeedRedraw{};
list_hpos_discriminator Discriminator;

for (auto& Item : Items)
{
if (Item.Flags & LIF_SEPARATOR) continue;

const auto ItemLength{ static_cast<int>(CheckFlags(VMENU_SHOWAMPERSAND) ? visual_string_length(Item.Name) : HiStrlen(Item.Name)) };
if (ItemLength <= 0) continue;
const auto [NeedRedraw, HScrollDiscriminator] = set_all_items_en_bloc_hpos(
Items,
[=](const auto& Item) { return Item.HPos + AdjustedShift; },
CheckFlags(VMENU_SHOWAMPERSAND));

const auto NewHPos{ Item.HPos + AdjustedShift };

Discriminator.accumulate(NewHPos, ItemLength);

if (Item.HPos == NewHPos) continue;

Item.HPos = NewHPos;
NeedRedraw = true;
}

EnBlocHScrollDiscriminator = Discriminator.classify();
EnBlocHScrollDiscriminator = HScrollDiscriminator;
return NeedRedraw;
}

bool VMenu::ShiftAllItemsHPosLimited(const int Shift, const int TextAreaWidth)
bool VMenu::ShiftAllItemsHPos(const int Shift)
{
const auto Policy{ CheckFlags(VMENU_ENABLEALIGNANNOTATIONS) ? item_hscroll_policy::cling_to_edge : item_hscroll_policy::bound_stick_to_left };

bool NeedRedraw{};
const auto TextAreaWidth{ CalculateTextAreaWidth() };
if (TextAreaWidth <= 0) return false;

for (auto& Item : Items)
const auto ShiftAllItemsHPosFunc{ EnBlocHScrollMode ? &VMenu::ShiftAllItemsHPosEnBlock : &VMenu::ShiftAllItemsHPosLimited };
if ((this->*ShiftAllItemsHPosFunc)(Shift, TextAreaWidth))
{
if (set_item_hpos(Item, [&](int) { return Item.HPos + Shift; }, CheckFlags(VMENU_SHOWAMPERSAND), TextAreaWidth, Policy))
NeedRedraw = true;
SetMenuFlags(VMENU_UPDATEREQUIRED);
return true;
}

return NeedRedraw;
return false;
}

// TBD: Remove
//bool VMenu::SetItemAbsoluteHPos(MenuItemEx& Item, const int NewHPos, const int ItemLength, const int TextAreaWidth, const item_hscroll_policy Policy)
//{
// // TBD: (TextAreaWidth <= 0) not needed?
// if (ItemLength <= 0 || TextAreaWidth <= 0) return false;
//
// if (Item.Flags & LIF_SEPARATOR) return false;
//
// const auto HPosLimits{ item_hpos_limits(Policy, ItemLength, TextAreaWidth) };
// const auto ClampedHPos = std::clamp(NewHPos, HPosLimits.first, HPosLimits.second);
//
// if (Item.HPos == ClampedHPos)
// return false;
//
// Item.HPos = ClampedHPos;
// return true;
//}

//bool VMenu::SetItemAbsoluteHPos(MenuItemEx& Item, const int NewHPos, const int TextAreaWidth, const item_hscroll_policy Policy)
//{
// return set_item_hpos(Item, [=](int) { return NewHPos; }, CheckFlags(VMENU_SHOWAMPERSAND), TextAreaWidth, Policy);
// //return set_item_hpos(Item, NewHPos, CheckFlags(VMENU_SHOWAMPERSAND), TextAreaWidth, Policy);
//}

//bool VMenu::SetItemSmartHPos(MenuItemEx& Item, const int NewHPos, const int TextAreaWidth, const item_hscroll_policy Policy)
//{
// return set_item_hpos(Item, [=](int ItemLength) { return NewHPos >= 0 ? NewHPos : TextAreaWidth - ItemLength + NewHPos + 1; }, CheckFlags(VMENU_SHOWAMPERSAND), TextAreaWidth, Policy);
//}

// TBD: Remove
//bool VMenu::ShiftItemHPos(MenuItemEx& Item, const int Shift, const int TextAreaWidth, const item_hscroll_policy Policy)
//{
// return SetItemAbsoluteHPos(Item, Item.HPos + Shift, TextAreaWidth, Policy);
//}
//
//bool VMenu::ShiftAllItemsHPos(const int Shift, const item_hscroll_policy Policy)
//{
// const auto TextAreaWidth{ CalculateTextAreaWidth() };
//
// return std::accumulate(Items.begin(), Items.end(), false, [&](const bool NeedRedraw, MenuItemEx& Item)
// {
// return ShiftItemHPos(Item, Shift, TextAreaWidth, Policy)
// || NeedRedraw;
// });
//}

void VMenu::Show()
{
const auto BoxType{ menu_layout::get_box_type(*this) };
Expand Down
1 change: 0 additions & 1 deletion far/vmenu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ struct MenuItemEx: menu_item
};

struct menu_layout;
enum class item_hscroll_policy;

struct SortItemParam
{
Expand Down

0 comments on commit 6bb1bbb

Please sign in to comment.