Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
jfV5lcyq
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
管理员
jfV5lcyq
Commits
0bd100dc
Commit
0bd100dc
authored
Jun 12, 2018
by
罗绍泽
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
实例监听
parent
577c0ea4
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1347 additions
and
0 deletions
+1347
-0
AssignmentTaskListener.java
...s/com/gaowj/activiti/listener/AssignmentTaskListener.java
+18
-0
DefaultProcessDiagramCanvas.java
.../org/activiti/image/impl/DefaultProcessDiagramCanvas.java
+1329
-0
No files found.
src_process/com/gaowj/activiti/listener/AssignmentTaskListener.java
0 → 100644
View file @
0bd100dc
package
com
.
gaowj
.
activiti
.
listener
;
import
org.activiti.engine.delegate.DelegateTask
;
import
org.activiti.engine.delegate.TaskListener
;
public
class
AssignmentTaskListener
implements
TaskListener
{
/**
*
*/
private
static
final
long
serialVersionUID
=
1L
;
@Override
public
void
notify
(
DelegateTask
task
)
{
task
.
setAssignee
(
"xiaohong"
);
}
}
src_process/org/activiti/image/impl/DefaultProcessDiagramCanvas.java
0 → 100644
View file @
0bd100dc
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
activiti
.
image
.
impl
;
import
java.awt.BasicStroke
;
import
java.awt.Color
;
import
java.awt.Font
;
import
java.awt.FontMetrics
;
import
java.awt.Graphics2D
;
import
java.awt.Paint
;
import
java.awt.Point
;
import
java.awt.Polygon
;
import
java.awt.Rectangle
;
import
java.awt.RenderingHints
;
import
java.awt.Shape
;
import
java.awt.Stroke
;
import
java.awt.font.FontRenderContext
;
import
java.awt.font.LineBreakMeasurer
;
import
java.awt.font.TextAttribute
;
import
java.awt.font.TextLayout
;
import
java.awt.geom.AffineTransform
;
import
java.awt.geom.Ellipse2D
;
import
java.awt.geom.Line2D
;
import
java.awt.geom.Path2D
;
import
java.awt.geom.PathIterator
;
import
java.awt.geom.Rectangle2D
;
import
java.awt.geom.RoundRectangle2D
;
import
java.awt.image.BufferedImage
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.text.AttributedCharacterIterator
;
import
java.text.AttributedString
;
import
java.util.ArrayList
;
import
java.util.List
;
import
javax.imageio.ImageIO
;
import
org.activiti.bpmn.model.AssociationDirection
;
import
org.activiti.bpmn.model.GraphicInfo
;
import
org.activiti.image.exception.ActivitiImageException
;
import
org.activiti.image.util.ReflectUtil
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
/**
* Represents a canvas on which BPMN 2.0 constructs can be drawn.
*
* Some of the icons used are licensed under a Creative Commons Attribution 2.5
* License, see http://www.famfamfam.com/lab/icons/silk/
*
* @see org.activiti.engine.impl.bpmn.diagram.DefaultProcessDiagramGenerator
* @author Joram Barrez
*/
public
class
DefaultProcessDiagramCanvas
{
protected
static
final
Logger
LOGGER
=
LoggerFactory
.
getLogger
(
DefaultProcessDiagramCanvas
.
class
);
public
enum
SHAPE_TYPE
{
Rectangle
,
Rhombus
,
Ellipse
}
// Predefined sized
protected
static
final
int
ARROW_WIDTH
=
5
;
protected
static
final
int
CONDITIONAL_INDICATOR_WIDTH
=
16
;
protected
static
final
int
DEFAULT_INDICATOR_WIDTH
=
10
;
protected
static
final
int
MARKER_WIDTH
=
12
;
protected
static
final
int
FONT_SIZE
=
11
;
protected
static
final
int
FONT_SPACING
=
2
;
protected
static
final
int
TEXT_PADDING
=
3
;
protected
static
final
int
ANNOTATION_TEXT_PADDING
=
7
;
protected
static
final
int
LINE_HEIGHT
=
FONT_SIZE
+
FONT_SPACING
;
// Colors
protected
static
Color
TASK_BOX_COLOR
=
new
Color
(
249
,
249
,
249
);
protected
static
Color
SUBPROCESS_BOX_COLOR
=
new
Color
(
255
,
255
,
255
);
protected
static
Color
EVENT_COLOR
=
new
Color
(
255
,
255
,
255
);
protected
static
Color
CONNECTION_COLOR
=
new
Color
(
88
,
88
,
88
);
protected
static
Color
CONDITIONAL_INDICATOR_COLOR
=
new
Color
(
255
,
255
,
255
);
protected
static
Color
HIGHLIGHT_COLOR
=
Color
.
RED
;
protected
static
Color
LABEL_COLOR
=
new
Color
(
112
,
146
,
190
);
protected
static
Color
TASK_BORDER_COLOR
=
new
Color
(
187
,
187
,
187
);
protected
static
Color
EVENT_BORDER_COLOR
=
new
Color
(
88
,
88
,
88
);
protected
static
Color
SUBPROCESS_BORDER_COLOR
=
new
Color
(
0
,
0
,
0
);
// Fonts
protected
static
Font
LABEL_FONT
=
null
;
protected
static
Font
ANNOTATION_FONT
=
new
Font
(
"Arial"
,
Font
.
PLAIN
,
FONT_SIZE
);
protected
static
Font
TASK_FONT
=
new
Font
(
"Arial"
,
Font
.
PLAIN
,
FONT_SIZE
);
// Strokes
protected
static
Stroke
THICK_TASK_BORDER_STROKE
=
new
BasicStroke
(
3.0f
);
protected
static
Stroke
GATEWAY_TYPE_STROKE
=
new
BasicStroke
(
3.0f
);
protected
static
Stroke
END_EVENT_STROKE
=
new
BasicStroke
(
3.0f
);
protected
static
Stroke
MULTI_INSTANCE_STROKE
=
new
BasicStroke
(
1.3f
);
protected
static
Stroke
EVENT_SUBPROCESS_STROKE
=
new
BasicStroke
(
1.0f
,
BasicStroke
.
CAP_BUTT
,
BasicStroke
.
JOIN_MITER
,
1.0f
,
new
float
[]
{
1.0f
},
0.0f
);
protected
static
Stroke
NON_INTERRUPTING_EVENT_STROKE
=
new
BasicStroke
(
1.0f
,
BasicStroke
.
CAP_BUTT
,
BasicStroke
.
JOIN_MITER
,
1.0f
,
new
float
[]
{
4.0f
,
3.0f
},
0.0f
);
protected
static
Stroke
HIGHLIGHT_FLOW_STROKE
=
new
BasicStroke
(
1.3f
);
protected
static
Stroke
ANNOTATION_STROKE
=
new
BasicStroke
(
2.0f
);
protected
static
Stroke
ASSOCIATION_STROKE
=
new
BasicStroke
(
2.0f
,
BasicStroke
.
CAP_BUTT
,
BasicStroke
.
JOIN_MITER
,
1.0f
,
new
float
[]
{
2.0f
,
2.0f
},
0.0f
);
// icons
protected
static
int
ICON_PADDING
=
5
;
protected
static
BufferedImage
USERTASK_IMAGE
;
protected
static
BufferedImage
SCRIPTTASK_IMAGE
;
protected
static
BufferedImage
SERVICETASK_IMAGE
;
protected
static
BufferedImage
RECEIVETASK_IMAGE
;
protected
static
BufferedImage
SENDTASK_IMAGE
;
protected
static
BufferedImage
MANUALTASK_IMAGE
;
protected
static
BufferedImage
BUSINESS_RULE_TASK_IMAGE
;
protected
static
BufferedImage
SHELL_TASK_IMAGE
;
protected
static
BufferedImage
MULE_TASK_IMAGE
;
protected
static
BufferedImage
CAMEL_TASK_IMAGE
;
protected
static
BufferedImage
TIMER_IMAGE
;
protected
static
BufferedImage
COMPENSATE_THROW_IMAGE
;
protected
static
BufferedImage
COMPENSATE_CATCH_IMAGE
;
protected
static
BufferedImage
ERROR_THROW_IMAGE
;
protected
static
BufferedImage
ERROR_CATCH_IMAGE
;
protected
static
BufferedImage
MESSAGE_THROW_IMAGE
;
protected
static
BufferedImage
MESSAGE_CATCH_IMAGE
;
protected
static
BufferedImage
SIGNAL_CATCH_IMAGE
;
protected
static
BufferedImage
SIGNAL_THROW_IMAGE
;
protected
int
canvasWidth
=
-
1
;
protected
int
canvasHeight
=
-
1
;
protected
int
minX
=
-
1
;
protected
int
minY
=
-
1
;
protected
BufferedImage
processDiagram
;
protected
Graphics2D
g
;
protected
FontMetrics
fontMetrics
;
protected
boolean
closed
;
protected
ClassLoader
customClassLoader
;
protected
String
activityFontName
=
"Arial"
;
protected
String
labelFontName
=
"Arial"
;
/**
* Creates an empty canvas with given width and height.
*
* Allows to specify minimal boundaries on the left and upper side of the
* canvas. This is useful for diagrams that have white space there.
* Everything beneath these minimum values will be cropped.
* It's also possible to pass a specific font name and a class loader for the icon images.
*
*/
public
DefaultProcessDiagramCanvas
(
int
width
,
int
height
,
int
minX
,
int
minY
,
String
imageType
,
String
activityFontName
,
String
labelFontName
,
ClassLoader
customClassLoader
)
{
this
.
canvasWidth
=
width
;
this
.
canvasHeight
=
height
;
this
.
minX
=
minX
;
this
.
minY
=
minY
;
if
(
activityFontName
!=
null
)
{
this
.
activityFontName
=
activityFontName
;
}
if
(
labelFontName
!=
null
)
{
this
.
labelFontName
=
labelFontName
;
}
this
.
customClassLoader
=
customClassLoader
;
initialize
(
imageType
);
}
/**
* Creates an empty canvas with given width and height.
*
* Allows to specify minimal boundaries on the left and upper side of the
* canvas. This is useful for diagrams that have white space there (eg
* Signavio). Everything beneath these minimum values will be cropped.
*
* @param minX
* Hint that will be used when generating the image. Parts that fall
* below minX on the horizontal scale will be cropped.
* @param minY
* Hint that will be used when generating the image. Parts that fall
* below minX on the horizontal scale will be cropped.
*/
public
DefaultProcessDiagramCanvas
(
int
width
,
int
height
,
int
minX
,
int
minY
,
String
imageType
)
{
this
.
canvasWidth
=
width
;
this
.
canvasHeight
=
height
;
this
.
minX
=
minX
;
this
.
minY
=
minY
;
initialize
(
imageType
);
}
public
void
initialize
(
String
imageType
)
{
if
(
"png"
.
equalsIgnoreCase
(
imageType
))
{
this
.
processDiagram
=
new
BufferedImage
(
canvasWidth
,
canvasHeight
,
BufferedImage
.
TYPE_INT_ARGB
);
}
else
{
this
.
processDiagram
=
new
BufferedImage
(
canvasWidth
,
canvasHeight
,
BufferedImage
.
TYPE_INT_RGB
);
}
this
.
g
=
processDiagram
.
createGraphics
();
if
(
"png"
.
equalsIgnoreCase
(
imageType
)
==
false
)
{
this
.
g
.
setBackground
(
new
Color
(
255
,
255
,
255
,
0
));
this
.
g
.
clearRect
(
0
,
0
,
canvasWidth
,
canvasHeight
);
}
g
.
setRenderingHint
(
RenderingHints
.
KEY_ANTIALIASING
,
RenderingHints
.
VALUE_ANTIALIAS_ON
);
g
.
setPaint
(
Color
.
black
);
Font
font
=
new
Font
(
activityFontName
,
Font
.
BOLD
,
FONT_SIZE
);
g
.
setFont
(
font
);
this
.
fontMetrics
=
g
.
getFontMetrics
();
LABEL_FONT
=
new
Font
(
labelFontName
,
Font
.
ITALIC
,
10
);
try
{
USERTASK_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/userTask.png"
,
customClassLoader
));
SCRIPTTASK_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/scriptTask.png"
,
customClassLoader
));
SERVICETASK_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/serviceTask.png"
,
customClassLoader
));
RECEIVETASK_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/receiveTask.png"
,
customClassLoader
));
SENDTASK_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/sendTask.png"
,
customClassLoader
));
MANUALTASK_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/manualTask.png"
,
customClassLoader
));
BUSINESS_RULE_TASK_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/businessRuleTask.png"
,
customClassLoader
));
SHELL_TASK_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/shellTask.png"
,
customClassLoader
));
CAMEL_TASK_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/camelTask.png"
,
customClassLoader
));
MULE_TASK_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/muleTask.png"
,
customClassLoader
));
TIMER_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/timer.png"
,
customClassLoader
));
COMPENSATE_THROW_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/compensate-throw.png"
,
customClassLoader
));
COMPENSATE_CATCH_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/compensate.png"
,
customClassLoader
));
ERROR_THROW_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/error-throw.png"
,
customClassLoader
));
ERROR_CATCH_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/error.png"
,
customClassLoader
));
MESSAGE_THROW_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/message-throw.png"
,
customClassLoader
));
MESSAGE_CATCH_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/message.png"
,
customClassLoader
));
SIGNAL_THROW_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/signal-throw.png"
,
customClassLoader
));
SIGNAL_CATCH_IMAGE
=
ImageIO
.
read
(
ReflectUtil
.
getResource
(
"org/activiti/icons/signal.png"
,
customClassLoader
));
}
catch
(
IOException
e
)
{
LOGGER
.
warn
(
"Could not load image for process diagram creation: {}"
,
e
.
getMessage
());
}
}
/**
* Generates an image of what currently is drawn on the canvas.
*
* Throws an {@link ActivitiException} when {@link #close()} is already
* called.
*/
public
InputStream
generateImage
(
String
imageType
)
{
if
(
closed
)
{
throw
new
ActivitiImageException
(
"ProcessDiagramGenerator already closed"
);
}
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
();
try
{
ImageIO
.
write
(
processDiagram
,
imageType
,
out
);
}
catch
(
IOException
e
)
{
throw
new
ActivitiImageException
(
"Error while generating process image"
,
e
);
}
finally
{
try
{
if
(
out
!=
null
)
{
out
.
close
();
}
}
catch
(
IOException
ignore
)
{
// Exception is silently ignored
}
}
return
new
ByteArrayInputStream
(
out
.
toByteArray
());
}
/**
* Generates an image of what currently is drawn on the canvas.
*
* Throws an {@link ActivitiException} when {@link #close()} is already
* called.
*/
public
BufferedImage
generateBufferedImage
(
String
imageType
)
{
if
(
closed
)
{
throw
new
ActivitiImageException
(
"ProcessDiagramGenerator already closed"
);
}
// Try to remove white space
minX
=
(
minX
<=
5
)
?
5
:
minX
;
minY
=
(
minY
<=
5
)
?
5
:
minY
;
BufferedImage
imageToSerialize
=
processDiagram
;
if
(
minX
>=
0
&&
minY
>=
0
)
{
imageToSerialize
=
processDiagram
.
getSubimage
(
minX
-
5
,
minY
-
5
,
canvasWidth
-
minX
+
5
,
canvasHeight
-
minY
+
5
);
}
return
imageToSerialize
;
}
/**
* Closes the canvas which dissallows further drawing and releases graphical
* resources.
*/
public
void
close
()
{
g
.
dispose
();
closed
=
true
;
}
public
void
drawNoneStartEvent
(
GraphicInfo
graphicInfo
)
{
drawStartEvent
(
graphicInfo
,
null
,
1.0
);
}
public
void
drawTimerStartEvent
(
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawStartEvent
(
graphicInfo
,
TIMER_IMAGE
,
scaleFactor
);
}
public
void
drawSignalStartEvent
(
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawStartEvent
(
graphicInfo
,
SIGNAL_CATCH_IMAGE
,
scaleFactor
);
}
public
void
drawMessageStartEvent
(
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawStartEvent
(
graphicInfo
,
MESSAGE_CATCH_IMAGE
,
scaleFactor
);
}
public
void
drawStartEvent
(
GraphicInfo
graphicInfo
,
BufferedImage
image
,
double
scaleFactor
)
{
Paint
originalPaint
=
g
.
getPaint
();
g
.
setPaint
(
EVENT_COLOR
);
Ellipse2D
circle
=
new
Ellipse2D
.
Double
(
graphicInfo
.
getX
(),
graphicInfo
.
getY
(),
graphicInfo
.
getWidth
(),
graphicInfo
.
getHeight
());
g
.
fill
(
circle
);
g
.
setPaint
(
EVENT_BORDER_COLOR
);
g
.
draw
(
circle
);
g
.
setPaint
(
originalPaint
);
if
(
image
!=
null
)
{
// calculate coordinates to center image
int
imageX
=
(
int
)
Math
.
round
(
graphicInfo
.
getX
()
+
(
graphicInfo
.
getWidth
()
/
2
)
-
(
image
.
getWidth
()
/
2
*
scaleFactor
));
int
imageY
=
(
int
)
Math
.
round
(
graphicInfo
.
getY
()
+
(
graphicInfo
.
getHeight
()
/
2
)
-
(
image
.
getHeight
()
/
2
*
scaleFactor
));
g
.
drawImage
(
image
,
imageX
,
imageY
,
(
int
)
(
image
.
getWidth
()
/
scaleFactor
),
(
int
)
(
image
.
getHeight
()
/
scaleFactor
),
null
);
}
}
public
void
drawNoneEndEvent
(
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
Paint
originalPaint
=
g
.
getPaint
();
Stroke
originalStroke
=
g
.
getStroke
();
g
.
setPaint
(
EVENT_COLOR
);
Ellipse2D
circle
=
new
Ellipse2D
.
Double
(
graphicInfo
.
getX
(),
graphicInfo
.
getY
(),
graphicInfo
.
getWidth
(),
graphicInfo
.
getHeight
());
g
.
fill
(
circle
);
g
.
setPaint
(
EVENT_BORDER_COLOR
);
if
(
scaleFactor
==
1.0
)
{
g
.
setStroke
(
END_EVENT_STROKE
);
}
else
{
g
.
setStroke
(
new
BasicStroke
(
2.0f
));
}
g
.
draw
(
circle
);
g
.
setStroke
(
originalStroke
);
g
.
setPaint
(
originalPaint
);
}
public
void
drawErrorEndEvent
(
String
name
,
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawErrorEndEvent
(
graphicInfo
,
scaleFactor
);
if
(
scaleFactor
==
1.0
)
{
drawLabel
(
name
,
graphicInfo
);
}
}
public
void
drawErrorEndEvent
(
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawNoneEndEvent
(
graphicInfo
,
scaleFactor
);
g
.
drawImage
(
ERROR_THROW_IMAGE
,
(
int
)
(
graphicInfo
.
getX
()
+
(
graphicInfo
.
getWidth
()
/
4
)),
(
int
)
(
graphicInfo
.
getY
()
+
(
graphicInfo
.
getHeight
()
/
4
)),
(
int
)
(
ERROR_THROW_IMAGE
.
getWidth
()
/
scaleFactor
),
(
int
)
(
ERROR_THROW_IMAGE
.
getHeight
()
/
scaleFactor
),
null
);
}
public
void
drawErrorStartEvent
(
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawNoneStartEvent
(
graphicInfo
);
g
.
drawImage
(
ERROR_CATCH_IMAGE
,
(
int
)
(
graphicInfo
.
getX
()
+
(
graphicInfo
.
getWidth
()
/
4
)),
(
int
)
(
graphicInfo
.
getY
()
+
(
graphicInfo
.
getHeight
()
/
4
)),
(
int
)
(
ERROR_CATCH_IMAGE
.
getWidth
()
/
scaleFactor
),
(
int
)
(
ERROR_CATCH_IMAGE
.
getHeight
()
/
scaleFactor
),
null
);
}
public
void
drawCatchingEvent
(
GraphicInfo
graphicInfo
,
boolean
isInterrupting
,
BufferedImage
image
,
String
eventType
,
double
scaleFactor
)
{
// event circles
Ellipse2D
outerCircle
=
new
Ellipse2D
.
Double
(
graphicInfo
.
getX
(),
graphicInfo
.
getY
(),
graphicInfo
.
getWidth
(),
graphicInfo
.
getHeight
());
int
innerCircleSize
=
(
int
)
(
4
/
scaleFactor
);
if
(
innerCircleSize
==
0
)
{
innerCircleSize
=
1
;
}
int
innerCircleX
=
(
int
)
graphicInfo
.
getX
()
+
innerCircleSize
;
int
innerCircleY
=
(
int
)
graphicInfo
.
getY
()
+
innerCircleSize
;
int
innerCircleWidth
=
(
int
)
graphicInfo
.
getWidth
()
-
(
2
*
innerCircleSize
);
int
innerCircleHeight
=
(
int
)
graphicInfo
.
getHeight
()
-
(
2
*
innerCircleSize
);
Ellipse2D
innerCircle
=
new
Ellipse2D
.
Double
(
innerCircleX
,
innerCircleY
,
innerCircleWidth
,
innerCircleHeight
);
Paint
originalPaint
=
g
.
getPaint
();
Stroke
originalStroke
=
g
.
getStroke
();
g
.
setPaint
(
EVENT_COLOR
);
g
.
fill
(
outerCircle
);
g
.
setPaint
(
EVENT_BORDER_COLOR
);
if
(
isInterrupting
==
false
)
g
.
setStroke
(
NON_INTERRUPTING_EVENT_STROKE
);
g
.
draw
(
outerCircle
);
g
.
setStroke
(
originalStroke
);
g
.
setPaint
(
originalPaint
);
g
.
draw
(
innerCircle
);
if
(
image
!=
null
)
{
// calculate coordinates to center image
int
imageX
=
(
int
)
(
graphicInfo
.
getX
()
+
(
graphicInfo
.
getWidth
()
/
2
)
-
(
image
.
getWidth
()
/
2
*
scaleFactor
));
int
imageY
=
(
int
)
(
graphicInfo
.
getY
()
+
(
graphicInfo
.
getHeight
()
/
2
)
-
(
image
.
getHeight
()
/
2
*
scaleFactor
));
if
(
scaleFactor
==
1.0
&&
"timer"
.
equals
(
eventType
))
{
// move image one pixel to center timer image
imageX
++;
imageY
++;
}
g
.
drawImage
(
image
,
imageX
,
imageY
,
(
int
)
(
image
.
getWidth
()
/
scaleFactor
),
(
int
)
(
image
.
getHeight
()
/
scaleFactor
),
null
);
}
}
public
void
drawCatchingCompensateEvent
(
String
name
,
GraphicInfo
graphicInfo
,
boolean
isInterrupting
,
double
scaleFactor
)
{
drawCatchingCompensateEvent
(
graphicInfo
,
isInterrupting
,
scaleFactor
);
drawLabel
(
name
,
graphicInfo
);
}
public
void
drawCatchingCompensateEvent
(
GraphicInfo
graphicInfo
,
boolean
isInterrupting
,
double
scaleFactor
)
{
drawCatchingEvent
(
graphicInfo
,
isInterrupting
,
COMPENSATE_CATCH_IMAGE
,
"compensate"
,
scaleFactor
);
}
public
void
drawCatchingTimerEvent
(
String
name
,
GraphicInfo
graphicInfo
,
boolean
isInterrupting
,
double
scaleFactor
)
{
drawCatchingTimerEvent
(
graphicInfo
,
isInterrupting
,
scaleFactor
);
drawLabel
(
name
,
graphicInfo
);
}
public
void
drawCatchingTimerEvent
(
GraphicInfo
graphicInfo
,
boolean
isInterrupting
,
double
scaleFactor
)
{
drawCatchingEvent
(
graphicInfo
,
isInterrupting
,
TIMER_IMAGE
,
"timer"
,
scaleFactor
);
}
public
void
drawCatchingErrorEvent
(
String
name
,
GraphicInfo
graphicInfo
,
boolean
isInterrupting
,
double
scaleFactor
)
{
drawCatchingErrorEvent
(
graphicInfo
,
isInterrupting
,
scaleFactor
);
drawLabel
(
name
,
graphicInfo
);
}
public
void
drawCatchingErrorEvent
(
GraphicInfo
graphicInfo
,
boolean
isInterrupting
,
double
scaleFactor
)
{
drawCatchingEvent
(
graphicInfo
,
isInterrupting
,
ERROR_CATCH_IMAGE
,
"error"
,
scaleFactor
);
}
public
void
drawCatchingSignalEvent
(
String
name
,
GraphicInfo
graphicInfo
,
boolean
isInterrupting
,
double
scaleFactor
)
{
drawCatchingSignalEvent
(
graphicInfo
,
isInterrupting
,
scaleFactor
);
drawLabel
(
name
,
graphicInfo
);
}
public
void
drawCatchingSignalEvent
(
GraphicInfo
graphicInfo
,
boolean
isInterrupting
,
double
scaleFactor
)
{
drawCatchingEvent
(
graphicInfo
,
isInterrupting
,
SIGNAL_CATCH_IMAGE
,
"signal"
,
scaleFactor
);
}
public
void
drawCatchingMessageEvent
(
GraphicInfo
graphicInfo
,
boolean
isInterrupting
,
double
scaleFactor
)
{
drawCatchingEvent
(
graphicInfo
,
isInterrupting
,
MESSAGE_CATCH_IMAGE
,
"message"
,
scaleFactor
);
}
public
void
drawCatchingMessageEvent
(
String
name
,
GraphicInfo
graphicInfo
,
boolean
isInterrupting
,
double
scaleFactor
)
{
drawCatchingEvent
(
graphicInfo
,
isInterrupting
,
MESSAGE_CATCH_IMAGE
,
"message"
,
scaleFactor
);
drawLabel
(
name
,
graphicInfo
);
}
public
void
drawThrowingCompensateEvent
(
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawCatchingEvent
(
graphicInfo
,
true
,
COMPENSATE_THROW_IMAGE
,
"compensate"
,
scaleFactor
);
}
public
void
drawThrowingSignalEvent
(
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawCatchingEvent
(
graphicInfo
,
true
,
SIGNAL_THROW_IMAGE
,
"signal"
,
scaleFactor
);
}
public
void
drawThrowingNoneEvent
(
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawCatchingEvent
(
graphicInfo
,
true
,
null
,
"none"
,
scaleFactor
);
}
public
void
drawSequenceflow
(
int
srcX
,
int
srcY
,
int
targetX
,
int
targetY
,
boolean
conditional
,
double
scaleFactor
)
{
drawSequenceflow
(
srcX
,
srcY
,
targetX
,
targetY
,
conditional
,
false
,
scaleFactor
);
}
public
void
drawSequenceflow
(
int
srcX
,
int
srcY
,
int
targetX
,
int
targetY
,
boolean
conditional
,
boolean
highLighted
,
double
scaleFactor
)
{
Paint
originalPaint
=
g
.
getPaint
();
if
(
highLighted
)
g
.
setPaint
(
HIGHLIGHT_COLOR
);
Line2D
.
Double
line
=
new
Line2D
.
Double
(
srcX
,
srcY
,
targetX
,
targetY
);
g
.
draw
(
line
);
drawArrowHead
(
line
,
scaleFactor
);
if
(
conditional
)
{
drawConditionalSequenceFlowIndicator
(
line
,
scaleFactor
);
}
if
(
highLighted
)
g
.
setPaint
(
originalPaint
);
}
public
void
drawAssociation
(
int
[]
xPoints
,
int
[]
yPoints
,
AssociationDirection
associationDirection
,
boolean
highLighted
,
double
scaleFactor
)
{
boolean
conditional
=
false
,
isDefault
=
false
;
drawConnection
(
xPoints
,
yPoints
,
conditional
,
isDefault
,
"association"
,
associationDirection
,
highLighted
,
scaleFactor
);
}
public
void
drawSequenceflow
(
int
[]
xPoints
,
int
[]
yPoints
,
boolean
conditional
,
boolean
isDefault
,
boolean
highLighted
,
double
scaleFactor
)
{
drawConnection
(
xPoints
,
yPoints
,
conditional
,
isDefault
,
"sequenceFlow"
,
AssociationDirection
.
ONE
,
highLighted
,
scaleFactor
);
}
public
void
drawConnection
(
int
[]
xPoints
,
int
[]
yPoints
,
boolean
conditional
,
boolean
isDefault
,
String
connectionType
,
AssociationDirection
associationDirection
,
boolean
highLighted
,
double
scaleFactor
)
{
Paint
originalPaint
=
g
.
getPaint
();
Stroke
originalStroke
=
g
.
getStroke
();
g
.
setPaint
(
CONNECTION_COLOR
);
if
(
connectionType
.
equals
(
"association"
))
{
g
.
setStroke
(
ASSOCIATION_STROKE
);
}
else
if
(
highLighted
)
{
g
.
setPaint
(
HIGHLIGHT_COLOR
);
g
.
setStroke
(
HIGHLIGHT_FLOW_STROKE
);
}
for
(
int
i
=
1
;
i
<
xPoints
.
length
;
i
++)
{
Integer
sourceX
=
xPoints
[
i
-
1
];
Integer
sourceY
=
yPoints
[
i
-
1
];
Integer
targetX
=
xPoints
[
i
];
Integer
targetY
=
yPoints
[
i
];
Line2D
.
Double
line
=
new
Line2D
.
Double
(
sourceX
,
sourceY
,
targetX
,
targetY
);
g
.
draw
(
line
);
}
if
(
isDefault
){
Line2D
.
Double
line
=
new
Line2D
.
Double
(
xPoints
[
0
],
yPoints
[
0
],
xPoints
[
1
],
yPoints
[
1
]);
drawDefaultSequenceFlowIndicator
(
line
,
scaleFactor
);
}
if
(
conditional
)
{
Line2D
.
Double
line
=
new
Line2D
.
Double
(
xPoints
[
0
],
yPoints
[
0
],
xPoints
[
1
],
yPoints
[
1
]);
drawConditionalSequenceFlowIndicator
(
line
,
scaleFactor
);
}
if
(
associationDirection
.
equals
(
AssociationDirection
.
ONE
)
||
associationDirection
.
equals
(
AssociationDirection
.
BOTH
))
{
Line2D
.
Double
line
=
new
Line2D
.
Double
(
xPoints
[
xPoints
.
length
-
2
],
yPoints
[
xPoints
.
length
-
2
],
xPoints
[
xPoints
.
length
-
1
],
yPoints
[
xPoints
.
length
-
1
]);
drawArrowHead
(
line
,
scaleFactor
);
}
if
(
associationDirection
.
equals
(
AssociationDirection
.
BOTH
))
{
Line2D
.
Double
line
=
new
Line2D
.
Double
(
xPoints
[
1
],
yPoints
[
1
],
xPoints
[
0
],
yPoints
[
0
]);
drawArrowHead
(
line
,
scaleFactor
);
}
g
.
setPaint
(
originalPaint
);
g
.
setStroke
(
originalStroke
);
}
public
void
drawSequenceflowWithoutArrow
(
int
srcX
,
int
srcY
,
int
targetX
,
int
targetY
,
boolean
conditional
,
double
scaleFactor
)
{
drawSequenceflowWithoutArrow
(
srcX
,
srcY
,
targetX
,
targetY
,
conditional
,
false
,
scaleFactor
);
}
public
void
drawSequenceflowWithoutArrow
(
int
srcX
,
int
srcY
,
int
targetX
,
int
targetY
,
boolean
conditional
,
boolean
highLighted
,
double
scaleFactor
)
{
Paint
originalPaint
=
g
.
getPaint
();
if
(
highLighted
)
g
.
setPaint
(
HIGHLIGHT_COLOR
);
Line2D
.
Double
line
=
new
Line2D
.
Double
(
srcX
,
srcY
,
targetX
,
targetY
);
g
.
draw
(
line
);
if
(
conditional
)
{
drawConditionalSequenceFlowIndicator
(
line
,
scaleFactor
);
}
if
(
highLighted
)
g
.
setPaint
(
originalPaint
);
}
public
void
drawArrowHead
(
Line2D
.
Double
line
,
double
scaleFactor
)
{
int
doubleArrowWidth
=
(
int
)
(
2
*
ARROW_WIDTH
/
scaleFactor
);
if
(
doubleArrowWidth
==
0
)
{
doubleArrowWidth
=
2
;
}
Polygon
arrowHead
=
new
Polygon
();
arrowHead
.
addPoint
(
0
,
0
);
int
arrowHeadPoint
=
(
int
)
(-
ARROW_WIDTH
/
scaleFactor
);
if
(
arrowHeadPoint
==
0
)
{
arrowHeadPoint
=
-
1
;
}
arrowHead
.
addPoint
(
arrowHeadPoint
,
-
doubleArrowWidth
);
arrowHeadPoint
=
(
int
)
(
ARROW_WIDTH
/
scaleFactor
);
if
(
arrowHeadPoint
==
0
)
{
arrowHeadPoint
=
1
;
}
arrowHead
.
addPoint
(
arrowHeadPoint
,
-
doubleArrowWidth
);
AffineTransform
transformation
=
new
AffineTransform
();
transformation
.
setToIdentity
();
double
angle
=
Math
.
atan2
(
line
.
y2
-
line
.
y1
,
line
.
x2
-
line
.
x1
);
transformation
.
translate
(
line
.
x2
,
line
.
y2
);
transformation
.
rotate
((
angle
-
Math
.
PI
/
2
d
));
AffineTransform
originalTransformation
=
g
.
getTransform
();
g
.
setTransform
(
transformation
);
g
.
fill
(
arrowHead
);
g
.
setTransform
(
originalTransformation
);
}
public
void
drawDefaultSequenceFlowIndicator
(
Line2D
.
Double
line
,
double
scaleFactor
)
{
double
length
=
DEFAULT_INDICATOR_WIDTH
/
scaleFactor
,
halfOfLength
=
length
/
2
,
f
=
8
;
Line2D
.
Double
defaultIndicator
=
new
Line2D
.
Double
(-
halfOfLength
,
0
,
halfOfLength
,
0
);
double
angle
=
Math
.
atan2
(
line
.
y2
-
line
.
y1
,
line
.
x2
-
line
.
x1
);
double
dx
=
f
*
Math
.
cos
(
angle
),
dy
=
f
*
Math
.
sin
(
angle
),
x1
=
line
.
x1
+
dx
,
y1
=
line
.
y1
+
dy
;
AffineTransform
transformation
=
new
AffineTransform
();
transformation
.
setToIdentity
();
transformation
.
translate
(
x1
,
y1
);
transformation
.
rotate
((
angle
-
3
*
Math
.
PI
/
4
));
AffineTransform
originalTransformation
=
g
.
getTransform
();
g
.
setTransform
(
transformation
);
g
.
draw
(
defaultIndicator
);
g
.
setTransform
(
originalTransformation
);
}
public
void
drawConditionalSequenceFlowIndicator
(
Line2D
.
Double
line
,
double
scaleFactor
)
{
if
(
scaleFactor
>
1.0
)
return
;
int
horizontal
=
(
int
)
(
CONDITIONAL_INDICATOR_WIDTH
*
0.7
);
int
halfOfHorizontal
=
horizontal
/
2
;
int
halfOfVertical
=
CONDITIONAL_INDICATOR_WIDTH
/
2
;
Polygon
conditionalIndicator
=
new
Polygon
();
conditionalIndicator
.
addPoint
(
0
,
0
);
conditionalIndicator
.
addPoint
(-
halfOfHorizontal
,
halfOfVertical
);
conditionalIndicator
.
addPoint
(
0
,
CONDITIONAL_INDICATOR_WIDTH
);
conditionalIndicator
.
addPoint
(
halfOfHorizontal
,
halfOfVertical
);
AffineTransform
transformation
=
new
AffineTransform
();
transformation
.
setToIdentity
();
double
angle
=
Math
.
atan2
(
line
.
y2
-
line
.
y1
,
line
.
x2
-
line
.
x1
);
transformation
.
translate
(
line
.
x1
,
line
.
y1
);
transformation
.
rotate
((
angle
-
Math
.
PI
/
2
d
));
AffineTransform
originalTransformation
=
g
.
getTransform
();
g
.
setTransform
(
transformation
);
g
.
draw
(
conditionalIndicator
);
Paint
originalPaint
=
g
.
getPaint
();
g
.
setPaint
(
CONDITIONAL_INDICATOR_COLOR
);
g
.
fill
(
conditionalIndicator
);
g
.
setPaint
(
originalPaint
);
g
.
setTransform
(
originalTransformation
);
}
public
void
drawTask
(
BufferedImage
icon
,
String
name
,
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawTask
(
name
,
graphicInfo
);
g
.
drawImage
(
icon
,
(
int
)
(
graphicInfo
.
getX
()
+
ICON_PADDING
/
scaleFactor
),
(
int
)
(
graphicInfo
.
getY
()
+
ICON_PADDING
/
scaleFactor
),
(
int
)
(
icon
.
getWidth
()
/
scaleFactor
),
(
int
)
(
icon
.
getHeight
()
/
scaleFactor
),
null
);
}
public
void
drawTask
(
String
name
,
GraphicInfo
graphicInfo
)
{
drawTask
(
name
,
graphicInfo
,
false
);
}
public
void
drawPoolOrLane
(
String
name
,
GraphicInfo
graphicInfo
)
{
int
x
=
(
int
)
graphicInfo
.
getX
();
int
y
=
(
int
)
graphicInfo
.
getY
();
int
width
=
(
int
)
graphicInfo
.
getWidth
();
int
height
=
(
int
)
graphicInfo
.
getHeight
();
g
.
drawRect
(
x
,
y
,
width
,
height
);
// Add the name as text, vertical
if
(
name
!=
null
&&
name
.
length
()
>
0
)
{
// Include some padding
int
availableTextSpace
=
height
-
6
;
// Create rotation for derived font
AffineTransform
transformation
=
new
AffineTransform
();
transformation
.
setToIdentity
();
transformation
.
rotate
(
270
*
Math
.
PI
/
180
);
Font
currentFont
=
g
.
getFont
();
Font
theDerivedFont
=
currentFont
.
deriveFont
(
transformation
);
g
.
setFont
(
theDerivedFont
);
String
truncated
=
fitTextToWidth
(
name
,
availableTextSpace
);
int
realWidth
=
fontMetrics
.
stringWidth
(
truncated
);
g
.
drawString
(
truncated
,
x
+
2
+
fontMetrics
.
getHeight
(),
3
+
y
+
availableTextSpace
-
(
availableTextSpace
-
realWidth
)
/
2
);
g
.
setFont
(
currentFont
);
}
}
protected
void
drawTask
(
String
name
,
GraphicInfo
graphicInfo
,
boolean
thickBorder
)
{
Paint
originalPaint
=
g
.
getPaint
();
int
x
=
(
int
)
graphicInfo
.
getX
();
int
y
=
(
int
)
graphicInfo
.
getY
();
int
width
=
(
int
)
graphicInfo
.
getWidth
();
int
height
=
(
int
)
graphicInfo
.
getHeight
();
// Create a new gradient paint for every task box, gradient depends on x and y and is not relative
g
.
setPaint
(
TASK_BOX_COLOR
);
int
arcR
=
6
;
if
(
thickBorder
)
arcR
=
3
;
// shape
RoundRectangle2D
rect
=
new
RoundRectangle2D
.
Double
(
x
,
y
,
width
,
height
,
arcR
,
arcR
);
g
.
fill
(
rect
);
g
.
setPaint
(
TASK_BORDER_COLOR
);
if
(
thickBorder
)
{
Stroke
originalStroke
=
g
.
getStroke
();
g
.
setStroke
(
THICK_TASK_BORDER_STROKE
);
g
.
draw
(
rect
);
g
.
setStroke
(
originalStroke
);
}
else
{
g
.
draw
(
rect
);
}
g
.
setPaint
(
originalPaint
);
// text
if
(
name
!=
null
&&
name
.
length
()
>
0
)
{
int
boxWidth
=
width
-
(
2
*
TEXT_PADDING
);
int
boxHeight
=
height
-
16
-
ICON_PADDING
-
ICON_PADDING
-
MARKER_WIDTH
-
2
-
2
;
int
boxX
=
x
+
width
/
2
-
boxWidth
/
2
;
int
boxY
=
y
+
height
/
2
-
boxHeight
/
2
+
ICON_PADDING
+
ICON_PADDING
-
2
-
2
;
drawMultilineCentredText
(
name
,
boxX
,
boxY
,
boxWidth
,
boxHeight
);
}
}
protected
void
drawMultilineCentredText
(
String
text
,
int
x
,
int
y
,
int
boxWidth
,
int
boxHeight
)
{
drawMultilineText
(
text
,
x
,
y
,
boxWidth
,
boxHeight
,
true
);
}
protected
void
drawMultilineAnnotationText
(
String
text
,
int
x
,
int
y
,
int
boxWidth
,
int
boxHeight
)
{
drawMultilineText
(
text
,
x
,
y
,
boxWidth
,
boxHeight
,
false
);
}
protected
void
drawMultilineText
(
String
text
,
int
x
,
int
y
,
int
boxWidth
,
int
boxHeight
,
boolean
centered
)
{
// Create an attributed string based in input text
AttributedString
attributedString
=
new
AttributedString
(
text
);
attributedString
.
addAttribute
(
TextAttribute
.
FONT
,
g
.
getFont
());
attributedString
.
addAttribute
(
TextAttribute
.
FOREGROUND
,
Color
.
black
);
AttributedCharacterIterator
characterIterator
=
attributedString
.
getIterator
();
int
currentHeight
=
0
;
// Prepare a list of lines of text we'll be drawing
List
<
TextLayout
>
layouts
=
new
ArrayList
<
TextLayout
>();
String
lastLine
=
null
;
LineBreakMeasurer
measurer
=
new
LineBreakMeasurer
(
characterIterator
,
g
.
getFontRenderContext
());
TextLayout
layout
=
null
;
while
(
measurer
.
getPosition
()
<
characterIterator
.
getEndIndex
()
&&
currentHeight
<=
boxHeight
)
{
int
previousPosition
=
measurer
.
getPosition
();
// Request next layout
layout
=
measurer
.
nextLayout
(
boxWidth
);
int
height
=
((
Float
)(
layout
.
getDescent
()
+
layout
.
getAscent
()
+
layout
.
getLeading
())).
intValue
();
if
(
currentHeight
+
height
>
boxHeight
)
{
// The line we're about to add should NOT be added anymore, append three dots to previous one instead
// to indicate more text is truncated
if
(!
layouts
.
isEmpty
())
{
layouts
.
remove
(
layouts
.
size
()
-
1
);
if
(
lastLine
.
length
()
>=
4
)
{
lastLine
=
lastLine
.
substring
(
0
,
lastLine
.
length
()
-
4
)
+
"..."
;
}
layouts
.
add
(
new
TextLayout
(
lastLine
,
g
.
getFont
(),
g
.
getFontRenderContext
()));
}
break
;
}
else
{
layouts
.
add
(
layout
);
lastLine
=
text
.
substring
(
previousPosition
,
measurer
.
getPosition
());
currentHeight
+=
height
;
}
}
int
currentY
=
y
+
(
centered
?
((
boxHeight
-
currentHeight
)
/
2
)
:
0
);
int
currentX
=
0
;
// Actually draw the lines
for
(
TextLayout
textLayout
:
layouts
)
{
currentY
+=
textLayout
.
getAscent
();
currentX
=
x
+
(
centered
?
((
boxWidth
-
((
Double
)
textLayout
.
getBounds
().
getWidth
()).
intValue
())
/
2
)
:
0
);
textLayout
.
draw
(
g
,
currentX
,
currentY
);
currentY
+=
textLayout
.
getDescent
()
+
textLayout
.
getLeading
();
}
}
protected
String
fitTextToWidth
(
String
original
,
int
width
)
{
String
text
=
original
;
// remove length for "..."
int
maxWidth
=
width
-
10
;
while
(
fontMetrics
.
stringWidth
(
text
+
"..."
)
>
maxWidth
&&
text
.
length
()
>
0
)
{
text
=
text
.
substring
(
0
,
text
.
length
()
-
1
);
}
if
(!
text
.
equals
(
original
))
{
text
=
text
+
"..."
;
}
return
text
;
}
public
void
drawUserTask
(
String
name
,
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawTask
(
USERTASK_IMAGE
,
name
,
graphicInfo
,
scaleFactor
);
}
public
void
drawScriptTask
(
String
name
,
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawTask
(
SCRIPTTASK_IMAGE
,
name
,
graphicInfo
,
scaleFactor
);
}
public
void
drawServiceTask
(
String
name
,
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawTask
(
SERVICETASK_IMAGE
,
name
,
graphicInfo
,
scaleFactor
);
}
public
void
drawReceiveTask
(
String
name
,
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawTask
(
RECEIVETASK_IMAGE
,
name
,
graphicInfo
,
scaleFactor
);
}
public
void
drawSendTask
(
String
name
,
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawTask
(
SENDTASK_IMAGE
,
name
,
graphicInfo
,
scaleFactor
);
}
public
void
drawManualTask
(
String
name
,
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawTask
(
MANUALTASK_IMAGE
,
name
,
graphicInfo
,
scaleFactor
);
}
public
void
drawBusinessRuleTask
(
String
name
,
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawTask
(
BUSINESS_RULE_TASK_IMAGE
,
name
,
graphicInfo
,
scaleFactor
);
}
public
void
drawCamelTask
(
String
name
,
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawTask
(
CAMEL_TASK_IMAGE
,
name
,
graphicInfo
,
scaleFactor
);
}
public
void
drawMuleTask
(
String
name
,
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
drawTask
(
MULE_TASK_IMAGE
,
name
,
graphicInfo
,
scaleFactor
);
}
public
void
drawExpandedSubProcess
(
String
name
,
GraphicInfo
graphicInfo
,
Boolean
isTriggeredByEvent
,
double
scaleFactor
)
{
RoundRectangle2D
rect
=
new
RoundRectangle2D
.
Double
(
graphicInfo
.
getX
(),
graphicInfo
.
getY
(),
graphicInfo
.
getWidth
(),
graphicInfo
.
getHeight
(),
8
,
8
);
// Use different stroke (dashed)
if
(
isTriggeredByEvent
)
{
Stroke
originalStroke
=
g
.
getStroke
();
g
.
setStroke
(
EVENT_SUBPROCESS_STROKE
);
g
.
draw
(
rect
);
g
.
setStroke
(
originalStroke
);
}
else
{
Paint
originalPaint
=
g
.
getPaint
();
g
.
setPaint
(
SUBPROCESS_BOX_COLOR
);
g
.
fill
(
rect
);
g
.
setPaint
(
SUBPROCESS_BORDER_COLOR
);
g
.
draw
(
rect
);
g
.
setPaint
(
originalPaint
);
}
if
(
scaleFactor
==
1.0
&&
name
!=
null
&&
!
name
.
isEmpty
())
{
String
text
=
fitTextToWidth
(
name
,
(
int
)
graphicInfo
.
getWidth
());
g
.
drawString
(
text
,
(
int
)
graphicInfo
.
getX
()
+
10
,
(
int
)
graphicInfo
.
getY
()
+
15
);
}
}
public
void
drawCollapsedSubProcess
(
String
name
,
GraphicInfo
graphicInfo
,
Boolean
isTriggeredByEvent
)
{
drawCollapsedTask
(
name
,
graphicInfo
,
false
);
}
public
void
drawCollapsedCallActivity
(
String
name
,
GraphicInfo
graphicInfo
)
{
drawCollapsedTask
(
name
,
graphicInfo
,
true
);
}
protected
void
drawCollapsedTask
(
String
name
,
GraphicInfo
graphicInfo
,
boolean
thickBorder
)
{
// The collapsed marker is now visualized separately
drawTask
(
name
,
graphicInfo
,
thickBorder
);
}
public
void
drawCollapsedMarker
(
int
x
,
int
y
,
int
width
,
int
height
)
{
// rectangle
int
rectangleWidth
=
MARKER_WIDTH
;
int
rectangleHeight
=
MARKER_WIDTH
;
Rectangle
rect
=
new
Rectangle
(
x
+
(
width
-
rectangleWidth
)
/
2
,
y
+
height
-
rectangleHeight
-
3
,
rectangleWidth
,
rectangleHeight
);
g
.
draw
(
rect
);
// plus inside rectangle
Line2D
.
Double
line
=
new
Line2D
.
Double
(
rect
.
getCenterX
(),
rect
.
getY
()
+
2
,
rect
.
getCenterX
(),
rect
.
getMaxY
()
-
2
);
g
.
draw
(
line
);
line
=
new
Line2D
.
Double
(
rect
.
getMinX
()
+
2
,
rect
.
getCenterY
(),
rect
.
getMaxX
()
-
2
,
rect
.
getCenterY
());
g
.
draw
(
line
);
}
public
void
drawActivityMarkers
(
int
x
,
int
y
,
int
width
,
int
height
,
boolean
multiInstanceSequential
,
boolean
multiInstanceParallel
,
boolean
collapsed
)
{
if
(
collapsed
)
{
if
(!
multiInstanceSequential
&&
!
multiInstanceParallel
)
{
drawCollapsedMarker
(
x
,
y
,
width
,
height
);
}
else
{
drawCollapsedMarker
(
x
-
MARKER_WIDTH
/
2
-
2
,
y
,
width
,
height
);
if
(
multiInstanceSequential
)
{
drawMultiInstanceMarker
(
true
,
x
+
MARKER_WIDTH
/
2
+
2
,
y
,
width
,
height
);
}
else
{
drawMultiInstanceMarker
(
false
,
x
+
MARKER_WIDTH
/
2
+
2
,
y
,
width
,
height
);
}
}
}
else
{
if
(
multiInstanceSequential
)
{
drawMultiInstanceMarker
(
true
,
x
,
y
,
width
,
height
);
}
else
if
(
multiInstanceParallel
)
{
drawMultiInstanceMarker
(
false
,
x
,
y
,
width
,
height
);
}
}
}
public
void
drawGateway
(
GraphicInfo
graphicInfo
)
{
Polygon
rhombus
=
new
Polygon
();
int
x
=
(
int
)
graphicInfo
.
getX
();
int
y
=
(
int
)
graphicInfo
.
getY
();
int
width
=
(
int
)
graphicInfo
.
getWidth
();
int
height
=
(
int
)
graphicInfo
.
getHeight
();
rhombus
.
addPoint
(
x
,
y
+
(
height
/
2
));
rhombus
.
addPoint
(
x
+
(
width
/
2
),
y
+
height
);
rhombus
.
addPoint
(
x
+
width
,
y
+
(
height
/
2
));
rhombus
.
addPoint
(
x
+
(
width
/
2
),
y
);
g
.
draw
(
rhombus
);
}
public
void
drawParallelGateway
(
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
// rhombus
drawGateway
(
graphicInfo
);
int
x
=
(
int
)
graphicInfo
.
getX
();
int
y
=
(
int
)
graphicInfo
.
getY
();
int
width
=
(
int
)
graphicInfo
.
getWidth
();
int
height
=
(
int
)
graphicInfo
.
getHeight
();
if
(
scaleFactor
==
1.0
)
{
// plus inside rhombus
Stroke
orginalStroke
=
g
.
getStroke
();
g
.
setStroke
(
GATEWAY_TYPE_STROKE
);
Line2D
.
Double
line
=
new
Line2D
.
Double
(
x
+
10
,
y
+
height
/
2
,
x
+
width
-
10
,
y
+
height
/
2
);
// horizontal
g
.
draw
(
line
);
line
=
new
Line2D
.
Double
(
x
+
width
/
2
,
y
+
height
-
10
,
x
+
width
/
2
,
y
+
10
);
// vertical
g
.
draw
(
line
);
g
.
setStroke
(
orginalStroke
);
}
}
public
void
drawExclusiveGateway
(
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
// rhombus
drawGateway
(
graphicInfo
);
int
x
=
(
int
)
graphicInfo
.
getX
();
int
y
=
(
int
)
graphicInfo
.
getY
();
int
width
=
(
int
)
graphicInfo
.
getWidth
();
int
height
=
(
int
)
graphicInfo
.
getHeight
();
int
quarterWidth
=
width
/
4
;
int
quarterHeight
=
height
/
4
;
if
(
scaleFactor
==
1.0
)
{
// X inside rhombus
Stroke
orginalStroke
=
g
.
getStroke
();
g
.
setStroke
(
GATEWAY_TYPE_STROKE
);
Line2D
.
Double
line
=
new
Line2D
.
Double
(
x
+
quarterWidth
+
3
,
y
+
quarterHeight
+
3
,
x
+
3
*
quarterWidth
-
3
,
y
+
3
*
quarterHeight
-
3
);
g
.
draw
(
line
);
line
=
new
Line2D
.
Double
(
x
+
quarterWidth
+
3
,
y
+
3
*
quarterHeight
-
3
,
x
+
3
*
quarterWidth
-
3
,
y
+
quarterHeight
+
3
);
g
.
draw
(
line
);
g
.
setStroke
(
orginalStroke
);
}
}
public
void
drawInclusiveGateway
(
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
// rhombus
drawGateway
(
graphicInfo
);
int
x
=
(
int
)
graphicInfo
.
getX
();
int
y
=
(
int
)
graphicInfo
.
getY
();
int
width
=
(
int
)
graphicInfo
.
getWidth
();
int
height
=
(
int
)
graphicInfo
.
getHeight
();
int
diameter
=
width
/
2
;
if
(
scaleFactor
==
1.0
)
{
// circle inside rhombus
Stroke
orginalStroke
=
g
.
getStroke
();
g
.
setStroke
(
GATEWAY_TYPE_STROKE
);
Ellipse2D
.
Double
circle
=
new
Ellipse2D
.
Double
(((
width
-
diameter
)
/
2
)
+
x
,
((
height
-
diameter
)
/
2
)
+
y
,
diameter
,
diameter
);
g
.
draw
(
circle
);
g
.
setStroke
(
orginalStroke
);
}
}
public
void
drawEventBasedGateway
(
GraphicInfo
graphicInfo
,
double
scaleFactor
)
{
// rhombus
drawGateway
(
graphicInfo
);
if
(
scaleFactor
==
1.0
)
{
int
x
=
(
int
)
graphicInfo
.
getX
();
int
y
=
(
int
)
graphicInfo
.
getY
();
int
width
=
(
int
)
graphicInfo
.
getWidth
();
int
height
=
(
int
)
graphicInfo
.
getHeight
();
double
scale
=
.
6
;
GraphicInfo
eventInfo
=
new
GraphicInfo
();
eventInfo
.
setX
(
x
+
width
*(
1
-
scale
)/
2
);
eventInfo
.
setY
(
y
+
height
*(
1
-
scale
)/
2
);
eventInfo
.
setWidth
(
width
*
scale
);
eventInfo
.
setHeight
(
height
*
scale
);
drawCatchingEvent
(
eventInfo
,
true
,
null
,
"eventGateway"
,
scaleFactor
);
double
r
=
width
/
6
.;
// create pentagon (coords with respect to center)
int
topX
=
(
int
)(.
95
*
r
);
// top right corner
int
topY
=
(
int
)(-.
31
*
r
);
int
bottomX
=
(
int
)(.
59
*
r
);
// bottom right corner
int
bottomY
=
(
int
)(.
81
*
r
);
int
[]
xPoints
=
new
int
[]{
0
,
topX
,
bottomX
,
-
bottomX
,
-
topX
};
int
[]
yPoints
=
new
int
[]{
-(
int
)
r
,
topY
,
bottomY
,
bottomY
,
topY
};
Polygon
pentagon
=
new
Polygon
(
xPoints
,
yPoints
,
5
);
pentagon
.
translate
(
x
+
width
/
2
,
y
+
width
/
2
);
// draw
g
.
drawPolygon
(
pentagon
);
}
}
public
void
drawMultiInstanceMarker
(
boolean
sequential
,
int
x
,
int
y
,
int
width
,
int
height
)
{
int
rectangleWidth
=
MARKER_WIDTH
;
int
rectangleHeight
=
MARKER_WIDTH
;
int
lineX
=
x
+
(
width
-
rectangleWidth
)
/
2
;
int
lineY
=
y
+
height
-
rectangleHeight
-
3
;
Stroke
orginalStroke
=
g
.
getStroke
();
g
.
setStroke
(
MULTI_INSTANCE_STROKE
);
if
(
sequential
)
{
g
.
draw
(
new
Line2D
.
Double
(
lineX
,
lineY
,
lineX
+
rectangleWidth
,
lineY
));
g
.
draw
(
new
Line2D
.
Double
(
lineX
,
lineY
+
rectangleHeight
/
2
,
lineX
+
rectangleWidth
,
lineY
+
rectangleHeight
/
2
));
g
.
draw
(
new
Line2D
.
Double
(
lineX
,
lineY
+
rectangleHeight
,
lineX
+
rectangleWidth
,
lineY
+
rectangleHeight
));
}
else
{
g
.
draw
(
new
Line2D
.
Double
(
lineX
,
lineY
,
lineX
,
lineY
+
rectangleHeight
));
g
.
draw
(
new
Line2D
.
Double
(
lineX
+
rectangleWidth
/
2
,
lineY
,
lineX
+
rectangleWidth
/
2
,
lineY
+
rectangleHeight
));
g
.
draw
(
new
Line2D
.
Double
(
lineX
+
rectangleWidth
,
lineY
,
lineX
+
rectangleWidth
,
lineY
+
rectangleHeight
));
}
g
.
setStroke
(
orginalStroke
);
}
public
void
drawHighLight
(
int
x
,
int
y
,
int
width
,
int
height
)
{
Paint
originalPaint
=
g
.
getPaint
();
Stroke
originalStroke
=
g
.
getStroke
();
g
.
setPaint
(
HIGHLIGHT_COLOR
);
g
.
setStroke
(
THICK_TASK_BORDER_STROKE
);
RoundRectangle2D
rect
=
new
RoundRectangle2D
.
Double
(
x
,
y
,
width
,
height
,
20
,
20
);
g
.
draw
(
rect
);
g
.
setPaint
(
originalPaint
);
g
.
setStroke
(
originalStroke
);
}
public
void
drawTextAnnotation
(
String
text
,
GraphicInfo
graphicInfo
)
{
int
x
=
(
int
)
graphicInfo
.
getX
();
int
y
=
(
int
)
graphicInfo
.
getY
();
int
width
=
(
int
)
graphicInfo
.
getWidth
();
int
height
=
(
int
)
graphicInfo
.
getHeight
();
Font
originalFont
=
g
.
getFont
();
Stroke
originalStroke
=
g
.
getStroke
();
//activiti原本写死的Arial字体,由于我们的字体库中没有该字体,会导致空格乱码
g
.
setFont
(
new
Font
(
"宋体"
,
Font
.
PLAIN
,
FONT_SIZE
));
Path2D
path
=
new
Path2D
.
Double
();
x
+=
.
5
;
int
lineLength
=
18
;
path
.
moveTo
(
x
+
lineLength
,
y
);
path
.
lineTo
(
x
,
y
);
path
.
lineTo
(
x
,
y
+
height
);
path
.
lineTo
(
x
+
lineLength
,
y
+
height
);
path
.
lineTo
(
x
+
lineLength
,
y
+
height
-
1
);
path
.
lineTo
(
x
+
1
,
y
+
height
-
1
);
path
.
lineTo
(
x
+
1
,
y
+
1
);
path
.
lineTo
(
x
+
lineLength
,
y
+
1
);
path
.
closePath
();
g
.
draw
(
path
);
int
boxWidth
=
width
-
(
2
*
ANNOTATION_TEXT_PADDING
);
int
boxHeight
=
height
-
(
2
*
ANNOTATION_TEXT_PADDING
);
int
boxX
=
x
+
width
/
2
-
boxWidth
/
2
;
int
boxY
=
y
+
height
/
2
-
boxHeight
/
2
;
if
(
text
!=
null
&&
text
.
isEmpty
()
==
false
)
{
drawMultilineAnnotationText
(
text
,
boxX
,
boxY
,
boxWidth
,
boxHeight
);
}
// restore originals
g
.
setFont
(
originalFont
);
g
.
setStroke
(
originalStroke
);
}
public
void
drawLabel
(
String
text
,
GraphicInfo
graphicInfo
){
drawLabel
(
text
,
graphicInfo
,
true
);
}
public
void
drawLabel
(
String
text
,
GraphicInfo
graphicInfo
,
boolean
centered
){
float
interline
=
1.0f
;
// text
if
(
text
!=
null
&&
text
.
length
()>
0
)
{
Paint
originalPaint
=
g
.
getPaint
();
Font
originalFont
=
g
.
getFont
();
g
.
setPaint
(
LABEL_COLOR
);
g
.
setFont
(
LABEL_FONT
);
int
wrapWidth
=
100
;
int
textY
=
(
int
)
graphicInfo
.
getY
();
// TODO: use drawMultilineText()
AttributedString
as
=
new
AttributedString
(
text
);
as
.
addAttribute
(
TextAttribute
.
FOREGROUND
,
g
.
getPaint
());
as
.
addAttribute
(
TextAttribute
.
FONT
,
g
.
getFont
());
AttributedCharacterIterator
aci
=
as
.
getIterator
();
FontRenderContext
frc
=
new
FontRenderContext
(
null
,
true
,
false
);
LineBreakMeasurer
lbm
=
new
LineBreakMeasurer
(
aci
,
frc
);
while
(
lbm
.
getPosition
()
<
text
.
length
())
{
TextLayout
tl
=
lbm
.
nextLayout
(
wrapWidth
);
textY
+=
tl
.
getAscent
();
Rectangle2D
bb
=
tl
.
getBounds
();
double
tX
=
graphicInfo
.
getX
();
if
(
centered
)
{
tX
+=
(
int
)
(
graphicInfo
.
getWidth
()
/
2
-
bb
.
getWidth
()
/
2
);
}
tl
.
draw
(
g
,
(
float
)
tX
,
textY
);
textY
+=
tl
.
getDescent
()
+
tl
.
getLeading
()
+
(
interline
-
1.0f
)
*
tl
.
getAscent
();
}
// restore originals
g
.
setFont
(
originalFont
);
g
.
setPaint
(
originalPaint
);
}
}
/**
* This method makes coordinates of connection flow better.
* @param sourceShapeType
* @param targetShapeType
* @param sourceGraphicInfo
* @param targetGraphicInfo
* @param graphicInfoList
*
*/
public
List
<
GraphicInfo
>
connectionPerfectionizer
(
SHAPE_TYPE
sourceShapeType
,
SHAPE_TYPE
targetShapeType
,
GraphicInfo
sourceGraphicInfo
,
GraphicInfo
targetGraphicInfo
,
List
<
GraphicInfo
>
graphicInfoList
)
{
Shape
shapeFirst
=
createShape
(
sourceShapeType
,
sourceGraphicInfo
);
Shape
shapeLast
=
createShape
(
targetShapeType
,
targetGraphicInfo
);
if
(
graphicInfoList
!=
null
&&
graphicInfoList
.
size
()
>
0
)
{
GraphicInfo
graphicInfoFirst
=
graphicInfoList
.
get
(
0
);
GraphicInfo
graphicInfoLast
=
graphicInfoList
.
get
(
graphicInfoList
.
size
()-
1
);
if
(
shapeFirst
!=
null
)
{
graphicInfoFirst
.
setX
(
shapeFirst
.
getBounds2D
().
getCenterX
());
graphicInfoFirst
.
setY
(
shapeFirst
.
getBounds2D
().
getCenterY
());
}
if
(
shapeLast
!=
null
)
{
graphicInfoLast
.
setX
(
shapeLast
.
getBounds2D
().
getCenterX
());
graphicInfoLast
.
setY
(
shapeLast
.
getBounds2D
().
getCenterY
());
}
Point
p
=
null
;
if
(
shapeFirst
!=
null
)
{
Line2D
.
Double
lineFirst
=
new
Line2D
.
Double
(
graphicInfoFirst
.
getX
(),
graphicInfoFirst
.
getY
(),
graphicInfoList
.
get
(
1
).
getX
(),
graphicInfoList
.
get
(
1
).
getY
());
p
=
getIntersection
(
shapeFirst
,
lineFirst
);
if
(
p
!=
null
)
{
graphicInfoFirst
.
setX
(
p
.
getX
());
graphicInfoFirst
.
setY
(
p
.
getY
());
}
}
if
(
shapeLast
!=
null
)
{
Line2D
.
Double
lineLast
=
new
Line2D
.
Double
(
graphicInfoLast
.
getX
(),
graphicInfoLast
.
getY
(),
graphicInfoList
.
get
(
graphicInfoList
.
size
()-
2
).
getX
(),
graphicInfoList
.
get
(
graphicInfoList
.
size
()-
2
).
getY
());
p
=
getIntersection
(
shapeLast
,
lineLast
);
if
(
p
!=
null
)
{
graphicInfoLast
.
setX
(
p
.
getX
());
graphicInfoLast
.
setY
(
p
.
getY
());
}
}
}
return
graphicInfoList
;
}
/**
* This method creates shape by type and coordinates.
* @param shapeType
* @param graphicInfo
* @return Shape
*/
private
static
Shape
createShape
(
SHAPE_TYPE
shapeType
,
GraphicInfo
graphicInfo
)
{
if
(
SHAPE_TYPE
.
Rectangle
.
equals
(
shapeType
))
{
// source is rectangle
return
new
Rectangle2D
.
Double
(
graphicInfo
.
getX
(),
graphicInfo
.
getY
(),
graphicInfo
.
getWidth
(),
graphicInfo
.
getHeight
());
}
else
if
(
SHAPE_TYPE
.
Rhombus
.
equals
(
shapeType
))
{
// source is rhombus
Path2D
.
Double
rhombus
=
new
Path2D
.
Double
();
rhombus
.
moveTo
(
graphicInfo
.
getX
(),
graphicInfo
.
getY
()
+
graphicInfo
.
getHeight
()
/
2
);
rhombus
.
lineTo
(
graphicInfo
.
getX
()
+
graphicInfo
.
getWidth
()
/
2
,
graphicInfo
.
getY
()
+
graphicInfo
.
getHeight
());
rhombus
.
lineTo
(
graphicInfo
.
getX
()
+
graphicInfo
.
getWidth
(),
graphicInfo
.
getY
()
+
graphicInfo
.
getHeight
()
/
2
);
rhombus
.
lineTo
(
graphicInfo
.
getX
()
+
graphicInfo
.
getWidth
()
/
2
,
graphicInfo
.
getY
());
rhombus
.
lineTo
(
graphicInfo
.
getX
(),
graphicInfo
.
getY
()
+
graphicInfo
.
getHeight
()
/
2
);
rhombus
.
closePath
();
return
rhombus
;
}
else
if
(
SHAPE_TYPE
.
Ellipse
.
equals
(
shapeType
))
{
// source is ellipse
return
new
Ellipse2D
.
Double
(
graphicInfo
.
getX
(),
graphicInfo
.
getY
(),
graphicInfo
.
getWidth
(),
graphicInfo
.
getHeight
());
}
else
{
// unknown source element, just do not correct coordinates
}
return
null
;
}
/**
* This method returns intersection point of shape border and line.
*
* @param shape
* @param line
* @return Point
*/
private
static
Point
getIntersection
(
Shape
shape
,
Line2D
.
Double
line
)
{
if
(
shape
instanceof
Ellipse2D
)
{
return
getEllipseIntersection
(
shape
,
line
);
}
else
if
(
shape
instanceof
Rectangle2D
||
shape
instanceof
Path2D
)
{
return
getShapeIntersection
(
shape
,
line
);
}
else
{
// something strange
return
null
;
}
}
/**
* This method calculates ellipse intersection with line
* @param shape
* Bounds of this shape used to calculate parameters of inscribed into this bounds ellipse.
* @param line
* @return Intersection point
*/
private
static
Point
getEllipseIntersection
(
Shape
shape
,
Line2D
.
Double
line
)
{
double
angle
=
Math
.
atan2
(
line
.
y2
-
line
.
y1
,
line
.
x2
-
line
.
x1
);
double
x
=
shape
.
getBounds2D
().
getWidth
()/
2
*
Math
.
cos
(
angle
)
+
shape
.
getBounds2D
().
getCenterX
();
double
y
=
shape
.
getBounds2D
().
getHeight
()/
2
*
Math
.
sin
(
angle
)
+
shape
.
getBounds2D
().
getCenterY
();
Point
p
=
new
Point
();
p
.
setLocation
(
x
,
y
);
return
p
;
}
/**
* This method calculates shape intersection with line.
*
* @param shape
* @param line
* @return Intersection point
*/
private
static
Point
getShapeIntersection
(
Shape
shape
,
Line2D
.
Double
line
)
{
PathIterator
it
=
shape
.
getPathIterator
(
null
);
double
[]
coords
=
new
double
[
6
];
double
[]
pos
=
new
double
[
2
];
Line2D
.
Double
l
=
new
Line2D
.
Double
();
while
(!
it
.
isDone
())
{
int
type
=
it
.
currentSegment
(
coords
);
switch
(
type
)
{
case
PathIterator
.
SEG_MOVETO
:
pos
[
0
]
=
coords
[
0
];
pos
[
1
]
=
coords
[
1
];
break
;
case
PathIterator
.
SEG_LINETO
:
l
=
new
Line2D
.
Double
(
pos
[
0
],
pos
[
1
],
coords
[
0
],
coords
[
1
]);
if
(
line
.
intersectsLine
(
l
))
{
return
getLinesIntersection
(
line
,
l
);
}
pos
[
0
]
=
coords
[
0
];
pos
[
1
]
=
coords
[
1
];
break
;
case
PathIterator
.
SEG_CLOSE
:
break
;
default
:
// whatever
}
it
.
next
();
}
return
null
;
}
/**
* This method calculates intersections of two lines.
* @param a Line 1
* @param b Line 2
* @return Intersection point
*/
private
static
Point
getLinesIntersection
(
Line2D
a
,
Line2D
b
)
{
double
d
=
(
a
.
getX1
()-
a
.
getX2
())*(
b
.
getY2
()-
b
.
getY1
())
-
(
a
.
getY1
()-
a
.
getY2
())*(
b
.
getX2
()-
b
.
getX1
());
double
da
=
(
a
.
getX1
()-
b
.
getX1
())*(
b
.
getY2
()-
b
.
getY1
())
-
(
a
.
getY1
()-
b
.
getY1
())*(
b
.
getX2
()-
b
.
getX1
());
// double db = (a.getX1()-a.getX2())*(a.getY1()-b.getY1()) - (a.getY1()-a.getY2())*(a.getX1()-b.getX1());
double
ta
=
da
/
d
;
// double tb = db/d;
Point
p
=
new
Point
();
p
.
setLocation
(
a
.
getX1
()+
ta
*(
a
.
getX2
()-
a
.
getX1
()),
a
.
getY1
()+
ta
*(
a
.
getY2
()-
a
.
getY1
()));
return
p
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment