Merge branch 'master' of linz:/srv/git/mandelbrot
authorRobert Kaiser <robert@notebook.(none)>
Fri, 31 Jul 2009 17:30:06 +0000 (19:30 +0200)
committerRobert Kaiser <robert@notebook.(none)>
Fri, 31 Jul 2009 17:30:06 +0000 (19:30 +0200)
mandelbrot
xulapp/chrome/mandelbrot/content/image-settings.xul
xulapp/chrome/mandelbrot/content/mandelbrot.js
xulapp/chrome/mandelbrot/content/mandelbrot.xul
xulapp/chrome/mandelbrot/locales/en-US/mandelbrot.dtd
xulapp/chrome/mandelbrot/locales/en-US/mandelbrot.properties

index 7d05df5a2ba0e477bb200bc566dd1bf74eb49eee..3a58794e3ccb2d5235f868c879d25763f9be1bfd 100755 (executable)
@@ -68,4 +68,4 @@ fi
 
 # add -jsconsole for debugging
 
-$xulrunner --app $app_ini
+$xulrunner --app $app_ini $@
index 3fc332f3ef8845d6a0cf237beb7d12b5b837eafb..605aac20a07f8b754936dc2b7a208a04f7c512b9 100644 (file)
@@ -76,7 +76,7 @@
     <groupbox>
       <caption label="&coord.title;"/>
       <description value="&coord.real.label;"/>
-      <hbox>
+      <hbox align="center">
         <label value="&coord.min.label;" control="Cr_min"/>
         <textbox id="Cr_min" size="10"
                  preference="mandelbrot.last_image.Cr_min"
@@ -90,7 +90,7 @@
                  onchange="recalcCoord('Cr', 'max');"/>
       </hbox>
       <description value="&coord.imag.label;"/>
-      <hbox>
+      <hbox align="center">
         <label value="&coord.min.label;" control="Ci_min"/>
         <textbox id="Ci_min" size="10"
                  preference="mandelbrot.last_image.Ci_min"
     <hbox flex="1">
       <groupbox>
         <caption label="&img.size.title;"/>
-        <hbox>
+        <hbox align="center">
           <label value="&img.width.label;" control="imgWidth"/>
           <textbox id="imgWidth" size="4"
                    preference="mandelbrot.image.width"
                    onchange="recalcCoord('Ci', 'scale');"/>
         </hbox>
-        <hbox>
+        <hbox align="center">
           <label value="&img.height.label;" control="imgHeight"/>
           <textbox id="imgHeight" size="4"
                    preference="mandelbrot.image.height"
 
       <groupbox>
         <caption label="&options.title;"/>
-        <hbox>
+        <hbox align="center">
           <checkbox id="syncProp"
                     preference="mandelbrot.syncProportions"
                     onclick="checkProportions();"/>
index bcc2df59110d7ea7adb4751ac8acc225a57c9041..28b443c1d50c1dd581a148eb4ddd6833c02e651f 100644 (file)
@@ -40,12 +40,13 @@ var gPref = Components.classes["@mozilla.org/preferences-service;1"]
                       .getService(Components.interfaces.nsIPrefService)
                       .getBranch(null);
 var gStartTime = 0;
