Dynamic Engine

Author Alberto Bellina
Title Dynamic Engine
Date 31 Marzo 1999
Version 1.0
Thanks to Luca Quintarelli for many, many, ... and many helps and also for some really useful routines (Scroller, ...).

Indice


index Introduzione

Con Dynamic Engine (di seguito nel documento DynEng) si intende una serie di motori che lavorando in collaborazione consentono di semplificare il lavoro di creazione dei programmi.
Allo stato attuale DynEng gestisce le seguenti operazioni:

                  forms        forms       printer        DB
                    |            |            |            |
                    v            v            v            v
    +--------------------------------------------------------------+
    |          +---------+  +---------+  +---------+  +---------+  |
    |          |         |  |         |  |         |  |         |  |
    |  DynEng  | DynGui  |  |DynSpread|  | DynRpt  |  | DynDb   |  |
    |          |         |  |         |  |         |  |         |  |
    |          +---------+  +---------+  +---------+  +---------+  |
    +--------------------------------------------------------------+
         ^                      ^
         |                      |
         |                      v
    +-------.              +---------+
    |       |\             |         |
    |       +-\            |  User   |
    | DynFile |            | Program |
    +---------+            +---------+

Questo strumento consente di avere un prodotto di RAD che consente di costruire un programma con pochi passi e senza necessitare di programmazione per la gestione delle operatività classiche.


^DynGui

Questa parte del motore si incarica della creazione e della gestione dell'interfaccia grafica.
E' la parte centrale in quanto è la parte che deve esistere per consentire l'esistenza delle altre componenti.
Si evince quindi che per avere la parte di report si deve avere una form di presentazione dei dati.
L'interfaccia grafica è creata a partire da files di formato testo o cryptato.


       +-------.        +---------+      +---------+
       |       |\       |         |      |         |
       | File  '-\ <--> | DynGui  | <--> |   GUI   |
       | dynGui  |      |         |      |         |
       +---------+      +---------+      +---------+

indexLogical Name

Il LogicalName è il nome con cui l'oggetto viene visto sia all'interno di DynEng che dall'applicativo e nel Database.
Se il programma trova lo stesso LogicalName per più oggetti segnala l'errore adeguatamente.

indexAttributes

Alcuni oggetti possono essere caratterizzati nelle loro funzioni mediante alcuni attributi.
Di seguito gli attributi disponibili, gli oggetti su cui operano e il loro significato.

ATTRIBUTEOBJECTSDESCRIPTION
A TextBoxCampo di soli caratteri alfabetici.
AN TextBoxCampo caratteri alfanumerici.
N TextBoxCampo di soli caratteri numerici.
P TextBoxCampo per valore percentuale 0-100.
H TextBoxRende invisibile l'oggetto.
Viene utilizzato per inserire calcoli intermedi oppure per eseguire dei controlli su una serie di campi
OUT TextBoxCampo di solo output.
LEFT TextBoxAllinea a sinistra
RIGHTTextBoxAllinea a destra
F TextBoxTO DO Campo di soli caratteri numerici con virgola.

indexLayout

Il layout degli elementi grafici su un frame segue alcune regole di massima che possono essere definite comuni alla maggior parte dei programmi che utilizzano una logica di data-entry.
E' possibile in effetti disporre in colonne gli elementi:


    +----------------------------------------------------+
    | Title of form...                                   |
    +----------------------------------------------------+
    |  +---------------------+    +-----------+ +-----+  |
    |  | label...            |    | textbox   | |label|  |
    |  | label...            |    | combobox  | |     |  |
    |  | label...            |    | checkbox  | |     |  |
    |  | ...                 |    | ...       | |...  |  |
    |  +---------------------+    +-----------+ +-----+  |
    +----------------------------------------------------+

La figura soprastante illustra una tipica disposizione, nella colonna 1 è inserita la descrizione del contenuto da inserire nell'oggetto in colonna 2, ed eventualmente in colonna 3 è presente una unità di misura del valore inserito.

Ovviamente quanto sopra e' solo un esempio di una tipica disposizione, ma l'elasticità della gestione del layout consente la creazione di maschere molto complicate.

Allo stato attuale è possibile gestire fino a 10 colonne (ma facilmente aumentabili).
E' possibile anche modificare la spaziatura verticale tra gli oggetti, consentendo la presentazione di oggetti più alti del solito (per esempio una label multilinea).


Il Layout delle colonne viene definito nel seguente modo:


    OPT{LAYOUTNCOL|Ncolumn|X1|W1|X2|W2...}

Dove Ncolumn indica il numero di coppie X e W che segue
Xn è la posizione orizzontale
Wn e' la larghezza massima che deve occupare la colonna.

Dove utilizzando al posto di Xn il carattere . significa prendi la precedente posizione X sommagli la precedente W ed aggiungi un piccolo spazio di margine.
Cioè scrivendo:
La seconda colonna partirà dalla posizione 2000 circa.

Il Layout delle righe viene definito nel seguente modo:


    OPT{LAYOUTROW|Heigth}

Dove Height è l'altezza che deve essere utilizzata per ogni linea.

E' possibile modificare piu' volte il layout durante la lettura delle specifiche di definizione di una interfaccia grafica, e questo consente la massima elasticità nella creazione delle stesse.


indexVertical ScrollBar

Quando campi inseriti dinamicamente nell'interfaccia grafica superano la capacità verticale del frame verrà automaticamente inserita una scrollbar verticale.


+----------+     +----------+     +------------------+
| finestra | --- | scroller | --- | elementi grafici |
+----------+     +----------+     +------------------+

L'elemento scroller provvederà a gestire lo scrolling degli elementi contenuti nella finestra in modo automatico.

Le relazioni degli attori in gioco nella fase di scrolling e' la seguente:


    +--------------------+
    |  Label     Text    |
    |  Label     Text    |
    |  Label     Text    |
    | +-----------------+|
    | |Label     Text |^|| ------> +----------+
    | |Label     Text | ||         | scroller |
    | |Label     Text |v|| ------> +----------+
    | +-----------------+|
    |  Label     Text    |
    |  Label     Text    |
    +--------------------+

In effetti esistono sempre due frame sovrapposti: uno di altezza sufficiente a contenere tutti gli oggetti, ed uno superiore dell'altezza della finestra.
L'elemento scroller provvede ad ogni azione sulla scrollbar a visualizzare la parte di frame sottostante nel fram superiore.
Il tutto in modo automatico e senza nessuna operazione a livello di codice utente.

indexGui Objects

Gli oggetti inseribili nell'interfaccia grafica sono i seguenti:

Ognuno di questi oggetti (in modo diverso) è configurabile per gestire le varie particolarità che necessitano in una interfaccia grafica evoluta.

Ogni oggetto ha delle caratteristiche base che consentono di poterlo utilizzare senza aggiungere alcun codice utente, per esempio se il campo è un TextBox e viene definito come numerico automaticamente viene inizializzato con il valore 0, allineato a destra, è consentito solo l'input di numeri e viene automaticamente mostrato il numero con i separatori dei decimali.

Per ciascun oggetto gestisce inoltre le seguenti caratteristiche

indexTab

La gestione dei Tab consente di creare un interfaccia grafica come da disegno:


    +------------------------------------------------------+
    | Title of form...                                     |
    +------------------------------------------------------+
    | +--------+---------+-----------+                     |
    | | Tab1   | Tab2    | Tab3      |                     |
    | |        +---------'-----------'-------------------+ |
    | | +---------------------+    +-----------+ +-----+ | |
    | | | label...            |    | textbox   | |label| | |
    | | | label...            |    | combobox  | |     | | |
    | | | label...            |    | checkbox  | |     | | |
    | | | ...                 |    | ...       | |...  | | |
    | | +---------------------+    +-----------+ +-----+ | |
    | +--------------------------------------------------+ |
    +------------------------------------------------------+

Ognuno dei tab contiene un set di oggetti grafici di tipo semplice che sono indipendenti tra di loro.
Eventuali formule possono comunque riferirsi a campi di Tab diversi.

La gestione delle selezioni dei vari Tab viene gestita mediante una semplice routine che utilizza il LogicalName del Tab.


Private Sub TabStrip1_Click()
    Dim i As Integer
    Dim f As cFrame
    Dim f1 As cFrame
    Dim key As String

    For i = 1 To ntab
        key = TabStrip1.SelectedItem.key
        Set f = fields.item("TAB" & i)
        Set f1 = fields.item("FRA" & i)
        If key = "TAB" & i Then
            f.visible = True
            f1.visible = True
        Else
            f.visible = False
            f1.visible = False
        End If
    Next i
End Sub

Viene definito nel seguente modo:


    TYPE{TAB|LogicalName|Caption}

indexLabel

La label è l'oggetto più semplice che può gestire DynEng, è composto semplicemente da un nome logico e dalla sua caption che viene presentata a video e stampata.

