/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016, 2019 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package javax.microedition.lcdui.game;
import javax.microedition.lcdui.*;
public class LayerManager extends Object
{
private int viewLeft;
private int viewTop;
private int viewWidth;
private int viewHeight;
private int count;
private Layer[] layers;
private Object lock;
public LayerManager()
{
this.viewWidth = Integer.MAX_VALUE;
this.viewHeight = Integer.MAX_VALUE;
this.layers = new Layer[2];
this.lock = new Object();
}
public void paint(Graphics render, int left, int top)
{
int i;
int clipLeft;
int clipTop;
int clipWidth;
int clipHeight;
int viewLeft;
int viewTop;
int viewWidth;
int viewHeight;
int viewRight;
int viewBottom;
int layerLeft;
int layerTop;
Layer[] layers;
Layer layer;
if(render == null)
{
throw new NullPointerException("LayerManager.paint: " +
"параметр render равен нулевой ссылке.");
}
clipLeft = render.getClipX();
clipTop = render.getClipY();
clipWidth = render.getClipWidth();
clipHeight = render.getClipHeight();
synchronized(lock)
{
viewRight = (viewLeft = this.viewLeft) + (viewWidth = this.viewWidth);
viewBottom = (viewTop = this.viewTop) + (viewHeight = this.viewHeight);
render.translate(left - viewLeft, top - viewTop);
render.clipRect(viewLeft, viewTop, viewWidth, viewHeight);
try
{
for(layers = this.layers, i = this.count; i-- > 0; )
{
if((!(layer = layers[i]).isVisible()) ||
(layerLeft = layer.getX()) >= viewRight ||
(layerTop = layer.getY()) >= viewBottom ||
layerLeft + layer.getWidth() <= viewLeft ||
layerTop + layer.getHeight() <= viewTop)
{
continue;
}
layer.paint(render);
}
}
finally
{
render.translate(viewLeft - left, viewTop - top);
render.setClip(clipLeft, clipTop, clipWidth, clipHeight);
}
}
}
public void setViewWindow(int left, int top, int width, int height)
{
if(width < 0 || height < 0)
{
throw new IllegalArgumentException("LayerManager.setViewWindow: " +
"размеры не могут быть отрицательными.");
}
synchronized(lock)
{
this.viewLeft = left;
this.viewTop = top;
this.viewWidth = width;
this.viewHeight = height;
}
}
public void insert(Layer layer, int layerIndex)
{
int c;
int error;
int count;
int olderIndex;
Layer[] layers;
if(layer == null)
{
throw new NullPointerException("LayerManager.insert: " +
"параметр layer равен нулевой ссылке.");
}
error = 0;
synchronized(lock)
{
label0:
{
count = this.count;
olderIndex = indexOf(layer);
if(layerIndex < 0 || layerIndex > (olderIndex >= 0 ? count - 1 : count))
{
error = 1;
break label0;
}
layers = this.layers;
if(olderIndex >= 0)
{
if((c = count - olderIndex - 1) > 0)
{
Array.copy(layers, olderIndex + 1, layers, olderIndex, c);
}
count--;
}
else if(count == layers.length)
{
Array.copy(layers, 0, layers = this.layers = new Layer[count << 1], 0, count);
}
if((c = count - layerIndex) > 0)
{
Array.copy(layers, layerIndex, layers, layerIndex + 1, c);
}
layers[layerIndex] = layer;
this.count = ++count;
}
}
if(error == 1)
{
throw new IndexOutOfBoundsException("LayerManager.insert: " +
"параметр layerIndex выходит из диапазона.");
}
}
public void remove(Layer layer)
{
int c;
int count;
int layerIndex;
Layer[] layers;
if(layer == null)
{
throw new NullPointerException("LayerManager.remove: " +
"параметр layer равен нулевой ссылке.");
}
synchronized(lock)
{
if((layerIndex = indexOf(layer)) >= 0)
{
count = this.count;
layers = this.layers;
if((c = count - layerIndex - 1) > 0)
{
Array.copy(layers, layerIndex + 1, layers, layerIndex, c);
}
layers[--count] = null;
this.count = count;
}
}
}
public void append(Layer layer)
{
int c;
int count;
int olderIndex;
Layer[] layers;
if(layer == null)
{
throw new NullPointerException("LayerManager.append: " +
"параметр layer равен нулевой ссылке.");
}
synchronized(lock)
{
count = this.count;
layers = this.layers;
if((olderIndex = indexOf(layer)) >= 0)
{
if((c = count - olderIndex - 1) > 0)
{
Array.copy(layers, olderIndex + 1, layers, olderIndex, c);
}
count--;
}
else if(count == layers.length)
{
Array.copy(layers, 0, layers = this.layers = new Layer[count << 1], 0, count);
}
layers[count++] = layer;
this.count = count;
}
}
public int getSize()
{
return count;
}
public Layer getLayerAt(int layerIndex)
{
int error;
Layer result;
error = 0;
synchronized(lock)
{
label0:
{
if(layerIndex < 0 || layerIndex >= count)
{
error = 1;
result = null;
break label0;
}
result = layers[layerIndex];
}
}
if(error == 1)
{
throw new IndexOutOfBoundsException("LayerManager.getLayerAt: " +
"параметр layerIndex выходит из диапазона.");
}
return result;
}
private int indexOf(Layer layer)
{
int i;
Layer[] layers;
for(layers = this.layers, i = this.count; i-- > 0; )
{
if(layers[i] == layer)
{
return i;
}
}
return -1;
}
}