blob: b3fad1e6a6851da2507f7d230c41a4761155e2fb [file] [log] [blame]
/*
* Copyright (c) 2014-2018 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
*/
import {HtmlComponent, IconDesc, Image, scout, Widget} from '../index';
/**
* Widget representing an icon. It may be a font icon or an image icon. Depending on the type, either a span or an img tag will be rendered.
* <p>
* See also jquery-scout.icon/appendIcon. Main difference to these implementations is that the image loading will invalidate the layout by using {@link Image}.
*/
export default class Icon extends Widget {
constructor() {
super();
this.autoFit = false;
/** @type {IconDesc} */
this.iconDesc = null;
/**
* Is set if the icon is rendered and an image, it is not set if it is a font icon
* @type Image
*/
this.image = null;
this.prepend = false;
}
_init(model) {
super._init(model);
this._setIconDesc(this.iconDesc);
}
_render() {
this._renderIconDesc(); // Must not be in _renderProperties because it creates $container -> properties like visible etc. need to be rendered afterwards
}
/**
* Accepts either an iconId as string or an {@link IconDesc}.
* @param {(string|IconDesc)} icon
*/
setIconDesc(iconDesc) {
this.setProperty('iconDesc', iconDesc);
}
_setIconDesc(iconDesc) {
iconDesc = IconDesc.ensure(iconDesc);
this._setProperty('iconDesc', iconDesc);
}
_renderIconDesc() {
this._removeFontIcon();
this._removeImageIcon();
if (!this.iconDesc || this.iconDesc.isFontIcon()) {
this._renderFontIcon();
} else if (this.iconDesc.iconType === 2) {
this._renderSvgIcon();
} else {
this._renderImageIcon();
}
if (!this.rendering) {
this._renderProperties();
}
this.invalidateLayoutTree();
}
_renderSvgIcon() {
if (this.iconDesc.iconUrl.indexOf('add-circle.svg') > -1) {
this.$container = this.$parent.prependElement(`
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
<title>add-circle</title>
<g>
<path d="M12,17.25c-0.414,0-0.75-0.336-0.75-0.75v-3.75H7.5c-0.414,0-0.75-0.336-0.75-0.75s0.336-0.75,0.75-0.75h3.75V7.5
c0-0.414,0.336-0.75,0.75-0.75s0.75,0.336,0.75,0.75v3.75h3.75c0.414,0,0.75,0.336,0.75,0.75s-0.336,0.75-0.75,0.75h-3.75v3.75
C12.75,16.914,12.414,17.25,12,17.25z"/>
<path d="M12,24C5.383,24,0,18.617,0,12C0,5.383,5.383,0,12,0c6.617,0,12,5.383,12,12C24,18.617,18.617,24,12,24z M12,1.5
C6.21,1.5,1.5,6.21,1.5,12c0,5.79,4.71,10.5,10.5,10.5c5.79,0,10.5-4.71,10.5-10.5C22.5,6.21,17.79,1.5,12,1.5z"/>
</g>
</svg>
`).addClass('icon');
} else if (this.iconDesc.iconUrl.indexOf('16px-outline.svg') > -1) {
this.$container = this.$parent.prependElement(`
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
\t viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<g>
\t<path d="M11,7.5H8.5V5c0-0.3-0.2-0.5-0.5-0.5S7.5,4.7,7.5,5v2.5H5C4.7,7.5,4.5,7.7,4.5,8S4.7,8.5,5,8.5h2.5V11
\t\tc0,0.3,0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5V8.5H11c0.3,0,0.5-0.2,0.5-0.5S11.3,7.5,11,7.5z"/>
\t<path d="M8,0C3.6,0,0,3.6,0,8s3.6,8,8,8s8-3.6,8-8S12.4,0,8,0z M8,15c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7
\t\tC15,11.9,11.9,15,8,15z"/>
</g>
</svg>
`).addClass('icon');
} else if (this.iconDesc.iconUrl.indexOf('16px-outline-pixel-perfect.svg') > -1) {
this.$container = this.$parent.prependElement(`
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
\t viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<g>
\t<path d="M11.5,8H9V5.5C9,5.2,8.8,5,8.5,5S8,5.2,8,5.5V8H5.5C5.2,8,5,8.2,5,8.5S5.2,9,5.5,9H8v2.5C8,11.8,8.2,12,8.5,12
\t\tS9,11.8,9,11.5V9h2.5C11.8,9,12,8.8,12,8.5S11.8,8,11.5,8z"/>
\t<path d="M8,0C3.6,0,0,3.6,0,8s3.6,8,8,8s8-3.6,8-8S12.4,0,8,0z M8,15c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7
\t\tC15,11.9,11.9,15,8,15z"/>
</g>
</svg>
`).addClass('icon');
} else if (this.iconDesc.iconUrl.indexOf('16px-stroke.svg') > -1) {
this.$container = this.$parent.prependElement(`
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
\t viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<style type="text/css">
\t.st0{fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;}
</style>
<line class="st0" x1="8" y1="5" x2="8" y2="11"/>
<line class="st0" x1="5" y1="8" x2="11" y2="8"/>
<circle class="st0" cx="8" cy="8" r="7.5"/>
</svg>
`).addClass('icon stroke');
} else if (this.iconDesc.iconUrl.indexOf('16px-stroke-pixel-perfect.svg') > -1) {
this.$container = this.$parent.prependElement(`
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
\t viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<style type="text/css">
\t.st0{fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;}
</style>
<line class="st0" x1="8.5" y1="5.5" x2="8.5" y2="11.5"/>
<line class="st0" x1="5.5" y1="8.5" x2="11.5" y2="8.5"/>
<circle class="st0" cx="8" cy="8" r="7.5"/>
</svg>
`).addClass('icon stroke');
} else if (this.iconDesc.iconUrl.indexOf('mail-16px-stroke-ink.svg') > -1) {
this.$container = this.$parent.prependElement(`
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<defs>
<style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style>
</defs>
<title>email-action-unread</title>
<path d="m1.5723 2c-0.86908 0-1.5723 0.72883-1.5723 1.5996v8.8008c0 0.87078 0.70319 1.5996 1.5723 1.5996h12.855c0.86908 0 1.5723-0.72883 1.5723-1.5996v-8.8008c0-0.87078-0.70319-1.5996-1.5723-1.5996h-12.855zm0 1h12.855c0.31806 0 0.57227 0.25159 0.57227 0.59961v8.8008c0 0.34802-0.2542 0.59961-0.57227 0.59961h-12.855c-0.31806 0-0.57227-0.25159-0.57227-0.59961v-8.8008c0-0.34802 0.2542-0.59961 0.57227-0.59961z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="currentColor" image-rendering="auto" shape-rendering="auto" solid-color="#000000" stop-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;isolation:auto;mix-blend-mode:normal;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
<path d="m0.71289 2.3926a0.5 0.5 0 0 0-0.36719 0.19531 0.5 0.5 0 0 0 0.091797 0.70117l5.8164 4.4707c1.0272 0.78966 2.465 0.78966 3.4922 0l5.8164-4.4707a0.5 0.5 0 0 0 0.091797-0.70117 0.5 0.5 0 0 0-0.70117-0.091797l-5.8164 4.4707c-0.67154 0.51627-1.6019 0.51627-2.2734 0l-5.8164-4.4707a0.5 0.5 0 0 0-0.33398-0.10352z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="currentColor" image-rendering="auto" shape-rendering="auto" solid-color="#000000" stop-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;isolation:auto;mix-blend-mode:normal;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</svg>
`).addClass('icon');
} else if (this.iconDesc.iconUrl.indexOf('circle-16px-outline-ink.svg') > -1) {
this.$container = this.$parent.prependElement(`
<svg
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 16 16"
style="enable-background:new 0 0 16 16;"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs43" />
<style
type="text/css"
id="style32">
\t.st0{fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;}
</style>
<path
id="line34"
style="color:#000000;fill:#000000;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
d="M 8 0 C 3.5876487 0 0 3.5876487 0 8 C 0 12.412351 3.5876487 16 8 16 C 12.412351 16 16 12.412351 16 8 C 16 3.5876487 12.412351 0 8 0 z M 8 1 C 11.871912 1 15 4.1280883 15 8 C 15 11.871912 11.871912 15 8 15 C 4.1280883 15 1 11.871912 1 8 C 1 4.1280883 4.1280883 1 8 1 z M 8 4.5 A 0.5 0.5 0 0 0 7.5 5 L 7.5 7.5 L 5 7.5 A 0.5 0.5 0 0 0 4.5 8 A 0.5 0.5 0 0 0 5 8.5 L 7.5 8.5 L 7.5 11 A 0.5 0.5 0 0 0 8 11.5 A 0.5 0.5 0 0 0 8.5 11 L 8.5 8.5 L 11 8.5 A 0.5 0.5 0 0 0 11.5 8 A 0.5 0.5 0 0 0 11 7.5 L 8.5 7.5 L 8.5 5 A 0.5 0.5 0 0 0 8 4.5 z " />
</svg>
`).addClass('icon');
} else if (this.iconDesc.iconUrl.indexOf('circle-16px-stroke-ink.svg') > -1) {
this.$container = this.$parent.prependElement(`
<svg
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 16 16"
style="enable-background:new 0 0 16 16;"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs43" />
<style
type="text/css"
id="style32">
\t.st0{fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;}
</style>
<line
class="st0"
x1="8"
y1="5"
x2="8"
y2="11"
id="line34" />
<line
class="st0"
x1="5"
y1="8"
x2="11"
y2="8"
id="line36" />
<circle
class="st0"
cx="8"
cy="8"
id="circle38"
r="7.5" />
</svg>
`).addClass('icon stroke');
}
}
_renderFontIcon() {
this.$container = this.$parent.appendIcon(this.iconDesc);
if (this.prepend) {
this.$container.prependTo(this.$parent);
}
this.htmlComp = HtmlComponent.install(this.$container, this.session);
}
_removeFontIcon() {
if (this.$container) {
this.$container.remove();
this.$container = null;
}
}
_renderImageIcon() {
if (this.image) {
return;
}
this.image = scout.create('Image', {
parent: this,
imageUrl: this.iconDesc.iconUrl,
cssClass: 'icon image-icon',
autoFit: this.autoFit,
prepend: this.prepend
});
this.image.render(this.$parent);
this.image.one('destroy', () => {
this.image = null;
});
this.image.on('load error', event => {
// propagate event
this.trigger(event.type, event);
});
this.$container = this.image.$container;
this.htmlComp = this.image.htmlComp;
}
_removeImageIcon() {
if (this.image) {
this.image.destroy();
this.image = null;
}
}
/**
* Delegates to this.image.setAutoFit, but only if Icon is an image. Beside updating the autoFit property, this method has no effect if the icon is a font-icon.
*/
setAutoFit(autoFit) {
this.setProperty('autoFit', autoFit);
if (this.image) {
this.image.setAutoFit(autoFit);
}
}
}