/**
* Copyright 2014
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @project loon
* @author cping
* @email:javachenpeng@yahoo.com
* @version 0.4.2
*/
package loon.component;
import loon.LTexture;
import loon.LTextures;
import loon.canvas.LColor;
import loon.component.skin.ScrollBarSkin;
import loon.component.skin.SkinManager;
import loon.event.SysTouch;
import loon.opengl.GLEx;
public class LScrollBar extends LComponent {
public static final int RIGHT = 0;
public static final int BOTTOM = 1;
public static final int LEFT = 2;
public static final int TOP = 3;
protected LScrollContainer scrollContainer;
protected int orientation;
protected int sliderWidth;
protected int sliderHeight;
protected int sliderX;
protected int sliderY;
protected int relativeClickX;
protected int relativeClickY;
private LTexture scrollBar;
private LTexture slider;
protected LColor scrollBarColor = LColor.white.darker();
protected LColor sliderColor = LColor.black.darker();
protected int sliderMargin = 3;
protected float offsetX, offsetY;
protected final int MAX_SLIDER_SIZE = 20;
public LScrollBar(int orientation) {
this(orientation, 0, 0, 150, 30);
}
public LScrollBar(int orientation, int x, int y, int width, int height) {
this(SkinManager.get().getScrollBarSkin().getScrollBarTexture(),
SkinManager.get().getScrollBarSkin().getSliderTexture(), orientation, x, y, width, height);
}
public LScrollBar(String patha, String pathb, int orientation, int x, int y, int width, int height) {
this(LTextures.loadTexture(patha), LTextures.loadTexture(pathb), orientation, x, y, width, height);
}
public LScrollBar(ScrollBarSkin skin, int orientation, int x, int y, int width, int height) {
this(skin.getScrollBarTexture(), skin.getSliderTexture(), x, y, orientation, width, height);
}
public LScrollBar(LTexture a, LTexture b, int orientation, int x, int y, int width, int height) {
super(x, y, width, height);
this.orientation = orientation;
this.scrollBar = a;
this.slider = b;
}
public void setScrollContainer(LScrollContainer scrollContainer) {
this.scrollContainer = scrollContainer;
adjustScrollbar();
}
public void adjustScrollbar() {
switch (getOrientation()) {
case LScrollBar.TOP:
initHorizontalTopScrollBar();
break;
case LScrollBar.RIGHT:
initVerticalRightScrollBar();
break;
case LScrollBar.BOTTOM:
initHorizontalBottomScrollBar();
break;
case LScrollBar.LEFT:
initVerticalLeftScrollBar();
break;
}
}
public void adjustSlider() {
switch (getOrientation()) {
case LScrollBar.TOP:
adjustHorizontalTopSlider();
break;
case LScrollBar.RIGHT:
adjustVerticalRightSlider();
break;
case LScrollBar.BOTTOM:
adjustHorizontalBottomSlider();
break;
case LScrollBar.LEFT:
adjustVerticalLeftSlider();
break;
}
}
private void initVerticalLeftScrollBar() {
setHeight(scrollContainer.getHeight());
int width = (int) (scrollContainer.getWidth() * 0.07);
setWidth(width > MAX_SLIDER_SIZE ? MAX_SLIDER_SIZE : width);
setX(scrollContainer.getX() - getWidth());
setY(scrollContainer.getY());
adjustVerticalLeftSlider();
}
public void adjustSlider(int sliderX, int sliderY, int sliderWidth, int sliderHeight) {
setSliderX(sliderX);
setSliderY(sliderY);
setSliderWidth(sliderWidth);
setSliderHeight(sliderHeight);
}
public void adjustSlider(int sliderWidth, int sliderHeight) {
adjustSlider(x() + getSliderMargin(), y() + getSliderMargin(), sliderWidth, sliderHeight);
}
private void adjustVerticalLeftSlider() {
setSliderWidth((int) (getWidth() - (getSliderMargin() * 2)) + 1);
setSliderX(x() + getSliderMargin());
setSliderY(y() + getSliderMargin());
float ratioHeight = scrollContainer.getHeight() / scrollContainer.getInnerHeight();
ratioHeight = ratioHeight > 1 ? 1 : ratioHeight;
setSliderHeight((int) ((ratioHeight * getHeight()) - (getSliderMargin() * 2)) + 1);
}
private void initVerticalRightScrollBar() {
int width = (int) (scrollContainer.getWidth() * 0.07);
setWidth(width > MAX_SLIDER_SIZE ? MAX_SLIDER_SIZE : width);
setX(scrollContainer.getX() + scrollContainer.getWidth() - width);
setY(scrollContainer.getY());
setHeight(scrollContainer.getHeight());
adjustVerticalRightSlider();
}
private void adjustVerticalRightSlider() {
setSliderWidth((int) (getWidth() - (getSliderMargin() * 2)) + 1);
setSliderX(x() + getSliderMargin());
setSliderY(y() + getSliderMargin());
float ratioHeight = getHeight() / scrollContainer.getInnerHeight();
ratioHeight = ratioHeight > 1 ? 1 : ratioHeight;
setSliderHeight((int) ((ratioHeight * getHeight()) - (getSliderMargin() * 2)) + 1);
}
private void initHorizontalTopScrollBar() {
setWidth(scrollContainer.getWidth());
int height = (int) (scrollContainer.getWidth() * 0.07);
setHeight(height > MAX_SLIDER_SIZE ? MAX_SLIDER_SIZE : height);
setX(scrollContainer.getX());
setY(scrollContainer.getY() - getHeight());
adjustHorizontalTopSlider();
}
private void adjustHorizontalTopSlider() {
setSliderHeight((int) (getHeight() - (getSliderMargin() * 2)) + 1);
setSliderX(x() + getSliderMargin());
setSliderY(y() + getSliderMargin());
float ratioWidth = getWidth() / scrollContainer.getInnerWidth();
ratioWidth = ratioWidth > 1 ? 1 : ratioWidth;
setSliderWidth((int) ((ratioWidth * getWidth()) - (getSliderMargin() * 2)) + 1);
}
private void initHorizontalBottomScrollBar() {
int height = (int) (scrollContainer.getWidth() * 0.07);
setHeight(height > MAX_SLIDER_SIZE ? MAX_SLIDER_SIZE : height);
setX(scrollContainer.getX());
setY(scrollContainer.getY() + scrollContainer.getHeight() - getHeight());
setWidth(scrollContainer.getWidth());
adjustHorizontalBottomSlider();
}
private void adjustHorizontalBottomSlider() {
setSliderHeight((int) (getHeight() - (getSliderMargin() * 2)) + 1);
setSliderX(x() + getSliderMargin());
setSliderY(y() + getSliderMargin());
float ratioWidth = getWidth() / scrollContainer.getInnerWidth();
ratioWidth = ratioWidth > 1 ? 1 : ratioWidth;
setSliderWidth((int) ((ratioWidth * getWidth()) - (getSliderMargin() * 2)) + 1);
}
@Override
public void setSize(int w, int h) {
super.setSize(w, h);
adjustSlider();
}
public void update(final long elapsedTime) {
super.update(elapsedTime);
if (SysTouch.isDrag()) {
if (isPointInUI(getTouchX(), getTouchY())) {
touchDragged(getUITouchX(), getUITouchY());
}
}
if (SysTouch.isDown()) {
if (isPointInUI(getTouchX(), getTouchY())) {
touchDown(getUITouchX(), getUITouchY());
}
}
}
public int getOrientation() {
return orientation;
}
public int getSliderWidth() {
return sliderWidth;
}
protected void setSliderWidth(int sliderWidth) {
this.sliderWidth = sliderWidth;
}
public int getSliderHeight() {
return sliderHeight;
}
public void setSliderHeight(int sliderHeight) {
this.sliderHeight = sliderHeight;
}
public int getSliderX() {
return sliderX;
}
protected void setSliderX(int sliderX) {
this.sliderX = sliderX;
}
public int getSliderY() {
return sliderY;
}
protected void setSliderY(int sliderY) {
this.sliderY = sliderY;
}
public LColor getScrollBarColor() {
return scrollBarColor;
}
public void setScrollBarColor(LColor scrollBarColor) {
this.scrollBarColor = scrollBarColor;
}
public LColor getSliderColor() {
return sliderColor;
}
public void setSliderColor(LColor sliderColor) {
this.sliderColor = sliderColor;
}
public int getSliderMargin() {
return sliderMargin;
}
public void setSliderMargin(int sliderMargin) {
this.sliderMargin = sliderMargin;
}
@Override
protected void processTouchDragged() {
super.processTouchDragged();
if (isPointInUI(getTouchX(), getTouchY())) {
touchDragged(getUITouchX(), getUITouchY());
}
}
@Override
protected void processTouchPressed() {
super.processKeyPressed();
if (isPointInUI(getTouchX(), getTouchY())) {
touchDown(getUITouchX(), getUITouchY());
}
}
@Override
protected void processTouchReleased() {
super.processTouchReleased();
if (isPointInUI(getTouchX(), getTouchY())) {
touchDown(getUITouchX(), getUITouchY());
}
}
public boolean touchDown(float screenX, float screenY) {
if (scrollContainer != null) {
relativeClickX = (int) (screenX - (x() + getSliderX() + scrollContainer.x()));
relativeClickY = (int) (screenY - (y() + getSliderY() + scrollContainer.y()));
return true;
}
return false;
}
public boolean touchDragged(float screenX, float screenY) {
if (scrollContainer != null) {
int rClickX = (int) (screenX - (x() + scrollContainer.x()));
int rClickY = (int) (screenY - (y() + scrollContainer.y()));
rClickX -= relativeClickX;
rClickY -= relativeClickY;
moveSlider(rClickX, rClickY);
return true;
}
return false;
}
protected void moveSlider(int dX, int dY) {
if (orientation == LEFT || orientation == RIGHT) {
moveVerticalSlider(dY);
} else {
moveHorizontalSlider(dX);
}
}
protected void moveVerticalSlider(int newY) {
int minY = y() + getSliderMargin();
int maxY = (int) (y() + getHeight() - (getSliderHeight() + getSliderMargin()));
if (newY < minY) {
setSliderY(minY);
} else if (newY > maxY) {
setSliderY(maxY);
} else {
setSliderY(newY);
}
updateScrollContainerY();
}
protected void updateScrollContainerY() {
float ratio = (float) ((scrollContainer.getInnerHeight()) - scrollContainer.getHeight())
/ (getHeight() - getSliderHeight() - (getSliderMargin() * 2));
if (Float.isNaN(ratio) || Float.isInfinite(ratio)) {
ratio = 0f;
}
int relativeSliderY = getSliderY() - (y() + getSliderMargin());
scrollContainer.moveScrollY((int) (relativeSliderY * ratio));
}
protected void moveHorizontalSlider(int newX) {
int minX = x() + getSliderMargin();
int maxX = (int) (x() + getWidth() - (getSliderWidth() + getSliderMargin()));
if (newX < minX) {
setSliderX(minX);
} else if (newX > maxX) {
setSliderX(maxX);
} else {
setSliderX(newX);
}
updateScrollContainerX();
}
protected void updateScrollContainerX() {
float ratio = ((scrollContainer.getInnerWidth()) - getWidth())
/ (getWidth() - getSliderWidth() - (getSliderMargin() * 2));
if (Double.isNaN(ratio) || Double.isInfinite(ratio)) {
ratio = 0.0f;
}
int relativeSliderX = getSliderX() - (x() + getSliderMargin());
scrollContainer.moveScrollX((int) (relativeSliderX * ratio));
}
@Override
public void setX(float x) {
super.setX(x);
adjustSlider();
}
@Override
public void setY(float y) {
super.setY(y);
adjustSlider();
}
@Override
public void setWidth(float width) {
super.setWidth(width);
adjustSlider();
}
@Override
public void setHeight(float height) {
super.setHeight(height);
adjustSlider();
}
@Override
public void createUI(GLEx g, int x, int y, LComponent component, LTexture[] buttonImage) {
if (scrollBar == null || slider == null) {
g.fillRect(x - 1 + offsetX, y - 1 + offsetY, getWidth() + 2, getHeight() + 2, scrollBarColor);
g.fillRect(sliderX - 1 + offsetX, sliderY - 1 + offsetY, sliderWidth, sliderHeight, sliderColor);
} else {
g.draw(scrollBar, x - 1 + offsetX, y - 1 + offsetY, getWidth() + 2, getHeight() + 2, baseColor);
g.draw(slider, sliderX - 1 + offsetX, sliderY - 1 + offsetY, sliderWidth, sliderHeight, baseColor);
}
}
public void paint(GLEx g) {
createUI(g, x(), y(), null, null);
}
public float getOffsetX() {
return offsetX;
}
public void setOffsetX(float offsetX) {
this.offsetX = offsetX;
}
public float getOffsetY() {
return offsetY;
}
public void setOffsetY(float offsetY) {
this.offsetY = offsetY;
}
@Override
public String getUIName() {
return "ScrollBar";
}
}