AllBASIC Forum
BASIC Developer & Support Resources => Interpreters => Topic started by: John on October 30, 2011, 08:39:55 AM
-
Curently, PxBasic and PxPlus only offers a native GUI for Windows using their Nomads GUI builder. The goal of this project is to use GTK-Server (.so shared object) to script the replacement of PxPlus native Windows API high level directives with Gtk for Nomads.
NOMADS (http://pvxplus.com/pgsrvr.pvp?pg=training/nomads.htm)
If you would like to contribute to this effort with the hope that the author will incorporate this feature into the language as a plug-in for Linux, send me a e-mail support@scriptbasic.org to obtain an account on the forum.
Update
It has become painfully obvious that trying to enhance a commercial Basic language is a losing battle. Beside having to deal with everything externally due to no source access, the company takes issue to your efforts as taking revenue away from their offerings. The Gtk cross platform desktop GUI for PxPlus will be my last contribution to this language. The amount of grief it generates isn't worth it.
Validation
This customer spent days trying to resolve his issues connecting to a MySQL database with PxPlus. The resolution stated by a PxPlus dealer says it all.
I think I know what is happening: you are using a v9 PxPLUS, I'm using a
v10 version. The MySQL interface is a part of a v9 ProvideX Professional
licence, but in PxPLUS v9 it's not included in a Professional licence. If
you want to use the MySQL interface in v9 PxPLUS, you will need to buy the
PxPLUS MySQL package (#10004). Starting with PxPLUS v10, the MySQL interface
is included in a Professional licence, so upgrading to v10 would also solve
your problem.
-
I created a generic libgtk-server.so shared object for Ubuntu 64 and attached it. If you would like to build the same for your version of Linux, visit the GTK-Server Project Site (http://www.gtk-server.org) and download the source.
-
90% of programming jobs are in creating Line of Business software:
Economics 101: the price for anything (including you) is a function of the supply of it and demand for it. Let’s talk about the demand side first. Most software is not sold in boxes, available on the Internet, or downloaded from the App Store. Most software is boring one-off applications in corporations, under-girding every imaginable facet of the global economy. It tracks expenses, it optimizes shipping costs, it assists the accounting department in preparing projections, it helps design new widgets, it prices insurance policies, it flags orders for manual review by the fraud department, etc etc. Software solves business problems. Software often solves business problems despite being soul-crushingly boring and of minimal technical complexity. For example, consider an internal travel expense reporting form. Across a company with 2,000 employees, that might save 5,000 man-hours a year (at an average fully-loaded cost of $50 an hour) versus handling expenses on paper, for a savings of $250,000 a year. It does not matter to the company that the reporting form is the world’s simplest CRUD app, it only matters that it either saves the company costs or generates additional revenue.
There are companies which create software which actually gets used by customers, which describes almost everything that you probably think of when you think of software. It is unlikely that you will work at one unless you work towards making this happen. Even if you actually work at one, many of the programmers there do not work on customer-facing software, either.
If this is true, companies will be looking at Linux and the vast offering of open source solutions to save money or increase revenues.
Don't assume just because you don't have to pay for the application and have free access to the code to change if you wish that open source software is free. Someone needs to maintain it and keep it current with the OS (community contributions) and support is either peer or pay depending on the popularity or business value.
-
I created a Ubuntu 32 bit Amazon EC2 instance and compiled gtk-server as a shared object to be used with the Ubuntu 32 bit version of PxPlus. When I have time I will show a Glade based GUI example running under PxPlus. I hate wasting my time and maybe someone will find this of value. The negative karma I get from most of the ProvideX list is disheartening.
-
John i really don't know why you wasting your time with PWX or Provide basic
(what is the real name anyway ???).?
-
I was able to verify that the gtk-server.so I built for Ubuntu 32 works with PxPlus version 10. My plan is to convert the ScriptBasic version of the Glade based calculator example to PxBasic. At that point with the Gtk definitions I already built and the Glade interface, one should be able to Use PxBasic/PxPlus/ProvideX to build native GUI applications under Linux and potentially OS X.
I'll call it my contribution to the PxPlus Linux developer's group with the hope a few brave souls will give it a try.
-
I decided to take a break from getting the PxPlus version of the calculator working and spent some time freshing up my Gtk installation under Windows XP. (in a VirtualBox) I really like the Gtk preference tool. It has a bunch of themes to choose from. I decided on Clear Looks to match my Ubuntu Linux theme.
(http://files.allbasic.info/ScriptBasic/clear_looks.png)
-
Here is Peter's on-line dictionary Gtk example running under Linux and Windows in ScriptBasic. The same SB script runs untouched on either platform.
Ubuntu Linux
(http://files.allbasic.info/ScriptBasic/gtk_dict.png)
Windows XP
(http://files.allbasic.info/ScriptBasic/Dictionary.png)
#!/usr/bin/scriba
REM ************************************************************************
REM
REM DICT client to lookup words
REM Using the HTML widgets of the Scriptbasic wrapper
REM
REM Expand the GTK namespace if you feel necessary!
REM Feb. 10, 2006 - PvE.
REM
REM ************************************************************************
REM Import GTK definition first
IMPORT gtk.bas
GLOBAL CONST nl = "\n"
GLOBAL CONST title = "Thesaurus!"
REM Create main window
mainwin = GTK::window(title, 500, 450)
REM Create droplist part
frame1 = GTK::frame(" Servers ", 255, 65)
GTK::attach(frame1, mainwin, 10, 10)
servers[0] = "dict.org"
servers[1] = "dict.aioe.org"
servers[2] = "dict.tugraz.at"
servers[3] = "mova.org"
servers[4] = "dict.tu-chemnitz.de"
servers[5] = "test.dict.org"
servers[6] = "dict.trit.org"
servers[7] = "dict.die.net"
servers[8] = "www.lojban.org"
servers[9] = "dict.arabeyes.org"
servers[10] = "muktaka.dyndns.org"
servers[11] = "dict.saugus.net"
servers[12] = "dictionary.bishopston.net"
servers[13] = "la-sorciere.de"
servers[14] = "es.dict.org"
servers[15] = "lividict.org"
servers[16] = "mali.geekcorps.org"
servers[17] = "dione.zcu.cz"
servers[18] = "dict.kurtwerks.com"
servers[19] = "madison.onespeeddave.com"
drop = GTK::droplist(servers, 165, 35)
GTK::attach(drop, mainwin, 20, 30)
fetch = GTK::button("Fetch", 60, 35)
GTK::attach(fetch, mainwin, 195, 30)
REM Create control panel
frame2 = GTK::frame(" Control ", 210, 65)
GTK::attach(frame2, mainwin, 275, 10)
about = GTK::button("About", 60, 35)
GTK::attach(about, mainwin, 285, 30)
clear = GTK::button("Clear", 60, 35)
GTK::attach(clear, mainwin, 350, 30)
exbut = GTK::button("Exit", 60, 35)
GTK::attach(exbut, mainwin, 415, 30)
REM Create dictionary panel
frame3 = GTK::frame(" Dictionaries ", 480, 125)
GTK::attach(frame3, mainwin, 10, 85)
dat[0] = ""
list = GTK::list(dat, 460, 90)
GTK::attach(list, mainwin, 20, 110)
GTK::bg_color(list, 49152, 49152, 49152)
REM Create text part
frame4 = GTK::frame(" Translation ", 480, 190)
GTK::attach(frame4, mainwin, 10, 220)
text = GTK::text(460, 155)
GTK::attach(text, mainwin, 20, 245)
GTK::disable(text)
GTK::bg_color(text, 49152, 49152, 49152)
REM Create entry and lookup button
entry = GTK::entry(360, 25)
GTK::attach(entry, mainwin, 10, 420)
utf8 = GTK::check("UTF-8", 60, 30)
GTK::attach(utf8, mainwin, 430, 415)
dflt = GTK::check("All", 40, 30)
GTK::attach(dflt, mainwin, 380, 415)
REM Create about window
aboutwin = GTK::window("About", 300, 120)
GTK::hide(aboutwin)
label1 = GTK::label("Demo program with the GTK module.", 280, 20)
GTK::attach(label1, aboutwin, 10, 5)
GTK::fg_color(label1, 32768, 0, 0)
label2 = GTK::label("Using " & GTK::version() & " with Scriptbasic.", 280, 20)
GTK::attach(label2, aboutwin, 10, 25)
GTK::fg_color(label2, 0, 0, 32768)
label3 = GTK::label("(C) Peter van Eerten - February 6, 2006", 280, 20)
GTK::attach(label3, aboutwin, 10, 45)
GTK::fg_color(label3, 0, 32768, 0)
okbut = GTK::button("OK", 60, 35)
GTK::attach(okbut, aboutwin, 120, 80)
REM Mainloop
REPEAT
REM Put focus to entry
GTK::focus(entry)
REM Wait for event
action = GTK::event()
REM Get all dictionaries of server
IF action = fetch THEN CALL Get_Dicts
REM Get meaning of word
IF action = entry THEN CALL Lookup_Word
REM Clear all widgets
IF action = clear THEN CALL Clear_All
REM Show about window
IF action = about THEN GTK::show(aboutwin)
REM Hide about window
IF action = okbut OR action = aboutwin THEN GTK::hide(aboutwin)
UNTIL action = mainwin OR action = exbut
END
REM ************************************************************************
SUB Get_Dicts
LOCAL dat$, total, count
ON ERROR GOTO G_NetError
OPEN GTK::get_text(drop) & ":2628" FOR socket AS 1
PRINT#1,"SHOW DB\n"
LINE INPUT#1, dat$
LINE INPUT#1, dat$
count = 0
WHILE LEFT(dat$, 1) <> "."
LINE INPUT#1, dat$
dat$ = REPLACE(dat$, CHR$(34), CHR$(92) & CHR$(34))
IF LEFT$(dat$, 1) <> "." THEN total[count] = TRIM(dat$)
count+=1
WEND
PRINT#1,"QUIT\n"
CLOSE 1
GTK::fg_color(list, 0, 0, 65535)
GTK::set_text(list, total)
EXIT SUB
G_NetError:
dat$[0] = "Server not available!"
GTK::fg_color(list, 65535, 0, 0)
GTK::set_text(list, dat$)
END SUB
REM ************************************************************************
SUB Lookup_Word
LOCAL dict$, dat$, total$, info$
GTK::set_text(mainwin, title & " - \\\"" & GTK::get_text(entry) & "\\\"")
GTK::fg_color(text, 0, 32768, 0)
GTK::set_text(text, "Fetching....")
GTK::async()
ON ERROR GOTO L_NetError
dict$ = LEFT(GTK::get_text(list), INSTR(GTK::get_text(list), " "))
OPEN GTK::get_text(drop) & ":2628" FOR socket AS 1
IF GTK::get_value(dflt) THEN
PRINT#1,"DEFINE * " & GTK::get_text(entry) & "\n"
ELSE
PRINT#1,"DEFINE " & dict$ & " " & GTK::get_text(entry) & "\n"
END IF
REPEAT
LINE INPUT#1, dat$
dat$ = REPLACE(dat$, CHR$(34), CHR$(92) & CHR$(34))
IF LEFT(dat$, 3) = "151" THEN
total$ &= "------------------------------\n"
total$ &= RIGHT(dat$, LEN(dat$) - LEN(GTK::get_text(entry)) - 9)
total$ &= "------------------------------\n"
REPEAT
LINE INPUT#1, info$
info$ = REPLACE(info$, CHR$(34), CHR$(92) & CHR$(34))
IF LEFT(info$, 1) <> "." THEN total$ &= TRIM(info$) & nl
UNTIL LEFT(info$, 1) = "."
total$ &= "\n"
END IF
UNTIL LEFT(dat$, 3) = "250" OR VAL(LEFT(dat$, 3)) > 499
PRINT#1,"QUIT\n"
CLOSE 1
IF LEFT(dat$, 3) = "552" THEN
total$ = "No match found."
GTK::fg_color(text, 65535, 0, 0)
ELSE IF LEFT(dat$, 3) = "501" THEN
total$ = "Select a dictionary first!"
GTK::fg_color(text, 65535, 0, 0)
ELSE IF LEFT(dat$, 3) = "550" THEN
total$ = "Invalid database!"
GTK::fg_color(text, 65535, 0, 0)
ELSE
GTK::fg_color(text, 0, 0, 49152)
END IF
IF GTK::get_value(utf8) THEN
GTK::set_text(text, GTK::UTF8(total$))
ELSE
GTK::set_text(text, total$)
END IF
GTK::set_value(text, 0)
EXIT SUB
L_NetError:
dat$[0] = "Could not lookup word!"
GTK::fg_color(list, 65535, 0, 0)
GTK::set_text(list, dat$)
END SUB
REM ************************************************************************
SUB Clear_All
LOCAL ar$
ar$[0] = ""
GTK::set_text(list, ar$)
GTK::set_text(text, "")
END SUB
REM ************************************************************************
-
I was able to get the Glade XML project based calculator demo running under Windows.
Linux
(http://files.allbasic.info/ScriptBasic/SBGtk%20Calculator.png)
Windows XP
(http://files.allbasic.info/ScriptBasic/sbcalc-win.png)
' Gtk Calculator
IMPORT gtk.bas
gtk_server_cfg("-cfg=C:\\GTK-server\\gtk-server.cfg")
' Initialize calculator state
calculator_state = 0
' Initialize calculator cache
calculator_cache = 0
' Initialize last calculator action
calculator_action = 0
' Initialize MEM function
mem = 0
' Process the action
SUB Handle_Operator(entry)
LOCAL value
IF calculator_state = 0 THEN
IF calculator_action = 1 THEN
value = gtk::gtk("gtk_entry_get_text " & entry)
calculator_cache += value
gtk::gtk("gtk_entry_set_text " & entry & " " & calculator_cache)
ELSE IF calculator_action = 2 THEN
value = gtk::gtk("gtk_entry_get_text " & entry)
calculator_cache -= value
gtk::gtk("gtk_entry_set_text " & entry & " " & calculator_cache)
ELSE IF calculator_action = 3 THEN
value = gtk::gtk("gtk_entry_get_text " & entry)
calculator_cache *= value
gtk::gtk("gtk_entry_set_text " & entry & " " & calculator_cache)
ELSE IF calculator_action = 4 THEN
value = gtk::gtk("gtk_entry_get_text " & entry)
IF value = 0 THEN
gtk::gtk("gtk_entry_set_text " & entry & " ERROR")
ELSE
calculator_cache /= value
gtk::gtk("gtk_entry_set_text " & entry & " " & calculator_cache)
END IF
END IF
END IF
END SUB
SUB Calc_Exit
gtk::gtk("gtk_server_exit")
END SUB
' All button actions here
SUB Button_Memread(entry, widget)
calculator_state = 0
calculator_cache = gtk::gtk("gtk_entry_get_text " & entry)
gtk::gtk("gtk_entry_set_text " & entry & " " & mem)
END SUB
SUB Button_Memadd(entry, widget)
mem = gtk::gtk("gtk_entry_get_text " & entry)
END SUB
SUB Button_C(entry, widget)
gtk::gtk("gtk_entry_set_text " & entry & " 0")
END SUB
SUB Button_CE(entry, widget)
calculator_state = 0
calculator_action = 0
calculator_cache = 0
mem = 0
gtk::gtk("gtk_entry_set_text " & entry & " 0")
END SUB
SUB Button_Add(entry, widget)
Handle_Operator(entry)
calculator_action = 1
calculator_state += 1
END SUB
SUB Button_Subtract(entry, widget)
Handle_Operator(entry)
calculator_action = 2
calculator_state += 1
END SUB
SUB Button_Multiply(entry, widget)
Handle_Operator(entry)
calculator_action = 3
calculator_state += 1
END SUB
SUB Button_Divide(entry, widget)
Handle_Operator(entry)
calculator_action = 4
calculator_state += 1
END SUB
SUB Button_Equals(entry, widget)
Handle_Operator(entry)
calculator_action = 0
calculator_state += 1
END SUB
SUB Button_Clicked(entry, widget)
LOCAL button, text
button = gtk::gtk("gtk_button_get_label " & widget)
text = gtk::gtk("gtk_entry_get_text " & entry)
IF text = "0" OR calculator_state > 0 THEN
calculator_cache = text
gtk::gtk("gtk_entry_set_text " & entry & " " & button)
ELSE
gtk::gtk("gtk_entry_set_text " & entry & " " & text & button)
END IF
calculator_state = 0
END SUB
' Main program
gtk::gtk("gtk_init NULL NULL")
gtk::gtk("glade_init")
' xml = gtk::gtk("glade_xml_new_from_buffer " & Calc_XML & " " & LEN(Calc_XML) & " 0 0")
xml = gtk::gtk("glade_xml_new \"calc.glade\" NULL NULL")
gtk::gtk("glade_xml_signal_autoconnect " & xml)
' Calc_Exit
win = gtk::gtk("glade_xml_get_widget " & xml & " window")
gtk::gtk("gtk_server_connect " & win & " delete-event window")
' Entry
ent = gtk::gtk("glade_xml_get_widget " & xml & " entry")
' Button_Clicked
but1 = gtk::gtk("glade_xml_get_widget " & xml & " button1")
gtk::gtk("gtk_server_connect " & but1 & " clicked button1")
but2 = gtk::gtk("glade_xml_get_widget " & xml & " button2")
gtk::gtk("gtk_server_connect " & but2 & " clicked button2")
but3 = gtk::gtk("glade_xml_get_widget " & xml & " button3")
gtk::gtk("gtk_server_connect " & but3 & " clicked button3")
but4 = gtk::gtk("glade_xml_get_widget " & xml & " button4")
gtk::gtk("gtk_server_connect " & but4 & " clicked button4")
but5 = gtk::gtk("glade_xml_get_widget " & xml & " button5")
gtk::gtk("gtk_server_connect " & but5 & " clicked button5")
but6 = gtk::gtk("glade_xml_get_widget " & xml & " button6")
gtk::gtk("gtk_server_connect " & but6 & " clicked button6")
but7 = gtk::gtk("glade_xml_get_widget " & xml & " button7")
gtk::gtk("gtk_server_connect " & but7 & " clicked button7")
but8 = gtk::gtk("glade_xml_get_widget " & xml & " button8")
gtk::gtk("gtk_server_connect " & but8 & " clicked button8")
but9 = gtk::gtk("glade_xml_get_widget " & xml & " button9")
gtk::gtk("gtk_server_connect " & but9 & " clicked button9")
but0 = gtk::gtk("glade_xml_get_widget " & xml & " button0")
gtk::gtk("gtk_server_connect " & but0 & " clicked button0")
' Button_Add
butADD = gtk::gtk("glade_xml_get_widget " & xml & " buttonAdd")
gtk::gtk("gtk_server_connect " & butADD & " clicked buttonAdd")
' Button_Subtract
butSUB = gtk::gtk("glade_xml_get_widget " & xml & " buttonMinus")
gtk::gtk("gtk_server_connect " & butSUB & " clicked buttonMinus")
' Button_Multiply
butMUL = gtk::gtk("glade_xml_get_widget " & xml & " buttonMul")
gtk::gtk("gtk_server_connect " & butMUL & " clicked buttonMul")
' Button_Divide
butDIV = gtk::gtk("glade_xml_get_widget " & xml & " buttonDiv")
gtk::gtk("gtk_server_connect " & butDIV & " clicked buttonDiv")
' Button_Equals
butEQ = gtk::gtk("glade_xml_get_widget " & xml & " buttonEq")
gtk::gtk("gtk_server_connect " & butEQ & " clicked buttonEq")
' Button_C
butC = gtk::gtk("glade_xml_get_widget " & xml & " buttonC")
gtk::gtk("gtk_server_connect " & butC & " clicked buttonC")
' Button_CE
butCE = gtk::gtk("glade_xml_get_widget " & xml & " buttonCE")
gtk::gtk("gtk_server_connect " & butCE & " clicked buttonCE")
' Button_Memadd
memadd = gtk::gtk("glade_xml_get_widget " & xml & " buttonMemadd")
gtk::gtk("gtk_server_connect " & memadd & " clicked buttonMemadd")
' Button_Memread
memread = gtk::gtk("glade_xml_get_widget " & xml & " buttonMemread")
gtk::gtk("gtk_server_connect " & memread & " clicked buttonMemread")
REPEAT
event = gtk::gtk("gtk_server_callback wait")
IF event = "button1" THEN Button_Clicked(ent, but1)
IF event = "button2" THEN Button_Clicked(ent, but2)
IF event = "button3" THEN Button_Clicked(ent, but3)
IF event = "button4" THEN Button_Clicked(ent, but4)
IF event = "button5" THEN Button_Clicked(ent, but5)
IF event = "button6" THEN Button_Clicked(ent, but6)
IF event = "button7" THEN Button_Clicked(ent, but7)
IF event = "button8" THEN Button_Clicked(ent, but8)
IF event = "button9" THEN Button_Clicked(ent, but9)
IF event = "button0" THEN Button_Clicked(ent, but0)
IF event = "buttonAdd" THEN Button_Add(ent, butADD)
IF event = "buttonMinus" THEN Button_Subtract(ent, butSUB)
IF event = "buttonMul" THEN Button_Multiply(ent, butMUL)
IF event = "buttonDiv" THEN Button_Divide(ent, butDIV)
IF event = "buttonEq" THEN Button_Equals(ent, butEQ)
IF event = "buttonC" THEN Button_C(ent, butC)
IF event = "buttonCE" THEN Button_CE(ent, butCE)
IF event = "buttonMemadd" THEN Button_Memadd(ent, memadd)
IF event = "buttonMemread" THEN Button_Memread(ent, memread)
UNTIL event = "window"
calc.glade
<?xml version="1.0"?>
<glade-interface>
<widget class="GtkWindow" id="window">
<property name="width_request">250</property>
<property name="height_request">225</property>
<property name="visible">True</property>
<property name="title" translatable="yes">SBGtk Calculator</property>
<property name="resizable">False</property>
<property name="window_position">center</property>
<property name="default_width">264</property>
<property name="default_height">248</property>
<property name="icon_name">calc</property>
<child>
<widget class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="n_rows">5</property>
<property name="n_columns">5</property>
<property name="homogeneous">True</property>
<child>
<widget class="GtkButton" id="buttonMemadd">
<property name="label" translatable="yes">M+</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="entry">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="editable">False</property>
<property name="xalign">1</property>
</widget>
<packing>
<property name="right_attach">5</property>
<property name="x_padding">4</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button1">
<property name="label" translatable="yes">1</property>
<property name="width_request">0</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button3">
<property name="label" translatable="yes">3</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="buttonC">
<property name="label" translatable="yes">C</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="buttonCE">
<property name="label" translatable="yes">CE</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">4</property>
<property name="right_attach">5</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button4">
<property name="label" translatable="yes">4</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button5">
<property name="label" translatable="yes">5</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button6">
<property name="label" translatable="yes">6</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="buttonAdd">
<property name="label" translatable="yes">+</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="buttonMinus">
<property name="label" translatable="yes">-</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">4</property>
<property name="right_attach">5</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button7">
<property name="label" translatable="yes">7</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button8">
<property name="label" translatable="yes">8</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_padding">5</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button9">
<property name="label" translatable="yes">9</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="buttonMul">
<property name="label" translatable="yes">*</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="buttonDiv">
<property name="label" translatable="yes">/</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">4</property>
<property name="right_attach">5</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button0">
<property name="label" translatable="yes">0</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="buttonMemread">
<property name="label" translatable="yes">MR</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">4</property>
<property name="right_attach">5</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="buttonEq">
<property name="label" translatable="yes">=</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button2">
<property name="label" translatable="yes">2</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_padding">4</property>
<property name="y_padding">8</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
FWIW
This should work under PxBasic/PxPlus (Windows/Linux/Mac) as well.
-
I was able to get PxBasic 10 under Windows to work with GTK-Server.
(http://files.allbasic.info/ProvideX/hello-pxbasic.png)
! Glade Hello World
gtk_lib = DLL(ADDR "gtk-server.dll")
ok=DLL(gtk_lib,"gtk","gtk_server_cfg-cfg=/GTK-server/gtk-server.cfg"+$00$)
! Initialize GTK & Glade
ok=DLL(gtk_lib,"gtk","gtk_init NULL NULL"+$00$)
ok=DLL(gtk_lib,"gtk","glade_init"+$00$)
! Load and show Glade defined window
strptr = DLL(gtk_lib,"gtk","glade_xml_new "+quo+"hello.glade"+quo+" NULL NULL"+$00$)
xml$=MEM(strptr,0)
ok=DLL(gtk_lib,"gtk","glade_xml_signal_autoconnect "+xml$+$00$)
! Get window ID and define window close event
strptr=DLL(gtk_lib,"gtk","glade_xml_get_widget "+xml$+" window1"+$00$)
gtkwin$=MEM(strptr,0)
ok=DLL(gtk_lib,"gtk","gtk_server_connect "+gtkwin$+" delete-event window"+$00$)
! Event Handler
REPEAT
strptr=DLL(gtk_lib,"gtk","gtk_server_callback WAIT"+$00$)
this_event$ = MEM(strptr,0)
UNTIL this_event$ = "window"
ok=DLL(gtk_lib,"gtk","gtk_widget_destroy "+gtkwin$+$00$)
ok=DLL(DROP gtk_lib)
hello.glade
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkWindow" id="window1">
<property name="visible">True</property>
<property name="title" translatable="yes">Hello</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="default_width">400</property>
<property name="default_height">350</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<child>
<widget class="GtkFixed" id="fixed1">
<property name="visible">True</property>
<child>
<widget class="GtkLabel" id="label1">
<property name="width_request">122</property>
<property name="height_request">17</property>
<property name="visible">True</property>
<property name="label" translatable="yes">Hello PxBasic!</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="x">128</property>
<property name="y">128</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
-
Windows Gtk Development Resources
- Gtk 2.22 Windows (http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.22/gtk+-bundle_2.22.1-20101227_win32.zip) (runtime/dev) - Project Site (http://www.gtk.org/download/win32.php)
- Glade3 (http://ftp.gnome.org/pub/GNOME/binaries/win32/glade3/3.6/glade3-3.6.7-with-GTK+.exe) - Cross platform GUI designer for the Gtk GUI toolkit - Project Site (http://glade.gnome.org/)
- GTK-Server Windows (http://downloads.sourceforge.net/gtk-server/gtk-server-2.3.1-installer.exe) - FFI interface for Gtk and other API libraries (see FreeImage example above) - Project Site (http://gtk-server.org)
- libglade interface (http://downloads.sourceforge.net/gtk-server/libglade-2.6.3.zip) - Required to access Glade XML project files via GTK-Server
-
Chris sent me his first pass working with GTK-Server. (TCP)
John,
Here is a first pass attempt at the example from gtk-server.org (using
PxBasic, Gtk-server and Gtk2 Runtime on Windows Vista):
0010 BEGIN
0020 OPEN (HFN)"[tcp];65000"; LET CHAN=LFO
0030 INVOKE "C:\GTK-server\gtk-server.exe -sock=127.0.0.1:65000"
0040 READ RECORD (CHAN,TIM=60,ERR=CONN_FAILURE)X$; IF X$<>"" THEN GOTO CONN_FAILURE
0050 LET JUNK$=FN_GTK$("gtk_init NULL NULL")
0060 LET HWIN$=FN_GTK$("gtk_window_new 0")
0070 LET JUNK$=FN_GTK$("gtk_window_set_title "+HWIN$+"""PxBasic GTK-server""")
0080 LET HTBL$=FN_GTK$("gtk_table_new 10 10 1")
0090 LET JUNK$=FN_GTK$("gtk_container_add "+HWIN$+" "+HTBL$)
0100 LET HBUT$=FN_GTK$("gtk_button_new_with_label ""Click to Quit""")
0110 LET JUNK$=FN_GTK$("gtk_table_attach_defaults "+HTBL$+" "+HBUT$+" 5 9 5 9")
0120 LET JUNK$=FN_GTK$("gtk_widget_show_all "+HWIN$)
0130 LET EVENT$=""
0140 WHILE CSE(EVENT$,HBUT$,HWIN$)=0
0150 LET EVENT$=FN_GTK$("gtk_server_callback wait")
0160 WEND
0170 LET JUNK$=FN_GTK$("gtk_server_exit",ERR=*NEXT)
0180 DONE:
0190 END
0200 CONN_FAILURE:
0210 PRINT "Connection failure"
0220 GOTO DONE
0230 GTK:
0240 DEF FN_GTK$(LOCAL COMMAND$)
0250 LOCAL X$
0260 WRITE RECORD (CHAN)COMMAND$
0270 LET X$=""; READ RECORD (CHAN,TIM=60)X$
0280 RETURN X$
0290 END DEF
(http://files.allbasic.info/ProvideX/CK_gtkdemo.png)
In my opinion, using TCP/IP has more promise than using the direct DLL
method and is easier to understand (at least for me). In addition, it
will ultimately provide for separation between the client and the server
(similar to the Windx model) which is something I care about. It would
be interesting to run this on non-Windows platforms. Doing so should be
just a matter of changing the location of the gtk-server executable on
line 30.
Cheers,
Chris Kukuchka
Sequoia Group, Inc.