Recent

Author Topic: Drawing selectable connections  (Read 8539 times)

Nitorami

  • Sr. Member
  • ****
  • Posts: 481
Drawing selectable connections
« on: October 07, 2017, 07:19:46 pm »
Hi all

My program requires the user to manually draw connections (polylines of small order, maybe 4..6 points ) between elements (rectangles) on the Form. The connections shall be selectable using the mouse. I expect up to a few hundred lines on the screen, and contemplated these options:

1) Simply draw the lines on Form1. However then I must manually take care of hit detection and restoring overpainted content..

2) Create a paintbox for each line, and draw the line inside this box. I can use the hit detection (MouseOver) of the paintbox, but with many connections in a narrow space, the boxes will be on top of each other and only the top one will be selectable.

3) Create a TWinControl with an arbitrary shape, basically an envelope around the line. I tried this, and in fact the mouseover event respects the shape. But it works only for descendants of TWinControl and not for simple Controls such as tShape or tPaintbox. A WinControl has an own handle, and in the end this might be too much overhead for just a simple connection line and react slow with many lines on the screen.

Anyone having experience with that, or a better proposal ?

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Drawing selectable connections
« Reply #1 on: October 07, 2017, 08:39:15 pm »
I am in the middle of doing something very close to that.

 I have a list of static and dynamic objects that sit on a label surface and a
 designer form for them.
 
   what I am doing is for each object contains a RECT and as I hover over these
objects the mouse X,Y etc is sent to a function that scans these objects which are
stored in a array of a custom record.
  The last object placed on then screen will be the first you test using the
 PtInRect call for example, if it returns false, then go to the next object before that
until you get one hwere the ptIinRect returns true.

 So for each object you place to be shown they are scanned in reverse order for their
locations.
 Please check back for me ;)
The only true wisdom is knowing you know nothing

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Drawing selectable connections
« Reply #2 on: October 07, 2017, 09:41:17 pm »
Hi all

My program requires the user to manually draw connections (polylines of small order, maybe 4..6 points ) between elements (rectangles) on the Form. The connections shall be selectable using the mouse. I expect up to a few hundred lines on the screen, and contemplated these options:

1) Simply draw the lines on Form1. However then I must manually take care of hit detection and restoring overpainted content..

2) Create a paintbox for each line, and draw the line inside this box. I can use the hit detection (MouseOver) of the paintbox, but with many connections in a narrow space, the boxes will be on top of each other and only the top one will be selectable.

3) Create a TWinControl with an arbitrary shape, basically an envelope around the line. I tried this, and in fact the mouseover event respects the shape. But it works only for descendants of TWinControl and not for simple Controls such as tShape or tPaintbox. A WinControl has an own handle, and in the end this might be too much overhead for just a simple connection line and react slow with many lines on the screen.

Anyone having experience with that, or a better proposal ?
try this control https://sourceforge.net/projects/evssimplegraph/ it has a learning curve but it does everything you described.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Nitorami

  • Sr. Member
  • ****
  • Posts: 481
Re: Drawing selectable connections
« Reply #3 on: October 08, 2017, 12:00:09 pm »
Thank you.

Taazz,
I am hestitant to launch an "import.exe".  Do you know it's safe ?
I downloaded the delphi source code first as a tutorial because I'd like to know a bit more how this all works, but it is a lot more complex than I expected.

Jamie,
I had hoped I can avoid hit detection by using LCL components but it looks like I'll either have to dig into it or use a third party component as taazz proposed.

Not sure. I am rather unexperienced with the workings of the LCL. On one hand, I should get a better understanding of all that by making own code, but there is a risk of getting lost in low level issues and never finishing the application. On the other hand, using a third party component may be comfortable but when problems should arise at a later stage, I may not be able to fix them because of lack of understanding.

Guess I will tinker along for a while and see where it takes me.


fred

  • Full Member
  • ***
  • Posts: 201
Re: Drawing selectable connections
« Reply #4 on: October 08, 2017, 12:17:20 pm »
Could this be something?

TECScheme
An advanced component for configuration of general scheme.
http://wiki.freepascal.org/Eye-Candy_Controls#TECScheme

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Drawing selectable connections
« Reply #5 on: October 08, 2017, 07:17:54 pm »
Thank you.

Taazz,
I am hestitant to launch an "import.exe".  Do you know it's safe ?
I downloaded the delphi source code first as a tutorial because I'd like to know a bit more how this all works, but it is a lot more complex than I expected.
erm import has nothing to do with the control. You want the file https://sourceforge.net/projects/evssimplegraph/files/Release/SimpleGraph.0.1.0.0.rar/download or better download the repository from https://sourceforge.net/p/evssimplegraph/code/ci/master/tree/ .

Once installed you can use the provided demo to see how it works.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Edson

  • Hero Member
  • *****
  • Posts: 1301
Re: Drawing selectable connections
« Reply #6 on: October 09, 2017, 05:59:25 am »
I'm doing something similar, but I have a library to start: https://github.com/t-edson/ogEditGraf
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

Nitorami

  • Sr. Member
  • ****
  • Posts: 481
