582 lines
14 KiB
Ucode
582 lines
14 KiB
Ucode
// ====================================================================
|
|
// The GUIList is a basic list component.
|
|
//
|
|
// Written by Joe Wilcox
|
|
// Updated by Ron Prestenback
|
|
// (c) 2002, 2003, Epic Games, Inc. All Rights Reserved
|
|
// ====================================================================
|
|
|
|
class GUIList extends GUIVertList
|
|
Native;
|
|
|
|
// if _RO_
|
|
// else
|
|
//#exec OBJ LOAD FILE=InterfaceContent.utx
|
|
// end if _RO_
|
|
|
|
cpptext
|
|
{
|
|
protected:
|
|
virtual void DrawItem(UCanvas* Canvas, INT Item, FLOAT X, FLOAT Y, FLOAT W, FLOAT HT, UBOOL bSelected, UBOOL bPending);
|
|
public:
|
|
}
|
|
|
|
var() eTextAlign TextAlign; // How is text Aligned in the control
|
|
var() editconstarray editconst array<GUIListElem> Elements;
|
|
var() editconstarray editconst array<GUIListElem> SelectedElements; // Used to easily support drag-n-drop between the same list
|
|
|
|
var() color OfficialColor; // Used to signify items standard in UT2003
|
|
var() color Official2004Color; // Used to signify items standard in UT2004
|
|
var() color BonusPackColor; // Used to signify items standard in BonusPacks
|
|
|
|
native final function SortList();
|
|
|
|
function Sort()
|
|
{
|
|
Super.Sort();
|
|
SortList();
|
|
}
|
|
|
|
// Used by SortList.
|
|
delegate int CompareItem(GUIListElem ElemA, GUIListElem ElemB)
|
|
{
|
|
return StrCmp(ElemA.Item, ElemB.Item);
|
|
}
|
|
|
|
// Accessor function for the items.
|
|
|
|
// Functions for manipulating entire list elements
|
|
function Add(string NewItem, optional Object obj, optional string Str, optional bool bSection)
|
|
{
|
|
local int NewIndex;
|
|
local GUIListElem E;
|
|
|
|
if ( !bAllowEmptyItems && NewItem == "" && Obj == None && Str == "" )
|
|
return;
|
|
|
|
E.Item = NewItem;
|
|
E.ExtraData = Obj;
|
|
E.ExtraStrData = Str;
|
|
E.bSection = bSection;
|
|
|
|
if (bSorted && Elements.Length > 0)
|
|
{
|
|
while (NewIndex < Elements.Length && CompareItem(Elements[NewIndex], E) < 0)
|
|
NewIndex++;
|
|
}
|
|
else NewIndex = Elements.Length;
|
|
|
|
Elements.Insert(NewIndex, 1);
|
|
Elements[NewIndex] = E;
|
|
|
|
ItemCount = Elements.Length;
|
|
|
|
if (Elements.Length == 1 && bInitializeList)
|
|
SetIndex(0);
|
|
else if ( bNotify )
|
|
CheckLinkedObjects(Self);
|
|
|
|
if (MyScrollBar != None)
|
|
MyScrollBar.AlignThumb();
|
|
}
|
|
|
|
function AddElement( GUIListElem NewElem )
|
|
{
|
|
Add( NewElem.Item, NewElem.ExtraData, NewElem.ExtraStrData );
|
|
}
|
|
|
|
function Replace(int i, string NewItem, optional Object obj, optional string Str, optional bool bNoSort)
|
|
{
|
|
if ( !IsValidIndex(i) )
|
|
Add(NewItem,Obj,Str);
|
|
else
|
|
{
|
|
if ( !bAllowEmptyItems && NewItem == "" && Obj == None && Str == "" )
|
|
return;
|
|
|
|
Elements[i].Item = NewItem;
|
|
Elements[i].ExtraData = obj;
|
|
Elements[i].ExtraStrData = Str;
|
|
if ( bSorted && !bNoSort )
|
|
Sort();
|
|
|
|
SetIndex(Index);
|
|
}
|
|
}
|
|
|
|
function Insert(int i, string NewItem, optional Object obj, optional string Str, optional bool bNoSort, optional bool bSection )
|
|
{
|
|
if ( !IsValidIndex(i) )
|
|
Add(NewItem,Obj,Str, bSection);
|
|
else
|
|
{
|
|
if ( !bAllowEmptyItems && NewItem == "" && Obj == None && Str == "" )
|
|
return;
|
|
|
|
Elements.Insert(i,1);
|
|
Elements[i].Item=NewItem;
|
|
Elements[i].ExtraData=obj;
|
|
Elements[i].ExtraStrData=Str;
|
|
Elements[i].bSection=bSection;
|
|
|
|
ItemCount = Elements.Length;
|
|
|
|
if ( bSorted && !bNoSort )
|
|
Sort();
|
|
|
|
SetIndex(Index);
|
|
|
|
if (MyScrollBar != None)
|
|
MyScrollBar.AlignThumb();
|
|
}
|
|
}
|
|
|
|
function InsertElement( int i, GUIListElem NewElem, optional bool bNoSort )
|
|
{
|
|
Insert( i, NewElem.Item, NewElem.ExtraData, NewElem.ExtraStrData, bNoSort );
|
|
}
|
|
|
|
event Swap(int IndexA, int IndexB)
|
|
{
|
|
local GUI.GUIListElem elem;
|
|
|
|
if ( IsValidIndex(IndexA) && IsValidIndex(IndexB) )
|
|
{
|
|
elem = Elements[IndexA];
|
|
Elements[IndexA] = Elements[IndexB];
|
|
Elements[IndexB] = elem;
|
|
|
|
if (bSorted)
|
|
Sort();
|
|
|
|
if ( bNotify )
|
|
CheckLinkedObjects(Self);
|
|
}
|
|
}
|
|
|
|
function LoadFrom(GUIList Source, optional bool bClearFirst)
|
|
{
|
|
local string t1,t2;
|
|
local object t;
|
|
local int i;
|
|
|
|
if (bClearfirst)
|
|
Clear();
|
|
|
|
for (i=0;i<Source.Elements.Length;i++)
|
|
{
|
|
Source.GetAtIndex(i,t1,t,t2);
|
|
Add(t1,t,t2);
|
|
}
|
|
}
|
|
|
|
function int Remove(int i, optional int Count, optional bool bNoSort)
|
|
{
|
|
Count = Max( Count, 1 );
|
|
|
|
if (!IsValidIndex(i))
|
|
return Index;
|
|
|
|
Elements.Remove(i, Min(Count, Elements.Length - i));
|
|
ItemCount = Elements.Length;
|
|
|
|
if ( bSorted && !bNoSort )
|
|
Sort();
|
|
|
|
// In case we now have an invalid index
|
|
SetIndex(Index);
|
|
|
|
if (MyScrollBar != None)
|
|
MyScrollBar.AlignThumb();
|
|
|
|
return Index;
|
|
}
|
|
|
|
function int RemoveSilent(int i, optional int Count)
|
|
{
|
|
bNotify = False;
|
|
i = Remove(i, Count, True);
|
|
bNotify = True;
|
|
return i;
|
|
}
|
|
|
|
function int RemoveElement(GUIListElem Elem, optional int Count, optional bool bNoSort)
|
|
{
|
|
local int i;
|
|
|
|
Count = Max( Count, 1 );
|
|
for ( i = 0; i < Elements.Length; i++ )
|
|
{
|
|
if ( Elements[i] == Elem )
|
|
{
|
|
Elements.Remove(i, Min(Count, Elements.Length - i));
|
|
break;
|
|
}
|
|
}
|
|
|
|
ItemCount = Elements.Length;
|
|
if ( bSorted && !bNoSort )
|
|
Sort();
|
|
|
|
// In case we now have an invalid index
|
|
SetIndex(Index);
|
|
|
|
if ( MyScrollBar != None )
|
|
MyScrollBar.AlignThumb();
|
|
|
|
return Index;
|
|
}
|
|
|
|
function Clear()
|
|
{
|
|
if (Elements.Length == 0)
|
|
return;
|
|
|
|
Elements.Remove(0,Elements.Length);
|
|
ItemCount = 0;
|
|
Super.Clear();
|
|
}
|
|
|
|
// =====================================================================================================================
|
|
// =====================================================================================================================
|
|
// Query Functions
|
|
// =====================================================================================================================
|
|
// =====================================================================================================================
|
|
|
|
// Backwards compatibility
|
|
function string SelectedText()
|
|
{
|
|
return Get();
|
|
}
|
|
|
|
// Current listitem
|
|
function string Get(optional bool bGuarantee)
|
|
{
|
|
if ( !IsValid() )
|
|
{
|
|
if (bGuarantee && Elements.Length > 0)
|
|
return Elements[0].Item;
|
|
|
|
return "";
|
|
}
|
|
|
|
return Elements[Index].Item;
|
|
}
|
|
|
|
function object GetObject()
|
|
{
|
|
if ( !IsValid() )
|
|
return none;
|
|
|
|
return Elements[Index].ExtraData;
|
|
}
|
|
|
|
function string GetExtra()
|
|
{
|
|
if ( !IsValid() )
|
|
return "";
|
|
|
|
return Elements[Index].ExtraStrData;
|
|
}
|
|
|
|
function bool IsSection()
|
|
{
|
|
if ( !IsValid() )
|
|
return false;
|
|
|
|
return Elements[Index].bSection;
|
|
}
|
|
|
|
// Arbitrary list Item
|
|
function string GetItemAtIndex(int i)
|
|
{
|
|
if (!IsValidIndex(i))
|
|
return "";
|
|
|
|
return Elements[i].Item;
|
|
}
|
|
|
|
function object GetObjectAtIndex(int i)
|
|
{
|
|
if (!IsValidIndex(i))
|
|
return None;
|
|
|
|
return Elements[i].ExtraData;
|
|
}
|
|
|
|
function string GetExtraAtIndex(int i)
|
|
{
|
|
if (!IsValidIndex(i))
|
|
return "";
|
|
|
|
return Elements[i].ExtraStrData;
|
|
}
|
|
|
|
function GetAtIndex(int i, out string ItemStr, out object ExtraObj, out string ExtraStr)
|
|
{
|
|
if (!IsValidIndex(i))
|
|
return;
|
|
|
|
ItemStr = Elements[i].Item;
|
|
ExtraObj = Elements[i].ExtraData;
|
|
ExtraStr = Elements[i].ExtraStrData;
|
|
}
|
|
|
|
// =====================================================================================================================
|
|
// =====================================================================================================================
|
|
// Assignment functions
|
|
// =====================================================================================================================
|
|
// =====================================================================================================================
|
|
|
|
function SetItemAtIndex(int i, string NewItem)
|
|
{
|
|
if (!IsValidIndex(i))
|
|
return;
|
|
|
|
Elements[i].Item = NewItem;
|
|
if ( bNotify )
|
|
CheckLinkedObjects(Self);
|
|
}
|
|
|
|
function SetObjectAtIndex(int i, Object NewObject)
|
|
{
|
|
if (!IsValidIndex(i))
|
|
return;
|
|
|
|
Elements[i].ExtraData = NewObject;
|
|
if ( bNotify )
|
|
CheckLinkedObjects(Self);
|
|
}
|
|
|
|
function SetExtraAtIndex(int i, string NewExtra)
|
|
{
|
|
if (!IsValidIndex(i))
|
|
return;
|
|
|
|
Elements[i].ExtraStrData = NewExtra;
|
|
if ( bNotify )
|
|
CheckLinkedObjects(Self);
|
|
}
|
|
|
|
function RemoveItem(string Item)
|
|
{
|
|
local int i;
|
|
|
|
// Work through array. If we find it, remove it (will reduce Elements.Length).
|
|
// If we don't, move on to next one.
|
|
while( i < Elements.Length)
|
|
{
|
|
if(Item ~= Elements[i].Item)
|
|
Elements.Remove(i, 1);
|
|
else
|
|
i++;
|
|
}
|
|
|
|
ItemCount = Elements.Length;
|
|
|
|
SetIndex(-1);
|
|
if (MyScrollBar != None)
|
|
MyScrollBar.AlignThumb();
|
|
}
|
|
|
|
function RemoveObject(Object Obj)
|
|
{
|
|
local int i;
|
|
|
|
while (i < Elements.Length)
|
|
{
|
|
if (Obj == Elements[i].ExtraData)
|
|
Elements.Remove(i, 1);
|
|
else i++;
|
|
}
|
|
|
|
ItemCount = Elements.Length;
|
|
|
|
SetIndex(-1);
|
|
if (MyScrollBar != None)
|
|
MyScrollBar.AlignThumb();
|
|
}
|
|
|
|
function RemoveExtra(string Str)
|
|
{
|
|
local int i;
|
|
|
|
while (i < Elements.Length)
|
|
{
|
|
if (Str ~= Elements[i].ExtraStrData)
|
|
Elements.Remove(i, 1);
|
|
else i++;
|
|
}
|
|
|
|
ItemCount = Elements.Length;
|
|
|
|
SetIndex(-1);
|
|
if (MyScrollBar != None)
|
|
MyScrollBar.AlignThumb();
|
|
}
|
|
|
|
|
|
// =====================================================================================================================
|
|
// =====================================================================================================================
|
|
// Search functions
|
|
// =====================================================================================================================
|
|
// =====================================================================================================================
|
|
function string Find(string Text, optional bool bExact, optional bool bExtra)
|
|
{
|
|
local int i;
|
|
|
|
i = FindIndex(Text, bExact, bExtra);
|
|
if (i != -1)
|
|
{
|
|
SetIndex(i);
|
|
return Elements[i].Item;
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
function int FindExtra(string Text, optional bool bExact)
|
|
{
|
|
return FindIndex(Text, bExact, True);
|
|
}
|
|
|
|
function int FindItemObject(Object Obj)
|
|
{
|
|
return FindIndex("",,,Obj);
|
|
}
|
|
|
|
function int FindIndex(string Test, optional bool bExact, optional bool bExtra, optional Object TestObject)
|
|
{
|
|
local int i;
|
|
|
|
if (TestObject != None)
|
|
{
|
|
for (i = 0; i < Elements.Length; i++)
|
|
if ( TestObject == Elements[i].ExtraData )
|
|
return i;
|
|
}
|
|
|
|
else if (Test != "")
|
|
{
|
|
if (bExtra)
|
|
{
|
|
for (i = 0; i < Elements.Length; i++)
|
|
if ( (bExact && Elements[i].ExtraStrData == Test) || (!bExact && Elements[i].ExtraStrData ~= Test) )
|
|
return i;
|
|
}
|
|
|
|
else
|
|
{
|
|
for ( i = 0; i < Elements.Length; i++)
|
|
if ( (bExact && Elements[i].Item == Test) || (!bExact && Elements[i].Item ~= Test) )
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// =====================================================================================================================
|
|
// =====================================================================================================================
|
|
// Drag-n-drop interface
|
|
// =====================================================================================================================
|
|
// =====================================================================================================================
|
|
|
|
// Called on the drop source when when an Item has been dropped. bAccepted tells it whether
|
|
// the operation was successful or not.
|
|
function InternalOnEndDrag(GUIComponent Accepting, bool bAccepted)
|
|
{
|
|
local int i;
|
|
|
|
// log(Name@"InternalOnEndDrag Accepting:"$Accepting@"bAccepted:"$bAccepted);
|
|
if (bAccepted && Accepting != None)
|
|
{
|
|
GetPendingElements();
|
|
if ( Accepting != Self )
|
|
{
|
|
for ( i = 0; i < SelectedElements.Length; i++ )
|
|
RemoveElement(SelectedElements[i]);
|
|
}
|
|
|
|
bRepeatClick = False;
|
|
}
|
|
|
|
// Simulate repeat click if the operation was a failure to prevent InternalOnMouseRelease from clearing
|
|
// the SelectedItems array
|
|
// This way we don't lose the items we clicked on
|
|
if (Accepting == None)
|
|
bRepeatClick = True;
|
|
|
|
SetOutlineAlpha(255);
|
|
if ( bNotify )
|
|
CheckLinkedObjects(Self);
|
|
}
|
|
|
|
// Called on the drop target when the mouse is released - Sender is always DropTarget
|
|
function bool InternalOnDragDrop(GUIComponent Sender)
|
|
{
|
|
local array<GUIListElem> NewItem;
|
|
local int i;
|
|
// log(Name@"InternalOnDragDrop Sender:"$ Sender);
|
|
|
|
if (Controller.DropTarget == Self)
|
|
{
|
|
if (Controller.DropSource != None && GUIList(Controller.DropSource) != None)
|
|
{
|
|
NewItem = GUIList(Controller.DropSource).GetPendingElements();
|
|
|
|
// Special case for drag-n-drop between the same list.
|
|
if ( Controller.DropSource == Self )
|
|
{
|
|
for ( i = NewItem.Length - 1; i >= 0; i-- )
|
|
RemoveElement(NewItem[i],,True);
|
|
}
|
|
|
|
if ( !IsValidIndex(DropIndex) )
|
|
DropIndex = ItemCount;
|
|
|
|
for (i = NewItem.Length - 1; i >= 0; i--)
|
|
Insert(DropIndex, NewItem[i].Item, NewItem[i].ExtraData, NewItem[i].ExtraStrData);
|
|
|
|
SetIndex(DropIndex);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function ClearPendingElements()
|
|
{
|
|
Super.ClearPendingElements();
|
|
if ( SelectedItems.Length == 0 )
|
|
SelectedElements.Remove(0, SelectedElements.Length);
|
|
}
|
|
|
|
function array<GUIListElem> GetPendingElements(optional bool bGuarantee)
|
|
{
|
|
local int i;
|
|
|
|
if ( (DropState == DRP_Source && Controller.DropSource == Self) || bGuarantee )
|
|
{
|
|
if ( SelectedElements.Length == 0 )
|
|
{
|
|
for (i = 0; i < SelectedItems.Length; i++)
|
|
if (IsValidIndex(SelectedItems[i]))
|
|
SelectedElements[SelectedElements.Length] = Elements[SelectedItems[i]];
|
|
|
|
if ( SelectedElements.Length == 0 && IsValid() )
|
|
{
|
|
SelectedElements.Length = SelectedElements.Length + 1;
|
|
GetAtIndex(Index, SelectedElements[0].Item, SelectedElements[0].ExtraData, SelectedElements[0].ExtraStrData);
|
|
}
|
|
}
|
|
|
|
return SelectedElements;
|
|
}
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
TextAlign=TXTA_Center
|
|
}
|