Roassal draggable/droppable

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Roassal draggable/droppable

Peter Uhnak
Hi,

Currently I don't see any way how to tell an element that another one has been dropped onto him. For example if I want to drag an element into a container (see example at the end).

Unfortunately in my solution i had to change the behaviour of Trachel (RTMorph), so could this be in some (better) way incorporated into Roassal (Trachel)?

My solution is making a subclass
-------------------------------------
TRAbstractMouseEvent subclass: #TRMouseDragDrop
-------------------------------------

And altering mouseDragEnd

-------------------------------------
RTMorph>>rtMouseDragEnd: evt
| ee dropEvent dropShape relativePosition |
"notify the dragged element"
ee := TRMouseDragEnd new.
ee shape: shapeBeingPointed.
ee canvas: trachelCanvas.
ee morph: self.
shapeBeingPointed announce: ee.
"notify the element onto which was the drag performed"
shapeBeingPointed = trachelCanvas
ifFalse: [ 
shapeBeingPointed element attributes
at: #rtDroppable
ifPresent: [ 
relativePosition := self relativePositionFor: evt.
dropShape := self shapeWithAction: TRMouseDragDrop forPositionInPixels: relativePosition.
dropShape = shapeBeingPointed
ifFalse: [ 
dropEvent := TRMouseDragDrop new
shape: shapeBeingPointed;
canvas: trachelCanvas;
morph: self.
dropShape announce: dropEvent ] ] ].
eventBeginingDragging := nil.
shapeBeingPointed := nil
-------------------------------------

Example (use case) is:

-------------------------------------
view := RTView new.

container := RTBox new size: 200; color: Color white; borderColor: Color black; element.
group := RTGroup new.

RTNest new on: container nest: group.
container trachelShape size: 200.

box := RTBox new size: 50; color: Color magenta; element.
box translateTo: 250 @ 0.

container @ RTDraggable.
container @ RTResizeable.
box @ RTDraggable.
box attributes at: #rtDroppable put: true.

container
when: TRMouseDragDrop
do: [ :event |
| el |
el := event shape element.
el attributes at: #container ifPresent: [
group remove: el.
].
group add: el.
el attributes at: #container put: group.
].

view canvas
when: TRMouseDragDrop
do: [ :event |
| el |
el := event shape element.
el attributes at: #container ifPresent: [ :parent |
parent remove: el.
el attributes removeKey: #container.
].
].

view
add: container;
add: box.
view open.
-------------------------------------

Also it would be nice to have an option to highlight the drop area. There is TRMouseEnter/TRMouseLeave but it fires only for the top level shape, perhaps it should for all? Or less invasive to add TRMouseDragEnter/TRMouseDragLeave which would work like regular Enter/Leave but on the next (on z-axis) shape.

Please let me know what you think.

Peter

_______________________________________________
Moose-dev mailing list
[hidden email]
https://www.iam.unibe.ch/mailman/listinfo/moose-dev
Reply | Threaded
Open this post in threaded view
|

Re: Roassal draggable/droppable

Gustavo Santos
I have the exactly same need :)

On Mon, Oct 13, 2014 at 1:02 AM, Peter Uhnák <[hidden email]> wrote:
Hi,

Currently I don't see any way how to tell an element that another one has been dropped onto him. For example if I want to drag an element into a container (see example at the end).

Unfortunately in my solution i had to change the behaviour of Trachel (RTMorph), so could this be in some (better) way incorporated into Roassal (Trachel)?

My solution is making a subclass
-------------------------------------
TRAbstractMouseEvent subclass: #TRMouseDragDrop
-------------------------------------

And altering mouseDragEnd

-------------------------------------
RTMorph>>rtMouseDragEnd: evt
| ee dropEvent dropShape relativePosition |
"notify the dragged element"
ee := TRMouseDragEnd new.
ee shape: shapeBeingPointed.
ee canvas: trachelCanvas.
ee morph: self.
shapeBeingPointed announce: ee.
"notify the element onto which was the drag performed"
shapeBeingPointed = trachelCanvas
ifFalse: [ 
shapeBeingPointed element attributes
at: #rtDroppable
ifPresent: [ 
relativePosition := self relativePositionFor: evt.
dropShape := self shapeWithAction: TRMouseDragDrop forPositionInPixels: relativePosition.
dropShape = shapeBeingPointed
ifFalse: [ 
dropEvent := TRMouseDragDrop new
shape: shapeBeingPointed;
canvas: trachelCanvas;
morph: self.
dropShape announce: dropEvent ] ] ].
eventBeginingDragging := nil.
shapeBeingPointed := nil
-------------------------------------

Example (use case) is:

-------------------------------------
view := RTView new.

container := RTBox new size: 200; color: Color white; borderColor: Color black; element.
group := RTGroup new.

RTNest new on: container nest: group.
container trachelShape size: 200.

box := RTBox new size: 50; color: Color magenta; element.
box translateTo: 250 @ 0.

container @ RTDraggable.
container @ RTResizeable.
box @ RTDraggable.
box attributes at: #rtDroppable put: true.

container
when: TRMouseDragDrop
do: [ :event |
| el |
el := event shape element.
el attributes at: #container ifPresent: [
group remove: el.
].
group add: el.
el attributes at: #container put: group.
].

view canvas
when: TRMouseDragDrop
do: [ :event |
| el |
el := event shape element.
el attributes at: #container ifPresent: [ :parent |
parent remove: el.
el attributes removeKey: #container.
].
].

view
add: container;
add: box.
view open.
-------------------------------------

Also it would be nice to have an option to highlight the drop area. There is TRMouseEnter/TRMouseLeave but it fires only for the top level shape, perhaps it should for all? Or less invasive to add TRMouseDragEnter/TRMouseDragLeave which would work like regular Enter/Leave but on the next (on z-axis) shape.

Please let me know what you think.

Peter

_______________________________________________
Moose-dev mailing list
[hidden email]
https://www.iam.unibe.ch/mailman/listinfo/moose-dev


--
Gustavo Santos

_______________________________________________
Moose-dev mailing list
[hidden email]
https://www.iam.unibe.ch/mailman/listinfo/moose-dev
Reply | Threaded
Open this post in threaded view
|

Re: Roassal draggable/droppable

abergel
In reply to this post by Peter Uhnak
Hi Peter and Gustavo!

Having a nice support for drag and drop is difficult. The idea is to go step by step. I have introduced a new interaction, called RTDragAndDroppable. You simply need to specify the host element, and the action you want to perform when you drag and drop.

You can run the following example after updating Roassal.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
v := RTView new.

e1 := (RTBox new size: 10; color: Color gray) element.
e2 := (RTEllipse new size: 30; color: Color blue) element.
e1 @ RTDraggable.

e1 translateTo: 50 @ 50.
v add: e1.
v add: e2.

e2 @ (RTDragAndDroppable new
                        host: e1;
                        do: [ :fromElement :toElement |
                                | newElement alreadyNested |
                                newElement := (RTBox new size: 20) element.
                                v add: newElement.
                                alreadyNested := toElement nestedElements.
                                toElement unbindNestedElements.
                                RTNest new
                                        layout: RTGridLayout new;
                                        on: toElement nest: alreadyNested, (Array with: newElement) ]).

v
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
I will work today a bit more on hilighting the receiving element. This is easy to do.

Cheers,
Alexandre


On Oct 12, 2014, at 8:02 PM, Peter Uhnák <[hidden email]> wrote:

