X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fgraphics%2FSurface.java;h=ced451a9c68a325ea7046ec9ac97d86386a1ba99;hp=7e23169c148078aa4f6c8966a95fbd66cc81a525;hb=76b21655a0710caf4f972c107a3ab991032d7e10;hpb=4daeeb4119b901d53b44913c86f8af3ce67db925 diff --git a/src/org/ibex/graphics/Surface.java b/src/org/ibex/graphics/Surface.java index 7e23169..ced451a 100644 --- a/src/org/ibex/graphics/Surface.java +++ b/src/org/ibex/graphics/Surface.java @@ -1,8 +1,14 @@ -// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] -package org.ibex; +// 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.*; import org.ibex.util.*; +import org.ibex.plat.*; + +import org.ibex.core.*; // FIXME /** * A Surface, as described in the Ibex Reference. @@ -10,23 +16,23 @@ import org.ibex.util.*; * Platform subclasses should include an inner class subclass of * Surface to return from the Platform._createSurface() method */ -public abstract class Surface extends PixelBuffer implements Scheduler.Task { +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(); /** When set to true, render() should abort as soon as possible and restart the rendering process */ - volatile boolean abort = false; + public volatile boolean abort = false; // these three variables are used to ensure that user resizes trump programmatic resizes - volatile boolean syncRootBoxToSurface = false; - volatile int pendingWidth = 0; - volatile int pendingHeight = 0; + public volatile boolean syncRootBoxToSurface = false; + public volatile int pendingWidth = 0; + public volatile int pendingHeight = 0; public static boolean alt = false; ///< true iff the alt button is pressed down public static boolean control = false; ///< true iff the control button is pressed down @@ -48,6 +54,7 @@ public abstract class Surface extends PixelBuffer implements Scheduler.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 ///////////////////////////////////////////////// @@ -74,6 +81,7 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task { public void setMinimumSize(int minx, int miny, boolean resizable) { } protected void setSize(int w, int h) { _setSize(w, h); } + public static Picture scarImage = null; // Helper methods for subclasses //////////////////////////////////////////////////////////// @@ -88,10 +96,10 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task { if (button == 1) new Message("_Press1", T, root); else if (button == 2) new Message("_Press2", T, root); else if (button == 3) { - Scheduler.add(new Scheduler.Task() { public void perform() throws JSExn { + 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; } @@ -125,8 +133,9 @@ public abstract class Surface extends PixelBuffer implements Scheduler.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 Scheduler.Task mover = new Scheduler.Task() { + private Task mover = new Task() { public void perform() { if (mousex == newmousex && mousey == newmousey) return; int oldmousex = mousex; mousex = newmousex; @@ -134,7 +143,7 @@ public abstract class Surface extends PixelBuffer implements Scheduler.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(); } }; @@ -150,14 +159,14 @@ public abstract class Surface extends PixelBuffer implements Scheduler.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; @@ -167,17 +176,17 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task { // FEATURE: can we avoid creating objects here? protected final void PosChange(final int x, final int y) { - Scheduler.add(new Scheduler.Task() { public void perform() throws JSExn { + 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); } @@ -220,15 +229,26 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task { public Surface(Box root) { this.root = root; - root.setMaxWidth(JS.N(Math.min(Platform.getScreenWidth(), root.maxwidth))); - root.setMaxHeight(JS.N(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(); Refresh(); } - private static VectorGraphics.Affine identity = VectorGraphics.Affine.identity(); + private static Affine identity = Affine.identity(); /** runs the prerender() and render() pipelines in the root Box to regenerate the backbuffer, then blits it to the screen */ public synchronized void render() { @@ -238,17 +258,19 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task { abort = false; root.pack(); if (syncRootBoxToSurface) { - root.setMaxWidth(JS.N(pendingWidth)); - root.setMaxHeight(JS.N(pendingHeight)); + root.setWidth(root.minwidth, pendingWidth); + 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 - Main.scarImage.height, Main.scarImage.width, Main.scarImage.height); - dirty(0, root.maxheight - Main.scarImage.height, Main.scarImage.width, Main.scarImage.height); + dirty(0, root.height - 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); @@ -266,7 +288,7 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task { if (w <= 0 || h <= 0) continue; root.render(0, 0, x, y, x + w, y + h, this, identity); - drawPicture(Main.scarImage, 0, root.height - Main.scarImage.height, x, y, x+w, y+h); + drawPicture(scarImage, 0, root.height - scarImage.height, x, y, x+w, y+h); if (abort) { // x,y,w,h is only partially reconstructed, so we must be careful not to re-blit it @@ -278,48 +300,50 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task { return; } } + + unrendered = false; } // FEATURE: reinstate recycler - public class Message implements Scheduler.Task { + 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) + "]"; } }