Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Another example doodle - flowchart.js #6

Open
psychemedia opened this issue May 15, 2020 · 2 comments
Open

Another example doodle - flowchart.js #6

psychemedia opened this issue May 15, 2020 · 2 comments

Comments

@psychemedia
Copy link

Been tinkering again... here's another possible misc example - flowchart.js

import jp_proxy_widget

fcode = '''
st=>start: Start|past:>http://www.google.com[blank]
e=>end: End|future:>http://www.google.com
op1=>operation: My Operation|past
op2=>operation: Stuff|current
sub1=>subroutine: My Subroutine|invalid
cond=>condition: Yes
or No?|approved:>http://www.google.com
c2=>condition: Good idea|rejected
io=>inputoutput: catch something...|future

st->op1(right)->cond
cond(yes, right)->c2
cond(no)->sub1(left)->op1
c2(yes)->io->e
c2(no)->op2->e
'''

class FlowchartWidget(jp_proxy_widget.JSProxyWidget):
    def __init__(self, *pargs, **kwargs):
        super(FlowchartWidget, self).__init__(*pargs, **kwargs)
        e = self.element
        
        # Call some standard jQuery method on the widget element:
        e.empty()
        # This is for the controls as well as the simulator
        e.width("1000") # 1181px 2362
        e.height("1000") # 551px 1143
        html = '<div id="fchart_canvas"></div>'
        e.html(html)
        self.load_js_files(["https://cdnjs.cloudflare.com/ajax/libs/raphael/2.3.0/raphael.min.js",
                            'https://cdnjs.cloudflare.com/ajax/libs/flowchart/1.13.0/flowchart.js'])
        
    def charter(self, chart):
        self.set_element("chartdef", chart)
        self.js_init("chart = flowchart.parse(element.chartdef); chart.drawSVG('fchart_canvas');")
        
testEmbed = FlowchartWidget()
testEmbed.charter(fcode)
testEmbed
@AaronWatters
Copy link
Owner

Nice! I put it here -- hope that's okay:

https://github.com/AaronWatters/jp_doodle/blob/master/notebooks/misc/flowcharts.ipynb

@psychemedia
Copy link
Author

psychemedia commented May 19, 2020

Yes, no probs...

I made a couple of tweaks, trying to make it easy to get hold of the asset that's created, eg as SVG and PNG.

import jp_proxy_widget

fcode = '''
st=>start: Start|past:>http://www.google.com[blank]
e=>end: End|future:>http://www.google.com
op1=>operation: My Operation|past
op2=>operation: Stuff|current
sub1=>subroutine: My Subroutine|invalid
cond=>condition: Yes
or No?|approved:>http://www.google.com
c2=>condition: Good idea|rejected
io=>inputoutput: catch something...|future

st->op1(right)->cond
cond(yes, right)->c2
cond(no)->sub1(left)->op1
c2(yes)->io->e
c2(no)->op2->e
'''
fcode='''
st=>start: Start
e=>end: End
op1=>operation: Generate
op2=>parallel: Evaluate
st(right)->op1(right)->op2
op2(path1, top)->op1
op2(path2, right)->e
'''
import uuid
from IPython.display import Image, SVG
import cairosvg

class FlowchartWidget(jp_proxy_widget.JSProxyWidget):
    """jp_proxy_widget to render flowchart.js diagrams."""
    def __init__(self, *pargs, **kwargs):
        super(FlowchartWidget, self).__init__(*pargs, **kwargs)
        e = self.element
        e.empty()
        self.load_js_files(["https://cdnjs.cloudflare.com/ajax/libs/raphael/2.3.0/raphael.min.js",
                            'https://cdnjs.cloudflare.com/ajax/libs/flowchart/1.13.0/flowchart.js'])
        self.uid = None
        self.svg = None

    def charter(self, chart, embed=False):
        """Render chart from chart description."""
        self.uid = uid = uuid.uuid4()
        self.element.html(f'<div id="{uid}"></div>')
        self.set_element("chartdef", chart)
        self.js_init(f"chart = flowchart.parse(element.chartdef); chart.drawSVG('{uid}');svg_data = document.getElementById('{uid}').innerHTML;")
        self.get_value_async(self.svg_callback, "svg_data")
        if embed:
            return self

    def svg_callback(self, svg):
        """Persist SVG state on Python side."""
        self.svg = svg
    
    def get_svg_data(self):
        """Return raw SVG data for flowchart."""
        return self.svg
    
    def get_svg(self):
        """Return SVG data of flowchart."""
        return SVG(self.svg)
    
    def get_png(self):
        """Return png of flowchart."""
        return Image(cairosvg.svg2png(self.svg));
 
    
testEmbed = FlowchartWidget()
testEmbed.charter(fcode)
testEmbed

#testEmbed.get_svg_data()
#testEmbed.get_svg()
#testEmbed.get_png()

You can also display the image directly as FlowchartWidget().charter(fcode, embed=True), though there's a flicker as the Uninitialised widget message displays before it's rendered (can that be made silent somehow?)

I'm not sure if the SVG conversion should really happen on the js side? It alls feels a bit hacky to me!

PS I tried to do the same for mermaid.js but mermaid seems to be a bit less well behaved and I couldn't get it to render properly...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants