/*******************************************************************************
* This file is part of RedReader.
*
* RedReader is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RedReader is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RedReader. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package org.quantumbadger.redreader.views.imageview;
import org.quantumbadger.redreader.common.MutableFloatPoint2D;
import org.quantumbadger.redreader.views.glview.displaylist.*;
import org.quantumbadger.redreader.views.glview.program.RRGLContext;
import org.quantumbadger.redreader.views.glview.program.RRGLMatrixStack;
public class ImageViewScrollbars extends RRGLRenderable {
private static final float EPSILON = 0.0001f;
private final RRGLRenderableBlend mRenderable;
// Vertical scroll bar
private final RRGLRenderableGroup mVScroll;
private final RRGLRenderableTranslation mVScrollMarkerTranslation;
private final RRGLRenderableScale mVScrollMarkerScale;
private final RRGLRenderableTranslation mVScrollBarTranslation;
private final RRGLRenderableScale mVScrollBarScale;
private final RRGLRenderableTranslation mVScrollBorderTranslation;
private final RRGLRenderableScale mVScrollBorderScale;
// Horizontal scroll bar
private final RRGLRenderableGroup mHScroll;
private final RRGLRenderableTranslation mHScrollMarkerTranslation;
private final RRGLRenderableScale mHScrollMarkerScale;
private final RRGLRenderableTranslation mHScrollBarTranslation;
private final RRGLRenderableScale mHScrollBarScale;
private final RRGLRenderableTranslation mHScrollBorderTranslation;
private final RRGLRenderableScale mHScrollBorderScale;
private final CoordinateHelper mCoordinateHelper;
private int mResX, mResY;
private final int mImageResX, mImageResY;
private final int mDimMarginSides;
private final int mDimMarginEnds;
private final int mDimBarWidth;
private final int mDimBorderWidth;
private long mShowUntil = -1;
private float mCurrentAlpha = 1;
private static final float ALPHA_STEP = 0.05f;
private boolean mIsVisible = true;
public ImageViewScrollbars(RRGLContext glContext, CoordinateHelper coordinateHelper, int imageResX, int imageResY) {
mCoordinateHelper = coordinateHelper;
mImageResX = imageResX;
mImageResY = imageResY;
final RRGLRenderableGroup group = new RRGLRenderableGroup();
mRenderable = new RRGLRenderableBlend(group);
mDimMarginSides = glContext.dpToPixels(10);
mDimMarginEnds = glContext.dpToPixels(20);
mDimBarWidth = glContext.dpToPixels(6);
mDimBorderWidth = glContext.dpToPixels(1);
// Vertical scroll bar
{
mVScroll = new RRGLRenderableGroup();
group.add(mVScroll);
final RRGLRenderableColouredQuad vScrollMarker = new RRGLRenderableColouredQuad(glContext);
final RRGLRenderableColouredQuad vScrollBar = new RRGLRenderableColouredQuad(glContext);
final RRGLRenderableColouredQuad vScrollBorder = new RRGLRenderableColouredQuad(glContext);
vScrollMarker.setColour(1, 1, 1, 0.8f);
vScrollBar.setColour(0, 0, 0, 0.5f);
vScrollBorder.setColour(1, 1, 1, 0.5f);
mVScrollMarkerScale = new RRGLRenderableScale(vScrollMarker);
mVScrollBarScale = new RRGLRenderableScale(vScrollBar);
mVScrollBorderScale = new RRGLRenderableScale(vScrollBorder);
mVScrollMarkerTranslation = new RRGLRenderableTranslation(mVScrollMarkerScale);
mVScrollBarTranslation = new RRGLRenderableTranslation(mVScrollBarScale);
mVScrollBorderTranslation = new RRGLRenderableTranslation(mVScrollBorderScale);
mVScroll.add(mVScrollBorderTranslation);
mVScroll.add(mVScrollBarTranslation);
mVScroll.add(mVScrollMarkerTranslation);
}
// Horizontal scroll bar
{
mHScroll = new RRGLRenderableGroup();
group.add(mHScroll);
final RRGLRenderableColouredQuad hScrollMarker = new RRGLRenderableColouredQuad(glContext);
final RRGLRenderableColouredQuad hScrollBar = new RRGLRenderableColouredQuad(glContext);
final RRGLRenderableColouredQuad hScrollBorder = new RRGLRenderableColouredQuad(glContext);
hScrollMarker.setColour(1, 1, 1, 0.8f);
hScrollBar.setColour(0, 0, 0, 0.5f);
hScrollBorder.setColour(1, 1, 1, 0.5f);
mHScrollMarkerScale = new RRGLRenderableScale(hScrollMarker);
mHScrollBarScale = new RRGLRenderableScale(hScrollBar);
mHScrollBorderScale = new RRGLRenderableScale(hScrollBorder);
mHScrollMarkerTranslation = new RRGLRenderableTranslation(mHScrollMarkerScale);
mHScrollBarTranslation = new RRGLRenderableTranslation(mHScrollBarScale);
mHScrollBorderTranslation = new RRGLRenderableTranslation(mHScrollBorderScale);
mHScroll.add(mHScrollBorderTranslation);
mHScroll.add(mHScrollBarTranslation);
mHScroll.add(mHScrollMarkerTranslation);
}
}
public void update() {
// TODO avoid GC
final MutableFloatPoint2D tmp1 = new MutableFloatPoint2D();
final MutableFloatPoint2D tmp2 = new MutableFloatPoint2D();
mCoordinateHelper.convertScreenToScene(tmp1, tmp2);
final float xStart = tmp2.x / (float)mImageResX;
final float yStart = tmp2.y / (float)mImageResY;
tmp1.set(mResX, mResY);
mCoordinateHelper.convertScreenToScene(tmp1, tmp2);
final float xEnd = tmp2.x / (float)mImageResX;
final float yEnd = tmp2.y / (float)mImageResY;
// Vertical scroll bar
if(yStart < EPSILON && yEnd > 1-EPSILON) {
mVScroll.hide();
} else {
mVScroll.show();
final float vScrollTotalHeight = mResY - 2 * mDimMarginEnds;
final float vScrollHeight = (yEnd - yStart) * vScrollTotalHeight;
final float vScrollTop = yStart * vScrollTotalHeight + mDimMarginEnds;
final float vScrollLeft = mResX - mDimBarWidth - mDimMarginSides;
mVScrollBorderTranslation.setPosition(vScrollLeft - mDimBorderWidth, mDimMarginEnds - mDimBorderWidth);
mVScrollBorderScale.setScale(mDimBarWidth + 2 * mDimBorderWidth, vScrollTotalHeight + 2 * mDimBorderWidth);
mVScrollBarTranslation.setPosition(vScrollLeft, mDimMarginEnds);
mVScrollBarScale.setScale(mDimBarWidth, vScrollTotalHeight);
mVScrollMarkerTranslation.setPosition(vScrollLeft, vScrollTop);
mVScrollMarkerScale.setScale(mDimBarWidth, vScrollHeight);
}
// Horizontal scroll bar
if(xStart < EPSILON && xEnd > 1-EPSILON) {
mHScroll.hide();
} else {
mHScroll.show();
final float hScrollTotalWidth = mResX - 2 * mDimMarginEnds;
final float hScrollWidth = (xEnd - xStart) * hScrollTotalWidth;
final float hScrollLeft = xStart * hScrollTotalWidth + mDimMarginEnds;
final float hScrollTop = mResY - mDimBarWidth - mDimMarginSides;
mHScrollBorderTranslation.setPosition(mDimMarginEnds - mDimBorderWidth, hScrollTop - mDimBorderWidth);
mHScrollBorderScale.setScale(hScrollTotalWidth + 2 * mDimBorderWidth, mDimBarWidth + mDimBorderWidth * 2);
mHScrollBarTranslation.setPosition(mDimMarginEnds, hScrollTop);
mHScrollBarScale.setScale(hScrollTotalWidth, mDimBarWidth);
mHScrollMarkerTranslation.setPosition(hScrollLeft, hScrollTop);
mHScrollMarkerScale.setScale(hScrollWidth, mDimBarWidth);
}
}
public synchronized void setResolution(int x, int y) {
mResX = x;
mResY = y;
}
@Override
public void onAdded() {
super.onAdded();
mRenderable.onAdded();
}
@Override
public void onRemoved() {
mRenderable.onRemoved();
super.onRemoved();
}
@Override
public synchronized boolean isAnimating() {
return mIsVisible;
}
public synchronized void showBars() {
mShowUntil = System.currentTimeMillis() + 600;
mIsVisible = true;
mCurrentAlpha = 1;
}
@Override
protected synchronized void renderInternal(RRGLMatrixStack stack, long time) {
if(mIsVisible && time > mShowUntil) {
mCurrentAlpha -= ALPHA_STEP;
if(mCurrentAlpha < 0) {
mIsVisible = false;
mCurrentAlpha = 0;
}
}
mRenderable.setOverallAlpha(mCurrentAlpha);
mRenderable.startRender(stack, time);
}
}