KF2-Server-Extension/ServerExt/Classes/KFGUI_HTMLTextBox.txt
2017-10-19 21:00:49 -05:00

928 lines
21 KiB
Plaintext

//====================================================================
// HTML Text box, written by Marco
// Simply call SetContents to change window contents.
// Only callback available is for LaunchKFURL.
// ====================================================================
class KFGUI_HTMLTextBox extends KFGUI_MultiComponent;
struct FTextLine
{
var string Text,URL;
var color Color,ALColor;
var Font Font;
var float FontScale;
var byte Align,FontSize;
var int X,Y,XS,YS,Tab,TOffset;
var byte LineSkips;
var array<int> ImgList;
var bool bHasURL,bSplit;
};
var array<FTextLine> Lines;
struct FImageEntry
{
var Surface Img;
var int X,Y,XS,YS,YOffset,XOffset;
var byte Align,Style;
};
var array<FImageEntry> Images;
var FImageEntry BgImage;
var float OldXSize,OldYSize;
var int YSize,HoverOverLinkLine,OldHoverLine;
var() Color BGColor,WhiteColor,BlueColor,RedColor;
var KFGUI_ScrollBarV MyScrollBar;
var string TitleString;
var int CurTab;
var byte DefaultFontSize;
var bool bNeedsInit,bHasSplitLines,bNeedScrollbar;
function InitMenu()
{
Super.InitMenu();
MyScrollBar = KFGUI_ScrollBarV(FindComponentID('Scrollbar'));
}
final function int AddText( string Input, color TextColor, byte TextAlign, byte FontSize, out byte NumSkips )
{
local int i;
i = Lines.Length;
Lines.Length = i+1;
Lines[i].Text = Input;
Lines[i].Color = TextColor;
Lines[i].Align = TextAlign;
Lines[i].FontSize = FontSize;
Lines[i].LineSkips = NumSkips;
Lines[i].Tab = CurTab;
NumSkips = 0;
return i;
}
final function string ParseLinkType( string URL )
{
if( InStr(URL,"//")>0 )
return URL;
if( Left(URL,4)~="ftp." )
return "ftp://"$URL;
return "http://"$URL;
}
final function AddImage( string Input )
{
local string Temp;
local byte Align,Sty;
local Material M;
local int X,Y,XS,YS,i,j,z;
Align = 3;
Temp = GetOption(Input, "ALIGN=");
if (Temp != "")
{
switch( Caps(Temp) )
{
case "LEFT":
case "0":
Align = 0;
break;
case "CENTER":
case "1":
Align = 1;
break;
case "RIGHT":
case "2":
Align = 2;
break;
}
}
Temp = GetOption(Input, "STYLE=");
if (Temp != "")
{
switch( Caps(Temp) )
{
case "NORMAL":
case "0":
Sty = 0;
break;
case "STRETCH":
case "1":
Sty = 1;
break;
case "TILEDX":
case "2":
Sty = 2;
break;
case "TILEDY":
case "3":
Sty = 3;
break;
case "TILED":
case "4":
Sty = 4;
break;
}
}
Temp = GetOption(Input, "SRC=");
if (Temp != "")
M = Surface(DynamicLoadObject(Temp,Class'Surface'));
if( M==None )
M = class'Canvas'.Default.DefaultTexture;
X = int(GetOption(Input, "VSPACE="));
Y = int(GetOption(Input, "HSPACE="));
XS = int(GetOption(Input, "WIDTH="));
YS = int(GetOption(Input, "HEIGHT="));
if( XS==0 )
XS = M.GetSurfaceWidth();
if( YS==0 )
YS = M.GetSurfaceHeight();
i = Images.Length;
Images.Length = i+1;
Images[i].Img = M;
Images[i].XOffset = X;
Images[i].YOffset = Y;
Images[i].XS = XS;
Images[i].YS = YS;
Images[i].Style = Sty;
Images[i].Align = Align;
j = Lines.Length-1;
z = Lines[j].ImgList.Length;
Lines[j].ImgList.Length = z+1;
Lines[j].ImgList[z] = i;
}
final function SetContents( string Input )
{
local string LeftText,HTML,RightText,Output,Temp,Link;
local int Index;
local color TextColor,LinkColor,ALinkColor,OrgTextColor;
local byte Alignment,FontScaler,NextLineSkips;
CurTab = 0;
BGColor.A = 0;
BgImage.Img = None;
Lines.Length = 0;
Images.Length = 0;
TitleString = "";
bHasSplitLines = false;
bNeedsInit = true;
// First remove new liners
Input = Repl(Input, Chr(13)$Chr(10), "");
Input = Repl(Input, Chr(13), "");
Input = Repl(Input, Chr(10), "");
Input = Repl(Input, Chr(9), " ");
Input = Repl(Input, "\\n", "<BR>");
TextColor = WhiteColor;
OrgTextColor = WhiteColor;
LinkColor = BlueColor;
ALinkColor = RedColor;
FontScaler = 3;
DefaultFontSize = 3;
Index = -1;
while (Input != "")
{
ParseHTML(Input, LeftText, HTML, RightText);
switch (GetTag(HTML))
{
// multiline HTML tags
case "P":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
NextLineSkips = 2;
Output = "";
}
else ++NextLineSkips;
break;
case "BR":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
NextLineSkips = 1;
Output = "";
}
else ++NextLineSkips;
break;
case "BODY":
Temp = GetOption(HTML, "BGCOLOR=");
if (Temp != "")
BGColor = ParseColor(Temp);
Temp = GetOption(HTML, "LINK=");
if (Temp != "")
LinkColor = ParseColor(Temp);
Temp = GetOption(HTML, "ALINK=");
if (Temp != "")
ALinkColor = ParseColor(Temp);
Temp = GetOption(HTML, "TEXT=");
if (Temp != "")
{
TextColor = ParseColor(Temp);
OrgTextColor = TextColor;
}
Temp = GetOption(HTML, "SIZE=");
if (Temp != "")
{
FontScaler = int(Temp);
DefaultFontSize = FontScaler;
}
Temp = GetOption(Input, "IMG=");
if (Temp != "")
{
if( BGColor.A==0 )
BGColor = Class'Hud'.Default.WhiteColor;
BgImage.Img = Surface(DynamicLoadObject(Temp,Class'Surface'));
if( BgImage.Img==None )
BgImage.Img = Class'Canvas'.Default.DefaultTexture;
BgImage.X = BgImage.Img.GetSurfaceWidth();
BgImage.Y = BgImage.Img.GetSurfaceHeight();
switch( Caps(GetOption(Input, "IMGSTYLE=")) )
{
case "TILED":
BgImage.XS = BgImage.X;
BgImage.YS = BgImage.Y;
BgImage.Style = 1;
Temp = GetOption(Input, "TILEX=");
if (Temp != "")
BgImage.XS = int(Temp);
Temp = GetOption(Input, "TILEY=");
if (Temp != "")
BgImage.YS = int(Temp);
break;
case "FITX":
BgImage.Style = 2;
break;
case "FITY":
BgImage.Style = 3;
break;
default: // FIT
BgImage.Style = 0;
}
BgImage.Align = 0;
if( GetOption(Input, "IMGLOCK=")=="0" )
BgImage.Align = 1;
}
Output $= LeftText;
break;
case "CENTER":
Output $= LeftText;
if ( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
NextLineSkips = Max(NextLineSkips,1);
Alignment = 1;
break;
case "RIGHT":
Output $= LeftText;
if ( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
NextLineSkips = Max(NextLineSkips,1);
Alignment = 2;
break;
case "/CENTER":
case "/RIGHT":
Index = AddText(Output $ LeftText,TextColor,Alignment,FontScaler,NextLineSkips);
++NextLineSkips;
Alignment = 0;
Output = "";
break;
// Inline HTML tags
case "H1":
Output $= LeftText;
if ( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
NextLineSkips = Max(NextLineSkips,1);
FontScaler = 5;
Alignment = 1;
break;
case "/H1":
Index = AddText(Output $ LeftText,TextColor,Alignment,FontScaler,NextLineSkips);
++NextLineSkips;
Output = "";
FontScaler = DefaultFontSize;
Alignment = 0;
break;
case "FONT":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
Temp = GetOption(HTML, "COLOR=");
if (Temp != "")
TextColor = ParseColor(Temp);
Temp = GetOption(HTML, "SIZE=");
if (Temp != "")
FontScaler = int(Temp);
break;
case "/FONT":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
TextColor = OrgTextColor;
FontScaler = DefaultFontSize;
break;
case "TAB":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
CurTab = int(GetOption(HTML, "X="));
break;
case "/TAB":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
CurTab = 0;
break;
case "TITLE":
Output $= LeftText;
break;
case "/TITLE":
TitleString = LeftText;
break;
case "A":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
Link = GetOption(HTML, "HREF=");
break;
case "/A":
Output $= LeftText;
Index = AddText(Output,LinkColor,Alignment,FontScaler,NextLineSkips);
Lines[Index].ALColor = ALinkColor;
Lines[Index].bHasURL = true;
if( Link=="" )
Lines[Index].URL = ParseLinkType(Output);
else Lines[Index].URL = ParseLinkType(Link);
Output = "";
FontScaler = DefaultFontSize;
Alignment = 0;
break;
case "IMG":
Output $= LeftText;
if( Output!="" || NextLineSkips>0 )
AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
AddImage(HTML);
break;
default:
Output = Output $ LeftText;
break;
}
Input = RightText;
}
AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
}
// Get the next HTML tag, the text before it and everthing after it.
final function ParseHTML(string Input, out string LeftText, out string HTML, out string RightText)
{
local int i;
i = InStr(Input, "<");
if (i == -1)
{
LeftText = Input;
HTML = "";
RightText = "";
return;
}
LeftText = Left(Input, i);
HTML = Mid(Input, i);
i = InStr(HTML, ">");
if (i == -1)
{
RightText = "";
return;
}
RightText = Mid(HTML, i+1);
HTML = Left(HTML, i+1);
}
final function string GetTag(string HTML)
{
local int i;
if (HTML == "")
return "";
HTML = Mid(HTML, 1); // lose <
i = FirstMatching(InStr(HTML, ">"), InStr(HTML, " "));
if (i == -1)
return Caps(HTML);
else
return Caps(Left(HTML, i));
}
final function string GetOption(string HTML, string Option)
{
local int i, j;
local string s;
i = InStr(Caps(HTML), Caps(Option));
if (i == 1 || Mid(HTML, i-1, 1) == " ")
{
s = Mid(HTML, i+Len(Option));
j = FirstMatching(InStr(s, ">"), InStr(s, " "));
s = Left(s, j);
if (Left(s, 1) == "\"")
s = Mid(s, 1);
if (Right(s, 1) == "\"")
s = Left(s, Len(s) - 1);
return s;
}
return "";
}
final function int FirstMatching(int i, int j)
{
if (i == -1)
return j;
if (j == -1)
return i;
return Min(i, j);
}
final function Color ParseColor(string S)
{
local Color C;
local int i;
S = Caps(S);
if (Left(S, 1) == "#")
{
C.R = (GetHexDigit(Mid(S, 1, 1)) << 4) + GetHexDigit(Mid(S, 2, 1));
C.G = (GetHexDigit(Mid(S, 3, 1)) << 4) + GetHexDigit(Mid(S, 4, 1));
C.B = (GetHexDigit(Mid(S, 5, 1)) << 4) + GetHexDigit(Mid(S, 6, 1));
}
else if (Left(S, 4) == "RGB(")
{
S = Mid(S, 4);
i = InStr(S,",");
C.R = int(Left(S,i));
S = Mid(S,i+1);
i = InStr(S,",");
C.G = int(Left(S,i));
C.B = int(Mid(S,i+1));
}
else
{
switch( S )
{
case "RED":
C.R = 255;
C.G = 0;
C.B = 0;
break;
case "BLUE":
C.R = 0;
C.G = 0;
C.B = 255;
break;
case "GREEN":
C.R = 0;
C.G = 255;
C.B = 0;
break;
case "YELLOW":
C.R = 255;
C.G = 255;
C.B = 0;
break;
case "BLACK":
C.R = 0;
C.G = 0;
C.B = 0;
break;
default: // WHITE
C.R = 255;
C.G = 255;
C.B = 255;
}
}
C.A = 255;
return C;
}
final function byte GetHexDigit(string D)
{
local byte i;
i = Asc(D);
if( i>=48 && i<=57 ) // i>='0' && i<='9'
return (i-48); // i-'0'
return Min(i-55,15); // i-('A'-10)
}
final function SplitLine( int iLine, int iOffset )
{
local int i;
local string S;
++iLine;
Lines.Insert(iLine,1);
S = Lines[iLine-1].Text;
for( i=iOffset; i<Len(S); ++i )
if( Mid(S,i,1)!=" " )
break;
Lines[iLine].Text = Mid(S,i);
Lines[iLine-1].Text = Left(S,iOffset);
Lines[iLine].URL = Lines[iLine-1].URL;
Lines[iLine].Color = Lines[iLine-1].Color;
Lines[iLine].ALColor = Lines[iLine-1].ALColor;
Lines[iLine].Align = Lines[iLine-1].Align;
Lines[iLine].FontSize = Lines[iLine-1].FontSize;
Lines[iLine].Tab = Lines[iLine-1].Tab;
Lines[iLine].LineSkips = 1;
Lines[iLine].bHasURL = Lines[iLine-1].bHasURL;
Lines[iLine].bSplit = true;
bHasSplitLines = true;
}
final protected function InitHTMLArea()
{
local float XS,YS;
local int i,j,X,Y,iStart,BestHeight,FontSize,PrevY,Remain,iLastWord,iLen,z,ImgHeight;
// Used to detect resolution changes when text needs realignment.
OldXSize = CompPos[2];
OldYSize = CompPos[3];
// Merge splitted lines again
if( bHasSplitLines )
{
bHasSplitLines = false;
for( i=1; i<Lines.Length; ++i )
{
if( Lines[i].bSplit )
{
Lines[i-1].Text @= Lines[i].Text;
Lines.Remove(i--,1);
}
}
}
// Setup background image scaling
if( BgImage.Img!=None )
{
switch( BgImage.Style )
{
case 1: // Tiled
if( BgImage.X==BgImage.XS )
BgImage.XOffset = Canvas.ClipX;
else
{
XS = Canvas.ClipX / float(BgImage.XS) * float(BgImage.X);
BgImage.XOffset = XS;
}
if( BgImage.Y==BgImage.YS )
BgImage.YOffset = Canvas.ClipY;
else
{
XS = Canvas.ClipY / float(BgImage.YS) * float(BgImage.Y);
BgImage.YOffset = XS;
}
break;
case 2: // Fit X
XS = Canvas.ClipY * (Canvas.ClipX / float(BgImage.X));
BgImage.YS = XS;
break;
case 3: // Fit Y
XS = Canvas.ClipX * (Canvas.ClipY / float(BgImage.Y));
BgImage.XS = XS;
break;
}
}
FontSize = Owner.CurrentStyle.DefaultFontSize;
Canvas.SetPos(0,0);
if( Lines.Length>0 )
{
while( true )
{
if( i>=Lines.Length || (i>0 && Lines[i].LineSkips>0) )
{
for( j=iStart; j<i; ++j )
{
switch( Lines[j].Align )
{
case 0: // Left
Lines[j].X = Lines[j].TOffset;
break;
case 1: // Center
Lines[j].X = (Canvas.ClipX-X+Lines[j].TOffset)/2;
break;
case 2: // Right
Lines[j].X = Canvas.ClipX-X+Lines[j].TOffset;
break;
}
}
if( i>=Lines.Length )
break;
X = 0;
iStart = i;
PrevY = BestHeight;
BestHeight = 0;
}
if( Lines[i].FontSize>=247 )
Lines[i].Font = Owner.CurrentStyle.PickFont(Max(Lines[i].FontSize-247,0),Lines[i].FontScale);
else Lines[i].Font = Owner.CurrentStyle.PickFont(Max(FontSize+Lines[i].FontSize,0),Lines[i].FontScale);
Canvas.Font = Lines[i].Font;
if( Lines[i].Text=="" )
{
Canvas.TextSize("ABC",XS,YS,Lines[i].FontScale,Lines[i].FontScale);
XS = 0;
}
else Canvas.TextSize(Lines[i].Text,XS,YS,Lines[i].FontScale,Lines[i].FontScale);
if( Lines[i].LineSkips>0 )
{
if( PrevY==0 )
PrevY = YS;
Y+=(PrevY*Lines[i].LineSkips);
}
X = Max(X,Lines[i].Tab);
Lines[i].TOffset = X;
Lines[i].Y = Y;
Lines[i].YS = YS;
BestHeight = Max(BestHeight,YS);
if( (X+XS)>Canvas.ClipX )
{
// Split to next row.
Remain = Canvas.ClipX-X;
iLastWord = 0;
iLen = Len(Lines[i].Text);
for( j=1; j<iLen; ++j )
{
Canvas.TextSize(Left(Lines[i].Text,j),XS,YS,Lines[i].FontScale,Lines[i].FontScale);
if( Remain<XS )
{
if( iLastWord==0 ) // Must cut off a word now.
SplitLine(i,Max(j-1,0));
else SplitLine(i,iLastWord);
break;
}
if( Mid(Lines[i].Text,j,1)==" " )
iLastWord = j+1;
}
Canvas.TextSize(Lines[i].Text,XS,YS,Lines[i].FontScale,Lines[i].FontScale);
}
Lines[i].XS = XS;
X+=XS;
for( j=0; j<Lines[i].ImgList.Length; ++j )
{
z = Lines[i].ImgList[j];
if( Images[z].Align==3 )
Images[z].X = X+Images[z].XOffset;
else Images[z].X = Images[z].XOffset;
Images[z].Y = Y+Images[z].YOffset;
ImgHeight = Max(ImgHeight,Images[z].Y+Images[z].YS);
}
++i;
}
YSize = Max(Y+BestHeight,ImgHeight);
}
else YSize = 0;
bNeedScrollbar = (YSize>Canvas.ClipY);
if( bNeedScrollbar )
{
MyScrollBar.SetDisabled(false);
MyScrollBar.UpdateScrollSize(0,YSize,Canvas.ClipY,512);
}
else MyScrollBar.SetDisabled(true);
}
simulated final function DrawTileStretchedClipped( Surface M, float XS, float YS )
{
Canvas.CurX += Canvas.OrgX;
Canvas.CurY += Canvas.OrgY;
if( Canvas.CurX<Canvas.OrgX )
{
XS-=(Canvas.OrgX-Canvas.CurX);
Canvas.CurX = Canvas.OrgX;
}
if( Canvas.CurY<Canvas.OrgY )
{
YS-=(Canvas.OrgY-Canvas.CurY);
Canvas.CurY = Canvas.OrgY;
}
if( (Canvas.CurX+XS)>Canvas.ClipX )
XS = (Canvas.ClipX-Canvas.CurX);
if( (Canvas.CurY+YS)>Canvas.ClipY )
YS = (Canvas.ClipY-Canvas.CurY);
if( Texture(M)!=None )
Canvas.DrawTileStretched(Texture(M),XS,YS);
}
function DrawMenu()
{
local float YS;
local int i,YOffset,MX,MY;
local bool bMouseOnClient;
if( bNeedsInit || OldXSize!=CompPos[2] || OldYSize!=CompPos[3] )
{
bNeedsInit = false;
InitHTMLArea();
}
if( bNeedScrollbar )
YOffset = MyScrollBar.CurrentScroll;
if( BGColor.A>0 )
{
C.SetPos(0,0);
C.DrawColor = BGColor;
if( BgImage.Img!=None )
{
if( BgImage.Align==1 ) // not locked on screen.
MX = YOffset;
switch( BgImage.Style )
{
case 0: // Stretched to fit
C.DrawTileClipped(BgImage.Img,C.ClipX,C.ClipY,0,MX,BgImage.X,BgImage.Y);
break;
case 1: // Tiled
C.DrawTileClipped(BgImage.Img,C.ClipX,C.ClipY,0,MX,BgImage.XOffset,BgImage.YOffset);
break;
case 2: // Fit X
C.DrawTileClipped(BgImage.Img,C.ClipX,C.ClipY,0,MX,BgImage.X,BgImage.YS);
break;
case 3: // Fit Y
C.DrawTileClipped(BgImage.Img,C.ClipX,C.ClipY,0,MX,BgImage.XS,BgImage.Y);
break;
}
}
else C.DrawTile(Texture'WhiteTexture',C.ClipX,C.ClipY,0,0,1,1);
}
MX = Controller.MouseX-C.OrgX;
MY = Controller.MouseY-C.OrgY;
bMouseOnClient = (MX>=0 && MX<=C.ClipX && MY>=0 && MY<=C.ClipY);
HoverOverLinkLine = -1;
MY+=YOffset;
C.DrawColor = Class'HUD'.Default.WhiteColor;
for( i=0; i<Images.Length; ++i )
{
C.CurY = Images[i].Y-YOffset;
if( (C.CurY+Images[i].YS)<0 || C.CurY>C.ClipY )
continue;
switch( Images[i].Align )
{
case 0: // Left
case 3: // Unaligned, postition after text.
C.CurX = 0;
break;
case 1: // Center
C.CurX = (C.ClipX-Images[i].XS)/2;
break;
case 1: // Right
C.CurX = C.ClipX-Images[i].XS;
break;
}
C.CurX += Images[i].X;
switch( Images[i].Style )
{
case 1: // Stretched
DrawTileStretchedClipped(C,Images[i].Img,Images[i].XS,Images[i].YS);
break;
case 2: // Tiled on X axis
C.DrawTileClipped(Images[i].Img,Images[i].XS,Images[i].YS,0,0,Images[i].XS,Images[i].Img.MaterialVSize());
break;
case 3: // Tiled on Y axis
C.DrawTileClipped(Images[i].Img,Images[i].XS,Images[i].YS,0,0,Images[i].Img.MaterialUSize(),Images[i].YS);
break;
case 4: // Fully tiled
C.DrawTileClipped(Images[i].Img,Images[i].XS,Images[i].YS,0,0,Images[i].XS,Images[i].YS);
break;
default: // Normal
C.DrawTileClipped(Images[i].Img,Images[i].XS,Images[i].YS,0,0,Images[i].Img.MaterialUSize(),Images[i].Img.MaterialVSize());
}
}
for( i=0; i<Lines.Length; ++i )
{
C.SetPos(Lines[i].X,Lines[i].Y-YOffset);
if( (C.CurY+Lines[i].YS)<0 || Lines[i].Text=="" )
continue;
if( C.CurY>C.ClipY )
break;
// Check if mouse hovers over URL
if( bMouseOnClient && Lines[i].bHasURL && MX>=Lines[i].X && MX<=(Lines[i].X+Lines[i].XS)
&& MY>=Lines[i].Y && MY<=(Lines[i].Y+Lines[i].YS) )
{
HoverOverLinkLine = i;
bMouseOnClient = false; // No need to check on rest anymore.
C.DrawColor = Lines[i].ALColor;
}
else C.DrawColor = Lines[i].Color;
C.Font = Lines[i].Font;
C.DrawTextClipped(Lines[i].Text);
if( Lines[i].bHasURL )
{
YS = Max(Lines[i].YS/15,1);
C.SetPos(Lines[i].X,Lines[i].Y+Lines[i].YS-(YS*2)-YOffset);
if( C.CurY<C.ClipY )
C.DrawTileClipped(Texture'WhiteTexture',Lines[i].XS,YS,0,0,1,1);
}
}
if( OldHoverLine!=HoverOverLinkLine )
{
OldHoverLine = HoverOverLinkLine;
if( HoverOverLinkLine>=0 )
{
Controller.PlayInterfaceSound(CS_Hover);
SetToolTipText(Lines[HoverOverLinkLine].URL);
}
else SetToolTipText("");
}
}
function bool LaunchURL(GUIComponent Sender)
{
if( HoverOverLinkLine>=0 )
{
if( Left(Lines[HoverOverLinkLine].URL,8)~="kfurl://" )
LaunchKFURL(Mid(Lines[HoverOverLinkLine].URL,8));
else if( Left(Lines[HoverOverLinkLine].URL,5)~="kf://" )
ChangeGameURL(Mid(Lines[HoverOverLinkLine].URL,5));
else LaunchURLPage(Lines[HoverOverLinkLine].URL);
}
}
delegate LaunchKFURL( string URL );
delegate ChangeGameURL( string URL )
{
Class'SRLevelCleanup'.Static.AddSafeCleanup(PlayerOwner(),URL);
}
delegate LaunchURLPage( string URL )
{
PlayerOwner().Player.Console.DelayedConsoleCommand("START "$URL);
}
defaultproperties
{
bNeedsInit=true
PropagateVisibility=true
OnDraw=RenderHTMLText
OnClick=LaunchURL
Begin Object Class=GUIVertScrollBar Name=TheScrollbar
bBoundToParent=true
bScaleToParent=true
WinWidth=0.03
WinLeft=0.97
WinTop=0.0
WinHeight=1.0
bVisible=true
PropagateVisibility=true
OnPreDraw=TheScrollbar.GripPreDraw
End Object
MyScrollBar=TheScrollbar
StyleName="NoBackground"
bAcceptsInput=True
Begin Object Class=GUIToolTip Name=GUIListBoxBaseToolTip
ExpirationSeconds=0
End Object
ToolTip=GUIListBoxBaseToolTip
WhiteColor=(R=255,G=255,B=255,A=255)
BlueColor=(R=0,G=0,B=255,A=255)
RedColor=(R=255,G=0,B=0,A=255)
}