// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreTypes.h" #include "Misc/FilterCollection.h" #include "Misc/TextFilter.h" #include "SlateFwd.h" #include "Widgets/DeclarativeSyntaxSupport.h" #include "Widgets/Input/SComboBox.h" #include "Widgets/SCompoundWidget.h" #include "Widgets/SWidget.h" #include "Widgets/Views/SHeaderRow.h" #include "Widgets/Views/STableRow.h" #include "Widgets/Views/STableViewBase.h" #include "Widgets/Views/STreeView.h" // TraceInsights #include "Insights/TimingProfiler/ViewModels/TimerGroupingAndSorting.h" #include "Insights/TimingProfiler/ViewModels/TimerNode.h" class FMenuBuilder; class FUICommandList; namespace TraceServices { class IAnalysisSession; } namespace UE::Insights { class FTable; class FTableColumn; class ITableCellValueSorter; class SAsyncOperationStatus; } class FTimingGraphTrack; namespace UE::Insights::TimingProfiler { class SFrameTrack; class FTimerAggregator; class STimingView; //////////////////////////////////////////////////////////////////////////////////////////////////// /** The filter collection - used for updating the list of timer nodes. */ typedef TFilterCollection FTimerNodeFilterCollection; /** The text based filter - used for updating the list of timer nodes. */ typedef TTextFilter FTimerNodeTextFilter; //////////////////////////////////////////////////////////////////////////////////////////////////// /** * A custom widget used to display the list of timers. */ class STimersView : public SCompoundWidget { public: /** Default constructor. */ STimersView(); /** Virtual destructor. */ virtual ~STimersView(); SLATE_BEGIN_ARGS(STimersView) {} SLATE_END_ARGS() /** * Construct this widget * @param InArgs - The declaration data for this widget */ void Construct(const FArguments& InArgs); TSharedPtr GetTable() const { return Table; } void Reset(); /** * Rebuilds the tree (if necessary). * @param bResync - If true, it forces a resync with list of timers from Analysis, even if the list did not changed since last sync. */ void RebuildTree(bool bResync); void ResetStats(); void UpdateStats(double StartTime, double EndTime); FTimerNodePtr GetTimerNode(uint32 TimerId) const; void SelectTimerNode(uint32 TimerId); ETraceFrameType GetFrameTypeMode() { return ModeFrameType; } void OnTimingViewTrackListChanged(); void ToggleTimingViewMainGraphEventSeries(FTimerNodePtr TimerNode) const; virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override; private: void InitCommandList(); void UpdateTree(); void FinishAggregation(); void ApplyAggregation(TraceServices::ITable* AggregatedStatsTable); /** Called when the session has changed. */ void InsightsManager_OnSessionChanged(); /** Called when the analysis was completed. */ void InsightsManager_OnSessionAnalysisCompleted(); /** * Populates OutSearchStrings with the strings that should be used in searching. * * @param GroupOrStatNodePtr - the group and stat node to get a text description from. * @param OutSearchStrings - an array of strings to use in searching. * */ void HandleItemToStringArray(const FTimerNodePtr& GroupOrStatNodePtr, TArray& OutSearchStrings) const; //////////////////////////////////////////////////////////////////////////////////////////////////// // Tree View - Context Menu TSharedPtr TreeView_GetMenuContent(); void TreeView_BuildSortByMenu(FMenuBuilder& MenuBuilder); void TreeView_BuildViewColumnMenu(FMenuBuilder& MenuBuilder); ////////////////////////////////////////////////// // Copy to Clipboard bool ContextMenu_CopyToClipboard_CanExecute() const; void ContextMenu_CopyToClipboard_Execute(); bool ContextMenu_CopyTimerNameToClipboard_CanExecute() const; void ContextMenu_CopyTimerNameToClipboard_Execute(); ////////////////////////////////////////////////// // Export void TreeView_BuildExportMenu(FMenuBuilder& MenuBuilder); bool ContextMenu_Export_CanExecute() const; void ContextMenu_Export_Execute(); void AddTimerNodeRecursive(FTimerNodePtr InNode, TSet& InOutIncludedTimers) const; bool ContextMenu_ExportTimingEventsSelection_CanExecute() const; void ContextMenu_ExportTimingEventsSelection_Execute() const; bool ContextMenu_ExportTimingEvents_CanExecute() const; void ContextMenu_ExportTimingEvents_Execute() const; bool ContextMenu_ExportThreads_CanExecute() const; void ContextMenu_ExportThreads_Execute() const; bool ContextMenu_ExportTimers_CanExecute() const; void ContextMenu_ExportTimers_Execute() const; bool OpenSaveTextFileDialog(const FString& InDialogTitle, const FString& InDefaultFile, FString& OutFilename) const; class IFileHandle* OpenExportFile(const TCHAR* InFilename) const; ////////////////////////////////////////////////// // Open Source File in IDE bool ContextMenu_OpenSource_CanExecute() const; void ContextMenu_OpenSource_Execute() const; void OpenSourceFileInIDE(FTimerNodePtr InNode) const; ////////////////////////////////////////////////// // Generate and Edit Timer Colors bool ContextMenu_GenerateNewColor_CanExecute() const; void ContextMenu_GenerateNewColor_Execute() const; bool ContextMenu_EditColor_CanExecute() const; void ContextMenu_EditColor_Execute(); void SetColorToNode(FTimerNode& TimerNode, FLinearColor CustomColor) const; void SetRandomColorToNode(FTimerNode& TimerNode) const; FLinearColor GetEditableColor() const; void SetEditableColor(FLinearColor NewColor); void ColorPickerCancelled(FLinearColor OriginalColor); ////////////////////////////////////////////////// // Plot (Graph Series) void TreeView_BuildPlotTimerMenu(FMenuBuilder& MenuBuilder); ////////////////////////////////////////////////// // Find Instance void TreeView_FindMenu(FMenuBuilder& MenuBuilder); bool ContextMenu_FindInstance_CanExecute() const; void ContextMenu_FindInstance_Execute(bool bFindMax) const; bool ContextMenu_FindInstanceInSelection_CanExecute() const; void ContextMenu_FindInstanceInSelection_Execute(bool bFindMax) const; //////////////////////////////////////////////////////////////////////////////////////////////////// // Tree View - Columns' Header void InitializeAndShowHeaderColumns(); FText GetColumnHeaderText(const FName ColumnId) const; TSharedRef TreeViewHeaderRow_GenerateColumnMenu(const FTableColumn& Column); //////////////////////////////////////////////////////////////////////////////////////////////////// // Tree View - Misc void TreeView_Refresh(); /** * Called by STreeView to retrieves the children for the specified parent item. * @param InParent - The parent node to retrieve the children from. * @param OutChildren - List of children for the parent node. */ void TreeView_OnGetChildren(FTimerNodePtr InParent, TArray& OutChildren); /** Called by STreeView when selection has changed. */ void TreeView_OnSelectionChanged(FTimerNodePtr SelectedItem, ESelectInfo::Type SelectInfo); FTimerNodePtr GetSingleSelectedTimerNode() const; /** Checks validity of one or more selected nodes*/ bool AreSelectedTimerNodesValid() const; /** Called by STreeView when a tree item is double clicked. */ void TreeView_OnMouseButtonDoubleClick(FTimerNodePtr TreeNode); //////////////////////////////////////////////////////////////////////////////////////////////////// // Tree View - Table Row /** Called by STreeView to generate a table row for the specified item. */ TSharedRef TreeView_OnGenerateRow(FTimerNodePtr TreeNode, const TSharedRef& OwnerTable); bool TableRow_ShouldBeEnabled(FTimerNodePtr NodePtr) const; void TableRow_SetHoveredCell(TSharedPtr TablePtr, TSharedPtr ColumnPtr, FTimerNodePtr NodePtr); EHorizontalAlignment TableRow_GetColumnOutlineHAlignment(const FName ColumnId) const; FText TableRow_GetHighlightText() const; FName TableRow_GetHighlightedNodeName() const; //////////////////////////////////////////////////////////////////////////////////////////////////// // Filtering /** Populates the group and stat tree with items based on the current data. */ void ApplyFiltering(); void FilterOutZeroCountTimers_OnCheckStateChanged(ECheckBoxState NewRadioState); ECheckBoxState FilterOutZeroCountTimers_IsChecked() const; TSharedRef GetToggleButtonForTimerType(const ETimerNodeType InNodeType); void FilterByTimerType_OnCheckStateChanged(ECheckBoxState NewRadioState, const ETimerNodeType InNodeType); ECheckBoxState FilterByTimerType_IsChecked(const ETimerNodeType InNodeType) const; bool SearchBox_IsEnabled() const; void SearchBox_OnTextChanged(const FText& InFilterText); //////////////////////////////////////////////////////////////////////////////////////////////////// // Grouping void CreateGroups(); void CreateGroupByOptionsSources(); void GroupBy_OnSelectionChanged(TSharedPtr NewGroupingMode, ESelectInfo::Type SelectInfo); TSharedRef GroupBy_OnGenerateWidget(TSharedPtr InGroupingMode) const; FText GroupBy_GetSelectedText() const; FText GroupBy_GetSelectedTooltipText() const; //////////////////////////////////////////////////////////////////////////////////////////////////// // Frame Type void CreateModeOptionsSources(); void Mode_OnSelectionChanged(TSharedPtr NewGroupingMode, ESelectInfo::Type SelectInfo); TSharedRef Mode_OnGenerateWidget(TSharedPtr InGroupingMode) const; FText Mode_GetSelectedText() const; FText Mode_GetText(ETraceFrameType InFrameType) const; FText Mode_GetSelectedTooltipText() const; FText Mode_GetTooltipText(ETraceFrameType InFrameType) const; //////////////////////////////////////////////////////////////////////////////////////////////////// // Sorting static const FName GetDefaultColumnBeingSorted(); static const EColumnSortMode::Type GetDefaultColumnSortMode(); void CreateSortings(); void UpdateCurrentSortingByColumn(); void SortTreeNodes(); void SortTreeNodesRec(FTimerNode& Node, const ITableCellValueSorter& Sorter); EColumnSortMode::Type GetSortModeForColumn(const FName ColumnId) const; void SetSortModeForColumn(const FName& ColumnId, EColumnSortMode::Type SortMode); void OnSortModeChanged(const EColumnSortPriority::Type SortPriority, const FName& ColumnId, const EColumnSortMode::Type SortMode); //////////////////////////////////////////////////////////////////////////////////////////////////// // Sorting Actions // SortMode (HeaderMenu) bool HeaderMenu_SortMode_IsChecked(const FName ColumnId, const EColumnSortMode::Type InSortMode); bool HeaderMenu_SortMode_CanExecute(const FName ColumnId, const EColumnSortMode::Type InSortMode) const; void HeaderMenu_SortMode_Execute(const FName ColumnId, const EColumnSortMode::Type InSortMode); // SortMode (ContextMenu) bool ContextMenu_SortMode_IsChecked(const EColumnSortMode::Type InSortMode); bool ContextMenu_SortMode_CanExecute(const EColumnSortMode::Type InSortMode) const; void ContextMenu_SortMode_Execute(const EColumnSortMode::Type InSortMode); // SortByColumn (ContextMenu) bool ContextMenu_SortByColumn_IsChecked(const FName ColumnId); bool ContextMenu_SortByColumn_CanExecute(const FName ColumnId) const; void ContextMenu_SortByColumn_Execute(const FName ColumnId); //////////////////////////////////////////////////////////////////////////////////////////////////// // Column Visibility Actions // ShowColumn bool CanShowColumn(const FName ColumnId) const; void ShowColumn(const FName ColumnId); // HideColumn bool CanHideColumn(const FName ColumnId) const; void HideColumn(const FName ColumnId); // ToggleColumnVisibility bool IsColumnVisible(const FName ColumnId) const; bool CanToggleColumnVisibility(const FName ColumnId) const; void ToggleColumnVisibility(const FName ColumnId); // ShowAllColumns (ContextMenu) bool ContextMenu_ShowAllColumns_CanExecute() const; void ContextMenu_ShowAllColumns_Execute(); // MinMaxMedColumns (ContextMenu) bool ContextMenu_ShowMinMaxMedColumns_CanExecute() const; void ContextMenu_ShowMinMaxMedColumns_Execute(); // ResetColumns (ContextMenu) bool ContextMenu_ResetColumns_CanExecute() const; void ContextMenu_ResetColumns_Execute(); //////////////////////////////////////////////////////////////////////////////////////////////////// // Event Highlight/Filtering in Timing View void ToggleTimingViewEventFilter(FTimerNodePtr TimerNode) const; //////////////////////////////////////////////////////////////////////////////////////////////////// // Plot (Graph Series) TSharedPtr GetTimingViewMainGraphTrack() const; TSharedPtr GetFrameTrack() const; void ToggleGraphInstanceSeries(TSharedRef GraphTrack, FTimerNodeRef NodePtr) const; bool IsInstanceSeriesInTimingViewMainGraph(FTimerNodePtr TimerNode) const; void ToggleTimingViewMainGraphEventInstanceSeries(FTimerNodePtr TimerNode) const; void ToggleGraphFrameStatsSeries(TSharedRef GraphTrack, FTimerNodeRef NodePtr, ETraceFrameType FrameType) const; bool IsFrameStatsSeriesInTimingViewMainGraph(FTimerNodePtr TimerNode, ETraceFrameType FrameType) const; void ToggleTimingViewMainGraphEventFrameStatsSeries(FTimerNodePtr TimerNode, ETraceFrameType FrameType) const; bool IsSeriesInFrameTrack(FTimerNodePtr TimerNode, ETraceFrameType FrameType) const; void ToggleFrameTrackSeries(FTimerNodePtr TimerNode, ETraceFrameType FrameType) const; //////////////////////////////////////////////////////////////////////////////////////////////////// /** * Ticks this widget. Override in derived classes, but always call the parent implementation. * * @param AllottedGeometry The space allotted for this widget * @param InCurrentTime Current absolute real time * @param InDeltaTime Real time passed since last tick */ virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override; void SaveSettings(); void SaveVisibleColumnsSettings(); void LoadSettings(); void LoadVisibleColumnsSettings(); void SetTimingViewFrameType(); TSharedPtr GetTimingView() const; private: /** Table view model. */ TSharedPtr Table; /** The analysis session used to populate this widget. */ TSharedPtr Session; TSharedPtr CommandList; /** Eye-Dropper selected color for graphing.*/ FLinearColor EditableColorValue; ////////////////////////////////////////////////// // Tree View, Columns /** The tree widget which holds the list of groups and timers corresponding with each group. */ TSharedPtr> TreeView; /** Holds the tree view header row widget which display all columns in the tree view. */ TSharedPtr TreeViewHeaderRow; /** External scrollbar used to synchronize tree view position. */ TSharedPtr ExternalScrollbar; ////////////////////////////////////////////////// // Hovered Column, Hovered Timer Node /** Name of the column currently being hovered by the mouse. */ FName HoveredColumnId; /** A shared pointer to the timer node currently being hovered by the mouse. */ FTimerNodePtr HoveredNodePtr; /** Name of the timer that should be drawn as highlighted. */ FName HighlightedNodeName; ////////////////////////////////////////////////// // Timer Nodes /** An array of group and timer nodes generated from the metadata. */ TArray GroupNodes; /** A filtered array of group and timer nodes to be displayed in the tree widget. */ TArray FilteredGroupNodes; /** All timer nodes. An index in this array is a TimerId. */ TArray TimerNodes; /** Currently expanded group nodes. */ TSet ExpandedNodes; /** If true, the expanded nodes have been saved before applying a text filter. */ bool bExpansionSaved = false; ////////////////////////////////////////////////// // Search box and filters //bool bUseFiltering; /** The search box widget used to filter items displayed in the tree. */ TSharedPtr SearchBox; /** The text based filter. */ TSharedPtr TextFilter; /** The filter collection. */ TSharedPtr Filters; /** Holds the visibility of each timer type. */ bool bTimerTypeIsVisible[static_cast(ETimerNodeType::InvalidOrMax)]; /** Filter out the timers having zero total instance count (aggregated stats). */ bool bFilterOutZeroCountTimers = false; ////////////////////////////////////////////////// // Grouping //bool bUseGrouping; TArray> GroupByOptionsSource; TSharedPtr>> GroupByComboBox; /** How we group the timers? */ ETimerGroupingMode GroupingMode = ETimerGroupingMode::ByType; ////////////////////////////////////////////////// // Frame Type TArray> ModeOptionsSource; TSharedPtr>> ModeComboBox; ETraceFrameType ModeFrameType = ETraceFrameType::TraceFrameType_Game; ////////////////////////////////////////////////// // Sorting /** All available sorters. */ TArray> AvailableSorters; /** Current sorter. It is nullptr if sorting is disabled. */ TSharedPtr CurrentSorter; /** Name of the column currently being sorted. Can be NAME_None if sorting is disabled (CurrentSorting == nullptr) or if a complex sorting is used (CurrentSorting != nullptr). */ FName ColumnBeingSorted; /** How we sort the nodes? Ascending or Descending. */ EColumnSortMode::Type ColumnSortMode = EColumnSortMode::Type::Ascending; ////////////////////////////////////////////////// TSharedRef Aggregator; TSharedPtr AsyncOperationStatus; }; //////////////////////////////////////////////////////////////////////////////////////////////////// } // namespace UE::Insights::TimingProfiler