Xojo Developer Conference
25/27th April 2018 in Denver.
MBS Xojo Conference
6/7th September 2018 in Munich, Germany.

[MBS] Selection rectangle in a canvas (MBS Xojo Plugin Mailinglist archive)

Back to the thread list
Previous thread: [MBS] GraphicsMagick image array labels not showing in Montage
Next thread: [MBS] [ANN] MonkeyBread Software Releases the MBS Xojo / Real Studio plug-ins in version 16.0


[MBS] Duplicate Classes error   -   Garth Hjelte
  [MBS] Selection rectangle in a canvas   -   Jean-Luc Arnaud
   Re: [MBS] Selection rectangle in a canvas   -   Marnaud
    Re: [MBS] Selection rectangle in a canvas   -   Jean-Luc Arnaud
    Re: [MBS] Selection rectangle in a canvas   -   Jean-Luc Arnaud
   Re: [MBS] Selection rectangle in a canvas   -   Marnaud
   Re: [MBS] Selection rectangle in a canvas   -   Marnaud

[MBS] Selection rectangle in a canvas
Date: 29.01.16 16:18 (Fri, 29 Jan 2016 16:18:29 +0100)
From: Jean-Luc Arnaud
Hi all,

I would like to manage a selection rectangle in a canvas, with handles
to modify its width and height, and the possibility to move it around
the canvas.
I know how to draw such a rectangle, but I don't know how to create
active handles (I mean something reacting when the cursor moves in) or
active borders, nor how to code the resizing of the selection rectangle.

I'm sure there is something in the MBS plugin, but I don't know what
looking for: selection rectangle? Highlighted rectangle? Highlighted
selection?

TIA for any help.

