mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #1747 from dannon/svg_lib_swap
Swapping from svgfig to svgwrite
This commit is contained in:
@@ -135,7 +135,7 @@ pbr==1.8.0 --hash:sha256=355a0c2ba71120dce1c522387e494c60eb4f44fa9d03067cb981618
|
||||
six==1.9.0 --hash:sha256=cf806ab65d5e16561df30c2cea2fb2cf3e6aa82e48f22036dff177e20f61e188
|
||||
Parsley==1.3 --hash:sha256=32fd648334146e4005dae41d559d32edfff9f3d5f503f8b5d233dbfe3a15a28b
|
||||
nose==1.3.7 --hash:sha256=f36054c5786e84ff6b131f3249a3cce82787f1a930ab053287c0edaa9f840d0f
|
||||
SVGFig==1.1.6 --hash:sha256=300cf4b37b4773498d4ea96c703cdb5f09215978b02828dadb786fb248e0b54b
|
||||
svgwrite==1.1.6 --hash:sha256=e404424dad5eaa41efec6e68daa5c0603e3f4f576ada5dca730669103ab83660
|
||||
|
||||
# Fabric and dependencies
|
||||
Fabric==1.10.2 --hash:sha256=8fe1eb0b0f271e2d41445e7da4470548d3bdf882aab1c1f143505c599996793b
|
||||
|
||||
@@ -51,7 +51,7 @@ pbr==1.8.0
|
||||
six==1.9.0
|
||||
Parsley==1.3
|
||||
nose==1.3.7
|
||||
SVGFig==1.1.6
|
||||
svgwrite==1.1.6
|
||||
|
||||
# Fabric and dependencies
|
||||
Fabric==1.10.2
|
||||
|
||||
@@ -514,7 +514,7 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
|
||||
def gen_image( self, trans, id ):
|
||||
stored = self.get_stored_workflow( trans, id, check_ownership=True )
|
||||
trans.response.set_content_type("image/svg+xml")
|
||||
return self._workflow_to_svg_canvas( trans, stored ).standalone_xml()
|
||||
return self._workflow_to_svg_canvas( trans, stored ).tostring()
|
||||
|
||||
@web.expose
|
||||
@web.require_login( "use Galaxy workflows" )
|
||||
@@ -749,7 +749,7 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
|
||||
workflow_name=workflow_dict['name'],
|
||||
workflow_description=workflow_dict['annotation'],
|
||||
workflow_content=workflow_content,
|
||||
workflow_svg=self._workflow_to_svg_canvas( trans, stored ).standalone_xml()
|
||||
workflow_svg=self._workflow_to_svg_canvas( trans, stored ).tostring()
|
||||
)
|
||||
# strip() b/c myExperiment XML parser doesn't allow white space before XML; utf-8 handles unicode characters.
|
||||
request = unicodify( request_raw.strip(), 'utf-8' )
|
||||
@@ -1290,7 +1290,6 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
|
||||
def _workflow_to_svg_canvas( self, trans, stored ):
|
||||
workflow = stored.latest_workflow
|
||||
workflow_canvas = WorkflowCanvas()
|
||||
canvas = workflow_canvas.canvas
|
||||
for step in workflow.steps:
|
||||
# Load from database representation
|
||||
module = module_factory.from_workflow_step( trans, step )
|
||||
@@ -1303,10 +1302,8 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
|
||||
module_data_inputs,
|
||||
module_data_outputs,
|
||||
)
|
||||
|
||||
workflow_canvas.add_steps( )
|
||||
workflow_canvas.finish( )
|
||||
return canvas
|
||||
workflow_canvas.add_steps()
|
||||
return workflow_canvas.finish()
|
||||
|
||||
|
||||
def _build_workflow_on_str(instance_ds_names):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import svgfig
|
||||
import svgwrite
|
||||
|
||||
MARGIN = 5
|
||||
LINE_SPACING = 15
|
||||
@@ -7,11 +7,11 @@ LINE_SPACING = 15
|
||||
class WorkflowCanvas( object ):
|
||||
|
||||
def __init__( self ):
|
||||
self.canvas = svgfig.canvas( style="stroke:black; fill:none; stroke-width:1px; stroke-linejoin:round; text-anchor:left" )
|
||||
self.text = svgfig.SVG( "g" )
|
||||
self.connectors = svgfig.SVG( "g" )
|
||||
self.boxes = svgfig.SVG( "g" )
|
||||
svgfig.Text.defaults[ "font-size" ] = "10px"
|
||||
self.canvas = svgwrite.Drawing(profile='full')
|
||||
|
||||
self.connectors = []
|
||||
self.boxes = []
|
||||
self.text = []
|
||||
self.in_pos = {}
|
||||
self.out_pos = {}
|
||||
self.widths = {}
|
||||
@@ -21,34 +21,35 @@ class WorkflowCanvas( object ):
|
||||
self.data = []
|
||||
|
||||
def finish( self ):
|
||||
max_x, max_y, max_width = self.max_x, self.max_y, self.max_width
|
||||
canvas = self.canvas
|
||||
canvas.append( self.connectors )
|
||||
canvas.append( self.boxes )
|
||||
canvas.append( self.text )
|
||||
width, height = ( max_x + max_width + 50 ), max_y + 300
|
||||
canvas[ 'width' ] = "%spx" % width
|
||||
canvas[ 'height' ] = "%spx" % height
|
||||
canvas[ 'viewBox' ] = "0 0 %s %s" % ( width, height )
|
||||
# max_x, max_y, max_width = self.max_x, self.max_y, self.max_width
|
||||
for box in self.boxes:
|
||||
self.canvas.add(box)
|
||||
for connector in self.connectors:
|
||||
self.canvas.add(connector)
|
||||
text_style_layer = self.canvas.g(style="font-family: Helvetica, Arial, FreeSans, Sans, sans, sans-serif;")
|
||||
for text in self.text:
|
||||
text_style_layer.add(text)
|
||||
self.canvas.add(text_style_layer)
|
||||
return self.canvas
|
||||
|
||||
def add_boxes( self, step_dict, width, name_fill ):
|
||||
x, y = step_dict[ 'position' ][ 'left' ], step_dict[ 'position' ][ 'top' ]
|
||||
self.boxes.append( svgfig.Rect( x - MARGIN, y, x + width - MARGIN, y + 30, fill=name_fill ).SVG() )
|
||||
self.boxes.append(svgwrite.shapes.Rect((x - MARGIN, y), (width, 30), fill=name_fill, stroke='#000000'))
|
||||
box_height = ( len( step_dict[ 'data_inputs' ] ) + len( step_dict[ 'data_outputs' ] ) ) * LINE_SPACING + MARGIN
|
||||
# Draw separator line.
|
||||
if len( step_dict[ 'data_inputs' ] ) > 0:
|
||||
box_height += 15
|
||||
box_height += LINE_SPACING
|
||||
sep_y = y + len( step_dict[ 'data_inputs' ] ) * LINE_SPACING + 40
|
||||
self.text.append( svgfig.Line( x - MARGIN, sep_y, x + width - MARGIN, sep_y ).SVG() )
|
||||
self.text.append( svgwrite.shapes.Line( (x - MARGIN, sep_y), (x + width - MARGIN, sep_y ), stroke=svgwrite.rgb(0, 0, 0)) )
|
||||
# Define an input/output box.
|
||||
self.boxes.append( svgfig.Rect( x - MARGIN, y + 30, x + width - MARGIN, y + 30 + box_height, fill="#ffffff" ).SVG() )
|
||||
self.boxes.append( svgwrite.shapes.Rect( (x - MARGIN, y + 30), (width, box_height), fill="#ffffff", stroke=svgwrite.rgb(0, 0, 0) ))
|
||||
|
||||
def add_text( self, module_data_inputs, module_data_outputs, step, module_name ):
|
||||
left, top = step.position[ 'left' ], step.position[ 'top' ]
|
||||
x, y = left, top
|
||||
order_index = step.order_index
|
||||
max_len = len( module_name ) * 1.5
|
||||
self.text.append( svgfig.Text( x, y + 20, module_name, **{ "font-size": "14px" } ).SVG() )
|
||||
self.text.append(svgwrite.text.Text(module_name, (x, y + 20), style='font-size:14px'))
|
||||
y += 45
|
||||
count = 0
|
||||
in_pos = self.in_pos
|
||||
@@ -58,17 +59,17 @@ class WorkflowCanvas( object ):
|
||||
if order_index not in in_pos:
|
||||
in_pos[ order_index ] = {}
|
||||
in_pos[ order_index ][ di[ 'name' ] ] = ( x, cur_y )
|
||||
self.text.append( svgfig.Text( x, cur_y, di[ 'label' ] ).SVG() )
|
||||
self.text.append( svgwrite.text.Text( di[ 'label' ], (x, cur_y), style='font-size:10px' ) )
|
||||
count += 1
|
||||
max_len = max( max_len, len( di[ 'label' ] ) )
|
||||
if len( module_data_inputs ) > 0:
|
||||
y += 15
|
||||
y += LINE_SPACING
|
||||
for do in module_data_outputs:
|
||||
cur_y = y + count * LINE_SPACING
|
||||
if order_index not in out_pos:
|
||||
out_pos[ order_index ] = {}
|
||||
out_pos[ order_index ][ do[ 'name' ] ] = ( x, cur_y )
|
||||
self.text.append( svgfig.Text( x, cur_y, do[ 'name' ] ).SVG() )
|
||||
self.text.append( svgwrite.text.Text( do[ 'name' ], (x, cur_y), style='font-size:10px' ))
|
||||
count += 1
|
||||
max_len = max( max_len, len( do['name' ] ) )
|
||||
self.widths[ order_index ] = max_len * 5.5
|
||||
@@ -95,16 +96,25 @@ class WorkflowCanvas( object ):
|
||||
key = out_conn_index_dict.keys()[0]
|
||||
out_conn_pos = self.out_pos[ out_pos_index ][ key ]
|
||||
adjusted = ( out_conn_pos[ 0 ] + self.widths[ output_dict[ 'id' ] ], out_conn_pos[ 1 ] )
|
||||
self.text.append( svgfig.SVG( "circle",
|
||||
cx=out_conn_pos[ 0 ] + self.widths[ output_dict[ 'id' ] ] - MARGIN,
|
||||
cy=out_conn_pos[ 1 ] - MARGIN,
|
||||
r=5,
|
||||
fill="#ffffff" ) )
|
||||
self.connectors.append( svgfig.Line( adjusted[ 0 ],
|
||||
adjusted[ 1 ] - MARGIN,
|
||||
in_coords[ 0 ] - 10,
|
||||
in_coords[ 1 ],
|
||||
arrow_end="conn_%s" % (len(self.connectors.keys()) + 1) ).SVG() )
|
||||
self.text.append( svgwrite.shapes.Circle(center=(out_conn_pos[ 0 ] + self.widths[ output_dict[ 'id' ] ] - MARGIN,
|
||||
out_conn_pos[ 1 ] - MARGIN),
|
||||
r=5,
|
||||
fill="#ffffff",
|
||||
stroke="#000000" ) )
|
||||
marker = self.canvas.marker(overflow='visible',
|
||||
refX="0", refY="5",
|
||||
viewBox="0 0 10 5",
|
||||
markerWidth="8",
|
||||
markerHeight="10",
|
||||
markerUnits="strokeWidth",
|
||||
orient="auto", stroke="none", fill="black")
|
||||
marker.add(self.canvas.path(d="M 0 0 L 10 5 L 0 10 z"))
|
||||
self.canvas.defs.add(marker)
|
||||
conn = svgwrite.shapes.Line( (adjusted[ 0 ], adjusted[ 1 ] - MARGIN),
|
||||
(in_coords[ 0 ] - 10, in_coords[ 1 ]),
|
||||
stroke="#000000")
|
||||
conn['marker-end'] = marker.get_funciri()
|
||||
self.connectors.append( conn )
|
||||
|
||||
def add_steps( self, highlight_errors=False ):
|
||||
# Only highlight missing tools if displaying in the tool shed.
|
||||
@@ -114,7 +124,6 @@ class WorkflowCanvas( object ):
|
||||
fill = "#EBBCB2"
|
||||
else:
|
||||
fill = "#EBD9B2"
|
||||
|
||||
width = self.widths[ step_dict[ 'id' ] ]
|
||||
self.add_boxes( step_dict, width, fill )
|
||||
for conn, output_dict in step_dict[ 'input_connections' ].iteritems():
|
||||
@@ -129,12 +138,10 @@ class WorkflowCanvas( object ):
|
||||
}
|
||||
if tool_errors:
|
||||
step_dict[ 'tool_errors' ] = tool_errors
|
||||
|
||||
input_conn_dict = {}
|
||||
for conn in step.input_connections:
|
||||
input_conn_dict[ conn.input_name ] = \
|
||||
dict( id=conn.output_step.order_index, output_name=conn.output_name )
|
||||
step_dict['input_connections'] = input_conn_dict
|
||||
|
||||
self.data.append(step_dict)
|
||||
self.add_text( module_data_inputs, module_data_outputs, step, module_name )
|
||||
|
||||
@@ -202,7 +202,7 @@ def generate_workflow_image( trans, workflow_name, repository_metadata_id=None,
|
||||
workflow_canvas.add_steps( highlight_errors=True )
|
||||
workflow_canvas.finish( )
|
||||
trans.response.set_content_type( "image/svg+xml" )
|
||||
return canvas.standalone_xml()
|
||||
return canvas.tostring()
|
||||
|
||||
|
||||
def get_workflow_data_inputs( step, module ):
|
||||
|
||||
@@ -66,4 +66,4 @@ def test_render():
|
||||
)
|
||||
workflow_canvas.add_steps()
|
||||
workflow_canvas.finish()
|
||||
assert workflow_canvas.canvas.standalone_xml()
|
||||
assert workflow_canvas.canvas.tostring()
|
||||
|
||||
Reference in New Issue
Block a user