438 lines
8.9 KiB
Ucode
438 lines
8.9 KiB
Ucode
|
// Columned list box (only for text lines).
|
||
|
Class KFGUI_ColumnList extends KFGUI_List;
|
||
|
|
||
|
struct FColumnItem
|
||
|
{
|
||
|
var() string Text;
|
||
|
var() float Width;
|
||
|
|
||
|
var transient bool bHidden;
|
||
|
var transient int X,XSize;
|
||
|
};
|
||
|
var() array<FColumnItem> Columns;
|
||
|
var() class<KFGUI_ListItem> ListItemClass;
|
||
|
var() int FontSize;
|
||
|
var() color FocusedLineColor,SelectedLineColor;
|
||
|
var KFGUI_ColumnTop ColumnComp;
|
||
|
var Canvas.FontRenderInfo LineFontInfo;
|
||
|
|
||
|
var int SelectedRowIndex;
|
||
|
var int LastSortedColumn;
|
||
|
|
||
|
var transient float TextHeight,ScalerSize,TextScaler;
|
||
|
var transient int OldItemsPerFrame;
|
||
|
|
||
|
var KFGUI_ListItem FirstItem,UnusedItem;
|
||
|
|
||
|
var transient bool bListSizeDirty;
|
||
|
var bool bLastSortedReverse;
|
||
|
var() bool bShouldSortList; // Should sort any new items added to the list instantly.
|
||
|
var() bool bCanSortColumn; // Allow user to sort columns.
|
||
|
|
||
|
delegate OnSelectedRow( KFGUI_ListItem Item, int Row, bool bRight, bool bDblClick );
|
||
|
|
||
|
function KFGUI_ListItem AddLine( string Value, optional int iValue, optional string SortValue, optional int Index=-1 )
|
||
|
{
|
||
|
local KFGUI_ListItem N,O;
|
||
|
local int i;
|
||
|
|
||
|
// Allocate list item object.
|
||
|
if( UnusedItem!=None )
|
||
|
{
|
||
|
N = UnusedItem;
|
||
|
UnusedItem = N.Next;
|
||
|
N.Next = None;
|
||
|
}
|
||
|
else N = new (None) ListItemClass;
|
||
|
|
||
|
// Setup column text value.
|
||
|
N.SetValue(Value,iValue,SortValue);
|
||
|
|
||
|
// Insert into list.
|
||
|
if( bShouldSortList && Index==-1 )
|
||
|
{
|
||
|
N.Temp = N.GetSortStr(LastSortedColumn);
|
||
|
|
||
|
if( ListCount==0 ) // No sorting needed yet.
|
||
|
{
|
||
|
N.Next = FirstItem;
|
||
|
FirstItem = N;
|
||
|
}
|
||
|
else if( bLastSortedReverse )
|
||
|
{
|
||
|
if( FirstItem.Temp<N.Temp )
|
||
|
{
|
||
|
N.Next = FirstItem;
|
||
|
FirstItem = N;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for( O=FirstItem; O!=None; O=O.Next )
|
||
|
{
|
||
|
if( O.Next==None || O.Next.Temp<N.Temp )
|
||
|
{
|
||
|
N.Next = O.Next;
|
||
|
O.Next = N;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( FirstItem.Temp>N.Temp )
|
||
|
{
|
||
|
N.Next = FirstItem;
|
||
|
FirstItem = N;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for( O=FirstItem; O!=None; O=O.Next )
|
||
|
{
|
||
|
if( O.Next==None || O.Next.Temp>N.Temp )
|
||
|
{
|
||
|
N.Next = O.Next;
|
||
|
O.Next = N;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( Index==-1 || Index>ListCount )
|
||
|
Index = ListCount;
|
||
|
if( Index==0 )
|
||
|
{
|
||
|
N.Next = FirstItem;
|
||
|
FirstItem = N;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
i = 0;
|
||
|
for( O=FirstItem; O!=None; O=O.Next )
|
||
|
{
|
||
|
if( (++i)==Index )
|
||
|
{
|
||
|
N.Next = O.Next;
|
||
|
O.Next = N;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
UpdateListSize();
|
||
|
|
||
|
return N;
|
||
|
}
|
||
|
final function RemoveLine( KFGUI_ListItem I )
|
||
|
{
|
||
|
local KFGUI_ListItem N;
|
||
|
|
||
|
if( I.Index==-1 )
|
||
|
return;
|
||
|
|
||
|
// Update selected row info.
|
||
|
if( SelectedRowIndex==I.Index )
|
||
|
SelectedRowIndex = -1;
|
||
|
else if( SelectedRowIndex>I.Index )
|
||
|
--SelectedRowIndex;
|
||
|
|
||
|
// Remove from list.
|
||
|
if( FirstItem==I )
|
||
|
FirstItem = I.Next;
|
||
|
else
|
||
|
{
|
||
|
for( N=FirstItem; N!=None; N=N.Next )
|
||
|
if( N.Next==I )
|
||
|
{
|
||
|
N.Next = I.Next;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Add to unused list.
|
||
|
I.Next = UnusedItem;
|
||
|
UnusedItem = I;
|
||
|
I.Index = -1;
|
||
|
|
||
|
UpdateListSize();
|
||
|
}
|
||
|
final function EmptyList()
|
||
|
{
|
||
|
local KFGUI_ListItem N,I;
|
||
|
|
||
|
for( I=FirstItem; I!=None; I=N )
|
||
|
{
|
||
|
N = I.Next;
|
||
|
|
||
|
// Add to unused list.
|
||
|
I.Next = UnusedItem;
|
||
|
UnusedItem = I;
|
||
|
I.Index = -1;
|
||
|
}
|
||
|
|
||
|
FirstItem = None;
|
||
|
UpdateListSize();
|
||
|
}
|
||
|
|
||
|
final function KFGUI_ListItem GetFromIndex( int Index )
|
||
|
{
|
||
|
local KFGUI_ListItem N;
|
||
|
|
||
|
if( Index<0 || Index>=ListCount )
|
||
|
return None;
|
||
|
for( N=FirstItem; N!=None; N=N.Next )
|
||
|
if( (Index--)==0 )
|
||
|
return N;
|
||
|
return None;
|
||
|
}
|
||
|
|
||
|
function SortColumn( int Column, optional bool bReverse )
|
||
|
{
|
||
|
local array<KFGUI_ListItem> List;
|
||
|
local KFGUI_ListItem Sel,N,P;
|
||
|
local int i;
|
||
|
|
||
|
if( !bCanSortColumn || Column<0 || Column>=Columns.Length )
|
||
|
return;
|
||
|
|
||
|
LastSortedColumn = Column;
|
||
|
bLastSortedReverse = bReverse;
|
||
|
bShouldSortList = true;
|
||
|
|
||
|
// Allocate memory space first.
|
||
|
List.Length = ListCount;
|
||
|
List.Length = 0;
|
||
|
|
||
|
// Grab current selected line.
|
||
|
Sel = GetFromIndex(SelectedRowIndex);
|
||
|
SelectedRowIndex = -1;
|
||
|
|
||
|
// Slow, sort it all.
|
||
|
for( N=FirstItem; N!=None; N=N.Next )
|
||
|
{
|
||
|
N.Temp = N.GetSortStr(Column);
|
||
|
|
||
|
if( bReverse )
|
||
|
{
|
||
|
for( i=0; i<List.Length; ++i )
|
||
|
if( List[i].Temp<N.Temp )
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for( i=0; i<List.Length; ++i )
|
||
|
if( List[i].Temp>N.Temp )
|
||
|
break;
|
||
|
}
|
||
|
List.Insert(i,1);
|
||
|
List[i] = N;
|
||
|
}
|
||
|
|
||
|
// Rebuild list.
|
||
|
FirstItem = None;
|
||
|
P = None;
|
||
|
for( i=0; i<List.Length; ++i )
|
||
|
{
|
||
|
N = List[i];
|
||
|
if( Sel==N )
|
||
|
SelectedRowIndex = i;
|
||
|
N.Index = i;
|
||
|
N.Next = None;
|
||
|
if( P==None )
|
||
|
FirstItem = N;
|
||
|
else P.Next = N;
|
||
|
P = N;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function ChangeListSize( int NewSize );
|
||
|
|
||
|
final function UpdateListSize()
|
||
|
{
|
||
|
local KFGUI_ListItem N;
|
||
|
|
||
|
ListCount = 0;
|
||
|
for( N=FirstItem; N!=None; N=N.Next )
|
||
|
N.Index = ListCount++;
|
||
|
bListSizeDirty = true;
|
||
|
}
|
||
|
|
||
|
function InitMenu()
|
||
|
{
|
||
|
ListCount = 0;
|
||
|
Super.InitMenu();
|
||
|
ColumnComp = KFGUI_ColumnTop(FindComponentID('Columns'));
|
||
|
}
|
||
|
|
||
|
final function DrawStrClipped( string S )
|
||
|
{
|
||
|
Canvas.PushMaskRegion(Canvas.OrgX,Canvas.OrgY,Canvas.ClipX,Canvas.ClipY);
|
||
|
Canvas.DrawText(S,,TextScaler,TextScaler,LineFontInfo);
|
||
|
Canvas.PopMaskRegion();
|
||
|
}
|
||
|
|
||
|
function DrawMenu()
|
||
|
{
|
||
|
local int i,n,j;
|
||
|
local float Y,TextY,YClip,XOffset;
|
||
|
local KFGUI_ListItem C;
|
||
|
local bool bCheckMouse;
|
||
|
|
||
|
Canvas.DrawColor = BackgroundColor;
|
||
|
Canvas.SetPos(0.f,0.f);
|
||
|
Owner.CurrentStyle.DrawWhiteBox(CompPos[2],CompPos[3]);
|
||
|
|
||
|
// Mouse focused item check.
|
||
|
bCheckMouse = bClickable && bFocused;
|
||
|
FocusMouseItem = -1;
|
||
|
if( bCheckMouse )
|
||
|
MouseYHit = Owner.MousePosition.Y - CompPos[1];
|
||
|
|
||
|
n = ScrollBar.CurrentScroll;
|
||
|
i = 0;
|
||
|
for( C=FirstItem; C!=None; C=C.Next )
|
||
|
if( (i++)==n )
|
||
|
break;
|
||
|
Y = 0.f;
|
||
|
TextY = (ItemHeight-TextHeight)*0.5f;
|
||
|
XOffset = TextY*0.75;
|
||
|
YClip = CompPos[1]+CompPos[3];
|
||
|
Canvas.SetDrawColor(250,250,250,255);
|
||
|
|
||
|
for( i=0; (i<ListItemsPerPage && C!=None); ++i )
|
||
|
{
|
||
|
// Check for mouse hit.
|
||
|
if( bCheckMouse && FocusMouseItem==-1 )
|
||
|
{
|
||
|
if( MouseYHit<ItemHeight )
|
||
|
FocusMouseItem = n;
|
||
|
else MouseYHit-=ItemHeight;
|
||
|
}
|
||
|
|
||
|
// Draw selection background.
|
||
|
if( SelectedRowIndex==n ) // Selected
|
||
|
{
|
||
|
Canvas.SetPos(0,Y);
|
||
|
Canvas.DrawColor = SelectedLineColor;
|
||
|
Owner.CurrentStyle.DrawWhiteBox(CompPos[2],ItemHeight);
|
||
|
Canvas.SetDrawColor(250,250,250,255);
|
||
|
}
|
||
|
else if( FocusMouseItem==n ) // Focused
|
||
|
{
|
||
|
Canvas.SetPos(0,Y);
|
||
|
Canvas.DrawColor = FocusedLineColor;
|
||
|
Owner.CurrentStyle.DrawWhiteBox(CompPos[2],ItemHeight);
|
||
|
Canvas.SetDrawColor(250,250,250,255);
|
||
|
}
|
||
|
|
||
|
// Draw columns of text
|
||
|
for( j=0; j<Columns.Length; ++j )
|
||
|
if( !Columns[j].bHidden )
|
||
|
{
|
||
|
Canvas.SetClip(Columns[j].X+Columns[j].XSize,YClip);
|
||
|
Canvas.SetPos(Columns[j].X+XOffset,TextY);
|
||
|
DrawStrClipped(C.GetDisplayStr(j));
|
||
|
}
|
||
|
Y+=ItemHeight;
|
||
|
TextY+=ItemHeight;
|
||
|
++n;
|
||
|
C = C.Next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function PreDraw()
|
||
|
{
|
||
|
local byte j;
|
||
|
local float XS,SpaceX;
|
||
|
|
||
|
ComputeCoords();
|
||
|
|
||
|
// Check font to use.
|
||
|
Canvas.Font = Owner.CurrentStyle.PickFont(Min(FontSize+Owner.CurrentStyle.DefaultFontSize,Owner.CurrentStyle.MaxFontScale),TextScaler);
|
||
|
Canvas.TextSize("ABC",XS,TextHeight,TextScaler,TextScaler);
|
||
|
|
||
|
for( j=0; j<4; ++j )
|
||
|
{
|
||
|
ScrollBar.InputPos[j] = CompPos[j];
|
||
|
ColumnComp.InputPos[j] = CompPos[j];
|
||
|
}
|
||
|
|
||
|
// Setup positioning.
|
||
|
// First compute the width scrollbar.
|
||
|
if( OldXSize!=InputPos[2] )
|
||
|
{
|
||
|
OldXSize = InputPos[2];
|
||
|
ScalerSize = ScrollBar.GetWidth();
|
||
|
ScrollBar.XPosition = 1.f - ScalerSize;
|
||
|
ColumnComp.XSize = ScrollBar.XPosition;
|
||
|
}
|
||
|
SpaceX = ScalerSize*CompPos[2];
|
||
|
CompPos[2] -= SpaceX;
|
||
|
ScrollBar.InputPos[3] = CompPos[3];
|
||
|
|
||
|
// Draw columns.
|
||
|
ColumnComp.YSize = (TextHeight*1.05) / CompPos[3];
|
||
|
ColumnComp.Canvas = Canvas;
|
||
|
ColumnComp.PreDraw();
|
||
|
|
||
|
// Move down to give space for columns.
|
||
|
CompPos[1] += ColumnComp.CompPos[3];
|
||
|
CompPos[3] -= ColumnComp.CompPos[3];
|
||
|
|
||
|
// Compute how many rows fit in with this setting.
|
||
|
ItemHeight = TextHeight*1.025;
|
||
|
ListItemsPerPage = CompPos[3]/ItemHeight;
|
||
|
ItemHeight = CompPos[3]/ListItemsPerPage;
|
||
|
if( OldItemsPerFrame!=ListItemsPerPage || bListSizeDirty )
|
||
|
{
|
||
|
if( SelectedRowIndex>=ListCount )
|
||
|
SelectedRowIndex = -1;
|
||
|
OldItemsPerFrame = ListItemsPerPage;
|
||
|
bListSizeDirty = false;
|
||
|
UpdateListVis();
|
||
|
}
|
||
|
|
||
|
// Draw vertical scrollbar
|
||
|
ScrollBar.Canvas = Canvas;
|
||
|
ScrollBar.PreDraw();
|
||
|
|
||
|
// Draw self.
|
||
|
Canvas.SetOrigin(CompPos[0],CompPos[1]);
|
||
|
Canvas.SetClip(CompPos[0]+CompPos[2],CompPos[1]+CompPos[3]);
|
||
|
DrawMenu();
|
||
|
|
||
|
// Reset scaling to allow mouse to capture input.
|
||
|
CompPos[1] -= ColumnComp.CompPos[3];
|
||
|
CompPos[2] += SpaceX;
|
||
|
CompPos[3] += ColumnComp.CompPos[3];
|
||
|
}
|
||
|
function InternalClickedItem( int Index, bool bRight, int MouseX, int MouseY )
|
||
|
{
|
||
|
SelectedRowIndex = Index;
|
||
|
OnSelectedRow(GetFromIndex(Index),Index,bRight,false);
|
||
|
}
|
||
|
function InternalDblClickedItem( int Index, bool bRight, int MouseX, int MouseY )
|
||
|
{
|
||
|
SelectedRowIndex = Index;
|
||
|
OnSelectedRow(GetFromIndex(Index),Index,bRight,true);
|
||
|
}
|
||
|
|
||
|
defaultproperties
|
||
|
{
|
||
|
ListItemClass=class'KFGUI_ListItem'
|
||
|
OnClickedItem=InternalClickedItem
|
||
|
OnDblClickedItem=InternalDblClickedItem
|
||
|
SelectedRowIndex=-1
|
||
|
bClickable=true
|
||
|
FocusedLineColor=(R=64,G=3,B=48,A=255)
|
||
|
SelectedLineColor=(R=84,G=26,B=128,A=255)
|
||
|
bCanSortColumn=true
|
||
|
|
||
|
Begin Object Class=KFGUI_ColumnTop Name=ColumnComps
|
||
|
XPosition=0
|
||
|
YPosition=0
|
||
|
XSize=1
|
||
|
YSize=0.04
|
||
|
ID="Columns"
|
||
|
End Object
|
||
|
Components.Add(ColumnComps)
|
||
|
|
||
|
LineFontInfo=(bClipText=true,bEnableShadow=false)
|
||
|
}
|