HOWTO développement Sashipa

 

 Généralités sur les états.

Vous trouverez ici quelques généralités pour comprendre les états en Sashipa.

 

Déclations d'éléments préliminaires

On déclare les états dans l'élément optionnel printReportSet, qui se situe entre les éléments graphicalUserInterface.formSet et defaultParameterSet. Exemple :

... </formSet>

<printReportSet>

  <printReport name='PRetat1'>
    <!-- ... -->
  </printReport>
  <printReport name='PRetat2'>
    <!-- ... -->
  </printReport>

</printReportSet>

<defaultParameterSet--> ...

Une fois un état créé, on peut l'ajouter dans un listForm. Il sera alors accessible depuis le menu contextuel de la liste. Voici le code :

  <listForm db='dbContact' doubleClicScreen='SCContactAdresse' delete='yes'>
    <!-- ... -->
    <insertScreen <!-- ... -->
    <printReportList>
      <printReportRef printReport='PRetat1' />
    </printReportList>
  </listForm>

 

Vue générale d'un état : l'élément printReport

Voici le contenu général d'un état :

<printReport name='PREtatExemple'>
  <pageFormat format='A4' orientation='portrait' />
  <pageImageableArea x='30' y='45' w='535' h='752'
                     relativeLocation='yes' />

  <caption>Etat exemple</caption>

  <pageHeader height='20'>
    <xxxDrawFigure> ... </xxxDrawFigure>
  </pageHeader>

  <pageContent>
    <xxxDistribution>

      ... contenu specifique a la distribution ...
      
      <dataRecordPrinter>
        <xxxDrawFigure> 
          ... 
        </xxxDrawFigure>
        <printerDataSource> 
          ... 
        </printerDataSource>
      </dataRecordPrinter>
    </xxxDistribution>
  </pageContent>

  <pageFoot height='13'>
    <xxxDrawFigure> ... </xxxDrawFigure>
  </pageFoot>
</printReport>

Tout d'abord le format de la page. On spécifie l'orientation ('portrait' ou 'landscape'). Puis on indique la zone dans laquelle on va dessiner. Attention : l'unité est une mesure américaine bizarre. Un format A4 (210mm * 297mm) devient 595 * 842. Tous les calculs de coordonnées des élément de l'état se feront dans cette unité de mesure. Si on enlève une marge d'un centimètre, on arrive à cette zone dessinable : x='30' y='45' w='535' h='752'. L'attribut relativeLocation='yes' signifie que au sein de la page, la coordonnée (0, 0) correspondra au coin en haut à gauche de la zone dessinable (et non de la page).

Pour imprimer en mode paysage, il suffit de positionner orientation='portrait'. Attention : ne pas modifier le contenu de pageImageableArea, les x et y ainsi que les width et height s'intervertissent automatiquement. De même si vous définissez la taille de la page manuellement.

Le contenu de l'élément caption sera le libellé affiché dans le menu contextuel des listForm.

Les éléments pageHeader et pageFoot sont optionnels.

L'élément pageContent contient un élément de distribution.

Le plus souvent, l'élément de distribution contiendra un élément dataRecordPrinter qui créera une instance du drawFigure pour chaque ligne de données. Le drawFigure contient donc l'ensemble des composants graphiques à dessiner pour une ligne de donnée. Les données recherchées sont définies dans l'élément printerDataSource.

Les éléments drawFigure et printerDataSource sont donc fortement dépendants l'un de l'autre. Aussi, il est nécessaire de les écrire en même temps.

La répartition des éléments est gérée par l'élément xxxDistribution. Voyons maintenant les trois catégories de répartition...

 

Les différents types de distributions

Les distributions répartissent les drawFigures créées pour chaque ligne de donnée. Vous en avez trois à disposition :

  • listDistribution dessine les drawFigures les uns à la suite des autres, de haut en bas.

  • mailingDistribution réparti les drawFigures sur des étiquettes, de gauche à droite puis de haut en bas.

  • singleRecordDistribution ne s'attend à recevoir qu'une unique ligne de donnée, qu'il dessine.

Un élément de distribution contient un drawFigure, qui créera autant de dessins que de lignes de donnée. Il est temps de voir quels drawFigures nous pouvons utiliser.

 

Les différents types de drawFigures

Les drawFigures sont des composants de dessin, en voici la liste exhaustive :

  • textDrawFigure dessine (en textuel) la valeur d'une instanceColumn de la ligne de données courante.

  • staticTextDrawFigure dessine le texte contenu en dur.

  • predefinedDrawFigure dessine une valeur textuelle automatique, telle que le numéro de page (type='pageNumero').

  • lineDrawFigure dessine un segment.

  • gapDrawFigure ne dessine rien du tout, mais fait comme si un rectangle était dessiné.

  • serieDrawFigure contient une série de drawFigure, alignés soit relativement en vertical (locations='relativeVertical'), soit relativement en horizontal (locations='relativeHorizontal'), soit avec des coordonnées absolues (locations='absolute'). Notez que les drawFigures enfants doivent être déclarés par ordre croissant d'ordonnées.

  • switchDrawFigure contient aussi une série de drawFigure, mais n'affiche que le premier qui dessine effectivement quelque-chose.

  • listDistributionDrawFigure contient une listDistribution (cf élément pageContent) qui peut ainsi contenir une sous-liste disposant d'une source de données autonome. Cette listDistribution peut utiliser comme filtre la clef primaire de la donnée en cours.

  • singleRecordDistributionDrawFigure contient un singleRecordDistribution (cf élément pageContent) qui peut ainsi contenir un unique sous-élément provenant de sa propre source de données. Ce singleRecordDistribution peut utiliser comme filtre la clef primaire de la donnée en cours.

