Jump to content

GTK4 UDF


smbape
 Share

Recommended Posts

After EmguCV (OpenCV wrapper) UDF , I wanted to improve the concept of generating autoit udf bindings from c/c++ source files.

GTK was a project that get my attention.

That means:

  • It is a heavy  UDF with more that 8900 functions since they were generated from the gtk source files
  • Complex gtk applications can be done with the UDF

Functions keep the same name as in the source files prefixed with an underscore.

The project is available here

Prerequisites

Examples

The classic Hello World

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

Opt("MustDeclareVars", 1)

#Region ; when you don't know where the functions are
; - include all files
; - use Ctrl+J at each function to go to their location
; - add an include of the located file
; - redo until all your functions are found
; - then you can remove the include of gtk_all.au3 which is two times slower to start with
; #include "gtk-autoit-bindings\gtk_all.au3"
#EndRegion ; when you don't know where the functions are

#Region ; when you know where the functions are
#include "gtk-autoit-bindings\include\glib-2.0\gio\gapplication.au3"
#include "gtk-autoit-bindings\include\glib-2.0\gobject\gobject.au3"
#include "gtk-autoit-bindings\include\gtk-4.0\gtk\gtkapplication.au3"
#include "gtk-autoit-bindings\include\gtk-4.0\gtk\gtkapplicationwindow.au3"
#include "gtk-autoit-bindings\include\gtk-4.0\gtk\gtkbutton.au3"
#include "gtk-autoit-bindings\include\gtk-4.0\gtk\gtkwindow.au3"
#EndRegion ; when you know where the functions are

#include "gtk-autoit-bindings\gtk_callback.au3"
#include "gtk-autoit-bindings\gtk_extra.au3"

_Gtk_Open("gtk-windows-4.3.2\bin")
main()
_Gtk_Close()

Func print_hello($widget, $data)
  ConsoleWrite("Hello World" & @CRLF)
EndFunc   ;==>print_hello

Func activate($app, $user_data)
  Local $window = _gtk_application_window_new($app)
  _gtk_window_set_title($window, "Window")
  _gtk_window_set_default_size($window, 200, 200)

  Local $button = _gtk_button_new_with_label("Hello World")
  _g_signal_connect($button, "clicked", _gtk_callback("print_hello"), NULL)
  _gtk_window_set_child($window, $button)

  _gtk_window_present($window)
EndFunc   ;==>activate

Func main()
  Local $app = _gtk_application_new("com.autoitscript.gtk.example", $G_APPLICATION_FLAGS_NONE)
  _g_signal_connect($app, "activate", _gtk_callback("activate"), NULL)
  Local $status = _g_application_run($app, 0, 0)
  _g_object_unref($app)
EndFunc   ;==>main

A more complex one

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

; Sources:
; https://docs.gtk.org/gtk4/getting_started.html#packing-buttons-with-gtkbuilder

Opt("MustDeclareVars", 1)

#Region ; when you don't know where the functions are
; - include all files
; - use Ctrl+J at each function to go to their location
; - add an include of the located file
; - redo until all your functions are found
; - then you can remove the include of gtk_all.au3 which is two times slower to start with
; #include "gtk-autoit-bindings\gtk_all.au3"
#EndRegion ; when you don't know where the functions are

#Region ; when you know where the functions are
#include "gtk-autoit-bindings\include\glib-2.0\gio\gapplication.au3"
#include "gtk-autoit-bindings\include\glib-2.0\gio\gfile.au3"
#include "gtk-autoit-bindings\include\glib-2.0\glib\gmem.au3"
#include "gtk-autoit-bindings\include\glib-2.0\gobject\gobject.au3"
#include "gtk-autoit-bindings\include\gtk-4.0\gtk\gtkapplication.au3"
#include "gtk-autoit-bindings\include\gtk-4.0\gtk\gtkbuilder.au3"
#include "gtk-autoit-bindings\include\gtk-4.0\gtk\gtkscrolledwindow.au3"
#include "gtk-autoit-bindings\include\gtk-4.0\gtk\gtkstack.au3"
#include "gtk-autoit-bindings\include\gtk-4.0\gtk\gtktextbuffer.au3"
#include "gtk-autoit-bindings\include\gtk-4.0\gtk\gtktextview.au3"
#include "gtk-autoit-bindings\include\gtk-4.0\gtk\gtkwidget.au3"
#include "gtk-autoit-bindings\include\gtk-4.0\gtk\gtkwindow.au3"
#EndRegion ; when you know where the functions are

#include "gtk-autoit-bindings\gtk_callback.au3"
#include "gtk-autoit-bindings\gtk_extra.au3"

Local $application = DllStructCreate("ptr window; ptr stack")

_Gtk_Open("gtk-windows-4.3.2\bin")
main()
_Gtk_Close()

Func application_init($app)
    ; Construct a GtkBuilder instance and load our UI description
    Local $builder = _gtk_builder_new()
    _gtk_builder_add_from_file($builder, "window.ui", Null)

    $application.window = _gtk_builder_get_object($builder, "window")
    $application.stack = _gtk_builder_get_object($builder, "stack")

    ; We do not need the builder any more
    _g_object_unref($builder)

    _gtk_window_set_application($application.window, $app)
EndFunc   ;==>application_init

Func activate($app, $user_data)
    application_init($app)

    ; show these files by default
    Local $argv[2] = ["main.au3", "window.ui"]
    Local $file

    For $i = 0 To UBound($argv) - 1
        $file = _g_file_new_for_path($argv[$i])
        open_file($file)
        _g_object_unref($file)
    Next

    _gtk_window_present($application.window)
EndFunc   ;==>activate

Func open_file($file)
    Local $contents = DllStructCreate("ptr value")
    Local $length = DllStructCreate("uint64 value")

    Local $basename = _g_file_get_basename($file)

    Local $scrolled = _gtk_scrolled_window_new()
    _gtk_widget_set_hexpand($scrolled, True)
    _gtk_widget_set_vexpand($scrolled, True)
    Local $view = _gtk_text_view_new()
    _gtk_text_view_set_editable($view, False)
    _gtk_text_view_set_cursor_visible($view, False)
    _gtk_scrolled_window_set_child($scrolled, $view)
    _gtk_stack_add_titled($application.stack, $scrolled, $basename, $basename)

    If _g_file_load_contents($file, Null, $contents, $length, Null, Null) Then
        Local $buffer = _gtk_text_view_get_buffer($view)
        _gtk_text_buffer_set_text($buffer, $contents.value, $length.value)
        _g_free($contents.value)
    EndIf

    _g_free($basename)
EndFunc   ;==>open_file

Func open($app, $files, $n_files, $hint)
    Local $windows = _gtk_application_get_windows($app)
    Local $win

    If $windows Then
        $windows = DllStructCreate($tagGList, $windows)
        $win = $windows.data
    Else
        application_init($app)
        $win = $application.window
    EndIf

    $files = DllStructCreate("ptr value[" & $n_files & "]", $files)
    For $i = 1 To $n_files
        open_file($files.value(($i)))
    Next

    _gtk_window_present($win)
EndFunc   ;==>open

Func main()
    Local $argc = UBound($CmdLine)
    Local $argv = DllStructCreate("ptr value[" & $argc & "]")

    ; create an array to keep reference to structs until the end of the function
    Local $tmp[$argc]
    Local $str

    For $i = 0 To $argc - 1
        $str = $CmdLine[$i]
        $tmp[$i] = DllStructCreate("char value[" & BinaryLen(StringToBinary($str)) + 1 & "]")
        $tmp[$i].value = $str
        $argv.value(($i + 1)) = DllStructGetPtr($tmp[$i])
    Next

    Local $app = _gtk_application_new("com.autoitscript.gtk.example", $G_APPLICATION_HANDLES_OPEN)
    _g_signal_connect($app, "activate", _gtk_callback("activate"), Null) ;
    _g_signal_connect($app, "open", _gtk_callback("open", "none:cdecl", "ptr;ptr;int;str"), Null)

    ; on windows, argv is completely ignored
    ; it is directly taken from the command line
    ; see https://gitlab.gnome.org/GNOME/glib/-/blob/2.69.2/gio/gapplication.c#L2460
    Local $status = _g_application_run($app, $argc, $argv)
    _g_object_unref($app)

    Return $status
EndFunc   ;==>main

window.ui

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <object id="window" class="GtkWindow">
    <property name="title" translatable="yes">Example Application</property>
    <property name="default-width">600</property>
    <property name="default-height">400</property>
    <child type="titlebar">
      <object class="GtkHeaderBar" id="header">
        <child type="title">
          <object class="GtkStackSwitcher" id="tabs">
            <property name="stack">stack</property>
          </object>
        </child>
      </object>
    </child>
    <child>
      <object class="GtkBox" id="content_box">
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkStack" id="stack"/>
        </child>
      </object>
    </child>
  </object>
</interface>

More examples are available here

A note on performance

Before trying to convert everything to the autoit equivalent, keep in mind that autoit is slow when dealing with loops.
For that reason, I recommend to create a dll that export functions that do the loops.
autoit-addon is a dll project example.

 

Link to comment
Share on other sites

  • 2 weeks later...
4 hours ago, supersonic said:

Can you provide a ListView example with 10+ columns and at least 1000 rows, please?

It may sound surprising, but I only know the basics of GTK. The UDF was generated by a script.
The things I know can be found in the Docs / Getting Started / Hello World and Gtk - 4.0: Getting Started with GTK

However, if you have a c++ or python code, I can translate it into the UDF for you.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...