2022-11-08 21:43:22 +01:00
# include <ui/pattern_drawer.hpp>
2022-04-08 16:08:02 +02:00
2022-04-17 16:57:30 +02:00
# include <pl/patterns/pattern_array_dynamic.hpp>
# include <pl/patterns/pattern_array_static.hpp>
# include <pl/patterns/pattern_bitfield.hpp>
# include <pl/patterns/pattern_boolean.hpp>
# include <pl/patterns/pattern_character.hpp>
# include <pl/patterns/pattern_enum.hpp>
# include <pl/patterns/pattern_float.hpp>
# include <pl/patterns/pattern_padding.hpp>
# include <pl/patterns/pattern_pointer.hpp>
# include <pl/patterns/pattern_signed.hpp>
# include <pl/patterns/pattern_string.hpp>
# include <pl/patterns/pattern_struct.hpp>
# include <pl/patterns/pattern_union.hpp>
# include <pl/patterns/pattern_unsigned.hpp>
# include <pl/patterns/pattern_wide_character.hpp>
# include <pl/patterns/pattern_wide_string.hpp>
2022-04-08 16:08:02 +02:00
# include <string>
2022-04-17 16:57:30 +02:00
# include <hex/api/imhex_api.hpp>
2023-01-20 21:16:28 +01:00
# include <hex/api/content_registry.hpp>
2023-08-06 21:33:15 +02:00
# include <hex/api/achievement_manager.hpp>
2022-11-08 21:43:22 +01:00
# include <hex/api/localization.hpp>
2023-08-06 21:33:15 +02:00
# include <hex/helpers/utils.hpp>
2022-12-16 11:20:39 +01:00
# include <content/helpers/math_evaluator.hpp>
2022-04-17 16:57:30 +02:00
# include <imgui.h>
# include <hex/ui/imgui_imhex_extensions.h>
2023-01-25 10:16:31 +01:00
# include <fonts/codicons_font.h>
2023-06-04 18:30:47 +02:00
# include <fonts/fontawesome_font.h>
2022-04-17 16:57:30 +02:00
2023-01-20 21:16:28 +01:00
2022-11-08 21:43:22 +01:00
namespace hex : : plugin : : builtin : : ui {
2022-04-08 16:08:02 +02:00
2022-09-07 23:11:13 +02:00
namespace {
2022-04-08 16:08:02 +02:00
2022-09-12 21:28:02 +02:00
constexpr auto DisplayEndDefault = 50U ;
2022-09-07 23:11:13 +02:00
using namespace : : std : : literals : : string_literals ;
2022-10-09 15:56:26 +02:00
bool isPatternSelected ( u64 address , u64 size ) {
auto currSelection = ImHexApi : : HexEditor : : getSelection ( ) ;
if ( ! currSelection . has_value ( ) )
return false ;
return Region { address , size } . overlaps ( * currSelection ) ;
}
template < typename T >
auto highlightWhenSelected ( u64 address , u64 size , const T & callback ) {
constexpr bool HasReturn = ! requires ( T t ) { { t ( ) } - > std : : same_as < void > ; } ;
auto selected = isPatternSelected ( address , size ) ;
if ( selected )
ImGui : : PushStyleColor ( ImGuiCol_Text , ImGui : : GetStyleColorVec4 ( ImGuiCol_HeaderActive ) ) ;
if constexpr ( HasReturn ) {
auto result = callback ( ) ;
if ( selected )
ImGui : : PopStyleColor ( ) ;
return result ;
} else {
callback ( ) ;
if ( selected )
ImGui : : PopStyleColor ( ) ;
}
}
template < typename T >
auto highlightWhenSelected ( const pl : : ptrn : : Pattern & pattern , const T & callback ) {
return highlightWhenSelected ( pattern . getOffset ( ) , pattern . getSize ( ) , callback ) ;
}
2022-09-07 23:11:13 +02:00
void drawTypenameColumn ( const pl : : ptrn : : Pattern & pattern , const std : : string & pattern_name ) {
ImGui : : TextFormattedColored ( ImColor ( 0xFFD69C56 ) , pattern_name ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextUnformatted ( pattern . getTypeName ( ) . c_str ( ) ) ;
ImGui : : TableNextColumn ( ) ;
}
void drawColorColumn ( const pl : : ptrn : : Pattern & pattern ) {
2023-06-04 18:30:47 +02:00
if ( pattern . getVisibility ( ) = = pl : : ptrn : : Visibility : : Visible )
ImGui : : ColorButton ( " color " , ImColor ( pattern . getColor ( ) ) , ImGuiColorEditFlags_NoTooltip , ImVec2 ( ImGui : : GetColumnWidth ( ) , ImGui : : GetTextLineHeight ( ) ) ) ;
2022-09-07 23:11:13 +02:00
ImGui : : TableNextColumn ( ) ;
}
2023-03-26 11:01:37 +02:00
inline void drawOffsetColumnForBitfieldMember ( const pl : : ptrn : : PatternBitfieldMember & pattern ) {
2023-05-28 15:44:01 +02:00
if ( pattern . isPatternLocal ( ) ) {
ImGui : : TextFormatted ( " [{}] " , " hex.builtin.pattern_drawer.local " _lang ) ;
2023-06-18 12:23:47 +02:00
ImGui : : TableNextColumn ( ) ;
ImGui : : TextFormatted ( " [{}] " , " hex.builtin.pattern_drawer.local " _lang ) ;
ImGui : : TableNextColumn ( ) ;
2023-05-28 15:44:01 +02:00
} else {
2023-06-18 12:23:47 +02:00
ImGui : : TextFormatted ( " 0x{0:08X}, bit {1} " , pattern . getOffset ( ) , pattern . getBitOffsetForDisplay ( ) ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : TextFormatted ( " 0x{0:08X}, bit {1} " , pattern . getOffset ( ) + pattern . getSize ( ) , pattern . getBitOffsetForDisplay ( ) + pattern . getBitSize ( ) - ( pattern . getSize ( ) = = 0 ? 0 : 1 ) ) ;
ImGui : : TableNextColumn ( ) ;
2023-05-28 15:44:01 +02:00
}
2023-06-18 12:23:47 +02:00
}
2023-05-28 15:44:01 +02:00
2023-06-18 12:23:47 +02:00
void drawOffsetColumn ( const pl : : ptrn : : Pattern & pattern ) {
if ( auto * bitfieldMember = dynamic_cast < pl : : ptrn : : PatternBitfieldMember const * > ( & pattern ) ; bitfieldMember ! = nullptr & & bitfieldMember - > getParentBitfield ( ) ! = nullptr )
drawOffsetColumnForBitfieldMember ( * bitfieldMember ) ;
else {
if ( pattern . isPatternLocal ( ) ) {
ImGui : : TextFormatted ( " [{}] " , " hex.builtin.pattern_drawer.local " _lang ) ;
} else {
2023-07-03 21:24:15 +02:00
ImGui : : TextFormatted ( " 0x{0:08X} " , pattern . getOffset ( ) ) ;
2023-06-18 12:23:47 +02:00
}
ImGui : : TableNextColumn ( ) ;
if ( pattern . isPatternLocal ( ) ) {
ImGui : : TextFormatted ( " [{}] " , " hex.builtin.pattern_drawer.local " _lang ) ;
} else {
2023-07-03 21:24:15 +02:00
ImGui : : TextFormatted ( " 0x{0:08X} " , pattern . getOffset ( ) + pattern . getSize ( ) - ( pattern . getSize ( ) = = 0 ? 0 : 1 ) ) ;
2023-06-18 12:23:47 +02:00
}
ImGui : : TableNextColumn ( ) ;
}
2022-09-07 23:11:13 +02:00
}
2023-03-26 11:01:37 +02:00
inline void drawSizeColumnForBitfieldMember ( const pl : : ptrn : : PatternBitfieldMember & pattern ) {
if ( pattern . getBitSize ( ) = = 1 )
ImGui : : TextFormatted ( " 1 bit " ) ;
else
ImGui : : TextFormatted ( " {0} bits " , pattern . getBitSize ( ) ) ;
}
2022-09-07 23:11:13 +02:00
void drawSizeColumn ( const pl : : ptrn : : Pattern & pattern ) {
2023-03-26 11:01:37 +02:00
if ( auto * bitfieldMember = dynamic_cast < pl : : ptrn : : PatternBitfieldMember const * > ( & pattern ) ; bitfieldMember ! = nullptr & & bitfieldMember - > getParentBitfield ( ) ! = nullptr )
drawSizeColumnForBitfieldMember ( * bitfieldMember ) ;
2023-07-03 21:24:15 +02:00
else
2023-03-26 11:01:37 +02:00
ImGui : : TextFormatted ( " 0x{0:04X} " , pattern . getSize ( ) ) ;
2022-09-07 23:11:13 +02:00
2023-06-04 18:30:47 +02:00
ImGui : : TableNextColumn ( ) ;
2023-05-12 08:49:08 +02:00
}
2022-09-07 23:11:13 +02:00
void drawCommentTooltip ( const pl : : ptrn : : Pattern & pattern ) {
2023-06-05 09:07:58 +02:00
if ( auto comment = pattern . getComment ( ) ; ! comment . empty ( ) ) {
ImGui : : InfoTooltip ( comment . c_str ( ) ) ;
2022-09-07 23:11:13 +02:00
}
}
2023-06-04 16:13:46 +02:00
std : : vector < std : : string > parseRValueFilter ( const std : : string & filter ) {
std : : vector < std : : string > result ;
if ( ! filter . empty ( ) ) {
result . emplace_back ( ) ;
for ( char c : filter ) {
if ( c = = ' . ' )
result . emplace_back ( ) ;
else if ( c = = ' [ ' ) {
result . emplace_back ( ) ;
result . back ( ) + = c ;
2023-06-04 18:35:44 +02:00
} else {
2023-06-04 16:13:46 +02:00
result . back ( ) + = c ;
2023-06-04 18:35:44 +02:00
}
2023-06-04 16:13:46 +02:00
}
}
return result ;
}
2023-01-25 10:16:31 +01:00
}
2022-12-23 14:33:27 +01:00
2023-01-28 00:03:20 +01:00
bool PatternDrawer : : isEditingPattern ( const pl : : ptrn : : Pattern & pattern ) const {
return this - > m_editingPattern = = & pattern & & this - > m_editingPatternOffset = = pattern . getOffset ( ) ;
}
void PatternDrawer : : resetEditing ( ) {
this - > m_editingPattern = nullptr ;
this - > m_editingPatternOffset = 0x00 ;
}
2023-06-24 16:40:34 +02:00
bool PatternDrawer : : matchesFilter ( const std : : vector < std : : string > & filterPath , const std : : vector < std : : string > & patternPath , bool fullMatch ) {
2023-06-04 18:30:47 +02:00
if ( fullMatch ) {
2023-06-24 16:40:34 +02:00
if ( patternPath . size ( ) ! = filterPath . size ( ) )
2023-06-04 18:30:47 +02:00
return false ;
}
2023-06-24 16:40:34 +02:00
if ( patternPath . size ( ) < = filterPath . size ( ) ) {
for ( ssize_t i = patternPath . size ( ) - 1 ; i > = 0 ; i - - ) {
2023-06-04 16:13:46 +02:00
const auto & filter = filterPath [ i ] ;
2023-06-24 16:40:34 +02:00
if ( patternPath [ i ] ! = filter & & ! filter . empty ( ) & & filter ! = " * " ) {
2023-06-04 16:13:46 +02:00
return false ;
}
}
}
return true ;
}
2023-06-04 18:30:47 +02:00
void PatternDrawer : : drawFavoriteColumn ( const pl : : ptrn : : Pattern & pattern ) {
if ( this - > m_showFavoriteStars ) {
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
if ( this - > m_favorites . contains ( this - > m_currPatternPath ) ) {
2023-06-04 22:52:36 +02:00
if ( ImGui : : DimmedIconButton ( ICON_VS_STAR_DELETE , ImGui : : GetStyleColorVec4 ( ImGuiCol_PlotHistogram ) ) ) {
2023-06-04 18:30:47 +02:00
this - > m_favorites . erase ( this - > m_currPatternPath ) ;
}
}
else {
2023-06-04 22:52:36 +02:00
if ( ImGui : : DimmedIconButton ( ICON_VS_STAR_ADD , ImGui : : GetStyleColorVec4 ( ImGuiCol_TextDisabled ) ) ) {
2023-06-04 18:30:47 +02:00
this - > m_favorites . insert ( { this - > m_currPatternPath , pattern . clone ( ) } ) ;
}
}
ImGui : : PopStyleVar ( ) ;
}
ImGui : : TableNextColumn ( ) ;
}
2023-07-04 22:18:06 +02:00
void PatternDrawer : : drawVisualizer ( const std : : map < std : : string , ContentRegistry : : PatternLanguage : : impl : : Visualizer > & visualizers , const std : : vector < pl : : core : : Token : : Literal > & arguments , pl : : ptrn : : Pattern & pattern , pl : : ptrn : : IIterable & iterable , bool reset ) {
2023-01-25 10:16:31 +01:00
auto visualizerName = arguments . front ( ) . toString ( true ) ;
2022-12-23 14:33:27 +01:00
2023-01-25 10:16:31 +01:00
if ( auto entry = visualizers . find ( visualizerName ) ; entry ! = visualizers . end ( ) ) {
const auto & [ name , visualizer ] = * entry ;
if ( visualizer . parameterCount ! = arguments . size ( ) - 1 ) {
ImGui : : TextUnformatted ( " hex.builtin.pattern_drawer.visualizer.invalid_parameter_count " _lang ) ;
2023-01-20 21:16:28 +01:00
} else {
2023-01-25 10:16:31 +01:00
try {
2023-06-04 18:30:47 +02:00
visualizer . callback ( pattern , iterable , reset , { arguments . begin ( ) + 1 , arguments . end ( ) } ) ;
2023-01-25 10:16:31 +01:00
} catch ( std : : exception & e ) {
this - > m_lastVisualizerError = e . what ( ) ;
}
2023-01-20 21:16:28 +01:00
}
2023-01-25 10:16:31 +01:00
} else {
ImGui : : TextUnformatted ( " hex.builtin.pattern_drawer.visualizer.unknown " _lang ) ;
2023-01-20 21:16:28 +01:00
}
2022-12-23 14:33:27 +01:00
2023-01-25 10:16:31 +01:00
if ( ! this - > m_lastVisualizerError . empty ( ) )
ImGui : : TextUnformatted ( this - > m_lastVisualizerError . c_str ( ) ) ;
2023-01-20 21:16:28 +01:00
}
2023-01-12 11:18:36 +01:00
2023-06-04 18:30:47 +02:00
void PatternDrawer : : drawValueColumn ( pl : : ptrn : : Pattern & pattern ) {
2023-06-04 22:52:36 +02:00
const auto value = pattern . getFormattedValue ( ) ;
2023-06-04 18:30:47 +02:00
2023-06-04 22:52:36 +02:00
const auto width = ImGui : : GetColumnWidth ( ) ;
2023-07-04 22:18:06 +02:00
if ( const auto & visualizeArgs = pattern . getAttributeArguments ( " hex::visualize " ) ; ! visualizeArgs . empty ( ) ) {
2023-01-20 21:16:28 +01:00
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
2023-06-04 18:30:47 +02:00
ImGui : : PushStyleVar ( ImGuiStyleVar_ButtonTextAlign , ImVec2 ( 0 , 0.5F ) ) ;
2023-06-06 08:20:58 +02:00
bool shouldReset = false ;
2023-07-04 22:18:06 +02:00
if ( ImGui : : Button ( hex : : format ( " {} {} " , ICON_VS_EYE_WATCH , value ) . c_str ( ) , ImVec2 ( width , ImGui : : GetTextLineHeight ( ) ) ) ) {
2023-06-06 08:20:58 +02:00
auto previousPattern = this - > m_currVisualizedPattern ;
2023-01-20 21:16:28 +01:00
this - > m_currVisualizedPattern = & pattern ;
2023-01-25 10:16:31 +01:00
this - > m_lastVisualizerError . clear ( ) ;
2023-06-06 08:20:58 +02:00
if ( this - > m_currVisualizedPattern ! = previousPattern )
shouldReset = true ;
2023-01-20 21:16:28 +01:00
ImGui : : OpenPopup ( " Visualizer " ) ;
}
2023-06-04 18:30:47 +02:00
ImGui : : PopStyleVar ( 2 ) ;
2023-01-18 17:17:34 +01:00
2023-01-25 10:16:31 +01:00
ImGui : : SameLine ( ) ;
2023-01-20 21:16:28 +01:00
if ( ImGui : : BeginPopup ( " Visualizer " ) ) {
if ( this - > m_currVisualizedPattern = = & pattern ) {
2023-07-04 22:18:06 +02:00
drawVisualizer ( ContentRegistry : : PatternLanguage : : impl : : getVisualizers ( ) , visualizeArgs , pattern , dynamic_cast < pl : : ptrn : : IIterable & > ( pattern ) , ! this - > m_visualizedPatterns . contains ( & pattern ) | | shouldReset ) ;
2023-01-24 23:27:15 +01:00
this - > m_visualizedPatterns . insert ( & pattern ) ;
2023-01-18 17:17:34 +01:00
}
2023-01-20 21:16:28 +01:00
ImGui : : EndPopup ( ) ;
2022-12-23 14:33:27 +01:00
}
2023-07-04 22:18:06 +02:00
} else if ( const auto & inlineVisualizeArgs = pattern . getAttributeArguments ( " hex::inline_visualize " ) ; ! inlineVisualizeArgs . empty ( ) ) {
drawVisualizer ( ContentRegistry : : PatternLanguage : : impl : : getInlineVisualizers ( ) , inlineVisualizeArgs , pattern , dynamic_cast < pl : : ptrn : : IIterable & > ( pattern ) , true ) ;
2023-06-04 18:30:47 +02:00
} else {
ImGui : : TextFormatted ( " {} " , value ) ;
2022-12-23 14:33:27 +01:00
}
2023-01-25 10:16:31 +01:00
2023-06-05 09:07:58 +02:00
if ( ImGui : : CalcTextSize ( value . c_str ( ) ) . x > width ) {
ImGui : : InfoTooltip ( value . c_str ( ) ) ;
2023-06-04 18:30:47 +02:00
}
2023-01-08 16:06:26 +01:00
}
2023-07-23 09:14:00 +02:00
std : : string PatternDrawer : : getDisplayName ( const pl : : ptrn : : Pattern & pattern ) const {
if ( this - > m_showSpecName & & pattern . hasAttribute ( " hex::spec_name " ) )
return pattern . getAttributeArguments ( " hex::spec_name " ) [ 0 ] . toString ( true ) ;
else
return pattern . getDisplayName ( ) ;
}
2023-06-04 18:30:47 +02:00
bool PatternDrawer : : createTreeNode ( const pl : : ptrn : : Pattern & pattern , bool leaf ) {
drawFavoriteColumn ( pattern ) ;
if ( pattern . isSealed ( ) | | leaf ) {
2023-01-08 16:06:26 +01:00
ImGui : : Indent ( ) ;
2023-07-23 09:14:00 +02:00
highlightWhenSelected ( pattern , [ & ] { ImGui : : TextUnformatted ( this - > getDisplayName ( pattern ) . c_str ( ) ) ; } ) ;
2023-01-08 16:06:26 +01:00
ImGui : : Unindent ( ) ;
return false ;
}
else {
return highlightWhenSelected ( pattern , [ & ] {
switch ( this - > m_treeStyle ) {
using enum TreeStyle ;
default :
case Default :
2023-07-23 09:14:00 +02:00
return ImGui : : TreeNodeEx ( this - > getDisplayName ( pattern ) . c_str ( ) , ImGuiTreeNodeFlags_SpanFullWidth ) ;
2023-01-08 16:06:26 +01:00
case AutoExpanded :
2023-07-23 09:14:00 +02:00
return ImGui : : TreeNodeEx ( this - > getDisplayName ( pattern ) . c_str ( ) , ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_DefaultOpen ) ;
2023-01-08 16:06:26 +01:00
case Flattened :
2023-07-23 09:14:00 +02:00
return ImGui : : TreeNodeEx ( this - > getDisplayName ( pattern ) . c_str ( ) , ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen ) ;
2023-01-08 16:06:26 +01:00
}
} ) ;
}
}
2022-12-18 23:11:22 +01:00
void PatternDrawer : : makeSelectable ( const pl : : ptrn : : Pattern & pattern ) {
ImGui : : PushID ( static_cast < int > ( pattern . getOffset ( ) ) ) ;
ImGui : : PushID ( pattern . getVariableName ( ) . c_str ( ) ) ;
2022-09-07 23:11:13 +02:00
2022-12-18 23:11:22 +01:00
if ( ImGui : : Selectable ( " ##PatternLine " , false , ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap ) ) {
2023-02-17 14:53:15 +01:00
this - > m_selectionCallback ( Region { pattern . getOffset ( ) , pattern . getSize ( ) } ) ;
2023-05-19 19:56:55 +02:00
if ( this - > m_editingPattern ! = & pattern ) {
this - > resetEditing ( ) ;
}
2022-09-07 23:11:13 +02:00
}
2023-01-28 00:03:20 +01:00
if ( ImGui : : IsItemHovered ( ) & & ImGui : : IsMouseDoubleClicked ( ImGuiMouseButton_Left ) ) {
2022-12-18 23:11:22 +01:00
this - > m_editingPattern = & pattern ;
2023-01-28 00:03:20 +01:00
this - > m_editingPatternOffset = pattern . getOffset ( ) ;
2023-08-06 21:33:15 +02:00
AchievementManager : : unlockAchievement ( " hex.builtin.achievement.patterns " , " hex.builtin.achievement.patterns.modify_data.name " ) ;
2023-01-28 00:03:20 +01:00
}
2022-09-07 23:11:13 +02:00
2022-12-18 23:11:22 +01:00
ImGui : : SameLine ( 0 , 0 ) ;
ImGui : : PopID ( ) ;
ImGui : : PopID ( ) ;
2022-09-07 23:11:13 +02:00
}
2022-04-08 16:08:02 +02:00
2022-12-18 23:11:22 +01:00
void PatternDrawer : : createDefaultEntry ( pl : : ptrn : : Pattern & pattern ) {
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
2023-06-04 18:30:47 +02:00
createTreeNode ( pattern , true ) ;
ImGui : : SameLine ( 0 , 0 ) ;
2022-12-18 23:11:22 +01:00
makeSelectable ( pattern ) ;
drawCommentTooltip ( pattern ) ;
2023-06-04 18:30:47 +02:00
ImGui : : TableNextColumn ( ) ;
2022-12-18 23:11:22 +01:00
drawColorColumn ( pattern ) ;
drawOffsetColumn ( pattern ) ;
drawSizeColumn ( pattern ) ;
ImGui : : TextFormattedColored ( ImColor ( 0xFF9BC64D ) , " {} " , pattern . getFormattedName ( ) . empty ( ) ? pattern . getTypeName ( ) : pattern . getFormattedName ( ) ) ;
ImGui : : TableNextColumn ( ) ;
}
2022-09-19 14:16:23 +02:00
2023-01-08 16:06:26 +01:00
void PatternDrawer : : closeTreeNode ( bool inlined ) {
if ( ! inlined & & this - > m_treeStyle ! = TreeStyle : : Flattened )
ImGui : : TreePop ( ) ;
}
2022-09-19 14:16:23 +02:00
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternArrayDynamic & pattern ) {
2022-09-19 14:16:23 +02:00
drawArray ( pattern , pattern , pattern . isInlined ( ) ) ;
2022-04-08 16:08:02 +02:00
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternArrayStatic & pattern ) {
2022-09-19 14:16:23 +02:00
drawArray ( pattern , pattern , pattern . isInlined ( ) ) ;
2022-04-08 16:08:02 +02:00
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternBitfieldField & pattern ) {
2022-04-08 16:08:02 +02:00
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
2023-06-06 11:29:58 +02:00
createTreeNode ( pattern , true ) ;
ImGui : : SameLine ( 0 , 0 ) ;
2022-04-08 16:08:02 +02:00
makeSelectable ( pattern ) ;
2022-07-25 12:09:28 +02:00
drawCommentTooltip ( pattern ) ;
2023-06-06 11:29:58 +02:00
ImGui : : TableNextColumn ( ) ;
2022-04-08 16:08:02 +02:00
drawColorColumn ( pattern ) ;
2023-03-26 11:01:37 +02:00
drawOffsetColumnForBitfieldMember ( pattern ) ;
drawSizeColumnForBitfieldMember ( pattern ) ;
2022-04-08 16:08:02 +02:00
ImGui : : TableNextColumn ( ) ;
ImGui : : TextFormattedColored ( ImColor ( 0xFF9BC64D ) , " bits " ) ;
ImGui : : TableNextColumn ( ) ;
2023-05-19 19:56:55 +02:00
if ( this - > isEditingPattern ( pattern ) ) {
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushItemWidth ( ImGui : : GetContentRegionAvail ( ) . x ) ;
auto value = pattern . getValue ( ) ;
auto valueString = pattern . toString ( ) ;
if ( pattern . getBitSize ( ) = = 1 ) {
bool boolValue = value . toBoolean ( ) ;
if ( ImGui : : Checkbox ( " ##boolean " , & boolValue ) ) {
pattern . setValue ( boolValue ) ;
}
} else if ( std : : holds_alternative < i128 > ( value ) ) {
if ( ImGui : : InputText ( " ##Value " , valueString , ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue ) ) {
MathEvaluator < i128 > mathEvaluator ;
if ( auto result = mathEvaluator . evaluate ( valueString ) ; result . has_value ( ) )
pattern . setValue ( result . value ( ) ) ;
this - > resetEditing ( ) ;
}
} else if ( std : : holds_alternative < u128 > ( value ) ) {
if ( ImGui : : InputText ( " ##Value " , valueString , ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue ) ) {
MathEvaluator < u128 > mathEvaluator ;
if ( auto result = mathEvaluator . evaluate ( valueString ) ; result . has_value ( ) )
pattern . setValue ( result . value ( ) ) ;
this - > resetEditing ( ) ;
}
}
ImGui : : PopItemWidth ( ) ;
ImGui : : PopStyleVar ( ) ;
} else {
drawValueColumn ( pattern ) ;
}
2022-04-08 16:08:02 +02:00
}
2023-03-26 11:01:37 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternBitfieldArray & pattern ) {
drawArray ( pattern , pattern , pattern . isInlined ( ) ) ;
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternBitfield & pattern ) {
2022-04-08 16:08:02 +02:00
bool open = true ;
2023-01-08 16:06:26 +01:00
if ( ! pattern . isInlined ( ) & & this - > m_treeStyle ! = TreeStyle : : Flattened ) {
2022-04-08 16:08:02 +02:00
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
open = createTreeNode ( pattern ) ;
2023-02-13 08:26:43 +01:00
ImGui : : SameLine ( 0 , 0 ) ;
2022-04-08 16:08:02 +02:00
makeSelectable ( pattern ) ;
drawCommentTooltip ( pattern ) ;
2023-02-13 08:26:43 +01:00
ImGui : : TableNextColumn ( ) ;
2023-04-12 16:03:58 +02:00
if ( pattern . isSealed ( ) )
drawColorColumn ( pattern ) ;
else
ImGui : : TableNextColumn ( ) ;
2022-04-08 16:08:02 +02:00
drawOffsetColumn ( pattern ) ;
drawSizeColumn ( pattern ) ;
drawTypenameColumn ( pattern , " bitfield " ) ;
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-04-08 16:08:02 +02:00
}
if ( open ) {
2022-12-21 11:31:33 +01:00
int id = 1 ;
2022-12-18 23:11:22 +01:00
pattern . forEachEntry ( 0 , pattern . getEntryCount ( ) , [ & ] ( u64 , auto * field ) {
2022-12-21 11:31:33 +01:00
ImGui : : PushID ( id ) ;
2022-12-18 23:11:22 +01:00
this - > draw ( * field ) ;
ImGui : : PopID ( ) ;
2022-12-21 11:31:33 +01:00
id + = 1 ;
2022-04-08 16:08:02 +02:00
} ) ;
2023-01-08 16:06:26 +01:00
closeTreeNode ( pattern . isInlined ( ) ) ;
2022-04-08 16:08:02 +02:00
}
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternBoolean & pattern ) {
2022-09-07 23:11:13 +02:00
createDefaultEntry ( pattern ) ;
2022-12-16 11:20:39 +01:00
2023-01-28 00:03:20 +01:00
if ( this - > isEditingPattern ( pattern ) ) {
2022-12-18 23:11:22 +01:00
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushItemWidth ( ImGui : : GetContentRegionAvail ( ) . x ) ;
2022-12-16 11:20:39 +01:00
2023-05-19 19:56:55 +02:00
bool value = pattern . getValue ( ) . toBoolean ( ) ;
if ( ImGui : : Checkbox ( " ##boolean " , & value ) ) {
2022-12-18 23:11:22 +01:00
pattern . setValue ( value ) ;
}
2022-12-16 11:20:39 +01:00
2022-12-18 23:11:22 +01:00
ImGui : : PopItemWidth ( ) ;
ImGui : : PopStyleVar ( ) ;
} else {
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-12-18 23:11:22 +01:00
}
2022-04-08 16:08:02 +02:00
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternCharacter & pattern ) {
2022-09-07 23:11:13 +02:00
createDefaultEntry ( pattern ) ;
2022-12-16 11:20:39 +01:00
2023-01-28 00:03:20 +01:00
if ( this - > isEditingPattern ( pattern ) ) {
2022-12-18 23:11:22 +01:00
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushItemWidth ( ImGui : : GetContentRegionAvail ( ) . x ) ;
auto value = hex : : encodeByteString ( pattern . getBytes ( ) ) ;
if ( ImGui : : InputText ( " ##Character " , value . data ( ) , value . size ( ) + 1 , ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue ) ) {
if ( ! value . empty ( ) ) {
auto result = hex : : decodeByteString ( value ) ;
if ( ! result . empty ( ) )
pattern . setValue ( char ( result [ 0 ] ) ) ;
2023-01-28 00:03:20 +01:00
this - > resetEditing ( ) ;
2022-12-18 23:11:22 +01:00
}
2022-12-16 11:20:39 +01:00
}
2022-12-18 23:11:22 +01:00
ImGui : : PopItemWidth ( ) ;
ImGui : : PopStyleVar ( ) ;
} else {
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-12-16 11:20:39 +01:00
}
2022-04-08 16:08:02 +02:00
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternEnum & pattern ) {
2022-04-08 16:08:02 +02:00
ImGui : : TableNextRow ( ) ;
2023-06-06 11:29:58 +02:00
ImGui : : TableNextColumn ( ) ;
2023-06-04 18:30:47 +02:00
createTreeNode ( pattern , true ) ;
2023-06-06 11:29:58 +02:00
ImGui : : SameLine ( 0 , 0 ) ;
makeSelectable ( pattern ) ;
2022-04-08 16:08:02 +02:00
drawCommentTooltip ( pattern ) ;
ImGui : : TableNextColumn ( ) ;
drawColorColumn ( pattern ) ;
drawOffsetColumn ( pattern ) ;
drawSizeColumn ( pattern ) ;
drawTypenameColumn ( pattern , " enum " ) ;
2022-12-16 11:20:39 +01:00
2023-01-28 00:03:20 +01:00
if ( this - > isEditingPattern ( pattern ) ) {
2022-12-18 23:11:22 +01:00
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushItemWidth ( ImGui : : GetContentRegionAvail ( ) . x ) ;
2022-12-16 11:20:39 +01:00
2022-12-18 23:11:22 +01:00
if ( ImGui : : BeginCombo ( " ##Enum " , pattern . getFormattedValue ( ) . c_str ( ) ) ) {
2023-01-23 13:53:29 +01:00
auto currValue = pattern . getValue ( ) . toUnsigned ( ) ;
2022-12-18 23:11:22 +01:00
for ( auto & value : pattern . getEnumValues ( ) ) {
2023-01-23 13:53:29 +01:00
auto min = value . min . toUnsigned ( ) ;
auto max = value . max . toUnsigned ( ) ;
2022-12-17 22:22:20 +01:00
2022-12-18 23:11:22 +01:00
bool isSelected = min < = currValue & & max > = currValue ;
if ( ImGui : : Selectable ( fmt : : format ( " {}::{} (0x{:0{}X}) " , pattern . getTypeName ( ) , value . name , min , pattern . getSize ( ) * 2 ) . c_str ( ) , isSelected ) ) {
pattern . setValue ( value . min ) ;
2023-01-28 00:03:20 +01:00
this - > resetEditing ( ) ;
2022-12-18 23:11:22 +01:00
}
if ( isSelected )
ImGui : : SetItemDefaultFocus ( ) ;
2022-12-16 11:20:39 +01:00
}
2022-12-18 23:11:22 +01:00
ImGui : : EndCombo ( ) ;
2022-12-16 11:20:39 +01:00
}
2022-12-18 23:11:22 +01:00
ImGui : : PopItemWidth ( ) ;
ImGui : : PopStyleVar ( ) ;
} else {
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-12-18 23:11:22 +01:00
}
2022-04-08 16:08:02 +02:00
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternFloat & pattern ) {
2022-09-07 23:11:13 +02:00
createDefaultEntry ( pattern ) ;
2022-12-16 11:20:39 +01:00
2023-01-28 00:03:20 +01:00
if ( this - > isEditingPattern ( pattern ) ) {
2022-12-18 23:11:22 +01:00
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushItemWidth ( ImGui : : GetContentRegionAvail ( ) . x ) ;
2022-12-16 11:20:39 +01:00
2022-12-18 23:11:22 +01:00
auto value = pattern . toString ( ) ;
if ( ImGui : : InputText ( " ##Value " , value , ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue ) ) {
MathEvaluator < long double > mathEvaluator ;
2022-12-17 22:22:20 +01:00
2022-12-18 23:11:22 +01:00
if ( auto result = mathEvaluator . evaluate ( value ) ; result . has_value ( ) )
pattern . setValue ( double ( result . value ( ) ) ) ;
2022-12-16 11:20:39 +01:00
2023-01-28 00:03:20 +01:00
this - > resetEditing ( ) ;
2022-12-18 23:11:22 +01:00
}
ImGui : : PopItemWidth ( ) ;
ImGui : : PopStyleVar ( ) ;
} else {
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-12-18 23:11:22 +01:00
}
2022-04-08 16:08:02 +02:00
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternPadding & pattern ) {
2022-04-08 16:08:02 +02:00
// Do nothing
hex : : unused ( pattern ) ;
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternPointer & pattern ) {
2022-04-08 16:08:02 +02:00
bool open = true ;
2023-01-08 16:06:26 +01:00
if ( ! pattern . isInlined ( ) & & this - > m_treeStyle ! = TreeStyle : : Flattened ) {
2022-04-08 16:08:02 +02:00
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
open = createTreeNode ( pattern ) ;
2023-02-13 08:26:43 +01:00
ImGui : : SameLine ( 0 , 0 ) ;
2022-04-08 16:08:02 +02:00
makeSelectable ( pattern ) ;
drawCommentTooltip ( pattern ) ;
2023-02-13 08:26:43 +01:00
ImGui : : TableNextColumn ( ) ;
2022-04-08 16:08:02 +02:00
drawColorColumn ( pattern ) ;
drawOffsetColumn ( pattern ) ;
drawSizeColumn ( pattern ) ;
ImGui : : TextFormattedColored ( ImColor ( 0xFF9BC64D ) , " {} " , pattern . getFormattedName ( ) ) ;
ImGui : : TableNextColumn ( ) ;
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-04-08 16:08:02 +02:00
}
if ( open ) {
pattern . getPointedAtPattern ( ) - > accept ( * this ) ;
2023-01-08 16:06:26 +01:00
closeTreeNode ( pattern . isInlined ( ) ) ;
2022-04-08 16:08:02 +02:00
}
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternSigned & pattern ) {
2022-09-07 23:11:13 +02:00
createDefaultEntry ( pattern ) ;
2022-12-16 11:20:39 +01:00
2023-01-28 00:03:20 +01:00
if ( this - > isEditingPattern ( pattern ) ) {
2022-12-18 23:11:22 +01:00
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushItemWidth ( ImGui : : GetContentRegionAvail ( ) . x ) ;
2022-12-16 11:20:39 +01:00
2022-12-18 23:11:22 +01:00
auto value = pattern . getFormattedValue ( ) ;
if ( ImGui : : InputText ( " ##Value " , value , ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue ) ) {
MathEvaluator < i128 > mathEvaluator ;
2022-12-16 11:20:39 +01:00
2022-12-18 23:11:22 +01:00
if ( auto result = mathEvaluator . evaluate ( value ) ; result . has_value ( ) )
pattern . setValue ( result . value ( ) ) ;
2022-12-16 11:20:39 +01:00
2023-01-28 00:03:20 +01:00
this - > resetEditing ( ) ;
2022-12-18 23:11:22 +01:00
}
ImGui : : PopItemWidth ( ) ;
ImGui : : PopStyleVar ( ) ;
} else {
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-12-18 23:11:22 +01:00
}
2022-04-08 16:08:02 +02:00
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternString & pattern ) {
2022-12-16 11:20:39 +01:00
if ( pattern . getSize ( ) > 0 ) {
2022-09-07 23:11:13 +02:00
createDefaultEntry ( pattern ) ;
2022-12-18 23:11:22 +01:00
2023-01-28 00:03:20 +01:00
if ( this - > isEditingPattern ( pattern ) ) {
2022-12-18 23:11:22 +01:00
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushItemWidth ( ImGui : : GetContentRegionAvail ( ) . x ) ;
auto value = pattern . toString ( ) ;
if ( ImGui : : InputText ( " ##Value " , value . data ( ) , value . size ( ) + 1 , ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue ) ) {
pattern . setValue ( value ) ;
2023-01-28 00:03:20 +01:00
this - > resetEditing ( ) ;
2022-12-18 23:11:22 +01:00
}
ImGui : : PopItemWidth ( ) ;
ImGui : : PopStyleVar ( ) ;
} else {
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-12-18 23:11:22 +01:00
}
2022-07-16 13:08:08 +02:00
}
2022-12-16 11:20:39 +01:00
}
2022-04-08 16:08:02 +02:00
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternStruct & pattern ) {
2022-04-08 16:08:02 +02:00
bool open = true ;
2023-01-08 16:06:26 +01:00
if ( ! pattern . isInlined ( ) & & this - > m_treeStyle ! = TreeStyle : : Flattened ) {
2022-04-08 16:08:02 +02:00
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
open = createTreeNode ( pattern ) ;
2023-02-13 08:26:43 +01:00
ImGui : : SameLine ( 0 , 0 ) ;
2022-04-08 16:08:02 +02:00
makeSelectable ( pattern ) ;
drawCommentTooltip ( pattern ) ;
2023-02-13 08:26:43 +01:00
ImGui : : TableNextColumn ( ) ;
2022-09-05 23:34:20 +02:00
if ( pattern . isSealed ( ) )
drawColorColumn ( pattern ) ;
else
ImGui : : TableNextColumn ( ) ;
2022-04-08 16:08:02 +02:00
drawOffsetColumn ( pattern ) ;
drawSizeColumn ( pattern ) ;
drawTypenameColumn ( pattern , " struct " ) ;
2022-12-17 22:22:20 +01:00
2023-07-04 22:18:06 +02:00
if ( this - > isEditingPattern ( pattern ) & & ! pattern . getWriteFormatterFunction ( ) . empty ( ) ) {
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushItemWidth ( ImGui : : GetContentRegionAvail ( ) . x ) ;
auto value = pattern . toString ( ) ;
if ( ImGui : : InputText ( " ##Value " , value , ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue ) ) {
pattern . setValue ( value ) ;
this - > resetEditing ( ) ;
2022-12-17 22:22:20 +01:00
}
2023-07-04 22:18:06 +02:00
ImGui : : PopItemWidth ( ) ;
ImGui : : PopStyleVar ( ) ;
2022-12-18 23:11:22 +01:00
} else {
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-12-17 22:22:20 +01:00
}
2022-04-08 16:08:02 +02:00
}
if ( open ) {
2022-12-21 11:31:33 +01:00
int id = 1 ;
2022-12-23 14:33:27 +01:00
pattern . forEachEntry ( 0 , pattern . getEntryCount ( ) , [ & ] ( u64 , auto * member ) {
2022-12-21 11:31:33 +01:00
ImGui : : PushID ( id ) ;
2022-09-19 14:16:23 +02:00
this - > draw ( * member ) ;
2022-12-18 23:11:22 +01:00
ImGui : : PopID ( ) ;
2022-12-21 11:31:33 +01:00
id + = 1 ;
2022-04-08 16:08:02 +02:00
} ) ;
2023-01-08 16:06:26 +01:00
closeTreeNode ( pattern . isInlined ( ) ) ;
2022-04-08 16:08:02 +02:00
}
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternUnion & pattern ) {
2022-04-08 16:08:02 +02:00
bool open = true ;
2023-01-08 16:06:26 +01:00
if ( ! pattern . isInlined ( ) & & this - > m_treeStyle ! = TreeStyle : : Flattened ) {
2022-04-08 16:08:02 +02:00
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
open = createTreeNode ( pattern ) ;
2023-02-13 08:26:43 +01:00
ImGui : : SameLine ( 0 , 0 ) ;
2022-04-08 16:08:02 +02:00
makeSelectable ( pattern ) ;
drawCommentTooltip ( pattern ) ;
2023-02-13 08:26:43 +01:00
ImGui : : TableNextColumn ( ) ;
2022-09-05 23:34:20 +02:00
if ( pattern . isSealed ( ) )
drawColorColumn ( pattern ) ;
else
ImGui : : TableNextColumn ( ) ;
2022-04-08 16:08:02 +02:00
drawOffsetColumn ( pattern ) ;
drawSizeColumn ( pattern ) ;
drawTypenameColumn ( pattern , " union " ) ;
2022-12-17 22:22:20 +01:00
2023-07-04 22:18:06 +02:00
if ( this - > isEditingPattern ( pattern ) & & ! pattern . getWriteFormatterFunction ( ) . empty ( ) ) {
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushItemWidth ( ImGui : : GetContentRegionAvail ( ) . x ) ;
auto value = pattern . toString ( ) ;
if ( ImGui : : InputText ( " ##Value " , value , ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue ) ) {
pattern . setValue ( value ) ;
this - > resetEditing ( ) ;
2022-12-17 22:22:20 +01:00
}
2023-07-04 22:18:06 +02:00
ImGui : : PopItemWidth ( ) ;
ImGui : : PopStyleVar ( ) ;
2022-12-18 23:11:22 +01:00
} else {
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-12-17 22:22:20 +01:00
}
2022-04-08 16:08:02 +02:00
}
if ( open ) {
2022-12-21 11:31:33 +01:00
int id = 1 ;
2022-09-19 14:16:23 +02:00
pattern . forEachEntry ( 0 , pattern . getEntryCount ( ) , [ & ] ( u64 , auto * member ) {
2022-12-21 11:31:33 +01:00
ImGui : : PushID ( id ) ;
2022-09-19 14:16:23 +02:00
this - > draw ( * member ) ;
2022-12-18 23:11:22 +01:00
ImGui : : PopID ( ) ;
2022-12-21 11:31:33 +01:00
id + = 1 ;
2022-04-08 16:08:02 +02:00
} ) ;
2023-01-08 16:06:26 +01:00
closeTreeNode ( pattern . isInlined ( ) ) ;
2022-04-08 16:08:02 +02:00
}
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternUnsigned & pattern ) {
2022-09-07 23:11:13 +02:00
createDefaultEntry ( pattern ) ;
2022-12-16 11:20:39 +01:00
2023-01-28 00:03:20 +01:00
if ( this - > isEditingPattern ( pattern ) ) {
2022-12-18 23:11:22 +01:00
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushItemWidth ( ImGui : : GetContentRegionAvail ( ) . x ) ;
auto value = pattern . toString ( ) ;
if ( ImGui : : InputText ( " ##Value " , value , ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue ) ) {
MathEvaluator < u128 > mathEvaluator ;
if ( auto result = mathEvaluator . evaluate ( value ) ; result . has_value ( ) )
pattern . setValue ( result . value ( ) ) ;
2022-12-16 11:20:39 +01:00
2023-01-28 00:03:20 +01:00
this - > resetEditing ( ) ;
2022-12-18 23:11:22 +01:00
}
ImGui : : PopItemWidth ( ) ;
ImGui : : PopStyleVar ( ) ;
} else {
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-12-16 11:20:39 +01:00
}
2022-04-08 16:08:02 +02:00
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternWideCharacter & pattern ) {
2022-09-07 23:11:13 +02:00
createDefaultEntry ( pattern ) ;
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-04-08 16:08:02 +02:00
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : visit ( pl : : ptrn : : PatternWideString & pattern ) {
2022-12-16 11:20:39 +01:00
if ( pattern . getSize ( ) > 0 ) {
2022-09-07 23:11:13 +02:00
createDefaultEntry ( pattern ) ;
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-12-16 11:20:39 +01:00
}
2022-04-08 16:08:02 +02:00
}
2022-08-06 21:38:09 +02:00
void PatternDrawer : : draw ( pl : : ptrn : : Pattern & pattern ) {
2023-01-27 10:45:07 +01:00
if ( pattern . getVisibility ( ) = = pl : : ptrn : : Visibility : : Hidden )
2022-04-08 16:08:02 +02:00
return ;
2023-06-04 18:30:47 +02:00
this - > m_currPatternPath . push_back ( pattern . getVariableName ( ) ) ;
2023-06-04 16:13:46 +02:00
ON_SCOPE_EXIT { this - > m_currPatternPath . pop_back ( ) ; } ;
2023-06-24 16:40:34 +02:00
if ( matchesFilter ( this - > m_filter , this - > m_currPatternPath , false ) )
2023-06-04 16:13:46 +02:00
pattern . accept ( * this ) ;
2022-04-08 16:08:02 +02:00
}
2023-06-04 18:30:47 +02:00
void PatternDrawer : : drawArray ( pl : : ptrn : : Pattern & pattern , pl : : ptrn : : IIterable & iterable , bool isInlined ) {
if ( iterable . getEntryCount ( ) = = 0 )
2022-09-19 14:16:23 +02:00
return ;
2022-04-08 16:08:02 +02:00
bool open = true ;
2023-01-08 16:06:26 +01:00
if ( ! isInlined & & this - > m_treeStyle ! = TreeStyle : : Flattened ) {
2022-04-08 16:08:02 +02:00
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
open = createTreeNode ( pattern ) ;
2023-02-13 08:26:43 +01:00
ImGui : : SameLine ( 0 , 0 ) ;
2022-04-08 16:08:02 +02:00
makeSelectable ( pattern ) ;
drawCommentTooltip ( pattern ) ;
2023-02-13 08:26:43 +01:00
ImGui : : TableNextColumn ( ) ;
2022-12-23 14:33:27 +01:00
2022-09-05 23:34:20 +02:00
if ( pattern . isSealed ( ) )
drawColorColumn ( pattern ) ;
else
ImGui : : TableNextColumn ( ) ;
2022-04-08 16:08:02 +02:00
drawOffsetColumn ( pattern ) ;
drawSizeColumn ( pattern ) ;
ImGui : : TextFormattedColored ( ImColor ( 0xFF9BC64D ) , " {0} " , pattern . getTypeName ( ) ) ;
ImGui : : SameLine ( 0 , 0 ) ;
ImGui : : TextUnformatted ( " [ " ) ;
ImGui : : SameLine ( 0 , 0 ) ;
2023-06-04 18:30:47 +02:00
ImGui : : TextFormattedColored ( ImColor ( 0xFF00FF00 ) , " {0} " , iterable . getEntryCount ( ) ) ;
2022-04-08 16:08:02 +02:00
ImGui : : SameLine ( 0 , 0 ) ;
ImGui : : TextUnformatted ( " ] " ) ;
ImGui : : TableNextColumn ( ) ;
2023-01-18 17:17:34 +01:00
2023-05-12 08:49:08 +02:00
drawValueColumn ( pattern ) ;
2022-04-08 16:08:02 +02:00
}
2022-09-19 14:16:23 +02:00
if ( open ) {
u64 chunkCount = 0 ;
2023-06-04 18:30:47 +02:00
for ( u64 i = 0 ; i < iterable . getEntryCount ( ) ; i + = ChunkSize ) {
2022-09-19 14:16:23 +02:00
chunkCount + + ;
auto & displayEnd = this - > getDisplayEnd ( pattern ) ;
if ( chunkCount > displayEnd ) {
2022-12-20 20:56:01 +01:00
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
2023-06-06 11:29:58 +02:00
ImGui : : TableNextColumn ( ) ;
2022-12-20 20:56:01 +01:00
2022-11-08 21:43:22 +01:00
ImGui : : Selectable ( hex : : format ( " ... ({}) " , " hex.builtin.pattern_drawer.double_click " _lang ) . c_str ( ) , false , ImGuiSelectableFlags_SpanAllColumns ) ;
2022-09-19 14:16:23 +02:00
if ( ImGui : : IsItemHovered ( ) & & ImGui : : IsMouseDoubleClicked ( ImGuiMouseButton_Left ) )
displayEnd + = DisplayEndStep ;
break ;
} else {
2023-06-04 18:30:47 +02:00
auto endIndex = std : : min < u64 > ( iterable . getEntryCount ( ) , i + ChunkSize ) ;
2022-09-19 14:16:23 +02:00
2022-12-20 20:56:01 +01:00
bool chunkOpen = true ;
2023-06-04 18:30:47 +02:00
if ( iterable . getEntryCount ( ) > ChunkSize ) {
auto startOffset = iterable . getEntry ( i ) - > getOffset ( ) ;
auto endOffset = iterable . getEntry ( endIndex - 1 ) - > getOffset ( ) ;
auto endSize = iterable . getEntry ( endIndex - 1 ) - > getSize ( ) ;
2022-12-20 20:56:01 +01:00
size_t chunkSize = ( endOffset - startOffset ) + endSize ;
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
2023-06-06 10:06:54 +02:00
ImGui : : TableNextColumn ( ) ;
2022-12-20 20:56:01 +01:00
2023-01-08 16:06:26 +01:00
chunkOpen = highlightWhenSelected ( startOffset , ( ( endOffset + endSize ) - startOffset ) - 1 , [ & ] {
2023-07-23 09:14:00 +02:00
return ImGui : : TreeNodeEx ( hex : : format ( " {0}[{1} ... {2}] " , this - > m_treeStyle = = TreeStyle : : Flattened ? this - > getDisplayName ( pattern ) . c_str ( ) : " " , i , endIndex - 1 ) . c_str ( ) , ImGuiTreeNodeFlags_SpanFullWidth ) ;
2023-01-08 16:06:26 +01:00
} ) ;
2022-12-20 20:56:01 +01:00
ImGui : : TableNextColumn ( ) ;
ImGui : : TableNextColumn ( ) ;
2023-07-24 16:55:35 +02:00
drawOffsetColumn ( pattern ) ;
2022-12-20 20:56:01 +01:00
ImGui : : TextFormatted ( " 0x{0:04X} " , chunkSize ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : TextFormattedColored ( ImColor ( 0xFF9BC64D ) , " {0} " , pattern . getTypeName ( ) ) ;
ImGui : : SameLine ( 0 , 0 ) ;
ImGui : : TextUnformatted ( " [ " ) ;
ImGui : : SameLine ( 0 , 0 ) ;
ImGui : : TextFormattedColored ( ImColor ( 0xFF00FF00 ) , " {0} " , endIndex - i ) ;
ImGui : : SameLine ( 0 , 0 ) ;
ImGui : : TextUnformatted ( " ] " ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : TextFormatted ( " [ ... ] " ) ;
}
2022-09-19 14:21:36 +02:00
2022-09-19 14:16:23 +02:00
if ( chunkOpen ) {
2022-12-21 11:31:33 +01:00
int id = 1 ;
2023-06-04 18:30:47 +02:00
iterable . forEachEntry ( i , endIndex , [ & ] ( u64 , auto * entry ) {
2022-12-21 11:31:33 +01:00
ImGui : : PushID ( id ) ;
2022-09-19 14:16:23 +02:00
this - > draw ( * entry ) ;
2022-12-18 23:11:22 +01:00
ImGui : : PopID ( ) ;
2022-12-21 11:31:33 +01:00
id + = 1 ;
2022-09-19 14:16:23 +02:00
} ) ;
2023-06-04 18:30:47 +02:00
if ( iterable . getEntryCount ( ) > ChunkSize )
2022-12-20 20:56:01 +01:00
ImGui : : TreePop ( ) ;
2022-09-19 14:16:23 +02:00
}
}
}
2022-04-08 16:08:02 +02:00
2023-01-08 16:06:26 +01:00
closeTreeNode ( isInlined ) ;
2022-04-08 16:08:02 +02:00
}
}
2022-08-06 21:38:09 +02:00
u64 & PatternDrawer : : getDisplayEnd ( const pl : : ptrn : : Pattern & pattern ) {
2022-09-07 23:11:13 +02:00
auto it = this - > m_displayEnd . find ( & pattern ) ;
if ( it ! = this - > m_displayEnd . end ( ) ) {
2022-04-08 16:08:02 +02:00
return it - > second ;
}
2022-09-07 23:11:13 +02:00
auto [ value , success ] = this - > m_displayEnd . emplace ( & pattern , DisplayEndDefault ) ;
return value - > second ;
2022-04-08 16:08:02 +02:00
}
2022-11-08 21:43:22 +01:00
2023-07-23 09:14:00 +02:00
bool PatternDrawer : : sortPatterns ( const ImGuiTableSortSpecs * sortSpecs , const pl : : ptrn : : Pattern * left , const pl : : ptrn : : Pattern * right ) const {
2022-11-08 21:43:22 +01:00
if ( sortSpecs - > Specs - > ColumnUserID = = ImGui : : GetID ( " name " ) ) {
if ( sortSpecs - > Specs - > SortDirection = = ImGuiSortDirection_Ascending )
2023-07-23 09:14:00 +02:00
return this - > getDisplayName ( * left ) < this - > getDisplayName ( * right ) ;
2023-03-16 13:35:09 +01:00
else
2023-07-23 09:14:00 +02:00
return this - > getDisplayName ( * left ) > this - > getDisplayName ( * right ) ;
2023-06-18 12:23:47 +02:00
} else if ( sortSpecs - > Specs - > ColumnUserID = = ImGui : : GetID ( " start " ) ) {
2022-11-08 21:43:22 +01:00
if ( sortSpecs - > Specs - > SortDirection = = ImGuiSortDirection_Ascending )
2023-03-26 11:01:37 +02:00
return left - > getOffsetForSorting ( ) < right - > getOffsetForSorting ( ) ;
2023-03-16 13:35:09 +01:00
else
2023-03-26 11:01:37 +02:00
return left - > getOffsetForSorting ( ) > right - > getOffsetForSorting ( ) ;
2023-06-18 12:23:47 +02:00
} else if ( sortSpecs - > Specs - > ColumnUserID = = ImGui : : GetID ( " end " ) ) {
if ( sortSpecs - > Specs - > SortDirection = = ImGuiSortDirection_Ascending )
return left - > getOffsetForSorting ( ) + left - > getSize ( ) < right - > getOffsetForSorting ( ) + right - > getSize ( ) ;
else
return left - > getOffsetForSorting ( ) + left - > getSize ( ) > right - > getOffsetForSorting ( ) + right - > getSize ( ) ;
2022-11-08 21:43:22 +01:00
} else if ( sortSpecs - > Specs - > ColumnUserID = = ImGui : : GetID ( " size " ) ) {
if ( sortSpecs - > Specs - > SortDirection = = ImGuiSortDirection_Ascending )
2023-03-26 11:01:37 +02:00
return left - > getSizeForSorting ( ) < right - > getSizeForSorting ( ) ;
2023-03-16 13:35:09 +01:00
else
2023-03-26 11:01:37 +02:00
return left - > getSizeForSorting ( ) > right - > getSizeForSorting ( ) ;
2022-11-08 21:43:22 +01:00
} else if ( sortSpecs - > Specs - > ColumnUserID = = ImGui : : GetID ( " value " ) ) {
if ( sortSpecs - > Specs - > SortDirection = = ImGuiSortDirection_Ascending )
2023-05-24 21:04:59 +02:00
return left - > getValue ( ) . toString ( true ) < right - > getValue ( ) . toString ( true ) ;
2023-03-16 13:35:09 +01:00
else
2023-05-24 21:04:59 +02:00
return left - > getValue ( ) . toString ( true ) > right - > getValue ( ) . toString ( true ) ;
2022-11-08 21:43:22 +01:00
} else if ( sortSpecs - > Specs - > ColumnUserID = = ImGui : : GetID ( " type " ) ) {
if ( sortSpecs - > Specs - > SortDirection = = ImGuiSortDirection_Ascending )
return left - > getTypeName ( ) < right - > getTypeName ( ) ;
2023-03-16 13:35:09 +01:00
else
return left - > getTypeName ( ) > right - > getTypeName ( ) ;
2022-11-08 21:43:22 +01:00
} else if ( sortSpecs - > Specs - > ColumnUserID = = ImGui : : GetID ( " color " ) ) {
if ( sortSpecs - > Specs - > SortDirection = = ImGuiSortDirection_Ascending )
return left - > getColor ( ) < right - > getColor ( ) ;
2023-03-16 13:35:09 +01:00
else
return left - > getColor ( ) > right - > getColor ( ) ;
2022-11-08 21:43:22 +01:00
}
return false ;
}
2023-07-23 09:14:00 +02:00
bool PatternDrawer : : beginPatternTable ( const std : : vector < std : : shared_ptr < pl : : ptrn : : Pattern > > & patterns , std : : vector < pl : : ptrn : : Pattern * > & sortedPatterns , float height ) {
2023-06-18 12:23:47 +02:00
if ( ImGui : : BeginTable ( " ##Patterntable " , 8 , ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY , ImVec2 ( 0 , height ) ) ) {
2022-11-08 21:43:22 +01:00
ImGui : : TableSetupScrollFreeze ( 0 , 1 ) ;
2023-06-04 18:30:47 +02:00
ImGui : : TableSetupColumn ( " ##favorite " , ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoReorder | ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_IndentDisable , ImGui : : GetTextLineHeight ( ) , ImGui : : GetID ( " favorite " ) ) ;
ImGui : : TableSetupColumn ( " hex.builtin.pattern_drawer.var_name " _lang , ImGuiTableColumnFlags_PreferSortAscending | ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_IndentEnable , 0 , ImGui : : GetID ( " name " ) ) ;
2022-11-08 21:43:22 +01:00
ImGui : : TableSetupColumn ( " hex.builtin.pattern_drawer.color " _lang , ImGuiTableColumnFlags_PreferSortAscending , 0 , ImGui : : GetID ( " color " ) ) ;
2023-06-18 12:23:47 +02:00
ImGui : : TableSetupColumn ( " hex.builtin.pattern_drawer.start " _lang , ImGuiTableColumnFlags_PreferSortAscending | ImGuiTableColumnFlags_DefaultSort , 0 , ImGui : : GetID ( " start " ) ) ;
ImGui : : TableSetupColumn ( " hex.builtin.pattern_drawer.end " _lang , ImGuiTableColumnFlags_PreferSortAscending | ImGuiTableColumnFlags_DefaultSort , 0 , ImGui : : GetID ( " end " ) ) ;
2022-11-08 21:43:22 +01:00
ImGui : : TableSetupColumn ( " hex.builtin.pattern_drawer.size " _lang , ImGuiTableColumnFlags_PreferSortAscending , 0 , ImGui : : GetID ( " size " ) ) ;
ImGui : : TableSetupColumn ( " hex.builtin.pattern_drawer.type " _lang , ImGuiTableColumnFlags_PreferSortAscending , 0 , ImGui : : GetID ( " type " ) ) ;
ImGui : : TableSetupColumn ( " hex.builtin.pattern_drawer.value " _lang , ImGuiTableColumnFlags_PreferSortAscending , 0 , ImGui : : GetID ( " value " ) ) ;
auto sortSpecs = ImGui : : TableGetSortSpecs ( ) ;
2022-11-10 11:18:14 +01:00
if ( patterns . empty ( ) )
sortedPatterns . clear ( ) ;
2022-11-08 21:43:22 +01:00
if ( ! patterns . empty ( ) & & ( sortSpecs - > SpecsDirty | | sortedPatterns . empty ( ) ) ) {
sortedPatterns . clear ( ) ;
std : : transform ( patterns . begin ( ) , patterns . end ( ) , std : : back_inserter ( sortedPatterns ) , [ ] ( const std : : shared_ptr < pl : : ptrn : : Pattern > & pattern ) {
return pattern . get ( ) ;
} ) ;
2023-07-23 09:14:00 +02:00
std : : sort ( sortedPatterns . begin ( ) , sortedPatterns . end ( ) , [ this , & sortSpecs ] ( pl : : ptrn : : Pattern * left , pl : : ptrn : : Pattern * right ) - > bool {
return this - > sortPatterns ( sortSpecs , left , right ) ;
2022-11-08 21:43:22 +01:00
} ) ;
for ( auto & pattern : sortedPatterns )
2023-07-23 09:14:00 +02:00
pattern - > sort ( [ this , & sortSpecs ] ( const pl : : ptrn : : Pattern * left , const pl : : ptrn : : Pattern * right ) {
return this - > sortPatterns ( sortSpecs , left , right ) ;
2022-11-08 21:43:22 +01:00
} ) ;
sortSpecs - > SpecsDirty = false ;
}
return true ;
}
return false ;
}
2023-06-24 16:40:34 +02:00
void PatternDrawer : : traversePatternTree ( pl : : ptrn : : Pattern & pattern , std : : vector < std : : string > & patternPath , const std : : function < void ( pl : : ptrn : : Pattern & ) > & callback ) {
patternPath . push_back ( pattern . getVariableName ( ) ) ;
ON_SCOPE_EXIT { patternPath . pop_back ( ) ; } ;
2023-06-04 18:30:47 +02:00
callback ( pattern ) ;
if ( auto iterable = dynamic_cast < pl : : ptrn : : IIterable * > ( & pattern ) ; iterable ! = nullptr ) {
iterable - > forEachEntry ( 0 , iterable - > getEntryCount ( ) , [ & ] ( u64 , pl : : ptrn : : Pattern * entry ) {
2023-06-24 16:40:34 +02:00
traversePatternTree ( * entry , patternPath , callback ) ;
2023-06-04 18:30:47 +02:00
} ) ;
}
}
2023-06-05 11:57:26 +02:00
void PatternDrawer : : draw ( const std : : vector < std : : shared_ptr < pl : : ptrn : : Pattern > > & patterns , pl : : PatternLanguage * runtime , float height ) {
2023-06-05 09:07:58 +02:00
const auto treeStyleButton = [ this ] ( auto icon , TreeStyle style , const char * tooltip ) {
bool pushed = false ;
if ( this - > m_treeStyle = = style ) {
ImGui : : PushStyleColor ( ImGuiCol_Border , ImGui : : GetStyleColorVec4 ( ImGuiCol_ButtonActive ) ) ;
pushed = true ;
}
if ( ImGui : : DimmedIconButton ( icon , ImGui : : GetStyleColorVec4 ( ImGuiCol_Text ) ) )
this - > m_treeStyle = style ;
if ( pushed )
ImGui : : PopStyleColor ( ) ;
ImGui : : InfoTooltip ( tooltip ) ;
} ;
2023-01-28 00:03:20 +01:00
if ( ImGui : : IsMouseClicked ( ImGuiMouseButton_Left ) & & ! ImGui : : IsAnyItemHovered ( ) ) {
this - > resetEditing ( ) ;
}
2022-12-18 23:11:22 +01:00
2023-07-23 09:14:00 +02:00
ImGui : : PushItemWidth ( ImGui : : GetContentRegionAvail ( ) . x - ImGui : : GetTextLineHeightWithSpacing ( ) * 9.5 ) ;
2023-06-04 16:13:46 +02:00
if ( ImGui : : InputTextIcon ( " ##Search " , ICON_VS_FILTER , this - > m_filterText ) ) {
this - > m_filter = parseRValueFilter ( this - > m_filterText ) ;
}
ImGui : : PopItemWidth ( ) ;
2023-06-05 09:07:58 +02:00
ImGui : : SameLine ( ) ;
2023-07-23 09:14:00 +02:00
ImGui : : DimmedIconToggle ( ICON_VS_BOOK , & this - > m_showSpecName ) ;
ImGui : : InfoTooltip ( " hex.builtin.pattern_drawer.spec_name " _lang ) ;
ImGui : : SameLine ( ) ;
2023-06-05 09:07:58 +02:00
treeStyleButton ( ICON_VS_SYMBOL_KEYWORD , TreeStyle : : Default , " hex.builtin.pattern_drawer.tree_style.tree " _lang ) ;
ImGui : : SameLine ( 0 , 0 ) ;
treeStyleButton ( ICON_VS_LIST_TREE , TreeStyle : : AutoExpanded , " hex.builtin.pattern_drawer.tree_style.auto_expanded " _lang ) ;
ImGui : : SameLine ( 0 , 0 ) ;
treeStyleButton ( ICON_VS_LIST_FLAT , TreeStyle : : Flattened , " hex.builtin.pattern_drawer.tree_style.flattened " _lang ) ;
2023-06-05 11:57:26 +02:00
ImGui : : SameLine ( 0 , 15 _scaled ) ;
const auto startPos = ImGui : : GetCursorPos ( ) ;
ImGui : : BeginDisabled ( runtime = = nullptr ) ;
if ( ImGui : : DimmedIconButton ( ICON_VS_EXPORT , ImGui : : GetStyleColorVec4 ( ImGuiCol_Text ) ) ) {
ImGui : : OpenPopup ( " ExportPatterns " ) ;
}
ImGui : : EndDisabled ( ) ;
ImGui : : InfoTooltip ( " hex.builtin.pattern_drawer.export " _lang ) ;
ImGui : : SetNextWindowPos ( ImGui : : GetWindowPos ( ) + ImVec2 ( startPos . x , ImGui : : GetCursorPosY ( ) ) ) ;
if ( ImGui : : BeginPopup ( " ExportPatterns " ) ) {
for ( const auto & formatter : this - > m_formatters ) {
2023-06-21 17:49:03 +02:00
const auto name = [ & ] {
auto name = formatter - > getName ( ) ;
std : : transform ( name . begin ( ) , name . end ( ) , name . begin ( ) , [ ] ( char c ) { return char ( std : : toupper ( c ) ) ; } ) ;
return name ;
} ( ) ;
2023-06-05 11:57:26 +02:00
const auto & extension = formatter - > getFileExtension ( ) ;
if ( ImGui : : MenuItem ( name . c_str ( ) ) ) {
fs : : openFileBrowser ( fs : : DialogMode : : Save , { { name . c_str ( ) , extension . c_str ( ) } } , [ & ] ( const std : : fs : : path & path ) {
auto result = formatter - > format ( * runtime ) ;
wolv : : io : : File output ( path , wolv : : io : : File : : Mode : : Create ) ;
output . writeVector ( result ) ;
} ) ;
}
}
ImGui : : EndPopup ( ) ;
}
2023-06-04 18:30:47 +02:00
if ( ! this - > m_favoritesUpdated ) {
this - > m_favoritesUpdated = true ;
2023-06-24 16:40:34 +02:00
if ( ! this - > m_favorites . empty ( ) & & ! patterns . empty ( ) & & ! this - > m_favoritesUpdateTask . isRunning ( ) ) {
this - > m_favoritesUpdateTask = TaskManager : : createTask ( " hex.builtin.pattern_drawer.updating " _lang , TaskManager : : NoProgress , [ this , patterns ] ( auto & task ) {
size_t updatedFavorites = 0 ;
for ( auto & pattern : patterns ) {
if ( updatedFavorites = = this - > m_favorites . size ( ) )
task . interrupt ( ) ;
task . update ( ) ;
std : : vector < std : : string > patternPath ;
traversePatternTree ( * pattern , patternPath , [ & , this ] ( pl : : ptrn : : Pattern & pattern ) {
for ( auto & [ path , favoritePattern ] : this - > m_favorites ) {
if ( updatedFavorites = = this - > m_favorites . size ( ) )
task . interrupt ( ) ;
task . update ( ) ;
if ( this - > matchesFilter ( patternPath , path , true ) ) {
favoritePattern = pattern . clone ( ) ;
updatedFavorites + = 1 ;
break ;
}
}
} ) ;
2023-06-04 18:30:47 +02:00
}
2023-06-24 16:40:34 +02:00
std : : erase_if ( this - > m_favorites , [ ] ( const auto & entry ) {
const auto & [ path , favoritePattern ] = entry ;
return favoritePattern = = nullptr ;
} ) ;
2023-06-04 18:30:47 +02:00
} ) ;
}
}
2022-11-08 21:43:22 +01:00
if ( beginPatternTable ( patterns , this - > m_sortedPatterns , height ) ) {
ImGui : : TableHeadersRow ( ) ;
2023-06-04 18:30:47 +02:00
this - > m_showFavoriteStars = false ;
if ( ! this - > m_favorites . empty ( ) ) {
ImGui : : TableNextColumn ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : PushID ( 1 ) ;
2023-06-04 18:41:58 +02:00
if ( ImGui : : TreeNodeEx ( " hex.builtin.pattern_drawer.favorites " _lang , ImGuiTreeNodeFlags_SpanFullWidth ) ) {
2023-06-24 16:40:34 +02:00
if ( ! this - > m_favoritesUpdateTask . isRunning ( ) ) {
for ( auto & [ path , pattern ] : this - > m_favorites ) {
if ( pattern = = nullptr )
continue ;
ImGui : : PushID ( pattern - > getDisplayName ( ) . c_str ( ) ) ;
this - > draw ( * pattern ) ;
ImGui : : PopID ( ) ;
}
} else {
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : TextSpinner ( " hex.builtin.pattern_drawer.updating " _lang ) ;
2023-06-04 18:30:47 +02:00
}
ImGui : : TreePop ( ) ;
}
ImGui : : PopID ( ) ;
}
this - > m_showFavoriteStars = true ;
int id = 2 ;
2022-11-08 21:43:22 +01:00
for ( auto & pattern : this - > m_sortedPatterns ) {
2022-12-21 11:31:33 +01:00
ImGui : : PushID ( id ) ;
2022-11-08 21:43:22 +01:00
this - > draw ( * pattern ) ;
2022-12-16 11:20:39 +01:00
ImGui : : PopID ( ) ;
2022-12-21 11:31:33 +01:00
id + = 1 ;
2022-11-08 21:43:22 +01:00
}
ImGui : : EndTable ( ) ;
}
}
2023-01-24 23:27:15 +01:00
void PatternDrawer : : reset ( ) {
2023-01-28 00:03:20 +01:00
this - > resetEditing ( ) ;
2023-01-24 23:27:15 +01:00
this - > m_displayEnd . clear ( ) ;
this - > m_visualizedPatterns . clear ( ) ;
this - > m_currVisualizedPattern = nullptr ;
this - > m_sortedPatterns . clear ( ) ;
2023-01-25 10:16:31 +01:00
this - > m_lastVisualizerError . clear ( ) ;
2023-06-04 16:13:46 +02:00
this - > m_currPatternPath . clear ( ) ;
2023-06-04 18:30:47 +02:00
for ( auto & [ path , pattern ] : this - > m_favorites )
pattern = nullptr ;
this - > m_favoritesUpdated = false ;
2023-01-24 23:27:15 +01:00
}
2022-10-02 17:30:26 +02:00
}