diff --git a/sources/include/cage-engine/guiComponents.h b/sources/include/cage-engine/guiComponents.h index 6a92431d..9bd9ad6d 100644 --- a/sources/include/cage-engine/guiComponents.h +++ b/sources/include/cage-engine/guiComponents.h @@ -79,15 +79,15 @@ namespace cage enum class TooltipCloseConditionEnum : uint32 { - Instant, // the tooltip is closed as soon as the cursor moves - Modal, // the tooltip acts as a modal window and is closed only when the cursor moves outside of the tooltip - Never, // the application is responsible for closing the tooltip by removing the entity + Instant, // closes as soon as cursor moves + Modal, // acts as a modal window and is closed when the cursor moves far away from the tooltip + Never, // the application is responsible for closing the tooltip (by removing the entity) }; enum class TooltipPlacementEnum : uint32 { Corner, // corner of the tooltip positioned at the cursor - Center, + Center, // center of the whole screen Manual, }; @@ -104,7 +104,7 @@ namespace cage { using Tooltip = Delegate; Tooltip tooltip; - uint64 delay = 500000; // duration to hold mouse over the widget before showing the tooltip + uint64 delay = 500000; // duration to hold cursor over the widget before showing the tooltip bool enableForDisabled = false; }; diff --git a/sources/libengine/gui/tooltips.cpp b/sources/libengine/gui/tooltips.cpp index d20745cb..b1d82d7c 100644 --- a/sources/libengine/gui/tooltips.cpp +++ b/sources/libengine/gui/tooltips.cpp @@ -25,6 +25,30 @@ namespace cage return r; return nullptr; } + + // test of B is descendant of A + bool isDescendantOf(const HierarchyItem *a, const HierarchyItem *b) + { + if (a == b) + return true; + for (const auto &it : a->children) + if (isDescendantOf(+it, b)) + return true; + return false; + } + + void closeAllExceptSequenceWith(GuiImpl *impl, Entity *ent) + { + const HierarchyItem *k = findHierarchy(+impl->root, ent); + for (auto &it : impl->ttData) + { + if (it.closeCondition == TooltipCloseConditionEnum::Never) + continue; + if (const HierarchyItem *h = findHierarchy(+impl->root, it.rect)) + if (!isDescendantOf(h, k)) + it.removing = true; + } + } } void GuiImpl::updateTooltips() @@ -95,7 +119,7 @@ namespace cage if ( [&]() { - for (const auto &tt : ttData) + for (const TooltipData &tt : ttData) if (tt.invoker == ent) return true; return false; @@ -111,12 +135,12 @@ namespace cage tt.rect = tt.tooltip; tt.anchor = outputMouse; c.tooltip(tt); - if (tt.placement != TooltipPlacementEnum::Manual) - needsReposition = true; if (!tt.tooltip->has()) tt.tooltip->value().skinIndex = 3; + closeAllExceptSequenceWith(this, ent); ttData.push_back(std::move(tt)); ttHasMovedSinceLast = false; + needsReposition = true; } catch (...) { @@ -131,8 +155,10 @@ namespace cage if (needsReposition) { prepareImplGeneration(); // regenerate the whole hierarchy to calculate the requested sizes - for (auto &it : ttData) + for (TooltipData &it : ttData) { + if (it.placement == TooltipPlacementEnum::Manual) + continue; if (const HierarchyItem *h = findHierarchy(+root, it.tooltip)) { Entity *f = entityMgr->createUnique(); @@ -151,8 +177,8 @@ namespace cage corner[1] = 1; // avoid centering the tooltip under the cursor f->value().alignment = (it.anchor - s * (Vec2(corner) * 0.5 + 0.5)) / (outputSize - s); f->value().alignment += -17 * Vec2(corner) / outputSize; + break; } - break; case TooltipPlacementEnum::Center: f->value().alignment = (it.anchor - s * Vec2(0.5)) / (outputSize - s); break;