not really known
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

313 lines
10 KiB

// Copyright (c) 2015 Walter Bender
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the The GNU Affero General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// You should have received a copy of the GNU Affero General Public
// License along with this library; if not, write to the Free Software
// Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
//
// FIXME: Use busy cursor
// A viewer for Turtle Blocks plugins
function PluginsViewer(canvas, stage, refreshCanvas, close, load) {
this.canvas = canvas;
this.stage = stage;
this.refreshCanvas = refreshCanvas;
this.closeViewer = close;
this.loadPlugin = load;
this.dict = {};
this.pluginFiles = [];
this.container = null;
this.prev = null;
this.next = null;
this.page = 0; // 4x4 image matrix per page
this.server = true;
this.setServer = function(server) {
this.server = server;
}
this.hide = function() {
if (this.container !== null) {
this.container.visible = false;
this.refreshCanvas();
}
}
this.show = function(scale) {
this.scale = scale;
this.page = 0;
if (this.server) {
try {
var rawData = httpGet();
var obj = JSON.parse(rawData);
// console.log('json parse: ' + obj);
// Look for svg
for (var file in obj) {
if (fileExt(obj[file]) === 'svg') {
var name = fileBasename(obj[file]);
if (this.pluginFiles.indexOf(name) === -1) {
this.pluginFiles.push(name);
}
}
}
// and corresponding .json files
for (var file in this.pluginFiles) {
var tbfile = this.pluginFiles[file] + '.json';
if (!tbfile in obj) {
this.pluginFiles.remove(this.pluginFiles[file]);
}
}
} catch (e) {
console.log(e);
return false;
}
} else {
// FIXME: grab files from a local server?
this.pluginFiles = SAMPLEPLUGINS;
}
console.log('found these projects: ' + this.pluginFiles.sort());
if (this.container === null) {
this.container = new createjs.Container();
this.stage.addChild(this.container);
this.container.x = Math.floor(((this.canvas.width / scale) - 650) / 2);
this.container.y = 27;
function processBackground(viewer, name, bitmap, extras) {
viewer.container.addChild(bitmap);
function processPrev(viewer, name, bitmap, extras) {
viewer.prev = bitmap;
viewer.container.addChild(viewer.prev);
viewer.prev.x = 270;
viewer.prev.y = 535;
function processNext(viewer, name, bitmap, scale) {
viewer.next = bitmap;
viewer.container.addChild(viewer.next);
viewer.next.x = 325;
viewer.next.y = 535;
viewer.container.visible = true;
viewer.refreshCanvas();
viewer.completeInit();
loadThumbnailContainerHandler(viewer);
return true;
}
makeViewerBitmap(viewer, NEXTBUTTON, 'viewer', processNext, null);
}
makeViewerBitmap(viewer, PREVBUTTON, 'viewer', processPrev, null);
}
makeViewerBitmap(this, BACKGROUND, 'viewer', processBackground, null);
} else {
this.container.visible = true;
this.refreshCanvas();
this.completeInit();
return true;
}
}
this.downloadImage = function(p, prepareNextImage) {
var header = 'data:image/svg+xml;utf8,';
var name = this.pluginFiles[p] + '.svg';
// console.log('getting ' + name + ' from samples');
if (this.server) {
var data = header + httpGet(name);
} else {
var data = header + SAMPLESSVG[name];
}
var image = new Image();
var viewer = this;
image.onload = function() {
bitmap = new createjs.Bitmap(data);
bitmap.scaleX = 0.5;
bitmap.scaleY = 0.5;
viewer.container.addChild(bitmap);
lastChild = last(viewer.container.children);
viewer.container.swapChildren(bitmap, lastChild);
viewer.dict[viewer.pluginFiles[p]] = bitmap;
x = 5 + (p % 4) * 160;
y = 55 + Math.floor((p % 16) / 4) * 120;
viewer.dict[viewer.pluginFiles[p]].x = x;
viewer.dict[viewer.pluginFiles[p]].y = y;
viewer.dict[viewer.pluginFiles[p]].visible = true;
viewer.refreshCanvas();
if (prepareNextImage !== null) {
prepareNextImage(viewer, p + 1);
}
}
image.src = data;
}
this.completeInit = function() {
var p = 0;
this.prepareNextImage(this, p);
}
this.prepareNextImage = function(viewer, p) {
// TODO: this.pluginFiles.sort()
// Only download the images on the first page.
if (p < viewer.pluginFiles.length && p < (viewer.page * 16 + 16)) {
if (viewer.pluginFiles[p] in viewer.dict) {
x = 5 + (p % 4) * 160;
y = 55 + Math.floor((p % 16) / 4) * 120;
viewer.dict[viewer.pluginFiles[p]].x = x;
viewer.dict[viewer.pluginFiles[p]].y = y;
viewer.dict[viewer.pluginFiles[p]].visible = true;
viewer.prepareNextImage(viewer, p + 1)
} else {
viewer.downloadImage(p, viewer.prepareNextImage);
}
} else {
if (viewer.page === 0) {
viewer.prev.visible = false;
}
if ((viewer.page + 1) * 16 < viewer.pluginFiles.length) {
viewer.next.visible = true;
}
viewer.refreshCanvas();
}
}
}
function hideCurrentPage(viewer) {
var min = viewer.page * 16;
var max = Math.min(viewer.pluginFiles.length, (viewer.page + 1) * 16);
// Hide the current page.
for (var p = min; p < max; p++) {
viewer.dict[viewer.pluginFiles[p]].visible = false;
}
// Go back to previous page.
viewer.page -= 1;
if (viewer.page === 0) {
viewer.prev.visible = false;
}
if ((viewer.page + 1) * 16 < viewer.pluginFiles.length) {
viewer.next.visible = true;
}
// Show the current page.
var min = viewer.page * 16;
var max = Math.min(viewer.pluginFiles.length, (viewer.page + 1) * 16);
for (var p = min; p < max; p++) {
viewer.dict[viewer.pluginFiles[p]].visible = true;
}
viewer.refreshCanvas();
}
function showNextPage(viewer) {
var min = viewer.page * 16;
var max = Math.min(viewer.pluginFiles.length, (viewer.page + 1) * 16);
// Hide the current page.
for (var p = min; p < max; p++) {
viewer.dict[viewer.pluginFiles[p]].visible = false;
}
// Advance to next page.
viewer.page += 1;
viewer.prev.visible = true;
if ((viewer.page + 1) * 16 + 1 > viewer.pluginFiles.length) {
viewer.next.visible = false;
}
viewer.prepareNextImage(viewer, max);
viewer.refreshCanvas();
}
function viewerClicked(viewer, event) {
var x = (event.stageX / viewer.scale) - viewer.container.x;
var y = (event.stageY / viewer.scale) - viewer.container.y;
if (x > 600 && y < 55) {
viewer.hide();
viewer.closeViewer();
} else if (y > 535) {
if (viewer.prev.visible && x < 325) {
hideCurrentPage(viewer);
} else if (viewer.next.visible && x > 325) {
showNextPage(viewer)
}
} else {
// Select a plugin.
var col = Math.floor((x - 5) / 160);
var row = Math.floor((y - 55) / 120);
var p = row * 4 + col + 16 * viewer.page;
if (p < viewer.pluginFiles.length) {
viewer.hide();
viewer.closeViewer();
viewer.loadPlugin(viewer.pluginFiles[p] + '.json');
}
}
}
function loadThumbnailContainerHandler(viewer) {
var hitArea = new createjs.Shape();
var w = 650;
var h = 590;
var startX, startY, endX, endY;
hitArea.graphics.beginFill('#FFF').drawRect(0, 0, w, h);
hitArea.x = 0;
hitArea.y = 0;
viewer.container.hitArea = hitArea;
var locked = false;
viewer.container.on('click', function(event) {
// We need a lock to "debouce" the click.
if (locked) {
console.log('debouncing click');
return;
}
locked = true;
setTimeout(function() {
locked = false;
}, 500);
viewerClicked(viewer, event)
});
viewer.container.on('mousedown', function(event) {
startX = event.stageX;
startY = event.stageY;
locked = true;
});
viewer.container.on('pressup', function(event) {
endX = event.stageX;
endY = event.stageY;
if (endY > startY + 30 || endX > startX + 30) {
// Down or right
if (viewer.next.visible) {
showNextPage(viewer);
}
}
else if(endY < startY - 30 || endX < startX - 30) {
// Up or left
if (viewer.prev.visible) {
hideCurrentPage(viewer);
}
}
else {
locked = false;
viewerClicked(viewer, event)
}
});
}
function makeViewerBitmap(viewer, data, name, callback, extras) {
// Async creation of bitmap from SVG data
// Works with Chrome, Safari, Firefox (untested on IE)
var img = new Image();
img.onload = function() {
bitmap = new createjs.Bitmap(img);
callback(viewer, name, bitmap, extras);
}
img.src = 'data:image/svg+xml;base64,' + window.btoa(
unescape(encodeURIComponent(data)));
}