/*
Реализация спецификаций 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 malik.emulator.media.graphics.*;
public class CharList extends ScrollingScreen
{
private int focusedCharIndex;
private int charSize;
private char[] chars;
private Font font;
private Object lock;
public CharList(boolean fullScreenMode, String title, Ticker ticker,
Command[] commands, Command defaultCommand, CommandListener listener,
char[] chars)
{
super(true, fullScreenMode, title, ticker, commands, defaultCommand, listener, HORIZONTAL);
int len;
char[] c;
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
if(chars == null)
{
c = new char[0];
} else
{
Array.copy(chars, 0, c = new char[len = chars.length], 0, len);
}
this.charSize = ((3 * font.getHeight()) >> 1) + 1;
this.chars = c;
this.font = font;
this.lock = new Object();
}
public void setChars(char[] chars)
{
int len;
char[] c;
synchronized(lock)
{
if(chars == null)
{
c = new char[len = 0];
} else
{
Array.copy(chars, 0, c = new char[len = chars.length], 0, len);
}
this.chars = c;
if(focusedCharIndex >= len)
{
focusedCharIndex = Math.max(0, len - 1);
}
correctScrollBarRange(getHeight());
}
}
public void setSelectedIndex(int selected)
{
int error = 0;
synchronized(lock)
{
label0:
{
if(selected < 0 || selected >= chars.length)
{
error = 1;
break label0;
}
focusedCharIndex = selected;
correctScrollBarPositionToChar();
}
}
if(error == 1)
{
throw new IndexOutOfBoundsException("CharList.setSelectedIndex: " +
"параметр selected выходит из диапазона.");
}
}
public char getChar(int index)
{
char result;
int error;
char[] c;
error = 0;
synchronized(lock)
{
label0:
{
if(index < 0 || index >= (c = chars).length)
{
error = 1;
result = 0;
break label0;
}
result = c[index];
}
}
if(error == 1)
{
throw new IndexOutOfBoundsException("CharList.getChar: " +
"параметр index выходит из диапазона.");
}
return result;
}
public int getSelectedIndex()
{
return focusedCharIndex;
}
public int size()
{
return chars.length;
}
void paint(Graphics render, ScrollBar horzScrollBar, ScrollBar vertScrollBar)
{
int i;
int t;
int x;
int y;
int len;
int size;
int left;
int right;
int focused;
int charsPerColumn;
char[] c;
Font font;
t = ((size = charSize) - (font = this.font).getHeight()) >> 1;
x = 0;
y = 0;
right = (left = horzScrollBar.getPosition()) + horzScrollBar.getPage();
render.setColor(RasterCanvas.getSystemColor(0x28));
render.setFont(font);
synchronized(lock)
{
len = (c = chars).length;
focused = focusedCharIndex;
charsPerColumn = Math.max(1, getHeight() / size);
for(i = 0; i < len; )
{
label0:
{
if(x >= right || x + size <= left)
{
break label0;
}
if(i == focused)
{
render.drawElementOfGUI(1, 0, 0, x, y, size, size);
}
render.drawChar(c[i], x + (size >> 1) - 1, y + t,
Graphics.HCENTER | Graphics.TOP);
}
if(++i % charsPerColumn == 0)
{
x += size;
y = 0;
} else
{
y += size;
}
}
}
}
void onKeyPressed(int key, int charCode)
{
if(!super.keyHandling(key))
{
moveCursor(key);
return;
}
super.onKeyPressed(key, charCode);
}
void onKeyRepeated(int key, int charCode)
{
if(!super.keyHandling(key))
{
moveCursor(key);
return;
}
super.onKeyRepeated(key, charCode);
}
void onClientPointerPressed(int x, int y, int button)
{
pointerHandle(x, y);
}
void onClientPointerDragged(int x, int y)
{
pointerHandle(x, y);
}
void onClientPointerReleased(int x, int y, int button)
{
pointerHandle(x, y);
}
void onSizeChanged(int width, int height)
{
correctScrollBarRange(height);
super.onSizeChanged(width, height);
}
private void moveCursor(int key)
{
int len;
int focused;
int charsPerColumn;
MIDletProxy proxy;
if(key == (proxy = MIDletProxy.getInstance()).getKeyUsedAs(MIDletProxy.DEVICE_KEY_UP))
{
synchronized(lock)
{
if((len = chars.length) > 0)
{
focusedCharIndex = (focusedCharIndex + len - 1) % len;
correctScrollBarPositionToChar();
}
}
return;
}
if(key == proxy.getKeyUsedAs(MIDletProxy.DEVICE_KEY_DOWN))
{
synchronized(lock)
{
if((len = chars.length) > 0)
{
focusedCharIndex = (focusedCharIndex + 1) % len;
correctScrollBarPositionToChar();
}
}
return;
}
if(key == proxy.getKeyUsedAs(MIDletProxy.DEVICE_KEY_LEFT))
{
synchronized(lock)
{
if((focused = focusedCharIndex) >= (charsPerColumn =
Math.max(1, getHeight() / charSize)))
{
focusedCharIndex = focused - charsPerColumn;
correctScrollBarPositionToChar();
}
}
return;
}
if(key == proxy.getKeyUsedAs(MIDletProxy.DEVICE_KEY_RIGHT))
{
synchronized(lock)
{
if((focused = focusedCharIndex) < chars.length - (charsPerColumn =
Math.max(1, getHeight() / charSize)))
{
focusedCharIndex = focused + charsPerColumn;
correctScrollBarPositionToChar();
}
}
}
}
private void pointerHandle(int x, int y)
{
int col;
int row;
int size;
int index;
int charsPerColumn;
synchronized(lock)
{
size = charSize;
col = x / size;
row = y / size;
charsPerColumn = Math.max(1, getHeight() / size);
if((index = row + col * charsPerColumn) >= 0 && index < chars.length)
{
focusedCharIndex = index;
correctScrollBarPositionToChar();
}
}
}
private void correctScrollBarRange(int height)
{
int len = chars.length;
int size = charSize;
int charsPerColumn = Math.max(1, height / size);
getHorzScrollBar().setRange(size * ((len / charsPerColumn) +
(len % charsPerColumn == 0 ? 0 : 1)));
}
private void correctScrollBarPositionToChar()
{
int pos;
int need;
int size = charSize;
int charsPerColumn = Math.max(1, getHeight() / size);
int focusedColumn = focusedCharIndex / charsPerColumn;
ScrollBar scrollbar = getHorzScrollBar();
if((pos = scrollbar.getPosition()) > (need = focusedColumn * size))
{
scrollbar.setPosition(need);
}
else if(pos < (need -= scrollbar.getPage() - size))
{
scrollbar.setPosition(need);
}
callSeriallyPaintScreen(CLIENT);
}
}