// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Types/Struct/DTFluxRaceDataStructs.h" #include "Widgets/Views/STreeView.h" #include "Widgets/Views/SHeaderRow.h" #include "Assets/DTFluxModelAsset.h" struct FHierarchicalTreeItem; class SDTFluxAssetModelDetailsWidget; // ✅ SOUS-CLASSE DE SMultiColumnTableRow class SHierarchicalTreeItemRow : public SMultiColumnTableRow> { public: SLATE_BEGIN_ARGS(SHierarchicalTreeItemRow) { } SLATE_ARGUMENT(TSharedPtr, Item) SLATE_ARGUMENT(SDTFluxAssetModelDetailsWidget*, ParentWidget) SLATE_END_ARGS() void Construct(const FArguments& InArgs, const TSharedRef& InOwnerTableView); protected: virtual TSharedRef GenerateWidgetForColumn(const FName& ColumnName) override; private: TSharedPtr Item; SDTFluxAssetModelDetailsWidget* ParentWidget; }; // ✅ STRUCTURE SIMPLE POUR TREEVIEW struct FHierarchicalTreeItem { enum class EItemType { Contest, Stage, Split, Participant }; EItemType Type; FString Name; FString ID; FString Details; FString Status; FString Extra; // Données pour retrouver l'élément original int32 ContestId = -1; int32 StageId = -1; int32 SplitId = -1; int32 Bib = -1; // Enfants pour la hiérarchie TArray> Children; FHierarchicalTreeItem(EItemType InType, const FString& InName) : Type(InType), Name(InName) { } void AddChild(TSharedPtr Child) { if (Child.IsValid()) { Children.Add(Child); } } // Factory methods pour créer les éléments static TSharedPtr CreateContest(const FString& ContestName, const FDTFluxContest& Contest) { TSharedPtr Item = MakeShareable( new FHierarchicalTreeItem(EItemType::Contest, ContestName)); Item->ContestId = Contest.ContestId; Item->ID = FString::Printf(TEXT("%d"), Contest.ContestId); Item->Details = FString::Printf( TEXT("%d stages, %d participants"), Contest.Stages.Num(), Contest.ParticipantsBib.Num()); Item->Status = Contest.Date.ToString(TEXT("%Y-%m-%d")); Item->Extra = Contest.IsFinished() ? TEXT("Finished") : TEXT("Active"); return Item; } static TSharedPtr CreateStage(const FDTFluxStage& Stage, int32 InContestId) { FString StageName = Stage.Name.IsEmpty() ? FString::Printf(TEXT("Stage %d"), Stage.StageId) : Stage.Name; TSharedPtr Item = MakeShareable(new FHierarchicalTreeItem(EItemType::Stage, StageName)); Item->ContestId = InContestId; Item->StageId = Stage.StageId; Item->ID = FString::Printf(TEXT("%d"), Stage.StageId); Item->Details = FString::Printf(TEXT("Start: %s"), *Stage.StartTime.ToString(TEXT("%H:%M"))); Item->Status = FString::Printf(TEXT("End: %s"), *Stage.EndTime.ToString(TEXT("%H:%M"))); Item->Extra = FString::Printf(TEXT("Cutoff: %s"), *Stage.CutOff.ToString(TEXT("%H:%M"))); return Item; } static TSharedPtr CreateSplit(const FDTFluxSplit& Split, int32 InContestId) { FString SplitName = Split.Name.IsEmpty() ? FString::Printf(TEXT("Split %d"), Split.SplitId) : Split.Name; TSharedPtr Item = MakeShareable(new FHierarchicalTreeItem(EItemType::Split, SplitName)); Item->ContestId = InContestId; Item->SplitId = Split.SplitId; Item->ID = FString::Printf(TEXT("%d"), Split.SplitId); Item->Details = FString::Printf(TEXT("%d rankings"), Split.SplitRankings.Num()); Item->Status = TEXT("-"); Item->Extra = TEXT("-"); return Item; } static TSharedPtr CreateParticipant(const FDTFluxParticipant& Participant, UDTFluxModelAsset* InModelAsset = nullptr) { FString ParticipantName = Participant.GetConcatFormattedName(); TSharedPtr Item = MakeShareable( new FHierarchicalTreeItem(EItemType::Participant, ParticipantName)); Item->Bib = Participant.Bib; Item->ContestId = Participant.ContestId; Item->ID = FString::Printf(TEXT("%d"), Participant.Bib); Item->Details = FString::Printf(TEXT("%s - %d teammates"), *Participant.Category, Participant.GetTeammate().Num()); FString Status = UEnum::GetValueAsString(Participant.Status); TArray StatusArray; Status.ParseIntoArray(StatusArray, TEXT("::")); Item->Status = StatusArray.Last(); Item->Extra = Participant.Club; return Item; } }; typedef TSharedPtr FHierarchicalTreeItemPtr; /** * Widget avec STreeView simple et efficace */ class DTFLUXASSETSEDITOR_API SDTFluxAssetModelDetailsWidget : public SCompoundWidget { public: SLATE_BEGIN_ARGS(SDTFluxAssetModelDetailsWidget) { } SLATE_ARGUMENT(UDTFluxModelAsset*, ModelAsset) SLATE_END_ARGS() void Construct(const FArguments& InArgs); void RefreshData(); // Méthodes publiques pour la sous-classe Row FSlateColor GetItemTypeColor(FHierarchicalTreeItem::EItemType Type) const; const FSlateBrush* GetItemIcon(FHierarchicalTreeItem::EItemType Type) const; private: // Données UDTFluxModelAsset* ModelAsset = nullptr; TArray RootItems; // Contests racines avec hiérarchie TArray ParticipantItems; // Participants séparés // Widgets - TreeView simple TSharedPtr> ContestTreeView; TSharedPtr> ParticipantTreeView; TSharedPtr StatsText; TSharedPtr SelectionText; // Méthodes de construction void BuildContestHierarchy(); void BuildParticipantList(); // Callbacks TreeView TSharedRef OnGenerateRowForTree(FHierarchicalTreeItemPtr Item, const TSharedRef& OwnerTable); void OnGetChildrenForTree(FHierarchicalTreeItemPtr Item, TArray& OutChildren); void OnTreeSelectionChanged(FHierarchicalTreeItemPtr SelectedItem, ESelectInfo::Type SelectInfo); void OnSetExpansionRecursive(FHierarchicalTreeItemPtr Item, bool bIsExpanded); // Callbacks des boutons FReply OnRefreshClicked(); FReply OnExpandAllClicked(); FReply OnCollapseAllClicked(); EActiveTimerReturnType ForceInitialLayout(double InCurrentTime, float InDeltaTime); // Utilitaires FText GetStatsText() const; };