├── pir └── .gitignore ├── examples ├── parrot_small.png ├── table.winxed ├── testgtk.winxed └── jsontree.winxed ├── README ├── WinxedGtk.winxhead ├── Makefile ├── setup.winxed └── src └── WinxedGtk.winxed /pir/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/parrot_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notfound/WinxedGtk/master/examples/parrot_small.png -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | WinxedGtk - A Gtk module for parrot via NCI. 2 | 3 | (C) 2011 Julián Albo "NotFound" 4 | 5 | Early bird version, use with care. 6 | 7 | Use make before setup.winxed. 8 | -------------------------------------------------------------------------------- /WinxedGtk.winxhead: -------------------------------------------------------------------------------- 1 | // Include file for WinxedGtk module 2 | 3 | namespace WinxedGtk 4 | { 5 | 6 | class VBox; 7 | class HBox; 8 | class ScrolledWindow; 9 | class Window; 10 | class Label; 11 | class Button; 12 | class Entry; 13 | class TextView; 14 | class DrawingArea; 15 | class Image; 16 | class Tree; 17 | class TreeItem; 18 | class MenuBar; 19 | class MenuItem; 20 | class Menu; 21 | class CList; 22 | 23 | } 24 | 25 | // End 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for WinxedGtk 2 | 3 | # winxed must be accesible in the PATH 4 | 5 | default: build 6 | 7 | #----------------------------------------------------------------------- 8 | 9 | build: build/WinxedGtk.pbc 10 | 11 | build/WinxedGtk.pbc: pir/WinxedGtk.pir 12 | winxed setup.winxed build 13 | 14 | pir/WinxedGtk.pir: src/WinxedGtk.winxed 15 | winxed -c -o pir/WinxedGtk.pir src/WinxedGtk.winxed 16 | 17 | #----------------------------------------------------------------------- 18 | 19 | install: build/WinxedGtk.pbc 20 | winxed setup.winxed install 21 | 22 | uninstall: build/WinxedGtk.pbc 23 | winxed setup.winxed uninstall 24 | 25 | #----------------------------------------------------------------------- 26 | 27 | clean: 28 | winxed setup.winxed clean 29 | rm -rf pir/WinxedGtk.pir 30 | 31 | # End 32 | -------------------------------------------------------------------------------- /setup.winxed: -------------------------------------------------------------------------------- 1 | #! winxed 2 | # (C) 2011 Julián Albo 3 | 4 | /* 5 | = head1 NAME 6 | 7 | Setup for WinxedGtk 8 | 9 | =head1 DESCRIPTION 10 | 11 | Setup program for WinxedGtk using parrot distutils. 12 | 13 | =head1 USAGE 14 | 15 | Handle with care. 16 | 17 | =cut 18 | */ 19 | 20 | $load 'Getopt/Obj.pbc'; 21 | $load 'distutils.pbc'; 22 | 23 | //********************************************************************** 24 | 25 | function main(argv) 26 | { 27 | string progname = argv.shift(); 28 | 29 | var data = 30 | //BEGIN_JSON_SETUP 31 | { 32 | "name" : "WinxedGtk", 33 | "version" : "0.0.0", 34 | 35 | "abstract" : "Gtk module", 36 | "description" : "Parrot Gtk bindings via Native Call Interface", 37 | "keywords" : [ 38 | "Gtk", "winxed" 39 | ], 40 | 41 | "copyright_holder" : "Julián Albo", 42 | "license_type" : "Artistic License 2.0", 43 | "license_uri" : "http://www.perlfoundation.org/artistic_license_2_0", 44 | 45 | "pir_winxed" : { 46 | "pir/WinxedGtk.pir" : "src/WinxedGtk.winxed" 47 | }, 48 | "pbc_pir" : { 49 | "build/WinxedGtk.pbc" : "pir/WinxedGtk.pir" 50 | }, 51 | "inst_inc" : "WinxedGtk.winxhead", 52 | "inst_lib" : "build/WinxedGtk.pbc" 53 | } 54 | //END_JSON_SETUP 55 | ; 56 | 57 | setup(argv:[flat], data:[flat,named]); 58 | } 59 | 60 | // End 61 | -------------------------------------------------------------------------------- /examples/table.winxed: -------------------------------------------------------------------------------- 1 | // CList - Pruebas WinxedGtk 2 | 3 | $load 'WinxedGtk.pbc'; 4 | $load 'Mysql.pbc'; 5 | 6 | $include 'WinxedGtk.winxhead'; 7 | 8 | //********************************************************************** 9 | 10 | 11 | using namespace WinxedGtk; 12 | 13 | class TableWindow : Window 14 | { 15 | function TableWindow(result) 16 | { 17 | self.Window(0); 18 | self.set_border_width(8); 19 | self.set_title('WinxedGtk tree view test'); 20 | self.signal_connect('destroy', 21 | function () 22 | { 23 | using WinxedGtk.gtk_main_quit; 24 | gtk_main_quit(); 25 | } 26 | ); 27 | var vbox = new VBox(0, 4); 28 | var label = new Label('Table'); 29 | 30 | var image = new Image('parrot_small.png'); 31 | image.show(); 32 | label.show(); 33 | 34 | int ncolumns = result.field_count(); 35 | var table = new CList(ncolumns); 36 | for (int i = 0; i < ncolumns; ++i) 37 | table.set_column_title(i, "Column" + string(i + 1)); 38 | table.column_titles_show(); 39 | var row; 40 | int rowcount = 0; 41 | while ((row = result.fetch_row()) != null) { 42 | // There is some problem when setting the row, directly. 43 | // Until fixed, set with empty strings and then 44 | // set each column value at once. 45 | string data[ncolumns]; 46 | for (int i = 0; i < ncolumns; ++i) 47 | data[i] = ''; 48 | table.append(data); 49 | for (int i = 0; i < ncolumns; ++i) { 50 | string r = row.get(i); 51 | if (r == null) 52 | r = '(null)'; 53 | table.set_text(rowcount, i, r); 54 | } 55 | ++rowcount; 56 | } 57 | 58 | table.show(); 59 | 60 | var hbox = new HBox(1, 4); 61 | 62 | var buttonclose = new Button('close'); 63 | buttonclose.signal_connect('clicked', 64 | function () 65 | { 66 | self.destroy(); 67 | } 68 | ); 69 | buttonclose.show(); 70 | hbox.pack_start(buttonclose, 0, 0, 0); 71 | 72 | vbox.pack_start(image, 0, 0, 4); 73 | vbox.pack_start(label, 0, 0, 6); 74 | vbox.add(table); 75 | vbox.pack_start(hbox, 0, 0, 6); 76 | 77 | self.add(vbox); 78 | hbox.show(); 79 | vbox.show(); 80 | } 81 | } 82 | 83 | namespace WinxedMysql 84 | { 85 | class Connection; 86 | } 87 | 88 | function main(args) 89 | { 90 | using WinxedGtk.init; 91 | using WinxedGtk.gtk_main; 92 | 93 | cry(elements(args)); 94 | string query = elements(args) > 1 ? args[1] : "select * from hello;"; 95 | 96 | say('Initializing'); 97 | init(args); 98 | 99 | var mysql = new WinxedMysql.Connection(); 100 | say('Mysql version: ', mysql.get_client_info()); 101 | mysql.connect("localhost", "parrot", "baDworD", "parrot", "utf8"); 102 | 103 | mysql.query(query); 104 | //mysql.query("describe hello;"); 105 | 106 | var result = mysql.use_result(); 107 | 108 | var window = new TableWindow(result); 109 | result.close(); 110 | 111 | window.show(); 112 | say('Running'); 113 | gtk_main(); 114 | 115 | say('End'); 116 | } 117 | 118 | // End 119 | -------------------------------------------------------------------------------- /examples/testgtk.winxed: -------------------------------------------------------------------------------- 1 | // Pruebas gtk 2 | 3 | $load 'WinxedGtk.pbc'; 4 | 5 | //********************************************************************** 6 | 7 | $include 'WinxedGtk.winxhead'; 8 | 9 | using namespace WinxedGtk; 10 | 11 | function show(widget) 12 | { 13 | widget.show(); 14 | return widget; 15 | } 16 | 17 | class SimpleTestWindow : Window 18 | { 19 | var entry; 20 | function SimpleTestWindow() 21 | { 22 | self.Window(0); 23 | self.set_border_width(0); 24 | self.set_title('WinxedGtk simple test'); 25 | self.signal_connect('destroy', function () { self.exit(); } ); 26 | 27 | var mainbox = new VBox(0, 0); 28 | var vbox = new VBox(0, 4); 29 | vbox.set_border_width(10); 30 | 31 | var itemexit = new MenuItem('exit'); 32 | itemexit.show(); 33 | itemexit.signal_connect('activate', function () { self.exit(); } ); 34 | var menufile = new Menu(); 35 | menufile.show(); 36 | menufile.append(itemexit); 37 | var itemfile = new MenuItem('File'); 38 | itemfile.show(); 39 | itemfile.set_submenu(menufile); 40 | 41 | var submenuitem = new MenuItem('subtest'); 42 | var submenu = new Menu(); 43 | submenu.append(submenuitem); 44 | var item = new MenuItem('test'); 45 | var menu = new MenuBar(); 46 | menu.append(itemfile); 47 | menu.append(item); 48 | item.set_submenu(submenu); 49 | mainbox.pack_start(menu, false, false, 0); 50 | mainbox.add(vbox); 51 | mainbox.show(); 52 | self.add(mainbox); 53 | 54 | submenuitem.show(); 55 | item.show(); 56 | submenu.show(); 57 | menu.show(); 58 | submenuitem.signal_connect('activate', 59 | function () 60 | { 61 | say('submenu item activated'); 62 | } 63 | ); 64 | 65 | var image = new Image('parrot_small.png'); 66 | image.show(); 67 | 68 | self.entry = new Entry(); 69 | self.entry.show(); 70 | var hbox = new HBox(1, 4); 71 | 72 | var tree = new Tree(); 73 | tree.show(); 74 | var item2 = new TreeItem('item'); 75 | tree.append(item2); 76 | item2.show(); 77 | var subtree = new Tree(); 78 | var subitem = new TreeItem('subitem'); 79 | subtree.append(subitem); 80 | item2.set_subtree(subtree); 81 | subtree.show(); 82 | subitem.show(); 83 | item2.show(); 84 | 85 | var text = new TextView(); 86 | //text.insert('Some text...'); 87 | text.set_editable(true); 88 | text.show(); 89 | 90 | var drawing; 91 | using WinxedGtk.gtk_check_version; 92 | string check = gtk_check_version(2, 14, 0); 93 | if (check != null) 94 | cry("Omiting DrawingArea test: " + check); 95 | else { 96 | drawing = new DrawingArea(); 97 | drawing.set_size_request(600, 400); 98 | drawing.signal_connect('expose_event', 99 | function () 100 | { 101 | cry('Exposed'); 102 | drawing.draw_rectangle(100, 100, 400, 100); 103 | } 104 | ); 105 | drawing.show(); 106 | } 107 | 108 | var button = new Button('say hello'); 109 | button.signal_connect('clicked', 110 | function () 111 | { 112 | string t = self.entry.get_text(); 113 | if (t != null && length(t) > 0) 114 | say('hello, ', t); 115 | else 116 | say('hello'); 117 | if (text.get_char_count() > 0) { 118 | t = text.get_text(); 119 | say("Here is some text:\n", t); 120 | } 121 | } 122 | ); 123 | var buttonclose = new Button('close'); 124 | buttonclose.signal_connect('clicked', 125 | function () 126 | { 127 | self.destroy(); 128 | } 129 | ); 130 | button.show(); 131 | buttonclose.show(); 132 | hbox.pack_start(button, 0, 0, 0); 133 | hbox.pack_start(buttonclose, 0, 0, 0); 134 | 135 | var label; 136 | vbox.add(show(new Label('This is a simple Window example'))); 137 | vbox.add(image); 138 | vbox.add((label =show(new Label('A Tree widget')))); 139 | label.set_alignment(0.0, 0.5); 140 | vbox.add(tree); 141 | vbox.add((label = show(new Label('A Entry widget')))); 142 | label.set_alignment(1.0, 0.5); 143 | vbox.add(self.entry); 144 | vbox.add(show(new Label('A Text widget'))); 145 | vbox.add(text); 146 | if (drawing != null) { 147 | vbox.add(show(new Label('A DrawingArea widget'))); 148 | vbox.add(drawing); 149 | } 150 | 151 | vbox.pack_start(hbox, 0, 0, 0); 152 | 153 | //self.add(vbox); 154 | hbox.show(); 155 | vbox.show(); 156 | 157 | } 158 | function exit() 159 | { 160 | using WinxedGtk.gtk_main_quit; 161 | gtk_main_quit(); 162 | } 163 | } 164 | 165 | function main(args) 166 | { 167 | using WinxedGtk.init; 168 | using WinxedGtk.gtk_main; 169 | 170 | say('Initializing'); 171 | init(args); 172 | 173 | var window = new SimpleTestWindow(); 174 | window.show(); 175 | say('Running'); 176 | gtk_main(); 177 | 178 | say('End'); 179 | } 180 | 181 | // End 182 | -------------------------------------------------------------------------------- /examples/jsontree.winxed: -------------------------------------------------------------------------------- 1 | #! winxed 2 | 3 | // JSON tree view - Pruebas WinxedGtk 4 | 5 | $load 'WinxedGtk.pbc'; 6 | 7 | $include 'WinxedGtk.winxhead'; 8 | 9 | //********************************************************************** 10 | 11 | using namespace WinxedGtk; 12 | 13 | // Set to 1 to compile a debug version. 14 | const int DEBUG = 0; 15 | 16 | class JsonTreeWindow : Window 17 | { 18 | function JsonTreeWindow(string filename, data) 19 | { 20 | self.Window(0); 21 | self.set_title('WinxedGtk tree view test'); 22 | self.set_border_width(0); 23 | self.signal_connect('destroy', 24 | function () 25 | { 26 | using WinxedGtk.gtk_main_quit; 27 | gtk_main_quit(); 28 | } 29 | ); 30 | var mainbox = new VBox(0, 0); 31 | mainbox.show(); 32 | var itemquit = new MenuItem('quit'); 33 | itemquit.signal_connect('activate', 34 | function () { self.destroy(); } ); 35 | itemquit.show(); 36 | var menubar = new MenuBar(); 37 | menubar.show(); 38 | var itemfile = new MenuItem('File'); 39 | itemfile.show(); 40 | var menufile = new Menu(); 41 | menufile.append(itemquit); 42 | menufile.show(); 43 | itemfile.set_submenu(menufile); 44 | menubar.append(itemfile); 45 | mainbox.pack_start(menubar, false, false, 0); 46 | 47 | var vbox = new VBox(0, 4); 48 | vbox.set_border_width(8); 49 | var label = new Label('JSON tree view'); 50 | var label2 = new Label(filename); 51 | 52 | var image = new Image('parrot_small.png'); 53 | image.show(); 54 | 55 | label.show(); 56 | label2.show(); 57 | var hbox = new HBox(1, 4); 58 | 59 | var tree = new Tree(); 60 | add_object(tree, data); 61 | tree.show(); 62 | 63 | var buttonclose = new Button('close'); 64 | buttonclose.signal_connect('clicked', 65 | function () { self.destroy(); } ); 66 | buttonclose.show(); 67 | hbox.pack_start(buttonclose, 0, 0, 0); 68 | 69 | vbox.pack_start(image, 0, 0, 4); 70 | vbox.pack_start(label, 0, 0, 10); 71 | 72 | var scrolled = new ScrolledWindow(); 73 | scrolled.add_with_viewport(tree); 74 | scrolled.set_policy(1, 1); 75 | vbox.pack_start(scrolled, true, true, 0); 76 | scrolled.show(); 77 | 78 | vbox.pack_start(label2, 0, 0, 6); 79 | vbox.pack_start(hbox, 0, 0, 6); 80 | 81 | mainbox.add(vbox); 82 | self.add(mainbox); 83 | hbox.show(); 84 | vbox.show(); 85 | } 86 | } 87 | 88 | function add_object(tree, object) 89 | { 90 | var item; 91 | switch { 92 | case object instanceof ['ResizablePMCArray']: 93 | int n = elements(object); 94 | for (int i = 0; i < n; ++i) { 95 | item = new TreeItem(string(i)); 96 | var subtree = new Tree(); 97 | add_object(subtree, object[i]); 98 | tree.append(item); 99 | subtree.show(); 100 | item.set_subtree(subtree); 101 | item.show(); 102 | } 103 | break; 104 | case object instanceof ['Hash']: 105 | for (string key in object) { 106 | item = new TreeItem(key); 107 | var subtree = new Tree(); 108 | add_object(subtree, object[key]); 109 | tree.append(item); 110 | subtree.show(); 111 | item.set_subtree(subtree); 112 | item.show(); 113 | } 114 | break; 115 | default: 116 | string str = object; 117 | item = new TreeItem(str); 118 | tree.append(item); 119 | item.show(); 120 | } 121 | } 122 | 123 | function read_data(string filename, string startmark, string endmark) 124 | { 125 | var json = load_language('data_json'); 126 | var text; 127 | if (substr(filename, 0, 7) == "http://") { 128 | using extern LWP.UserAgent; 129 | var ua = new ['LWP', 'UserAgent']; 130 | var nargs = { 131 | 'Connection' : 'close' 132 | }; 133 | var resp = ua.get(filename, nargs:[named,flat]); 134 | int code = resp.code; 135 | if (code != 200) 136 | throw "Failed to load from url: " + string(code); 137 | // LWP currently does not provide a way to automatically apply 138 | // the encoding, thus do it here. 139 | var b = new ['ByteBuffer']; 140 | b =: string(resp.content); 141 | text = b.get_string('utf8'); 142 | } 143 | else { 144 | var file = open(filename); 145 | file.encoding('utf8'); 146 | text = file.readall(); 147 | file.close(); 148 | } 149 | 150 | if (startmark != null) { 151 | string mark = "\n" + startmark + "\n"; 152 | int pos = indexof(text, mark); 153 | if (pos >= 0) { 154 | int cutinitpos = pos + length(mark); 155 | if (endmark == null) 156 | text = substr(text, cutinitpos); 157 | else { 158 | mark = "\n" + endmark + "\n"; 159 | int cutlength; 160 | pos = indexof(text, mark, cutinitpos); 161 | if (pos >= 0) 162 | text = substr(text, cutinitpos, pos - cutinitpos + 1); 163 | else 164 | text = substr(text, cutinitpos); 165 | } 166 | if (DEBUG) cry('Filtered: "', text, '"'); 167 | } 168 | } 169 | 170 | var code = json.compile(text); 171 | var data = code(); 172 | return data; 173 | } 174 | 175 | function main(args) 176 | { 177 | using WinxedGtk.init; 178 | using WinxedGtk.gtk_main; 179 | 180 | if (DEBUG) cry('Initializing Gtk'); 181 | init(args); 182 | 183 | // Simplified way of getting command line args 184 | args.shift(); 185 | if (elements(args) < 1) { 186 | cry("No file"); 187 | exit(1); 188 | } 189 | :(string filename, string markbegin[optional], string markend[optional]) = 190 | function (a) { return a:[flat]; } (args); 191 | 192 | if (DEBUG) cry('Loading JSON'); 193 | var data = read_data(filename, markbegin, markend); 194 | 195 | var window = new JsonTreeWindow(filename, data); 196 | 197 | if (DEBUG) cry('Running main loop'); 198 | window.show(); 199 | gtk_main(); 200 | 201 | if (DEBUG) cry('End'); 202 | } 203 | 204 | // End 205 | -------------------------------------------------------------------------------- /src/WinxedGtk.winxed: -------------------------------------------------------------------------------- 1 | // Pruebas gtk 2 | 3 | 4 | //********************************************************************** 5 | 6 | namespace WinxedGtk 7 | { 8 | 9 | const int DEBUG = 0; 10 | 11 | namespace __private 12 | { 13 | 14 | $include_const 'datatypes.pasm'; 15 | 16 | function get_parrot_func(string name, string signature) 17 | { 18 | return dlfunc(null, name, signature); 19 | } 20 | 21 | function str_to_cstring(string s) 22 | { 23 | var cstring = new ['ByteBuffer']; 24 | if (s != null) { 25 | string enc = encoding_name(s); 26 | if (enc != 'ascii' && enc != 'utf8') 27 | s = trans_encoding(s, 'utf8'); 28 | cstring =: s; 29 | push(cstring, 0); 30 | } 31 | return cstring; 32 | } 33 | 34 | function string_from_nci(p) 35 | { 36 | return p.as_string('utf8'); 37 | } 38 | 39 | //********************************************************************** 40 | 41 | namespace internal 42 | { 43 | 44 | function loadgtklib[anon]() 45 | { 46 | var lib; 47 | 48 | for (string libname in [ 49 | 'libgtk-x11', 50 | 'libgtk-x11-2.0', 51 | 'libgtk-x11-2.0.so', 52 | '/usr/lib/libgtk-x11-2.0.so', 53 | '/usr/lib/libgtk-x11-2.0.so.0' 54 | ] ) { 55 | lib = loadlib(libname); 56 | if (lib) { 57 | if (DEBUG) cry("Loaded library: '", libname, "'"); 58 | break; 59 | } 60 | } 61 | if (lib == null) 62 | throw "Cannot load lib"; 63 | 64 | return lib; 65 | } 66 | 67 | } 68 | 69 | function getlib() 70 | { 71 | var ns = namespace internal; 72 | var lib = ns["lib"]; 73 | if (lib == null) 74 | ns["lib"] = lib = internal.loadgtklib(); 75 | return lib; 76 | } 77 | 78 | function getsignatures() 79 | { 80 | return { 81 | "g_free" : "vp", 82 | "g_object_get" : "vpppp", 83 | "gtk_signal_connect_full" : "lppppPpii", 84 | "g_signal_handler_disconnect" : "vpl", 85 | "gtk_check_version" : "piii", 86 | "gtk_init" : "ipp", 87 | "gtk_main_level" : "i", 88 | "gtk_main_iteration" : "i", 89 | "gtk_main_quit" : "v", 90 | "gtk_widget_show" : "vp", 91 | "gtk_widget_set_size_request" : "vpii", 92 | "gtk_widget_get_style" : "pp", 93 | "gtk_widget_get_window" : "pp", 94 | "gtk_widget_destroy" : "vp", 95 | "gtk_window_new" : "pi", 96 | "gtk_window_set_title" : "vpp", 97 | "gtk_button_new_with_label" : "pp", 98 | "gtk_container_set_border_width" : "vpi", 99 | "gtk_container_add" : "vpp", 100 | "gtk_box_pack_start" : "vppiii", 101 | "gtk_vbox_new" : "pii", 102 | "gtk_hbox_new" : "pii" 103 | }; 104 | } 105 | 106 | function gtkfunc(string name) 107 | { 108 | var ns = namespace internal; 109 | var func = ns[name]; 110 | if (func == null) { 111 | var sigs = ns["signatures"]; 112 | if (sigs == null) 113 | ns["signatures"] = sigs = getsignatures(); 114 | if (! exists sigs[name]) 115 | throw "signature for " + name + " not available"; 116 | func = dlfunc(getlib(), name, sigs[name]); 117 | } 118 | return func; 119 | } 120 | 121 | //********************************************************************** 122 | 123 | function g_free(p) 124 | { 125 | gtkfunc("g_free")(p); 126 | } 127 | 128 | function gtk_main_level() 129 | { 130 | return int(gtkfunc("gtk_main_level")()); 131 | } 132 | 133 | function mainloop_quit() 134 | { 135 | var ns = namespace internal; 136 | var quit = ns["quit"]; 137 | if (quit == null) 138 | ns["quit"] = quit = 0; 139 | return quit; 140 | } 141 | 142 | function __text_iter_new() 143 | { 144 | // There is no function to allocate a new GtkTextIter, 145 | // this does the trick. 146 | var iter_copy = dlfunc(getlib(), "gtk_text_iter_copy", "pp"); 147 | var ugly = new ['ManagedStruct'](256); 148 | return iter_copy(ugly); 149 | } 150 | 151 | function __text_iter_free(iter) 152 | { 153 | var iter_free = dlfunc(getlib(), "gtk_text_iter_free", "vp"); 154 | iter_free(iter); 155 | } 156 | 157 | function __check_version() 158 | { 159 | var ns = namespace internal; 160 | var retfunc = ns["__check_version"]; 161 | if (retfunc == null) { 162 | var func = gtkfunc("gtk_check_version"); 163 | if (func == null) 164 | retfunc = function (int major, int minor, int micro) 165 | { 166 | return "Cannot check gtk version"; 167 | }; 168 | else retfunc = function (int major, int minor, int micro) 169 | { 170 | var p = func(major, minor, micro); 171 | string result; 172 | if (p != null) 173 | result = string_from_nci(p); 174 | return result; 175 | }; 176 | ns["__check_version"] = retfunc; 177 | } 178 | return retfunc; 179 | } 180 | 181 | function __widget_get_window() 182 | { 183 | var ns = namespace internal; 184 | var retfunc = ns["__widget_get_window"]; 185 | if (retfunc == null) { 186 | var func = gtkfunc("gtk_widget_get_window"); 187 | if (func != null) 188 | retfunc = function (gtkw) 189 | { 190 | var gdkwindow = func(gtkw); 191 | return gdkwindow; 192 | }; 193 | else 194 | retfunc = function (gtkw) 195 | { 196 | // The function gtk_widget_get_window is not available 197 | // until Gtk+ 2.14 198 | // This is a veeeery convoluted way to get 199 | // the window property from the widget. 200 | var interp = getinterp(); 201 | var pointee = new['ManagedStruct']([DATATYPE_INT, 0, 0]); 202 | var pointer = new ['Pointer']; 203 | var get = get_parrot_func("Parrot_PMC_get_pointer", "ipP"); 204 | var set = get_parrot_func("Parrot_PMC_set_pointer", "vpPi"); 205 | if (get == null || set == null) throw "Vaya"; 206 | int pval = get(interp, pointee); 207 | set(interp, pointer, pval); 208 | var func = gtkfunc("g_object_get"); 209 | var p = str_to_cstring('window'); 210 | func(gtkw, p, pointer, null); 211 | int n = pointee[0]; 212 | var result = new ['UnManagedStruct']; 213 | set(interp, result, n); 214 | return result; 215 | }; 216 | ns["__widget_get_window"] = retfunc; 217 | } 218 | return retfunc; 219 | } 220 | 221 | function __widget_get_style() 222 | { 223 | var ns = namespace internal; 224 | var retfunc = ns["__widget_get_style"]; 225 | if (retfunc == null) { 226 | var func = gtkfunc("gtk_widget_get_style"); 227 | if (func != null) 228 | retfunc = function (gtkw) 229 | { 230 | var gdkstyke = func(gtkw); 231 | return gdkstyke; 232 | }; 233 | else 234 | retfunc = function (gtkw) 235 | { 236 | throw "Can't draw with this gtk"; 237 | }; 238 | ns["__widget_get_style"] = retfunc; 239 | } 240 | return retfunc; 241 | } 242 | 243 | } // namespace __private 244 | 245 | //********************************************************************** 246 | 247 | using namespace __private; 248 | 249 | function init(args) 250 | { 251 | int argc = elements(args); 252 | var pargs = new 'ManagedStruct'([ DATATYPE_CSTR, argc, 0]); 253 | for (int i = 0; i < argc; ++i) 254 | pargs[0,i] = string(args[i]); 255 | var pargc = new 'ManagedStruct'([ DATATYPE_PTR, 0, 0]); 256 | gtkfunc("gtk_init")(pargc, pargs); 257 | } 258 | 259 | function gtk_main() 260 | { 261 | var func = gtkfunc("gtk_main_iteration"); 262 | int i; 263 | var quit = mainloop_quit(); 264 | do { 265 | i = func(); 266 | sleep(0.001); 267 | } while (i && ! quit); 268 | } 269 | 270 | function gtk_main_quit() 271 | { 272 | int i = gtk_main_level(); 273 | if (i == 0) 274 | mainloop_quit() =: true; 275 | else 276 | gtkfunc("gtk_main_quit")(); 277 | } 278 | 279 | function gtk_check_version(int major, int minor, int micro) 280 | { 281 | return __check_version()(major, minor, micro); 282 | } 283 | 284 | //********************************************************************** 285 | 286 | class GObject 287 | { 288 | var gtkw; 289 | function __gtkset(gtkw) 290 | { 291 | self.gtkw = gtkw; 292 | } 293 | } 294 | 295 | class Widget : GObject 296 | { 297 | function destroy() 298 | { 299 | gtkfunc("gtk_widget_destroy")(self.gtkw); 300 | } 301 | function show() 302 | { 303 | gtkfunc("gtk_widget_show")(self.gtkw); 304 | } 305 | function set_size_request(int width, int height) 306 | { 307 | gtkfunc("gtk_widget_set_size_request")(self.gtkw, width, height); 308 | } 309 | function signal_connect(string signal_name, callback, 310 | data[optional], int has_data[opt_flag]) 311 | { 312 | var func = gtkfunc("gtk_signal_connect_full"); 313 | var callback_function = has_data ? 314 | function(widget, actualdata) 315 | { 316 | callback(actualdata); 317 | } : 318 | function(widget, actualdata) 319 | { 320 | callback(); 321 | }; 322 | var cb_data = has_data ? data : callback_function; 323 | var funback; 324 | ${ new_callback funback, callback_function, cb_data, 'iUp' }; 325 | if (DEBUG) cry("connecting signal '", signal_name, "'"); 326 | int r = func(self.gtkw, str_to_cstring(signal_name), 327 | funback, null, cb_data, null, 1, 1); 328 | return r; 329 | } 330 | function signal_disconnect(handler_id) 331 | { 332 | gtkfunc("g_signal_handler_disconnect")(self.gtkw, handler_id); 333 | } 334 | } 335 | 336 | class Misc : Widget 337 | { 338 | function set_alignment(float xalign, float yalign) 339 | { 340 | var func = dlfunc(getlib(), "gtk_misc_set_alignment", "vpff"); 341 | func(self.gtkw, xalign, yalign); 342 | } 343 | function set_padding(float xpad, float ypad) 344 | { 345 | var func = dlfunc(getlib(), "gtk_misc_set_padding", "vpff"); 346 | func(self.gtkw, xpad, ypad); 347 | } 348 | } 349 | 350 | class Label : Misc 351 | { 352 | function Label(string text) 353 | { 354 | var func = dlfunc(getlib(), "gtk_label_new", "pp"); 355 | self.__gtkset(func(str_to_cstring(text))); 356 | } 357 | } 358 | 359 | class Editable : Widget { 360 | function get_chars(int start_pos, int end_pos) 361 | { 362 | var func = dlfunc(getlib(), "gtk_editable_get_chars", "ppii"); 363 | var p = func(self.gtkw, start_pos, end_pos); 364 | string r; 365 | if (p != null) { 366 | r = string_from_nci(p); 367 | g_free(p); 368 | } 369 | return r; 370 | } 371 | } 372 | 373 | class Entry : Editable 374 | { 375 | function Entry() 376 | { 377 | var func = dlfunc(getlib(), "gtk_entry_new", "p"); 378 | self.__gtkset(func()); 379 | } 380 | function get_text() 381 | { 382 | var func = dlfunc(getlib(), "gtk_entry_get_text", "pp"); 383 | var t = func(self.gtkw); 384 | string result; 385 | if (t != null) { 386 | result = string_from_nci(t); 387 | if (DEBUG) cry("Entry.get_text - got '", result, "'"); 388 | } 389 | return result; 390 | } 391 | } 392 | 393 | class Text : Editable 394 | { 395 | function Text() 396 | { 397 | var func = dlfunc(getlib(), "gtk_text_new", "ppp"); 398 | self.__gtkset(func(null, null)); 399 | } 400 | function set_editable(int editable) 401 | { 402 | var func = dlfunc(getlib(), "gtk_text_set_editable", "vpi"); 403 | func(self.gtkw, editable); 404 | } 405 | function insert(string text) 406 | { 407 | var func = dlfunc(getlib(), "gtk_text_insert", "vpppppi"); 408 | func(self.gtkw, null, null, null, str_to_cstring(text), -1); 409 | } 410 | } 411 | 412 | class Container : Widget 413 | { 414 | function set_border_width(int width) 415 | { 416 | gtkfunc("gtk_container_set_border_width")(self.gtkw, width); 417 | } 418 | function add(item) 419 | { 420 | gtkfunc("gtk_container_add")(self.gtkw, item.gtkw); 421 | } 422 | } 423 | 424 | class TextIter 425 | { 426 | var gtkiter; 427 | function TextIter() 428 | { 429 | self.gtkiter = __text_iter_new(); 430 | } 431 | } 432 | 433 | class TextBuffer : GObject 434 | { 435 | function TextBuffer() 436 | { 437 | var func = dlfunc(getlib(), "gtk_text_buffer_new", "p"); 438 | self.__gtkset(func()); 439 | } 440 | function get_char_count() 441 | { 442 | var func = dlfunc(getlib(), "gtk_text_buffer_get_char_count", "ip"); 443 | return func(self.gtkw); 444 | } 445 | function get_start_iter() 446 | { 447 | var func = dlfunc(getlib(), "gtk_text_buffer_get_start_iter", "vpp"); 448 | var textiter = new TextIter(); 449 | func(self.gtkw, textiter.gtkiter); 450 | return textiter; 451 | } 452 | function get_end_iter() 453 | { 454 | var func = dlfunc(getlib(), "gtk_text_buffer_get_end_iter", "vpp"); 455 | var textiter = new TextIter(); 456 | func(self.gtkw, textiter.gtkiter); 457 | return textiter; 458 | } 459 | function get_text(start, end, int include_hidden_chars) 460 | { 461 | var func = dlfunc(getlib(), "gtk_text_buffer_get_text", "ppppi"); 462 | var p = func(self.gtkw, start.gtkiter, end.gtkiter, include_hidden_chars); 463 | string result; 464 | if (p != null) { 465 | result = string_from_nci(p); 466 | g_free(p); 467 | } 468 | return result; 469 | } 470 | function set_text(string text) 471 | { 472 | //TODO reencode text if not already utf8 473 | var func = dlfunc(getlib(), "gtk_text_buffer_set_text", "vppi"); 474 | int len = bytelength(text); 475 | func(self.gtkw, str_to_cstring(text), len); 476 | } 477 | } 478 | 479 | class TextView : Container 480 | { 481 | function TextView() 482 | { 483 | var func = dlfunc(getlib(), "gtk_text_view_new", "p"); 484 | self.__gtkset(func()); 485 | } 486 | function set_editable(int editable) 487 | { 488 | var func = dlfunc(getlib(), "gtk_text_view_set_editable", "vpi"); 489 | func(self.gtkw, editable); 490 | } 491 | function __get_buffer() 492 | { 493 | var func = dlfunc(getlib(), "gtk_text_view_get_buffer", "pp"); 494 | return func(self.gtkw); 495 | } 496 | function get_buffer() 497 | { 498 | var textbuffer = new TextBuffer; // Don't call the constructor 499 | textbuffer.__gtkset(self.__get_buffer()); 500 | return textbuffer; 501 | } 502 | function get_char_count() 503 | { 504 | return self.get_buffer().get_char_count(); 505 | } 506 | function get_text() 507 | { 508 | var buffer = self.get_buffer(); 509 | return buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter(), 0); 510 | } 511 | } 512 | 513 | class Bin : Container 514 | { 515 | } 516 | 517 | class Box : Container 518 | { 519 | function pack_start(widget, int expand, int fill, int padding) 520 | { 521 | gtkfunc("gtk_box_pack_start") 522 | (self.gtkw, widget.gtkw, expand, fill, padding); 523 | } 524 | } 525 | 526 | class VBox : Box 527 | { 528 | function VBox(int homogeneous, int spacing) 529 | { 530 | var func = gtkfunc("gtk_vbox_new"); 531 | self.__gtkset(func(homogeneous, spacing)); 532 | } 533 | } 534 | 535 | class HBox : Box 536 | { 537 | function HBox(int homogeneous, int spacing) 538 | { 539 | var func = gtkfunc("gtk_hbox_new"); 540 | self.__gtkset(func(homogeneous, spacing)); 541 | } 542 | } 543 | 544 | class ScrolledWindow : Bin 545 | { 546 | function ScrolledWindow() 547 | { 548 | var func = dlfunc(getlib(), "gtk_scrolled_window_new", "ppp"); 549 | self.__gtkset(func(null, null)); 550 | } 551 | function add_with_viewport(child) 552 | { 553 | var func = dlfunc(getlib(), "gtk_scrolled_window_add_with_viewport", "vpp"); 554 | func(self.gtkw, child.gtkw); 555 | } 556 | function set_policy(int hpolicy, int vpolicy) 557 | { 558 | var func = dlfunc(getlib(), "gtk_scrolled_window_set_policy", "vpii"); 559 | func(self.gtkw, hpolicy, vpolicy); 560 | } 561 | } 562 | 563 | class Window : Bin 564 | { 565 | function Window(int level) 566 | { 567 | var func = gtkfunc("gtk_window_new"); 568 | self.__gtkset(func(0)); 569 | } 570 | function set_title(string title) 571 | { 572 | gtkfunc("gtk_window_set_title")(self.gtkw, str_to_cstring(title)); 573 | } 574 | } 575 | 576 | class Dialog : Window 577 | { 578 | function run() 579 | { 580 | var func = dlfunc(getlib(), "gtk_dialog_run", "ip"); 581 | int r = func(self.gtkw); 582 | return r; 583 | } 584 | } 585 | 586 | class MessageDialog : Dialog 587 | { 588 | function MessageDialog(parent, int flags, int type, int buttons, string message) 589 | { 590 | var func = dlfunc(getlib(), "gtk_message_dialog_new", "ppiiipp"); 591 | self.__gtkset(func(parent.gtkw, flags, type, buttons, 592 | str_to_cstring("%s"), str_to_cstring(message))); 593 | } 594 | } 595 | 596 | class Button : Bin 597 | { 598 | function Button(string label) 599 | { 600 | var func = gtkfunc("gtk_button_new_with_label"); 601 | self.__gtkset(func(str_to_cstring(label))); 602 | } 603 | } 604 | 605 | class TreeItem : Widget 606 | { 607 | function TreeItem(string label) 608 | { 609 | var func = dlfunc(getlib(), "gtk_tree_item_new_with_label", "pp"); 610 | self.__gtkset(func(str_to_cstring(label))); 611 | } 612 | function set_subtree(tree) 613 | { 614 | var func = dlfunc(getlib(), "gtk_tree_item_set_subtree", "vpp"); 615 | func(self.gtkw, tree.gtkw); 616 | } 617 | } 618 | 619 | class Tree : Widget 620 | { 621 | function Tree() 622 | { 623 | var func = dlfunc(getlib(), "gtk_tree_new", "p"); 624 | self.__gtkset(func(0)); 625 | } 626 | function append(item) 627 | { 628 | var func = dlfunc(getlib(), "gtk_tree_append", "vpp"); 629 | func(self.gtkw, item.gtkw); 630 | } 631 | } 632 | 633 | class CList : Widget 634 | { 635 | function CList(int ncolumns) 636 | { 637 | var func = dlfunc(getlib(), "gtk_clist_new", "pi"); 638 | self.__gtkset(func(ncolumns)); 639 | } 640 | function column_titles_show() 641 | { 642 | var func = dlfunc(getlib(), "gtk_clist_column_titles_show", "vp"); 643 | func(self.gtkw); 644 | } 645 | function set_column_title(int column, string title) 646 | { 647 | var func = dlfunc(getlib(), "gtk_clist_set_column_title", "vpip"); 648 | func(self.gtkw, column, str_to_cstring(title)); 649 | } 650 | function set_text(int row, int column, string text) 651 | { 652 | var func = dlfunc(getlib(), "gtk_clist_set_text", "vpiip"); 653 | func(self.gtkw, row, column, str_to_cstring(text)); 654 | } 655 | function append(row) 656 | { 657 | int n = elements(row); 658 | var data = new 'ManagedStruct'([ DATATYPE_CSTR, n, 0]); 659 | for (int i = 0; i < n; ++i) { 660 | string r = row[i]; 661 | data[0,i] = r; 662 | } 663 | var func = dlfunc(getlib(), "gtk_clist_append", "vpp"); 664 | func(self.gtkw, data); 665 | } 666 | } 667 | 668 | class Image : Misc 669 | { 670 | function Image(string filename) 671 | { 672 | var func = dlfunc(getlib(), "gtk_image_new_from_file", "pp"); 673 | self.__gtkset(func(str_to_cstring(filename))); 674 | } 675 | } 676 | 677 | class DrawingArea : Widget 678 | { 679 | function DrawingArea() 680 | { 681 | var func = dlfunc(getlib(), "gtk_drawing_area_new", "p"); 682 | self.__gtkset(func()); 683 | } 684 | function draw_rectangle(int x, int y, int width, int height) 685 | { 686 | var gdkwindow = __widget_get_window()(self.gtkw); 687 | var style = __widget_get_style()(self.gtkw); 688 | var func = dlfunc(getlib(), "gtk_draw_box", "vppiiiiii"); 689 | func(style, gdkwindow, 0, 0, x, y, width, height); 690 | } 691 | } 692 | 693 | class MenuItem : Bin 694 | { 695 | function MenuItem(string label) 696 | { 697 | var func = dlfunc(getlib(), "gtk_menu_item_new_with_label", "pp"); 698 | self.__gtkset(func(str_to_cstring(label))); 699 | } 700 | function set_submenu(submenu) 701 | { 702 | var func = dlfunc(getlib(), "gtk_menu_item_set_submenu", "vpp"); 703 | func(self.gtkw, submenu.gtkw); 704 | } 705 | } 706 | 707 | class MenuShell : Container 708 | { 709 | function append(item) 710 | { 711 | var func = dlfunc(getlib(), "gtk_menu_shell_append", "vpp"); 712 | func(self.gtkw, item.gtkw); 713 | } 714 | } 715 | 716 | class MenuBar : MenuShell 717 | { 718 | function MenuBar() 719 | { 720 | var func = dlfunc(getlib(), "gtk_menu_bar_new", "p"); 721 | self.__gtkset(func()); 722 | } 723 | } 724 | 725 | class Menu : MenuShell 726 | { 727 | function Menu() 728 | { 729 | var func = dlfunc(getlib(), "gtk_menu_new", "p"); 730 | self.__gtkset(func()); 731 | } 732 | } 733 | 734 | } // namespace WinxedGtk 735 | 736 | //********************************************************************** 737 | 738 | // End 739 | --------------------------------------------------------------------------------