javauis/lcdui_akn/javalcdui/javasrc.nokialcdui/javax/microedition/lcdui/CanvasGraphicsItemPainter.java
/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package javax.microedition.lcdui;
import com.nokia.mj.impl.rt.legacy.NativeError;
import com.nokia.mid.ui.CanvasGraphicsItem;
class CanvasGraphicsItemPainter
extends com.nokia.mid.ui.CanvasGraphicsItemPainter
{
// Toolkit
private Toolkit iToolkit;
// Native handle
private int iHandle;
// Graphics
private Graphics iGraphics;
//
// Repainting
//
private boolean iRepaintPending; //waiting for paint to be called
private int iRepaintX1;
private int iRepaintY1;
private int iRepaintX2;
private int iRepaintY2;
private boolean iPaintEventPending;
Object iCallbackLock;
CanvasGraphicsItemPainter(
CanvasGraphicsItem aItem,
Object aToolkit,
int aWidth,
int aHeight)
{
iItem = aItem;
iToolkit = (Toolkit)aToolkit;
synchronized (iToolkit)
{
iHandle = Toolkit.checkHandle(
_createNativePeer(iToolkit.getHandle(), aWidth, aHeight));
iCallbackLock = iToolkit.getCallbackLock();
}
iGraphics = null;
}
/**
* Hidden default constructor.
*/
protected CanvasGraphicsItemPainter()
{
}
protected void Repaint(int aX, int aY, int aWidth, int aHeight)
{
synchronized (iToolkit)
{
if (iItem.isVisible() && (aWidth > 0) && (aHeight > 0))
{
int x1 = aX;
int y1 = aY;
int x2 = aX + aWidth;
int y2 = aY + aHeight;
// Union of clip rect and damage rect
if (iRepaintPending)
{
iRepaintX1 = Math.min(iRepaintX1, x1);
iRepaintY1 = Math.min(iRepaintY1, y1);
iRepaintX2 = Math.max(iRepaintX2, x2);
iRepaintY2 = Math.max(iRepaintY2, y2);
}
else
{
iRepaintX1 = x1;
iRepaintY1 = y1;
iRepaintX2 = x2;
iRepaintY2 = y2;
iRepaintPending = true;
}
// Clip to bounds
iRepaintX1 = Math.max(iRepaintX1, 0);
iRepaintY1 = Math.max(iRepaintY1, 0);
iRepaintX2 = Math.min(iRepaintX2, iItem.getWidth());
iRepaintY2 = Math.min(iRepaintY2, iItem.getHeight());
if (!iPaintEventPending)
{
iToolkit.postEvent(this, Toolkit.EVENT_PAINT);
iPaintEventPending = true;
}
}
}
}
private void paint()
{
boolean clipped;
int rx;
int ry;
int rw;
int rh;
int width;
int height;
synchronized (iToolkit)
{
iPaintEventPending = false;
if (!iRepaintPending)
{
return; // Don't draw if all the repaints have already been done
}
iRepaintPending = false;
if (!iItem.isVisible())
{
return;
}
rx = iRepaintX1;
ry = iRepaintY1;
rw = iRepaintX2 - iRepaintX1;
rh = iRepaintY2 - iRepaintY1;
width = iItem.getWidth();
height = iItem.getHeight();
if (iGraphics == null)
{
iGraphics = new Graphics(
(Toolkit)iToolkit, this, iHandle,
iItem.getWidth(), iItem.getHeight());
}
iGraphics.reset(width, height);
}
clipped = (rw < width) || (rh < height);
if (clipped)
{
iGraphics.setClip(rx, ry, rw, rh);
}
_resetFrameBuffer(iToolkit.getHandle(), iHandle,
rx, ry, rw, rh);
synchronized (iCallbackLock)
{
Repaint(iGraphics); //this will invoke paint(Graphics) in MIDlet
}
synchronized (iToolkit)
{
if (clipped)
{
iToolkit.sync(getHandle(), rx, ry, rw, rh);
}
else
{
iToolkit.sync(getHandle());
}
}
}
public int getHandle()
{
if (iHandle <= 0)
{
throw new RuntimeException(
"CanvasGraphicsItemPainter.getHandle(" +
this +
") dead item");
}
return iHandle;
}
private void handleSizeChanged(int aWidth, int aHeight)
{
// We don't need to check here if size was really changed
// because it is done on native side and event is sent
// only if size was really changed there
synchronized (iToolkit)
{
DisposeGraphics();
}
Repaint(0, 0, iItem.getWidth(), iItem.getHeight());
}
/*
* Method handles callback events from native side.
* aEvent - id of event, only EVENT_PAINT and EVENT_SIZE_CHANGED are used.
*/
final void handleEvent(int aEvent, int aData0, int aData1)
{
switch (aEvent)
{
case Toolkit.EVENT_PAINT:
paint();
break;
case Toolkit.EVENT_SIZE_CHANGED:
handleSizeChanged(aData0, aData1);
break;
case Toolkit.EVET_CANVAS_GRAPHICS_ITEM_REPAINT:
Repaint(0, 0, iItem.getWidth(), iItem.getHeight());
break;
}
}
private void DisposeGraphics()
{
final Graphics graphics = iGraphics;
iGraphics = null;
if (null != graphics)
{
graphics.dispose();
}
}
// Native methods
private native int _createNativePeer(
int aToolkit,
int aWidth,
int aHeight);
private native int _resetFrameBuffer(
int aToolkit,
int aNativePeerHandle,
int aPositionX,
int aPositionY,
int aWidth,
int aHeight);
}