+var gMbrotBundle;
 
 function Startup() {
   updateIterMenu();
   updatePaletteMenu();
-  document.getElementById("statusLabel").value =
-      document.getElementById("mbrotBundle").getString("statusEmpty");
+  gMbrotBundle = document.getElementById("mbrotBundle");
+  document.getElementById("statusLabel").value = gMbrotBundle.getString("statusEmpty");
 }
 
 function drawImage() {
@@ -54,8 +55,7 @@ function drawImage() {
 
   document.getElementById("drawButton").hidden = true;
 
-  document.getElementById("statusLabel").value =
-      document.getElementById("mbrotBundle").getString("statusDrawing");
+  document.getElementById("statusLabel").value = gMbrotBundle.getString("statusDrawing");
 
   let Cr_min = -2.0;
   let Cr_max = 1.0;
@@ -147,7 +147,8 @@ function EndCalc() {
   let endTime = new Date();
   let timeUsed = (endTime.getTime() - gStartTime.getTime()) / 1000;
   document.getElementById("statusLabel").value =
-      document.getElementById("mbrotBundle").getFormattedString("statusTime", [timeUsed.toFixed(3)]);
+      gMbrotBundle.getFormattedString("statusTime", [timeUsed.toFixed(3)]);
+  gStartTime = 0;
 }
 
 function complex(aReal, aImag) {
@@ -335,8 +336,34 @@ function drawPoint(context, img_x, img_y, C, iterMax, algorithm) {
 
 /***** pure UI functions *****/
 
+var zoomstart;
+
+function mouseevent(etype, event) {
+  let canvas = document.getElementById("mbrotImage");
+  switch (etype) {
+    case 'down':
+      if (event.button == 0)
+        // left button - start dragzoom
+        zoomstart = {x: event.clientX - canvas.offsetLeft,
+                     y: event.clientY - canvas.offsetTop};
+      break;
+    case 'up':
+      if (event.button == 0) {
+        var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+                                .getService(Components.interfaces.nsIPromptService);
+        var ok = prompts.confirm(null, gMbrotBundle.getString("zoomConfirmTitle"),
+            gMbrotBundle.getString("zoomConfirmLabel") + ' --- ' +
+            zoomstart.x + ',' + zoomstart.y + '-' +
+            (event.clientX - canvas.offsetLeft) + ',' +
+            (event.clientY - canvas.offsetTop));
+        // ok is now true if OK was clicked, and false if cancel was clicked
+      }
+      zoomstart = undefined;
+    break;
+  }
+}
+
 function saveImage() {
-  const bundle = document.getElementById("mbrotBundle");
   const nsIFilePicker = Components.interfaces.nsIFilePicker;
   var fp = null;
   try {
@@ -344,9 +371,9 @@ function saveImage() {
                    .createInstance(nsIFilePicker);
   } catch (e) {}
   if (!fp) return;
-  var promptString = bundle.getString("savePrompt");
+  var promptString = gMbrotBundle.getString("savePrompt");
   fp.init(window, promptString, nsIFilePicker.modeSave);
-  fp.appendFilter(bundle.getString("pngFilterName"), "*.png");
+  fp.appendFilter(gMbrotBundle.getString("pngFilterName"), "*.png");
   fp.defaultString = "mandelbrot.png";
 
   var fpResult = fp.show();
@@ -355,6 +382,89 @@ function saveImage() {
   }
 }
 
+function updateBookmarkMenu(aParent) {
+  document.getElementById("bookmarkSave").disabled =
+    (!document.getElementById("drawButton").hidden || (gStartTime > 0));
+
+  while (aParent.hasChildNodes() &&
+         aParent.lastChild.id != 'bookmarkSeparator')
+    aParent.removeChild(aParent.lastChild);
+
+  var file = Components.classes["@mozilla.org/file/directory_service;1"]
+                       .getService(Components.interfaces.nsIProperties)
+                       .get("ProfD", Components.interfaces.nsIFile);
+  file.append("mandelbookmarks.sqlite");
+  if (file.exists()) {
+    var connection = Components.classes["@mozilla.org/storage/service;1"]
+                               .getService(Components.interfaces.mozIStorageService)
+                               .openDatabase(file);
+    try {
+      if (connection.tableExists("bookmarks")) {
+        var statement = connection.createStatement(
+            "SELECT name FROM bookmarks ORDER BY ROWID DESC");
+        while (statement.executeStep())
+          aParent.appendChild(document.createElement("menuitem"))
+                 .setAttribute("label", statement.getString(0));
+        statement.reset();
+        statement.finalize();
+        return;
+      }
+    } finally {
+      connection.close();
+    }
+  }
+  // Create the "Nothing Available" Menu item and disable it.
+  var na = aParent.appendChild(document.createElement("menuitem"));
+  na.setAttribute("label", gMbrotBundle.getString("noBookmarks"));
+  na.setAttribute("disabled", "true");
+}
+
+function callBookmark(evtarget) {
+}
+
+function saveBookmark() {
+  // retrieve wanted bookmark name with a prompt
+  var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+                          .getService(Components.interfaces.nsIPromptService);
+  var input = {value: ""}; // empty default value
+  var ok = prompts.prompt(null, gMbrotBundle.getString("saveBookmarkTitle"), gMbrotBundle.getString("saveBookmarkLabel"), input, null, {});
+  // ok is true if OK is pressed, false if Cancel. input.value holds the value of the edit field if "OK" was pressed.
+  if (!ok || !input.value)
+    return
+
+  var bmName = input.value;
+
+  // Open or create the bookmarks database.
+  var file = Components.classes["@mozilla.org/file/directory_service;1"]
+                       .getService(Components.interfaces.nsIProperties)
+                       .get("ProfD", Components.interfaces.nsIFile);
+  file.append("mandelbookmarks.sqlite");
+  var connection = Components.classes["@mozilla.org/storage/service;1"]
+                             .getService(Components.interfaces.mozIStorageService)
+                             .openDatabase(file);
+  connection.beginTransaction();
+  if (!connection.tableExists("bookmarks"))
+    connection.createTable("bookmarks", "name TEXT, iteration_max INTEGER, Cr_min REAL, Cr_max REAL, Ci_min REAL, Ci_max REAL");
+  // NULL. The value is a NULL value.
+  // INTEGER. The value is a signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value.
+  // REAL. The value is a floating point value, stored as an 8-byte IEEE floating point number.
+  // TEXT. The value is a text string, stored using the database encoding (UTF-8, UTF-16BE or UTF-16-LE).
+
+  // Put value of the current image into the bookmarks table
+  var statement = connection.createStatement(
+      "INSERT INTO bookmarks (name,iteration_max,Cr_min,Cr_max,Ci_min,Ci_max) VALUES (?1,?2,?3,?4,?5,?6)");
+  statement.bindStringParameter(0, bmName);
+  statement.bindStringParameter(1, gPref.getIntPref("mandelbrot.iteration_max"));
+  statement.bindStringParameter(2, parseFloat(gPref.getCharPref("mandelbrot.last_image.Cr_min")));
+  statement.bindStringParameter(3, parseFloat(gPref.getCharPref("mandelbrot.last_image.Cr_max")));
+  statement.bindStringParameter(4, parseFloat(gPref.getCharPref("mandelbrot.last_image.Ci_min")));
+  statement.bindStringParameter(5, parseFloat(gPref.getCharPref("mandelbrot.last_image.Ci_max")));
+  statement.execute();
+  statement.finalize();
+  connection.commitTransaction();
+  connection.close();
+}
+
 function updateIterMenu() {
   try {
     var currentIter = gPref.getIntPref("mandelbrot.iteration_max");
index c5c2cc60594e351a6e252539759ffb7c56cee586..596a4e7bbe07d676bcdd5e14cadeeec0dfa47342 100644 (file)
           <menuitem id="fileQuit" label="&fileQuit.label;" oncommand="quitApp(false);"/>
         </menupopup>
       </menu>
+      <menu id="bookmarkMenu" label="&bookmarkMenu.label;">
+        <menupopup id="menu_bookmarkPopup"
+                   onpopupshowing="updateBookmarkMenu(event.target);"
+                   oncommand="callBookmark(event.target);">
+          <menuitem id="bookmarkOverview" label="&bookmarkOverview.label;"/>
+          <menuitem id="bookmarkSave" label="&bookmarkSave.label;" oncommand="saveBookmark();"/>
+          <menuseparator id="bookmarkSeparator"/>
+        </menupopup>
+      </menu>
       <menu id="prefMenu" label="&prefMenu.label;">
         <menupopup id="menu_prefPopup">
           <menu id="iterMenu" label="&iterMenu.label;">
   </toolbox>
   <hbox flex="1" pack="center" align="center">
     <stack>
-      <html:canvas id="mbrotImage" width="300" height="300"></html:canvas>
+      <html:canvas id="mbrotImage" width="300" height="300"
+                   onmousedown="mouseevent('down', event);"
+                   onmouseup="mouseevent('up',event);">
+      </html:canvas>
       <button id="drawButton" label="&fileDraw.label;" oncommand="drawImage();"/>
     </stack>
   </hbox>
index 1c2eda0efbc3a587c44743ebfddd29678ecca394..738b7fb224fa4e336e87af5de1a12460f54afd79 100644 (file)
 <!ENTITY fileSave.label   "Save Image…">
 <!ENTITY fileQuit.label   "Quit">
 
+<!ENTITY bookmarkMenu.label "Locations">
+<!ENTITY bookmarkOverview.label "Overview">
+<!ENTITY bookmarkSave.label "Save Bookmark…">
+
 <!ENTITY prefMenu.label   "Settings">
 <!ENTITY iterMenu.label   "Iterations">
 <!ENTITY iter50.label     "50">
index 2af8f0521a47747fe11223770e56011490f09579..d5f2d39f0301c66d81acb50d16516c7c9a372005 100644 (file)
@@ -40,3 +40,8 @@ statusDrawing=Drawing image…
 statusTime=Time: %S seconds
 savePrompt=Save Image As…
 pngFilterName=PNG Files
+noBookmarks=[No bookmarks found]
+saveBookmarkTitle=Bookmark This Location
+saveBookmarkLabel=Please enter a name for bookmarking the current location
+zoomConfirmTitle=Confirm zooming
+zoomConfirmLabel=Zoom in on the area you dragged your mouse over?