From bb0ac39919f80732d74eb754fed3fa1b986bba4e Mon Sep 17 00:00:00 2001 From: Rory Fewell Date: Thu, 22 Jan 2026 19:56:28 +0000 Subject: [PATCH] Enhancement: Fixes #498, wizard97 - initial implementation --- private/play/wizard/CMakeLists.txt | 86 ++ private/play/wizard/README.MD | 5 + private/play/wizard/deps | 5 + .../wizard/icons/16x16/wintc-wizard-test.png | Bin 0 -> 204 bytes .../wizard/icons/32x32/wintc-wizard-test.png | Bin 0 -> 256 bytes private/play/wizard/src/application.c | 90 ++ private/play/wizard/src/application.h | 25 + private/play/wizard/src/main.c | 20 + private/play/wizard/src/res/header.png | Bin 0 -> 1264 bytes private/play/wizard/src/res/resources.xml | 11 + private/play/wizard/src/res/watermk.png | Bin 0 -> 6661 bytes private/play/wizard/src/res/wizpg1.ui | 47 + private/play/wizard/src/res/wizpg2.ui | 27 + private/play/wizard/src/res/wizpg3.ui | 64 + private/play/wizard/src/res/wizpg4.ui | 66 + private/play/wizard/src/window.c | 261 ++++ private/play/wizard/src/window.h | 30 + private/play/wizard/wintc-wizard-test.desktop | 9 + shared/comctl/src/menubind.c | 3 +- shared/comctl/src/res/default.css | 23 + shared/comgtk/CMakeLists.txt | 2 + shared/comgtk/public/container.h | 4 +- shared/comgtk/public/libapi.h.in | 1 + shared/comgtk/public/radio.h | 19 + shared/comgtk/src/container.c | 22 +- shared/comgtk/src/radio.c | 31 + shared/wizard97/CMakeLists.txt | 87 ++ shared/wizard97/README.MD | 5 + shared/wizard97/deps | 4 + shared/wizard97/public/libapi.h.in | 6 + shared/wizard97/public/wizpage.h | 41 + shared/wizard97/public/wizwnd.h | 70 + shared/wizard97/src/res/default.css | 40 + shared/wizard97/src/res/default_p.css | 19 + shared/wizard97/src/res/resources.xml | 10 + shared/wizard97/src/res/wizext.ui | 42 + shared/wizard97/src/res/wizint.ui | 106 ++ shared/wizard97/src/res/wizwnd.ui | 125 ++ shared/wizard97/src/wizpage.c | 258 ++++ shared/wizard97/src/wizwnd.c | 1136 +++++++++++++++++ shell/cpl/desk/src/pagedesk.c | 6 +- shell/explorer/src/toolbars/stdbar.c | 5 +- shell/taskband/src/start/personal.c | 3 +- tools/bldutils/depmap/apk-maps | 1 + tools/bldutils/depmap/archpkg-maps | 1 + tools/bldutils/depmap/bsdpkg-maps | 1 + tools/bldutils/depmap/deb-maps | 1 + tools/bldutils/depmap/rpm-maps | 1 + tools/bldutils/depmap/xbps-maps | 1 + 49 files changed, 2810 insertions(+), 10 deletions(-) create mode 100644 private/play/wizard/CMakeLists.txt create mode 100644 private/play/wizard/README.MD create mode 100644 private/play/wizard/deps create mode 100644 private/play/wizard/icons/16x16/wintc-wizard-test.png create mode 100644 private/play/wizard/icons/32x32/wintc-wizard-test.png create mode 100644 private/play/wizard/src/application.c create mode 100644 private/play/wizard/src/application.h create mode 100644 private/play/wizard/src/main.c create mode 100644 private/play/wizard/src/res/header.png create mode 100644 private/play/wizard/src/res/resources.xml create mode 100644 private/play/wizard/src/res/watermk.png create mode 100644 private/play/wizard/src/res/wizpg1.ui create mode 100644 private/play/wizard/src/res/wizpg2.ui create mode 100644 private/play/wizard/src/res/wizpg3.ui create mode 100644 private/play/wizard/src/res/wizpg4.ui create mode 100644 private/play/wizard/src/window.c create mode 100644 private/play/wizard/src/window.h create mode 100644 private/play/wizard/wintc-wizard-test.desktop create mode 100644 shared/comgtk/public/radio.h create mode 100644 shared/comgtk/src/radio.c create mode 100644 shared/wizard97/CMakeLists.txt create mode 100644 shared/wizard97/README.MD create mode 100644 shared/wizard97/deps create mode 100644 shared/wizard97/public/libapi.h.in create mode 100644 shared/wizard97/public/wizpage.h create mode 100644 shared/wizard97/public/wizwnd.h create mode 100644 shared/wizard97/src/res/default.css create mode 100644 shared/wizard97/src/res/default_p.css create mode 100644 shared/wizard97/src/res/resources.xml create mode 100644 shared/wizard97/src/res/wizext.ui create mode 100644 shared/wizard97/src/res/wizint.ui create mode 100644 shared/wizard97/src/res/wizwnd.ui create mode 100644 shared/wizard97/src/wizpage.c create mode 100644 shared/wizard97/src/wizwnd.c diff --git a/private/play/wizard/CMakeLists.txt b/private/play/wizard/CMakeLists.txt new file mode 100644 index 0000000..8a8fdfd --- /dev/null +++ b/private/play/wizard/CMakeLists.txt @@ -0,0 +1,86 @@ +cmake_minimum_required(VERSION 3.12) + +project( + wintc-wizard-test + VERSION 1.0 + DESCRIPTION "Windows Total Conversion 'Hello World' application." + 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-wizard97 WINTC_WIZARD97) + +wintc_compile_resources() + +add_executable( + wintc-wizard-test + src/application.c + src/application.h + src/main.c + src/resources.c + src/window.c + src/window.h +) + +target_compile_options( + wintc-wizard-test + PRIVATE ${WINTC_COMPILE_OPTIONS} +) + +target_include_directories( + wintc-wizard-test + SYSTEM + PRIVATE ${GLIB_INCLUDE_DIRS} + PRIVATE ${GTK3_INCLUDE_DIRS} + PRIVATE ${WINTC_COMCTL_INCLUDE_DIRS} + PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS} + PRIVATE ${WINTC_WIZARD97_INCLUDE_DIRS} +) + +target_link_directories( + wintc-wizard-test + PRIVATE ${GLIB_LIBRARY_DIRS} + PRIVATE ${GTK3_LIBRARY_DIRS} + PRIVATE ${WINTC_COMCTL_LIBRARY_DIRS} + PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS} + PRIVATE ${WINTC_WIZARD97_LIBRARY_DIRS} +) + +target_link_libraries( + wintc-wizard-test + PRIVATE ${GLIB_LIBRARIES} + PRIVATE ${GTK3_LIBRARIES} + PRIVATE ${WINTC_COMCTL_LIBRARIES} + PRIVATE ${WINTC_COMGTK_LIBRARIES} + PRIVATE ${WINTC_WIZARD97_LIBRARIES} +) + +# Installation +# +wintc_configure_and_install_packaging() +wintc_install_icons_into_package() + +install( + FILES wintc-wizard-test.desktop + DESTINATION share/applications +) +install( + TARGETS wintc-wizard-test + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/private/play/wizard/README.MD b/private/play/wizard/README.MD new file mode 100644 index 0000000..9b814dd --- /dev/null +++ b/private/play/wizard/README.MD @@ -0,0 +1,5 @@ +# wizard +This directory contains the source code for the sample wizard. + +Image +Image diff --git a/private/play/wizard/deps b/private/play/wizard/deps new file mode 100644 index 0000000..41159d4 --- /dev/null +++ b/private/play/wizard/deps @@ -0,0 +1,5 @@ +bt,rt:glib2 +bt,rt:gtk3 +bt,rt:wintc-comctl +bt,rt:wintc-comgtk +bt,rt:wintc-wizard97 diff --git a/private/play/wizard/icons/16x16/wintc-wizard-test.png b/private/play/wizard/icons/16x16/wintc-wizard-test.png new file mode 100644 index 0000000000000000000000000000000000000000..3c117bcc9628afeaf68c417316b636e8ba029ba6 GIT binary patch literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFP2=EDU{r~?zkjc=%(9i&)fHaT* zf&&K*fF%AifaQS%hy?`FF9lnH;*2Fhe!&b5&u*jvIbNPFjv*Dda?fq#Jz&7W;&9`D z#?$^uOMU;Ie!5Zjwrhrk;>UzExr;te6*e!?%RCV1>!HHp^F-g``hinBABJ2qE~+}B g{YLoti>k-WGoy_wqHbR<2Aay?>FVdQ&MBb@0QcZeNdN!< literal 0 HcmV?d00001 diff --git a/private/play/wizard/icons/32x32/wintc-wizard-test.png b/private/play/wizard/icons/32x32/wintc-wizard-test.png new file mode 100644 index 0000000000000000000000000000000000000000..44289d796c3e8d1ba86940b982849af8ab8d25a3 GIT binary patch literal 256 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvg8-ip*Z=?j1DOmB3=It+3P=M9 zAUJT~07&9L16UqNfLK5v{Zg5g1bfDcC~uDsBHWV$P6^C971C<*u*>+QfOX@HGoh+WR81J|xwf!qH(1Un zDLr4nuxr6SdZxPU0d_N!P%;57qjoFXZ +#include +#include +#include + +#include "application.h" +#include "window.h" + +// +// GTK OOP CLASS/INSTANCE DEFINITIONS +// +struct _WinTCWizardApplicationClass +{ + GtkApplicationClass __parent__; +}; + +struct _WinTCWizardApplication +{ + GtkApplication __parent__; +}; + +// +// FORWARD DECLARATIONS +// +static void wintc_wizard_application_activate( + GApplication* application +); +static void wintc_wizard_application_startup( + GApplication* application +); + +// +// GTK TYPE DEFINITIONS & CTORS +// +G_DEFINE_TYPE( + WinTCWizardApplication, + wintc_wizard_application, + GTK_TYPE_APPLICATION +) + +static void wintc_wizard_application_class_init( + WinTCWizardApplicationClass* klass +) +{ + GApplicationClass* application_class = G_APPLICATION_CLASS(klass); + + application_class->activate = wintc_wizard_application_activate; + application_class->startup = wintc_wizard_application_startup; +} + +static void wintc_wizard_application_init( + WINTC_UNUSED(WinTCWizardApplication* self) +) { } + +// +// CLASS VIRTUAL METHODS +// +static void wintc_wizard_application_activate( + GApplication* application +) +{ + GtkWidget* new_window = + wintc_wizard_window_new(WINTC_WIZARD_APPLICATION(application)); + + gtk_widget_show_all(new_window); +} + +static void wintc_wizard_application_startup( + GApplication* application +) +{ + (G_APPLICATION_CLASS(wintc_wizard_application_parent_class)) + ->startup(application); + + wintc_ctl_install_default_styles(); +} + +// +// PUBLIC FUNCTIONS +// +WinTCWizardApplication* wintc_wizard_application_new(void) +{ + return WINTC_WIZARD_APPLICATION( + g_object_new( + wintc_wizard_application_get_type(), + "application-id", "uk.oddmatics.wintc.play.wizard", + NULL + ) + ); +} diff --git a/private/play/wizard/src/application.h b/private/play/wizard/src/application.h new file mode 100644 index 0000000..b84cc0d --- /dev/null +++ b/private/play/wizard/src/application.h @@ -0,0 +1,25 @@ +#ifndef __APPLICATION_H__ +#define __APPLICATION_H__ + +#include +#include + +// +// GTK OOP BOILERPLATE +// +#define WINTC_TYPE_WIZARD_APPLICATION (wintc_wizard_application_get_type()) + +G_DECLARE_FINAL_TYPE( + WinTCWizardApplication, + wintc_wizard_application, + WINTC, + WIZARD_APPLICATION, + GtkApplication +) + +// +// PUBLIC FUNCTIONS +// +WinTCWizardApplication* wintc_wizard_application_new(void); + +#endif diff --git a/private/play/wizard/src/main.c b/private/play/wizard/src/main.c new file mode 100644 index 0000000..56054f8 --- /dev/null +++ b/private/play/wizard/src/main.c @@ -0,0 +1,20 @@ +#include + +#include "application.h" + +int main( + int argc, + char* argv[] +) +{ + WinTCWizardApplication* app = wintc_wizard_application_new(); + int status; + + g_set_application_name("Wizard"); + + status = g_application_run(G_APPLICATION(app), argc, argv); + + g_object_unref(app); + + return status; +} diff --git a/private/play/wizard/src/res/header.png b/private/play/wizard/src/res/header.png new file mode 100644 index 0000000000000000000000000000000000000000..32c7d6e21089d8667ea75332532f4ef53634cc0e GIT binary patch literal 1264 zcmV6+ES1ezIHWBmmNfSZ zZanztC6LrDVKt7-2$aq^Ph;fij~~OOjb@-`J0Djy3V<@;0bqiX%r}yg^Yb(lsMBD|$wr0#%j! z|2(bi#CW5-Hw2wew*58??j5MtZ2RlTw(G~>dW4Ho)4wJ;O?`-7Yij-j@NL4`Wm8M- z!ub{qJQztc`6IbxJF{7MJ%yeG^xZ)BawDtXb58Cdz9GNp8us=fAoqPM-|z=$0wK^P zVgLXD32;bRa{vGi!vFvd!vV){sAK>D11U*FK~!ko?ONZ9O+g%=bM5BGO01NPU4+F( zJa`aUNnV5}@!(A<|AqV=it?oP4KEUkc1e^UD-k7Dt`wV6SoZpS&D`#pfJx@XS!duG1hnKR$-%-oYGRja8sN2O>3x=tAM*u`4rntYrE6ZN-V(Xxh4#tFii zV!Ks@(^e_-I<@B9sBPU_wWI1F9_9}DW(3+_pkR~s$^Z+ctgIg=NI2Qv<& z`{R(&;XpkS5+yZA9`Ha!wFro4T2;Cp| zGs)ix8tN&|Y>i|#76I7EfmvLGtNmJ=P}glC9d3T_1FDIKAn7HxksC%B2d z3*4W%w*$NgerS{c^kk?=ZS{h!u{++9nPVDA}C^uY%74jqd}G7zgUur1bXn z0{FejGZm(kI}+O%BWUS-OxfE_DJWYX%{Wj8?Mn{iJZI-K;l!4#@oC?D0$eZ9rOu)q z;3;qwqc_4l-+=I-fEIOw0=*&dIQRm*tMn;o4>7$ybnEhchg>?+ok z>>hw;m5$^864${Sj65jBra=b*=NyfMf&#&Lr8ig{><}Ax7E7SvrV*h`E(xm~YQ}JB z$3&mSrt#WvoziiC$n$wR0(zqK62l#Z@(}4n9WMl%+-lql|$70000 + + + header.png + watermk.png + wizpg1.ui + wizpg2.ui + wizpg3.ui + wizpg4.ui + + diff --git a/private/play/wizard/src/res/watermk.png b/private/play/wizard/src/res/watermk.png new file mode 100644 index 0000000000000000000000000000000000000000..3a40ca92a89d38fbdf1bfe0b4208525aa7cd5f6c GIT binary patch literal 6661 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 literal 0 HcmV?d00001 diff --git a/private/play/wizard/src/res/wizpg1.ui b/private/play/wizard/src/res/wizpg1.ui new file mode 100644 index 0000000..469df67 --- /dev/null +++ b/private/play/wizard/src/res/wizpg1.ui @@ -0,0 +1,47 @@ + + + + True + False + Welcome + Welcome to the test wizard. + True + vertical + + + + Welcome to the Sample Test Wizard + True + False + 25 + True + 0.0 + + + + + False + False + 0 + + + + + + This wizard guides you in the process of doing nothing, achieving nothing, and ultimately reaching enlightenment. + True + False + 25 + True + 0.0 + + + False + False + 1 + + + + diff --git a/private/play/wizard/src/res/wizpg2.ui b/private/play/wizard/src/res/wizpg2.ui new file mode 100644 index 0000000..d524510 --- /dev/null +++ b/private/play/wizard/src/res/wizpg2.ui @@ -0,0 +1,27 @@ + + + + True + False + Welcome + Welcome to the test wizard. + True + vertical + + + + This is a second exterior page, a bit like the Hardware Update Wizard uses. + True + False + 25 + True + 0.0 + + + False + False + 0 + + + + diff --git a/private/play/wizard/src/res/wizpg3.ui b/private/play/wizard/src/res/wizpg3.ui new file mode 100644 index 0000000..b02ae32 --- /dev/null +++ b/private/play/wizard/src/res/wizpg3.ui @@ -0,0 +1,64 @@ + + + + True + False + Page 2 + This is page two. + vertical + + + + Please select which one of these you think is better: + True + False + 25 + True + 0.0 + + + + + False + False + 0 + + + + + + Apples + True + True + + + + + False + False + 1 + + + + + Oranges + True + True + radio-apples + + + + + False + False + 2 + + + + diff --git a/private/play/wizard/src/res/wizpg4.ui b/private/play/wizard/src/res/wizpg4.ui new file mode 100644 index 0000000..277ad7e --- /dev/null +++ b/private/play/wizard/src/res/wizpg4.ui @@ -0,0 +1,66 @@ + + + + True + False + Finished + Completing the test wizard. + True + vertical + + + + Completing the Sample Test Wizard + True + False + 0.0 + + + + + False + False + 0 + + + + + + The Sample Test Wizard is now complete! + +You have managed to: + True + False + 25 + True + 0.0 + + + False + False + 1 + + + + + + True + False + 25 + True + 0.0 + + + + + False + False + 2 + + + + diff --git a/private/play/wizard/src/window.c b/private/play/wizard/src/window.c new file mode 100644 index 0000000..3e48024 --- /dev/null +++ b/private/play/wizard/src/window.c @@ -0,0 +1,261 @@ +#include +#include +#include +#include + +#include "application.h" +#include "window.h" + +// +// PRIVATE ENUMS +// +enum +{ + PROP_NULL, + PROP_CAN_HELP, + N_PROPERTIES +}; + +enum +{ + WIZPAGE_INTRO, + WIZPAGE_INTRO2, + WIZPAGE_DECISION, + WIZPAGE_FINISHED +}; + +enum +{ + DECISION_APPLES, + DECISION_ORANGES +}; + +// +// FORWARD DECLARATIONS +// +static void wintc_wizard_window_get_property( + GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec +); + +static void wintc_wizard_window_constructing_page( + WinTCWizard97Window* wiz_wnd, + guint page_num, + GtkBuilder* builder +); +static guint wintc_wizard_window_get_next_page( + WinTCWizard97Window* wiz_wnd, + guint current_page +); +static void wintc_wizard_window_help( + WinTCWizard97Window* wiz_wnd, + guint current_page +); + +// +// GTK OOP CLASS/INSTANCE DEFINITIONS +// +struct _WinTCWizardWindowClass +{ + WinTCWizard97WindowClass __parent__; +}; + +struct _WinTCWizardWindow +{ + WinTCWizard97Window __parent__; + + // UI stuff + // + GtkWidget* radio_apples; + GtkWidget* label_done_prefer; +}; + +// +// GTK TYPE DEFINITION & CTORS +// +G_DEFINE_TYPE( + WinTCWizardWindow, + wintc_wizard_window, + WINTC_TYPE_WIZARD97_WINDOW +) + +static void wintc_wizard_window_class_init( + WinTCWizardWindowClass* klass +) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + WinTCWizard97WindowClass* wizard_class = + WINTC_WIZARD97_WINDOW_CLASS(klass); + + wizard_class->constructing_page = wintc_wizard_window_constructing_page; + wizard_class->get_next_page = wintc_wizard_window_get_next_page; + wizard_class->help = wintc_wizard_window_help; + object_class->get_property = wintc_wizard_window_get_property; + + g_object_class_override_property( + object_class, + PROP_CAN_HELP, + "can-help" + ); + + wintc_wizard97_window_class_setup_from_resources( + wizard_class, + "/uk/oddmatics/wintc/play/wizard/watermk.png", + "/uk/oddmatics/wintc/play/wizard/header.png", + "/uk/oddmatics/wintc/play/wizard/wizpg1.ui", + "/uk/oddmatics/wintc/play/wizard/wizpg2.ui", + "/uk/oddmatics/wintc/play/wizard/wizpg3.ui", + "/uk/oddmatics/wintc/play/wizard/wizpg4.ui", + NULL + ); +} + +static void wintc_wizard_window_init( + WinTCWizardWindow* self +) +{ + wintc_wizard97_window_init_wizard( + WINTC_WIZARD97_WINDOW(self) + ); +} + +// +// CLASS VIRTUAL METHODS +// +static void wintc_wizard_window_get_property( + GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec +) +{ + switch (prop_id) + { + case PROP_CAN_HELP: + g_value_set_boolean(value, TRUE); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void wintc_wizard_window_constructing_page( + WinTCWizard97Window* wiz_wnd, + guint page_num, + GtkBuilder* builder +) +{ + WinTCWizardWindow* swiz_wnd = WINTC_WIZARD_WINDOW(wiz_wnd); + + switch (page_num) + { + case WIZPAGE_DECISION: + wintc_builder_get_objects( + builder, + "radio-apples", &(swiz_wnd->radio_apples), + NULL + ); + + break; + + case WIZPAGE_FINISHED: + wintc_builder_get_objects( + builder, + "label-done-prefer", &(swiz_wnd->label_done_prefer), + NULL + ); + + break; + + default: break; + } +} + +static guint wintc_wizard_window_get_next_page( + WinTCWizard97Window* wiz_wnd, + guint current_page +) +{ + WinTCWizardWindow* swiz_wnd = WINTC_WIZARD_WINDOW(wiz_wnd); + + guint next_page = current_page + 1; + + switch (next_page) + { + case WIZPAGE_FINISHED: + { + guint idx_prefer; + const gchar* text_prefer_item; + gchar* text_prefer; + + idx_prefer = + wintc_radio_group_get_selection( + gtk_radio_button_get_group( + GTK_RADIO_BUTTON(swiz_wnd->radio_apples) + ) + ); + + switch (idx_prefer) + { + case DECISION_APPLES: text_prefer_item = "apples"; break; + case DECISION_ORANGES: text_prefer_item = "oranges"; break; + } + + text_prefer = + g_strdup_printf( + "Decide that %s are better.", + text_prefer_item + ); + + gtk_label_set_text( + GTK_LABEL(swiz_wnd->label_done_prefer), + text_prefer + ); + + g_free(text_prefer); + + break; + } + + default: break; + } + + return + (WINTC_WIZARD97_WINDOW_CLASS(wintc_wizard_window_parent_class)) + ->get_next_page(wiz_wnd, current_page); +} + +static void wintc_wizard_window_help( + WinTCWizard97Window* wiz_wnd, + WINTC_UNUSED(guint current_page) +) +{ + wintc_messagebox_show( + GTK_WINDOW(wiz_wnd), + "And this is where I'd display the help dialog... IF I HAD ONE!", + "Help", + GTK_BUTTONS_OK, + GTK_MESSAGE_ERROR + ); +} + +// +// PUBLIC FUNCTIONS +// +GtkWidget* wintc_wizard_window_new( + WinTCWizardApplication* app +) +{ + return GTK_WIDGET( + g_object_new( + WINTC_TYPE_WIZARD_WINDOW, + "application", GTK_APPLICATION(app), + "title", "My Sample Wizard", + NULL + ) + ); +} diff --git a/private/play/wizard/src/window.h b/private/play/wizard/src/window.h new file mode 100644 index 0000000..e758723 --- /dev/null +++ b/private/play/wizard/src/window.h @@ -0,0 +1,30 @@ +#ifndef __WINDOW_H__ +#define __WINDOW_H__ + +#include +#include +#include + +#include "application.h" + +// +// GTK OOP BOILERPLATE +// +#define WINTC_TYPE_WIZARD_WINDOW (wintc_wizard_window_get_type()) + +G_DECLARE_FINAL_TYPE( + WinTCWizardWindow, + wintc_wizard_window, + WINTC, + WIZARD_WINDOW, + WinTCWizard97Window +) + +// +// PUBLIC FUNCTIONS +// +GtkWidget* wintc_wizard_window_new( + WinTCWizardApplication* app +); + +#endif diff --git a/private/play/wizard/wintc-wizard-test.desktop b/private/play/wizard/wintc-wizard-test.desktop new file mode 100644 index 0000000..4a04fa9 --- /dev/null +++ b/private/play/wizard/wintc-wizard-test.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=Hello (WinTC Sample) +Comment=WinTC demonstration hello program. +Exec=wintc-hello +Icon=wintc-hello +Terminal=false +StartupNotify=false +Type=Application +Categories=Utility;GTK; diff --git a/shared/comctl/src/menubind.c b/shared/comctl/src/menubind.c index d8fce1e..358a804 100644 --- a/shared/comctl/src/menubind.c +++ b/shared/comctl/src/menubind.c @@ -167,7 +167,8 @@ static void wintc_ctl_menu_binding_constructed( WinTCCtlMenuBinding* menu_binding = WINTC_CTL_MENU_BINDING(object); wintc_container_clear( - GTK_CONTAINER(menu_binding->menu_shell) + GTK_CONTAINER(menu_binding->menu_shell), + TRUE ); wintc_ctl_menu_binding_track_menu( diff --git a/shared/comctl/src/res/default.css b/shared/comctl/src/res/default.css index ab8d1ff..6d00d8e 100644 --- a/shared/comctl/src/res/default.css +++ b/shared/comctl/src/res/default.css @@ -55,3 +55,26 @@ box.vertical.wintc-button-box button:last-child { margin-bottom: 0px; } + +/** + * Edges + */ +.wintc-edge-bottom +{ + border-bottom: 1px solid @borders; +} + +.wintc-edge-left +{ + border-left: 1px solid @borders; +} + +.wintc-edge-right +{ + border-right: 1px solid @borders; +} + +.wintc-edge-top +{ + border-top: 1px solid @borders; +} diff --git a/shared/comgtk/CMakeLists.txt b/shared/comgtk/CMakeLists.txt index 6840a0b..92a3a17 100644 --- a/shared/comgtk/CMakeLists.txt +++ b/shared/comgtk/CMakeLists.txt @@ -70,6 +70,8 @@ add_library( public/msgbox.h src/profile.c public/profile.h + src/radio.c + public/radio.h src/regex.c public/regex.h public/shorthand.h diff --git a/shared/comgtk/public/container.h b/shared/comgtk/public/container.h index 31e8d99..f4fbd7c 100644 --- a/shared/comgtk/public/container.h +++ b/shared/comgtk/public/container.h @@ -13,9 +13,11 @@ * Destroys all child widgets of a container. * * @param container The container. + * @param destroy True to destroy, rather than just remove, the children. */ void wintc_container_clear( - GtkContainer* container + GtkContainer* container, + gboolean destroy ); /** diff --git a/shared/comgtk/public/libapi.h.in b/shared/comgtk/public/libapi.h.in index 653bec7..e4bea3e 100644 --- a/shared/comgtk/public/libapi.h.in +++ b/shared/comgtk/public/libapi.h.in @@ -21,6 +21,7 @@ #include "@LIB_HEADER_DIR@/menu.h" #include "@LIB_HEADER_DIR@/msgbox.h" #include "@LIB_HEADER_DIR@/profile.h" +#include "@LIB_HEADER_DIR@/radio.h" #include "@LIB_HEADER_DIR@/regex.h" #include "@LIB_HEADER_DIR@/shorthand.h" #include "@LIB_HEADER_DIR@/signals.h" diff --git a/shared/comgtk/public/radio.h b/shared/comgtk/public/radio.h new file mode 100644 index 0000000..201edb4 --- /dev/null +++ b/shared/comgtk/public/radio.h @@ -0,0 +1,19 @@ +#ifndef __COMGTK_RADIO_H__ +#define __COMGTK_RADIO_H__ + +#include + +// +// PUBLIC FUNCTIONS +// + +/** + * Retrieve the index of the active selection in a radio button group. + * + * @param group The radio button group. + */ +guint wintc_radio_group_get_selection( + GSList* group +); + +#endif diff --git a/shared/comgtk/src/container.c b/shared/comgtk/src/container.c index 4208c09..aaed670 100644 --- a/shared/comgtk/src/container.c +++ b/shared/comgtk/src/container.c @@ -7,17 +7,29 @@ // PUBLIC FUNCTIONS // void wintc_container_clear( - GtkContainer* container + GtkContainer* container, + gboolean destroy ) { GList* children = gtk_container_get_children(container); GList* iter = children; - while (iter) + if (destroy) { - gtk_widget_destroy(GTK_WIDGET(iter->data)); - - iter = iter->next; + for (; iter; iter = iter->next) + { + gtk_widget_destroy(GTK_WIDGET(iter->data)); + } + } + else + { + for (; iter; iter = iter->next) + { + gtk_container_remove( + container, + GTK_WIDGET(iter->data) + ); + } } g_list_free(children); diff --git a/shared/comgtk/src/radio.c b/shared/comgtk/src/radio.c new file mode 100644 index 0000000..281ef3a --- /dev/null +++ b/shared/comgtk/src/radio.c @@ -0,0 +1,31 @@ +#include +#include + +#include "../public/radio.h" + +// +// PUBLIC FUNCTIONS +// +guint wintc_radio_group_get_selection( + GSList* group +) +{ + GSList* iter = group; + + for (guint i = 0; iter; iter = iter->next, i++) + { + if ( + gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON(iter->data) + ) + ) + { + // From GtkBuilder, it's in reverse + // + return g_slist_length(group) - i - 1; + } + } + + g_critical("%s", "comgtk: no radio in group was active"); + return 0; +} diff --git a/shared/wizard97/CMakeLists.txt b/shared/wizard97/CMakeLists.txt new file mode 100644 index 0000000..1e802c6 --- /dev/null +++ b/shared/wizard97/CMakeLists.txt @@ -0,0 +1,87 @@ +cmake_minimum_required(VERSION 3.12) + +project( + libwintc-wizard97 + VERSION 1.0 + DESCRIPTION "Windows Total Conversion wizard UI library." + 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/libraries/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(gdk-pixbuf-2.0 GDK_PIXBUF) +wintc_resolve_library(glib-2.0 GLIB) +wintc_resolve_library(gtk+-3.0 GTK3) +wintc_resolve_library(wintc-comgtk WINTC_COMGTK) + +wintc_compile_resources() + +add_library( + libwintc-wizard97 + src/resources.c + src/wizpage.c + public/wizpage.h + src/wizwnd.c + public/wizwnd.h +) + +set_target_properties( + libwintc-wizard97 + PROPERTIES + SOVERSION 1 + VERSION ${PROJECT_VERSION} +) + +target_compile_options( + libwintc-wizard97 + PRIVATE ${WINTC_COMPILE_OPTIONS} +) + +target_include_directories( + libwintc-wizard97 + SYSTEM + BEFORE + PRIVATE ${GDK_PIXBUF_INCLUDE_DIRS} + PRIVATE ${GLIB_INCLUDE_DIRS} + PRIVATE ${GTK3_INCLUDE_DIRS} + PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS} +) + +target_link_directories( + libwintc-wizard97 + PRIVATE ${GDK_PIXBUF_LIBRARY_DIRS} + PRIVATE ${GLIB_LIBRARY_DIRS} + PRIVATE ${GTK3_LIBRARY_DIRS} + PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS} +) + +target_link_libraries( + libwintc-wizard97 + PRIVATE ${GDK_PIXBUF_LIBRARIES} + PRIVATE ${GLIB_LIBRARIES} + PRIVATE ${GTK3_LIBRARIES} + PRIVATE ${WINTC_COMGTK_LIBRARIES} +) + +# Installation +# +wintc_configure_and_install_packaging() +wintc_add_pkgconfig_install() +wintc_install_public_headers() + +install( + TARGETS libwintc-wizard97 + LIBRARY DESTINATION ${LIB_DIR} +) diff --git a/shared/wizard97/README.MD b/shared/wizard97/README.MD new file mode 100644 index 0000000..8dd6518 --- /dev/null +++ b/shared/wizard97/README.MD @@ -0,0 +1,5 @@ +# libwintc-wizard97 +This directory contains the source code for the wizard library. + +## Purpose +This library is essentially a GTK-ised version of wizard97, used for making the nice looking wizards in Windows 2000 and XP. diff --git a/shared/wizard97/deps b/shared/wizard97/deps new file mode 100644 index 0000000..7e95f86 --- /dev/null +++ b/shared/wizard97/deps @@ -0,0 +1,4 @@ +bt,rt:gdk-pixbuf2 +bt,rt:glib2 +bt,rt:gtk3 +bt,rt:wintc-comgtk diff --git a/shared/wizard97/public/libapi.h.in b/shared/wizard97/public/libapi.h.in new file mode 100644 index 0000000..2211ee6 --- /dev/null +++ b/shared/wizard97/public/libapi.h.in @@ -0,0 +1,6 @@ +#ifndef __WINTC_WIZARD97_H__ +#define __WINTC_WIZARD97_H__ + +#include "@LIB_HEADER_DIR@/wizwnd.h" + +#endif diff --git a/shared/wizard97/public/wizpage.h b/shared/wizard97/public/wizpage.h new file mode 100644 index 0000000..76d5351 --- /dev/null +++ b/shared/wizard97/public/wizpage.h @@ -0,0 +1,41 @@ +#ifndef __WIZARD97_WIZPAGE_H__ +#define __WIZARD97_WIZPAGE_H__ + +#include +#include + +// +// GTK OOP BOILERPLATE +// +#define WINTC_TYPE_WIZARD97_PAGE (wintc_wizard97_page_get_type()) + +G_DECLARE_DERIVABLE_TYPE( + WinTCWizard97Page, + wintc_wizard97_page, + WINTC, + WIZARD97_PAGE, + GtkBox +) + +struct _WinTCWizard97PageClass +{ + GtkBoxClass __parent__; +}; + +// +// PUBLIC FUNCTIONS +// +gboolean wintc_wizard97_page_get_is_exterior_page( + WinTCWizard97Page* wiz_page +); +gboolean wintc_wizard97_page_get_is_final_page( + WinTCWizard97Page* wiz_page +); +const gchar* wintc_wizard97_page_get_subtitle( + WinTCWizard97Page* wiz_page +); +const gchar* wintc_wizard97_page_get_title( + WinTCWizard97Page* wiz_page +); + +#endif diff --git a/shared/wizard97/public/wizwnd.h b/shared/wizard97/public/wizwnd.h new file mode 100644 index 0000000..3fbb22d --- /dev/null +++ b/shared/wizard97/public/wizwnd.h @@ -0,0 +1,70 @@ +#ifndef __WIZARD97_WIZWND_H__ +#define __WIZARD97_WIZWND_H__ + +#include +#include + +// +// GTK OOP BOILERPLATE +// +#define WINTC_TYPE_WIZARD97_WINDOW (wintc_wizard97_window_get_type()) + +G_DECLARE_DERIVABLE_TYPE( + WinTCWizard97Window, + wintc_wizard97_window, + WINTC, + WIZARD97_WINDOW, + GtkWindow +) + +struct _WinTCWizard97WindowClass +{ + GtkWindowClass __parent__; + + // Wizard stuff + // + gchar* resource_watermark; + gchar* resource_header; + + GList* list_resources_pages; + + // Vfuncs + // + gboolean (*cancel) ( + WinTCWizard97Window* wiz_wnd, + guint current_page + ); + void (*constructing_page) ( + WinTCWizard97Window* wiz_wnd, + guint page_num, + GtkBuilder* builder + ); + gboolean (*finish) ( + WinTCWizard97Window* wiz_wnd, + guint current_page + ); + guint (*get_next_page) ( + WinTCWizard97Window* wiz_wnd, + guint current_page + ); + void (*help) ( + WinTCWizard97Window* wiz_wnd, + guint current_page + ); +}; + +// +// PUBLIC FUNCTIONS +// +void wintc_wizard97_window_class_setup_from_resources( + WinTCWizard97WindowClass* wizard_class, + const gchar* resource_watermark, + const gchar* resource_header, + ... +); + +void wintc_wizard97_window_init_wizard( + WinTCWizard97Window* wiz_wnd +); + +#endif diff --git a/shared/wizard97/src/res/default.css b/shared/wizard97/src/res/default.css new file mode 100644 index 0000000..db65be7 --- /dev/null +++ b/shared/wizard97/src/res/default.css @@ -0,0 +1,40 @@ +/** + * Default wizard97-specific styles + */ +.wintc-w97-title +{ + font-weight: bold; +} + +.wintc-w97-header +{ + background-color: @theme_base_color; + font-family: 'Microsoft Sans Serif', sans-serif; +} + +.wintc-w97-page-area +{ + font-family: 'Microsoft Sans Serif', sans-serif; +} + +.wintc-w97-header .wintc-w97-title +{ + margin-left: 18px; + margin-top: 8px; +} + +.wintc-w97-header .wintc-w97-subtitle +{ + margin-left: 25px +} + +.wintc-w97-exterior .wintc-w97-page-area +{ + background-color: @theme_base_color; +} + +.wintc-w97-page-area .wintc-w97-title +{ + font-size: 13pt; + margin: 8px 0px; +} diff --git a/shared/wizard97/src/res/default_p.css b/shared/wizard97/src/res/default_p.css new file mode 100644 index 0000000..05275b4 --- /dev/null +++ b/shared/wizard97/src/res/default_p.css @@ -0,0 +1,19 @@ +/** + * Default wizard97 priority styles + */ + +/** Unfortunately padding is app priority, because of #249 */ +.wintc-w97-header +{ + padding: 5px; +} + +.wintc-w97-exterior .wintc-w97-page-area +{ + padding: 8px; +} + +.wintc-w97-interior .wintc-w97-page-area +{ + padding: 12px 12px 12px 42px; +} diff --git a/shared/wizard97/src/res/resources.xml b/shared/wizard97/src/res/resources.xml new file mode 100644 index 0000000..3a5a326 --- /dev/null +++ b/shared/wizard97/src/res/resources.xml @@ -0,0 +1,10 @@ + + + + default.css + default_p.css + wizext.ui + wizint.ui + wizwnd.ui + + diff --git a/shared/wizard97/src/res/wizext.ui b/shared/wizard97/src/res/wizext.ui new file mode 100644 index 0000000..2aafff8 --- /dev/null +++ b/shared/wizard97/src/res/wizext.ui @@ -0,0 +1,42 @@ + + + + True + False + horizontal + + + + False + False + + + False + False + 0 + + + + + + False + False + vertical + + + + + True + True + 1 + + + + + + diff --git a/shared/wizard97/src/res/wizint.ui b/shared/wizard97/src/res/wizint.ui new file mode 100644 index 0000000..3a8d971 --- /dev/null +++ b/shared/wizard97/src/res/wizint.ui @@ -0,0 +1,106 @@ + + + + True + False + vertical + + + + True + False + horizontal + + + + True + False + vertical + + + + This is a title + True + False + 0.0 + + + + + False + False + 0 + + + + + And this is a subtitle + True + False + 0.0 + + + + + False + False + 1 + + + + + True + True + 0 + + + + + False + False + + + False + False + 1 + + + + + + + False + False + 0 + + + + + + False + False + vertical + + + + + True + True + 1 + + + + + + diff --git a/shared/wizard97/src/res/wizwnd.ui b/shared/wizard97/src/res/wizwnd.ui new file mode 100644 index 0000000..9fcc2e2 --- /dev/null +++ b/shared/wizard97/src/res/wizwnd.ui @@ -0,0 +1,125 @@ + + + + True + False + vertical + + + + True + False + vertical + + + + + True + True + 0 + + + + + True + False + horizontal + + + + Help + + True + True + win.help + + + False + False + end + 0 + + + + + + Cancel + True + True + True + win.cancel + + + False + False + end + 1 + + + + + + Finish + + True + True + win.next + + + False + False + end + 2 + + + + + + Next > + + True + True + win.next + + + False + False + end + 3 + + + + + + < Back + True + True + True + win.back + + + False + False + end + 4 + + + + + + + False + False + 1 + + + + diff --git a/shared/wizard97/src/wizpage.c b/shared/wizard97/src/wizpage.c new file mode 100644 index 0000000..ea48b89 --- /dev/null +++ b/shared/wizard97/src/wizpage.c @@ -0,0 +1,258 @@ +#include +#include +#include + +#include "../public/wizpage.h" + +// +// PRIVATE ENUMS +// +enum +{ + PROP_NULL, + PROP_TITLE, + PROP_SUBTITLE, + PROP_IS_FINAL_PAGE, + PROP_IS_EXTERIOR_PAGE, + N_PROPERTIES +}; + +// +// FORWARD DECLARATIONS +// +static void wintc_wizard97_page_finalize( + GObject* object +); +static void wintc_wizard97_page_get_property( + GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec +); +static void wintc_wizard97_page_set_property( + GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec +); + +// +// STATIC DATA +// +static GParamSpec* wintc_wizard97_page_properties[N_PROPERTIES] = { 0 }; + +// +// GTK OOP CLASS/INSTANCE DEFINITIONS +// +typedef struct _WinTCWizard97PagePrivate +{ + gchar* title; + gchar* subtitle; + gboolean is_final_page; + gboolean is_exterior_page; +} WinTCWizard97PagePrivate; + +// +// GTK TYPE DEFINITIONS & CTORS +// +G_DEFINE_TYPE_WITH_PRIVATE( + WinTCWizard97Page, + wintc_wizard97_page, + GTK_TYPE_BOX +) + +static void wintc_wizard97_page_class_init( + WinTCWizard97PageClass* klass +) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + + object_class->finalize = wintc_wizard97_page_finalize; + object_class->get_property = wintc_wizard97_page_get_property; + object_class->set_property = wintc_wizard97_page_set_property; + + wintc_wizard97_page_properties[PROP_TITLE] = + g_param_spec_string( + "title", + "Title", + "The title of the page.", + NULL, + G_PARAM_READWRITE + ); + wintc_wizard97_page_properties[PROP_SUBTITLE] = + g_param_spec_string( + "subtitle", + "Subtitle", + "The subtitle of the page.", + NULL, + G_PARAM_READWRITE + ); + wintc_wizard97_page_properties[PROP_IS_FINAL_PAGE] = + g_param_spec_boolean( + "is-final-page", + "IsFinalPage", + "Determines whether this is a final page in the wizard.", + FALSE, + G_PARAM_READWRITE + ); + wintc_wizard97_page_properties[PROP_IS_EXTERIOR_PAGE] = + g_param_spec_boolean( + "is-exterior-page", + "IsExteriorPage", + "Determines whether this is an exterior page.", + FALSE, + G_PARAM_READWRITE + ); + + g_object_class_install_properties( + object_class, + N_PROPERTIES, + wintc_wizard97_page_properties + ); +} + +static void wintc_wizard97_page_init( + WINTC_UNUSED(WinTCWizard97Page* self) +) {} + +// +// CLASS VIRTUAL METHODS +// +static void wintc_wizard97_page_finalize( + GObject* object +) +{ + WinTCWizard97PagePrivate* priv = + wintc_wizard97_page_get_instance_private( + WINTC_WIZARD97_PAGE(object) + ); + + g_free(priv->title); + g_free(priv->subtitle); + + (G_OBJECT_CLASS(wintc_wizard97_page_parent_class)) + ->finalize(object); +} + +static void wintc_wizard97_page_get_property( + GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec +) +{ + WinTCWizard97PagePrivate* priv = + wintc_wizard97_page_get_instance_private( + WINTC_WIZARD97_PAGE(object) + ); + + switch (prop_id) + { + case PROP_TITLE: + g_value_set_string(value, priv->title); + break; + + case PROP_SUBTITLE: + g_value_set_string(value, priv->subtitle); + break; + + case PROP_IS_FINAL_PAGE: + g_value_set_boolean(value, priv->is_final_page); + break; + + case PROP_IS_EXTERIOR_PAGE: + g_value_set_boolean(value, priv->is_exterior_page); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void wintc_wizard97_page_set_property( + GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec +) +{ + WinTCWizard97PagePrivate* priv = + wintc_wizard97_page_get_instance_private( + WINTC_WIZARD97_PAGE(object) + ); + + switch (prop_id) + { + case PROP_TITLE: + priv->title = g_value_dup_string(value); + break; + + case PROP_SUBTITLE: + priv->subtitle = g_value_dup_string(value); + break; + + case PROP_IS_FINAL_PAGE: + priv->is_final_page = g_value_get_boolean(value); + break; + + case PROP_IS_EXTERIOR_PAGE: + priv->is_exterior_page = g_value_get_boolean(value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +// +// PUBLIC FUNCTIONS +// +gboolean wintc_wizard97_page_get_is_exterior_page( + WinTCWizard97Page* wiz_page +) +{ + WinTCWizard97PagePrivate* priv = + wintc_wizard97_page_get_instance_private( + wiz_page + ); + + return priv->is_exterior_page; +} + +gboolean wintc_wizard97_page_get_is_final_page( + WinTCWizard97Page* wiz_page +) +{ + WinTCWizard97PagePrivate* priv = + wintc_wizard97_page_get_instance_private( + wiz_page + ); + + return priv->is_final_page; +} + +const gchar* wintc_wizard97_page_get_subtitle( + WinTCWizard97Page* wiz_page +) +{ + WinTCWizard97PagePrivate* priv = + wintc_wizard97_page_get_instance_private( + wiz_page + ); + + return priv->subtitle; +} + +const gchar* wintc_wizard97_page_get_title( + WinTCWizard97Page* wiz_page +) +{ + WinTCWizard97PagePrivate* priv = + wintc_wizard97_page_get_instance_private( + wiz_page + ); + + return priv->title; +} diff --git a/shared/wizard97/src/wizwnd.c b/shared/wizard97/src/wizwnd.c new file mode 100644 index 0000000..e71f6b6 --- /dev/null +++ b/shared/wizard97/src/wizwnd.c @@ -0,0 +1,1136 @@ +#include +#include +#include +#include +#include +#include + +#include "../public/wizpage.h" +#include "../public/wizwnd.h" + +#define WIZARD97_WATERMARK_WIDTH 164 +#define WIZARD97_WATERMARK_HEIGHT 314 + +#define WIZARD97_HEADERPIC_SIZE 49 + +#define WIZARD97_PAGE_NUM_FINAL 171717 + +// +// PRIVATE ENUMS +// +enum +{ + PROP_NULL, + PROP_CAN_CANCEL, + PROP_CAN_PREV, + PROP_CAN_NEXT, + PROP_CAN_HELP, + PROP_FINAL_PAGE, + N_PROPERTIES +}; + +// +// FORWARD DECLARATIONS +// +static void wintc_wizard97_window_dispose( + GObject* object +); +static void wintc_wizard97_window_finalize( + GObject* object +); +static void wintc_wizard97_window_get_property( + GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec +); +static void wintc_wizard97_window_set_property( + GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec +); + +static gboolean wintc_wizard97_window_cancel( + WinTCWizard97Window* wiz_wnd, + guint current_page +); +static void wintc_wizard97_window_constructing_page( + WinTCWizard97Window* wiz_wnd, + guint page_num, + GtkBuilder* builder +); +static gboolean wintc_wizard97_window_finish( + WinTCWizard97Window* wiz_wnd, + guint current_page +); +static guint wintc_wizard97_window_get_next_page( + WinTCWizard97Window* wiz_wnd, + guint current_page +); +static void wintc_wizard97_window_help( + WinTCWizard97Window* wiz_wnd, + guint current_page +); + +static GtkBuilder* wintc_wizard97_window_create_builder( + WinTCWizard97Window* wiz_wnd +); +static GtkWidget* wintc_wizard97_window_create_page( + WinTCWizard97Window* wiz_wnd, + const gchar* resource_path, + guint page_num +); +static GtkWidget* wintc_wizard97_window_get_page( + WinTCWizard97Window* wiz_wnd, + guint page_num +); +static void wintc_wizard97_window_go_to_page( + WinTCWizard97Window* wiz_wnd, + guint page_num, + gboolean push_history +); +static gboolean wintc_wizard97_window_is_on_final_page( + WinTCWizard97Window* wiz_wnd +); + +static void action_back( + GSimpleAction* action, + GVariant* parameter, + gpointer user_data +); +static void action_cancel( + GSimpleAction* action, + GVariant* parameter, + gpointer user_data +); +static void action_help( + GSimpleAction* action, + GVariant* parameter, + gpointer user_data +); +static void action_next( + GSimpleAction* action, + GVariant* parameter, + gpointer user_data +); + +static gboolean on_window_map_event( + GtkWidget* widget, + GdkEvent* event, + gpointer user_data +); + +// +// STATIC DATA +// +static GParamSpec* wintc_wizard97_window_properties[N_PROPERTIES] = { 0 }; + +static const GActionEntry S_ACTIONS[] = { + { + .name = "back", + .activate = action_back, + .parameter_type = NULL, + .state = NULL, + .change_state = NULL + }, + { + .name = "cancel", + .activate = action_cancel, + .parameter_type = NULL, + .state = NULL, + .change_state = NULL + }, + { + .name = "help", + .activate = action_help, + .parameter_type = NULL, + .state = NULL, + .change_state = NULL + }, + { + .name = "next", + .activate = action_next, + .parameter_type = NULL, + .state = NULL, + .change_state = NULL + } +}; +static const gchar* S_ACTION_BINDINGS[] = { + "back", "can-prev", + "cancel", "can-cancel", + "help", "can-help", + "next", "can-next" +}; + +// +// GTK OOP CLASS/INSTANCE DEFINITIONS +// +typedef struct _WinTCWizard97WindowPrivate +{ + // State + // + guint current_page; + GSList* history; + + // UI stuff + // + GtkWidget* box_page_area; + + GtkWidget* box_tmpl_ext_page_area; + GtkWidget* box_tmpl_int_page_area; + GtkWidget* img_ext_watermark; + GtkWidget* img_int_header; + GtkWidget* label_int_subtitle; + GtkWidget* label_int_title; + + // Stuff we maintain an additional ref to + // + GdkPixbuf* pixbuf_watermark; + GdkPixbuf* pixbuf_header; + + GList* list_pages; + + GtkWidget* box_tmpl_ext_page; + GtkWidget* box_tmpl_int_page; +} WinTCWizard97WindowPrivate; + +// +// GTK TYPE DEFINITIONS & CTORS +// +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE( + WinTCWizard97Window, + wintc_wizard97_window, + GTK_TYPE_WINDOW +) + +static void wintc_wizard97_window_class_init( + WinTCWizard97WindowClass* klass +) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + + klass->cancel = wintc_wizard97_window_cancel; + klass->constructing_page = wintc_wizard97_window_constructing_page; + klass->finish = wintc_wizard97_window_finish; + klass->help = wintc_wizard97_window_help; + klass->get_next_page = wintc_wizard97_window_get_next_page; + object_class->dispose = wintc_wizard97_window_dispose; + object_class->finalize = wintc_wizard97_window_finalize; + object_class->get_property = wintc_wizard97_window_get_property; + object_class->set_property = wintc_wizard97_window_set_property; + + // Install properties + // + wintc_wizard97_window_properties[PROP_CAN_CANCEL] = + g_param_spec_boolean( + "can-cancel", + "CanCancel", + "Determines whether it is possible to cancel the wizard.", + TRUE, + G_PARAM_READABLE + ); + wintc_wizard97_window_properties[PROP_CAN_PREV] = + g_param_spec_boolean( + "can-prev", + "CanPrev", + "Determines whether it is possible go backward in the wizard.", + TRUE, + G_PARAM_READABLE + ); + wintc_wizard97_window_properties[PROP_CAN_NEXT] = + g_param_spec_boolean( + "can-next", + "CanNext", + "Determines whether it is possible to proceed in the wizard.", + TRUE, + G_PARAM_READABLE + ); + wintc_wizard97_window_properties[PROP_CAN_HELP] = + g_param_spec_boolean( + "can-help", + "CanHelp", + "Determines whether it is possible to get help.", + FALSE, + G_PARAM_READABLE + ); + wintc_wizard97_window_properties[PROP_FINAL_PAGE] = + g_param_spec_boolean( + "final-page", + "FinalPage", + "Determines whether the wizard is on a final page.", + FALSE, + G_PARAM_READABLE + ); + + g_object_class_install_properties( + object_class, + N_PROPERTIES, + wintc_wizard97_window_properties + ); + + // Load styles + // + GtkCssProvider* css_default = gtk_css_provider_new(); + GtkCssProvider* css_default_p = gtk_css_provider_new(); + + gtk_css_provider_load_from_resource( + css_default, + "/uk/oddmatics/wintc/wizard97/default.css" + ); + gtk_css_provider_load_from_resource( + css_default_p, + "/uk/oddmatics/wintc/wizard97/default_p.css" + ); + + gtk_style_context_add_provider_for_screen( + gdk_screen_get_default(), + GTK_STYLE_PROVIDER(css_default), + GTK_STYLE_PROVIDER_PRIORITY_FALLBACK + ); + gtk_style_context_add_provider_for_screen( + gdk_screen_get_default(), + GTK_STYLE_PROVIDER(css_default_p), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + ); +} + +static void wintc_wizard97_window_init( + WINTC_UNUSED(WinTCWizard97Window* self) +) {} + +// +// CLASS VIRTUAL METHODS +// +static void wintc_wizard97_window_dispose( + GObject* object +) +{ + WinTCWizard97WindowPrivate* priv = + wintc_wizard97_window_get_instance_private( + WINTC_WIZARD97_WINDOW(object) + ); + + g_clear_object(&(priv->pixbuf_watermark)); + g_clear_object(&(priv->pixbuf_header)); + g_clear_list( + &(priv->list_pages), + (GDestroyNotify) g_object_unref + ); + + (G_OBJECT_CLASS(wintc_wizard97_window_parent_class)) + ->dispose(object); +} + +static void wintc_wizard97_window_finalize( + GObject* object +) +{ + WinTCWizard97WindowPrivate* priv = + wintc_wizard97_window_get_instance_private( + WINTC_WIZARD97_WINDOW(object) + ); + + g_slist_free( + g_steal_pointer(&(priv->history)) + ); + + (G_OBJECT_CLASS(wintc_wizard97_window_parent_class)) + ->finalize(object); +} + +static void wintc_wizard97_window_get_property( + GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec +) +{ + WinTCWizard97WindowPrivate* priv = + wintc_wizard97_window_get_instance_private( + WINTC_WIZARD97_WINDOW(object) + ); + + switch (prop_id) + { + case PROP_CAN_CANCEL: + g_value_set_boolean(value, TRUE); + break; + + case PROP_CAN_PREV: + g_value_set_boolean(value, !!(priv->history)); + break; + + case PROP_CAN_NEXT: + g_value_set_boolean(value, TRUE); + break; + + case PROP_CAN_HELP: + g_value_set_boolean(value, FALSE); + break; + + case PROP_FINAL_PAGE: + g_value_set_boolean( + value, + wintc_wizard97_window_is_on_final_page( + WINTC_WIZARD97_WINDOW(object) + ) + ); + + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void wintc_wizard97_window_set_property( + GObject* object, + guint prop_id, + WINTC_UNUSED(const GValue* value), + GParamSpec* pspec +) +{ + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static gboolean wintc_wizard97_window_cancel( + WINTC_UNUSED(WinTCWizard97Window* wiz_wnd), + WINTC_UNUSED(guint current_page) +) +{ + return TRUE; +} + +static void wintc_wizard97_window_constructing_page( + WINTC_UNUSED(WinTCWizard97Window* wiz_wnd), + WINTC_UNUSED(guint page_num), + WINTC_UNUSED(GtkBuilder* builder) +) {} + +static gboolean wintc_wizard97_window_finish( + WINTC_UNUSED(WinTCWizard97Window* wiz_wnd), + WINTC_UNUSED(guint current_page) +) +{ + return TRUE; +} + +static guint wintc_wizard97_window_get_next_page( + WinTCWizard97Window* wiz_wnd, + guint current_page +) +{ + WinTCWizard97WindowPrivate* priv = + wintc_wizard97_window_get_instance_private(wiz_wnd); + + if (current_page + 1 >= g_list_length(priv->list_pages)) + { + return WIZARD97_PAGE_NUM_FINAL; + } + + return current_page + 1; +} + +static void wintc_wizard97_window_help( + WINTC_UNUSED(WinTCWizard97Window* wiz_wnd), + WINTC_UNUSED(guint current_page) +) {} + +// +// PUBLIC FUNCTIONS +// +void wintc_wizard97_window_class_setup_from_resources( + WinTCWizard97WindowClass* wizard_class, + const gchar* resource_watermark, + const gchar* resource_header, + ... +) +{ + va_list ap; + gchar* next_res; + + wizard_class->resource_watermark = g_strdup(resource_watermark); + wizard_class->resource_header = g_strdup(resource_header); + + va_start(ap, resource_header); + + next_res = va_arg(ap, gchar*); + + while (next_res) + { + wizard_class->list_resources_pages = + g_list_append( + wizard_class->list_resources_pages, + g_strdup(next_res) + ); + + next_res = va_arg(ap, gchar*); + } + + va_end(ap); +} + +void wintc_wizard97_window_init_wizard( + WinTCWizard97Window* wiz_wnd +) +{ + WinTCWizard97WindowClass* wizard_class = + WINTC_WIZARD97_WINDOW_GET_CLASS(wiz_wnd); + + WinTCWizard97WindowPrivate* priv = + wintc_wizard97_window_get_instance_private( + WINTC_WIZARD97_WINDOW(wiz_wnd) + ); + + GtkBuilder* builder; + GError* error = NULL; + + g_type_ensure(WINTC_TYPE_WIZARD97_PAGE); + + // General GtkWindow setup + // + gtk_window_set_resizable(GTK_WINDOW(wiz_wnd), FALSE); + + // Add actions + // + GSimpleActionGroup* action_group = g_simple_action_group_new(); + + g_action_map_add_action_entries( + G_ACTION_MAP(action_group), + S_ACTIONS, + G_N_ELEMENTS(S_ACTIONS), + wiz_wnd + ); + + for (gsize i = 0; i < G_N_ELEMENTS(S_ACTION_BINDINGS); i += 2) + { + const gchar* action_name = S_ACTION_BINDINGS[i]; + const gchar* property_name = S_ACTION_BINDINGS[i + 1]; + + GAction* action = + g_action_map_lookup_action( + G_ACTION_MAP(action_group), + action_name + ); + + g_object_bind_property( + wiz_wnd, + property_name, + action, + "enabled", + G_BINDING_SYNC_CREATE + ); + } + + gtk_widget_insert_action_group( + GTK_WIDGET(wiz_wnd), + "win", + G_ACTION_GROUP(action_group) + ); + + g_object_unref(action_group); + + // External page template + // + builder = + gtk_builder_new_from_resource( + "/uk/oddmatics/wintc/wizard97/wizext.ui" + ); + + wintc_builder_get_objects( + builder, + "main-box", &(priv->box_tmpl_ext_page), + "box-page", &(priv->box_tmpl_ext_page_area), + "img-watermark", &(priv->img_ext_watermark), + NULL + ); + + g_object_ref(priv->box_tmpl_ext_page); + + g_clear_object(&builder); + + // Internal page template + // + builder = + gtk_builder_new_from_resource( + "/uk/oddmatics/wintc/wizard97/wizint.ui" + ); + + wintc_builder_get_objects( + builder, + "main-box", &(priv->box_tmpl_int_page), + "box-page", &(priv->box_tmpl_int_page_area), + "img-header", &(priv->img_int_header), + "label-subtitle", &(priv->label_int_subtitle), + "label-title", &(priv->label_int_title), + NULL + ); + + g_object_ref(priv->box_tmpl_int_page); + + g_clear_object(&builder); + + // Iterate over internal pages + // + GList* iter = wizard_class->list_resources_pages; + + for (guint i = 0; iter; iter = iter->next, i++) + { + GtkWidget* page = + wintc_wizard97_window_create_page( + wiz_wnd, + (gchar*) iter->data, + i + ); + + if (!page) + { + i--; + continue; + } + + if ( + wintc_wizard97_page_get_is_exterior_page( + WINTC_WIZARD97_PAGE(page) + ) + ) + { + gtk_widget_set_size_request( + page, + 317, + 193 + ); + } + else + { + gtk_widget_set_size_request( + page, + 317, + 143 + ); + } + + priv->list_pages = + g_list_append( + priv->list_pages, + page + ); + } + + // Pixbufs + // + if (wizard_class->resource_watermark) + { + GdkPixbuf* pixbuf_watermark_src = + gdk_pixbuf_new_from_resource( + wizard_class->resource_watermark, + &error + ); + + if (pixbuf_watermark_src) + { + priv->pixbuf_watermark = + gdk_pixbuf_scale_simple( + pixbuf_watermark_src, + WIZARD97_WATERMARK_WIDTH, + WIZARD97_WATERMARK_HEIGHT, + GDK_INTERP_NEAREST + ); + + g_object_unref(pixbuf_watermark_src); + + gtk_image_set_from_pixbuf( + GTK_IMAGE(priv->img_ext_watermark), + priv->pixbuf_watermark + ); + } + else + { + gtk_widget_set_size_request( + priv->img_ext_watermark, + WIZARD97_WATERMARK_WIDTH, + WIZARD97_WATERMARK_HEIGHT + ); + + wintc_log_error_and_clear(&error); + } + } + + if (wizard_class->resource_header) + { + GdkPixbuf* pixbuf_header_src = + gdk_pixbuf_new_from_resource( + wizard_class->resource_header, + &error + ); + + if (pixbuf_header_src) + { + priv->pixbuf_header = + gdk_pixbuf_scale_simple( + pixbuf_header_src, + WIZARD97_HEADERPIC_SIZE, + WIZARD97_HEADERPIC_SIZE, + GDK_INTERP_NEAREST + ); + + g_object_unref(pixbuf_header_src); + + gtk_image_set_from_pixbuf( + GTK_IMAGE(priv->img_int_header), + priv->pixbuf_header + ); + } + else + { + gtk_widget_set_size_request( + priv->img_int_header, + WIZARD97_HEADERPIC_SIZE, + WIZARD97_HEADERPIC_SIZE + ); + + wintc_log_error_and_clear(&error); + } + } + + // Set up the window + // + builder = gtk_builder_new(); + + gtk_builder_expose_object( + builder, + "wizard", + G_OBJECT(wiz_wnd) + ); + + gtk_builder_add_from_resource( + builder, + "/uk/oddmatics/wintc/wizard97/wizwnd.ui", + NULL + ); + + priv->box_page_area = + GTK_WIDGET( + gtk_builder_get_object(builder, "box-page-area") + ); + + gtk_container_add( + GTK_CONTAINER(wiz_wnd), + GTK_WIDGET( + gtk_builder_get_object(builder, "main-box") + ) + ); + + g_clear_object(&builder); + + // Unify page sizes - load each page, figure out the largest size, and make + // that our size request so the window doesn't grow/shrink between pages + // + GtkRequisition req; + GtkRequisition req_largest; + + iter = priv->list_pages; + + for (guint i = 0; iter; iter = iter->next, i++) + { + wintc_wizard97_window_go_to_page( + wiz_wnd, + i, + FALSE + ); + + gtk_widget_get_preferred_size( + priv->box_page_area, + NULL, + &req + ); + + req_largest.width = MAX(req_largest.width, req.width); + req_largest.height = MAX(req_largest.height, req.height); + } + + gtk_widget_set_size_request( + priv->box_page_area, + req_largest.width, + req_largest.height + ); + + // Connect to map event to finish start up after being shown + // + g_signal_connect( + wiz_wnd, + "map-event", + G_CALLBACK(on_window_map_event), + NULL + ); +} + +// +// PRIVATE FUNCTIONS +// +static GtkBuilder* wintc_wizard97_window_create_builder( + WinTCWizard97Window* wiz_wnd +) +{ + GtkBuilder* builder = gtk_builder_new(); + + gtk_builder_expose_object( + builder, + "wizard", + G_OBJECT(wiz_wnd) + ); + + return builder; +} + +static GtkWidget* wintc_wizard97_window_create_page( + WinTCWizard97Window* wiz_wnd, + const gchar* resource_path, + guint page_num +) +{ + WinTCWizard97WindowClass* wiz_class = + WINTC_WIZARD97_WINDOW_GET_CLASS(wiz_wnd); + + GtkBuilder* builder = wintc_wizard97_window_create_builder(wiz_wnd); + GError* error = NULL; + GtkWidget* ret = NULL; + + if ( + gtk_builder_add_from_resource( + builder, + resource_path, + &error + ) + ) + { + ret = GTK_WIDGET(gtk_builder_get_object(builder, "page")); + + if (!WINTC_IS_WIZARD97_PAGE(ret)) + { + g_critical( + "wizard97: the resource at %s doesn't have a 'page'", + resource_path + ); + } + + wiz_class->constructing_page( + wiz_wnd, + page_num, + builder + ); + + g_object_ref(ret); + } + else + { + wintc_log_error_and_clear(&error); + } + + g_object_unref(builder); + + return ret; +} + +static GtkWidget* wintc_wizard97_window_get_page( + WinTCWizard97Window* wiz_wnd, + guint page_num +) +{ + WinTCWizard97WindowPrivate* priv = + wintc_wizard97_window_get_instance_private( + WINTC_WIZARD97_WINDOW(wiz_wnd) + ); + + return GTK_WIDGET( + g_list_nth_data( + priv->list_pages, + page_num + ) + ); +} + +static void wintc_wizard97_window_go_to_page( + WinTCWizard97Window* wiz_wnd, + guint page_num, + gboolean push_history +) +{ + WinTCWizard97WindowPrivate* priv = + wintc_wizard97_window_get_instance_private( + WINTC_WIZARD97_WINDOW(wiz_wnd) + ); + + // Remove any existing page from view + // + GtkWidget* page_current = + wintc_wizard97_window_get_page( + wiz_wnd, + priv->current_page + ); + + if (gtk_widget_get_parent(page_current)) + { + gtk_container_remove( + GTK_CONTAINER(gtk_widget_get_parent(page_current)), + page_current + ); + } + + wintc_container_clear( + GTK_CONTAINER(priv->box_page_area), + FALSE + ); + + // Retrieve the boxes we need + // + GtkWidget* box_template; + GtkWidget* box_template_page_area; + GtkWidget* page_next; + + page_next = + wintc_wizard97_window_get_page( + wiz_wnd, + page_num + ); + + if ( + wintc_wizard97_page_get_is_exterior_page( + WINTC_WIZARD97_PAGE(page_next) + ) + ) + { + box_template = priv->box_tmpl_ext_page; + box_template_page_area = priv->box_tmpl_ext_page_area; + } + else + { + box_template = priv->box_tmpl_int_page; + box_template_page_area = priv->box_tmpl_int_page_area; + + gtk_label_set_text( + GTK_LABEL(priv->label_int_title), + wintc_wizard97_page_get_title( + WINTC_WIZARD97_PAGE(page_next) + ) + ); + gtk_label_set_text( + GTK_LABEL(priv->label_int_subtitle), + wintc_wizard97_page_get_subtitle( + WINTC_WIZARD97_PAGE(page_next) + ) + ); + } + + // Pack the page now + // + gtk_box_pack_start( + GTK_BOX(box_template_page_area), + page_next, + TRUE, + TRUE, + 0 + ); + + gtk_box_pack_start( + GTK_BOX(priv->box_page_area), + box_template, + TRUE, + TRUE, + 0 + ); + + gtk_widget_show_all(box_template); + + // Update state + // + if (push_history) + { + priv->history = + g_slist_prepend( + priv->history, + GUINT_TO_POINTER(priv->current_page) + ); + } + + priv->current_page = page_num; + + // Ping everything + // + for (gint i = PROP_CAN_PREV; i < N_PROPERTIES; i++) + { + g_object_notify_by_pspec( + G_OBJECT(wiz_wnd), + wintc_wizard97_window_properties[i] + ); + } +} + +static gboolean wintc_wizard97_window_is_on_final_page( + WinTCWizard97Window* wiz_wnd +) +{ + WinTCWizard97WindowPrivate* priv = + wintc_wizard97_window_get_instance_private(wiz_wnd); + + WinTCWizard97WindowClass* wiz_class = + WINTC_WIZARD97_WINDOW_GET_CLASS(wiz_wnd); + + if ( + wintc_wizard97_page_get_is_final_page( + WINTC_WIZARD97_PAGE( + wintc_wizard97_window_get_page(wiz_wnd, priv->current_page) + ) + ) || + wiz_class->get_next_page( + wiz_wnd, + priv->current_page + ) == WIZARD97_PAGE_NUM_FINAL + ) + { + return TRUE; + } + + + return FALSE; +} + +// +// CALLBACKS +// +static void action_back( + WINTC_UNUSED(GSimpleAction* action), + WINTC_UNUSED(GVariant* parameter), + gpointer user_data +) +{ + WinTCWizard97WindowPrivate* priv = + wintc_wizard97_window_get_instance_private( + WINTC_WIZARD97_WINDOW(user_data) + ); + + // Check what page we should go to + // + guint prev_page; + + if (!priv->history) + { + g_critical("%s", "wizard97: attempted to go back with no history"); + return; + } + + prev_page = GPOINTER_TO_UINT(priv->history->data); + + priv->history = + g_slist_delete_link( + priv->history, + priv->history + ); + + // Go! + // + wintc_wizard97_window_go_to_page( + WINTC_WIZARD97_WINDOW(user_data), + prev_page, + FALSE + ); +} + +static void action_cancel( + WINTC_UNUSED(GSimpleAction* action), + WINTC_UNUSED(GVariant* parameter), + gpointer user_data +) +{ + WinTCWizard97Window* wiz_wnd = WINTC_WIZARD97_WINDOW(user_data); + WinTCWizard97WindowClass* wiz_class = + WINTC_WIZARD97_WINDOW_GET_CLASS(wiz_wnd); + + WinTCWizard97WindowPrivate* priv = + wintc_wizard97_window_get_instance_private( + wiz_wnd + ); + + if (wiz_class->cancel(wiz_wnd, priv->current_page)) + { + gtk_window_close(GTK_WINDOW(user_data)); + } +} + +static void action_help( + WINTC_UNUSED(GSimpleAction* action), + WINTC_UNUSED(GVariant* parameter), + gpointer user_data +) +{ + WinTCWizard97Window* wiz_wnd = WINTC_WIZARD97_WINDOW(user_data); + WinTCWizard97WindowClass* wiz_class = + WINTC_WIZARD97_WINDOW_GET_CLASS(wiz_wnd); + + WinTCWizard97WindowPrivate* priv = + wintc_wizard97_window_get_instance_private( + wiz_wnd + ); + + wiz_class->help(wiz_wnd, priv->current_page); +} + +static void action_next( + WINTC_UNUSED(GSimpleAction* action), + WINTC_UNUSED(GVariant* parameter), + gpointer user_data +) +{ + WinTCWizard97Window* wiz_wnd = WINTC_WIZARD97_WINDOW(user_data); + WinTCWizard97WindowClass* wiz_class = + WINTC_WIZARD97_WINDOW_GET_CLASS(wiz_wnd); + + WinTCWizard97WindowPrivate* priv = + wintc_wizard97_window_get_instance_private( + wiz_wnd + ); + + if (wintc_wizard97_window_is_on_final_page(wiz_wnd)) + { + if (!wiz_class->finish(wiz_wnd, priv->current_page)) + { + return; + } + + gtk_window_close(GTK_WINDOW(wiz_wnd)); + } + else + { + wintc_wizard97_window_go_to_page( + WINTC_WIZARD97_WINDOW(user_data), + wiz_class->get_next_page(wiz_wnd, priv->current_page), + TRUE + ); + } +} + +static gboolean on_window_map_event( + GtkWidget* widget, + WINTC_UNUSED(GdkEvent* event), + WINTC_UNUSED(gpointer user_data) +) +{ + WinTCWizard97Window* wiz_wnd = WINTC_WIZARD97_WINDOW(widget); + + // Load the first page + // + wintc_wizard97_window_go_to_page( + wiz_wnd, + 0, + FALSE + ); + + return FALSE; +} diff --git a/shell/cpl/desk/src/pagedesk.c b/shell/cpl/desk/src/pagedesk.c index 636593b..9e0be8f 100644 --- a/shell/cpl/desk/src/pagedesk.c +++ b/shell/cpl/desk/src/pagedesk.c @@ -276,7 +276,11 @@ static void refresh_wallpaper_list( ) { g_list_free_full(wnd->list_wallpapers, g_free); - wintc_container_clear(GTK_CONTAINER(wnd->listbox_wallpapers)); + + wintc_container_clear( + GTK_CONTAINER(wnd->listbox_wallpapers), + TRUE + ); // Load up wallpapers // diff --git a/shell/explorer/src/toolbars/stdbar.c b/shell/explorer/src/toolbars/stdbar.c index 6e9ec52..e6b2677 100644 --- a/shell/explorer/src/toolbars/stdbar.c +++ b/shell/explorer/src/toolbars/stdbar.c @@ -576,7 +576,10 @@ static void populate_toolbar( { GtkWidget* toolbar = (WINTC_EXPLORER_TOOLBAR(toolbar_std))->toolbar; - wintc_container_clear(GTK_CONTAINER(toolbar)); + wintc_container_clear( + GTK_CONTAINER(toolbar), + TRUE + ); WINTC_LOG_DEBUG("explorer: populating std toolbar with %s", config_str); diff --git a/shell/taskband/src/start/personal.c b/shell/taskband/src/start/personal.c index fa414a4..cde9f10 100644 --- a/shell/taskband/src/start/personal.c +++ b/shell/taskband/src/start/personal.c @@ -778,7 +778,8 @@ static void refresh_personal_menu( // Clear existing items // wintc_container_clear( - GTK_CONTAINER(toolbar_start->personal.menubar_programs) + GTK_CONTAINER(toolbar_start->personal.menubar_programs), + TRUE ); // Set up signal tuple array diff --git a/tools/bldutils/depmap/apk-maps b/tools/bldutils/depmap/apk-maps index a7caba0..4736e42 100644 --- a/tools/bldutils/depmap/apk-maps +++ b/tools/bldutils/depmap/apk-maps @@ -44,6 +44,7 @@ wintc-shlang-->bt,rt-->libwintc-shlang wintc-sndapi-->bt,rt-->libwintc-sndapi wintc-syscfg-->bt,rt-->libwintc-syscfg wintc-winbrand-->bt,rt-->libwintc-winbrand +wintc-wizard97-->bt,rt-->libwintc-wizard97 xcursorgen-->bt,rt-->xcursorgen xdg-mime-->bt,rt-->xdg-utils xml2-->bt-->libxml2-dev diff --git a/tools/bldutils/depmap/archpkg-maps b/tools/bldutils/depmap/archpkg-maps index 01ea6c8..4e9f878 100644 --- a/tools/bldutils/depmap/archpkg-maps +++ b/tools/bldutils/depmap/archpkg-maps @@ -32,6 +32,7 @@ wintc-shlang-->bt,rt-->wintc-shlang wintc-sndapi-->bt,rt-->wintc-sndapi wintc-syscfg-->bt,rt-->wintc-syscfg wintc-winbrand-->bt,rt-->wintc-winbrand +wintc-wizard97-->bt,rt-->wintc-wizard97 xcursorgen-->bt,rt-->xorg-xcursorgen xdg-mime-->bt,rt-->xdg-utils xml2-->bt,rt-->libxml2 diff --git a/tools/bldutils/depmap/bsdpkg-maps b/tools/bldutils/depmap/bsdpkg-maps index 9a49d9f..d39ffc5 100644 --- a/tools/bldutils/depmap/bsdpkg-maps +++ b/tools/bldutils/depmap/bsdpkg-maps @@ -31,6 +31,7 @@ wintc-shlang-->bt,rt-->wintc-shlang wintc-sndapi-->bt,rt-->wintc-sndapi wintc-syscfg-->bt,rt-->wintc-syscfg wintc-winbrand-->bt,rt-->wintc-winbrand +wintc-wizard97-->bt,rt-->wintc-wizard97 xcursorgen-->bt,rt-->xcursorgen xdg-mime-->bt,rt-->xdg-utils xml2-->bt,rt-->libxml2 diff --git a/tools/bldutils/depmap/deb-maps b/tools/bldutils/depmap/deb-maps index e6576f3..a8133fa 100644 --- a/tools/bldutils/depmap/deb-maps +++ b/tools/bldutils/depmap/deb-maps @@ -45,6 +45,7 @@ wintc-shlang-->bt,rt-->libwintc-shlang wintc-sndapi-->bt,rt-->libwintc-sndapi wintc-syscfg-->bt,rt-->libwintc-syscfg wintc-winbrand-->bt,rt-->libwintc-winbrand +wintc-wizard97-->bt,rt-->libwintc-wizard97 xcursorgen-->bt,rt-->x11-apps xdg-mime-->bt,rt-->xdg-utils xml2-->bt-->libxml2-dev diff --git a/tools/bldutils/depmap/rpm-maps b/tools/bldutils/depmap/rpm-maps index 365d38d..23b34ee 100644 --- a/tools/bldutils/depmap/rpm-maps +++ b/tools/bldutils/depmap/rpm-maps @@ -44,6 +44,7 @@ wintc-shlang-->bt,rt-->wintc-shlang wintc-sndapi-->bt,rt-->wintc-sndapi wintc-syscfg-->bt,rt-->wintc-syscfg wintc-winbrand-->bt,rt-->wintc-winbrand +wintc-wizard97-->bt,rt-->wintc-wizard97 xcursorgen-->bt,rt-->xcursorgen xdg-mime-->bt,rt-->xdg-utils xml2-->bt-->libxml2-devel diff --git a/tools/bldutils/depmap/xbps-maps b/tools/bldutils/depmap/xbps-maps index 68bbc1e..188ad96 100644 --- a/tools/bldutils/depmap/xbps-maps +++ b/tools/bldutils/depmap/xbps-maps @@ -44,6 +44,7 @@ wintc-shlang-->bt,rt-->wintc-shlang wintc-sndapi-->bt,rt-->wintc-sndapi wintc-syscfg-->bt,rt-->wintc-syscfg wintc-winbrand-->bt,rt-->wintc-winbrand +wintc-wizard97-->bt,rt-->wintc-wizard97 xcursorgen-->bt,rt-->xcursorgen xdg-mime-->bt,rt-->xdg-utils xml2-->bt-->libxml2-devel