--- /dev/null
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+static GtkBuilder *builder;
+
+// typedef struct wdg_command {
+// GType wdg;
+// const char *cmd;
+// void (*action)(GtkTextView*, char*);
+// } wdg_command;
+//
+// const wdg_command action[] = {
+// { GTK_TYPE_TEXT_VIEW, "set", &ca_text_view }
+// };
+
+void app_quit(GtkWidget *wdg, gpointer user_data) {
+ exit(0);
+}
+
+void text_content(GtkWidget *wdg, gpointer user_data) {
+ GtkEntry *e;
+ if (GTK_IS_ENTRY(wdg)) {
+ e = GTK_ENTRY( wdg );
+ printf( "ENTRY:%s:%s\n",
+ gtk_buildable_get_name(GTK_BUILDABLE(wdg)),
+ gtk_entry_buffer_get_text( gtk_entry_get_buffer( e ) )
+ );
+ }
+}
+
+void button_click(GtkWidget *wdg, gpointer d) {
+ printf( "BUTTON:%s:clicked\n",
+ gtk_buildable_get_name(GTK_BUILDABLE(wdg))
+ );
+}
+
+// ====== CLI ACTIONS =======
+
+void a_widget_enable(GtkWidget *w) {
+ gtk_widget_set_sensitive(w, TRUE);
+}
+void a_widget_disable(GtkWidget *w) {
+ gtk_widget_set_sensitive(w, FALSE);
+}
+
+void a_text_view_set(GtkTextView *v, char *c) {
+ gtk_text_buffer_set_text(
+ gtk_text_view_get_buffer( v ), c, -1
+ );
+}
+
+void a_button(GtkButton *w, char *cli) {
+ char *cmd = strtok(cli, " \n");
+
+ if (!w || !cmd || !cmd[0]) return;
+ else if (!strcmp(cli, "enable")) a_widget_enable(GTK_WIDGET(w));
+ else if (!strcmp(cli, "disable")) a_widget_disable(GTK_WIDGET(w));
+}
+void a_entry(GtkEntry *w, char *cli) {
+ char *cmd = strtok(cli, " \n");
+
+ if (!w || !cmd || !cmd[0]) return;
+ else if (!strcmp(cli, "enable")) a_widget_enable(GTK_WIDGET(w));
+ else if (!strcmp(cli, "disable")) a_widget_disable(GTK_WIDGET(w));
+ else if (!strcmp(cli, "lock")) gtk_editable_set_editable(GTK_EDITABLE(w), FALSE);
+ else if (!strcmp(cli, "unlock")) gtk_editable_set_editable(GTK_EDITABLE(w), TRUE);
+}
+void a_window(GtkWindow *w, char *cli) {
+ char *cmd = strtok(cli, " \n");
+
+ if (!w || !cmd || !cmd[0]) return;
+ else if (!strcmp(cli, "enable")) a_widget_enable(GTK_WIDGET(w));
+ else if (!strcmp(cli, "disable")) a_widget_disable(GTK_WIDGET(w));
+}
+void a_text_view(GtkTextView *w, char *cli) {
+ char *cmd = strtok(cli, " \n");
+
+ if (!w || !cmd || !cmd[0]) return;
+ else if (!strcmp(cli, "set")) a_text_view_set(w, strtok(NULL, ""));
+ else if (!strcmp(cli, "enable")) a_widget_enable(GTK_WIDGET(w));
+ else if (!strcmp(cli, "disable")) a_widget_disable(GTK_WIDGET(w));
+ else if (!strcmp(cli, "lock")) gtk_text_view_set_editable(w, FALSE);
+ else if (!strcmp(cli, "unlock")) gtk_text_view_set_editable(w, TRUE);
+}
+
+void a_widget(GtkWidget *wdg, char *cli) {
+ if (!wdg) return;
+ else if (GTK_IS_BUTTON(wdg)) a_button( GTK_BUTTON(wdg), cli );
+ else if (GTK_IS_ENTRY(wdg)) a_entry( GTK_ENTRY(wdg), cli );
+ else if (GTK_IS_WINDOW(wdg)) a_window( GTK_WINDOW(wdg), cli );
+ else if (GTK_IS_TEXT_VIEW(wdg)) a_text_view( GTK_TEXT_VIEW(wdg), cli );
+}
+
+void a_command(char *cli) {
+ GtkWidget *wdg;
+ char *wid = strtok(cli, " \n"); // Separator: Space, Tab
+
+ if ( wdg = GTK_WIDGET(gtk_builder_get_object(builder, wid)) ) {
+ a_widget(wdg, strtok(NULL, ""));
+ }
+}
+
+gboolean idle_readline(gpointer d) {
+ // GtkBuilder *bld = GTK_BUILDER(d);
+ static char buf[128];
+ int len;
+
+ if ( (len = read(0, &buf, 127)) > 0 ) {
+ buf[len] = 0;
+ a_command(buf);
+ }
+ return 1;
+}
+
+void init_widgets(gpointer wp, gpointer data) {
+ GtkWidget *wdg;
+
+ fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
+
+ if (GTK_IS_WIDGET(wp)) {
+ wdg = GTK_WIDGET(wp);
+ printf("WIDGET:%s:load\n", gtk_widget_get_name(wdg));
+
+ if (GTK_IS_BUTTON(wdg)) g_signal_connect(wdg, "clicked", G_CALLBACK(button_click), NULL);
+ else if (GTK_IS_ENTRY(wdg) ) g_signal_connect(wdg, "changed", G_CALLBACK(text_content), NULL);
+ else if (GTK_IS_WINDOW(wdg)) g_signal_connect(wdg, "destroy", G_CALLBACK(app_quit), NULL);
+
+ } else if (GTK_IS_STATUS_ICON(wp)) {
+ // printf("WIDGET:%s:load\n", gtk_status_icon_get_title(GTK_STATUS_ICON(wp)));
+ printf("WIDGET:StatusIcon:load\n");
+ g_signal_connect(wp, "activate", G_CALLBACK(button_click), NULL);
+ }
+}
+
+int main(int argc, char *argv[]) {
+ GSList *widgets;
+
+ gtk_init(&argc, &argv);
+ builder = gtk_builder_new_from_file("glade1.glade");
+ widgets = gtk_builder_get_objects(builder);
+ g_slist_foreach(widgets, *init_widgets, NULL);
+ g_slist_free(widgets);
+
+ g_idle_add(idle_readline, builder);
+ // gtk_builder_connect_signals(builder, NULL);
+
+ gtk_main();
+ return 0;
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.40.0 -->
+<interface>
+ <requires lib="gtk+" version="3.24"/>
+ <object class="GtkStatusIcon" id="tray">
+ <property name="icon-name">applications-science</property>
+ <property name="title" translatable="yes">LLameAss</property>
+ </object>
+ <object class="GtkWindow" id="win1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">applications-science</property>
+ <signal name="destroy" handler="app_quit" swapped="no"/>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkTextView" id="view">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="editable">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="input">
+ <property name="name">input</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <signal name="changed" handler="foo" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button">
+ <property name="label" translatable="yes">button</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <signal name="clicked" handler="app_quit" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>