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.

1686 lines
63 KiB

  1. define(["easel","sugar-web/datastore","sugar-web/env","webL10n","humane"], function (easel, datastore, env, l10n, humane) {
  2. env.getEnvironment(function(err, environment) {
  3. var defaultLanguage = (typeof chrome != 'undefined' && chrome.app && chrome.app.runtime) ? chrome.i18n.getUILanguage() : navigator.language;
  4. var language = environment.user ? environment.user.language : defaultLanguage;
  5. l10n.language.code = language;
  6. console.log('LANG ' + language);
  7. });
  8. function _(text) {
  9. // copied from activity.js
  10. translation = l10n.get(text);
  11. if (translation == '') {
  12. translation = text;
  13. };
  14. return translation;
  15. };
  16. var onAndroid = /Android/i.test(navigator.userAgent);
  17. var smallScreen = (window.innerWidth < 700) || (window.innerHeight < 600);
  18. var font = smallScreen ? "16px Arial" : "24px Arial";
  19. var LINE_WIDTH = 3;
  20. var BLACK = "#000000";
  21. var WHITE = "#ffffff";
  22. // Spanish names for historic reasons
  23. var DIR_DOWN = "abajo";
  24. var DIR_UP = "arriba";
  25. var DIR_LEFT = "izq";
  26. var DIR_RIGHT = "der";
  27. var MODE_NORMAL = 'normal';
  28. var MODE_WHISPER = 'despacio';
  29. var SIZE_RESIZE_AREA = 40; // TODO style.GRID_CELL_SIZE / 2
  30. var TYPE_GLOBE = 'GLOBE';
  31. var TYPE_CLOUD = 'CLOUD';
  32. var TYPE_EXCLAMATION = 'EXCLAMATION';
  33. var TYPE_RECTANGLE = 'RECTANGLE';
  34. // TYPE_WHISPER is saved as TYPE_GLOBE and mode MODE_WHISPER
  35. var TYPE_WHISPER = 'WHISPER';
  36. var DEFAULT_FONT_SIZE = 14;
  37. toon = {};
  38. function createAsyncBitmap(box, url, callback) {
  39. // Async creation of bitmap from SVG data
  40. // Works with Chrome, Safari, Firefox (untested on IE)
  41. var img = new Image();
  42. img.onload = function () {
  43. bitmap = new createjs.Bitmap(img);
  44. bitmap.setBounds(0, 0, img.width, img.height);
  45. bitmap.mouseEnabled = false;
  46. callback(box, bitmap);
  47. };
  48. img.onerror = function (errorMsg, url, lineNumber) {
  49. callback(box, null);
  50. };
  51. img.src = url;
  52. };
  53. function createAsyncBitmapButton(globe, url, callback) {
  54. // creates a square black button with a image inside
  55. // is used for the corner controls in the globe
  56. var img = new Image();
  57. img.cont = null;
  58. img.globe = globe;
  59. img.onload = function () {
  60. var bitmap = new createjs.Bitmap(img);
  61. bitmap.setBounds(0, 0, img.width, img.height);
  62. bounds = bitmap.getBounds();
  63. var scale = SIZE_RESIZE_AREA / bounds.height;
  64. bitmap.scaleX = scale;
  65. bitmap.scaleY = scale;
  66. if (this.cont == null) {
  67. this.cont = new createjs.Container();
  68. this.cont.name = 'button';
  69. var hitArea = new createjs.Shape();
  70. hitArea.graphics.beginFill("#000").drawRect(0, 0,
  71. SIZE_RESIZE_AREA, SIZE_RESIZE_AREA);
  72. this.cont.width = SIZE_RESIZE_AREA;
  73. this.cont.height = SIZE_RESIZE_AREA;
  74. this.cont.hitArea = hitArea;
  75. this.cont.addChild(hitArea);
  76. this.cont.addChild(bitmap);
  77. callback(this.globe, this.cont);
  78. };
  79. };
  80. img.src = url;
  81. return img;
  82. };
  83. function Model(data, canvas, textpalette) {
  84. this._data = data;
  85. // this._data have the following fields:
  86. // 'version':'1' (don't change, for compatibility with python version)
  87. // 'boxs': [] array with the boxes information
  88. // every item have the background properties and a array of globes
  89. //
  90. // The next properites are temporary and are not saved:
  91. // 'images': are loaded async, then have no garatie of be present.
  92. // we use the fact that the first box do not have a background
  93. // image, and expect that when the user change to the next box
  94. // the images will be charged.
  95. // 'previews': loaded from the canvas, will be displayed on the sorting
  96. // mode.
  97. this._canvas = canvas;
  98. this._textpalette = textpalette;
  99. this.comicBox = null;
  100. this._imageCounter = 0;
  101. this._pageCounterDisplay = null;
  102. this._prevButton = null;
  103. this._nextButton = null;
  104. this._boxSorter = null;
  105. this._sortButton = null;
  106. this._data['previews'] = [];
  107. // wait dialog
  108. this._waitMsg = document.getElementById("wait");
  109. this.comicBox = new ComicBox(this._canvas, this);
  110. this.init = function() {
  111. this.activeBox = 0;
  112. var comic_box_data = this._data['boxs'][this.activeBox];
  113. this._imageCounter = this._data['boxs'].length;
  114. if (this._data['boxs'].length == 1) {
  115. if (comic_box_data['globes'].length == 0) {
  116. console.log('EMPTY TOON');
  117. // add a globe for the title
  118. var titleGlobe = {
  119. "direction": null, "text_font_description": "Sans 30",
  120. "globe_type": "RECTANGLE", "height": 50, "width": 200,
  121. "text_color": [0, 0, 0], "radio": 15, "text_width": 76,
  122. "y": this._canvas.height / 2,
  123. "x": this._canvas.width / 2,
  124. "text_height": 8, "title_globe": true,
  125. "text_text": _('Title')};
  126. comic_box_data['globes'].push(titleGlobe);
  127. };
  128. };
  129. this.comicBox.init(comic_box_data, this._data['images']);
  130. this.comicBox.attachTextEditionPalette(this._textpalette);
  131. this._updatePageCounter();
  132. };
  133. this.setData = function(data) {
  134. this._data = data;
  135. this._data['previews'] = [];
  136. this.init();
  137. };
  138. this.showWait = function () {
  139. this._waitMsg.style.display = 'block';
  140. };
  141. this.hideWait = function () {
  142. this._waitMsg.style.display = 'none';
  143. };
  144. this.getTitle = function() {
  145. var firstBoxData = this._data['boxs'][0];
  146. for (var i = 0; i < firstBoxData['globes'].length; i ++) {
  147. var globeData = firstBoxData['globes'][i];
  148. if (globeData['title_globe']) {
  149. return globeData['text_text'];
  150. }
  151. };
  152. return '';
  153. };
  154. this.initSort = function(sortCanvas) {
  155. this._canvas.style.display = 'none';
  156. this._boxSorter = new BoxSorter(sortCanvas, this._data);
  157. this._boxSorter.init();
  158. if (this._pageCounterDisplay != null) {
  159. // hide the page counter
  160. this._pageCounterDisplay.parentNode.style.display = "none";
  161. };
  162. };
  163. this.finishSort = function() {
  164. var sortedBoxes = [];
  165. // get a rray with the new order for the boxes, like [0, 3, 2, 1]
  166. var newOrders = this._boxSorter.getSortOrder();
  167. this.changeToEditMode();
  168. for (var i = 0; i < newOrders.length; i++) {
  169. sortedBoxes.push(this._data['boxs'][newOrders[i]]);
  170. };
  171. this._data['boxs'] = sortedBoxes;
  172. };
  173. this.changeToEditMode = function() {
  174. this._boxSorter.hide();
  175. this._canvas.style.display = 'block';
  176. if (this._pageCounterDisplay != null) {
  177. // hide the page counter
  178. this._pageCounterDisplay.parentNode.style.display = "block";
  179. };
  180. };
  181. this.changeBox = function(newOrder) {
  182. if (newOrder >= 0 && newOrder < this._data['boxs'].length) {
  183. this.updateData();
  184. // load the new data
  185. this.activeBox = newOrder;
  186. this.comicBox.init(this._data['boxs'][this.activeBox],
  187. this._data['images'], (this.activeBox > 0));
  188. this._updatePageCounter();
  189. };
  190. };
  191. this.removeBox = function() {
  192. // remove the actual box */
  193. this._data['boxs'].splice(this.activeBox, 1);
  194. this._data['previews'] = [];
  195. if (this.activeBox > this._data['boxs'].length - 1) {
  196. this.activeBox --;
  197. }
  198. this.comicBox.init(this._data['boxs'][this.activeBox],
  199. this._data['images'], (this.activeBox > 0));
  200. this._updatePageCounter();
  201. };
  202. this.updateData = function() {
  203. this._data['boxs'][this.activeBox] = this.comicBox.getJson();
  204. };
  205. this.initPreviews = function() {
  206. // store the initial preview images
  207. for (var i = 0; i < this._data['boxs'].length; i++) {
  208. this.storePreview(i);
  209. };
  210. };
  211. this.storePreview = function(boxOrder) {
  212. var previewCanvas = document.createElement('canvas');
  213. previewCanvas.width = this._canvas.width;
  214. previewCanvas.height = this._canvas.height;
  215. var previewComicBox = new ComicBox(previewCanvas);
  216. var that = this;
  217. previewComicBox.init(this._data['boxs'][boxOrder],
  218. this._data['images'], false, {canvas: previewCanvas, order: boxOrder}, function(context) {
  219. that._data['previews'][context.order] =
  220. context.canvas.toDataURL("image/png");
  221. });
  222. };
  223. this._updatePageCounter = function() {
  224. if (this._pageCounterDisplay != null) {
  225. this._pageCounterDisplay.innerHTML = (this.activeBox + 1) +
  226. ' ' + _('of') + ' ' + this._data['boxs'].length;
  227. };
  228. if (this._prevButton != null) {
  229. this._prevButton.disabled = (this.activeBox == 0);
  230. };
  231. if (this._nextButton != null) {
  232. this._nextButton.disabled = (this.activeBox ==
  233. (this._data['boxs'].length - 1));
  234. };
  235. if (this._sortButton != null) {
  236. this._sortButton.disabled = this._data['boxs'].length < 3;
  237. }
  238. };
  239. this.addGlobe = function(globeType) {
  240. this.comicBox.addGlobe(globeType);
  241. };
  242. this.showPreviousBox = function() {
  243. var prevBox = this.activeBox - 1;
  244. this.changeBox(prevBox);
  245. };
  246. this.showNextBox = function() {
  247. var nextBox = this.activeBox + 1;
  248. this.changeBox(nextBox);
  249. };
  250. this.addImage = function(url) {
  251. if (this._data['images'] == undefined) {
  252. this._data['images'] = {};
  253. };
  254. this._imageCounter = this._imageCounter + 1;
  255. var imageName = 'bAcKgRoUnD_' + this._imageCounter;
  256. // verify if the name already exists
  257. while (this._data['images'][imageName] != undefined) {
  258. this._imageCounter = this._imageCounter + 1;
  259. imageName = 'bAcKgRoUnD_' + this._imageCounter;
  260. };
  261. var emptyData = {'image_name': imageName, 'globes':[]};
  262. this._data['boxs'].push(emptyData);
  263. this._data['images'][imageName] = url;
  264. this.changeBox(this._data['boxs'].length - 1);
  265. };
  266. this.getData = function() {
  267. this.updateData();
  268. return this._data;
  269. };
  270. this.attachPageCounterViewer = function(div) {
  271. this._pageCounterDisplay = div.children[0];
  272. this._updatePageCounter();
  273. };
  274. this.attachPrevNextButtons = function(prevButton, nextButton) {
  275. this._prevButton = prevButton;
  276. this._nextButton = nextButton;
  277. this._updatePageCounter();
  278. };
  279. this.attachSortButton = function(sortButton) {
  280. this._sortButton = sortButton;
  281. this._updatePageCounter();
  282. };
  283. this.saveAsImage = function(columns) {
  284. /* columns can be '0', '1', or '2'
  285. if '0' means show the images in a single row */
  286. this.showWait();
  287. var cantBoxes = this._data['boxs'].length;
  288. var MARGIN = 20;
  289. if (columns == '0') {
  290. var width = (this._canvas.width + MARGIN) * cantBoxes + MARGIN;
  291. var height = this._canvas.height + MARGIN * 2;
  292. } else if (columns == '1') {
  293. var width = this._canvas.width + MARGIN * 2;
  294. var height = (this._canvas.height + MARGIN) * cantBoxes + MARGIN;
  295. } else if (columns == '2') {
  296. var width = this._canvas.width * 2 + MARGIN * 3;
  297. var height = (this._canvas.height + MARGIN) *
  298. Math.ceil(cantBoxes / 2) + MARGIN;
  299. };
  300. // create the canvas where will draw all
  301. var imageCanvas = document.createElement('canvas');
  302. imageCanvas.width = width;
  303. imageCanvas.height = height;
  304. var ctx = imageCanvas.getContext("2d");
  305. // add a white background
  306. ctx.fillStyle="#FFFFFF";
  307. ctx.fillRect(0, 0, width, height);
  308. var currentbox = 0;
  309. for (var i = 0; i < cantBoxes; i++) {
  310. // load the bix image in a temp canvas
  311. var that = this;
  312. var tmpCanvas = document.createElement('canvas');
  313. tmpCanvas.width = this._canvas.width;
  314. tmpCanvas.height = this._canvas.height;
  315. var tmpComicBox = new ComicBox(tmpCanvas);
  316. tmpComicBox.init(this._data['boxs'][i],
  317. this._data['images'], false, tmpCanvas, function(mycanvas) {
  318. // add to the image canvas
  319. var img = new Image();
  320. img.src = mycanvas.toDataURL("image/png");
  321. img.addEventListener("load", function() {
  322. // calculate coordinates
  323. if (columns == '0') {
  324. var x = MARGIN + (that._canvas.width + MARGIN) * currentbox;
  325. var y = MARGIN;
  326. } else if (columns == '1') {
  327. var x = MARGIN;
  328. var y = MARGIN + (that._canvas.height + MARGIN) * currentbox;
  329. } else if (columns == '2') {
  330. var x = MARGIN + (currentbox % 2) * (that._canvas.width + MARGIN);
  331. var y = MARGIN + Math.floor(currentbox / 2) * (that._canvas.height + MARGIN);
  332. };
  333. // draw image
  334. ctx.drawImage(this, x, y);
  335. if (currentbox++ >= cantBoxes-1) {
  336. // save in datastore
  337. var imgAsDataURL = imageCanvas.toDataURL("image/png");
  338. var metadata = {
  339. mimetype: "image/png",
  340. title: "Image FotoToon",
  341. activity: "org.olpcfrance.MediaViewerActivity",
  342. timestamp: new Date().getTime(),
  343. creation_time: new Date().getTime(),
  344. file_size: 0
  345. };
  346. datastore.create(metadata, function(err) {
  347. if (err) {
  348. console.log("error saving image in journal");
  349. humane.log(_("SavingError"));
  350. } else {
  351. console.log("image saved in journal.");
  352. humane.log(_("ImageSaved"));
  353. }
  354. that.hideWait();
  355. }, imgAsDataURL);
  356. }
  357. });
  358. });
  359. };
  360. };
  361. };
  362. function ComicBox(canvas, model) {
  363. /* model is only used to call the removeBox method,
  364. the data is set in the init() method */
  365. this.canvas = canvas;
  366. this._model = model;
  367. this._width = canvas.width - LINE_WIDTH * 2;
  368. this._height = canvas.height - LINE_WIDTH * 2;
  369. this.stage = new createjs.Stage(canvas);
  370. // Enable touch interactions if supported on the current device
  371. createjs.Touch.enable(this.stage);
  372. this.globes = [];
  373. this._globeSelected = null;
  374. // reference to the text palette used to edit the text in the globes
  375. this._textpalette = null;
  376. this.init = function (data, imagesData, canRemove, context, callback) {
  377. this._data = data;
  378. this.imagesData = imagesData
  379. this.canRemove = canRemove;
  380. this.globes = [];
  381. this.stage.removeAllChildren();
  382. this._backContainer = new createjs.Container();
  383. var background = new createjs.Shape();
  384. background.graphics.setStrokeStyle(LINE_WIDTH, "round");
  385. background.graphics.beginStroke(
  386. BLACK).drawRect(LINE_WIDTH, LINE_WIDTH,
  387. this._width, this._height);
  388. this.stage.addChild(this._backContainer);
  389. this._backContainer.addChild(background);
  390. this._backContainer.cache(0, 0, this.canvas.width, this.canvas.height);
  391. if (this._data != null) {
  392. if (this._data['image_name'] != '' &&
  393. this._data['image_name'] != undefined) {
  394. this._image_x = this._data['img_x'];
  395. this._image_y = this._data['img_y'];
  396. this._image_width = this._data['img_w'];
  397. this._image_height = this._data['img_h'];
  398. this._image_name = this._data['image_name'];
  399. this._slideshow_duration = this._data['slideshow_duration'];
  400. if (this.imagesData != null) {
  401. this._setBackgroundImageDataUrl(
  402. this.imagesData[this._image_name], context, callback);
  403. };
  404. } else {
  405. this._image_x = 0;
  406. this._image_y = 0;
  407. this._image_width = canvas.width;
  408. this._image_height = canvas.height;
  409. this._image_name = '';
  410. this._slideshow_duration = 10;
  411. this.createGlobes();
  412. if (callback) callback(context);
  413. };
  414. };
  415. this.stage.update();
  416. };
  417. this._setBackgroundImageDataUrl = function(imageUrl, context, callback) {
  418. this._image_x = 0;
  419. this._image_y = 0;
  420. this._image_width = this._width;
  421. this._image_height = this._height;
  422. var img = new Image();
  423. var that = this;
  424. img.addEventListener("load", function() {
  425. bitmap = new createjs.Bitmap(img);
  426. bitmap.setBounds(0, 0, img.width, img.height);
  427. // calculate scale
  428. var scale_x = that._width / img.width;
  429. var scale_y = that._height / img.height;
  430. var scale = Math.min(scale_x, scale_y);
  431. bitmap.mouseEnabled = false;
  432. bitmap.x = LINE_WIDTH;
  433. bitmap.y = LINE_WIDTH;
  434. bitmap.scaleX = scale;
  435. bitmap.scaleY = scale;
  436. that._backContainer.addChildAt(bitmap, 0);
  437. // add a trash button
  438. if (that.canRemove) {
  439. createAsyncBitmapButton(that, './icons/remove.svg',
  440. function(comicBox, button) {
  441. button.x = 0;
  442. button.y = comicBox._height - button.height;
  443. button.visible = true;
  444. comicBox._removeButton = button;
  445. comicBox._backContainer.addChildAt(button, 1);
  446. comicBox._backContainer.updateCache();
  447. button.on('click', function(event) {
  448. comicBox.remove();
  449. });
  450. comicBox.createGlobes();
  451. });
  452. } else {
  453. that._backContainer.updateCache();
  454. that.createGlobes();
  455. };
  456. if (callback) {
  457. callback(context);
  458. }
  459. });
  460. img.src = imageUrl;
  461. };
  462. this.remove = function() {
  463. console.log('remove');
  464. this._model.removeBox();
  465. };
  466. this.attachTextEditionPalette = function(textpalette) {
  467. this._textpalette = textpalette;
  468. var box = this;
  469. // NOTE: this not work on IE see here for more info:
  470. // http://stackoverflow.com/questions/2823733/textarea-onchange-detection
  471. this._textpalette.editorElem.addEventListener('input', function() {
  472. if (box.getSelectedGlobe() != null) {
  473. box.getSelectedGlobe().getTextViewer().setText(this.value);
  474. };
  475. }, false);;
  476. var editor = this._textpalette.editorElem;
  477. var colorButtons = this._textpalette.colorButtons;
  478. for (var i = 0; i < colorButtons.length; i++) {
  479. colorButtons[i].addEventListener('click', function(e) {
  480. editor.style.color =
  481. box.getSelectedGlobe().getTextViewer().setColor(this.value);
  482. });
  483. };
  484. this._textpalette.incTextBtn.addEventListener('click', function(e) {
  485. editor.style.fontSize =
  486. box.getSelectedGlobe().getTextViewer().incSize() + "px";
  487. });
  488. this._textpalette.decTextBtn.addEventListener('click', function(e) {
  489. editor.style.fontSize =
  490. box.getSelectedGlobe().getTextViewer().decSize() + "px";
  491. });
  492. this._textpalette.boldTextBtn.addEventListener('click', function(e) {
  493. var bold = box.getSelectedGlobe().getTextViewer().toggleBold();
  494. if (bold) {
  495. editor.style.fontWeight = 'bold';
  496. } else {
  497. editor.style.fontWeight = 'normal';
  498. };
  499. });
  500. this._textpalette.italicTextBtn.addEventListener('click', function(e) {
  501. var italic = box.getSelectedGlobe().getTextViewer().toggleItalic();
  502. if (italic) {
  503. editor.style.fontStyle = 'italic';
  504. } else {
  505. editor.style.fontStyle = 'normal';
  506. };
  507. });
  508. };
  509. this.popupTextEditionPalette = function() {
  510. if (this._textpalette != null) {
  511. this._textpalette.popUp();
  512. this._textpalette.editorElem.focus();
  513. };
  514. };
  515. this.getSelectedGlobe = function() {
  516. return this._globeSelected;
  517. };
  518. this.isGlobeSelected = function(globe) {
  519. return this._globeSelected == globe;
  520. };
  521. this.selectGlobe = function(globe) {
  522. this._globeSelected = globe;
  523. var textpalette = this._textpalette;
  524. this.globes.forEach(
  525. function (element, index, array) {
  526. if (element != globe) {
  527. element.setSelected(false);
  528. } else {
  529. if (textpalette != null) {
  530. textpalette.setText(
  531. element.getTextViewer().getText());
  532. element.getTextViewer().applyTextProperties(
  533. textpalette.editorElem);
  534. };
  535. };
  536. });
  537. };
  538. this.addGlobe = function (globeType) {
  539. var width = 100;
  540. var height = 50;
  541. globeData = {'globe_type': globeType, 'x': 100, 'y': 100,
  542. 'width': width, 'height': height,
  543. 'point_0': width / 2, 'point_1': height / 2,
  544. 'radio': 100, 'direction': DIR_DOWN,
  545. 'mode': MODE_NORMAL};
  546. if (globeType == TYPE_WHISPER) {
  547. globeData['globe_type'] = TYPE_GLOBE;
  548. globeData['mode'] = MODE_WHISPER;
  549. };
  550. var globe = new Globe(this, globeData);
  551. this.globes.push(globe);
  552. this.stage.update();
  553. };
  554. this.getJson = function() {
  555. jsonData = {};
  556. jsonData['img_x'] = this._image_x;
  557. jsonData['img_y'] = this._image_y;
  558. jsonData['img_w'] = this._image_width;
  559. jsonData['img_h'] = this._image_height;
  560. jsonData['image_name'] = this._image_name;
  561. jsonData['slideshow_duration'] = this._slideshow_duration;
  562. jsonData['globes'] = [];
  563. for (var n = 0; n < this.globes.length; n++) {
  564. globe = this.globes[n];
  565. globeData = {};
  566. globeData['globe_type'] = globe._type;
  567. globeData['x'] = globe._x;
  568. globeData['y'] = globe._y;
  569. globeData['width'] = globe._width;
  570. globeData['height'] = globe._height;
  571. if (globe._type != TYPE_RECTANGLE) {
  572. globeData['point_0'] = globe._point[0];
  573. globeData['point_1'] = globe._point[1];
  574. };
  575. if (globe._type == TYPE_GLOBE) {
  576. globeData['mode'] = globe._mode;
  577. };
  578. globeData['radio'] = globe._radio;
  579. globeData['direction'] = globe._direction;
  580. globeData['title_globe'] = globe._isTitleGlobe;
  581. // text properties
  582. globeData['text_text'] = globe._textViewer.getText();
  583. globeData['text_font_description'] =
  584. globe._textViewer.getCairoFontFormat();
  585. globeData['text_color'] =
  586. globe._textViewer.HtmlToGdkColor(
  587. globe._textViewer._color);
  588. globeData['text_width'] = globe._textViewer._width;
  589. globeData['text_height'] = globe._textViewer._height;
  590. jsonData['globes'].push(globeData);
  591. };
  592. return jsonData;
  593. };
  594. this.createGlobes = function() {
  595. var globes = this._data['globes'];
  596. for (var n = 0; n < globes.length; n++) {
  597. var globe = new Globe(this, globes[n]);
  598. this.globes.push(globe);
  599. };
  600. this.stage.update();
  601. };
  602. };
  603. function TextViewer(globe, globeData) {
  604. this._globe = globe;
  605. this._globeData = globeData;
  606. this.init = function() {
  607. this._text = '';
  608. this._color = BLACK;
  609. this._width = globe._width - 20;
  610. this._height = SIZE_RESIZE_AREA / 2;
  611. this._size = DEFAULT_FONT_SIZE;
  612. this._bold = false;
  613. this._italic = false;
  614. if (this._globeData != null) {
  615. /* example of the text data in the json globe data stored
  616. {"text_font_description": "Sans 10",
  617. "text_text": "Hmm, esto parece estar funcionando",
  618. "text_color": [0, 0, 0],
  619. "text_width": 78, "text_height": 22}
  620. NOTE: color components are in the range 0-65535
  621. https://developer.gnome.org/pygtk/stable/class-gdkcolor.html#constructor-gdkcolor
  622. */
  623. if (this._globeData['text_text'] != undefined) {
  624. this._text = this._globeData['text_text'];
  625. };
  626. if (this._globeData['text_font_description'] != undefined) {
  627. this.ReadHtmlFontFormat(
  628. this._globeData['text_font_description']);
  629. };
  630. if (this._globeData['text_color'] != undefined) {
  631. this._color = this.GdkToHtmlColor(
  632. this._globeData['text_color']);
  633. };
  634. if (this._globeData['text_width'] != undefined) {
  635. this._width = this._globeData['text_width'];
  636. };
  637. if (this._globeData['text_height'] != undefined) {
  638. this._height = this._globeData['text_height'];
  639. };
  640. this._textView = null;
  641. };
  642. };
  643. this.GdkToHtmlColor = function(color) {
  644. // int array [r, g, b] are int in the range 0-65535
  645. // returns a str with the format "#rrggbb"
  646. rh = (color[0] / 65535 * 255).toString(16);
  647. gh = (color[1] / 65535 * 255).toString(16);
  648. bh = (color[2] / 65535 * 255).toString(16);
  649. // Number.toString() can return a single char.
  650. if (rh.length < 2) { rh = '0' + rh};
  651. if (gh.length < 2) { gh = '0' + gh};
  652. if (bh.length < 2) { bh = '0' + bh};
  653. return "#" + rh + gh + bh;
  654. };
  655. this.HtmlToGdkColor = function(rgb) {
  656. // rgb is a str with the format "#rrggbb"
  657. // return a array [r, g, b] with int in the range 0-65535
  658. rh = rgb.substr(1, 2);
  659. gh = rgb.substr(3, 2);
  660. bh = rgb.substr(5, 2);
  661. r = parseInt(rh, 16) / 255 * 65535;
  662. g = parseInt(gh, 16) / 255 * 65535;
  663. b = parseInt(bh, 16) / 255 * 65535;
  664. return [r, g, b];
  665. };
  666. this.ReadHtmlFontFormat = function(cairoFormat) {
  667. // get a str with format "Sans 10" or "Sans bold 10"
  668. // return a str with format "10px Sans" or "bold 10px Sans"
  669. var parts = cairoFormat.split(' ');
  670. var family = parts[0];
  671. if (parts.length == 2) {
  672. size = parts[1];
  673. style = '';
  674. } else {
  675. style = parts[1] + ' ';
  676. size = parts[2];
  677. };
  678. this._size = Number(size);
  679. this._family = family;
  680. this._bold = style.toLowerCase().indexOf('bold') > -1;
  681. this._italic = style.toLowerCase().indexOf('italic') > -1;
  682. };
  683. this.getCairoFontFormat = function() {
  684. // return a str with format "Sans 10" or "Sans bold 10"
  685. var cairoFormat = this._family;
  686. if (this._bold) {
  687. cairoFormat = cairoFormat + ' ' + 'bold';
  688. };
  689. if (this._italic) {
  690. cairoFormat = cairoFormat + ' ' + 'italic';
  691. };
  692. return cairoFormat + ' ' + this._size;
  693. };
  694. this.getFontDescription = function() {
  695. // return a str with format "10px Sans" or "bold 10px Sans"
  696. var cairoFormat = '';
  697. if (this._bold) {
  698. cairoFormat = cairoFormat + ' ' + 'bold';
  699. };
  700. if (this._italic) {
  701. cairoFormat = cairoFormat + ' ' + 'italic';
  702. };
  703. return cairoFormat + ' ' + this._size + 'px ' + this._family;
  704. };
  705. this.update = function() {
  706. if (this._textView != null) {
  707. this._globe._stage.removeChild(this._textView);
  708. };
  709. this._textView = new createjs.Text(this._text,
  710. this.getFontDescription(),
  711. this._color);
  712. this._textView.textAlign = 'center';
  713. this._textView.lineWidth = this._globe._width * 2;
  714. this._textView.x = this._globe._x;
  715. this._textView.y = this._globe._y -
  716. this._textView.getMeasuredHeight() / 2;
  717. this._globe._stage.addChild(this._textView);
  718. this._globe._stage.update();
  719. };
  720. this.getText = function() {
  721. return this._text;
  722. };
  723. this.setText = function(text) {
  724. this._text = text;
  725. this.update();
  726. };
  727. this.setColor = function(color) {
  728. this._color = color;
  729. this.update();
  730. return this._color;
  731. };
  732. this.incSize = function() {
  733. if (this._size < 60) {
  734. this._size = this._size + Math.round(this._size / 4);
  735. this.update();
  736. };
  737. return this._size;
  738. };
  739. this.decSize = function() {
  740. if (this._size > 10) {
  741. this._size = this._size - Math.round(this._size / 4);
  742. this.update();
  743. };
  744. return this._size;
  745. };
  746. this.toggleBold = function() {
  747. this._bold = ! this._bold;
  748. this.update();
  749. return this._bold;
  750. };
  751. this.toggleItalic = function() {
  752. this._italic = ! this._italic;
  753. this.update();
  754. return this._italic;
  755. };
  756. this.applyTextProperties = function(editor) {
  757. // apply the viewer text properties to the editor
  758. // (used when a globe is selected)
  759. editor.style.fontSize = this._size + 'px';
  760. editor.style.color = this._color;
  761. if (this._italic) {
  762. editor.style.fontStyle = 'italic';
  763. } else {
  764. editor.style.fontStyle = 'normal';
  765. };
  766. if (this._bold) {
  767. editor.style.fontWeight = 'bold';
  768. } else {
  769. editor.style.fontWeight = 'normal';
  770. };
  771. };
  772. this.remove = function() {
  773. this._globe._stage.removeChild(this._textView);
  774. };
  775. this.init();
  776. return this;
  777. };
  778. function Globe(box, globeData) {
  779. this._box = box;
  780. this._stage = box.stage;
  781. this._shapeControls = null;
  782. this._pointerControl = null;
  783. this._resizeButton = null;
  784. this._editButton = null;
  785. this._rotateButton = null;
  786. this._removeButton = null;
  787. this._shapeChanged = true;
  788. this._pointerChanged = true;
  789. this.init = function() {
  790. if (globeData == null) {
  791. this._type = TYPE_GLOBE;
  792. this._x = 100;
  793. this._y = 100;
  794. this._width = 100;
  795. this._height = 50;
  796. this._point = [this._width / 2,
  797. this._height / 2];
  798. this._radio = 100;
  799. this._direction = DIR_DOWN;
  800. this._textViewer = new TextViewer(this, null);
  801. this._mode = MODE_NORMAL;
  802. // title_globe can't be deleted
  803. this._isTitleGlobe = false;
  804. } else {
  805. /* example of the json data stored
  806. {"direction": "abajo", "text_font_description": "Sans 10",
  807. "globe_type": "GLOBE",
  808. "text_text": "Hmm, esto parece estar funcionando",
  809. "height": 36.66666666666667, "width": 130.0,
  810. "text_color": [0, 0, 0], "radio": 30, "mode": "normal",
  811. "text_width": 78, "y": 63.0, "x": 202.0,
  812. "text_height": 22, "title_globe": false, "point_0": 40.5,
  813. "point_1": 54}
  814. */
  815. this._type = globeData['globe_type'];
  816. this._x = globeData['x'];
  817. this._y = globeData['y'];
  818. this._width = globeData['width'];
  819. this._height = globeData['height'];
  820. if (this._type != TYPE_RECTANGLE) {
  821. this._point = [globeData['point_0'],
  822. globeData['point_1']];
  823. } else {
  824. this._point = [0, 0];
  825. };
  826. if (this._type == TYPE_GLOBE) {
  827. this._mode = globeData['mode'];
  828. } else {
  829. this._mode = MODE_NORMAL;
  830. };
  831. this._radio = globeData['radio'];
  832. this._direction = globeData['direction'];
  833. this._textViewer = new TextViewer(this, globeData);
  834. this._isTitleGlobe = globeData['title_globe'];
  835. };
  836. this._shape = null;
  837. };
  838. this.createShape = function() {
  839. if (this._shape != null) {
  840. this._stage.removeChild(this._shape);
  841. if (this._type == TYPE_CLOUD) {
  842. this._stage.removeChild(this._shapeCircles);
  843. };
  844. };
  845. var scale_x = this._width /this._radio;
  846. var scale_y = this._height /this._radio;
  847. var scaled_x = this._x / scale_x;
  848. var scaled_y = this._y / scale_y;
  849. if (this._type == TYPE_CLOUD) {
  850. this.createShapeCloud(scaled_x, scaled_y, scale_x, scale_y);
  851. } else if (this._type == TYPE_EXCLAMATION) {
  852. this.createShapeExclamation(scaled_x, scaled_y, scale_x, scale_y);
  853. } else if (this._type == TYPE_RECTANGLE) {
  854. this.createShapeRectangle();
  855. } else {
  856. this.createShapeGlobe(scaled_x, scaled_y, scale_x, scale_y);
  857. };
  858. this._shape.on('click', function(event) {
  859. this.setSelected(true);
  860. }, this);
  861. this._shape.on("pressmove",function(event) {
  862. this._x = event.stageX;
  863. this._y = event.stageY;
  864. this.setSelected(true);
  865. this.update();
  866. }, this);
  867. };
  868. this.getSelected = function() {
  869. return this._box.isGlobeSelected(this);
  870. };
  871. this.setSelected = function(selected) {
  872. if (selected) {
  873. this._box.selectGlobe(this);
  874. this._shapeControls.visible = true;
  875. if (this._type != TYPE_RECTANGLE) {
  876. this._pointerControl.visible = true;
  877. this._rotateButton.visible = true;
  878. };
  879. this._resizeButton.visible = true;
  880. this._editButton.visible = true;
  881. if (!this._isTitleGlobe) {
  882. this._removeButton.visible = true;
  883. };
  884. } else {
  885. this._shapeControls.visible = false;
  886. if (this._type != TYPE_RECTANGLE) {
  887. this._pointerControl.visible = false;
  888. this._rotateButton.visible = false;
  889. };
  890. this._resizeButton.visible = false;
  891. this._editButton.visible = false;
  892. if (!this._isTitleGlobe) {
  893. this._removeButton.visible = false;
  894. };
  895. };
  896. this._stage.update();
  897. };
  898. this.getTextViewer = function() {
  899. return this._textViewer;
  900. };
  901. this.createShapeGlobe = function(x, y, scale_x, scale_y) {
  902. switch (this._direction) {
  903. case DIR_DOWN:
  904. var begin = 100;
  905. var end = 80;
  906. break;
  907. case DIR_RIGHT:
  908. var begin = 10;
  909. var end = 350;
  910. break;
  911. case DIR_LEFT:
  912. var begin = 190;
  913. var end = 170;
  914. break;
  915. case DIR_UP:
  916. var begin = 280;
  917. var end = 260;
  918. };
  919. this._shape = new createjs.Shape();
  920. this._shape.name = 'globe';
  921. this._stage.addChild(this._shape);
  922. this._shape.graphics.setStrokeStyle(LINE_WIDTH, "round",
  923. null, null, true);
  924. this._shape.graphics.beginStroke(BLACK);
  925. this._shape.graphics.beginFill(WHITE);
  926. if (this._mode == MODE_WHISPER) {
  927. this._shape.graphics.setStrokeDash([3]);
  928. };
  929. this._shape.graphics.arc(x, y, this._radio,
  930. begin / (180.0) * Math.PI,
  931. end / (180.0) * Math.PI)
  932. point_pos = this.getPointPosition(true);
  933. this._shape.graphics.lineTo(point_pos[0], point_pos[1]);
  934. this._shape.graphics.closePath();
  935. this._shape.graphics.endStroke();
  936. this._shape.setTransform(0, 0, scale_x, scale_y);
  937. };
  938. this.createShapeRectangle = function() {
  939. var x = this._x;
  940. var y = this._y;
  941. var w = this._width;
  942. var h = this._height;
  943. this._shape = new createjs.Shape();
  944. this._shape.name = 'rect';
  945. this._stage.addChild(this._shape);
  946. this._shape.graphics.setStrokeStyle(LINE_WIDTH, "round",
  947. null, null, true);
  948. this._shape.graphics.beginStroke(BLACK);
  949. this._shape.graphics.beginFill(WHITE);
  950. this._shape.graphics.rect(x - w , y - h, w * 2, h * 2);
  951. this._shape.graphics.endStroke();
  952. };
  953. this.createShapeCloud = function(x, y, scale_x, scale_y) {
  954. this._shape = new createjs.Shape();
  955. this._shape.name = 'cloud';
  956. this._stage.addChild(this._shape);
  957. this._shape.graphics.setStrokeStyle(LINE_WIDTH, "round",
  958. null, null, true);
  959. this._shape.graphics.beginStroke(BLACK);
  960. this._shape.graphics.beginFill(WHITE);
  961. var w = this._width / scale_x;
  962. var h = this._height / scale_y;
  963. var steps = 36;
  964. var state = 0;
  965. for (var i = 0; i < steps; i++) {
  966. var alpha = 2.0 * i * (Math.PI / steps);
  967. var sinalpha = Math.sin(alpha);
  968. var cosalpha = Math.cos(alpha);
  969. if (state == 0) {
  970. var x1 = x + w * cosalpha;
  971. var y1 = y + h * sinalpha;
  972. } else if (state == 1) {
  973. var x2 = x + w * cosalpha;
  974. var y2 = y + h * sinalpha;
  975. } else if (state == 2) {
  976. var x3 = x + 0.8 * w * cosalpha;
  977. var y3 = y + 0.8 * h * sinalpha;
  978. };
  979. if (state == 2) {
  980. this._shape.graphics.bezierCurveTo(x1, y1, x2, y2, x3, y3);
  981. };
  982. state += 1;
  983. if (state == 3) {
  984. state = 0;
  985. };
  986. if (i == 0) {
  987. this._shape.graphics.moveTo(x1, y1);
  988. };
  989. };
  990. x1 = x + w * cosalpha;
  991. y1 = y + h * sinalpha;
  992. x2 = x + w;
  993. y2 = y;
  994. x3 = x + w;
  995. y3 = y;
  996. this._shape.graphics.bezierCurveTo(x1, y1, x2, y2, x3, y3);
  997. this._shape.graphics.closePath();
  998. this._shape.graphics.endStroke();
  999. firstCirclePos = this.getCloudPointPosition();
  1000. this._shapeCircles = new createjs.Shape();
  1001. this._shapeCircles.name = 'cloud circles';
  1002. this._stage.addChild(this._shapeCircles);
  1003. this._shapeCircles.graphics.setStrokeStyle(LINE_WIDTH, "round");
  1004. this._shapeCircles.graphics.beginStroke(BLACK);
  1005. this._shapeCircles.graphics.beginFill(WHITE);
  1006. this._shapeCircles.graphics.arc(
  1007. firstCirclePos[0], firstCirclePos[1], 7,
  1008. 0, 2 * Math.PI);
  1009. this._shapeCircles.graphics.endStroke();
  1010. secondCirclePos = this.getPointPosition(false);
  1011. this._shapeCircles.graphics.beginStroke(BLACK);
  1012. this._shapeCircles.graphics.beginFill(WHITE);
  1013. this._shapeCircles.graphics.arc(
  1014. secondCirclePos[0], secondCirclePos[1], 5,
  1015. 0, 2 * Math.PI);
  1016. this._shapeCircles.graphics.endStroke();
  1017. this._shape.setTransform(0, 0, scale_x, scale_y);
  1018. };
  1019. this.getCloudPointPosition = function() {
  1020. var x = this._x;
  1021. var y = this._y;
  1022. var w = this._width;
  1023. var h = this._height;
  1024. switch (this._direction) {
  1025. case DIR_DOWN:
  1026. return [x + this._point[0] / 2,
  1027. y + h + this._point[1] / 2];
  1028. case DIR_RIGHT:
  1029. return [x + w + this._point[0] / 2,
  1030. y + this._point[1] / 2];
  1031. case DIR_LEFT:
  1032. return [x - w - this._point[0] / 2,
  1033. y + this._point[1] / 2];
  1034. case DIR_UP:
  1035. return [x + this._point[0] / 2,
  1036. y - h - this._point[1] / 2];
  1037. };
  1038. };
  1039. this.createShapeExclamation = function(x, y, scale_x, scale_y) {
  1040. this._shape = new createjs.Shape();
  1041. this._shape.name = 'exclamation';
  1042. this._stage.addChild(this._shape);
  1043. this._shape.graphics.setStrokeStyle(LINE_WIDTH, "round",
  1044. null, null, true);
  1045. this._shape.graphics.beginStroke(BLACK);
  1046. this._shape.graphics.beginFill(WHITE);
  1047. var w = this._width / scale_x;
  1048. var h = this._height / scale_y;
  1049. var steps = 24;
  1050. for (var i = 0; i < steps; i++) {
  1051. var alpha = 2.0 * i * (Math.PI / steps);
  1052. var sinalpha = Math.sin(alpha);
  1053. var cosalpha = Math.cos(alpha);
  1054. if (i % 2 > 0) {
  1055. xi = x + 0.8 * w * cosalpha;
  1056. yi = y + 0.8 * h * sinalpha;
  1057. } else {
  1058. xi = x + w * cosalpha;
  1059. yi = y + h * sinalpha;
  1060. };
  1061. if ((this._direction == DIR_DOWN && i == 6) ||
  1062. (this._direction == DIR_RIGHT && i == 0) ||
  1063. (this._direction == DIR_LEFT && i == 12) ||
  1064. (this._direction == DIR_UP && i == 18)) {
  1065. pos = this.getPointPosition(true);
  1066. xi = pos[0];
  1067. yi = pos[1];
  1068. };
  1069. if (i == 0) {
  1070. this._shape.graphics.moveTo(xi, yi);
  1071. } else {
  1072. this._shape.graphics.lineTo(xi, yi);
  1073. };
  1074. }
  1075. this._shape.graphics.closePath();
  1076. this._shape.graphics.endStroke();
  1077. this._shape.setTransform(0, 0, scale_x, scale_y);
  1078. };
  1079. this.createControls = function() {
  1080. var x = this._x;
  1081. var y = this._y;
  1082. var w = this._width;
  1083. var h = this._height;
  1084. if (this._shapeControls != null && this._shapeChanged) {
  1085. this._stage.removeChild(this._shapeControls);
  1086. this._shapeControls = null;
  1087. };
  1088. if (this._shapeControls == null) {
  1089. this._shapeControls = new createjs.Shape();
  1090. this._shapeControls.name = 'control_rect';
  1091. // draw dotted rectangle around the globe
  1092. this._shapeControls.graphics.setStrokeStyle(1, "round");
  1093. this._shapeControls.graphics.beginStroke(WHITE);
  1094. this._shapeControls.x = x;
  1095. this._shapeControls.y = y;
  1096. this._shapeControls.graphics.rect(- w ,- h, w * 2, h * 2);
  1097. this._shapeControls.graphics.setStrokeDash([2]);
  1098. this._shapeControls.graphics.beginFill("rgba(0, 0, 0, 0)");
  1099. this._shapeControls.graphics.beginStroke(BLACK);
  1100. this._shapeControls.graphics.rect(- w ,- h, w * 2, h * 2);
  1101. this._shapeControls.graphics.endStroke();
  1102. this._shapeControls.visible = this.getSelected();
  1103. this._stage.addChild(this._shapeControls);
  1104. } else {
  1105. this._shapeControls.visible = this.getSelected();
  1106. this._shapeControls.x = x;
  1107. this._shapeControls.y = y;
  1108. };
  1109. // point position
  1110. if (this._type != TYPE_RECTANGLE) {
  1111. if (this._pointerControl != null &&
  1112. (this._pointerChanged || this._shapeChanged)) {
  1113. this._stage.removeChild(this._pointerControl);
  1114. this._pointerControl = null;
  1115. };
  1116. if (this._pointerControl == null) {
  1117. this._pointerControl = new createjs.Shape();
  1118. this._pointerControl.x = x;
  1119. this._pointerControl.y = y;
  1120. point_pos = this.getPointPositionRelative();
  1121. this._pointerControl.graphics.beginStroke(BLACK);
  1122. this._pointerControl.graphics.arc(point_pos[0], point_pos[1],
  1123. SIZE_RESIZE_AREA / 2,
  1124. 0, 2 * Math.PI);
  1125. this._pointerControl.graphics.endStroke();
  1126. var hitArea = new createjs.Shape();
  1127. hitArea.graphics.beginFill("#000").arc(
  1128. point_pos[0], point_pos[1], SIZE_RESIZE_AREA / 2,
  1129. 0, 2 * Math.PI);
  1130. this._pointerControl.hitArea = hitArea;
  1131. this._pointerControl.visible = this.getSelected();
  1132. this._stage.addChild(this._pointerControl);
  1133. this._pointerControl.on("pressmove",function(event) {
  1134. this.setPointPosition(event.stageX, event.stageY);
  1135. this._box.selectGlobe(this);
  1136. this._pointerChanged = true;
  1137. this.update();
  1138. }, this);
  1139. } else {
  1140. this._pointerControl.x = x;
  1141. this._pointerControl.y = y;
  1142. this._pointerControl.visible = this.getSelected();
  1143. };
  1144. };
  1145. if (this._resizeButton == null) {
  1146. createAsyncBitmapButton(this, './icons/resize.svg',
  1147. function(globe, button) {
  1148. button.x = globe._x - globe._width - button.width / 2;
  1149. button.y = globe._y - globe._height - button.height / 2;
  1150. button.visible = globe.getSelected();
  1151. globe._resizeButton = button;
  1152. globe._stage.addChild(button);
  1153. globe._stage.update();
  1154. button.on('pressmove', function(event) {
  1155. this._width = Math.max(globe._x - event.stageX,
  1156. SIZE_RESIZE_AREA / 2);
  1157. this._height = Math.max(globe._y - event.stageY,
  1158. SIZE_RESIZE_AREA / 2);
  1159. this._shapeChanged = true;
  1160. this.update();
  1161. }, globe);
  1162. });
  1163. } else {
  1164. this._resizeButton.x = this._x - this._width - this._resizeButton.width / 2;
  1165. this._resizeButton.y = this._y - this._height - this._resizeButton.height / 2;
  1166. this._resizeButton.visible = this.getSelected();
  1167. };
  1168. if (this._editButton == null) {
  1169. createAsyncBitmapButton(this, './icons/edit.svg',
  1170. function(globe, button) {
  1171. button.x = globe._x + globe._width - button.width / 2;
  1172. button.y = globe._y - globe._height - button.height / 2;
  1173. button.visible = globe.getSelected();
  1174. globe._editButton = button;
  1175. globe._stage.addChild(button);
  1176. globe._stage.update();
  1177. button.on('click', function(event) {
  1178. globe._box.popupTextEditionPalette();
  1179. });
  1180. });
  1181. } else {
  1182. this._editButton.x = this._x + this._width - this._editButton.width / 2;
  1183. this._editButton.y = this._y - this._height - this._editButton.height / 2;
  1184. this._editButton.visible = this.getSelected();
  1185. };
  1186. if (this._type != TYPE_RECTANGLE) {
  1187. if (this._rotateButton == null) {
  1188. createAsyncBitmapButton(this, './icons/object_rotate_right.svg',
  1189. function(globe, button) {
  1190. button.x = globe._x + globe._width - button.width / 2;
  1191. button.y = globe._y + globe._height - button.height / 2;
  1192. button.visible = globe.getSelected();
  1193. globe._rotateButton = button;
  1194. globe._stage.addChild(button);
  1195. globe._stage.update();
  1196. button.on('click', function(event) {
  1197. globe.rotate();
  1198. });
  1199. });
  1200. } else {
  1201. this._rotateButton.x = this._x + this._width - this._rotateButton.width / 2;
  1202. this._rotateButton.y = this._y + this._height - this._rotateButton.height / 2;
  1203. this._rotateButton.visible = this.getSelected();
  1204. };
  1205. };
  1206. if (! this._isTitleGlobe) {
  1207. if (this._removeButton == null) {
  1208. createAsyncBitmapButton(this, './icons/remove.svg',
  1209. function(globe, button) {
  1210. button.x = globe._x - globe._width - button.width / 2;
  1211. button.y = globe._y + globe._height - button.height / 2;
  1212. button.visible = globe.getSelected();
  1213. globe._removeButton = button;
  1214. globe._stage.addChild(button);
  1215. globe._stage.update();
  1216. button.on('click', function(event) {
  1217. globe.remove();
  1218. });
  1219. });
  1220. } else {
  1221. this._removeButton.x = this._x - this._width - this._removeButton.width / 2;
  1222. this._removeButton.y = this._y + this._height - this._removeButton.height / 2;
  1223. this._removeButton.visible = this.getSelected();
  1224. };
  1225. };
  1226. this._shapeChanged = false;
  1227. this._pointerChanged = false;
  1228. };
  1229. this.rotate = function () {
  1230. switch (this._direction) {
  1231. case DIR_DOWN:
  1232. this._direction = DIR_LEFT;
  1233. break;
  1234. case DIR_RIGHT:
  1235. this._direction = DIR_DOWN;
  1236. break;
  1237. case DIR_LEFT:
  1238. this._direction = DIR_UP;
  1239. break;
  1240. case DIR_UP:
  1241. this._direction = DIR_RIGHT;
  1242. break;
  1243. };
  1244. var i = this._point[0];
  1245. this._point[0] = this._point[1]; this._point[1] = i;
  1246. this._pointerChanged = true;
  1247. this.update();
  1248. };
  1249. this.remove = function() {
  1250. var globeIndex = this._box.globes.indexOf(this);
  1251. if (globeIndex != -1) {
  1252. this._box.globes.splice(globeIndex, 1);
  1253. this._stage.removeChild(this._shape);
  1254. this._stage.removeChild(this._shapeControls);
  1255. if (this._type != TYPE_RECTANGLE) {
  1256. this._stage.removeChild(this._pointerControl);
  1257. this._stage.removeChild(this._rotateButton);
  1258. };
  1259. if (this._type == TYPE_CLOUD) {
  1260. this._stage.removeChild(this._shapeCircles);
  1261. };
  1262. this._stage.removeChild(this._resizeButton);
  1263. this._stage.removeChild(this._editButton);
  1264. this._stage.removeChild(this._removeButton);
  1265. this._textViewer.remove();
  1266. this._stage.update();
  1267. };
  1268. };
  1269. this.update = function() {
  1270. this.createShape();
  1271. this._textViewer.update();
  1272. this.createControls();
  1273. this._stage.update();
  1274. }
  1275. this.getPointPosition = function (scaled) {
  1276. var scale_x = 1;
  1277. var scale_y = 1;
  1278. if (scaled) {
  1279. scale_x = this._width / this._radio;
  1280. scale_y = this._height / this._radio;
  1281. };
  1282. var x = this._x / scale_x;
  1283. var y = this._y /scale_y;
  1284. var w = this._width / scale_x;
  1285. var h = this._height /scale_y;
  1286. switch (this._direction) {
  1287. case DIR_DOWN:
  1288. return [x + this._point[0] / scale_x,
  1289. y + h + this._point[1] / scale_y];
  1290. case DIR_RIGHT:
  1291. return [x + w + this._point[0] / scale_x,
  1292. y + this._point[1] / scale_y];
  1293. case DIR_LEFT:
  1294. return [x - w - this._point[0] / scale_x,
  1295. y + this._point[1] / scale_y];
  1296. case DIR_UP:
  1297. return [x + this._point[0] / scale_x,
  1298. y - h - this._point[1] / scale_y];
  1299. };
  1300. };
  1301. this.getPointPositionRelative = function () {
  1302. var w = this._width;
  1303. var h = this._height;
  1304. switch (this._direction) {
  1305. case DIR_DOWN:
  1306. return [this._point[0], h + this._point[1]];
  1307. case DIR_RIGHT:
  1308. return [w + this._point[0], this._point[1]];
  1309. case DIR_LEFT:
  1310. return [- w - this._point[0], this._point[1]];
  1311. case DIR_UP:
  1312. return [this._point[0], - h - this._point[1]];
  1313. };
  1314. };
  1315. this.setPointPosition = function (new_x, new_y) {
  1316. switch (this._direction) {
  1317. case DIR_DOWN:
  1318. this._point[0] = new_x - this._x;
  1319. this._point[1] = new_y - this._y - this._height;
  1320. break;
  1321. case DIR_RIGHT:
  1322. this._point[0] = new_x - this._x - this._width;
  1323. this._point[1] = new_y - this._y;
  1324. break;
  1325. case DIR_LEFT:
  1326. this._point[0] = - new_x + this._x - this._width;
  1327. this._point[1] = new_y - this._y;
  1328. break;
  1329. case DIR_UP:
  1330. this._point[0] = new_x - this._x;
  1331. this._point[1] = - new_y + this._y - this._height;
  1332. };
  1333. };
  1334. this.init();
  1335. this.update();
  1336. };
  1337. function BoxSorter(canvas, data) {
  1338. this.canvas = canvas;
  1339. this._data = data;
  1340. this._width = canvas.width - LINE_WIDTH * 2;
  1341. this._height = canvas.height - LINE_WIDTH * 2;
  1342. this._previewWidth = this._height * 4 / 3;
  1343. this._previewBitmaps = [];
  1344. this._deltaX = null;
  1345. this.stage = new createjs.Stage(canvas);
  1346. // Enable touch interactions if supported on the current device
  1347. createjs.Touch.enable(this.stage);
  1348. this.init = function () {
  1349. this.canvas.style.display = 'block';
  1350. this._backContainer = new createjs.Container();
  1351. var background = new createjs.Shape();
  1352. background.graphics.setStrokeStyle(LINE_WIDTH, "round");
  1353. background.graphics.beginStroke(
  1354. BLACK).drawRect(LINE_WIDTH, LINE_WIDTH,
  1355. this._width, this._height);
  1356. this.stage.addChild(this._backContainer);
  1357. this._backContainer.addChild(background);
  1358. this._backContainer.cache(0, 0, this.canvas.width, this.canvas.height);
  1359. this.loadPreviews();
  1360. this.stage.update();
  1361. };
  1362. this.hide = function() {
  1363. this.canvas.style.display = 'none';
  1364. };
  1365. this.loadPreviews = function () {
  1366. // create bitmaps for every box preview (if not avilable,
  1367. // use the background
  1368. for (var i = 0;i < this._data['boxs'].length; i++) {
  1369. var imageData = this._data['previews'][i];
  1370. if (imageData == undefined) {
  1371. var imageName = this._data['boxs'][i]['image_name'];
  1372. // if the preview was not loaded use the background
  1373. if (imageName != '' && imageName != undefined) {
  1374. imageData = this._data['images'][imageName];
  1375. };
  1376. };
  1377. if (imageData != undefined) {
  1378. this._createPreview(imageData, i);
  1379. };
  1380. };
  1381. };
  1382. this.getSortOrder = function() {
  1383. var newOrder = [0];
  1384. for (var i = 0; i < this._previewBitmaps.length; i++) {
  1385. newOrder.push(this._previewBitmaps[i]._order);
  1386. };
  1387. return newOrder;
  1388. };
  1389. this._createPreview = function(imageUrl, order) {
  1390. var img = new Image();
  1391. var that = this;
  1392. img.addEventListener("load", function() {
  1393. bitmap = new createjs.Bitmap(this);
  1394. bitmap.setBounds(0, 0, this.width, this.height);
  1395. bitmap._order = order;
  1396. // calculate scale
  1397. var scale_x = that._previewWidth / this.width;
  1398. var scale_y = that._height / this.height;
  1399. var scale = Math.min(scale_x, scale_y);
  1400. bitmap.x = that._previewWidth * order;
  1401. bitmap.y = LINE_WIDTH;
  1402. bitmap.scaleX = scale;
  1403. bitmap.scaleY = scale;
  1404. var hitArea = new createjs.Shape();
  1405. hitArea.graphics.beginFill("#000").drawRect(
  1406. 0, 0, this.width, this.height);
  1407. bitmap.hitArea = hitArea;
  1408. // don't move first box
  1409. if (order > 0) {
  1410. that._previewBitmaps.push(bitmap);
  1411. bitmap.on('pressmove', function(event) {
  1412. console.log('TOON pressmove');
  1413. if (that._deltaX == null) {
  1414. that._deltaX = event.stageX - event.target.x;
  1415. // move the bitmap to the top
  1416. var thisBitmap = event.target;
  1417. that.stage.sortChildren(function (bitmapA, bitmapB) {
  1418. if (bitmapA == thisBitmap) {
  1419. return 1;
  1420. } else {
  1421. return 0;
  1422. };});
  1423. };
  1424. new_x = event.stageX - that._deltaX;
  1425. if (new_x > this._previewWidth / 2) {
  1426. event.target.x = new_x;
  1427. that.stage.update();
  1428. };
  1429. }, that);
  1430. bitmap.on('pressup', function(event) {
  1431. console.log('TOON pressup');
  1432. that._deltaX = null;
  1433. // sort the preview bitmaps
  1434. that._previewBitmaps.sort(function (bitmapA, bitmapB) {
  1435. return bitmapA.x - bitmapB.x;});
  1436. // adjust the positions
  1437. for (var i = 0; i < that._previewBitmaps.length; i++) {
  1438. that._previewBitmaps[i].x = that._previewWidth * (i + 1);
  1439. };
  1440. that.stage.update();
  1441. }, that);
  1442. };
  1443. that.stage.addChildAt(bitmap, 0);
  1444. that.stage.update();
  1445. });
  1446. img.src = imageUrl;
  1447. }
  1448. };
  1449. toon.Model = Model;
  1450. toon.TYPE_GLOBE = TYPE_GLOBE;
  1451. toon.TYPE_CLOUD = TYPE_CLOUD;
  1452. toon.TYPE_EXCLAMATION = TYPE_EXCLAMATION;
  1453. toon.TYPE_RECTANGLE = TYPE_RECTANGLE;
  1454. toon.TYPE_WHISPER = TYPE_WHISPER;
  1455. return toon;
  1456. });