2022-07-02 16:22:38 +02:00
# include <hex/api/imhex_api.hpp>
2021-08-29 14:18:45 +02:00
# include <hex/api/content_registry.hpp>
2023-11-21 14:38:01 +01:00
# include <hex/api/localization_manager.hpp>
2022-12-29 19:26:00 +01:00
# include <hex/api/theme_manager.hpp>
2023-11-18 14:50:43 +01:00
# include <hex/api/shortcut_manager.hpp>
# include <hex/api/event_manager.hpp>
2021-09-08 15:18:24 +02:00
2023-03-23 11:23:07 +01:00
# include <hex/helpers/http_requests.hpp>
2023-11-15 22:22:57 +01:00
# include <hex/helpers/utils.hpp>
2022-07-02 16:22:38 +02:00
2021-08-29 14:18:45 +02:00
# include <imgui.h>
2022-02-18 22:34:54 +01:00
# include <hex/ui/imgui_imhex_extensions.h>
# include <fonts/codicons_font.h>
2021-08-29 14:18:45 +02:00
# include <nlohmann/json.hpp>
2021-01-22 18:01:39 +01:00
2023-11-17 14:46:21 +01:00
# include <utility>
2023-12-06 13:49:58 +01:00
# include <hex/api/layout_manager.hpp>
2023-10-21 23:07:33 +02:00
# include <wolv/utils/string.hpp>
2022-07-14 11:38:23 +02:00
2021-01-22 18:01:39 +01:00
namespace hex : : plugin : : builtin {
2023-10-21 23:07:33 +02:00
namespace {
2023-03-14 14:07:18 +01:00
2023-06-20 11:55:56 +02:00
/*
2023-10-21 23:07:33 +02:00
Values of this setting :
2023-06-20 11:55:56 +02:00
0 - do not check for updates on startup
1 - check for updates on startup
2 - default value - ask the user if he wants to check for updates . This value should only be encountered on the first startup .
*/
2023-10-21 23:07:33 +02:00
class ServerContactWidget : public ContentRegistry : : Settings : : Widgets : : Widget {
public :
bool draw ( const std : : string & name ) override {
2023-12-19 13:10:25 +01:00
bool enabled = m_value = = 1 ;
2023-05-15 11:30:24 +02:00
2023-10-21 23:07:33 +02:00
if ( ImGui : : Checkbox ( name . data ( ) , & enabled ) ) {
2023-12-19 13:10:25 +01:00
m_value = enabled ? 1 : 0 ;
2023-10-21 23:07:33 +02:00
return true ;
2022-12-29 19:26:00 +01:00
}
2022-07-02 16:22:38 +02:00
2023-10-21 23:07:33 +02:00
return false ;
2021-02-10 18:17:09 +01:00
}
2023-10-21 23:07:33 +02:00
void load ( const nlohmann : : json & data ) override {
if ( data . is_number ( ) )
2023-12-19 13:10:25 +01:00
m_value = data . get < int > ( ) ;
2023-10-21 23:07:33 +02:00
}
2021-08-21 13:55:21 +02:00
2023-10-21 23:07:33 +02:00
nlohmann : : json store ( ) override {
2023-12-19 13:10:25 +01:00
return m_value ;
2023-10-21 23:07:33 +02:00
}
2021-08-21 13:55:21 +02:00
2023-10-21 23:07:33 +02:00
private :
u32 m_value = 2 ;
} ;
class FPSWidget : public ContentRegistry : : Settings : : Widgets : : Widget {
public :
bool draw ( const std : : string & name ) override {
auto format = [ this ] - > std : : string {
2023-12-19 13:10:25 +01:00
if ( m_value > 200 )
2023-10-21 23:07:33 +02:00
return " hex.builtin.setting.interface.fps.unlocked " _lang ;
2023-12-19 13:10:25 +01:00
else if ( m_value < 15 )
2023-10-21 23:07:33 +02:00
return " hex.builtin.setting.interface.fps.native " _lang ;
else
return " %d FPS " ;
} ( ) ;
2023-12-19 13:10:25 +01:00
if ( ImGui : : SliderInt ( name . data ( ) , & m_value , 14 , 201 , format . c_str ( ) , ImGuiSliderFlags_AlwaysClamp ) ) {
2022-02-21 21:46:25 +01:00
return true ;
}
2021-08-21 13:55:21 +02:00
2022-02-21 21:46:25 +01:00
return false ;
2021-02-10 18:17:09 +01:00
}
2023-10-21 23:07:33 +02:00
void load ( const nlohmann : : json & data ) override {
if ( data . is_number ( ) )
2023-12-19 13:10:25 +01:00
m_value = data . get < int > ( ) ;
2022-05-22 23:26:46 +02:00
}
2023-10-21 23:07:33 +02:00
nlohmann : : json store ( ) override {
2023-12-19 13:10:25 +01:00
return m_value ;
2021-03-06 13:09:20 +01:00
}
2023-10-21 23:07:33 +02:00
private :
int m_value = 60 ;
} ;
2021-03-06 13:09:20 +01:00
2023-10-21 23:07:33 +02:00
class UserFolderWidget : public ContentRegistry : : Settings : : Widgets : : Widget {
public :
bool draw ( const std : : string & ) override {
bool result = false ;
2022-10-06 21:26:24 +02:00
2023-11-15 22:22:57 +01:00
if ( ! ImGui : : BeginListBox ( " " , ImVec2 ( - 40 _scaled , 280 _scaled ) ) ) {
2023-10-21 23:07:33 +02:00
return false ;
} else {
2023-12-19 13:10:25 +01:00
for ( size_t n = 0 ; n < m_paths . size ( ) ; n + + ) {
const bool isSelected = ( m_itemIndex = = n ) ;
if ( ImGui : : Selectable ( wolv : : util : : toUTF8String ( m_paths [ n ] ) . c_str ( ) , isSelected ) ) {
m_itemIndex = n ;
2023-10-21 23:07:33 +02:00
}
if ( isSelected ) {
ImGui : : SetItemDefaultFocus ( ) ;
}
}
ImGui : : EndListBox ( ) ;
}
ImGui : : SameLine ( ) ;
ImGui : : BeginGroup ( ) ;
2022-10-06 21:26:24 +02:00
2023-11-16 22:24:06 +01:00
if ( ImGuiExt : : IconButton ( ICON_VS_NEW_FOLDER , ImGui : : GetStyleColorVec4 ( ImGuiCol_Text ) , ImVec2 ( 30 , 30 ) ) ) {
2023-10-21 23:07:33 +02:00
fs : : openFileBrowser ( fs : : DialogMode : : Folder , { } , [ & ] ( const std : : fs : : path & path ) {
2023-12-19 13:10:25 +01:00
if ( std : : find ( m_paths . begin ( ) , m_paths . end ( ) , path ) = = m_paths . end ( ) ) {
m_paths . emplace_back ( path ) ;
ImHexApi : : System : : setAdditionalFolderPaths ( m_paths ) ;
2022-10-06 21:26:24 +02:00
2023-10-21 23:07:33 +02:00
result = true ;
}
} ) ;
}
2023-11-16 22:24:06 +01:00
ImGuiExt : : InfoTooltip ( " hex.builtin.setting.folders.add_folder " _lang ) ;
2022-05-27 20:42:07 +02:00
2023-11-16 22:24:06 +01:00
if ( ImGuiExt : : IconButton ( ICON_VS_REMOVE_CLOSE , ImGui : : GetStyleColorVec4 ( ImGuiCol_Text ) , ImVec2 ( 30 , 30 ) ) ) {
2023-12-19 13:10:25 +01:00
if ( ! m_paths . empty ( ) ) {
m_paths . erase ( std : : next ( m_paths . begin ( ) , m_itemIndex ) ) ;
ImHexApi : : System : : setAdditionalFolderPaths ( m_paths ) ;
2022-05-27 20:42:07 +02:00
2023-10-21 23:07:33 +02:00
result = true ;
}
}
2023-11-16 22:24:06 +01:00
ImGuiExt : : InfoTooltip ( " hex.builtin.setting.folders.remove_folder " _lang ) ;
2022-05-27 20:42:07 +02:00
2023-10-21 23:07:33 +02:00
ImGui : : EndGroup ( ) ;
2021-03-29 23:07:18 +02:00
2023-10-21 23:07:33 +02:00
return result ;
2021-03-29 23:07:18 +02:00
}
2023-10-21 23:07:33 +02:00
void load ( const nlohmann : : json & data ) override {
if ( data . is_array ( ) ) {
std : : vector < std : : string > pathStrings = data ;
2022-09-18 16:22:08 +02:00
2023-10-21 23:07:33 +02:00
for ( const auto & pathString : pathStrings ) {
2023-12-19 13:10:25 +01:00
m_paths . emplace_back ( pathString ) ;
2023-10-21 23:07:33 +02:00
}
2024-02-17 21:30:23 +01:00
ImHexApi : : System : : setAdditionalFolderPaths ( m_paths ) ;
2023-10-21 23:07:33 +02:00
}
2022-09-18 16:22:08 +02:00
}
2023-10-21 23:07:33 +02:00
nlohmann : : json store ( ) override {
std : : vector < std : : string > pathStrings ;
2022-09-18 16:22:08 +02:00
2023-12-19 13:10:25 +01:00
for ( const auto & path : m_paths ) {
2023-10-21 23:07:33 +02:00
pathStrings . push_back ( wolv : : util : : toUTF8String ( path ) ) ;
}
2022-10-07 11:28:44 +02:00
2023-10-21 23:07:33 +02:00
return pathStrings ;
2022-10-07 11:28:44 +02:00
}
2023-10-21 23:07:33 +02:00
private :
u32 m_itemIndex = 0 ;
std : : vector < std : : fs : : path > m_paths ;
} ;
class ScalingWidget : public ContentRegistry : : Settings : : Widgets : : Widget {
public :
bool draw ( const std : : string & name ) override {
auto format = [ this ] - > std : : string {
2023-12-19 13:10:25 +01:00
if ( m_value = = 0 )
2024-01-03 18:26:48 +01:00
return " hex.builtin.setting.interface.scaling.native " _lang + hex : : format ( " (x{:.1f}) " , ImHexApi : : System : : getNativeScale ( ) ) ;
2023-12-11 11:42:33 +01:00
else
return " x%.1f " ;
2023-10-21 23:07:33 +02:00
} ( ) ;
2023-12-19 13:10:25 +01:00
if ( ImGui : : SliderFloat ( name . data ( ) , & m_value , 0 , 10 , format . c_str ( ) , ImGuiSliderFlags_AlwaysClamp ) ) {
2023-10-21 23:07:33 +02:00
return true ;
}
2022-10-07 11:28:44 +02:00
2023-10-21 23:07:33 +02:00
return false ;
2022-10-07 11:28:44 +02:00
}
2023-10-21 23:07:33 +02:00
void load ( const nlohmann : : json & data ) override {
if ( data . is_number ( ) )
2023-12-19 13:10:25 +01:00
m_value = data . get < float > ( ) ;
2023-10-21 23:07:33 +02:00
}
2023-07-31 11:17:37 +02:00
2023-10-21 23:07:33 +02:00
nlohmann : : json store ( ) override {
2023-12-19 13:10:25 +01:00
return m_value ;
2023-07-31 11:17:37 +02:00
}
2023-10-21 23:07:33 +02:00
private :
float m_value = 0 ;
} ;
2023-07-31 11:17:37 +02:00
2023-12-11 11:42:33 +01:00
class AutoBackupWidget : public ContentRegistry : : Settings : : Widgets : : Widget {
public :
bool draw ( const std : : string & name ) override {
auto format = [ this ] - > std : : string {
2023-12-19 13:10:25 +01:00
auto value = m_value * 30 ;
2023-12-11 11:42:33 +01:00
if ( value = = 0 )
2023-12-23 21:09:41 +01:00
return " hex.ui.common.off " _lang ;
2023-12-11 11:42:33 +01:00
else if ( value < 60 )
return hex : : format ( " hex.builtin.setting.general.auto_backup_time.format.simple " _lang , value ) ;
else
return hex : : format ( " hex.builtin.setting.general.auto_backup_time.format.extended " _lang , value / 60 , value % 60 ) ;
} ( ) ;
2023-12-19 13:10:25 +01:00
if ( ImGui : : SliderInt ( name . data ( ) , & m_value , 0 , ( 30 * 60 ) / 30 , format . c_str ( ) , ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_NoInput ) ) {
2023-12-11 11:42:33 +01:00
return true ;
}
return false ;
}
void load ( const nlohmann : : json & data ) override {
if ( data . is_number ( ) )
2023-12-19 13:10:25 +01:00
m_value = data . get < int > ( ) ;
2023-12-11 11:42:33 +01:00
}
nlohmann : : json store ( ) override {
2023-12-19 13:10:25 +01:00
return m_value ;
2023-12-11 11:42:33 +01:00
}
private :
int m_value = 0 ;
} ;
2023-11-17 14:46:21 +01:00
class KeybindingWidget : public ContentRegistry : : Settings : : Widgets : : Widget {
public :
2023-12-06 09:09:32 +01:00
KeybindingWidget ( View * view , const Shortcut & shortcut ) : m_view ( view ) , m_shortcut ( shortcut ) , m_drawShortcut ( shortcut ) , m_defaultShortcut ( shortcut ) { }
2023-11-17 14:46:21 +01:00
bool draw ( const std : : string & name ) override {
std : : string label ;
2023-12-19 13:10:25 +01:00
if ( ! m_editing )
label = m_drawShortcut . toString ( ) ;
2023-11-17 14:46:21 +01:00
else
label = " ... " ;
if ( label . empty ( ) )
label = " ??? " ;
2023-11-18 14:34:33 +01:00
2023-12-19 13:10:25 +01:00
if ( m_hasDuplicate )
2023-11-18 14:34:33 +01:00
ImGui : : PushStyleColor ( ImGuiCol_Text , ImGuiExt : : GetCustomColorVec4 ( ImGuiCustomCol_LoggerError ) ) ;
2023-11-17 14:46:21 +01:00
ImGui : : PushID ( this ) ;
2023-11-18 14:34:33 +01:00
if ( ImGui : : Button ( label . c_str ( ) , ImVec2 ( 250 _scaled , 0 ) ) ) {
2023-12-19 13:10:25 +01:00
m_editing = ! m_editing ;
2023-11-17 14:46:21 +01:00
2023-12-19 13:10:25 +01:00
if ( m_editing )
2023-11-17 14:46:21 +01:00
ShortcutManager : : pauseShortcuts ( ) ;
else
ShortcutManager : : resumeShortcuts ( ) ;
}
2023-11-18 14:34:33 +01:00
ImGui : : SameLine ( ) ;
2023-12-19 13:10:25 +01:00
if ( m_hasDuplicate )
2023-11-18 14:34:33 +01:00
ImGui : : PopStyleColor ( ) ;
2023-11-19 18:22:57 +01:00
bool settingChanged = false ;
2023-12-19 13:10:25 +01:00
ImGui : : BeginDisabled ( m_drawShortcut = = m_defaultShortcut ) ;
2023-11-18 14:34:33 +01:00
if ( ImGuiExt : : IconButton ( ICON_VS_X , ImGui : : GetStyleColorVec4 ( ImGuiCol_Text ) ) ) {
2023-12-19 13:10:25 +01:00
m_hasDuplicate = ! ShortcutManager : : updateShortcut ( m_shortcut , m_defaultShortcut , m_view ) ;
2023-11-19 18:22:57 +01:00
2023-12-19 13:10:25 +01:00
m_drawShortcut = m_defaultShortcut ;
if ( ! m_hasDuplicate ) {
m_shortcut = m_defaultShortcut ;
2023-12-06 09:09:32 +01:00
settingChanged = true ;
}
2023-11-18 14:34:33 +01:00
}
ImGui : : EndDisabled ( ) ;
2023-11-17 14:46:21 +01:00
if ( ! ImGui : : IsItemHovered ( ) & & ImGui : : IsMouseClicked ( ImGuiMouseButton_Left ) ) {
2023-12-19 13:10:25 +01:00
m_editing = false ;
2023-11-17 14:46:21 +01:00
ShortcutManager : : resumeShortcuts ( ) ;
}
ImGui : : SameLine ( ) ;
ImGuiExt : : TextFormatted ( " {} " , name ) ;
2023-11-18 14:34:33 +01:00
ImGui : : PopID ( ) ;
2023-12-19 13:10:25 +01:00
if ( m_editing ) {
2023-11-17 14:46:21 +01:00
if ( this - > detectShortcut ( ) ) {
2023-12-19 13:10:25 +01:00
m_editing = false ;
2023-11-17 14:46:21 +01:00
ShortcutManager : : resumeShortcuts ( ) ;
2023-12-06 09:09:32 +01:00
settingChanged = true ;
2023-12-19 13:10:25 +01:00
if ( ! m_hasDuplicate ) {
2023-12-06 09:09:32 +01:00
}
2023-11-17 14:46:21 +01:00
}
}
2023-11-19 18:22:57 +01:00
return settingChanged ;
2023-11-17 14:46:21 +01:00
}
void load ( const nlohmann : : json & data ) override {
std : : set < Key > keys ;
for ( const auto & key : data . get < std : : vector < u32 > > ( ) )
keys . insert ( Key ( Keys ( key ) ) ) ;
if ( keys . empty ( ) )
return ;
auto newShortcut = Shortcut ( keys ) ;
2023-12-19 13:10:25 +01:00
m_hasDuplicate = ! ShortcutManager : : updateShortcut ( m_shortcut , newShortcut , m_view ) ;
m_shortcut = std : : move ( newShortcut ) ;
m_drawShortcut = m_shortcut ;
2023-11-17 14:46:21 +01:00
}
nlohmann : : json store ( ) override {
std : : vector < u32 > keys ;
2023-12-19 13:10:25 +01:00
for ( const auto & key : m_shortcut . getKeys ( ) ) {
2023-11-17 14:46:21 +01:00
if ( key ! = CurrentView )
keys . push_back ( key . getKeyCode ( ) ) ;
}
return keys ;
}
private :
bool detectShortcut ( ) {
2023-11-24 20:17:01 +01:00
if ( const auto & shortcut = ShortcutManager : : getPreviousShortcut ( ) ; shortcut . has_value ( ) ) {
2023-12-19 13:10:25 +01:00
auto keys = m_shortcut . getKeys ( ) ;
2023-11-17 14:46:21 +01:00
std : : erase_if ( keys , [ ] ( Key key ) {
return key ! = AllowWhileTyping & & key ! = CurrentView ;
} ) ;
for ( const auto & key : shortcut - > getKeys ( ) ) {
keys . insert ( key ) ;
}
auto newShortcut = Shortcut ( std : : move ( keys ) ) ;
2023-12-19 13:10:25 +01:00
m_hasDuplicate = ! ShortcutManager : : updateShortcut ( m_shortcut , newShortcut , m_view ) ;
m_drawShortcut = std : : move ( newShortcut ) ;
2023-11-17 14:46:21 +01:00
2023-12-19 13:10:25 +01:00
if ( ! m_hasDuplicate ) {
m_shortcut = m_drawShortcut ;
2023-12-06 09:09:32 +01:00
log : : info ( " Changed shortcut to {} " , shortcut - > toString ( ) ) ;
} else {
log : : warn ( " Changing shortcut failed as it overlapped with another one " , shortcut - > toString ( ) ) ;
2023-11-24 20:17:01 +01:00
}
2023-12-06 09:09:32 +01:00
return true ;
2023-11-17 14:46:21 +01:00
}
return false ;
}
private :
View * m_view = nullptr ;
2023-12-06 09:09:32 +01:00
Shortcut m_shortcut , m_drawShortcut , m_defaultShortcut ;
2023-11-17 14:46:21 +01:00
bool m_editing = false ;
2023-11-18 14:34:33 +01:00
bool m_hasDuplicate = false ;
2023-11-17 14:46:21 +01:00
} ;
2024-01-21 18:39:32 +01:00
class ToolbarIconsWidget : public ContentRegistry : : Settings : : Widgets : : Widget {
private :
struct MenuItemSorter {
bool operator ( ) ( const auto * a , const auto * b ) const {
return a - > toolbarIndex < b - > toolbarIndex ;
}
} ;
public :
bool draw ( const std : : string & ) override {
bool changed = false ;
// Top level layout table
if ( ImGui : : BeginTable ( " ##top_level " , 2 , ImGuiTableFlags_None , ImGui : : GetContentRegionAvail ( ) ) ) {
ImGui : : TableSetupColumn ( " ##left " , ImGuiTableColumnFlags_WidthStretch , 0.3F ) ;
ImGui : : TableSetupColumn ( " ##right " , ImGuiTableColumnFlags_WidthStretch , 0.7F ) ;
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
// Draw list of menu items that can be added to the toolbar
if ( ImGui : : BeginTable ( " ##all_icons " , 1 , ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY , ImVec2 ( 0 , 280 _scaled ) ) ) {
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
// Loop over all available menu items
for ( auto & [ priority , menuItem ] : ContentRegistry : : Interface : : impl : : getMenuItems ( ) ) {
// Filter out items without icon, separators, submenus and items that are already in the toolbar
if ( menuItem . icon . glyph . empty ( ) )
continue ;
const auto & unlocalizedName = menuItem . unlocalizedNames . back ( ) ;
if ( menuItem . unlocalizedNames . size ( ) > 2 )
continue ;
if ( unlocalizedName . get ( ) = = ContentRegistry : : Interface : : impl : : SeparatorValue )
continue ;
if ( unlocalizedName . get ( ) = = ContentRegistry : : Interface : : impl : : SubMenuValue )
continue ;
if ( menuItem . toolbarIndex ! = - 1 )
continue ;
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
// Draw the menu item
ImGui : : Selectable ( hex : : format ( " {} {} " , menuItem . icon . glyph , Lang ( unlocalizedName ) ) . c_str ( ) , false , ImGuiSelectableFlags_SpanAllColumns ) ;
// Handle draggin the menu item to the toolbar box
if ( ImGui : : BeginDragDropSource ( ) ) {
auto ptr = & menuItem ;
ImGui : : SetDragDropPayload ( " MENU_ITEM_PAYLOAD " , & ptr , sizeof ( void * ) ) ;
ImGuiExt : : TextFormatted ( " {} {} " , menuItem . icon . glyph , Lang ( unlocalizedName ) ) ;
ImGui : : EndDragDropSource ( ) ;
}
}
ImGui : : EndTable ( ) ;
}
// Handle dropping menu items from the toolbar box
if ( ImGui : : BeginDragDropTarget ( ) ) {
if ( auto payload = ImGui : : AcceptDragDropPayload ( " TOOLBAR_ITEM_PAYLOAD " ) ; payload ! = nullptr ) {
auto & menuItem = * static_cast < ContentRegistry : : Interface : : impl : : MenuItem * * > ( payload - > Data ) ;
menuItem - > toolbarIndex = - 1 ;
changed = true ;
}
ImGui : : EndDragDropTarget ( ) ;
}
ImGui : : TableNextColumn ( ) ;
// Draw toolbar icon box
ImGuiExt : : BeginSubWindow ( " hex.builtin.setting.toolbar.icons " _lang , ImGui : : GetContentRegionAvail ( ) ) ;
{
if ( ImGui : : BeginTable ( " ##icons " , 6 , ImGuiTableFlags_SizingStretchSame , ImGui : : GetContentRegionAvail ( ) ) ) {
ImGui : : TableNextRow ( ) ;
// Find all menu items that are in the toolbar and sort them by their toolbar index
std : : set < ContentRegistry : : Interface : : impl : : MenuItem * , MenuItemSorter > toolbarItems ;
2024-02-10 23:31:05 +01:00
for ( auto & [ priority , menuItem ] : ContentRegistry : : Interface : : impl : : getMenuItemsMutable ( ) ) {
2024-01-21 18:39:32 +01:00
if ( menuItem . toolbarIndex = = - 1 )
continue ;
toolbarItems . emplace ( & menuItem ) ;
}
// Loop over all toolbar items
for ( auto & menuItem : toolbarItems ) {
// Filter out items without icon, separators, submenus and items that are not in the toolbar
if ( menuItem - > icon . glyph . empty ( ) )
continue ;
const auto & unlocalizedName = menuItem - > unlocalizedNames . back ( ) ;
if ( menuItem - > unlocalizedNames . size ( ) > 2 )
continue ;
if ( unlocalizedName . get ( ) = = ContentRegistry : : Interface : : impl : : SubMenuValue )
continue ;
if ( menuItem - > toolbarIndex = = - 1 )
continue ;
ImGui : : TableNextColumn ( ) ;
// Draw the toolbar item
ImGui : : InvisibleButton ( unlocalizedName . get ( ) . c_str ( ) , ImVec2 ( ImGui : : GetContentRegionAvail ( ) . x , ImGui : : GetContentRegionAvail ( ) . x ) ) ;
// Handle dragging the toolbar item around
if ( ImGui : : BeginDragDropSource ( ) ) {
ImGui : : SetDragDropPayload ( " TOOLBAR_ITEM_PAYLOAD " , & menuItem , sizeof ( void * ) ) ;
ImGuiExt : : TextFormatted ( " {} {} " , menuItem - > icon . glyph , Lang ( unlocalizedName ) ) ;
ImGui : : EndDragDropSource ( ) ;
}
// Handle dropping toolbar items onto each other to reorder them
if ( ImGui : : BeginDragDropTarget ( ) ) {
if ( auto payload = ImGui : : AcceptDragDropPayload ( " TOOLBAR_ITEM_PAYLOAD " ) ; payload ! = nullptr ) {
auto & otherMenuItem = * static_cast < ContentRegistry : : Interface : : impl : : MenuItem * * > ( payload - > Data ) ;
std : : swap ( menuItem - > toolbarIndex , otherMenuItem - > toolbarIndex ) ;
changed = true ;
}
ImGui : : EndDragDropTarget ( ) ;
}
// Handle right clicking toolbar items to open the color selection popup
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) )
ImGui : : OpenPopup ( unlocalizedName . get ( ) . c_str ( ) ) ;
// Draw the color selection popup
if ( ImGui : : BeginPopup ( unlocalizedName . get ( ) . c_str ( ) ) ) {
constexpr static std : : array Colors = {
ImGuiCustomCol_ToolbarGray ,
ImGuiCustomCol_ToolbarRed ,
ImGuiCustomCol_ToolbarYellow ,
ImGuiCustomCol_ToolbarGreen ,
ImGuiCustomCol_ToolbarBlue ,
ImGuiCustomCol_ToolbarPurple ,
ImGuiCustomCol_ToolbarBrown
} ;
// Draw all the color buttons
for ( auto color : Colors ) {
ImGui : : PushID ( & color ) ;
if ( ImGui : : ColorButton ( hex : : format ( " ##color{} " , u32 ( color ) ) . c_str ( ) , ImGuiExt : : GetCustomColorVec4 ( color ) , ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker , ImVec2 ( 20 , 20 ) ) ) {
menuItem - > icon . color = color ;
ImGui : : CloseCurrentPopup ( ) ;
changed = true ;
}
ImGui : : PopID ( ) ;
ImGui : : SameLine ( ) ;
}
ImGui : : EndPopup ( ) ;
}
auto min = ImGui : : GetItemRectMin ( ) ;
auto max = ImGui : : GetItemRectMax ( ) ;
auto iconSize = ImGui : : CalcTextSize ( menuItem - > icon . glyph . c_str ( ) ) ;
auto text = Lang ( unlocalizedName ) . get ( ) ;
if ( text . ends_with ( " ... " ) )
text = text . substr ( 0 , text . size ( ) - 3 ) ;
auto textSize = ImGui : : CalcTextSize ( text . c_str ( ) ) ;
// Draw icon and text of the toolbar item
auto drawList = ImGui : : GetWindowDrawList ( ) ;
drawList - > AddText ( ( min + ( ( max - min ) - iconSize ) / 2 ) - ImVec2 ( 0 , 10 _scaled ) , ImGuiExt : : GetCustomColorU32 ( ImGuiCustomCol ( menuItem - > icon . color ) ) , menuItem - > icon . glyph . c_str ( ) ) ;
drawList - > AddText ( ( min + ( ( max - min ) ) / 2 ) + ImVec2 ( - textSize . x / 2 , 5 _scaled ) , ImGui : : GetColorU32 ( ImGuiCol_Text ) , text . c_str ( ) ) ;
}
ImGui : : EndTable ( ) ;
}
}
ImGuiExt : : EndSubWindow ( ) ;
// Handle dropping menu items onto the toolbar box
if ( ImGui : : BeginDragDropTarget ( ) ) {
if ( auto payload = ImGui : : AcceptDragDropPayload ( " MENU_ITEM_PAYLOAD " ) ; payload ! = nullptr ) {
auto & menuItem = * static_cast < ContentRegistry : : Interface : : impl : : MenuItem * * > ( payload - > Data ) ;
menuItem - > toolbarIndex = m_currIndex ;
m_currIndex + = 1 ;
changed = true ;
}
ImGui : : EndDragDropTarget ( ) ;
}
ImGui : : EndTable ( ) ;
}
return changed ;
}
nlohmann : : json store ( ) override {
std : : map < i32 , std : : pair < std : : string , u32 > > items ;
for ( const auto & [ priority , menuItem ] : ContentRegistry : : Interface : : impl : : getMenuItems ( ) ) {
if ( menuItem . toolbarIndex ! = - 1 )
items . emplace ( menuItem . toolbarIndex , std : : make_pair ( menuItem . unlocalizedNames . back ( ) . get ( ) , menuItem . icon . color ) ) ;
}
return items ;
}
void load ( const nlohmann : : json & data ) override {
if ( data . is_null ( ) )
return ;
auto toolbarItems = data . get < std : : map < i32 , std : : pair < std : : string , u32 > > > ( ) ;
if ( toolbarItems . empty ( ) )
return ;
2024-02-10 23:31:05 +01:00
for ( auto & [ priority , menuItem ] : ContentRegistry : : Interface : : impl : : getMenuItemsMutable ( ) )
2024-01-21 18:39:32 +01:00
menuItem . toolbarIndex = - 1 ;
2024-02-10 23:31:05 +01:00
for ( auto & [ priority , menuItem ] : ContentRegistry : : Interface : : impl : : getMenuItemsMutable ( ) ) {
2024-01-21 18:39:32 +01:00
for ( const auto & [ index , value ] : toolbarItems ) {
const auto & [ name , color ] = value ;
if ( menuItem . unlocalizedNames . back ( ) . get ( ) = = name ) {
menuItem . toolbarIndex = index ;
menuItem . icon . color = ImGuiCustomCol ( color ) ;
break ;
}
}
}
m_currIndex = toolbarItems . size ( ) ;
}
private :
i32 m_currIndex = 0 ;
} ;
2024-02-24 22:46:52 +01:00
class FontFilePicker : public ContentRegistry : : Settings : : Widgets : : FilePicker {
public :
bool draw ( const std : : string & name ) {
bool changed = false ;
const auto & fonts = hex : : getFonts ( ) ;
bool customFont = false ;
std : : string pathPreview = " " ;
if ( m_path . empty ( ) ) {
pathPreview = " Default Font " ;
} else if ( fonts . contains ( m_path ) ) {
pathPreview = fonts . at ( m_path ) ;
} else {
pathPreview = wolv : : util : : toUTF8String ( m_path . filename ( ) ) ;
customFont = true ;
}
if ( ImGui : : BeginCombo ( name . c_str ( ) , pathPreview . c_str ( ) ) ) {
if ( ImGui : : Selectable ( " Default Font " , m_path . empty ( ) ) ) {
m_path . clear ( ) ;
changed = true ;
}
if ( ImGui : : Selectable ( " Custom Font " , customFont ) ) {
changed = fs : : openFileBrowser ( fs : : DialogMode : : Open , { { " TTF Font " , " ttf " } , { " OTF Font " , " otf " } } , [ this ] ( const std : : fs : : path & path ) {
m_path = path ;
} ) ;
}
for ( const auto & [ path , fontName ] : fonts ) {
if ( ImGui : : Selectable ( fontName . c_str ( ) , m_path = = path ) ) {
m_path = path ;
changed = true ;
}
}
ImGui : : EndCombo ( ) ;
}
return changed ;
}
} ;
2024-02-11 14:12:14 +01:00
bool getDefaultBorderlessWindowMode ( ) {
bool result = false ;
# if defined (OS_WINDOWS) || defined(OS_MACOS)
result = true ;
# endif
// 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 ( ) ) {
const bool isIntelGPU = hex : : containsIgnoreCase ( ImHexApi : : System : : getGPUVendor ( ) , " Intel " ) ;
result = ! 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 " ) ;
}
return result ;
}
2023-10-21 23:07:33 +02:00
}
2022-02-21 21:46:25 +01:00
2023-10-21 23:07:33 +02:00
void registerSettings ( ) {
namespace Widgets = ContentRegistry : : Settings : : Widgets ;
2022-02-21 21:46:25 +01:00
2024-02-10 23:31:05 +01:00
/* General */
{
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.general " , " " , " hex.builtin.setting.general.show_tips " , false ) ;
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.general " , " " , " hex.builtin.setting.general.save_recent_providers " , true ) ;
ContentRegistry : : Settings : : add < AutoBackupWidget > ( " hex.builtin.setting.general " , " " , " hex.builtin.setting.general.auto_backup_time " ) ;
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.general " , " hex.builtin.setting.general.patterns " , " hex.builtin.setting.general.auto_load_patterns " , true ) ;
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.general " , " hex.builtin.setting.general.patterns " , " hex.builtin.setting.general.sync_pattern_source " , false ) ;
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.general " , " hex.builtin.setting.general.network " , " hex.builtin.setting.general.network_interface " , false ) ;
# if !defined(OS_WEB)
ContentRegistry : : Settings : : add < ServerContactWidget > ( " hex.builtin.setting.general " , " hex.builtin.setting.general.network " , " hex.builtin.setting.general.server_contact " ) ;
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.general " , " hex.builtin.setting.general.network " , " hex.builtin.setting.general.upload_crash_logs " , true ) ;
# endif
}
2022-02-21 21:46:25 +01:00
2023-10-21 23:07:33 +02:00
/* Interface */
2024-02-10 23:31:05 +01:00
{
auto themeNames = ThemeManager : : getThemeNames ( ) ;
std : : vector < nlohmann : : json > themeJsons = { } ;
for ( const auto & themeName : themeNames )
themeJsons . emplace_back ( themeName ) ;
themeNames . emplace ( themeNames . begin ( ) , ThemeManager : : NativeTheme ) ;
themeJsons . emplace ( themeJsons . begin ( ) , ThemeManager : : NativeTheme ) ;
ContentRegistry : : Settings : : add < Widgets : : DropDown > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.style " , " hex.builtin.setting.interface.color " ,
themeNames ,
themeJsons ,
" Dark " ) . setChangedCallback ( [ ] ( auto & widget ) {
auto dropDown = static_cast < Widgets : : DropDown * > ( & widget ) ;
if ( dropDown - > getValue ( ) = = ThemeManager : : NativeTheme )
ImHexApi : : System : : enableSystemThemeDetection ( true ) ;
else {
ImHexApi : : System : : enableSystemThemeDetection ( false ) ;
ThemeManager : : changeTheme ( dropDown - > getValue ( ) ) ;
}
} ) ;
ContentRegistry : : Settings : : add < ScalingWidget > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.style " , " hex.builtin.setting.interface.scaling_factor " ) . requiresRestart ( ) ;
# if defined (OS_WEB)
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.style " , " hex.builtin.setting.interface.crisp_scaling " , false )
. setChangedCallback ( [ ] ( Widgets : : Widget & widget ) {
auto checkBox = static_cast < Widgets : : Checkbox * > ( & widget ) ;
EM_ASM ( {
var canvas = document . getElementById ( ' canvas ' ) ;
if ( $ 0 )
canvas . style . imageRendering = ' pixelated ' ;
else
canvas . style . imageRendering = ' smooth ' ;
} , checkBox - > isChecked ( ) ) ;
} ) ;
# endif
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.style " , " hex.builtin.setting.interface.pattern_data_row_bg " , false ) ;
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.style " , " hex.builtin.setting.interface.always_show_provider_tabs " , false ) ;
2024-02-18 22:45:52 +01:00
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.style " , " hex.builtin.setting.interface.show_header_command_palette " , true ) ;
2024-02-10 23:31:05 +01:00
std : : vector < std : : string > languageNames ;
std : : vector < nlohmann : : json > languageCodes ;
for ( auto & [ languageCode , languageName ] : LocalizationManager : : getSupportedLanguages ( ) ) {
languageNames . emplace_back ( languageName ) ;
languageCodes . emplace_back ( languageCode ) ;
}
2022-02-21 21:46:25 +01:00
2024-02-10 23:31:05 +01:00
ContentRegistry : : Settings : : add < Widgets : : DropDown > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.language " , " hex.builtin.setting.interface.language " , languageNames , languageCodes , " en-US " ) ;
2022-02-21 21:46:25 +01:00
2024-02-10 23:31:05 +01:00
ContentRegistry : : Settings : : add < Widgets : : TextBox > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.language " , " hex.builtin.setting.interface.wiki_explain_language " , " en " ) ;
ContentRegistry : : Settings : : add < FPSWidget > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.window " , " hex.builtin.setting.interface.fps " ) ;
2023-11-25 13:42:51 +01:00
2024-02-10 23:31:05 +01:00
# if defined (OS_LINUX)
constexpr static auto MultiWindowSupportEnabledDefault = 0 ;
# else
constexpr static auto MultiWindowSupportEnabledDefault = 1 ;
# endif
2022-02-21 21:46:25 +01:00
2024-02-10 23:31:05 +01:00
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.window " , " hex.builtin.setting.interface.multi_windows " , MultiWindowSupportEnabledDefault ) . requiresRestart ( ) ;
2024-02-11 14:12:14 +01:00
# if !defined(OS_WEB)
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.window " , " hex.builtin.setting.interface.native_window_decorations " , ! getDefaultBorderlessWindowMode ( ) ) . requiresRestart ( ) ;
# endif
2024-02-10 23:31:05 +01:00
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.window " , " hex.builtin.setting.interface.restore_window_pos " , false ) ;
2022-02-21 21:46:25 +01:00
2024-02-10 23:31:05 +01:00
ContentRegistry : : Settings : : add < Widgets : : ColorPicker > ( " hex.builtin.setting.hex_editor " , " " , " hex.builtin.setting.hex_editor.highlight_color " , ImColor ( 0x80 , 0x80 , 0xC0 , 0x60 ) ) ;
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.hex_editor " , " " , " hex.builtin.setting.hex_editor.sync_scrolling " , false ) ;
ContentRegistry : : Settings : : add < Widgets : : SliderInteger > ( " hex.builtin.setting.hex_editor " , " " , " hex.builtin.setting.hex_editor.byte_padding " , 0 , 0 , 50 ) ;
ContentRegistry : : Settings : : add < Widgets : : SliderInteger > ( " hex.builtin.setting.hex_editor " , " " , " hex.builtin.setting.hex_editor.char_padding " , 0 , 0 , 50 ) ;
2024-02-11 14:12:14 +01:00
2024-02-25 14:30:56 +01:00
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.hex_editor " , " " , " hex.builtin.setting.hex_editor.pattern_parent_highlighting " , true ) ;
2024-02-11 14:12:14 +01:00
2023-10-21 23:07:33 +02:00
}
2022-02-21 21:46:25 +01:00
2023-10-21 23:07:33 +02:00
/* Fonts */
2024-02-10 23:31:05 +01:00
{
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.font " , " hex.builtin.setting.font.glyphs " , " hex.builtin.setting.font.load_all_unicode_chars " , false )
. requiresRestart ( ) ;
2023-11-24 11:29:05 +01:00
2024-02-10 23:31:05 +01:00
auto customFontEnabledSetting = ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.font " , " hex.builtin.setting.font.custom_font " , " hex.builtin.setting.font.custom_font_enable " , false ) . requiresRestart ( ) ;
2023-12-09 12:14:45 +01:00
2024-02-10 23:31:05 +01:00
const auto customFontsEnabled = [ customFontEnabledSetting ] {
auto & customFontsEnabled = static_cast < Widgets : : Checkbox & > ( customFontEnabledSetting . getWidget ( ) ) ;
2023-12-09 12:14:45 +01:00
2024-02-10 23:31:05 +01:00
return customFontsEnabled . isChecked ( ) ;
} ;
2023-12-09 12:14:45 +01:00
2024-02-24 22:46:52 +01:00
auto customFontPathSetting = ContentRegistry : : Settings : : add < FontFilePicker > ( " hex.builtin.setting.font " , " hex.builtin.setting.font.custom_font " , " hex.builtin.setting.font.font_path " )
2024-02-10 23:31:05 +01:00
. requiresRestart ( )
. setEnabledCallback ( customFontsEnabled ) ;
2023-12-09 12:14:45 +01:00
2024-02-10 23:31:05 +01:00
const auto customFontSettingsEnabled = [ customFontEnabledSetting , customFontPathSetting ] {
auto & customFontsEnabled = static_cast < Widgets : : Checkbox & > ( customFontEnabledSetting . getWidget ( ) ) ;
auto & fontPath = static_cast < Widgets : : FilePicker & > ( customFontPathSetting . getWidget ( ) ) ;
2022-07-14 11:38:23 +02:00
2024-02-10 23:31:05 +01:00
return customFontsEnabled . isChecked ( ) & & ! fontPath . getPath ( ) . empty ( ) ;
} ;
2022-02-18 22:34:54 +01:00
2024-02-10 23:31:05 +01:00
ContentRegistry : : Settings : : add < Widgets : : Label > ( " hex.builtin.setting.font " , " hex.builtin.setting.font.custom_font " , " hex.builtin.setting.font.custom_font_info " )
. setEnabledCallback ( customFontsEnabled ) ;
ContentRegistry : : Settings : : add < Widgets : : SliderInteger > ( " hex.builtin.setting.font " , " hex.builtin.setting.font.custom_font " , " hex.builtin.setting.font.font_size " , 13 , 0 , 100 )
. requiresRestart ( )
. setEnabledCallback ( customFontSettingsEnabled ) ;
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.font " , " hex.builtin.setting.font.custom_font " , " hex.builtin.setting.font.font_bold " , false )
. requiresRestart ( )
. setEnabledCallback ( customFontSettingsEnabled ) ;
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.font " , " hex.builtin.setting.font.custom_font " , " hex.builtin.setting.font.font_italic " , false )
. requiresRestart ( )
. setEnabledCallback ( customFontSettingsEnabled ) ;
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.font " , " hex.builtin.setting.font.custom_font " , " hex.builtin.setting.font.font_antialias " , true )
. requiresRestart ( )
. setEnabledCallback ( customFontSettingsEnabled ) ;
}
2022-07-02 17:53:13 +02:00
2023-10-21 23:07:33 +02:00
/* Folders */
2024-02-10 23:31:05 +01:00
{
ContentRegistry : : Settings : : setCategoryDescription ( " hex.builtin.setting.folders " , " hex.builtin.setting.folders.description " ) ;
ContentRegistry : : Settings : : add < UserFolderWidget > ( " hex.builtin.setting.folders " , " " , " hex.builtin.setting.folders.description " ) ;
}
2022-07-01 14:05:32 +02:00
/* Proxy */
2024-02-10 23:31:05 +01:00
{
HttpRequest : : setProxyUrl ( ContentRegistry : : Settings : : read < std : : string > ( " hex.builtin.setting.proxy " , " hex.builtin.setting.proxy.url " , " " ) ) ;
2022-07-01 14:05:32 +02:00
2024-02-10 23:31:05 +01:00
ContentRegistry : : Settings : : setCategoryDescription ( " hex.builtin.setting.proxy " , " hex.builtin.setting.proxy.description " ) ;
2022-07-01 14:05:32 +02:00
2024-02-10 23:31:05 +01:00
auto proxyEnabledSetting = ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.proxy " , " " , " hex.builtin.setting.proxy.enable " , false )
. setChangedCallback ( [ ] ( Widgets : : Widget & widget ) {
auto checkBox = static_cast < Widgets : : Checkbox * > ( & widget ) ;
2022-07-01 14:05:32 +02:00
2024-02-10 23:31:05 +01:00
HttpRequest : : setProxyState ( checkBox - > isChecked ( ) ) ;
} ) ;
2022-07-01 14:05:32 +02:00
2024-02-10 23:31:05 +01:00
ContentRegistry : : Settings : : add < Widgets : : TextBox > ( " hex.builtin.setting.proxy " , " " , " hex.builtin.setting.proxy.url " , " " )
. setEnabledCallback ( [ proxyEnabledSetting ] {
auto & checkBox = static_cast < Widgets : : Checkbox & > ( proxyEnabledSetting . getWidget ( ) ) ;
2022-07-01 14:05:32 +02:00
2024-02-10 23:31:05 +01:00
return checkBox . isChecked ( ) ;
} )
. setChangedCallback ( [ ] ( Widgets : : Widget & widget ) {
auto textBox = static_cast < Widgets : : TextBox * > ( & widget ) ;
2023-11-10 20:47:08 +01:00
2024-02-10 23:31:05 +01:00
HttpRequest : : setProxyUrl ( textBox - > getValue ( ) ) ;
} ) ;
}
2023-11-10 20:47:08 +01:00
/* Experiments */
2024-02-10 23:31:05 +01:00
{
ContentRegistry : : Settings : : setCategoryDescription ( " hex.builtin.setting.experiments " , " hex.builtin.setting.experiments.description " ) ;
EventImHexStartupFinished : : subscribe ( [ ] {
for ( const auto & [ name , experiment ] : ContentRegistry : : Experiments : : impl : : getExperiments ( ) ) {
ContentRegistry : : Settings : : add < Widgets : : Checkbox > ( " hex.builtin.setting.experiments " , " " , experiment . unlocalizedName , false )
2023-11-21 14:38:01 +01:00
. setTooltip ( Lang ( experiment . unlocalizedDescription ) )
2023-11-10 20:47:08 +01:00
. setChangedCallback ( [ name ] ( Widgets : : Widget & widget ) {
auto checkBox = static_cast < Widgets : : Checkbox * > ( & widget ) ;
ContentRegistry : : Experiments : : enableExperiement ( name , checkBox - > isChecked ( ) ) ;
} ) ;
2024-02-10 23:31:05 +01:00
}
} ) ;
}
2023-11-10 20:47:08 +01:00
2023-11-17 14:46:21 +01:00
/* Shorcuts */
2024-02-10 23:31:05 +01:00
{
EventImHexStartupFinished : : subscribe ( [ ] {
for ( const auto & shortcutEntry : ShortcutManager : : getGlobalShortcuts ( ) ) {
ContentRegistry : : Settings : : add < KeybindingWidget > ( " hex.builtin.setting.shortcuts " , " hex.builtin.setting.shortcuts.global " , shortcutEntry . unlocalizedName , nullptr , shortcutEntry . shortcut ) ;
}
2023-11-17 14:46:21 +01:00
2024-02-10 23:31:05 +01:00
for ( auto & [ viewName , view ] : ContentRegistry : : Views : : impl : : getEntries ( ) ) {
for ( const auto & shortcutEntry : ShortcutManager : : getViewShortcuts ( view . get ( ) ) ) {
ContentRegistry : : Settings : : add < KeybindingWidget > ( " hex.builtin.setting.shortcuts " , viewName , shortcutEntry . unlocalizedName , view . get ( ) , shortcutEntry . shortcut ) ;
}
2023-11-17 14:46:21 +01:00
}
2024-02-10 23:31:05 +01:00
} ) ;
}
2023-11-17 14:46:21 +01:00
2024-02-10 23:31:05 +01:00
/* Toolbar icons */
{
ContentRegistry : : Settings : : setCategoryDescription ( " hex.builtin.setting.toolbar " , " hex.builtin.setting.toolbar.description " ) ;
2024-01-21 18:39:32 +01:00
2024-02-10 23:31:05 +01:00
ContentRegistry : : Settings : : add < ToolbarIconsWidget > ( " hex.builtin.setting.toolbar " , " " , " hex.builtin.setting.toolbar.icons " ) ;
}
2024-01-21 18:39:32 +01:00
2021-01-22 18:01:39 +01:00
}
2023-12-06 13:49:58 +01:00
static void loadLayoutSettings ( ) {
2024-02-03 12:16:36 +01:00
const bool locked = ContentRegistry : : Settings : : read < bool > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.layout_locked " , false ) ;
2023-12-06 13:49:58 +01:00
LayoutManager : : lockLayout ( locked ) ;
}
2022-07-02 16:22:38 +02:00
static void loadThemeSettings ( ) {
2024-02-03 12:16:36 +01:00
auto theme = ContentRegistry : : Settings : : read < std : : string > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.color " , ThemeManager : : NativeTheme ) ;
2022-07-02 16:22:38 +02:00
2023-12-27 16:33:49 +01:00
if ( theme = = ThemeManager : : NativeTheme ) {
2022-12-29 19:26:00 +01:00
ImHexApi : : System : : enableSystemThemeDetection ( true ) ;
2023-12-27 16:33:49 +01:00
} else {
2022-12-29 19:26:00 +01:00
ImHexApi : : System : : enableSystemThemeDetection ( false ) ;
2023-03-23 20:35:16 +01:00
ThemeManager : : changeTheme ( theme ) ;
2022-12-29 19:26:00 +01:00
}
2024-02-11 14:12:14 +01:00
auto borderlessWindowMode = ! ContentRegistry : : Settings : : read < bool > ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.native_window_decorations " , ! getDefaultBorderlessWindowMode ( ) ) ;
ImHexApi : : System : : impl : : setBorderlessWindowMode ( borderlessWindowMode ) ;
2022-07-02 16:22:38 +02:00
}
2023-10-21 23:07:33 +02:00
static void loadFolderSettings ( ) {
2024-02-03 12:16:36 +01:00
auto folderPathStrings = ContentRegistry : : Settings : : read < std : : vector < std : : string > > ( " hex.builtin.setting.folders " , " hex.builtin.setting.folders " , { } ) ;
2023-10-21 23:07:33 +02:00
std : : vector < std : : fs : : path > paths ;
for ( const auto & pathString : folderPathStrings ) {
paths . emplace_back ( pathString ) ;
}
2023-03-21 15:33:43 +01:00
2023-10-21 23:07:33 +02:00
ImHexApi : : System : : setAdditionalFolderPaths ( paths ) ;
2022-07-14 11:38:23 +02:00
}
2022-07-02 16:22:38 +02:00
void loadSettings ( ) {
2023-12-06 13:49:58 +01:00
loadLayoutSettings ( ) ;
2022-07-02 16:22:38 +02:00
loadThemeSettings ( ) ;
2023-10-21 23:07:33 +02:00
loadFolderSettings ( ) ;
2022-07-02 16:22:38 +02:00
}
2022-02-18 22:34:54 +01:00
}