created mirror
This commit is contained in:
253
Java/ZZUpdateManager.java
Normal file
253
Java/ZZUpdateManager.java
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
ZZUpdateManager.java
|
||||
*
|
||||
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
|
||||
*
|
||||
* You may use and distribute under the terms of either the GNU Lesser
|
||||
* General Public License, either version 2 of the license or,
|
||||
* at your choice, any later version. Alternatively, you may use and
|
||||
* distribute under the terms of the XPL.
|
||||
*
|
||||
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
|
||||
* the licenses.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
|
||||
* file for more details.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Written by Tuomas Lukka
|
||||
*/
|
||||
package org.gzigzag;
|
||||
import java.util.*;
|
||||
|
||||
/** A single global instance to manage the updating of views.
|
||||
* The views are set in a priority order so that even if the user is
|
||||
* moving fast, he will get an immediate response through the less important
|
||||
* views not being updated at each step.
|
||||
*/
|
||||
|
||||
public class ZZUpdateManager implements Runnable {
|
||||
public static final String rcsid = "$Id: ZZUpdateManager.java,v 1.29 2001/02/27 08:36:15 raulir Exp $";
|
||||
public static boolean dbg = false;
|
||||
private static void p(String s) { if(dbg) ZZLogger.log(s); }
|
||||
private static void pa(String s) { ZZLogger.log(s); }
|
||||
|
||||
/** The order of views, from the most important to the least.
|
||||
*/
|
||||
private static Vector ordering = new Vector();
|
||||
|
||||
/** Whether an update is currently in progress, through
|
||||
* a view being painted.
|
||||
*/
|
||||
private static boolean updating;
|
||||
private static int disabled;
|
||||
private static boolean noanimation;
|
||||
/** Whether the currently ongoing update should stop immediately
|
||||
* and restart from the beginning
|
||||
*/
|
||||
private static boolean restartUpd = false;
|
||||
|
||||
public static void addView(ZZView v) { ordering.addElement(v); }
|
||||
public static void rmView(ZZView v) { ordering.removeElement(v); }
|
||||
|
||||
/** Set the view that has the privilege of animating the next
|
||||
* update.
|
||||
* Setting this to null will make all views update fast.
|
||||
*/
|
||||
public static void setFast(ZZView v) {
|
||||
p("Setfast: "+v + " cur: "+ordering.elementAt(0));
|
||||
if(v == null) {
|
||||
noanimation = true;
|
||||
return;
|
||||
}
|
||||
if(ordering.elementAt(0)!=v) {
|
||||
ordering.removeElement(v);
|
||||
ordering.insertElementAt(v, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Called by a space to inform that some cells have been
|
||||
* changed
|
||||
*/
|
||||
public static void chg() {
|
||||
p("UPDMANAGER CHG");
|
||||
if(restartUpd) return;
|
||||
synchronized(ordering) {
|
||||
restartUpd = true;
|
||||
ordering.notifyAll();
|
||||
}
|
||||
p("UPDMANAGER CHGOUT");
|
||||
}
|
||||
|
||||
/** Disable all updating of views.
|
||||
* XXX While frozen, might consider updating e.g. once every
|
||||
* second...
|
||||
*/
|
||||
public static void freeze() {
|
||||
p("ZZUpdatemanager freeze");
|
||||
synchronized(ordering) { disabled++; }
|
||||
p("ZZUpdatemanager frozen "+disabled);
|
||||
}
|
||||
/** Enable again the updating of views. */
|
||||
public static void thaw() {
|
||||
p("ZZUpdatemanager thaw");
|
||||
synchronized(ordering) {
|
||||
if(disabled<=0)
|
||||
throw new ZZError("thaw() without matching freeze()!");
|
||||
if(--disabled==0) ordering.notifyAll();
|
||||
}
|
||||
p("ZZUpdatemanager thawed "+disabled);
|
||||
}
|
||||
|
||||
static ZZUpdateManager m = new ZZUpdateManager();
|
||||
static Thread t= new Thread(m);
|
||||
static {
|
||||
p("STARTORDTHREAD");
|
||||
t.start();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
int ind = -1;
|
||||
boolean reras = true;
|
||||
boolean anim = false;
|
||||
Vector curUpdVec = new Vector();
|
||||
|
||||
while(true) {
|
||||
p("STARTORD");
|
||||
synchronized(ordering) {
|
||||
p("STARTORD SYNCHED");
|
||||
if(!anim) ind++;
|
||||
updating = false;
|
||||
try {
|
||||
while(disabled>0 || (ind>=curUpdVec.size() && !restartUpd)) {
|
||||
p("STARTORD "+disabled+" "+ind+" "+restartUpd);
|
||||
ordering.wait();
|
||||
}
|
||||
} catch(Exception e) {
|
||||
ZZLogger.exc(e);
|
||||
}
|
||||
p("STARTORD WAITED");
|
||||
updating = true;
|
||||
if(restartUpd) {
|
||||
restartUpd = false;
|
||||
curUpdVec = (Vector)ordering.clone();
|
||||
ind = 0;
|
||||
reras = true;
|
||||
// Try to make the system stop less at
|
||||
// inconvenient, unequal times.
|
||||
|
||||
// System.gc(); // doesn't seem to work.
|
||||
}
|
||||
if(curUpdVec.size()==0) continue;
|
||||
}
|
||||
try {
|
||||
p("STARTORD DOING " + ind + " "+ curUpdVec+" "+reras);
|
||||
ZZView v = (ZZView)curUpdVec.elementAt(ind);
|
||||
if(ind==0) { // animate if need be
|
||||
if(reras) {
|
||||
timeNewCycle();
|
||||
|
||||
anim = v.reraster();
|
||||
reras = false;
|
||||
}
|
||||
float fract = timeAnimFract();
|
||||
|
||||
if(fract >= 1 || !anim || noanimation) {
|
||||
fract = 1;
|
||||
anim = false;
|
||||
noanimation = false;
|
||||
}
|
||||
p("PN 0: "+fract+" "+anim+" "+lastStart+" "+millis);
|
||||
// XXX paintNow() is not really safe here, because ZZ code
|
||||
// in general isn't thread-safe. If Kaffe someday provides
|
||||
// EventQueue.invokeAndWait(), this could be fixed.
|
||||
boolean care = ZZDrawing.instance.enableQuality(false);
|
||||
v.paintNow((float)fract);
|
||||
if (fract == 1 && care) {
|
||||
ZZDrawing.instance.enableQuality(true);
|
||||
v.paintNow(1.0f);
|
||||
}
|
||||
} else {
|
||||
p("PN: "+ind);
|
||||
v.reraster();
|
||||
// XXX Ditto.
|
||||
boolean care = ZZDrawing.instance.enableQuality(false);
|
||||
v.paintNow(1.0f);
|
||||
if (care) {
|
||||
ZZDrawing.instance.enableQuality(true);
|
||||
v.paintNow(1.0f);
|
||||
}
|
||||
}
|
||||
((java.awt.Component)v).getToolkit().sync();
|
||||
} catch(ZZError e) {
|
||||
ZZLogger.exc(e);
|
||||
System.out.println("EXCEPTION WHILE UPDATING!");
|
||||
}
|
||||
p("STARTORD DONE: anim "+anim);
|
||||
}
|
||||
} finally {
|
||||
System.out.println("HELP! UPDATE LOOP STOPPED. XXX");
|
||||
}
|
||||
}
|
||||
|
||||
static final long defmillis = 800;
|
||||
/** The time before the next user event
|
||||
* to try to be ready.
|
||||
*/
|
||||
static final long trybefore = 150;
|
||||
/** The time to increment the interval with.
|
||||
*/
|
||||
static final long inctime = 80;
|
||||
private static long lastStart = 0;
|
||||
/** The interval between start and end of animation.
|
||||
*/
|
||||
private static long millis = defmillis;
|
||||
|
||||
/** Called when we begin a new animation. */
|
||||
private void timeNewCycle() {
|
||||
long cur = System.currentTimeMillis();
|
||||
// Interval between start of last animation and start of the new one.
|
||||
long sinceLast = cur-lastStart;
|
||||
|
||||
// sinceLast - millis = interval between end of last animation and
|
||||
// start of the new one. We try to end the last animation
|
||||
// trybefore ticks before the start of the new one, so if
|
||||
// sinceLast - millis < trybefore, the animation takes too long.
|
||||
if(sinceLast - millis < trybefore)
|
||||
millis = sinceLast-trybefore; // Shorten the animation time.
|
||||
|
||||
// If the animation didn't take too long, and if it's at least a unit
|
||||
// (inctime) shorter than it was by default, gradually lengthen it.
|
||||
else if(millis < defmillis - inctime)
|
||||
millis += inctime;
|
||||
|
||||
lastStart = cur;
|
||||
}
|
||||
|
||||
private float timeAnimFract() {
|
||||
long cur = System.currentTimeMillis();
|
||||
|
||||
double fract = 1.0;
|
||||
|
||||
// If we are animating at all (20 milliseconds is
|
||||
// minimum time we try to use animation with),
|
||||
// calculate the fraction of the animation we are at.
|
||||
if(millis > 20)
|
||||
fract = (cur-lastStart) / (double)millis;
|
||||
|
||||
// Test for a really weird JVM problem.
|
||||
if(cur - lastStart >= millis && fract < 1) {
|
||||
System.out.println("AAAARRRRRGGGHHH!!! Division problem "+ cur + " "+lastStart+" "+millis);
|
||||
}
|
||||
|
||||
return (float)fract;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user