Re: [MBS] Selection rectangle in a canvas
Date: 30.01.16 14:19 (Sat, 30 Jan 2016 14:19:12 +0100)
From: Marnaud
> In you canvas (where everything will be done, unless stated), add these properties: Selection() as integer, ClickedCorner As Integer=-1
> When Selection is an empty array, it means there's no selection; else, we expect it to have a size of 7 (0-7), with x and y for each bound.
> ClickedCorner is meant to know what the user has clicked.
>
> First part, the selection:
> In the MouseDown event:
> Selection ray(x,y,x,y,x,y,x,y) //All bounds default to the origin
> Return True
>
> In the MouseDrag:
> Selection(2)=x 'New x for the right-top corner
> Selection(5)=y 'New y for the left-bottom corner
> Selection(6)=x 'New x for the right-bottom corner
> Selection(7)=y 'New y for the right-bottom corner
> me.refresh false
>
> In the paint event, near the end:
> if UBound(Selection)>pthen
> g.ForeColor=HighlightColor
> g.DrawRect Selection(0),Selection(1),Selection(2)-Selection(0),Selection(3),Selection(4),Selection(5)-Selection(1),Selection(6)-Selection(0),Selection(7)-Selection(1)
> end if
>
> Now, add a method like this:
> Function GetCornerForXAndY(x as integer,y as integer)
> if UBound(selection)<7 then return -1 //No corner exists
>
> if abs(x-selection(0))<5 then 'We're at the left line
> if abs(y-selection(1))<5 then Return 0 //Left-Top
> if abs(y-selection(7)<5 then Return 2 //Left-Bottom
> elseif abs(x-selection(2)<5 then 'We're at the right line
> if abs(y-selection(1))<5 then Return 1 //Right-Top
> if abs(y-selection(7)<5 then Return 3 //Right-Bottom
> end if

if x<selection(0) or y<selection(1) or x>selection(6) or y>selection(7) then return -1 //the user clicked outside of the rectangle; we may start a new one
return 4 //User clicked inside the rectangle; we'll move it
End Function

Add another method:
Function GetXAndYForCorner(CornerID as integer) as Pair
if UBound(Selection)<7 then return nil
select case CornerID
case 0
return new Pair(selection(0),selection(1))
case 1
return new Pair(selection(2),selection(3))
case 2
return new Pair(selection(4),selection(5))
case 3
return new Pair(selection(6),selection(7))
end select
end function

Add two properties to the canvas: DeltaX as integer, DeltaY as integer. Those will be used for the distance between the mouse and (either) the centre of a handle or the left-top corner for a move.
Modify the MouseDown event like this (since we're at the next step):

ClickedCorner=GetCornerForXAndY(x,y)
select case ClickedCorner
case -1 //Start new selection
Selection ray(x,y,x,y,x,y,x,y) //All bounds default to the origin
Return True
case 4 //Move
DeltaX=x-Selection(0)
DeltaY=y-Selection(1)
Return True
else 'A handler
dim p as pair

p=GetXAndYForCorner(ClickedCorner)
if p<>nil then
DeltaX=x-p.left
DeltaY=y-p.right
return true
end if
end select

Add another method:
Sub MoveSelection(Corner as integer,HValue as integer,VValue as integer)
dim i as integer

select case Corner
case 4 //Move
for ito UBound(selection)
if i mod 2then
selection(i)=selection(i)+HValue
else
selection(i)=selection(i)+VValue
end if
next
else
selection(corner*2)=selection(corner*2)+HValue
selection(corner*2+1)=selection(corner*2+1)+VValue
end select
end sub

Modify the MouseDrag:
select case ClickedCorner
case -1 //Start new selection
Selection(2)=x 'New x for the right-top corner
Selection(5)=y 'New y for the left-bottom corner
Selection(6)=x 'New x for the right-bottom corner
Selection(7)=y 'New y for the right-bottom corner
case 4 //Move
MoveSelection(ClickedCorner,selection(0),(x-selection(0))-DeltaX,(y-selection(1))-DeltaY)
else 'A handler
dim p as pair

p=GetXAndYForCorner(ClickedCorner)
if p<>nil then
MoveSelection(ClickedCorner,(x-p.left)-DeltaX,(y-p.right)-DeltaY
end if
end select
me.refresh false

Again, it's not a tested code, just a hint.
_______________________________________________
Mbsplugins_monkeybreadsoftware.info mailing list
<email address removed>
https://ml01.ispgateway.de/mailman/listinfo/mbsplugins_monkeybreadsoftware.info

Re: [MBS] Selection rectangle in a canvas
Date: 01.02.16 09:53 (Mon, 1 Feb 2016 09:53:39 +0100)
From: Jean-Luc Arnaud
Wouhh, that seems very impressive!! I will try your code ASAP.

Many thanks, Arnaud.
I will let you know if it works and will publish modifications (if any)
for members interested in.

Jean-Luc Arnaud

Le 30/01/2016 14:19, Marnaud a écrit :
>> In you canvas (where everything will be done, unless stated), add these properties: Selection() as integer, ClickedCorner As Integer=-1
>> When Selection is an empty array, it means there's no selection; else, we expect it to have a size of 7 (0-7), with x and y for each bound.
>> ClickedCorner is meant to know what the user has clicked.
>>
>> First part, the selection:
>> In the MouseDown event:
>> Selection=Array(x,y,x,y,x,y,x,y) //All bounds default to the origin
>> Return True
>>
>> In the MouseDrag:
>> Selection(2)=x 'New x for the right-top corner
>> Selection(5)=y 'New y for the left-bottom corner
>> Selection(6)=x 'New x for the right-bottom corner
>> Selection(7)=y 'New y for the right-bottom corner
>> me.refresh false
>>
>> In the paint event, near the end:
>> if UBound(Selection)>=7 then
>> g.ForeColor=HighlightColor
>> g.DrawRect Selection(0),Selection(1),Selection(2)-Selection(0),Selection(3),Selection(4),Selection(5)-Selection(1),Selection(6)-Selection(0),Selection(7)-Selection(1)
>> end if
>>
>> Now, add a method like this:
>> Function GetCornerForXAndY(x as integer,y as integer)
>> if UBound(selection)<7 then return -1 //No corner exists
>>
>> if abs(x-selection(0))<5 then 'We're at the left line
>> if abs(y-selection(1))<5 then Return 0 //Left-Top
>> if abs(y-selection(7)<5 then Return 2 //Left-Bottom
>> elseif abs(x-selection(2)<5 then 'We're at the right line
>> if abs(y-selection(1))<5 then Return 1 //Right-Top
>> if abs(y-selection(7)<5 then Return 3 //Right-Bottom
>> end if
> if x<selection(0) or y<selection(1) or x>selection(6) or y>selection(7) then return -1 //the user clicked outside of the rectangle; we may start a new one
> return 4 //User clicked inside the rectangle; we'll move it
> End Function
>
> Add another method:
> Function GetXAndYForCorner(CornerID as integer) as Pair
> if UBound(Selection)<7 then return nil
> select case CornerID
> case 0
> return new Pair(selection(0),selection(1))
> case 1
> return new Pair(selection(2),selection(3))
> case 2
> return new Pair(selection(4),selection(5))
> case 3
> return new Pair(selection(6),selection(7))
> end select
> end function
>
> Add two properties to the canvas: DeltaX as integer, DeltaY as integer. Those will be used for the distance between the mouse and (either) the centre of a handle or the left-top corner for a move.
> Modify the MouseDown event like this (since we're at the next step):
>
> ClickedCorner=GetCornerForXAndY(x,y)
> select case ClickedCorner
> case -1 //Start new selection
> Selection=Array(x,y,x,y,x,y,x,y) //All bounds default to the origin
> Return True
> case 4 //Move
> DeltaX=x-Selection(0)
> DeltaY=y-Selection(1)
> Return True
> else 'A handler
> dim p as pair
>
> p=GetXAndYForCorner(ClickedCorner)
> if p<>nil then
> DeltaX=x-p.left
> DeltaY=y-p.right
> return true
> end if
> end select
>
> Add another method:
> Sub MoveSelection(Corner as integer,HValue as integer,VValue as integer)
> dim i as integer
>
> select case Corner
> case 4 //Move
> for i=0 to UBound(selection)
> if i mod 2=0 then
> selection(i)=selection(i)+HValue
> else
> selection(i)=selection(i)+VValue
> end if
> next
> else
> selection(corner*2)=selection(corner*2)+HValue
> selection(corner*2+1)=selection(corner*2+1)+VValue
> end select
> end sub
>
> Modify the MouseDrag:
> select case ClickedCorner
> case -1 //Start new selection
> Selection(2)=x 'New x for the right-top corner
> Selection(5)=y 'New y for the left-bottom corner
> Selection(6)=x 'New x for the right-bottom corner
> Selection(7)=y 'New y for the right-bottom corner
> case 4 //Move
> MoveSelection(ClickedCorner,selection(0),(x-selection(0))-DeltaX,(y-selection(1))-DeltaY)
> else 'A handler
> dim p as pair
>
> p=GetXAndYForCorner(ClickedCorner)
> if p<>nil then
> MoveSelection(ClickedCorner,(x-p.left)-DeltaX,(y-p.right)-DeltaY
> end if
> end select
> me.refresh false
>
> Again, it's not a tested code, just a hint.
> _______________________________________________
> Mbsplugins_monkeybreadsoftware.info mailing list
> <email address removed>
> https://ml01.ispgateway.de/mailman/listinfo/mbsplugins_monkeybreadsoftware.info
>

_______________________________________________
Mbsplugins_monkeybreadsoftware.info mailing list
<email address removed>
https://ml01.ispgateway.de/mailman/listinfo/mbsplugins_monkeybreadsoftware.info

Re: [MBS] Selection rectangle in a canvas
Date: 01.02.16 16:03 (Mon, 1 Feb 2016 16:03:41 +0100)
From: Jean-Luc Arnaud
Arnaud,

Except some minor corrections (missing parenthesis) I had to do, your
code works fine: congratulation!
The main mistake was in the Paint event, where you should replace:

g.DrawRect Selection(0),Selection(1),Selection(2)-Selection(0),Selection(3),Selection(4),Selection(5)-Selection(1),Selection(6)-Selection(0),Selection(7)-Selection(1)

With:

g.DrawRect
Selection(0),Selection(1),Selection(2)-Selection(0),Selection(5)-Selection(1)

Your Selection array is actually a great idea. I will now adapt my own
code (already working) for resizing the selection rectangle.

Thanks again.

Jean-Luc Arnaud

Le 30/01/2016 14:19, Marnaud a écrit :
>> In you canvas (where everything will be done, unless stated), add these properties: Selection() as integer, ClickedCorner As Integer=-1
>> When Selection is an empty array, it means there's no selection; else, we expect it to have a size of 7 (0-7), with x and y for each bound.
>> ClickedCorner is meant to know what the user has clicked.
>>
>> First part, the selection:
>> In the MouseDown event:
>> Selection=Array(x,y,x,y,x,y,x,y) //All bounds default to the origin
>> Return True
>>
>> In the MouseDrag:
>> Selection(2)=x 'New x for the right-top corner
>> Selection(5)=y 'New y for the left-bottom corner
>> Selection(6)=x 'New x for the right-bottom corner
>> Selection(7)=y 'New y for the right-bottom corner
>> me.refresh false
>>
>> In the paint event, near the end:
>> if UBound(Selection)>=7 then
>> g.ForeColor=HighlightColor
>> g.DrawRect Selection(0),Selection(1),Selection(2)-Selection(0),Selection(3),Selection(4),Selection(5)-Selection(1),Selection(6)-Selection(0),Selection(7)-Selection(1)
>> end if
>>
>> Now, add a method like this:
>> Function GetCornerForXAndY(x as integer,y as integer)
>> if UBound(selection)<7 then return -1 //No corner exists
>>
>> if abs(x-selection(0))<5 then 'We're at the left line
>> if abs(y-selection(1))<5 then Return 0 //Left-Top
>> if abs(y-selection(7)<5 then Return 2 //Left-Bottom
>> elseif abs(x-selection(2)<5 then 'We're at the right line
>> if abs(y-selection(1))<5 then Return 1 //Right-Top
>> if abs(y-selection(7)<5 then Return 3 //Right-Bottom
>> end if
> if x<selection(0) or y<selection(1) or x>selection(6) or y>selection(7) then return -1 //the user clicked outside of the rectangle; we may start a new one
> return 4 //User clicked inside the rectangle; we'll move it
> End Function
>
> Add another method:
> Function GetXAndYForCorner(CornerID as integer) as Pair
> if UBound(Selection)<7 then return nil
> select case CornerID
> case 0
> return new Pair(selection(0),selection(1))
> case 1
> return new Pair(selection(2),selection(3))
> case 2
> return new Pair(selection(4),selection(5))
> case 3
> return new Pair(selection(6),selection(7))
> end select
> end function
>
> Add two properties to the canvas: DeltaX as integer, DeltaY as integer. Those will be used for the distance between the mouse and (either) the centre of a handle or the left-top corner for a move.
> Modify the MouseDown event like this (since we're at the next step):
>
> ClickedCorner=GetCornerForXAndY(x,y)
> select case ClickedCorner
> case -1 //Start new selection
> Selection=Array(x,y,x,y,x,y,x,y) //All bounds default to the origin
> Return True
> case 4 //Move
> DeltaX=x-Selection(0)
> DeltaY=y-Selection(1)
> Return True
> else 'A handler
> dim p as pair
>
> p=GetXAndYForCorner(ClickedCorner)
> if p<>nil then
> DeltaX=x-p.left
> DeltaY=y-p.right
> return true
> end if
> end select
>
> Add another method:
> Sub MoveSelection(Corner as integer,HValue as integer,VValue as integer)
> dim i as integer
>
> select case Corner
> case 4 //Move
> for i=0 to UBound(selection)
> if i mod 2=0 then
> selection(i)=selection(i)+HValue
> else
> selection(i)=selection(i)+VValue
> end if
> next
> else
> selection(corner*2)=selection(corner*2)+HValue
> selection(corner*2+1)=selection(corner*2+1)+VValue
> end select
> end sub
>
> Modify the MouseDrag:
> select case ClickedCorner
> case -1 //Start new selection
> Selection(2)=x 'New x for the right-top corner
> Selection(5)=y 'New y for the left-bottom corner
> Selection(6)=x 'New x for the right-bottom corner
> Selection(7)=y 'New y for the right-bottom corner
> case 4 //Move
> MoveSelection(ClickedCorner,selection(0),(x-selection(0))-DeltaX,(y-selection(1))-DeltaY)
> else 'A handler
> dim p as pair
>
> p=GetXAndYForCorner(ClickedCorner)
> if p<>nil then
> MoveSelection(ClickedCorner,(x-p.left)-DeltaX,(y-p.right)-DeltaY
> end if
> end select
> me.refresh false
>
> Again, it's not a tested code, just a hint.
> _______________________________________________
> Mbsplugins_monkeybreadsoftware.info mailing list
> <email address removed>
> https://ml01.ispgateway.de/mailman/listinfo/mbsplugins_monkeybreadsoftware.info
>

_______________________________________________
Mbsplugins_monkeybreadsoftware.info mailing list
<email address removed>
https://ml01.ispgateway.de/mailman/listinfo/mbsplugins_monkeybreadsoftware.info

Re: [MBS] Selection rectangle in a canvas
Date: 30.01.16 13:40 (Sat, 30 Jan 2016 13:40:58 +0100)
From: Marnaud
Le 29 janv. 2016 à 16:18, Jean-Luc Arnaud <<email address removed>> a écrit:

> Hi all,
>
> I would like to manage a selection rectangle in a canvas, with handles
> to modify its width and height, and the possibility to move it around
> the canvas.
> I know how to draw such a rectangle, but I don't know how to create
> active handles (I mean something reacting when the cursor moves in) or
> active borders, nor how to code the resizing of the selection rectangle.
>
> I'm sure there is something in the MBS plugin, but I don't know what
> looking for: selection rectangle? Highlighted rectangle? Highlighted
> selection?

Hello Jean-Luc,

Making your own is really simple. I'm going to give you some tracks. I recommend making a distinct class (based on canvas) so the properties won't end up in the window itself.

I've written this from hand, I hope I've not made a mistake.
In you canvas (where everything will be done, unless stated), add these properties: Selection() as integer, ClickedCorner As Integer=-1
When Selection is an empty array, it means there's no selection; else, we expect it to have a size of 7 (0-7), with x and y for each bound.
ClickedCorner is meant to know what the user has clicked.

First part, the selection:
In the MouseDown event:
Selection=Array(x,y,x,y,x,y,x,y) //All bounds default to the origin
Return True

In the MouseDrag:
Selection(2)=x 'New x for the right-top corner
Selection(5)=y 'New y for the left-bottom corner
Selection(6)=x 'New x for the right-bottom corner
Selection(7)=y 'New y for the right-bottom corner
me.refresh false

In the paint event, near the end:
if UBound(Selection)>=7 then
g.ForeColor=HighlightColor
g.DrawRect Selection(0),Selection(1),Selection(2)-Selection(0),Selection(3),Selection(4),Selection(5)-Selection(1),Selection(6)-Selection(0),Selection(7)-Selection(1)
end if

Now, add a method like this:
Function GetCornerForXAndY(x as integer,y as integer)
if UBound(selection)<7 then return -1 //No corner exists

if abs(x-selection(0))<5 then 'We're at the left line
if abs(y-selection(1))<5 then Return 0 //Left-Top
if abs(y-selection(7)<5 then Return 2 //Left-Bottom
elseif abs(x-selection(2)<5 then 'We're at the right line
if abs(y-selection(1))<5 then Return 1 //Right-Top
if abs(y-selection(7)<5 then Return 3 //Right-Bottom
end if

(I'll post the remaining later, as I have to go; sorry)
_______________________________________________
Mbsplugins_monkeybreadsoftware.info mailing list
<email address removed>
https://ml01.ispgateway.de/mailman/listinfo/mbsplugins_monkeybreadsoftware.info

Re: [MBS] Selection rectangle in a canvas
Date: 01.02.16 20:32 (Mon, 01 Feb 2016 20:32:46 +0100)
From: Marnaud
Le 1 févr. 2016 à 16:03, Jean-Luc Arnaud <<email address removed>> a écrit:

> Arnaud,
>
> Except some minor corrections (missing parenthesis) I had to do, your
> code works fine: congratulation!
> The main mistake was in the Paint event, where you should replace:
>
> g.DrawRect Selection(0),Selection(1),Selection(2)-Selection(0),Selection(3),Selection(4),Selection(5)-Selection(1),Selection(6)-Selection(0),Selection(7)-Selection(1)
>
> With:
>
> g.DrawRect
> Selection(0),Selection(1),Selection(2)-Selection(0),Selection(5)-Selection(1)
>
> Your Selection array is actually a great idea. I will now adapt my own
> code (already working) for resizing the selection rectangle.

Hello Jean-Luc,
I'm glad this suits your needs; I had the need for it to try to make a drawing application in the past (well, it'll probably never be finished, as it's too complex).

Thank you for having reported my mistake; I'm yet unable to understand why I've put so many parameters while I knew it takes only 4…
_______________________________________________
Mbsplugins_monkeybreadsoftware.info mailing list
<email address removed>
https://ml01.ispgateway.de/mailman/listinfo/mbsplugins_monkeybreadsoftware.info