Viene definita nel seguente modo:


    TYPE{LABEL|LogicalName|Caption}
    TYPE{LABELCR|LogicalName|Caption}

indexTextBox

Questo è l'elemento sicuramente più utilizzato nelle interfaccie grafiche e di conseguenza anche il più complesso.

Viene definito nel seguente modo:


    TYPE{LTEXT|LogicalName|Len|Attribute|Formula|Default|Help}
    TYPE{LTEXTCR|LogicalName|Len|Attribute|Formula|Default|Help}

indexComboBox


Viene definito nel seguente modo:


    TYPE{COMBO|LogicalName|Len|Caption}
    TYPE{COMBOCR|LogicalName|Len|Caption}

indexCheckBox


Viene definito nel seguente modo:


    TYPE{CHECK|LogicalName|Caption}
    TYPE{CHECKCR|LogicalName|Caption}

indexCommandButton


Viene definito nel seguente modo:


    TYPE{COMMAND|LogicalName|Len|Caption}
    TYPE{COMMANDCR|LogicalName|Len|Caption}

indexOptions

Per rendere il più possibile versatile la gestione degli oggetti è stato già previsto in fase di creazione di DynEng la possibilità di memorizzare per ogni oggetto grafico 10 diverse opzioni.
L'utilizzo di queste opzioni è lasciato libero e sono definibili dall'utilizzatore a suo piacimento.
Per esempio potrebbe essere utilizzata una opzione per definire i campi che devono o meno essere stampati.
Le opzioni sono memorizzate come stringhe di caratteri e se si vuole utilizzarle come numeriche (o boolean) le relative operazioni di conversioni devono essere fatte.

indexDynRpt

Il motore di stampa provvede alla stampa automatica dei dati sull'interfaccia grafica.
I campi HIDE non sono stampati.

indexDynDb

La gestione dei dati a video definisce anche la conformazione fisica del DB.

indexTables

Le tabelle del DB non sono costituite come nel classico DB: cioè una tabella raggruppa informazioni e record logicamente correlati tra di loro.
In DynEng invece tutti i dati sono inseriti in una unica tabella dove esistono due chiavi che li identificano: l'oggetto di appartenenza e il nome logico del campo relativo.


     +-------+                +--------------------+
     | OBJ   |                | DATA               |
     | obj   |                | obj  name  value   |
     |   3   | -----------+-> |   3  A1    prova   |
     |  12   | ----+      '-> |   3  A2    test    |
     | ...   |     +------+-> |  12  A1    nome... |
     +-------+            +-> |  12  A2    cogn... |
                          '-> |  12  A3    via...  |
                              | ...                |
                              +--------------------+

Il disegno sopra indica in maniera schematica la relazione tra le tabelle principali che compongono il DB.
Questa soluzione presenta alcuni vantaggi ed alcuni svantaggi.
Vediamo prima quali vantaggi presenta:
Per contro presenta i seguenti svantaggi:


indexTable OBJ

La tabella OBJ è la tabella in cui sono memorizzati i dati generali di un oggetto e da cui si può puntare ai suoi dati nella tabella DATA.

Qui devono essere inoltre memorizzati anche i dati che devono essere utilizzati spesso, per esempio per stampe.
Alcuni dei campi della tabella OBJ sono costanti, mentre possono esserne aggiunti a piacere (dimensione massima dei record di Access permettendo) per scopi del programma che utilizza DynEng.
Per esempio se decidiamo di gestire oggetti anagrafici, alcuni dati come cognome, nome, ed indirizzo può essere comodo inserirli nella tabella OBJ cosi da averli pronti all'uso nel caso di stampe tabellari.

indexTable DATA

La tabella DATA contiene tutti i dati presenti nell'interfaccia grafica in modo automatico.
Ogni campo viene contrassegnato dal nome logico e dal valore contenuto, e tali dati sono utlizzati nella tabella DATA.

indexTable FIELD

La tabella FIELD non è indispensabile, ma viene utilizzata per velocizzare alcuni accessi ai dati.

indexTable MODEL

La tabella MODEL contiene l'indicazione dei modelli presenti.

indexDynSpread

Il motore di calcolo stile spreadsheet è automaticamente incluso creando l'interfaccia grafica.
Il semplice inserimento di una formula ne determina la sua attivazione.
Le formule sono costituite da variabili, funzioni ed operatori.
vediamo di seguito cosa si intende nei vari casi.

