Diálogos con JavaScript

Este es uno de los capítulos del tutorial Diálogos para scripts. Encontrarás los enlaces a todos los de capítulos, al final de este artículo.

Este capítulo del tutorial de diálogos para scripts, es muy similar, tanto en el contenido como en los ejemplos al capítulo precedente. Hasta el capítulo anterior, en todo momento, habías visto herramientas. Sin embargo, tanto en el capítulo anterior, como en este capítulo, me he centrado en utilizar las propias librerías GTK+, y un lenguaje de programación, que en el capítulo anterior fue Python, y en este capítulo es JavaScript. Así, en este capítulo me centraré en mostrar como realizar diálogos con JavaScript.

La cuestión de centrarme en el uso de JavaScript, es por el rápido crecimiento que ha tenido este lenguaje de programación en los últimos años. Es probable, que si te dedicas al desarrollo, conozcas este lenguaje de programación. De esta manera, conociendo, como hacer diálogos con JavaScript, te puedes centrar, en crear tus propios scripts, también para el escritorio, y porque no hacer incluso aplicaciones, que poder utilizar.

Y si, por el contrario, no conoces JavaScript, esta es una interesante oportunidad, para comenzar a aprender a utilizarlo, convertir tus scripts en Bash, o en el lenguaje, que utilices, en herramientas mas interactivas y potentes. De esta manera, no tienes que limitar lo que haces al terminal.

JavaScript

Diálogos con JavaScript

¿Que es gjs?

Como gjs es algo que vas repetidas veces a lo largo de este capítulo del tutorial, es importante aclarar que es esto. Gjs es una vinculación de JavaScript para GNOME y lo puedes utilizar para interactuar con GTK. GTK, ya es un viejo conocido, puesto que lo pudiste ver en el capítulo anterior, pero, indicarte que se trata de un kit de herramientas que te permite crear tus propias interfaces gráficas.

¿Que necesito para hacer mis diálogos con JavaScript?

Si estás utilizando Ubuntu, en sus últimas versiones, no necesitas nada para hacer tus diálogos con JavaScript. En otros casos, dependerá de la distribución que estés utilizando y del entorno de escritorio. Sin embargo, te recomiendo que consultes tanto la versión de gjs como la versión de JavaScript que hay instalada en tu equipo.

Así, para ver la versión de gjs que estás utilizando, simplemente tienes que ejecutar la siguiente instrucción en un terminal,

gjs --version

Y, por otro lado, si lo que quieres es conocer la versión del motor de JavaScript instalada, tienes que ejecutar esta otra instrucción,

gjs --jsversion

Por supuesto, además de necesitar gjs vas a necesitar un editor de código. En este sentido, te quiero dar dos sugerencias, y ya eliges tu la que mejor se adapte a tus necesidades, o de lo productivo que quieras llegar a ser,

  • Visual Studio Code. Si prefieres trabajar con un interfaz gráfico, esta es una muy buena solución, y seguro que se adaptará perfectamente a cualquier lenguaje de programación que tu utilices. Esto es así, por la cantidad de extensiones que tienes disponibles, para adaptarlo a tus necesidades.
  • Vim. Sin lugar a dudas, la niña de mis ojos. Eso si, por un lado tienes que estar acostumbrado a trabajar con el terminal. Pero no solo esto, sino que además tienes que superar la curva de aprendizaje de esta herramienta. Pero una vez dominado Vim, tu productividad se verá ampliamente recompensada.

Tu primer diálogo con JavaScript y Gtk

Una vez tienes todas las herramientas, ha llegado el momento de ver como puedes empezar a crear tus diálogos en JavaScript. En este sentido, indicarte, que si vienes del capítulo anterior sobre diálogos con Python, vas a encontrar muchos parecidos, con lo que lo vas a encontrar realmente sencillo.

Por otro lado, recordarte que todos los ejemplos que muestro a continuación están en un repositorio de GitHub, eso si, te recomiendo que lo sigas por aquí, que seguro te será mas sencillo.

Un diálogo sencillo con JavaScript

En este primer ejemplo, voy a poner el código completo con el fin de explicar cada una de las partes del mismo. En los siguientes, omitiré la primera parte por que es exactamente igual.

