···8989 {
9090 new TooltipSpriteText("this text has a tooltip!"),
9191 new InstantTooltipSpriteText("this text has an instant tooltip!"),
9292- new TooltipSpriteText("this one too!"),
9393- new CustomTooltipSpriteText("this text has an empty tooltip!", string.Empty),
9494- new CustomTooltipSpriteText("this text has a nulled tooltip!", null),
9292+ new CustomTooltipSpriteText("this one is custom!"),
9393+ new TooltipSpriteText("this text has an empty tooltip!", string.Empty),
9494+ new TooltipSpriteText("this text has a nulled tooltip!", null),
9595 new TooltipTextbox
9696 {
9797 Text = "with real time updates!",
···143143 ttc.Add(makeBox(Anchor.BottomRight));
144144 }
145145146146- private class CustomTooltipSpriteText : Container, IHasTooltip
146146+ private class CustomTooltipSpriteText : Container, IHasCustomTooltip
147147 {
148148- private readonly string tooltipText;
149149-150150- public string TooltipText => tooltipText;
148148+ public object TooltipContent { get; }
151149152152- public CustomTooltipSpriteText(string displayedText, string tooltipText)
150150+ public CustomTooltipSpriteText(string displayedContent, object tooltipContent = null)
153151 {
154154- this.tooltipText = tooltipText;
152152+ TooltipContent = tooltipContent ?? displayedContent;
155153156154 AutoSizeAxes = Axes.Both;
157155 Children = new[]
158156 {
159157 new SpriteText
160158 {
161161- Text = displayedText,
159159+ Text = displayedContent,
162160 }
163161 };
164162 }
163163+164164+ public ITooltip GetCustomTooltip() => new TooltipContainer.Tooltip { Colour = Color4.Blue };
165165 }
166166167167- private class TooltipSpriteText : CustomTooltipSpriteText
167167+ private class TooltipSpriteText : Container, IHasTooltip
168168 {
169169- public TooltipSpriteText(string tooltipText)
170170- : base(tooltipText, tooltipText)
169169+ private readonly string tooltipContent;
170170+171171+ public string TooltipText => tooltipContent;
172172+173173+ public TooltipSpriteText(string displayedContent)
174174+ : this(displayedContent, displayedContent)
171175 {
172176 }
177177+178178+ public TooltipSpriteText(string displayedContent, string tooltipContent)
179179+ {
180180+ this.tooltipContent = tooltipContent;
181181+182182+ AutoSizeAxes = Axes.Both;
183183+ Children = new[]
184184+ {
185185+ new SpriteText
186186+ {
187187+ Text = displayedContent,
188188+ }
189189+ };
190190+ }
173191 }
174192175175- private class InstantTooltipSpriteText : CustomTooltipSpriteText, IHasAppearDelay
193193+ private class InstantTooltipSpriteText : TooltipSpriteText, IHasAppearDelay
176194 {
177177- public InstantTooltipSpriteText(string tooltipText)
178178- : base(tooltipText, tooltipText)
195195+ public InstantTooltipSpriteText(string tooltipContent)
196196+ : base(tooltipContent, tooltipContent)
179197 {
180198 }
181199
+1-1
osu.Framework/Graphics/Cursor/IHasAppearDelay.cs
···66 /// <summary>
77 /// A tooltip which provides a custom delay until it appears, override the <see cref="TooltipContainer"/>-wide default.
88 /// </summary>
99- public interface IHasAppearDelay : IHasTooltip
99+ public interface IHasAppearDelay : ITooltipContentProvider
1010 {
1111 /// <summary>
1212 /// The delay until the tooltip should be displayed.
···77 /// Implementing this interface allows the implementing <see cref="Drawable"/> to display a custom tooltip if it is the child of a <see cref="TooltipContainer"/>.
88 /// Keep in mind that tooltips can only be displayed by a <see cref="TooltipContainer"/> if the <see cref="Drawable"/> implementing <see cref="IHasCustomTooltip"/> has <see cref="Drawable.HandlePositionalInput"/> set to true.
99 /// </summary>
1010- public interface IHasCustomTooltip : IHasTooltip
1010+ public interface IHasCustomTooltip : ITooltipContentProvider
1111 {
1212 /// <summary>
1313 /// The custom tooltip that should be displayed.
1414 /// </summary>
1515 /// <returns>The custom tooltip that should be displayed.</returns>
1616 ITooltip GetCustomTooltip();
1717+1818+ /// <summary>
1919+ /// Tooltip text that shows when hovering the drawable.
2020+ /// </summary>
2121+ object TooltipContent { get; }
1722 }
1823}
+2-2
osu.Framework/Graphics/Cursor/IHasTooltip.cs
···77 /// Implementing this interface allows the implementing <see cref="Drawable"/> to display a tooltip if it is the child of a <see cref="TooltipContainer"/>. The tooltip used is
88 /// dependent on the implementation of the <see cref="TooltipContainer.CreateTooltip"/> method of the <see cref="TooltipContainer"/> containing this <see cref="Drawable"/>.
99 /// </summary>
1010- public interface IHasTooltip : IDrawable
1010+ public interface IHasTooltip : ITooltipContentProvider
1111 {
1212 /// <summary>
1313- /// Tooltip that shows when hovering the drawable.
1313+ /// Tooltip text that shows when hovering the drawable.
1414 /// </summary>
1515 string TooltipText { get; }
1616 }
+9
osu.Framework/Graphics/Cursor/ITooltip.cs
···11// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
22// See the LICENCE file in the repository root for full licence text.
3344+using System;
45using osuTK;
5667namespace osu.Framework.Graphics.Cursor
···1314 /// <summary>
1415 /// The text to display on the tooltip.
1516 /// </summary>
1717+ [Obsolete]
1618 string TooltipText { set; }
1919+2020+ /// <summary>
2121+ /// Set new content be displayed on this tooltip.
2222+ /// </summary>
2323+ /// <param name="content">The content to be displayed.</param>
2424+ /// <returns>Whether this <see cref="ITooltip"/> can display the provided content.</returns>
2525+ bool SetContent(object content);
17261827 /// <summary>
1928 /// Refreshes the tooltip, updating potential non-text elements such as textures and colours.
···11+// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
22+// See the LICENCE file in the repository root for full licence text.
33+44+namespace osu.Framework.Graphics.Cursor
55+{
66+ /// <summary>
77+ /// Marker interface for interfaces that provide tooltip content.
88+ /// </summary>
99+ public interface ITooltipContentProvider : IDrawable
1010+ {
1111+ }
1212+}
+44-25
osu.Framework/Graphics/Cursor/TooltipContainer.cs
···1717 /// <summary>
1818 /// Displays Tooltips for all its children that inherit from the <see cref="IHasTooltip"/> or <see cref="IHasCustomTooltip"/> interfaces. Keep in mind that only children with <see cref="Drawable.HandlePositionalInput"/> set to true will be checked for their tooltips.
1919 /// </summary>
2020- public class TooltipContainer : CursorEffectContainer<TooltipContainer, IHasTooltip>, IHandleGlobalInput
2020+ public class TooltipContainer : CursorEffectContainer<TooltipContainer, ITooltipContentProvider>, IHandleGlobalInput
2121 {
2222 private readonly CursorContainer cursorContainer;
2323 private readonly ITooltip defaultTooltip;
···3838 /// </summary>
3939 protected virtual float AppearRadius => 20;
40404141- private IHasTooltip currentlyDisplayed;
4141+ private ITooltipContentProvider currentlyDisplayed;
42424343 /// <summary>
4444 /// Creates a new tooltip. Can be overridden to supply custom subclass of <see cref="Tooltip"/>.
4545 /// </summary>
4646 protected virtual ITooltip CreateTooltip() => new Tooltip();
47474848- private bool hasValidTooltip(IHasTooltip target) => !string.IsNullOrEmpty(target?.TooltipText);
4848+ private bool hasValidTooltip(ITooltipContentProvider target)
4949+ {
5050+ var targetContent = getTargetContent(target);
5151+5252+ if (targetContent is string strContent)
5353+ return !string.IsNullOrEmpty(strContent);
5454+5555+ return targetContent != null;
5656+ }
49575058 private readonly Container content;
5159 protected override Container<Drawable> Content => content;
···135143 public Vector2 Position;
136144 }
137145146146+ private object getTargetContent(ITooltipContentProvider target) => (target as IHasCustomTooltip)?.TooltipContent ?? (target as IHasTooltip)?.TooltipText;
147147+138148 protected override void Update()
139149 {
140150 base.Update();
141151142142- IHasTooltip target = findTooltipTarget();
152152+ ITooltipContentProvider target = findTooltipTarget();
143153144154 if (target != null && target != currentlyDisplayed)
145155 {
146156 currentlyDisplayed = target;
147157148148- var newTooltip = getTooltip(target);
158158+ if (CurrentTooltip?.SetContent(getTargetContent(target)) != true)
159159+ {
160160+ var newTooltip = getTooltip(target);
149161150150- if (newTooltip != CurrentTooltip)
151151- {
152162 RemoveInternal((Drawable)CurrentTooltip);
153163 CurrentTooltip = newTooltip;
154164 AddInternal((Drawable)newTooltip);
···161171 }
162172 }
163173174174+ protected override void UpdateAfterChildren()
175175+ {
176176+ base.UpdateAfterChildren();
177177+178178+ RefreshTooltip(CurrentTooltip, currentlyDisplayed);
179179+180180+ if (currentlyDisplayed != null && ShallHideTooltip(currentlyDisplayed))
181181+ hideTooltip();
182182+ }
183183+164184 private readonly List<TimedPosition> recentMousePositions = new List<TimedPosition>();
165185 private double lastRecordedPositionTime;
166186167167- private IHasTooltip lastCandidate;
187187+ private ITooltipContentProvider lastCandidate;
168188169189 /// <summary>
170190 /// Determines which drawable should currently receive a tooltip, taking into account
···172192 /// target is found.
173193 /// </summary>
174194 /// <returns>The tooltip target. null if no valid one is found.</returns>
175175- private IHasTooltip findTooltipTarget()
195195+ private ITooltipContentProvider findTooltipTarget()
176196 {
177197 // While we are dragging a tooltipped drawable we should show a tooltip for it.
178198 if (inputManager.DraggedDrawable is IHasTooltip draggedTarget)
179199 return hasValidTooltip(draggedTarget) ? draggedTarget : null;
180200181181- IHasTooltip targetCandidate = FindTargets().Find(t => t.TooltipText != null);
201201+ if (inputManager.DraggedDrawable is IHasCustomTooltip customDraggedTarget)
202202+ return customDraggedTarget;
203203+204204+ ITooltipContentProvider targetCandidate = FindTargets().Find(hasValidTooltip);
182205183206 // check this first - if we find no target candidate we still want to clear the recorded positions and update the lastCandidate.
184207 if (targetCandidate != lastCandidate)
···234257 /// </summary>
235258 /// <param name="tooltip">The tooltip that is refreshed.</param>
236259 /// <param name="tooltipTarget">The target of the tooltip.</param>
237237- protected virtual void RefreshTooltip(ITooltip tooltip, IHasTooltip tooltipTarget)
260260+ protected virtual void RefreshTooltip(ITooltip tooltip, ITooltipContentProvider tooltipTarget)
238261 {
239262 bool isValid = tooltipTarget != null && hasValidTooltip(tooltipTarget);
240263241264 if (isValid)
242265 {
243243- tooltip.TooltipText = tooltipTarget.TooltipText;
266266+ tooltip.SetContent(getTargetContent(tooltipTarget));
244267 tooltip.Refresh();
245268 }
246269···248271 tooltip.Move(computeTooltipPosition());
249272 }
250273251251- protected override void UpdateAfterChildren()
252252- {
253253- base.UpdateAfterChildren();
254254-255255- RefreshTooltip(CurrentTooltip, currentlyDisplayed);
256256-257257- if (currentlyDisplayed != null && ShallHideTooltip(currentlyDisplayed))
258258- hideTooltip();
259259- }
260260-261274 private void hideTooltip()
262275 {
263276 CurrentTooltip.Hide();
···269282 /// </summary>
270283 /// <param name="tooltipTarget">The target of the tooltip.</param>
271284 /// <returns>True if the currently visible tooltip should be hidden, false otherwise.</returns>
272272- protected virtual bool ShallHideTooltip(IHasTooltip tooltipTarget) => !hasValidTooltip(tooltipTarget) || !tooltipTarget.IsHovered && !tooltipTarget.IsDragged;
285285+ protected virtual bool ShallHideTooltip(ITooltipContentProvider tooltipTarget) => !hasValidTooltip(tooltipTarget) || !tooltipTarget.IsHovered && !tooltipTarget.IsDragged;
273286274274- private ITooltip getTooltip(IHasTooltip target) => (target as IHasCustomTooltip)?.GetCustomTooltip() ?? defaultTooltip;
287287+ private ITooltip getTooltip(ITooltipContentProvider target) => (target as IHasCustomTooltip)?.GetCustomTooltip() ?? defaultTooltip;
275288276289 /// <summary>
277290 /// The default tooltip. Simply displays its text on a gray background and performs no easing.
···285298 /// </summary>
286299 public virtual string TooltipText
287300 {
288288- set => text.Text = value;
301301+ set => SetContent(value);
302302+ }
303303+304304+ public bool SetContent(object content)
305305+ {
306306+ text.Text = content.ToString();
307307+ return true;
289308 }
290309291310 private const float text_size = 16;