Variabili Sono variabili tutti quei nomi che iniziano con un carattere alfabetico (A-Z,a-z) e NON hanno come carattere immediatamente seguente il nome la parentesi tonda aperta.
La lunghezza delle variabili è arbitraria.
Esempio di nomi di variabili:
    var1, VAR2, VaR3, V_A_R_4, ...
            
Funzioni Sono funzioni tutti quei nomi che iniziano con un carattere alfabetico (A-Z,a-z) e hanno come carattere immediatamente seguente il nome la parentesi tonda aperta.
Sono possibili funzioni senza e con parametri.
La lunghezza delle funzioni è arbitraria.
Un certo numero di funzioni sono built-in:
    abs(n), neg(n), date(), time(), ... 
Esempio di nomi di funzione:
    funzione1(), sum(A1,A2), ... 
Operatori Gli operatori sono di tipo aritmetico:
                (+ - / * ^)
            

Il parser delle espressioni è stato volutamente semplificato per consentire la maggior velocità possibile di funzionamento.
E' possibile inoltre di chiamare funzioni implementate dall'utente semplicemente inserendole nella classe cFunction.cls, senza dover modificare il parser delle funzioni.

indexCell names


indexBuild-in Function

Le funzioni built-in sono quelle di maggior utilizzo per effettuare calcoli o controlli sulle celle.
Di seguito l'elenco delle funzioni utilizzabili e loro spiegazione:

NAMEDESCRIPTION
date()Ritorna la data odierna in formato dd/mm/yyyy
time()Ritorna l'ora corrente in formato hh:mm
abs(v)Ritorna il valore assoluto di v. Es: se v=-3 ritorna 3
neg(v)Ritorna il valore negato di v. Es: se v=3 ritorna -3

indexEsempi

Esempi di formule valide:

indexDynFile

Il file di definizione della GUI deve definire tutti gli oggetti grafici utilizzati.
E' stato costruito con i seguenti obiettivi.














indexTechnical


            +------------+------------+-------------------+
            |            |            |                   V
       +-------.    +-------.    +-------.           +-------.
       |       |\   |       |\   |       |\          |       |\
       | Class '-\  | Class '-\  | Class '-\         |       '-\
       | cLabel  |  | cText   |  | cCombo  |         |  Vars   |
       +---------+  +---------+  +---------+         +---------+
            |            |            |                   |
            +------------+------------+                   |
                         |                                |
                    +-------.                             |
                    |       |\                            |
                    | I/F   '-\                           |
                    | DynObj  |                           |
                    +---------+                           |
                         |                                V
                    +-------.                        +-------.
                    | Class |\                       | NT    |\
                    | Obj   '-\ -------------------> | Parser'-\
                    | Collect |                      | Runtime |
                    +---------+                      +---------+
                         |
                    +-------.                        +------+
                    |       |\                       |      |
                    | Class '-\ <------------------> |  DB  |
                    | cDynamic|                      |      |
                    +---------+                      +------+
                         |                               ^
                         V                               |
                    +---------+                          |
                    |         |                          |
                    |   APP   | <------------------------+
                    |         |
                    +---------+
Ogni oggetto appartenente all'interfaccia grafica del programma viene inserito in una collezione che ne gestisce gli aspetti generali.
La classe NT contiene il parser delle formule (che le compila) e il RunTime che le esegue.
Alla partenza del programma viene attivato il parser delle formule che le compila preparandole per l'esecuzione.
Ogni nome e valore di un campo viene memorizzato in una classe di Variabili, per essere piu' rapidamente accessibili dal RunTime.
Ad ogni variazione di valore di un campo la relativa variabile viene aggiornata e viene richiamato il RunTime per l'esecuzione delle formule (possibilmente solo quelle che contengono la variabile variata).
In modalità realizzazione facendo doppio click su un campo è possibile modificarne le caratteristiche.
ATTENZIONE: si deve gestire il riferimento relativo, cioè quando una cella si riferisce ad un altra cella che è solo risultato di un altra cella, p.es:
A1 .. input valore
A2 .. input valore
A3 .. IIF(A1>A2, A1, A2)
A4 .. IIF(A3>10, A3, 10)
Modificando la cella A1 o A2 la cella A4 non riesegue il calcolo !!!
Eventualmente mettere flag per indicare di ricalcolare tutto quando toccata una cella che fa parte di altri calcoli.



indexGlossary

GUI Graphics User Interface
RAD Rapid Application Development

indexBibliografy

Rif.Document
[1]
[2]
[3]