/*
Реализация спецификаций 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.*;
public abstract class ScrollingScreen extends Screen
{
private static final class ScrollBar extends WeakReference
implements javax.microedition.lcdui.ScrollBar
{
private static int correctPosition(int position, int page, int range)
{
return Math.max(0, Math.min(range - page, position));
}
private boolean visible;
private int kind;
private int range;
private int position;
public ScrollBar(ScrollingScreen thisScreen, boolean visible, int kind)
{
super(thisScreen);
this.visible = visible;
this.kind = kind;
}
public void repaintOwner()
{
ScrollingScreen thisScreen;
if((thisScreen = (ScrollingScreen) get()) == null)
{
return;
}
thisScreen.callSeriallyPaintScreen(ScrollingScreen.CLIENT);
}
public void hide()
{
setVisible(false);
}
public void show()
{
setVisible(true);
}
public void setVisible(boolean visible)
{
ScrollingScreen thisScreen;
if(this.visible == visible)
{
return;
}
this.visible = visible;
if((thisScreen = (ScrollingScreen) get()) == null)
{
return;
}
thisScreen.callSeriallySizeChanged();
(kind == HORIZONTAL ? thisScreen.vertScrollBar :
thisScreen.horzScrollBar).recomputePosition(thisScreen);
thisScreen.callSeriallyPaintScreen(CLIENT);
}
public void setPosition(int position)
{
ScrollingScreen thisScreen;
if((thisScreen = (ScrollingScreen) get()) == null)
{
this.position = 0;
return;
}
if(this.position == (position = correctPosition(position, kind == HORIZONTAL ?
thisScreen.getClientWidth() : thisScreen.getClientHeight(), this.range)))
{
return;
}
this.position = position;
thisScreen.callSeriallyScroll();
}
public void setRange(int range)
{
ScrollingScreen thisScreen;
if(range < 0)
{
range = 0;
}
if(this.range == range)
{
return;
}
this.range = range;
if((thisScreen = (ScrollingScreen) get()) == null)
{
this.position = 0;
return;
}
recomputePosition(thisScreen, range);
thisScreen.callSeriallyPaintScreen(CLIENT);
}
public void scroll(int delta)
{
setPosition(position + delta);
}
public boolean isVisible()
{
return visible;
}
public int getPosition()
{
return position;
}
public int getRange()
{
return range;
}
public int getPage()
{
ScrollingScreen thisScreen;
return (thisScreen = (ScrollingScreen) get()) != null ? (kind == HORIZONTAL ?
thisScreen.getClientWidth() : thisScreen.getClientHeight()) : range;
}
private void recomputePosition(ScrollingScreen scr)
{
int position;
if((position = this.position) == (this.position = correctPosition(position,
kind == HORIZONTAL ? scr.getClientWidth() : scr.getClientHeight(), range)))
{
return;
}
scr.callSeriallyScroll();
}
private void recomputePosition(ScrollingScreen scr, int range)
{
int position;
if((position = this.position) == (this.position = correctPosition(position,
kind == HORIZONTAL ? scr.getClientWidth() : scr.getClientHeight(), range)))
{
return;
}
scr.callSeriallyScroll();
}
}
private static final class ScrollEvent extends Object
implements Runnable
{
private ScrollingScreen thisScreen;
ScrollEvent(ScrollingScreen thisScreen)
{
this.thisScreen = thisScreen;
}
public void run()
{
ScrollingScreen thisScreen;
(thisScreen = this.thisScreen).stayScroll = false;
if(!thisScreen.isReallyShown())
{
thisScreen.needScroll = true;
return;
}
thisScreen.needScroll = false;
thisScreen.onScroll(thisScreen.getHorzScrollBar(), thisScreen.getVertScrollBar());
thisScreen.callSeriallyPaintScreen(CLIENT);
}
}
static final int NONE = 0;
static final int HORIZONTAL = 1;
static final int VERTICAL = 2;
static final int BOTH = 3;
private static final int FOCUSED_CLIENT_OUT = -1;
private static final int FOCUSED_NONE = 0;
private static final int FOCUSED_CLIENT = 1;
private static final int FOCUSED_HORZ_SCROLL_BAR = 2;
private static final int FOCUSED_VERT_SCROLL_BAR = 3;
private static ScrollBarStyle getScrollBarStyle()
{
ScrollBarStyle result;
try
{
result = (ScrollBarStyle) Class.forName(System.getSystemProperty(
"malik.emulator.microedition.scrollbar.style")).newInstance();
}
catch(Exception e)
{
result = new ScrollBarDefault();
}
return result;
}
private boolean needScroll;
private boolean stayScroll;
private boolean shiftPressed;
private int focused;
private int hbutton;
private ScrollBar horzScrollBar;
private ScrollBar vertScrollBar;
private ScrollBarStyle style;
ScrollingScreen(boolean system, boolean fullScreenMode, String title, Ticker ticker,
Command[] commands, Command defaultCommand, CommandListener listener,
int scrollbars)
{
this(system, fullScreenMode, title, ticker, commands, defaultCommand, listener,
scrollbars, getScrollBarStyle());
}
ScrollingScreen(boolean system, boolean fullScreenMode, String title, Ticker ticker,
Command[] commands, Command defaultCommand, CommandListener listener,
int scrollbars, ScrollBarStyle style)
{
super(system, fullScreenMode, title, ticker, commands, defaultCommand, listener);
this.needScroll = true;
this.horzScrollBar = new ScrollBar(this, (scrollbars & HORIZONTAL) != 0, HORIZONTAL);
this.vertScrollBar = new ScrollBar(this, (scrollbars & VERTICAL) != 0, VERTICAL);
this.style = style == null ? new ScrollBarDefault() : style;
}
public final void scroll(int deltaX, int deltaY)
{
horzScrollBar.scroll(deltaX);
vertScrollBar.scroll(deltaY);
}
public final void scrollTo(int x, int y)
{
horzScrollBar.setPosition(x);
vertScrollBar.setPosition(y);
}
public final javax.microedition.lcdui.ScrollBar getHorzScrollBar()
{
return horzScrollBar;
}
public final javax.microedition.lcdui.ScrollBar getVertScrollBar()
{
return vertScrollBar;
}
abstract void paint(Graphics render, javax.microedition.lcdui.ScrollBar horzScrollBar,
javax.microedition.lcdui.ScrollBar vertScrollBar);
void onShow()
{
super.onShow();
if(needScroll)
{
callSeriallyScroll();
}
focused = FOCUSED_NONE;
shiftPressed = false;
}
void onHide()
{
shiftPressed = false;
focused = FOCUSED_NONE;
super.onHide();
}
void onKeyPressed(int key, int charCode)
{
if((!super.keyHandling(key)) && (key == MIDletProxy.KEY_SHIFT ||
key == MIDletProxy.KEY_LSHIFT || key == MIDletProxy.KEY_RSHIFT))
{
shiftPressed = true;
}
super.onKeyPressed(key, charCode);
}
void onKeyReleased(int key)
{
if((!super.keyHandling(key)) && (key == MIDletProxy.KEY_SHIFT ||
key == MIDletProxy.KEY_LSHIFT || key == MIDletProxy.KEY_RSHIFT))
{
shiftPressed = false;
}
super.onKeyReleased(key);
}
boolean keyHandling(int key)
{
return key == MIDletProxy.KEY_SHIFT || key == MIDletProxy.KEY_LSHIFT ||
key == MIDletProxy.KEY_RSHIFT || super.keyHandling(key);
}
boolean coordinateHandling(int x, int y)
{
int l;
int t;
Display display = MIDletProxy.getInstance().getEmulatorScreen();
return x >= (l = display.getGUIElementLeft(this, GUI_ELEMENT_CLIENT)) &&
x < l + display.getGUIElementWidth(this, GUI_ELEMENT_CLIENT) &&
y >= (t = display.getGUIElementTop(this, GUI_ELEMENT_CLIENT)) &&
y < t + display.getGUIElementHeight(this, GUI_ELEMENT_CLIENT) ||
super.coordinateHandling(x, y);
}
int getMarginRight()
{
return super.getMarginRight() + (vertScrollBar.isVisible() ? getVertScrollBarWidth() : 0);
}
int getMarginBottom()
{
return super.getMarginBottom() + (horzScrollBar.isVisible() ? getHorzScrollBarWidth() : 0);
}
void paintHorzScrollBar(Graphics clientRender, javax.microedition.lcdui.ScrollBar scrollbar,
int length, int width)
{
style.paintHorzScrollBar(clientRender, scrollbar, length, width);
}
void paintVertScrollBar(Graphics clientRender, javax.microedition.lcdui.ScrollBar scrollbar,
int length, int width)
{
style.paintVertScrollBar(clientRender, scrollbar, length, width);
}
void onScroll(javax.microedition.lcdui.ScrollBar horzScrollBar,
javax.microedition.lcdui.ScrollBar vertScrollBar)
{
}
void onClientPointerPressed(int x, int y, int button)
{
}
void onClientPointerDragged(int x, int y)
{
}
void onClientPointerReleased(int x, int y, int button)
{
}
void onHorzScrollBarPointerPressed(javax.microedition.lcdui.ScrollBar scrollbar,
int length, int width, int x, int y, int button)
{
style.onHorzScrollBarPointerPressed(scrollbar, length, width, x, y, button);
}
void onHorzScrollBarPointerDragged(javax.microedition.lcdui.ScrollBar scrollbar,
int length, int width, int x, int y)
{
style.onHorzScrollBarPointerDragged(scrollbar, length, width, x, y);
}
void onHorzScrollBarPointerReleased(javax.microedition.lcdui.ScrollBar scrollbar,
int length, int width, int x, int y, int button)
{
style.onHorzScrollBarPointerReleased(scrollbar, length, width, x, y, button);
}
void onVertScrollBarPointerPressed(javax.microedition.lcdui.ScrollBar scrollbar,
int length, int width, int x, int y, int button)
{
style.onVertScrollBarPointerPressed(scrollbar, length, width, x, y, button);
}
void onVertScrollBarPointerDragged(javax.microedition.lcdui.ScrollBar scrollbar,
int length, int width, int x, int y)
{
style.onVertScrollBarPointerDragged(scrollbar, length, width, x, y);
}
void onVertScrollBarPointerReleased(javax.microedition.lcdui.ScrollBar scrollbar,
int length, int width, int x, int y, int button)
{
style.onVertScrollBarPointerReleased(scrollbar, length, width, x, y, button);
}
int getHorzScrollBarWidth()
{
return style.getHorzScrollBarWidth();
}
int getVertScrollBarWidth()
{
return style.getVertScrollBarWidth();
}
final void paint(Graphics render)
{
int horzPos;
int vertPos;
int clientLeft;
int clientTop;
int clientWidth;
int clientHeight;
int horzWidth;
int vertWidth;
ScrollBar horz = horzScrollBar;
ScrollBar vert = vertScrollBar;
horzPos = horz.getPosition();
vertPos = vert.getPosition();
clientLeft = getClientLeft();
clientTop = getClientTop();
clientWidth = getClientWidth();
clientHeight = getClientHeight();
horzWidth = getHorzScrollBarWidth();
vertWidth = getVertScrollBarWidth();
try
{
render.translate(-horzPos, -vertPos);
render.setClip(horzPos, vertPos, clientWidth, clientHeight);
paint(render, horz, vert);
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
if(horz.isVisible())
{
try
{
render.reset();
render.translate(clientLeft, clientTop + clientHeight);
render.setClip(0, 0, clientWidth, horzWidth);
paintHorzScrollBar(render, horz, clientWidth, horzWidth);
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
if(vert.isVisible())
{
try
{
render.reset();
render.translate(clientLeft + clientWidth, clientTop);
render.setClip(0, 0, vertWidth, clientHeight);
paintVertScrollBar(render, vert, clientHeight, vertWidth);
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
}
final void onPointerPressed(int x, int y, int button)
{
int l;
int t;
int horzWidth;
int vertWidth;
int clientLeft;
int clientTop;
int clientWidth;
int clientHeight;
int clientRight;
int clientBottom;
Display display;
ScrollBar horz = horzScrollBar;
ScrollBar vert = vertScrollBar;
ScrollBar scrollbar = shiftPressed ? horz : (vert.isVisible() ? vert : horz);
switch(button)
{
case MIDletProxy.BUTTON_WHEEL_UP:
scrollbar.scroll(-scrollbar.getPage() / 4);
return;
case MIDletProxy.BUTTON_WHEEL_DOWN:
scrollbar.scroll(scrollbar.getPage() / 4);
return;
}
display = MIDletProxy.getInstance().getEmulatorScreen();
if(focused == FOCUSED_NONE && (!super.coordinateHandling(x, y)) &&
x >= (l = display.getGUIElementLeft(this, GUI_ELEMENT_CLIENT)) &&
x < l + display.getGUIElementWidth(this, GUI_ELEMENT_CLIENT) &&
y >= (t = display.getGUIElementTop(this, GUI_ELEMENT_CLIENT)) &&
y < t + display.getGUIElementHeight(this, GUI_ELEMENT_CLIENT))
{
hbutton = button;
x -= l;
y -= t;
horzWidth = getHorzScrollBarWidth();
vertWidth = getVertScrollBarWidth();
clientRight = (clientLeft = getClientLeft()) + (clientWidth = getClientWidth());
clientBottom = (clientTop = getClientTop()) + (clientHeight = getClientHeight());
if(x >= clientLeft && x < clientRight && y >= clientTop && y < clientBottom)
{
focused = FOCUSED_CLIENT;
onClientPointerPressed(
x - clientLeft + horz.getPosition(),
y - clientTop + vert.getPosition(), button);
return;
}
if((scrollbar = horz).isVisible() &&
x >= clientLeft && x < clientRight &&
y >= clientBottom && y < clientBottom + horzWidth)
{
focused = FOCUSED_HORZ_SCROLL_BAR;
onHorzScrollBarPointerPressed(scrollbar,
clientWidth, horzWidth,
x - clientLeft, y - clientBottom, button);
return;
}
if((scrollbar = vert).isVisible() &&
y >= clientTop && y < clientBottom &&
x >= clientRight && x < clientRight + vertWidth)
{
focused = FOCUSED_VERT_SCROLL_BAR;
onVertScrollBarPointerPressed(scrollbar,
clientHeight, vertWidth,
x - clientRight, y - clientTop, button);
return;
}
focused = FOCUSED_CLIENT_OUT;
return;
}
super.onPointerPressed(x, y, button);
}
final void onPointerDragged(int x, int y)
{
int f;
int clientLeft;
int clientTop;
int clientWidth;
int clientHeight;
int clientRight;
int clientBottom;
Display display;
if((f = focused) != FOCUSED_NONE)
{
display = MIDletProxy.getInstance().getEmulatorScreen();
x -= display.getGUIElementLeft(this, GUI_ELEMENT_CLIENT);
y -= display.getGUIElementTop(this, GUI_ELEMENT_CLIENT);
clientRight = (clientLeft = getClientLeft()) + (clientWidth = getClientWidth());
clientBottom = (clientTop = getClientTop()) + (clientHeight = getClientHeight());
switch(f)
{
default:
return;
case FOCUSED_CLIENT:
onClientPointerDragged(
x - clientLeft + horzScrollBar.getPosition(),
y - clientTop + vertScrollBar.getPosition());
return;
case FOCUSED_HORZ_SCROLL_BAR:
onHorzScrollBarPointerDragged(horzScrollBar,
clientWidth, getHorzScrollBarWidth(),
x - clientLeft, y - clientBottom);
return;
case FOCUSED_VERT_SCROLL_BAR:
onVertScrollBarPointerDragged(vertScrollBar,
clientHeight, getVertScrollBarWidth(),
x - clientRight, y - clientTop);
return;
}
}
super.onPointerDragged(x, y);
}
final void onPointerReleased(int x, int y, int button)
{
int f;
int clientLeft;
int clientTop;
int clientWidth;
int clientHeight;
int clientRight;
int clientBottom;
Display display;
if((f = focused) != FOCUSED_NONE && hbutton == button)
{
focused = FOCUSED_NONE;
display = MIDletProxy.getInstance().getEmulatorScreen();
x -= display.getGUIElementLeft(this, GUI_ELEMENT_CLIENT);
y -= display.getGUIElementTop(this, GUI_ELEMENT_CLIENT);
clientRight = (clientLeft = getClientLeft()) + (clientWidth = getClientWidth());
clientBottom = (clientTop = getClientTop()) + (clientHeight = getClientHeight());
switch(f)
{
default:
return;
case FOCUSED_CLIENT:
onClientPointerReleased(
x - clientLeft + horzScrollBar.getPosition(),
y - clientTop + vertScrollBar.getPosition(), button);
return;
case FOCUSED_HORZ_SCROLL_BAR:
onHorzScrollBarPointerReleased(horzScrollBar,
clientWidth, getHorzScrollBarWidth(),
x - clientLeft, y - clientBottom, button);
return;
case FOCUSED_VERT_SCROLL_BAR:
onVertScrollBarPointerReleased(vertScrollBar,
clientHeight, getVertScrollBarWidth(),
x - clientRight, y - clientTop, button);
return;
}
}
super.onPointerReleased(x, y, button);
}
final void callSeriallyScroll()
{
if(stayScroll)
{
return;
}
stayScroll = true;
callSerially(new ScrollEvent(this));
}
}