206 lines
7.4 KiB
C#
206 lines
7.4 KiB
C#
using System;
|
|
using SharpUI.Source.Common.UI.Util;
|
|
using SharpUI.Source.Common.UI.Util.Layout;
|
|
using SharpUI.Source.Common.Util.Extensions;
|
|
using SharpUI.Source.Common.Util.Reactive;
|
|
using UniRx;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace SharpUI.Source.Common.UI.Elements.TooltipInfo
|
|
{
|
|
public class Tooltip : MonoBehaviour, ITooltip
|
|
{
|
|
private CompositeDisposable _showDisposable = new CompositeDisposable();
|
|
private Margin _margin = new Margin(10, 10, 10, 10);
|
|
private readonly IUiUtil _util = new UiUtil();
|
|
private ITooltipPointer _tooltipPointer;
|
|
private RectTransform _rectTransform;
|
|
private RectTransform _sourceTransform;
|
|
private RectTransform _contentTransform;
|
|
private long _showDelayTimeMillis;
|
|
private IDelayObserver _delayObserver = new DelayObserver();
|
|
|
|
public void Awake()
|
|
{
|
|
_tooltipPointer = GetComponentInChildren<TooltipPointer>();
|
|
_rectTransform = GetComponent<RectTransform>();
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
PositionPointerTo(PointerPosition.Right);
|
|
}
|
|
|
|
public void OnDestroy()
|
|
{
|
|
_showDisposable.Dispose();
|
|
}
|
|
|
|
public void SetShowDisposable(CompositeDisposable disposable) => _showDisposable = disposable;
|
|
|
|
public void SetDelayObserver(IDelayObserver observer)
|
|
{
|
|
_delayObserver = observer;
|
|
}
|
|
|
|
public void SetTooltipPointer(ITooltipPointer pointer)
|
|
{
|
|
_tooltipPointer = pointer;
|
|
}
|
|
|
|
public void PositionPointerTo(PointerPosition pointerPosition)
|
|
{
|
|
_tooltipPointer.SetPosition(pointerPosition);
|
|
}
|
|
|
|
public void OffsetPointerByPercentage(float offset)
|
|
{
|
|
_tooltipPointer.SetOffsetPercentage(offset);
|
|
}
|
|
|
|
public void Hide()
|
|
{
|
|
_showDisposable.Clear();
|
|
_contentTransform.SetParent(null);
|
|
gameObject.SetActive(false);
|
|
}
|
|
|
|
public long GetShowDelayTime() => _showDelayTimeMillis;
|
|
|
|
public void SetShowDelayTimeMillis(long millis) => _showDelayTimeMillis = millis;
|
|
|
|
private void ShowInside(RectTransform parentTransform)
|
|
{
|
|
_sourceTransform = parentTransform;
|
|
transform.SetParent(parentTransform.transform.parent);
|
|
_contentTransform.SetParent(_rectTransform);
|
|
gameObject.SetActive(true);
|
|
}
|
|
|
|
private float CenterHorizontalOffset()
|
|
=> _util.Half(_sourceTransform.sizeDelta.x) - _util.Half(_tooltipPointer.Height) -
|
|
_tooltipPointer.OffsetSize();
|
|
|
|
private float CenterVerticalOffset()
|
|
=> _util.Half(_sourceTransform.sizeDelta.y) - _util.Half(_tooltipPointer.Height) -
|
|
_tooltipPointer.OffsetSize();
|
|
|
|
private float PivotHorizontalOffset()
|
|
=> -_sourceTransform.pivot.x * _sourceTransform.sizeDelta.x
|
|
+_rectTransform.pivot.x * _rectTransform.sizeDelta.x;
|
|
|
|
private float PivotVerticalOffset()
|
|
=> -_sourceTransform.pivot.y * _sourceTransform.sizeDelta.y
|
|
+_rectTransform.pivot.y * _rectTransform.sizeDelta.y;
|
|
|
|
private float TopVerticalOffset()
|
|
=> _sourceTransform.sizeDelta.y + _tooltipPointer.Width;
|
|
|
|
private float BottomVerticalOffset()
|
|
=> -_rectTransform.sizeDelta.y - _tooltipPointer.Width;
|
|
|
|
private float LeftHorizontalOffset()
|
|
=> -_rectTransform.sizeDelta.x - _tooltipPointer.Width;
|
|
|
|
private float RightHorizontalOffset()
|
|
=> _sourceTransform.sizeDelta.x + _tooltipPointer.Width;
|
|
|
|
private Vector2 TopOffset()
|
|
=> new Vector2(
|
|
PivotHorizontalOffset() + CenterHorizontalOffset(),
|
|
PivotVerticalOffset() + TopVerticalOffset());
|
|
|
|
private Vector2 BottomOffset()
|
|
=> new Vector2(
|
|
PivotHorizontalOffset() + CenterHorizontalOffset(),
|
|
PivotVerticalOffset() + BottomVerticalOffset());
|
|
|
|
private Vector2 LeftOffset()
|
|
=> new Vector2(
|
|
PivotHorizontalOffset() + LeftHorizontalOffset(),
|
|
PivotVerticalOffset() + CenterVerticalOffset());
|
|
|
|
private Vector2 RightOffset()
|
|
=> new Vector2(
|
|
PivotHorizontalOffset() + RightHorizontalOffset(),
|
|
PivotVerticalOffset() + CenterVerticalOffset());
|
|
|
|
private void SetLocalPositionWith(Vector2 offset)
|
|
{
|
|
var sourceLocalPosition = _sourceTransform.localPosition;
|
|
_rectTransform.localPosition = new Vector3(
|
|
sourceLocalPosition.x + offset.x,
|
|
sourceLocalPosition.y + offset.y);
|
|
_contentTransform.gameObject.SetActive(true);
|
|
}
|
|
|
|
private IObservable<long> ClearAndDelay()
|
|
{
|
|
_showDisposable.Clear();
|
|
return _delayObserver.DelayMilliseconds(_showDelayTimeMillis, Scheduler.MainThread);
|
|
}
|
|
|
|
public void ShowToLeftOf(RectTransform sourceTransform)
|
|
{
|
|
ClearAndDelay().SubscribeWith(_showDisposable, _ =>
|
|
{
|
|
_tooltipPointer.SetPosition(PointerPosition.Right);
|
|
ShowInside(sourceTransform);
|
|
SetLocalPositionWith(LeftOffset());
|
|
});
|
|
}
|
|
|
|
public void ShowToRightOf(RectTransform sourceTransform)
|
|
{
|
|
ClearAndDelay().SubscribeWith(_showDisposable, _ =>
|
|
{
|
|
_tooltipPointer.SetPosition(PointerPosition.Left);
|
|
ShowInside(sourceTransform);
|
|
SetLocalPositionWith(RightOffset());
|
|
});
|
|
}
|
|
|
|
public void ShowAbove(RectTransform sourceTransform)
|
|
{
|
|
ClearAndDelay().SubscribeWith(_showDisposable, _ =>
|
|
{
|
|
_tooltipPointer.SetPosition(PointerPosition.Bottom);
|
|
ShowInside(sourceTransform);
|
|
SetLocalPositionWith(TopOffset());
|
|
});
|
|
}
|
|
|
|
public void ShowBelow(RectTransform sourceTransform)
|
|
{
|
|
ClearAndDelay().SubscribeWith(_showDisposable, _ =>
|
|
{
|
|
_tooltipPointer.SetPosition(PointerPosition.Top);
|
|
ShowInside(sourceTransform);
|
|
SetLocalPositionWith(BottomOffset());
|
|
});
|
|
}
|
|
|
|
public void SetMargins(Margin margin) => _margin = margin;
|
|
|
|
public void BindContent(RectTransform contentTransform)
|
|
{
|
|
_contentTransform = contentTransform;
|
|
LayoutRebuilder.ForceRebuildLayoutImmediate(_contentTransform);
|
|
SetContentSize(_contentTransform.rect);
|
|
_contentTransform.SetParent(_rectTransform);
|
|
_contentTransform.localPosition = new Vector3(
|
|
-(_rectTransform.pivot.x - 0.5f) * _rectTransform.sizeDelta.x,
|
|
-(_rectTransform.pivot.y - 0.5f) * _rectTransform.sizeDelta.y);
|
|
_contentTransform.gameObject.SetActive(false);
|
|
}
|
|
|
|
private void SetContentSize(Rect rect)
|
|
{
|
|
var width = rect.width + _margin.Left + _margin.Right;
|
|
var height = rect.height + _margin.Top + _margin.Bottom;
|
|
_rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width);
|
|
_rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
|
|
}
|
|
}
|
|
} |