// Copyright Steve Streeting 2020 onwards // Released under the MIT license #include "StevesUI/TabListWidget.h" #include "Components/HorizontalBoxSlot.h" #include "Components/WidgetSwitcher.h" #include "StevesUI/TabButton.h" #include "StevesUI/FocusableButton.h" #include "StevesUI/MenuBase.h" #include "Widgets/SPanel.h" void UTabListWidget::SetTargetWidgetSwitcher(UWidgetSwitcher* WidgetSwitcher) { TargetWidgetSwitcher=WidgetSwitcher; } bool UTabListWidget::RegisterTab(const FName TabID, const TSubclassOf ButtonWidgetType,FText Label, UWidget* ContentWidget) { if (RegisteredTabs.Contains(TabID)) { UE_LOG(LogTemp,Error,TEXT("UTabListWidget::RegisterTab Already Registered ID %s"),*TabID.ToString()); return false; } if (TabButtonContainer==nullptr) { UE_LOG(LogTemp,Error,TEXT("UTabListWidget::RegisterTab TabButtonContainer is not set")); return false; } FName const ButtonName( *FString::Printf(TEXT("TabButton_%s"),*TabID.ToString())); UTabButton* const NewTabButton = Cast(CreateWidget(this,ButtonWidgetType,ButtonName)); const int CurrentTabCount = RegisteredTabs.Num(); const int NewTabIndex = CurrentTabCount; FTabListRegisteredTabInfo TabInfo; TabInfo.TabIndex = NewTabIndex; TabInfo.TabButton = NewTabButton; TabInfo.ContentInstance = ContentWidget; RegisteredTabs.Add(TabID, TabInfo); UPanelSlot* ButtonPanelSlot=TabButtonContainer->AddChild(NewTabButton); UHorizontalBoxSlot* HorizontalBoxSlot=Cast(ButtonPanelSlot); if (HorizontalBoxSlot) { HorizontalBoxSlot->SetPadding(TabButtonPadding); } NewTabButton->OnTabSelected.AddUniqueDynamic(this,&UTabListWidget::TabPressed); NewTabButton->TabIndex=NewTabIndex; NewTabButton->Initialise(NewTabIndex,Label); // If first tab added, select this if (CurrentTabCount==0) { SelectTab(0); } return true; } void UTabListWidget::TabPressed(int TabIndex) { SelectTab(TabIndex); } bool UTabListWidget::GetTabDataForIndex(const int Index,FTabListRegisteredTabInfo& TabInfo) { for (const auto& InfoPair : RegisteredTabs) { if (InfoPair.Value.TabIndex==Index) { TabInfo=InfoPair.Value; return true; } } return false; } void UTabListWidget::IncrementTabIndex(int Amount) { int NewTabIndex=SelectedTabIndex+Amount; while (NewTabIndex<0) NewTabIndex+=RegisteredTabs.Num(); NewTabIndex%=RegisteredTabs.Num(); SelectTab(NewTabIndex); } void UTabListWidget::SelectTab(int TabIndex) { if (TabIndex==SelectedTabIndex) return; // No Change // If a tab button has previously been selected, deselect if (SelectedTabIndex!=-1) { FTabListRegisteredTabInfo PreviousTabInfo; if (GetTabDataForIndex(SelectedTabIndex,PreviousTabInfo)) { PreviousTabInfo.TabButton->SetTabSelected(false); } else { UE_LOG(LogTemp,Warning,TEXT("Couldn't find button for previously index %i"),SelectedTabIndex); } } SelectedTabIndex=TabIndex; FTabListRegisteredTabInfo CurrentTabInfo; if (GetTabDataForIndex(SelectedTabIndex,CurrentTabInfo)) { CurrentTabInfo.TabButton->SetTabSelected(true); } if (!TargetWidgetSwitcher) { UE_LOG(LogTemp,Warning,TEXT("TargetWidgetSwitcher not set")); return; } if (!CurrentTabInfo.ContentInstance) { UE_LOG(LogTemp,Warning,TEXT("Content not set for tab index %i"),SelectedTabIndex); return; } // If there is a current content widget, cache the current focus so that it can be restored when moving back to this tab UWidget* PreviousContentWidget=TargetWidgetSwitcher->GetActiveWidget(); if (PreviousContentWidget) { if (UFocusablePanel* TargetFocusableWidget=Cast(PreviousContentWidget)) { TargetFocusableWidget->SavePreviousFocus(); } } TargetWidgetSwitcher->SetActiveWidget(CurrentTabInfo.ContentInstance); // If this is an instance of UFocusableUserWidget, notify to activate default focus if (UFocusableUserWidget* TargetFocusableWidget=Cast(CurrentTabInfo.ContentInstance)) { UE_LOG(LogTemp,Warning,TEXT("Focusable widget found for widget %s"),*CurrentTabInfo.ContentInstance->GetName()); TargetFocusableWidget->SetFocusProperly(); }else { UE_LOG(LogTemp,Warning,TEXT("Widget not focusable widget %s"),*CurrentTabInfo.ContentInstance->GetName()); } // Notify OnContentWidgetChanged.Broadcast(PreviousContentWidget,CurrentTabInfo.ContentInstance); } bool UTabListWidget::HandleKeyDownEvent(const FKeyEvent& InKeyEvent) { Super::HandleKeyDownEvent(InKeyEvent); if (!this->GetIsEnabled()) return false; // Ignore if not enabled const FKey Key = InKeyEvent.GetKey(); if (PreviousTabKeys.Contains(Key)) { IncrementTabIndex(-1); return true; } if (NextTabKeys.Contains(Key)) { IncrementTabIndex(1); return true; } return false; }