> Hi,
>
> Currently I don't see any way how to tell an element that another one has been dropped onto him. For example if I want to drag an element into a container (see example at the end).
>
> Unfortunately in my solution i had to change the behaviour of Trachel (RTMorph), so could this be in some (better) way incorporated into Roassal (Trachel)?
>
> My solution is making a subclass
> -------------------------------------
> TRAbstractMouseEvent subclass: #TRMouseDragDrop
> -------------------------------------
>
> And altering mouseDragEnd
>
> -------------------------------------
> RTMorph>>rtMouseDragEnd: evt
> | ee dropEvent dropShape relativePosition |
> "notify the dragged element"
> ee := TRMouseDragEnd new.
> ee shape: shapeBeingPointed.
> ee canvas: trachelCanvas.
> ee morph: self.
> shapeBeingPointed announce: ee.
>
> "notify the element onto which was the drag performed"
> shapeBeingPointed = trachelCanvas
> ifFalse: [
> shapeBeingPointed element attributes
> at: #rtDroppable
> ifPresent: [
> relativePosition := self relativePositionFor: evt.
> dropShape := self shapeWithAction: TRMouseDragDrop forPositionInPixels: relativePosition.
> dropShape = shapeBeingPointed
> ifFalse: [
> dropEvent := TRMouseDragDrop new
> shape: shapeBeingPointed;
> canvas: trachelCanvas;
> morph: self.
> dropShape announce: dropEvent ] ] ].
>
> eventBeginingDragging := nil.
> shapeBeingPointed := nil
> -------------------------------------
>
> Example (use case) is:
>
> -------------------------------------
> view := RTView new.
>
> container := RTBox new size: 200; color: Color white; borderColor: Color black; element.
> group := RTGroup new.
>
> RTNest new on: container nest: group.
> container trachelShape size: 200.
>
> box := RTBox new size: 50; color: Color magenta; element.
> box translateTo: 250 @ 0.
>
> container @ RTDraggable.
> container @ RTResizeable.
> box @ RTDraggable.
> box attributes at: #rtDroppable put: true.
>
> container
> when: TRMouseDragDrop
> do: [ :event |
> | el |
> el := event shape element.
> el attributes at: #container ifPresent: [
> group remove: el.
> ].
> group add: el.
> el attributes at: #container put: group.
> ].
>
> view canvas
> when: TRMouseDragDrop
> do: [ :event |
> | el |
> el := event shape element.
> el attributes at: #container ifPresent: [ :parent |
> parent remove: el.
> el attributes removeKey: #container.
> ].
> ].
>
> view
> add: container;
> add: box.
>
> view open.
> -------------------------------------
>
> Also it would be nice to have an option to highlight the drop area. There is TRMouseEnter/TRMouseLeave but it fires only for the top level shape, perhaps it should for all? Or less invasive to add TRMouseDragEnter/TRMouseDragLeave which would work like regular Enter/Leave but on the next (on z-axis) shape.
>
> Please let me know what you think.
>
> Peter
> _______________________________________________
> Moose-dev mailing list
> [hidden email]
> https://www.iam.unibe.ch/mailman/listinfo/moose-dev

--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel  http://www.bergel.eu
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.




_______________________________________________
Moose-dev mailing list
[hidden email]
https://www.iam.unibe.ch/mailman/listinfo/moose-dev
Reply | Threaded
Open this post in threaded view
|

Re: Roassal draggable/droppable

Peter Uhnak
Hi Alex,

I tried the example but it throws "Block cannot return" error when trying to drag the blue circle... somewhere around RTDragAndDroppable>>prepareElementForDND: anElement and [^self] so I wasn't able to try it. Also the error looks really wonky. I tried it in the latest Pharo4.0 image.

Also I am confused about the RTDragAndDroppable>>host: functionality. I do not know beforehand what element will be dropped or where (as it is used in the example). Usually I would have many containers and elements and they should themselves decide whether they accept a particular item or not. But I do agree that this is more complex issue. Should I work on it and give you a better proposal in couple of days?

Peter

On Mon, Oct 13, 2014 at 4:22 PM, Alexandre Bergel <[hidden email]> wrote:
Hi Peter and Gustavo!

Having a nice support for drag and drop is difficult. The idea is to go step by step. I have introduced a new interaction, called RTDragAndDroppable. You simply need to specify the host element, and the action you want to perform when you drag and drop.

You can run the following example after updating Roassal.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
v := RTView new.

e1 := (RTBox new size: 10; color: Color gray) element.
e2 := (RTEllipse new size: 30; color: Color blue) element.
e1 @ RTDraggable.

e1 translateTo: 50 @ 50.
v add: e1.
v add: e2.

e2 @ (RTDragAndDroppable new
                        host: e1;
                        do: [ :fromElement :toElement |
                                | newElement alreadyNested |
                                newElement := (RTBox new size: 20) element.
                                v add: newElement.
                                alreadyNested := toElement nestedElements.
                                toElement unbindNestedElements.
                                RTNest new
                                        layout: RTGridLayout new;
                                        on: toElement nest: alreadyNested, (Array with: newElement) ]).

v
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

I will work today a bit more on hilighting the receiving element. This is easy to do.

Cheers,
Alexandre


On Oct 12, 2014, at 8:02 PM, Peter Uhnák <[hidden email]> wrote:

> Hi,
>
> Currently I don't see any way how to tell an element that another one has been dropped onto him. For example if I want to drag an element into a container (see example at the end).
>
> Unfortunately in my solution i had to change the behaviour of Trachel (RTMorph), so could this be in some (better) way incorporated into Roassal (Trachel)?
>
> My solution is making a subclass
> -------------------------------------
> TRAbstractMouseEvent subclass: #TRMouseDragDrop
> -------------------------------------
>
> And altering mouseDragEnd
>
> -------------------------------------
> RTMorph>>rtMouseDragEnd: evt
>       | ee dropEvent dropShape relativePosition |
>       "notify the dragged element"
>       ee := TRMouseDragEnd new.
>       ee shape: shapeBeingPointed.
>       ee canvas: trachelCanvas.
>       ee morph: self.
>       shapeBeingPointed announce: ee.
>
>       "notify the element onto which was the drag performed"
>       shapeBeingPointed = trachelCanvas
>               ifFalse: [
>                       shapeBeingPointed element attributes
>                               at: #rtDroppable
>                               ifPresent: [
>                                       relativePosition := self relativePositionFor: evt.
>                                       dropShape := self shapeWithAction: TRMouseDragDrop forPositionInPixels: relativePosition.
>                                       dropShape = shapeBeingPointed
>                                               ifFalse: [
>                                                       dropEvent := TRMouseDragDrop new
>                                                               shape: shapeBeingPointed;
>                                                               canvas: trachelCanvas;
>                                                               morph: self.
>                                                       dropShape announce: dropEvent ] ] ].
>
>       eventBeginingDragging := nil.
>       shapeBeingPointed := nil
> -------------------------------------
>
> Example (use case) is:
>
> -------------------------------------
> view := RTView new.
>
> container := RTBox new size: 200; color: Color white; borderColor: Color black; element.
> group := RTGroup new.
>
> RTNest new on: container nest: group.
> container trachelShape size: 200.
>
> box := RTBox new size: 50; color: Color magenta; element.
> box translateTo: 250 @ 0.
>
> container @ RTDraggable.
> container @ RTResizeable.
> box @ RTDraggable.
> box attributes at: #rtDroppable put: true.
>
> container
>       when: TRMouseDragDrop
>       do: [ :event |
>               | el |
>               el := event shape element.
>               el attributes at: #container ifPresent: [
>                       group remove: el.
>               ].
>               group add: el.
>               el attributes at: #container put: group.
> ].
>
> view canvas
>       when: TRMouseDragDrop
>       do: [ :event |
>       | el |
>       el := event shape element.
>       el attributes at: #container ifPresent: [ :parent |
>                       parent remove: el.
>                       el attributes removeKey: #container.
>               ].
>       ].
>
> view
>       add: container;
>       add: box.
>
> view open.
> -------------------------------------
>
> Also it would be nice to have an option to highlight the drop area. There is TRMouseEnter/TRMouseLeave but it fires only for the top level shape, perhaps it should for all? Or less invasive to add TRMouseDragEnter/TRMouseDragLeave which would work like regular Enter/Leave but on the next (on z-axis) shape.
>
> Please let me know what you think.
>
> Peter
> _______________________________________________
> Moose-dev mailing list
> [hidden email]
> https://www.iam.unibe.ch/mailman/listinfo/moose-dev

--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel  http://www.bergel.eu
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.




_______________________________________________
Moose-dev mailing list
[hidden email]
https://www.iam.unibe.ch/mailman/listinfo/moose-dev


_______________________________________________
Moose-dev mailing list
[hidden email]
https://www.iam.unibe.ch/mailman/listinfo/moose-dev
Reply | Threaded
Open this post in threaded view
|

Re: Roassal draggable/droppable

abergel
Sure! I will try to have a look at it tomorrow. But feel free to work on the drag and drop. My proposal is just a starting point. 
Contribution are welcome!

Alexandre

Le 13-10-2014 à 12:58, Peter Uhnák <[hidden email]> a écrit :

Hi Alex,

I tried the example but it throws "Block cannot return" error when trying to drag the blue circle... somewhere around RTDragAndDroppable>>prepareElementForDND: anElement and [^self] so I wasn't able to try it. Also the error looks really wonky. I tried it in the latest Pharo4.0 image.

Also I am confused about the RTDragAndDroppable>>host: functionality. I do not know beforehand what element will be dropped or where (as it is used in the example). Usually I would have many containers and elements and they should themselves decide whether they accept a particular item or not. But I do agree that this is more complex issue. Should I work on it and give you a better proposal in couple of days?

Peter

On Mon, Oct 13, 2014 at 4:22 PM, Alexandre Bergel <[hidden email]> wrote:
Hi Peter and Gustavo!

Having a nice support for drag and drop is difficult. The idea is to go step by step. I have introduced a new interaction, called RTDragAndDroppable. You simply need to specify the host element, and the action you want to perform when you drag and drop.

You can run the following example after updating Roassal.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
v := RTView new.

e1 := (RTBox new size: 10; color: Color gray) element.
e2 := (RTEllipse new size: 30; color: Color blue) element.
e1 @ RTDraggable.

