licensing cleanup (GPLv2)
[org.ibex.core.git] / src / org / ibex / graphics / Surface.java
index b9207bb..ced451a 100644 (file)
@@ -1,4 +1,7 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
+// Copyright 2000-2005 the Contributors, as shown in the revision logs.
+// Licensed under the GNU General Public License version 2 ("the License").
+// You may not use this file except in compliance with the License.
+
 package org.ibex.graphics;
 
 import org.ibex.js.*;
@@ -17,8 +20,8 @@ public abstract class Surface extends PixelBuffer implements Task {
 
     // Static Data ////////////////////////////////////////////////////////////////////////////////
 
-    private static Boolean T = Boolean.TRUE;
-    private static Boolean F = Boolean.FALSE;
+    private static final JS T = JS.T;
+    private static final JS F = JS.F;
 
     /** all instances of Surface which need to be refreshed by the Scheduler */
     public static Vec allSurfaces = new Vec();
@@ -51,6 +54,7 @@ public abstract class Surface extends PixelBuffer implements Task {
     public int newmousey = -1;                         ///< y position of the mouse, in real time; this lets us collapse Move's
     public boolean minimized = false;                  ///< True iff this surface is minimized, in real time
     public boolean maximized = false;                  ///< True iff this surface is maximized, in real time
+    public boolean unrendered = true;                  ///< True iff this surface has not yet been rendered
     DirtyList dirtyRegions = new DirtyList();          ///< Dirty regions on the surface
 
     // Used For Simulating Clicks and DoubleClicks /////////////////////////////////////////////////
@@ -95,7 +99,7 @@ public abstract class Surface extends PixelBuffer implements Task {
             Scheduler.add(new Task() { public void perform() throws JSExn {
                 Platform.clipboardReadEnabled = true;
                 try {
-                    root.putAndTriggerTraps("_Press3", T);
+                    root.putAndTriggerTraps(JS.S("_Press3"), T);
                 } finally {
                     Platform.clipboardReadEnabled = false;
                 }
@@ -129,6 +133,7 @@ public abstract class Surface extends PixelBuffer implements Task {
         }
     }
 
+    private final static JS MOVE = JS.S("_Move");
     /** we enqueue ourselves in the Scheduler when we have a Move message to deal with */
     private Task mover = new Task() {
             public void perform() {
@@ -138,7 +143,7 @@ public abstract class Surface extends PixelBuffer implements Task {
                 String oldcursor = cursor;  cursor = "default";
                 // FIXME: Root (ONLY) gets motion events outside itself (if trapped)
                 if (oldmousex != mousex || oldmousey != mousey)
-                    root.putAndTriggerTrapsAndCatchExceptions("_Move", T);
+                    root.putAndTriggerTrapsAndCatchExceptions(MOVE, T);
                 if (!cursor.equals(oldcursor)) syncCursor();
             } };
 
@@ -154,14 +159,14 @@ public abstract class Surface extends PixelBuffer implements Task {
         Scheduler.add(mover);
     }
 
-    protected final void HScroll(int pixels) { new Message("_HScroll", new Integer(pixels), root); }
-    protected final void VScroll(int pixels) { new Message("_VScroll", new Integer(pixels), root); }
-    protected final void HScroll(float lines) { new Message("_HScroll", new Float(lines), root); }
-    protected final void VScroll(float lines) { new Message("_VScroll", new Float(lines), root); }
+    protected final void HScroll(int pixels) { new Message("_HScroll", JS.N(pixels), root); }
+    protected final void VScroll(int pixels) { new Message("_VScroll", JS.N(pixels), root); }
+    protected final void HScroll(float lines) { new Message("_HScroll", JS.N(lines), root); }
+    protected final void VScroll(float lines) { new Message("_VScroll", JS.N(lines), root); }
 
     /** subclasses should invoke this method when the user resizes the window */
     protected final void SizeChange(final int width, final int height) {
-        if (pendingWidth == width && pendingHeight == height) return;
+        if (unrendered || (pendingWidth == width && pendingHeight == height)) return;
         pendingWidth = width;
         pendingHeight = height;
         syncRootBoxToSurface = true;
@@ -174,14 +179,14 @@ public abstract class Surface extends PixelBuffer implements Task {
         Scheduler.add(new Task() { public void perform() throws JSExn {
             root.x = x;
             root.y = y;
-            root.putAndTriggerTrapsAndCatchExceptions("PosChange", T);
+            root.putAndTriggerTrapsAndCatchExceptions(JS.S("PosChange"), T);
         }});
     }
 
     private final String[] doubleClick = new String[] { null, "_DoubleClick1", "_DoubleClick2", "_DoubleClick3" };
     protected final void DoubleClick(int button) { new Message(doubleClick[button], T, root); }
-    protected final void KeyPressed(String key) { new Message("_KeyPressed", key, root); }
-    protected final void KeyReleased(String key) { new Message("_KeyReleased", key, root); }
+    protected final void KeyPressed(String key) { new Message("_KeyPressed", JS.S(key), root); }
+    protected final void KeyReleased(String key) { new Message("_KeyReleased", JS.S(key), root); }
     protected final void Close() { new Message("Close", T, root); }
     protected final void Minimized(boolean b) { minimized = b; new Message("Minimized", b ? T : F, root); }
     protected final void Maximized(boolean b) { maximized = b; new Message("Maximized", b ? T : F, root); }
@@ -224,8 +229,19 @@ public abstract class Surface extends PixelBuffer implements Task {
 
     public Surface(Box root) {
         this.root = root;
-        root.setWidth(root.minwidth, Math.min(Platform.getScreenWidth(), root.maxwidth));
-        root.setHeight(root.minheight, Math.min(Platform.getScreenHeight(), root.maxheight));
+        // FIXME: document this in the reference
+        if (!root.test(root.HSHRINK) && root.maxwidth == Integer.MAX_VALUE)
+            root.maxwidth = Platform.getScreenWidth() / 2;
+        if (!root.test(root.VSHRINK) && root.maxheight == Integer.MAX_VALUE)
+            root.maxheight = Platform.getScreenHeight() / 2;
+        root.setWidth(root.minwidth,
+                      root.test(root.HSHRINK)
+                      ? Math.max(root.minwidth, root.contentwidth)
+                      : Math.min(Platform.getScreenWidth(), root.maxwidth));
+        root.setHeight(root.minheight,
+                      root.test(root.VSHRINK)
+                      ? Math.max(root.minheight, root.contentheight)
+                      : Math.min(Platform.getScreenHeight(), root.maxheight));
         Surface old = fromBox(root);
         if (old != null) old.dispose(false);
         else root.removeSelf();
@@ -246,13 +262,15 @@ public abstract class Surface extends PixelBuffer implements Task {
                 root.setHeight(root.minheight, pendingHeight);
                 syncRootBoxToSurface = false;
             }
-            if (root.maxwidth != root.width || root.maxheight != root.height) {
+            int rootwidth = root.test(root.HSHRINK) ? root.contentwidth : root.maxwidth;
+            int rootheight = root.test(root.VSHRINK) ? root.contentheight : root.maxheight;
+            if (rootwidth != root.width || rootheight != root.height) {
                 // dirty the place where the scar used to be and where it is now
                 dirty(0, root.height - scarImage.height, scarImage.width, scarImage.height);
-                dirty(0, root.maxheight - scarImage.height, scarImage.width, scarImage.height);
+                dirty(0, rootheight - scarImage.height, scarImage.width, scarImage.height);
             }
             root.reflow();
-            setSize(root.width, root.height);
+            setSize(rootwidth, rootheight);
             /*String oldcursor = cursor;
             cursor = "default";
             root.putAndTriggerTrapsAndCatchExceptions("_Move", JS.T);
@@ -282,48 +300,50 @@ public abstract class Surface extends PixelBuffer implements Task {
                 return;
             }
         }
+
+        unrendered = false;
     }
 
     // FEATURE: reinstate recycler
     public class Message implements Task {
         
         private Box boxContainingMouse;
-        private Object value;
+        private JS value;
         public String name;
         
-        Message(String name, Object value, Box boxContainingMouse) {
+        Message(String name, JS value, Box boxContainingMouse) {
             this.boxContainingMouse = boxContainingMouse;
             this.name = name;
             this.value = value;
             Scheduler.add(this);
         }
         
-        public void perform() {
+        public void perform() throws JSExn {
             if (name.equals("_KeyPressed")) {
-                String value = (String)this.value;
+                String value = JS.toString(this.value);
                 if (value.toLowerCase().endsWith("shift")) shift = true;     else if (shift) value = value.toUpperCase();
                 if (value.toLowerCase().equals("alt")) alt = true;           else if (alt) value = "A-" + value;
                 if (value.toLowerCase().endsWith("control")) control = true; else if (control) value = "C-" + value;
                 if (value.equals("C-v") || value.equals("A-v")) Platform.clipboardReadEnabled = true;
-                this.value = value;
+                this.value = JS.S(value);
             } else if (name.equals("_KeyReleased")) {
-                String value = (String)this.value;
+                String value = JS.toString(this.value);
                 if (value.toLowerCase().equals("alt")) alt = false;
                 else if (value.toLowerCase().equals("control")) control = false;
                 else if (value.toLowerCase().equals("shift")) shift = false;
-                this.value = value;
+                this.value = JS.S(value);
             } else if (name.equals("_HScroll") || name.equals("_VScroll")) {
                 // FIXME: technically points != pixels
-                if (value instanceof Integer)
-                    value = new Float(((Integer)value).intValue() * root.fontSize());
+                if (JS.isInt(value))
+                    value = JS.N(JS.toInt(value) * root.fontSize());
             }
             try {
-                boxContainingMouse.putAndTriggerTrapsAndCatchExceptions(name, value);
+                boxContainingMouse.putAndTriggerTrapsAndCatchExceptions(JS.S(name), value);
             } finally {
                 Platform.clipboardReadEnabled = false;
             }
         }
-        public String toString() { return "Message [name=" + name + ", value=" + value + "]"; }
+        public String toString() { return "Message [name=" + name + ", value=" + JS.debugToString(value) + "]"; }
     }