sábado, 30 de julio de 2011

Anexo 2: Tabla Resumen de Controles/Propiedades/Funciones


Control
Propiedad / Función / Subrutina añadida
convertirnumeroaletra



Valor: es el numero que introducimos


Enletra: es el texto que nos devuelve la funcion


Moneda: moneda del numero (euro,dolar,etc)


Centimo: unidad de centimo de la moneda (centimo, centavo, etc)


Convertiraletra(): subrutina que nos convierte el numero en letras (publica)


convierteNumero_a_letra(): funcion de conversión (privada)


PalabraPlural(): funcion para pasar al plurales (privada)


Num2Text(): funcion (privada)
supergridviews



Tag2: propiedad de texto, para incluir información (como tag)


Colorfondoimpar: propiedad


Colorfondopar: propiedad


Colorletraimpar:propiedad


Colorletrapar:propiedad


Colorear(): funcion publica


Ponercolorear(): funcion privada


Par(): saber si es un numero par o impar. Funcion privada


Ordenadoalgunavez: comprueba si se ha ordenado. Variable privada


Titulosiniciales: almacena los título de la columnas. Variable privada


Ordenactual: indica como esta actualmente ordenado. Variable privada


Guardartitulosiniciales(): guarda los titulos de las columnas. Subrutina publica


Restaurartitulosiniciales(): restaura los titulos iniciales de las columnas. Subrutina publica


Ordenar(): subrutina pública


ord_ZA(): subrutina privada. Orden Z a la A


ord_AZ(): subrutina privada. Orden Z a la Z


Copiaralportapapeles(): subrutina publica


Revisa(): subrutina privada. Cambia el “.” por la “,” decimal.


Pegardelportapapeles(): subrutina publica


Crearhtml(): crea un archivo en .html del contenido de nuestro supergridviews. Subrutina publica


Suma(): suma la columna que le indiquemos. Función pública


Sumaproducto(): hace el produco de las columnas indicadas. Función pública


Edita(): editamos el contenido de una celda. Subrutina pública


Var.editado: variable global dentro del supergridviews, guarda el contenido de la celda editada, para pasarlo al formulario Feditor


Feditor: formulario para edición del supergridviews
EjesCartesiano



C: distancia del nuevo eje U'x medido segun unidades eje Ux (el del propio control drawingArea) . Propiedad pública


B: distancia del nuevo eje U'y medido segun unidaes Uy (el del propio control DrawingArea. Propiedad pública


Ap1: (A'1) Inicio del intervalo de representación eje U'x


Ap2: (A'2) Fin del intervalo de representación eje U'x


Colorejes: color con el que se van a dibujar los ejes


PasarUpxaUx: funcion para pasar del sistema U' al U, en coordenadas x (horizontal)


PasarUpyaUy: función para pasar del sistema U' al U, en coordenadas y (vertical)


PasarUxaUpx: función para pasar del sistema U al U', en coordenadas x (horizontal)


PasarUyaUpy: función para pasar del sistema U al U', en coordenadas y (vertical)


Dibujarejeup(): función para dibujar el eje U'
Utextbox



Deshacer(): deshace los cambios realizados en un textbox.Función Pública


Rehacer(): rehace los cambios realizados en un textbox.Función Pública


limpiar_deshacer(): funcion para limpiar la memoria de deshacer. Función Pública








Anexo I: Explicación de Soplo de controles

Soplo y maikl
Tu creas una clase nueva.
Si te basas en una clase ya existente pones el inherits
Luego añades la claúsula export.
Luego tienes que definir la constante _properties que es obligatoria. Esta constante proporciona información al IDE de como debe operar con esa propiedad.
También tienes que definir un icono para ese control en la caja de herramientas.
Y por último te tienes que poner a escribir código para esas propiedades y métodos.

la constante _properties
Luego pones la variable _properties que tiene el siguiente formato:
Código: [Descargar] [Ocultar] [Seleccionar]
PUBLIC CONST _properties="*, propiedad1, propiedad2, ..., etc"

cada propiedad en la línea anterior lleva la siguiente información:
Código: [Descargar] [Ocultar] [Seleccionar]
[-] Name [ { Kind [ Arguments ] } ] = Default

El signo menos: Si una de las propiedades la declaras con un signo - significa que las quitas. Eso ocurre si usas un * para heredar todas las propiedades del padre, pero alguna de ellas no la quieres. Entonces la declaras como una mas pero con un signo menos.
La clase puede valer lo siguiente:
Color ---> un entero que representa a un color. Al verlo el IDE sacará un colorchooser para elegir el color
Font ---> Una fuente. El IDE sacará un fontchooser para elegir una fuente.
Path ---> Un path. El IDE sacará un filechooser para elegir un path
Picture ---> Una imagen o un icono de stock. El IDE sacará un picturechooser para elegirla.
Range ---> Una propiedad con valor entero y un valor mínimo y máximo. El IDE sacará un spinbox para elegirlo.
Clase ---> En vez de los casos anteriores puedes poner el nombre de una clase que contenga una lista de constantes.

Si no especificas clase entonces se utiliza el tipo de dato de la propiedad (string, ..., etc).

Ejemplo
Código: [Descargar] [Ocultar] [Seleccionar]
PUBLIC CONST _properties="Enabled=True,Font{Font},Background{Color}=-1,Foreground{Color}=-1," &
"mode{select.*}=Single,Handle,Tag"

Esto declara las siguientes propiedades:
Una propiedad TAG que no tiene ningún valor inicial. Al no especificarle nada el IDE asumirá su valor datatype especificado posteriormente.
Una propiedad HANDLE que no tienen ningún valor inicial. Al no especificarle nada el IDE asumirá su valor datatype especificado posteriormente y que como veremos es integer.
Una propiedad ENABLED que inicialmente valdrá TRUE
Una propiedad FONT. No tiene un valor inicial y para seleccionar una fuente el IDE mostrará el fontchooser.
Una propiedad BACKGROUND que tiene valor inicial -1 (no se que color es ese) y para elegirla el IDE usará el colorchooser.
Una propiedad FOREGROUND que funciona igual que la anterior.
Una propiedad MODE cuyos valores posibles están definidos como constantes en una clase llamada 'select'. Tiene por valor por defecto 'single' que es el nombre de una de esas constantes de esa clase.

Con ello habrás definido el nombre de las diversas propiedades que tendrás. el * se utiliza para heredar todas las propiedades de la clase padre si estás basando tu nueva clase en una ha existente que tendrás que heredar de la siguiente forma:
Código: [Descargar] [Ocultar] [Seleccionar]
inherits nombre_clase

Si una de las propiedades la declaras con un signo - significa que las quitas. Eso ocurre si usas un * para heredar todas las propiedades del padre, pero alguna de ellas no la quieres. Entonces la declaras como una mas pero con un signo menos.

La constante DefaultEvent
Código: [Descargar] [Ocultar] [Seleccionar]
PUBLIC CONST _DefaultEvent AS String = "Click"

Si pones esto (no es obligatorio) entonces al estar en el IDE y hacer doble click para acceder al código te saldrá el evento click para escribir código.

La constante DefaultSize
Código: [Descargar] [Ocultar] [Seleccionar]
PUBLIC CONST _DefaultSize AS String = "36,36"

Es el tamaño del control cuando lo pones en un formulario del IDE. En este caso es 36x36.

La constante _DrawWith
Código: [Descargar] [Ocultar] [Seleccionar]
PUBLIC CONST _DrawWith AS String = "TextBox"

Cuando pongas un control de esta clase en el formulario del IDE pintará un textbox.

La constante _Arrangement
Código: [Descargar] [Ocultar] [Seleccionar]
PUBLIC CONST _Arrangement AS Integer = 2 ' Arrange.Vertical

Es el arrange que tendrán sus hijos si se trata de un contenedor. En el caso propuesto es 2. Los valores posibles son los de la clase arrange.class
Solo se usa si el control es un container.

El icono del componente
En la caja de herramientas debe aparecer un icono del control para poder seleccionarlo. Para definirlo hacemos lo siguiente:
En la raíz del directorio del proyecto creamos una carpeta llamada control que contendrá los iconos (deben ser png) y el nombre del icono debe ser el nombre de la clase.

Implementación de las propiedades
Anteriormente se explicó como declararlas para el IDE. Esto es el icono que tendrá en la caja de herramientas o la manera en que el IDE debe ofrecernos dar valores a las propiedades o el valor por defecto que tendrán.

Pero llega el momento en que hay que escribir código de lo que esas propiedades hacen. Una propiedad será de tipo string o integer o lo que sea.
Código: [Descargar] [Ocultar] [Seleccionar]
PROPERTY Enabled AS Boolean
PROPERTY READ Handle AS Integer
...

PRIVATE $bEnabled AS Boolean
PRIVATE $iHandle AS Integer

' Implements the Enabled property
FUNCTION Enabled_Read() AS Boolean
RETURN $bEnabled
END

SUB Enabled_Write(bEnabled AS Boolean)
$bEnabled = bEnabled
UpdateEverything
END

' Implements the Handle property
FUNCTION Handle_Read() AS Integer
RETURN $iHandle
END

En este caso implementamos la propiedad ENABLED que es de tipo boolean.
Código: [Descargar] [Ocultar] [Seleccionar]
PROPERTY Enabled AS Boolean

y también definimos una propiedad handle que es de tipo entero y de solo lectura
Código: [Descargar] [Ocultar] [Seleccionar]
PROPERTY READ Handle AS Integer


Recuerdo que en _properties se escribió una propiedad enabled=true osea que el ide pondrá el valor true a una propiedad enabled que ahora definimos como boolean.
Como la propiedad ENABLED es de lectura escritura esta será la función para el caso de lectura (nota el _Read)
Código: [Descargar] [Ocultar] [Seleccionar]
FUNCTION Enabled_Read() AS Boolean
RETURN $bEnabled
END

Y esta será la función de escritura para ENABLED (nota el _write)
Código: [Descargar] [Ocultar] [Seleccionar]
SUB Enabled_Write(bEnabled AS Boolean)
$bEnabled = bEnabled
UpdateEverything
END

La variable $bEnabled es una variable privada y UpdateEverything es un método privado de esta clase.

La función handle es de solo lectura así que solo tiene función _read
Código: [Descargar] [Ocultar] [Seleccionar]
FUNCTION Handle_Read() AS Integer
RETURN $iHandle
END


Tras la codificación de las propiedades vendrían los métodos uno de los cuales será un método privado llamado UpdateEverything
Código: [Descargar] [Ocultar] [Seleccionar]
PRIVATE SUB UptadeEverything()
...
END

Y otros serán públicos y devolverán valores
Código: [Descargar] [Ocultar] [Seleccionar]
PUBLIC FUNCTION Ordenar(MiArray as string[]) as string[]
...
return MiArray
END


Así que en definitiva un componente nuevo que se base en un textbox y que admita la propiedad locked que sea boolean y por defecto false sería así:
Código: [Descargar] [Ocultar] [Seleccionar]
inherits textbox
export

PUBLIC CONST _properties="*,locked=false" 'el * hereda todas las propiedades de textbox
PUBLIC CONST _DefaultEvent AS String = "Keypress" 'el evento por defecto en el IDE es keypress
PUBLIC CONST _DrawWith AS String = "TextBox" 'se pinta como un textbox

PROPERTY Locked AS Boolean
PRIVATE FUNCTION Locked_read()
...
END
PRIVATE FUNCTION Locked_write()
...
END
y aquí comenzaría la declaración de métodos

Además crearemos un icono para la caja de herramientas, lo dejaremos en la carpeta controls, será de tipo png y tendrá por nombre el de la clase "miclase.png"

Con esto habremos conseguido un nuevo textbox que se llame como sea y que además de las propiedades del textbox tenga una propiedad nueva llamada locked que puede valer true o false y que hace lo que corresponda según locked_read al leer o locked_write al escribirla.(por ejemplo en este caso anular el keypress) cuando sea true

Se trata de agregar la información global del nuevo componente. Cuando vas a proyecto y propiedades para agregar algún nuevo componente aparece una lista que puedes elegir donde cada componente tiene una descripción y unos requerimientos.

Se trata de completar esa información. Se hace en Proyecto - Propiedades
Pestaña Provee
Por cada clase hay que especificar el tipo y el grupo.
El tipo es si es un control y que clase de control.
Los distintos tipos son:
class ----> una clase normal que no es un control
control --> un control que no es un container
virtual ---> Es una clase que puede ser puesta en el formulario y hace cosas pero no muetra nada (ej. el timer).
container ---> pues eso
multicontainer ----> un control container que contiene otros container pero solo uno visible a la vez como por ejemplo el tabstrip
form ---> solo posible en gambas 3 para especificar alguna nueva clase de formulario.

El grupo es el nombre de la pestaña de la caja de herramientas donde este contról estará incluído (containers, form, network, ..., etc).

La pestaña requiere
Aquí se anotan las dependencias de componentes de este nuevo componente. Por ejemplo quizá hemos hecho un componente que requiere gb.settings.

Hay cuatro opciones. Activar una de ellas (por ejemplo gestión gráfica de formularios) supone que requerimos los componentes básicos para la gestión gráfica de formularios sean cuales fueren.

Si por alguna razón necesitamos uno concreto (quizá porque es uno propio) podemos agregarlo un poquito mas abajo en la opción de componentes. en principio con las cuatro opciones anteriores no debiera ser necesario cuando se trata de componentes nativos de gambas.

Instalación
Basta con hacer el ejecutable y aparecerá en la lista de componentes de las propiedades de un proyecto.


11. Crear el Paquete de Instalación de nuestros componentes

Hasta ahora hemos trabajados con los componentes que hemos realizados en nuestro propio ordenador, pero ¿que pasa si lo tenemos que darselo a otro usuario y que lo instale el en su ordenador?.

Tendríamos entonces tres casos:

  1. Que haya instalado gambas2 con el “centro de software de ubuntu
  2. Que no tenga instalado gambas2, entonces Ubuntu procederá a instalar automáticamente el paquete gambas2-runtime-2.19, actualmente (octubre de 2010) es el paquete que viene en los repositorios oficiales.

Para estos dos casos, la solución es sencilla, ya que desde el proyecto de componente, pulsamos en el menú “Proyecto/Crear/Paquete de Instalación/


Es necesario poner el nombre del
vendedor “gambas2”



Nota:
Elegimos dos opciones como mínimo (en este caso Debian y Ubuntu)
Definimos el Grupo/Admin para Debian

Y también el Grupo/Admin para Ubuntu

Elegimos el destino y pulsamos en “Crear directorio para cada distribución”
Y
finalmente se crean los paquetes










Vemos como se han creado las carpetas y los archivos de instalación para Ubuntu y Debian para el componente “supergridviews”

  1. Caso que lo hallamos instalado con el script de jguardon.
Para este caso lo tendríamos que realizar a “mano”, o sea, con la estructura que sabemos que se crea de carpetas/accesos directo a archivos (ver pag 20, 32 y 33.), hacerlos de igual modo para nuestro componente.
Esto lo podiamos hacer con un pequeño script con bash.
Nota:
En el caso de que instalemos por error el paquete .deb, Ubuntu instalara en gambas2-runtime-2.19, con lo cual estropeará gambas2, y no nos funcionara. La solución que he encontrado es desinstalar el runtime desde Synaptic, y ya tendremos otra nuestro gambas2.21 otra vez en funcionamiento. Pero el componente no aparecerá.

10. Utextbox: deshacer y rehacer

Este código creado inicialmente por angelnu, y mejorado por fabianfv en el hilo del foro gambas-es.org (http://www.gambas-es.org/viewtopic.php?f=4&t=1031&postdays=0&postorder=asc&start=0), nos describe como crear un control textbox añadiendole la propiedad de deshacer y rehacer. A destacar que crea sus propios eventos con su propio observador de eventos y con varios niveles de undo.
Según la documentación:
hObserver = NEW Observer ( Object AS Object [ , After AS Boolean ] )
Crea un nuevo observador en el objeto especificado.
Si el valor de After se establece en TRUE, entonces el observador capturará los eventos después de que hayan sido procesados. En ese caso, no podrá cancelarlos.
A continuación el código:
EXPORT
INHERITS TextBox
'Para que el control se dibuje como un TextBox
PUBLIC CONST _DrawWith AS String = "TextBox"
PRIVATE MiTexto AS String[] 'almacena el texto
PRIVATE indice AS Integer ' numero de elementos del array
PRIVATE DondeEstoy AS Integer ' posicion dentro del array
PRIVATE $hObserver AS Observer ' interceptar el evento change del textbox
PRIVATE BolDeshago AS Boolean ' bandera para no disparar el evento change cada vez que deshacemos o rehacemos

PUBLIC SUB _new()
MiTexto = NEW String[]
MiTexto.Add(SUPER.Text, 0)
$hObserver = NEW Observer(ME) AS "TextBox"
END

PUBLIC SUB TextBox_Change()
IF BolDeshago THEN
STOP EVENT
ELSE
indice += 1
MiTexto.Add(SUPER.Text, indice)
DondeEstoy = indice
ENDIF
END

PUBLIC SUB Deshacer()
IF indice > 0 AND DondeEstoy > 0 THEN
BolDeshago = TRUE
DondeEstoy -= 1
SUPER.Text = MiTexto[DondeEstoy]
BolDeshago = FALSE
ENDIF
END

PUBLIC SUB Rehacer()
IF indice > 0 AND DondeEstoy < indice THEN
BolDeshago = TRUE
DondeEstoy += 1
SUPER.Text = MiTexto[DondeEstoy]
BolDeshago = FALSE
ENDIF
END

PUBLIC SUB Limpiar_Deshacer()
MiTexto.Clear
MiTexto.Add("", 0) 'Añadimos un elemento vacio
indice = 0
BolDeshago = FALSE
DondeEstoy = 0
END


Bien, una vez hecho todo esto, para crear el control haríamos como los casos anteriores (no los voy a explicar ya que están dicho en las paginas 18 y 19 )

Ahora vamos a probarlo en un programa. Creamos un programa llamado “pruebautextbox”, añadimos el componente que hemos diseñado “utextbox” y en el formulario, añadimos 2 botones (hacer y deshacer) y un utextbox, que quede así:


Luego en el código ponemos:

PUBLIC SUB Buttonrehacer_Click()
utextbox1.Rehacer()
END

PUBLIC SUB Buttondeshacer_Click()
utextbox1.Deshacer()
END

Le damos a ejecutar, metemos varios caracteres (incluso podemos borrar) y pulsando el boton deshacer y rehacer vemos como se van realizado los cambios.

9.2 Vamos a utilizar el nuevo control en un ejemplo.


Crearemos un proyecto, incluyendo estos controles: 1 control ejescartesiano, 2 botones (ButtonFuncion y dibujar eje) y dos Toolbotones (ToolButtonmenos y ToolButtonmas)






En el formulario Fmain, colocamos el siguiente código:

' Gambas class file
PUBLIC valor1 AS Float 'contiene donde empieza el gráfico
PUBLIC valor2 AS Float 'contiene donde termina el gráfico
PUBLIC valor AS Integer 'para escalado con botones + o -

PUBLIC SUB Form_Open()
valor1 = -6.28
valor2 = 6.28
valor = 0

ejescartesiano1.ap1 = valor1
ejescartesiano1.ap2 = valor2
ejescartesiano1.B = ejescartesiano1.Height / 2
ejescartesiano1.c = ejescartesiano1.Width / 2

ejescartesiano1.colorejes = 17700

ejescartesiano1.dibujarejeup()
END

PUBLIC SUB dibujafuncionseno(empiezo AS Float, termino AS Float)
DIM x AS Float
DIM puntoxanterior AS Float
DIM puntoyanterior AS Float
Draw.Begin(ejescartesiano1)
Draw.ForeColor = Color.red
Draw.Text("f(x)=sin(x)*x", 40, 60)
ejescartesiano1.dibujarejeup()

FOR x = empiezo TO termino + 0.1 STEP 0.1
IF x = (empiezo) THEN
Draw.Point(ejescartesiano1.pasarUpxaUx(x), ejescartesiano1.pasarUpyaUy(Sin(x)))
puntoxanterior = ejescartesiano1.pasarUpxaUx(x)
puntoyanterior = ejescartesiano1.pasarUpyaUy(Sin(x) * x)
ELSE
Draw.line(puntoxanterior, puntoyanterior, ejescartesiano1.pasarUpxaUx(x), ejescartesiano1.pasarUpyaUy(Sin(x) * x))
puntoxanterior = ejescartesiano1.pasarUpxaUx(x)
puntoyanterior = ejescartesiano1.pasarUpyaUy(Sin(x) * x)
ENDIF
NEXT
Draw.End
END

PUBLIC SUB ejescartesiano1_DblClick()
ejescartesiano1.Clear
ejescartesiano1.B = Mouse.y ' - ejescartesiano1.y
ejescartesiano1.c = Mouse.x ' - ejescartesiano1.x
ejescartesiano1.dibujarejeup()
END

PUBLIC SUB dibujafuncioncos(empiezo AS Float, termino AS Float)
DIM x AS Float
DIM puntoxanterior AS Float
DIM puntoyanterior AS Float
ejescartesiano1.dibujarejeup()
Draw.Begin(ejescartesiano1)
Draw.ForeColor = Color.Orange
Draw.Text("funciones:", 10, 20)
Draw.ForeColor = Color.green
Draw.Text("cos(x)*x*2", 40, 40)
FOR x = empiezo TO termino + 0.1 STEP 0.1
Draw.Begin(ejescartesiano1)
Draw.ForeColor = Color.green
IF x = (empiezo) THEN
Draw.Point(ejescartesiano1.pasarUpxaUx(x), ejescartesiano1.pasarUpyaUy(Cos(x) * x * 2))
puntoxanterior = ejescartesiano1.pasarUpxaUx(x)
puntoyanterior = ejescartesiano1.pasarUpyaUy(Cos(x) * 2 * x)
ELSE
Draw.line(puntoxanterior, puntoyanterior, ejescartesiano1.pasarUpxaUx(x), ejescartesiano1.pasarUpyaUy(Cos(x) * x * 2))
puntoxanterior = ejescartesiano1.pasarUpxaUx(x)
puntoyanterior = ejescartesiano1.pasarUpyaUy(Cos(x) * 2 * x)
ENDIF
NEXT
Draw.End
END


PUBLIC SUB ToolButtonmas_Click()
valor = -1
ejescartesiano1.ap1 = ejescartesiano1.ap1 - valor
ejescartesiano1.ap2 = ejescartesiano1.ap2 + valor
ejescartesiano1.clear
ButtonFuncion_Click()
END

PUBLIC SUB ToolButtonmenos_Click()
valor = 1
ejescartesiano1.ap1 = ejescartesiano1.ap1 - valor
ejescartesiano1.ap2 = ejescartesiano1.ap2 + valor
ejescartesiano1.clear
ButtonFuncion_Click()
END

PUBLIC SUB ButtonFuncion_Click()
ejescartesiano1.dibujarejeup()
dibujafuncionseno(ejescartesiano1.ap1, ejescartesiano1.ap2)
dibujafuncioncos(ejescartesiano1.ap1, ejescartesiano1.ap2)
END

PUBLIC SUB Buttondibujareje_Click()
ejescartesiano1.Clear
Draw.Begin(ejescartesiano1)
Draw.BackColor = Color.blue
ejescartesiano1.dibujarejeup()
Draw.end
END

Y al ejecutar el programa, pulsando el boton “funciones” obtenemos,

Y con al pulsar boton – (lupa menos), podemos hacer zoom



Y al contrario con el + (lupa mas). También podemos hacer click en algun lugar del control para redefinir la posicion de los ejes: