/*
Реализация спецификаций 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;
import java.lang.ref.*;
public class Form extends Container
{
private static final class ItemCommandEnumerator extends Object
implements CommandEnumeration
{
private CommandEnumeration formCommands;
private CommandEnumeration itemCommands;
ItemCommandEnumerator(CommandEnumeration formCommands, CommandEnumeration itemCommands)
{
this.formCommands = formCommands;
this.itemCommands = itemCommands;
}
public int getCommandsCount()
{
return formCommands.getCommandsCount() + itemCommands.getCommandsCount();
}
public Command getCommand(int index)
{
int itemCommandsCount;
CommandEnumeration formCommands;
CommandEnumeration itemCommands;
CommandEnumeration result;
if(index < 0 || index >= (formCommands = this.formCommands).getCommandsCount() +
(itemCommandsCount = (itemCommands = this.itemCommands).getCommandsCount()))
{
throw new IndexOutOfBoundsException("Form.getCommands: " +
"индекс выходит из диапазона.");
}
if(index < itemCommandsCount)
{
result = itemCommands;
} else
{
result = formCommands;
index -= itemCommandsCount;
}
return result.getCommand(index);
}
public Command getDefaultCommand()
{
Command result;
return (result = itemCommands.getDefaultCommand()) != null ?
result : formCommands.getDefaultCommand();
}
public Object getMonitor()
{
return itemCommands.getMonitor();
}
}
private static final class ItemStateChangedEvent extends Object
implements Runnable
{
private ItemStateListener listener;
private Item item;
ItemStateChangedEvent(ItemStateListener listener, Item item)
{
this.listener = listener;
this.item = item;
}
public void run()
{
listener.itemStateChanged(item);
}
}
private static final class DeleteAllItemsEvent extends Object
implements Runnable
{
private int focusedIndex;
private int count;
private Item[] items;
private Form form;
DeleteAllItemsEvent(Form form, Item[] items, int count, int focusedIndex)
{
this.focusedIndex = focusedIndex;
this.count = count;
this.items = items;
this.form = form;
}
public void run()
{
int i;
int curr = focusedIndex;
Item[] list = items;
Item item;
for(i = count; i-- > 0; )
{
item = list[i];
if(curr == i)
{
try
{
item.onTraverseOut();
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
if(item.isVisible())
{
item.setVisible(false);
try
{
item.onHide();
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
}
form.placeItems();
}
}
private static final class RefocusItemEvent extends Object
implements Runnable
{
private boolean focused;
private Item oldItem;
private Item newItem;
private Form form;
RefocusItemEvent(Form form, boolean deletedItemIsFocused, Item deletedItem,
Item itemForFocus)
{
this.focused = deletedItemIsFocused;
this.oldItem = deletedItem;
this.newItem = itemForFocus;
this.form = form;
}
public void run()
{
Item item;
Form form;
if((item = oldItem) != null)
{
if(focused)
{
try
{
item.onTraverseOut();
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
if(item.isVisible())
{
item.setVisible(false);
try
{
item.onHide();
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
}
(form = this.form).placeItems();
if((item = newItem) != null)
{
form.focusItem(item);
}
}
}
private static final class FocusItemEvent extends Object
implements Runnable
{
private Form form;
private Item item;
FocusItemEvent(Form form, Item item)
{
this.form = form;
this.item = item;
}
public void run()
{
form.focusItem(item);
}
}
private static final class Helper extends WeakReference
implements ItemStateListener, Runnable
{
Helper(Form thisForm)
{
super(thisForm);
}
public void itemStateChanged(Item item)
{
Object thisForm;
if(!((thisForm = get()) instanceof ItemStateListener))
{
return;
}
((ItemStateListener) thisForm).itemStateChanged(item);
}
public void run()
{
Form thisForm;
if((thisForm = (Form) get()) == null)
{
return;
}
thisForm.placeItems();
}
}
private static final int LEFT = 0;
private static final int TOP = 1;
private static final int WIDTH = 2;
private static final int HEIGHT = 3;
private static final int DIR_NONE = CustomItem.NONE;
private static final int DIR_UP = Canvas.UP;
private static final int DIR_LEFT = Canvas.LEFT;
private static final int DIR_RIGHT = Canvas.RIGHT;
private static final int DIR_DOWN = Canvas.DOWN;
private static int keyToDirection(int key)
{
int keyCode;
MIDletProxy proxy;
if((keyCode = (proxy = MIDletProxy.getInstance()).getKeyCode(key)) == 0)
{
return DIR_NONE;
}
if(proxy.getKeyCodeFor(MIDletProxy.DEVICE_KEY_UP) == keyCode)
{
return DIR_UP;
}
if(proxy.getKeyCodeFor(MIDletProxy.DEVICE_KEY_LEFT) == keyCode)
{
return DIR_LEFT;
}
if(proxy.getKeyCodeFor(MIDletProxy.DEVICE_KEY_RIGHT) == keyCode)
{
return DIR_RIGHT;
}
if(proxy.getKeyCodeFor(MIDletProxy.DEVICE_KEY_DOWN) == keyCode)
{
return DIR_DOWN;
}
return DIR_NONE;
}
private boolean needPlaceItems;
private boolean stayPlaceItems;
private boolean firstSizeChanged;
private int focusedIndex;
private int count;
private int[] rect;
private Item[] items;
private ItemStateListener listener;
private Helper helper;
private Object lock;
public Form(String title)
{
this(false, title, null, null, null, null, null);
}
public Form(String title, Item[] items)
{
this(false, title, null, null, null, items, null);
}
public Form(String title, Ticker ticker,
Command[] commands, CommandListener listener,
Item[] items, ItemStateListener itemlistener)
{
this(true, title, ticker, commands, listener, items, itemlistener);
}
private Form(boolean system, String title, Ticker ticker,
Command[] commands, CommandListener listener,
Item[] items, ItemStateListener itemlistener)
{
super(system, title, ticker, commands, null, listener, BOTH);
int i;
int j;
int len;
int error;
Item[] list;
Item item;
error = 0;
synchronized(getOwningLock())
{
label0:
{
list = new Item[Math.max(len = items == null ? 0 : items.length, 1)];
for(i = len; i-- > 0; )
{
if((item = items[i]) == null)
{
error = 1;
break label0;
}
if(item.getOwner() != null)
{
error = 2;
break label0;
}
for(j = i + 1; j < len; j++)
{
if(item == list[j])
{
error = 2;
break label0;
}
}
list[i] = item;
}
for(i = len; i-- > 0; )
{
list[i].setOwner(this);
}
}
}
switch(error)
{
case 1:
throw new NullPointerException("Form: " +
"один из элементов параметра items равен нулевой ссылке.");
case 2:
throw new IllegalStateException("Form: " +
"один из элементов уже принадлежит контейнеру.");
}
this.needPlaceItems = true;
this.firstSizeChanged = true;
this.count = len;
this.rect = new int[4];
this.items = list;
this.listener = itemlistener;
this.helper = new Helper(this);
this.lock = new Object();
}
public int getWidth()
{
return super.getWidth();
}
public int getHeight()
{
return super.getHeight();
}
public void setItemStateListener(ItemStateListener listener)
{
this.listener = listener == this ? helper : listener;
}
public void set(int itemIndex, Item item)
{
boolean focused;
int error;
Item[] list;
Item old;
if(item == null)
{
throw new NullPointerException("Form.set: " +
"параметр item равен нулевой ссылке.");
}
error = 0;
synchronized(lock)
{
label0:
{
if(itemIndex < 0 || itemIndex >= count)
{
error = 1;
break label0;
}
old = (list = items)[itemIndex];
synchronized(getOwningLock())
{
label1:
{
if(item.getOwner() != null)
{
error = 2;
break label1;
}
old.setOwner(null);
item.setOwner(this);
}
}
if(error == 2)
{
break label0;
}
list[itemIndex] = item;
if(focused = focusedIndex == itemIndex)
{
focusedIndex = -1;
}
callSerially(new RefocusItemEvent(this, focused, old, focused ? item : null));
}
}
switch(error)
{
case 1:
throw new IndexOutOfBoundsException("Form.set: " +
"параметр itemIndex выходит из диапазона.");
case 2:
throw new IllegalStateException("Form.set: " +
"параметр item уже принадлежит контейнеру.");
}
}
public void insert(int itemIndex, Item item)
{
boolean empty;
int i;
int len;
int error;
Item[] list;
if(item == null)
{
throw new NullPointerException("Form.insert: " +
"параметр item равен нулевой ссылке.");
}
error = 0;
synchronized(lock)
{
label0:
{
if(itemIndex < 0 || itemIndex > (len = count))
{
error = 1;
break label0;
}
synchronized(getOwningLock())
{
label1:
{
if(item.getOwner() != null)
{
error = 2;
break label1;
}
item.setOwner(this);
}
}
if(error == 2)
{
break label0;
}
if(len == (list = items).length)
{
Array.copy(list, 0, list = items = new Item[(len << 1) + 1], 0, len);
}
if((i = len - itemIndex) > 0)
{
Array.copy(list, itemIndex, list, itemIndex + 1, i);
}
list[itemIndex] = item;
count = ++len;
if(empty = len == 1)
{
focusedIndex = -1;
}
else if((i = focusedIndex) >= itemIndex)
{
focusedIndex = i + 1;
}
callSerially(new RefocusItemEvent(this, false, null, empty ? item : null));
}
}
switch(error)
{
case 1:
throw new IndexOutOfBoundsException("Form.insert: " +
"параметр itemIndex выходит из диапазона.");
case 2:
throw new IllegalStateException("Form.insert: " +
"параметр item уже принадлежит контейнеру.");
}
}
public void delete(int itemIndex)
{
boolean focused;
int i;
int len;
int error;
Item[] list;
Item old;
Item item;
error = 0;
synchronized(lock)
{
label0:
{
if(itemIndex < 0 || itemIndex >= (len = count))
{
error = 1;
break label0;
}
old = (list = items)[itemIndex];
synchronized(getOwningLock())
{
old.setOwner(null);
}
if((i = len - itemIndex - 1) > 0)
{
Array.copy(list, itemIndex + 1, list, itemIndex, i);
}
list[--len] = null;
count = len;
item = null;
if(focused = (i = focusedIndex) == itemIndex)
{
focusedIndex = -1;
item = len > 0 ? list[Math.min(i, len - 1)] : null;
}
else if(i > itemIndex)
{
focusedIndex = i - 1;
}
callSerially(new RefocusItemEvent(this, focused, old, item));
}
}
if(error == 1)
{
throw new IndexOutOfBoundsException("Form.delete: " +
"параметр itemIndex выходит из диапазона.");
}
}
public void deleteAll()
{
int i;
int len;
Item[] list;
synchronized(lock)
{
if((len = count) > 0)
{
i = focusedIndex;
list = items;
focusedIndex = 0;
count = 0;
items = new Item[1];
callSerially(new DeleteAllItemsEvent(this, list, len, i));
}
}
}
public int append(Item item)
{
return appendHelper(item);
}
public int append(Image image)
{
return appendHelper(new ImageItem(null, image, Item.LAYOUT_DEFAULT, null, Item.PLAIN));
}
public int append(String text)
{
return appendHelper(new StringItem(null, text, Item.PLAIN));
}
public int size()
{
return count;
}
public Item get(int itemIndex)
{
int error;
Item result;
error = 0;
synchronized(lock)
{
label0:
{
if(itemIndex < 0 || itemIndex >= count)
{
error = 1;
result = null;
break label0;
}
result = items[itemIndex];
}
}
if(error == 1)
{
throw new IndexOutOfBoundsException("Form.get: " +
"параметр itemIndex выходит из диапазона.");
}
return result;
}
void paint(GraphicsClipRestricted render, ScrollBar horzScrollBar, ScrollBar vertScrollBar)
{
int tx = render.getTranslateX();
int ty = render.getTranslateY();
int cl = render.getClipX();
int ct = render.getClipY();
int cw = render.getClipWidth();
int ch = render.getClipHeight();
int i;
Item[] list;
Item item;
synchronized(lock)
{
for(list = items, i = count; i-- > 0; )
{
if((item = list[i]).isVisible())
{
render.reset();
render.translate(tx, ty);
render.restrictClipRect(cl, ct, cw, ch);
render.translate(item.getLeft(), item.getTop());
render.restrictClipRect(0, 0, item.getWidth(), item.getHeight());
item.onPaint(render);
}
}
}
}
void onShow()
{
super.onShow();
int viewportWidth = getClientWidth();
ScrollBar horz = getHorzScrollBar();
ScrollBar vert = getVertScrollBar();
synchronized(lock)
{
if(needPlaceItems)
{
needPlaceItems = false;
place(viewportWidth, horz, vert);
}
showAll(horz.getPosition(), vert.getPosition(), viewportWidth, getClientHeight());
focus();
}
}
void onHide()
{
synchronized(lock)
{
defocus();
showAll(0, 0, 0, 0);
}
super.onHide();
}
void onSizeChanged(int width, int height)
{
ScrollBar horz;
ScrollBar vert;
label0:
{
if(firstSizeChanged)
{
firstSizeChanged = false;
break label0;
}
synchronized(lock)
{
place(width, horz = getHorzScrollBar(), vert = getVertScrollBar());
showAll(horz.getPosition(), vert.getPosition(), width, height);
}
}
super.onSizeChanged(width, height);
}
void onScroll(ScrollBar horzScrollBar, ScrollBar vertScrollBar)
{
synchronized(lock)
{
showAll(horzScrollBar.getPosition(), vertScrollBar.getPosition(),
getClientWidth(), getClientHeight());
}
}
void onKeyPressed(int key, int charCode)
{
int direction;
if((direction = keyToDirection(key)) != DIR_NONE)
{
synchronized(lock)
{
traverse(direction);
}
return;
}
if(keyPressedHandled(key, charCode))
{
return;
}
super.onKeyPressed(key, charCode);
}
void onKeyRepeated(int key, int charCode)
{
int direction;
if((direction = keyToDirection(key)) != DIR_NONE)
{
synchronized(lock)
{
traverse(direction);
}
return;
}
if(keyRepeatedHandled(key, charCode))
{
return;
}
super.onKeyRepeated(key, charCode);
}
void onKeyReleased(int key)
{
if(keyToDirection(key) != DIR_NONE || keyReleasedHandled(key))
{
return;
}
super.onKeyReleased(key);
}
void onClientPointerPressed(int x, int y, int button)
{
int next;
Item nextItem;
synchronized(lock)
{
if((next = getItemIndexUnderPointer(x, y)) >= 0)
{
focus(next);
(nextItem = items[next]).onPointerPressed(
x - nextItem.getLeft(), y - nextItem.getTop(), button);
}
}
}
void onClientPointerDragged(int x, int y)
{
int curr;
Item currItem;
synchronized(lock)
{
if((curr = focusedIndex) >= 0 && curr < count)
{
(currItem = items[curr]).onPointerDragged(
x - currItem.getLeft(), y - currItem.getTop());
}
}
}
void onClientPointerReleased(int x, int y, int button)
{
int curr;
Item currItem;
synchronized(lock)
{
if((curr = focusedIndex) >= 0 && curr < count)
{
(currItem = items[curr]).onPointerReleased(
x - currItem.getLeft(), y - currItem.getTop(), button);
}
}
}
void onCommandAction(Command command)
{
if(commandActionHandled(command))
{
return;
}
super.onCommandAction(command);
}
boolean isFocused(Item item)
{
boolean result;
int curr;
synchronized(lock)
{
result = (curr = focusedIndex) >= 0 && curr < count && items[curr] == item;
}
return result;
}
CommandEnumeration getCommands()
{
int curr;
Object lock;
CommandEnumeration result;
if((lock = this.lock) == null)
{
return super.getCommands();
}
synchronized(lock)
{
result = (curr = focusedIndex) < 0 || curr >= count ? super.getCommands() :
new ItemCommandEnumerator(super.getCommands(), items[curr].getCommands());
}
return result;
}
final void setCurrent(Item item, Display display)
{
display.setCurrent(this);
display.callSeriallyEvent(this, new FocusItemEvent(this, item));
}
final void notifyPlaceItems()
{
if(stayPlaceItems)
{
return;
}
stayPlaceItems = true;
callSerially(helper);
}
final void notifyItemStateChanged(Item item)
{
ItemStateListener listener;
if((listener = this.listener) == null)
{
return;
}
callSerially(new ItemStateChangedEvent(listener, item));
}
final void focusItem(Item item)
{
int next;
synchronized(lock)
{
if((next = indexOf(item)) >= 0)
{
if(isReallyShown())
{
focus(next);
} else
{
focusedIndex = next;
}
}
}
}
final void placeItems()
{
int viewportWidth = getClientWidth();
ScrollBar horz = getHorzScrollBar();
ScrollBar vert = getVertScrollBar();
synchronized(lock)
{
place(viewportWidth, horz, vert);
if(isReallyShown())
{
showAll(horz.getPosition(), vert.getPosition(), viewportWidth, getClientHeight());
traverse();
}
}
}
private void defocus()
{
int curr;
if((curr = focusedIndex) < 0 || curr >= count)
{
return;
}
try
{
items[curr].onTraverseOut();
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
private void focus()
{
int viewportWidth;
int viewportHeight;
int curr;
Item currItem;
if((curr = focusedIndex) < 0 || curr >= count)
{
return;
}
viewportWidth = getClientWidth();
viewportHeight = getClientHeight();
currItem = items[curr];
try
{
currItem.onTraverseNeedStayOn(
DIR_NONE, viewportWidth, viewportHeight, getVisibleRectangle(currItem, false,
DIR_NONE, viewportWidth, viewportHeight));
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
updateCommands();
callSeriallyPaintScreen(CLIENT);
}
private void focus(int next)
{
int viewportWidth;
int viewportHeight;
int curr;
Item[] list = items;
Item nextItem;
if((curr = focusedIndex) == next)
{
return;
}
if(curr >= 0 && curr < count)
{
try
{
list[curr].onTraverseOut();
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
viewportWidth = getClientWidth();
viewportHeight = getClientHeight();
nextItem = list[next];
focusedIndex = next;
try
{
nextItem.onTraverseNeedStayOn(
DIR_NONE, viewportWidth, viewportHeight, getVisibleRectangle(nextItem, false,
DIR_NONE, viewportWidth, viewportHeight));
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
updateVisibleRectangle(nextItem, viewportWidth, viewportHeight);
updateCommands();
callSeriallyPaintScreen(CLIENT);
}
private void traverse()
{
int viewportWidth;
int viewportHeight;
int curr;
Item currItem;
if((curr = focusedIndex) < 0 || curr >= count)
{
return;
}
viewportWidth = getClientWidth();
viewportHeight = getClientHeight();
currItem = items[curr];
try
{
currItem.onTraverseNeedStayOn(
DIR_NONE, viewportWidth, viewportHeight, getVisibleRectangle(currItem, false,
DIR_NONE, viewportWidth, viewportHeight));
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
updateVisibleRectangle(currItem, viewportWidth, viewportHeight);
updateCommands();
callSeriallyPaintScreen(CLIENT);
}
private void traverse(int direction)
{
boolean needStayOn;
int viewportWidth;
int viewportHeight;
int curr;
int next;
Item[] list;
Item currItem;
Item nextItem;
if((curr = focusedIndex) < 0 || curr >= count)
{
return;
}
viewportWidth = getClientWidth();
viewportHeight = getClientHeight();
currItem = (list = items)[curr];
try
{
needStayOn = currItem.onTraverseNeedStayOn(
direction, viewportWidth, viewportHeight, getVisibleRectangle(currItem, true,
direction, viewportWidth, viewportHeight));
}
catch(RuntimeException e)
{
e.printRealStackTrace();
needStayOn = false;
}
if(needStayOn || (next = getItemIndexForFocus(curr, direction)) < 0)
{
updateVisibleRectangle(currItem, viewportWidth, viewportHeight);
return;
}
try
{
currItem.onTraverseOut();
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
nextItem = list[next];
focusedIndex = next;
try
{
nextItem.onTraverseNeedStayOn(
direction, viewportWidth, viewportHeight, getVisibleRectangle(nextItem, false,
direction, viewportWidth, viewportHeight));
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
updateVisibleRectangle(nextItem, viewportWidth, viewportHeight);
updateCommands();
callSeriallyPaintScreen(CLIENT);
}
private void showAll(int viewportLeft, int viewportTop, int viewportWidth, int viewportHeight)
{
boolean visible;
boolean formVisible;
boolean realVisible;
int i;
int tmp;
int left;
int top;
int right;
int bottom;
Item[] list;
Item item;
formVisible = viewportWidth > 0 && viewportHeight > 0;
right = (left = viewportLeft) + viewportWidth;
bottom = (top = viewportTop) + viewportHeight;
for(list = items, i = count; i-- > 0; )
{
item = list[i];
visible = formVisible &&
(tmp = item.getLeft()) + item.getWidth() > left && tmp < right &&
(tmp = item.getTop()) + item.getHeight() > top && tmp < bottom;
realVisible = item.isVisible();
item.setVisible(visible);
if(realVisible && !visible)
{
item.setVisible(false);
try
{
item.onHide();
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
if(visible && !realVisible)
{
item.setVisible(true);
try
{
item.onShow();
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
}
}
private void place(int containerClientWidth, ScrollBar horzScrollBar, ScrollBar vertScrollBar)
{
int c;
int p;
int i;
int j;
int len;
int tmp;
int left;
int top;
int width;
int iwidth;
int rowTop;
int rowHeight;
int rowFinish;
int leftWidth;
int centerIndex;
int centerLeft;
int centerWidth;
int rightIndex;
int rightLeft;
int rightWidth;
int formWidth;
int formHeight;
Item[] list;
Item item;
stayPlaceItems = false;
/* вычисляем размеры каждого элемента */
for(list = items, i = len = count; i-- > 0; )
{
list[i].computeSizes(containerClientWidth);
}
formWidth = 0;
formHeight = 0;
for(rowTop = 0, i = 0; i < len; rowTop += rowHeight, i = rowFinish)
{
/* вычисляем индекс конечного элемента на текущей строке элементов */
for(width = 0, j = i; j < len; width += iwidth, j++)
{
/* Очередной элемент будет перенесён на новую строку,
* если выполняется хотя бы одно из следующих условий:
* 1. У очередного элемента выставлен принудительный перенос на новую строку
* перед ним (Item.LAYOUT_NEWLINE_BEFORE);
* 2. У предыдущего элемента выставлен принудительный перенос на новую строку
* после него (Item.LAYOUT_NEWLINE_AFTER);
* 3. Очередной элемент не помещается на текущей строке;
* 4. Предыдущий элемент выравнен по центру (Item.LAYOUT_CENTER), а
* очередной элемент выравнен по левому краю (Item.LAYOUT_LEFT);
* 5. Предыдущий элемент выравнен по павому краю (Item.LAYOUT_RIGHT), а
* очередной элемент не выравнен по правому краю.
* Условия проверяются в указанном порядке.
*/
iwidth = (item = list[j]).getWidth();
if(j > i && (((c = item.getRealLayout()) & Item.LAYOUT_NEWLINE_BEFORE) != 0 ||
((p = list[j - 1].getRealLayout()) & Item.LAYOUT_NEWLINE_AFTER) != 0 ||
width + iwidth > containerClientWidth ||
(p &= Item.LAYOUT_CENTER) == Item.LAYOUT_CENTER && (
(c &= Item.LAYOUT_CENTER) == Item.LAYOUT_LEFT || c == 0) ||
p == Item.LAYOUT_RIGHT && c != Item.LAYOUT_RIGHT))
{
break;
}
}
/* вычисляем высоту в пикселах текущей строки элементов */
for(rowFinish = j, rowHeight = 0, j = i; j < rowFinish; j++)
{
if(rowHeight < (tmp = list[j].getHeight()))
{
rowHeight = tmp;
}
}
/* корректируем размеры формы */
if(formWidth < width)
{
formWidth = width;
}
formHeight += rowHeight;
/* распределяем элементы текущей строки элементов следующим образом:
* LAYOUT_DEFAULT
* LAYOUT_LEFT LAYOUT_CENTER LAYOUT_RIGHT
* +-----+-----+-----+ +-----+-----+ +-----+-----+ текущая
* | [0] | [1] | [2] | -- | [3] | [4] | -- | [5] | [6] | -- строка
* +-----+-----+-----+ +-----+-----+ +-----+-----+ элементов
* | leftWidth | |centerWidth| | rightWidth|
* +-----------------+ +-----------+ +-----------+
* | centerLeft | | |
* +----------------------+ | |
* | rightLeft | |
* +---------------------------------------+ |
* | containerClientWidth |
* +---------------------------------------------------+
* i = 0
* rowFinish = 7
* centerIndex = 3
* rightIndex = 5
*/
for(centerIndex = rowFinish, leftWidth = 0, j = i; j < rowFinish; j++)
{
switch((item = list[j]).getRealLayout() & Item.LAYOUT_CENTER)
{
default://LAYOUT_LEFT:
leftWidth += item.getWidth();
continue;
case Item.LAYOUT_CENTER:
case Item.LAYOUT_RIGHT:
centerIndex = j;
break;
}
break;
}
for(rightIndex = rowFinish, centerWidth = 0; j < rowFinish; j++)
{
switch((item = list[j]).getRealLayout() & Item.LAYOUT_CENTER)
{
case Item.LAYOUT_CENTER:
centerWidth += item.getWidth();
continue;
case Item.LAYOUT_RIGHT:
default://LAYOUT_LEFT:
rightIndex = j;
break;
}
break;
}
for(rightWidth = 0; j < rowFinish; j++)
{
rightWidth += list[j].getWidth();
}
centerLeft = Math.max(leftWidth + ((containerClientWidth -
(leftWidth + centerWidth + rightWidth)) / 2), leftWidth);
rightLeft = Math.max(containerClientWidth - rightWidth,
leftWidth + centerWidth);
/* устанавливаем положение каждого элемента текущей строки элементов */
for(left = 0, j = i; j < rowFinish; j++)
{
if(j == centerIndex)
{
left = centerLeft;
}
if(j == rightIndex)
{
left = rightLeft;
}
switch(((item = list[j]).getRealLayout() & Item.LAYOUT_VCENTER) >> 4)
{
default://LAYOUT_TOP >> 4:
top = rowTop;
break;
case Item.LAYOUT_VCENTER >> 4:
top = rowTop + ((rowHeight - item.getHeight()) >> 1);
break;
case Item.LAYOUT_BOTTOM >> 4:
top = rowTop + rowHeight - item.getHeight();
break;
}
item.setPosition(left, top);
left += item.getWidth();
}
}
horzScrollBar.setVisible(formWidth > containerClientWidth);
horzScrollBar.setRange(formWidth);
vertScrollBar.setVisible(true);
vertScrollBar.setRange(formHeight);
}
private void updateVisibleRectangle(Item item, int viewportWidth, int viewportHeight)
{
int l;
int t;
int x;
int y;
int tmp;
int vrw;
int vrh;
int[] visibleRectangle = rect;
ScrollBar horz = getHorzScrollBar();
ScrollBar vert = getVertScrollBar();
visibleRectangle[WIDTH] = vrw = (tmp = visibleRectangle[WIDTH]) < 0 ? 0 :
(tmp > viewportWidth ? viewportWidth : tmp);
visibleRectangle[HEIGHT] = vrh = (tmp = visibleRectangle[HEIGHT]) < 0 ? 0 :
(tmp > viewportHeight ? viewportHeight : tmp);
x = horz.getPosition() - (l = item.getLeft());
y = vert.getPosition() - (t = item.getTop());
x = x > (tmp = visibleRectangle[LEFT]) ? tmp :
(x < (tmp += vrw - viewportWidth) ? tmp : x);
y = y > (tmp = visibleRectangle[TOP]) ? tmp :
(y < (tmp += vrh - viewportHeight) ? tmp : y);
horz.setPosition(x + l);
vert.setPosition(y + t);
}
private boolean keyPressedHandled(int key, int charCode)
{
boolean result;
int curr;
Item currItem;
synchronized(lock)
{
label0:
{
if((curr = focusedIndex) < 0 || curr >= count ||
(!(currItem = items[curr]).keyHandling(key)))
{
result = false;
break label0;
}
try
{
currItem.onKeyPressed(key, charCode);
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
result = true;
}
}
return result;
}
private boolean keyRepeatedHandled(int key, int charCode)
{
boolean result;
int curr;
Item currItem;
synchronized(lock)
{
label0:
{
if((curr = focusedIndex) < 0 || curr >= count ||
(!(currItem = items[curr]).keyHandling(key)))
{
result = false;
break label0;
}
try
{
currItem.onKeyRepeated(key, charCode);
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
result = true;
}
}
return result;
}
private boolean keyReleasedHandled(int key)
{
boolean result;
int curr;
Item currItem;
synchronized(lock)
{
label0:
{
if((curr = focusedIndex) < 0 || curr >= count ||
(!(currItem = items[curr]).keyHandling(key)))
{
result = false;
break label0;
}
try
{
currItem.onKeyReleased(key);
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
result = true;
}
}
return result;
}
private boolean commandActionHandled(Command command)
{
boolean result;
int curr;
Item currItem;
synchronized(lock)
{
label0:
{
if((curr = focusedIndex) < 0 || curr >= count ||
(!(currItem = items[curr]).getCommands().hasCommand(command)))
{
result = false;
break label0;
}
try
{
currItem.onCommandAction(command);
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
result = true;
}
}
return result;
}
private int appendHelper(Item item)
{
boolean empty;
int len;
int error;
int result;
Item[] list;
if(item == null)
{
throw new NullPointerException("Form.append: " +
"параметр item равен нулевой ссылке.");
}
error = 0;
synchronized(lock)
{
label0:
{
result = len = count;
synchronized(getOwningLock())
{
label1:
{
if(item.getOwner() != null)
{
error = 1;
break label1;
}
item.setOwner(this);
}
}
if(error == 1)
{
break label0;
}
if(len == (list = items).length)
{
Array.copy(list, 0, list = items = new Item[(len << 1) + 1], 0, len);
}
list[len] = item;
count = ++len;
if(empty = len == 1)
{
focusedIndex = -1;
}
callSerially(new RefocusItemEvent(this, false, null, empty ? item : null));
}
}
if(error == 1)
{
throw new IllegalStateException("Form.append: " +
"параметр item уже принадлежит контейнеру.");
}
return result;
}
private int indexOf(Item item)
{
int i;
Item[] list;
for(list = items, i = count; i-- > 0; )
{
if(list[i] == item)
{
return i;
}
}
return -1;
}
private int getItemIndexForFocus(int focusedItemIndex, int direction)
{
int i;
int pos;
int len;
int result = -1;
Item[] list;
Item current = (list = items)[focusedItemIndex];
Item item;
switch(direction)
{
case DIR_UP:
pos = current.getTop();
for(i = focusedItemIndex; i-- > 0; )
{
if((item = list[i]).getTop() + item.getHeight() <= pos)
{
result = i;
break;
}
}
break;
case DIR_LEFT:
result = focusedItemIndex - 1;
break;
case DIR_RIGHT:
if(focusedItemIndex < count - 1)
{
result = focusedItemIndex + 1;
}
break;
case DIR_DOWN:
pos = current.getTop() + current.getHeight();
for(len = count, i = focusedItemIndex + 1; i < len; i++)
{
if(list[i].getTop() >= pos)
{
result = i;
break;
}
}
break;
}
return result;
}
private int getItemIndexUnderPointer(int x, int y)
{
int i;
int tmp;
Item[] list;
Item item;
for(list = items, i = count; i-- > 0; )
{
if(x >= (tmp = (item = list[i]).getLeft()) && x < tmp + item.getWidth() &&
y >= (tmp = item.getTop()) && y < tmp + item.getHeight())
{
return i;
}
}
return -1;
}
private int[] getVisibleRectangle(Item item, boolean focused,
int direction, int viewportWidth, int viewportHeight)
{
int l;
int t;
int l1;
int t1;
int tmp;
int hpos;
int vpos;
int itemWidth = item.getWidth();
int itemHeight = item.getHeight();
int[] result = rect;
label0:
{
if((!focused) && itemWidth <= viewportWidth && itemHeight <= viewportHeight)
{
result[LEFT] = 0;
result[TOP] = 0;
result[WIDTH] = itemWidth;
result[HEIGHT] = itemHeight;
break label0;
}
hpos = getHorzScrollBar().getPosition();
vpos = getVertScrollBar().getPosition();
if(focused || direction == DIR_NONE)
{
result[LEFT] = l1 = Math.max(l = hpos - item.getLeft(), 0);
result[TOP] = t1 = Math.max(t = vpos - item.getTop(), 0);
result[WIDTH] = Math.min(l + viewportWidth, itemWidth) - l1;
result[HEIGHT] = Math.min(t + viewportHeight, itemHeight) - t1;
break label0;
}
switch(direction)
{
case DIR_UP:
result[LEFT] = tmp = Math.max(hpos - item.getLeft(), 0);
result[TOP] = Math.max(itemHeight - viewportHeight, 0);
result[WIDTH] = Math.min(viewportWidth, itemWidth - tmp);
result[HEIGHT] = Math.min(viewportHeight, itemHeight);
break;
case DIR_LEFT:
result[LEFT] = Math.max(itemWidth - viewportWidth, 0);
result[TOP] = tmp = Math.max(vpos - item.getTop(), 0);
result[WIDTH] = Math.min(viewportWidth, itemWidth);
result[HEIGHT] = Math.min(viewportHeight, itemHeight - tmp);
break;
case DIR_RIGHT:
result[LEFT] = 0;
result[TOP] = tmp = Math.max(vpos - item.getTop(), 0);
result[WIDTH] = Math.min(viewportWidth, itemWidth);
result[HEIGHT] = Math.min(viewportHeight, itemHeight - tmp);
break;
case DIR_DOWN:
result[LEFT] = tmp = Math.max(hpos - item.getLeft(), 0);
result[TOP] = 0;
result[WIDTH] = Math.min(viewportWidth, itemWidth - tmp);
result[HEIGHT] = Math.min(viewportHeight, itemHeight);
break;
}
}
return result;
}
}