mirror of
https://github.com/wassname/baukit.git
synced 2026-06-27 17:14:53 +08:00
Update labwidget and show to latest.
This commit is contained in:
+553
-153
File diff suppressed because it is too large
Load Diff
+63
-31
@@ -1,37 +1,49 @@
|
||||
from .labwidget import Widget, Property
|
||||
import html
|
||||
from .labwidget import Widget, Property, minify
|
||||
|
||||
|
||||
class PaintWidget(Widget):
|
||||
def __init__(self,
|
||||
width=256, height=256,
|
||||
image='', mask='', brushsize=10.0, oneshot=False, disabled=False):
|
||||
super().__init__()
|
||||
self.mask = Property(mask)
|
||||
self.image = Property(image)
|
||||
self.brushsize = Property(brushsize)
|
||||
self.erase = Property(False)
|
||||
self.oneshot = Property(oneshot)
|
||||
self.disabled = Property(disabled)
|
||||
self.width = Property(width)
|
||||
self.height = Property(height)
|
||||
def __init__(self,
|
||||
width=256, height=256,
|
||||
image='', mask='', brushsize=10.0, oneshot=False, disabled=False,
|
||||
vanishing=True, opacity=0.7, fillStyle='#fff',
|
||||
**kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.mask = Property(mask)
|
||||
self.image = Property(image)
|
||||
self.vanishing = Property(vanishing)
|
||||
self.brushsize = Property(brushsize)
|
||||
self.erase = Property(False)
|
||||
self.oneshot = Property(oneshot)
|
||||
self.disabled = Property(disabled)
|
||||
self.width = Property(width)
|
||||
self.height = Property(height)
|
||||
self.opacity = Property(opacity)
|
||||
self.fillStyle = Property(fillStyle)
|
||||
self.startpos = Property(None)
|
||||
self.dragpos = Property(None)
|
||||
self.dragging = Property(False)
|
||||
|
||||
def widget_js(self):
|
||||
return f'''
|
||||
def widget_js(self):
|
||||
return minify(f'''
|
||||
{PAINT_WIDGET_JS}
|
||||
var pw = new PaintWidget(element, model);
|
||||
'''
|
||||
def widget_html(self):
|
||||
v = self.view_id()
|
||||
return f'''
|
||||
''')
|
||||
|
||||
def widget_html(self):
|
||||
v = self.view_id()
|
||||
return minify(f'''
|
||||
<style>
|
||||
#{v} {{ position: relative; display: inline-block; }}
|
||||
#{v} .paintmask {{
|
||||
position: absolute; top:0; left: 0; z-index: 1;
|
||||
opacity: { self.opacity } }}
|
||||
#{v} .paintmask.vanishing {{
|
||||
opacity: 0; transition: opacity .1s ease-in-out; }}
|
||||
#{v} .paintmask:hover {{ opacity: 0.7; }}
|
||||
#{v} .paintmask.vanishing:hover {{ opacity: { self.opacity }; }}
|
||||
</style>
|
||||
<div id="{v}"></div>
|
||||
'''
|
||||
''')
|
||||
|
||||
|
||||
PAINT_WIDGET_JS = """
|
||||
class PaintWidget {
|
||||
@@ -41,11 +53,20 @@ class PaintWidget {
|
||||
this.size_changed();
|
||||
this.model.on('mask', this.mask_changed.bind(this));
|
||||
this.model.on('image', this.image_changed.bind(this));
|
||||
this.model.on('vanishing', this.mask_changed.bind(this));
|
||||
this.model.on('width', this.size_changed.bind(this));
|
||||
this.model.on('height', this.size_changed.bind(this));
|
||||
}
|
||||
mouse_stroke(first_event) {
|
||||
var self = this;
|
||||
if (first_event.which === 3 || first_event.button === 2) {
|
||||
first_event.preventDefault();
|
||||
self.mask_canvas.style.pointerEvents = 'none';
|
||||
setTimeout(() => {
|
||||
self.mask_canvas.style.pointerEvents = 'all';
|
||||
}, 3000);
|
||||
return;
|
||||
}
|
||||
if (self.model.get('disabled')) { return; }
|
||||
if (self.model.get('oneshot')) {
|
||||
var canvas = self.mask_canvas;
|
||||
@@ -58,6 +79,9 @@ class PaintWidget {
|
||||
window.removeEventListener('mousemove', track_mouse);
|
||||
window.removeEventListener('mouseup', track_mouse);
|
||||
window.removeEventListener('keydown', track_mouse, true);
|
||||
if (self.model.get('dragging')) {
|
||||
self.model.set('dragging', false);
|
||||
}
|
||||
self.mask_changed();
|
||||
}
|
||||
return;
|
||||
@@ -67,13 +91,19 @@ class PaintWidget {
|
||||
window.removeEventListener('mousemove', track_mouse);
|
||||
window.removeEventListener('mouseup', track_mouse);
|
||||
window.removeEventListener('keydown', track_mouse, true);
|
||||
self.model.set('dragging', false);
|
||||
self.model.set('mask', self.mask_canvas.toDataURL());
|
||||
return;
|
||||
}
|
||||
var p = self.cursor_position();
|
||||
var p = self.cursor_position(evt);
|
||||
var d = self.model.get('dragging');
|
||||
var e = self.model.get('erase') ^ (evt.metaKey);
|
||||
if (!d) { self.model.set('startpos', [p.x, p.y]); }
|
||||
self.model.set('dragpos', [p.x, p.y]);
|
||||
if (!d) { self.model.set('dragging', true); }
|
||||
self.fill_circle(p.x, p.y,
|
||||
self.model.get('brushsize'),
|
||||
self.model.get('erase'));
|
||||
e);
|
||||
}
|
||||
this.mask_canvas.focus();
|
||||
window.addEventListener('mousemove', track_mouse);
|
||||
@@ -81,24 +111,25 @@ class PaintWidget {
|
||||
window.addEventListener('keydown', track_mouse, true);
|
||||
track_mouse(first_event);
|
||||
}
|
||||
mask_changed(val) {
|
||||
mask_changed() {
|
||||
this.mask_canvas.classList.toggle("vanishing", this.model.get('vanishing'));
|
||||
this.draw_data_url(this.mask_canvas, this.model.get('mask'));
|
||||
}
|
||||
image_changed() {
|
||||
this.draw_data_url(this.image_canvas, this.model.get('image'));
|
||||
this.image.src = this.model.get('image');
|
||||
}
|
||||
size_changed() {
|
||||
this.mask_canvas = document.createElement('canvas');
|
||||
this.image_canvas = document.createElement('canvas');
|
||||
this.image = document.createElement('img');
|
||||
this.mask_canvas.className = "paintmask";
|
||||
this.image_canvas.className = "paintimage";
|
||||
this.image.className = "paintimage";
|
||||
for (var attr of ['width', 'height']) {
|
||||
this.mask_canvas[attr] = this.model.get(attr);
|
||||
this.image_canvas[attr] = this.model.get(attr);
|
||||
this.image[attr] = this.model.get(attr);
|
||||
}
|
||||
|
||||
this.el.innerHTML = '';
|
||||
this.el.appendChild(this.image_canvas);
|
||||
this.el.appendChild(this.image);
|
||||
this.el.appendChild(this.mask_canvas);
|
||||
this.mask_canvas.addEventListener('mousedown',
|
||||
this.mouse_stroke.bind(this));
|
||||
@@ -121,7 +152,8 @@ class PaintWidget {
|
||||
}
|
||||
ctx.globalCompositeOperation = (
|
||||
erase ? "destination-out" : 'source-over');
|
||||
ctx.fillStyle = '#fff';
|
||||
// ctx.fillStyle = '#fff';
|
||||
ctx.fillStyle = 'rgb(230, 230, 64)';
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, r, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
|
||||
+38
-12
@@ -8,18 +8,26 @@
|
||||
# - show an array of arrays to horizontally lay them out as inline blocks.
|
||||
# - show an array of tuples to create a table.
|
||||
|
||||
import PIL.Image, base64, io, IPython, types, sys
|
||||
import PIL.Image
|
||||
import base64
|
||||
import io
|
||||
import IPython
|
||||
import types
|
||||
import sys
|
||||
import html as html_module
|
||||
from IPython.display import display
|
||||
|
||||
g_buffer = None
|
||||
|
||||
|
||||
def blocks(obj, space=''):
|
||||
return IPython.display.HTML(space.join(blocks_tags(obj)))
|
||||
|
||||
|
||||
def rows(obj, space=''):
|
||||
return IPython.display.HTML(space.join(rows_tags(obj)))
|
||||
|
||||
|
||||
def rows_tags(obj):
|
||||
if isinstance(obj, dict):
|
||||
obj = obj.items()
|
||||
@@ -29,13 +37,14 @@ def rows_tags(obj):
|
||||
results.append('<tr style="padding:0">')
|
||||
for item in row:
|
||||
results.append('<td style="text-align:left; vertical-align:top;' +
|
||||
'padding:1px">')
|
||||
'padding:1px">')
|
||||
results.extend(blocks_tags(item))
|
||||
results.append('</td>')
|
||||
results.append('</tr>')
|
||||
results.append('</table>')
|
||||
return results
|
||||
|
||||
|
||||
def blocks_tags(obj):
|
||||
results = []
|
||||
if hasattr(obj, '_repr_html_'):
|
||||
@@ -49,17 +58,23 @@ def blocks_tags(obj):
|
||||
elif isinstance(obj, dict):
|
||||
results.extend(blocks_tags([(k, v) for k, v in obj.items()]))
|
||||
elif hasattr(obj, '__iter__'):
|
||||
if hasattr(obj, 'tolist'):
|
||||
# Handle numpy/pytorch tensors as lists.
|
||||
try:
|
||||
obj = obj.tolist()
|
||||
except:
|
||||
pass
|
||||
blockstart, blockend, tstart, tend, rstart, rend, cstart, cend = [
|
||||
'<div style="display:inline-block;text-align:center;line-height:1;' +
|
||||
'vertical-align:top;padding:1px">',
|
||||
'</div>',
|
||||
'<table style="display:inline-table">',
|
||||
'</table>',
|
||||
'<tr style="padding:0">',
|
||||
'</tr>',
|
||||
'<td style="text-align:left; vertical-align:top; padding:1px">',
|
||||
'</td>',
|
||||
]
|
||||
'<div style="display:inline-block;text-align:center;line-height:1;' +
|
||||
'vertical-align:top;padding:1px">',
|
||||
'</div>',
|
||||
'<table style="display:inline-table">',
|
||||
'</table>',
|
||||
'<tr style="padding:0">',
|
||||
'</tr>',
|
||||
'<td style="text-align:left; vertical-align:top; padding:1px">',
|
||||
'</td>',
|
||||
]
|
||||
needs_end = False
|
||||
table_mode = False
|
||||
for i, line in enumerate(obj):
|
||||
@@ -88,18 +103,22 @@ def blocks_tags(obj):
|
||||
results.append(table_mode and tend or blockend)
|
||||
return results
|
||||
|
||||
|
||||
def pil_to_b64(img, format='png'):
|
||||
buffered = io.BytesIO()
|
||||
img.save(buffered, format=format)
|
||||
return base64.b64encode(buffered.getvalue()).decode('utf-8')
|
||||
|
||||
|
||||
def pil_to_url(img, format='png'):
|
||||
return 'data:image/%s;base64,%s' % (format, pil_to_b64(img, format))
|
||||
|
||||
|
||||
def pil_to_html(img, margin=1):
|
||||
mattr = ' style="margin:%dpx"' % margin
|
||||
return '<img src="%s"%s>' % (pil_to_url(img), mattr)
|
||||
|
||||
|
||||
def a(x, cols=None):
|
||||
global g_buffer
|
||||
if g_buffer is None:
|
||||
@@ -108,10 +127,12 @@ def a(x, cols=None):
|
||||
if cols is not None and len(g_buffer) >= cols:
|
||||
flush()
|
||||
|
||||
|
||||
def reset():
|
||||
global g_buffer
|
||||
g_buffer = None
|
||||
|
||||
|
||||
def flush(*args, **kwargs):
|
||||
global g_buffer
|
||||
if g_buffer is not None:
|
||||
@@ -119,20 +140,25 @@ def flush(*args, **kwargs):
|
||||
g_buffer = None
|
||||
display(blocks(x, *args, **kwargs))
|
||||
|
||||
|
||||
def show(x=None, *args, **kwargs):
|
||||
flush(*args, **kwargs)
|
||||
if x is not None:
|
||||
display(blocks(x, *args, **kwargs))
|
||||
|
||||
|
||||
def html(obj, space=''):
|
||||
return blocks(obj, space)._repr_html_()
|
||||
|
||||
|
||||
class CallableModule(types.ModuleType):
|
||||
def __init__(self):
|
||||
# or super().__init__(__name__) for Python 3
|
||||
types.ModuleType.__init__(self, __name__)
|
||||
self.__dict__.update(sys.modules[__name__].__dict__)
|
||||
|
||||
def __call__(self, x=None, *args, **kwargs):
|
||||
show(x, *args, **kwargs)
|
||||
|
||||
|
||||
sys.modules[__name__] = CallableModule()
|
||||
|
||||
Reference in New Issue
Block a user