// ==================================================================== // 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 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 NewPanelClass; local GUITabButton NewTabButton; local GUITabPanel NewTabPanel; local int i; // Make sure this doesn't exist first for (i=0;i(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 NewPanelClass; local GUITabPanel NewTabPanel; local GUITabButton NewTabButton; if (ExistingPanel == None) NewPanelClass = class(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 NewPanelClass; local GUITabPanel NewTabPanel, OldTabPanel; if (ExistingPanel==None) NewPanelClass = class(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 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 }