Java tutorial
/* * Copyright (C) 2014 team-cachebox.de * * Licensed under the : GNU General Public License (GPL); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.gnu.org/licenses/gpl.html * * 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. */ package CB_UI_Base.GL_UI; import java.util.ArrayList; import java.util.Iterator; import CB_Utils.Log.Log; import org.slf4j.LoggerFactory; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import CB_UI_Base.GL_UI.GL_Listener.GL; import CB_UI_Base.Math.CB_RectF; import CB_UI_Base.Math.SizeF; import CB_UI_Base.Math.UI_Size_Base; import CB_Utils.Log.Log; import CB_Utils.Util.MoveableList; public abstract class GL_View_Base extends CB_RectF { final static org.slf4j.Logger log = LoggerFactory.getLogger(GL_View_Base.class); // # CONSTANTS /** * Pointer ID for Mouse wheel scrolling up */ public static final int MOUSE_WHEEL_POINTER_UP = -280272; private final ParentInfo myInfoForChild = new ParentInfo(); protected final Matrix4 rotateMatrix = new Matrix4(); /** * Pointer ID for Mouse wheel scrolling down */ public static final int MOUSE_WHEEL_POINTER_DOWN = -280273; public static boolean debug = false; public static boolean disableScissor = false; public boolean withoutScissor = false; private boolean forceHandleTouchEvents = false; public void setForceHandleTouchEvents(boolean value) { this.forceHandleTouchEvents = value; } // # private Member protected String name = ""; protected Drawable drawableBackground; /** * Enthaelt alle GL_Views innerhalb dieser Gl_View */ protected final MoveableList<GL_View_Base> childs = new MoveableList<GL_View_Base>(); protected OnClickListener mOnClickListener; protected OnClickListener mOnLongClickListener; protected OnClickListener mOnDoubleClickListener; public Pixmap debugRegPixmap = null; public Texture debugRegTexture = null; protected Sprite DebugSprite = null; /** * Don't use this Flag direct, use the method isClickable() </br></br> Maby a child is clickable!! */ private boolean isClickable = false; private boolean isLongClickable = false; private boolean isDoubleClickable = false; private boolean ChildIsClickable = false; private boolean ChildIsLongClickable = false; private boolean ChildIsDoubleClickable = false; protected boolean onTouchUp = false; protected boolean onTouchDown = false; public Vector2 lastTouchPos; private boolean mVisible = true; protected GL_View_Base parent; protected static int nDepthCounter = 0; private boolean enabled = true; protected float Weight = 1f; // # Constructors public GL_View_Base() { super(); name = ""; } public GL_View_Base(String Name) { super(); name = Name; } /** * Constructor fuer ein neues GL_View_Base mit Angabe der linken unteren Ecke und der Hoehe und Breite * * @param X * @param Y * @param Width * @param Height */ public GL_View_Base(float X, float Y, float Width, float Height, String Name) { super(X, Y, Width, Height); name = Name; } public GL_View_Base(float X, float Y, float Width, float Height, GL_View_Base Parent, String Name) { super(X, Y, Width, Height); parent = Parent; name = Name; } public GL_View_Base(CB_RectF rec, String Name) { super(rec); name = Name; } public GL_View_Base(CB_RectF rec, GL_View_Base Parent, String Name) { super(rec); parent = Parent; name = Name; } public GL_View_Base(SizeF size, String Name) { super(0, 0, size.width, size.height); name = Name; } public void setVisible(boolean On) { if (On) { setVisible(); } else { setInvisible(); } } public void setVisible() { if (mVisible) return; mVisible = true; GL.that.renderOnce(); } public void setInvisible() { if (!mVisible) return; mVisible = false; GL.that.renderOnce(); } public MoveableList<GL_View_Base> getchilds() { return childs; } /** * Gibt die Parent View zurck, wenn diese ber den Constructor bergeben wurde! * * @return parent View oder null */ public GL_View_Base getParent() { return parent; } /** * Returns TRUE if with and height >0, is not disposed and is not set to invisible * * @return */ public boolean isVisible() { if (this.isDisposed) return false; if (this.getWidth() <= 0f || this.getHeight() <= 0f) return false; return mVisible; } public GL_View_Base addChild(final GL_View_Base view) { return addChild(view, false); } public GL_View_Base addChild(final GL_View_Base view, final boolean last) { if (childs.contains(view)) return view; GL.that.RunOnGLWithThreadCheck(new IRunOnGL() { @Override public void run() { if (last) { childs.add(0, view); } else { childs.add(view); } chkChildClickable(); } }); return view; } public void removeChild(final GL_View_Base view) { GL.that.RunOnGLWithThreadCheck(new IRunOnGL() { @Override public void run() { try { if (childs != null && childs.size() > 0) childs.remove(view); } catch (Exception e) { } chkChildClickable(); } }); } public void removeChilds() { GL.that.RunOnGLWithThreadCheck(new IRunOnGL() { @Override public void run() { try { if (childs != null && childs.size() > 0) childs.clear(); } catch (Exception e) { } chkChildClickable(); } }); } public void removeChilds(final MoveableList<GL_View_Base> Childs) { GL.that.RunOnGLWithThreadCheck(new IRunOnGL() { @Override public void run() { try { if (childs != null && childs.size() > 0) childs.remove(Childs); } catch (Exception e) { } chkChildClickable(); } }); } /** * Checks whether any child has the status Clickable. </br>If so, then this view must also Clickable! */ protected void chkChildClickable() { boolean tmpClickable = false; boolean tmpDoubleClickable = false; boolean tmpLongClickable = false; if (childs != null) { try { for (int i = 0, n = childs.size(); i < n; i++) { GL_View_Base tmp = childs.get(i); if (tmp != null) { if (tmp.isClickable()) tmpClickable = true; if (tmp.isLongClickable()) tmpLongClickable = true; if (tmp.isDoubleClickable()) tmpDoubleClickable = true; } } } catch (Exception e) { } } ChildIsClickable = tmpClickable; ChildIsDoubleClickable = tmpDoubleClickable; ChildIsLongClickable = tmpLongClickable; } protected float leftBorder = 0; protected float rightBorder = 0; protected float topBorder = 0; protected float bottomBorder = 0; /** * the width (member[2]) without left and right borders (0 or from background left and right width) */ protected float innerWidth = getWidth(); protected float innerHeight = getHeight(); /** * * setting the drawableBackground and changes the Borders (do own Borders afterwards) **/ public void setBackground(Drawable background) { if (isDisposed) return; drawableBackground = background; if (background != null) { leftBorder = background.getLeftWidth(); rightBorder = background.getRightWidth(); topBorder = background.getTopHeight(); bottomBorder = background.getBottomHeight(); // this.BottomHeight; } else { leftBorder = 0; rightBorder = 0; topBorder = 0; bottomBorder = 0; // this.BottomHeight; } innerWidth = getWidth() - leftBorder - rightBorder; innerHeight = getHeight() - topBorder - bottomBorder; } /** * * no borders to use on this (page), if you want **/ public void setNoBorders() { leftBorder = 0f; rightBorder = 0f; innerWidth = getWidth(); } /** * * setting the borders to use on this (page), if you want **/ public void setBorders(float l, float r) { leftBorder = l; rightBorder = r; innerWidth = getWidth() - l - r; } public Drawable getBackground() { return drawableBackground; } public float getLeftWidth() { return leftBorder; } public float getRightWidth() { return rightBorder; } public float getTopHeight() { return topBorder; } public float getBottomHeight() { return bottomBorder; } /** * * get available width (not filled with objects) **/ public float getInnerWidth() { return innerWidth; } /** * * get available height (not filled with objects) **/ public float getInnerHeight() { return innerHeight; } /** * Die renderChilds() Methode wird vom GL_Listener bei jedem Render-Vorgang aufgerufen. * Hier wird dann zuerst die render() Methode dieser View aufgerufen. * Danach werden alle Childs iteriert und deren renderChilds() Methode aufgerufen, wenn die View sichtbar ist (Visibility). * * @param batch */ public void renderChilds(final Batch batch, ParentInfo parentInfo) { if (myParentInfo == null) return; if (this.isDisposed) return; if (thisInvalidate) { myParentInfo.setParentInfo(parentInfo); CalcMyInfoForChild(); } if (!withoutScissor) { if (intersectRec == null || intersectRec.getHeight() + 1 < 0 || intersectRec.getWidth() + 1 < 0) return; // hier gibt es nichts zu rendern if (!disableScissor) Gdx.gl.glEnable(GL20.GL_SCISSOR_TEST); Gdx.gl.glScissor((int) intersectRec.getX(), (int) intersectRec.getY(), (int) intersectRec.getWidth() + 1, (int) intersectRec.getHeight() + 1); } float A = 0, R = 0, G = 0, B = 0; // Farbwerte der batch um diese wieder einzustellen, wenn ein ColorFilter angewandt wurde! boolean ColorFilterSeted = false; // Wir benutzen hier dieses Boolean um am ende dieser Methode zu entscheiden, ob wir die alte // Farbe des Batches wieder herstellen mssen. Wir verlassen uns hier nicht darauf, das // mColorFilter!= null ist, da dies in der zwichenzeit passiert sein kann. // Set Colorfilter ? if (mColorFilter != null) { ColorFilterSeted = true; // zuerst alte Farbe abspeichern, um sie Wieder Herstellen zu knnen // hier muss jeder Wert einzeln abgespeichert werden, da bei getColor() // nur eine Referenz zurck gegeben wird Color c = batch.getColor(); A = c.a; R = c.r; G = c.g; B = c.b; batch.setColor(mColorFilter); } // first Draw Background? if (drawableBackground != null) { drawableBackground.draw(batch, 0, 0, getWidth(), getHeight()); } // set rotation boolean isRotated = false; if (mRotate != 0 || mScale != 1) { isRotated = true; rotateMatrix.idt(); rotateMatrix.translate(mOriginX, mOriginY, 0); rotateMatrix.rotate(0, 0, 1, mRotate); rotateMatrix.scale(mScale, mScale, 1); rotateMatrix.translate(-mOriginX, -mOriginY, 0); batch.setTransformMatrix(rotateMatrix); } try { this.render(batch); } catch (IllegalStateException e) { e.printStackTrace(); // reset Colorfilter ? if (ColorFilterSeted) { // alte abgespeicherte Farbe des Batches wieder herstellen! batch.setColor(R, G, B, A); } return; } // reverse rotation if (isRotated) { rotateMatrix.idt(); // rotateMatrix.rotate(0, 0, 1, 0); // rotateMatrix.scale(1, 1, 1); batch.setTransformMatrix(rotateMatrix); } if (childs != null && childs.size() > 0) { for (int i = 0, n = childs.size(); i < n; i++) { if (i >= childs.size()) { break; // ConcurrentModificationException } // alle renderChilds() der in dieser GL_View_Base // enthaltenen Childs auf rufen. try { GL_View_Base view = childs.get(i); // hier nicht view.render(batch) aufrufen, da sonnst die in der // view enthaldenen Childs nicht aufgerufen werden. try { if (view != null && !view.isDisposed() && view.isVisible()) { synchronized (view) { if (childsInvalidate) view.invalidate(); getMyInfoForChild().setParentInfo(myParentInfo); getMyInfoForChild().setWorldDrawRec(intersectRec); getMyInfoForChild().add(view.getX(), view.getY()); batch.setProjectionMatrix(getMyInfoForChild().Matrix()); nDepthCounter++; view.renderChilds(batch, getMyInfoForChild()); nDepthCounter--; } } else { if (view != null && view.isDisposed()) { // Remove disposedView from child list this.removeChild(view); } } } catch (java.lang.IllegalStateException e) { if (view != null && view.isDisposed()) { // Remove disposedView from child list this.removeChild(view); } } } catch (java.util.NoSuchElementException e) { break; // da die Liste nicht mehr gltig ist, brechen wir hier den Iterator ab } catch (java.util.ConcurrentModificationException e) { break; // da die Liste nicht mehr gltig ist, brechen wir hier den Iterator ab } catch (java.lang.IndexOutOfBoundsException e) { break; // da die Liste nicht mehr gltig ist, brechen wir hier den Iterator ab } } childsInvalidate = false; } // Draw Debug REC if (debug) { if (DebugSprite != null) { batch.flush(); DebugSprite.draw(batch); } } // reset Colorfilter ? if (ColorFilterSeted) { // alte abgespeicherte Farbe des Batches wieder herstellen! batch.setColor(R, G, B, A); } } public boolean isDisposed() { return isDisposed; } protected void writeDebug() { if (DebugSprite == null) { try { GL.that.RunOnGLWithThreadCheck(new IRunOnGL() { @Override public void run() { // int w = getNextHighestPO2((int) getWidth()); // int h = getNextHighestPO2((int) getHeight()); int w = (int) getWidth(); int h = (int) getHeight(); debugRegPixmap = new Pixmap(w, h, Pixmap.Format.RGBA8888); debugRegPixmap.setColor(1f, 0f, 0f, 1f); debugRegPixmap.drawRectangle(1, 1, (int) getWidth() - 1, (int) getHeight() - 1); debugRegTexture = new Texture(debugRegPixmap, Pixmap.Format.RGBA8888, false); DebugSprite = new Sprite(debugRegTexture, (int) getWidth(), (int) getHeight()); } }); } catch (Exception e) { e.printStackTrace(); } } } public CB_RectF thisWorldRec = new CB_RectF(); public CB_RectF intersectRec = new CB_RectF(); public ParentInfo myParentInfo = new ParentInfo(); private boolean mustSetScissor = false; protected boolean childsInvalidate = false; protected boolean thisInvalidate = true; public CB_RectF getWorldRec() { if (thisWorldRec == null) return new CB_RectF(); return thisWorldRec.copy(); } /** * Berechnet das Scissor Rechteck und die Infos fuer die Childs immer dann wenn sich etwas an Position oder Groesse dieses GL_View_Base * geaendert hat.<br> * Wenn sich etwas geaendert hat, wird auch ein Invalidate an die Childs uebergeben, da diese auch neu berechnet werden * muessen.<br> * Die detection, wann sich etwas geaendert hat, kommt von der ueberschriebenen CB_RectF Methode CalcCrossPos, da diese bei * jeder Aenderung aufgerufen wird. */ protected void CalcMyInfoForChild() { childsInvalidate = true; thisWorldRec.setRec(this); thisWorldRec.offset(-this.getX() + myParentInfo.Vector().x, -this.getY() + myParentInfo.Vector().y); mustSetScissor = !myParentInfo.drawRec().contains(thisWorldRec); if (mustSetScissor) { intersectRec.setRec(myParentInfo.drawRec().createIntersection(thisWorldRec)); } else { intersectRec.setRec(thisWorldRec); } thisInvalidate = false; if (debug) writeDebug(); } public void invalidate() { thisInvalidate = true; } /** * render * * @param batch */ protected abstract void render(Batch batch); // ######################## // Rotate Property // ######################## protected float mRotate = 0; protected float mOriginX; protected float mOriginY; protected float mScale = 1f; private boolean isDisposed = false; public void setRotate(float Rotate) { mRotate = Rotate; } public void setOrigin(float originX, float originY) { mOriginX = originX; mOriginY = originY; } public void setOriginCenter() { mOriginX = this.getHalfWidth(); mOriginY = this.getHalfHeight(); } /** * setzt den Scale Factor des dargestellten Images, wobei die Gre nicht verndert wird. Ist das Image grer, wird es abgeschnitten * * @param value */ public void setScale(float value) { mScale = value; } @Override public void resize(float width, float height) { super.resize(width, height); try { innerWidth = width - leftBorder - rightBorder; innerHeight = height - topBorder - bottomBorder; onResized(this); } catch (Exception e1) { int i = 0; i = i + 1; } DebugSprite = null; // Eine Grennderung an die Childs melden if (childs != null && childs.size() > 0) { try { for (int i = 0, n = childs.size(); i < n; i++) { // alle renderChilds() der in dieser GL_View_Base enthaltenen Childs auf rufen. GL_View_Base view = childs.get(i); if (view != null) view.onParentResized(this); } } catch (Exception e) { // do nothing } } } public abstract void onResized(CB_RectF rec); public abstract void onParentResized(CB_RectF rec); public void onShow() { if (childs != null && childs.size() > 0) { try { for (int i = 0, n = childs.size(); i < n; i++) { // alle renderChilds() der in dieser GL_View_Base // enthaltenen Childs auf rufen. GL_View_Base view = childs.get(i); if (view != null) view.onShow(); } } catch (Exception e) { e.printStackTrace(); } } } public void onHide() { if (childs != null && childs.size() > 0) { try { for (int i = 0, n = childs.size(); i < n; i++) { // alle renderChilds() der in dieser GL_View_Base // enthaltenen Childs auf rufen. GL_View_Base view = childs.get(i); if (view != null) view.onHide(); } } catch (Exception e) { e.printStackTrace(); } } } public void onStop() { if (childs != null && childs.size() > 0) { try { for (int i = 0, n = childs.size(); i < n; i++) { // alle renderChilds() der in dieser GL_View_Base // enthaltenen Childs auf rufen. GL_View_Base view = childs.get(i); view.onStop(); } } catch (Exception e) { e.printStackTrace(); } } } public boolean click(int x, int y, int pointer, int button) { // final gives errors // Achtung: dieser click ist nicht virtual und darf nicht berschrieben werden!!! // das Ereignis wird dann in der richtigen View an click bergeben!!! boolean handled = false; try { if (childs != null && childs.size() > 0) { for (Iterator<GL_View_Base> iterator = childs.reverseIterator(); iterator.hasNext();) { // Child View suchen, innerhalb derer Bereich der touchDown statt gefunden hat. GL_View_Base view = iterator.next(); if (view == null || !view.isClickable()) continue; // Invisible Views can not be clicked! if (!view.isVisible()) continue; if (view.contains(x, y)) { // touch innerhalb des Views // -> Klick an das View weitergeben handled = view.click(x - (int) view.getX(), y - (int) view.getY(), pointer, button); // if handled, we can break and don't test the rest if (handled) break; } } } if (!handled) { // kein Klick in einem untergeordnetem View // -> hier behandeln if (mOnClickListener != null) { handled = mOnClickListener.onClick(this, x, y, pointer, button); } } } catch (Exception e) { Log.err(log, "click", e); } return handled; } public boolean doubleClick(int x, int y, int pointer, int button) { // final gives errors // Achtung: dieser doubleClick ist nicht virtual und darf nicht berschrieben werden!!! // das Ereignis wird dann in der richtigen View an doubleClick bergeben!!! boolean behandelt = false; try { if (childs != null && childs.size() > 0) { for (Iterator<GL_View_Base> iterator = childs.reverseIterator(); iterator.hasNext();) { // Child View suchen, innerhalb derer Bereich der touchDown statt gefunden hat. GL_View_Base view = iterator.next(); if (view == null || !view.isClickable()) continue; // Invisible Views can not be clicked! if (!view.isVisible()) continue; if (view.contains(x, y)) { // touch innerhalb des Views // -> Klick an das View weitergeben behandelt = view.doubleClick(x - (int) view.getX(), y - (int) view.getY(), pointer, button); if (behandelt) break; } } } if (!behandelt) { // kein Klick in einem untergeordnetem View // -> hier behandeln if (mOnDoubleClickListener != null) { behandelt = mOnDoubleClickListener.onClick(this, x, y, pointer, button); } } } catch (Exception e) { e.printStackTrace(); } return behandelt; } public boolean longClick(int x, int y, int pointer, int button) { // final gives errors // Achtung: dieser longClick ist nicht virtual und darf nicht berschrieben werden!!! // das Ereignis wird dann in der richtigen View an longClick bergeben!!! boolean behandelt = false; try { if (childs != null && childs.size() > 0) { for (Iterator<GL_View_Base> iterator = childs.reverseIterator(); iterator.hasNext();) { // Child View suchen, innerhalb derer Bereich der touchDown statt gefunden hat. GL_View_Base view = iterator.next(); if (view == null || !view.isClickable()) continue; if (view.contains(x, y)) { // touch innerhalb des Views // -> Klick an das View weitergeben behandelt = view.longClick(x - (int) view.getX(), y - (int) view.getY(), pointer, button); } } } if (!behandelt) { // kein Klick in einem untergeordnetem View // -> hier behandeln if (mOnLongClickListener != null) { behandelt = mOnLongClickListener.onClick(this, x, y, pointer, button); } } } catch (Exception e) { e.printStackTrace(); } return behandelt; } public final GL_View_Base touchDown(int x, int y, int pointer, int button) { // Achtung: dieser touchDown ist nicht virtual und darf nicht berschrieben werden!!! // das Ereignis wird dann in der richtigen View an onTouchDown bergeben!!! // touchDown liefert die View zurck, die dieses TochDown Ereignis angenommen hat GL_View_Base resultView = null; if (childs != null && childs.size() > 0) { try { for (Iterator<GL_View_Base> iterator = childs.reverseIterator(); iterator.hasNext();) { // Child View suchen, innerhalb derer Bereich der touchDown statt gefunden hat. GL_View_Base view = iterator.next(); // Invisible Views can not be clicked! if (view == null || !view.isVisible()) continue; if (!view.isEnabled()) continue; if (view.contains(x, y)) { // touch innerhalb des Views // -> Klick an das View weitergeben lastTouchPos = new Vector2(x - view.getX(), y - view.getY()); resultView = view.touchDown(x - (int) view.getX(), y - (int) view.getY(), pointer, button); } if (resultView != null) break; } } catch (Exception e) { return null; } } if (forceHandleTouchEvents || resultView == null) { // kein Klick in einem untergeordnetem View // -> hier behandeln boolean behandelt = onTouchDown(x, y, pointer, button); if (behandelt) resultView = this; } GL.that.renderOnce(); return resultView; } /** * touchDragged * * @param x * @param y * @param pointer * @param KineticPan * @return */ public final boolean touchDragged(int x, int y, int pointer, boolean KineticPan) { // Achtung: dieser touchDragged ist nicht virtual und darf nicht berschrieben werden!!! // das Ereignis wird dann in der richtigen View an onTouchDown bergeben!!! boolean behandelt = false; if (childs != null && childs.size() > 0) { try { for (Iterator<GL_View_Base> iterator = childs.reverseIterator(); iterator.hasNext();) { GL_View_Base view = iterator.next(); if (view != null && view.contains(x, y)) { behandelt = view.touchDragged(x - (int) view.getX(), y - (int) view.getY(), pointer, KineticPan); } if (behandelt) break; } } catch (Exception e) { return false; } } if (forceHandleTouchEvents || !behandelt) { // kein Klick in einem untergeordnetem View -> hier behandeln behandelt = onTouchDragged(x, y, pointer, KineticPan); } return behandelt; } public final boolean touchUp(int x, int y, int pointer, int button) { // Achtung: dieser touchDown ist nicht virtual und darf nicht berschrieben werden!!! // das Ereignis wird dann in der richtigen View an onTouchDown bergeben!!! boolean behandelt = false; if (childs != null && childs.size() > 0) { try { for (Iterator<GL_View_Base> iterator = childs.reverseIterator(); iterator.hasNext();) { GL_View_Base view = iterator.next(); if (view != null && view.contains(x, y)) { // touch innerhalb des Views // -> Klick an das View weitergeben behandelt = view.touchUp(x - (int) view.getX(), y - (int) view.getY(), pointer, button); } if (behandelt) break; } } catch (Exception e) { return false; } } if (forceHandleTouchEvents || !behandelt) { // kein Klick in einem untergeordnetem View // -> hier behandeln behandelt = onTouchUp(x, y, pointer, button); } return behandelt; } // die untergeordneten Klassen mssen diese Event-Handler berschreiben!!! // public abstract boolean onClick(int x, int y, int pointer, int button); public abstract boolean onLongClick(int x, int y, int pointer, int button); /** * @param x * @param y * @param pointer * @param button * @return */ public abstract boolean onTouchDown(int x, int y, int pointer, int button); /** * abstract onTouchDragged: implementation should return true, if handled. * * @param x * @param y * @param pointer * @param KineticPan * @return */ public abstract boolean onTouchDragged(int x, int y, int pointer, boolean KineticPan); /** * @param x * @param y * @param pointer * @param button * @return */ public abstract boolean onTouchUp(int x, int y, int pointer, int button); @Override public void dispose() { isDisposed = true; DebugSprite = null; try { GL.that.RunOnGLWithThreadCheck(new IRunOnGL() { @Override public void run() { if (debugRegTexture != null) { debugRegTexture.dispose(); debugRegTexture = null; } if (debugRegPixmap != null) { debugRegPixmap.dispose(); debugRegPixmap = null; } } }); } catch (Exception e) { e.printStackTrace(); } try { } catch (Exception e) { e.printStackTrace(); } name = null; data = null; mOnClickListener = null; mOnLongClickListener = null; mOnDoubleClickListener = null; drawableBackground = null; parent = null; DebugSprite = null; lastTouchPos = null; if (debugRegPixmap != null) { debugRegPixmap.dispose(); } debugRegPixmap = null; if (childs != null) { for (int i = 0; i < childs.size(); i++) { childs.get(i).dispose(); } childs.clear(); } super.dispose(); } /** * Interface definition for a callback to be invoked when a view is clicked. */ public interface OnClickListener { /** * Called when a view has been clicked. * * @param v The view that was clicked. */ boolean onClick(GL_View_Base v, int x, int y, int pointer, int button); } /** * Register a callback to be invoked when this view is clicked. If this view is not clickable, it becomes clickable. * * @param listener The callback that will run * @see #setClickable(boolean) */ public void setOnClickListener(OnClickListener listener) { isClickable = listener != null; mOnClickListener = listener; } public OnClickListener getOnClickListener() { return mOnClickListener; } public OnClickListener getOnLongClickListener() { return mOnLongClickListener; } public OnClickListener getOnDoubleClickListener() { return mOnDoubleClickListener; } /** * Register a callback to be invoked when this view is long clicked. If this view is not clickable, it becomes clickable. * * @param l The callback that will run * @see #setClickable(boolean) */ public void setOnLongClickListener(OnClickListener l) { isLongClickable = l != null; mOnLongClickListener = l; } /** * Register a callback to be invoked when this view is double clicked. If this view is not clickable, it becomes clickable. * * @param l The callback that will run * @see #setClickable(boolean) */ public void setOnDoubleClickListener(OnClickListener l) { isDoubleClickable = l != null; mOnDoubleClickListener = l; } public boolean isDoubleClickable() { if (!this.isVisible()) return false; return isDoubleClickable | ChildIsDoubleClickable; } public boolean isLongClickable() { if (!this.isVisible()) return false; return isLongClickable | ChildIsLongClickable; } public boolean isClickable() { if (!this.isVisible()) return false; return isClickable | ChildIsClickable; } /** * if value is true, clicks will be sent else not * * @param value */ public void setClickable(boolean value) { isClickable = value; } public void setLongClickable(boolean value) { isLongClickable = value; } public void setDoubleClickable(boolean value) { isDoubleClickable = value; } public String getName() { return name; } @Override public void setY(float i) { if (this.getY() == i) return; super.setY(i); this.invalidate(); // Scissor muss neu berechnet werden GL.that.renderOnce(); } @Override public void setX(float i) { if (this.getX() == i) return; super.setX(i); this.invalidate(); // Scissor muss neu berechnet werden GL.that.renderOnce(); } @Override public void setPos(Vector2 Pos) { if (this.getX() == Pos.x && this.getY() == Pos.y) return; super.setPos(Pos); this.invalidate(); // Scissor muss neu berechnet werden GL.that.renderOnce(); } public void setZeroPos() { super.setPos(0, 0); this.invalidate(); // Scissor muss neu berechnet werden GL.that.renderOnce(); } @Override public void setPos(float x, float y) { super.setPos(x, y); this.invalidate(); // Scissor muss neu berechnet werden GL.that.renderOnce(); } // Abfrage der clickToleranz, mit der Bestimmt wird ab welcher Bewegung ein onTouchDragged erzeugt wird und beim loslassen kein click // dies kann hier fr einzelne Views unabhngig bestimmt werden public int getClickTolerance() { // wenn eine View clickable ist dann mu fr die Verschiebung (onTouchDragged) ein gewisser Toleranzbereich definiert werden, // innerhalb dem erstmal kein onTouchDragged aufgerufen wird if (isClickable()) return UI_Size_Base.that.getClickToleranz(); else // Wenn aber eine View nicht clickable ist dann darf der onTouchDragged sofort aufgerufen werden return 1; } // ############# Skin changed ################ private interface SkinChangedEventListener { public void SkinChanged(); } private static ArrayList<SkinChangedEventListener> skinChangedEventList = new ArrayList<GL_View_Base.SkinChangedEventListener>(); public void registerSkinChangedEvent() { if (calling) return; // synchronized (skinChangedEventList) // { skinChangedEventList.add(mSkinChangedEventListener); // } } private static boolean calling = false; public static void CallSkinChanged() { // synchronized (skinChangedEventList) // { calling = true; for (SkinChangedEventListener listener : skinChangedEventList) { if (listener != null) listener.SkinChanged(); } calling = false; // } } protected SkinChangedEventListener mSkinChangedEventListener = new SkinChangedEventListener() { @Override public void SkinChanged() { SkinIsChanged(); } }; protected abstract void SkinIsChanged(); // ############# End Skin changed ############ protected Color mColorFilter = null; public void setColorFilter(Color color) { mColorFilter = color; } public void clearColorFilter() { mColorFilter = null; } public Color getColorFilter() { return mColorFilter; } public void setEnabled(boolean value) { enabled = value; } public boolean isEnabled() { return enabled; } private Object data = null; public void setData(Object data) { this.data = data; } public Object getData() { return data; } public ParentInfo getMyInfoForChild() { return myInfoForChild; } }