Base : Réentrance des macros basic dans le traitement des évènements des formulaires ...

classic Classic list List threaded Threaded
3 messages Options
Patrick Gelin Patrick Gelin
Reply | Threaded
Open this post in threaded view
|

Base : Réentrance des macros basic dans le traitement des évènements des formulaires ...

Bonjour,

J'utilise Base avec les Macros Basic pour développer une base de donnée
documentaire. Lors du traitement de l'évènement du formulaire principal
"Changement d'enregistrement" j’exécute une macro un peu longue et je
suis confronté à un problème de réentrance. Ma macro est un peu longue
car j'utilise des formulaires un peu complexes utilisant des sections
pour gérer à la fois des onglets mais aussi l'affichage contextuel de
telle ou telle section en fonction des valeurs de certains champs
saisies par l'utilisateur... Ce problème de réentrance peut être
schématisé par le scénario suivant :

t = 0                  Enregistrement courrant de la forme est le n°10
t1                     EVENEMENT 1 (Enregistrement courrant de la forme
devient le n°11)
t1 + delta t           EVENEMENT 2 (Enregistrement courrant de la forme
devient le n°12, Macros évènement 1 interrompue n'importe où...)
t2                     FIN TRAITEMENT EVENEMENT 2 (synchrone avec
l'enregistrement courrant n°12 de la forme)
t3                     REPRISE ET FIN DU TRAITEMENT DE L'EVENEMENT 1
(/!\ Traitement de l'enregistrement n°11 qui n'est plus l'enregistrement
courrant de la forme, et qui devrait au contraire s'interrompre
immédiatement par un appel à exit())

Ce problème n'est pas seulement révélé par la durée du traitement de ma
macro mais aussi il me semble pour deux raisons spécifiques à
l'application LibreOffice:

1. Il me semble que par défaut la barre de navigation des formulaires
utiliserait le principe de la répétition sur ses touches (activé après
un délai très cours). Si bien que très souvent l'appui sur le bouton
(avec le triangle) pour passer à l'enregistrement suivant commande un
double changement d'enregistrement... Et donc je reçois deux évènements
très rapprochés à traiter...
2. J'ai lu dans le livre "Benitez , Roberto - Database Programming with
OpenOffice.org Base & Basic – 10 septembre 2008" que le formulaire
pouvait déclencher deux évènements envoyés pour le premier par le
composant "com.sun.star.form.FmXFormController" et l'autre par
"com.sun.star.comp.forms.ODatabaseForm". Mais un test dans mon code de
traitement de l'évènement ne semble pas révéler ce problème... C'est
plutôt le cas 1 qui semble concerner ma macro...

Pour essayer une première solution j'ai caché la barre de navigation des
formulaires et j'ai ajouté 2 ou 3 boutons de navigation spécifiques à
mon formulaire, en veillant à désactiver la répétition de touche. De
fait je suis moins confronté au problème des doubles évènements. Mais
cela n'empêche pas l'utilisateur de double cliquer rapidement ou même
triple cliquer rapidement sur les boutons, et je me retrouve à nouveau
avec le même problème de réentrance...

J'ai essayé d'utiliser dans ma macro basic les appels aux quelques APIs
UNO comme par exemple ThisDatabaseDocument.lockControllers (ou encore
addActionLock). Mais cela n'empêche pas l'envoi des doubles messages.
J'ai cherché dans la documentation UNO des informations sur les mutex,
le multithreading mais je n'ai trouvé aucune API disponible dans les
macros basic... J'ai compris que cette partie de LibreOffice était en
cours de refactoring. Mais cela concernera t-il les APIs des macro Basic
? Pour quelle prochaine date/version ?

J'ai également essayé de mettre en place un flag et un appel à wait()
pour gérer une forme de Mutex. J'ai aussi utilisé un chien de garde pour
détruire ma tache si le temps d'attente dépassait un timer. Mais l'appel
à wait dans l'évènement n°2 ne redonne pas la main au thread du
traitement de l'évènement n°1, et donc cela ne sert à rien...

Je me pause une autre question : Est-il possible de modifier la gestion
des évènements au niveau de l'objet gérant le broadcaste, pour envoyer
les évènement uniquement en série ? je crois comprendre que le broadcast
serait géré par un objet frame en lien avec mon formulaire ...

Je pourrais aussi envisager transformer ma macro pour la rendre
réentrante. Techniquement j'ai compris qu'il suffirait de n'utiliser que
des variables locales. Mais lorsque la macro de l'évènement 1 terminera
son traitement elle ne sera pas informée que l'enregistrement courrant a
été modifié, et donc elle ne devrait pas être réentrante, mais plutôt
quitter par un appel exit() ou même un appel stop()... Et pour cela il
faudrait que les évènements 1 et 2 communiquent ensembles ...

Merci pour votre aide ...
Patrick

--
Envoyez un mail à [hidden email] pour vous désinscrire
Les archives de la liste sont disponibles à https://listarchives.libreoffice.org/fr/users/
Tous les messages envoyés sur cette liste seront archivés publiquement et ne pourront pas être supprimés
Jean-Francois Nifenecker Jean-Francois Nifenecker
Reply | Threaded
Open this post in threaded view
|

Re: Base : Réentrance des macros basic dans le traitement des évènements des formulaires ...

Bonjour Patrick,

Le 19/01/2018 à 09:51, [hidden email] a écrit :

>
> J'utilise Base avec les Macros Basic pour développer une base de donnée
> documentaire. Lors du traitement de l'évènement du formulaire principal
> "Changement d'enregistrement" j’exécute une macro un peu longue et je
> suis confronté à un problème de réentrance. Ma macro est un peu longue
> car j'utilise des formulaires un peu complexes utilisant des sections
> pour gérer à la fois des onglets mais aussi l'affichage contextuel de
> telle ou telle section en fonction des valeurs de certains champs
> saisies par l'utilisateur... Ce problème de réentrance peut être
> schématisé par le scénario suivant :
>
> t = 0                  Enregistrement courrant de la forme est le n°10
> t1                     EVENEMENT 1 (Enregistrement courrant de la forme
> devient le n°11)
> t1 + delta t           EVENEMENT 2 (Enregistrement courrant de la forme
> devient le n°12, Macros évènement 1 interrompue n'importe où...)
> t2                     FIN TRAITEMENT EVENEMENT 2 (synchrone avec
> l'enregistrement courrant n°12 de la forme)
> t3                     REPRISE ET FIN DU TRAITEMENT DE L'EVENEMENT 1
> (/!\ Traitement de l'enregistrement n°11 qui n'est plus l'enregistrement
> courrant de la forme, et qui devrait au contraire s'interrompre
> immédiatement par un appel à exit())
>
> Ce problème n'est pas seulement révélé par la durée du traitement de ma
> macro mais aussi il me semble pour deux raisons spécifiques à
> l'application LibreOffice:
>
> 1. Il me semble que par défaut la barre de navigation des formulaires
> utiliserait le principe de la répétition sur ses touches (activé après
> un délai très cours). Si bien que très souvent l'appui sur le bouton
> (avec le triangle) pour passer à l'enregistrement suivant commande un
> double changement d'enregistrement... Et donc je reçois deux évènements
> très rapprochés à traiter...
> [...]
> Pour essayer une première solution j'ai caché la barre de navigation des
> formulaires et j'ai ajouté 2 ou 3 boutons de navigation spécifiques à
> mon formulaire, en veillant à désactiver la répétition de touche. De
> fait je suis moins confronté au problème des doubles évènements. Mais
> cela n'empêche pas l'utilisateur de double cliquer rapidement ou même
> triple cliquer rapidement sur les boutons, et je me retrouve à nouveau
> avec le même problème de réentrance... [...]

Tu pourrais, lors de l'événement Clic sur ton bouton de navigation,
initialiser un drapeau qui pourrait être lu lors du clic sur les divers
boutons de navigation. Tant que ce drapeau serait à True, les événements
correspondants ne lanceraient aucune exécution.

Tu pourrais aussi, et ça me semble plus visuel pour l'utilisateur,
puisque ces boutons sont sous ton contrôle, les désactiver dès que l'un
d'entre eux est cliqué, puis les réactiver lorsque l'événement a été traité.

Ces solutions me semblent plus facile à gérer que d'essayer de gérer la
réentrance. Je considère pour ma part que le langage de macro Basic de
LibreOffice n'est pas destiné à ça. Si les besoins deviennent très
pointus, je pense qu'un autre langage serait plus approprié (Python ?).


Si vous répondez, merci de penser à utiliser la fonction "répondre à
tous" de votre logiciel de courrier électronique de façon que la liste
reçoive une copie de votre réponse.

Bien cordialement,
--
Jean-Francois Nifenecker, Bordeaux


--
Envoyez un mail à [hidden email] pour vous désinscrire
Les archives de la liste sont disponibles à https://listarchives.libreoffice.org/fr/users/
Tous les messages envoyés sur cette liste seront archivés publiquement et ne pourront pas être supprimés
Patrick Gelin Patrick Gelin
Reply | Threaded
Open this post in threaded view
|

Re: Base : Réentrance des macros basic dans le traitement des évènements des formulaires ...

On 19/01/2018 18:19, Jean-Francois Nifenecker wrote:

> Bonjour Patrick,
>
> Le 19/01/2018 à 09:51, [hidden email] a écrit :
>>
>> J'utilise Base avec les Macros Basic pour développer une base de donnée
>> documentaire. Lors du traitement de l'évènement du formulaire principal
>> "Changement d'enregistrement" j’exécute une macro un peu longue et je
>> suis confronté à un problème de réentrance. Ma macro est un peu longue
>> car j'utilise des formulaires un peu complexes utilisant des sections
>> pour gérer à la fois des onglets mais aussi l'affichage contextuel de
>> telle ou telle section en fonction des valeurs de certains champs
>> saisies par l'utilisateur... Ce problème de réentrance peut être
>> schématisé par le scénario suivant :
>>
>> t = 0                  Enregistrement courrant de la forme est le n°10
>> t1                     EVENEMENT 1 (Enregistrement courrant de la forme
>> devient le n°11)
>> t1 + delta t           EVENEMENT 2 (Enregistrement courrant de la forme
>> devient le n°12, Macros évènement 1 interrompue n'importe où...)
>> t2                     FIN TRAITEMENT EVENEMENT 2 (synchrone avec
>> l'enregistrement courrant n°12 de la forme)
>> t3                     REPRISE ET FIN DU TRAITEMENT DE L'EVENEMENT 1
>> (/!\ Traitement de l'enregistrement n°11 qui n'est plus l'enregistrement
>> courrant de la forme, et qui devrait au contraire s'interrompre
>> immédiatement par un appel à exit())
>>
>> Ce problème n'est pas seulement révélé par la durée du traitement de ma
>> macro mais aussi il me semble pour deux raisons spécifiques à
>> l'application LibreOffice:
>>
>> 1. Il me semble que par défaut la barre de navigation des formulaires
>> utiliserait le principe de la répétition sur ses touches (activé après
>> un délai très cours). Si bien que très souvent l'appui sur le bouton
>> (avec le triangle) pour passer à l'enregistrement suivant commande un
>> double changement d'enregistrement... Et donc je reçois deux évènements
>> très rapprochés à traiter...
>> [...]
>> Pour essayer une première solution j'ai caché la barre de navigation des
>> formulaires et j'ai ajouté 2 ou 3 boutons de navigation spécifiques à
>> mon formulaire, en veillant à désactiver la répétition de touche. De
>> fait je suis moins confronté au problème des doubles évènements. Mais
>> cela n'empêche pas l'utilisateur de double cliquer rapidement ou même
>> triple cliquer rapidement sur les boutons, et je me retrouve à nouveau
>> avec le même problème de réentrance... [...]
>
> Tu pourrais, lors de l'événement Clic sur ton bouton de navigation,
> initialiser un drapeau qui pourrait être lu lors du clic sur les
> divers boutons de navigation. Tant que ce drapeau serait à True, les
> événements correspondants ne lanceraient aucune exécution.
>
> Tu pourrais aussi, et ça me semble plus visuel pour l'utilisateur,
> puisque ces boutons sont sous ton contrôle, les désactiver dès que
> l'un d'entre eux est cliqué, puis les réactiver lorsque l'événement a
> été traité.
>
> Ces solutions me semblent plus facile à gérer que d'essayer de gérer
> la réentrance. Je considère pour ma part que le langage de macro Basic
> de LibreOffice n'est pas destiné à ça. Si les besoins deviennent très
> pointus, je pense qu'un autre langage serait plus approprié (Python ?).
>
>
> Si vous répondez, merci de penser à utiliser la fonction "répondre à
> tous" de votre logiciel de courrier électronique de façon que la liste
> reçoive une copie de votre réponse.
>
> Bien cordialement,

Bonjour,

Merci pour ta réponse Jean-François. Je pense également que traiter le
problème à la source, au niveau de l'interface, est une approche
intéressante. Utiliser Python ou Java me semble aussi intéressant
néanmoins je suis venu vers LibreOffice pour l'utiliser comme un atelier
permettant de développer rapidement la preuve de mon concept. Si je
devais choisir Python ou Java j'aurais peut être une approche totalement
différente en cherchant à utiliser un ORB et framework d'interface MVC
de type Qt ...

Pour revenir à l'utilisation de LibreOffice Base la solution que tu me
propose mérite vraiment d'être testée mais j'ai une remarque : cela
permet de traiter correctement le premier évènement en refusant les
suivants, alors que du point de vu de l'utilisateur il aurait peut être
souhaité traiter le dernier évènement en annulant les précédant. Cela
dit je peux aussi ajouter à mon interface un contrôle de grille qui lui
permettra de cliquer directement N enregistrements devant sans être
obligé de s'énerver sur le bouton suivant ...

Aussi je me pose encore deux questions :

1. Les boutons peuvent envoyer plusieurs types d'évènements, en
particulier pour les boutons l'évènement "Accepter l'action" retient mon
attention ce matin. Je n'y avais pas fait attention avant ...Je
comprends que cet évènement serait envoyé avant "Executer l'action" que
j'utilise pour actualiser mon interface. Et donc je comprends qu'il
faudrait que j'utilise cet évènement pour gérer le drapeau avant
l'éventuelle réentrance dans l’exécution de l'action. J'avais lu aussi
dans la documentation UNO sur le modèle des évènements qu'il existait à
côté des Listners d'autres types de traitements renvoyant un boolean
pour annuler l'évènement. Est-ce bien celui que je devrait utiliser pour
rejeter les évènements réentrants ?

2. Avec mes boutons sans replay j'ai moins de problème de double
messages. Mais si l'utilisateur affiche la barre de navigation du
formulaire alors cette barre m'envoie presque systématiquement des
doubles messages extrêmement rapprochés (nombre de tics parfois égaux à
0 ... ce qui m'empêchait complètement de gérer correctement mon drapeau
de réentrance car chaque appel le voyait baissé !), et je n'arrive pas,
même lentement, à passer d'un enregistrement à l'autre à la fois, je
passe souvent de deux en deux ... Et je cherche encore l'API en macro
Basic pour paramétrer cette barre de navigation afin éventuellement de
supprimer son replay sur les boutons, et aussi peut être de capturer les
évènements "Accepter l'action" de ses boutons pour les renvoyer sur mon
traitement de réentrance et desactiver ses boutons de navigation... En
édition de mon formulaire, lorsque je fais un clique droit sur la barre
de navigation je n'ai pas accès dans le menu contextuel à un item me
permettant de fixer les propriétés de cette barre et encore moins
individuellement aux propriétés de ses boutons ... Donc il me faut une
API pour attacher les évènements de ses boutons de navigation à ma
prochaine macro...

Merci pour votre aide...
Patrick

--
Envoyez un mail à [hidden email] pour vous désinscrire
Les archives de la liste sont disponibles à https://listarchives.libreoffice.org/fr/users/
Tous les messages envoyés sur cette liste seront archivés publiquement et ne pourront pas être supprimés