Le Glisser&Déposer
C'est le document de référence pour la construction d'objet
BMessage qui sont utilisé par BeOS pour effectuer les actions de
drag&drop. Si vous lisez ce chapitre pour la première fois,
il est probable que vous soyez obliger de tout lire. Si vous voulez juste
voir quelque chose et le lire avec votre navigateur, vous pouvez sauter
directement au sujet choisis
NOTE: Pour la traduction, l'utilisation du therme drag(déplacer)
et drop(déposer) n'est pas toujours traduite pour des raisons de
commodité; et seront utiliser indifférement.
1. Glisser
déposer Simple vs. Glisser déposser communiquant.
2. les principes fondamentaux
du Drag&Drop
3. Format
des BMessages dans la communication Drag'n'Drop
3a. Protocole
pour les messages glisser(drag)
3b. Protocole
pour les Messages de negociation dans le cadre du drag&drop communiquant.
3c. Protocole
pour les Messages de données
4. Résumé
des protocole de négociation Drag&Drop
Prérequis
Le Drag&Drop ou Glisser/déposer utilise un certains nombre d'élement
du kit de programmation BeOS, et vous devrez être raisonnablement
familier avec les notions suivantes, afin d'être à l'aise
dans la lecture du document suivant:
-
la classe BMessage, puisque les objets trainés sont
envoyé à leurs cible comme des objets BMessage
. Vous devez comprendre ce qu'est un BMessage, comment
ajouter une donnée à un BMessage ou extraire
celle-ci, comment envoyer un BMessage, et où placer
le code pour controler les BMessages recut.
-
La classe BView. Les action Drag&Drop sont principalement
des opérations sur le GUI(Interface graphique utilisateur), et l'objet
BView
est le plus important des objets pour la manipulation du GUI; c'est dans
une classe dérivée de BView que vous devrez
inserer le code pour le initialiser le glisser, et prévoir le déposer.
-
Le Kit de traduction, si vous souhaitez utiliser les capacité incorporées
de traduction de BeOS pour (par exemple) glisser une image JPEG d'une application
à une autre qui ne comprend que les image BMP simple.
Glisser/Déposer
Simple
vs. Glisser/Déposer Communiquant
Pour parler abrutement, vous avez deux méthodes différentes
pour effectuer les opérations de drag&drop, et qui, si elles
semblent identique pour l'utilisateur final, sont en réalité
très différentes dans la complexité de la mise en
oeuvre des protocoles de négociation entre la source du glisser,
et la cible du poser.
Le Glisser/Déposer Simple
Un drag'n'drop dit simple est une opération de glisser/poser
qui corresponds à l'envois interne d'un seul BMessage,
de la source du glisser à la cible du poser. C'était au départ
le protocol original pour BeOS, et il est encore très utilisé
pour le glisser/poser à l'interieur d'une unique application, ou
à l'interieur d'un couple étroit d'application qui "connaissent
tout au sujet" des autres. Par exemple, vous pouvez glisser un morceau
d'Image dans programme de dessin qui utilse ce protocole; cette opération
de glisser va provoquer dans l'application de dessin l'envois d'un BMessage
depuis celui-ci, et ce BMessage va contenir toutes les données nécessaire
indiquant quel morceau d'image à été déplacé,
et où. Utiliser les capacités des fonctions interne de Drag&Drop
à la manière BeOS diminue votre travail de chargement, puisque
pour beaucoup d'aspect fondammentaux, comme les déplacement visuel
de bitmap sur l'écran, les actions se font automatiquement.
Le Drag'n'Dro communicant
Un drag&drop communicant est généralement utilisé
dans un contexte plus général, lorsque l'application d'où
provient le glisser, la source, et le recepteur de ce glisser ne connaissent
pas nécessairement tous l'un de l'autre, c'est à dire l'objet
même de ce glisser. Ce drag&drop plus général est
nécessaire si nous voulons que l'usage de BeOS, en particulier lors
d'application media, soit le plus intuitives possible. Par exemple, l'utilisateur
peut faire glisser une image d'un programme graphique (le viewer par exemple)
vers un autre programme graphique(comme un programme de dessin) sans difficulté.
Pourtant, il y a beaucoup de format différent pour représenter
une image, et les deux programmes doivent communiquer (avec l'aide du Kit
de Traduction) pour prendre en compte le plus précis ou possible
formats, et s'accorder sur un choix communs.
Notez que le protocole du drag&drop communicant n'a aucune exigence
"difficile et rapide"; il n'est pas imposé par le système,
et peut facilement être modifié; par exemple, si vous avez
besoin d'un systeme de communication complexe qui prend plus de pas que
définis par le standard. La majorité des utilisations des
drag&drop communiquant que vous risquez de rencontrerez maintenant
sont dans le Tracker, et nous allons parlez de celui-ci avec plus de détail
par la suite. Les autres applications peuvent supporter le drag&drop
communiquant ou ne le peuvent pas. Aussi, il faut noter que c'est un protocole
simple qui a été définis au départ, et qui
peut être utilisé par les anciennes applications. Il est simple
de construire votre code basé sur l'ancien protocole; pour cela
regardez à la fin de cette section, à " Ancien protocole
Drag&drop"
Débuter avec le Drag
& Drop
On suppose que l'utilisateur travaille avec deux applications, et qu'il
va glisser quelque chose de la première application (que nous appellerons
l'application d'expéditeur) vers la seconde application (application
que nous appellerons l'application
réceptrice). En un mot, il y a tout ici pour décrire
le fonctionnement de la marche du processus en totalité:
1. Detection: Le code de l'objet BView
de l'application d'envois envois un avertissement lorsque l'utilisateur
clique sur quelque chose d'interréssant, et débute le glisser
de celui ci. Le code de controle that notices this is usually spread out
entre les fonctions BView::MouseDown() et BView::MouseMoved()
, et peut généralement faire la différence entre le
début d'un vrai Drag&drop, et le simple click sans conséquence
qui (par exemple) est utilisé pour sélectionner un objet
sans le déplacer, mais qui bouge de deux ou trois pixel parceque
l'utilisateur est trop lent à lacher le bouton. Ce code de détection
du glissé est intégré dans l'utilisation de BView::SetMouseEventMask()
pour temporairement activer le report de tous les déplacements de
la souris (qui ne sont pas normalement pas tous signalé à
l'application, pour des raisons de vitesse d'executions).
2. Initiation: Une fois que le code
de detection de l'application d'envois à décidé qu'une
action de drag & drop débutais, il initialise internement celle-ci,
par le création d'un objet BMessage qui contient
toutes les informations sur la nature de l'objet qui est glissé,
et qui par la suite passe ce BMessage à la fonction
BView::DragMessage().
BView::DragMessage()
determine également comment l'objet déplacé par l'utilisateur
doit apparaitre visuellement à celui ci; pour cela vous devez soit
lui passer un BBitmap, pour que le glisser soit effectuer
avec une image se déplacant sur l'écran, ou alors juste un
Brect,
si vous voulez juste que ce soit un rectangle transparent qui s'affiche
lors du glisser. Après avoir appelé DragMessage,
le code d'envois dois se souvenir de supprimer sa propre copie du BMessage.
Note: L'envois ne supprime pas le BBitmap qui
est passé au DragMessage; mais ceci est effectué
par le systeme.
3. Drag(Glisser): Ceci est la partie
facile, une fois que l'application expéditeur à initialisé
le glisser, comme décrit dans l'étape précedente,
la représentation visuelle de celui-ci sur l'écran est controlé
par le système. La prochaine fois que le code est invoqué,
c'est pour le...
4. Dépot(Drop): L'utilisateur
relâche le bouton de la souris pendant que celle ci est dans un BView
de l'application réceptrice. Cela provoque l'execution de la fonction
MessageReceived()
de BView, avec le BMessage du glisser comme
message reçut. C'est le premier des trois objets BMessage
qui peut être envoyé et recut, mais le seul lors d'une action
de simple drag&drop . Nous appellerons ce premier message le message
du glisser. Dans un drag&drop simple, le message du glisser peut
contenir tout ce que vous voulez, dans l'ordre que vous voulez; puisque
l'application expéditrice et l'application receveuse "savent" tout
l'une de l'autre, et qu'elles ont certainement un protocole privé
commun de communication. Ce qui permet à l'application receptrice
de savoir immédiatement ce qu'elle à faire ce message. Dans
le drag'n'drop communiquant, le message du glisser ne comporte généralement
pas les données qui définissent l'objet laché; par
exemple, si vous laisser tomber un morceau de texte, le message qui est
normalement déposer ne contient pas le texte qui a été
glisser. Effectivement, le message du glisser contient des informations
au sujet des différents formats et méthodes par lesquelles
l'application expéditrice peut fournir les données à
l'application receptrice, et par quels actions celle-ci peut interroger
l'application expéditrices pour récupérer les informations.
5. Communication [facultatif, uniquement
dans le drag&drop communicant]: L'application receptrice répond
au déposer par un second message, qui est envoyé à
l'application expéditrice par l'utilisation de la fonction BMessage::SendReply().
Nous appellerons ce second message le message de communication.
Le récepteur crée le message de négociation en parcourant
les options fournis par l'expéditeur dans le premier message, en
choisis une ou plusieurs, et intègre celle-ci dans sa réponse
pour que l'expediteur sache parmis les formats disponibles qu'il peut fournir,
lequel utiliser pour transmettre les données. Le message de négociation
contient aussi des informations concernant ce que le récepteur désire
que fasse l'expéditeur de ces données; par exemple, si vous
trainer des données jusqu'a la corbeille, le récepteur va
demander à l'expéditeur de supprimer celle-ci.
6. Transmission de donnée[facultatifl,
uniquement dans le drag'n'drop communicant]: L'expéditeur examine
le second message, celui retourné par le récepteur, pour
trouver dans quel format possible le récepteur désire recevoir
les données. L'expéditeur emballe alors ces données
comme voulus par le recepteur, et envoie celle-ci dans le message de
donné.(Facultativement, l'expéditeur peut, à la
demande du récepteur, créer un fichier par où il passera
les données au récepteur, plutôt que de passer les
données directement dans le BMessage. Nous parlerons de ceci quand
nous discuterons des détails du dépot, de la négociation,
et des messages de données.)
7. Le final [facultatif, utilisé
dans le drag&drop communicant] : Le récepteur reçoit
le message de données de l'expéditeur, extrait les données
désirées, et les utilise comme il le désire pour la
continuité du programme.
Ceci semble plus complexe qu'il est. Et comme une image vaut mieux que
mille mots, voici un simplifié schématique du procédé:
:
Exemple: Simple Drag&Drop
Avant de passer aux questions plus complexe, voyons déjà
à quoi peut ressembler simplement un "simple" drag&drop. Le
code ci dessous définis une application très simple, qui
permet de trainer un carré noir dans une fenêtre. L'application
est l'expéditeur (c'est à dire que vous cliquez sur le carré
fans la fenêtre d'application pour commencer la glisser), et aussi
le récepteur (vous relâcher le bouton de souris dans le fenêtre
d'application, pour repositionner le carré). La plupart du code
du programme est similaire à ce qui se trouve dans n'importe quel
application utilisant un BView. Les parties du code qui
se rapporte en particulier au drag&drop sont affiché en gras.
/* Trainer le carré noir avec un drag&drop --un programme
très simple. Les étapes de La DETECTION, L'INITIALISATION,
le DRAG&DROP correspondent aux même nom que dans
le section précédente, "les principes fondamentaux du drag&drop". */
#include <Application.h>
#include <InterfaceKit.h>
rgb_color black = {0, 0, 0, 64};
const char *APP_SIGNATURE = "application/x-vnd.Be-MyDragnDrop";
/* The constant below is arbitrary--the fact that is is 'drag' is
meaningless. However, it MUST be chosen so as not to conflict
with system-wide BMessage 'what' values--see the BMessage
documentation for details. */
const uint32 MY_DRAG_ACTION = 'drag';
class MyDragDropView : public BView {
private:
BPoint _button_click;
BRect _SquareSides;
public:
MyDragDropView(BRect rect) : BView(rect, "",
B_FOLLOW_ALL_SIDES, B_WILL_DRAW) {
_SquareSides = BRect(20, 20, 90, 90);
}
void Draw(BRect where) {
SetHighColor(black);
FillRect(_SquareSides);
}
void MouseDown( BPoint where ) {
/* 1. DETECTION : Notre code de détection est très simple;
si l'utilisateur clique sur le carré noire, le glisser démarre. */
if (_SquareSides.Contains(where)) {
// Turn on the event mask for all pointer events, so we'll know when
// the user lets go of the mouse button.
SetMouseEventMask( B_POINTER_EVENTS, 0 );
/* 2. INITIATION : Creons une instance deBMessage, et passsons le
à BView::DragMessage() pour débuter le glisser. */
BMessage *drag_message = new BMessage( MY_DRAG_ACTION );
/* Souvenez vous, dans le message du glisser, ou celui ci débute */
drag_message->AddPoint("click_location", where);
DragMessage( drag_message, _SquareSides, this );
/* 3. DRAG : this is handled by the user and system, we
don't write any code at all to do the dragging. The
next step will take place in the MessageReceived() function. */
/* N'OUBLIEZ PAS DE SUPPRIMER LE MESSAGE APRES L'ENVOIS */
delete drag_message;
}
}; /* end of MouseDown() */
void MessageReceived(BMessage *msg) {
/* 4. DROP : MessageReceived() can called for many different
messages. We're only interested in ones with a 'what'
field of MY_DRAG_ACTION, as was created in the MouseDown()
function. */
if (msg->what == MY_DRAG_ACTION) {
BPoint clicked;
/* We put "click_location" into the original message, now
we can get it out */
msg->FindPoint("click_location", &clicked);
BPoint whereto;
/* The "_drop_point_" message field is automatically
inserted by the OS; is is the screen point the
mouse was on when the drag ended. */
msg->FindPoint("_drop_point_", &whereto);
/* Convert "_drop_point_" to view coordinates. */
whereto = ConvertFromScreen(whereto);
/* Move the square by the same amount the mouse moved
in the drag. */
_SquareSides.OffsetBy(whereto-clicked);
/* Ensure the view is redrawn */
Invalidate();
}
}; /* fin de MessageReceived() */
}; /* fin de la classe MyDragDropView */
class MyDragDropWindow : public BWindow {
public:
MyDragDropWindow(BRect frame)
: BWindow(frame, "Drag'n'Drop Example", B_TITLED_WINDOW, B_NOT_ZOOMABLE) {
interior = new MyDragDropView(this->Bounds());
AddChild(interior);
Show();
}
bool QuitRequested() {
be_app->PostMessage(B_QUIT_REQUESTED);
return true;
}
private:
BView *interior;
}; /* fin de la classe MyDragDropWindow */
class MyDragDropApp : public BApplication {
public:
MyDragDropApp::MyDragDropApp() : BApplication(APP_SIGNATURE) {
BRect windowRect;
windowRect.Set(50,50,349,399);
new MyDragDropWindow(windowRect);
}
private:
MyDragDropWindow *theWindow;
}; /* fin de la classe MyDragDropApp */
/* La fonction "main" créé et lance l'application*/
int main(void) {
MyDragDropApp *theApp;
theApp = new(MyDragDropApp);
theApp->Run();
delete theApp;
}
Les
Formats
des BMessages
dans le Drag'n'Drop Communicant
Avec le "simple" drag&drop, vous êtes libre d'utiliser les BMessages
plus ou moins comme vous le souhaitez; vous définissez simplement
un membre what constant qui sera l'unique identificateur
de votre message de dépot à la cible, et vous mettez les
données que vous voulez dans le corps du message. Le récepteur
examinera le membre what du message, et est sencés
comprendre la teneur de celui-ci, donc savoir extraire correctement les
données (n'importe lesquelles) dans le corps même du message.
Le drag&drop communicant est différent, puisqu'il suppose
que l'expéditeur et le récepteur n'ont pas une connaissance
implicite les uns des autres. Dans le but de communiquer efficacement toutes
les deux, les applications doivent consentir d'un protocole communs entre
eux. Ce protocole prend la forme d'une structure de prédéfinie
concernant le message du glisser, le message de la négociation,
et pour finir le message de données, comme décrit dans les
sections suivante.
Astuce: Il existe un génialissime petit utilitaire appelé
ViewIt,
qui devrait être disponible (comme élement d'un groupement
d'utililaire appelé Geb Goodies) sur les sites de
téléchargement normaux, tel que www.bebits.com
. Vous pouvez trainer n'importe quoi sur ViewIt, et il
vous montrera le contenus du message drag.
Protocole pour les
messages de glisser "Drag"
Le message de glisser est le premier qui est envoyé au début
par l'application expéditrice. vous devez l'assigner à un
membre what de B_SIMPLE_DATA. Le champs
du message dans un message de glisser peut être fractionné
en ce que vous avez besoins, pour vous, et ce que le système remplira
automatiquement. Jetons un coup d'oeil sur chacun de ces champs.
Champs
du Message du glisser Remplis par votre Code
Les structures de champs du message présenté ici auront besoin
d'être rempli par votre code. Les descritpions détaillées
de ces domaines sont trouvées ci-dessous.
"be:types", "be:filetypes", et"be:type_descriptions":
Ces champs indiquent dans quel formats l'expéditeurs veut fournir
ses données, et sont remplis avec celle-ci.
"be:actions": Une liste d'actions que l'expéditeur peut
effectuer sur ces données, à la demande du récepteur.
"be:clip_name": Un nom suggéré pour les données
envoyées, qui pourra éventuellemnt être utilisé
comme option par le récepteur. Ce champs est facultatif.
"be:originator", "be:originator_data": utilisé
pour préserver le contexte des informations à travers les
envois de message asynchrones.
"be:data": Ceci été utilisé par l'ancien[et
obsolete] drag&drop, comme conteneur des données du glisser.
Vous n'avez pas besoin de l'utiliser avec les applications modernes.
Champs
du Message Glissé Remplis par le Système
"_drop_point_", "_drop_offset_": Les valeurs dans ces champs
sont automatiquement réglées par le système; il ne
faut pas que vous les régliez vous-même. Elles donnent l'emplacement
sur l'écran du déposer.
Description
Détaillé des Champs du Message "Glisser"
Champs "be:types", "be:filetypes", et "be:type_descriptions"
Le but principal du drag&drop communicant est de proposer un compromis
optimal entre les formats de données que peut fournir l'application
expéditrice, et ceux que le récepteur peut comprendre. En
conséquence, les trois plus importants champs dans le drag&drop
communicant sont "be:types" et"be:filetypes"
;
"be:type_descriptions"
accompagne ici le champ "be:filetypes" , donc nous le décrirons
ici aussi. Chacun de ces champs est remplis avec une liste de chaîne
de valeur.
Les valeurs pour ces champs sont habituellement obtenus par le Kit de
Traduction, par demande au Kit de Traduction quels formats de données
il pourra fournir pour les données glisser, et de remplir les champs
avec l'information retournée par les appels au Kit de Traduction.
(Par exemple, si les traducteurs approprié sont installés
sur le système, le Kit de Traduction pourrait pouvoir traduire un
bitmap dans n'importe quel format JPEG,GIF,PNG, ou TIFF.)
Les sens spécifiques de ces trois domaines sont les suivants:
-
"be:types": Chaque valeur dans ce champ indique dans quel format
de donnée l'application expéditrice peut transmettre ses
informations (c'est une chaîne MIME en fait), mais vous n'êtes
normalement pas obligé de savoir ce que contient cette chaîne,
puisque vous obtiendrez cette information du Kit de Traduction, ou par
une constante prédéfinis. Si "be:types" est constitué
d'un seul élément, dont la valeur est égale à
celle de la variable globale B_FILE_MIME_TYPE, alors l'expéditeur
n'est pas disposé à fournir ses données dans un BMessage;
et le récepteur doit accepter les données par un fichier,
dans un des formats spécifié dans le "be:filetypes" du message.
Si vous voulez indiquer que votre application veut envoyer ses données
par un BMessage ou par un fichier, alors il faut ajouter
B_FILE_MIME_TYPE
comme dernier élément de "be:types", après tous les
types qui peuvent être envoyé par un BMessage.
-
"be:filetypes": identique à "be:types", mais la valeur dans
ce champs indique les formats dans lesquels l'expéditeur peut fournir
ses données via un fichier. Ceci peut être
lourd de conséquence, par exemple, si l'utilisateur glisse sur l'application
un clip vidéo de 30 MegaBytes, vous ne voulez probablement pas passer
ceci dans un dans un BMessage. Dans la plupart des cas,
"be:filetypes" sera identique à "be:types". Si votre application
n'est pas disposée à passer des données via un fichier,
alors ce que vous mettrez (si vous voulez) dans "be:filetypes" n'a aucune
importance. Important: Voir la section ci-dessous dans "Passer
des données via un Ficher" pour plus de documentation sur cette
fonction, et si vous avez l'intention de l'utiliser.
-
"be:type_descriptions":Ceci est juste une description plus facile
d'accès du format "be:filetypes". Il peut être montré
sur l'écran à l'utilisateur, pour que celui-ci puisse choisir
entre plusieurs formats pendant une sauvegarde de fichier. Il n'est pas
utilisé dans d'autre cas.
Les Champs "be:actions"
Dans le Drag&Drop communicant, l'expéditeur et le récepteur
communiquent non seulement pour connaitre le format de donnée envoyé,
mais aussi sur l'action exécutée sur ces données.
Est-ce que les données doivent être copier de l'expéditeur
au récepteur, déplacé de l'expéditeur au récepteur,
ou quelque chose d'autre encore? La première partie de cette "communication
des actions" a lieu dans le message du glissé, via le champ "be:actions".
"be:actions" contient une liste de valeurs (En fait des entiers sur
32-Bits) qui définit les actions que l'expéditeur peut/veut
bien effectuer, et demande au récepteur ce qu'il désire.
Aucune action n'est engagé si le récepteur ne répond
pas. Les demandes d'actions possibles sont données par les constantes
suivantes:
-
B_COPY_TARGET : L'expéditeur effectue une copie de l'objet
déplacé.
-
B_MOVE_TARGET : L'expéditeur peut déplacer la cible
sur le récepteur; si le récepteur le demande. Dans ce cas,
l'expéditeur envoie une copie des données, puis efface sa
propre copie.
-
B_LINK_TARGET : L'expéditeur peut fournir un lien sur la
cible. [xxx qu'est ce que cela signifie réellemnt? Si l'expéditeur
est le Tracker, Je peux comprendre, mais si c'est le document de Chros,
B-LING_TARGER est énuméré comme une action générale,
et pas une action spécifique du Tracker]
-
B_TRASH_TARGET : L'expéditeur peut effacer ses données
sans l'envoie de celle ci. Ceci est utile si, par exemple, vous voulez
que votre utilisateur puisse glisser quelque chose de l'application à
l'icône de la corbeille du Tracker, et de supprimer l'objet de votre
application.
En plus des quatres actions "standard" décrit ci-dessus, il existe
quelques actions qui peuvent être effectuer en particulier lorsque
le Tracker est l'application expéditrice. [xxx Le tracker doit
être le récepteur aussi? S'il en est ainsi, est-ce que nous
devrions documenter quand même ces actions?]:
-
B_COPY_SELECTION_TO : Un ou plusieurs éléments (fichiers,
répertoires) sont sélectionné dans une fenêtre
du Tracker; le Tracker peut copier ces fichiers sur la destination entry_ref,
qui sera fournis dans un domaine "refs" donné par le message de
communication, c'est l'application de récepteur qui choisit cette
action.
-
B_MOVE_SELECTION_TO : Un ou plusieurs éléments (fichiers,
répertoires) sont sélectionné dans une fenêtre
du Tracker; le Tracker peut déplacer ces fichiers sur la destination
entry_ref,
qui sera fournis dans un domaine "refs" donné par le message de
communication, c'est l'application de récepteur qui choisit cette
action.
[xxx Le document de Chris suggère que le Tracker peut aussi faire
des liens grâce à une actions spécifique du Tracker,
est-ce que c'est quelque chose comme B_LINK_SELECTION_TO?]
Le champ "be:clip_name"
C'est un champ facile. Si il est présent (ce n'est pas obligatoire),
il contients une chaîne qui suggère un nom pour les données
qui seront envoyées. Ce nom peut être utilisé par le
recepteur; par exemple, si les données sont traînées
sur le Tracker, le Tracker essaiera d'utiliser la valeur dans "be:clip_name"
comme base pour le nom du fichier qu'il va créer avec ces données.
Cependant, le récepteur n'est pas obliger de prendre en considération
cette valeur.
Les Champs "be:originator" et"be:originator_data"
Imaginons que vous êtes une application expéditrice, et que
vous avez envoyé un message de glissé asynchrone. Par suite
vous recevez un BMessage. Est-ce la réponse à
votre message originel? Et si c'est le cas, comment pouvoir accéder
aux donnée d'accès du message de drag originel (Là
où il y a eut le clic de souris) que vous pourriez avoir besoin
afin de completer le message de donnée? Puisque votre message de
glissé originel a été envoyé asynchronement,
votre application a continuée son fonctionnement normal dès
la fin de l'envois, et ne se souviens plus de ce qui a été
déplacé. Que faire? C'est la qu'intervienne les Champs "be:originator"
et "be:originator_data".
-
"be:originator" doit être remplis avec quelque chose qui identifie
personnellement votre application; le nom de cet identificateur n'a pas
de réelle importance. Nous verrons comment utiliser celui-ci dans
une seconde...
-
"be:originator_data" peut être remplis avec les données
du glisser que vous aurez besoin d'utiliser plus tard pour la négociation
drag&drop. Ceci pourrait être quelque chose aussi simple que
la position de la souris, ou ce pourrait être une information beaucoup
plus complexe, au sujet du contexte de l'application au moment du début
du glissé. C'est à vous de le définir selon votre
choix, sans limite, et vous pouvez ne pas utiliser "be:originator_data"
du tout.
Si vous remplissez "be:originator" et "be:originator_data" convenablement
sur tout votre message sortant du glissé, alors voici ce que votre
application peut faire lorsqu'elle recoit un BMessage qui
peut
être un message de communication en réponse à un envois
précédement(asynchrone) lors du glissé:
1. Votre application effectue une vérification
pour s'assurer que le message reçut a le format exact pour un message
de communication (nous décrirons le format de message de négociation
plus loin). Si il est exact, alors le processus continue...
2. Votre application utilise BMessage::IsReply()
pour vérifier si le message reçu est une réponse à
un message précédent.
3. Si le message reçut est bien une
réponse, votre application utilise BMessage::Previous()
pour obtenir le message originel; le message qui est l'objet de la réponse
présente.
4. Maintenant, votre application peut examiner
"be:originator" dans le message originel, et voir s'il reconnaît
cette valeur comme un indicateur lui appartenant et qu'il a lui même
envoyé. Si c'est le cas, alors le BMessage reçut
est en fait un message de communication en réponse à l'originel
message du glissé; votre application peut extraire les données
de contexte nécessaires de "be:originator_data", et continuer la
construction et l'envois du message de données.
Le champ "be:data"
Ce champ était utilisé dans le protocole de glissé/déposé
de départ pour porter les données traînées.
Il n'est pas utilisé dans le protocole de glissé/déposé
communicant.
Le Champ "_drop_point_"
Ce champ contient un BPoint qui donne la coordonnée
d'écran du curseur de souris, lorsque le glissé est terminé
(note: Lorsque le bouton de la souris à été relaché,
et que les données sont "déposé"). Il est automatiquement
ajouté par le système -- vous ne le créez pas ou ne
l'ajoutez pas vous même.
Le Champ "_drop_offset_"
Si vous avez votre application qui montre un bitmap ou un schéma
rectangulaire pendant le glissé, le domaine glissé occupe
un rectangle (Bien qu'il n'apparaisse pas toujours à l'utilisateur
comme tel, puisque avec un bitmap, certaines sections peuvent être
transparentes). "_drop_offset" donne comme un BPoint
la
distance depuis le point supérieur gauche du champ glissé
jusqu'à la position de la souris dans le champs du glissé.
[xxx
je pense que ceci est exact, mais seulement pour être sur.] Ce
champ est ajouté automatiquement par le système -- vous ne
le créez pas ou ne l'ajoutez pas vous même.
Passer les Données
dans un Fichier
Utiliser un BMessage pour passer une grande quantité
de donnée d'une application à l'autre n'est pas forcement
désirable; à l'extrême, vous pourrez ne pas avoir assez
de mémoire pour contenir le BMessage dans sa totalité.
Si vous avez besoin de passer de grandes quantités de données
par une opération de glissé/déposé, vous préférerez
ainsi le faire via un fichier.
Quelque que sot la taille des données passée par un fichier,
l'application expéditrice doit indiquer une ou deux choses en envoyant
le message de glissé à l'application réceptrice.
-
L'expéditeur peut offrir de passer les données par un fichier,
tout comme via un BMessage Le récepteur à
alors l'option d'accepter les données soit via un fichier, soit
via un BMessage.
-
L'expéditeur peut déclarer qu'il ne passera ses données
que sous forme d'un fichier. L'application réceptrice, s'y elle
veut ces données, doit accepter cet état des choses.
Dans les deux cas, la capacité de l'expéditeur à
envoyer des données par un fichier est indiqué dans les champs
du message du glissé "be:types" par B_FILE_MIME_TYPE.
Si B_FILE_MIME_TYPE est la première entré dans
le champ "be:types", alors cela signifie que l'expéditeur ne peut
passer ses données que par un fichier, et tous les autres champs
de "be:types" peuvent être ignoré; si il y a des données
dans "be:types" avant la valeur B_FILE_MIME_TYPE, alors ces
entrées peuvent être utilisées pour que l'expéditeur
les envoies directement dans un message de données.
Si l'expéditeur l'indique, par la présence de la valeur
B_FILE_MIME_TYPE
dans "be:types", c'est qu'il veut passer les données par un fichier,
et que les formats qu'il peut utilisé pour celui-ci sont énuméré
dans le champ "be:filetypes". Si aucune valeur B_FILE_MIME_TYPE
n'est présente dans le champs "be:types", alors l'expéditeur
ne peut pas passer ses données par un fichier dans aucun cas, et
toutes les valeurs situées dans le champ "be:filetypes" sont ignorées.
Protocole Pour
les Message de Communication
Lorsque l'application réceptrice reçois le message de glissé
initial de l'application expéditrice, elle examine les données
contenus dans ce message, pour vérifier quelles actions l'application
expéditrice peut exécuter, et comment elle peut fournir les
données voulus dans le message de glissé final. En utilisant
ces informations, le récepteur crée un message de communication,
qui sera une réponse au message original du glissé, par l'utilisation
de la fonction BMessage: : SendReply().
Un
Message de Communication est Caractérisé par son membre "what"
Souvenez vous que le message de glissé construit par l'application
expéditrice contient (entre autre chose) un champ de message "be:actions",
qui indique les actions que l'expéditeur peut effectuer avec les
données glissées. Les actions admissible (à ce moment
de l'écriture -- des actions peuvent être ajouté dans
le futur de BeOS) sont données par les constantes suivantes:
-
B_COPY_TARGET
-
B_MOVE_TARGET
-
B_LINK_TARGET
-
B_TRASH_TARGET
-
B_MOVE_SELECTION_TO (Pour les glissé du Tracker
seulement.)
-
B_COPY_SELECTION_TO (Pour les glissé du Tracker
seulement.)
En construisant le message de communication, l'application réceptrice
peut choisir l'une des actions définis dans le champs du message
de données "be:types" (souvenez vous, toutes les actions admissibles
seront nécessairement énumérées dans ce champs),
et utiliser cette valeur dans le membre what du message de communication.
Celui-ci informera l'application expéditrice quel action possible
est voulus par le récepteur.
Champs
de Message dans le Message de Comunication
En plus des actions contenus dans le membre what, le message de
négociation peut aussi contenir un certain nombre de champs de message;
et ceux-ci dépendent un peu de l'action demandé par le récepteur.
Les Champs de message admissible sont les suivant:
-
"be:types": Un ou plusieurs chaîne de caractère indique
les formats de données que le récepteur accepte pour les
données glissé, pour le morceau du message de données
contenant celle-ci. Celles-ci sont choisis dans le champ "be:types" du
message de glissé de départ. Si le champ "be:types" du message
de communication contiens plus d'une valeur, alors la première valeur
est le format que le récepteur pour recevoir les données,
mais l'expéditeur peut choisir la valeur qu'il désire. Bien
sur, si l'expéditeur indique dans son message de glissé qu'il
ne peut passer ses données que par un fichier, la valeur de champs
"be:types" du message de communication peut être ignoré lorsque
le message de communication retourne à l'expéditeur.
-
"be:filetypes": Une ou plusieurs chaîne de caractère
indique les formats de données que le récepteur peut accepter
pour la reception de celle-ci, en supposant bien sur que l'expéditeur
à bien spécifier dans sa réponse qu'il désirait
les données sous forme d'un fichier. Les valeurs dans le champs
"be:filetypes" du message de communication doit être choisis parmis
les valeur du message de glissé originel situé dans le champ
"be:filetypes". Si ce message de communication contient plus d'une valeur
dans "be:filetypes", alors c'est que le récepteur préférerais
le premier de a liste, mais l'expéditeur est libre de choisir celui
qui lui convient.
-
"directory": Si l'expéditeur décide (ou est obligé
de) passer les données au récepteur par un fichier, la valeur
entry_ref du champ "directory" du message de communication indique dans
quel répertoire le fichier sera créé.
-
"name": 'Si l'expéditeur décide (ou est obligé
de) passer les données au récepteur par un fichier, la chaine
de caractère de ce champs sera utilisé comme nom pour le
fichier. Note: le récepteur devrait par ailleurs, c'est conseillé,
créer le fichier, avant de choisir le nom, et s'assurer que ce nom
de fichier est bien disponible, et le restera.
Bien sur, vous pouvez omettre des champs qui ne s'applique pas à
votre cas. Par exemple, si le récepteur choisis B_TRASH_TARGET
comme action (par l'utilisation de la valeur B_TRASH_TARGER dans
le membre what du message de communication), aucun champs ne sont
requis; en réalité, l'expéditeur n'a pas besoin de
répondre à une demande de B_TRASH_TARGER avec un message
de donnée, il doit simplement effacer les données glissées.
Protocol pour le Message
de Donnée
Le message de données est le troisième et dernier message
envoyé par le drag&drop communicant. Il est envoyé en
réponse au message de communication, en utilisant la fonction BMessage:
:SendReply(), et il est envoyé seulement si l'application expéditrice
à décidé de passé directement ses données
par un message. Si l'application expéditrice envois les données
au récepteur par un fichier, aucun message de données n'est
envoyé. [xxx Juste pour vérifier, cela est-il correct?
Il semblerait que l'envois d'un message soit effectué, au moins
pour confirmer que l'écriture du fichier à réussis.
Ou est-ce au récepteur de faire tout le travail de récupération?]
Quand
les Données sont Envoyé dans le Message de donnée
Si l'application expéditrice décide d'envoyer les données
glissé directement dans le message de données, alors le message
de donnée sera construit avec la stucture suivante:
-
Un membre what avec la valeur de la constante B_MIME_DATA
-
Un unique champs de message, dont le nom indique le type de donné
mime envoyé, et dont le contenus n'est autre que les données
elles-même. Par exemple, si vous glisser un texte d'une fenêtre
de traitement de texte à une autre, le message de données
finale (après que les messages de dépot et de communication
aient été envoyé) pourrait contenir un champs nommé
"text/plain", qui contiendrait le texte glissé. Autre exemple, si
vous avez glissé un texte depuis un navigateur HTML, le message
de données contiendra (cela dépend des messages de communication)
un seul champs appelé "text/html", qui contiendra le texte y
compris/avec le formatage html
Notez que lorsque les messages de données arrivent au récepteur,
il peut contenir plus qu'un simple champ de message seul comme traité
si dessus; d'autre champ de message peuvent être ajouté automatiquement,
par le système. Cependant, le champ de message ci-dessus est le
seul et unique que vous ajoutez.
Controle
des 'Ancienne' Applications
de Glisser/Déposers
Le glisser/déposer communicant a été définis
relativement récemment; et les anciennes application utilisant "le
vieux style" de glisser/déposer. Il est cependant relativement simple
pour votre application de prendre en compte un tel dépot, en tant
que réceptrice.
Avec l'ancien glisser/déposer, un seul message est envoyé
de l'expéditeur au récepteur, avec un membre what de type
B_MIME_DATA,
et la valeur des données glissées se situe dans le champ
"be:data" du message.[xxx comment le type de celle ci est-il déterminé?]
Depuis votre application réceptrice qui reçoit le BMessage
avec un membre what contenant un B_MIME_DATA (note: votre application
doit chercher les message de données qui pourrait arriver comme
la partie d'un glisser/déposer communiquant), il est simple d'ajouter
un petit bout de code qui contrôle le fait qu'un tel message peut
arriver, sans communication autre, et peut contenir un champs "be:data".
Résumé
du Protocole de Communication Glisser/Déposer
Message du glisser
La structure d'un message de glisser est la suivante:
-
Un membre what, de type B_SIMPLE_DATA.
-
Trois champs de message "be:types", "be:filetypes" et "be:type-description",
qui contiennent (respectivement) le format dans lequel l'expéditeur
veut passer ses données dans le message de donnée, le format
dans lequel l'expéditeur veux passer ses sonnées dans un
fichier, et une description concut pour l'utilisateur des différents
formats.
-
Un champ message "be:actions" qui contient une liste d'action que
l'expéditeur peut effectuer à la demande du récepteur.
-
Un champ optionnel "be:clip_name" qui propose un nom pour un clipping
-
Les champs optionnels "be:originator" et "be:originator_data",
qui peuvent être utilisé pour données des informations
sur le contexte d'execution lors d'un glisser/déposer asynchrone.
-
"_drop_point" et "_drop_offset", qui sont remplis par le
système, et qui donnent des informations sur l'emplacement du curseur
de la souris, et où le glisser est effectué.
Message de Communication
Le structure d'un message de communication est la suivante:
-
Un membre what, qui est l'une des valeurs extraite du champ "be:actions"
du message de glissé, et dont ce message de communication est la
réponse.
-
Une liste de format dans le champs du message "be:types", choisis
parmis la liste proposée par "be:types" du message de glisser. Ceux-ci
indique les formats dans lesquel que le récepteur peut recevoir
les données. Si la valeur constitué par la constante globale
B_FILE_TYPE
est dans la liste, alors le récepteur accepte de recevoir les données
via un fichier, aussi bien que par un Message de donnée. Notez que
les valeurs situées après B_FILE_TYPE seront ignorées;
ainsi, si B_FILE_TYPE est le premier élément de "be:types",
alors le récepteur n'accepte les données uniquement
via un fichier. Si il y a plusieurs valeurs dans "be:types", la première
valeur est celle qui est préféré par le recepteur.
-
Une liste de format dans le champs "be:filetypes" du message, qui
indique les formats de fichier que le recepteur peut accepter, si les données
sont passée par un fichier. Cela a de l'importance uniquement si
"be:types" contiens la valeurs B_FILE_MIME_TYPE comme une
possibilitée. Si il y a plus d'une valeurs dans "be:filetypes",
la première valeurs est celle qui est désiré le plus,
bien que les autres soient aussi acceptée
-
Les champs "directory" et "name", qui sont utilisés
uniquement si le message de communication accepte les données
passée par un fichier. "directory" est du type entry_ref, et spécifie
ou le fichier doit être placé, et le champ "nom" contient
une chaine de caractères avec le nom désiré pour le
fichier.
Message de donnée
La strcture du message de donnée est la suivante:
-
Un membre what de type B_MIME_DATA.
-
Un simple champ du message de donnée ajouté par le
code du programme; le nom de ce champs est le type mime des données
passées, et la valeur de ce champ est les données
elles même. Par example, un morceau de texte sera envoyé dans
un message dans le champs se nommera"text/plain". Le type mime pour les
données est choisis parmis une liste de format choisis, cf le champ "be:types"
du message de négociation auquel ce message repond.
The BeBook,
...in lovely HTML...
pour BeOS Version 5.
Copyright © 2000 Be, Inc. Tout droit réservé.
Dernière modification du texte Janvier 26, 2000.