Page 1 sur 1

DragnDrop par BindGadgetEvent

Publié : mer. 05/oct./2016 11:09
par Marc56
Hello,

L'exemple que j'ai donné à Micoute la semaine dernière pour illustrer le splitter m'a donné l'envie d'ajouter un gestionnaire de notes à mon ACME Desk.

Afin de mettre au point le "moteur" (from scratch, car j'aime comprendre), j'en ai réalisé un programme autonome.
Voici donc ACME TreeNote 8)
La première beta version est disponible ici
C'est pour l'instant rudimentaire, cela ne peut qu'ajouter des notes, les renommer et remplir :wink:
Les données sont sauvées au format JSON

Je cherche maintenant à déplacer les notes dans l'arbre (pour l'instant uniquement à la verticale)
J'en profite aussi pour (essayer de) gérer tous les évènements à l'aide des BindEvent. :!:

Exemple épuré (basé sur ce que j'avais proposé à Micoute au sujet du splitter)

Code : Tout sélectionner

EnableExplicit

; --- Form (réalisé par le Form Designer)
Enumeration FormWindow
  #Window_0
EndEnumeration

Enumeration FormGadget
  #Tree_0
  #Editor_0
  #Splitter_0
  #Btn_Quit
EndEnumeration

Declare ResizeGadgetsWindow_0()

Procedure OpenWindow_0(x = 0, y = 0, width = 600, height = 400)
  OpenWindow(#Window_0, x, y, width, height, "", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
  TreeGadget(#Tree_0, 10, 15, 177, 340)
  EditorGadget(#Editor_0, 196, 15, 394, 340)
  SplitterGadget(#Splitter_0, 10, 15, 580, 340, #Tree_0, #Editor_0, #PB_Splitter_Vertical)
  SetGadgetState(#Splitter_0, 177)
  ButtonGadget(#Btn_Quit, 490, 365, 100, 25, "Quitter")
EndProcedure

Procedure ResizeGadgetsWindow_0()
  Protected FormWindowWidth, FormWindowHeight
  FormWindowWidth = WindowWidth(#Window_0)
  FormWindowHeight = WindowHeight(#Window_0)
  ResizeGadget(#Tree_0, 10, 15, 177, FormWindowHeight - 60)
  ResizeGadget(#Editor_0, FormWindowWidth - 404, 15, 394, FormWindowHeight - 60)
  ResizeGadget(#Splitter_0, 10, 15, FormWindowWidth - 20, FormWindowHeight - 60)
  ResizeGadget(#Btn_Quit, GadgetWidth(#Splitter_0) - 90, GadgetHeight(#Splitter_0) - -25, 100, 25)
EndProcedure

; --- Code principal
OpenWindow_0()

; --- Activation du D&D pour le treegadget
EnableGadgetDrop(#Tree_0, #PB_Drop_Private, #PB_Drag_Move, 1)

Define a.c
For a = 0 To 3
     AddGadgetItem(#Tree_0, -1, "Elément normal "+Str(a), 0, 0)  
     AddGadgetItem(#Tree_0, -1, "Noeud "+Str(a), 0, 0)          
     AddGadgetItem(#Tree_0, -1, "Sous-élément 1", 0, 1)         
     AddGadgetItem(#Tree_0, -1, "Sous-élément 2", 0, 1)
     AddGadgetItem(#Tree_0, -1, "Sous-élément 3", 0, 1)
     AddGadgetItem(#Tree_0, -1, "Sous-élément 4", 0, 1)
     AddGadgetItem(#Tree_0, -1, "Fichier "+ Str(a), 0, 0) 
Next



Procedure Quit()
     End
EndProcedure


Procedure Note_Select()
     SetGadgetText(#Editor_0, "Note N° " + 
                              GetGadgetState(#Tree_0) +
                              " - Titre : " + 
                              GetGadgetItemText(#Tree_0, GetGadgetState(#Tree_0)))     
EndProcedure



Procedure Drag_Start()
     Debug "Drag_Start"
     DragPrivate(1, #PB_Drag_Move)
EndProcedure



Procedure Drag_Drop()
     Debug "Drop"
     ; Devrait afficher "Drop" quand on relache la souris, mais ne fonctionne pas
EndProcedure


; --- Gestion des évènements

; --- Fenêtre
BindEvent(#PB_Event_CloseWindow,   @Quit(),                      #Window_0)
BindEvent(#PB_Event_SizeWindow,    @ResizeGadgetsWindow_0(),     #Window_0)

; --- Gadgets
BindGadgetEvent(#Btn_Quit,         @Quit())

; --- Déplacement des notes dans le TreeGadget par drag'n'drop
BindGadgetEvent(#Tree_0,           @Drag_Start(),                #PB_EventType_DragStart)   
BindGadgetEvent(#Tree_0,           @Drag_Drop(),                 #PB_Drop_Private) ; <--- ça marche pô :o(  

; --- Sélection
BindGadgetEvent(#Tree_0,           @Note_Select(),               #PB_EventType_LeftClick)           



Repeat : WaitWindowEvent() : ForEver
Le "tout Bind or not tout Bind" rend le code vachement plus clair :P

Tout fonctionne, sauf qu'il ne détecte pas le Drop (le debug devrait afficher drop) :?
Il y a quelque chose qui ne va pas dans ma ligne ?

Code : Tout sélectionner

BindGadgetEvent(#Tree_0,           @Drag_Drop(),                 #PB_Drop_Private)
ou alors on ne peut pas utiliser les bind pour le drop ?

Il doit y avoir un truc bête :?: :roll:

Re: DragnDrop par BindGadgetEvent

Publié : mer. 05/oct./2016 12:13
par Marc56
Bon, j'ai trouvé, mais pas complètement

Code : Tout sélectionner

BindGadgetEvent(#Tree_0,           @Drag_Drop(),                 #PB_All)
Le problème est que je reçois ainsi deux fois Drop (ce qui est logique à cause du #PB_All)

Code : Tout sélectionner

Drop
Drag_Start
Drop
Drop
Mais on s'approche
:)

Re: DragnDrop par BindGadgetEvent

Publié : mer. 05/oct./2016 12:27
par Marc56
:idea: Ça y est, j'ai trouvé, vive le débug :P

J'ai mis #PB_All pour voir tous les évènements que voit passer le TreeGadget

Code : Tout sélectionner

 BindGadgetEvent(#Tree_0, @Drag_Drop(), #PB_All) 
puis Debug EventType() dans la callback @Drag_Drop()

Code : Tout sélectionner

Procedure Drag_Drop()
     Debug "Drop"
     Debug EventType() ; <--- Affiche tous les évènements reçus par le gadget 
EndProcedure
J'ai ainsi vu le numéro passer lors du lâché de souris: 768

Puis j'ai mis ce numéro dans la procedure callback

Code : Tout sélectionner

BindGadgetEvent(#Tree_0, @Drag_Drop(),  768)
Hacker niveau zéro que je suis :mrgreen: mais pure logique: ça marche 8)

Edit: Hum :o
Je reçois quand même un Drop au début (?), donc ce ne doit pas être exactement ça :?
(je vais résoudre provisoirement en mettant un flag lors du drag start)

Re: DragnDrop par BindGadgetEvent

Publié : mer. 05/oct./2016 13:15
par falsam
Parce que ça ne fonctionne pas, commente

Code : Tout sélectionner

BindGadgetEvent(#Tree_0,           @Drag_Drop(),                 #PB_Drop_Private) ; <--- ça marche pô :o( 
et ajoute

Code : Tout sélectionner

BindEvent(#PB_Event_GadgetDrop,    @Drag_Drop(),                 #Window_0)
Debug a écrit :Drag_Start
Drop

Re: DragnDrop par BindGadgetEvent

Publié : mer. 05/oct./2016 13:27
par Kwai chang caine
J'ai cherché et pas trouvé, alors j'ai pas jugé bon de répondre :cry:

J'ai eu la même démarche que toi, sauf que connaissant pas le #pb_all, j'ai affiché les eventtype dans la boucle

Code : Tout sélectionner

Repeat : WaitWindowEvent() : ForEver
J'ai essayé de remplacer ton #PB_Drop_Private par 14002, 768 etc...mais aucun ne correspondaient vraiment à l'evenement drop

Bref.... apres de nombreux essais..je suis parti pleurer tout seul dans mon coin :(

Re: DragnDrop par BindGadgetEvent

Publié : mer. 05/oct./2016 13:27
par Marc56
falsam a écrit :

Code : Tout sélectionner

BindEvent(#PB_Event_GadgetDrop,    @Drag_Drop(),                 #Window_0)
Yes :!: Merci :P

Je remet en résumé les éléments nécessaires pour faire un d&d sur un TreeGadget avec la méthode Bind...
Beaucoup moins de lignes qu'avec la méthode classique :)
Il ne me reste plus qu'à mettre la partie pour écarter les éléments lors du drop.

Code : Tout sélectionner

; ... (voir post précédent)
; --- Indiquer au TreeGadget qu'il peut recevoir (depuis la fenêtre elle-même)
EnableGadgetDrop(#Tree_0, #PB_Drop_Private, #PB_Drag_Move, 1)

; --- Les deux procédures qui seront appelées en Callback
Procedure Drag_Start()
     Debug "Drag #" + GetGadgetState(#Tree_0)
     ; --- Démarrer le d&d
     DragPrivate(1, #PB_Drag_Move)
EndProcedure

Procedure Drag_Drop()
     Debug "Drop #" + GetGadgetState(#Tree_0) 
     Debug ""
EndProcedure

; --- Les deux Callback
; --- Callback lors du démarrage du d&d
BindGadgetEvent(#Tree_0,        @Drag_Start(),    #PB_EventType_DragStart)
; --- Callback lors de la réception du d&d
BindEvent(#PB_Event_GadgetDrop, @Drag_Drop(),     #Window_0) 

; Et quand on a tout fait avec les Callback, la boucle principale se résume à:
Repeat : WaitWindowEvent() : ForEver

:idea: Effectivement, en Drop_Private il fallait tester le drop sur la fenêtre elle-même et pas sur le gadget!

Merci Falsam :wink:

PS. Tant de choses avec si peu de lignes, merci Fred pour cette remarquable implémentation du Basic 8)

Re: DragnDrop par BindGadgetEvent

Publié : mer. 05/oct./2016 13:29
par Kwai chang caine
Alors la....le mister Falsard....il me trou le c.... 8O
Sincerement...le FRED il aurait pu creer un #PB_EventType_Drop ou un truc du genre.... :?

Bon alors...on dit merci qui ???
Merci FALSAM 8)

Re: DragnDrop par BindGadgetEvent

Publié : jeu. 06/oct./2016 11:48
par Ulix
@Marc56


Salut !

Je n'ai pas (encore, ce soir dès que je rentre) tester ton code ! :oops:

Par contre je pense que tu auras le même problème que moi, le DragNDrop ne prend pas en
compte le scrolling (le Drag ne peut remonte au dessus du premier item visible, ni en dessous
du dernier item visible)
Voir : http://www.purebasic.fr/french/viewtopi ... 14&t=16290


Je n'ai pas trouvé la solution (solution en natif, pour DRagNDrop ) :twisted:
Par contre je gère le déplacement des item par raccourci clavier, c'est aussi rapide !

Il es sûrement possible de contourné le problème en passant par les Apis (Win ou Gtk selon)
et les callback prévus dans la lib DragNDrop.

A+