Tous les drawFigure disposent des attributs optionnels x et y. A l'exception du listDistributionDrawFigure et du singleRecordDistributionDrawFigure, tous les drawFigure disposent aussi des attributs maxWidth et maxHeight.

 

L'élément printerDataSource

L'élément printerDataSource est le fournisseur de lignes de données d'une distribution. Il contient soit une selectQuery, soit une selectQueryBuilder ou soit rien.

Il faut savoir qu'un état est calculé depuis un listForm. L'état dispose donc de la source de donnée (et de la requête) du listForm. Il doit la prendre en compte si l'on souhaite imprimer les mêmes données (et dans le même ordre) que le listForm.

  • Une selectQuery est une requête statique. Lorsque le printerDataSource contient une selectQuery, on peut décider soit de remplacer complètement (mode='replace') la requête du listForm (la requête du listForm est alors ignorée). Soit de fusionner (mode='merge' c'est le mode par défaut) : les clauses redéfinies remplacent celles de la listForm, et celles manquantes sont reprises à la requête du listForm. On reprendra au moins les clauses WHERE et ORDER BY si l'on souhaite afficher les mêmes données dans le même ordre.

  • Lorsqu'il contient une selectQueryBuilder le mode devient obligatoirement 'replace'. En revanche, la selectQueryBuilder génère une requête dynamiquement en prenant en compte le filtre courant.

  • Lorsque le printerDataSource ne contient rien du tout, le mode devient obligatoirement 'dispatchParentValues'. Ici, le printerDataSource se contente de reprendre les données qu'il reçoit, c'est à dire celles du listForm le plus souvent.

Voyons un exemple avec une selectQuery :

  <printerDataSource mode='merge'>
    <selectQuery db='dbContact' distinctRequired='no'>
      <selectStatement>
        <instancePk>
          <instanceTable schemaTable='tableContactAdresse' />
        </instancePk>
        <instanceColumnList>
          <instanceColumn schemaColumn='cta_ContactNom' />
          <instanceColumn schemaColumn='cta_ContactPrenom' />
          <instanceColumn schemaColumn='adr_AdresseRue' />
          <instanceColumn schemaColumn='adr_AdresseCP' />
          <instanceColumn schemaColumn='adr_AdresseVille' />
        </instanceColumnList>
      </selectStatement>
      <fromStatement>
        <mainInstanceTable schemaTable='tableContactAdresse' />
        <fkJoin join='inner'>
          <instanceFk schemaFk='fk_adr_Contact' />
        </fkJoin>
      </fromStatement>
    </selectQuery>
  </printerDataSource>

Remarque : le mode par défaut avec une selectQuery est 'merge'. On le reprécise ici pour l'exemple, mais ce n'est pas nécessaire.

 

Choisir un staticRecordPrinter

Revenons un chouilla en arrière : "Le plus souvent, l'élément de distribution contiendra un élément dataRecordPrinter". Le plus souvent mais pas toujours...

On peut lui préférer un élément staticRecordPrinter qui dessine un unique drawFigure quel que soit le nombre et les données qu'il reçoit. En l'utilisant conjointement à un listDistributionDrawFigure on peut, par exemple, créer des titres pour les colonnes qui ne s'afficheraient que sur la première page.

Exemple :

<printReport name='PREtatExemple'>
  <pageFormat format='A4' orientation='portrait' />
  <pageImageableArea x='30' y='45' w='535' h='752' 
                     relativeLocation='yes' />

  <caption>Etat exemple</caption>

  <pageContent>
    <singleRecordDistribution>

      <staticRecordPrinter>
        <serieDrawFigure locations='absolute' atomic='no'
                         visibleAsChild='drawData'>

          ... staticTextDrawFigure pour dessiner les titres ...

          <listDistributionDrawFigure name='drawData' y='26'>
            <listDistribution>
              ...
            </listDistribution>
          </listDistributionDrawFigure>

        </serieDrawFigure>

    </singleRecordDistribution>
  </pageContent>
</printReport>

Remarquez l'attribut visibleAsChild qui spécifie dans quel cas le serieDrawFigure sera visible. Si l'on ne le spécifiait pas, il y aurait systématiquement une page de titre même avec une liste vide. Notez aussi que le changement de page peut survenir entre deux éléments enfants serieDrawFigure (atomic='no'). Il vaut mieux sinon vous ne pourriez imprimer une liste plus grande qu'une page.

 

© Copyright 2003 Sashipa-Melba Team. Ce document de la technologie Sashipa-Melba est sous licence GNU FDL Vous pouvez le copier et modifier librement les copies tant que cette mention apparaît clairement.