mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
PDF editor: New text element implementation (#4246)
* draft * almost working * Widgth adjustment * Fix crash on empty text * Change default layouts * Fix editor bugs * Update src/pretix/control/templates/pretixcontrol/pdf/index.html Co-authored-by: Richard Schreiber <schreiber@rami.io> * Show deprecated text on old text * lockScalingFlip * Regroup editor controls * Update src/pretix/static/pretixcontrol/js/ui/main.js Co-authored-by: Richard Schreiber <schreiber@rami.io> * Update src/pretix/static/pretixcontrol/js/ui/main.js Co-authored-by: Richard Schreiber <schreiber@rami.io> * Update src/pretix/static/pretixcontrol/js/ui/main.js Co-authored-by: Richard Schreiber <schreiber@rami.io> * Update src/pretix/static/pretixcontrol/js/ui/editor.js Co-authored-by: Richard Schreiber <schreiber@rami.io> * Increase default height even further * Add a small version warning * Update src/pretix/control/templates/pretixcontrol/pdf/index.html Co-authored-by: Richard Schreiber <schreiber@rami.io> * Update src/pretix/control/templates/pretixcontrol/pdf/index.html Co-authored-by: Richard Schreiber <schreiber@rami.io> --------- Co-authored-by: Richard Schreiber <schreiber@rami.io>
This commit is contained in:
@@ -956,7 +956,7 @@ class Renderer:
|
|||||||
)
|
)
|
||||||
canvas.restoreState()
|
canvas.restoreState()
|
||||||
|
|
||||||
def _draw_textarea(self, canvas: Canvas, op: OrderPosition, order: Order, o: dict):
|
def _text_paragraph(self, op: OrderPosition, order: Order, o: dict, legacy_lineheight=False, override_fontsize=None):
|
||||||
font = o['fontfamily']
|
font = o['fontfamily']
|
||||||
|
|
||||||
# Since pdfmetrics.registerFont is global, we want to make sure that no one tries to sneak in a font, they
|
# Since pdfmetrics.registerFont is global, we want to make sure that no one tries to sneak in a font, they
|
||||||
@@ -970,12 +970,13 @@ class Renderer:
|
|||||||
if o['italic']:
|
if o['italic']:
|
||||||
font += ' I'
|
font += ' I'
|
||||||
|
|
||||||
|
fontsize = override_fontsize if override_fontsize is not None else float(o['fontsize'])
|
||||||
try:
|
try:
|
||||||
ad = getAscentDescent(font, float(o['fontsize']))
|
ad = getAscentDescent(font, fontsize)
|
||||||
except KeyError: # font not known, fall back
|
except KeyError: # font not known, fall back
|
||||||
logger.warning(f'Use of unknown font "{font}"')
|
logger.warning(f'Use of unknown font "{font}"')
|
||||||
font = 'Open Sans'
|
font = 'Open Sans'
|
||||||
ad = getAscentDescent(font, float(o['fontsize']))
|
ad = getAscentDescent(font, fontsize)
|
||||||
|
|
||||||
align_map = {
|
align_map = {
|
||||||
'left': TA_LEFT,
|
'left': TA_LEFT,
|
||||||
@@ -985,16 +986,17 @@ class Renderer:
|
|||||||
# lineheight display differs from browser canvas. This calc is just empirical values to get
|
# lineheight display differs from browser canvas. This calc is just empirical values to get
|
||||||
# reportlab render similarly to browser canvas.
|
# reportlab render similarly to browser canvas.
|
||||||
# for backwards compatability use „uncorrected“ lineheight of 1.0 instead of 1.15
|
# for backwards compatability use „uncorrected“ lineheight of 1.0 instead of 1.15
|
||||||
lineheight = float(o['lineheight']) * 1.15 if 'lineheight' in o else 1.0
|
lineheight = float(o['lineheight']) * 1.15 if not legacy_lineheight or 'lineheight' in o else 1.0
|
||||||
style = ParagraphStyle(
|
style = ParagraphStyle(
|
||||||
name=uuid.uuid4().hex,
|
name=uuid.uuid4().hex,
|
||||||
fontName=font,
|
fontName=font,
|
||||||
fontSize=float(o['fontsize']),
|
fontSize=fontsize,
|
||||||
leading=lineheight * float(o['fontsize']),
|
leading=lineheight * fontsize,
|
||||||
# for backwards compatability use autoLeading if no lineheight is given
|
# for backwards compatability use autoLeading if no lineheight is given
|
||||||
autoLeading='off' if 'lineheight' in o else 'max',
|
autoLeading='off' if not legacy_lineheight or 'lineheight' in o else 'max',
|
||||||
textColor=Color(o['color'][0] / 255, o['color'][1] / 255, o['color'][2] / 255),
|
textColor=Color(o['color'][0] / 255, o['color'][1] / 255, o['color'][2] / 255),
|
||||||
alignment=align_map[o['align']]
|
alignment=align_map[o['align']],
|
||||||
|
splitLongWords=o.get('splitlongwords', True),
|
||||||
)
|
)
|
||||||
# add an almost-invisible space   after hyphens as word-wrap in ReportLab only works on space chars
|
# add an almost-invisible space   after hyphens as word-wrap in ReportLab only works on space chars
|
||||||
text = conditional_escape(
|
text = conditional_escape(
|
||||||
@@ -1013,6 +1015,41 @@ class Renderer:
|
|||||||
logger.exception('Reshaping/Bidi fixes failed on string {}'.format(repr(text)))
|
logger.exception('Reshaping/Bidi fixes failed on string {}'.format(repr(text)))
|
||||||
|
|
||||||
p = Paragraph(text, style=style)
|
p = Paragraph(text, style=style)
|
||||||
|
return p, ad, lineheight
|
||||||
|
|
||||||
|
def _draw_textcontainer(self, canvas: Canvas, op: OrderPosition, order: Order, o: dict):
|
||||||
|
fontsize = float(o['fontsize'])
|
||||||
|
height = float(o['height']) * mm
|
||||||
|
width = float(o['width']) * mm
|
||||||
|
while True:
|
||||||
|
p, ad, lineheight = self._text_paragraph(op, order, o, override_fontsize=fontsize)
|
||||||
|
w, h = p.wrapOn(canvas, width, 1000 * mm)
|
||||||
|
widths = p.getActualLineWidths0()
|
||||||
|
if not widths:
|
||||||
|
break
|
||||||
|
actual_w = max(widths)
|
||||||
|
if not o.get('autoresize', False) or (h <= height and actual_w <= width) or fontsize <= 1.0:
|
||||||
|
break
|
||||||
|
if h > height: # we can do larger steps for height
|
||||||
|
fontsize -= max(1.0, fontsize * .1)
|
||||||
|
else:
|
||||||
|
fontsize -= max(.25, fontsize * .025)
|
||||||
|
|
||||||
|
canvas.saveState()
|
||||||
|
# The ascent/descent offsets here are not really proven to be correct, they're just empirical values to get
|
||||||
|
# reportlab render similarly to browser canvas.
|
||||||
|
canvas.translate(float(o['left']) * mm, float(o['bottom']) * mm + height)
|
||||||
|
canvas.rotate(o.get('rotation', 0) * -1)
|
||||||
|
if o.get('verticalalign', 'top') == 'top':
|
||||||
|
p.drawOn(canvas, 0, - h)
|
||||||
|
elif o.get('verticalalign', 'top') == 'middle':
|
||||||
|
p.drawOn(canvas, 0, (-height - h) / 2)
|
||||||
|
elif o.get('verticalalign', 'top') == 'bottom':
|
||||||
|
p.drawOn(canvas, 0, -height)
|
||||||
|
canvas.restoreState()
|
||||||
|
|
||||||
|
def _draw_textarea(self, canvas: Canvas, op: OrderPosition, order: Order, o: dict):
|
||||||
|
p, ad, lineheight = self._text_paragraph(op, order, o, legacy_lineheight=True)
|
||||||
w, h = p.wrapOn(canvas, float(o['width']) * mm, 1000 * mm)
|
w, h = p.wrapOn(canvas, float(o['width']) * mm, 1000 * mm)
|
||||||
# p_size = p.wrap(float(o['width']) * mm, 1000 * mm)
|
# p_size = p.wrap(float(o['width']) * mm, 1000 * mm)
|
||||||
canvas.saveState()
|
canvas.saveState()
|
||||||
@@ -1051,6 +1088,8 @@ class Renderer:
|
|||||||
self._draw_barcodearea(canvas, op, order, o)
|
self._draw_barcodearea(canvas, op, order, o)
|
||||||
elif o['type'] == "imagearea":
|
elif o['type'] == "imagearea":
|
||||||
self._draw_imagearea(canvas, op, order, o)
|
self._draw_imagearea(canvas, op, order, o)
|
||||||
|
elif o['type'] == "textcontainer":
|
||||||
|
self._draw_textcontainer(canvas, op, order, o)
|
||||||
elif o['type'] == "textarea":
|
elif o['type'] == "textarea":
|
||||||
self._draw_textarea(canvas, op, order, o)
|
self._draw_textarea(canvas, op, order, o)
|
||||||
elif o['type'] == "poweredby":
|
elif o['type'] == "poweredby":
|
||||||
|
|||||||
@@ -177,7 +177,7 @@
|
|||||||
{% if name %}
|
{% if name %}
|
||||||
<div class="row control-group pdf-info">
|
<div class="row control-group pdf-info">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<label>{% trans "Layout name" %}</label><br>
|
<label for="pdf-info-name">{% trans "Layout name" %}</label><br>
|
||||||
<input type="text" id="pdf-info-name" class="input-block-level form-control" name="name" value="{{ name }}">
|
<input type="text" id="pdf-info-name" class="input-block-level form-control" name="name" value="{{ name }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -185,11 +185,11 @@
|
|||||||
<div class="row control-group pdf-info">
|
<div class="row control-group pdf-info">
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label>{% trans "Width (mm)" %}</label><br>
|
<label for="pdf-info-width">{% trans "Width (mm)" %}</label><br>
|
||||||
<input type="number" id="pdf-info-width" class="input-block-level form-control">
|
<input type="number" id="pdf-info-width" class="input-block-level form-control">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label>{% trans "Height (mm)" %}</label><br>
|
<label for="pdf-info-height">{% trans "Height (mm)" %}</label><br>
|
||||||
<input type="number" id="pdf-info-height" class="input-block-level form-control">
|
<input type="number" id="pdf-info-height" class="input-block-level form-control">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -227,7 +227,7 @@
|
|||||||
<div class="row control-group pdf-info">
|
<div class="row control-group pdf-info">
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<label>{% trans "Preferred language" %}</label><br>
|
<label for="pdf-info-locale">{% trans "Preferred language" %}</label><br>
|
||||||
<select class="form-control" id="pdf-info-locale">
|
<select class="form-control" id="pdf-info-locale">
|
||||||
<option value="">{% trans "Order locale" %}</option>
|
<option value="">{% trans "Order locale" %}</option>
|
||||||
{% for l in locales %}
|
{% for l in locales %}
|
||||||
@@ -238,7 +238,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row control-group poweredby">
|
<div class="row control-group poweredby">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<label>{% trans "Style" %}</label><br>
|
<label for="toolbox-poweredby-style">{% trans "Style" %}</label><br>
|
||||||
<select class="input-block-level form-control" id="toolbox-poweredby-style">
|
<select class="input-block-level form-control" id="toolbox-poweredby-style">
|
||||||
<option value="dark">{% trans "Dark" %}</option>
|
<option value="dark">{% trans "Dark" %}</option>
|
||||||
<option value="white">{% trans "Light" %}</option>
|
<option value="white">{% trans "Light" %}</option>
|
||||||
@@ -247,7 +247,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row control-group imagecontent">
|
<div class="row control-group imagecontent">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<label>{% trans "Image content" %}</label><br>
|
<label for="toolbox-imagecontent">{% trans "Image content" %}</label><br>
|
||||||
<select class="input-block-level form-control" id="toolbox-imagecontent">
|
<select class="input-block-level form-control" id="toolbox-imagecontent">
|
||||||
<option value="">{% trans "Empty" %}</option>
|
<option value="">{% trans "Empty" %}</option>
|
||||||
{% for varname, var in images.items %}
|
{% for varname, var in images.items %}
|
||||||
@@ -258,7 +258,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row control-group text textcontent">
|
<div class="row control-group text textcontent">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<label>{% trans "Content" %}</label><br>
|
<label for="toolbox-content">{% trans "Content" %}</label><br>
|
||||||
<select class="input-block-level form-control" id="toolbox-content">
|
<select class="input-block-level form-control" id="toolbox-content">
|
||||||
{% for varname, var in variables.items %}
|
{% for varname, var in variables.items %}
|
||||||
{% if not var.hidden %}
|
{% if not var.hidden %}
|
||||||
@@ -293,31 +293,31 @@
|
|||||||
<div class="row control-group position">
|
<div class="row control-group position">
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label>{% trans "x (mm)" %}</label><br>
|
<label for="toolbox-position-x">{% trans "x (mm)" %}</label><br>
|
||||||
<input type="number" value="13" class="input-block-level form-control" step="0.01"
|
<input type="number" value="13" class="input-block-level form-control" step="0.01"
|
||||||
id="toolbox-position-x">
|
id="toolbox-position-x">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label>{% trans "y (mm)" %}</label><br>
|
<label for="toolbox-position-y">{% trans "y (mm)" %}</label><br>
|
||||||
<input type="number" value="13" class="input-block-level form-control" step="0.01"
|
<input type="number" value="13" class="input-block-level form-control" step="0.01"
|
||||||
id="toolbox-position-y">
|
id="toolbox-position-y">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row control-group rectsize">
|
<div class="row control-group rectsize">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label>{% trans "Width (mm)" %}</label><br>
|
<label for="toolbox-width">{% trans "Width (mm)" %}</label><br>
|
||||||
<input type="number" value="13" class="input-block-level form-control" step="0.01"
|
<input type="number" value="13" class="input-block-level form-control" step="0.01"
|
||||||
id="toolbox-width">
|
id="toolbox-width">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label>{% trans "Height (mm)" %}</label><br>
|
<label for="toolbox-height">{% trans "Height (mm)" %}</label><br>
|
||||||
<input type="number" value="13" class="input-block-level form-control" step="0.01"
|
<input type="number" value="13" class="input-block-level form-control" step="0.01"
|
||||||
id="toolbox-height">
|
id="toolbox-height">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row control-group squaresize poweredby">
|
<div class="row control-group squaresize poweredby">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<label>{% trans "Size (mm)" %}</label><br>
|
<label for="toolbox-squaresize">{% trans "Size (mm)" %}</label><br>
|
||||||
<input type="number" value="13" class="input-block-level form-control" step="0.01"
|
<input type="number" value="13" class="input-block-level form-control" step="0.01"
|
||||||
id="toolbox-squaresize">
|
id="toolbox-squaresize">
|
||||||
</div>
|
</div>
|
||||||
@@ -335,13 +335,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row control-group text">
|
<div class="row control-group text">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6 textarea">
|
||||||
<label>{% trans "Width (mm)" %}</label><br>
|
<label for="toolbox-textwidth">{% trans "Width (mm)" %}</label><br>
|
||||||
<input type="number" value="13" class="input-block-level form-control" step="0.01"
|
<input type="number" value="13" class="input-block-level form-control" step="0.01"
|
||||||
id="toolbox-textwidth">
|
id="toolbox-textwidth">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label>{% trans "Rotation (°)" %}</label><br>
|
<label for="toolbox-textrotation">{% trans "Rotation (°)" %}</label><br>
|
||||||
<input type="number" value="0" class="input-block-level form-control" step="0.1"
|
<input type="number" value="0" class="input-block-level form-control" step="0.1"
|
||||||
id="toolbox-textrotation">
|
id="toolbox-textrotation">
|
||||||
</div>
|
</div>
|
||||||
@@ -349,7 +349,7 @@
|
|||||||
<div class="row control-group text">
|
<div class="row control-group text">
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<label>{% trans "Font" %}</label><br>
|
<label for="toolbox-fontfamily">{% trans "Font" %}</label><br>
|
||||||
<select class="input-block-level form-control" id="toolbox-fontfamily">
|
<select class="input-block-level form-control" id="toolbox-fontfamily">
|
||||||
<option>Open Sans</option>
|
<option>Open Sans</option>
|
||||||
{% for family in fonts.keys %}
|
{% for family in fonts.keys %}
|
||||||
@@ -360,43 +360,50 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row control-group text">
|
<div class="row control-group text">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label>{% trans "Font size (pt)" %}</label><br>
|
<label for="toolbox-fontsize">{% trans "Font size (pt)" %}</label><br>
|
||||||
<input type="number" value="13" class="input-block-level form-control" step="0.1"
|
<input type="number" value="13" class="input-block-level form-control" step="0.1"
|
||||||
id="toolbox-fontsize">
|
id="toolbox-fontsize">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label>{% trans "Line height" %}</label><br>
|
<label for="toolbox-lineheight">{% trans "Line height" %}</label><br>
|
||||||
<input type="number" value="1" class="input-block-level form-control" step="0.1"
|
<input type="number" value="1" class="input-block-level form-control" step="0.1"
|
||||||
id="toolbox-lineheight">
|
id="toolbox-lineheight">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row control-group text">
|
<div class="row control-group text">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label>{% trans "Text color" %}</label><br>
|
<label for="toolbox-col">{% trans "Text color" %}</label><br>
|
||||||
<input type="text" value="#000000" class="input-block-level form-control colorpickerfield"
|
<div class="input-group">
|
||||||
id="toolbox-col">
|
<input type="text" value="#000000" class="input-block-level form-control colorpickerfield"
|
||||||
|
id="toolbox-col">
|
||||||
|
<span class="input-group-addon contrast-icon">
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label> </label><br>
|
<label> </label><br>
|
||||||
<div class="btn-group btn-group-justified" role="group">
|
<div class="btn-group btn-group-justified" role="group">
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group text" role="group">
|
||||||
<button type="button" class="btn btn-default toggling" data-action="bold">
|
<button type="button" class="btn btn-default toggling" data-action="bold">
|
||||||
<span class="fa fa-bold"></span>
|
<span class="fa fa-bold"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group text" role="group">
|
||||||
<button type="button" class="btn btn-default toggling" data-action="italic">
|
<button type="button" class="btn btn-default toggling" data-action="italic">
|
||||||
<span class="fa fa-italic"></span>
|
<span class="fa fa-italic"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group textarea" role="group">
|
||||||
<button type="button" class="btn btn-default toggling" data-action="downward"
|
<button type="button" class="btn btn-default toggling" data-action="downward"
|
||||||
data-toggle="tooltip" title="{% trans "Flow multiple lines downward from specified position" %}">
|
data-toggle="tooltip" title="{% trans "Flow multiple lines downward from specified position" %}">
|
||||||
<span class="fa fa-caret-square-o-down"></span>
|
<span class="fa fa-caret-square-o-down"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<label> </label><br>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row control-group text">
|
||||||
|
<div class="col-sm-6">
|
||||||
<div class="btn-group btn-group-justified" id="toolbox-align">
|
<div class="btn-group btn-group-justified" id="toolbox-align">
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group" role="group">
|
||||||
<button type="button" class="btn btn-default option toggling" data-action="left">
|
<button type="button" class="btn btn-default option toggling" data-action="left">
|
||||||
@@ -415,6 +422,45 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div class="textcontainer">
|
||||||
|
<div class="btn-group btn-group-justified" id="toolbox-verticalalign">
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
<button type="button" class="btn btn-default option toggling" data-action="top">
|
||||||
|
<span class="fa fa-toggle-down"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
<button type="button" class="btn btn-default option toggling" data-action="middle">
|
||||||
|
<span class="fa fa-sort"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
<button type="button" class="btn btn-default option toggling" data-action="bottom">
|
||||||
|
<span class="fa fa-toggle-up"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row control-group textcontainer">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div class="btn-group btn-group-justified">
|
||||||
|
<div class="btn-group textcontainer" role="group">
|
||||||
|
<button type="button" class="btn btn-default toggling" data-action="autoresize"
|
||||||
|
data-toggle="tooltip" title="{% trans "Automatically reduce font size to fit content" %}">
|
||||||
|
<span class="fa fa-text-height"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group textcontainer" role="group">
|
||||||
|
<button type="button" class="btn btn-default toggling" data-action="splitlongwords"
|
||||||
|
data-toggle="tooltip" title="{% trans "Allow long words to be split (preview is not accurate)" %}">
|
||||||
|
<span class="fa fa-scissors fa-rotate-90"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -423,9 +469,13 @@
|
|||||||
{% trans "Add a new object" %}
|
{% trans "Add a new object" %}
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body add-buttons">
|
<div class="panel-body add-buttons">
|
||||||
|
<button class="btn btn-default btn-block" id="editor-add-textcontainer" disabled>
|
||||||
|
<span class="fa fa-font"></span>
|
||||||
|
{% trans "Text box" %}
|
||||||
|
</button>
|
||||||
<button class="btn btn-default btn-block" id="editor-add-text" disabled>
|
<button class="btn btn-default btn-block" id="editor-add-text" disabled>
|
||||||
<span class="fa fa-font"></span>
|
<span class="fa fa-font"></span>
|
||||||
{% trans "Text" %}
|
{% trans "Text (deprecated)" %}
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-default btn-block" id="editor-add-qrcode" data-content="secret" disabled>
|
<button class="btn btn-default btn-block" id="editor-add-qrcode" data-content="secret" disabled>
|
||||||
<span class="fa fa-qrcode"></span>
|
<span class="fa fa-qrcode"></span>
|
||||||
@@ -456,7 +506,6 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form method="post" action="" id="preview-form" target="_blank">
|
<form method="post" action="" id="preview-form" target="_blank">
|
||||||
<div class="form-group submit-group">
|
<div class="form-group submit-group">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
@@ -472,6 +521,13 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<p> </p>
|
||||||
|
<div class="alert alert-info" id="version-notice">
|
||||||
|
{% blocktrans trimmed with print_version="2.18" scan_version="1.22" %}
|
||||||
|
This layout uses new features. If you print from your device, make sure you use pretixPRINT version
|
||||||
|
{{ print_version }} (or newer) or pretixSCAN Desktop version {{ scan_version }} (or newer).
|
||||||
|
{% endblocktrans %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/plain" id="schema-url">{% static "schema/pdf-layout.schema.json" %}</script>
|
<script type="text/plain" id="schema-url">{% static "schema/pdf-layout.schema.json" %}</script>
|
||||||
|
|||||||
@@ -30,11 +30,11 @@ def _simple_template(w, h):
|
|||||||
company_size = name_size - 2
|
company_size = name_size - 2
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
"type": "textarea",
|
"type": "textcontainer",
|
||||||
"page": 1,
|
"page": 1,
|
||||||
"locale": "",
|
"locale": "",
|
||||||
"left": "5.00",
|
"left": "5.00",
|
||||||
"bottom": "%.2f" % (((h - company_size * 1.5 - name_size) / 2 + company_size * 1.5) / mm),
|
"bottom": "%.2f" % (h / mm / 2 + 2),
|
||||||
"fontsize": name_size,
|
"fontsize": name_size,
|
||||||
"lineheight": "1",
|
"lineheight": "1",
|
||||||
"color": [0, 0, 0, 1],
|
"color": [0, 0, 0, 1],
|
||||||
@@ -42,19 +42,22 @@ def _simple_template(w, h):
|
|||||||
"bold": True,
|
"bold": True,
|
||||||
"italic": False,
|
"italic": False,
|
||||||
"width": "%.2f" % (w / mm - 10),
|
"width": "%.2f" % (w / mm - 10),
|
||||||
"downward": False,
|
"height": "%.2f" % (h / mm / 2 - 7),
|
||||||
"content": "attendee_name",
|
"content": "attendee_name",
|
||||||
"text": "John Doe",
|
"text": "Dr John Doe",
|
||||||
"text_i18n": {},
|
"text_i18n": {},
|
||||||
"rotation": 0,
|
"rotation": 0,
|
||||||
"align": "center",
|
"align": "center",
|
||||||
|
"verticalalign": "bottom",
|
||||||
|
"autoresize": True,
|
||||||
|
"splitlongwords": False,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "textarea",
|
"type": "textcontainer",
|
||||||
"page": 1,
|
"page": 1,
|
||||||
"locale": "",
|
"locale": "",
|
||||||
"left": "5.00",
|
"left": "5.00",
|
||||||
"bottom": "%.2f" % ((((h - company_size * 1.5 - name_size) / 2) + company_size) / mm),
|
"bottom": "5.00",
|
||||||
"fontsize": company_size,
|
"fontsize": company_size,
|
||||||
"lineheight": "1",
|
"lineheight": "1",
|
||||||
"color": [0, 0, 0, 1],
|
"color": [0, 0, 0, 1],
|
||||||
@@ -62,12 +65,15 @@ def _simple_template(w, h):
|
|||||||
"bold": False,
|
"bold": False,
|
||||||
"italic": False,
|
"italic": False,
|
||||||
"width": "%.2f" % (w / mm - 10),
|
"width": "%.2f" % (w / mm - 10),
|
||||||
"downward": True,
|
"height": "%.2f" % (h / mm / 2 - 7),
|
||||||
"content": "attendee_company",
|
"content": "attendee_company",
|
||||||
"text": "Sample company",
|
"text": "Sample company",
|
||||||
"text_i18n": {},
|
"text_i18n": {},
|
||||||
"rotation": 0,
|
"rotation": 0,
|
||||||
"align": "center",
|
"align": "center",
|
||||||
|
"verticalalign": "top",
|
||||||
|
"autoresize": True,
|
||||||
|
"splitlongwords": False,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -94,15 +100,17 @@ TEMPLATES = {
|
|||||||
"layout": _simple_template(*pagesizes.portrait(pagesizes.A7)),
|
"layout": _simple_template(*pagesizes.portrait(pagesizes.A7)),
|
||||||
},
|
},
|
||||||
"82x203butterfly": {
|
"82x203butterfly": {
|
||||||
"label": format_lazy(_("{width} x {height} mm butterfly badge"), width=82, height=203),
|
"label": format_lazy(
|
||||||
|
_("{width} x {height} mm butterfly badge"), width=82, height=203
|
||||||
|
),
|
||||||
"pagesize": (82 * mm, 203 * mm),
|
"pagesize": (82 * mm, 203 * mm),
|
||||||
"layout": [
|
"layout": [
|
||||||
{
|
{
|
||||||
"type": "textarea",
|
"type": "textcontainer",
|
||||||
"page": 1,
|
"page": 1,
|
||||||
"locale": "",
|
"locale": "",
|
||||||
"left": "5.00",
|
"left": "5.00",
|
||||||
"bottom": "152.55",
|
"bottom": "153.00",
|
||||||
"fontsize": "20.0",
|
"fontsize": "20.0",
|
||||||
"lineheight": "1",
|
"lineheight": "1",
|
||||||
"color": [0, 0, 0, 1],
|
"color": [0, 0, 0, 1],
|
||||||
@@ -110,19 +118,22 @@ TEMPLATES = {
|
|||||||
"bold": True,
|
"bold": True,
|
||||||
"italic": False,
|
"italic": False,
|
||||||
"width": "72.00",
|
"width": "72.00",
|
||||||
"downward": False,
|
"height": "20.00",
|
||||||
"content": "attendee_name",
|
"content": "attendee_name",
|
||||||
"text": "John Doe",
|
"text": "Dr John Doe",
|
||||||
"text_i18n": {},
|
"text_i18n": {},
|
||||||
"rotation": 0,
|
"rotation": 0,
|
||||||
"align": "center",
|
"align": "center",
|
||||||
|
"verticalalign": "bottom",
|
||||||
|
"autoresize": True,
|
||||||
|
"splitlongwords": False,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "textarea",
|
"type": "textcontainer",
|
||||||
"page": 1,
|
"page": 1,
|
||||||
"locale": "",
|
"locale": "",
|
||||||
"left": "5.00",
|
"left": "5.00",
|
||||||
"bottom": "144.55",
|
"bottom": "132.10",
|
||||||
"fontsize": "18.0",
|
"fontsize": "18.0",
|
||||||
"lineheight": "1",
|
"lineheight": "1",
|
||||||
"color": [0, 0, 0, 1],
|
"color": [0, 0, 0, 1],
|
||||||
@@ -130,19 +141,22 @@ TEMPLATES = {
|
|||||||
"bold": False,
|
"bold": False,
|
||||||
"italic": False,
|
"italic": False,
|
||||||
"width": "72.00",
|
"width": "72.00",
|
||||||
"downward": False,
|
"height": "20.00",
|
||||||
"content": "attendee_company",
|
"content": "attendee_company",
|
||||||
"text": "Sample company",
|
"text": "Sample company",
|
||||||
"text_i18n": {},
|
"text_i18n": {},
|
||||||
"rotation": 0,
|
"rotation": 0,
|
||||||
"align": "center",
|
"align": "center",
|
||||||
|
"verticalalign": "top",
|
||||||
|
"autoresize": True,
|
||||||
|
"splitlongwords": False,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "textarea",
|
"type": "textcontainer",
|
||||||
"page": 1,
|
"page": 1,
|
||||||
"locale": "",
|
"locale": "",
|
||||||
"left": "77.10",
|
"left": "76.97",
|
||||||
"bottom": "34.68",
|
"bottom": "10.86",
|
||||||
"fontsize": "20.0",
|
"fontsize": "20.0",
|
||||||
"lineheight": "1",
|
"lineheight": "1",
|
||||||
"color": [0, 0, 0, 1],
|
"color": [0, 0, 0, 1],
|
||||||
@@ -150,19 +164,22 @@ TEMPLATES = {
|
|||||||
"bold": True,
|
"bold": True,
|
||||||
"italic": False,
|
"italic": False,
|
||||||
"width": "72.00",
|
"width": "72.00",
|
||||||
"downward": False,
|
"height": "20.00",
|
||||||
"content": "attendee_name",
|
"content": "attendee_name",
|
||||||
"text": "John Doe",
|
"text": "Dr John Doe",
|
||||||
"text_i18n": {},
|
"text_i18n": {},
|
||||||
"rotation": 180,
|
"rotation": -180,
|
||||||
"align": "center",
|
"align": "center",
|
||||||
|
"verticalalign": "bottom",
|
||||||
|
"autoresize": True,
|
||||||
|
"splitlongwords": False,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "textarea",
|
"type": "textcontainer",
|
||||||
"page": 1,
|
"page": 1,
|
||||||
"locale": "",
|
"locale": "",
|
||||||
"left": "77.06",
|
"left": "77.07",
|
||||||
"bottom": "44.28",
|
"bottom": "31.76",
|
||||||
"fontsize": "18.0",
|
"fontsize": "18.0",
|
||||||
"lineheight": "1",
|
"lineheight": "1",
|
||||||
"color": [0, 0, 0, 1],
|
"color": [0, 0, 0, 1],
|
||||||
@@ -170,12 +187,15 @@ TEMPLATES = {
|
|||||||
"bold": False,
|
"bold": False,
|
||||||
"italic": False,
|
"italic": False,
|
||||||
"width": "72.00",
|
"width": "72.00",
|
||||||
"downward": False,
|
"height": "20.00",
|
||||||
"content": "attendee_company",
|
"content": "attendee_company",
|
||||||
"text": "Sample company",
|
"text": "Sample company",
|
||||||
"text_i18n": {},
|
"text_i18n": {},
|
||||||
"rotation": 180,
|
"rotation": -180,
|
||||||
"align": "center",
|
"align": "center",
|
||||||
|
"verticalalign": "top",
|
||||||
|
"autoresize": True,
|
||||||
|
"splitlongwords": False,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -235,7 +255,9 @@ TEMPLATES = {
|
|||||||
"layout": _simple_template(40 * mm, 40 * mm),
|
"layout": _simple_template(40 * mm, 40 * mm),
|
||||||
},
|
},
|
||||||
"88.9x33.87": {
|
"88.9x33.87": {
|
||||||
"label": format_lazy(_("{width} x {height} mm label"), width=88.9, height=33.87),
|
"label": format_lazy(
|
||||||
|
_("{width} x {height} mm label"), width=88.9, height=33.87
|
||||||
|
),
|
||||||
"pagesize": (88.9 * mm, 33.87 * mm),
|
"pagesize": (88.9 * mm, 33.87 * mm),
|
||||||
"layout": _simple_template(88.9 * mm, 33.87 * mm),
|
"layout": _simple_template(88.9 * mm, 33.87 * mm),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -27,191 +27,279 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
|
|
||||||
from pretix.base.models import LoggedModel
|
from pretix.base.models import LoggedModel
|
||||||
|
|
||||||
DEFAULT_TICKET_LAYOUT = '''[{
|
DEFAULT_TICKET_LAYOUT = '''[
|
||||||
"type":"textarea",
|
{
|
||||||
"left":"17.50",
|
"type": "barcodearea",
|
||||||
"bottom":"274.60",
|
"page": 1,
|
||||||
"fontsize":"16.0",
|
"left": "130.40",
|
||||||
"color":[
|
"bottom": "204.50",
|
||||||
0,
|
"size": "64.00",
|
||||||
0,
|
"content": "secret",
|
||||||
0,
|
"text": "",
|
||||||
1
|
"text_i18n": {},
|
||||||
],
|
"nowhitespace": false
|
||||||
"fontfamily":"Open Sans",
|
},
|
||||||
"bold":false,
|
{
|
||||||
"italic":false,
|
"type": "poweredby",
|
||||||
"width":"175.00",
|
"page": 1,
|
||||||
"content":"event_name",
|
"left": "88.72",
|
||||||
"text":"Sample event name",
|
"bottom": "10.00",
|
||||||
"align":"left"
|
"size": "20.00",
|
||||||
},
|
"content": "dark"
|
||||||
{
|
},
|
||||||
"type":"textarea",
|
{
|
||||||
"left":"17.50",
|
"type": "textcontainer",
|
||||||
"bottom":"262.90",
|
"page": 1,
|
||||||
"fontsize":"13.0",
|
"locale": "",
|
||||||
"color":[
|
"left": "16.35",
|
||||||
0,
|
"bottom": "272.09",
|
||||||
0,
|
"fontsize": "14.0",
|
||||||
0,
|
"lineheight": "1",
|
||||||
1
|
"color": [
|
||||||
],
|
0,
|
||||||
"fontfamily":"Open Sans",
|
0,
|
||||||
"bold":false,
|
0,
|
||||||
"italic":false,
|
1
|
||||||
"width":"110.00",
|
],
|
||||||
"content":"itemvar",
|
"fontfamily": "Open Sans",
|
||||||
"text":"Sample product – sample variation",
|
"bold": false,
|
||||||
"align":"left"
|
"italic": false,
|
||||||
},
|
"width": "177.07",
|
||||||
{
|
"height": "11.80",
|
||||||
"type":"textarea",
|
"content": "event_name",
|
||||||
"left":"17.50",
|
"text": "Sample event name",
|
||||||
"bottom":"252.50",
|
"text_i18n": {},
|
||||||
"fontsize":"13.0",
|
"rotation": 0,
|
||||||
"color":[
|
"align": "left",
|
||||||
0,
|
"verticalalign": "middle",
|
||||||
0,
|
"autoresize": true,
|
||||||
0,
|
"splitlongwords": true
|
||||||
1
|
},
|
||||||
],
|
{
|
||||||
"fontfamily":"Open Sans",
|
"type": "textcontainer",
|
||||||
"bold":false,
|
"page": 1,
|
||||||
"italic":false,
|
"locale": "",
|
||||||
"width":"110.00",
|
"left": "16.35",
|
||||||
"content":"attendee_name",
|
"bottom": "261.77",
|
||||||
"text":"John Doe",
|
"fontsize": "13.0",
|
||||||
"align":"left"
|
"lineheight": "1",
|
||||||
},
|
"color": [
|
||||||
{
|
0,
|
||||||
"type":"textarea",
|
0,
|
||||||
"left":"17.50",
|
0,
|
||||||
"bottom":"242.10",
|
1
|
||||||
"fontsize":"13.0",
|
],
|
||||||
"color":[
|
"fontfamily": "Open Sans",
|
||||||
0,
|
"bold": false,
|
||||||
0,
|
"italic": false,
|
||||||
0,
|
"width": "113.03",
|
||||||
1
|
"height": "7.83",
|
||||||
],
|
"content": "itemvar",
|
||||||
"fontfamily":"Open Sans",
|
"text": "Sample product – sample variation",
|
||||||
"bold":false,
|
"text_i18n": {},
|
||||||
"italic":false,
|
"rotation": 0,
|
||||||
"width":"110.00",
|
"align": "left",
|
||||||
"content":"event_begin",
|
"verticalalign": "middle",
|
||||||
"text":"2016-05-31 20:00",
|
"autoresize": true,
|
||||||
"align":"left"
|
"splitlongwords": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type":"textarea",
|
"type": "textcontainer",
|
||||||
"left":"17.50",
|
"page": 1,
|
||||||
"bottom":"231.70",
|
"locale": "",
|
||||||
"fontsize":"13.0",
|
"left": "16.35",
|
||||||
"color":[
|
"bottom": "251.30",
|
||||||
0,
|
"fontsize": "13.0",
|
||||||
0,
|
"lineheight": "1",
|
||||||
0,
|
"color": [
|
||||||
1
|
0,
|
||||||
],
|
0,
|
||||||
"fontfamily":"Open Sans",
|
0,
|
||||||
"bold":false,
|
1
|
||||||
"italic":false,
|
],
|
||||||
"width":"110.00",
|
"fontfamily": "Open Sans",
|
||||||
"content":"seat",
|
"bold": false,
|
||||||
"text":"Ground floor, Row 3, Seat 4",
|
"italic": false,
|
||||||
"align":"left"
|
"width": "113.03",
|
||||||
},
|
"height": "7.83",
|
||||||
{
|
"content": "attendee_name",
|
||||||
"type":"textarea",
|
"text": "Dr John Doe",
|
||||||
"left":"17.50",
|
"text_i18n": {},
|
||||||
"bottom":"204.80",
|
"rotation": 0,
|
||||||
"fontsize":"13.0",
|
"align": "left",
|
||||||
"color":[
|
"verticalalign": "middle",
|
||||||
0,
|
"autoresize": true,
|
||||||
0,
|
"splitlongwords": true
|
||||||
0,
|
},
|
||||||
1
|
{
|
||||||
],
|
"type": "textcontainer",
|
||||||
"fontfamily":"Open Sans",
|
"page": 1,
|
||||||
"bold":false,
|
"locale": "",
|
||||||
"italic":false,
|
"left": "16.35",
|
||||||
"width":"110.00",
|
"bottom": "240.30",
|
||||||
"content":"event_location",
|
"fontsize": "13.0",
|
||||||
"text":"Random City",
|
"lineheight": "1",
|
||||||
"align":"left"
|
"color": [
|
||||||
},
|
0,
|
||||||
{
|
0,
|
||||||
"type":"textarea",
|
0,
|
||||||
"left":"17.50",
|
1
|
||||||
"bottom":"194.50",
|
],
|
||||||
"fontsize":"13.0",
|
"fontfamily": "Open Sans",
|
||||||
"color":[
|
"bold": false,
|
||||||
0,
|
"italic": false,
|
||||||
0,
|
"width": "113.03",
|
||||||
0,
|
"height": "7.83",
|
||||||
1
|
"content": "event_begin",
|
||||||
],
|
"text": "2017-05-31 20:00",
|
||||||
"fontfamily":"Open Sans",
|
"text_i18n": {},
|
||||||
"bold":false,
|
"rotation": 0,
|
||||||
"italic":false,
|
"align": "left",
|
||||||
"width":"30.00",
|
"verticalalign": "middle",
|
||||||
"content":"order",
|
"autoresize": true,
|
||||||
"text":"A1B2C",
|
"splitlongwords": true
|
||||||
"align":"left"
|
},
|
||||||
},
|
{
|
||||||
{
|
"type": "textcontainer",
|
||||||
"type":"textarea",
|
"page": 1,
|
||||||
"left":"52.50",
|
"locale": "",
|
||||||
"bottom":"194.50",
|
"left": "16.35",
|
||||||
"fontsize":"13.0",
|
"bottom": "231.30",
|
||||||
"color":[
|
"fontsize": "13.0",
|
||||||
0,
|
"lineheight": "1",
|
||||||
0,
|
"color": [
|
||||||
0,
|
0,
|
||||||
1
|
0,
|
||||||
],
|
0,
|
||||||
"fontfamily":"Open Sans",
|
1
|
||||||
"bold":false,
|
],
|
||||||
"italic":false,
|
"fontfamily": "Open Sans",
|
||||||
"width":"45.00",
|
"bold": false,
|
||||||
"content":"price",
|
"italic": false,
|
||||||
"text":"123.45 EUR",
|
"width": "113.03",
|
||||||
"align":"right"
|
"height": "7.83",
|
||||||
},
|
"content": "seat",
|
||||||
{
|
"text": "Ground floor, Row 3, Seat 4",
|
||||||
"type":"textarea",
|
"text_i18n": {},
|
||||||
"left":"102.50",
|
"rotation": 0,
|
||||||
"bottom":"194.50",
|
"align": "left",
|
||||||
"fontsize":"13.0",
|
"verticalalign": "middle",
|
||||||
"color":[
|
"autoresize": true,
|
||||||
0,
|
"splitlongwords": true
|
||||||
0,
|
},
|
||||||
0,
|
{
|
||||||
1
|
"type": "textcontainer",
|
||||||
],
|
"page": 1,
|
||||||
"fontfamily":"Open Sans",
|
"locale": "",
|
||||||
"bold":false,
|
"left": "16.35",
|
||||||
"italic":false,
|
"bottom": "203.43",
|
||||||
"width":"90.00",
|
"fontsize": "13.0",
|
||||||
"content":"secret",
|
"lineheight": "1",
|
||||||
"text":"tdmruoekvkpbv1o2mv8xccvqcikvr58u",
|
"color": [
|
||||||
"align":"left"
|
0,
|
||||||
},
|
0,
|
||||||
{
|
0,
|
||||||
"type":"barcodearea",
|
1
|
||||||
"left":"130.40",
|
],
|
||||||
"bottom":"204.50",
|
"fontfamily": "Open Sans",
|
||||||
"size":"64.00",
|
"bold": false,
|
||||||
"content":"secret"
|
"italic": false,
|
||||||
},
|
"width": "113.03",
|
||||||
{
|
"height": "25.70",
|
||||||
"type":"poweredby",
|
"content": "event_location",
|
||||||
"left":"88.72",
|
"text": "Random City",
|
||||||
"bottom":"10.00",
|
"text_i18n": {},
|
||||||
"size":"20.00",
|
"rotation": 0,
|
||||||
"content":"dark"
|
"align": "left",
|
||||||
}]'''
|
"verticalalign": "bottom",
|
||||||
|
"autoresize": true,
|
||||||
|
"splitlongwords": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "textcontainer",
|
||||||
|
"page": 1,
|
||||||
|
"locale": "",
|
||||||
|
"left": "101.50",
|
||||||
|
"bottom": "193.33",
|
||||||
|
"fontsize": "13.0",
|
||||||
|
"lineheight": "1",
|
||||||
|
"color": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"fontfamily": "Open Sans",
|
||||||
|
"bold": false,
|
||||||
|
"italic": false,
|
||||||
|
"width": "91.93",
|
||||||
|
"height": "7.83",
|
||||||
|
"content": "secret",
|
||||||
|
"text": "tdmruoekvkpbv1o2mv8xccvqcikvr58u",
|
||||||
|
"text_i18n": {},
|
||||||
|
"rotation": 0,
|
||||||
|
"align": "left",
|
||||||
|
"verticalalign": "middle",
|
||||||
|
"autoresize": true,
|
||||||
|
"splitlongwords": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "textcontainer",
|
||||||
|
"page": 1,
|
||||||
|
"locale": "",
|
||||||
|
"left": "51.50",
|
||||||
|
"bottom": "193.33",
|
||||||
|
"fontsize": "13.0",
|
||||||
|
"lineheight": "1",
|
||||||
|
"color": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"fontfamily": "Open Sans",
|
||||||
|
"bold": false,
|
||||||
|
"italic": false,
|
||||||
|
"width": "47.38",
|
||||||
|
"height": "7.83",
|
||||||
|
"content": "price",
|
||||||
|
"text": "123.45 EUR",
|
||||||
|
"text_i18n": {},
|
||||||
|
"rotation": 0,
|
||||||
|
"align": "right",
|
||||||
|
"verticalalign": "middle",
|
||||||
|
"autoresize": true,
|
||||||
|
"splitlongwords": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "textcontainer",
|
||||||
|
"page": 1,
|
||||||
|
"locale": "",
|
||||||
|
"left": "16.50",
|
||||||
|
"bottom": "193.33",
|
||||||
|
"fontsize": "13.0",
|
||||||
|
"lineheight": "1",
|
||||||
|
"color": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"fontfamily": "Open Sans",
|
||||||
|
"bold": false,
|
||||||
|
"italic": false,
|
||||||
|
"width": "32.32",
|
||||||
|
"height": "7.83",
|
||||||
|
"content": "order",
|
||||||
|
"text": "A1B2C",
|
||||||
|
"text_i18n": {},
|
||||||
|
"rotation": 0,
|
||||||
|
"align": "left",
|
||||||
|
"verticalalign": "middle",
|
||||||
|
"autoresize": true,
|
||||||
|
"splitlongwords": true
|
||||||
|
}
|
||||||
|
]'''
|
||||||
|
|
||||||
|
|
||||||
def bg_name(instance, filename: str) -> str:
|
def bg_name(instance, filename: str) -> str:
|
||||||
|
|||||||
@@ -47,6 +47,105 @@ fabric.Imagearea = fabric.util.createClass(fabric.Rect, {
|
|||||||
fabric.Imagearea.fromObject = function (object, callback, forceAsync) {
|
fabric.Imagearea.fromObject = function (object, callback, forceAsync) {
|
||||||
return fabric.Object._fromObject('Imagearea', object, callback, forceAsync);
|
return fabric.Object._fromObject('Imagearea', object, callback, forceAsync);
|
||||||
};
|
};
|
||||||
|
fabric.Textcontainer = fabric.util.createClass(fabric.Rect, {
|
||||||
|
type: 'textcontainer',
|
||||||
|
|
||||||
|
initialize: function (text, options) {
|
||||||
|
options || (options = {});
|
||||||
|
|
||||||
|
this.callSuper('initialize', options);
|
||||||
|
|
||||||
|
//this.textbox = new fabric.Textbox(text, JSON.parse(JSON.stringify(options)));
|
||||||
|
this.set('content', options.content || '');
|
||||||
|
|
||||||
|
this.cacheProperties.push(
|
||||||
|
"width", "height", "fontSize", "lineHeight", "fill", "fontFamily", "fontWeight",
|
||||||
|
"fontStyle", "text", "textAlign", "splitLongWords", "splitByGrapheme", "verticalAlign",
|
||||||
|
"autoResize",
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
toObject: function (propertiesToInclude) {
|
||||||
|
return this.callSuper('toObject', ['content'].concat(propertiesToInclude));
|
||||||
|
},
|
||||||
|
|
||||||
|
_internalTextbox: function () {
|
||||||
|
var fontSize = parseFloat(this.fontSize);
|
||||||
|
var text = (this.text || "").replace("-", "-\u200B");
|
||||||
|
while (true) {
|
||||||
|
var tmptext = new fabric.Textbox(text, {
|
||||||
|
_wordJoiners: /[ \t\r\u200B]/u,
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
originY: 'top',
|
||||||
|
originX: 'left',
|
||||||
|
width: this.width,
|
||||||
|
height: this.height,
|
||||||
|
fontSize: fontSize,
|
||||||
|
lineHeight: this.lineHeight,
|
||||||
|
fill: this.fill,
|
||||||
|
fontFamily: this.fontFamily,
|
||||||
|
fontWeight: this.fontWeight,
|
||||||
|
fontStyle: this.fontStyle,
|
||||||
|
text: text,
|
||||||
|
textAlign: this.textAlign,
|
||||||
|
splitByGrapheme: this.splitLongWords
|
||||||
|
})
|
||||||
|
tmptext.setCoords();
|
||||||
|
var lineHeights = 0;
|
||||||
|
for (var i = 0, len = tmptext._textLines.length; i < len; i++) {
|
||||||
|
var heightOfLine = tmptext.getHeightOfLine(i);
|
||||||
|
lineHeights += heightOfLine;
|
||||||
|
}
|
||||||
|
if (!this.autoResize || (lineHeights <= this.height && tmptext.width <= this.width) || fontSize <= 1.0) {
|
||||||
|
return {textbox: tmptext, height: lineHeights, width: tmptext.width}
|
||||||
|
}
|
||||||
|
if (lineHeights > this.height) { // we can do larger steps for height
|
||||||
|
fontSize = fontSize - Math.max(1.0, fontSize * .1)
|
||||||
|
} else {
|
||||||
|
fontSize = fontSize - Math.max(.25, fontSize * .025)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_render: function (ctx) {
|
||||||
|
var h = this.height, w = this.width;
|
||||||
|
|
||||||
|
/*
|
||||||
|
var x = -this.width / 2,
|
||||||
|
y = -this.height / 2;
|
||||||
|
ctx.fillStyle = '#ccc';
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(x, y);
|
||||||
|
ctx.lineTo(x + w, y);
|
||||||
|
ctx.lineTo(x + w, y + h);
|
||||||
|
ctx.lineTo(x, y + h);
|
||||||
|
ctx.lineTo(x, y);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.fill();
|
||||||
|
*/
|
||||||
|
var { textbox, height, width } = this._internalTextbox();
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
if (this.verticalAlign === "top") {
|
||||||
|
ctx.translate(0, - (h - height) / 2);
|
||||||
|
} else if (this.verticalAlign === "bottom") {
|
||||||
|
ctx.translate(0, (h - height) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// it is entirely unclear to me why overflow is always rendered centered, so we manually readjust
|
||||||
|
if (this.textAlign === "left" && width > w) {
|
||||||
|
ctx.translate(-(w - width) / 2, 0);
|
||||||
|
} else if (this.verticalAlign === "right" && width > w) {
|
||||||
|
ctx.translate((w - width) / 2, 0);
|
||||||
|
}
|
||||||
|
textbox._render(ctx);
|
||||||
|
ctx.restore();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
fabric.Textcontainer.fromObject = function (object, callback, forceAsync) {
|
||||||
|
return fabric.Object._fromObject('Textcontainer', object, callback, forceAsync);
|
||||||
|
};
|
||||||
fabric.Barcodearea = fabric.util.createClass(fabric.Rect, {
|
fabric.Barcodearea = fabric.util.createClass(fabric.Rect, {
|
||||||
type: 'barcodearea',
|
type: 'barcodearea',
|
||||||
|
|
||||||
@@ -150,9 +249,10 @@ var editor = {
|
|||||||
top += o.group.top + o.group.height / 2;
|
top += o.group.top + o.group.height / 2;
|
||||||
left += o.group.left + o.group.width / 2;
|
left += o.group.left + o.group.width / 2;
|
||||||
}
|
}
|
||||||
|
var col, bottom;
|
||||||
if (o.type === "textarea") {
|
if (o.type === "textarea") {
|
||||||
var col = (new fabric.Color(o.fill))._source;
|
col = (new fabric.Color(o.fill))._source;
|
||||||
var bottom = editor.pdf_viewport.height - o.height - top;
|
bottom = editor.pdf_viewport.height - o.height - top;
|
||||||
if (o.downward) {
|
if (o.downward) {
|
||||||
bottom = editor.pdf_viewport.height - top;
|
bottom = editor.pdf_viewport.height - top;
|
||||||
}
|
}
|
||||||
@@ -176,6 +276,32 @@ var editor = {
|
|||||||
rotation: o.angle,
|
rotation: o.angle,
|
||||||
align: o.textAlign,
|
align: o.textAlign,
|
||||||
});
|
});
|
||||||
|
} else if (o.type === "textcontainer") {
|
||||||
|
col = (new fabric.Color(o.fill))._source;
|
||||||
|
bottom = editor.pdf_viewport.height - o.height - top;
|
||||||
|
d.push({
|
||||||
|
type: "textcontainer",
|
||||||
|
page: editor.pdf_page_number,
|
||||||
|
locale: $("#pdf-info-locale").val(),
|
||||||
|
left: editor._px2mm(left).toFixed(2),
|
||||||
|
bottom: editor._px2mm(bottom).toFixed(2),
|
||||||
|
fontsize: editor._px2pt(o.fontSize).toFixed(1),
|
||||||
|
lineheight: o.lineHeight,
|
||||||
|
color: col,
|
||||||
|
fontfamily: o.fontFamily,
|
||||||
|
bold: o.fontWeight === 'bold',
|
||||||
|
italic: o.fontStyle === 'italic',
|
||||||
|
width: editor._px2mm(o.width).toFixed(2),
|
||||||
|
height: editor._px2mm(o.height).toFixed(2),
|
||||||
|
content: o.content,
|
||||||
|
text: o.text,
|
||||||
|
text_i18n: o.text_i18n || {},
|
||||||
|
rotation: o.angle,
|
||||||
|
align: o.textAlign || 'left',
|
||||||
|
verticalalign: o.verticalAlign || 'middle',
|
||||||
|
autoresize: o.autoResize || false,
|
||||||
|
splitlongwords: o.splitLongWords || false,
|
||||||
|
});
|
||||||
} else if (o.type === "imagearea") {
|
} else if (o.type === "imagearea") {
|
||||||
d.push({
|
d.push({
|
||||||
type: "imagearea",
|
type: "imagearea",
|
||||||
@@ -239,6 +365,36 @@ var editor = {
|
|||||||
o = editor._add_poweredby(d.content);
|
o = editor._add_poweredby(d.content);
|
||||||
o.content = d.content;
|
o.content = d.content;
|
||||||
o.scaleToHeight(editor._mm2px(d.size));
|
o.scaleToHeight(editor._mm2px(d.size));
|
||||||
|
} else if (d.type === "textcontainer") {
|
||||||
|
o = editor._add_textcontainer();
|
||||||
|
o.set('fill', 'rgb(' + d.color[0] + ',' + d.color[1] + ',' + d.color[2] + ')');
|
||||||
|
o.set('fontSize', editor._pt2px(d.fontsize));
|
||||||
|
o.set('lineHeight', d.lineheight || 1);
|
||||||
|
o.set('fontFamily', d.fontfamily);
|
||||||
|
o.set('fontWeight', d.bold ? 'bold' : 'normal');
|
||||||
|
o.set('fontStyle', d.italic ? 'italic' : 'normal');
|
||||||
|
o.content = d.content;
|
||||||
|
o.set('textAlign', d.align);
|
||||||
|
o.set('verticalAlign', d.verticalalign);
|
||||||
|
o.set('autoResize', d.autoresize);
|
||||||
|
o.set('splitLongWords', d.splitlongwords);
|
||||||
|
if (d.rotation) {
|
||||||
|
o.rotate(d.rotation);
|
||||||
|
}
|
||||||
|
if (d.content === "other") {
|
||||||
|
o.set('text', d.text);
|
||||||
|
} else if (d.content === "other_i18n") {
|
||||||
|
o.text_i18n = d.text_i18n
|
||||||
|
o.set('text', d.text_i18n[Object.keys(d.text_i18n)[0]]);
|
||||||
|
} else if (d.content) {
|
||||||
|
o.set('text', editor._get_text_sample(d.content));
|
||||||
|
}
|
||||||
|
o.set('width', editor._mm2px(d.width)); // needs to be after setText
|
||||||
|
o.set('height', editor._mm2px(d.height)); // needs to be after setText
|
||||||
|
if (d.locale) {
|
||||||
|
// The data format allows to set the locale per text field but we currently only expose a global field
|
||||||
|
$("#pdf-info-locale").val(d.locale);
|
||||||
|
}
|
||||||
} else if (d.type === "textarea" || o.type === "text") {
|
} else if (d.type === "textarea" || o.type === "text") {
|
||||||
o = editor._add_text();
|
o = editor._add_text();
|
||||||
o.set('fill', 'rgb(' + d.color[0] + ',' + d.color[1] + ',' + d.color[2] + ')');
|
o.set('fill', 'rgb(' + d.color[0] + ',' + d.color[1] + ',' + d.color[2] + ')');
|
||||||
@@ -455,6 +611,11 @@ var editor = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_update_toolbox_values: function () {
|
_update_toolbox_values: function () {
|
||||||
|
$("#version-notice").toggle(
|
||||||
|
editor._other_page_objects.some((o) => o.type === "textcontainer") ||
|
||||||
|
editor.fabric.getObjects().some((o) => o.type === "textcontainer")
|
||||||
|
);
|
||||||
|
|
||||||
var o = editor.fabric.getActiveObject();
|
var o = editor.fabric.getActiveObject();
|
||||||
if (!o) {
|
if (!o) {
|
||||||
return;
|
return;
|
||||||
@@ -484,6 +645,35 @@ var editor = {
|
|||||||
} else if (o.type === "poweredby") {
|
} else if (o.type === "poweredby") {
|
||||||
$("#toolbox-squaresize").val(editor._px2mm(o.height * o.scaleY).toFixed(2));
|
$("#toolbox-squaresize").val(editor._px2mm(o.height * o.scaleY).toFixed(2));
|
||||||
$("#toolbox-poweredby-style").val(o.content);
|
$("#toolbox-poweredby-style").val(o.content);
|
||||||
|
} else if (o.type === "textcontainer") {
|
||||||
|
var col = (new fabric.Color(o.fill))._source;
|
||||||
|
$("#toolbox-col").val("#" + ((1 << 24) + (col[0] << 16) + (col[1] << 8) + col[2]).toString(16).slice(1));
|
||||||
|
$("#toolbox-fontsize").val(editor._px2pt(o.fontSize).toFixed(1));
|
||||||
|
$("#toolbox-lineheight").val(o.lineHeight || 1);
|
||||||
|
$("#toolbox-fontfamily").val(o.fontFamily);
|
||||||
|
$("#toolbox").find("button[data-action=bold]").toggleClass('active', o.fontWeight === 'bold');
|
||||||
|
$("#toolbox").find("button[data-action=italic]").toggleClass('active', o.fontStyle === 'italic');
|
||||||
|
$("#toolbox").find("button[data-action=autoresize]").toggleClass('active', o.autoResize || false)
|
||||||
|
$("#toolbox").find("button[data-action=splitlongwords]").toggleClass('active', o.splitLongWords || false)
|
||||||
|
$("#toolbox").find("button[data-action=left]").toggleClass('active', o.textAlign === 'left' || !o.textAlign);
|
||||||
|
$("#toolbox").find("button[data-action=center]").toggleClass('active', o.textAlign === 'center');
|
||||||
|
$("#toolbox").find("button[data-action=right]").toggleClass('active', o.textAlign === 'right');
|
||||||
|
$("#toolbox").find("button[data-action=top]").toggleClass('active', o.verticalAlign === 'top' || !o.verticalAlign);
|
||||||
|
$("#toolbox").find("button[data-action=middle]").toggleClass('active', o.verticalAlign === 'middle');
|
||||||
|
$("#toolbox").find("button[data-action=bottom]").toggleClass('active', o.verticalAlign === 'bottom');
|
||||||
|
|
||||||
|
if (o.scaleY !== 1 || o.scaleX !== 1) {
|
||||||
|
o.set({
|
||||||
|
height: o.height * o.scaleY,
|
||||||
|
width: o.width * o.scaleX,
|
||||||
|
scaleX: 1,
|
||||||
|
scaleY: 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#toolbox-height").val(editor._px2mm(o.height).toFixed(2));
|
||||||
|
$("#toolbox-width").val(editor._px2mm(o.width).toFixed(2));
|
||||||
|
$("#toolbox-textrotation").val((o.angle || 0.0).toFixed(1));
|
||||||
} else if (o.type === "text" || o.type === "textarea") {
|
} else if (o.type === "text" || o.type === "textarea") {
|
||||||
var col = (new fabric.Color(o.fill))._source;
|
var col = (new fabric.Color(o.fill))._source;
|
||||||
$("#toolbox-col").val("#" + ((1 << 24) + (col[0] << 16) + (col[1] << 8) + col[2]).toString(16).slice(1));
|
$("#toolbox-col").val("#" + ((1 << 24) + (col[0] << 16) + (col[1] << 8) + col[2]).toString(16).slice(1));
|
||||||
@@ -500,7 +690,7 @@ var editor = {
|
|||||||
$("#toolbox-textrotation").val((o.angle || 0.0).toFixed(1));
|
$("#toolbox-textrotation").val((o.angle || 0.0).toFixed(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o.type === "textarea" || o.type === "barcodearea") {
|
if (o.type === "textarea" || o.type === "barcodearea" || o.type === "textcontainer") {
|
||||||
if (!o.content && o.type == "barcodearea") {
|
if (!o.content && o.type == "barcodearea") {
|
||||||
o.content = "secret";
|
o.content = "secret";
|
||||||
}
|
}
|
||||||
@@ -598,6 +788,50 @@ var editor = {
|
|||||||
editor.fabric.discardActiveObject();
|
editor.fabric.discardActiveObject();
|
||||||
editor.fabric.setActiveObject(newo);
|
editor.fabric.setActiveObject(newo);
|
||||||
}
|
}
|
||||||
|
} else if (o.type === "textcontainer") {
|
||||||
|
o.set('fill', $("#toolbox-col").val());
|
||||||
|
o.set('fontSize', editor._pt2px($("#toolbox-fontsize").val()));
|
||||||
|
o.set('lineHeight', $("#toolbox-lineheight").val() || 1);
|
||||||
|
o.set('fontFamily', $("#toolbox-fontfamily").val());
|
||||||
|
o.set('fontWeight', $("#toolbox").find("button[data-action=bold]").is('.active') ? 'bold' : 'normal');
|
||||||
|
o.set('fontStyle', $("#toolbox").find("button[data-action=italic]").is('.active') ? 'italic' : 'normal');
|
||||||
|
var align = $("#toolbox-align").find(".active").attr("data-action");
|
||||||
|
if (align) {
|
||||||
|
o.set('textAlign', align);
|
||||||
|
}
|
||||||
|
var verticalAlign = $("#toolbox-verticalalign").find(".active").attr("data-action");
|
||||||
|
if (verticalAlign) {
|
||||||
|
o.set('verticalAlign', verticalAlign);
|
||||||
|
}
|
||||||
|
o.set('autoResize', $("#toolbox").find("button[data-action=autoresize]").is('.active'));
|
||||||
|
o.set('splitLongWords', $("#toolbox").find("button[data-action=splitlongwords]").is('.active'));
|
||||||
|
// todo: verticalalign
|
||||||
|
o.rotate(parseFloat($("#toolbox-textrotation").val()));
|
||||||
|
$("#toolbox-content-other").toggle($("#toolbox-content").val() === "other");
|
||||||
|
$("#toolbox-content-other-i18n").toggle($("#toolbox-content").val() === "other_i18n");
|
||||||
|
$("#toolbox-content-other-help").toggle($("#toolbox-content").val() === "other" || $("#toolbox-content").val() === "other_i18n");
|
||||||
|
o.content = $("#toolbox-content").val();
|
||||||
|
if ($("#toolbox-content").val() === "other") {
|
||||||
|
if (e.target.id === "toolbox-content") {
|
||||||
|
// user used dropdown to switch content-type, update value with value from i18n textarea
|
||||||
|
$("#toolbox-content-other").val($("#toolbox-content-other-i18n textarea").val());
|
||||||
|
}
|
||||||
|
o.set('text', $("#toolbox-content-other").val());
|
||||||
|
} else if ($("#toolbox-content").val() === "other_i18n") {
|
||||||
|
if (e.target.id === "toolbox-content") {
|
||||||
|
// user used dropdown to switch content-type, update value with value from "other" textarea
|
||||||
|
$("#toolbox-content-other-i18n textarea").val($("#toolbox-content-other").val());
|
||||||
|
}
|
||||||
|
o.text_i18n = {}
|
||||||
|
$("#toolbox-content-other-i18n textarea").each(function () {
|
||||||
|
o.text_i18n[$(this).attr("lang")] = $(this).val();
|
||||||
|
});
|
||||||
|
o.set('text', $("#toolbox-content-other-i18n textarea").first().val());
|
||||||
|
} else {
|
||||||
|
o.set('text', editor._get_text_sample($("#toolbox-content").val()));
|
||||||
|
}
|
||||||
|
o.set('width', editor._mm2px($("#toolbox-width").val()));
|
||||||
|
o.set('height', editor._mm2px($("#toolbox-height").val()));
|
||||||
} else if (o.type === "textarea" || o.type === "text") {
|
} else if (o.type === "textarea" || o.type === "text") {
|
||||||
o.set('fill', $("#toolbox-col").val());
|
o.set('fill', $("#toolbox-col").val());
|
||||||
o.set('fontSize', editor._pt2px($("#toolbox-fontsize").val()));
|
o.set('fontSize', editor._pt2px($("#toolbox-fontsize").val()));
|
||||||
@@ -658,7 +892,9 @@ var editor = {
|
|||||||
var o = selected[0];
|
var o = selected[0];
|
||||||
$("#toolbox").attr("data-type", o.type);
|
$("#toolbox").attr("data-type", o.type);
|
||||||
if (o.type === "textarea" || o.type === "text") {
|
if (o.type === "textarea" || o.type === "text") {
|
||||||
$("#toolbox-heading").text(gettext("Text object"));
|
$("#toolbox-heading").text(gettext("Text object (deprecated)"));
|
||||||
|
} else if (o.type === "textarea" || o.type === "text" || o.type === "textcontainer") {
|
||||||
|
$("#toolbox-heading").text(gettext("Text box"));
|
||||||
} else if (o.type === "barcodearea") {
|
} else if (o.type === "barcodearea") {
|
||||||
$("#toolbox-heading").text(gettext("Barcode area"));
|
$("#toolbox-heading").text(gettext("Barcode area"));
|
||||||
} else if (o.type === "imagearea") {
|
} else if (o.type === "imagearea") {
|
||||||
@@ -727,6 +963,44 @@ var editor = {
|
|||||||
return rect;
|
return rect;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_add_textcontainer: function () {
|
||||||
|
var rect = new fabric.Textcontainer(editor._get_text_sample('event_name'), {
|
||||||
|
left: 100,
|
||||||
|
top: 100,
|
||||||
|
width: 300,
|
||||||
|
height: 29,
|
||||||
|
lockRotation: false,
|
||||||
|
fill: '#000',
|
||||||
|
content: 'event_name',
|
||||||
|
text: editor._get_text_sample('event_name'),
|
||||||
|
fontFamily: 'Open Sans',
|
||||||
|
fontStyle: 'normal',
|
||||||
|
lineHeight: 1,
|
||||||
|
editable: false,
|
||||||
|
fontSize: editor._pt2px(13),
|
||||||
|
verticalAlign: 'middle',
|
||||||
|
textAlign: 'left',
|
||||||
|
splitLongWords: true,
|
||||||
|
autoResize: true,
|
||||||
|
lockScalingFlip: true,
|
||||||
|
});
|
||||||
|
rect.setControlsVisibility({
|
||||||
|
'tr': true,
|
||||||
|
'tl': true,
|
||||||
|
'mt': true,
|
||||||
|
'br': true,
|
||||||
|
'bl': true,
|
||||||
|
'mb': true,
|
||||||
|
'mr': true,
|
||||||
|
'ml': true,
|
||||||
|
'mtr': true
|
||||||
|
});
|
||||||
|
editor.fabric.add(rect);
|
||||||
|
editor._create_savepoint();
|
||||||
|
$("#version-notice").show();
|
||||||
|
return rect;
|
||||||
|
},
|
||||||
|
|
||||||
_add_imagearea: function () {
|
_add_imagearea: function () {
|
||||||
var rect = new fabric.Imagearea({
|
var rect = new fabric.Imagearea({
|
||||||
left: 100,
|
left: 100,
|
||||||
@@ -1063,6 +1337,7 @@ var editor = {
|
|||||||
editor._load_pdf();
|
editor._load_pdf();
|
||||||
$("#editor-add-qrcode, #editor-add-qrcode-lead, #editor-add-qrcode-other").click(editor._add_qrcode);
|
$("#editor-add-qrcode, #editor-add-qrcode-lead, #editor-add-qrcode-other").click(editor._add_qrcode);
|
||||||
$("#editor-add-image").click(editor._add_imagearea);
|
$("#editor-add-image").click(editor._add_imagearea);
|
||||||
|
$("#editor-add-textcontainer").click(editor._add_textcontainer);
|
||||||
$("#editor-add-text").click(editor._add_text);
|
$("#editor-add-text").click(editor._add_text);
|
||||||
$("#editor-add-poweredby").click(function() {editor._add_poweredby("dark")});
|
$("#editor-add-poweredby").click(function() {editor._add_poweredby("dark")});
|
||||||
editor.$cva.get(0).tabIndex = 1000;
|
editor.$cva.get(0).tabIndex = 1000;
|
||||||
@@ -1144,6 +1419,7 @@ var editor = {
|
|||||||
editor._update_save_button();
|
editor._update_save_button();
|
||||||
});
|
});
|
||||||
$("#pdf-info-width, #pdf-info-height").bind('change input', editor._paper_size_warning);
|
$("#pdf-info-width, #pdf-info-height").bind('change input', editor._paper_size_warning);
|
||||||
|
editor._update_toolbox_values();
|
||||||
|
|
||||||
$.getJSON($("#schema-url").text(), function (data) {
|
$.getJSON($("#schema-url").text(), function (data) {
|
||||||
editor.schema = data;
|
editor.schema = data;
|
||||||
|
|||||||
@@ -298,29 +298,45 @@ var form_handlers = function (el) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).not(".no-contrast").on('changeColor create', function (e) {
|
}).not(".no-contrast").on('changeColor create', function (e) {
|
||||||
|
if (e.type == 'changeColor' && !e.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
var rgb = $(this).colorpicker('color').toRGB();
|
var rgb = $(this).colorpicker('color').toRGB();
|
||||||
var c = contrast([255,255,255], [rgb.r, rgb.g, rgb.b]);
|
var c = contrast([255,255,255], [rgb.r, rgb.g, rgb.b]);
|
||||||
var mark = 'times';
|
var mark = 'times';
|
||||||
if ($(this).parent().find(".contrast-state").length === 0) {
|
var $icon = $(this).parent().find(".contrast-icon");
|
||||||
|
if ($icon.length === 0 && $(this).parent().find(".contrast-state").length === 0) {
|
||||||
$(this).parent().append("<div class='help-block contrast-state'></div>");
|
$(this).parent().append("<div class='help-block contrast-state'></div>");
|
||||||
}
|
}
|
||||||
var $note = $(this).parent().find(".contrast-state");
|
var $note = $(this).parent().find(".contrast-state");
|
||||||
if ($(this).val() === "") {
|
if ($(this).val() === "") {
|
||||||
$note.remove();
|
$note.remove();
|
||||||
}
|
}
|
||||||
|
var icon, text, cls;
|
||||||
if (c > 7) {
|
if (c > 7) {
|
||||||
$note.html("<span class='fa fa-fw fa-check-circle'></span>")
|
icon = "fa-check-circle";
|
||||||
.append(gettext('Your color has great contrast and is very easy to read!'));
|
text = gettext('Your color has great contrast and is very easy to read!');
|
||||||
$note.addClass("text-success").removeClass("text-warning").removeClass("text-danger");
|
cls = "text-success";
|
||||||
} else if (c > 2.5) {
|
} else if (c > 2.5) {
|
||||||
$note.html("<span class='fa fa-fw fa-info-circle'></span>")
|
icon = "fa-info-circle";
|
||||||
.append(gettext('Your color has decent contrast and is probably good-enough to read!'));
|
text = gettext('Your color has decent contrast and is probably good-enough to read!');
|
||||||
$note.removeClass("text-success").removeClass("text-warning").removeClass("text-danger");
|
cls = "";
|
||||||
} else {
|
} else {
|
||||||
$note.html("<span class='fa fa-fw fa-warning'></span>")
|
icon = "fa-warning";
|
||||||
.append(gettext('Your color has bad contrast for text on white background, please choose a darker ' +
|
text = gettext('Your color has bad contrast for text on white background, please choose a darker shade.');
|
||||||
'shade.'));
|
cls = "text-danger";
|
||||||
$note.addClass("text-danger").removeClass("text-success").removeClass("text-warning");
|
}
|
||||||
|
if ($icon.length === 0) {
|
||||||
|
$note.html("<span class='fa fa-fw " + icon + "'></span>")
|
||||||
|
.append(text);
|
||||||
|
$note.removeClass("text-success").removeClass("text-danger").addClass(cls);
|
||||||
|
} else {
|
||||||
|
$icon.html("<span class='fa fa-fw " + icon + " " + cls + "'></span>")
|
||||||
|
$icon.attr("title", text);
|
||||||
|
$icon.tooltip('destroy');
|
||||||
|
window.setTimeout(function() {
|
||||||
|
$icon.tooltip({"title": text});
|
||||||
|
}, 250);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ body {
|
|||||||
#toolbox .poweredby,
|
#toolbox .poweredby,
|
||||||
#toolbox[data-type] .pdf-info,
|
#toolbox[data-type] .pdf-info,
|
||||||
#toolbox .text,
|
#toolbox .text,
|
||||||
|
#toolbox .textarea,
|
||||||
|
#toolbox .textcontainer,
|
||||||
#toolbox .imagecontent,
|
#toolbox .imagecontent,
|
||||||
#toolbox .object-buttons {
|
#toolbox .object-buttons {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -30,10 +32,23 @@ body {
|
|||||||
#toolbox[data-type=imagearea] .imagecontent,
|
#toolbox[data-type=imagearea] .imagecontent,
|
||||||
#toolbox[data-type=poweredby] .poweredby,
|
#toolbox[data-type=poweredby] .poweredby,
|
||||||
#toolbox[data-type=text] .text,
|
#toolbox[data-type=text] .text,
|
||||||
|
#toolbox[data-type=text] .textarea,
|
||||||
|
#toolbox[data-type=textcontainer] .text,
|
||||||
|
#toolbox[data-type=textcontainer] .textcontainer,
|
||||||
|
#toolbox[data-type=textcontainer] .rectsize,
|
||||||
#toolbox[data-type=textarea] .text,
|
#toolbox[data-type=textarea] .text,
|
||||||
|
#toolbox[data-type=textarea] .textarea,
|
||||||
#toolbox[data-type] .object-buttons {
|
#toolbox[data-type] .object-buttons {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
#toolbox[data-type=text] .btn-group-justified > .btn-group.text,
|
||||||
|
#toolbox[data-type=text] .btn-group-justified > .btn-group.textarea,
|
||||||
|
#toolbox[data-type=textcontainer] .btn-group-justified > .btn-group.text,
|
||||||
|
#toolbox[data-type=textcontainer] .btn-group-justified > .btn-group.textcontainer,
|
||||||
|
#toolbox[data-type=textarea] .btn-group-justified > .btn-group.text,
|
||||||
|
#toolbox[data-type=textarea] .btn-group-justified > .btn-group.textarea {
|
||||||
|
display: table-cell;
|
||||||
|
}
|
||||||
#loading-container {
|
#loading-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user