CLayerpublic class CLayer extends Object This class represents a "layer". A layer is an element used to comprise
a higher-level "window" (see CWindow.java). A layer has several properties
such as its visibility, whether it accepts input, its size, etc. A layer
also has content, such as its background and its foreground. |
Fields Summary |
---|
private boolean | dirtyFlag indicating this layer is in need of repainting. | protected int[] | dirtyBoundsArray holding a bounding rectangle of an area needing repainting. | protected int[] | boundsCopyCopy of the layer bounds needed to unlock the layers for painting | protected int[] | dirtyBoundsCopyCopy of the dirty bounds needed to unlock the layers for painting | protected boolean | transparentFlag indicating if this layer has a transparent background or not. | protected boolean | visibleFlag indicating the current visibility state of this layer. | protected boolean | supportsInputFlag indicating the ability of this layer to support key/pen input. | protected boolean | opaqueFlag indicating this layer is either completely opaque, or not.
By default, a layer is not opaque, and thus requires the background
and any layers below it to be painted in addition to itself. However,
if a layer is opaque, it does not require anything it is obscuring to
be painted, just itself. All layers are opaque by default. | protected int | bgColorIf this layer has a filled color background,
the 0xrrggbbaa value of that color | protected Image[] | bgImageThe image to use as a background for this layer if this layer
is not transparent and does not use a fill color. | protected boolean | tileBGIf this layer is not transparent and uses a background image,
a flag indicating if that image should be tiled or otherwise centered. | protected CWindow | ownerThe window which owns this layer. If this layer has not been added
to a window or it has been removed from a window, the owner will be
null. | public int[] | boundsAn array holding the bounds of this layer. The indices are
as follows:
0 = layer's 'x' coordinate
1 = layer's 'y' coordinate
2 = layer's width
3 = layer's height
The 'x' and 'y' coordinates are in the coordinate space of the
window which contains this layer. | public static final int | XConstant used to reference the '0' index of the bounds array | public static final int | YConstant used to reference the '1' index of the bounds array | public static final int | WConstant used to reference the '2' index of the bounds array | public static final int | HConstant used to reference the '3' index of the bounds array | int | graphicsColorWhen in the paint() routine, graphicsColor will be set to the
default graphics color. This is a convenience variable for
subclasses to easily modify and then reset the graphics color. | Font | graphicsFontWhen in the paint() routine, graphicsFont will be set to the
default graphics Font. This is a convenience variable for
subclasses to easily modify and then reset the graphics font. |
Constructors Summary |
---|
public CLayer()Construct a default, transparent layer. As a result, the
'transparent' value will be set to true.
this((Image)null, -1);
| public CLayer(Image bgImage, int bgColor)Construct a layer with the given background image if it is not null
or with a background fill color.
The color should be in the 0xaarrggbb format. If the bgColor is
invalid and bgImage is null, this layer will be transparent and
equal to the no-argument constructor.
if (bgImage != null) {
this.bgImage = new Image[] { bgImage };
this.tileBG = true;
transparent = false;
} else {
transparent = (bgColor < 0);
}
this.bgColor = bgColor;
initialize();
| public CLayer(Image[] bgImages, int bgColor)Construct a layer with the given background images (if not null)
or with a background fill color and border. The background images
should be a 9 element array, creating a 9-piece image background.
The color should be in the 0xaarrggbb format. If the bgColor is
invalid and bgImages are null, this layer will be transparent and
equal to the no-argument constructor.
if (bgImages != null) {
this.bgImage = new Image[bgImages.length];
System.arraycopy(bgImages, 0, this.bgImage, 0, bgImages.length);
this.tileBG = false;
transparent = false;
} else {
transparent = (bgColor < 0);
}
this.bgColor = bgColor;
initialize();
|
Methods Summary |
---|
public void | addDirtyRegion()Add this layer's entire area to be marked for repaint. Any pending
dirty regions will be cleared and the entire layer will be painted
on the next repaint.
if (CGraphicsQ.DEBUG) {
System.err.println("Layer " + layerID() + ":");
System.err.println("\tMarking entire layer dirty");
}
cleanDirtyRegions();
setDirty();
| public boolean | addDirtyRegion(int x, int y, int w, int h)Add an area to be marked for repaint to this layer. This could
be needed for a variety of reasons, such as this layer being
obscured by another layer or window element. The new region should
be in the coordinate space of this layer.
if (CGraphicsQ.DEBUG) {
System.err.println("Layer " + this + ":");
System.err.println("\tAdd dirty: " + x + ", "
+ y + ", " + w + ", " + h);
}
// The whole layer is dirty already
if (isDirty() && isEmptyDirtyRegions()) {
if (CGraphicsQ.DEBUG) {
System.err.println(
"\tWhole layer is dirty already");
}
return false;
}
// Cache layer bounds
int bw = bounds[W];
int bh = bounds[H];
int x2 = x + w;
int y2 = y + h;
// Dirty region can be outside of the layer
if (x >= bw || y >= bh || x2 <= 0 || y2 <=0) {
if (CGraphicsQ.DEBUG) {
System.err.println(
"\tAdded region is outside of the layer");
}
return false;
}
boolean res = false;
int dx, dy, dx2, dy2;
if (isEmptyDirtyRegions()) {
dx = x; dy = y;
dx2 = x2; dy2 = y2;
} else {
dx = dirtyBounds[X];
dy = dirtyBounds[Y];
dx2 = dx + dirtyBounds[W];
dy2 = dy + dirtyBounds[H];
if (dx2 < x2) dx2 = x2;
if (dy2 < y2) dy2 = y2;
if (x < dx) dx = x;
if (y < dy) dy = y;
}
// Lastly, we carefully restrict the dirty region
// to be within the bounds of this layer
if (dx < 0) dx = 0;
if (dy < 0) dy = 0;
if (dx2 > bw) dx2 = bw;
if (dy2 > bh) dy2 = bh;
// Update changed dirty region
int dw = dx2 - dx;
int dh = dy2 - dy;
if (dirtyBounds[W] != dw || dirtyBounds[H] != dh) {
if (dw == bw && dh == bh) {
// The entire layer is dirty now
cleanDirtyRegions();
if (CGraphicsQ.DEBUG) {
System.err.println(
"\tThe entire layer became dirty");
}
} else {
dirtyBounds[X] = dx;
dirtyBounds[Y] = dy;
dirtyBounds[W] = dw;
dirtyBounds[H] = dh;
if (CGraphicsQ.DEBUG) {
System.err.println(
"\tCurrent dirty: " + dirtyBounds[X] + ", "
+ dirtyBounds[Y] + ", " + dirtyBounds[W] + ", "
+ dirtyBounds[H]);
}
}
res = true;
setDirty();
}
return res;
| public void | addNotify()Called by CWindow to notify the layer that is has been
added to the active stack. By default this method do nothing.
This method could be re-implemented by particular layer to
do some specific action as soon as it's added to the stack
| protected void | cleanDirty()Clean any dirty regions of the layer and mark layer as not dirty.
dirty = false;
cleanDirtyRegions();
| protected void | cleanDirtyRegions()Clean any dirty regions of the layer.
dirtyBounds[X] = dirtyBounds[Y]
= dirtyBounds[W] = dirtyBounds[H] = -1;
| public boolean | containsPoint(int x, int y)Utility method to determine if the given point lies within
the bounds of this layer. The point should be in the coordinate
space of this layer's containing CWindow.
return (visible &&
x >= bounds[X] && x <= (bounds[X] + bounds[W]) &&
y >= bounds[Y] && y <= (bounds[Y] + bounds[H]));
| void | copyLayerBounds()Copy bounds of the layer to use them on dirty layers painting
when the layers are not locked for changes from other threads
if (dirtyBounds[X] == -1) {
// Whole layer is dirty
dirtyBoundsCopy[X] = 0;
dirtyBoundsCopy[Y] = 0;
dirtyBoundsCopy[W] = bounds[W];
dirtyBoundsCopy[H] = bounds[H];
} else {
System.arraycopy(
dirtyBounds, 0, dirtyBoundsCopy, 0, 4);
}
System.arraycopy(
bounds, 0, boundsCopy, 0, 4);
| public int[] | getBounds()Return the bounds of this layer (in the coordinate space of
its parent Window). Returns a 4 element array, containing the
x, y, width, and height representing this layer's bounding
rectangle
return bounds;
| public boolean | handlePoint(int x, int y)Utility method to determine if this layer wanna handle
the given point. By default the layer handles the point if it
lies within the bounds of this layer. The point should be in
the coordinate space of this layer's containing CWindow.
return containsPoint(x, y);
| protected void | initialize()Finish initialization of this CLayer. This can
be extended by subclasses. The dimensions of the
CLayer are stored in its bounds[]. The 'x' and 'y'
coordinates are in the coordinate space of the
window which contains this layer. By default, a layer is
located at the origin and is as large as the screen size.
The X and Y coordinates represent the upper left position
of this CLayer in the containing CWindow's coordinate space.
bounds = new int[4];
bounds[X] = 0;
bounds[Y] = 0;
bounds[W] = ScreenSkin.WIDTH;
bounds[H] = ScreenSkin.HEIGHT;
dirtyBounds = new int[4];
dirtyBoundsCopy = new int[4];
boundsCopy = new int[4];
cleanDirtyRegions();
// IMPL_NOTE : center the background image by default
| public boolean | isDirty()Returns true if this layer is in need of repainting.
return this.dirty;
| protected boolean | isEmptyDirtyRegions()Determines whether dirty regions are empty.
return dirtyBounds[X] == -1;
| public boolean | isOpaque()Determine if this layer is opaque
return opaque;
| public boolean | isVisible()Determine the current visibility of this layer. Note that this
state only pertains to the layer's visibility status within its
containing window. The window itself may or may not be actually
visible on the physical display.
return visible;
| public boolean | keyInput(int type, int code)Handle key input from a keypad. Parameters describe
the type of key event and the platform-specific
code for the key. (Codes are translated using the
lcdui.Canvas)
return false;
| protected java.lang.String | layerID()A String identifier used by subclasses (for debug purposes)
int i;
String res = getClass().getName();
if (res != null && (i = res.lastIndexOf('.")) > -1) {
res = res.substring(i+1);
}
return res + "@" +
Integer.toHexString(hashCode());
| public boolean | methodInput(java.lang.String str)Handle input from some type of device-dependent
input method. This could be input from something
such as T9, or a phonebook lookup, etc.
return false;
| public void | paint(Graphics g)Paint this layer. This method should not generally be overridden by
subclasses. This method carefully stores the clip, translation, and
color before calling into subclasses. The graphics region will be
translated such that it is in this layer's coordinate space (0,0 is
the top left corner of this layer). The paintBackground() method will
be called first, then the paintBody() method. The graphics will then
carefully be put back into its original state before returning.
Subclasses should override the paintBody() method and do not generally
need to do any translates or bother to undo any changes made to
the Graphics object.
try {
// We first reset our dirty flag
this.dirty = false;
graphicsColor = g.getColor();
graphicsFont = g.getFont();
// Paint the background
if (!transparent) {
paintBackground(g);
}
// Just in case subclasses modified these values,
// return them to standard
g.setColor(graphicsColor);
g.setFont(graphicsFont);
// Paint the body
paintBody(g);
// Just in case subclasses modified these values,
// return them to standard
g.setColor(graphicsColor);
g.setFont(graphicsFont);
// We reset our dirty bounds region
cleanDirtyRegions();
} catch (Throwable t) {
t.printStackTrace();
}
| protected void | paintBackground(Graphics g)Paint the background of this layer. This method will automatically
handle a transparent layer, a layer with a background color (and/or
border color), and a layer with a background image (either centered
or tiled). Subclasses may override this method if they require a
more advanced background (note that the transparent value should be
set to false in order for the paintBackground() method to be called),
but subclasses must be careful to reset any modifications made to
the Graphics object before returning.
if (bgImage == null) {
// background is null, just fill using the fill color
g.setColor(bgColor);
g.fillRect(g.getClipX(), g.getClipY(),
g.getClipWidth(), g.getClipHeight());
} else {
if (bgImage.length == 1) {
CGraphicsUtil.paintBackground(g, bgImage[0], tileBG, bgColor,
bounds[W], bounds[H]);
} else if (bgImage.length == 9) {
CGraphicsUtil.draw9pcsBackground(g, 0, 0,
bounds[W], bounds[H],
bgImage);
} else if (bgImage.length == 3) {
CGraphicsUtil.draw3pcsBackground(g, 0, 0, bounds[W], bgImage);
}
}
| protected void | paintBody(Graphics g)Paint the body or content of this layer. This method should be
overridden by subclasses. Note that the Graphics object will
already be translated into this layer's coordinate space. Subclasses
do not need to reset any changes made to the Graphics object as the
CLayer paint() routine will do that automatically.
| public boolean | pointerInput(int type, int x, int y)Handle input from a pen tap.
Parameters describe the type of pen event and the x,y location in the
layer at which the event occurred.
Important: the x,y location of the pen tap will already be translated
into the coordinate space of the layer.
return false;
| public void | relocateNotify(int[] oldBounds)Called by CWindow to notify the layer that is has been
moved to another location. By default this method do nothing.
This method could be re-implemented by particular layer to
do some specific action as soon as it's moved
| public void | removeNotify(CWindow owner)Called by CWindow to notify the layer that is has been
removed from the active stack. By default this method do nothing.
This method could be re-implemented by particular layer to
do some specific action as soon as it's removed from the stack
| public void | requestRepaint()Request a repaint for the entire contents of this layer.
requestRepaint(0, 0, bounds[W], bounds[H]);
| public void | requestRepaint(int x, int y, int w, int h)Request a repaint for a specific region of this layer.
addDirtyRegion(x, y, w, h);
if (owner != null && visible) {
// We request a repaint of our parent window after translating
// the origin into the coordinate space of the window.
owner.requestRepaint();
}
| public void | setBackground(Image bgImage, boolean tileBG, int bgColor)Establish a background. This method will evaluate the parameters
and create a background which is appropriate. If the image is non-null,
the image will be used to create the background. If the image is null,
the values for the colors will be used and the background will be
painted in fill color instead. If the image is null, and the background
color is a negative value, this layer will become transparent and no
background will be painted.
if (bgImage != null) {
this.bgImage = new Image[] { bgImage };
this.tileBG = tileBG;
transparent = false;
} else {
this.bgImage = null;
transparent = (bgColor < 0);
}
this.bgColor = bgColor;
addDirtyRegion();
| public void | setBackground(Image[] bgImages, int bgColor)Establish a background. This method will evaluate the parameters
and create a background which is appropriate. If the images are
non-null, the images will be used to create a 9-piece background.
If the images are null, the value for the color will be used and
the background will be painted in fill color instead. If the images
are null, and the background color is a negative value, this layer
will become transparent and no background will be painted.
if (bgImages != null) {
this.bgImage = new Image[bgImages.length];
System.arraycopy(bgImages, 0, this.bgImage, 0, bgImages.length);
this.tileBG = false;
transparent = false;
} else {
this.bgImage = null;
transparent = (bgColor < 0);
}
this.bgColor = bgColor;
addDirtyRegion();
| public void | setBounds(int x, int y, int w, int h)Establish the bounds of this layer. The coordinate space for
the 'x' and 'y' anchor will be interpreted in that of the window
which contains this layer.
if (bounds == null) {
bounds = new int[4];
}
bounds[X] = x;
bounds[Y] = y;
bounds[W] = w;
bounds[H] = h;
| protected void | setDirty()Mark this layer as being dirty.
By default, this will also mark the containing window (if there is one)
as being dirty as well.
setDirtyButNotNotifyOwner();
if (owner != null) {
owner.setDirty();
}
| protected void | setDirtyButNotNotifyOwner()Mark this layer as being dirty
but don't mark the containing window.
this.dirty = true;
| public void | setOpaque(boolean opaque)Set the opacity flag for this layer. True means that this
layer does not have any transparent or translucent areas
this.opaque = opaque;
| public void | setSupportsInput(boolean support)Toggle the ability of this layer to receive input.
this.supportsInput = support;
| public void | setVisible(boolean visible)Toggle the visibility state of this layer within its containing
window.
this.visible = visible;
addDirtyRegion();
| boolean | subDirtyRegion(int x, int y, int w, int h)Subtract a layer area not needed for repaint of this layer.
It could be needed for a variety of reasons, such as layer being
overlapped with opague higher layer or window element.
The subtracted region should be in the coordinate space
of this layer.
if (!isDirty()) {
return false;
}
if (CGraphicsQ.DEBUG) {
System.err.println("Layer " + this + ":");
System.err.println("\tSub dirty: " + x + ", "
+ y + ", " + w + ", " + h);
}
int x2 = x + w;
int y2 = y + h;
boolean res = false;
int dx, dy, dx2, dy2;
if (isEmptyDirtyRegions()) {
dx = 0; dy = 0;
dx2 = bounds[W];
dy2 = bounds[H];
} else {
dx = dirtyBounds[X];
dy = dirtyBounds[Y];
dx2 = dx + dirtyBounds[W];
dy2 = dy + dirtyBounds[H];
}
// Subtracted region can be outside of the dirty area
if (x >= dx2 || y >= dy2 || x2 <= dx || y2 <=dy) {
if (CGraphicsQ.DEBUG) {
System.err.println(
"\tSubtracted region is outside of dirty area");
}
return false;
}
boolean insideVert = (y <= dy && y2 >= dy2);
boolean insideHorz = (x <= dx && x2 >= dx2);
if (insideVert) {
if (dx >= x && dx < x2) dx = x2;
else if (dx2 > x && dx2 <= x2) dx2 = x;
} else if (insideHorz) {
if (dy >= y && dy < y2) dy = y2;
else if (dy2 > y && dy2 <= y2) dy2 = y;
} else {
// We can subtract only such a regions that result
// of subtraction is a rectangular area
if (CGraphicsQ.DEBUG) {
System.err.println(
"\tSubtraction can't be done");
}
return false;
}
// Result of subtraction can be an empty dirty region
if (dx >= dx2 || dy >= dy2) {
cleanDirty();
res = true;
if (CGraphicsQ.DEBUG) {
System.err.println(
"\tThe layer is no more dirty");
}
} else if (dirtyBounds[W] != dx2 - dx ||
dirtyBounds[H] != dy2 - dy) {
// Update changed dirty region
dirtyBounds[X] = dx;
dirtyBounds[Y] = dy;
dirtyBounds[W] = dx2 - dx;
dirtyBounds[H] = dy2 - dy;
res = true;
if (CGraphicsQ.DEBUG) {
System.err.println(
"\tCurrent dirty: " + dirtyBounds[X] + ", "
+ dirtyBounds[Y] + ", " + dirtyBounds[W] + ", "
+ dirtyBounds[H]);
}
} else {
if (CGraphicsQ.DEBUG) {
System.err.println(
"\tDirty area has not been changed");
}
}
return res;
| public boolean | supportsInput()Determine if this layer supports input, such as key and pen events.
return supportsInput;
| public java.lang.String | toString()Get the layer details including
its bound and dirty region information
String res = layerID() + " [" +
bounds[X] + ", " + bounds[Y] + ", " +
bounds[W] + ", " + bounds[H] + "]";
if (isDirty()) {
res += ", dirty";
if (!isEmptyDirtyRegions()) {
res += " (" +
dirtyBounds[X] + ", " + dirtyBounds[Y] + ", " +
dirtyBounds[W] + ", " + dirtyBounds[H] + ")";
}
}
res += ", opaque: " + (opaque ? 1 : 0);
res += ", visible: " + (visible ? 1 : 0);
res += ", transparent: " + (transparent ? 1 : 0);
return res;
| public void | update(com.sun.midp.chameleon.CLayer[] mainLayers)
if (visible) {
addDirtyRegion();
}
|
|