rott/kf_sources/XInterface/Classes/GUIToolTip.uc
2026-07-14 20:27:09 +07:00

227 lines
5.9 KiB
Ucode

//==============================================================================
// Created on: 01/19/2004
// Tooltip that appears when this component is moused over
//
// Written by Ron Prestenback
// © 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class GUIToolTip extends GUIComponent
native;
cpptext
{
void PreDraw( UCanvas* C );
void Draw( UCanvas* C );
void SetTip( FString& NewTip );
}
var() bool bResetPosition; // Position of this component needs to be updated
var() bool bTrackMouse; // This tooltip will follow the mouse as it moves
var() bool bMultiLine; // Allow hint text to be wrapped if it's too long
var() bool bTrackInput; // Should this tooltip disappear when input is received
var() const string Text; // Entire tooltip
var() const array<string> Lines; // If multiline == true, contains the tooltip lines
var() noexport float StartTime;
var() noexport float CurrentTime;
var() globalconfig float MaxWidth; // Max width of the tooltip area, in percent of the screen width
var() globalconfig float InitialDelay; // Number of seconds of inactivity before appearing
var() globalconfig float ExpirationSeconds; // Number of seconds to display before fading out
// Return true to override default behavior
// SetPosition() is called at the end of the native PreDraw(), if (bResetPosition || bTrackMouse),
// which means SetPosition() will NOT be called if you return true from OnPreDraw()
// delegate bool OnPreDraw( Canvas C );
// Draw will NOT be called if bResetPosition == true
// delegate bool OnDraw( Canvas C );
// called when the mouse is first moved over the component associated with this tooltip
delegate GUIToolTip EnterArea()
{
return InternalEnterArea();
}
function GUIToolTip InternalEnterArea()
{
if (Controller==None)
{
if ( class'GUIController'.default.bModAuthor )
log("ToolTip ("$self$") not initialized");
return none;
}
StartTime = PlayerOwner().Level.TimeSeconds;
// if there was a hint currently being displayed, bypass the initial delay
if ( Controller != None && Controller.MouseOver != None && Controller.MouseOver != Self && Controller.MouseOver.bVisible )
CurrentTime = InitialDelay;
else CurrentTime = 0.0;
bResetPosition = true;
return self;
}
// Called when the mouse is moved away from the component associated with this tooltip
// Return false to keep displaying the tooltip - though sometimes controller will force the tooltip to disappear
// (for instance, if opening a context menu, etc.)
delegate bool LeaveArea()
{
return InternalLeaveArea();
}
function bool InternalLeaveArea()
{
StartTime = -1;
CurrentTime = -1;
SetVisibility(false);
if ( Controller != None && Controller.MouseOver == Self )
Controller.MouseOver = None;
return true;
}
// Only received when active
delegate Tick( float RealSeconds )
{
CurrentTime += RealSeconds;
if ( !bVisible && CurrentTime > InitialDelay && (ExpirationSeconds == 0.0 || CurrentTime <= ExpirationSeconds) )
ShowToolTip();
if ( bVisible && CurrentTime > ExpirationSeconds && ExpirationSeconds > 0.0 )
HideToolTip();
}
delegate ShowToolTip()
{
SetVisibility(true);
}
delegate HideToolTip()
{
SetVisibility(false);
}
// This is normally called at the end of PreDraw().
event UpdatePosition( Canvas C )
{
WinWidth = GetWidth(C);
WinHeight = GetHeight(C);
WinLeft = GetLeft(C);
WinTop = GetTop(C);
bResetPosition = false;
}
delegate float GetLeft( Canvas C )
{
local float X;
if ( C == None || MenuOwner == None || Style == None )
return -1.0;
X = FMin(Controller.MouseX, Controller.MouseCursorBounds.X1);
if ( X + WinWidth > C.SizeX )
X -= WinWidth + 10;
return X;
}
delegate float GetTop( Canvas C )
{
local float TargetTop;
if ( C == None || MenuOwner == None || Style == None )
return -1.0;
if ( Controller.MouseY > C.SizeY / 8 )
TargetTop = GetTopAboveCursor(C);
else TargetTop = GetTopBelowCursor(C);
if ( TargetTop < 0 )
TargetTop = GetTopBelowCursor(C);
return TargetTop;
}
delegate float GetWidth( Canvas C )
{
local int i;
local float MaxLineWidth, XL, YL;
if ( C == None || Lines.Length == 0 || MenuOwner == None || Style == None )
return 0.0;
for ( i = 0; i < Lines.Length; i++ )
{
Style.TextSize(C, MenuOwner.MenuState, Lines[i], XL, YL, FontScale);
if ( XL > MaxLineWidth )
MaxLineWidth = XL;
}
return FMin( MaxLineWidth, MaxWidth * C.SizeX ) + Style.BorderOffsets[0] + Style.BorderOffsets[2];
}
delegate float GetHeight( Canvas C )
{
local float XL, YL;
if ( C == None || Lines.Length == 0 || MenuOwner == None || Style == None )
return 0.0;
Style.TextSize( C, MenuOwner.MenuState, Lines[0], XL, YL, FontScale );
return (YL * Lines.Length) + Style.BorderOffsets[1] + Style.BorderOffsets[3];
}
singular function float GetTopAboveCursor( Canvas C )
{
local float TargetY, TempY;
if ( MenuOwner == None || C == None || Controller == None )
return -1.0;
TargetY = FMin(Controller.MouseCursorBounds.Y1, Controller.MouseY) - (WinHeight + 10);
if ( TargetY < 0 )
TempY = GetTopBelowCursor(C);
return FMax(TempY, TargetY);
}
singular function float GetTopBelowCursor( Canvas C )
{
local float TargetY, TempY;
if ( MenuOwner == None || C == None || Controller == None )
return -1.0;
TargetY = FMax(Controller.MouseCursorBounds.Y2, Controller.MouseY) + 10;
if ( TargetY + WinHeight > C.SizeY )
TempY = GetTopAboveCursor(C);
return FMax(TargetY, TempY);
}
native final function SetTip( coerce string NewTip );
DefaultProperties
{
bRequiresStyle=True
bVisible=false
bTrackMouse=false
bMultiLine=true
bTrackInput=true
MaxWidth=0.3
ExpirationSeconds=3.0
InitialDelay=0.25
StyleName="MouseOver"
}