Re: Drawing selectable connections
« Reply #7 on: October 09, 2017, 07:49:49 pm »
Alright, that is a lot to look into. Thanks to all. Guess I'll come back with new problems soon.

Edit- did I say "soon" ? I had a look into the evssimplegraph code today, and restructured bits of my own code accordingly... for instance, the event logic. Puzzled why simplegraph does not seem to use the usual handlers such as OnMouseMove etc., I found that it simply overrides the MouseMove() procedure. Clever. I begin to understand how this works.
But I stumbled across this: When dragging an element (Paintbox) on its parent (Scrollbox) - the drag is logically initiated by the element's mouse down. Ok. But then, when I move the mouse, the event (mouse move or dragover, doesn't matter) goes either to the element or to the parent; thus, if I implement the drag routine in the element, it only works within the bounds of the element; if I implement it in the parent, it only works when the mouse has left the element... my workaround currently is to set enabled to false for all elements during dragging, but I wonder whether this is state of the art.

« Last Edit: October 09, 2017, 08:04:16 pm by Nitorami »

zamtmn

  • Hero Member
  • *****
  • Posts: 594
Re: Drawing selectable connections
« Reply #8 on: October 09, 2017, 07:59:38 pm »
And another program where you can draw https://sourceforge.net/projects/zcad/

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Drawing selectable connections
« Reply #9 on: October 09, 2017, 09:36:35 pm »
But I stumbled across this: When dragging an element (Paintbox) on its parent (Scrollbox) - the drag is logically initiated by the element's mouse down. Ok. But then, when I move the mouse, the event (mouse move or dragover, doesn't matter) goes either to the element or to the parent; thus, if I implement the drag routine in the element, it only works within the bounds of the element; if I implement it in the parent, it only works when the mouse has left the element... my workaround currently is to set enabled to false for all elements during dragging, but I wonder whether this is state of the art.
On the event Mousebuttondown set the control's mousecapture property to true and to false on the event onmousebuttonup, this should force all mouse messages to be handled by the control during the drag operation.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Nitorami

  • Sr. Member
  • ****
  • Posts: 481
Re: Drawing selectable connections
« Reply #10 on: October 09, 2017, 10:27:43 pm »
Mmhm, sounds interesting, but does not work.

Odd:
MouseCapture is a protected property of TControl.
My own Control is TGraphContainer = Class (TScrollBox).

TScrollBox (Mycontrol).MouseCapture does not compile ("idents no member")
TControl  (Mycontrol).MouseCapture neither
TWinControl (Mycontrol).MouseCapture neither

TGraphContainer(mycontrol).MouseCapture compiles but does not work
 ???

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Drawing selectable connections
« Reply #11 on: October 09, 2017, 10:46:44 pm »
I have no idea if you are on windows try to use the SetCapture Windows API directly or the clipcursor api, or Mouse.Capture := Self;
« Last Edit: October 09, 2017, 10:54:20 pm by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Nitorami

  • Sr. Member
  • ****
  • Posts: 481
Re: Drawing selectable connections
« Reply #12 on: October 10, 2017, 05:38:37 pm »
I am on windows but don't want to fuff around with the API.
Mouse.capture expects a HRGN which I don't know where to get from.

Capturing the mouse may not be the ultimate solution anyway, as I want to have other controls react on it, e.g. to show a snap symbol when the cursor approaches it. I found that my problem can be solved by hooking all child controls into the OnDragDrop event. Had overlooked this obvious solution. If sender is not the main control, just convert the mouse coordinates into coordinates of the main control by a method like ClientToParent and job done.

I fear this may get a bit twisted later on, and indeed the easiest way may be to disable child controls altogether and leave the mouse handling to the main control entirely. This requires extra hit detection but as far as I can see, this is what simplegraph does, and what Jamie proposed.

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Drawing selectable connections
« Reply #13 on: October 25, 2017, 07:00:59 pm »
TRect has most of all members that are supported in the API for doing GUI target setting and tracking..

So you don't need to use the windows unit if you chose not to..

 Look at the define for the TRect and you'll see most it not all you need to create a Mouse targeting
object detector and overlay calculator.

 I normally use a windows unit but I found recently the TRECT has been enhanced and this is good because it'll
work cross platform with no code change.
The only true wisdom is knowing you know nothing

Nitorami

  • Sr. Member
  • ****
  • Posts: 481
Re: Drawing selectable connections
« Reply #14 on: October 29, 2017, 09:50:34 am »
Yes, a TRect will do part of the job, but my concern is less the geometry but the overall handling, as I am not yet used to event handlers and messages going back and forth. But I'm getting there.
In the meantime I experimented with TreeLists instead, which seemed to be suitable for the kind of task I have in mind, but not quite.

Many issues to think about. For instance, when several connections end in the same point, it will not be possible to select a specific one. My first idea was to create an envelope around the lines for mouse targeting; for polylines composed of vertical and horizontal lines only this could be achieved simply by a list of rectangles enveloping the line. However for curved lines ... %)
What I'll try now instead is three hot spots for each line, both end points and one in the middle. That should give me some freedom to design lines in whichever shape I choose, and (I hope) the lines will remain individually selectable even when densely packed.

 

TinyPortal © 2005-2018