support current trunk
[mandelbrot.git] / content / mandelbrot.js
index 68cdffe30e20cb902589518683a53182fefd3903..279d3ae26f2a656438ab4b561f85bb3310f9d128 100644 (file)
  *
  * ***** END LICENSE BLOCK ***** */
 
+Components.utils.import("resource://gre/modules/Services.jsm");
+
 var gColorPalette = [];
-var gPref = Components.classes["@mozilla.org/preferences-service;1"]
-                      .getService(Components.interfaces.nsIPrefService)
-                      .getBranch(null);
 var gStartTime = 0;
 var gMbrotBundle;
 var gCurrentImageData;
+var gLastImageData;
 
 function Startup() {
-  updateIterMenu();
-  updateAlgoMenu();
-  updatePaletteMenu();
   gMbrotBundle = document.getElementById("mbrotBundle");
   document.getElementById("statusLabel").value = gMbrotBundle.getString("statusEmpty");
 
@@ -61,6 +58,8 @@ function Startup() {
   img.addEventListener("touchcancel", imgEvHandler, false);
   img.addEventListener("touchleave", imgEvHandler, false);
   img.addEventListener("touchmove", imgEvHandler, false);
+
+  Services.obs.notifyObservers(window, "mandelbrot-loaded", null);
 }
 
 function getAdjustPref(prefname) {
@@ -70,48 +69,48 @@ function getAdjustPref(prefname) {
     case "image.height":
       value = 0;
       try {
-        value = gPref.getIntPref("mandelbrot." + prefname);
+        value = Services.prefs.getIntPref("mandelbrot." + prefname);
       }
       catch (e) { }
       if ((value < 10) || (value > 5000)) {
         value = 300;
-        gPref.setIntPref("mandelbrot." + prefname, value);
+        Services.prefs.setIntPref("mandelbrot." + prefname, value);
       }
       return value;
     case "last_image.Cr_*":
       let Cr_min = -2.0;
       let Cr_max = 1.0;
       try {
-        Cr_min = parseFloat(gPref.getCharPref("mandelbrot.last_image.Cr_min"));
-        Cr_max = parseFloat(gPref.getCharPref("mandelbrot.last_image.Cr_max"));
+        Cr_min = parseFloat(Services.prefs.getCharPref("mandelbrot.last_image.Cr_min"));
+        Cr_max = parseFloat(Services.prefs.getCharPref("mandelbrot.last_image.Cr_max"));
       }
       catch (e) { }
       if ((Cr_min < -3) || (Cr_min > 2) ||
           (Cr_max < -3) || (Cr_max > 2) || (Cr_min >= Cr_max)) {
         Cr_min = -2.0; Cr_max = 1.0;
       }
-      gPref.setCharPref("mandelbrot.last_image.Cr_min", Cr_min);
-      gPref.setCharPref("mandelbrot.last_image.Cr_max", Cr_max);
+      Services.prefs.setCharPref("mandelbrot.last_image.Cr_min", Cr_min);
+      Services.prefs.setCharPref("mandelbrot.last_image.Cr_max", Cr_max);
       return {Cr_min: Cr_min, Cr_max: Cr_max};
     case "last_image.Ci_*":
       let Ci_min = -1.5;
       let Ci_max = 1.5;
       try {
-        Ci_min = parseFloat(gPref.getCharPref("mandelbrot.last_image.Ci_min"));
-        Ci_max = parseFloat(gPref.getCharPref("mandelbrot.last_image.Ci_max"));
+        Ci_min = parseFloat(Services.prefs.getCharPref("mandelbrot.last_image.Ci_min"));
+        Ci_max = parseFloat(Services.prefs.getCharPref("mandelbrot.last_image.Ci_max"));
       }
       catch (e) { }
       if ((Ci_min < -2.5) || (Ci_min > 2.5) ||
           (Ci_max < -2.5) || (Ci_max > 2.5) || (Ci_min >= Ci_max)) {
         Ci_min = -1.5; Ci_max = 1.5;
       }
-      gPref.setCharPref("mandelbrot.last_image.Ci_min", Ci_min);
-      gPref.setCharPref("mandelbrot.last_image.Ci_max", Ci_max);
+      Services.prefs.setCharPref("mandelbrot.last_image.Ci_min", Ci_min);
+      Services.prefs.setCharPref("mandelbrot.last_image.Ci_max", Ci_max);
       return {Ci_min: Ci_min, Ci_max: Ci_max};
     case "iteration_max":
       value = 500;
       try {
-        value = gPref.getIntPref("mandelbrot." + prefname);
+        value = Services.prefs.getIntPref("mandelbrot." + prefname);
       }
       catch (e) {
         setIter(value);
@@ -124,7 +123,7 @@ function getAdjustPref(prefname) {
     case "use_algorithm":
       value = "numeric";
       try {
-        value = gPref.getCharPref("mandelbrot." + prefname);
+        value = Services.prefs.getCharPref("mandelbrot." + prefname);
       }
       catch (e) {
         setAlgorithm(value);
@@ -133,7 +132,7 @@ function getAdjustPref(prefname) {
    case "color_palette":
       value = "kairo";
       try {
-        value = gPref.getCharPref("mandelbrot." + prefname);
+        value = Services.prefs.getCharPref("mandelbrot." + prefname);
       }
       catch(e) {
         setPalette(value);
@@ -142,10 +141,10 @@ function getAdjustPref(prefname) {
    case "syncProportions":
       value = true;
       try {
-        value = gPref.getBoolPref("mandelbrot." + prefname);
+        value = Services.prefs.getBoolPref("mandelbrot." + prefname);
       }
       catch(e) {
-        gPref.setBoolPref("mandelbrot." + prefname, value);
+        Services.prefs.setBoolPref("mandelbrot." + prefname, value);
       }
       return value;
     default:
@@ -179,10 +178,10 @@ function adjustCoordsAndDraw(aC_min, aC_max) {
 
   let CRatio = Math.max(CWidth / iWidth, CHeight / iHeight);
 
-  gPref.setCharPref("mandelbrot.last_image.Cr_min", C_mid.r - iWidth * CRatio / 2);
-  gPref.setCharPref("mandelbrot.last_image.Cr_max", C_mid.r + iWidth * CRatio / 2);
-  gPref.setCharPref("mandelbrot.last_image.Ci_min", C_mid.i - iHeight * CRatio / 2);
-  gPref.setCharPref("mandelbrot.last_image.Ci_max", C_mid.i + iHeight * CRatio / 2);
+  Services.prefs.setCharPref("mandelbrot.last_image.Cr_min", C_mid.r - iWidth * CRatio / 2);
+  Services.prefs.setCharPref("mandelbrot.last_image.Cr_max", C_mid.r + iWidth * CRatio / 2);
+  Services.prefs.setCharPref("mandelbrot.last_image.Ci_min", C_mid.i - iHeight * CRatio / 2);
+  Services.prefs.setCharPref("mandelbrot.last_image.Ci_max", C_mid.i + iHeight * CRatio / 2);
 
   drawImage();
 }
@@ -195,6 +194,10 @@ function drawImage() {
 
   document.getElementById("statusLabel").value = gMbrotBundle.getString("statusDrawing");
 
+  if (gCurrentImageData) {
+    gLastImageData = gCurrentImageData;
+  }
+
   let Cr_vals = getAdjustPref("last_image.Cr_*");
   let Cr_min = Cr_vals.Cr_min;
   let Cr_max = Cr_vals.Cr_max;
@@ -206,6 +209,10 @@ function drawImage() {
   let iterMax = getAdjustPref("iteration_max");
   let algorithm = getAdjustPref("use_algorithm");
 
+  let currentPalette = getAdjustPref("color_palette");
+  if (!gColorPalette || !gColorPalette.length)
+    gColorPalette = getColorPalette(currentPalette);
+
   let iWidth = getAdjustPref("image.width");
   let iHeight = getAdjustPref("image.height");
 
@@ -460,27 +467,45 @@ function drawPoint(context, img_x, img_y, C, iterMax, algorithm) {
 
 var zoomstart;
 var imgBackup;
+var zoomTouchID;
 
 let imgEvHandler = {
   handleEvent: function(aEvent) {
     let canvas = document.getElementById("mbrotImage");
     let context = canvas.getContext("2d");
+    let touchEvent = aEvent.type.indexOf('touch') != -1;
+
+    // Bail out if this is neither a touch nor left-click.
+    if (!touchEvent && aEvent.button != 0)
+      return;
+
+    // Bail out if the started touch can't be found.
+    if (touchEvent && zoomstart &&
+        !aEvent.changedTouches.identifiedTouch(zoomTouchID))
+      return;
+
+    let coordObj = touchEvent ?
+                   aEvent.changedTouches.identifiedTouch(zoomTouchID) :
+                   aEvent;
+
     switch (aEvent.type) {
       case 'mousedown':
       case 'touchstart':
-        if (aEvent.button == 0) {
-          // left button - start dragzoom
-          zoomstart = {x: aEvent.clientX - canvas.offsetLeft,
-                       y: aEvent.clientY - canvas.offsetTop};
-          imgBackup = context.getImageData(0, 0, canvas.width, canvas.height);
+        if (touchEvent) {
+          zoomTouchID = aEvent.changedTouches.item(0).identifier;
+          coordObj = aEvent.changedTouches.identifiedTouch(zoomTouchID);
         }
+        // left button - start dragzoom
+        zoomstart = {x: coordObj.clientX - canvas.offsetLeft,
+                     y: coordObj.clientY - canvas.offsetTop};
+        imgBackup = context.getImageData(0, 0, canvas.width, canvas.height);
         break;
       case 'mouseup':
       case 'touchend':
-        if (aEvent.button == 0 && zoomstart) {
+        if (zoomstart) {
           context.putImageData(imgBackup, 0, 0);
-          let zoomend = {x: aEvent.clientX - canvas.offsetLeft,
-                        y: aEvent.clientY - canvas.offsetTop};
+          let zoomend = {x: coordObj.clientX - canvas.offsetLeft,
+                         y: coordObj.clientY - canvas.offsetTop};
 
           // make sure zoomend is bigger than zoomstart
           if ((zoomend.x == zoomstart.x) || (zoomend.y == zoomstart.y)) {
@@ -509,12 +534,12 @@ let imgEvHandler = {
         break;
       case 'mousemove':
       case 'touchmove':
-        if (aEvent.button == 0 && zoomstart) {
+        if (zoomstart) {
           context.putImageData(imgBackup, 0, 0);
           context.strokeStyle = "rgb(255,255,31)";
           context.strokeRect(zoomstart.x, zoomstart.y,
-                             aEvent.clientX - canvas.offsetLeft - zoomstart.x,
-                             aEvent.clientY - canvas.offsetTop - zoomstart.y);
+                             coordObj.clientX - canvas.offsetLeft - zoomstart.x,
+                             coordObj.clientY - canvas.offsetTop - zoomstart.y);
         }
       break;
     }
@@ -540,18 +565,11 @@ function saveImage() {
   }
 }
 
-function exitMandelbrot() {
-  var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
-                          .getService(Components.interfaces.nsIXULAppInfo);
-  if (appInfo.ID == "mandelbrot@kairo.at")
-    quitApp(false);
-  else
-    window.close();
-}
-
 function updateBookmarkMenu(aParent) {
   document.getElementById("bookmarkSave").disabled =
-    (!document.getElementById("drawButton").hidden || (gStartTime > 0));
+      (!document.getElementById("drawButton").hidden || (gStartTime > 0));
+
+  document.getElementById("bookmarkBack").disabled = !gLastImageData;
 
   while (aParent.hasChildNodes() &&
          aParent.lastChild.id != "bookmarkSeparator")
@@ -588,6 +606,16 @@ function updateBookmarkMenu(aParent) {
   na.setAttribute("disabled", "true");
 }
 
+function goBack() {
+  if (gLastImageData) {
+    Services.prefs.setIntPref("mandelbrot.iteration_max",
+                              gLastImageData.iterMax);
+    // use gLastImageData.iWidth, gLastImageData.iHeight ???
+    adjustCoordsAndDraw(gLastImageData.C_min, gLastImageData.C_max);
+    gLastImageData = undefined;
+  }
+}
+
 function callBookmark(evtarget) {
   if (evtarget.id == "bookmarkSave" || evtarget.id == "bookmarkSeparator")
     return;
@@ -620,7 +648,7 @@ function callBookmark(evtarget) {
     connection.close();
 
     if (iterMax && C_min && C_max) {
-      gPref.setIntPref("mandelbrot.iteration_max", iterMax);
+      Services.prefs.setIntPref("mandelbrot.iteration_max", iterMax);
       adjustCoordsAndDraw(C_min, C_max);
     }
   }
@@ -669,53 +697,10 @@ function saveBookmark() {
   connection.close();
 }
 
-function updateIterMenu() {
-  let currentIter = getAdjustPref("iteration_max");
-
-  let popup = document.getElementById("menu_iterPopup");
-  let item = popup.firstChild;
-  while (item) {
-    if (item.getAttribute("name") == "iter") {
-      if (item.getAttribute("value") == currentIter)
-        item.setAttribute("checked","true");
-      else
-        item.removeAttribute("checked");
-    }
-    item = item.nextSibling;
-  }
-}
-
-function setIter(aIter) {
-  gPref.setIntPref("mandelbrot.iteration_max", aIter);
-}
-
-function updatePaletteMenu() {
-  let currentPalette = getAdjustPref("color_palette");
-  if (!gColorPalette || !gColorPalette.length)
-    gColorPalette = getColorPalette(currentPalette);
-
-  let popup = document.getElementById("menu_palettePopup");
-  let item = popup.firstChild;
-  while (item) {
-    if (item.getAttribute("name") == "palette") {
-      if (item.getAttribute("value") == currentPalette)
-        item.setAttribute("checked", "true");
-      else
-        item.removeAttribute("checked");
-    }
-    item = item.nextSibling;
-  }
-}
-
-function setPalette(aPaletteID) {
-  gPref.setCharPref("mandelbrot.color_palette", aPaletteID);
-  gColorPalette = getColorPalette(aPaletteID);
-}
-
 function imgSettings() {
   let anchor = null;
   let position = "before_start";
-  if (document.getElementById("mandelbrotWindow").nodeName == "page") {
+  if (document.getElementById("mandelbrot-page").nodeName == "page") {
     anchor = document.getElementById("mandelbrotToolbar");
   }
   else {
@@ -725,56 +710,6 @@ function imgSettings() {
   document.getElementById("imgSettingsPanel").showPopup(anchor, position);
 }
 
-function updateDebugMenu() {
-  let scope = (document.getElementById("mandelbrotWindow").nodeName == "page") ? "content" : "chrome";
-  try {
-    // This throws in versions that don't have JaegerMonkey yet --> catch block
-    gPref.getBoolPref("javascript.options.methodjit." + scope);
-
-    // We have JaegerMonkey, i.e. two prefs for trace/method JIT
-    for each (let type in ["tracejit", "methodjit"]) {
-      let jitMenuItem = document.getElementById(type + "Enabled");
-      jitMenuItem.setAttribute("checked", gPref.getBoolPref("javascript.options." + type + "." + scope));
-    }
-  }
-  catch (e) {
-    // We have TraceMonkey only, i.e. one JIT pref, care only that is displayed
-    for each (let type in ["tracejit", "methodjit"])
-      document.getElementById(type + "Enabled").hidden = true;
-    let jitMenuItem = document.getElementById("jitEnabled");
-    jitMenuItem.hidden = false;
-    jitMenuItem.setAttribute("checked", gPref.getBoolPref("javascript.options.jit." + scope));
-  }
-}
-
-function toggleJITState(jitMenuItem, jittype) {
-  let scope = (document.getElementById("mandelbrotWindow").nodeName == "page") ? "content" : "chrome";
-  let jitpref = "javascript.options." + jittype + "jit." + scope;
-  let jitEnabled = !gPref.getBoolPref(jitpref);
-  gPref.setBoolPref(jitpref, jitEnabled)
-  jitMenuItem.setAttribute("checked", jitEnabled ? "true" : "false");
-}
-
-function updateAlgoMenu() {
-  let currentAlgo = getAdjustPref("use_algorithm");
-
-  let popup = document.getElementById("menu_algoPopup");
-  let item = popup.firstChild;
-  while (item) {
-    if (item.getAttribute("name") == "algorithm") {
-      if (item.getAttribute("value") == currentAlgo)
-        item.setAttribute("checked", "true");
-      else
-        item.removeAttribute("checked");
-    }
-    item = item.nextSibling;
-  }
-}
-
-function setAlgorithm(algoID) {
-  gPref.setCharPref("mandelbrot.use_algorithm", algoID);
-}
-
 function initImgSettings() {
   // Get values from prefs.
   for each (let coord in ["Cr", "Ci"]) {
@@ -796,6 +731,11 @@ function initImgSettings() {
   let context = canvas.getContext("2d");
   context.fillStyle = "rgba(255, 255, 255, 127)";
   context.fillRect(0, 0, canvas.width, canvas.height);
+
+  // Set lists to correct values.
+  updateIterList();
+  updatePaletteList();
+  updateAlgoList();
 }
 
 function closeImgSettings() {
@@ -806,15 +746,15 @@ function closeImgSettings() {
 function saveImgSettings() {
   // Get values to prefs.
   for each (let coord in ["Cr_min", "Cr_max", "Ci_min", "Ci_max"]) {
-    gPref.setCharPref("mandelbrot.last_image." + coord,
-                      document.getElementById("is_" + coord).value);
+    Services.prefs.setCharPref("mandelbrot.last_image." + coord,
+                               document.getElementById("is_" + coord).value);
   }
   for each (let dim in ["width", "height"]) {
-    gPref.setIntPref("mandelbrot.image." + dim,
-                     document.getElementById("is_img_" + dim).value);
+    Services.prefs.setIntPref("mandelbrot.image." + dim,
+                              document.getElementById("is_img_" + dim).value);
   }
-  gPref.setBoolPref("mandelbrot.syncProportions",
-                    document.getElementById("is_syncProp").checked);
+  Services.prefs.setBoolPref("mandelbrot.syncProportions",
+                             document.getElementById("is_syncProp").checked);
 }
 
 function checkISValue(textbox, type) {
@@ -913,6 +853,37 @@ function roundCoord(floatval) {
   return parseFloat(floatval.toFixed(10));
 }
 
+function updateIterList() {
+  let currentIter = getAdjustPref("iteration_max");
+  document.getElementById("iterList").value = currentIter;
+}
+
+function updatePaletteList() {
+  let currentPalette = getAdjustPref("color_palette");
+  if (!gColorPalette || !gColorPalette.length)
+    gColorPalette = getColorPalette(currentPalette);
+  document.getElementById("colorList").value = currentPalette;
+}
+
+function updateAlgoList() {
+  let currentAlgo = getAdjustPref("use_algorithm");
+  document.getElementById("algoList").value = currentAlgo;
+}
+
+function setIter(aIter) {
+  Services.prefs.setIntPref("mandelbrot.iteration_max", aIter);
+}
+
+function setPalette(aPaletteID) {
+  Services.prefs.setCharPref("mandelbrot.color_palette", aPaletteID);
+  gColorPalette = getColorPalette(aPaletteID);
+}
+
+function setAlgorithm(algoID) {
+  Services.prefs.setCharPref("mandelbrot.use_algorithm", algoID);
+}
+
+
 /***** helper functions from external sources *****/
 
 // function below is based on http://developer.mozilla.org/en/docs/Code_snippets:Canvas