#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';
const {Gtk} = imports.gi;

Gtk.init(null);

let dialog = new Gtk.MessageDialog({
    title: 'https://www.atareao.es',
    text: 'Este es el mensaje que se muestra'
    });

let response =  dialog.run();

Algunos aspectos en los que te deberías fijar,

  • la llamada del script #!/usr/bin/gjs
  • El requerimiento de las versiones a importar imports.gi.versions.Gtk = '3.0';
  • La forma de importar las librería const {Gtk} = imports.gi;
  • Es necesario inicializar Gtk, para lo que se utiliza Gtk.init(null)

Con esto ya lo tendríamos todo mas o menos claro. Es interesante, la forma en la que se pasan los atributos en el momento de crear nuestro nuevo objeto Gtk.MessageDialog.

Por otro lado, esto lo podrías simplificar ligeramente, pero no se si será muy ventajoso, sobre todo a la hora de leer el código.

(new Gtk.MessageDialog({
    title: 'https://www.atareao.es',
    text: 'Este es el mensaje que se muestra'
    })).run();

Recordarte, como te he indicado anteriormente, que es necesario añadir las líneas de importar así como la de iniciar Gtk, pero, por comodidad, a partir de ahora, no lo repetiré.

Preguntando al usuario

Como en otros capítulos del tutorial, el siguiente objetivo es conseguir interactuar con el usuario. Es decir, hacerle una pregunta, y que nos de una respuesta a la misma, aunque sea un simple Si o No.

En este caso, el ejemplo, es tal y como te muestro a continuación, donde quiero que te fijes en algún que otro detalle,

function show_dialog(){
    let dialog = new Gtk.MessageDialog({
        title: 'https://www.atareao.es',
        text: '¿Estás <span weight="bold" foreground="red">seguro</span>?',
        use_markup: true
        });
    dialog.add_button('Si', Gtk.ResponseType.YES);
    dialog.add_button('No', Gtk.ResponseType.NO);
    try{
        if(dialog.run() == Gtk.ResponseType.YES){
            return 0;
        }
    }catch(error){
    }
    return 1;
}
show_dialog();
Preguntando con JavaScript

En este caso, también puedes utilizar el formato Pango, para resaltar la información que le estás dando al usuario. Para esto, tienes que utilizar la propiedad use_markup, tal y como puedes ver en ese ejemplo.

Para poder utilizar este cuadro de diálogo desde Bash, lo puedes hacer como te muestro a continuación,

gjs ejemplo_03.js
ans=$?
if [ $ans -eq 0 ]
then
    echo "Si que quiere continuar"
else
    echo "No quiere continuar"
fi

Mas información

¿Y si necesitamos mas información del usuario? En el caso de que necesites que el usuario te facilite mas información, el asunto se complica un poco. Pero no te preocupes, porque como verás no es nada complejo, y es bastante sencillo e intuitivo.

Así, por ejemplo, si quisieras, que el usuario te dijera su nombre, lo podrías hacer conforme te muestro en el siguiente ejemplo,

function show_dialog(){
    let dialog = Gtk.Dialog.new();
    dialog.set_title('https://www.atareao.es');
    dialog.add_button('Si', Gtk.ResponseType.YES);
    dialog.add_button('No', Gtk.ResponseType.NO);
    let box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 10);
    box.set_margin_top(10);
    box.set_margin_bottom(10);
    dialog.get_content_area().add(box);
    let label = Gtk.Label.new('Dime tu nombre');
    box.pack_start(label, true, true, 5);
    let entry = Gtk.Entry.new();
    box.pack_start(entry, true, true, 5);
    dialog.show_all();
    try{
        if(dialog.run() == Gtk.ResponseType.YES && entry.get_text()){
            print(entry.get_text());
            return 0;
        }
        print(entry.get_text());
    }catch(error){
        print(error);
    }
    return 1;
}
show_dialog();
Un sencillo formulario con JavaScript

De la misma forma que en el ejemplo anterior, si esto, lo quieres integrar con un script en Bash, lo puedes hacer conforme te muestro en el siguiente ejemplo,

nombre=$(gjs ejemplo_04.js)
ans=$?
if [ $ans -eq 0 ]
then
    echo "Tu nombre es ${nombre}"
else
    echo "No me ha querido decir el nombre"
fi

Preguntando mas y mas..

A partir de aquí todo es mas sencillo, porque como te has podido dar cuenta, esto no es mas que un sencillo formulario, donde puedes solicitar tanta información como necesites. Así, habrá una parte común y otra parte que habrá que ir modificando en función de todo lo que quieras preguntar al usuario. Así, la estructura fija será como te muestro a continuación,

function show_dialog(){
    let dialog = Gtk.Dialog.new();
    dialog.set_title('https://www.atareao.es');
    dialog.add_button('Si', Gtk.ResponseType.YES);
    dialog.add_button('No', Gtk.ResponseType.NO);
    let grid = Gtk.Grid.new();
    grid.set_margin_top(10);
    grid.set_margin_bottom(10);
    grid.set_margin_start(10);
    grid.set_margin_end(10);
    grid.set_column_spacing(10);
    grid.set_row_spacing(10);
    dialog.get_content_area().add(grid);
    // === inicio contenido ===
    // ===   fin contenido  ===
    dialog.show_all();
    try{
        if(dialog.run() == Gtk.ResponseType.YES){
            // === inicio salida ===
            // ===   fin salida  ===
            return 0;
        }
    }catch(error){
        print(error)
    }
    return 1;
}
show_dialog();

Por ejemplo, para el caso anterior, si además quisieras preguntarle la contraseña, tendrías que intercalar las siguientes líneas de código,

grid.attach(Gtk.Label.new('Contraseña:'), 0, 1, 1, 1);
let password = Gtk.Entry.new();
password.set_visibility(false);
grid.attach(password, 1, 1, 1, 1);
Diálogos con JavaScript

Y para recuperar el resultado del usuario, tienes que utilizar las siguientes líneas de código,

if(dialog.run() == Gtk.ResponseType.YES &&
    nombre.get_text() && password.get_text()){
    print(nombre.get_text() + '|' +password.get_text());
    return 0;
}

Que el usuario elija

En el caso de que una de las preguntas que le quieres formular al usuario, le tengas que facilitar opciones para que el usuario elija, lo puedes hacer mediante un componente del tipo Gtk.ComboBox. Así, tendrías que añadir el siguiente código en tu diálogo,

grid.attach(Gtk.Label.new('Selecciona un componente:'), 0, 0, 1, 1);
let model = new Gtk.ListStore();
model.set_column_types([GObject.TYPE_STRING]);
let items = ['Jamón', 'Queso', 'Huevo'];
for(let i=0; i < items.length; i++){
    model.set(model.append(), [0], [items[i]]);
}
let componente = Gtk.ComboBox.new_with_model(model);
let renderer_text = new Gtk.CellRendererText();
componente.pack_start(renderer_text, true);
componente.add_attribute(renderer_text, 'text', 0);
componente.set_active(0);
grid.attach(componente, 1, 0, 1, 1);
Selección de opciones en un cuadro de diálogo

Y para saber lo que eligió nuestro usuario, tendrías que hacerlo conforme te muestro en las siguientes líneas,

if(dialog.run() == Gtk.ResponseType.YES){
    let activeItem = componente.get_active();
    print(items[activeItem]);
    return 0;
}

En el caso de que en el combo quieras mostrar mas información, es muy sencillo. Te indico a continuación las líneas de código que tendrías que modificar,

grid.attach(Gtk.Label.new('Selecciona un componente:'), 0, 0, 1, 1);
let model = new Gtk.ListStore();
model.set_column_types([GObject.TYPE_STRING, GObject.TYPE_STRING]);
let items = [['Jamón', 100],
             ['Queso', 150],
             ['Huevo', 200]];
for(let i=0; i < items.length; i++){
    let iter = model.append();
    model.set(iter, [0], [items[i][0]]);
    model.set(iter, [1], [items[i][1]]);
}
let componente = Gtk.ComboBox.new_with_model(model);
let renderer_text = new Gtk.CellRendererText();
componente.pack_start(renderer_text, true);
componente.add_attribute(renderer_text, 'text', 0);
let renderer_cal = new Gtk.CellRendererText();
componente.pack_start(renderer_cal, true);
componente.add_attribute(renderer_cal, 'text', 1);
componente.set_active(0);
grid.attach(componente, 1, 0, 1, 1);
Mas variantes de selección de opciones, mostrando mas información

Probablemente, los objetos de la clase Gtk.ComboBox, son de los menos intuitivos que conozco, pero una vez los tienes de la mano, todo resulta mucho mas sencillo.

Seleccionar archivos

Otro de los cuadros de diálogos mas habituales, es aquel que te permita seleccionar archivos. Esto se resuelve de forma muy sencilla con la clase Gtk.FileChooserDialog, tal y como puedes ver en el siguiente ejemplo,

function show_dialog(){
    let filter = new Gtk.FileFilter();
    filter.add_mime_type('text/plain');
    let dialog = new Gtk.FileChooserDialog({
        title: 'https://www.atareao.es',
        action: Gtk.FileChooserAction.OPEN,
        filter: filter,
        select_multiple: false
        });
    dialog.add_button('Si', Gtk.ResponseType.YES);
    dialog.add_button('No', Gtk.ResponseType.NO);
    try{
        if(dialog.run() == Gtk.ResponseType.YES){
            print(dialog.get_filename());
            return 0;
        }
    }catch(error){
    }
    return 1;
}
show_dialog();
Selección de archivos

Selección de tipografías

Otro cuadro de diálogo que puedes utilizar de forma sencilla es el de selección de tipografías y fuentes de texto. De nuevo, para este caso, existe a tu disposición una clase que es Gtk.FontChooserDialog. Esto no quiere decir que no te lo puedas montar tu de cero, utilizando la estructura que te he mostrado anteriormente, y la clase Gtk.FontButton. En el caso de que te decidas por el diálogo que ya está preparado para este fin, lo puedes utilizar como en el ejemplo que te muestro a continuación,

function show_dialog(){
    let dialog = new Gtk.FontChooserDialog({
        title: 'https://www.atareao.es'
    });
    try{
        if(dialog.run() == Gtk.ResponseType.OK){
            print(dialog.get_font());
            return 0;
        }
    }catch(error){
    }
    return 1;
}
show_dialog();
Selección de tipografías con cuadros de diálogo con JavaScript y Gtk

Seleccionar colores

Otro cuadro de diálogo que tienes de la mano, es el de seleccionar colores. Su uso es tan sencillo e intuitivo como en el caso anterior, solo tienes que cambiar la clase a Gtk.ColorChooserDialog, tal y como puedes ver en el siguiente ejemplo,

function show_dialog(){
    let dialog = new Gtk.ColorChooserDialog({
        title: 'https://www.atareao.es'
    });
    try{
        if(dialog.run() == Gtk.ResponseType.OK){
            print(dialog.get_rgba());
            return 0;
        }
    }catch(error){
    }
    return 1;
}
show_dialog();
Selección de colores

Seleccionas una fecha

Para el caso de selección de una fecha, no existe un cuadro de diálogo por defecto, como en los casos anteriores, sino que tendrás que utilizar la clase Gtk.Calendar, añadiéndolo en el formulario tipo que te he indicado anteriormente. Por ejemplo,

grid.attach(Gtk.Label.new('Fecha:'), 0, 0, 1, 1);
let fecha = Gtk.Calendar.new();
grid.attach(fecha, 1, 0, 1, 1);
dialog.show_all();
try{
    if(dialog.run() == Gtk.ResponseType.YES){
        print(fecha.get_date());
        return 0;
    }
}catch(error){
    print(error);
}
Seleccionar una fecha

Conclusiones

Con esto tienes una idea muy general, de todas las opciones que te brinda la combinación JavaScript + Gtk, y como crear diálogos con JavaScript. Si vienes de leer los capítulos anteriores, verás que tiene una sintaxis muy parecida a Python, y que salvo algunas particularidades, casi se podría copiar uno para el otro.

Desde luego que dependiendo de lo que quieras hacer, será mas interesante utilizar una solución u otra, de todas las soluciones que te he ido comentando en este tutorial. Sin embargo, dado que desde GNOME, se está potenciando el uso de JavaScript, es una opción, tienes que tener en cuenta.


Imagen de portada de Ferenc Almasi en Unsplash

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *