[Solved] Change a line to a connector programmatically
-
- Posts: 7
- Joined: Wed Jan 22, 2014 3:16 am
[Solved] Change a line to a connector programmatically
Hello All,
I have many drawings that I need to change lines into connectors. Is it possible to convert a Line to a Connector either programmatically or through the user interface?
I am running OpenOffice 4.0 on a Windows 7 machine.
Thank you for your help.
I have many drawings that I need to change lines into connectors. Is it possible to convert a Line to a Connector either programmatically or through the user interface?
I am running OpenOffice 4.0 on a Windows 7 machine.
Thank you for your help.
Last edited by Hagar Delest on Sat Feb 01, 2014 12:58 am, edited 1 time in total.
Reason: tagged [Solved].
Reason: tagged [Solved].
OpenOffice 4.1 on Windows 7
- Charlie Young
- Volunteer
- Posts: 1559
- Joined: Fri May 14, 2010 1:07 am
Re: Change a line to a connector programmatically
I think you need to post an example document showing what kind of arrangement of shapes and lines you have.
I don't think it is possible to change a line to a connector, but it is possible to create a new connector via a program. But of course then one needs to know what to connect it to. I'm thinking if you have lines drawn, it might be possible to determine the nearest gluepoint of a shape, but I need a clearer picture of what I'm up against.
I don't think it is possible to change a line to a connector, but it is possible to create a new connector via a program. But of course then one needs to know what to connect it to. I'm thinking if you have lines drawn, it might be possible to determine the nearest gluepoint of a shape, but I need a clearer picture of what I'm up against.
Apache OpenOffice 4.1.1
Windows XP
Windows XP
-
- Posts: 7
- Joined: Wed Jan 22, 2014 3:16 am
Re: Change a line to a connector programmatically
Hello Charlie,
I was thinking about it today and came to a similar conclusion. I was thinking that I could select the line to convert a connector and then run a macro that would use its attributes to make a new connector. Using the nearest available glue point would make sense.
I've attached an example. I want to change some of the lines that show the process flow to connectors to make it easier to rearrange the pieces without having to redraw the lines. This is a very simple example and many of my drawings are process flow diagrams used in chemical plants that can have thousands of elements.
I am very familiar with VBA but am just starting on OpenOffice. I am just so tired of having legacy problems with MS using proprietary file encodings
that I have to convert to something far more stable. The plants can go for 50 years and this is the 4th time we've changed file formats in 10 years. I am not doing it again lol/
I sincerely appreciate the help.
Regards,
Bruce
I was thinking about it today and came to a similar conclusion. I was thinking that I could select the line to convert a connector and then run a macro that would use its attributes to make a new connector. Using the nearest available glue point would make sense.
I've attached an example. I want to change some of the lines that show the process flow to connectors to make it easier to rearrange the pieces without having to redraw the lines. This is a very simple example and many of my drawings are process flow diagrams used in chemical plants that can have thousands of elements.
I am very familiar with VBA but am just starting on OpenOffice. I am just so tired of having legacy problems with MS using proprietary file encodings

