4D dispose de fonctions intégrées vous permettant de gérer le glisser-déposer ("drag and drop") parmi les objets de vos formulaires et vos applications. Vous pouvez glisser-déposer un objet sur un autre objet situé dans la même fenêtre ou dans une autre fenêtre. Autrement dit, vous pouvez effectuer des glisser-déposer à l'intérieur d'un même process ou entre différents process.
Vous pouvez également glisser-déposer des objets entre les formulaires 4D et d’autres applications ou effectuer l’opération inverse. Par exemple, il est possible de glisser-déposer un fichier image PNG dans un champ image 4D. Il est également possible de sélectionner du texte dans une application de traitement de texte et de le déposer dans une variable texte 4D ou une listbox.
Enfin, il est possible de déposer des objets directement sur l’application sans qu’un formulaire ne soit nécessairement au premier plan. La Méthode base Sur déposer permet dans ce cas de gérer le glisser-déposer. Ce principe permet par exemple d’ouvrir un document 4D Write Pro en le déposant sur l’icône de l’application 4D. Cette opération spécifique est décrite dans la page Méthode base Sur déposer.
Deux modes de glisser-déposer sont proposés dans 4D :
Un mode personnalisé, dans lequel le glisser-déposer est géré intégralement par le programmeur. Ce mode vous permet de mettre en place des interfaces basées sur le glisser-déposer, y compris des interfaces qui ne déplacent pas nécessairement des données mais qui peuvent effectuer tout type d'action telle que l'ouverture de fichiers ou le lancement d'un calcul. Ce mode est basé sur un ensemble de propriétés, d'événements et de commandes spécifiques à partir du thème Conteneur de données.
Un mode automatique, dans lequel le glisser-déposer copie ou déplace automatiquement des données d'un objet à l'autre. Ce mode est disponible pour les objets texte et (en partie) les images, et peut être activé simplement en cochant une propriété. Ce mode est détaillé dans la section Glisser-Déposer automatique ci-dessous.
La mise en place d'une interface de glisser-déposer consiste à combiner des propriétés, des événements et généralement des commandes du thème Conteneur de données. Le diagramme suivant illustre les points essentiels d'une séquence de glisser-déposer personnalisée :
Votre implémentation sera basée sur le scénario suivant :
Dans l'événement Sur glisser de l'objet de destination (avec la propriété"Déposable"), lisez les types et les signatures de données présentes dans le conteneur à l'aide des commandes LIRE TYPE DONNEES DANS CONTENEUR ou LIRE DONNEES CONTENEUR et vérifiez s'ils sont compatibles avec l'objet de destination. La commande Position deposer retourne le numéro ou l'emplacement de l'élément cible ou de l'élément de liste, si l'objet de destination est un tableau (i.e., une zone de défilement), une liste hiérarchique, un texte ou une combo box, ainsi que le numéro de colonne si l'objet est une listbox. Si l'objet ou l'élément de destination est compatible, retournez 0 dans $0 pour accepter le déposer, sinon retournez -1 dans $0.
Dans l'événement Sur déposer de l'objet de destination (avec la propriété"Déposable"), exécutez toute action en réponse au déposer. Si l'opération de glisser-déposer est destinée à copier les données glissées, assignez simplement les données à l'objet de destination. Si le glisser-déposer n'est pas destiné à déplacer des données mais plutôt à créer une métaphore de l'interface utilisateur pour une opération particulière, vous pouvez effectuer tout type d'action, comme par exemple lire des chemins de dossiers à l'aide de la commande Lire fichier dans conteneur.
L'ensemble de ces propriétés et événements est détaillé ci-dessous.
Si vous souhaitez qu'un objet soit glissable, c'est-à-dire que vous puissiez le faire glisser et le déposer sur un autre objet, vous devez sélectionner la propriété "Glissable"pour cet objet dans la Liste des propriétés. L'objet que vous faites glisser est appelé objet source de l'opération de glisser-déposer.
Si vous souhaitez qu'un objet soit déposable, c'est-à-dire que l'objet puisse être la destination d'une opération de glisser-déposer, vous devez sélectionner la propriété "Déposable" pour cet objet dans la Liste des propriétés. L'objet qui reçoit les données est appelé objet de destination de l'opération de glisser-déposer.
Note : Les propriétés supplémentaires Glisser automatique et Déposer automatique sont disponibles pour les champs et variables texte, combo box et list box. L'option Déposer automatique est également disponible pour les champs et variables image. Elles permettent d'activer un mode de glisser-déposer automatique basé sur la copie du contenu (le glisser-déposer n'est plus géré par les événements formulaires 4D). Reportez-vous au paragraphe Glisser-Déposer automatique à la fin de cette section.
Par défaut, les objets nouvellement créés ne possèdent aucune de ces propriétés. Il est de votre ressort de les sélectionner explicitement.
Tous les objets situés dans un formulaire entrée ou dans une boîte de dialogue peuvent être définis comme glissables et déposables. Les éléments individuels d'un tableau (par exemple une zone de défilement), les éléments d'une liste hiérarchique ou les lignes d'une list box peuvent être glissé(e)s et déposé(e)s. Inversement, vous pouvez faire glisser et déposer tout objet sur un élément individuel d'un tableau ou d'une liste hiérarchique, ou encore une ligne de list box. Il n'est toutefois pas possible de faire glisser et de déposer des objets depuis la zone de corps d'un formulaire sortie.
Vous pouvez également gérer les glisser-déposer sur l'application, en-dehors de tout formulaire, via la Méthode base Sur déposer.
Afin de vous laisser "carte blanche" lors de la construction d'une interface utilisateur exploitant le glisser-déposer, 4D vous permet d'utiliser tout type d'objet actif (champ ou variable) en tant qu'objet source ou destination. Par exemple, si vous le souhaitez, vous pouvez glisser-déposer des boutons.
Notes
Pour faire glisser un texte ou un bouton ayant la propriété "glissable", vous devez au préalable appuyer sur la touche Alt (Windows) ou Option (macOS).
Par défaut, dans le cas des variables et champs image, l'image et sa référence sont glissées. Pour ne faire glisser que la référence de la variable ou du champ, appuyez au préalable sur la touche Alt (Windows) ou Option (macOS).
Lorsque, pour un objet de type List box, les propriétés “Glissable” et “Ligne déplaçable” sont définies simultanément, la propriété “Ligne déplaçable” est prioritaire en cas de déplacement d’une ligne. Le glisser n’est pas possible dans ce cas.
Notez qu'un objet "glissable" et "déposable" peut être déposé sur lui-même (à moins que vous n'interdisiez cette opération, reportez-vous aux paragraphes suivants).
Voici la Liste des propriétés, dans laquelle les propriétés "Glissable" et "Déposable" ont été définies pour l'objet sélectionné :
La gestion du glisser-déposer par programmation est basée sur trois événements formulaires : Sur début glisser, Sur glisser et Sur déposer. A noter que l'événement Sur début glisserest généré dans le contexte de l'objet source du glisser tandis que Sur glisser et Sur déposersont envoyés à l'objet de destination uniquement.
Pour que l'application puisse traiter ces événements, il doivent avoir été sélectionnés de manière appropriée dans la Liste des propriétés pour les objets source et destination :
L'événement formulaire Sur début glisser est sélectionnable pour tous les objets de formulaire pouvant être glissés. Il est généré dans tous les cas lorsque l’objet dispose de la propriété Glissable. Il peut être appelé dans la méthode de l’objet source ou la méthode du formulaire de l’objet source.
Note : A la différence de Sur glisser, l’événement formulaire Sur début glisser est appelé dans le contexte de l’objet à la source du glisser.
L'événement Sur début glisser est utile pour mettre en place le glisser. Il permet notamment :
d'utiliser une icône personnalisée pendant l'action de glisser (via la commande FIXER ICONE GLISSER).
d'accepter ou refuser le glisser via $0 dans la méthode de l’objet glissé. Pour signaler que le glisser est accepté, la méthode de l'objet source doit retourner 0 (zéro), vous exécutez donc $0:=0. Pour signaler que le glisser est refusé, la méthode de l'objet source doit retourner -1 (moins un), vous exécutez donc $0:=-1. Si aucun résultat n'est retourné, 4D considère que le glisser est accepté.
Les données de 4D sont placées dans le conteneur de données avant l’appel de l’événement. Par exemple, pour un glisser sans l’option Glisser automatique, le texte glissé est déjà dans le conteneur au moment de l’appel de l’événement.
L'événement Sur glisser est envoyé de manière répétée à l'objet de destination lorsque le pointeur de la souris est placé sur l'objet. Généralement, en réponse à cet événement, vous effectuez les actions suivantes :
Vous lisez les données et les signatures renseignées dans le conteneur (via la commande LIRE DONNEES CONTENEUR).
En fonction de la nature et du type de données renseignées dans le conteneur, vous acceptez ou refusez le glisser-déposer.
Pour signaler que le glisser est accepté, la méthode de l'objet de destination doit retourner 0 (zéro), vous exécutez donc $0:=0. Pour signaler que le glisser est refusé, la méthode de l'objet de destination doit retourner -1 (moins un), vous exécutez donc $0:=-1. Pendant un événement Sur glisser, 4D traite la méthode de l'objet comme une fonction. Si aucun résultat n'est retourné, 4D considère que le glisser est accepté.
Si vous acceptez le glisser, l'objet de destination est activé. Si vous le refusez, l'objet de destination reste inactivé. Accepter le glisser ne signifie pas que les données glissées vont être insérées dans l'objet de destination. Cela signifie uniquement que l'objet de destination, si le bouton de la souris était relâché à cet instant, accepterait les données et que l'événement Sur glisser serait déclenché.
Si vous ne gérez pas l'événement Sur glisser pour un objet dont la propriété "Déposable" a été sélectionnée, l'objet sera activé pour tous les glisser, quels que soient la nature et le type des données glissées.
La traitement de l'événement Sur glisser vous permet de contrôler la première phase d'une opération de glisser-déposer : non seulement vous pouvez tester si le type des données glissées est compatible avec l'objet de destination — et donc accepter ou refuser le glisser — mais également, vous en informez l'utilisateur, car 4D active ou non l'objet de destination en fonction de votre décision.
Le code traitant un événement Sur glisser doit être court et s'exécuter rapidement car cet événement est envoyé de manière répétée à l'objet de destination courant, en fonction des mouvements de la souris.
L'événement Sur déposer est envoyé (une seule fois) à l'objet de destination lorsque le bouton de la souris est relâché alors que le pointeur se trouvait au-dessus de l'objet. Cet événement est la seconde phase d'un glisser-déposer, dans laquelle vous effectuez les véritables opérations répondant à l'action de l'utilisateur.
Cet événement n'est pas envoyé à l'objet si le glisser n'a pas été accepté dans le ou les événement(s) Sur glisser. Si vous traitez l'événement Sur glisser pour un objet et refusez le glisser, l'événement Sur déposer ne se déclenche pas. Ainsi, si pendant l'événement Sur glisser vous avez testé la compatibilité entre le type des données de l'objet source et de destination et accepté le glisser, vous n'avez pas besoin de tester de nouveau les données dans l'événement Sur déposer : vous savez déjà qu'elles sont compatibles.
L'aspect le plus intéressant de l'implémentation du glisser-déposer dans 4D est que le programme vous permet de faire ce que vous voulez. Par exemple :
Si un élément de liste hiérarchique est déposé sur un champ de type Texte, vous pouvez décider d'insérer le texte de l'élément de liste au début, au milieu ou à la fin du champ de texte.
Votre formulaire contient un bouton image à deux états représentant une corbeille vide et une corbeille pleine. Le glisser-déposer d'un objet sur ce bouton pourrait provoquer, du point de vue de l'interface utilisateur : “supprimer l'objet qui a été glissé-déposé dans la corbeille”. Ici, le glisser-déposer ne transporte pas des données d'un point à un autre, mais plutôt il déclenche une action.
Glisser un élément de tableau depuis une palette flottante vers un objet dans un formulaire pourrait signifier “afficher dans cette fenêtre l'enregistrement du client dont le nom a été glissé-déposé depuis la fenêtre flottante listant les noms de tous les clients stockés dans la base”.
Etc.
La gestion du glisser-déposer de 4D est une boîte à outils vous permettant d'implémenter toutes les métaphores d'interface utilisateur auxquelles vous pouvez penser.
Les objets texte (champs, variables, combo box et list box) ainsi que les objets image autorisent le glisser-déposer automatique, c’est-à-dire le déplacement ou la copie direct(e) de la sélection de texte ou d'une image d’une zone à une autre par simple clic. Il peut être employé dans la même zone 4D, entre deux zones 4D, ou entre 4D et une autre application, par exemple WordPad.
Note : En cas de glisser-déposer automatique entre deux zones 4D, les données sont déplacées, c’est-à-dire qu’elles sont supprimées de la zone source. Si vous souhaitez recopier les données, appuyez sur la touche Ctrl (Windows) ou Option (OS X) pendant l’opération (sous OS X, vous devez appuyer sur la touche Optionaprès avoir commencé le glisser).
Le glisser-déposer automatique peut être paramétré séparément pour chaque objet d'un formulaire via deux options de la Liste des propriétés : Glisser automatique et Déposer automatique :
Glisser automatique (objets de type texte uniquement) : Lorsque cette option est cochée, le mode de glisser automatique est activé pour l'objet. Dans ce mode, l'événement formulaire Sur début glisser n'est PAS généré. Si vous souhaitez “forcer” l’utilisation du glisser standard lorsque le glisser automatique est activé, appuyez sur la touche Alt (Windows) ou Option (OS X) pendant l’opération (sous OS X, vous devez appuyer sur la touche Optionavant de commencer le glisser). Cette option n'est pas disponible pour les images.
Déposer automatique : Cette option permet d’activer le mode de déposer automatique. Dans ce mode, 4D gère automatiquement — si possible — l’insertion des données glissées de type texte ou image et déposées sur l’objet (les données sont collées dans l’objet). Les événements Sur glisser et Sur déposer dans ce cas ne sont pas générés. En revanche, les événements Sur après modification (lors du déposer) et Sur données modifiées (lorsque l'objet perd le focus) sont générés. En cas de déposer de données autres que du texte ou des images (autre objet 4D, fichier, etc. ) ou de données complexes, l’application se réfère à la valeur de l’option Déposable : si elle est cochée, les événements Sur glisser et Sur déposer sont générés, dans le cas contraire le déposer est refusé. Ce principe dépend également de la valeur de l’option “Interdire de glisser des données ne provenant pas de 4D” (cf. ci-dessous).
A compter de la version 11, 4D permet le glisser-déposer de sélections, d’objets ou de fichiers extérieurs à 4D, comme par exemple des fichiers image. Cette possibilité doit être prise en charge par le code de la base. Dans les bases de données converties depuis une version précédente de 4D, cette possibilité peut entraîner des dysfonctionnements si le code existant n’est pas adapté. Pour cette raison, une option de Préférences permet d'inactiver cette fonction : Interdire de glisser des données ne provenant pas de 4D. Cette option est placée dans la page Application/Compatibilité. Elle est cochée par défaut dans les bases converties.
Lorsque cette option est cochée, le déposer d’objets externes est refusé dans les formulaires 4D. A noter toutefois que l’insertion d’objets externes reste possible dans les objets disposant de l’option Déposer automatique, lorsque l’application peut interpréter les données déposées (texte ou image).
// Méthode objet : label1 Si(Evenement formulaire code=Sur déposer) //Nécessite une action Déposable activée à partir de la Liste de propriétés TABLEAU TEXTE($signatures_at;0) TABLEAU TEXTE($nativeTypes_at;0) TABLEAU TEXTE($formatNames_at;0) LIRE TYPE DONNEES DANS CONTENEUR($signatures_at;$nativeTypes_at;$formatNames_at) Si(Chercher dans tableau($signatures_at;"com.4d.private.text.native")#-1) // le conteneur comporte du texte 4D OBJET Lire pointeur(Objet courant)->:=Lire texte dans conteneur Fin de si Fin de si
Combiner des fonctionnalités de glisser-déposer personnalisé et automatique permet de créer des interfaces simples et puissantes. Dans cet exemple, nous souhaitons remplir une zone de texte avec des données glissées à partir d'une list box :
List box : Propriété "Glissable" et événement "Sur début glisser" cochés
Zone de texte : Propriété "Déposer automatique" cochée.
//méthode objet de la list box Au cas ou
:(Evenement formulaire code=Sur début glisser) CHARGER ENREGISTREMENT([Clients]) $label:=[Clients]Name+Caractere(CR ASCII code)+[Clients]Contact+Caractere(CR ASCII code)+\ [Clients]Address1+Caractere(CR ASCII code)+[Clients]City+", "+[Clients]State+" "+[Clients]ZipCode) FIXER TEXTE DANS CONTENEUR($label) Fin de cas
Le déplacement et le formatage des données se fait via le glisser-déposer :
Vous souhaitez que l'utilisateur sélectionne un fichier sur le disque, le glisse et le dépose dans une variable saisissable (de type objet) afin d'afficher une description json du chemin fichier.
Dans la méthode objet de la variable, écrivez simplement :
C_ENTIER LONG($0) Au cas ou
:(Evenement formulaire code=Sur glisser) // Acceptez l'événement Sur déposer uniquement si le conteneur comporte des fichiers, sinon refusez-le. Si(Lire fichier dans conteneur(1)="") //aucun fichier dans le conteneur $0:=-1 //refuse le déposer Fin de si
Vous souhaitez que l'utilisateur sélectionne plusieurs fichiers sur le disque, les glisse et les dépose dans une list box afin d'afficher les chemins de fichiers.
Dans la méthode objet de la list box, écrivez simplement :
C_ENTIER LONG($0) Au cas ou
:(Evenement formulaire code=Sur glisser) // Accepte l'événement Sur déposer uniquement si le conteneur comporte des fichiers, sinon le refuse. Si(Lire fichier dans conteneur(1)#"") //au moins un fichier déposé $0:=0 //accepte le déposer Sinon//aucun fichier dans le conteneur $0:=-1 //refuse le déposer Fin de si
Evenement formulaire code=Sur déposer) //Nécessite une action Déposable activée à partir de la liste de propriétés TABLEAU TEXTE(importedPath_at;0) C_TEXTE($path_t) C_ENTIER LONG($index_l) $index_l:=1 Repeter $path_t:=Lire fichier dans conteneur($index_l) Si($path_t#"") AJOUTER A TABLEAU(importedPath_at;$path_t) Fin de si $index_l:=$index_l+1 Jusque($path_t="") Fin de cas