FileDocCategorySizeDatePackage
RepaintEventProducer.javaAPI DocphoneME MR2 API (J2ME)9456Wed May 02 18:00:24 BST 2007com.sun.midp.lcdui

RepaintEventProducer

public class RepaintEventProducer extends Object implements com.sun.midp.events.EventListener
This class performs all of the repaint event handling.

Fields Summary
private com.sun.midp.events.EventQueue
eventQueue
Cached reference to the MIDP event queue.
private RepaintEvent
pooledEvent1
Repaint event free for reuse.
private RepaintEvent
pooledEvent2
Repaint event free for reuse.
private RepaintEvent
pooledEvent3
Repaint event free for reuse.
private RepaintEvent
queuedEvent
Repaint event in the queue or waiting to be moved to the processed slot. Events are rotated to different slots in preprocessRepaints.
private RepaintEvent
eventInProcess
Repaint event being processed (queue has event also) or has been processed (no event in the queue).
Constructors Summary
public RepaintEventProducer(com.sun.midp.events.EventQueue theEventQueue)
The constructor LCDUI repaint events handler.

param
theEventQueue the event queue

        
        eventQueue = theEventQueue;

        pooledEvent1 = RepaintEvent.createRepaintEvent(null, 0, 0, 0, 0, null);
        pooledEvent2 = RepaintEvent.createRepaintEvent(null, 0, 0, 0, 0, null);
        pooledEvent3 = RepaintEvent.createRepaintEvent(null, 0, 0, 0, 0, null);
        
        eventQueue.registerEventListener(EventTypes.REPAINT_EVENT, this);
    
Methods Summary
public booleanpreprocess(com.sun.midp.events.Event event, com.sun.midp.events.Event waitingEvent)
Preprocess an event that is being posted to the event queue.

param
event event being posted
param
waitingEvent previous event of this type waiting in the queue to be processed
return
true to allow the post to continue, false to not post the event to the queue

        /*
         * Because of the needs of serviceRepaints the preprocessing
         * is done in scheduleRepaint.
         */
        return true;
    
public voidprocess(com.sun.midp.events.Event genericEvent)
Process an event.

param
genericEvent event to process

        RepaintEvent event = (RepaintEvent)genericEvent;

        synchronized (this) {
            queuedEvent = null;
            eventInProcess = event;
        }

        /*
         * Target DisplayEventConsumer is obtained directly from event field.
         * Assumed that target consumer is not null.
         */
        event.display.handleRepaintEvent(
                event.paintX1, event.paintY1, 
                event.paintX2, event.paintY2, 
                event.paintTarget);

        synchronized (this) {
            /* Change the ID here to signal waitForRepaint. */
            eventInProcess.perUseID++;
            
            eventInProcess = null;

            // ServiceRepaints may be blocking.
            notifyAll();
        }
    
public voidscheduleRepaint(DisplayEventConsumer d, int x, int y, int w, int h, java.lang.Object target)
Called to schedule a repaint of the current Displayable as soon as possible.

param
d The Display
param
x The x coordinate of the origin of the repaint rectangle
param
y The y coordinate of the origin of the repaint rectangle
param
w The width of the repaint rectangle
param
h The height of the repaint rectangle
param
target An optional target Object, which may have been the original requestor for the repaint

        RepaintEvent freeEvent;

        synchronized (this) {
            freeEvent = pooledEvent1;

            freeEvent.setRepaintFields(d, x, y, w, h, target);

            if (queuedEvent == null) {
                /*
                 * Since the queue does not lock posting during event
                 * processing, we need to rotate 3 repaint events for reuse.
                 *
                 * 1 for the queued event, 1 for the event begin processed
                 * and 1 for temporary use when merging a new event with
                 * a queued event.
                 *
                 * Event pooling is done because game can generate upto 15
                 * repaints a second and cause a lot garbage collection if
                 * we created new repaint every time.
                 */
                pooledEvent1 = pooledEvent2;
                pooledEvent2 = pooledEvent3;
                pooledEvent3 = freeEvent;

                queuedEvent = freeEvent;

                eventQueue.post(queuedEvent);
            } else if (queuedEvent.display != d) {
                /*
                 * A new display has come to the foreground so don't
                 * bother paint the display in the queued event.
                 *
                 * Overwrite this fields in queue event with new values.
                 */
                 queuedEvent.setRepaintFields(d, x, y, w, h, target);
            } else {
                /*
                 * When there is a pending repaint
                 * union the dirty regions into one event
                 */
                if (queuedEvent.paintX1 > freeEvent.paintX1) {
                    queuedEvent.paintX1 = freeEvent.paintX1;
                }

                if (queuedEvent.paintY1 > freeEvent.paintY1) {
                    queuedEvent.paintY1 = freeEvent.paintY1;
                }

                if (queuedEvent.paintX2 < freeEvent.paintX2) {
                    queuedEvent.paintX2 = freeEvent.paintX2;
                }
                
                if (queuedEvent.paintY2 < freeEvent.paintY2) {
                    queuedEvent.paintY2 = freeEvent.paintY2;
                }

                queuedEvent.paintTarget = null;
            }
        }
    
public voidserviceRepaints()
Called to block the calling MIDlet until the the pending repaint operation is performed.

Does not return until the pending repaint (if any) has been processed.

        if (EventQueue.isDispatchThread()) {
            Event event;

            if (eventInProcess != null) {
                /*
                 * We are in the midst of a calling the application's
                 * paint method, avoid recursion, simply return
                 */
                return;
            }

            /*
             * Since we are in the dispatch thread, at this point
             * there can only one repaint in the queue so remove it
             * from the queue and process it.
             */
            event = eventQueue.remove(EventTypes.REPAINT_EVENT);

            /* Do not hold a lock when calling out to the application */
            if (event != null) {
                process(event);
            }
        } else {
            /*
             * We only want paint events to be process in the dispatch
             * to avoid deadlocks. So wait for the repaint event to occur.
             */
            waitForCurrentRepaintEvents();
        }
    
private voidwaitForCurrentRepaintEvents()
Wait for the event queue to process all of the events currently in the queue but not any new ones after the start of this method.

        RepaintEvent eventToWaitFor = null;
        int currentEventUseID;

        synchronized (this) {
            if (queuedEvent != null) {
                eventToWaitFor = queuedEvent;
            } else if (eventInProcess != null) {
                eventToWaitFor = eventInProcess;
            } else {
                /* Nothing to wait for, done. */
                return;
            }

            currentEventUseID = eventToWaitFor.perUseID;
            while (eventToWaitFor.perUseID == currentEventUseID) {
                try {
                    wait();
                } catch (InterruptedException ie) {
                    /* The application wants this thread to unblock */
                    break;
                }
            }
                
        }