/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016, 2019 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package javax.microedition.lcdui;
import malik.emulator.media.graphics.*;
public class Gauge extends Item
{
public static final int INDEFINITE = -1;
public static final int CONTINUOUS_IDLE = 0;
public static final int INCREMENTAL_IDLE = 1;
public static final int CONTINUOUS_RUNNING = 2;
public static final int INCREMENTAL_UPDATING = 3;
private static final int TRACK_HEIGHT;
private static final int THUMB_WIDTH;
private static final int THUMB_HEIGHT;
private static final Font FONT;
static
{
int b;
int c = RasterCanvas.getElementOfGUISizes(11, 0, 0);
TRACK_HEIGHT = (b = RasterCanvas.getElementOfGUISizes(11, 3, 0) >> 16) == -1 ? 8 : b;
THUMB_WIDTH = (b = (short) c) == -1 ? 8 : b;
THUMB_HEIGHT = (b = c >> 16) == -1 ? 16 : b;
FONT = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
}
private boolean controlFocused;
private boolean sliderFocused;
private boolean interactive;
private boolean newInput;
private boolean pressed;
private int contentWidth;
private int argument;
private long fields;
private TextOutput output;
public Gauge(String label, boolean interactive, int maximum, int position)
{
this(LAYOUT_DEFAULT, -1, -1, label, null, null, null, interactive, maximum, position);
}
public Gauge(int layout, int lockedWidth, int lockedHeight, String label,
Command[] commands, Command defaultCommand, ItemCommandListener listener,
boolean interactive, int maximum, int position)
{
super(layout, lockedWidth, lockedHeight, label, commands, defaultCommand, listener);
boolean f;
if((f = interactive || maximum != INDEFINITE) ?
maximum <= 0 : (position < 0 || position > 3))
{
throw new IllegalArgumentException("Gauge: " +
"неправильные параметры для создания полосы прогресса.");
}
if(f)
{
position = position < 0 ? 0 : (position > maximum ? maximum : position);
}
this.interactive = interactive;
this.newInput = true;
this.fields = (((long) maximum) << 32) | (long) position;
this.output = interactive ? new TextOutput(23) : null;
}
public void setMaxValue(int maximum)
{
boolean needPaint;
int position;
int current;
long fields;
position = (int) (fields = this.fields);
current = (int) (fields >> 32);
if(interactive)
{
if(maximum <= 0)
{
throw new IllegalArgumentException("Gauge.setMaxValue: " +
"параметр maximum для интерактивной полосы прогресса может быть " +
"только положительным.");
}
} else
{
if(maximum <= 0 && maximum != INDEFINITE)
{
throw new IllegalArgumentException("Gauge.setMaxValue: " +
"параметр maximum для неинтерактивной полосы прогресса может быть " +
"положительным или равняться специальному значению INDEFINITE.");
}
if(current > 0 && maximum == INDEFINITE)
{
setFields(INDEFINITE, CONTINUOUS_IDLE);
notifyPaint();
return;
}
if(current == INDEFINITE)
{
if(maximum > 0)
{
if(isVisible() && position == CONTINUOUS_RUNNING)
{
stopUpdating();
}
setFields(maximum, 0);
notifyPaint();
}
return;
}
}
needPaint = false;
if(position > maximum)
{
needPaint = true;
position = maximum;
}
if(current != maximum || needPaint)
{
setFields(maximum, position);
notifyPaint();
}
}
public void setValue(int position)
{
int current;
int maximum;
long fields;
current = (int) (fields = this.fields);
maximum = (int) (fields >> 32);
if(interactive || maximum != INDEFINITE)
{
position = position < 0 ? 0 : (position > maximum ? maximum : position);
}
else if(position < 0 || position > 3)
{
throw new IllegalArgumentException("Gauge.setValue: " +
"недопустимое значение параметра position для неинтерактивной " +
"неопределённой полосы прогресса.");
}
if(current != position)
{
if(isVisible() && maximum == INDEFINITE)
{
if(position == CONTINUOUS_RUNNING)
{
startUpdating();
} else
{
stopUpdating();
}
}
setFields(maximum, position);
notifyPaint();
}
}
public boolean isInteractive()
{
return interactive;
}
public int getMaxValue()
{
return (int) (fields >> 32);
}
public int getValue()
{
return (int) fields;
}
void paintContent(Graphics render, int contentWidth, int contentHeight)
{
boolean focused;
double dtw;
int itw;
int i;
int len;
int position;
int maximum;
long fields;
char[] chars;
TextOutput output;
focused = controlFocused;
position = (int) (fields = this.fields);
maximum = (int) (fields >> 32);
if(interactive)
{
(output = this.output).clear();
output.append(position, 10, true);
output.append(" / ");
output.append(maximum, 10, true);
chars = output.getChars();
len = output.getLength();
render.drawElementOfGUI(11, 3, focused ? 1 : 0,
(THUMB_WIDTH / 2) - 1, (THUMB_HEIGHT - TRACK_HEIGHT) / 2,
contentWidth - THUMB_WIDTH + 2, TRACK_HEIGHT);
render.drawElementOfGUI(11, 0, focused ? (pressed ? 1 : 3) : 0,
(int) (((long) position) * ((long) (contentWidth - THUMB_WIDTH)) /
(long) maximum), 0, THUMB_WIDTH, THUMB_HEIGHT);
render.setFont(FONT);
render.setColor(RasterCanvas.getSystemColor(0x28));
render.drawChars(chars, 0, len,
Math.max(contentWidth - FONT.charsWidth(chars, 0, len), 0), THUMB_HEIGHT,
Graphics.LEFT | Graphics.TOP);
return;
}
if(maximum > 0)
{
render.drawElementOfGUI(9, 0, 0, 0, 0, contentWidth, contentHeight);
render.drawElementOfGUI(9, 1, 0, 2, 2,
(int) (((long) position) * ((long) (contentWidth - 4)) / (long) maximum),
contentHeight - 4);
return;
}
switch(position)
{
default:
return;
case CONTINUOUS_IDLE:
case INCREMENTAL_IDLE:
itw = (int) (dtw = (1.d / 7.d) * ((double) (contentWidth - 4)));
render.drawElementOfGUI(9, 0, 0, 0, 0, contentWidth, contentHeight);
for(i = 1; i < 7; i += 2)
{
render.drawElementOfGUI(9, 1, 0, ((int) (dtw * (double) i)) + 2, 2,
itw, contentHeight - 4);
}
return;
case CONTINUOUS_RUNNING:
itw = (contentWidth - 4) / 5;
render.drawElementOfGUI(9, 0, 0, 0, 0, contentWidth, contentHeight);
render.drawElementOfGUI(9, 1, 0,
((int) Math.round(0.5d * ((double) (contentWidth - itw - 4)) *
(1.d + Math.sin((0.0625d * Math.PI) * (double) argument)))) + 2, 2,
itw, contentHeight - 4);
return;
case INCREMENTAL_UPDATING:
itw = (contentWidth - 4) / 5;
render.drawElementOfGUI(9, 0, 0, 0, 0, contentWidth, contentHeight);
render.drawElementOfGUI(9, 1, 0, ((contentWidth - itw - 4) / 2) + 2, 2,
itw, contentHeight - 4);
return;
}
}
void onUpdate()
{
argument = (argument + 1) & 0x1f;
}
void onShow()
{
if(fields == ((((long) INDEFINITE) << 32) | (long) CONTINUOUS_RUNNING))
{
startUpdating();
}
}
void onHide()
{
if(fields == ((((long) INDEFINITE) << 32) | (long) CONTINUOUS_RUNNING))
{
stopUpdating();
}
}
void onSizeChanged(int contentWidth, int contentHeight)
{
this.contentWidth = contentWidth;
}
void onKeyPressed(int key, int charCode)
{
keyHandle(key);
}
void onKeyRepeated(int key, int charCode)
{
keyHandle(key);
}
void onContentPointerPressed(int x, int y, int button)
{
int l;
int newPos;
int position;
int maximum;
long fields;
if((!interactive) || button != MIDletProxy.BUTTON_MAIN)
{
return;
}
if(y < THUMB_HEIGHT)
{
position = (int) (fields = this.fields);
maximum = (int) (fields >> 32);
newInput = true;
l = (int) (((long) position) * ((long) (contentWidth - THUMB_WIDTH)) / (long) maximum);
if(x >= l + THUMB_WIDTH)
{
if((newPos = position + (maximum < 10 ? 1 : maximum / 10)) < 0)
{
newPos = 0;
}
else if(newPos > maximum)
{
newPos = maximum;
}
}
else if(x < l)
{
if((newPos = position - (maximum < 10 ? 1 : maximum / 10)) < 0)
{
newPos = 0;
}
else if(newPos > maximum)
{
newPos = maximum;
}
}
else
{
pressed = true;
notifyPaint();
return;
}
if(newPos != position)
{
setFields(maximum, newPos);
notifyPaint();
super.notifyStateChanged();
}
}
}
void onContentPointerDragged(int x, int y)
{
int w;
int newPos;
int position;
int maximum;
long fields;
if((!interactive) || (!pressed) || (w = contentWidth - THUMB_WIDTH) <= 0)
{
return;
}
position = (int) (fields = this.fields);
maximum = (int) (fields >> 32);
newInput = true;
if((newPos = (int) (((long) (x - (THUMB_WIDTH / 2))) * ((long) maximum) / (long) w)) < 0)
{
newPos = 0;
}
else if(newPos > maximum)
{
newPos = maximum;
}
if(newPos != position)
{
setFields(maximum, newPos);
notifyPaint();
super.notifyStateChanged();
}
}
void onContentPointerReleased(int x, int y, int button)
{
int w;
int newPos;
int position;
int maximum;
long fields;
if((!interactive) || (!pressed) || button != MIDletProxy.BUTTON_MAIN ||
(w = contentWidth - THUMB_WIDTH) <= 0)
{
return;
}
position = (int) (fields = this.fields);
maximum = (int) (fields >> 32);
newInput = true;
pressed = false;
if((newPos = (int) (((long) (x - (THUMB_WIDTH / 2))) * ((long) maximum) / (long) w)) < 0)
{
newPos = 0;
}
else if(newPos > maximum)
{
newPos = maximum;
}
setFields(maximum, newPos);
notifyPaint();
if(newPos != position)
{
super.notifyStateChanged();
}
}
void onTraverseOut()
{
if(!interactive)
{
return;
}
controlFocused = false;
pressed = false;
notifyPaint();
}
boolean onTraverseNeedStayOn(int direction, int viewportWidth, int viewportHeight,
int[] visibleRectangle)
{
boolean cfocused;
int position;
int maximum;
long fields;
if(!interactive)
{
return false;
}
if((cfocused = controlFocused) != (controlFocused = true))
{
newInput = true;
notifyPaint();
}
if(sliderFocused)
{
return true;
}
switch(direction)
{
case Canvas.LEFT:
if(cfocused)
{
position = (int) (fields = this.fields);
maximum = (int) (fields >> 32);
newInput = true;
if(position > 0)
{
setFields(maximum, position - 1);
notifyPaint();
super.notifyStateChanged();
}
}
return true;
case Canvas.RIGHT:
if(cfocused)
{
position = (int) (fields = this.fields);
maximum = (int) (fields >> 32);
newInput = true;
if(position < maximum)
{
setFields(maximum, position + 1);
notifyPaint();
super.notifyStateChanged();
}
}
return true;
case Canvas.UP:
case Canvas.DOWN:
return !cfocused;
}
return true;
}
boolean keyHandling(int key)
{
int keyCode;
return (keyCode = MIDletProxy.getInstance().getKeyCode(key)) >= Canvas.KEY_NUM0 &&
keyCode <= Canvas.KEY_NUM9;
}
boolean isMatchForAlert()
{
return (!interactive) && super.isMatchForAlert();
}
int getPreferredContentWidth(int contentHeight, int containerClientWidth)
{
return containerClientWidth;
}
int getPreferredContentHeight(int contentWidth)
{
return interactive ? FONT.getHeight() + THUMB_HEIGHT : 16;
}
private void setFields(int maximum, int position)
{
fields = (((long) maximum) << 32) | (long) position;
}
private void keyHandle(int key)
{
int digit;
int newPos;
int keyCode;
int position;
int maximum;
long fields;
if(!interactive)
{
return;
}
if((keyCode = MIDletProxy.getInstance().getKeyCode(key)) >= Canvas.KEY_NUM0 &&
keyCode <= Canvas.KEY_NUM9)
{
digit = keyCode - Canvas.KEY_NUM0;
position = (int) (fields = this.fields);
maximum = (int) (fields >> 32);
if((newPos = newInput ? digit : (10 * position) + digit) >= maximum ||
newPos < 0)
{
newPos = maximum;
newInput = true;
} else
{
newInput = false;
}
if(newPos != position)
{
setFields(maximum, newPos);
notifyPaint();
super.notifyStateChanged();
}
}
}
}