// 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 Columns; var() class 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.TempN.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 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; iN.Temp ) break; } List.Insert(i,1); List[i] = N; } // Rebuild list. FirstItem = None; P = None; for( i=0; i=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) }