/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016, 2019 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package javax.microedition.lcdui;
import java.lang.ref.*;
import java.util.*;
import malik.emulator.media.graphics.*;
import malik.emulator.time.*;
public class DateField extends Item
{
private static final class TimeZonesListCommandHandler extends WeakReference
implements CommandListener
{
TimeZonesListCommandHandler(DateField thisItem)
{
super(thisItem);
}
public void commandAction(Command command, Displayable screen)
{
int i;
int f;
List list;
DateField thisItem;
if((thisItem = (DateField) get()) == null || screen != (list = thisItem.timeZonesList))
{
return;
}
if(command == List.SELECT_COMMAND)
{
i = thisItem.offset;
f = thisItem.offset = list.getSelectedIndex();
thisItem.showSourceScreen();
if(i != f)
{
thisItem.invokeNotifyStateChanged();
}
return;
}
if(command == BACK)
{
thisItem.showSourceScreen();
}
}
}
private static abstract class Component extends WeakReference
{
protected static final long DAY_MASK = 0xffL << 32;
public boolean visible;
public int left;
public int top;
public int width;
public int height;
protected Component(DateField thisItem)
{
super(thisItem);
}
public abstract void paint(Graphics render, int width, int height,
boolean focused, boolean pressed, long fields, String offset);
public abstract int getWidth();
public abstract int getHeight();
public void keyPressed(int keyCode)
{
}
public void pointerPressed(int x, int y)
{
}
public void pointerDragged(int x, int y)
{
}
public void pointerReleased(int x, int y)
{
}
public void select()
{
}
public boolean hasSelectCommand()
{
return false;
}
public boolean traverse(int direction, boolean focused)
{
return false;
}
protected final void repaint()
{
Item thisItem;
if((thisItem = (Item) get()) == null)
{
return;
}
thisItem.notifyPaint();
}
protected final void setFields(long fields)
{
int tmp;
DateField thisItem;
if((thisItem = (DateField) get()) == null)
{
return;
}
if((((int) (fields >> 32)) & 0xff) > (tmp = GregorianCalendar.getNumOfDays(
(int) (fields >>> 48), ((int) (fields >> 40)) & 0xff)))
{
fields = (fields & ~DAY_MASK) | ((((long) tmp) << 32) & DAY_MASK);
}
if(thisItem.fields == fields)
{
return;
}
thisItem.fields = fields;
thisItem.notifyPaint();
thisItem.invokeNotifyStateChanged();
}
protected final long getFields()
{
DateField thisItem;
return (thisItem = (DateField) get()) == null ? 0L : thisItem.fields;
}
}
private static abstract class Integral extends Component
{
private boolean newInput;
private int maxDigits;
private int minValue;
private int maxValue;
private int shift;
private long mask;
public Integral(DateField thisItem, boolean oneBased, int maxValue, int shift)
{
super(thisItem);
this.newInput = true;
this.maxDigits = (maxValue &= 0xffff) < 10 ? 1 : (maxValue < 100 ? 2 :
(maxValue < 1000 ? 3 : (maxValue < 10000 ? 4 : 5)));
this.minValue = oneBased ? 1 : 0;
this.maxValue = maxValue;
this.shift = shift;
this.mask = maxValue < 0x0100 ? 0x00ffL : 0xffffL;
}
public void paint(Graphics render, int width, int height,
boolean focused, boolean pressed, long fields, String offset)
{
int lprev;
int lval;
int lnext;
int t;
int a;
Font font = render.getFont();
lval = (lprev = pressed ? 3 : 2) + font.charWidth('<');
lnext = width - (4 - lprev) - font.charWidth('>');
t = pressed ? 3 : 2;
render.setColor(RasterCanvas.getSystemColor(
(a = pressed ? 1 : (focused ? 3 : 0)) + 0x24));
render.drawElementOfGUI(4, a, 0, 0, 0, width, height);
render.drawChar('<', lprev, t, Graphics.LEFT | Graphics.TOP);
render.drawChar('>', lnext, t, Graphics.LEFT | Graphics.TOP);
render.translate(lval, t);
paintValue(render, lnext - lval, font.getHeight(), (int) ((fields >> shift) & mask));
}
public void keyPressed(int keyCode)
{
int value;
if(keyCode < Canvas.KEY_NUM0 || keyCode > Canvas.KEY_NUM9)
{
return;
}
if(newInput)
{
newInput = false;
setValue(keyCode - Canvas.KEY_NUM0);
return;
}
if(((value = getValue()) < 10 ? 1 : (value < 100 ? 2 :
(value < 1000 ? 3 : (value < 10000 ? 4 : 5)))) >= maxDigits - 1)
{
newInput = true;
}
setValue((value * 10) + (keyCode - Canvas.KEY_NUM0));
}
public void pointerReleased(int x, int y)
{
int w;
int value;
newInput = true;
if(y < 0 || y >= height)
{
return;
}
if(x < (w = width) / 2 && x >= 0)
{
setValue((value = getValue()) <= minValue ? maxValue : value - 1);
return;
}
if(x < w && x >= 0)
{
setValue((value = getValue()) >= maxValue ? minValue : value + 1);
}
}
public boolean traverse(int direction, boolean focused)
{
int value;
if(direction != 0)
{
newInput = true;
}
if(!focused)
{
return true;
}
if(direction == Canvas.LEFT)
{
setValue((value = getValue()) <= minValue ? maxValue : value - 1);
return true;
}
if(direction == Canvas.RIGHT)
{
setValue((value = getValue()) >= maxValue ? minValue : value + 1);
return true;
}
return false;
}
public int getWidth()
{
Font font = FONT;
return getValueMaxWidth() + font.charWidth('<') + font.charWidth('>') + 4;
}
public int getHeight()
{
return FONT.getHeight() + 4;
}
protected abstract void paintValue(Graphics render, int width, int height, int value);
protected abstract int getValueMaxWidth();
protected final void setValue(int value)
{
int tmp;
int shift = this.shift;
long mask = this.mask << shift;
if(value < (tmp = minValue))
{
value = tmp;
}
if(value > (tmp = maxValue))
{
value = tmp;
}
setFields((getFields() & ~mask) | ((((long) value) << shift) & mask));
}
protected final int getValue()
{
return (int) ((getFields() >> shift) & mask);
}
protected final int getMaxDigits()
{
return maxDigits;
}
}
private static class DigitalIntegral extends Integral
{
private char[] digits;
public DigitalIntegral(DateField thisItem, boolean oneBased, int maxValue, int shift)
{
super(thisItem, oneBased, maxValue, shift);
this.digits = new char[getMaxDigits()];
}
protected void paintValue(Graphics render, int width, int height, int value)
{
paintValue(render, width, height, value, digits);
}
protected int getValueMaxWidth()
{
return MAX_DIGIT_WIDTH * getMaxDigits();
}
protected void paintValue(Graphics render, int width, int height, int value, char[] digits)
{
int i;
int len;
for(i = len = digits.length; i-- > 0; )
{
digits[i] = (char) ((value % 10) + '0');
if((value /= 10) == 0)
{
break;
}
}
render.drawChars(digits, i, len - i, width / 2, 0, Graphics.HCENTER | Graphics.TOP);
}
}
private static class DigitalIntegralWithLeadingZeros extends DigitalIntegral
{
public DigitalIntegralWithLeadingZeros(DateField thisItem,
boolean oneBased, int maxValue, int shift)
{
super(thisItem, oneBased, maxValue, shift);
}
protected void paintValue(Graphics render, int width, int height, int value, char[] digits)
{
int i;
int len;
for(i = len = digits.length; i-- > 0; value /= 10)
{
digits[i] = (char) ((value % 10) + '0');
}
render.drawChars(digits, 0, len, width / 2, 0, Graphics.HCENTER | Graphics.TOP);
}
}
private static class Month extends Integral
{
private static final String[] MONTHS;
static
{
MONTHS = new String[] {
"Январь", "Февраль", "Март", "Апрель", "Май", "Июнь",
"Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь",
};
}
public Month(DateField thisItem)
{
super(thisItem, true, MONTHS.length, 40);
}
protected void paintValue(Graphics render, int width, int height, int value)
{
int len = MONTHS.length;
render.drawString(MONTHS[--value < 0 ? 0 : (value >= len ? len - 1 : value)],
width / 2, 0, Graphics.HCENTER | Graphics.TOP);
}
protected int getValueMaxWidth()
{
int i;
int tmp;
int result = 0;
Font font = FONT;
for(i = MONTHS.length; i-- > 0; )
{
if(result < (tmp = font.stringWidth(MONTHS[i])))
{
result = tmp;
}
}
return result;
}
}
private static class Day extends Component
{
private static final String[] DAYS;
static
{
DAYS = new String[] {
"пн", "вт", "ср", "чт", "пт", "сб", "вс"
};
}
private static int toInnerFormat(int dayOfWeek)
{
return dayOfWeek == 0 ? 6 : dayOfWeek - 1;
}
private int numOfDays;
private int focusedDay;
private int firstDayOfWeek;
private char[] digits;
public Day(DateField thisField)
{
super(thisField);
this.focusedDay = 1;
this.digits = new char[2];
}
public void paint(Graphics render, int width, int height,
boolean focused, boolean pressed, long fields, String offset)
{
int i;
int j;
int l;
int t;
int w = width / 7;
int h = height / 7;
int nd;
int sd;
int ofs;
int len;
int year = (int) (fields >>> 48);
int month = ((int) (fields >> 40)) & 0xff;
int day = ((int) (fields >> 32)) & 0xff;
int fday = focused ? focusedDay : 0;
int color;
int outday;
char[] digs = digits;
numOfDays = nd = GregorianCalendar.getNumOfDays(year, month);
firstDayOfWeek = sd = toInnerFormat(GregorianCalendar.getDayOfWeek(year, month, 1));
render.setColor(color = RasterCanvas.getSystemColor(0x28));
for(l = 0, t = 0, i = 0; i < 7; l += w, i++)
{
render.drawString(DAYS[i], l + (w / 2), t + 2, Graphics.HCENTER | Graphics.TOP);
}
outday = 1 - sd;
for(t = h, j = 0; j < 6; t += h, j++)
{
for(l = 0, i = 0; i < 7; l += w, outday++, i++)
{
if(outday < 1 || outday > nd)
{
continue;
}
render.setColor(outday == fday ? RasterCanvas.getSystemColor(0x27) :
(outday != day ? color : RasterCanvas.getSystemColor(0x24)));
if(outday == fday)
{
render.drawElementOfGUI(4, 3, 0, l, t, w, h);
}
else if(outday == day)
{
render.drawElementOfGUI(4, 0, 0, l, t, w, h);
}
digs[0] = (char) ((outday / 10) + '0');
digs[1] = (char) ((outday % 10) + '0');
if(outday < 10)
{
ofs = 1;
len = 1;
} else
{
ofs = 0;
len = 2;
}
render.drawChars(digs, ofs, len, l + (w / 2), t + 2,
Graphics.HCENTER | Graphics.TOP);
}
}
}
public void pointerPressed(int x, int y)
{
int fday;
if((fday = getDayUnderPointer(x, y)) > 0 && focusedDay != fday)
{
focusedDay = fday;
repaint();
}
}
public void pointerDragged(int x, int y)
{
int fday;
if((fday = getDayUnderPointer(x, y)) > 0 && focusedDay != fday)
{
focusedDay = fday;
repaint();
}
}
public void pointerReleased(int x, int y)
{
int fday;
if((fday = getDayUnderPointer(x, y)) > 0)
{
focusedDay = fday;
setFields((getFields() & ~DAY_MASK) | ((((long) fday) << 32) & DAY_MASK));
}
}
public void select()
{
setFields((getFields() & ~DAY_MASK) | ((((long) focusedDay) << 32) & DAY_MASK));
}
public boolean hasSelectCommand()
{
return true;
}
public boolean traverse(int direction, boolean focused)
{
int f;
switch(direction)
{
case Canvas.UP:
if(focused)
{
focusedDay = f = focusedDay - 7;
repaint();
return f >= 1;
}
focusedDay = numOfDays;
break;
case Canvas.LEFT:
if(focused)
{
focusedDay = f = focusedDay - 1;
repaint();
return f >= 1;
}
focusedDay = numOfDays;
break;
case Canvas.RIGHT:
if(focused)
{
focusedDay = f = focusedDay + 1;
repaint();
return f <= numOfDays;
}
focusedDay = 1;
break;
case Canvas.DOWN:
if(focused)
{
focusedDay = f = focusedDay + 7;
repaint();
return f <= numOfDays;
}
focusedDay = 1;
break;
}
return true;
}
public int getWidth()
{
return (2 * MAX_DIGIT_WIDTH + 4) * 7;
}
public int getHeight()
{
return (FONT.getHeight() + 4) * 7;
}
private int getDayUnderPointer(int x, int y)
{
int w = Math.max(1, width / 7);
int h = Math.max(1, height / 7);
int col = x / w;
int row = y / h;
int result;
return (result = 7 * row + col + (-6 - firstDayOfWeek)) < 1 ||
result > numOfDays ? 0 : result;
}
}
private static class Offset extends Component
{
public Offset(DateField thisField)
{
super(thisField);
}
public void paint(Graphics render, int width, int height,
boolean focused, boolean pressed, long fields, String offset)
{
int l;
int t;
int a;
l = pressed ? 3 : 2;
t = pressed ? 3 : 2;
render.setColor(RasterCanvas.getSystemColor(
(a = pressed ? 1 : (focused ? 3 : 0)) + 0x24));
render.drawElementOfGUI(4, a, 0, 0, 0, width, height);
render.drawSubstring(offset, 0, 9, l, t, Graphics.LEFT | Graphics.TOP);
}
public void pointerReleased(int x, int y)
{
if(x >= 0 && x < width && y >= 0 && y < height)
{
select();
}
}
public void select()
{
DateField thisItem;
if((thisItem = (DateField) get()) == null)
{
return;
}
thisItem.showTimeZonesList();
}
public boolean hasSelectCommand()
{
return true;
}
public int getWidth()
{
Font font = FONT;
return font.stringWidth("UTC+") + 4 * MAX_DIGIT_WIDTH + font.charWidth(':') + 4;
}
public int getHeight()
{
return FONT.getHeight() + 4;
}
}
public static final int DATE = 1;
public static final int TIME = 2;
public static final int DATE_TIME = 3;
private static final int MONTH = 0;
private static final int YEAR = 1;
private static final int DAY = 2;
private static final int HOUR = 3;
private static final int MINUTE = 4;
private static final int OFFSET = 5;
private static final int ZERO_OFFSET_INDEX;
private static final int MAX_DIGIT_WIDTH;
private static final int[] OFFSETS;
private static final String[] NAMES;
private static final Command BACK;
private static final Command SELECT;
private static final Font FONT;
static
{
char j;
int w;
int i;
int len;
int ofs;
int tmp;
int zeroOffsetIndex;
int[] offsets;
String[] names;
String s;
Font f;
names = new String[] {
"UTC-12:00", "UTC-11:00", "UTC-10:00", "UTC-09:30", "UTC-09:00",
"UTC-08:30*", "UTC-08:00", "UTC-07:00", "UTC-06:00", "UTC-05:00",
"UTC-04:30", "UTC-04:00", "UTC-03:30", "UTC-03:00", "UTC-02:30",
"UTC-02:00", "UTC-01:00", "UTC-00:44*", "UTC-00:25*", "UTC+00:00",
"UTC+00:20*", "UTC+00:30*", "UTC+01:00", "UTC+02:00", "UTC+03:00",
"UTC+03:30", "UTC+04:00", "UTC+04:30", "UTC+04:51*", "UTC+05:00",
"UTC+05:30", "UTC+05:40*", "UTC+05:45", "UTC+06:00", "UTC+06:30",
"UTC+07:00", "UTC+07:20*", "UTC+07:30*", "UTC+08:00", "UTC+08:30",
"UTC+08:45", "UTC+09:00", "UTC+09:30", "UTC+10:00", "UTC+10:30",
"UTC+11:00", "UTC+11:30*", "UTC+12:00", "UTC+12:45", "UTC+13:00",
"UTC+13:45", "UTC+14:00",
};
zeroOffsetIndex = -1;
offsets = new int[len = names.length];
for(i = len; i-- > 0; )
{
if((s = names[i]).length() < 9)
{
continue;
}
ofs = (s.charAt(4) - '0') * 36000000 + (s.charAt(5) - '0') * 3600000 +
(s.charAt(7) - '0') * 600000 + (s.charAt(8) - '0') * 60000;
offsets[i] = s.charAt(3) == '-' ? -ofs : ofs;
if(ofs == 0 && zeroOffsetIndex < 0)
{
zeroOffsetIndex = i;
}
}
if(zeroOffsetIndex < 0)
{
zeroOffsetIndex = 0;
}
w = (f = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL)).charWidth('0');
for(j = '1'; j <= '9'; j++)
{
if(w < (tmp = f.charWidth(j)))
{
w = tmp;
}
}
ZERO_OFFSET_INDEX = zeroOffsetIndex;
MAX_DIGIT_WIDTH = w;
OFFSETS = offsets;
NAMES = names;
BACK = new Command("Назад", Command.BACK, 0);
SELECT = new Command("Выбрать", Command.OK, 0);
FONT = f;
}
private static int indexOfOffset(int offset)
{
int i;
for(i = OFFSETS.length; i-- > 0; )
{
if(OFFSETS[i] == offset)
{
return i;
}
}
return ZERO_OFFSET_INDEX;
}
private boolean controlFocused;
private boolean componentFocused;
private boolean needPlaceComponents;
private int contentWidth;
private int contentHeight;
private int focused;
private int pressed;
private int mode;
private int offset;
private long fields;
private Component[] components;
private List timeZonesList;
private Displayable sourceScreen;
public DateField(String label, int mode)
{
this(LAYOUT_NEWLINE_AFTER, label, null, null, null, mode, null, null);
}
public DateField(String label, int mode, TimeZone zone)
{
this(LAYOUT_NEWLINE_AFTER, label, null, null, null, mode, null, zone);
}
public DateField(int layout, String label,
Command[] commands, Command defaultCommand, ItemCommandListener listener,
int mode, Date time, TimeZone zone)
{
super(layout, -1, -1, label, commands, defaultCommand, listener);
int ofs;
Command[] timeZonesCommands;
if(mode < DATE || mode > DATE_TIME)
{
throw new IllegalArgumentException("DateField: " +
"недопустимое значение параметра mode.");
}
timeZonesCommands = new Command[] {
BACK
};
this.needPlaceComponents = true;
this.focused = -1;
this.pressed = -1;
this.mode = mode;
this.offset = ofs = indexOfOffset((
zone == null ? ListOfTimeZones.getDefault() : zone).getRawOffset());
this.fields = GregorianCalendar.computeFields(
time == null ? System.currentTimeMillis() : time.getTime(), OFFSETS[ofs]);
this.components = new Component[] {
new Month(this),
new DigitalIntegral(this, true, 0xffff, 48),
new Day(this),
new DigitalIntegralWithLeadingZeros(this, false, 23, 24),
new DigitalIntegralWithLeadingZeros(this, false, 59, 16),
new Offset(this)
};
this.timeZonesList = new List(false, "Часовой пояс (* – исторический):", null,
timeZonesCommands, List.SELECT_COMMAND, new TimeZonesListCommandHandler(this),
Choice.IMPLICIT, NAMES, null);
}
public void setInputMode(int mode)
{
if(mode < DATE || mode > DATE_TIME)
{
throw new IllegalArgumentException("DateField.setInputMode: " +
"недопустимое значение параметра mode.");
}
this.needPlaceComponents = true;
this.mode = mode;
notifyUpdate();
}
public void setDate(Date time)
{
this.fields = GregorianCalendar.computeFields(
time == null ? System.currentTimeMillis() : time.getTime(), OFFSETS[offset]);
notifyPaint();
}
public int getInputMode()
{
return mode;
}
public Date getDate()
{
int tz;
long f;
switch(mode)
{
case DATE:
tz = 0;
f = fields & ~0xffffffffL;
break;
case TIME:
tz = 0;
f = ((1970L << 48) | (1L << 40) | (1L << 32)) | (fields & 0xffff0000L);
break;
case DATE_TIME:
tz = OFFSETS[offset];
f = fields & ~0xffffL;
break;
default:
tz = 0;
f = 0L;
break;
}
return new Date(GregorianCalendar.computeTime(f, tz));
}
void paintContent(Graphics render, int contentWidth, int contentHeight)
{
boolean cfocused = controlFocused;
int i;
int w;
int h;
int f = focused;
int p = pressed;
int tx = render.getTranslateX();
int ty = render.getTranslateY();
long fields = this.fields;
Component[] list;
Component comp;
String offset = NAMES[this.offset];
for(i = (list = components).length; i-- > 0; )
{
if(!(comp = list[i]).visible)
{
continue;
}
render.translate(
tx + comp.left - render.getTranslateX(),
ty + comp.top - render.getTranslateY());
render.setFont(FONT);
w = comp.width;
h = comp.height;
if(i == HOUR)
{
render.setColor(RasterCanvas.getSystemColor(0x27));
render.setClip(0, 0, w + FONT.charWidth(':') + 2, h);
render.drawChar(':', w + 1, 2, Graphics.LEFT | Graphics.TOP);
}
render.setClip(0, 0, w, h);
comp.paint(render, w, h, cfocused && i == f, cfocused && i == p, fields, offset);
}
}
void onKeyPressed(int key, int charCode)
{
int f;
Component[] list;
if((f = focused) >= 0 && f < (list = components).length)
{
list[f].keyPressed(MIDletProxy.getInstance().getKeyCode(key));
}
}
void onContentPointerPressed(int x, int y, int button)
{
int f;
int next;
Component comp;
if(button == MIDletProxy.BUTTON_MAIN && (next = getComponentIndexUnderPointer(x, y)) >= 0)
{
f = focused;
componentFocused = true;
focus(next, true);
(comp = components[next]).traverse(0, f == next);
comp.pointerPressed(x - comp.left, y - comp.top);
notifyPaint();
}
}
void onContentPointerDragged(int x, int y)
{
int f;
Component comp;
if(componentFocused)
{
(comp = components[f = focused]).pointerDragged(x - comp.left, y - comp.top);
if(pressed != (pressed = f == getComponentIndexUnderPointer(x, y) ? f : -1))
{
notifyPaint();
}
}
}
void onContentPointerReleased(int x, int y, int button)
{
Component comp;
if(button == MIDletProxy.BUTTON_MAIN && componentFocused)
{
pressed = -1;
componentFocused = false;
(comp = components[focused]).pointerReleased(x - comp.left, y - comp.top);
notifyPaint();
}
}
void onCommandAction(Command command)
{
if(command == SELECT)
{
components[focused].select();
return;
}
super.onCommandAction(command);
}
void onTraverseOut()
{
controlFocused = false;
notifyPaint();
}
boolean onTraverseNeedStayOn(int direction, int viewportWidth, int viewportHeight,
int[] visibleRectangle)
{
boolean cfocused;
int labelHeight;
int f;
int i;
int tmp;
int cmo;
int cms;
int vro;
int vrs;
int len;
Component[] list;
Component comp;
if((cfocused = controlFocused) != (controlFocused = true))
{
notifyPaint();
}
if(componentFocused)
{
return true;
}
len = (list = components).length;
label0:
{
switch(direction)
{
case Canvas.UP:
case Canvas.LEFT:
if(!cfocused)
{
for(i = len; i-- > 0; )
{
if(list[i].visible)
{
focus(f = i, false);
break label0;
}
}
}
break;
case Canvas.RIGHT:
case Canvas.DOWN:
if(!cfocused)
{
for(i = 0; i < len; i++)
{
if(list[i].visible)
{
focus(f = i, false);
break label0;
}
}
}
break;
}
if(cfocused && (i = focused) >= 0 && i < len)
{
if(list[i].traverse(direction, true))
{
return true;
}
switch(direction)
{
case Canvas.UP:
case Canvas.LEFT:
while(i-- > 0)
{
if(list[i].visible)
{
focus(f = i, false);
break label0;
}
}
break;
case Canvas.RIGHT:
case Canvas.DOWN:
for(i++; i < len; i++)
{
if(list[i].visible)
{
focus(f = i, false);
break label0;
}
}
break;
}
}
return false;
}
(comp = list[f]).traverse(direction, false);
labelHeight = super.getPreferredHeight() - contentHeight;
if((vrs = visibleRectangle[WIDTH]) < (cms = comp.width))
{
visibleRectangle[WIDTH] = vrs = cms;
}
if((vro = visibleRectangle[LEFT]) > (tmp = (cmo = comp.left)))
{
visibleRectangle[LEFT] = tmp;
}
else if(vro < (tmp = cmo + cms - vrs))
{
visibleRectangle[LEFT] = tmp;
}
if((vrs = visibleRectangle[HEIGHT]) < (cms = comp.height))
{
visibleRectangle[HEIGHT] = vrs = cms;
}
if((vro = visibleRectangle[TOP]) > (tmp = labelHeight + (cmo = comp.top)))
{
visibleRectangle[TOP] = tmp;
}
else if(vro < (tmp = labelHeight + cmo + cms - vrs))
{
visibleRectangle[TOP] = tmp;
}
notifyPaint();
return true;
}
boolean keyHandling(int key)
{
int keyCode;
return (keyCode = MIDletProxy.getInstance().getKeyCode(key)) >= Canvas.KEY_NUM0 &&
keyCode <= Canvas.KEY_NUM9;
}
int getPreferredContentWidth(int contentHeight, int containerClientWidth)
{
if(needPlaceComponents)
{
needPlaceComponents = false;
placeComponents();
}
return contentWidth;
}
int getPreferredContentHeight(int contentWidth)
{
if(needPlaceComponents)
{
needPlaceComponents = false;
placeComponents();
}
return contentHeight;
}
private void showTimeZonesList()
{
List screen = timeZonesList;
if((sourceScreen = getOwner()) != null)
{
screen.setSelectedIndex(offset, true);
MIDletProxy.getInstance().getEmulatorScreen().setCurrent(screen);
}
}
private void showSourceScreen()
{
Displayable next;
Display display = MIDletProxy.getInstance().getEmulatorScreen();
if((next = sourceScreen).isSystem())
{
display.setCurrent(next);
} else
{
display.hideSystemScreen();
}
sourceScreen = null;
}
private void invokeNotifyStateChanged()
{
super.notifyStateChanged();
}
private void placeComponents()
{
boolean vis;
int l;
int t;
int r;
int b;
int i;
int len;
int maxWidth;
int maxHeight;
Component[] list;
Component prev;
Component comp;
maxWidth = 0;
maxHeight = 0;
len = (list = components).length;
switch(mode)
{
case DATE:
for(prev = null, i = 0; i < len; prev = comp, i++)
{
comp = list[i];
switch(i)
{
case MONTH:
comp.visible = vis = true;
comp.left = l = 0;
comp.top = t = 0;
break;
case YEAR:
comp.visible = vis = true;
comp.left = l = prev.left + prev.width;
comp.top = t = prev.top;
break;
case DAY:
comp.visible = vis = true;
comp.left = l = 0;
comp.top = t = prev.top + prev.height;
break;
default:
comp.visible = vis = false;
l = 0;
t = 0;
break;
}
if(vis)
{
r = l + (comp.width = comp.getWidth());
b = t + (comp.height = comp.getHeight());
if(maxWidth < r)
{
maxWidth = r;
}
if(maxHeight < b)
{
maxHeight = b;
}
}
}
(comp = list[YEAR]).left = maxWidth - comp.width;
break;
case TIME:
for(prev = null, i = 0; i < len; prev = comp, i++)
{
comp = list[i];
switch(i)
{
case HOUR:
comp.visible = vis = true;
comp.left = l = 0;
comp.top = t = 0;
break;
case MINUTE:
comp.visible = vis = true;
comp.left = l = prev.left + prev.width + FONT.charWidth(':') + 2;
comp.top = t = prev.top;
break;
default:
comp.visible = vis = false;
l = 0;
t = 0;
break;
}
if(vis)
{
r = l + (comp.width = comp.getWidth());
b = t + (comp.height = comp.getHeight());
if(maxWidth < r)
{
maxWidth = r;
}
if(maxHeight < b)
{
maxHeight = b;
}
}
}
break;
case DATE_TIME:
for(prev = null, i = 0; i < len; prev = comp, i++)
{
(comp = list[i]).visible = true;
switch(i)
{
case MONTH:
comp.left = l = 0;
comp.top = t = 0;
break;
case DAY:
case HOUR:
comp.left = l = 0;
comp.top = t = prev.top + prev.height;
break;
case MINUTE:
comp.left = l = prev.left + prev.width + FONT.charWidth(':') + 2;
comp.top = t = prev.top;
break;
default:
comp.left = l = prev.left + prev.width;
comp.top = t = prev.top;
break;
}
r = l + (comp.width = comp.getWidth());
b = t + (comp.height = comp.getHeight());
if(maxWidth < r)
{
maxWidth = r;
}
if(maxHeight < b)
{
maxHeight = b;
}
}
(comp = list[YEAR]).left = maxWidth - comp.width;
(comp = list[OFFSET]).left = maxWidth - comp.width;
break;
}
contentWidth = maxWidth;
contentHeight = maxHeight;
}
private void focus(int componentIndex, boolean fromPointer)
{
boolean oldHasSelectCommand;
boolean newHasSelectCommand;
int len;
int f;
Component[] list;
len = (list = components).length;
oldHasSelectCommand = (f = focused) >= 0 && f < len && list[f].hasSelectCommand();
newHasSelectCommand = (f = componentIndex) >= 0 && f < len && list[f].hasSelectCommand();
focused = componentIndex;
if(fromPointer)
{
pressed = componentIndex;
}
if(oldHasSelectCommand && !newHasSelectCommand)
{
super.removeCommand(SELECT);
}
if(newHasSelectCommand && !oldHasSelectCommand)
{
super.setDefaultCommand(SELECT);
}
}
private int getComponentIndexUnderPointer(int x, int y)
{
int i;
int tmp;
Component[] list;
Component comp;
for(i = (list = components).length; i-- > 0; )
{
if((comp = list[i]).visible &&
x >= (tmp = comp.left) && x < tmp + comp.width &&
y >= (tmp = comp.top) && y < tmp + comp.height)
{
return i;
}
}
return -1;
}
}