2021-08-29 14:18:45 +02:00
# include <hex/api/content_registry.hpp>
2022-10-21 12:01:28 +02:00
# include <hex/api/imhex_api.hpp>
2022-07-02 16:22:38 +02:00
# include <hex/api/localization.hpp>
2021-06-07 18:13:54 +02:00
2022-05-27 20:42:07 +02:00
# include <hex/ui/view.hpp>
2021-08-29 22:15:18 +02:00
# include <hex/helpers/utils.hpp>
# include <hex/helpers/fmt.hpp>
2022-07-02 17:53:13 +02:00
# include <hex/helpers/logger.hpp>
2021-08-29 22:15:18 +02:00
2022-07-26 14:59:08 +02:00
# include <fonts/codicons_font.h>
2021-08-21 00:52:11 +02:00
# include <imgui.h>
# include <imgui_internal.h>
2021-12-31 01:10:06 +01:00
# include <hex/ui/imgui_imhex_extensions.h>
2021-08-21 00:52:11 +02:00
2021-06-07 18:13:54 +02:00
namespace hex : : plugin : : builtin {
2022-07-02 17:53:13 +02:00
static std : : string s_popupMessage ;
static std : : function < void ( ) > s_yesCallback , s_noCallback ;
2023-01-28 00:01:53 +01:00
static std : : set < u32 > s_selectableFileIndices ;
2022-07-02 17:53:13 +02:00
static std : : vector < std : : fs : : path > s_selectableFiles ;
static std : : function < void ( std : : fs : : path ) > s_selectableFileOpenCallback ;
static std : : vector < nfdfilteritem_t > s_selectableFilesValidExtensions ;
2023-01-28 00:01:53 +01:00
static bool s_selectableFileMultiple ;
2022-07-02 17:53:13 +02:00
2022-05-27 20:42:07 +02:00
static void drawGlobalPopups ( ) {
// "Are you sure you want to exit?" Popup
if ( ImGui : : BeginPopupModal ( " hex.builtin.popup.exit_application.title " _lang , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) ) {
ImGui : : NewLine ( ) ;
ImGui : : TextUnformatted ( " hex.builtin.popup.exit_application.desc " _lang ) ;
ImGui : : NewLine ( ) ;
2022-08-08 21:23:52 +02:00
View : : confirmButtons ( " hex.builtin.common.yes " _lang , " hex.builtin.common.no " _lang ,
2023-01-28 12:16:41 +01:00
[ ] {
ImHexApi : : Provider : : resetDirty ( ) ;
2023-03-21 15:33:43 +01:00
ImHexApi : : System : : closeImHex ( ) ;
2023-01-28 12:16:41 +01:00
} ,
[ ] { ImGui : : CloseCurrentPopup ( ) ; }
) ;
2022-08-08 21:23:52 +02:00
if ( ImGui : : IsKeyDown ( ImGui : : GetKeyIndex ( ImGuiKey_Escape ) ) )
ImGui : : CloseCurrentPopup ( ) ;
ImGui : : EndPopup ( ) ;
}
// "Are you sure you want to close provider?" Popup
if ( ImGui : : BeginPopupModal ( " hex.builtin.popup.close_provider.title " _lang , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) ) {
ImGui : : NewLine ( ) ;
ImGui : : TextUnformatted ( " hex.builtin.popup.close_provider.desc " _lang ) ;
ImGui : : NewLine ( ) ;
View : : confirmButtons ( " hex.builtin.common.yes " _lang , " hex.builtin.common.no " _lang ,
[ ] { ImHexApi : : Provider : : remove ( ImHexApi : : Provider : : impl : : getClosingProvider ( ) , true ) ; ImGui : : CloseCurrentPopup ( ) ; } ,
[ ] { ImGui : : CloseCurrentPopup ( ) ; }
) ;
2022-05-27 20:42:07 +02:00
if ( ImGui : : IsKeyDown ( ImGui : : GetKeyIndex ( ImGuiKey_Escape ) ) )
ImGui : : CloseCurrentPopup ( ) ;
ImGui : : EndPopup ( ) ;
}
2022-07-02 17:53:13 +02:00
2023-01-28 12:44:40 +01:00
if ( ImGui : : BeginPopupModal ( " hex.builtin.popup.waiting_for_tasks.title " _lang , nullptr , ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove ) ) {
2023-01-28 12:16:41 +01:00
ImGui : : TextUnformatted ( " hex.builtin.popup.waiting_for_tasks.desc " _lang ) ;
ImGui : : Separator ( ) ;
ImGui : : SetCursorPosX ( ( ImGui : : GetWindowWidth ( ) - ImGui : : CalcTextSize ( " [-] " ) . x ) / 2 ) ;
ImGui : : TextSpinner ( " " ) ;
ImGui : : NewLine ( ) ;
2023-01-28 14:36:39 +01:00
ImGui : : SetCursorPosX ( ( ImGui : : GetWindowWidth ( ) - 150 _scaled ) / 2 ) ;
if ( ImGui : : ButtonEx ( " hex.builtin.common.cancel " _lang , ImVec2 ( 150 , 0 ) ) | | ImGui : : IsKeyDown ( ImGuiKey_Escape ) )
ImGui : : CloseCurrentPopup ( ) ;
2023-01-28 12:16:41 +01:00
if ( TaskManager : : getRunningTaskCount ( ) = = 0 & & TaskManager : : getRunningBackgroundTaskCount ( ) = = 0 ) {
ImGui : : CloseCurrentPopup ( ) ;
2023-03-21 15:33:43 +01:00
ImHexApi : : System : : closeImHex ( ) ;
2023-01-28 12:16:41 +01:00
}
ImGui : : EndPopup ( ) ;
}
2022-07-02 17:53:13 +02:00
auto windowSize = ImHexApi : : System : : getMainWindowSize ( ) ;
// Info popup
ImGui : : SetNextWindowSizeConstraints ( scaled ( ImVec2 ( 400 , 100 ) ) , scaled ( ImVec2 ( 600 , 300 ) ) ) ;
if ( ImGui : : BeginPopupModal ( " hex.builtin.common.info " _lang , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) ) {
ImGui : : TextFormattedWrapped ( " {} " , s_popupMessage . c_str ( ) ) ;
ImGui : : NewLine ( ) ;
ImGui : : Separator ( ) ;
if ( ImGui : : Button ( " hex.builtin.common.okay " _lang ) | | ImGui : : IsKeyDown ( ImGuiKey_Escape ) )
ImGui : : CloseCurrentPopup ( ) ;
ImGui : : SetWindowPos ( ( windowSize - ImGui : : GetWindowSize ( ) ) / 2 , ImGuiCond_Appearing ) ;
ImGui : : EndPopup ( ) ;
}
// Error popup
ImGui : : SetNextWindowSizeConstraints ( scaled ( ImVec2 ( 400 , 100 ) ) , scaled ( ImVec2 ( 600 , 300 ) ) ) ;
if ( ImGui : : BeginPopupModal ( " hex.builtin.common.error " _lang , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) ) {
ImGui : : TextFormattedWrapped ( " {} " , s_popupMessage . c_str ( ) ) ;
ImGui : : NewLine ( ) ;
ImGui : : Separator ( ) ;
if ( ImGui : : Button ( " hex.builtin.common.okay " _lang ) | | ImGui : : IsKeyDown ( ImGuiKey_Escape ) )
ImGui : : CloseCurrentPopup ( ) ;
ImGui : : SetWindowPos ( ( windowSize - ImGui : : GetWindowSize ( ) ) / 2 , ImGuiCond_Appearing ) ;
ImGui : : EndPopup ( ) ;
}
// Fatal error popup
ImGui : : SetNextWindowSizeConstraints ( scaled ( ImVec2 ( 400 , 100 ) ) , scaled ( ImVec2 ( 600 , 300 ) ) ) ;
if ( ImGui : : BeginPopupModal ( " hex.builtin.common.fatal " _lang , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) ) {
ImGui : : TextFormattedWrapped ( " {} " , s_popupMessage . c_str ( ) ) ;
ImGui : : NewLine ( ) ;
ImGui : : Separator ( ) ;
if ( ImGui : : Button ( " hex.builtin.common.okay " _lang ) | | ImGui : : IsKeyDown ( ImGuiKey_Escape ) ) {
2023-03-21 15:33:43 +01:00
ImHexApi : : System : : closeImHex ( ) ;
2022-07-02 17:53:13 +02:00
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SetWindowPos ( ( windowSize - ImGui : : GetWindowSize ( ) ) / 2 , ImGuiCond_Appearing ) ;
ImGui : : EndPopup ( ) ;
}
// Yes/No question popup
ImGui : : SetNextWindowSizeConstraints ( scaled ( ImVec2 ( 400 , 100 ) ) , scaled ( ImVec2 ( 600 , 300 ) ) ) ;
if ( ImGui : : BeginPopupModal ( " hex.builtin.common.question " _lang , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) ) {
ImGui : : TextFormattedWrapped ( " {} " , s_popupMessage . c_str ( ) ) ;
ImGui : : NewLine ( ) ;
ImGui : : Separator ( ) ;
View : : confirmButtons (
" hex.builtin.common.yes " _lang , " hex.builtin.common.no " _lang , [ ] {
s_yesCallback ( ) ;
ImGui : : CloseCurrentPopup ( ) ; } , [ ] {
s_noCallback ( ) ;
ImGui : : CloseCurrentPopup ( ) ; } ) ;
ImGui : : SetWindowPos ( ( windowSize - ImGui : : GetWindowSize ( ) ) / 2 , ImGuiCond_Appearing ) ;
ImGui : : EndPopup ( ) ;
}
// File chooser popup
bool opened = true ;
ImGui : : SetNextWindowPos ( ImGui : : GetMainViewport ( ) - > GetCenter ( ) , ImGuiCond_Appearing , ImVec2 ( 0.5F , 0.5F ) ) ;
if ( ImGui : : BeginPopupModal ( " hex.builtin.common.choose_file " _lang , & opened , ImGuiWindowFlags_AlwaysAutoResize ) ) {
2023-01-28 14:28:06 +01:00
if ( ImGui : : BeginListBox ( " ##files " , scaled ( ImVec2 ( 500 , 400 ) ) ) ) {
2022-07-02 17:53:13 +02:00
u32 index = 0 ;
for ( auto & path : s_selectableFiles ) {
2022-07-07 23:29:50 +02:00
ImGui : : PushID ( index ) ;
2023-01-28 00:01:53 +01:00
bool selected = s_selectableFileIndices . contains ( index ) ;
2023-03-12 18:43:05 +01:00
if ( ImGui : : Selectable ( wolv : : util : : toUTF8String ( path . filename ( ) ) . c_str ( ) , selected ) ) {
2023-01-28 00:01:53 +01:00
if ( ! s_selectableFileMultiple ) {
s_selectableFileIndices . clear ( ) ;
s_selectableFileIndices . insert ( index ) ;
} else {
if ( selected ) {
s_selectableFileIndices . erase ( index ) ;
} else {
s_selectableFileIndices . insert ( index ) ;
}
}
}
2022-07-07 23:29:50 +02:00
ImGui : : PopID ( ) ;
2022-07-02 17:53:13 +02:00
index + + ;
}
ImGui : : EndListBox ( ) ;
}
if ( ImGui : : Button ( " hex.builtin.common.open " _lang ) ) {
2023-01-28 00:01:53 +01:00
for ( auto & index : s_selectableFileIndices )
s_selectableFileOpenCallback ( s_selectableFiles [ index ] ) ;
2022-07-02 17:53:13 +02:00
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " hex.builtin.common.browse " _lang ) ) {
fs : : openFileBrowser ( fs : : DialogMode : : Open , s_selectableFilesValidExtensions , [ ] ( const auto & path ) {
s_selectableFileOpenCallback ( path ) ;
ImGui : : CloseCurrentPopup ( ) ;
2023-01-28 00:01:53 +01:00
} , { } , s_selectableFileMultiple ) ;
2022-07-02 17:53:13 +02:00
}
ImGui : : EndPopup ( ) ;
}
2022-09-03 23:56:57 +02:00
// Task exception popup
for ( const auto & task : TaskManager : : getRunningTasks ( ) ) {
if ( task - > hadException ( ) ) {
EventManager : : post < RequestShowErrorPopup > ( hex : : format ( " hex.builtin.popup.error.task_exception " _lang , LangEntry ( task - > getUnlocalizedName ( ) ) , task - > getExceptionMessage ( ) ) ) ;
task - > clearException ( ) ;
break ;
}
}
2022-05-27 20:42:07 +02:00
}
void addGlobalUIItems ( ) {
EventManager : : subscribe < EventFrameEnd > ( drawGlobalPopups ) ;
2022-07-02 17:53:13 +02:00
EventManager : : subscribe < RequestShowInfoPopup > ( [ ] ( const std : : string & message ) {
s_popupMessage = message ;
2022-08-17 16:15:36 +02:00
TaskManager : : doLater ( [ ] { ImGui : : OpenPopup ( " hex.builtin.common.info " _lang ) ; } ) ;
2022-07-02 17:53:13 +02:00
} ) ;
EventManager : : subscribe < RequestShowErrorPopup > ( [ ] ( const std : : string & message ) {
s_popupMessage = message ;
2022-08-17 16:15:36 +02:00
TaskManager : : doLater ( [ ] { ImGui : : OpenPopup ( " hex.builtin.common.error " _lang ) ; } ) ;
2022-07-02 17:53:13 +02:00
} ) ;
EventManager : : subscribe < RequestShowFatalErrorPopup > ( [ ] ( const std : : string & message ) {
s_popupMessage = message ;
2022-08-17 16:15:36 +02:00
TaskManager : : doLater ( [ ] { ImGui : : OpenPopup ( " hex.builtin.common.fatal " _lang ) ; } ) ;
2022-07-02 17:53:13 +02:00
} ) ;
EventManager : : subscribe < RequestShowYesNoQuestionPopup > ( [ ] ( const std : : string & message , const std : : function < void ( ) > & yesCallback , const std : : function < void ( ) > & noCallback ) {
s_popupMessage = message ;
s_yesCallback = yesCallback ;
s_noCallback = noCallback ;
2022-08-17 16:15:36 +02:00
TaskManager : : doLater ( [ ] { ImGui : : OpenPopup ( " hex.builtin.common.question " _lang ) ; } ) ;
2022-07-02 17:53:13 +02:00
} ) ;
2023-01-28 00:01:53 +01:00
EventManager : : subscribe < RequestShowFileChooserPopup > ( [ ] ( const std : : vector < std : : fs : : path > & paths , const std : : vector < nfdfilteritem_t > & validExtensions , const std : : function < void ( std : : fs : : path ) > & callback , bool multiple ) {
s_selectableFileIndices = { } ;
2022-07-02 17:53:13 +02:00
s_selectableFiles = paths ;
2023-02-17 14:59:19 +01:00
std : : sort ( s_selectableFiles . begin ( ) , s_selectableFiles . end ( ) ,
[ ] ( const auto & a , const auto & b ) {
return a . filename ( ) < b . filename ( ) ;
}
) ;
2022-07-02 17:53:13 +02:00
s_selectableFilesValidExtensions = validExtensions ;
s_selectableFileOpenCallback = callback ;
2023-01-28 00:01:53 +01:00
s_selectableFileMultiple = multiple ;
2022-07-02 17:53:13 +02:00
2022-08-17 16:15:36 +02:00
TaskManager : : doLater ( [ ] { ImGui : : OpenPopup ( " hex.builtin.common.choose_file " _lang ) ; } ) ;
2022-07-02 17:53:13 +02:00
} ) ;
2022-05-27 20:42:07 +02:00
}
2021-06-07 18:13:54 +02:00
void addFooterItems ( ) {
2021-12-13 22:58:23 +01:00
if ( hex : : isProcessElevated ( ) ) {
ContentRegistry : : Interface : : addFooterItem ( [ ] {
ImGui : : TextUnformatted ( ICON_VS_SHIELD ) ;
} ) ;
}
2022-09-05 22:37:28 +02:00
# if defined(DEBUG)
ContentRegistry : : Interface : : addFooterItem ( [ ] {
static float framerate = 0 ;
if ( ImGui : : HasSecondPassed ( ) ) {
framerate = 1.0F / ImGui : : GetIO ( ) . DeltaTime ;
}
2021-06-07 18:13:54 +02:00
2022-09-05 22:37:28 +02:00
ImGui : : TextFormatted ( " FPS {0:2}.{1:02} " , u32 ( framerate ) , u32 ( framerate * 100 ) % 100 ) ;
} ) ;
# endif
2021-12-16 23:48:52 +01:00
ContentRegistry : : Interface : : addFooterItem ( [ ] {
2022-08-17 16:15:36 +02:00
auto taskCount = TaskManager : : getRunningTaskCount ( ) ;
if ( taskCount > 0 ) {
2023-01-24 14:59:19 +01:00
const auto & tasks = TaskManager : : getRunningTasks ( ) ;
2022-08-17 16:15:36 +02:00
auto frontTask = tasks . front ( ) ;
2021-12-16 23:48:52 +01:00
2023-01-24 13:42:08 +01:00
auto progress = frontTask - > getMaxValue ( ) = = 0 ? 1 : float ( frontTask - > getValue ( ) ) / frontTask - > getMaxValue ( ) ;
2023-01-14 14:21:16 +01:00
ImHexApi : : System : : setTaskBarProgress ( ImHexApi : : System : : TaskProgressState : : Progress , ImHexApi : : System : : TaskProgressType : : Normal , progress * 100 ) ;
2022-08-17 16:15:36 +02:00
auto widgetStart = ImGui : : GetCursorPos ( ) ;
2021-12-16 23:48:52 +01:00
2022-08-04 11:00:49 +02:00
ImGui : : TextSpinner ( hex : : format ( " ({}) " , taskCount ) . c_str ( ) ) ;
2022-08-17 16:15:36 +02:00
ImGui : : SameLine ( ) ;
2023-01-24 13:42:08 +01:00
ImGui : : SmallProgressBar ( progress , ( ImGui : : GetCurrentWindow ( ) - > MenuBarHeight ( ) - 10 _scaled ) / 2.0 ) ;
2022-08-17 16:15:36 +02:00
ImGui : : SameLine ( ) ;
auto widgetEnd = ImGui : : GetCursorPos ( ) ;
ImGui : : SetCursorPos ( widgetStart ) ;
ImGui : : InvisibleButton ( " FrontTask " , ImVec2 ( widgetEnd . x - widgetStart . x , ImGui : : GetCurrentWindow ( ) - > MenuBarHeight ( ) ) ) ;
ImGui : : SetCursorPos ( widgetEnd ) ;
ImGui : : InfoTooltip ( LangEntry ( frontTask - > getUnlocalizedName ( ) ) . get ( ) . c_str ( ) ) ;
if ( ImGui : : BeginPopupContextItem ( " FrontTask " , ImGuiPopupFlags_MouseButtonLeft ) ) {
for ( const auto & task : tasks ) {
2022-10-04 23:37:48 +02:00
if ( task - > isBackgroundTask ( ) )
continue ;
2022-08-17 16:15:36 +02:00
ImGui : : PushID ( & task ) ;
ImGui : : TextFormatted ( " {} " , LangEntry ( task - > getUnlocalizedName ( ) ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : SeparatorEx ( ImGuiSeparatorFlags_Vertical ) ;
ImGui : : SameLine ( ) ;
ImGui : : SmallProgressBar ( frontTask - > getMaxValue ( ) = = 0 ? 1 : ( float ( frontTask - > getValue ( ) ) / frontTask - > getMaxValue ( ) ) , ( ImGui : : GetTextLineHeightWithSpacing ( ) - 5 _scaled ) / 2 ) ;
ImGui : : SameLine ( ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_WindowPadding , ImVec2 ( 0 , 0 ) ) ;
if ( ImGui : : ToolBarButton ( ICON_VS_DEBUG_STOP , ImGui : : GetStyleColorVec4 ( ImGuiCol_Text ) ) )
task - > interrupt ( ) ;
ImGui : : PopStyleVar ( ) ;
ImGui : : PopID ( ) ;
}
ImGui : : EndPopup ( ) ;
}
2021-12-16 23:48:52 +01:00
ImGui : : SameLine ( ) ;
2022-08-17 16:15:36 +02:00
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , scaled ( ImVec2 ( 1 , 2 ) ) ) ;
if ( ImGui : : ToolBarButton ( ICON_VS_DEBUG_STOP , ImGui : : GetStyleColorVec4 ( ImGuiCol_Text ) ) )
frontTask - > interrupt ( ) ;
ImGui : : PopStyleVar ( ) ;
2023-01-14 14:21:16 +01:00
} else {
ImHexApi : : System : : setTaskBarProgress ( ImHexApi : : System : : TaskProgressState : : Reset , ImHexApi : : System : : TaskProgressType : : Normal , 0 ) ;
2021-12-16 23:48:52 +01:00
}
2021-06-07 18:13:54 +02:00
} ) ;
}
2021-08-21 00:52:11 +02:00
void addToolbarItems ( ) {
ContentRegistry : : Interface : : addToolbarItem ( [ ] {
2022-03-13 17:46:59 +01:00
auto provider = ImHexApi : : Provider : : get ( ) ;
bool providerValid = provider ! = nullptr ;
2022-08-17 16:15:36 +02:00
bool tasksRunning = TaskManager : : getRunningTaskCount ( ) > 0 ;
2021-08-21 13:53:50 +02:00
// Undo
2022-05-27 20:42:07 +02:00
ImGui : : BeginDisabled ( ! providerValid | | ! provider - > canUndo ( ) ) ;
{
2021-10-07 11:34:46 +02:00
if ( ImGui : : ToolBarButton ( ICON_VS_DISCARD , ImGui : : GetCustomColorVec4 ( ImGuiCustomCol_ToolbarBlue ) ) )
2021-08-21 13:53:50 +02:00
provider - > undo ( ) ;
2022-05-27 20:42:07 +02:00
}
ImGui : : EndDisabled ( ) ;
2021-08-21 13:53:50 +02:00
// Redo
2022-05-27 20:42:07 +02:00
ImGui : : BeginDisabled ( ! providerValid | | ! provider - > canRedo ( ) ) ;
{
2021-10-07 11:34:46 +02:00
if ( ImGui : : ToolBarButton ( ICON_VS_REDO , ImGui : : GetCustomColorVec4 ( ImGuiCustomCol_ToolbarBlue ) ) )
2021-08-21 13:53:50 +02:00
provider - > redo ( ) ;
2022-05-27 20:42:07 +02:00
}
ImGui : : EndDisabled ( ) ;
2021-08-21 00:52:11 +02:00
ImGui : : SeparatorEx ( ImGuiSeparatorFlags_Vertical ) ;
2022-07-29 11:35:29 +02:00
ImGui : : BeginDisabled ( tasksRunning ) ;
{
// Create new file
2022-10-21 12:01:28 +02:00
if ( ImGui : : ToolBarButton ( ICON_VS_FILE , ImGui : : GetCustomColorVec4 ( ImGuiCustomCol_ToolbarGray ) ) ) {
auto newProvider = hex : : ImHexApi : : Provider : : createProvider ( " hex.builtin.provider.mem_file " , true ) ;
if ( newProvider ! = nullptr & & ! newProvider - > open ( ) )
hex : : ImHexApi : : Provider : : remove ( newProvider ) ;
else
EventManager : : post < EventProviderOpened > ( newProvider ) ;
}
2021-08-21 13:53:50 +02:00
2022-07-29 11:35:29 +02:00
// Open file
if ( ImGui : : ToolBarButton ( ICON_VS_FOLDER_OPENED , ImGui : : GetCustomColorVec4 ( ImGuiCustomCol_ToolbarBrown ) ) )
EventManager : : post < RequestOpenWindow > ( " Open File " ) ;
}
ImGui : : EndDisabled ( ) ;
2021-08-21 00:52:11 +02:00
ImGui : : SeparatorEx ( ImGuiSeparatorFlags_Vertical ) ;
2021-08-21 13:53:50 +02:00
// Save file
2022-05-27 20:42:07 +02:00
ImGui : : BeginDisabled ( ! providerValid | | ! provider - > isWritable ( ) | | ! provider - > isSavable ( ) ) ;
{
2021-10-07 11:34:46 +02:00
if ( ImGui : : ToolBarButton ( ICON_VS_SAVE , ImGui : : GetCustomColorVec4 ( ImGuiCustomCol_ToolbarBlue ) ) )
2021-08-21 13:53:50 +02:00
provider - > save ( ) ;
2022-05-27 20:42:07 +02:00
}
ImGui : : EndDisabled ( ) ;
2021-08-21 13:53:50 +02:00
// Save file as
2022-05-27 20:42:07 +02:00
ImGui : : BeginDisabled ( ! providerValid | | ! provider - > isSavable ( ) ) ;
{
2021-10-07 11:34:46 +02:00
if ( ImGui : : ToolBarButton ( ICON_VS_SAVE_AS , ImGui : : GetCustomColorVec4 ( ImGuiCustomCol_ToolbarBlue ) ) )
2022-03-27 00:01:28 +01:00
fs : : openFileBrowser ( fs : : DialogMode : : Save , { } , [ & provider ] ( auto path ) {
2021-08-21 13:53:50 +02:00
provider - > saveAs ( path ) ;
} ) ;
2022-05-27 20:42:07 +02:00
}
ImGui : : EndDisabled ( ) ;
2021-08-21 13:53:50 +02:00
2021-08-21 00:52:11 +02:00
ImGui : : SeparatorEx ( ImGuiSeparatorFlags_Vertical ) ;
2021-08-21 13:53:50 +02:00
// Create bookmark
2022-05-27 20:42:07 +02:00
ImGui : : BeginDisabled ( ! providerValid | | ! provider - > isReadable ( ) | | ! ImHexApi : : HexEditor : : isSelectionValid ( ) ) ;
{
2021-10-07 11:34:46 +02:00
if ( ImGui : : ToolBarButton ( ICON_VS_BOOKMARK , ImGui : : GetCustomColorVec4 ( ImGuiCustomCol_ToolbarGreen ) ) ) {
2022-05-27 20:42:07 +02:00
auto region = ImHexApi : : HexEditor : : getSelection ( ) ;
2021-08-21 13:53:50 +02:00
2022-05-27 20:42:07 +02:00
if ( region . has_value ( ) )
2022-07-23 21:17:17 +02:00
ImHexApi : : Bookmarks : : add ( region - > getStartAddress ( ) , region - > getSize ( ) , { } , { } ) ;
2021-08-21 13:53:50 +02:00
}
2022-05-27 20:42:07 +02:00
}
ImGui : : EndDisabled ( ) ;
2021-09-21 02:29:54 +02:00
ImGui : : SeparatorEx ( ImGuiSeparatorFlags_Vertical ) ;
ImGui : : Spacing ( ) ;
2022-07-30 21:25:18 +02:00
ImGui : : Spacing ( ) ;
ImGui : : Spacing ( ) ;
2021-09-21 02:29:54 +02:00
// Provider switcher
2022-07-29 11:35:29 +02:00
ImGui : : BeginDisabled ( ! providerValid | | tasksRunning ) ;
2022-05-27 20:42:07 +02:00
{
2021-09-21 02:29:54 +02:00
auto & providers = ImHexApi : : Provider : : getProviders ( ) ;
2022-07-30 21:25:18 +02:00
ImGui : : PushStyleColor ( ImGuiCol_TabActive , ImGui : : GetColorU32 ( ImGuiCol_MenuBarBg ) ) ;
ImGui : : PushStyleColor ( ImGuiCol_TabUnfocusedActive , ImGui : : GetColorU32 ( ImGuiCol_MenuBarBg ) ) ;
2022-07-31 11:09:20 +02:00
auto providerSelectorVisible = ImGui : : BeginTabBar ( " provider_switcher " , ImGuiTabBarFlags_FittingPolicyScroll | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_AutoSelectNewTabs ) ;
2022-07-30 21:25:18 +02:00
ImGui : : PopStyleColor ( 2 ) ;
2021-09-21 02:29:54 +02:00
2022-07-30 21:25:18 +02:00
if ( providerSelectorVisible ) {
2022-03-27 00:01:28 +01:00
for ( size_t i = 0 ; i < providers . size ( ) ; i + + ) {
2022-07-31 10:55:10 +02:00
auto & tabProvider = providers [ i ] ;
2022-07-30 21:25:18 +02:00
bool open = true ;
2022-07-31 10:55:10 +02:00
ImGui : : PushID ( tabProvider ) ;
2022-08-14 19:11:49 +02:00
if ( ImGui : : BeginTabItem ( tabProvider - > getName ( ) . c_str ( ) , & open , tabProvider - > isDirty ( ) ? ImGuiTabItemFlags_UnsavedDocument : ImGuiTabItemFlags_None ) ) {
2022-02-01 18:09:40 +01:00
ImHexApi : : Provider : : setCurrentProvider ( i ) ;
2022-07-30 21:25:18 +02:00
ImGui : : EndTabItem ( ) ;
2021-09-21 02:29:54 +02:00
}
2022-07-31 10:55:10 +02:00
ImGui : : PopID ( ) ;
2021-09-21 02:29:54 +02:00
2022-07-30 21:25:18 +02:00
if ( ! open ) {
ImHexApi : : Provider : : remove ( providers [ i ] ) ;
break ;
}
}
ImGui : : EndTabBar ( ) ;
2021-09-21 02:29:54 +02:00
}
2022-05-27 20:42:07 +02:00
}
ImGui : : EndDisabled ( ) ;
2021-08-21 00:52:11 +02:00
} ) ;
}
2022-07-02 17:53:13 +02:00
void handleBorderlessWindowMode ( ) {
// Intel's OpenGL driver has weird bugs that cause the drawn window to be offset to the bottom right.
// This can be fixed by either using Mesa3D's OpenGL Software renderer or by simply disabling it.
// If you want to try if it works anyways on your GPU, set the hex.builtin.setting.interface.force_borderless_window_mode setting to 1
if ( ImHexApi : : System : : isBorderlessWindowModeEnabled ( ) ) {
bool isIntelGPU = hex : : containsIgnoreCase ( ImHexApi : : System : : getGPUVendor ( ) , " Intel " ) ;
ImHexApi : : System : : impl : : setBorderlessWindowMode ( ! isIntelGPU ) ;
if ( isIntelGPU )
log : : warn ( " Intel GPU detected! Intel's OpenGL driver has bugs that can cause issues when using ImHex. If you experience any rendering bugs, please try the Mesa3D Software Renderer " ) ;
}
}
2021-06-07 18:13:54 +02:00
}