I sincerely appreciate the help.
Regards,
Bruce
- Attachments
-
- Pressure Control diagram.odg
- Example of what I need to do regarding changing lines to connectors.
- (11.08 KiB) Downloaded 254 times
OpenOffice 4.1 on Windows 7
- Charlie Young
- Volunteer
- Posts: 1559
- Joined: Fri May 14, 2010 1:07 am
Re: Change a line to a connector programmatically
it should be helpful that you're a programmer certainly. You'll need to consult the API documentation, particularly the drawing API.
In the first experiments I conducted before I posted here, I restricted myself to plain LineShapes connecting to RectangleShapes. Your attached document seems to mostly involve PolyLineShapes and GroupShapes, so that is what I'm focusing on for now. I suspect it will ultimately prove to be an oversimplification, but we've got to start somewhere.
The pieces we need for starters:
This gets the coordinates of all the GluePoints of a shape. If the GluePoint IsRelative then the coordinates are relative to the page, and no adjustment is needed. If IsRelative is False though, and it seems it always is, then the GluePoint positions are with respect to the shape's center, and we need to adjust to get the page coordinates accordingly.
Then we need a simple function to get the distance between two points
With that, select a PolyLine in the UI, and run this
Like I said, this probably is ultimately a special case, but hopefully it's a start.
In the first experiments I conducted before I posted here, I restricted myself to plain LineShapes connecting to RectangleShapes. Your attached document seems to mostly involve PolyLineShapes and GroupShapes, so that is what I'm focusing on for now. I suspect it will ultimately prove to be an oversimplification, but we've got to start somewhere.
The pieces we need for starters:
This gets the coordinates of all the GluePoints of a shape. If the GluePoint IsRelative then the coordinates are relative to the page, and no adjustment is needed. If IsRelative is False though, and it seems it always is, then the GluePoint positions are with respect to the shape's center, and we need to adjust to get the page coordinates accordingly.
Code: Select all
Function GlueCoords(oShape As Object)
Dim ShapeCenter As New com.sun.star.awt.Point
Dim oGlue
Dim g As Long
Dim oPos As New com.sun.star.awt.Point
Dim oSize As New com.sun.star.awt.Size
Dim GluePointCoords(0) As New com.sun.star.awt.Point
Dim oPoint As New com.sun.star.drawing.GluePoint2
oPos = oShape.getPosition()
oSize = oShape.getSize()
ShapeCenter.X = oPos.X + oSize.Width\2
ShapeCenter.Y = oPos.Y + oSize.Height\2
oGlue = oShape.getGluePoints()
For g = 0 to oGlue.getCount() - 1
oPoint = oGlue.getByIndex(g)
Redim Preserve GluePointCoords(g) As com.sun.star.awt.Point
If oPoint.IsRelative Then
GluePointCoords(g).X = oPoint.Position.X
GluePointCoords(g).Y = oPoint.Position.Y
Else
GluePointCoords(g).X = ShapeCenter.X + oPoint.Position.X
GluePointCoords(g).Y = ShapeCenter.Y + oPoint.Position.Y
End If
Next g
GlueCoords = GluePointCoords
End Function
Code: Select all
Function Distance(a As com.sun.star.awt.Point, b As com.sun.star.awt.Point) As Double
Distance = Sqr((a.X - b.X)^2 + (a.Y - b.Y)^2)
End Function
Code: Select all
Sub PolyLine2Connector
Dim oDoc As Object
Dim oConnector As Object
Dim oShapes(0) As Object, oShape As Object
Dim oDP As Object
Dim oSelection As Object, oLine As Object
Dim i As Long, j As Long, k As Long, n As Long
Dim oCoords, PolyPoints
Dim EndPoints(1) As New com.sun.star.awt.Point
Dim MinDistance(1) As Double, MinShapeIndex(1) As Long, MinGlueIndex(1) As Long
Dim Dist As Double
oDoc = ThisComponent
oSelection = oDoc.getCurrentController().getSelection()
oLine = oSelection.getByIndex(0)
'Make sure selection is a PolyLine
If oLine.getShapeType() <> "com.sun.star.drawing.PolyLineShape" Then
MsgBox("No PolyLine Selected")
Exit Sub
End If
'Get EndPoints of the polyline
PolyPoints = oLine.getPropertyValue("Polygon")
EndPoints(0).X = PolyPoints(0).X
EndPoints(0).Y = PolyPoints(0).Y
EndPoints(1).X = PolyPoints(UBound(PolyPoints)).X
EndPoints(1).Y = PolyPoints(UBound(PolyPoints)).Y
oDP = oDoc.getDrawPages().getByIndex(0)
'Make a connector
oConnector = oDoc.createInstance("com.sun.star.drawing.ConnectorShape")
oConnector.EdgeKind = com.sun.star.drawing.ConnectorType.STANDARD
i = 0
n = 0
'Get all the GroupShapes
Do While i < oDP.getCount()
oShape = oDP.getByIndex(i)
If oShape.supportsService("com.sun.star.drawing.GroupShape") Then
Redim Preserve oShapes(n) As Object
oShapes(n) = oShape
n = n + 1
EndIf
i = i + 1
Loop
'Find closest GluePoint to each EndPoint
For i = 0 To 1
oCoords = GlueCoords(oShapes(0))
MinShapeIndex(i) = 0
MinGlueIndex(i) = 0
MinDistance(i) = Distance(EndPoints(i),oCoords(0))
For j = 0 To n - 1
oCoords = GlueCoords(oShapes(j))
For k = 0 To UBound(oCoords)
Dist = Distance(EndPoints(i),oCoords(k))
If Dist < MinDistance(i) Then
MinDistance(i) = Dist
MinShapeIndex(i) = j
MinGlueIndex(i) = k
End If
Next k
Next j
Next i
'Connect the connector to the closest Gluepoints
oDP.add(oConnector)
oConnector.setPropertyValue("StartShape",oShapes(MinShapeIndex(0)))
oConnector.setPropertyValue("StartGluePointIndex",MinGlueIndex(0))
oConnector.setPropertyValue("EndShape",oShapes(MinShapeIndex(1)))
oConnector.setPropertyValue("EndGluePointIndex",MinGlueIndex(1))
'Remove original line
oDP.remove(oLine)
End Sub
- Attachments
-
- PressureControldiagram_X1.odg
- Version 1
- (14.23 KiB) Downloaded 264 times
Apache OpenOffice 4.1.1
Windows XP
Windows XP
-
- Posts: 7
- Joined: Wed Jan 22, 2014 3:16 am
Re: Change a line to a connector programmatically
Dear Charlie,
Thank you so much! That goes a long way toward my goal!!!!! My next biggest problem is getting my head around the API. I've been spoiled by the VBA .NET IDE that serves the properties up on a silver platter.
Is there something that will help me explore the API or is it just available as a text document?
Thank you again.
Thank you so much! That goes a long way toward my goal!!!!! My next biggest problem is getting my head around the API. I've been spoiled by the VBA .NET IDE that serves the properties up on a silver platter.
Is there something that will help me explore the API or is it just available as a text document?
Thank you again.
OpenOffice 4.1 on Windows 7
- Charlie Young
- Volunteer
- Posts: 1559
- Joined: Fri May 14, 2010 1:07 am
Re: Change a line to a connector programmatically
You will need hanya's MRI and/or Bernard Marcelly's XRay, and yes, you will still need to cross-reference the online API documentation, though note also that there are many examples in the Wiki, in the forums (both these and the old ones), and Andrew Pitonyak's stuff. Andrew, hanya, and Bernard all peek in here from time to time.bowcoastie wrote:Dear Charlie,
Is there something that will help me explore the API or is it just available as a text document?
Apache OpenOffice 4.1.1
Windows XP
Windows XP
-
- Posts: 7
- Joined: Wed Jan 22, 2014 3:16 am
Re: Change a line to a connector programmatically
Hello Charlie,
You are truly a godsend.
Thank you for all your support. I'll work getting this up an running over the next couple of days.
Warmest Regards,
Bruce
You are truly a godsend.

