/*
Реализация спецификаций 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.system;
import com.nokia.mid.ui.*;
import java.io.*;
import java.util.*;
import javax.microedition.io.*;
import javax.microedition.io.file.*;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import javax.microedition.media.protocol.*;
import javax.microedition.rms.*;
import javax.wireless.messaging.*;
import malik.emulator.application.*;
import malik.emulator.fileformats.*;
import malik.emulator.fileformats.graphics.*;
import malik.emulator.fileformats.graphics.bmp.*;
import malik.emulator.fileformats.graphics.gif.*;
import malik.emulator.fileformats.graphics.jpeg.*;
import malik.emulator.fileformats.graphics.png.*;
import malik.emulator.fileformats.sound.sampled.*;
import malik.emulator.fileformats.sound.sampled.wave.*;
import malik.emulator.fileformats.sound.synthetic.*;
import malik.emulator.fileformats.sound.synthetic.midi.*;
import malik.emulator.io.cloud.*;
import malik.emulator.media.graphics.*;
import malik.emulator.microedition.*;
import malik.emulator.microedition.lcdui.*;
import malik.emulator.microedition.media.*;
import malik.emulator.microedition.system.player.*;
import malik.emulator.microedition.system.protocol.*;
import malik.emulator.microedition.system.protocol.file.*;
import malik.emulator.microedition.system.protocol.resource.*;
import malik.emulator.microedition.system.protocol.sms.*;
import malik.emulator.util.*;
public class SystemManager extends DeviceManager implements CommandListener, ItemCommandListener, ItemStateListener, ThreadTerminationListener
{
public static final int MIDLET_NAME = 0;
public static final int MIDLET_ICON = 1;
public static final int MIDLET_CLASS = 2;
private static final int[] FONT_SIZES;
private static final int[] DEVICE_KEYS;
private static final int[] KEYBOARD_KEYS;
private static final KeyCodeSet[] KEY_CODE_SETS;
private static final String[] EMPTY_STRING_ARRAY;
static {
FONT_SIZES = new int[] {
DeviceSettings.FONT_SIZE_SMALL, DeviceSettings.FONT_SIZE_MEDIUM, DeviceSettings.FONT_SIZE_LARGE
};
DEVICE_KEYS = new int[] {
DeviceSettings.DEVICE_KEY_UP, DeviceSettings.DEVICE_KEY_DOWN, DeviceSettings.DEVICE_KEY_LEFT,
DeviceSettings.DEVICE_KEY_RIGHT, DeviceSettings.DEVICE_KEY_SELECT, DeviceSettings.DEVICE_KEY_SOFT1,
DeviceSettings.DEVICE_KEY_SOFT2, DeviceSettings.DEVICE_KEY_CONSOLE, DeviceSettings.DEVICE_KEY_EXITAPP,
DeviceSettings.DEVICE_KEY_1, DeviceSettings.DEVICE_KEY_2, DeviceSettings.DEVICE_KEY_3,
DeviceSettings.DEVICE_KEY_4, DeviceSettings.DEVICE_KEY_5, DeviceSettings.DEVICE_KEY_6,
DeviceSettings.DEVICE_KEY_7, DeviceSettings.DEVICE_KEY_8, DeviceSettings.DEVICE_KEY_9,
DeviceSettings.DEVICE_KEY_STAR, DeviceSettings.DEVICE_KEY_0, DeviceSettings.DEVICE_KEY_POUND
};
KEYBOARD_KEYS = new int[] {
0, KeyboardEvent.KEY_ESCAPE, KeyboardEvent.KEY_F1, KeyboardEvent.KEY_F2, KeyboardEvent.KEY_F3, KeyboardEvent.KEY_F4, KeyboardEvent.KEY_F5, KeyboardEvent.KEY_F6, KeyboardEvent.KEY_F7,
KeyboardEvent.KEY_F8, KeyboardEvent.KEY_F9, KeyboardEvent.KEY_F10, KeyboardEvent.KEY_F11, KeyboardEvent.KEY_F12, KeyboardEvent.KEY_ENTER, KeyboardEvent.KEY_SPACE, KeyboardEvent.KEY_INSERT,
KeyboardEvent.KEY_DELETE, KeyboardEvent.KEY_HOME, KeyboardEvent.KEY_END, KeyboardEvent.KEY_PAGE_UP, KeyboardEvent.KEY_PAGE_DOWN, KeyboardEvent.KEY_UP, KeyboardEvent.KEY_DOWN,
KeyboardEvent.KEY_LEFT, KeyboardEvent.KEY_RIGHT, KeyboardEvent.KEY_NUM_PLUS, KeyboardEvent.KEY_NUM_MINUS, KeyboardEvent.KEY_NUM_STAR, KeyboardEvent.KEY_NUM_DIVIDE,
KeyboardEvent.KEY_NUM_DECIMAL, KeyboardEvent.KEY_NUM_0, KeyboardEvent.KEY_NUM_1, KeyboardEvent.KEY_NUM_2, KeyboardEvent.KEY_NUM_3, KeyboardEvent.KEY_NUM_4, KeyboardEvent.KEY_NUM_5,
KeyboardEvent.KEY_NUM_6, KeyboardEvent.KEY_NUM_7, KeyboardEvent.KEY_NUM_8, KeyboardEvent.KEY_NUM_9
};
KEY_CODE_SETS = new KeyCodeSet[] {
new KeyCodeSet("Свои настройки", 0, 0, 0, 0, 0, 0, 0),
new KeyCodeSet("Motorola", -1, -6, -2, -5, -20, -21, -22),
new KeyCodeSet("Nokia (по умолчанию)", -1, -2, -3, -4, -5, -6, -7),
new KeyCodeSet("Siemens", -59, -60, -61, -62, -26, -1, -4)
};
EMPTY_STRING_ARRAY = new String[0];
}
public static boolean containsString(String[] array, String string) {
int len;
if(array == null || (len = array.length) <= 0) return false;
if(string == null) return Array.findf(array, 0, null) < len;
for(int i = len; i-- > 0; ) if(string.equals(array[i])) return true;
return false;
}
public static String deviceKeyToString(int deviceKey) {
DeviceSettings settings;
switch(deviceKey)
{
case DeviceSettings.DEVICE_KEY_CONSOLE:
return "Вызов консоли";
case DeviceSettings.DEVICE_KEY_EXITAPP:
return "Выход из приложения";
default:
return (settings = DeviceManager.getInstance().getSettings()).getKeyName(settings.getKeyCodeFor(deviceKey));
}
}
public static String calendarToString(Calendar calendar) {
StringBuilder result = new StringBuilder();
switch(calendar.get(Calendar.DAY_OF_WEEK))
{
case Calendar.MONDAY:
result.append("понедельник, ");
break;
case Calendar.TUESDAY:
result.append("вторник, ");
break;
case Calendar.WEDNESDAY:
result.append("среда, ");
break;
case Calendar.THURSDAY:
result.append("четверг, ");
break;
case Calendar.FRIDAY:
result.append("пятница, ");
break;
case Calendar.SATURDAY:
result.append("суббота, ");
break;
case Calendar.SUNDAY:
result.append("воскресенье, ");
break;
}
result.append(calendar.get(Calendar.DAY_OF_MONTH));
switch(calendar.get(Calendar.MONTH))
{
case Calendar.JANUARY:
result.append(" января ");
break;
case Calendar.FEBRUARY:
result.append(" февраля ");
break;
case Calendar.MARCH:
result.append(" марта ");
break;
case Calendar.APRIL:
result.append(" апреля ");
break;
case Calendar.MAY:
result.append(" мая ");
break;
case Calendar.JUNE:
result.append(" июня ");
break;
case Calendar.JULY:
result.append(" июля ");
break;
case Calendar.AUGUST:
result.append(" августа ");
break;
case Calendar.SEPTEMBER:
result.append(" сентября ");
break;
case Calendar.OCTOBER:
result.append(" октября ");
break;
case Calendar.NOVEMBER:
result.append(" ноября ");
break;
case Calendar.DECEMBER:
result.append(" декабря ");
break;
}
return result.
append(calendar.get(Calendar.YEAR)).append(", ").append(calendar.get(Calendar.HOUR_OF_DAY)).append(':').append(calendar.get(Calendar.MINUTE)).append(' ').append(calendar.getTimeZone()).
toString();
}
public static Image loadImageFromFile(String fileName) {
Image result;
try
{
HandleInputStream stream;
(stream = new FileInputStream(fileName)).checkOpenError();
try
{
result = Image.createImage(stream);
}
finally
{
stream.close();
}
}
catch(IOException e)
{
e.printRealStackTrace();
result = null;
}
return result;
}
public static Image loadApplicationIcon() {
String resourceName;
if((resourceName = DeviceManager.getInstance().getSettings().getMIDletProperty("MIDlet-Icon")) == null) return null;
if(resourceName.length() > 0 && resourceName.charAt(0) == '/') resourceName = resourceName.substring(1);
return loadImageFromFile("/res/".concat(resourceName));
}
private static void fillKeysList(Choice list) {
int[] keys = KEYBOARD_KEYS;
list.deleteAll();
for(int len = keys.length, i = 0; i < len; i++)
{
int key;
list.append((key = keys[i]) == 0 ? "Свои настройки" : DeviceSettings.keyToString(key), null);
}
}
private static int indexOfKey(int key) {
int index;
int[] keys;
return (index = Array.findb(keys = KEYBOARD_KEYS, keys.length - 1, key)) <= 0 ? 0 : index;
}
private static int indexOfString(Choice list, String string) {
for(int i = list.size(); i-- > 0; ) if(list.getString(i).equals(string)) return i;
return -1;
}
private static MIDletDisplay createDefaultApplicationDisplay() {
RasterCanvas screen = RasterCanvas.screen;
return new MIDletDisplay(false, screen.getWidth(), screen.getHeight());
}
private boolean firstConnectionOpened;
private boolean consoleGreetingPrinted;
private int saveSettingsElementIndex;
private String[] supportedProtocols;
private String[] supportedContentTypes;
private String[] applicationClassNames;
private final SettingsForm[] screenSettings;
private ChoiceGroup itemKeyCodeSets;
private ButtonSet itemDeviceButtons;
private StringItem itemRecordProperties;
private StringItem itemKeyDescription;
private StringItem itemKeyEquivalent;
private StringItem itemErrorInfo;
private Command commandNo;
private Command commandYes;
private Command commandExit;
private Command commandBack;
private Command commandApply;
private Command commandClear;
private Command commandDelete;
private Command commandLaunch;
private Command commandUpdate;
private Command commandSettings;
private Command commandProperties;
private Command commandAboutApplication;
private Command commandAboutImplementation;
private List screenRecordsList;
private List screenSettingsList;
private List screenApplicationList;
private Form screenApplicationError;
private Form screenAboutApplication;
private Form screenAboutImplementation;
private Form screenRecordProperties;
private Form screenDeviceButtonsView;
private Alert screenError;
private Alert screenExitApplication;
private Alert screenRecordsClearConfirm;
private Alert screenRecordDeleteConfirm;
private Displayable screenBackground;
private SettingsForm screenSettingFonts;
private SettingsForm screenSettingSystem;
private SettingsForm screenSettingControls;
private SettingsForm screenSettingKeyCodes;
private SurfaceTextViewer screenLongOperation;
private final MIDletDisplay applicationDisplay;
private final BackgroundConsoleCommand imagesCommand;
private final BackgroundConsoleCommand soundsCommand;
final Console console;
public SystemManager() {
Console console;
MIDletDisplay ref1;
BackgroundConsoleCommand cmd1;
BackgroundConsoleCommand cmd2;
Run.instance.setThreadTerminationListener(this);
this.screenSettings = new SettingsForm[4];
this.applicationDisplay = (ref1 = createApplicationDisplay()) == null ? createDefaultApplicationDisplay() : ref1;
this.imagesCommand = cmd1 = new ImagesSearchConsoleCommand(this);
this.soundsCommand = cmd2 = new SoundsSearchConsoleCommand(this);
this.console = console = new Console("Консоль J2ME", null, false, this);
console.addConsoleCommand(new HideForegroundScreenConsoleCommand(this));
console.addConsoleCommand(cmd1);
console.addConsoleCommand(cmd2);
for(int i = 1; ; i++)
{
String value;
if((value = System.getSystemProperty("malik.emulator.microedition.console.command.".concat(Integer.toString(i)))) == null) break;
try
{
console.addConsoleCommand((ConsoleCommand) Class.forName(value).newInstance());
}
catch(Exception e)
{
e.printRealStackTrace();
}
}
}
public void playTone(int note, int duration, int volume) throws MediaException {
super.playTone(note, duration > 10000 ? 10000 : duration, volume);
}
public void applicationStarted(Display display) {
super.applicationStarted(display);
super.getMainDisplay().setCurrent(console);
}
public void applicationStopped(Display display) {
super.applicationStopped(display);
Run.instance.terminate();
}
public String[] getSupportedContentTypes(String protocol) {
String[] protocols;
String[] contentTypes;
if((protocols = supportedProtocols) == null && ((protocols = supportedProtocols = getSupportedProtocols()) == null || protocols.length <= 0))
{
protocols = supportedProtocols = getSystemSupportedProtocols();
}
if((contentTypes = supportedContentTypes) == null && ((contentTypes = supportedContentTypes = getSupportedContentTypes()) == null || contentTypes.length <= 0))
{
contentTypes = supportedContentTypes = getSystemSupportedContentTypes();
}
if(protocol == null || containsString(protocols, protocol))
{
int len;
String[] result;
Array.copy(contentTypes, 0, result = new String[len = contentTypes.length], 0, len);
return result;
}
return EMPTY_STRING_ARRAY;
}
public String[] getSupportedProtocols(String contentType) {
String[] protocols;
String[] contentTypes;
if((protocols = supportedProtocols) == null && ((protocols = supportedProtocols = getSupportedProtocols()) == null || protocols.length <= 0))
{
protocols = supportedProtocols = getSystemSupportedProtocols();
}
if((contentTypes = supportedContentTypes) == null && ((contentTypes = supportedContentTypes = getSupportedContentTypes()) == null || contentTypes.length <= 0))
{
contentTypes = supportedContentTypes = getSystemSupportedContentTypes();
}
if(contentType == null || containsString(contentTypes, contentType))
{
int len;
String[] result;
Array.copy(protocols, 0, result = new String[len = protocols.length], 0, len);
return result;
}
return EMPTY_STRING_ARRAY;
}
public Player createPlayer(String locator) throws IOException, MediaException {
InputStream stream;
if((stream = Connector.openInputStream(locator)) != null)
{
Player result = null;
try
{
long signature = (long) (new DataInputStream(stream)).readInt() & 0x00000000ffffffffL;
if(WaveDecoder.SIGNATURE == signature) result = new SampledPlayer(new WaveDecoder(), stream, true);
if(MIDIDecoder.SIGNATURE == signature) result = new SyntheticPlayer(new MIDIDecoder(), stream, true);
}
finally
{
if(result == null) stream.close();
}
if(result != null) return result;
}
throw new MediaException("Manager.createPlayer: невозможно создать проигрыватель.");
}
public Player createPlayer(DataSource source) throws IOException, MediaException {
throw new MediaException("Manager.createPlayer: эта реализация не поддерживает создание проигрывателей из DataSource.");
}
public Player createPlayer(InputStream stream, String contentType) throws IOException, MediaException {
long signature = (long) (new DataInputStream(stream)).readInt() & 0x00000000ffffffffL;
if(WaveDecoder.SIGNATURE == signature) return new SampledPlayer(new WaveDecoder(), stream, false);
if(MIDIDecoder.SIGNATURE == signature) return new SyntheticPlayer(new MIDIDecoder(), stream, false);
throw new MediaException("Manager.createPlayer: невозможно создать проигрыватель.");
}
public Connection openConnection(String url, int mode, boolean timeouts) throws IOException {
int localPort;
String address;
String loc = url.toLowerCase();
synchronized(screenSettings)
{
if(!firstConnectionOpened && loc.startsWith("sms://"))
{
MessageConnection ourMessageServer;
firstConnectionOpened = true;
InboundConnections.instance.registerLocalPort(InboundConnections.UDP, ClientMessageConnection.LOCAL_PORT);
(ourMessageServer = new ServerMessageConnection(
ClientMessageConnection.LOCAL_ADDRESS, ClientMessageConnection.LOCAL_PORT
)).setMessageListener(new DefaultMessageHandler(ourMessageServer));
}
}
label0:
{
if(loc.startsWith("sms://"))
{
if(!(address = url.substring("sms://".length())).startsWith(":")) return new ClientMessageConnection(url);
if((localPort = Integer.parseInt(address.substring(1))) < 0x0000 || localPort > 0xffff)
{
throw new NumberFormatException("Connector.open: номер порта выходит из диапазона.");
}
InboundConnections.instance.registerLocalPort(InboundConnections.UDP, localPort);
return new ServerMessageConnection(url, localPort);
}
if(loc.startsWith("file://"))
{
if(!(address = url.substring("file://".length())).startsWith("/")) url = "file://".concat(address = "/".concat(address));
if(address.indexOf("//") >= 0)
{
throw new IllegalArgumentException("Connector.open: аргумент url имеет неправильный формат.");
}
if(VFSConnection.isForbiddenPath(null, address))
{
throw new SecurityException("Connector.open: доступ к заданному объекту запрещён для протокола file.");
}
return new VFSConnection(url, null, address, mode);
}
if(loc.startsWith("resource://"))
{
if(mode != READ)
{
throw new IllegalArgumentException("Connector.open: аргумент mode может быть только READ для протокола resource.");
}
if(!(address = url.substring("resource://".length())).startsWith("/")) url = "resource://".concat(address = "/".concat(address));
if(address.indexOf("//") >= 0)
{
throw new IllegalArgumentException("Connector.open: аргумент url имеет неправильный формат.");
}
try
{
CloudFileSystem.instance.readAttributes("/res".concat(address), null);
}
catch(IOException e)
{
e.printRealStackTrace();
break label0;
}
return new ResourceConnection(url, address);
}
}
throw new ConnectionNotFoundException("Connector.open: соединение не найдено: ".concat(url));
}
public ImageDecoder openImageDecoder(InputStream stream) throws IOException {
long signature;
DataInputStream data;
signature = (long) (data = new DataInputStream(stream)).readUnsignedShort();
if(JPEGDecoder.SIGNATURE == signature) return new JPEGDecoder();
if(BMPDecoder.SIGNATURE == signature) return new BMPDecoder();
signature = signature << 8 | (long) data.readUnsignedByte();
if(GIFDecoder.SIGNATURE == signature) return new GIFDecoder();
signature = signature << 40 | (long) data.readUnsignedByte() << 32 | (long) data.readInt() & 0x00000000ffffffffL;
if(PNGDecoder.SIGNATURE == signature) return new PNGDecoder();
throw new InvalidDataFormatException("SystemManager.openImageDecoder: неизвестный формат изображения.");
}
public void commandAction(Command command, Displayable screen) {
SettingsForm[] settingsForms;
List screenList;
final Display display = super.getMainDisplay();
if(Array.findb(settingsForms = screenSettings, settingsForms.length - 1, screen) >= 0)
{
if(command == commandApply) settingApply((SettingsForm) screen);
display.setCurrent(getScreenSettingsList());
return;
}
if(screen == screenExitApplication)
{
if(command == commandYes)
{
applicationDisplay.applicationStop(true);
return;
}
if(command == commandNo) switchToApplicationDisplay();
return;
}
if(screen == (screenList = screenSettingsList))
{
if(command == List.SELECT_COMMAND)
{
int settingIndex = screenList.getSelectedIndex();
settingSelect(settingIndex, screenList.getString(settingIndex));
return;
}
if(command == commandBack) display.setCurrent(getScreenApplicationList());
return;
}
if(screen == (screenList = screenRecordsList))
{
if(command == commandClear)
{
display.setCurrent(getScreenRecordsClearConfirm());
return;
}
if(command == commandDelete)
{
display.setCurrent(getScreenRecordDeleteConfirm(screenList.getString(screenList.getSelectedIndex())));
return;
}
if(command == commandUpdate)
{
fillRecordsList(screenList);
return;
}
if(command == commandProperties)
{
display.setCurrent(getScreenRecordProperties(screenList.getString(screenList.getSelectedIndex())));
return;
}
if(command == commandBack) display.setCurrent(getScreenSettingsList());
return;
}
if(screen == screenRecordsClearConfirm)
{
if(command == commandYes)
{
final Runnable nextTask = new Runnable() {
public void run() {
display.setCurrent((SystemManager.this).getScreenRecordsList());
}
};
display.setCurrent(getScreenLongOperation("Очистка записей…"));
((Thread) (new Thread("Очистка записей…") {
public void run() {
String[] recordStores;
for(int i = (recordStores = RecordStore.listRecordStores()).length; i-- > 0; )
{
try
{
RecordStore.deleteRecordStore(recordStores[i]);
}
catch(RecordStoreException e)
{
e.printRealStackTrace();
}
}
try
{
sleep(1000L);
}
catch(InterruptedException e)
{
e.printRealStackTrace();
}
display.callSerially(nextTask);
}
})).start();
return;
}
if(command == commandNo) display.setCurrent(screenRecordsList);
return;
}
if(screen == screenRecordDeleteConfirm)
{
if(command == commandYes)
{
try
{
RecordStore.deleteRecordStore((screenList = screenRecordsList).getString(screenList.getSelectedIndex()));
fillRecordsList(screenList);
}
catch(RecordStoreException e)
{
e.printRealStackTrace();
fillRecordsList(screenList);
display.setCurrent(getScreenError("Ошибка возникла при удалении записи.\n\n".concat(e.getRealMessage())));
return;
}
}
display.setCurrent(screenRecordsList);
return;
}
if(screen == screenRecordProperties)
{
if(command == commandBack) display.setCurrent(screenRecordsList);
return;
}
if(screen == screenDeviceButtonsView)
{
if(command == commandBack) display.setCurrent(getScreenSettingsList());
return;
}
if(screen == screenAboutApplication || screen == screenAboutImplementation)
{
if(command == commandBack) display.setCurrent(getScreenApplicationList());
return;
}
if(screen == screenApplicationError)
{
if(command == commandExit) Run.instance.terminate();
return;
}
if(screen == (screenList = screenApplicationList))
{
if(command == commandLaunch)
{
String applicationClassName = applicationClassNames[screenList.getSelectedIndex()];
display.setCurrent(getScreenLongOperation("Приложение запускается…"));
clearFields();
prepareForApplicationLaunch(console);
applicationDisplay.applicationStart(applicationClassName);
return;
}
if(command == commandSettings)
{
display.setCurrent(getScreenSettingsList());
return;
}
if(command == commandAboutApplication)
{
display.setCurrent(getScreenAboutApplication());
return;
}
if(command == commandAboutImplementation)
{
display.setCurrent(getScreenAboutImplementation());
return;
}
if(command == commandExit) Run.instance.terminate();
}
}
public void commandAction(Command command, Item item) {
SettingsForm[] settingsForms;
Display display = super.getMainDisplay();
for(int i = (settingsForms = screenSettings).length; i-- > 0; )
{
SettingsForm screen;
if((screen = settingsForms[i]) == null) continue;
if(item == screen.getApplyButton())
{
settingApply(screen);
display.setCurrent(getScreenSettingsList());
break;
}
if(item == screen.getBackButton())
{
display.setCurrent(getScreenSettingsList());
break;
}
}
}
public void itemStateChanged(Item item) {
ButtonSet itemButtonSet;
ChoiceGroup itemChoiceGroup;
if(item == (itemChoiceGroup = itemKeyCodeSets))
{
int index;
if((index = itemChoiceGroup.getSelectedIndex()) > 0)
{
int[] keys = KEY_CODE_SETS[index].getKeyCodesAsArray();
SettingsForm screen;
for(int j = (screen = screenSettingKeyCodes).size() - 1, i = j; i-- > 0; j--) ((Input) screen.get(j)).setString(Integer.toString(keys[i]));
}
return;
}
if(item == (itemButtonSet = itemDeviceButtons))
{
int keyCode;
int deviceKey;
DeviceSettings settings = super.getSettings();
switch(deviceKey = itemButtonSet.getPressedButtonID())
{
case DeviceSettings.DEVICE_KEY_UP:
case DeviceSettings.DEVICE_KEY_DOWN:
case DeviceSettings.DEVICE_KEY_LEFT:
case DeviceSettings.DEVICE_KEY_RIGHT:
case DeviceSettings.DEVICE_KEY_SELECT:
case DeviceSettings.DEVICE_KEY_SOFT1:
case DeviceSettings.DEVICE_KEY_SOFT2:
case DeviceSettings.DEVICE_KEY_1:
case DeviceSettings.DEVICE_KEY_2:
case DeviceSettings.DEVICE_KEY_3:
case DeviceSettings.DEVICE_KEY_4:
case DeviceSettings.DEVICE_KEY_5:
case DeviceSettings.DEVICE_KEY_6:
case DeviceSettings.DEVICE_KEY_7:
case DeviceSettings.DEVICE_KEY_8:
case DeviceSettings.DEVICE_KEY_9:
case DeviceSettings.DEVICE_KEY_0:
case DeviceSettings.DEVICE_KEY_STAR:
itemKeyDescription.setText((new StringBuilder()).append(settings.getKeyName(keyCode = settings.getKeyCodeFor(deviceKey))).append("\nКод клавиши: ").append(keyCode).append(
"\nНазначение: посылает в приложение соответствующий код клавиши."
).toString());
break;
case DeviceSettings.DEVICE_KEY_POUND:
itemKeyDescription.setText((new StringBuilder()).append(settings.getKeyName(keyCode = settings.getKeyCodeFor(deviceKey))).append("\nКод клавиши: ").append(keyCode).append(
"\nНазначение: посылает в приложение соответствующий код клавиши.\n" +
"Примечание: эта клавиша позволяет полностью просмотреть выделенный элемент списка. Если на экране отображается стандартный список каких-либо элементов и среди них есть " +
"такие, которые заканчиваются на многоточие («…»), выделите такой элемент и нажмите эту клавишу. Пока вы её удерживаете, на экране отображается полный текст выделенного " +
"элемента, без многоточия."
).toString());
break;
case DeviceSettings.DEVICE_KEY_CONSOLE:
itemKeyDescription.setText("Вызов консоли\nНазначение: вызывает системную консоль (доступно только во время работы приложения).");
break;
case DeviceSettings.DEVICE_KEY_EXITAPP:
itemKeyDescription.setText("Выход из приложения\nНазначение: вызывает диалог выхода из приложения (доступно только во время работы приложения).");
break;
default:
return;
}
itemKeyEquivalent.setText(DeviceSettings.keyToString(settings.getKeyUsedAs(deviceKey)));
}
}
public void threadTerminated(Thread terminatedThread, Throwable exitThrowable) {
if(exitThrowable != null)
{
Display main = super.getMainDisplay();
Display curr = super.getCurrentDisplay();
RecordStore.closeAllRecordStores();
exitThrowable.printRealStackTrace();
getItemErrorInfo().setText((new StringBuilder()).append(exitThrowable.getRealMessage()).append("\n\n – ").append(exitThrowable.getClass().getCanonicalName()).toString());
main.setCurrent(getScreenApplicationError());
if(curr != main) super.setCurrentDisplay(main);
}
}
public final MIDletDisplay getApplicationDisplay() {
return applicationDisplay;
}
protected void showStartScreen(Display display) {
display.setCurrent(getScreenApplicationList());
}
protected void showConsoleScreen(Display display) {
Console console = this.console;
if(!consoleGreetingPrinted)
{
consoleGreetingPrinted = true;
console.println(
(new StringBuilder()).append("Добро пожаловать в ").append(console.getTitle()).append("!\nНаберите на консоли команду\n ?\nчтобы увидеть список доступных команд.").toString()
);
}
display.setCurrent(console);
}
protected void showExitAppScreen(Display display) {
display.setCurrent(getScreenExitApplication(), getScreenBackground());
}
protected void keyboardEvent(KeyboardEvent event) {
super.keyboardEvent(event);
if(super.getCurrentDisplay() instanceof MIDletDisplay && event.getAction() == KeyboardEvent.ACTION_KEY_PRESSED) switch(event.getKey())
{
case KeyboardEvent.KEY_F5:
if(!isKeyUsed(KeyboardEvent.KEY_F5)) imagesCommand.executeInBackground();
break;
case KeyboardEvent.KEY_F6:
if(!isKeyUsed(KeyboardEvent.KEY_F6)) soundsCommand.executeInBackground();
break;
}
}
protected void buildAuthorList(ManagerStringList authors) {
}
protected void buildLicenseList(ManagerStringList licenses) {
}
protected void buildSpecificationList(ManagerStringList specifications) {
}
protected void buildSettingList(ManagerSettingList settings) {
}
protected void settingSelected(int settingIndex, String settingName, Display display) {
}
protected void prepareForApplicationLaunch(Console console) {
}
protected String[] getSupportedContentTypes() {
return getSystemSupportedContentTypes();
}
protected String[] getSupportedProtocols() {
return getSystemSupportedProtocols();
}
protected MIDletDisplay createApplicationDisplay() {
return null;
}
protected final void returnToSettingsScreen() {
super.getMainDisplay().setCurrent(getScreenSettingsList());
}
final void switchToApplicationDisplay() {
super.setCurrentDisplay(applicationDisplay);
}
final void switchToSystemDisplay() {
super.setCurrentDisplay(super.getMainDisplay());
}
final List getScreenRecordsList() {
List result;
if((result = screenRecordsList) == null)
{
(result = screenRecordsList = new List("Записи", null, false, null, Choice.IMPLICIT, "(нет записей)", new String[0], null)).setCommandListener(this);
result.setSelectCommand(getCommandProperties());
result.addCommand(getCommandUpdate());
result.addCommand(getCommandBack());
}
fillRecordsList(result);
return result;
}
private void clearFields() {
Object[] array;
applicationClassNames = null;
itemKeyCodeSets = null;
itemDeviceButtons = null;
itemRecordProperties = null;
itemKeyDescription = null;
itemKeyEquivalent = null;
commandBack = null;
commandApply = null;
commandClear = null;
commandDelete = null;
commandLaunch = null;
commandUpdate = null;
commandSettings = null;
commandProperties = null;
commandAboutApplication = null;
commandAboutImplementation = null;
screenRecordsList = null;
screenSettingsList = null;
screenApplicationList = null;
screenAboutApplication = null;
screenAboutImplementation = null;
screenRecordProperties = null;
screenDeviceButtonsView = null;
screenError = null;
screenRecordsClearConfirm = null;
screenRecordDeleteConfirm = null;
screenSettingFonts = null;
screenSettingSystem = null;
screenSettingControls = null;
screenSettingKeyCodes = null;
screenLongOperation = null;
Array.fill(array = screenSettings, 0, array.length, null);
}
private void fillRecordsList(List list) {
int len;
int selected;
String[] records;
len = (records = RecordStore.listRecordStores()).length;
selected = list.getSelectedIndex();
list.deleteAll();
for(int i = 0; i < len; i++) list.append(records[i], null);
if(selected >= 0 && len > 0)
{
if(selected >= len) selected = len - 1;
list.setSelectedIndex(selected, true);
}
if(len > 0)
{
list.addCommand(getCommandClear());
list.addCommand(getCommandDelete());
list.addCommand(getCommandProperties());
return;
}
list.removeCommand(getCommandClear());
list.removeCommand(getCommandDelete());
list.removeCommand(getCommandProperties());
}
private void settingSelect(int settingIndex, String settingName) {
final Display display = super.getMainDisplay();
if(settingIndex == saveSettingsElementIndex)
{
final DeviceSettings settings = super.getSettings();
final Displayable nextScreen = getScreenApplicationList();
display.setCurrent(getScreenLongOperation("Сохранение настроек…"));
((Thread) (new Thread("Сохранение настроек…") {
public void run() {
settings.saveMIDletProperties();
try
{
sleep(1000L);
}
catch(InterruptedException e)
{
e.printRealStackTrace();
}
display.setCurrent(nextScreen);
}
})).start();
return;
}
switch(settingIndex)
{
case 0:
display.setCurrent(getScreenSettingControls());
break;
case 1:
display.setCurrent(getScreenSettingKeyCodes());
break;
case 2:
display.setCurrent(getScreenSettingFonts());
break;
case 3:
display.setCurrent(getScreenSettingSystem());
break;
case 4:
display.setCurrent(getScreenRecordsList());
break;
case 5:
display.setCurrent(getScreenDeviceButtonsView());
break;
default:
settingSelected(settingIndex, settingName, display);
break;
}
}
private void settingApply(SettingsForm settingForm) {
DeviceSettings settings = super.getSettings();
if(settingForm == screenSettingControls)
{
int[] deviceKeys = DEVICE_KEYS;
int[] keybrdKeys = KEYBOARD_KEYS;
for(int i = settingForm.size(); i-- > 0; )
{
int key;
if((key = keybrdKeys[((Choice) settingForm.get(i)).getSelectedIndex()]) != 0) settings.setKeyUsedAs(deviceKeys[i], key);
}
return;
}
if(settingForm == screenSettingKeyCodes)
{
int[] deviceKeys = DEVICE_KEYS;
for(int j = settingForm.size() - 1, i = j; i-- > 0; j--)
{
int keyCode;
try
{
keyCode = Integer.parseInt(((TextField) settingForm.get(j)).getString());
settings.setKeyCodeFor(deviceKeys[i], keyCode);
}
catch(NumberFormatException e)
{
}
}
return;
}
if(settingForm == screenSettingFonts)
{
int[] sizes = FONT_SIZES;
for(int i = settingForm.size(); i-- > 0; )
{
Choice list;
settings.setFont(i & 3, sizes[i >> 2], SystemFont.get((list = (Choice) settingForm.get(i)).getString(list.getSelectedIndex())));
}
return;
}
if(settingForm == screenSettingSystem)
{
Choice list;
settings.setMaximumFrequency(((Gauge) settingForm.get(0)).getValue());
settings.setEnableStackTrace((list = (Choice) settingForm.get(1)).isSelected(0));
settings.setKeyRepeatedEvent(list.isSelected(1));
}
}
private boolean isKeyUsed(int key) {
int[] deviceKeys;
DeviceSettings settings = super.getSettings();
for(int i = (deviceKeys = DEVICE_KEYS).length; i-- > 0; ) if(settings.getKeyUsedAs(deviceKeys[i]) == key) return true;
return false;
}
private String[] buildApplicationList(List dest) {
int len = 0;
String[] attributes;
String[] result = new String[1];
DeviceSettings settings = super.getSettings();
dest.setTitle(settings.getMIDletProperty("MIDlet-Name"));
dest.deleteAll();
for(int i = 0; (attributes = settings.getMIDletAttributes("MIDlet-".concat(Integer.toString(i + 1)))) != null && attributes.length >= 3; i++)
{
Image icon = null;
String appName = attributes[MIDLET_NAME];
String iconName = attributes[MIDLET_ICON];
String className = attributes[MIDLET_CLASS];
if(appName == null || className == null || className.length() <= 0) continue;
if(iconName != null && iconName.length() > 0)
{
if(iconName.charAt(0) == '/') iconName = iconName.substring(1);
icon = loadImageFromFile("/res/".concat(iconName));
}
if(len == result.length) Array.copy(result, 0, result = new String[(len << 1) + 1], 0, len);
dest.append(appName, icon);
result[len++] = className;
}
if(len != result.length) Array.copy(result, 0, result = new String[len], 0, len);
return result;
}
private String[] getSystemSupportedContentTypes() {
return new String[] { MIDIDecoder.MIME_TYPE, WaveDecoder.MIME_TYPE };
}
private String[] getSystemSupportedProtocols() {
return new String[] { "file", "resource" };
}
private ChoiceGroup getItemKeyCodeSets() {
ChoiceGroup result;
if((result = itemKeyCodeSets) == null)
{
int len;
String[] names;
KeyCodeSet[] sets;
names = new String[len = (sets = KEY_CODE_SETS).length];
for(int i = len; i-- > 0; names[i] = sets[i].getName());
(result = itemKeyCodeSets = new ChoiceGroup("Предустановки", Choice.POPUP, names, null)).setLayout(Item.LAYOUT_EXPAND);
}
return result;
}
private ButtonSet getItemDeviceButtons() {
ButtonSet result;
if((result = itemDeviceButtons) == null)
{
Image background;
if((background = loadImageFromFile("/ui/keypad.png")) == null)
{
throw new RuntimeException("SystemManager.getItemDeviceButtons: ошибка при загрузке /ui/keypad.png.");
}
(result = itemDeviceButtons = new ButtonSet(null, background)).setLayout(Item.LAYOUT_CENTER | Item.LAYOUT_NEWLINE_AFTER);
try
{
HandleInputStream input;
(input = new FileInputStream("/ui/keypad.dat")).checkOpenError();
try
{
for(DataInputStream stream = new DataInputStream(input); stream.available() >= 5; )
{
int buttonID = stream.readUnsignedByte();
int left = stream.readUnsignedByte();
int top = stream.readUnsignedByte();
int width = stream.readUnsignedByte();
int height = stream.readUnsignedByte();
result.setButton(buttonID, left, top, width, height);
}
}
finally
{
input.close();
}
}
catch(IOException e)
{
e.printRealStackTrace();
throw new RuntimeException("SystemManager.getItemDeviceButtons: ошибка при загрузке /ui/keypad.dat.");
}
}
return result;
}
private StringItem getItemRecordProperties() {
StringItem result;
if((result = itemRecordProperties) == null)
{
(result = itemRecordProperties = new StringItem(null, null)).setLayout(Item.LAYOUT_EXPAND);
result.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM));
}
return result;
}
private StringItem getItemKeyDescription() {
StringItem result;
if((result = itemKeyDescription) == null)
{
(result = itemKeyDescription = new StringItem(
"Описание", "Укажите клавишу на этой виртуальной клавиатуре, чтобы увидеть её описание здесь."
)).setLayout(Item.LAYOUT_EXPAND | Item.LAYOUT_NEWLINE_AFTER);
}
return result;
}
private StringItem getItemKeyEquivalent() {
StringItem result;
if((result = itemKeyEquivalent) == null)
{
(result = itemKeyEquivalent = new StringItem("Эквивалентная клавиша", "(Клавиша не выбрана)")).setLayout(Item.LAYOUT_EXPAND | Item.LAYOUT_NEWLINE_AFTER);
}
return result;
}
private StringItem getItemErrorInfo() {
StringItem result;
if((result = itemErrorInfo) == null)
{
(result = itemErrorInfo = new StringItem(null, null)).setLayout(Item.LAYOUT_EXPAND);
result.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL));
}
return result;
}
private Command getCommandNo() {
Command result;
if((result = commandNo) == null) result = commandNo = new Command("Нет", Command.BACK, 0);
return result;
}
private Command getCommandYes() {
Command result;
if((result = commandYes) == null) result = commandYes = new Command("Да", Command.OK, 0);
return result;
}
private Command getCommandExit() {
Command result;
if((result = commandExit) == null) result = commandExit = new Command("Выход", Command.EXIT, 0);
return result;
}
private Command getCommandBack() {
Command result;
if((result = commandBack) == null) result = commandBack = new Command("Назад", Command.BACK, 0);
return result;
}
private Command getCommandApply() {
Command result;
if((result = commandApply) == null) result = commandApply = new Command("Применить", Command.SCREEN, Integer.MAX_VALUE);
return result;
}
private Command getCommandClear() {
Command result;
if((result = commandClear) == null) result = commandClear = new Command("Удалить все", Command.SCREEN, 3);
return result;
}
private Command getCommandDelete() {
Command result;
if((result = commandDelete) == null) result = commandDelete = new Command("Удалить", Command.SCREEN, 2);
return result;
}
private Command getCommandLaunch() {
Command result;
if((result = commandLaunch) == null) result = commandLaunch = new Command("Запустить", Command.OK, 0);
return result;
}
private Command getCommandUpdate() {
Command result;
if((result = commandUpdate) == null) result = commandUpdate = new Command("Обновить", Command.SCREEN, 1);
return result;
}
private Command getCommandSettings() {
Command result;
if((result = commandSettings) == null) result = commandSettings = new Command("Настройки…", Command.SCREEN, 1);
return result;
}
private Command getCommandProperties() {
Command result;
if((result = commandProperties) == null) result = commandProperties = new Command("Свойства", Command.OK, 0);
return result;
}
private Command getCommandAboutApplication() {
Command result;
if((result = commandAboutApplication) == null) result = commandAboutApplication = new Command("О приложении…", Command.SCREEN, 2);
return result;
}
private Command getCommandAboutImplementation() {
Command result;
if((result = commandAboutImplementation) == null) result = commandAboutImplementation = new Command("О реализации…", Command.SCREEN, 3);
return result;
}
private List getScreenSettingsList() {
List result;
if((result = screenSettingsList) == null)
{
SystemSettingList settings;
Ticker ticker = new Ticker("Это настройки приложения. ВАЖНО: не забудьте сохранить настройки. Настройки шрифтов применяются только после перезапуска программы.");
(result = screenSettingsList = settings = new SystemSettingList("Настройки", ticker, false, null, null)).setCommandListener(this);
settings.addCommand(getCommandBack());
settings.append("Управление", null);
settings.append("Коды клавиш", null);
settings.append("Шрифты", null);
settings.append("Система", null);
settings.append("Записи", null);
settings.append("Показать клавиатуру", null);
buildSettingList(settings);
saveSettingsElementIndex = settings.append("Сохранить настройки", null);
}
return result;
}
private List getScreenApplicationList() {
List result;
if((result = screenApplicationList) == null)
{
(result = screenApplicationList = new List(null, Choice.IMPLICIT)).setCommandListener(this);
applicationClassNames = buildApplicationList(result);
result.setTicker(new Ticker("Выберите приложение и нажмите кнопку «Запустить». Если хотите настроить приложение, то сперва нажмите кнопку «Меню» и выберите «Настройки…»."));
result.addCommand(getCommandExit());
result.addCommand(getCommandSettings());
result.addCommand(getCommandAboutApplication());
result.addCommand(getCommandAboutImplementation());
result.setSelectCommand(getCommandLaunch());
}
return result;
}
private Form getScreenApplicationError() {
Form result;
if((result = screenApplicationError) == null)
{
(result = screenApplicationError = new Form("Ошибка приложения", new Item[] { getItemErrorInfo() })).setCommandListener(this);
result.addCommand(getCommandExit());
result.getHorizontalScrollBar().hide();
}
return result;
}
private Form getScreenAboutApplication() {
Form result;
if((result = screenAboutApplication) == null)
{
Item[] items;
String[] classes;
DeviceSettings settings = super.getSettings();
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
String site1 = settings.getMIDletProperty("MIDlet-Info-URL");
String site2 = settings.getMIDletProperty("SiteURL");
ImageItem icon = new ImageItem(null, loadApplicationIcon(), Item.LAYOUT_VCENTER, null);
Spacer space = new Spacer(4, 1);
StringItem name = new StringItem(null, settings.getMIDletProperty("MIDlet-Name"));
StringItem version = new StringItem("Версия", "\u0020".concat(settings.getMIDletProperty("MIDlet-Version")));
StringItem vendor = new StringItem("Поставщик", "\u0020".concat(settings.getMIDletProperty("MIDlet-Vendor")));
StringItem config = new StringItem("Конфигурация", "\u0020".concat(settings.getMIDletProperty("MicroEdition-Configuration")));
StringItem profile = new StringItem("Профиль", "\u0020".concat(settings.getMIDletProperty("MicroEdition-Profile")));
SystemStringItem midlets = new SystemStringItem("Класс мидлета");
StringItem internet =
site1 != null && site1.length() > 0 ? new StringItem("Интернет", "\u0020".concat(site1)) :
site2 != null && site2.length() > 0 ? new StringItem("Интернет", "\u0020".concat(site2)) :
null
;
name.setLayout(Item.LAYOUT_EXPAND | Item.LAYOUT_VCENTER | Item.LAYOUT_NEWLINE_AFTER);
name.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM));
for(int len = (classes = applicationClassNames).length, i = 0; i < len; i++) midlets.add(classes[i]);
if(internet == null)
{
items = new Item[] { icon, space, name, version, vendor, config, profile, midlets };
} else
{
items = new Item[] { icon, space, name, version, vendor, internet, config, profile, midlets };
}
for(int i = items.length; i-- > 0; )
{
Item item;
if((item = items[i]) != name && item instanceof StringItem)
{
item.setLayout(Item.LAYOUT_EXPAND | Item.LAYOUT_NEWLINE_AFTER);
((StringItem) item).setFont(font);
}
}
(result = screenAboutApplication = new Form("О приложении", items)).setCommandListener(this);
result.addCommand(getCommandBack());
result.getHorizontalScrollBar().hide();
}
return result;
}
private Form getScreenAboutImplementation() {
Form result;
if((result = screenAboutImplementation) == null)
{
StringItem[] items;
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
String softwareVersion = System.getProperty("software.version");
String configuration = System.getProperty("microedition.configuration");
String profiles = System.getProperty("microedition.profiles");
StringItem version = new StringItem(
"Информация о версии",
(new StringBuilder()).append(" Версия: ").append(softwareVersion).append("\n Конфигурация: ").append(configuration).append("\n Профили: ").append(profiles).toString()
);
StringItem classList = new StringItem(
"Важные классы",
(new StringBuilder()).append(' ').append(super.getSettings().getClass().getCanonicalName()).append("\n ").append(super.getClass().getCanonicalName()).toString()
);
SystemStringItem specList = new SystemStringItem("Поддерживаемые спецификации");
SystemStringItem authorList = new SystemStringItem("Авторы");
SystemStringItem licenseList = new SystemStringItem("Лицензии");
for(int i = (items = new StringItem[] { version, specList, classList, authorList, licenseList }).length; i-- > 0; )
{
StringItem item;
(item = items[i]).setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_EXPAND);
item.setFont(font);
}
specList.add("WMA 1.1 (JSR-120)");
specList.add("MMAPI 1.2 (JSR-135)");
specList.add("File connection (JSR-75)");
specList.add("Nokia UI API 1.1");
specList.add("Samsung API");
buildSpecificationList(specList);
authorList.add("Малик Разработчик (malik-elaborarer@protonmail.com)");
buildAuthorList(authorList);
licenseList.add("GNU LGPL 3");
licenseList.add("ZLib");
buildLicenseList(licenseList);
licenseList.add("Обратитесь к исходному коду за подробностями.");
(result = screenAboutImplementation = new Form("О реализации", items)).setCommandListener(this);
result.addCommand(getCommandBack());
result.getHorizontalScrollBar().hide();
}
return result;
}
private Form getScreenRecordProperties(String recordStoreName) {
Form result;
if((result = screenRecordProperties) == null)
{
(result = screenRecordProperties = new Form(null, new Item[] { getItemRecordProperties() })).setCommandListener(this);
result.addCommand(getCommandBack());
result.getHorizontalScrollBar().hide();
}
result.setTitle("Свойства: ".concat(recordStoreName));
try
{
RecordStore store = RecordStore.openRecordStore(recordStoreName, false);
try
{
Calendar calendar;
(calendar = Calendar.getInstance()).setTime(new Date(store.getLastModified()));
itemRecordProperties.setText((new StringBuilder()).
append(" Название: ").append(recordStoreName).append("\n Размер: ").append(store.getSize()).append(" байт\n Количество подзаписей: ").append(store.getNumRecords()).
append("\n Последнее изменение: ").append(calendarToString(calendar)).append("\n Количество изменений: ").append(store.getVersion()).
toString());
}
finally
{
store.closeRecordStore();
}
}
catch(RecordStoreException e)
{
e.printRealStackTrace();
itemRecordProperties.setText("Ошибка возникла при чтении свойств записи.\n\n".concat(e.getRealMessage()));
}
return result;
}
private Form getScreenDeviceButtonsView() {
Form result;
if((result = screenDeviceButtonsView) == null)
{
try
{
(result = screenDeviceButtonsView = new Form("Клавиатура", new Item[] { getItemDeviceButtons(), getItemKeyDescription(), getItemKeyEquivalent() })).setCommandListener(this);
result.setItemStateListener(this);
result.addCommand(getCommandBack());
result.getHorizontalScrollBar().hide();
}
catch(RuntimeException e)
{
threadTerminated(Thread.currentThread(), e);
throw e;
}
}
return result;
}
private Alert getScreenError(String message) {
Alert result;
if((result = screenError) == null) result = screenError = new Alert(null, null, null, AlertType.ERROR);
result.setString(message);
return result;
}
private Alert getScreenExitApplication() {
Alert result;
if((result = screenExitApplication) == null)
{
String applicationName = super.getSettings().getMIDletProperty("MIDlet-Name");
(result = screenExitApplication = new Alert(
null, (new StringBuilder()).append("Выйти из приложения ").append(applicationName).append("? Все несохранённые данные будут утеряны.").toString(), null, AlertType.CONFIRMATION
)).setCommandListener(this);
result.addCommand(getCommandYes());
result.addCommand(getCommandNo());
}
return result;
}
private Alert getScreenRecordsClearConfirm() {
Alert result;
if((result = screenRecordsClearConfirm) == null)
{
(result = screenRecordsClearConfirm = new Alert(
null, "Удаление всех записей приведёт приложение к состоянию, в котором оно находилось сразу после установки. Удалить все записи?", null, AlertType.CONFIRMATION
)).setCommandListener(this);
result.addCommand(getCommandYes());
result.addCommand(getCommandNo());
}
return result;
}
private Alert getScreenRecordDeleteConfirm(String recordStoreName) {
Alert result;
if((result = screenRecordDeleteConfirm) == null)
{
(result = screenRecordDeleteConfirm = new Alert(null, null, null, AlertType.WARNING)).setCommandListener(this);
result.addCommand(getCommandYes());
result.addCommand(getCommandNo());
}
result.setString((new StringBuilder()).
append("Осторожно: удаление одной записи может привести к ошибкам в работе приложения. Удаляйте записи только если уверены, что всё делаете правильно. Удалить запись ").
append(recordStoreName).append('?').
toString());
return result;
}
private Displayable getScreenBackground() {
Displayable result;
if((result = screenBackground) == null) result = screenBackground = new BlackScreen();
return result;
}
private SettingsForm getScreenSettingFonts() {
int[] sizes;
DeviceSettings proxy;
SettingsForm result;
if((result = screenSettingFonts) == null)
{
int len;
String[] fontTypes = new String[] {
"Мелкий нормальный", "Мелкий жирный", "Мелкий курсив", "Мелкий жирный курсив",
"Средний нормальный", "Средний жирный", "Средний курсив", "Средний жирный курсив",
"Крупный нормальный", "Крупный жирный", "Крупный курсив", "Крупный жирный курсив"
};
ChoiceGroup[] items = new ChoiceGroup[len = fontTypes.length];
for(int i = len; i-- > 0; )
{
ChoiceGroup list;
items[i] = list = new ChoiceGroup(fontTypes[i], Choice.POPUP);
list.setLayout(Item.LAYOUT_2 | Item.LAYOUT_EXPAND);
list.setPreferredSize(150, -1);
for(Enumeration e = SystemFont.systemFonts(); e.hasMoreElements(); )
{
SystemFont sysFont;
Font midpFont = Font.getFont(sysFont = (SystemFont) e.nextElement(), 0, 0, 0);
list.setFont(list.append(sysFont.getName(), null), midpFont);
}
}
(result = screenSettings[2] = screenSettingFonts = new SettingsForm("Шрифты", items)).setCommandListener(this);
result.setButtonListener(this);
result.setHelpContents(
"Здесь можно задать шрифты, которые приложение будет использовать для вывода текста.\nНастройки шрифтов вступят в силу только после перезапуска программы. " +
"До перезапуска программы надписи на элементах могут быть выполнены не тем шрифтом, что был задан здесь."
);
result.addCommand(getCommandBack());
result.addCommand(getCommandApply());
result.getHorizontalScrollBar().hide();
}
sizes = FONT_SIZES;
proxy = super.getSettings();
for(int i = result.size(); i-- > 0; )
{
Choice list;
(list = (Choice) result.get(i)).setSelectedIndex(indexOfString(list, proxy.getFont(i & 3, sizes[i >> 2]).getName()), true);
}
return result;
}
private SettingsForm getScreenSettingSystem() {
Choice list;
DeviceSettings proxy;
SettingsForm result;
if((result = screenSettingSystem) == null)
{
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
Gauge frequency = new Gauge("Максимальная частота кадров в секунду", true, 99, 0);
ChoiceGroup system = new ChoiceGroup("Поведение системы", Choice.MULTIPLE, new String[] {
"Трассировка стака в исключениях\n\n" +
"Состояние по умолчанию: включено\n" +
"Отключите эту опцию, если приложение работает с ошибками и генерирует много исключений, увеличивая размер файла /err.txt. " +
"Кроме того, отключение этой опции может повысить быстродействие приложения. " +
"В противном случае эту опцию рекомендуется включить (для отслеживания ошибок в программе).",
"Вызов метода Canvas.keyRepeated(int)\n\n" +
"Состояние по умолчанию: отключено\n" +
"Изменение состояния этого флага может привести к изменению поведения приложения в тот момент, когда вы удерживаете нажатой какую-либо клавишу. " +
"Установите или снимите этот флаг в соответствии с вашими предпочтениями."
}, null);
frequency.setLayout(Item.LAYOUT_EXPAND);
system.setLayout(Item.LAYOUT_EXPAND);
for(int i = system.size(); i-- > 0; system.setFont(i, font));
(result = screenSettings[3] = screenSettingSystem = new SettingsForm("Система", new Item[] { frequency, system })).setCommandListener(this);
result.setButtonListener(this);
result.setHelpContents(
"Здесь можно настроить максимальную частоту обновления экрана и поведение системы.\nРекомендуемый максимум частоты – 25 кадров в секунду. Большие значения могут привести к " +
"«подвисанию» программы и пропуску некоторых кадров. Проверьте также максимум кадров в секунду в настройках самого Малик Эмулятора.\nВ опциях поведения системы выберите опцию, " +
"нажмите и удерживайте клавишу #, чтобы увидеть подробное описание выбранной опции."
);
result.addCommand(getCommandBack());
result.addCommand(getCommandApply());
result.getHorizontalScrollBar().hide();
}
proxy = super.getSettings();
((Gauge) result.get(0)).setValue(proxy.getMaximumFrequency());
(list = (Choice) result.get(1)).setSelectedIndex(0, proxy.isEnableStackTrace());
list.setSelectedIndex(1, proxy.isKeyRepeatedEvent());
return result;
}
private SettingsForm getScreenSettingControls() {
int len;
int[] keys;
DeviceSettings proxy;
SettingsForm result;
len = (keys = DEVICE_KEYS).length;
if((result = screenSettingControls) == null)
{
ChoiceGroup[] items = new ChoiceGroup[len];
for(int i = len; i-- > 0; )
{
ChoiceGroup list;
fillKeysList(items[i] = list = new ChoiceGroup(deviceKeyToString(keys[i]), Choice.POPUP));
list.setLayout(Item.LAYOUT_2 | Item.LAYOUT_EXPAND);
list.setPreferredSize(150, -1);
}
(result = screenSettings[0] = screenSettingControls = new SettingsForm("Управление", items)).setCommandListener(this);
result.setButtonListener(this);
result.setHelpContents(
"Здесь можно задать соответствие между клавишами виртуального устройства и клавишами компьютера.\nВАЖНО: следите, чтобы в разных полях были разные названия клавиш компьютера, " +
"так как программа этого не проверяет.\nРасшифровка непонятных названий клавиш компьютера:\n UP – \u2191\n DOWN – \u2193\n LEFT – \u2190\n RIGHT – \u2192\n NUM_PLUS – Num +\n" +
" NUM_MINUS – Num -\n NUM_STAR – Num *\n NUM_DIVIDE – Num /\n NUM_DECIMAL – Num .\nОпция «Свои настройки» не изменяет заданную клавишу компьютера при нажатии кнопки " +
"«Применить», оставляя раннее заданную клавишу. Эта опция была специально добавлена на случай, когда файл настроек /midlet.properties редактировался вручную."
);
result.addCommand(getCommandBack());
result.addCommand(getCommandApply());
result.getHorizontalScrollBar().hide();
}
proxy = super.getSettings();
for(int i = len; i-- > 0; ) ((Choice) result.get(i)).setSelectedIndex(indexOfKey(proxy.getKeyUsedAs(keys[i])), true);
return result;
}
private SettingsForm getScreenSettingKeyCodes() {
int[] keys = DEVICE_KEYS;
SettingsForm result;
DeviceSettings proxy = super.getSettings();
if((result = screenSettingKeyCodes) == null)
{
Item[] items;
(items = new Item[8])[0] = getItemKeyCodeSets();
for(int j = items.length - 1, i = j; i-- > 0; j--)
{
TextField field;
items[j] = field = new TextField(proxy.getKeyName(proxy.getKeyCodeFor(keys[i])), null, 11, Input.NUMERIC);
field.setLayout(Item.LAYOUT_2 | Item.LAYOUT_EXPAND);
field.setPreferredSize(150, -1);
}
(result = screenSettings[1] = screenSettingKeyCodes = new SettingsForm("Коды клавиш", items)).setCommandListener(this);
result.setItemStateListener(this);
result.setButtonListener(this);
result.setHelpContents(
"Здесь можно задать коды тех клавиш, которые не были предусмотрены спецификацией MIDP, в результате чего коды этих клавиш стали зависимыми от конкретных моделей устройств. " +
"Особенно это касается тех приложений, которые работают только на устройствах определённых моделей. Вы можете задать особые числовые коды для клавиш или выбрать предустановленные " +
"коды клавиш для некоторых моделей устройств."
);
result.addCommand(getCommandBack());
result.addCommand(getCommandApply());
result.getHorizontalScrollBar().hide();
}
for(int j = result.size() - 1, i = j; i-- > 0; j--) ((Input) result.get(j)).setString(Integer.toString(proxy.getKeyCodeFor(keys[i])));
return result;
}
private SurfaceTextViewer getScreenLongOperation(String message) {
SurfaceTextViewer result;
if((result = screenLongOperation) == null) (result = screenLongOperation = new SurfaceTextViewer(null, Font.getDefaultFont())).getScrollBar().hide();
result.setText(message);
return result;
}
}
final class SystemStringItem extends StringItem implements ManagerStringList
{
public SystemStringItem(String label) {
super(label, null);
}
public void add(String string) {
String text;
if(string == null) return;
if((text = getText()) == null) text = "";
setText(text.concat("\n ".concat(string)));
}
}
final class SystemSettingList extends List implements ManagerSettingList
{
public SystemSettingList(String title, Ticker ticker, boolean fullScreen, ScrollBarStyle style, String emptyLabel) {
super(title, ticker, fullScreen, style, IMPLICIT, emptyLabel, new String[0], null);
}
public int add(String settingName) {
return append(settingName, null);
}
public int add(String settingName, Image settingIcon) {
return append(settingName, settingIcon);
}
}
final class BlackScreen extends Canvas
{
public BlackScreen() {
super(null, null, true);
}
protected void paint(Graphics render) {
render.setColor(0x000000);
render.fillRect(0, 0, super.getWidth(), super.getHeight());
}
}
final class DefaultMessageHandler extends Object implements MessageListener, Runnable
{
private final MessageConnection connection;
public DefaultMessageHandler(MessageConnection connection) {
this.connection = connection;
}
public void notifyIncomingMessage(MessageConnection connection) {
if(connection == this.connection) Run.instance.request(this);
}
public void run() {
String address;
Message message;
try
{
message = connection.receive();
}
catch(IOException e)
{
e.printRealStackTrace();
return;
}
address = message.getAddress();
if(message instanceof TextMessage)
{
String text = ((TextMessage) message).getPayloadText();
System.out.println((new StringBuilder()).
append("Приложение отправило на адрес ").append(address == null || address.length() <= 0 ? "<не указан>" : address).append(" сообщение с текстом:\n").
append(text == null || text.length() <= 0 ? "<нет содержимого>\n" : text.concat("\n")).
toString());
return;
}
if(message instanceof BinaryMessage)
{
byte[] data = ((BinaryMessage) message).getPayloadData();
System.out.println((new StringBuilder()).
append("Приложение отправило на адрес ").append(address == null || address.length() <= 0 ? "<не указан>" : address).append(" двоичное сообщение длиной ").
append(data == null ? 0 : data.length).append(" байт.").
toString());
}
}
}
final class HideForegroundScreenConsoleCommand extends ConsoleCommand
{
private final SystemManager manager;
public HideForegroundScreenConsoleCommand(SystemManager manager) {
super("фон");
this.manager = manager;
}
protected void execute(String[] arguments, Console console) {
SystemManager manager = this.manager;
Display display = manager.getApplicationDisplay();
if(display.getForeground() instanceof SurfaceScreen)
{
console.println("Любите красить пасхальные яйца?\nФоновый экран мидлета, наверное, уже ничем не перекрыт.");
} else
{
console.println("Любите красить пасхальные яйца?");
}
display.hideForeground();
if(arguments != null && arguments.length > 0)
{
manager.setCurrentDisplay(display);
}
}
}
abstract class BackgroundConsoleCommand extends ConsoleCommand
{
protected BackgroundConsoleCommand(String name) {
super(name);
}
protected abstract void execute(String[] arguments, Console console);
protected abstract void executeInBackground();
}
abstract class SearchConsoleCommand extends BackgroundConsoleCommand implements Runnable
{
private static final int SEARCH = 1;
private static final int CANCELLED = 2;
private static final int INITIALIZED = 3;
private static final int UNINITIALIZED = 0;
private boolean calledFromConsole;
private int state;
protected final SystemManager manager;
protected SearchConsoleCommand(String name, SystemManager manager) {
super(name);
this.manager = manager;
}
public void run() {
switch(state)
{
case SEARCH:
state = INITIALIZED;
showFoundScreen(DeviceManager.getInstance().getMainDisplay());
manager.switchToSystemDisplay();
break;
case CANCELLED:
state = UNINITIALIZED;
break;
}
}
protected abstract void searchProcess();
protected abstract void showProgressScreen(Display display);
protected abstract void showFoundScreen(Display display);
protected void execute(String[] arguments, Console console) {
calledFromConsole = true;
startSearchProcess();
}
protected void executeInBackground() {
calledFromConsole = false;
startSearchProcess();
}
protected final void cancelSearchProcess() {
if(state == SEARCH)
{
state = CANCELLED;
returnToSystem();
}
}
protected final void returnToSystem() {
if(calledFromConsole)
{
DeviceManager.getInstance().getMainDisplay().setCurrent(manager.console);
return;
}
manager.switchToApplicationDisplay();
}
private void startSearchProcess() {
int s = state;
state = SEARCH;
if(calledFromConsole) showProgressScreen(DeviceManager.getInstance().getMainDisplay());
if(s == CANCELLED || s == SEARCH) return;
((Thread) (new Thread() {
public void run() {
SearchConsoleCommand parent;
(parent = SearchConsoleCommand.this).searchProcess();
DeviceManager.getInstance().getMainDisplay().callSerially(parent);
}
})).start();
}
}
final class SoundsSearchConsoleCommand extends SearchConsoleCommand implements PlayerListener, CommandListener, ItemCommandListener, ItemStateListener
{
private static final int GLYPH_COLOR;
static {
GLYPH_COLOR = RasterCanvas.getSystemColor(0x24);
}
private boolean delay;
private int current;
private CustomPlayer[] sounds;
private Image imagePrev;
private Image imageNext;
private Image imagePlay;
private Image imagePause;
private Command commandSaveAction;
private Command commandCancel;
private Command commandSelect;
private Command commandSave;
private Command commandBack;
private Gauge itemVolumeBar;
private Gauge itemProgressBar;
private StringItem itemSoundNum;
private ImageItem itemSoundPrev;
private ImageItem itemSoundNext;
private ImageItem itemSoundPlay;
private TextField itemFileName;
private Alert screenProgress;
private Form screenSounds;
private Form screenEmpty;
private Form screenSave;
public SoundsSearchConsoleCommand(SystemManager manager) {
super("звуки", manager);
}
public void playerUpdate(Player player, String event, Object data) {
Player[] found;
if((found = sounds) != null && current == Array.findf(found, 0, player)) updateScreenSounds();
}
public void commandAction(Command command, Displayable screen) {
int index;
CustomPlayer[] found;
if(screen == screenSounds)
{
if(command == commandSave)
{
if((found = sounds) != null && (index = current) >= 0 && index < found.length)
{
CustomPlayer player;
if((player = found[index]) instanceof SyntheticPlayer)
{
getItemFileName().setString("/имя.mid");
}
else if(player instanceof SampledPlayer)
{
getItemFileName().setString("/имя.wav");
}
else
{
getItemFileName().setString("/имя");
}
}
DeviceManager.getInstance().getMainDisplay().setCurrent(getScreenSave());
return;
}
if(command == commandBack)
{
for(int i = (found = sounds) == null ? 0 : found.length; i-- > 0; )
{
CustomPlayer player;
if((player = found[i]).getState() == Player.CLOSED) continue;
try
{
player.removePlayerListener(this);
}
catch(IllegalStateException e)
{
e.printRealStackTrace();
}
}
sounds = null;
returnToSystem();
}
return;
}
if(screen == screenSave)
{
if(command == commandSaveAction && (found = sounds) != null && (index = current) >= 0 && index < found.length)
{
final String fileName = getItemFileName().getString();
final CustomPlayer player = found[index];
((Thread) (new Thread("Сохранение звука") {
public void run() {
String destFileName = fileName;
CustomPlayer destPlayer = player;
System.out.println((new StringBuilder()).append("Сохранение звука в ").append(destFileName).append(" …").toString());
try
{
OutputStream stream;
OutputAdapter adapter;
FileConnection connection;
if(destPlayer instanceof SyntheticPlayer)
{
SyntheticSoundEncoder encoder;
SyntheticSoundDecoder decoder = ((SyntheticPlayer) destPlayer).getDecoder();
(encoder = new MIDIEncoder()).setMessages(decoder.getMessages());
adapter = encoder;
}
else if(destPlayer instanceof SampledPlayer)
{
SampledSoundEncoder encoder;
SampledSoundDecoder decoder = ((SampledPlayer) destPlayer).getDecoder();
(encoder = new WaveEncoder()).setSamples(decoder.getChannels(), decoder.getSamplesPerSecond(), decoder.getSamples());
adapter = encoder;
}
else
{
adapter = null;
}
connection = (FileConnection) Connector.open("file://".concat(destFileName));
try
{
if(connection.exists()) connection.delete();
connection.create();
stream = connection.openOutputStream();
try
{
adapter.saveToOutputStream(stream);
}
finally
{
stream.close();
}
}
finally
{
connection.close();
}
System.out.println((new StringBuilder()).append("Звук успешно сохранён в ").append(destFileName).append('.').toString());
}
catch(Exception e)
{
System.out.println((new StringBuilder()).append("Ошибка возникла при сохранении звука в ").append(destFileName).append('.').toString());
e.printRealStackTrace();
}
}
})).start();
}
DeviceManager.getInstance().getMainDisplay().setCurrent(getScreenSounds());
return;
}
if(screen == screenProgress && command == commandCancel)
{
cancelSearchProcess();
return;
}
if(screen == screenEmpty && command == commandBack) returnToSystem();
}
public void commandAction(Command command, Item item) {
int len;
CustomPlayer[] found;
if((found = sounds) == null || (len = found.length) <= 0) return;
if(item == itemSoundPrev)
{
current = current == 0 ? len - 1 : current - 1;
updateScreenSounds();
return;
}
if(item == itemSoundNext)
{
current = current == len - 1 ? 0 : current + 1;
updateScreenSounds();
return;
}
if(item == itemSoundPlay)
{
try
{
CustomPlayer player;
if((player = found[current]).getState() == Player.STARTED)
{
player.stop();
} else
{
player.start();
}
}
catch(MediaException e)
{
e.printRealStackTrace();
}
updateScreenSounds();
}
}
public void itemStateChanged(Item item) {
Gauge itemGauge;
if(item == (itemGauge = itemVolumeBar))
{
int index;
CustomPlayer[] found;
if((found = sounds) != null && (index = current) >= 0 && index < found.length)
{
VolumeControl volume;
(volume = (VolumeControl) found[index].getControl("VolumeControl")).setMute(false);
volume.setLevel(itemGauge.getValue() * 10);
}
}
}
protected void searchProcess() {
int len;
int count;
Object[] memory = Memory.getAllObjects();
Gauge progress = getItemProgressBar();
Vector players = new Vector();
if((len = memory != null ? memory.length : 0) >= 100) progress.setMaxValue(len / 100);
for(int i = 0; i < len; i++)
{
Object curr;
if(i % 100 == 0)
{
progress.setValue(i / 100);
if(delay)
{
try
{
Thread.sleep(100L);
}
catch(InterruptedException e)
{
e.printRealStackTrace();
}
}
}
if((curr = memory[i]) != null && (curr instanceof SyntheticPlayer || curr instanceof SampledPlayer))
{
int state;
CustomPlayer player;
if((state = (player = (CustomPlayer) curr).getState()) == Player.STARTED || state == Player.PREFETCHED) players.addElement(player);
}
}
if((count = players.size()) > 0) players.copyInto(this.sounds = new CustomPlayer[count]);
progress.setValue(len / 100);
if(delay)
{
try
{
Thread.sleep(100L);
}
catch(InterruptedException e)
{
e.printRealStackTrace();
}
}
}
protected void showProgressScreen(Display display) {
Displayable screen;
(screen = getScreenEmpty()).setTitle("Любите красить пасхальные яйца?");
display.setCurrent(getScreenProgress(), screen);
}
protected void showFoundScreen(Display display) {
int count;
CustomPlayer[] found;
Displayable screen;
current = 0;
if((found = sounds) == null || (count = found.length) <= 0)
{
screen = getScreenEmpty();
} else
{
for(int i = count; i-- > 0; )
{
CustomPlayer player;
if((player = found[i]).getState() == Player.CLOSED) continue;
try
{
player.addPlayerListener(this);
}
catch(IllegalStateException e)
{
e.printRealStackTrace();
}
}
updateScreenSounds();
screen = getScreenSounds();
}
screen.setTitle("Звуки");
display.setCurrent(screen);
}
protected void execute(String[] arguments, Console console) {
delay = true;
super.execute(arguments, console);
}
protected void executeInBackground() {
delay = false;
super.executeInBackground();
}
private void updateScreenSounds() {
int len;
int index;
CustomPlayer[] found;
if((found = sounds) != null && (index = current) >= 0 && index < (len = found.length))
{
CustomPlayer player = found[index];
try
{
VolumeControl volume = (VolumeControl) player.getControl("VolumeControl");
getItemVolumeBar().setValue(volume.isMuted() ? 0 : volume.getLevel() / 10);
}
catch(Exception e)
{
getItemVolumeBar().setValue(0);
}
getItemSoundPlay().setImage(player.getState() == Player.STARTED ? getImagePause() : getImagePlay());
getItemSoundNum().setText((new StringBuilder()).append(' ').append(index + 1).append(" / ").append(len).toString());
}
}
private Image getImagePrev() {
Image result;
if((result = imagePrev) == null)
{
Graphics render;
(render = (result = imagePrev = DirectUtils.createImage(24, 24, 0x00000000)).getGraphics()).setColor(GLYPH_COLOR);
render.fillTriangle(19, 1, 9, 11, 19, 21);
render.fillRect(4, 1, 5, 21);
}
return result;
}
private Image getImageNext() {
Image result;
if((result = imageNext) == null)
{
Graphics render;
(render = (result = imageNext = DirectUtils.createImage(24, 24, 0x00000000)).getGraphics()).setColor(GLYPH_COLOR);
render.fillTriangle(4, 1, 14, 11, 4, 21);
render.fillRect(15, 1, 5, 21);
}
return result;
}
private Image getImagePlay() {
Image result;
if((result = imagePlay) == null)
{
Graphics render;
(render = (result = imagePlay = DirectUtils.createImage(24, 24, 0x00000000)).getGraphics()).setColor(GLYPH_COLOR);
render.fillTriangle(1, 1, 21, 11, 1, 21);
}
return result;
}
private Image getImagePause() {
Image result;
if((result = imagePause) == null)
{
Graphics render;
(render = (result = imagePause = DirectUtils.createImage(24, 24, 0x00000000)).getGraphics()).setColor(GLYPH_COLOR);
render.fillRect(5, 1, 5, 21);
render.fillRect(14, 1, 5, 21);
}
return result;
}
private Command getCommandSaveAction() {
Command result;
if((result = commandSaveAction) == null) result = commandSaveAction = new Command("Сохранить", Command.OK, 0);
return result;
}
private Command getCommandCancel() {
Command result;
if((result = commandCancel) == null) result = commandCancel = new Command("Отменить", Command.CANCEL, 0);
return result;
}
private Command getCommandSelect() {
Command result;
if((result = commandSelect) == null) result = commandSelect = new Command("Выбрать", Command.OK, 0);
return result;
}
private Command getCommandSave() {
Command result;
if((result = commandSave) == null) result = commandSave = new Command("Сохранить…", Command.SCREEN, 0);
return result;
}
private Command getCommandBack() {
Command result;
if((result = commandBack) == null) result = commandBack = new Command("Назад", Command.BACK, 0);
return result;
}
private Gauge getItemVolumeBar() {
Gauge result;
if((result = itemVolumeBar) == null) result = itemVolumeBar = new Gauge("Громкость", true, 10, 0);
return result;
}
private Gauge getItemProgressBar() {
Gauge result;
if((result = itemProgressBar) == null) result = itemProgressBar = new Gauge(null, false, 1, 0);
return result;
}
private StringItem getItemSoundNum() {
StringItem result;
if((result = itemSoundNum) == null) (result = itemSoundNum = new StringItem(null, " ")).setLayout(Item.LAYOUT_LEFT | Item.LAYOUT_EXPAND);
return result;
}
private ImageItem getItemSoundPrev() {
ImageItem result;
if((result = itemSoundPrev) == null)
{
(result = itemSoundPrev = new ImageItem(null, getImagePrev(), Item.LAYOUT_EXPAND, null, Item.BUTTON)).setItemCommandListener(this);
result.setDefaultCommand(getCommandSelect());
}
return result;
}
private ImageItem getItemSoundNext() {
ImageItem result;
if((result = itemSoundNext) == null)
{
(result = itemSoundNext = new ImageItem(null, getImageNext(), Item.LAYOUT_EXPAND, null, Item.BUTTON)).setItemCommandListener(this);
result.setDefaultCommand(getCommandSelect());
}
return result;
}
private ImageItem getItemSoundPlay() {
ImageItem result;
if((result = itemSoundPlay) == null)
{
(result = itemSoundPlay = new ImageItem(null, getImagePlay(), Item.LAYOUT_EXPAND, null, Item.BUTTON)).setItemCommandListener(this);
result.setDefaultCommand(getCommandSelect());
}
return result;
}
private TextField getItemFileName() {
TextField result;
if((result = itemFileName) == null) (result = itemFileName = new TextField("Имя файла", null, 128, Input.ANY)).setLayout(Item.LAYOUT_EXPAND);
return result;
}
private Alert getScreenProgress() {
Alert result;
if((result = screenProgress) == null)
{
(result = screenProgress = new Alert(null, "Поиск звуков в памяти…", null, AlertType.INFO)).setCommandListener(this);
result.addCommand(getCommandCancel());
result.setIndicator(getItemProgressBar());
}
return result;
}
private Form getScreenSounds() {
Form result;
if((result = screenSounds) == null)
{
ImageItem soundIcon = new ImageItem(null, SystemManager.loadImageFromFile("/ui/audio.png"), Item.LAYOUT_NEWLINE_BEFORE | Item.LAYOUT_CENTER | Item.LAYOUT_NEWLINE_AFTER, null);
(result = screenSounds = new Form(null, new Item[] { getItemSoundNum(), soundIcon, getItemVolumeBar(), getItemSoundPrev(), getItemSoundPlay(), getItemSoundNext() }) {
protected void sizeChanged(int width, int height) {
get(1).setPreferredSize(-1, height - get(0).getPreferredHeight() - get(2).getPreferredHeight() - get(3).getPreferredHeight());
}
}).setCommandListener(this);
result.setItemStateListener(this);
result.addCommand(getCommandBack());
result.addCommand(getCommandSave());
result.getHorizontalScrollBar().hide();
}
return result;
}
private Form getScreenEmpty() {
Form result;
if((result = screenEmpty) == null)
{
Font font;
String text;
StringItem empty;
(empty = new StringItem(null, text = "(нет звуков)")).setLayout(Item.LAYOUT_CENTER);
empty.setFont(font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_SMALL));
empty.setPreferredSize(font.stringWidth(text), -1);
(result = screenEmpty = new Form(null, new Item[] { empty })).setCommandListener(this);
result.addCommand(getCommandBack());
result.getHorizontalScrollBar().hide();
}
return result;
}
private Form getScreenSave() {
Form result;
if((result = screenSave) == null)
{
(result = screenSave = new Form("Сохранить", new Item[] { getItemFileName() })).setCommandListener(this);
result.addCommand(getCommandSaveAction());
result.addCommand(getCommandBack());
result.getHorizontalScrollBar().hide();
}
return result;
}
}
final class ImagesSearchConsoleCommand extends SearchConsoleCommand implements CommandListener, ItemCommandListener
{
private static final int GLYPH_COLOR;
static {
GLYPH_COLOR = RasterCanvas.getSystemColor(0x24);
}
private boolean delay;
private int current;
private Image[] images;
private Image imagePrev;
private Image imageNext;
private Command commandSaveAction;
private Command commandCancel;
private Command commandSelect;
private Command commandSave;
private Command commandBack;
private Gauge itemProgressBar;
private StringItem itemImageNum;
private ImageItem itemImagePrev;
private ImageItem itemImageNext;
private ImageItem itemImageShow;
private TextField itemFileName;
private Alert screenProgress;
private Form screenImages;
private Form screenEmpty;
private Form screenSave;
public ImagesSearchConsoleCommand(SystemManager manager) {
super("изображения", manager);
}
public void commandAction(Command command, Displayable screen) {
int index;
Image[] found;
if(screen == screenImages)
{
if(command == commandSave)
{
getItemFileName().setString("/имя.png");
DeviceManager.getInstance().getMainDisplay().setCurrent(getScreenSave());
return;
}
if(command == commandBack)
{
images = null;
returnToSystem();
}
return;
}
if(screen == screenSave)
{
if(command == commandSaveAction && (found = images) != null && (index = current) >= 0 && index < found.length)
{
final String fileName = getItemFileName().getString();
final Image image = found[index];
((Thread) (new Thread("Сохранение изображения") {
public void run() {
Image destImage = image;
String destFileName = fileName;
System.out.println((new StringBuilder()).append("Сохранение изображения в ").append(destFileName).append(" …").toString());
try
{
int width = destImage.getWidth();
int height = destImage.getHeight();
int[] pixels = new int[width * height];
OutputStream stream;
ImageEncoder encoder;
FileConnection connection;
destImage.getRGB(pixels, 0, width, 0, 0, width, height);
(encoder = new PNGEncoder()).setPixels(true, width, height, pixels);
connection = (FileConnection) Connector.open("file://".concat(destFileName));
try
{
if(connection.exists()) connection.delete();
connection.create();
stream = connection.openOutputStream();
try
{
encoder.saveToOutputStream(stream);
}
finally
{
stream.close();
}
}
finally
{
connection.close();
}
System.out.println((new StringBuilder()).append("Изображение успешно сохранено в ").append(destFileName).append('.').toString());
}
catch(Exception e)
{
System.out.println((new StringBuilder()).append("Ошибка возникла при сохранении изображения в ").append(destFileName).append('.').toString());
e.printRealStackTrace();
}
}
})).start();
}
DeviceManager.getInstance().getMainDisplay().setCurrent(getScreenImages());
return;
}
if(screen == screenProgress && command == commandCancel)
{
cancelSearchProcess();
return;
}
if(screen == screenEmpty && command == commandBack) returnToSystem();
}
public void commandAction(Command command, Item item) {
int len;
Object[] found;
if((found = images) == null || (len = found.length) <= 0) return;
if(item == itemImagePrev)
{
current = current == 0 ? len - 1 : current - 1;
updateScreenImages();
return;
}
if(item == itemImageNext)
{
current = current == len - 1 ? 0 : current + 1;
updateScreenImages();
}
}
protected void searchProcess() {
int len;
int count;
Object[] memory = Memory.getAllObjects();
Gauge progress = getItemProgressBar();
Vector images = new Vector();
if((len = memory != null ? memory.length : 0) >= 100) progress.setMaxValue(len / 100);
for(int i = 0; i < len; i++)
{
Object curr;
if(i % 100 == 0)
{
progress.setValue(i / 100);
if(delay)
{
try
{
Thread.sleep(100L);
}
catch(InterruptedException e)
{
e.printRealStackTrace();
}
}
}
if((curr = memory[i]) instanceof Image) images.addElement(curr);
}
if((count = images.size()) > 0) images.copyInto(this.images = new Image[count]);
progress.setValue(len / 100);
if(delay)
{
try
{
Thread.sleep(100L);
}
catch(InterruptedException e)
{
e.printRealStackTrace();
}
}
}
protected void showProgressScreen(Display display) {
Displayable screen;
(screen = getScreenEmpty()).setTitle("Любите красить пасхальные яйца?");
display.setCurrent(getScreenProgress(), screen);
}
protected void showFoundScreen(Display display) {
Image[] found;
Displayable screen;
current = 0;
if((found = images) == null || found.length <= 0)
{
screen = getScreenEmpty();
} else
{
updateScreenImages();
screen = getScreenImages();
}
screen.setTitle("Изображения");
display.setCurrent(screen);
}
protected void execute(String[] arguments, Console console) {
delay = true;
super.execute(arguments, console);
}
protected void executeInBackground() {
delay = false;
super.executeInBackground();
}
private void updateScreenImages() {
int len;
int index;
Image[] found;
if((found = images) != null && (index = current) >= 0 && index < (len = found.length))
{
getItemImageShow().setImage(found[index]);
getItemImageNum().setText((new StringBuilder()).append(' ').append(index + 1).append(" / ").append(len).toString());
}
}
private Image getImagePrev() {
Image result;
if((result = imagePrev) == null)
{
Graphics render;
(render = (result = imagePrev = DirectUtils.createImage(24, 24, 0x00000000)).getGraphics()).setColor(GLYPH_COLOR);
render.fillTriangle(19, 1, 9, 11, 19, 21);
render.fillRect(4, 1, 5, 21);
}
return result;
}
private Image getImageNext() {
Image result;
if((result = imageNext) == null)
{
Graphics render;
(render = (result = imageNext = DirectUtils.createImage(24, 24, 0x00000000)).getGraphics()).setColor(GLYPH_COLOR);
render.fillTriangle(4, 1, 14, 11, 4, 21);
render.fillRect(15, 1, 5, 21);
}
return result;
}
private Command getCommandSaveAction() {
Command result;
if((result = commandSaveAction) == null) result = commandSaveAction = new Command("Сохранить", Command.OK, 0);
return result;
}
private Command getCommandCancel() {
Command result;
if((result = commandCancel) == null) result = commandCancel = new Command("Отменить", Command.CANCEL, 0);
return result;
}
private Command getCommandSelect() {
Command result;
if((result = commandSelect) == null) result = commandSelect = new Command("Выбрать", Command.OK, 0);
return result;
}
private Command getCommandSave() {
Command result;
if((result = commandSave) == null) result = commandSave = new Command("Сохранить…", Command.SCREEN, 0);
return result;
}
private Command getCommandBack() {
Command result;
if((result = commandBack) == null) result = commandBack = new Command("Назад", Command.BACK, 0);
return result;
}
private Gauge getItemProgressBar() {
Gauge result;
if((result = itemProgressBar) == null) result = itemProgressBar = new Gauge(null, false, 1, 0);
return result;
}
private StringItem getItemImageNum() {
StringItem result;
if((result = itemImageNum) == null) (result = itemImageNum = new StringItem(null, " ")).setLayout(Item.LAYOUT_VCENTER | Item.LAYOUT_EXPAND);
return result;
}
private ImageItem getItemImagePrev() {
ImageItem result;
if((result = itemImagePrev) == null)
{
(result = itemImagePrev = new ImageItem(null, getImagePrev(), Item.LAYOUT_VCENTER, null, Item.BUTTON)).setItemCommandListener(this);
result.setDefaultCommand(getCommandSelect());
}
return result;
}
private ImageItem getItemImageNext() {
ImageItem result;
if((result = itemImageNext) == null)
{
(result = itemImageNext = new ImageItem(null, getImageNext(), Item.LAYOUT_VCENTER, null, Item.BUTTON)).setItemCommandListener(this);
result.setDefaultCommand(getCommandSelect());
}
return result;
}
private ImageItem getItemImageShow() {
ImageItem result;
if((result = itemImageShow) == null) result = itemImageShow = new ImageItem(null, null, Item.LAYOUT_NEWLINE_BEFORE, null);
return result;
}
private TextField getItemFileName() {
TextField result;
if((result = itemFileName) == null) (result = itemFileName = new TextField("Имя файла", null, 128, Input.ANY)).setLayout(Item.LAYOUT_EXPAND);
return result;
}
private Alert getScreenProgress() {
Alert result;
if((result = screenProgress) == null)
{
(result = screenProgress = new Alert(null, "Поиск изображений в памяти…", null, AlertType.INFO)).setCommandListener(this);
result.addCommand(getCommandCancel());
result.setIndicator(getItemProgressBar());
}
return result;
}
private Form getScreenImages() {
Form result;
if((result = screenImages) == null)
{
(result = screenImages = new Form(null, new Item[] { getItemImagePrev(), getItemImageNext(), getItemImageNum(), getItemImageShow() })).setCommandListener(this);
result.addCommand(getCommandBack());
result.addCommand(getCommandSave());
}
return result;
}
private Form getScreenEmpty() {
Form result;
if((result = screenEmpty) == null)
{
Font font;
String text;
StringItem empty;
(empty = new StringItem(null, text = "(нет изображений)")).setLayout(Item.LAYOUT_CENTER);
empty.setFont(font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_SMALL));
empty.setPreferredSize(font.stringWidth(text), -1);
(result = screenEmpty = new Form(null, new Item[] { empty })).setCommandListener(this);
result.addCommand(getCommandBack());
result.getHorizontalScrollBar().hide();
}
return result;
}
private Form getScreenSave() {
Form result;
if((result = screenSave) == null)
{
(result = screenSave = new Form("Сохранить", new Item[] { getItemFileName() })).setCommandListener(this);
result.addCommand(getCommandSaveAction());
result.addCommand(getCommandBack());
result.getHorizontalScrollBar().hide();
}
return result;
}
}