neft
Version:
Universal Platform
217 lines (182 loc) • 6.85 kB
text/coffeescript
'use strict'
module.exports = (impl) ->
{Item} = impl.Types
DATA =
shader: null
isSvg: false
callback: null
image:
source: ''
width: 0
height: 0
resource: null
onSvgImageResize = ->
if this.sourceSize.width < this.width
this.sourceSize.width = this.width * 1.2
if this.sourceSize.height < this.height
this.sourceSize.height = this.height * 1.2
return
useShader = (item) ->
data = item._impl
data.shader = impl.utils.createQmlObject """
Item {
id: shader;
property variant image: null;
property double offsetX: 0;
property double offsetY: 0;
property int xDir: 1;
property int yDir: 1;
anchors.fill: this.image;
clip: true;
onOffsetXChanged: {
this.updateOffset();
}
onOffsetYChanged: {
this.updateOffset();
}
onWidthChanged: {
this.updateSize();
}
onHeightChanged: {
this.updateSize();
}
onXDirChanged: {
this.updateDir();
}
onYDirChanged: {
this.updateDir();
}
function updateSize(){
this.updateImages();
this.updateOffset();
}
function updateDir(){
var children = this.children,
c00 = children[0],
c10 = children[1],
c01 = children[2],
c11 = children[3];
c10.baseX = c11.baseX = c00.width * this.xDir * -1;
c01.baseY = c11.baseY = c00.height * this.yDir * -1;
}
function updateImages(){
var children = this.children,
width = Math.floor(this.width / this.image.width) * this.image.width,
height = Math.floor(this.height / this.image.height) * this.image.height;
if (!isFinite(width) || !isFinite(height)){
return;
}
for (var i = 0; i < 4; i++){
var child = children[i];
child.width = width;
child.height = height;
}
this.updateDir();
}
function updateOffset(){
var children = this.children,
offsetX = this.offsetX % this.width,
offsetY = this.offsetY % this.height;
if (children.length !== 5){
return;
}
for (var i = 0; i < 4; i++){
var child = children[i];
child.offsetX = offsetX;
child.offsetY = offsetY;
}
this.xDir = offsetX > 0 ? 1 : -1;
this.yDir = offsetY > 0 ? 1 : -1;
}
Repeater {
model: 4;
Image {
source: shader.image ? shader.image.source : '';
sourceSize.width: shader.image ? shader.image.sourceSize.width : 0;
sourceSize.height: shader.image ? shader.image.sourceSize.height : 0;
fillMode: Image.Tile;
property double offsetX: 0;
property double offsetY: 0;
property double baseX: 0;
property double baseY: 0;
x: this.baseX + this.offsetX;
y: this.baseY + this.offsetY;
}
}
}
""", data.elem.parent
# TODO: what with elem children and items order
data.shader.image = data.elem
return
DATA: DATA
createData: impl.utils.createDataCloner 'Item', DATA
create: (data) ->
data.elem ?= impl.utils.createQmlObject 'Image { asynchronous: true }'
Item.create.call @, data
setImageSource: do ->
onStatusChanged = ->
data =
{elem, callback} = data
elem.statusChanged.disconnect @, onStatusChanged
if elem.status is Image.Ready
data.image.width = data.resource?.width or elem.sourceSize.width
data.image.height = data.resource?.height or elem.sourceSize.height
callback?.call @, null, data.image
else if elem.status is Image.Error
callback?.call @, true
(val, callback) ->
data =
{elem} = data
data.image.source = val
data.callback = callback
data.resource = null
unless impl.utils.DATA_URI_RE.test(val)
# if rsc = impl.Renderer.resources?.getResource(val)
# data.resource = rsc
# val = 'qrc:' + rsc.resolve(val, ImageResourceRequest)
# else
val = impl.utils.toUrl(val)
elem.source = val or ''
if ///^data:image\/svg+|\.svg$///.test(val)
elem.fillMode = Image.PreserveAspectFit
unless data.isSvg
elem.widthChanged.connect elem, onSvgImageResize
elem.heightChanged.connect elem, onSvgImageResize
elem.statusChanged.connect elem, onSvgImageResize
data.isSvg = true
else
elem.fillMode = Image.Stretch
if data.isSvg
elem.widthChanged.disconnect elem, onSvgImageResize
elem.heightChanged.disconnect elem, onSvgImageResize
elem.statusChanged.disconnect elem, onSvgImageResize
data.isSvg = false
switch elem.status
when Image.Ready, Image.Error
onStatusChanged.call @
else
elem.statusChanged.connect @, onStatusChanged
return
setImageSourceWidth: (val) ->
.elem.sourceSize.width = val
return
setImageSourceHeight: (val) ->
.elem.sourceSize.height = val
return
setImageFillMode: (val) ->
switch val
when 'Stretch'
.elem.fillMode = Image.Stretch
when 'Tile'
.elem.fillMode = Image.Tile
return
setImageOffsetX: (val) ->
# unless .shader
# useShader @
# .shader.offsetX = val
return
setImageOffsetY: (val) ->
# unless .shader
# useShader @
# .shader.offsetY = val
return