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

653 lines
16 KiB
Ucode

// ====================================================================
// GUITabControl - This control has a number of tabs
//
// Written by Joe Wilcox
// (c) 2003, Epic Games, Inc. All Rights Reserved
//
// Updated by Ron Prestenback
// ====================================================================
class GUITabControl extends GUIMultiComponent
Native;
cpptext
{
void PreDraw(UCanvas* Canvas);
void Draw(UCanvas* Canvas);
UGUIComponent* UnderCursor(FLOAT MouseX, FLOAT MouseY);
UBOOL SpecialHit( UBOOL bForce );
UBOOL MousePressed(UBOOL IsRepeat); // The Mouse was pressed
UBOOL MouseReleased(); // The Mouse was released
UBOOL IsFocusedOn( const UGUIComponent* Comp ) const;
#ifdef UCONST_Counter
virtual void ResetCounter();
#endif
}
var() bool bFillSpace; // Tab buttons should be resized if cumulative width is smaller than WinWidth
var() bool bDockPanels; // If true, associated panels will dock vertically with this control
var() bool bDrawTabAbove; // If true, tabs are drawn above the tab panels
var() bool bFillBackground;
var() color FillColor;
var() float FadeInTime;
var() float TabHeight;
var() string BackgroundStyleName;
var() Material BackgroundImage;
var() editconst noexport array<GUITabButton> TabStack;
var() editconst noexport GUITabButton ActiveTab, PendingTab;
var() editconst noexport GUIStyles BackgroundStyle;
var() editconst noexport GUIBorder MyFooter;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController, MyOwner);
if (BackgroundStyleName != "")
BackgroundStyle = Controller.GetStyle(BackgroundStyleName,FontScale);
OnKeyEvent = InternalOnKeyEvent;
}
event Opened( GUIComponent Sender )
{
local int i;
Super.Opened(Sender);
for ( i = 0; i < TabStack.Length; i++ )
{
if ( TabStack[i] != None )
TabStack[i].Opened(Self);
}
if ( !bInit && bVisible && ActiveTab != None && ActiveTab.MyPanel != None )
ActivateTab(ActiveTab, True);
bInit = false;
}
event Closed( GUIComponent Sender, bool bCancelled )
{
local int i;
Super.Closed(Sender,bCancelled);
for ( i = 0; i < TabStack.Length; i++ )
if ( TabStack[i] != None )
TabStack[i].Closed(Sender,bCancelled);
}
function bool InternalOnKeyEvent(out byte Key, out byte State, float delta)
{
local int i,aTabIndex, StartIndex;
if ( (FocusedControl!=None) || (TabStack.Length<=0) )
return false;
if (ActiveTab == None)
return false;
for(i=0;i<TabStack.Length;i++)
{
if (TabStack[i]==ActiveTab)
{
aTabIndex = i;
break;
}
}
if ( Key==0x25 && State == 1 ) // Left
{
StartIndex = aTabIndex;
while (true)
{
if (aTabIndex==0)
aTabIndex=TabStack.Length-1;
else
aTabIndex--;
// Send false for bFocusPanel to ActivateTab here to continue using left/right
if (aTabIndex == StartIndex || ActivateTab(TabStack[aTabIndex], False))
break;
}
return true;
}
if ( Key==0x27 && State == 1 ) // Right
{
StartIndex = aTabIndex;
while (true)
{
aTabIndex++;
if (aTabIndex==TabStack.Length)
aTabIndex=0;
// Send false for bFocusPanel to ActivateTab here to continue using left/right
if (StartIndex == aTabIndex || ActivateTab(TabStack[aTabIndex], False))
break;
}
return true;
}
return false;
}
function GUITabPanel AddTabItem( GUITabItem Item )
{
return AddTab( Item.Caption, Item.ClassName, ,Item.Hint );
}
function GUITabPanel AddTab(string InCaption, string PanelClass, optional GUITabPanel ExistingPanel, optional string InHint, optional bool bForceActive)
{
local class<GUITabPanel> NewPanelClass;
local GUITabButton NewTabButton;
local GUITabPanel NewTabPanel;
local int i;
// Make sure this doesn't exist first
for (i=0;i<TabStack.Length;i++)
{
if (TabStack[i].Caption ~= InCaption)
{
log("A tab with the caption"@InCaption@"already exists.");
return none;
}
}
if (ExistingPanel==None)
NewPanelClass = class<GUITabPanel>(Controller.AddComponentClass(PanelClass));
if ( (ExistingPanel!=None) || (NewPanelClass != None) )
{
if (ExistingPanel != None)
NewTabPanel = GUITabPanel(AppendComponent(ExistingPanel,True));
else if (NewPanelClass != None)
NewTabPanel = GUITabPanel(AddComponent(PanelClass,True));
if (NewTabPanel == None)
{
log("Could not create panel for"@NewPanelClass);
return None;
}
if (NewTabPanel.MyButton != None)
NewTabButton = NewTabPanel.MyButton;
else
{
NewTabButton = new class'GUITabButton';
if (NewTabButton==None)
{
log("Could not create tab for"@NewPanelClass);
return None;
}
NewTabButton.InitComponent(Controller, Self);
NewTabButton.Opened(Self);
NewTabPanel.MyButton = NewTabButton;
if (!bDrawTabAbove)
{
NewTabPanel.MyButton.bBoundToParent = False;
NewTabPanel.MyButton.Style = Controller.GetStyle("FlippedTabButton",NewTabPanel.FontScale);
}
}
NewTabPanel.MyButton.Hint = Eval(InHint != "", InHint, NewTabPanel.Hint);
NewTabPanel.MyButton.Caption = Eval(InCaption != "", InCaption, NewTabPanel.PanelCaption);
NewTabPanel.MyButton.OnClick = InternalTabClick;
NewTabPanel.MyButton.MyPanel = NewTabPanel;
NewTabPanel.MyButton.FocusInstead = self;
NewTabPanel.MyButton.bNeverFocus = true;
NewTabPanel.InitPanel();
// Add the tab to controls
TabStack[TabStack.Length] = NewTabPanel.MyButton;
if ( (TabStack.Length==1 && bVisible) || (bForceActive) )
ActivateTab(NewTabPanel.MyButton,true);
else NewTabPanel.Hide();
return NewTabPanel;
}
return none;
}
function GUITabPanel InsertTab(int Pos, string Caption, string PanelClass, optional GUITabPanel ExistingPanel, optional string InHint, optional bool bForceActive)
{
local class<GUITabPanel> NewPanelClass;
local GUITabPanel NewTabPanel;
local GUITabButton NewTabButton;
if (ExistingPanel == None)
NewPanelClass = class<GUITabPanel>(Controller.AddComponentClass(PanelClass));
if ( ExistingPanel != None || NewPanelClass != None)
{
if (ExistingPanel != None)
NewTabPanel = GUITabPanel(AppendComponent(ExistingPanel,True));
else if (NewPanelClass != None)
NewTabPanel = GUITabPanel(AddComponent(PanelClass,True));
if (NewTabPanel == None)
{
log("Could not create panel for"@NewPanelClass);
return None;
}
if (NewTabPanel.MyButton != None)
NewTabButton = NewTabPanel.MyButton;
else
{
NewTabButton = new class'GUITabButton';
if (NewTabButton==None)
{
log("Could not create tab for"@NewPanelClass);
return None;
}
NewTabButton.InitComponent(Controller, Self);
NewTabButton.Opened(Self);
NewTabPanel.MyButton = NewTabButton;
}
NewTabPanel.MyButton.Caption = Caption;
NewTabPanel.MyButton.Hint = InHint;
NewTabPanel.MyButton.OnClick = InternalTabClick;
NewTabPanel.MyButton.MyPanel = NewTabPanel;
NewTabPanel.MyButton.FocusInstead = self;
NewTabPanel.MyButton.bNeverFocus = true;
NewTabPanel.InitPanel();
TabStack.Insert(Pos, 1);
TabStack[Pos] = NewTabPanel.MyButton;
if (TabStack.Length==1 || bForceActive)
ActivateTab(NewTabPanel.MyButton,true);
else NewTabPanel.Hide();
return NewTabPanel;
}
return None;
}
function GUITabPanel ReplaceTab(GUITabButton Which, string Caption, string PanelClass, optional GUITabPanel ExistingPanel, optional string InHint, optional bool bForceActive)
{
local class<GUITabPanel> NewPanelClass;
local GUITabPanel NewTabPanel, OldTabPanel;
if (ExistingPanel==None)
NewPanelClass = class<GUITabPanel>(Controller.AddComponentClass(PanelClass));
if ( (ExistingPanel!=None) || (NewPanelClass != None) )
{
OldTabPanel = Which.MyPanel;
if (ExistingPanel==None)
NewTabPanel = GUITabPanel(AddComponent(PanelClass, True));
else
NewTabPanel = GUITabPanel(AppendComponent(ExistingPanel, True));
if (NewTabPanel==None)
{
log("Could not create panel"@NewPanelClass);
return none;
}
Which.Caption = Caption;
Which.Hint = InHint;
Which.MyPanel = NewTabPanel;
NewTabPanel.MyButton = Which;
// Init new panel
NewTabPanel.InitPanel();
// Make sure to notify old tab - so use ActivateTab
if ( bForceActive )
ActivateTab(NewTabPanel.MyButton, True);
else NewTabPanel.Hide();
// Notify old panel
RemoveComponent(OldTabPanel);
OldTabPanel.Free();
return NewTabPanel;
}
return none;
}
function RemoveTab(optional string Caption, optional GUITabButton who)
{
local int i;
local bool bActive;
local GUITabPanel OldPanel;
if ( (caption=="") && (Who==None) )
return;
if (Who==None)
i = TabIndex(Caption);
else i = TabIndex(Who.Caption);
if (i < 0)
return;
OldPanel = TabStack[i].MyPanel;
bActive = TabStack[i] == ActiveTab;
TabStack[i].OnClick = None;
TabStack[i].Free();
TabStack.Remove(i, 1);
RemoveComponent(OldPanel,True);
OldPanel.Free();
if (bActive)
LostActiveTab();
}
function bool LostActiveTab()
{
local int i;
if (!Controller.bCurMenuInitialized)
return false;
for (i = 0; i < TabStack.Length; i++)
if (ActivateTab(TabStack[i],true))
return true;
return false;
}
event MakeTabActive(GUITabButton Who)
{
if (ActiveTab!=None)
ActiveTab.ChangeActiveState(false,false);
PendingTab = None;
ActiveTab = Who;
OnChange(Who);
}
function bool ActivateTab(GUITabButton Who, bool bFocusPanel)
{
if (Who == none || PendingTab != None || !Who.CanShowPanel()) // null or not selectable
return false;
Who.bForceFlash = False;
if (Who==ActiveTab) // Same Tab, just accept
{
if ( ActiveTab.ChangeActiveState(True, bFocusPanel) )
return true;
return false;
}
PendingTab = Who;
if ( PendingTab.ChangeActiveState(True, bFocusPanel) )
{
if (PendingTab.MyPanel.FadeInTime==0.0 || TabStack.Length<2)
MakeTabActive(Who);
else
{
FadeInTime = PendingTab.MyPanel.FadeInTime;
if (!Controller.bQuietMenu)
PlayerOwner().PlayOwnedSound(Controller.FadeSound,SLOT_Interface,1.0);
}
return true;
}
PendingTab = None;
return false;
}
function bool ActivateTabByName(string tabname, bool bFocusPanel)
{
local int i;
i = TabIndex(TabName);
if (i < 0 || i >= TabStack.Length) return false;
return ActivateTab(TabStack[i], bFocusPanel);
}
function bool ActivateTabByPanel( GUITabPanel Panel, bool bFocusPanel )
{
local int i;
if ( Panel == None || !Panel.CanShowPanel() )
return false;
for ( i = 0; i < TabStack.Length; i++ )
if ( TabStack[i] != None && TabStack[i].MyPanel == Panel )
return ActivateTab(TabStack[i], bFocusPanel);
return false;
}
function bool InternalTabClick(GUIComponent Sender)
{
local GUITabButton But;
But = GUITabButton(Sender);
if (But==None)
return false;
ActivateTab(But,true);
return true;
}
event bool NextPage()
{
local int i;
// If 1 or no tabs in the stack, then query parents
if (TabStack.Length < 2)
return Super.NextPage();
if (ActiveTab == None)
i = 0;
else
{
i = TabIndex(ActiveTab.Caption) + 1;
if ( i >= TabStack.Length )
i = 0;
}
return ActivateTab(TabStack[i], true);
}
event bool PrevPage()
{
local int i;
if (TabStack.Length < 2)
return Super.PrevPage();
if (ActiveTab == None)
i = TabStack.Length - 1;
else
{
i = TabIndex(ActiveTab.Caption) - 1;
if ( i < 0 )
i = TabStack.Length - 1;
}
return ActivateTab(TabStack[i], true);
}
event bool NextControl(GUIComponent Sender)
{
if (Sender != None)
{
Super(GUIComponent).SetFocus(None);
return true;
}
else
{
if ( Super(GUIComponent).NextControl(Self) )
return true;
else FocusFirst(None);
return true;
}
return false;
}
event bool PrevControl(GUIComponent Sender)
{
if ( Sender != None )
{
Super(GUIComponent).SetFocus(None);
return true;
}
else
{
if ( Super(GUIComponent).PrevControl(Self) )
return true;
else FocusLast(None);
}
return false;
}
function int TabIndex(string TabName)
{
local int i;
for (i = 0; i < TabStack.Length; i++)
if (TabStack[i].Caption ~= TabName)
return i;
return -1;
}
function GUITabPanel FindPanelClass( class<GUITabPanel> PanelClass )
{
local int i;
if ( PanelClass == None )
return None;
for ( i = 0; i < TabStack.Length; i++ )
{
if ( TabStack[i] != None && TabStack[i].MyPanel != None &&
ClassIsChildOf(TabStack[i].MyPanel.Class, PanelClass) )
return TabStack[i].MyPanel;
}
return None;
}
function GUITabPanel BorrowPanel(string Caption)
{
local int i;
if (Caption == "") return None;
i = TabIndex(Caption);
if (i < 0) return None;
return TabStack[i].MyPanel;
}
function SetVisibility(bool bIsVisible)
{
Super.SetVisibility(bIsVisible);
if (ActiveTab != None)
ActiveTab.ChangeActiveState(bIsVisible, False);
}
function InternalOnActivate()
{
if (ActiveTab == None)
LostActiveTab();
}
function bool FocusFirst(GUIComponent Sender)
{
if ( ActiveTab != None && ActiveTab.MyPanel != None && ActiveTab.MyPanel.CanAcceptFocus() && ActiveTab.MyPanel.FocusFirst(None) )
return true;
else if (!Super.FocusFirst(Sender))
Super(GUIComponent).SetFocus(None);
return true;
}
function bool FocusLast(GUIComponent Sender)
{
if ( ActiveTab != None && ActiveTab.MyPanel != None && ActiveTab.MyPanel.CanAcceptFocus() && ActiveTab.MyPanel.FocusLast(None) )
return true;
else if ( !Super.FocusLast(Sender) )
Super(GUIComponent).SetFocus(None);
return true;
}
function CenterMouse()
{
if ( ActiveTab != None )
ActiveTab.CenterMouse();
else Super.CenterMouse();
}
event Free()
{
local int i;
for ( i = 0; i < TabStack.Length; i++ )
{
if ( TabStack[i] != None )
TabStack[i].Free();
}
Super.Free();
}
function LevelChanged()
{
local int i;
for ( i = 0; i < TabStack.Length; i++ )
{
if ( TabStack[i] != None )
TabStack[i].LevelChanged();
}
Super.LevelChanged();
}
defaultproperties
{
OnActivate=InternalOnActivate
bDrawTabAbove=true
TabHeight=0.0350
bFillSpace=false
bTabStop=true
bDockPanels=false
bFillBackground=true
}