My projects website

I have uploaded some of my projects to dotsboxes.tk.

domingo, 28 de septiembre de 2008

Crear Widgets en Scheme 2

La entrada anterior sobre como hacer widgets en Scheme no traía ningún ejemplo. Aquí pondré un ejemplo de como hacer el widget (con código). ¡Se trata de un widget que permite pintar en un canvas% !

(define canva-pintable%
    (class canvas%
      (init-field parent) ; el padre de este control
      (init-field color)  ; el color con el que dibujaré

      (super-new (parent parent)(min-width 400)(min-height 400)(horiz-margin 2)(vert-margin 2)
                 (paint-callback (lambda (cnv dc)(void)))
                 (style '(control-border vscroll hscroll)))
      
      (send (send this get-dc) set-pen color 1 'solid)
      
      ;recibe un mouse-event%
      (define/override (on-event evento)
        (cond ((send evento dragging?) (send (send this get-dc) draw-point (send evento get-x) (send evento get-y)))
        )
        )
      
      (define/override (on-char evento)
        (send (send this get-dc) clear)
        )
      )
    ) ;fin de mi widget

(define miVentana (new frame% (label "Dibujame!")))
(define miCanva (new canva-pintable% (parent miVentana)(color "black")))
(send miVentana show #t)

El programa final se vería algo así:

sábado, 27 de septiembre de 2008

Crear widgets en Dr. Scheme

Haciendo una progra en Dr Scheme (el administrador de álbumes para Ruidosa S.A.) quise usar una tabla para mostrar la información sobre los álbumes, etcétera. Investigando en la documentación descubrí la pavorosa noticia: ¡Mr. Ed NO tiene tablas!

Para solventar esto inicialmente usé varias list-box% pegadas, pero como el resultado es estéticamente feo (y quise agregar extras a la tabla) me decidí por implementar por completo mi propio widget.

Un "widget" en Scheme en realidad es una clase que extiende a otra clase que sí es un widget. Cuando hagamos nuestros widgets lo más probable es que extendamos alguna clase horizontal-panel%, vertical-panel%, o canvas%. También puede usar cualquier otro control si lo desea. La imagen es una captura de mi widget tabla. Esta permite añadir texto o imágenes a una columna, añadir filas, encabezado, cambiar el tamaño de las columnas y autoordenar por columna al hacer clic en el encabezado. Este una extensión de la clase canvas%.

Un widget tiene como ventaja que se puede programar una vez y usarse muchas veces, incluso en proyectos ajenos (obviamente si está bien diseñado). También se caracteriza porque cada instancia es independiente de las demás. Por ejemplo, podemos crear un widget formulario y los datos de cada formulario estarán aislados de los otros.

A por el código

El código propio del widget no es muy diferente a cualquier otro programa de Scheme. "Simplemente" hay que programar todo el comportamiento de este, que sucede cuando recibe el foco, cuando lo pierde, cuando recibe clics, teclasos, etc. La parte diferente viene acá:

(module advTable
  mzscheme
  
  (provide (all-defined))
  
  (require  (lib "mred.ss" "mred")
            (lib "class.ss")
            (file "sortCadenas.ss"))
  
  (define advanced-list%
    (class canvas%
      (init-field parent)
      (init-field callback)

      (super-new (parent parent)(min-width 500)(horiz-margin 2)(vert-margin 2)
                 (paint-callback (lambda (cnv dc)(Redibujar cnv dc)))
                 (style '(control-border vscroll hscroll)))

   ;...
   ;el resto del código va aquí
   ;...
   ;hay que cerrar los paréntesis :)

  1. El "module advTable" indica que se desea crear un módulo, en este caso llamado advTable.
  2. La instrucción (provide (all-defined)) indica que el módulo expone al exterior todas las funciones definidas (esto tal vez no es algo deseado, pero esto lo programé en aquellos tiempos que...).
  3. Luego vienen las instrucciones "require": las dos primeras aparentemente son necesarias, la última es de una clase auxiliar de mi programa.
  4. Luego viene la definición del widget propiamente dicha. En este caso la variable se llama advanced-list% (para seguir con los nombres de Dr. Scheme...). Como se ve el valor de la variable es una clase canvas%.
  5. Los init-field sirven para especificar valores a la hora de crear el widget en el programa (mas tarde hablaré de ellos).
  6. Para finalizar el super-new lo que hace es que instancia la clase padre del widget, en este caso un canvas%, de estos parámetros todos son los normales a la hora de crear un canvas% excepto quizá (lambda (cnv dc)(Redibujar cnv dc)). Esta es una función que redibuja la canvas% y está dentro del widget. Quizá hayan notado que hay un (init-field parent) y un (parent parent); las palabras en rojo se refieren a la misma variable.
  7. El canvas% tiene funciones propias, como on-event, on-size, entre otras. Lo que debemos hacer para implementar nuestras funciones es suplantar estas funciones. Esto se hace definiendo la función con el mismo nombre, pero en lugar de usar un define se escribe define/override. Esto indicará a Scheme que se desea suplantar la función actual por esta. Es importante verificar que nuestra función tenga la misma sintaxis que la original.

Finalmente para poder usar nuestro widget en nuestro programa debemos el siguiente código al principio del programa:

(require (file "advTable.ss") ; así se llama nuestro archivo con el widget
         ;... otras bibliotecas que se requieran...
         )

Y ya podemos usar nuestro widget como cualquier otro. Por ejemplo para crear una instancia de la tabla se usaría el siguiente código:

(define tbxRecorridos (new advanced-list%
                           (parent panRecorridos) ; formulario padre que contiene el widget
                           (callback recorridosCallback) ; función a la que se llamará 
                                                         ; cuando ocurra un evento
                           )
  )

Nótese que "parent" y "callback" son los nombres especificados en los init-field del widget.

Para crear documentos...

Tal vez se hayan encontrado en la situación que necesitan crear un documento pero al comenzar a redactarlo notan que el programa que usan se queda corto para lo que necesitan. Esto es especialmente cierto si el documento es "muy técnico": tiene gran cantidad de expresiones matemáticas, código fuente de programas, si el documento es exageradamente largo o si quieren cambiar la numeración de las páginas para que primero sea en números romanos y luego en arábigos.

Afortunadamente para aquellos que de vez en cuando tenemos que hacer esta clase de documentos existe LATEX. Según Wikipedia:

(LaTeX) es un lenguaje de marcado para documentos, y un sistema de preparación de documentos, formado por un gran conjunto de macros de TeX, escritas inicialmente por Leslie Lamport (LamportTeX) en 1984, con la intención de facilitar el uso del lenguaje de composición tipográfica creado por Donald Knuth. Es muy utilizado para la composición de artículos académicos, tesis y libros técnicos, dado que la calidad tipográfica de los documentos realizados con LaTeX es comparable a la de una editorial científica de primera línea. LaTeX es software libre bajo licencia LPPL.

Para comenzar a usar LaTeX solo es necesario un editor de textos (Bloc de Notas, KWrite, etc), bajarse el paquete de LaTeX (para Windows está miktex, para Linux quizá ya esté instalado :)) y no asustarse por la impresión inicial. Es menos complicado de lo que parece.

Lo que yo hice en Windows fue instalar MikTex (http://miktex.org/) y luego instalar TeXnicCenter (http://www.toolscenter.org/). TeXnicCenter es un programa que facilita la escritura de documentos en LaTeX.

Entradas relacionadas

Related Posts with Thumbnails