Thank you for all your support. I'll work getting this up an running over the next couple of days.
Warmest Regards,
Bruce
OpenOffice 4.1 on Windows 7
- Charlie Young
- Volunteer
- Posts: 1559
- Joined: Fri May 14, 2010 1:07 am
Re: Change a line to a connector programmatically
You're welcome.
I guess I'll correct a couple of, I think, inconsequential items in my earlier code.
in PolyLine2Connector, there is no need for MinDistance to be an array, just use MinDistance as a scalar wherever MinDistance() appears.
That probably doesn't matter at all, but in GlueCoords, I am needlessly using ReDim for each g, when we know the needed array size in advance
That probalby doesn't matter much either, but i can see where it might improve speed and allocation efficiency if there are many shapes.
Another thing I have been looking at is the business with PolyLines. In Your example that's mostly what we're dealing with, but the line going to the left from the Control Valve is a simple LineShape, and since its left terminus (with the arrow), is on a GroupShape, it is easy to include such a LineShape in the code
As I supposed though, we'll run into difficulties. The line going left from the Pressure Gauge doesn't end at a Gluepoint, it just bumps into a vertical line. So if the macro is run on the line going left, it winds up connected to the wrong thing.
Another glitch was when I ran it on the PolyLine going into the top of the Vacuum Pump, since the PolyLine extended left, it wound up attaching to the left side of the pump instead of the top. I want to mention these things because I imagine you'll run into many such problems.
I also will say, though I'm sure you realize it, that someone very knowledgeable about the engineering better look at these things after the changes.
I guess I'll correct a couple of, I think, inconsequential items in my earlier code.
in PolyLine2Connector, there is no need for MinDistance to be an array, just use MinDistance as a scalar wherever MinDistance() appears.
That probably doesn't matter at all, but in GlueCoords, I am needlessly using ReDim for each g, when we know the needed array size in advance
Code: Select all
Function GlueCoords(oShape As Object)
Dim ShapeCenter As New com.sun.star.awt.Point
Dim oGlue
Dim g As Long
Dim oPos As New com.sun.star.awt.Point
Dim oSize As New com.sun.star.awt.Size
Dim oPoint As New com.sun.star.drawing.GluePoint2
oPos = oShape.getPosition()
oSize = oShape.getSize()
ShapeCenter.X = oPos.X + oSize.Width\2
ShapeCenter.Y = oPos.Y + oSize.Height\2
oGlue = oShape.getGluePoints()
Dim GluePointCoords(oGlue.getCount() - 1) As New com.sun.star.awt.Point
For g = 0 to oGlue.getCount() - 1
oPoint = oGlue.getByIndex(g)
If oPoint.IsRelative Then
GluePointCoords(g).X = oPoint.Position.X
GluePointCoords(g).Y = oPoint.Position.Y
Else
GluePointCoords(g).X = ShapeCenter.X + oPoint.Position.X
GluePointCoords(g).Y = ShapeCenter.Y + oPoint.Position.Y
End If
Next g
GlueCoords = GluePointCoords
End Function
That probalby doesn't matter much either, but i can see where it might improve speed and allocation efficiency if there are many shapes.
Another thing I have been looking at is the business with PolyLines. In Your example that's mostly what we're dealing with, but the line going to the left from the Control Valve is a simple LineShape, and since its left terminus (with the arrow), is on a GroupShape, it is easy to include such a LineShape in the code
Code: Select all
Sub Line2Connector
Dim oDoc As Object
Dim oConnector As Object
Dim oShapes(0) As Object, oShape As Object
Dim oDP As Object
Dim oSelection As Object, oLine As Object
Dim i As Long, j As Long, k As Long, n As Long
Dim oCoords, PolyPoints
Dim EndPoints(1) As New com.sun.star.awt.Point
Dim MinDistance As Double, MinShapeIndex(1) As Long, MinGlueIndex(1) As Long
Dim Dist As Double
oDoc = ThisComponent
oSelection = oDoc.getCurrentController().getSelection()
oLine = oSelection.getByIndex(0)
'Make sure selection is a PolyLine or a line.
If oLine.getShapeType() <> "com.sun.star.drawing.PolyLineShape" And oLine.getShapeType() <> "com.sun.star.drawing.LineShape" Then
MsgBox("No Line Selected")
Exit Sub
End If
'Get EndPoints of the polyline
PolyPoints = oLine.getPropertyValue("Polygon")
EndPoints(0).X = PolyPoints(0).X
EndPoints(0).Y = PolyPoints(0).Y
EndPoints(1).X = PolyPoints(UBound(PolyPoints)).X
EndPoints(1).Y = PolyPoints(UBound(PolyPoints)).Y
oDP = oDoc.getDrawPages().getByIndex(0)
'Make a connector
oConnector = oDoc.createInstance("com.sun.star.drawing.ConnectorShape")
oConnector.EdgeKind = com.sun.star.drawing.ConnectorType.STANDARD
i = 0
n = 0
'Get all the GroupShapes
Do While i < oDP.getCount()
oShape = oDP.getByIndex(i)
If oShape.supportsService("com.sun.star.drawing.GroupShape") Then
Redim Preserve oShapes(n) As Object
oShapes(n) = oShape
n = n + 1
EndIf
i = i + 1
Loop
'Find closest GluePoint to each EndPoint
For i = 0 To 1
oCoords = GlueCoords(oShapes(0))
MinShapeIndex(i) = 0
MinGlueIndex(i) = 0
MinDistance = Distance(EndPoints(i),oCoords(0))
For j = 0 To n - 1
oCoords = GlueCoords(oShapes(j))
For k = 0 To UBound(oCoords)
Dist = Distance(EndPoints(i),oCoords(k))
If Dist < MinDistance Then
MinDistance = Dist
MinShapeIndex(i) = j
MinGlueIndex(i) = k
End If
Next k
Next j
Next i
'Connect the connector to the closest Gluepoints
oDP.add(oConnector)
oConnector.setPropertyValue("StartShape",oShapes(MinShapeIndex(0)))
oConnector.setPropertyValue("StartGluePointIndex",MinGlueIndex(0))
oConnector.setPropertyValue("EndShape",oShapes(MinShapeIndex(1)))
oConnector.setPropertyValue("EndGluePointIndex",MinGlueIndex(1))
'Remove original line
oDP.remove(oLine)
End Sub
Another glitch was when I ran it on the PolyLine going into the top of the Vacuum Pump, since the PolyLine extended left, it wound up attaching to the left side of the pump instead of the top. I want to mention these things because I imagine you'll run into many such problems.
I also will say, though I'm sure you realize it, that someone very knowledgeable about the engineering better look at these things after the changes.
Apache OpenOffice 4.1.1
Windows XP
Windows XP
-
- Posts: 7
- Joined: Wed Jan 22, 2014 3:16 am
Re: Change a line to a connector programmatically
Hello Charlie,
As far as the minor imperfections in getting the glue points right, it's not a real issue as I will have to manually connect them if they are out. I got the code running and added a button to the tool bar; it works really well!!!! Now I just need to add it to the right click menu and I'll be going even faster!!! I can't thank you enough for your help and professionalism.
This is the first time I have ever reached out for help on a programming matter (I was just too far out of my element); I am shocked to say the least! I am really grateful.
Thank you again. If you get to the New Orleans area, let me know and we can do lunch.
Regards,
Bruce
As far as the minor imperfections in getting the glue points right, it's not a real issue as I will have to manually connect them if they are out. I got the code running and added a button to the tool bar; it works really well!!!! Now I just need to add it to the right click menu and I'll be going even faster!!! I can't thank you enough for your help and professionalism.
This is the first time I have ever reached out for help on a programming matter (I was just too far out of my element); I am shocked to say the least! I am really grateful.
Thank you again. If you get to the New Orleans area, let me know and we can do lunch.
Regards,
Bruce
OpenOffice 4.1 on Windows 7