/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016–2017, 2019–2023 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии 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 final Object monitor;
public LayerManager() {
this.viewWidth = Integer.MAX_VALUE;
this.viewHeight = Integer.MAX_VALUE;
this.layers = new Layer[7];
this.monitor = new Object();
}
public void insert(Layer layer, int index) {
int error;
if(layer == null)
{
throw new NullPointerException("LayerManager.insert: аргумент layer равен нулевой ссылке.");
}
error = 0;
synchronized(monitor)
{
label0:
{
int c;
int len;
int prevIndex;
Layer[] list;
prevIndex = Array.findb(list = layers, (len = count) - 1, layer);
if(index < 0 || index > (prevIndex >= 0 ? len - 1 : len))
{
error = 1;
break label0;
}
if(prevIndex >= 0)
{
if((c = --len - prevIndex) > 0) Array.copy(list, prevIndex + 1, list, prevIndex, c);
}
else if(len == list.length)
{
Array.copy(list, 0, list = layers = new Layer[(len << 1) + 1], 0, len);
}
if((c = len++ - index) > 0) Array.copy(list, index, list, index + 1, c);
list[index] = layer;
count = len;
}
}
if(error == 1)
{
throw new IndexOutOfBoundsException("LayerManager.insert: аргумент index выходит из диапазона.");
}
}
public void remove(Layer layer) {
if(layer == null)
{
throw new NullPointerException("LayerManager.remove: аргумент layer равен нулевой ссылке.");
}
synchronized(monitor)
{
int len;
int index;
Layer[] list;
if((index = Array.findb(list = layers, len = count - 1, layer)) >= 0)
{
int c;
if((c = len - index) > 0) Array.copy(list, index + 1, list, index, c);
list[count = len] = null;
}
}
}
public void append(Layer layer) {
if(layer == null)
{
throw new NullPointerException("LayerManager.insert: аргумент layer равен нулевой ссылке.");
}
synchronized(monitor)
{
int c;
int len;
int prevIndex;
Layer[] list;
if((prevIndex = Array.findb(list = layers, (len = count) - 1, layer)) >= 0)
{
if((c = --len - prevIndex) > 0) Array.copy(list, prevIndex + 1, list, prevIndex, c);
}
else if(len == list.length)
{
Array.copy(list, 0, list = layers = new Layer[(len << 1) + 1], 0, len);
}
list[len++] = layer;
count = len;
}
}
public void paint(Graphics render, int left, int top) {
int clipLeft;
int clipTop;
int clipWidth;
int clipHeight;
if(render == null)
{
throw new NullPointerException("LayerManager.paint: аргумент render равен нулевой ссылке.");
}
clipLeft = render.getClipX();
clipTop = render.getClipY();
clipWidth = render.getClipWidth();
clipHeight = render.getClipHeight();
synchronized(monitor)
{
int viewLeft;
int viewTop;
int viewWidth;
int viewHeight;
int viewRight = (viewLeft = this.viewLeft) + (viewWidth = this.viewWidth);
int viewBottom = (viewTop = this.viewTop) + (viewHeight = this.viewHeight);
render.translate(left - viewLeft, top - viewTop);
render.clipRect(viewLeft, viewTop, viewWidth, viewHeight);
try
{
Layer[] list = layers;
for(int i = count; i-- > 0; )
{
int currLeft;
int currTop;
Layer c;
if((c = list[i]).visibility && (currLeft = c.left) < viewRight && (currTop = c.top) < viewBottom && currLeft + c.width > viewLeft && currTop + c.height > viewTop) c.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)
{
throw new IllegalArgumentException("LayerManager.setViewWindow: аргумент width не может быть отрицательным.");
}
if(height < 0)
{
throw new IllegalArgumentException("LayerManager.setViewWindow: аргумент height не может быть отрицательным.");
}
synchronized(monitor)
{
this.viewLeft = left;
this.viewTop = top;
this.viewWidth = width;
this.viewHeight = height;
}
}
public int getSize() {
return count;
}
public Layer getLayerAt(int index) {
int error = 0;
Layer result;
synchronized(monitor)
{
label0:
{
if(index < 0 || index >= count)
{
error = 1;
result = null;
break label0;
}
result = layers[index];
}
}
if(error == 1)
{
throw new IndexOutOfBoundsException("LayerManager.getLayerAt: аргумент index выходит из диапазона.");
}
return result;
}
}