miércoles, 3 de julio de 2013

Array unidimensionales y multidimensionales

Si no deseamos usar la librería libgee podemos usar el siguiente tipo de listas llamados arrays y que son de fácil uso para arrays de tipo int,string,char, etc..

[indent=4]
arr : array of string[,]  // declaramos el array de dos dimensiones
init
    arr = new array of string[1,1]   // marcamos el numero de entradas.
    arr[0,0] = "esto" 
    arr[1,1] = "es"
    arr[0,1] = "un"
    arr[1,0] = "array"
    stderr.printf("%s %s %s %s\n", arr[0,0], arr[1,1],arr[0,1], arr[1,0])



Para compilar no es necesario usar libgee solo valac -o array array.gs

Agur.

miércoles, 22 de agosto de 2012

Listas complejas

Si lo que queremos es crear listas mas complejas conteniendo datos de diferentes tipos yo recomiendo crear un objeto y después crear una lista de este objeto.

// complila con valac  nombre.gs  --pkg gee-1.0

[indent=4]
uses Gee
//creamos la clase casa

class casa: Object
    Portal: int
    Piso:int
    Puerta:string
    Calle:string


casa0:casa
init
    var lista_de_casas = new list of casa
 

    //Instanciamos el objeto casa
    casa0= new casa()
    //Introducimos datos
    casa0.Portal=4
    casa0.Piso=3
    casa0.Puerta="A"
    casa0.Calle ="Calle Mayor"
    //Introducimos en la lista
    lista_de_casas.add(casa0)
   
    // Si queremos obtener un nuevo item en la lista deberemos reinstanciar
    // el objeto casa y lo podemos hacer con el mismo nombre
    casa0= new casa()
    casa0.Portal=6
    casa0.Piso=7
    casa0.Puerta="B"
    casa0.Calle ="Calle Menor"
    lista_de_casas.add(casa0)
   
    for var e in lista_de_casas
        print e.Calle+" "+e.Portal.to_string()+ "-"+ e.Piso.to_string()+ " "+e.Puerta+ " "
    // este for tiene un warning consigo fallo de la librería gee
   



En este tipo de listas podríamos introducir tipos de variables creados por nosotros desde otros objetos o usar otros que ya están creados como los de las librerías SDL. Por ejemplo : Rect y Surface. Es decir, podemos anidar objetos dentro de otros y todos meterlos en una lista. En el siguiente ejemplo Introduciremos un objeto dentro de otro objeto, es decir el objeto persona lo introduciremos dentro del objeto casa. Pero claro esta que los objetos necesitan instanciarse para ser usados y si el objeto casa quiere usar el objeto persona este debe de haber sido correctamente instanciado. Lo haré mediante el constructor de casa. Aún así lo podría haber hecho a través de init. ¿Para que sirve el constructor? Es el que recoge las variables de construccion del objeto cuando lo instanciamos con new. En este caso no tiene ninguna. init al igual que construct se ejecutan cuando instanciamos el objeto con new. Sin embargo se dispara antes que construct. Pero bueno, dejemos esto de la construccion de objetos para otro capítulo.

[indent=4]
uses Gee
class persona: Object
    Nombre:string
    Apellidos:string
    
class casa: Object
    Portal: int
    Piso:int
    Puerta:string
    Calle:string
    Persona:persona
    construct () // también se podría haber puesto init aquí.
        Persona= new persona()
casa0:casa
e:Collection
init
    var lista_de_casas = new list of casa
    //Instanciamos el objeto casa
    casa0= new casa()
    //Introducimos datos
    casa0.Portal=4
    casa0.Piso=3
    casa0.Puerta="A"
    casa0.Calle ="Calle Mayor"
    casa0.Persona.Nombre="Gorka"
    casa0.Persona.Apellidos="Santos Garmendia"
    
    //Introducimos en la lista
    lista_de_casas.add(casa0)
    
    // Si queremos obtener un nuevo item en la lista deberemos reinstanciar
    // el objeto casa y lo podemos hacer con el mismo nombre
    casa0= new casa()
    casa0.Portal=6
    casa0.Piso=7
    casa0.Puerta="B"
    casa0.Calle ="Calle Menor"
    casa0.Persona.Nombre="Gaizka"
    casa0.Persona.Apellidos="Sanchez Soler"
    lista_de_casas.add(casa0)
    
    for e in lista_de_casas
        print e.Persona.Nombre + " " +e.Persona.Apellidos
        print e.Calle+ " "+ e.Portal.to_string()+ "-"+ e.Piso.to_string()+ " "+ e.Puerta+ " \n"
        
    // este for tiene un warnin consigo fallo de la librería gee
    



Si lo necesitamos también podemos incluir listas dentro de los objetos. Imaginemos que dentro del objeto persona introducimos una lista de los nombres de los hijos, el resultado sería el siguiente. No olvideís que las listas dentro de las clases también tienen que ser inicializadas.


uses Gee

class persona: Object
    Nombre:string
    Apellidos:string
    Hijos:new list of string
    init
        Hijos= new list of string //inicializamos la lista de hijos así.
   
class casa: Object
    Portal: int
    Piso:int
    Puerta:string
    Calle:string
    Persona:persona
    init
        Persona= new persona()
casa0:casa
e:Collection
init
    var lista_de_casas = new list of casa
    //Instanciamos el objeto casa
    casa0= new casa
    //Introducimos datos
    casa0.Portal=4
    casa0.Piso=3
    casa0.Puerta="A"
    casa0.Calle ="Calle Mayor"
    casa0.Persona.Nombre="Gorka"
    casa0.Persona.Apellidos="Santos Garmendia"
    casa0.Persona.Hijos.add("Felipe") // introducimos los hijos dentro de la sublista
    casa0.Persona.Hijos.add("Rosa")
    casa0.Persona.Hijos.add("Marta")

   
    //Introducimos en la lista
    lista_de_casas.add(casa0)
   
    // Si queremos obtener un nuevo item en la lista deberemos reinstanciar
    // el objeto casa y lo podemos hacer con el mismo nombre
    casa0= new casa()
    casa0.Portal=6
    casa0.Piso=7
    casa0.Puerta="B"
    casa0.Calle ="Calle Menor"
    casa0.Persona.Nombre="Gaizka"
    casa0.Persona.Apellidos="Sanchez Soler"
    casa0.Persona.Hijos.add("Leire")
    casa0.Persona.Hijos.add("Agurtzane")
    lista_de_casas.add(casa0)
   
    for e in lista_de_casas
        print e.Persona.Nombre + " " +e.Persona.Apellidos
        for hijo in e.Persona.Hijos // imprimimos la lista de hijos
            print "Hijo:"+hijo
          
        print e.Calle+ " "+ e.Portal.to_string()+ "-"+ e.Piso.to_string()+ " "+ e.Puerta+ " \n"
      
    // este for tiene un warnin consigo fallo de la librería gee

domingo, 5 de agosto de 2012

Conversión de variables

De INT o DOUBLE  a   STRING
[indent=4]
a: int
init
    a=1
    print " numero: " + a.to_string() //imprimira la cadena 1

De  STRING a INT
[indent=4]
c : string
init
    c="123"
    print "%i", int.parse(c)

De  STRING a DOUBLE

[indent=4]
c : string
init
    c="123.3"
    print "%f", double.parse(c)

De DOUBLE a INT
numero : double
init 
    numero = 2584833
    print "%i", (int)numero
 

De DOUBLE a INT
numero : int
init 
    numero = 2584
    print "%f", (double)numero


miércoles, 25 de julio de 2012

Gtk_Timeout - Pon un timer en tu vida.


 En esta ejemplo hemos añadido al ejemplo de TextView una función que es llamada por el Timer de Gtk. Con ello hemos conseguido crear un texto animado. Cuando pulsamos el boton activamos el Timer.
 Timeout.add(50, mover) --> Llama a mover con velocidad de 50 ticks

  Atención puesto que "mover" tiene que ser una funcion de tipo booleano y retornar true para continuar en funcionamiento.

Nota: Booleano es de tipo lógico y sus valores posibles son true o false

Muy sencillo:


[indent=4]
uses
    Gtk
init

    Gtk.init (ref args)
    var test = new Miventana ()
    test.show_all ()
  
    Gtk.main ()
  
  
class Miventana : Window
    texto1: Gtk.TextView = new TextView
  
    rojo: Gtk.TextTag
    blanco: Gtk.TextTag
    ti1: Gtk.TextIter;     ti2: Gtk.TextIter;    ti3: Gtk.TextIter;    ti4: Gtk.TextIter
  
    acolor : Gdk.Color
  
    boton1: Button= new Button.with_label ("Pulsa este botón")
    contador: int = 0
    frase:string ="La casa esta rota, pero ya la estamos arreglando. La casa esta rota, pero ya la estamos arreglando."
    vbox : VBox = new VBox (true, 5)
      
    init
        Gdk.Color.parse("#1F2AF1", out acolor)
        rojo=texto1.buffer.create_tag("rojo", "foreground-gdk", acolor);
        blanco=texto1.buffer.create_tag("blanco", "foreground", "White");
      
        texto1.editable = false
        texto1.cursor_visible = false
        title = "Ventana de prueba"
        default_height = 360
        default_width = 560
        window_position = WindowPosition.CENTER
        boton1.clicked.connect (pulsado)
      
        destroy.connect(Gtk.main_quit)
        vbox.add (boton1)
        vbox.add(texto1)
        add (vbox)
        texto1.set_size_request(100, 200)
        boton1.set_size_request(100,10)
        texto1.buffer.text = frase
        texto1.buffer.get_iter_at_mark (out ti1, texto1.buffer.get_insert ())
        texto1.buffer.get_iter_at_mark (out ti2, texto1.buffer.get_insert ())
        texto1.buffer.get_iter_at_mark (out ti3, texto1.buffer.get_insert ())
        texto1.buffer.get_iter_at_mark (out ti4, texto1.buffer.get_insert ())
  
        Timeout.add(50, mover)
      
    def pulsado (btn : Button)
        contador=0
      
    def mover():bool
        contador+=1
      
        ti1.set_offset(0)
        ti2.set_offset(contador)
        ti3.set_offset(contador+5)
        ti4.set_offset(longitud(frase))
      
        texto1.buffer.remove_all_tags (ti1,ti4)
        texto1.buffer.apply_tag (blanco,ti1,ti2)
        texto1.buffer.apply_tag (rojo,ti2,ti3)
        texto1.buffer.apply_tag (blanco,ti3,ti4)
        return true



Gtk + Textview y variables de clase

En este ejemplo también vamos a ver como podemos inicializar ciertas variables de una clase y las podrémos usar por toda la clase. Ejemplo: texto1, rojo, blanco,contador. Estas variables las declararemos antes del init de la clase.

Como vemos mucho del texto no es sintaxis propia de vala sino la de GTK+. Por lo tanto para alguien experimentado en Python Gtk (pygtk) o quien haya programado en este interface antes en uno u otro idioma la dinámica es parecida.

Este ejemplo es un pequeño programa en el cual cuando pulsamos el botón el texto se va descubriendo hacia la derecha.   Lo conseguimos usando un contador de posición y creando "tags" que son estilos de texto:(subrayado, negrita,fuente, color...)
e insertando esos estilos en ciertos "Iters" que son por así decirlo punteros para el texto del buffer.


[indent=4]
uses
    Gtk
init

    Gtk.init (ref args)
    var test = new TestWindow ()
    test.show_all ()
    Gtk.main ();
   
   
class TestWindow : Window
    texto1: Gtk.TextView = new TextView
   
    rojo: Gtk.TextTag
    blanco: Gtk.TextTag
    ti1: Gtk.TextIter
    ti2: Gtk.TextIter
    ti3: Gtk.TextIter
    ti4: Gtk.TextIter
       
    acolor : Gdk.Color
    cont:int=0
    boton1: Button= new Button.with_label ("Pulsa este botón")
    contador: int = 0
    palabras: new array of string
    frase:string ="La casa esta rota, pero ya la estamos arreglando"
    vbox : VBox = new VBox (true, 5)
       
    init
        Gdk.Color.parse("#1F2AF1", out acolor)
        rojo=texto1.buffer.create_tag("rojo", "foreground-gdk", acolor);
        blanco=texto1.buffer.create_tag("blanco", "foreground", "White");
       
        texto1.editable = false
        texto1.cursor_visible = false
        palabras= frase.split(" ")
        title = "Ventana de prueba"
        default_height = 360
        default_width = 560
        window_position = WindowPosition.CENTER
        boton1.clicked.connect (pulsado)
       
        destroy.connect(Gtk.main_quit)
        vbox.add (boton1)
        vbox.add(texto1)
        add (vbox)
        texto1.set_size_request(100, 200)
        texto1.buffer.text = frase
        texto1.buffer.get_iter_at_mark (out ti1, texto1.buffer.get_insert ())
        texto1.buffer.get_iter_at_mark (out ti2, texto1.buffer.get_insert ())
        texto1.buffer.get_iter_at_mark (out ti3, texto1.buffer.get_insert ())
        texto1.buffer.get_iter_at_mark (out ti4, texto1.buffer.get_insert ())
       
    def pulsado (btn : Button)
               
        contador++
        ti1.set_offset(0)
        ti2.set_offset(contador)
        ti3.set_offset(contador+5)
        ti4.set_offset(longitud(frase))
       
        texto1.buffer.remove_all_tags (ti1,ti4)
        texto1.buffer.apply_tag (blanco,ti1,ti2)
        texto1.buffer.apply_tag (rojo,ti2,ti3)
        texto1.buffer.apply_tag (blanco,ti3,ti4)


lunes, 23 de julio de 2012

Archivos

Para abrir archivos tenemos una serie de métodos como estos: http://references.valadoc.org/#!api=glib-2.0/GLib.FileStream . En este caso
hemos creado una variable f que será el archivo en modo lectura. Los datos se meterán en "a" a través del método f.gets(a) y nosotros los pasamos a una cadena creada con StringBuilder (Constructor de cadenas) en la variable bu y lo metemos una lista de Gee(atención al compilar usar --pkg gee-1.0 ).

Para aprender el funcionamiento de Stringbuilder. Por ejemplo para crear una cadena a partir de variables tipo caracter. http://references.valadoc.org/#!api=glib-2.0/GLib.StringBuilder


[indent=4] uses Gee init var f = FileStream.open("/home/gontzal/for","r") var a = new array of char[1000] var bu = new StringBuilder () var lista =new list of string while f.gets(a)!= null for s in a do bu.append_c(s) lista.add (bu.str) bu.erase() for h in lista stdout.printf(h)

Importar librerias propias

Cuando nuestro código es muy grande o cuando creamos unas pequeñas librerías para crear un código más limpio llevamos estas funciones o clases a otro fichero. Lo aplicaremos al ejemplo de las cadenas unicode que se ha expuesto en  el capítulo 4.

En el archivo "cadenas.gs" escribiremos las siguientes funciones:
 
[indent=4]

def toma_cadena (a:string,i :int,f:int=-1):string
    b: string
   
    var bu = new StringBuilder ();
    if f==-1
        bu.append_unichar(a.get_char(a.index_of_nth_char(i)))
        b=bu.str
    else
        for var p =i to f
            bu.append_unichar(a.get_char(a.index_of_nth_char(p)))
        b=bu.str
   
    return b


def longitud (a:string):int
    return a.char_count()
 
En el archivo "principal.gs" escribiremos el siguiente código:

[indent=4] a: string init a="áéíóú" stdout.printf ("%i",longitud (a) ) print ("\n") stdout.printf( "%s\n",toma_cadena(a,0,1))


Y para compilar haremos lo siguiente en Geany:
valac -o "%e" cadenas.gs "%f" 
o lo que es lo mismo:
valac -o principal cadenas.gs principal.gs


Esto creará un archivo ejecutable que se llamará principal y usará como fuentes ambos archivos. Por lo tanto no dará error al compilar puesto que las funciones que le faltan en el archivo principal.gs las encontrará en cadenas.gs