Glade in Libre Application Summit

First of all ISponsored by GNOME Foundation would like to thanks the GNOME foundation for sponsoring my trip to Denver to attend Libre Application Summit

As usual, it was a great opportunity to catch up with old friends and make new ones specially outside the GNOME community.

This opportunity I talked about the plans I have to integrate Glade with Gnome Builder and other IDEs

You can find the slides of my talk as PDF here, and the sources here!

Sources you say?

Yes sources, since my talk about custom UI interfaces in 2013 I been making all my slides with Glade and using glade-previewer to present them live

glade-previewer is a tiny application shipped with Glade used mainly to preview UI

It’s relevant options are:

-f, --filename=FILENAME  Name of the file to preview
--screenshot             File name to save a screenshot
--css                    CSS file to use
--slideshow              Make a slideshow of every toplevel widget
                         by adding them in a GtkStack

Normally to preview a glade file with a custom css file you would use a command like

$ glade-previewer -f talk.glade --css talk.css

Now if you instead want to make a presentation with it all you need to do is add –slideshow option and glade-previewer will pack every toplevel widget in a GtkStack and switch between pages with PageUp/PageDown buttons

As a bonus I extended –screenshot option so that when used in conjunction with –slideshow it will take a screenshot of every toplevel and save them as multiple pages if the format supports it!

Posted in Glade | Leave a comment

GUADEC a la española

Tapas, jamón are the first words that come to my mind after this year GUADEC in Almería

One of the best part of traveling is discovering new customs and trying new things…

 

 

 

 

Do you want tomato with your toast for breakfast?

– Sure!

 

 

 

What about tuna?

– why not!

 

 

 

 

But more important than food, for me GUADEC is always about the people, meeting new people, people you always respected (still can not believe I meet the legendary JH) or putting a face to an irc nickname or email (albfan, never expected you to be so tall!) and of course catching up with old friends because being able to continue talking with someone like if it was yesterday when in fact it was a year, is priceless.

This GUADEC was special to me because it was the first time I did not talked about Glade, instead I showed a new library called Maxwell I made working at Endless.

What is Maxwell?

Maxwell is a proof of concept library that extends WebKitWebView and lets you embed/pack Gtk widgets in it as a regular Gtk container.

Etymology

The project started inspired by the Broadway Gdk backend which lets you run any Gtk application over HTTP using HTML5 and web sockets which was named after X Consortium’s Broadway release where one of its key features was X-Agent 96.

X Agent 96 => Agent 86 => Maxwell Smart => Maxwell

How does it work?

The introduction of the split process model in WebKit2 made embedding widgets in WebView rather difficult since part of WebKit operates in one process and the rest like WebCore and JS engine in another (UI/Web process).

Maxwell takes a similar approach to Broadway, all it needs is a way to render widgets in the DOM tree and get events from them.

To render widgets we use a CANVAS element the same size of the widget and a custom URI scheme to get the raw image data from each widget.

/* Get image data from widget */
let xhr = new XMLHttpRequest();
xhr.open('GET', 'maxwell:///widget_id', false);
xhr.responseType = 'arraybuffer';
xhr.send();

/* Render image data in canvas */
let data = new Uint8ClampedArray(xhr.response);
let image = new ImageData(data, canvas.width, canvas.height);
canvas.getContext('2d').putImageData(image, 0, 0);

On the Gtk side, each child is rendered in an offscreen window which we use as the source image data to implement the custom URI scheme handler.

Gtk UI process JavaScript/WebCore
GtkWidget:draw↴
Damage event ⟶ JS child_draw() ⟶ GET maxwell://
URI handler ⟵
↳[offscreen]⟶[GdkPixbuf]⟶GIOStream ⟶ [ImageData]↴
putImageData()

For events all we have to do is properly implement GdkWindow::pick-embedded-child and let Gtk know which child widget should get the event. In order to do so we need to keep track of the elements position relative to WebView’s viewport which can be calculated with getBoundingClientRect().

API

The API is pretty straightforward, all you have to do is name the child widget and add it using regular GtkContainer API.

/* Create a Maxwell Web View */
webview = maxwell_web_view_new ();

/* Create a widget to embed */
entry = gtk_entry_new ();

/* Set a unique name on the widget */
gtk_widget_set_name (entry, "myentry");

/* Add widget to web view container */
gtk_container_add (GTK_CONTAINER (webview), entry);

In order for MaxwellWebView to know where to place a child in the DOM tree you need to add a CANVAS element with a “GtkWidget” class and the unique ID you used as the widget’s name.

<canvas class="GtkWidget" id="myentry"></canvas>

Maxwell will also try to honor width and height style properties set on the canvas element. So for example if you want your widget to expand horizontally you can do:

<canvas class="GtkWidget" style="width: 100%;" id="myentry"></canvas>

You can get it at https://github.com/endlessm/maxwell

Sponsored by GNOME FoundationAs usual I would like to thanks the GNOME Foundation for sponsoring my trip to Spain and making all this possible.

 

 

 

Finally some extra pictures…

Posted in General, GTK+, Programming | 1 Comment

It’s always fun to be at GUADEC

Sponsored by GNOME FoundationAs usual I would like to thanks the GNOME foundation for sponsoring my trip to Manchester to enjoy such a wonderful conference and give me the opportunity to present to the community the work I been doing on Glade’s UI for the past few months.

You can find the slides at https://people.gnome.org/~jpu/docs/2017-GUADEC/

Obviously they are made with Glade, something which might seems odd, but is it really?

modern-ui branch

 

So besides a PDF you will find a tarball with all the source files. BTW You can use glade-previewer and PgUp and PgDown to switch pages

$ glade-previewer -f talk.glade --css talk.css --slideshow

 

And some random pictures from GUADEC…

Posted in General, Glade, Programming | 5 Comments

Developer Experience Hackfest 2016

Sponsored by GNOME FoundationFirst of all I would like to thanks the GNOME Foundation for sponsoring once again my trip to Brussels for the GNOME Developer Experience Hackfest.
Besides hacking on Glade and attending FOSDEM I had a great time meeting with old friends and making new ones, not to mention the amount and variety of beers consumed!

beerBut beer was not the only thing we had!

wafles

Back on the hacking, together with Tristan we managed to fix several bugs and add the much needed support for id-less objects! This way Glade is one step closer to support every Gtk+ template file.
I will not go into much details since it was already covered by him in his blog post

Pretty workspace

Besides doing some CSS cleanups in the workspace and user survey window to improve theme compatibility I added the modernized original Glade logo to the workspace background as a tribute to Glade roots!
Glade workspace logo

I also got the chance to work on the Glade User Survey results, the final results will be posted soon on Glade’s website once I finish automating the results from the Data Base.

Glade User Survey Preliminary Results

3114 people took the time to fill the survey since 11-11-2013.
54 % of them use it for commercial purposes and 42 % for personal use.
Most users are from the US and Brazil with Germany, China and France as a close third.

USA 10.98 % Italy 3.44 %
Brazil 10.18 % Spain 3.37 %
Germany 6.29 % UK 3.11 %
China 5.59 % Canada 2.37 %
France 4.65 % Poland 2.21 %
Mexico 4.07 % Argentina 1.70 %
Russia 3.85 % Australia 1.47 %
India 3.76 % Turkey 1.44 %

How long have you been programming? (years)

< 1 5.17 % 11 – 20 15.83 %
1 – 2 30.72 % 21 – 30 6.26 %
3 – 5 18.49 % 31 – 40 2.95 %
6 – 10 18.33 % > 40 2.21 %

Not Programmer 16.66 %

Preferred programming languages do you prefer?

Python 50.32 % JavaScript 21.80 %
C 47.01 % C Sharp 15.25 %
CPP 38.59 % Vala 9.24 %
Java 24.85 % Perl 6.96 %
Other 25.49 %

When did you start using Glade? (years ago)

1 58.38 % 4 – 5 5.94 %
2 4.94 % 6 – 10 6.48 %
3 2.79 % > 11 2.98 %

Which version do you normally use?

What is available in my OS 82.72 % Master 1.47 %
Latest stable from sources 9.44 % Other 0.83 %
3.8 for Gtk+ 2 3.94 %

On what operating system?

Linux 58.83 % OSX 1.02 %
Windows 2.69 % BSD 0.96 %
Other 1.25 % Solaris 0.44 %

How often do you use it?

Every day 43.89 % Few days a week 10.82 %
A few times a year 20 % Every week 5.84 %
A few times a month 13.96 % Once a month 3.94 %

What level of Glade user would you say you are?

Beginner 78.29 %
Intermediate 16.44 %
Advanced 3.78 %

Under what kind of license(s) do you release the software you used Glade to create?

Free Software 42.19 % None 25.72 %
Open Source 34.32 % Commercial 9.5 %

In which field(s) is the software you used Glade to create generally used?

Desktop applications 42.77 % Industrial applications 8.95 %
Academic 18.68 % Embedded applications 7.35 %
Educational 13.48 % Accounting 4.56 %
Scientific 12.13 % Medical 2.92 %

In your opinion what is the biggest problem with Glade?

Lack of documentation 66.89 %
Other 11.23 %
Lack of publicity/exposure 9.79 %
Lack of official binary releases for other OS (Win32, OSX) 5.78 %
Lack of professional training 2.63 %
Lack of professional support 1.5 %

18 % of users found a bug, 6.9 % reported it and 21.96 % contributed to the project.

Posted in General, Glade, GTK+ | 4 Comments

We are not enemies

I do not usually blog, much less about unrelated topics but I think the events and comments of the past few days are worth reflecting on.

Simply put, just because someone have a different opinion it does not make him your enemy!

It is really sad to see there is still people that thinks censorship is acceptable.

Luckily not everyone does, kudos for that!

Posted in General | 1 Comment

Glade User Survey goes live!

Hello everyone! in the past few weeks I been working on a survey for Glade. The idea is that it will help us to better know our user base and thus allow us to take inform decisions to improve Glade users experience.
So please take a few minutes to complete it!

thanks

Juan Pablo

Posted in General, Glade | 1 Comment

Porting widgets to the new template API… the LAZY way!

First of all I want to thanks everyone involved in GUADEC organization specially to the GNOME foundation for sponsoring me once again.

It is been great meeting with old friends and making new ones!

So after Tristan’s talk UI developer experience with Glade/GtkBuilder where he talked about the new template API some good friend of us, lets see if you can guess who, came and ask:

friend: How do I port my widgets to the new templates stuff?
friend: I do not want to redo all of them in glade
me: What kind of widgets?
friend: “A grid with some s#it in it!”
me: hmmm…
 

So we talked about it and told him if that he was that lazy not to redo all widgets in glade manually he could do some function that iterate over containers and spit some xml to get at least the hierarchy right.

As we all know the lazier a programmer is the better, since it will end up writing a program to do its chores!

Anyways I did!

I made a function you can paste in your program and use it together with libgladeui api to dump a runtime GtkWidget to an xml definition.

#include <gladeui/glade.h>

/* Create a Glade project */
GladeProject *project = glade_project_new ();

/* add as many widgets as you want in the project */
glade_project_add_widget_from_object (project, widget, NULL);

/* And then save it to a file */
glade_project_save (project, "myclass.ui", NULL);

And that is all you have to do if the widget is simple enough.
You will have to mark internal children manually since there is no easy way to introspect them, say for example you want to dump a GtkDialog derived widget…

#include <gladeui/glade.h>

/* Create a Glade project */
GladeProject *project = glade_project_new ();

/* We need to mark every internal children manually */
INTERNAL_CHILD (gtk_dialog_get_action_area (GTK_DIALOG (widget)),
                "action_area");
INTERNAL_CHILD (gtk_dialog_get_content_area (GTK_DIALOG (widget)),
                "vbox");

/* add as many widgets as you want in the project */
glade_project_add_widget_from_object (project, widget, NULL);

/* And then save it to a file */
glade_project_save (project, "myclass.ui", NULL);

Here is the cut&paste code glade_dump.c

This is obviously hacky code, it was not heavily tested and will probably make gladeui and gtk API complain a lot but it works pretty well for what is intended.

BTW you have to link with gladeui-2.0 library for this code to work!

I think that is all, happy porting!

Sponsored by GNOME Foundation

Posted in Glade, GTK+ | 1 Comment

High DPI bug workaround!

hidpi

Posted in Uncategorized | 1 Comment

Glade Drag & Drop support

New Drag & Drop support in 3.15 development series:Sponsored by GNOME Foundation

First of all I would like to thanks once again to the foundation for sponsoring my trip to Brussels to attend the Developer Experience Hackhest and Alberto for inviting me in the first place!

After the hackfest we all agreed that Glade needs some love to make it more newbie friendly, nothing we did not already knew, but please do not move along Glade needs your help!

On of the thing that new people find the most difficult to understand about creating GUI with Gtk+/Glade is the container packing paradigm which is very powerful once you get used to it but not as intuitive as one would like.

A way to improve this situation would be to create a new free form layout container similar to Java’s GroupLayout as suggested by Alex in this mail which of course is a lot of work specially in Glade so… help and/or sponsorship is welcome!!

But for now being able to drag & drop widgets around should make thinks easier, right?

The next thing we want to address is the property editor. Not only does not look good (In its defense the whole thing is autogenerated) but thanks to wide screen displays being ubiquitous nowadays it is wasting some precious vertical space :S

This is how it currently looks like

glade_property_editor_old

So… to save some vertical space and make it look more modern this are the changes I made

glade_property_editor_new

  • New ATK icon
  • Replaced toggle buttons with switches
  • Fields do not expand by default
  • Replaced text field edit button with an entry edit icon
  • Removed class field title
  • Moved clear and help buttons to the top of the notebook

The last item is definitely not definitive since it might make more sense to move it inside the scrolled window or simply to the toolbar.

As you can see there is lot of room for improvement so if you come up with a good idea help us!

Posted in Glade | 16 Comments

GtkBuilder and external objects

What if you want to reference an object you created from a GtkBuilder script? or even more add children to a container created outside the scope of GtkBuilder?

You can not!

But do not worry, a simple API like the following will allow us to reference any external object from builder.

void gtk_builder_expose_object (GtkBuilder *builder,
                                const gchar *name,
                                GObject *object);

Now consider a GtkBuilder script like this…

<interface>
  <object class="GtkButton" id="button">
    <property name="image" external-object="True">image</property>
    <signal name="clicked" handler="on_button_clicked"
     object="builder" external-object="yes"/>
  </object>
</interface>

All you have to do is tell builder which objects are external setting the “external-object” parameter then is as simple as calling gtk_builder_expose_object() to actually expose it.
Please note that the external-object parameter is needed to avoid naming space conflicts.

GtkWidget *image = gtk_image_new ();
GtkBuilder *builder = gtk_builder_new ();
gtk_builder_expose_object (builder, "image", G_OBJECT (image));
gtk_builder_expose_object (builder, "builder", G_OBJECT (builder));
gtk_builder_add_from_string (builder, buffer, -1, &error);

Ok but what about adding children to an existing container ?¿

The first idea was to use a fragment of builder xml format (basically the &ltchild&gt tag) and a new API gtk_builder_add_to_parent_*() but then I realize that would prevent us from setting properties on the external object and also it will not allow us to define anarchist objects that is objects outside the container hierarchy like for example a GtkAction.

So instead, I decided to add a new element: <template>

This new element is similar to <object> with the only difference it will be used as an entry point for the external object referenced by the template id.
Now with a template defined by this xml you can add children and set properties on an external object called “mybox”

<?xml version="1.0"?>
<interface>
  <!-- interface-requires gtk+ 3.0 -->
  <template class="GtkBox" id="mybox">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <child>
      <object id="entry">
        <property name="visible">True</property>
        <property name="can_focus">True</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">0</property>
      </packing>
    </child>
    <child>
      <object id="button">
        <property name="label">gtk-apply</property>
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="receives_default">True</property>
        <property name="use_stock">True</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">1</property>
      </packing>
    </child>
  </template>
</interface>

by simply using gtk_builder_add_from_string() in conjunction with gtk_builder_expose_object() like this:

builder = gtk_builder_new ();
mybox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
g_object_ref_sink (mybox);
gtk_builder_expose_object (builder, "mybox", G_OBJECT (mybox));
gtk_builder_add_from_string (builder, buffer, -1, &error);

Pretty simple is not it?

Patch available @ Bugzilla #688205 or if you prefer git this is the branch I been working on

git checkout -b composite-templates origin/composite-templates
Posted in GTK+ | Comments Off on GtkBuilder and external objects