/* Copyright (c) 2002-2011 by XMLVM.org
*
* Project Info: http://www.xmlvm.org
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package android.view;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.xmlvm.acl.common.objects.CommonView;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.internal.Assert;
import android.internal.CommonDeviceAPIFinder;
import android.internal.Dimension;
import android.internal.IBinderImpl;
import android.internal.TopActivity;
import android.os.Handler;
import android.os.IBinder;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.animation.Animation;
import android.widget.AbsListView;
/**
* iPhone implementation of Android's View class.
*
* @see http://developer.android.com/reference/android/view/View.html
*/
public class View {
public static final int NO_ID = 0xffffffff;
public static final int VISIBLE = 0;
public static final int INVISIBLE = 4;
public static final int GONE = 8;
private static final int FORCE_LAYOUT = 0x00001000;
private static final int LAYOUT_REQUIRED = 0x00002000;
static final int MEASURED_DIMENSION_SET = 0x00000800;
static final int DRAWABLE_STATE_DIRTY = 0x00000400;
public final int[] EMPTY_STATE_SET = {};
public final int[] PRESSED_STATE_SET = { 0x010100a7 };
public final int[] CHECKED_STATE_SET = {};
private boolean ignoreRequestLayout;
private int flags;
protected int widthMeasureSpec;
protected int heightMeasureSpec;
private int[] drawableState = EMPTY_STATE_SET;
protected ViewGroup.LayoutParams layoutParams;
protected int paddingLeft;
protected int paddingRight;
protected int paddingTop;
protected int paddingBottom;
private WeakReference<Context> c;
private CommonView commonView;
private WeakReference<ViewParent> parent;
private OnTouchListener listener;
private int id;
private int measuredWidth;
private int measuredHeight;
private int left;
private int top;
private int width;
private int height;
private int minimumWidth;
private int minimumHeight;
private int visibility;
protected Drawable backgroundDrawable;
private Resources mResources;
private Handler handler;
protected OnClickListener onClickListener;
private ViewTreeObserver viewTreeObserver;
/**
* <p>
* Enables low quality mode for the drawing cache.
* </p>
*/
public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
/**
* <p>
* Enables high quality mode for the drawing cache.
* </p>
*/
public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
/**
* Copyright (C) 2006 The Android Open Source Project
*
* A MeasureSpec encapsulates the layout requirements passed from parent to
* child. Each MeasureSpec represents a requirement for either the width or
* the height. A MeasureSpec is comprised of a size and a mode. There are
* three possible modes:
* <dl>
* <dt>UNSPECIFIED</dt>
* <dd>
* The parent has not imposed any constraint on the child. It can be
* whatever size it wants.</dd>
*
* <dt>EXACTLY</dt>
* <dd>
* The parent has determined an exact size for the child. The child is going
* to be given those bounds regardless of how big it wants to be.</dd>
*
* <dt>AT_MOST</dt>
* <dd>
* The child can be as large as it wants up to the specified size.</dd>
* </dl>
*
* MeasureSpecs are implemented as ints to reduce object allocation. This
* class is provided to pack and unpack the <size, mode> tuple into
* the int.
*/
public static class MeasureSpec {
private static final int MODE_SHIFT = 30;
private static final int MODE_MASK = 0x3 << MODE_SHIFT;
/**
* Measure specification mode: The parent has not imposed any constraint
* on the child. It can be whatever size it wants.
*/
public static final int UNSPECIFIED = 0 << MODE_SHIFT;
/**
* Measure specification mode: The parent has determined an exact size
* for the child. The child is going to be given those bounds regardless
* of how big it wants to be.
*/
public static final int EXACTLY = 1 << MODE_SHIFT;
/**
* Measure specification mode: The child can be as large as it wants up
* to the specified size.
*/
public static final int AT_MOST = 2 << MODE_SHIFT;
/**
* Creates a measure specification based on the supplied size and mode.
*
* The mode must always be one of the following:
* <ul>
* <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
* <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
* <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
* </ul>
*
* @param size
* the size of the measure specification
* @param mode
* the mode of the measure specification
* @return the measure specification based on size and mode
*/
public static int makeMeasureSpec(int size, int mode) {
return size + mode;
}
/**
* Extracts the mode from the supplied measure specification.
*
* @param measureSpec
* the measure specification to extract the mode from
* @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
* {@link android.view.View.MeasureSpec#AT_MOST} or
* {@link android.view.View.MeasureSpec#EXACTLY}
*/
public static int getMode(int measureSpec) {
return (measureSpec & MODE_MASK);
}
/**
* Extracts the size from the supplied measure specification.
*
* @param measureSpec
* the measure specification to extract the size from
* @return the size in pixels defined in the supplied measure
* specification
*/
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
/**
* Returns a String representation of the specified measure
* specification.
*
* @param measureSpec
* the measure specification to convert to a String
* @return a String with the following format: "MeasureSpec: MODE SIZE"
*/
public static String toString(int measureSpec) {
int mode = getMode(measureSpec);
int size = getSize(measureSpec);
StringBuilder sb = new StringBuilder("MeasureSpec: ");
if (mode == UNSPECIFIED)
sb.append("UNSPECIFIED ");
else if (mode == EXACTLY)
sb.append("EXACTLY ");
else if (mode == AT_MOST)
sb.append("AT_MOST ");
else
sb.append(mode).append(" ");
sb.append(size);
return sb.toString();
}
}
public static interface OnTouchListener {
/**
* Called when a touch event is dispatched to a view. This allows
* listeners to get a chance to respond before the target view.
*
* @param v
* The view the touch event has been dispatched to.
* @param event
* he MotionEvent object containing full information about
* the event.
*
* @return True if the listener has consumed the event, false otherwise.
*/
public boolean onTouch(View v, MotionEvent event);
}
public static interface OnClickListener {
public void onClick(View view);
}
public View(Context c) {
this(c, null, 0);
}
public View(Context c, AttributeSet attrs) {
this(c, attrs, 0);
}
public View(Context c, AttributeSet attrs, int defStyle) {
flags |= FORCE_LAYOUT;
this.c = new WeakReference<Context>(c);
mResources = c != null ? c.getResources() : null;
commonView = xmlvmNewCommonDeviceView(attrs);
commonView.setOpaque(false);
commonView.setUserInteractionEnabled(true);
if (attrs != null && attrs.getAttributeCount() > 0) {
parseViewAttributes(attrs);
}
}
protected CommonView xmlvmNewCommonDeviceView(AttributeSet attrs) {
return CommonDeviceAPIFinder.instance().getWidgetFactory().createView(this);
}
public ViewGroup.LayoutParams getLayoutParams() {
return layoutParams;
}
public void invalidate() {
commonView.setNeedsDisplay();
}
public void invalidate(int l, int t, int r, int b) {
Assert.NOT_IMPLEMENTED();
}
public void setLayoutParams(ViewGroup.LayoutParams l) {
layoutParams = l;
}
public final Context getContext() {
return c == null ? null : c.get();
}
public void bringToFront() {
CommonView superView = commonView.getSuperview();
if (superView != null)
superView.bringSubviewToFront(commonView);
}
public ViewParent getParent() {
return parent == null ? null : parent.get();
}
public IBinder getWindowToken() {
return new IBinderImpl(this);
}
public void setOnTouchListener(OnTouchListener listener) {
this.listener = listener;
}
public void setOnClickListener(OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
public boolean onTouchEvent(MotionEvent event) {
return false;
}
public void xmlvmSetParent(ViewParent parent) {
this.parent = new WeakReference<ViewParent>(parent);
}
public void xmlvmSetMeasureSpec(int widthMeasureSpec, int heightMeasureSpec) {
this.widthMeasureSpec = widthMeasureSpec;
this.heightMeasureSpec = heightMeasureSpec;
}
private void parseViewAttributes(AttributeSet attrs) {
setIgnoreRequestLayout(true);
setId(attrs.getIdAttributeResourceValue(0));
String str = attrs.getAttributeValue(null, "visibility");
if ("gone".equals(str)) {
setVisibility(GONE);
} else if ("invisible".equals(str)) {
setVisibility(INVISIBLE);
} else {
setVisibility(VISIBLE);
}
str = attrs.getAttributeValue(null, "background");
// Resolve drawable background
if (str != null) {
// background references an id, so create a BitmapDrawable
if (str.charAt(0) == '@') {
int backgroundId = attrs.getAttributeResourceValue(null, "background", -1);
if (backgroundId != -1) {
setBackgroundResource(backgroundId);
}
}
// background specifies a color value, so create a ColorDrawable
else if (str.charAt(0) == '#') {
int color = xmlvmParseColorValue(str);
ColorDrawable d = new ColorDrawable(color);
setBackgroundDrawable(d);
}
}
DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults();
int pl = (int) Dimension.resolveDimension(getContext(),
attrs.getAttributeValue(null, "padding"), metrics);
pl = pl < 0 ? 0 : pl;
int pt = pl;
int pr = pl;
int pb = pl;
int d = (int) Dimension.resolveDimension(getContext(),
attrs.getAttributeValue(null, "paddingLeft"), metrics);
pl = d > 0 ? d : pl;
d = (int) Dimension.resolveDimension(getContext(),
attrs.getAttributeValue(null, "paddingTop"), metrics);
pt = d > 0 ? d : pt;
d = (int) Dimension.resolveDimension(getContext(),
attrs.getAttributeValue(null, "paddingRight"), metrics);
pr = d > 0 ? d : pr;
d = (int) Dimension.resolveDimension(getContext(),
attrs.getAttributeValue(null, "paddingBottom"), metrics);
pb = d > 0 ? d : pb;
setPadding(pl, pt, pr, pb);
d = (int) Dimension.resolveDimension(getContext(),
attrs.getAttributeValue(null, "minWidth"), metrics);
setMinimumWidth(d);
// Set onClick callback method
String callbackName = attrs.getAttributeValue(null, "onClick");
if (callbackName != null) {
try {
InternalOnClickListener l = new InternalOnClickListener(getContext());
l.setCallback(callbackName);
setOnClickListener(l);
} catch (NoSuchMethodException e) {
// Ignore non-existent callback name
}
}
setIgnoreRequestLayout(false);
}
protected int xmlvmParseColorValue(String str) {
int color = 0;
int a;
int r;
int g;
int b;
long l = Long.parseLong(str.substring(1), 16);
switch (str.length()) {
case 9:
color = (int) l;
break;
case 7:
color = (int) l;
color |= 0xff << 24;
break;
case 5:
a = (int) ((l & 0xf000) >> 8) | 0xf;
r = (int) ((l & 0x0f00) >> 4) | 0xf;
g = (int) (l & 0x00f0) | 0xf;
b = (int) ((l & 0x000f) << 4) | 0xf;
color = (a << 24) | (r << 16) | (g << 8) | b;
break;
case 4:
a = 0xff;
r = (int) ((l & 0x0f00) >> 4) | 0xf;
g = (int) (l & 0x00f0) | 0xf;
b = (int) ((l & 0x000f) << 4) | 0xf;
color = (a << 24) | (r << 16) | (g << 8) | b;
break;
}
return color;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public Resources getResources() {
return mResources;
}
public void setBackgroundResource(int resourceId) {
Drawable d = getContext().getResources().getDrawable(resourceId);
setBackgroundDrawable(d);
}
public void setBackgroundDrawable(Drawable drawable) {
backgroundDrawable = drawable;
if (drawable instanceof StateListDrawable) {
refreshBackgroundStateDrawable();
} else {
commonView.setBackgroundDrawable(drawable);
}
// TODO: Is this really required?
requestLayout();
}
public void setBackgroundColor(int color) {
setBackgroundDrawable(new ColorDrawable(color));
}
public boolean postDelayed(Runnable runnable, long delay) {
if (handler == null) {
handler = new Handler();
}
return handler.postDelayed(runnable, delay);
}
public int getLeft() {
return left;
}
public int getTop() {
return top;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public final int getRight() {
return getLeft() + getWidth();
}
public final int getBottom() {
return getTop() + getHeight();
}
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
this.measuredWidth = measuredWidth;
this.measuredHeight = measuredHeight;
flags |= MEASURED_DIMENSION_SET;
}
public int getMeasuredWidth() {
return measuredWidth;
}
public int getMeasuredHeight() {
return measuredHeight;
}
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
if ((flags & FORCE_LAYOUT) == FORCE_LAYOUT || widthMeasureSpec != this.widthMeasureSpec
|| heightMeasureSpec != this.heightMeasureSpec) {
// first clears the measured dimension flag
flags &= ~MEASURED_DIMENSION_SET;
// measure ourselves, this should set the measured dimension flag
// back
onMeasure(widthMeasureSpec, heightMeasureSpec);
// flag not set, setMeasuredDimension() was not invoked, we raise
// an exception to warn the developer
if ((flags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
throw new IllegalStateException("onMeasure() did not set the"
+ " measured dimension by calling" + " setMeasuredDimension()");
}
flags |= LAYOUT_REQUIRED;
}
this.widthMeasureSpec = widthMeasureSpec;
this.heightMeasureSpec = heightMeasureSpec;
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO: If background is set use the background's dimension instead of
// null
// int backgroundWidth = 0;
// int backgroundHeight = 0;
//
// int widthSpec = MeasureSpec.getSize(widthMeasureSpec);
// int heightSpec = MeasureSpec.getSize(heightMeasureSpec);
// int width = MeasureSpec.getMode(widthMeasureSpec) ==
// MeasureSpec.EXACTLY ? MeasureSpec
// .getSize(widthMeasureSpec) : Math.min(backgroundWidth, widthSpec);
// int height = MeasureSpec.getMode(heightMeasureSpec) ==
// MeasureSpec.EXACTLY ? MeasureSpec
// .getSize(heightMeasureSpec) : Math.min(backgroundHeight, heightSpec);
// setMeasuredDimension(width, height);
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
public final void layout(int left, int top, int right, int bottom) {
boolean changed = setFrame(left, top, right, bottom);
flags &= ~FORCE_LAYOUT;
if (changed || (flags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
onLayout(changed, left, top, right, bottom);
flags &= ~LAYOUT_REQUIRED;
if (viewTreeObserver != null) {
viewTreeObserver.dispatchOnGlobalLayout();
}
}
}
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
}
public boolean isLayoutRequested() {
return (flags & FORCE_LAYOUT) == FORCE_LAYOUT;
}
public void requestLayout() {
if (!getIgnoreRequestLayout()) {
flags |= FORCE_LAYOUT;
if (getParent() != null && !getParent().isLayoutRequested()) {
getParent().requestLayout();
} else {
measure(widthMeasureSpec, heightMeasureSpec);
layout(getLeft(), getTop(), getMeasuredWidth(), getMeasuredHeight());
}
}
}
public int getVisibility() {
return visibility;
}
public void setVisibility(int visibility) {
this.visibility = visibility;
commonView.setHidden(visibility != VISIBLE);
requestLayout();
}
public void scrollTo(int x, int y) {
Log.w("xmlvm", "android.view.View.scrollTo() not implemented");
}
public int getBaseline() {
return -1;
}
public void draw(Canvas canvas) {
onDraw(canvas);
}
protected void onDraw(Canvas canvas) {
}
public void setPressed(boolean pressed) {
int[] state = pressed ? PRESSED_STATE_SET : EMPTY_STATE_SET;
xmlvmSetDrawableState(state);
}
public int getPaddingLeft() {
return paddingLeft;
}
public int getPaddingRight() {
return paddingRight;
}
public int getPaddingTop() {
return paddingTop;
}
public int getPaddingBottom() {
return paddingBottom;
}
public void setPadding(int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
boolean changed = false;
if (this.paddingLeft != paddingLeft) {
this.paddingLeft = paddingLeft;
changed = true;
}
if (this.paddingTop != paddingTop) {
this.paddingTop = paddingTop;
changed = true;
}
if (this.paddingRight != paddingRight) {
this.paddingRight = paddingRight;
changed = true;
}
if (this.paddingBottom != paddingBottom) {
this.paddingBottom = paddingBottom;
changed = true;
}
if (changed) {
requestLayout();
}
}
public int getMinimumWidth() {
return minimumWidth;
}
public void setMinimumWidth(int minimumWidth) {
this.minimumWidth = minimumWidth;
}
public int getMinimumHeight() {
return minimumHeight;
}
public void setMinimumHeight(int minimumHeight) {
this.minimumHeight = minimumHeight;
}
/**
* Utility to reconcile a desired size with constraints imposed by a
* MeasureSpec. Will take the desired size, unless a different size is
* imposed by the constraints.
*
* @param size
* How big the view wants to be
* @param measureSpec
* Constraints imposed by the parent
* @return The size this view should be.
*/
public static int resolveSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
result = size;
break;
case MeasureSpec.AT_MOST:
result = Math.min(size, specSize);
break;
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
/**
* Returns the suggested minimum height that the view should use. This
* returns the maximum of the view's minimum height and the background's
* minimum height (
* {@link android.graphics.drawable.Drawable#getMinimumHeight()}).
* <p>
* When being used in {@link #onMeasure(int, int)}, the caller should still
* ensure the returned height is within the requirements of the parent.
*
* @return The suggested minimum height of the view.
*/
protected int getSuggestedMinimumHeight() {
int suggestedMinHeight = minimumHeight;
if (backgroundDrawable != null) {
final int bgMinHeight = backgroundDrawable.getMinimumHeight();
if (suggestedMinHeight < bgMinHeight) {
suggestedMinHeight = bgMinHeight;
}
}
return suggestedMinHeight;
}
/**
* Returns the suggested minimum width that the view should use. This
* returns the maximum of the view's minimum width) and the background's
* minimum width (
* {@link android.graphics.drawable.Drawable#getMinimumWidth()}).
* <p>
* When being used in {@link #onMeasure(int, int)}, the caller should still
* ensure the returned width is within the requirements of the parent.
*
* @return The suggested minimum width of the view.
*/
protected int getSuggestedMinimumWidth() {
int suggestedMinWidth = minimumWidth;
if (backgroundDrawable != null) {
final int bgMinWidth = backgroundDrawable.getMinimumWidth();
if (suggestedMinWidth < bgMinWidth) {
suggestedMinWidth = bgMinWidth;
}
}
return suggestedMinWidth;
}
/**
* Utility to return a default size. Uses the supplied size if the
* MeasureSpec imposed no contraints. Will get larger if allowed by the
* MeasureSpec.
*
* @param size
* Default size for this view
* @param measureSpec
* Constraints imposed by the parent
* @return The size this view should be.
*/
public static int getDefaultSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
result = size;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
/**
* Assign a size and position to this view.
*
* This is called from layout.
*
* @param left
* Left position, relative to parent
* @param top
* Top position, relative to parent
* @param right
* Right position, relative to parent
* @param bottom
* Bottom position, relative to parent
* @return true if the new size and position are different than the previous
* ones {@hide}
*/
protected boolean setFrame(int left, int top, int right, int bottom) {
boolean changed = false;
if (this.left != left || getRight() != right || this.top != top || getBottom() != bottom) {
changed = true;
// Remember our drawn bit
// int drawn = mPrivateFlags & DRAWN;
// Invalidate our old position
invalidate();
final int oldWidth = width;
final int oldHeight = height;
this.left = left;
this.top = top;
this.width = right - left;
this.height = bottom - top;
commonView.setFrame(new RectF(left, top, left + width, top + height));
// mPrivateFlags |= HAS_BOUNDS;
final int newWidth = right - left;
final int newHeight = bottom - top;
if (newWidth != oldWidth || newHeight != oldHeight) {
CommonDeviceAPIFinder.instance().getDispatcher().postDelayed(new Runnable() {
@Override
public void run() {
onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
}
}, 0);
}
if (visibility == VISIBLE) {
// If we are visible, force the DRAWN bit to on so that
// this invalidate will go through (at least to our parent).
// This is because someone may have invalidated this view
// before this call to setFrame came in, therby clearing
// the DRAWN bit.
// mPrivateFlags |= DRAWN;
invalidate();
}
// Reset drawn bit to original value (invalidate turns it off)
// mPrivateFlags |= drawn;
//
// mBackgroundSizeChanged = true;
}
return changed;
}
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
}
/**
* Look for a child view with the given id. If this view has the given id,
* return this view.
*
* @param id
* The id to search for.
* @return The view that has the given id in the hierarchy or null
*/
public final View findViewById(int id) {
if (id < 0) {
return null;
}
return findViewTraversal(id);
}
/**
* {@hide}
*
* @param id
* the id of the view to be found
* @return the view of the specified id, null if cannot be found
*/
protected View findViewTraversal(int id) {
if (id == this.id) {
return this;
}
return null;
}
protected boolean getIgnoreRequestLayout() {
return ignoreRequestLayout;
}
protected void setIgnoreRequestLayout(boolean ignoreRequestLayout) {
this.ignoreRequestLayout = ignoreRequestLayout;
}
public final int[] getDrawableState() {
return drawableState;
}
protected boolean verifyDrawable(Drawable who) {
return who == backgroundDrawable;
}
protected void drawableStateChanged() {
Drawable d = backgroundDrawable;
if (d != null && d.isStateful()) {
d.setState(getDrawableState());
}
}
public void xmlvmSetDrawableState(int[] drawableState) {
this.drawableState = drawableState;
refreshBackgroundStateDrawable();
}
private void refreshBackgroundStateDrawable() {
// TODO: Check implementation after ViewHandler refactoring
if (backgroundDrawable instanceof StateListDrawable) {
StateListDrawable d = (StateListDrawable) backgroundDrawable;
int i = d.getStateDrawableIndex(getDrawableState());
d.selectDrawable(i);
Drawable newDrawable = d.getStateDrawable(i);
Drawable currentDrawable = commonView.getBackgroundDrawable();
if (currentDrawable != newDrawable) {
boolean relayout = (currentDrawable == null && newDrawable != null)
|| (currentDrawable != null && newDrawable != null && !currentDrawable
.getBounds().equals(newDrawable.getBounds()));
commonView.setBackgroundDrawable(newDrawable);
if (relayout) {
requestLayout();
}
}
}
}
public void setDrawingCacheQuality(int quality) {
Assert.NOT_IMPLEMENTED();
}
public void setOnScrollListener(AbsListView.OnScrollListener listener) {
Assert.NOT_IMPLEMENTED();
}
public void setClickable(boolean clickable) {
Assert.NOT_IMPLEMENTED();
}
public void startAnimation(Animation animation) {
Assert.NOT_IMPLEMENTED();
}
public void setEnabled(boolean enabled) {
Assert.NOT_IMPLEMENTED();
}
public void postInvalidate() {
TopActivity.get().runOnUiThread(new Runnable() {
@Override
public void run() {
commonView.setNeedsDisplay();
}
});
}
public void requestFocus() {
// Do we really want that? On iPhone a keyboards pops on immediately
// after requesting focus. Maybe it es better to simply ignore
// requestFocus.
// viewHandler.getContentView().becomeFirstResponder();
}
public OnClickListener getOnClickListener() {
return this.onClickListener;
}
public OnTouchListener getOnTouchListener() {
return this.listener;
}
private static class InternalOnClickListener implements OnClickListener {
private Object target;
private Method m;
private InternalOnClickListener(Object target) {
this.target = target;
}
private void setCallback(String methodName) throws NoSuchMethodException {
m = target.getClass().getDeclaredMethod(methodName, View.class);
}
@Override
public void onClick(View view) {
try {
m.invoke(target, view);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated method stub
}
}
public ViewTreeObserver getViewTreeObserver() {
if (viewTreeObserver == null) {
viewTreeObserver = new ViewTreeObserver();
}
return viewTreeObserver;
}
public void refreshBackground() {
Drawable drawable = this.backgroundDrawable;
if (drawable != null && drawable instanceof BitmapDrawable) {
setBackgroundDrawable(null);
setBackgroundDrawable(drawable);
}
}
public CommonView getCommonView() {
return commonView;
}
}