diff --git a/shared/comctl/src/cpl.c b/shared/comctl/src/cpl.c index 99b46e3..f03b712 100644 --- a/shared/comctl/src/cpl.c +++ b/shared/comctl/src/cpl.c @@ -25,7 +25,7 @@ void wintc_ctl_cpl_notebook_append_page_from_resource( // wintc_lc_builder_preprocess_widget_text(builder); - box_page = GTK_WIDGET(gtk_builder_get_object(builder, "page-box")); + box_page = GTK_WIDGET(gtk_builder_get_object(builder, "page")); label_title = GTK_WIDGET(gtk_builder_get_object(builder, "label-title")); gtk_notebook_append_page( diff --git a/shared/comgtk/CMakeLists.txt b/shared/comgtk/CMakeLists.txt index 71d6787..e415e3c 100644 --- a/shared/comgtk/CMakeLists.txt +++ b/shared/comgtk/CMakeLists.txt @@ -33,6 +33,8 @@ configure_file(src/version.c.in ${PROJECT_ROOT}/src/version.c @ONLY) add_library( libwintc-comgtk + src/accelerator.c + public/accelerator.h src/application.c public/application.h public/assets.h diff --git a/shared/comgtk/public/accelerator.h b/shared/comgtk/public/accelerator.h new file mode 100644 index 0000000..d1b7133 --- /dev/null +++ b/shared/comgtk/public/accelerator.h @@ -0,0 +1,41 @@ +/** @file */ + +#ifndef __COMGTK_ACCELERATOR_H__ +#define __COMGTK_ACCELERATOR_H__ + +#include +#include + +// +// PUBLIC STRUCTURES +// + +/** + * Convenience structure for defining accelerators for use with + * wintc_application_set_accelerators. + */ +typedef struct _WinTCAccelEntry +{ + const gchar* action_name; + const gchar* accelerator[2]; +} WinTCAccelEntry; + +// +// PUBLIC FUNCTIONS +// + +/** + * Convenience function for setting up many accelerators at once with + * gtk_application_set_accels_for_action(). + * + * @param application The application. + * @param accelerators The array of accelerator entries. + * @param n_accelerators The number of accelerators in the array. + */ +void wintc_application_set_accelerators( + GtkApplication* application, + const WinTCAccelEntry* accelerators, + guint n_accelerators +); + +#endif diff --git a/shared/comgtk/public/libapi.h.in b/shared/comgtk/public/libapi.h.in index ba983dd..93820d1 100644 --- a/shared/comgtk/public/libapi.h.in +++ b/shared/comgtk/public/libapi.h.in @@ -1,6 +1,7 @@ #ifndef __WINTC_COMGTK_H__ #define __WINTC_COMGTK_H__ +#include "@LIB_HEADER_DIR@/accelerator.h" #include "@LIB_HEADER_DIR@/application.h" #include "@LIB_HEADER_DIR@/assets.h" #include "@LIB_HEADER_DIR@/builder.h" diff --git a/shared/comgtk/src/accelerator.c b/shared/comgtk/src/accelerator.c new file mode 100644 index 0000000..3ac93f9 --- /dev/null +++ b/shared/comgtk/src/accelerator.c @@ -0,0 +1,23 @@ +#include +#include + +#include "../public/accelerator.h" + +// +// PUBLIC FUNCTIONS +// +void wintc_application_set_accelerators( + GtkApplication* application, + const WinTCAccelEntry* accelerators, + guint n_accelerators +) +{ + for (guint i = 0; i < n_accelerators; i++) + { + gtk_application_set_accels_for_action( + application, + accelerators[i].action_name, + accelerators[i].accelerator + ); + } +} diff --git a/shared/comgtk/src/builder.c b/shared/comgtk/src/builder.c index e0c6111..359a591 100644 --- a/shared/comgtk/src/builder.c +++ b/shared/comgtk/src/builder.c @@ -12,9 +12,9 @@ void wintc_builder_get_objects( ... ) { - va_list ap; - GtkWidget** next_dst; - gchar* next_name; + va_list ap; + GObject** next_dst; + gchar* next_name; va_start(ap, builder); @@ -22,8 +22,8 @@ void wintc_builder_get_objects( while (next_name) { - next_dst = va_arg(ap, GtkWidget**); - *next_dst = GTK_WIDGET(gtk_builder_get_object(builder, next_name)); + next_dst = va_arg(ap, GObject**); + *next_dst = gtk_builder_get_object(builder, next_name); next_name = va_arg(ap, gchar*); } diff --git a/shell/cpl/desk/src/res/page-appearance.ui b/shell/cpl/desk/src/res/page-appearance.ui index 7c9517d..b483d01 100644 --- a/shell/cpl/desk/src/res/page-appearance.ui +++ b/shell/cpl/desk/src/res/page-appearance.ui @@ -6,7 +6,7 @@ True Appearance - + True False vertical diff --git a/shell/cpl/desk/src/res/page-desktop.ui b/shell/cpl/desk/src/res/page-desktop.ui index 9bc237c..5f8b172 100644 --- a/shell/cpl/desk/src/res/page-desktop.ui +++ b/shell/cpl/desk/src/res/page-desktop.ui @@ -29,7 +29,7 @@ True Desktop - + True False vertical diff --git a/shell/cpl/desk/src/res/page-scrnsave.ui b/shell/cpl/desk/src/res/page-scrnsave.ui index 40156ba..e4039e3 100644 --- a/shell/cpl/desk/src/res/page-scrnsave.ui +++ b/shell/cpl/desk/src/res/page-scrnsave.ui @@ -6,7 +6,7 @@ True Screen Saver - + True False vertical diff --git a/shell/cpl/desk/src/res/page-settings.ui b/shell/cpl/desk/src/res/page-settings.ui index f4e1b17..3d3f571 100644 --- a/shell/cpl/desk/src/res/page-settings.ui +++ b/shell/cpl/desk/src/res/page-settings.ui @@ -6,7 +6,7 @@ True Settings - + True False vertical diff --git a/shell/cpl/desk/src/res/page-themes.ui b/shell/cpl/desk/src/res/page-themes.ui index 3730cdf..ac00034 100644 --- a/shell/cpl/desk/src/res/page-themes.ui +++ b/shell/cpl/desk/src/res/page-themes.ui @@ -6,7 +6,7 @@ True Themes - + True False vertical diff --git a/tools/resvwr/CMakeLists.txt b/tools/resvwr/CMakeLists.txt new file mode 100644 index 0000000..3aebaf5 --- /dev/null +++ b/tools/resvwr/CMakeLists.txt @@ -0,0 +1,90 @@ +cmake_minimum_required(VERSION 3.5) + +project( + wintc-resvwr + VERSION 1.0 + DESCRIPTION "Windows Total Conversion resource viewer tool." + LANGUAGES C +) + +set(PROJECT_ANYARCH false) +set(PROJECT_FREESTATUS true) +set(PROJECT_MAINTAINER "Rory Fewell ") + +set(PROJECT_ROOT ${CMAKE_CURRENT_LIST_DIR}) + +include(GNUInstallDirs) + +include(../../packaging/cmake-inc/common/CMakeLists.txt) +include(../../packaging/cmake-inc/linking/CMakeLists.txt) +include(../../packaging/cmake-inc/packaging/CMakeLists.txt) +include(../../packaging/cmake-inc/resources/CMakeLists.txt) + +wintc_resolve_library(glib-2.0 GLIB) +wintc_resolve_library(gtk+-3.0 GTK3) +wintc_resolve_library(wintc-comctl WINTC_COMCTL) +wintc_resolve_library(wintc-comgtk WINTC_COMGTK) +wintc_resolve_library(wintc-shcommon WINTC_SHCOMMON) +wintc_resolve_library(wintc-shlang WINTC_SHLANG) + +wintc_compile_resources() + +add_executable( + wintc-resvwr + src/application.c + src/application.h + src/main.c + src/resources.c + src/window.c + src/window.h +) + +target_compile_options( + wintc-resvwr + PRIVATE ${WINTC_COMPILE_OPTIONS} +) + +target_include_directories( + wintc-resvwr + SYSTEM + PRIVATE ${GLIB_INCLUDE_DIRS} + PRIVATE ${GTK3_INCLUDE_DIRS} + PRIVATE ${WINTC_COMCTL_INCLUDE_DIRS} + PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS} + PRIVATE ${WINTC_SHCOMMON_INCLUDE_DIRS} + PRIVATE ${WINTC_SHLANG_INCLUDE_DIRS} +) + +target_link_directories( + wintc-resvwr + PRIVATE ${GLIB_LIBRARY_DIRS} + PRIVATE ${GTK3_LIBRARY_DIRS} + PRIVATE ${WINTC_COMCTL_LIBRARY_DIRS} + PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS} + PRIVATE ${WINTC_SHCOMMON_LIBRARY_DIRS} + PRIVATE ${WINTC_SHLANG_LIBRARY_DIRS} +) + +target_link_libraries( + wintc-resvwr + PRIVATE ${GLIB_LIBRARIES} + PRIVATE ${GTK3_LIBRARIES} + PRIVATE ${WINTC_COMCTL_LIBRARIES} + PRIVATE ${WINTC_COMGTK_LIBRARIES} + PRIVATE ${WINTC_SHCOMMON_LIBRARIES} + PRIVATE ${WINTC_SHLANG_LIBRARIES} +) + +# Installation +# +wintc_configure_and_install_packaging() +wintc_install_icons_into_package() + +install( + FILES wintc-resvwr.desktop + DESTINATION share/applications +) +install( + TARGETS wintc-resvwr + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/tools/resvwr/README.MD b/tools/resvwr/README.MD new file mode 100644 index 0000000..a853740 --- /dev/null +++ b/tools/resvwr/README.MD @@ -0,0 +1,20 @@ +# Resource Viewer +This directory contains the source code for the *Resource Viewer* tool. + +![image](https://github.com/user-attachments/assets/a2c67868-29d2-4f4d-9b47-fa7b6723307f) + +## Installation +This tool must be compiled before it can be used. Build, package, and install it the same way you would with any other program in this repo, eg: +``` +(in the /packaging dir) +./build.sh tools/resvwr +./package.sh tools/resvwr +sudo dpkg -i local-out/wintc-resvwr.deb +``` + +Adjust the `dpkg` command to whatever the package manager is on your distro (eg. for Fedora do `sudo dnf install ./local-out/wintc-resvwr.rpm`) + +# Usage +The tool allows you to view most of the GTK builder XML resources in this project. Some of course require custom widgets which may not be available. + +It's a viewer only, to aid with development. It is not a fully featured editor like Glade. diff --git a/tools/resvwr/deps b/tools/resvwr/deps new file mode 100644 index 0000000..3f751a1 --- /dev/null +++ b/tools/resvwr/deps @@ -0,0 +1,5 @@ +bt,rt:glib2 +bt,rt:gtk3 +bt,rt:wintc-comctl +bt,rt:wintc-comgtk +bt,rt:wintc-shlang diff --git a/tools/resvwr/icons/16x16/wintc-resvwr.png b/tools/resvwr/icons/16x16/wintc-resvwr.png new file mode 100644 index 0000000..06234ed Binary files /dev/null and b/tools/resvwr/icons/16x16/wintc-resvwr.png differ diff --git a/tools/resvwr/icons/32x32/wintc-resvwr.png b/tools/resvwr/icons/32x32/wintc-resvwr.png new file mode 100644 index 0000000..04cb48a Binary files /dev/null and b/tools/resvwr/icons/32x32/wintc-resvwr.png differ diff --git a/tools/resvwr/src/application.c b/tools/resvwr/src/application.c new file mode 100644 index 0000000..5a64c03 --- /dev/null +++ b/tools/resvwr/src/application.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include + +#include "application.h" +#include "window.h" + +// +// FORWARD DECLARATIONS +// +static void wintc_resvwr_application_activate( + GApplication* application +); +static void wintc_resvwr_application_startup( + GApplication* application +); + +// +// STATIC DATA +// +static const WinTCAccelEntry S_ACCELS[] = { + { + "win.open", + { + "O", + NULL + } + }, + { + "win.refresh", + { + "F5", + NULL + } + }, + { + "win.exit", + { + "F4", + NULL + } + } +}; + +// +// GTK OOP CLASS/INSTANCE DEFINITIONS +// +typedef struct _WinTCResvwrApplication +{ + GtkApplication __parent__; +} WinTCResvwrApplication; + +// +// GTK TYPE DEFINITIONS & CTORS +// +G_DEFINE_TYPE( + WinTCResvwrApplication, + wintc_resvwr_application, + GTK_TYPE_APPLICATION +) + +static void wintc_resvwr_application_class_init( + WinTCResvwrApplicationClass* klass +) +{ + GApplicationClass* application_class = G_APPLICATION_CLASS(klass); + + application_class->activate = wintc_resvwr_application_activate; + application_class->startup = wintc_resvwr_application_startup; +} + +static void wintc_resvwr_application_init( + WINTC_UNUSED(WinTCResvwrApplication* self) +) { } + +// +// CLASS VIRTUAL METHODS +// +static void wintc_resvwr_application_activate( + GApplication* application +) +{ + GtkWidget* new_window = + wintc_resvwr_window_new(WINTC_RESVWR_APPLICATION(application)); + + gtk_widget_show_all(new_window); +} + +static void wintc_resvwr_application_startup( + GApplication* application +) +{ + (G_APPLICATION_CLASS(wintc_resvwr_application_parent_class)) + ->startup(application); + + // Init comctl + // + wintc_ctl_install_default_styles(); + + g_type_ensure(WINTC_TYPE_CTL_ANIMATION); + + // Init accelerators + // + wintc_application_set_accelerators( + GTK_APPLICATION(application), + S_ACCELS, + G_N_ELEMENTS(S_ACCELS) + ); +} + +// +// PUBLIC FUNCTIONS +// +WinTCResvwrApplication* wintc_resvwr_application_new(void) +{ + return WINTC_RESVWR_APPLICATION( + g_object_new( + wintc_resvwr_application_get_type(), + "application-id", "uk.oddmatics.wintc.tools.resvwr", + NULL + ) + ); +} diff --git a/tools/resvwr/src/application.h b/tools/resvwr/src/application.h new file mode 100644 index 0000000..aa0655e --- /dev/null +++ b/tools/resvwr/src/application.h @@ -0,0 +1,25 @@ +#ifndef __APPLICATION_H__ +#define __APPLICATION_H__ + +#include +#include + +// +// GTK OOP BOILERPLATE +// +#define WINTC_TYPE_RESVWR_APPLICATION (wintc_resvwr_application_get_type()) + +G_DECLARE_FINAL_TYPE( + WinTCResvwrApplication, + wintc_resvwr_application, + WINTC, + RESVWR_APPLICATION, + GtkApplication +) + +// +// PUBLIC FUNCTIONS +// +WinTCResvwrApplication* wintc_resvwr_application_new(void); + +#endif diff --git a/tools/resvwr/src/main.c b/tools/resvwr/src/main.c new file mode 100644 index 0000000..a48cca0 --- /dev/null +++ b/tools/resvwr/src/main.c @@ -0,0 +1,20 @@ +#include + +#include "application.h" + +int main( + int argc, + char* argv[] +) +{ + WinTCResvwrApplication* app = wintc_resvwr_application_new(); + int status; + + g_set_application_name("Resvwr"); + + status = g_application_run(G_APPLICATION(app), argc, argv); + + g_object_unref(app); + + return status; +} diff --git a/tools/resvwr/src/res/menubar.ui b/tools/resvwr/src/res/menubar.ui new file mode 100644 index 0000000..944113f --- /dev/null +++ b/tools/resvwr/src/res/menubar.ui @@ -0,0 +1,30 @@ + + + + + File + +
+ + <Control>O + win.open + Open + +
+
+ + F5 + win.refresh + Refresh + +
+
+ + <Alt>F4 + win.exit + Exit + +
+
+
+
diff --git a/tools/resvwr/src/res/resources.xml b/tools/resvwr/src/res/resources.xml new file mode 100644 index 0000000..4e66e8a --- /dev/null +++ b/tools/resvwr/src/res/resources.xml @@ -0,0 +1,7 @@ + + + + menubar.ui + resvwr.ui + + diff --git a/tools/resvwr/src/res/resvwr.ui b/tools/resvwr/src/res/resvwr.ui new file mode 100644 index 0000000..356ba21 --- /dev/null +++ b/tools/resvwr/src/res/resvwr.ui @@ -0,0 +1,32 @@ + + + + True + False + vertical + + + + True + False + + + False + False + 0 + + + + + True + True + in + + + True + True + 1 + + + + diff --git a/tools/resvwr/src/window.c b/tools/resvwr/src/window.c new file mode 100644 index 0000000..d740763 --- /dev/null +++ b/tools/resvwr/src/window.c @@ -0,0 +1,422 @@ +#include +#include +#include +#include + +#include "application.h" +#include "window.h" + +// +// FORWARD DECLARATIONS +// +static void wintc_resvwr_window_finalize( + GObject* object +); + +static void wintc_resvwr_window_refresh( + WinTCResvwrWindow* wnd +); + +static void action_exit( + GSimpleAction* action, + GVariant* parameter, + gpointer user_data +); +static void action_open( + GSimpleAction* action, + GVariant* parameter, + gpointer user_data +); +static void action_refresh( + GSimpleAction* action, + GVariant* parameter, + gpointer user_data +); + +// +// STATIC DATA +// +static GActionEntry s_window_actions[] = { + { + .name = "exit", + .activate = action_exit, + .parameter_type = NULL, + .state = NULL, + .change_state = NULL + }, + { + .name = "open", + .activate = action_open, + .parameter_type = NULL, + .state = NULL, + .change_state = NULL + }, + { + .name = "refresh", + .activate = action_refresh, + .parameter_type = NULL, + .state = NULL, + .change_state = NULL + }, +}; + +// +// GTK OOP CLASS/INSTANCE DEFINITIONS +// +typedef struct _WinTCResvwrWindow +{ + GtkApplicationWindow __parent__; + + // State + // + gchar* path_resource; + GtkWidget* scrollwnd_view; +} WinTCResvwrWindow; + +// +// GTK TYPE DEFINITION & CTORS +// +G_DEFINE_TYPE( + WinTCResvwrWindow, + wintc_resvwr_window, + GTK_TYPE_APPLICATION_WINDOW +) + +static void wintc_resvwr_window_class_init( + WinTCResvwrWindowClass* klass +) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + + object_class->finalize = wintc_resvwr_window_finalize; +} + +static void wintc_resvwr_window_init( + WinTCResvwrWindow* self +) +{ + GtkBuilder* builder; + + // Set up action map + // + g_action_map_add_action_entries( + G_ACTION_MAP(self), + s_window_actions, + G_N_ELEMENTS(s_window_actions), + self + ); + + // Build menu + // + GMenuModel* menubar; + + builder = + gtk_builder_new_from_resource( + "/uk/oddmatics/wintc/tools/resvwr/menubar.ui" + ); + + menubar = + G_MENU_MODEL( + g_object_ref( + gtk_builder_get_object(builder, "menubar") + ) + ); + + g_object_unref(builder); + + // Initialize UI + // + GtkWidget* menubar_main; + + builder = + gtk_builder_new_from_resource( + "/uk/oddmatics/wintc/tools/resvwr/resvwr.ui" + ); + + wintc_lc_builder_preprocess_widget_text(builder); + + wintc_builder_get_objects( + builder, + "menubar-main", &menubar_main, + "scrollwnd-view", &(self->scrollwnd_view), + NULL + ); + + gtk_menu_shell_bind_model( + GTK_MENU_SHELL(menubar_main), + menubar, + NULL, + FALSE + ); + + gtk_container_add( + GTK_CONTAINER(self), + GTK_WIDGET(gtk_builder_get_object(builder, "main-box")) + ); + + g_object_unref(builder); + g_object_unref(menubar); + + gtk_window_set_default_size( + GTK_WINDOW(self), + 320, + 260 + ); +} + +// +// CLASS VIRTUAL METHODS +// +static void wintc_resvwr_window_finalize( + GObject* object +) +{ + WinTCResvwrWindow* wnd = WINTC_RESVWR_WINDOW(object); + + g_free(wnd->path_resource); + + (G_OBJECT_CLASS(wintc_resvwr_window_parent_class)) + ->finalize(object); +} + +// +// PUBLIC FUNCTIONS +// +GtkWidget* wintc_resvwr_window_new( + WinTCResvwrApplication* app +) +{ + return GTK_WIDGET( + g_object_new( + WINTC_TYPE_RESVWR_WINDOW, + "application", GTK_APPLICATION(app), + "title", "Resource Viewer", + NULL + ) + ); +} + +// +// PRIVATE FUNCTIONS +// +static void wintc_resvwr_window_refresh( + WinTCResvwrWindow* wnd +) +{ + // Have we got any selection? + // + if (!(wnd->path_resource)) + { + return; + } + + // Clear existing stuff (if any) + // + GtkWidget* child = gtk_bin_get_child(GTK_BIN(wnd->scrollwnd_view)); + + if (child) + { + gtk_container_remove(GTK_CONTAINER(wnd->scrollwnd_view), child); + } + + // Create new from file + // + GtkBuilder* builder = gtk_builder_new(); + GError* error = NULL; + + if ( + gtk_builder_add_from_file( + builder, + wnd->path_resource, + &error + ) + ) + { + // Based on what we find in the builder, construct the UI in the + // scrolled window + // + GtkWidget* label_title; + GMenuModel* menu; + GMenuModel* menubar; + GtkWidget* main_box; + GtkWidget* page; + GtkWidget* toolbar; + + wintc_builder_get_objects( + builder, + "label-title", &label_title, + "main-box", &main_box, + "menu", &menu, + "menubar", &menubar, + "page", &page, + "toolbar", &toolbar, + NULL + ); + + if (main_box) + { + gtk_container_add( + GTK_CONTAINER(wnd->scrollwnd_view), + main_box + ); + } + else if (menu || menubar) + { + GtkWidget* box_wrapper = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + GtkWidget* menu_built; + + if (menu) // Floating menu - create menubar to attach to + { + GtkWidget* submenu_built = gtk_menu_new_from_model(menu); + GtkWidget* submenu_item = gtk_menu_item_new_with_label("_"); + + menu_built = gtk_menu_bar_new(); + + gtk_menu_item_set_submenu( + GTK_MENU_ITEM(submenu_item), + submenu_built + ); + gtk_menu_shell_append( + GTK_MENU_SHELL(menu_built), + submenu_item + ); + } + else // Menubar - attach immediately + { + menu_built = gtk_menu_bar_new_from_model(menubar); + } + + gtk_container_add( + GTK_CONTAINER(box_wrapper), + menu_built + ); + gtk_container_add( + GTK_CONTAINER(wnd->scrollwnd_view), + box_wrapper + ); + } + else if (page) + { + GtkWidget* notebook = gtk_notebook_new(); + + gtk_notebook_append_page( + GTK_NOTEBOOK(notebook), + page, + label_title + ); + + gtk_container_add( + GTK_CONTAINER(wnd->scrollwnd_view), + notebook + ); + } + else if (toolbar) + { + GtkWidget* box_wrapper = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + + gtk_container_add( + GTK_CONTAINER(box_wrapper), + toolbar + ); + gtk_container_add( + GTK_CONTAINER(wnd->scrollwnd_view), + box_wrapper + ); + } + else + { + // FIXME: Probably just append the first item? Who knows... + // + wintc_messagebox_show( + GTK_WINDOW(wnd), + "Don't know how to deal with this widget tree.", + "Unrecognised Widget Tree", + GTK_BUTTONS_OK, + GTK_MESSAGE_ERROR + ); + } + + gtk_widget_show_all(wnd->scrollwnd_view); + } + else + { + wintc_display_error_and_clear(&error); + } + + g_object_unref(builder); +} + +// +// CALLBACKS +// +static void action_exit( + WINTC_UNUSED(GSimpleAction* action), + WINTC_UNUSED(GVariant* parameter), + gpointer user_data +) +{ + gtk_window_close(GTK_WINDOW(user_data)); +} + +static void action_open( + WINTC_UNUSED(GSimpleAction* action), + WINTC_UNUSED(GVariant* parameter), + gpointer user_data +) +{ + WinTCResvwrWindow* wnd = WINTC_RESVWR_WINDOW(user_data); + + // Open file dialog stuff + // + GtkWidget* dlg; + GtkFileFilter* filter_xml; + + filter_xml = gtk_file_filter_new(); + + gtk_file_filter_set_name(filter_xml, "XML Files"); + gtk_file_filter_add_mime_type(filter_xml, "text/xml"); + + dlg = + gtk_file_chooser_dialog_new( + wintc_lc_get_control_text(WINTC_CTLTXT_OPEN, WINTC_PUNC_NONE), + GTK_WINDOW(wnd), + GTK_FILE_CHOOSER_ACTION_OPEN, + wintc_lc_get_control_text(WINTC_CTLTXT_CANCEL, WINTC_PUNC_NONE), + GTK_RESPONSE_CANCEL, + wintc_lc_get_control_text(WINTC_CTLTXT_OPEN, WINTC_PUNC_NONE), + GTK_RESPONSE_ACCEPT, + NULL + ); + + gtk_file_chooser_add_filter( + GTK_FILE_CHOOSER(dlg), + filter_xml + ); + + // Execute dialog and handle result + // + gint result = gtk_dialog_run(GTK_DIALOG(dlg)); + + if (result == GTK_RESPONSE_ACCEPT) + { + wnd->path_resource = + gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg)); + + wintc_resvwr_window_refresh(wnd); + } + + gtk_widget_destroy(dlg); +} + +static void action_refresh( + WINTC_UNUSED(GSimpleAction* action), + WINTC_UNUSED(GVariant* parameter), + gpointer user_data +) +{ + WinTCResvwrWindow* wnd = WINTC_RESVWR_WINDOW(user_data); + + WINTC_LOG_DEBUG("resvwr: refreshing..."); + + wintc_resvwr_window_refresh(wnd); +} diff --git a/tools/resvwr/src/window.h b/tools/resvwr/src/window.h new file mode 100644 index 0000000..9860309 --- /dev/null +++ b/tools/resvwr/src/window.h @@ -0,0 +1,29 @@ +#ifndef __WINDOW_H__ +#define __WINDOW_H__ + +#include +#include + +#include "application.h" + +// +// GTK OOP BOILERPLATE +// +#define WINTC_TYPE_RESVWR_WINDOW (wintc_resvwr_window_get_type()) + +G_DECLARE_FINAL_TYPE( + WinTCResvwrWindow, + wintc_resvwr_window, + WINTC, + RESVWR_WINDOW, + GtkApplicationWindow +) + +// +// PUBLIC FUNCTIONS +// +GtkWidget* wintc_resvwr_window_new( + WinTCResvwrApplication* app +); + +#endif diff --git a/tools/resvwr/wintc-resvwr.desktop b/tools/resvwr/wintc-resvwr.desktop new file mode 100644 index 0000000..3f980d5 --- /dev/null +++ b/tools/resvwr/wintc-resvwr.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=Resource Viewer (WinTC) +Comment=Development tool for viewing resources in the WinTC project. +Exec=wintc-resvwr +Icon=wintc-resvwr +Terminal=false +StartupNotify=false +Type=Application +Categories=Development;GTK;