|
Post by vovchik on May 14, 2020 18:12:00 GMT 1
Dear Peter, I'm glad it works for you! I am also still experimenting and trying things out - like using global vars. Here is a version where the image changes, just to demonstrate a way of doing it via the CLICKED sub. Plenty of widgets to test, as well as functions to return widget values. With kind regards, vovchik Attachments:gtktest01.bac.tar.gz (2.24 KB)
|
|
|
Post by bigbass on May 15, 2020 1:41:14 GMT 1
Hello vovchik very nice progress looking really good the svgs give it a clean image without adding any extra size to the widget and your properties added a special touch that we can really customize the widget easily Thanks Peter for adding gtk2 and gtk3 that opens a large door and we all have many ideas to test out I hope I have some time tonight to add something to the mix Joe
|
|
|
Post by Pjot on May 15, 2020 16:51:22 GMT 1
Thanks vovchik,
Indeed very nice! I have the impression that GTK needs less definitions, the code looks very concise.
BR Peter
|
|
|
Post by vovchik on May 15, 2020 18:13:15 GMT 1
Dear Peter and Joe, Here is another demo with a few more widgets (slider, spinbox, statusbar). They show, but I am still trying to figure out how to set and get values. Any ideas? In the example, I split out the GUIDEFINE essentials and properties so that I could more easily play with them. I think it also makes the code a bit easier to understand and more readable, but that is just personal preference. With kind regards, vovchik Attachments:gtktest02.bac.tar.gz (6.43 KB)
|
|
|
Post by Pjot on May 15, 2020 20:49:02 GMT 1
Hi vovchik, Setting the right properties can be tricky, both with functions or with properties. I took a quick look into the GtkSpinButton, but the upper and lower values are determined by its child widget, which is a GtkAdjustment. So, first you need to obtain the child widget: CALL GUIGET(id, "spin", "adjustment", &widget)
Then you can set the 'upper' and 'lower' property for the adjustment. I am struggling too with the LIST widget. The whole GtkList stuff has changed in GTK2.x and turned into an API for masochistic programmers, even when using plain functions. But starting from GTK 3.10 they now have the GtkListBox which is really helpful. Also I have ported now most event types to the GTK callback, so we should be able to query relevant events (see fossil). Below my work in progress porting the Internet Radio program. Regards Peter OPTION GUI TRUE PRAGMA GUI gtk3
OPTION COLLAPSE TRUE OPTION SOCKET 1
CONST Conf$ = GETENVIRON$("HOME") & "/.radio.cfg" CONST Fifo$ = "/dev/shm/mpg.fifo." & STR$(MYPID) CONST Ipc$ = "/dev/shm/mpg.ipc" CONST Buffer = 32768
SIGNAL SIG_IGN, SIGCHLD
'-----------------------------------------------------------------------------------------------
SUB Load_Config(id)
LOCAL config$, station$, name$, url$
CALL gtk_container_foreach(GTK_CONTAINER(GUIWIDGET(id, "list")), (GtkCallback)gtk_widget_destroy, NULL)
IF FILEEXISTS(Conf$) THEN config$ = LOAD$(Conf$) FOR station$ IN config$ STEP "#" IF LEN(CHOP$(station$)) = 0 THEN CONTINUE name$ = TOKEN$(CHOP$(station$), 1, NL$) url$ = TOKEN$(CHOP$(station$), 2, NL$) CALL gtk_list_box_insert(GTK_LIST_BOX(GUIWIDGET(id, "list")), gtk_widget_new(GTK_TYPE_LABEL, "xalign", 0.0, "label", TOKEN$(name$, 2, "="), NULL), -1) NEXT ENDIF
ENDSUB
'-----------------------------------------------------------------------------------------------
FUNCTION Create_Gui
LOCAL window
window = GUIDEFINE(" \ { type=WINDOW name=window callback=delete-event title=\"BaCon Internet Radio\" height-request=200 width-request=350 } \ { type=BOX name=box parent=window orientation=GTK_ORIENTATION_VERTICAL } \ { type=SCROLLED_WINDOW name=swin parent=box expand=TRUE callback=button_press_event,popup } \ { type=LIST_BOX name=list parent=swin } \ { type=LABEL name=label parent=box use-markup=1 label=\"<big>Hello world</big>\" } \ { type=MENU name=menu visible=TRUE } \ { type=MENU_ITEM name=item1 parent=menu callback=activate visible=TRUE label=\"Pause\" } \ { type=MENU_ITEM name=item2 parent=menu callback=activate visible=TRUE label=\"Resume\" } \ { type=SEPARATOR_MENU_ITEM name=sep1 parent=menu visible=TRUE } \ { type=MENU_ITEM name=item3 parent=menu callback=activate visible=TRUE label=\"Add\" } \ { type=MENU_ITEM name=item4 parent=menu callback=activate visible=TRUE label=\"Edit\" } \ { type=MENU_ITEM name=item5 parent=menu callback=activate visible=TRUE label=\"Delete\" } \ { type=SEPARATOR_MENU_ITEM name=sep2 parent=menu visible=TRUE } \ { type=MENU_ITEM name=item_exit parent=menu callback=activate visible=TRUE label=\"Exit\" } \ ")
CALL Load_Config(window)
RETURN window
ENDFUNCTION
'-----------------------------------------------------------------------------------------------
SUB Main_Function(id)
LOCAL event TYPE GdkEventButton*
WHILE TRUE
event$ = GUIEVENT$(id, TRUE) ? event$
SELECT TOKEN$(event$, 1) CASE "window", "item_exit" END CASE "popup" event = (GdkEventButton*)INT(VAL(TOKEN$(event$, 2))) IF event->type = GDK_BUTTON_PRESS AND event->button = GDK_BUTTON_SECONDARY THEN CALL gtk_menu_popup_at_pointer(GTK_MENU(GUIWIDGET(id, "menu")), (GdkEvent*)event) ENDSELECT WEND
ENDSUB
'-----------------------------------------------------------------------------------------------
Main_Function(Create_Gui())
'-----------------------------------------------------------------------------------------------
Attachments:
|
|
|
Post by vovchik on May 15, 2020 22:18:20 GMT 1
Dear Peter, Thanks. Here is your latest with a touch of eye candy... I am looking at how you are dealing with getting back widget results and learining. With kind regards, vovchik Attachments:
gtkradio1.bac.tar.gz (2.36 KB)
|
|
|
Post by bigbass on May 15, 2020 23:22:08 GMT 1
Hello vovchik I did this in 2014 and fixed it to compile again today basic-converter.proboards.com/post/6314/threadported from this developer.gnome.org/gnome-devel-demos/3.32/scale.c.html.enhere is the fixed version its easier to see all the widget in one place hope this helps with the callbacks it would be better to add what you need I UPLOADED it with the fixes I guess I need to go back and check some of those old widget demos they will be more useful now to see all the parts needed sliders-gtk3-2020.tar.gz (13.74 KB) Joe P.S I got to the low level gtk like this maybe it would work with the GUI also ? I know that's not the official way to do it but it worked '---was DECLARE changed to PROTO PROTO gtk_adjustment_new(double,double,double,double,double,double) TYPE long
'--- had to replace low level stuff styled after HUG PROTO gtk_adjustment_get_value(long) TYPE double
SPIN BUTTON PRAGMA OPTIONS `pkg-config --cflags gtk+-3.0` PRAGMA LDFLAGS `pkg-config --libs gtk+-3.0` PRAGMA INCLUDE <gtk-3.0/gtk/gtk.h> PRAGMA COMPILER gcc
OPTION PARSE FALSE
PROTO gtk_window_set_title PROTO gtk_box_pack_start PROTO gtk_container_add PROTO gtk_init PROTO gtk_main PROTO gtk_widget_show PROTO gtk_widget_show_all PROTO gtk_adjustment_new PROTO gtk_button_new_with_label PROTO gtk_hbox_new PROTO gtk_label_new PROTO gtk_spin_button_get_value_as_int PROTO gtk_spin_button_new PROTO gtk_window_new PROTO gtk_main_quit PROTO g_signal_connect_data PROTO gtk_window_set_default_size
'--- Declare variables GLOBAL *window TYPE GtkWidget GLOBAL *label TYPE GtkWidget GLOBAL *grid TYPE GtkWidget GLOBAL *spin_button TYPE GtkWidget
GLOBAL *adjustment TYPE GtkAdjustment
'============== SUB EXIT_PROG '============== gtk_main_quit END SUB
'--- This is the callback function. '--- It is a handler function which reacts to the signal. '--- In this case, it will notify the user the value of their spinbutton
'============== SUB spin_clicked '==============
value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_button)) PRINT value END SUB
gtk_init(0, 0)
'--- Create a window with a title, a border width, and a default size window = gtk_window_new(GTK_WINDOW_TOPLEVEL) gtk_window_set_title (GTK_WINDOW (window), "SpinButton Example") gtk_window_set_default_size (GTK_WINDOW (window), 270, 70) gtk_container_set_border_width (GTK_CONTAINER (window), 5)
'---Connecting the clicked signal to the callback function g_signal_connect_data(window, "destroy", EXIT_PROG, 0, 0, 0)
'--- Create a label to be shown in the window label = gtk_label_new ("Press enter to get the value")
'--- Create an adjustment representing an adjustable bounded value adjustment = gtk_adjustment_new (0, 0, 100, 1, 0, 0)
'--- Create a spin button that is to be as wide as possible spin_button = gtk_spin_button_new (adjustment, 1, 0) gtk_widget_set_hexpand (spin_button, TRUE)
'--- Connecting the "value-changed" signal for the spinbutton '--- to the appropriate callback function. g_signal_connect_data(spin_button, "activate", spin_clicked, 0, 0, 0)
'--- Create a grid and arrange everything accordingly grid = gtk_grid_new () gtk_grid_set_column_spacing (GTK_GRID (grid), 10) gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE) gtk_grid_attach (GTK_GRID (grid), spin_button, 0, 0, 1, 1) gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1)
gtk_container_add (GTK_CONTAINER (window), grid) gtk_widget_show_all (window) gtk_main
|
|
|
Post by Pjot on May 16, 2020 8:43:48 GMT 1
Thanks vovchik,
I like the eye candy! Hopefully I can finish the port this weekend.
For your SpinBox issue, I took another look. The problem is that the "GtkAdjustment" itself is not a real GTK widget. It is more like a model to determine how the SpinButton should behave.
Therefore, we can not use the GtkAdjustment in the GUIDEFINE function, because GUIDEFINE only accepts genuine widgets.
As you may have observed with my Internet Radio program, both for Motif and also GTK, we cannot avoid using helper functions to setup our GUI. I am still not sure what to do about this.
For the GtkSpinner, the sample code below shows how it can work. Clearly, I am using a helper function as well.
HTH Peter
OPTION GUI TRUE PRAGMA GUI gtk2
id = GUIDEFINE(" \ { type=WINDOW name=window callback=delete-event title=\"BaCon\" width-request=300 } \ { type=VBOX name=box parent=window } \ { type=LABEL name=label parent=box height-request=50 use-markup=1 label=\"<big><i>How to use a SpinButton</i></big>\" } \ { type=SPIN_BUTTON name=spin parent=box } \ { type=HBUTTON_BOX name=bbox parent=box layout-style=GTK_BUTTONBOX_END } \ { type=BUTTON name=button parent=bbox callback=clicked label=\"Exit\" }")
CALL GUISET(id, "spin", "adjustment", gtk_adjustment_new(0, 0, 50, 1, 0, 0))
WHILE TRUE event$ = GUIEVENT$(id)
SELECT event$ CASE "window", "button" END ENDSELECT WEND
|
|
|
Post by vovchik on May 16, 2020 11:24:00 GMT 1
Dear Joe and Peter, Thanks. I think I have it now...and we can get the value back easily. The same can be done for the slider, I suppose. I'll try that next. With kind regards, vovchik Attachments:gtkspin.bac.tar.gz (885 B)
|
|
|
Post by bigbass on May 16, 2020 20:26:43 GMT 1
Hello vovchik
well done! this is a whole new approach to gtk
I almost had it I was using int (the standard way in the function)
value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_button))
and it looks like the adjustment needs a double (built in ) are we getting this from glib directly? wonder if we can use this idea for other low level callbacks
we need more docs on this callback approach but I tried several properties and see how its working now
GtkObject * gtk_adjustment_new (gdouble value, gdouble lower, gdouble upper, gdouble step_increment, gdouble page_increment, gdouble page_size); gdouble gtk_adjustment_get_value (GtkAdjustment * adjustment); void gtk_adjustment_set_value (GtkAdjustment * adjustment, gdouble value);
|
|
|
Post by bigbass on May 17, 2020 1:53:33 GMT 1
I dont want to admit how many tries it took to get the GUISET to work I felt like a blind squirrel that got lucky in finding a nut but at least I got the idea OPTION GUI TRUE
' We can specify gtk3 too PRAGMA GUI gtk2
' Needed if we run this GTK2 sample in GTK3 'PRAGMA OPTIONS -Wno-deprecated-declarations
SUB LINK_CB() PRINT "going to web site" '---cant set it from in the sub so it's in the main ? END SUB
' Here, we can say type=WINDOW, or type=LABEL, etc. id = GUIDEFINE(" \ { type=GTK_TYPE_WINDOW name=window callback=delete-event title=\"BaCon LinkButton\" width-request=300 } \ { type=GTK_TYPE_VBOX name=box parent=window } \ { type=GTK_TYPE_LABEL name=label parent=box height-request=50 use-markup=1 label=\"<big><i>Need Help!</i></big>\" } \ { type=GTK_TYPE_HBUTTON_BOX name=bbox parent=box layout-style=GTK_BUTTONBOX_END } \ { type=GTK_TYPE_LINK_BUTTON name=linkbutton parent=bbox callback=clicked label=\"Link\" } \ { type=GTK_TYPE_BUTTON name=button parent=bbox callback=clicked label=\"Exit\" }") ' To demonstrate that GUISET works too. CALL GUISET(id, "window", "window-position", GTK_WIN_POS_CENTER, "resizable", FALSE) CALL GUISET(id,"linkbutton","uri","http://www.basic-converter.org/")
WHILE TRUE event$ = GUIEVENT$(id)
SELECT event$ CASE "window" CASE "linkbutton" CALL LINK_CB END ENDSELECT WEND
|
|
|
Post by Pjot on May 17, 2020 8:42:19 GMT 1
Thanks all for your comments and testing! Below my Internet Radio program ported to GTK3. There were a few hindrances to overcome. - The GTK dialog widgets use a slightly different way of sending their data to the callback, so I have updated the callback mechanics a bit more to allow querying which of the dialogue buttons was pressed (see fossil).
- Menu tear-off items appear to be deprecated in GTK3
- We still have the category of "helper-functions", most of which are showing and hiding actions, for which I have no better solution as of yet other than to use them directly in our code.
In the process of porting I have updated the Motif code as well. Here are the links, screenshot of the final radio program for GTK3 is attached (I did not add vovchik's eye-candy yet).
- The BaCon Internet Radio program using Motif
- The BaCon Internet Radio program using GTK3
I like the way we can use dialogues now in GTK. They only need one line and we can use them conveniently in our code. This is exactly how I envisioned the GUI code should be. Below a small program to demonstrate how dialogues work in GTK. BR Peter OPTION GUI TRUE PRAGMA GUI gtk3
id = GUIDEFINE("{ type=MESSAGE_DIALOG name=dialog callback=delete-event callback=response,yesno message-type=GTK_MESSAGE_WARNING buttons=GTK_BUTTONS_YES_NO title=\"Dialog\" text=\"Are you sure?\" } ")
LOCAL response TYPE int*
WHILE TRUE event$ = GUIEVENT$(id, TRUE)
SELECT TOKEN$(event$, 1) CASE "yesno" response = (int*)INT(VAL(TOKEN$(event$, 2))) IF *response = GTK_RESPONSE_YES THEN PRINT "Yes button clicked" ELSE PRINT "No button clicked" ENDIF CASE "dialog" END ENDSELECT WEND
Attachments:
|
|
|
Post by vovchik on May 17, 2020 10:39:36 GMT 1
Dear Peter, Thanks. It is working nicely. And I use it every day. With kind regards, vovchik UPDATED: Here are some tiny radio svgs I just banged together that might be appropriate as desktop icons for this nice little app. Attachments:radio-svg.tar.gz (738 B)
|
|
|
Post by Pjot on May 17, 2020 16:39:38 GMT 1
Thanks vovchik,
I am using those icons now myself in my desktop shortcut to the programs.
Also I am happy to hear you're using the program daily, this is what I also do. There's a lot of good music out there, especially the 'Classical Oasis' channel and KingFM.
For the "helper functions", I am considering to add symbols like GUISHOW and GUIHIDE, which would cover approx. 60% of the usage of helper functions.
BR Peter
|
|
|
Post by vovchik on May 17, 2020 20:49:01 GMT 1
Dear Peter,
I am glad that the icons were useful. I also use them for the same purpose. As for GUIHID and GUISHOW - it's great idea, if you can find a way to do so. I am playing around a bit, too, with widgets and hope to post some additional demos soon.
With kind regards, vovchik
|
|