e1 translateTo: 50 @ 50.
v add: e1.
v add: e2.

e2 @ (RTDragAndDroppable new
                        host: e1;
                        do: [ :fromElement :toElement |
                                | newElement alreadyNested |
                                newElement := (RTBox new size: 20) element.
                                v add: newElement.
                                alreadyNested := toElement nestedElements.
                                toElement unbindNestedElements.
                                RTNest new
                                        layout: RTGridLayout new;
                                        on: toElement nest: alreadyNested, (Array with: newElement) ]).

v
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

I will work today a bit more on hilighting the receiving element. This is easy to do.

Cheers,
Alexandre


On Oct 12, 2014, at 8:02 PM, Peter Uhnák <[hidden email]> wrote:

> Hi,
>
> Currently I don't see any way how to tell an element that another one has been dropped onto him. For example if I want to drag an element into a container (see example at the end).
>
> Unfortunately in my solution i had to change the behaviour of Trachel (RTMorph), so could this be in some (better) way incorporated into Roassal (Trachel)?
>
> My solution is making a subclass
> -------------------------------------
> TRAbstractMouseEvent subclass: #TRMouseDragDrop
> -------------------------------------
>
> And altering mouseDragEnd
>
> -------------------------------------
> RTMorph>>rtMouseDragEnd: evt
>       | ee dropEvent dropShape relativePosition |
>       "notify the dragged element"
>       ee := TRMouseDragEnd new.
>       ee shape: shapeBeingPointed.
>       ee canvas: trachelCanvas.
>       ee morph: self.
>       shapeBeingPointed announce: ee.
>
>       "notify the element onto which was the drag performed"
>       shapeBeingPointed = trachelCanvas
>               ifFalse: [
>                       shapeBeingPointed element attributes
>                               at: #rtDroppable
>                               ifPresent: [
>                                       relativePosition := self relativePositionFor: evt.
>                                       dropShape := self shapeWithAction: TRMouseDragDrop forPositionInPixels: relativePosition.
>                                       dropShape = shapeBeingPointed
>                                               ifFalse: [
>                                                       dropEvent := TRMouseDragDrop new
>                                                               shape: shapeBeingPointed;
>                                                               canvas: trachelCanvas;
>                                                               morph: self.
>                                                       dropShape announce: dropEvent ] ] ].
>
>       eventBeginingDragging := nil.
>       shapeBeingPointed := nil
> -------------------------------------
>
> Example (use case) is:
>
> -------------------------------------
> view := RTView new.
>
> container := RTBox new size: 200; color: Color white; borderColor: Color black; element.
> group := RTGroup new.
>
> RTNest new on: container nest: group.
> container trachelShape size: 200.
>
> box := RTBox new size: 50; color: Color magenta; element.
> box translateTo: 250 @ 0.
>
> container @ RTDraggable.
> container @ RTResizeable.
> box @ RTDraggable.
> box attributes at: #rtDroppable put: true.
>
> container
>       when: TRMouseDragDrop
>       do: [ :event |
>               | el |
>               el := event shape element.
>               el attributes at: #container ifPresent: [
>                       group remove: el.
>               ].
>               group add: el.
>               el attributes at: #container put: group.
> ].
>
> view canvas
>       when: TRMouseDragDrop
>       do: [ :event |
>       | el |
>       el := event shape element.
>       el attributes at: #container ifPresent: [ :parent |
>                       parent remove: el.
>                       el attributes removeKey: #container.
>               ].
>       ].
>
> view
>       add: container;
>       add: box.
>
> view open.
> -------------------------------------
>
> Also it would be nice to have an option to highlight the drop area. There is TRMouseEnter/TRMouseLeave but it fires only for the top level shape, perhaps it should for all? Or less invasive to add TRMouseDragEnter/TRMouseDragLeave which would work like regular Enter/Leave but on the next (on z-axis) shape.
>
> Please let me know what you think.
>
> Peter
> _______________________________________________
> Moose-dev mailing list
> [hidden email]
> https://www.iam.unibe.ch/mailman/listinfo/moose-dev

--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel  http://www.bergel.eu
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.




_______________________________________________
Moose-dev mailing list
[hidden email]
https://www.iam.unibe.ch/mailman/listinfo/moose-dev

_______________________________________________
Moose-dev mailing list
[hidden email]
https://www.iam.unibe.ch/mailman/listinfo/moose-dev

_______________________________________________
Moose-dev mailing list
[hidden email]
https://www.iam.unibe.ch/mailman/listinfo/moose-dev