org.microemu.device.ui.EventDispatcher Maven / Gradle / Ivy
The newest version!
/**
* MicroEmulator
* Copyright (C) 2002 Bartek Teodorczyk
*
* It is licensed under the following two licenses as alternatives:
* 1. GNU Lesser General Public License (the "LGPL") version 2.1 or any newer version
* 2. Apache License (the "AL") Version 2.0
*
* You may not use this file except in compliance with at least one of
* the above two licenses.
*
* You may obtain a copy of the LGPL at
* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
*
* You may obtain a copy of the AL at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the LGPL or the AL for the specific language governing permissions and
* limitations.
*/
package org.microemu.device.ui;
import org.microemu.device.DeviceFactory;
public class EventDispatcher implements Runnable {
public static final String EVENT_DISPATCHER_NAME = "event-thread";
public static int maxFps = -1;
private volatile boolean cancelled = false;
private Event head = null;
private Event tail = null;
private PaintEvent scheduledPaintEvent = null;
private PointerEvent scheduledPointerDraggedEvent = null;
private Object serviceRepaintsLock = new Object();
private long lastPaintEventTime = 0;
public EventDispatcher() {
}
public void run() {
while (!cancelled) {
Event event = null;
synchronized (this) {
if (head != null) {
event = head;
if (maxFps > 0 && event instanceof PaintEvent) {
long difference = System.currentTimeMillis() - lastPaintEventTime;
if (difference < (1000 / maxFps)) {
event = null;
try {
wait((1000 / maxFps) - difference);
} catch (InterruptedException e) {
}
}
}
if (event != null) {
head = event.next;
if (head == null) {
tail = null;
}
if (event instanceof PointerEvent && ((PointerEvent) event).type == PointerEvent.POINTER_DRAGGED) {
scheduledPointerDraggedEvent = null;
}
}
} else {
try {
wait();
} catch (InterruptedException e) {
}
}
}
if (event != null) {
if (event instanceof PaintEvent) {
synchronized (serviceRepaintsLock) {
scheduledPaintEvent = null;
lastPaintEventTime = System.currentTimeMillis();
post(event);
serviceRepaintsLock.notifyAll();
}
} else {
post(event);
}
}
}
}
/**
* Do not service any more events
*/
public final void cancel() {
cancelled = true;
synchronized (this) {
notify();
}
}
public void put(Event event) {
synchronized (this) {
if (event instanceof PaintEvent && scheduledPaintEvent != null) {
scheduledPaintEvent.merge((PaintEvent) event);
} else if (event instanceof PointerEvent && scheduledPointerDraggedEvent != null
&& ((PointerEvent) event).type == PointerEvent.POINTER_DRAGGED) {
scheduledPointerDraggedEvent.x = ((PointerEvent) event).x;
scheduledPointerDraggedEvent.y = ((PointerEvent) event).y;
} else {
if (event instanceof PaintEvent) {
scheduledPaintEvent = (PaintEvent) event;
}
if (event instanceof PointerEvent && ((PointerEvent) event).type == PointerEvent.POINTER_DRAGGED) {
scheduledPointerDraggedEvent = (PointerEvent) event;
}
if (tail != null) {
tail.next = event;
}
tail = event;
if (head == null) {
head = event;
}
notify();
}
}
}
public void put(Runnable runnable) {
put(new RunnableEvent(runnable));
}
public void serviceRepaints() {
synchronized (serviceRepaintsLock) {
synchronized (this) {
if (scheduledPaintEvent == null) {
return;
}
// TODO move scheduledPaintEvent to head
}
try {
serviceRepaintsLock.wait();
} catch (InterruptedException e) {
}
}
}
protected void post(Event event) {
event.run();
}
public abstract class Event implements Runnable {
Event next = null;
}
public final class PaintEvent extends Event {
private int x = -1, y = -1, width = -1, height = -1;
public PaintEvent(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void run() {
DeviceFactory.getDevice().getDeviceDisplay().repaint(x, y, width, height);
}
/**
* Do a 2-D merge of the paint areas
*
* @param event
*/
public final void merge(PaintEvent event) {
int xMax = x + width;
int yMax = y + height;
this.x = Math.min(this.x, event.x);
xMax = Math.max(xMax, event.x + event.width);
this.y = Math.min(this.y, event.y);
yMax = Math.max(yMax, event.y + event.height);
this.width = xMax - x;
this.height = yMax - y;
}
}
public final class PointerEvent extends EventDispatcher.Event {
public static final short POINTER_PRESSED = 0;
public static final short POINTER_RELEASED = 1;
public static final short POINTER_DRAGGED = 2;
private Runnable runnable;
private short type;
private int x;
private int y;
public PointerEvent(Runnable runnable, short type, int x, int y) {
this.runnable = runnable;
this.type = type;
this.x = x;
this.y = y;
}
public void run() {
runnable.run();
}
}
public final class ShowNotifyEvent extends EventDispatcher.Event {
private Runnable runnable;
public ShowNotifyEvent(Runnable runnable) {
this.runnable = runnable;
}
public void run() {
runnable.run();
}
}
public final class HideNotifyEvent extends EventDispatcher.Event {
private Runnable runnable;
public HideNotifyEvent(Runnable runnable) {
this.runnable = runnable;
}
public void run() {
runnable.run();
}
}
private class RunnableEvent extends Event {
private Runnable runnable;
public RunnableEvent(Runnable runnable) {
this.runnable = runnable;
}
public void run() {
runnable.run();
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy