parent
130d4deb0a
commit
b92fc0dabc
7 changed files with 3808 additions and 2 deletions
@ -0,0 +1,48 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
# -*- coding: utf-8 -*- |
||||||
|
|
||||||
|
# Copyright (C) 2018 Andy Stewart |
||||||
|
# |
||||||
|
# Author: Andy Stewart <lazycat.manatee@gmail.com> |
||||||
|
# Maintainer: Andy Stewart <lazycat.manatee@gmail.com> |
||||||
|
# |
||||||
|
# This program is free software: you can redistribute it and/or modify |
||||||
|
# it under the terms of the GNU General Public License as published by |
||||||
|
# the Free Software Foundation, either version 3 of the License, or |
||||||
|
# any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||||
|
|
||||||
|
from PyQt5.QtCore import QUrl |
||||||
|
from PyQt5.QtGui import QColor |
||||||
|
from core.browser import BrowserBuffer |
||||||
|
import os |
||||||
|
|
||||||
|
class AppBuffer(BrowserBuffer): |
||||||
|
def __init__(self, buffer_id, url, config_dir, arguments, emacs_var_dict): |
||||||
|
BrowserBuffer.__init__(self, buffer_id, url, config_dir, arguments, emacs_var_dict, False, QColor(255, 255, 255, 255)) |
||||||
|
|
||||||
|
self.url = "file://" + (os.path.join(os.path.dirname(__file__), "index.html")) |
||||||
|
self.buffer_widget.setUrl(QUrl(self.url)) |
||||||
|
|
||||||
|
def add_sub_node(self): |
||||||
|
self.buffer_widget.eval_js("add_node();") |
||||||
|
|
||||||
|
def remove_node(self): |
||||||
|
self.buffer_widget.eval_js("remove_node();") |
||||||
|
|
||||||
|
def update_node_topic(self): |
||||||
|
self.send_input_message("Update topic: ", "update_node_topic") |
||||||
|
|
||||||
|
def handle_update_node_topic(self, topic): |
||||||
|
self.buffer_widget.eval_js("update_node_topic('{}');".format(topic)) |
||||||
|
|
||||||
|
def handle_input_message(self, result_type, result_content): |
||||||
|
if result_type == "update_node_topic": |
||||||
|
self.handle_update_node_topic(str(result_content)) |
||||||
@ -0,0 +1,75 @@ |
|||||||
|
<!doctype html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
||||||
|
<link type="text/css" rel="stylesheet" href="jsmind.css" /> |
||||||
|
|
||||||
|
<script type="text/javascript" src="jsmind.js"></script> |
||||||
|
<script type="text/javascript" src="jsmind.draggable.js"></script> |
||||||
|
<script type="text/javascript" src="jsmind.screenshot.js"></script> |
||||||
|
<style type="text/css"> |
||||||
|
html, body { |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
margin: 0; |
||||||
|
padding: 0; |
||||||
|
} |
||||||
|
|
||||||
|
#jsmind_container{ |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
} |
||||||
|
</style> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div id="jsmind_container"></div> |
||||||
|
|
||||||
|
<script type="text/javascript"> |
||||||
|
var _jm = null; |
||||||
|
function open_empty(){ |
||||||
|
var options = { |
||||||
|
container:'jsmind_container', |
||||||
|
theme:'greensea', |
||||||
|
editable:true |
||||||
|
} |
||||||
|
_jm = jsMind.show(options); |
||||||
|
} |
||||||
|
|
||||||
|
open_empty(); |
||||||
|
|
||||||
|
function add_node(){ |
||||||
|
var selected_node = _jm.get_selected_node(); // as parent of new node |
||||||
|
if(!selected_node) { |
||||||
|
_jm.move_node(selected_id,'_first_'); |
||||||
|
} |
||||||
|
|
||||||
|
var nodeid = jsMind.util.uuid.newid(); |
||||||
|
var node = _jm.add_node(selected_node, nodeid, 'Topic'); |
||||||
|
} |
||||||
|
|
||||||
|
function get_selected_nodeid(){ |
||||||
|
var selected_node = _jm.get_selected_node(); |
||||||
|
if(!!selected_node){ |
||||||
|
return selected_node.id; |
||||||
|
}else{ |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function remove_node(){ |
||||||
|
var selected_id = get_selected_nodeid(); |
||||||
|
if(selected_id) { |
||||||
|
_jm.remove_node(selected_id); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function update_node_topic(topic) { |
||||||
|
var selected_id = get_selected_nodeid(); |
||||||
|
if (selected_id) { |
||||||
|
_jm.update_node(selected_id, topic); |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
</body> |
||||||
|
</html> |
||||||
@ -0,0 +1,48 @@ |
|||||||
|
/* |
||||||
|
* Released under BSD License |
||||||
|
* Copyright (c) 2014-2015 hizzgdev@163.com |
||||||
|
* |
||||||
|
* Project Home: |
||||||
|
* https://github.com/hizzgdev/jsmind/ |
||||||
|
*/ |
||||||
|
|
||||||
|
/* important section */ |
||||||
|
.jsmind-inner{position:relative;overflow:auto;width:100%;height:100%;}/*box-shadow:0 0 2px #000;*/ |
||||||
|
.jsmind-inner{ |
||||||
|
moz-user-select:-moz-none; |
||||||
|
-moz-user-select:none; |
||||||
|
-o-user-select:none; |
||||||
|
-khtml-user-select:none; |
||||||
|
-webkit-user-select:none; |
||||||
|
-ms-user-select:none; |
||||||
|
user-select:none; |
||||||
|
} |
||||||
|
|
||||||
|
/* z-index:1 */ |
||||||
|
canvas{position:absolute;z-index:1;} |
||||||
|
|
||||||
|
/* z-index:2 */ |
||||||
|
jmnodes{position:absolute;z-index:2;background-color:rgba(0,0,0,0);}/*background color is necessary*/ |
||||||
|
jmnode{position:absolute;cursor:default;max-width:400px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;} |
||||||
|
jmexpander{position:absolute;width:11px;height:11px;display:block;overflow:hidden;line-height:12px;font-size:12px;text-align:center;border-radius:6px;border-width:1px;border-style:solid;cursor:pointer;} |
||||||
|
|
||||||
|
/* default theme */ |
||||||
|
jmnode{padding:10px;background-color:#fff;color:#333;border-radius:5px;box-shadow:1px 1px 1px #666;font:16px/1.125 Verdana,Arial,Helvetica,sans-serif;} |
||||||
|
jmnode:hover{box-shadow:2px 2px 8px #000;background-color:#ebebeb;color:#333;} |
||||||
|
jmnode.selected{background-color:#11f;color:#fff;box-shadow:2px 2px 8px #000;} |
||||||
|
jmnode.root{font-size:24px;} |
||||||
|
jmexpander{border-color:gray;} |
||||||
|
jmexpander:hover{border-color:#000;} |
||||||
|
|
||||||
|
@media screen and (max-device-width: 1024px) { |
||||||
|
jmnode{padding:5px;border-radius:3px;font-size:14px;} |
||||||
|
jmnode.root{font-size:21px;} |
||||||
|
} |
||||||
|
|
||||||
|
/* greensea theme */ |
||||||
|
jmnodes.theme-greensea jmnode{background-color:#1abc9c;color:#fff;} |
||||||
|
jmnodes.theme-greensea jmnode:hover{background-color:#16a085;} |
||||||
|
jmnodes.theme-greensea jmnode.selected{background-color:#11f;color:#fff;} |
||||||
|
jmnodes.theme-greensea jmnode.root{} |
||||||
|
jmnodes.theme-greensea jmexpander{} |
||||||
|
jmnodes.theme-greensea jmexpander:hover{} |
||||||
@ -0,0 +1,349 @@ |
|||||||
|
/* |
||||||
|
* Released under BSD License |
||||||
|
* Copyright (c) 2014-2015 hizzgdev@163.com |
||||||
|
*
|
||||||
|
* Project Home: |
||||||
|
* https://github.com/hizzgdev/jsmind/
|
||||||
|
*/ |
||||||
|
|
||||||
|
(function($w){ |
||||||
|
'use strict'; |
||||||
|
var $d = $w.document; |
||||||
|
var __name__ = 'jsMind'; |
||||||
|
var jsMind = $w[__name__]; |
||||||
|
if(!jsMind){return;} |
||||||
|
if(typeof jsMind.draggable != 'undefined'){return;} |
||||||
|
|
||||||
|
var jdom = jsMind.util.dom; |
||||||
|
var jcanvas = jsMind.util.canvas; |
||||||
|
|
||||||
|
var clear_selection = 'getSelection' in $w ? function(){ |
||||||
|
$w.getSelection().removeAllRanges(); |
||||||
|
} : function(){ |
||||||
|
$d.selection.empty(); |
||||||
|
}; |
||||||
|
|
||||||
|
var options = { |
||||||
|
line_width : 5, |
||||||
|
lookup_delay : 500, |
||||||
|
lookup_interval : 80 |
||||||
|
}; |
||||||
|
|
||||||
|
jsMind.draggable = function(jm){ |
||||||
|
this.jm = jm; |
||||||
|
this.e_canvas = null; |
||||||
|
this.canvas_ctx = null; |
||||||
|
this.shadow = null; |
||||||
|
this.shadow_w = 0; |
||||||
|
this.shadow_h = 0; |
||||||
|
this.active_node = null; |
||||||
|
this.target_node = null; |
||||||
|
this.target_direct = null; |
||||||
|
this.client_w = 0; |
||||||
|
this.client_h = 0; |
||||||
|
this.offset_x = 0; |
||||||
|
this.offset_y = 0; |
||||||
|
this.hlookup_delay = 0; |
||||||
|
this.hlookup_timer = 0; |
||||||
|
this.capture = false; |
||||||
|
this.moved = false; |
||||||
|
}; |
||||||
|
|
||||||
|
jsMind.draggable.prototype = { |
||||||
|
init:function(){ |
||||||
|
this._create_canvas(); |
||||||
|
this._create_shadow(); |
||||||
|
this._event_bind(); |
||||||
|
}, |
||||||
|
|
||||||
|
resize:function(){ |
||||||
|
this.jm.view.e_nodes.appendChild(this.shadow); |
||||||
|
this.e_canvas.width=this.jm.view.size.w; |
||||||
|
this.e_canvas.height=this.jm.view.size.h; |
||||||
|
}, |
||||||
|
|
||||||
|
_create_canvas:function(){ |
||||||
|
var c = $d.createElement('canvas'); |
||||||
|
this.jm.view.e_panel.appendChild(c); |
||||||
|
var ctx = c.getContext('2d'); |
||||||
|
this.e_canvas = c; |
||||||
|
this.canvas_ctx = ctx; |
||||||
|
}, |
||||||
|
|
||||||
|
_create_shadow:function(){ |
||||||
|
var s = $d.createElement('jmnode'); |
||||||
|
s.style.visibility = 'hidden'; |
||||||
|
s.style.zIndex = '3'; |
||||||
|
s.style.cursor = 'move'; |
||||||
|
s.style.opacity= '0.7'; |
||||||
|
this.shadow = s; |
||||||
|
}, |
||||||
|
|
||||||
|
reset_shadow:function(el){ |
||||||
|
var s = this.shadow.style; |
||||||
|
this.shadow.innerHTML = el.innerHTML; |
||||||
|
s.left = el.style.left; |
||||||
|
s.top = el.style.top; |
||||||
|
s.width = el.style.width; |
||||||
|
s.height = el.style.height; |
||||||
|
s.backgroundImage = el.style.backgroundImage; |
||||||
|
s.backgroundSize = el.style.backgroundSize; |
||||||
|
s.transform = el.style.transform; |
||||||
|
this.shadow_w = this.shadow.clientWidth; |
||||||
|
this.shadow_h = this.shadow.clientHeight; |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
show_shadow:function(){ |
||||||
|
if(!this.moved){ |
||||||
|
this.shadow.style.visibility = 'visible'; |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
hide_shadow:function(){ |
||||||
|
this.shadow.style.visibility = 'hidden'; |
||||||
|
}, |
||||||
|
|
||||||
|
clear_lines:function(){ |
||||||
|
jcanvas.clear(this.canvas_ctx, 0, 0, this.jm.view.size.w, this.jm.view.size.h); |
||||||
|
}, |
||||||
|
|
||||||
|
_magnet_shadow:function(node){ |
||||||
|
if(!!node){ |
||||||
|
this.canvas_ctx.lineWidth = options.line_width; |
||||||
|
this.canvas_ctx.strokeStyle = 'rgba(0,0,0,0.3)'; |
||||||
|
this.canvas_ctx.lineCap = 'round'; |
||||||
|
this.clear_lines(); |
||||||
|
jcanvas.lineto(this.canvas_ctx, |
||||||
|
node.sp.x, |
||||||
|
node.sp.y, |
||||||
|
node.np.x, |
||||||
|
node.np.y); |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
_lookup_close_node:function(){ |
||||||
|
var root = this.jm.get_root(); |
||||||
|
var root_location = root.get_location(); |
||||||
|
var root_size = root.get_size(); |
||||||
|
var root_x = root_location.x + root_size.w/2; |
||||||
|
|
||||||
|
var sw = this.shadow_w; |
||||||
|
var sh = this.shadow_h; |
||||||
|
var sx = this.shadow.offsetLeft; |
||||||
|
var sy = this.shadow.offsetTop; |
||||||
|
|
||||||
|
var ns,nl; |
||||||
|
|
||||||
|
var direct = (sx + sw/2)>=root_x ? |
||||||
|
jsMind.direction.right : jsMind.direction.left; |
||||||
|
var nodes = this.jm.mind.nodes; |
||||||
|
var node = null; |
||||||
|
var min_distance = Number.MAX_VALUE; |
||||||
|
var distance = 0; |
||||||
|
var closest_node = null; |
||||||
|
var closest_p = null; |
||||||
|
var shadow_p = null; |
||||||
|
for(var nodeid in nodes){ |
||||||
|
var np,sp; |
||||||
|
node = nodes[nodeid]; |
||||||
|
if(node.isroot || node.direction == direct){ |
||||||
|
if(node.id == this.active_node.id){ |
||||||
|
continue; |
||||||
|
} |
||||||
|
ns = node.get_size(); |
||||||
|
nl = node.get_location(); |
||||||
|
if(direct == jsMind.direction.right){ |
||||||
|
if(sx-nl.x-ns.w<=0){continue;} |
||||||
|
distance = Math.abs(sx-nl.x-ns.w) + Math.abs(sy+sh/2-nl.y-ns.h/2); |
||||||
|
np = {x:nl.x+ns.w-options.line_width,y:nl.y+ns.h/2}; |
||||||
|
sp = {x:sx+options.line_width,y:sy+sh/2}; |
||||||
|
}else{ |
||||||
|
if(nl.x-sx-sw<=0){continue;} |
||||||
|
distance = Math.abs(sx+sw-nl.x) + Math.abs(sy+sh/2-nl.y-ns.h/2); |
||||||
|
np = {x:nl.x+options.line_width,y:nl.y+ns.h/2}; |
||||||
|
sp = {x:sx+sw-options.line_width,y:sy+sh/2}; |
||||||
|
} |
||||||
|
if(distance < min_distance){ |
||||||
|
closest_node = node; |
||||||
|
closest_p = np; |
||||||
|
shadow_p = sp; |
||||||
|
min_distance = distance; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
var result_node = null; |
||||||
|
if(!!closest_node){ |
||||||
|
result_node = { |
||||||
|
node:closest_node, |
||||||
|
direction:direct, |
||||||
|
sp:shadow_p, |
||||||
|
np:closest_p |
||||||
|
}; |
||||||
|
} |
||||||
|
return result_node; |
||||||
|
}, |
||||||
|
|
||||||
|
lookup_close_node:function(){ |
||||||
|
var node_data = this._lookup_close_node(); |
||||||
|
if(!!node_data){ |
||||||
|
this._magnet_shadow(node_data); |
||||||
|
this.target_node = node_data.node; |
||||||
|
this.target_direct = node_data.direction; |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
_event_bind:function(){ |
||||||
|
var jd = this; |
||||||
|
var container = this.jm.view.container; |
||||||
|
jdom.add_event(container,'mousedown',function(e){ |
||||||
|
var evt = e || event; |
||||||
|
jd.dragstart.call(jd,evt); |
||||||
|
}); |
||||||
|
jdom.add_event(container,'mousemove',function(e){ |
||||||
|
var evt = e || event; |
||||||
|
jd.drag.call(jd,evt); |
||||||
|
}); |
||||||
|
jdom.add_event(container,'mouseup',function(e){ |
||||||
|
var evt = e || event; |
||||||
|
jd.dragend.call(jd,evt); |
||||||
|
}); |
||||||
|
jdom.add_event(container,'touchstart',function(e){ |
||||||
|
var evt = e || event; |
||||||
|
jd.dragstart.call(jd,evt); |
||||||
|
}); |
||||||
|
jdom.add_event(container,'touchmove',function(e){ |
||||||
|
var evt = e || event; |
||||||
|
jd.drag.call(jd,evt); |
||||||
|
}); |
||||||
|
jdom.add_event(container,'touchend',function(e){ |
||||||
|
var evt = e || event; |
||||||
|
jd.dragend.call(jd,evt); |
||||||
|
}); |
||||||
|
}, |
||||||
|
|
||||||
|
dragstart:function(e){ |
||||||
|
if(!this.jm.get_editable()){return;} |
||||||
|
if(this.capture){return;} |
||||||
|
this.active_node = null; |
||||||
|
|
||||||
|
var jview = this.jm.view; |
||||||
|
var el = e.target || event.srcElement; |
||||||
|
if(el.tagName.toLowerCase() != 'jmnode'){return;} |
||||||
|
var nodeid = jview.get_binded_nodeid(el); |
||||||
|
if(!!nodeid){ |
||||||
|
var node = this.jm.get_node(nodeid); |
||||||
|
if(!node.isroot){ |
||||||
|
this.reset_shadow(el); |
||||||
|
this.active_node = node; |
||||||
|
this.offset_x = (e.clientX || e.touches[0].clientX) - el.offsetLeft; |
||||||
|
this.offset_y = (e.clientY || e.touches[0].clientY) - el.offsetTop; |
||||||
|
this.client_hw = Math.floor(el.clientWidth/2); |
||||||
|
this.client_hh = Math.floor(el.clientHeight/2); |
||||||
|
if(this.hlookup_delay != 0){ |
||||||
|
$w.clearTimeout(this.hlookup_delay); |
||||||
|
} |
||||||
|
if(this.hlookup_timer != 0){ |
||||||
|
$w.clearInterval(this.hlookup_timer); |
||||||
|
} |
||||||
|
var jd = this; |
||||||
|
this.hlookup_delay = $w.setTimeout(function(){ |
||||||
|
jd.hlookup_delay = 0; |
||||||
|
jd.hlookup_timer = $w.setInterval(function(){ |
||||||
|
jd.lookup_close_node.call(jd); |
||||||
|
},options.lookup_interval); |
||||||
|
},options.lookup_delay); |
||||||
|
this.capture = true; |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
drag:function(e){ |
||||||
|
if(!this.jm.get_editable()){return;} |
||||||
|
if(this.capture){ |
||||||
|
e.preventDefault(); |
||||||
|
this.show_shadow(); |
||||||
|
this.moved = true; |
||||||
|
clear_selection(); |
||||||
|
var px = (e.clientX || e.touches[0].clientX) - this.offset_x; |
||||||
|
var py = (e.clientY || e.touches[0].clientY) - this.offset_y; |
||||||
|
var cx = px + this.client_hw; |
||||||
|
var cy = py + this.client_hh; |
||||||
|
this.shadow.style.left = px + 'px'; |
||||||
|
this.shadow.style.top = py + 'px'; |
||||||
|
clear_selection(); |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
dragend:function(e){ |
||||||
|
if(!this.jm.get_editable()){return;} |
||||||
|
if(this.capture){ |
||||||
|
if(this.hlookup_delay != 0){ |
||||||
|
$w.clearTimeout(this.hlookup_delay); |
||||||
|
this.hlookup_delay = 0; |
||||||
|
this.clear_lines(); |
||||||
|
} |
||||||
|
if(this.hlookup_timer != 0){ |
||||||
|
$w.clearInterval(this.hlookup_timer); |
||||||
|
this.hlookup_timer = 0; |
||||||
|
this.clear_lines(); |
||||||
|
} |
||||||
|
if(this.moved){ |
||||||
|
var src_node = this.active_node; |
||||||
|
var target_node = this.target_node; |
||||||
|
var target_direct = this.target_direct; |
||||||
|
this.move_node(src_node,target_node,target_direct); |
||||||
|
} |
||||||
|
this.hide_shadow(); |
||||||
|
} |
||||||
|
this.moved = false; |
||||||
|
this.capture = false; |
||||||
|
}, |
||||||
|
|
||||||
|
move_node:function(src_node,target_node,target_direct){ |
||||||
|
var shadow_h = this.shadow.offsetTop; |
||||||
|
if(!!target_node && !!src_node && !jsMind.node.inherited(src_node, target_node)){ |
||||||
|
// lookup before_node
|
||||||
|
var sibling_nodes = target_node.children; |
||||||
|
var sc = sibling_nodes.length; |
||||||
|
var node = null; |
||||||
|
var delta_y = Number.MAX_VALUE; |
||||||
|
var node_before = null; |
||||||
|
var beforeid = '_last_'; |
||||||
|
while(sc--){ |
||||||
|
node = sibling_nodes[sc]; |
||||||
|
if(node.direction == target_direct && node.id != src_node.id){ |
||||||
|
var dy = node.get_location().y - shadow_h; |
||||||
|
if(dy > 0 && dy < delta_y){ |
||||||
|
delta_y = dy; |
||||||
|
node_before = node; |
||||||
|
beforeid = '_first_'; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if(!!node_before){beforeid = node_before.id;} |
||||||
|
this.jm.move_node(src_node.id, beforeid, target_node.id, target_direct); |
||||||
|
} |
||||||
|
this.active_node = null; |
||||||
|
this.target_node = null; |
||||||
|
this.target_direct = null; |
||||||
|
}, |
||||||
|
|
||||||
|
jm_event_handle:function(type,data){ |
||||||
|
if(type === jsMind.event_type.resize){ |
||||||
|
this.resize(); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
var draggable_plugin = new jsMind.plugin('draggable',function(jm){ |
||||||
|
var jd = new jsMind.draggable(jm); |
||||||
|
jd.init(); |
||||||
|
jm.add_event_listener(function(type,data){ |
||||||
|
jd.jm_event_handle.call(jd,type,data); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
jsMind.register_plugin(draggable_plugin); |
||||||
|
|
||||||
|
})(window); |
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,349 @@ |
|||||||
|
/* |
||||||
|
* Released under BSD License |
||||||
|
* Copyright (c) 2014-2015 hizzgdev@163.com |
||||||
|
*
|
||||||
|
* Project Home: |
||||||
|
* https://github.com/hizzgdev/jsmind/
|
||||||
|
*/ |
||||||
|
|
||||||
|
(function($w){ |
||||||
|
'use strict'; |
||||||
|
|
||||||
|
var __name__ = 'jsMind'; |
||||||
|
var jsMind = $w[__name__]; |
||||||
|
if(!jsMind){return;} |
||||||
|
if(typeof jsMind.screenshot != 'undefined'){return;} |
||||||
|
|
||||||
|
var $d = $w.document; |
||||||
|
var $c = function(tag){return $d.createElement(tag);}; |
||||||
|
|
||||||
|
var css = function(cstyle,property_name){ |
||||||
|
return cstyle.getPropertyValue(property_name); |
||||||
|
}; |
||||||
|
var is_visible = function(cstyle){ |
||||||
|
var visibility = css(cstyle,'visibility'); |
||||||
|
var display = css(cstyle,'display'); |
||||||
|
return (visibility !== 'hidden' && display !== 'none'); |
||||||
|
}; |
||||||
|
var jcanvas = jsMind.util.canvas; |
||||||
|
jcanvas.rect = function (ctx,x,y,w,h,r) { |
||||||
|
if (w < 2 * r) r = w / 2; |
||||||
|
if (h < 2 * r) r = h / 2; |
||||||
|
ctx.moveTo(x+r, y); |
||||||
|
ctx.arcTo(x+w, y, x+w, y+h, r); |
||||||
|
ctx.arcTo(x+w, y+h, x, y+h, r); |
||||||
|
ctx.arcTo(x, y+h, x, y, r); |
||||||
|
ctx.arcTo(x, y, x+w, y, r); |
||||||
|
}; |
||||||
|
|
||||||
|
jcanvas.text_multiline = function(ctx,text,x,y,w,h,lineheight){ |
||||||
|
var line = ''; |
||||||
|
var text_len = text.length; |
||||||
|
var chars = text.split(''); |
||||||
|
var test_line = null; |
||||||
|
ctx.textAlign = 'left'; |
||||||
|
ctx.textBaseline = 'top'; |
||||||
|
for(var i=0;i<text_len;i++){ |
||||||
|
test_line = line + chars[i]; |
||||||
|
if(ctx.measureText(test_line).width > w && i>0){ |
||||||
|
ctx.fillText(line,x,y); |
||||||
|
line = chars[i]; |
||||||
|
y += lineheight; |
||||||
|
}else{ |
||||||
|
line = test_line; |
||||||
|
} |
||||||
|
} |
||||||
|
ctx.fillText(line,x,y); |
||||||
|
}; |
||||||
|
|
||||||
|
jcanvas.text_ellipsis = function(ctx,text,x,y,w,h){ |
||||||
|
var center_y = y+h/2; |
||||||
|
var text = jcanvas.fittingString(ctx,text,w); |
||||||
|
ctx.textAlign = 'left'; |
||||||
|
ctx.textBaseline = 'middle'; |
||||||
|
ctx.fillText(text,x,center_y,w); |
||||||
|
}; |
||||||
|
|
||||||
|
jcanvas.fittingString = function(ctx,text,max_width) { |
||||||
|
var width = ctx.measureText(text).width; |
||||||
|
var ellipsis = '…' |
||||||
|
var ellipsis_width = ctx.measureText(ellipsis).width; |
||||||
|
if (width<=max_width || width<=ellipsis_width) { |
||||||
|
return text; |
||||||
|
} else { |
||||||
|
var len = text.length; |
||||||
|
while (width>=max_width-ellipsis_width && len-->0) { |
||||||
|
text = text.substring(0, len); |
||||||
|
width = ctx.measureText(text).width; |
||||||
|
} |
||||||
|
return text+ellipsis; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
jcanvas.image = function(ctx,backgroundUrl,x,y,w,h,r,rotation,callback){ |
||||||
|
var img = new Image(); |
||||||
|
img.onload = function () { |
||||||
|
ctx.save(); |
||||||
|
ctx.translate(x,y); |
||||||
|
ctx.save(); |
||||||
|
ctx.beginPath(); |
||||||
|
jcanvas.rect(ctx,0,0,w,h,r); |
||||||
|
ctx.closePath(); |
||||||
|
ctx.clip(); |
||||||
|
ctx.translate(w/2,h/2); |
||||||
|
ctx.rotate(rotation*Math.PI/180); |
||||||
|
ctx.drawImage(img,-w/2,-h/2); |
||||||
|
ctx.restore(); |
||||||
|
ctx.restore(); |
||||||
|
callback(); |
||||||
|
} |
||||||
|
img.src = backgroundUrl; |
||||||
|
}; |
||||||
|
|
||||||
|
jsMind.screenshot = function(jm){ |
||||||
|
this.jm = jm; |
||||||
|
this.canvas_elem = null; |
||||||
|
this.canvas_ctx = null; |
||||||
|
this._inited = false; |
||||||
|
}; |
||||||
|
|
||||||
|
jsMind.screenshot.prototype = { |
||||||
|
init:function(){ |
||||||
|
if(this._inited){return;} |
||||||
|
console.log('init'); |
||||||
|
var c = $c('canvas'); |
||||||
|
var ctx = c.getContext('2d'); |
||||||
|
|
||||||
|
this.canvas_elem = c; |
||||||
|
this.canvas_ctx = ctx; |
||||||
|
this.jm.view.e_panel.appendChild(c); |
||||||
|
this._inited = true; |
||||||
|
this.resize(); |
||||||
|
}, |
||||||
|
|
||||||
|
shoot:function(callback){ |
||||||
|
this.init(); |
||||||
|
this._watermark(); |
||||||
|
var jms = this; |
||||||
|
this._draw(function(){ |
||||||
|
if(!!callback){ |
||||||
|
callback(jms); |
||||||
|
} |
||||||
|
jms.clean(); |
||||||
|
}); |
||||||
|
}, |
||||||
|
|
||||||
|
shootDownload: function(){ |
||||||
|
this.shoot(function(jms){ |
||||||
|
jms._download(); |
||||||
|
}); |
||||||
|
}, |
||||||
|
|
||||||
|
shootAsDataURL: function(callback){ |
||||||
|
this.shoot(function(jms){ |
||||||
|
callback(jms.canvas_elem.toDataURL()); |
||||||
|
}); |
||||||
|
}, |
||||||
|
|
||||||
|
resize:function(){ |
||||||
|
if(this._inited){ |
||||||
|
this.canvas_elem.width=this.jm.view.size.w; |
||||||
|
this.canvas_elem.height=this.jm.view.size.h; |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
clean:function(){ |
||||||
|
var c = this.canvas_elem; |
||||||
|
this.canvas_ctx.clearRect(0,0,c.width,c.height); |
||||||
|
}, |
||||||
|
|
||||||
|
_draw:function(callback){ |
||||||
|
var ctx = this.canvas_ctx; |
||||||
|
ctx.textAlign = 'left'; |
||||||
|
ctx.textBaseline = 'top'; |
||||||
|
this._draw_lines(); |
||||||
|
this._draw_nodes(callback); |
||||||
|
}, |
||||||
|
|
||||||
|
_watermark:function(){ |
||||||
|
var c = this.canvas_elem; |
||||||
|
var ctx = this.canvas_ctx; |
||||||
|
ctx.textAlign='right'; |
||||||
|
ctx.textBaseline='bottom'; |
||||||
|
ctx.fillStyle='#000'; |
||||||
|
ctx.font='11px Verdana,Arial,Helvetica,sans-serif'; |
||||||
|
ctx.fillText('hizzgdev.github.io/jsmind',c.width-5.5,c.height-2.5); |
||||||
|
ctx.textAlign='left'; |
||||||
|
ctx.fillText($w.location,5.5,c.height-2.5); |
||||||
|
}, |
||||||
|
|
||||||
|
_draw_lines:function(){ |
||||||
|
this.jm.view.show_lines(this.canvas_ctx); |
||||||
|
}, |
||||||
|
|
||||||
|
_draw_nodes:function(callback){ |
||||||
|
var nodes = this.jm.mind.nodes; |
||||||
|
var node; |
||||||
|
for(var nodeid in nodes){ |
||||||
|
node = nodes[nodeid]; |
||||||
|
this._draw_node(node); |
||||||
|
} |
||||||
|
|
||||||
|
function check_nodes_ready() { |
||||||
|
console.log('check_node_ready'+new Date()); |
||||||
|
var allOk = true; |
||||||
|
for(var nodeid in nodes){ |
||||||
|
node = nodes[nodeid]; |
||||||
|
allOk = allOk & node.ready; |
||||||
|
} |
||||||
|
|
||||||
|
if(!allOk) { |
||||||
|
$w.setTimeout(check_nodes_ready, 200); |
||||||
|
} else { |
||||||
|
$w.setTimeout(callback, 200); |
||||||
|
} |
||||||
|
} |
||||||
|
check_nodes_ready(); |
||||||
|
}, |
||||||
|
|
||||||
|
_draw_node:function(node){ |
||||||
|
var ctx = this.canvas_ctx; |
||||||
|
var view_data = node._data.view; |
||||||
|
var node_element = view_data.element; |
||||||
|
var ncs = getComputedStyle(node_element); |
||||||
|
if(!is_visible(ncs)){ |
||||||
|
node.ready = true; |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
var bgcolor = css(ncs,'background-color'); |
||||||
|
var round_radius = parseInt(css(ncs,'border-top-left-radius')); |
||||||
|
var color = css(ncs,'color'); |
||||||
|
var padding_left = parseInt(css(ncs,'padding-left')); |
||||||
|
var padding_right = parseInt(css(ncs,'padding-right')); |
||||||
|
var padding_top = parseInt(css(ncs,'padding-top')); |
||||||
|
var padding_bottom = parseInt(css(ncs,'padding-bottom')); |
||||||
|
var text_overflow = css(ncs,'text-overflow'); |
||||||
|
var font = css(ncs,'font-style')+' '+ |
||||||
|
css(ncs,'font-variant')+' '+ |
||||||
|
css(ncs,'font-weight')+' '+ |
||||||
|
css(ncs,'font-size')+'/'+css(ncs,'line-height')+' '+ |
||||||
|
css(ncs,'font-family'); |
||||||
|
|
||||||
|
var rb = {x:view_data.abs_x, |
||||||
|
y:view_data.abs_y, |
||||||
|
w:view_data.width+1, |
||||||
|
h:view_data.height+1}; |
||||||
|
var tb = {x:rb.x+padding_left, |
||||||
|
y:rb.y+padding_top, |
||||||
|
w:rb.w-padding_left-padding_right, |
||||||
|
h:rb.h-padding_top-padding_bottom}; |
||||||
|
|
||||||
|
ctx.font=font; |
||||||
|
ctx.fillStyle = bgcolor; |
||||||
|
ctx.beginPath(); |
||||||
|
jcanvas.rect(ctx, rb.x, rb.y, rb.w, rb.h, round_radius); |
||||||
|
ctx.closePath(); |
||||||
|
ctx.fill(); |
||||||
|
|
||||||
|
ctx.fillStyle = color; |
||||||
|
if ('background-image' in node.data) { |
||||||
|
var backgroundUrl = css(ncs,'background-image').slice(5, -2); |
||||||
|
node.ready = false; |
||||||
|
var rotation = 0; |
||||||
|
if ('background-rotation' in node.data) { |
||||||
|
rotation = node.data['background-rotation']; |
||||||
|
} |
||||||
|
jcanvas.image(ctx, backgroundUrl, rb.x, rb.y, rb.w, rb.h, round_radius, rotation, |
||||||
|
function() { |
||||||
|
node.ready = true; |
||||||
|
}); |
||||||
|
} |
||||||
|
if (!!node.topic) { |
||||||
|
if(text_overflow === 'ellipsis'){ |
||||||
|
jcanvas.text_ellipsis(ctx, node.topic, tb.x, tb.y, tb.w, tb.h); |
||||||
|
}else{ |
||||||
|
var line_height = parseInt(css(ncs,'line-height')); |
||||||
|
jcanvas.text_multiline(ctx, node.topic, tb.x, tb.y, tb.w, tb.h,line_height); |
||||||
|
} |
||||||
|
} |
||||||
|
if(!!view_data.expander){ |
||||||
|
this._draw_expander(view_data.expander); |
||||||
|
} |
||||||
|
if (!('background-image' in node.data)) { |
||||||
|
node.ready = true; |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
_draw_expander:function(expander){ |
||||||
|
var ctx = this.canvas_ctx; |
||||||
|
var ncs = getComputedStyle(expander); |
||||||
|
if(!is_visible(ncs)){ return; } |
||||||
|
|
||||||
|
var style_left = css(ncs,'left'); |
||||||
|
var style_top = css(ncs,'top'); |
||||||
|
var font = css(ncs,'font'); |
||||||
|
var left = parseInt(style_left); |
||||||
|
var top = parseInt(style_top); |
||||||
|
var is_plus = expander.innerHTML === '+'; |
||||||
|
|
||||||
|
ctx.lineWidth = 1; |
||||||
|
|
||||||
|
ctx.beginPath(); |
||||||
|
ctx.arc(left+7,top+7,5,0,Math.PI*2,true); |
||||||
|
ctx.moveTo(left+10,top+7); |
||||||
|
ctx.lineTo(left+4,top+7); |
||||||
|
if(is_plus){ |
||||||
|
ctx.moveTo(left+7,top+4); |
||||||
|
ctx.lineTo(left+7,top+10); |
||||||
|
} |
||||||
|
ctx.closePath(); |
||||||
|
ctx.stroke(); |
||||||
|
}, |
||||||
|
|
||||||
|
_download:function(){ |
||||||
|
var c = this.canvas_elem; |
||||||
|
var name = this.jm.mind.name+'.png'; |
||||||
|
|
||||||
|
if (navigator.msSaveBlob && (!!c.msToBlob)) { |
||||||
|
var blob = c.msToBlob(); |
||||||
|
navigator.msSaveBlob(blob,name); |
||||||
|
} else { |
||||||
|
var bloburl = this.canvas_elem.toDataURL(); |
||||||
|
var anchor = $c('a'); |
||||||
|
if ('download' in anchor) { |
||||||
|
anchor.style.visibility = 'hidden'; |
||||||
|
anchor.href = bloburl; |
||||||
|
anchor.download = name; |
||||||
|
$d.body.appendChild(anchor); |
||||||
|
var evt = $d.createEvent('MouseEvents'); |
||||||
|
evt.initEvent('click', true, true); |
||||||
|
anchor.dispatchEvent(evt); |
||||||
|
$d.body.removeChild(anchor); |
||||||
|
} else { |
||||||
|
location.href = bloburl; |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
jm_event_handle:function(type,data){ |
||||||
|
if(type === jsMind.event_type.resize){ |
||||||
|
this.resize(); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
var screenshot_plugin = new jsMind.plugin('screenshot',function(jm){ |
||||||
|
var jss = new jsMind.screenshot(jm); |
||||||
|
jm.screenshot = jss; |
||||||
|
jm.shoot = function(){ |
||||||
|
jss.shoot(); |
||||||
|
}; |
||||||
|
jm.add_event_listener(function(type,data){ |
||||||
|
jss.jm_event_handle.call(jss,type,data); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
jsMind.register_plugin(screenshot_plugin); |
||||||
|
|
||||||
|
})(window); |
||||||
Loading…
Reference in new issue