/*
Реализация спецификаций 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 malik.emulator.microedition.lcdui;
import javax.microedition.lcdui.*;
import malik.emulator.application.*;
import malik.emulator.media.graphics.*;
import malik.emulator.microedition.*;
public class CharacterList extends CustomSurfaceScreen
{
private int selected;
private char[] chars;
private Font font;
private final Object monitor;
public CharacterList(String title, ScrollBarStyle style) {
super(title, 0, true, style);
this.chars = new char[0];
this.font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
this.monitor = new Object();
correctScrollBarRange(0);
}
public CharacterList(String title, ScrollBarStyle style, char[] list) {
super(title, 0, true, style);
char[] chars;
if(list != null)
{
int len;
Array.copy(list, 0, chars = new char[len = list.length], 0, len);
} else
{
chars = new char[0];
}
this.chars = chars;
this.font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
this.monitor = new Object();
correctScrollBarRange(chars.length);
}
public CharacterList(String title, ScrollBarStyle style, String list) {
super(title, 0, true, style);
char[] chars;
this.chars = chars = list == null ? new char[0] : list.toCharArray();
this.font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
this.monitor = new Object();
correctScrollBarRange(chars.length);
}
public void setSelectedIndex(int index) {
synchronized(monitor)
{
int lim;
char[] list;
if(index > (lim = (list = chars).length - 1)) index = lim;
if(index < 0) index = 0;
correctScrollBarPosition(list, selected = index);
}
}
public void setList(char[] list) {
int len;
if(list != null)
{
Array.copy(list, 0, list = new char[len = list.length], 0, len);
} else
{
list = new char[len = 0];
}
synchronized(monitor)
{
int lim;
int index;
if((index = selected) > (lim = len - 1)) index = lim;
if(index < 0) index = 0;
correctScrollBarRange(list.length);
correctScrollBarPosition(chars = list, selected = index);
}
}
public void setList(String list) {
char[] clist = list == null ? new char[0] : list.toCharArray();
synchronized(monitor)
{
int lim;
int index;
if((index = selected) > (lim = clist.length - 1)) index = lim;
if(index < 0) index = 0;
correctScrollBarRange(clist.length);
correctScrollBarPosition(chars = clist, selected = index);
}
}
public void setFont(Font font) {
if(font == null) font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
synchronized(monitor)
{
char[] list;
this.font = font;
correctScrollBarRange((list = chars).length);
correctScrollBarPosition(list, selected);
}
}
public char getChar(int index) {
char[] list;
if(index < 0 || index >= (list = chars).length)
{
throw new IndexOutOfBoundsException("CharacterList.getChar: аргумент index выходит из диапазона.");
}
return list[index];
}
public char getSelectedChar() {
int lim;
int index;
char[] list;
if((lim = (list = chars).length - 1) < 0)
{
throw new IndexOutOfBoundsException("CharacterList.getSelectedChar: список символов пуст.");
}
if((index = selected) > lim) index = lim;
if(index < 0) index = 0;
return list[index];
}
public int getSelectedIndex() {
return chars.length <= 0 ? -1 : selected;
}
public int getSize() {
return chars.length;
}
public char[] getList() {
int len;
char[] result;
Array.copy(result = chars, 0, result = new char[len = result.length], 0, len);
return result;
}
public Font getFont() {
return font;
}
protected void paint(Graphics render) {
int temp;
int cols;
int line;
int srow;
int frow;
int length;
int selected = this.selected;
char[] chars = this.chars;
Font font = this.font;
cols = super.getWidth() / 32;
line = font.getHeight() + 8;
srow = (temp = render.getClipY()) / line;
frow = (temp + render.getClipHeight() - 1) / line;
length = chars.length;
if(cols < 1) cols = 1;
render.setFont(font);
label0: for(int index = srow * cols, top = srow * line, row = srow; row <= frow; top += line, row++) for(int left = 0, col = 0; col < cols; index++, left += 32, col++)
{
if(index >= length) break label0;
if(index != selected)
{
render.setColor(RasterCanvas.getSystemColor(0x07));
} else
{
render.setColor(RasterCanvas.getSystemColor(0x0d));
render.fillRect(left, top, 32, line);
render.setColor(RasterCanvas.getSystemColor(0x0e));
}
render.drawChar(chars[index], left + 16, top + 4, Graphics.TOP | Graphics.HCENTER);
}
}
protected void keyboardNotify(KeyboardEvent event) {
int key = event.getKey();
DeviceSettings settings = DeviceManager.getInstance().getSettings();
switch(event.getAction())
{
case KeyboardEvent.ACTION_KEY_PRESSED:
case KeyboardEvent.ACTION_KEY_REPEATED:
if(settings.getKeyUsedAs(DeviceSettings.DEVICE_KEY_UP) == key)
{
int cols;
if((cols = super.getWidth() / 32) < 1) cols = 1;
synchronized(monitor)
{
int index;
if((index = selected) >= cols) index -= cols;
correctScrollBarPosition(chars, selected = index, cols);
}
break;
}
if(settings.getKeyUsedAs(DeviceSettings.DEVICE_KEY_DOWN) == key)
{
int cols;
if((cols = super.getWidth() / 32) < 1) cols = 1;
synchronized(monitor)
{
int index;
char[] list;
if((index = selected) < ((list = chars).length - cols)) index += cols;
correctScrollBarPosition(list, selected = index, cols);
}
break;
}
if(settings.getKeyUsedAs(DeviceSettings.DEVICE_KEY_LEFT) == key)
{
synchronized(monitor)
{
int index;
if((index = selected) > 0) index--;
correctScrollBarPosition(chars, selected = index);
}
break;
}
if(settings.getKeyUsedAs(DeviceSettings.DEVICE_KEY_RIGHT) == key)
{
synchronized(monitor)
{
int lim;
int index;
char[] list;
if((index = selected) < (lim = (list = chars).length - 1))
{
index++;
} else
{
index = lim;
}
correctScrollBarPosition(list, selected = index);
}
break;
}
break;
}
}
protected void pointerNotify(PointerEvent event) {
int action = event.getAction();
if(
event.isButtonPressed(PointerEvent.BUTTON_MAIN) || (action == PointerEvent.ACTION_BUTTON_RELEASED ||
action == PointerEvent.ACTION_POINTER_RELEASED) && event.getButton() == PointerEvent.BUTTON_MAIN
)
{
int cols = super.getWidth() / 32;
synchronized(monitor)
{
int lim;
int line = font.getHeight() + 8;
int index = (event.getX() / 32) + (event.getY() / line) * (cols < 1 ? 1 : cols);
char[] list;
if(index > (lim = (list = chars).length - 1)) index = lim;
if(index < 0) index = 0;
correctScrollBarPosition(list, selected = index);
}
}
}
private void correctScrollBarRange(int chars) {
int cols = super.getWidth() / 32;
int line = font.getHeight() + 8;
int rows = chars / (cols = cols < 1 ? 1 : cols) + (chars % cols <= 0 ? 0 : 1);
super.getScrollBar().setRange(rows * line);
}
private void correctScrollBarPosition(char[] chars, int selected) {
correctScrollBarPosition(chars, selected, super.getWidth() / 32);
}
private void correctScrollBarPosition(char[] chars, int selected, int cols) {
int pos;
int page;
int line = font.getHeight() + 8;
int top1 = (selected / (cols < 1 ? 1 : cols)) * line;
int top2 = line + top1;
ScrollBar scroll = super.getScrollBar();
if(top1 < (pos = scroll.getPosition()))
{
scroll.setPosition(top1);
}
else if(top2 > pos + (page = scroll.getPage()))
{
scroll.setPosition(top2 - page);
}
else
{
repaint();
}
}
}