From a5db7f3bba96a1550daab9255f66a63b918df515 Mon Sep 17 00:00:00 2001 From: Fred Ross-Perry Date: Fri, 16 Sep 2016 13:53:07 -0700 Subject: Android example: move kankan module. Out of platform/java and into the platform/android/example. --- .../main/java/kankan/wheel/widget/ItemsRange.java | 81 ++ .../wheel/widget/OnWheelChangedListener.java | 33 + .../wheel/widget/OnWheelClickedListener.java | 32 + .../kankan/wheel/widget/OnWheelScrollListener.java | 34 + .../java/kankan/wheel/widget/WheelAdapter.java | 46 ++ .../java/kankan/wheel/widget/WheelRecycle.java | 153 ++++ .../java/kankan/wheel/widget/WheelScroller.java | 252 ++++++ .../main/java/kankan/wheel/widget/WheelView.java | 889 +++++++++++++++++++++ .../widget/adapters/AbstractWheelAdapter.java | 74 ++ .../widget/adapters/AbstractWheelTextAdapter.java | 268 +++++++ .../kankan/wheel/widget/adapters/AdapterWheel.java | 62 ++ .../wheel/widget/adapters/ArrayWheelAdapter.java | 62 ++ .../widget/adapters/ArrayWheelAdapterColor.java | 50 ++ .../wheel/widget/adapters/NumericWheelAdapter.java | 85 ++ .../wheel/widget/adapters/WheelViewAdapter.java | 64 ++ .../java/src/kankan/wheel/widget/ItemsRange.java | 81 -- .../wheel/widget/OnWheelChangedListener.java | 33 - .../wheel/widget/OnWheelClickedListener.java | 32 - .../kankan/wheel/widget/OnWheelScrollListener.java | 34 - .../java/src/kankan/wheel/widget/WheelAdapter.java | 46 -- .../java/src/kankan/wheel/widget/WheelRecycle.java | 153 ---- .../src/kankan/wheel/widget/WheelScroller.java | 252 ------ .../java/src/kankan/wheel/widget/WheelView.java | 889 --------------------- .../widget/adapters/AbstractWheelAdapter.java | 74 -- .../widget/adapters/AbstractWheelTextAdapter.java | 268 ------- .../kankan/wheel/widget/adapters/AdapterWheel.java | 62 -- .../wheel/widget/adapters/ArrayWheelAdapter.java | 62 -- .../widget/adapters/ArrayWheelAdapterColor.java | 50 -- .../wheel/widget/adapters/NumericWheelAdapter.java | 85 -- .../wheel/widget/adapters/WheelViewAdapter.java | 64 -- 30 files changed, 2185 insertions(+), 2185 deletions(-) create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/ItemsRange.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/OnWheelChangedListener.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/OnWheelClickedListener.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/OnWheelScrollListener.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelAdapter.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelRecycle.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelScroller.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelView.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/AbstractWheelAdapter.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/AbstractWheelTextAdapter.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/AdapterWheel.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/ArrayWheelAdapter.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/ArrayWheelAdapterColor.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/NumericWheelAdapter.java create mode 100644 platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/WheelViewAdapter.java delete mode 100644 platform/java/src/kankan/wheel/widget/ItemsRange.java delete mode 100644 platform/java/src/kankan/wheel/widget/OnWheelChangedListener.java delete mode 100644 platform/java/src/kankan/wheel/widget/OnWheelClickedListener.java delete mode 100644 platform/java/src/kankan/wheel/widget/OnWheelScrollListener.java delete mode 100644 platform/java/src/kankan/wheel/widget/WheelAdapter.java delete mode 100644 platform/java/src/kankan/wheel/widget/WheelRecycle.java delete mode 100644 platform/java/src/kankan/wheel/widget/WheelScroller.java delete mode 100644 platform/java/src/kankan/wheel/widget/WheelView.java delete mode 100644 platform/java/src/kankan/wheel/widget/adapters/AbstractWheelAdapter.java delete mode 100644 platform/java/src/kankan/wheel/widget/adapters/AbstractWheelTextAdapter.java delete mode 100644 platform/java/src/kankan/wheel/widget/adapters/AdapterWheel.java delete mode 100644 platform/java/src/kankan/wheel/widget/adapters/ArrayWheelAdapter.java delete mode 100644 platform/java/src/kankan/wheel/widget/adapters/ArrayWheelAdapterColor.java delete mode 100644 platform/java/src/kankan/wheel/widget/adapters/NumericWheelAdapter.java delete mode 100644 platform/java/src/kankan/wheel/widget/adapters/WheelViewAdapter.java (limited to 'platform') diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/ItemsRange.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/ItemsRange.java new file mode 100644 index 00000000..8b58a557 --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/ItemsRange.java @@ -0,0 +1,81 @@ +/* + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * 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. + */ + +package kankan.wheel.widget; + +/** + * Range for visible items. + */ +public class ItemsRange { + // First item number + private int first; + + // Items count + private int count; + + /** + * Default constructor. Creates an empty range + */ + public ItemsRange() { + this(0, 0); + } + + /** + * Constructor + * @param first the number of first item + * @param count the count of items + */ + public ItemsRange(int first, int count) { + this.first = first; + this.count = count; + } + + /** + * Gets number of first item + * @return the number of the first item + */ + public int getFirst() { + return first; + } + + /** + * Gets number of last item + * @return the number of last item + */ + public int getLast() { + return getFirst() + getCount() - 1; + } + + /** + * Get items count + * @return the count of items + */ + public int getCount() { + return count; + } + + /** + * Tests whether item is contained by range + * @param index the item number + * @return true if item is contained + */ + public boolean contains(int index) { + return index >= getFirst() && index <= getLast(); + } +} diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/OnWheelChangedListener.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/OnWheelChangedListener.java new file mode 100644 index 00000000..baad897c --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/OnWheelChangedListener.java @@ -0,0 +1,33 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * 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. + */ + +package kankan.wheel.widget; + +/** + * Wheel changed listener interface. + *

The onChanged() method is called whenever current wheel positions is changed: + *

  • New Wheel position is set + *
  • Wheel view is scrolled + */ +public interface OnWheelChangedListener { + /** + * Callback method to be invoked when current item changed + * @param wheel the wheel view whose state has changed + * @param oldValue the old value of current item + * @param newValue the new value of current item + */ + void onChanged(WheelView wheel, int oldValue, int newValue); +} diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/OnWheelClickedListener.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/OnWheelClickedListener.java new file mode 100644 index 00000000..040bfc7b --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/OnWheelClickedListener.java @@ -0,0 +1,32 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * 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. + */ + +package kankan.wheel.widget; + +/** + * Wheel clicked listener interface. + *

    The onItemClicked() method is called whenever a wheel item is clicked + *

  • New Wheel position is set + *
  • Wheel view is scrolled + */ +public interface OnWheelClickedListener { + /** + * Callback method to be invoked when current item clicked + * @param wheel the wheel view + * @param itemIndex the index of clicked item + */ + void onItemClicked(WheelView wheel, int itemIndex); +} diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/OnWheelScrollListener.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/OnWheelScrollListener.java new file mode 100644 index 00000000..8571a4fe --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/OnWheelScrollListener.java @@ -0,0 +1,34 @@ +/* + * Copyright 2010 Yuri Kanivets + * + * 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. + */ + +package kankan.wheel.widget; + +/** + * Wheel scrolled listener interface. + */ +public interface OnWheelScrollListener { + /** + * Callback method to be invoked when scrolling started. + * @param wheel the wheel view whose state has changed. + */ + void onScrollingStarted(WheelView wheel); + + /** + * Callback method to be invoked when scrolling ended. + * @param wheel the wheel view whose state has changed. + */ + void onScrollingFinished(WheelView wheel); +} diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelAdapter.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelAdapter.java new file mode 100644 index 00000000..841c0b15 --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelAdapter.java @@ -0,0 +1,46 @@ +/* + * Copyright 2010 Yuri Kanivets + * + * 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. + */ + +package kankan.wheel.widget; + +/** + * Wheel adapter interface + * + * @deprecated Use WheelViewAdapter + */ +public interface WheelAdapter { + /** + * Gets items count + * @return the count of wheel items + */ + public int getItemsCount(); + + /** + * Gets a wheel item by index. + * + * @param index the item index + * @return the wheel item text or null + */ + public String getItem(int index); + + /** + * Gets maximum item length. It is used to determine the wheel width. + * If -1 is returned there will be used the default wheel width. + * + * @return the maximum item length or -1 + */ + public int getMaximumLength(); +} diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelRecycle.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelRecycle.java new file mode 100644 index 00000000..242fc89e --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelRecycle.java @@ -0,0 +1,153 @@ +/* + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * 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. + */ + +package kankan.wheel.widget; + +import android.view.View; +import android.widget.LinearLayout; + +import java.util.LinkedList; +import java.util.List; + +/** + * Recycle stores wheel items to reuse. + */ +public class WheelRecycle { + // Cached items + private List items; + + // Cached empty items + private List emptyItems; + + // Wheel view + private WheelView wheel; + + /** + * Constructor + * @param wheel the wheel view + */ + public WheelRecycle(WheelView wheel) { + this.wheel = wheel; + } + + /** + * Recycles items from specified layout. + * There are saved only items not included to specified range. + * All the cached items are removed from original layout. + * + * @param layout the layout containing items to be cached + * @param firstItem the number of first item in layout + * @param range the range of current wheel items + * @return the new value of first item number + */ + public int recycleItems(LinearLayout layout, int firstItem, ItemsRange range) { + int index = firstItem; + for (int i = 0; i < layout.getChildCount();) { + if (!range.contains(index)) { + recycleView(layout.getChildAt(i), index); + layout.removeViewAt(i); + if (i == 0) { // first item + firstItem++; + } + } else { + i++; // go to next item + } + index++; + } + return firstItem; + } + + /** + * Gets item view + * @return the cached view + */ + public View getItem() { + return getCachedView(items); + } + + /** + * Gets empty item view + * @return the cached empty view + */ + public View getEmptyItem() { + return getCachedView(emptyItems); + } + + /** + * Clears all views + */ + public void clearAll() { + if (items != null) { + items.clear(); + } + if (emptyItems != null) { + emptyItems.clear(); + } + } + + /** + * Adds view to specified cache. Creates a cache list if it is null. + * @param view the view to be cached + * @param cache the cache list + * @return the cache list + */ + private List addView(View view, List cache) { + if (cache == null) { + cache = new LinkedList(); + } + + cache.add(view); + return cache; + } + + /** + * Adds view to cache. Determines view type (item view or empty one) by index. + * @param view the view to be cached + * @param index the index of view + */ + private void recycleView(View view, int index) { + int count = wheel.getViewAdapter().getItemsCount(); + + if ((index < 0 || index >= count) && !wheel.isCyclic()) { + // empty view + emptyItems = addView(view, emptyItems); + } else { + while (index < 0) { + index = count + index; + } + index %= count; + items = addView(view, items); + } + } + + /** + * Gets view from specified cache. + * @param cache the cache + * @return the first view from cache. + */ + private View getCachedView(List cache) { + if (cache != null && cache.size() > 0) { + View view = cache.get(0); + cache.remove(0); + return view; + } + return null; + } + +} diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelScroller.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelScroller.java new file mode 100644 index 00000000..0372da1a --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelScroller.java @@ -0,0 +1,252 @@ +/* + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * 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. + */ + +package kankan.wheel.widget; + +import android.content.Context; +import android.os.Handler; +import android.os.Message; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.GestureDetector.SimpleOnGestureListener; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +/** + * Scroller class handles scrolling events and updates the + */ +public class WheelScroller { + /** + * Scrolling listener interface + */ + public interface ScrollingListener { + /** + * Scrolling callback called when scrolling is performed. + * @param distance the distance to scroll + */ + void onScroll(int distance); + + /** + * Starting callback called when scrolling is started + */ + void onStarted(); + + /** + * Finishing callback called after justifying + */ + void onFinished(); + + /** + * Justifying callback called to justify a view when scrolling is ended + */ + void onJustify(); + } + + /** Scrolling duration */ + private static final int SCROLLING_DURATION = 400; + + /** Minimum delta for scrolling */ + public static final int MIN_DELTA_FOR_SCROLLING = 1; + + // Listener + private ScrollingListener listener; + + // Context + private Context context; + + // Scrolling + private GestureDetector gestureDetector; + private Scroller scroller; + private int lastScrollY; + private float lastTouchedY; + private boolean isScrollingPerformed; + + /** + * Constructor + * @param context the current context + * @param listener the scrolling listener + */ + public WheelScroller(Context context, ScrollingListener listener) { + gestureDetector = new GestureDetector(context, gestureListener); + gestureDetector.setIsLongpressEnabled(false); + + scroller = new Scroller(context); + + this.listener = listener; + this.context = context; + } + + /** + * Set the the specified scrolling interpolator + * @param interpolator the interpolator + */ + public void setInterpolator(Interpolator interpolator) { + scroller.forceFinished(true); + scroller = new Scroller(context, interpolator); + } + + /** + * Scroll the wheel + * @param distance the scrolling distance + * @param time the scrolling duration + */ + public void scroll(int distance, int time) { + scroller.forceFinished(true); + + lastScrollY = 0; + + scroller.startScroll(0, 0, 0, distance, time != 0 ? time : SCROLLING_DURATION); + setNextMessage(MESSAGE_SCROLL); + + startScrolling(); + } + + /** + * Stops scrolling + */ + public void stopScrolling() { + scroller.forceFinished(true); + } + + /** + * Handles Touch event + * @param event the motion event + * @return + */ + public boolean onTouchEvent(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + lastTouchedY = event.getY(); + scroller.forceFinished(true); + clearMessages(); + break; + + case MotionEvent.ACTION_MOVE: + // perform scrolling + int distanceY = (int)(event.getY() - lastTouchedY); + if (distanceY != 0) { + startScrolling(); + listener.onScroll(distanceY); + lastTouchedY = event.getY(); + } + break; + } + + if (!gestureDetector.onTouchEvent(event) && event.getAction() == MotionEvent.ACTION_UP) { + justify(); + } + + return true; + } + + // gesture listener + private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() { + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + // Do scrolling in onTouchEvent() since onScroll() are not call immediately + // when user touch and move the wheel + return true; + } + + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + lastScrollY = 0; + final int maxY = 0x7FFFFFFF; + final int minY = -maxY; + scroller.fling(0, lastScrollY, 0, (int) -velocityY, 0, 0, minY, maxY); + setNextMessage(MESSAGE_SCROLL); + return true; + } + }; + + // Messages + private final int MESSAGE_SCROLL = 0; + private final int MESSAGE_JUSTIFY = 1; + + /** + * Set next message to queue. Clears queue before. + * + * @param message the message to set + */ + private void setNextMessage(int message) { + clearMessages(); + animationHandler.sendEmptyMessage(message); + } + + /** + * Clears messages from queue + */ + private void clearMessages() { + animationHandler.removeMessages(MESSAGE_SCROLL); + animationHandler.removeMessages(MESSAGE_JUSTIFY); + } + + // animation handler + private Handler animationHandler = new Handler() { + public void handleMessage(Message msg) { + scroller.computeScrollOffset(); + int currY = scroller.getCurrY(); + int delta = lastScrollY - currY; + lastScrollY = currY; + if (delta != 0) { + listener.onScroll(delta); + } + + // scrolling is not finished when it comes to final Y + // so, finish it manually + if (Math.abs(currY - scroller.getFinalY()) < MIN_DELTA_FOR_SCROLLING) { + currY = scroller.getFinalY(); + scroller.forceFinished(true); + } + if (!scroller.isFinished()) { + animationHandler.sendEmptyMessage(msg.what); + } else if (msg.what == MESSAGE_SCROLL) { + justify(); + } else { + finishScrolling(); + } + } + }; + + /** + * Justifies wheel + */ + private void justify() { + listener.onJustify(); + setNextMessage(MESSAGE_JUSTIFY); + } + + /** + * Starts scrolling + */ + private void startScrolling() { + if (!isScrollingPerformed) { + isScrollingPerformed = true; + listener.onStarted(); + } + } + + /** + * Finishes scrolling + */ + void finishScrolling() { + if (isScrollingPerformed) { + listener.onFinished(); + isScrollingPerformed = false; + } + } +} diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelView.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelView.java new file mode 100644 index 00000000..e8324e88 --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/WheelView.java @@ -0,0 +1,889 @@ +/* + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * 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. + */ + +package kankan.wheel.widget; + +import android.content.Context; +import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.GradientDrawable.Orientation; +import android.media.AudioManager; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.view.animation.Interpolator; +import android.widget.LinearLayout; + +import com.artifex.mupdf.fitz.R; + +import java.util.LinkedList; +import java.util.List; + +import kankan.wheel.widget.adapters.WheelViewAdapter; + + + +/** + * Numeric wheel view. + * + * @author Yuri Kanivets + */ +public class WheelView extends View { + + /** Top and bottom shadows colors */ + private static final int[] SHADOWS_COLORS = new int[] { 0xFF111111, + 0x00AAAAAA, 0x00AAAAAA }; + + /** Top and bottom items offset (to hide that) */ + private static final int ITEM_OFFSET_PERCENT = 10; + + /** Left and right padding value */ + private static final int PADDING = 10; + + /** Default count of visible items */ + private static final int DEF_VISIBLE_ITEMS = 5; + + // Wheel Values + private int currentItem = 0; + + // Count of visible items + private int visibleItems = DEF_VISIBLE_ITEMS; + + // Item height + private int itemHeight = 0; + + // Center Line + private Drawable centerDrawable; + + // // Shadows drawables + private GradientDrawable topShadow; + private GradientDrawable bottomShadow; + + // Scrolling + private WheelScroller scroller; + private boolean isScrollingPerformed; + private int scrollingOffset; + + // Cyclic + boolean isCyclic = false; + + // Items layout + private LinearLayout itemsLayout; + + // The number of first item in layout + private int firstItem; + + // View adapter + private WheelViewAdapter viewAdapter; + + // Recycle + private WheelRecycle recycle = new WheelRecycle(this); + + // Listeners + private List changingListeners = new LinkedList(); + private List scrollingListeners = new LinkedList(); + private List clickingListeners = new LinkedList(); + + /** + * Constructor + */ + public WheelView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initData(context); + } + + /** + * Constructor + */ + public WheelView(Context context, AttributeSet attrs) { + super(context, attrs); + initData(context); + } + + /** + * Constructor + */ + public WheelView(Context context) { + super(context); + initData(context); + } + + /** + * Initializes class data + * @param context the context + */ + private void initData(Context context) { + scroller = new WheelScroller(getContext(), scrollingListener); + } + + // Scrolling listener + WheelScroller.ScrollingListener scrollingListener = new WheelScroller.ScrollingListener() { + public void onStarted() { + isScrollingPerformed = true; + notifyScrollingListenersAboutStart(); + } + + public void onScroll(int distance) { + doScroll(distance); + + int height = getHeight(); + if (scrollingOffset > height) { + scrollingOffset = height; + scroller.stopScrolling(); + } else if (scrollingOffset < -height) { + scrollingOffset = -height; + scroller.stopScrolling(); + } + } + + public void onFinished() { + if (isScrollingPerformed) { + notifyScrollingListenersAboutEnd(); + isScrollingPerformed = false; + } + + scrollingOffset = 0; + invalidate(); + } + + public void onJustify() { + if (Math.abs(scrollingOffset) > WheelScroller.MIN_DELTA_FOR_SCROLLING) { + scroller.scroll(scrollingOffset, 0); + } + } + }; + + /** + * Set the the specified scrolling interpolator + * @param interpolator the interpolator + */ + public void setInterpolator(Interpolator interpolator) { + scroller.setInterpolator(interpolator); + } + + /** + * Gets count of visible items + * + * @return the count of visible items + */ + public int getVisibleItems() { + return visibleItems; + } + + /** + * Sets the desired count of visible items. + * Actual amount of visible items depends on wheel layout parameters. + * To apply changes and rebuild view call measure(). + * + * @param count the desired count for visible items + */ + public void setVisibleItems(int count) { + visibleItems = count; + } + + /** + * Gets view adapter + * @return the view adapter + */ + public WheelViewAdapter getViewAdapter() { + return viewAdapter; + } + + // Adapter listener + private DataSetObserver dataObserver = new DataSetObserver() { + @Override + public void onChanged() { + invalidateWheel(false); + } + + @Override + public void onInvalidated() { + invalidateWheel(true); + } + }; + + /** + * Sets view adapter. Usually new adapters contain different views, so + * it needs to rebuild view by calling measure(). + * + * @param viewAdapter the view adapter + */ + public void setViewAdapter(WheelViewAdapter viewAdapter) { + if (this.viewAdapter != null) { + this.viewAdapter.unregisterDataSetObserver(dataObserver); + } + this.viewAdapter = viewAdapter; + if (this.viewAdapter != null) { + this.viewAdapter.registerDataSetObserver(dataObserver); + } + + invalidateWheel(true); + } + + /** + * Adds wheel changing listener + * @param listener the listener + */ + public void addChangingListener(OnWheelChangedListener listener) { + changingListeners.add(listener); + } + + /** + * Removes wheel changing listener + * @param listener the listener + */ + public void removeChangingListener(OnWheelChangedListener listener) { + changingListeners.remove(listener); + } + + /** + * Notifies changing listeners + * @param oldValue the old wheel value + * @param newValue the new wheel value + */ + protected void notifyChangingListeners(int oldValue, int newValue) { + for (OnWheelChangedListener listener : changingListeners) { + listener.onChanged(this, oldValue, newValue); + } + + // play a sound. + // TODO: something better + this.playSoundEffect(SoundEffectConstants.CLICK); + } + + /** + * Adds wheel scrolling listener + * @param listener the listener + */ + public void addScrollingListener(OnWheelScrollListener listener) { + scrollingListeners.add(listener); + } + + /** + * Removes wheel scrolling listener + * @param listener the listener + */ + public void removeScrollingListener(OnWheelScrollListener listener) { + scrollingListeners.remove(listener); + } + + /** + * Notifies listeners about starting scrolling + */ + protected void notifyScrollingListenersAboutStart() { + for (OnWheelScrollListener listener : scrollingListeners) { + listener.onScrollingStarted(this); + } + } + + /** + * Notifies listeners about ending scrolling + */ + protected void notifyScrollingListenersAboutEnd() { + for (OnWheelScrollListener listener : scrollingListeners) { + listener.onScrollingFinished(this); + } + } + + /** + * Adds wheel clicking listener + * @param listener the listener + */ + public void addClickingListener(OnWheelClickedListener listener) { + clickingListeners.add(listener); + } + + /** + * Removes wheel clicking listener + * @param listener the listener + */ + public void removeClickingListener(OnWheelClickedListener listener) { + clickingListeners.remove(listener); + } + + /** + * Notifies listeners about clicking + */ + protected void notifyClickListenersAboutClick(int item) { + for (OnWheelClickedListener listener : clickingListeners) { + listener.onItemClicked(this, item); + } + } + + /** + * Gets current value + * + * @return the current value + */ + public int getCurrentItem() { + return currentItem; + } + + /** + * Sets the current item. Does nothing when index is wrong. + * + * @param index the item index + * @param animated the animation flag + */ + public void setCurrentItem(int index, boolean animated) { + if (viewAdapter == null || viewAdapter.getItemsCount() == 0) { + return; // throw? + } + + int itemCount = viewAdapter.getItemsCount(); + if (index < 0 || index >= itemCount) { + if (isCyclic) { + while (index < 0) { + index += itemCount; + } + index %= itemCount; + } else{ + return; // throw? + } + } + if (index != currentItem) { + if (animated) { + int itemsToScroll = index - currentItem; + if (isCyclic) { + int scroll = itemCount + Math.min(index, currentItem) - Math.max(index, currentItem); + if (scroll < Math.abs(itemsToScroll)) { + itemsToScroll = itemsToScroll < 0 ? scroll : -scroll; + } + } + scroll(itemsToScroll, 0); + } else { + scrollingOffset = 0; + + int old = currentItem; + currentItem = index; + + notifyChangingListeners(old, currentItem); + + invalidate(); + } + } + } + + /** + * Sets the current item w/o animation. Does nothing when index is wrong. + * + * @param index the item index + */ + public void setCurrentItem(int index) { + setCurrentItem(index, false); + } + + /** + * Tests if wheel is cyclic. That means before the 1st item there is shown the last one + * @return true if wheel is cyclic + */ + public boolean isCyclic() { + return isCyclic; + } + + /** + * Set wheel cyclic flag + * @param isCyclic the flag to set + */ + public void setCyclic(boolean isCyclic) { + this.isCyclic = isCyclic; + invalidateWheel(false); + } + + /** + * Invalidates wheel + * @param clearCaches if true then cached views will be clear + */ + public void invalidateWheel(boolean clearCaches) { + if (clearCaches) { + recycle.clearAll(); + if (itemsLayout != null) { + itemsLayout.removeAllViews(); + } + scrollingOffset = 0; + } else if (itemsLayout != null) { + // cache all items + recycle.recycleItems(itemsLayout, firstItem, new ItemsRange()); + } + + invalidate(); + } + + /** + * Initializes resources + */ + private void initResourcesIfNecessary() { + if (centerDrawable == null) { + centerDrawable = getContext().getResources().getDrawable(R.drawable.wheel_val); + } + + if (topShadow == null) { + topShadow = new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS); + } + + if (bottomShadow == null) { + bottomShadow = new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS); + } + + setBackgroundResource(R.drawable.wheel_bg); + } + + /** + * Calculates desired height for layout + * + * @param layout + * the source layout + * @return the desired layout height + */ + private int getDesiredHeight(LinearLayout layout) { + if (layout != null && layout.getChildAt(0) != null) { + itemHeight = layout.getChildAt(0).getMeasuredHeight(); + } + + int desired = itemHeight * visibleItems - itemHeight * ITEM_OFFSET_PERCENT / 50; + + return Math.max(desired, getSuggestedMinimumHeight()); + } + + /** + * Returns height of wheel item + * @return the item height + */ + private int getItemHeight() { + if (itemHeight != 0) { + return itemHeight; + } + + if (itemsLayout != null && itemsLayout.getChildAt(0) != null) { + itemHeight = itemsLayout.getChildAt(0).getHeight(); + return itemHeight; + } + + return getHeight() / visibleItems; + } + + /** + * Calculates control width and creates text layouts + * @param widthSize the input layout width + * @param mode the layout mode + * @return the calculated control width + */ + private int calculateLayoutWidth(int widthSize, int mode) { + initResourcesIfNecessary(); + + // TODO: make it static + itemsLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + itemsLayout.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.UNSPECIFIED), + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + int width = itemsLayout.getMeasuredWidth(); + + if (mode == MeasureSpec.EXACTLY) { + width = widthSize; + } else { + width += 2 * PADDING; + + // Check against our minimum width + width = Math.max(width, getSuggestedMinimumWidth()); + + if (mode == MeasureSpec.AT_MOST && widthSize < width) { + width = widthSize; + } + } + + itemsLayout.measure(MeasureSpec.makeMeasureSpec(width - 2 * PADDING, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + + return width; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + buildViewForMeasuring(); + + int width = calculateLayoutWidth(widthSize, widthMode); + + int height; + if (heightMode == MeasureSpec.EXACTLY) { + height = heightSize; + } else { + height = getDesiredHeight(itemsLayout); + + if (heightMode == MeasureSpec.AT_MOST) { + height = Math.min(height, heightSize); + } + } + + setMeasuredDimension(width, height); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + layout(r - l, b - t); + } + + /** + * Sets layouts width and height + * @param width the layout width + * @param height the layout height + */ + private void layout(int width, int height) { + int itemsWidth = width - 2 * PADDING; + + itemsLayout.layout(0, 0, itemsWidth, height); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (viewAdapter != null && viewAdapter.getItemsCount() > 0) { + updateView(); + + drawItems(canvas); + drawCenterRect(canvas); + } + +// drawShadows(canvas); + } + + /** + * Draws shadows on top and bottom of control + * @param canvas the canvas for drawing + */ + private void drawShadows(Canvas canvas) { + int height = (int)(1.5 * getItemHeight()); + topShadow.setBounds(0, 0, getWidth(), height); + topShadow.draw(canvas); + + bottomShadow.setBounds(0, getHeight() - height, getWidth(), getHeight()); + bottomShadow.draw(canvas); + } + + /** + * Draws items + * @param canvas the canvas for drawing + */ + private void drawItems(Canvas canvas) { + canvas.save(); + + int top = (currentItem - firstItem) * getItemHeight() + (getItemHeight() - getHeight()) / 2; + canvas.translate(PADDING, - top + scrollingOffset); + + itemsLayout.draw(canvas); + + canvas.restore(); + } + + /** + * Draws rect for current value + * @param canvas the canvas for drawing + */ + private void drawCenterRect(Canvas canvas) { + int center = getHeight() / 2; + int offset = (int) (getItemHeight() / 2 * 1.2); + centerDrawable.setBounds(0, center - offset, getWidth(), center + offset); + centerDrawable.draw(canvas); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!isEnabled() || getViewAdapter() == null) { + return true; + } + + switch (event.getAction()) { + case MotionEvent.ACTION_MOVE: + if (getParent() != null) { + getParent().requestDisallowInterceptTouchEvent(true); + } + break; + + case MotionEvent.ACTION_UP: + if (!isScrollingPerformed) { + int distance = (int) event.getY() - getHeight() / 2; + if (distance > 0) { + distance += getItemHeight() / 2; + } else { + distance -= getItemHeight() / 2; + } + int items = distance / getItemHeight(); + if (items != 0 && isValidItemIndex(currentItem + items)) { + notifyClickListenersAboutClick(currentItem + items); + } + } + break; + } + + return scroller.onTouchEvent(event); + } + + /** + * Scrolls the wheel + * @param delta the scrolling value + */ + private void doScroll(int delta) { + scrollingOffset += delta; + + int itemHeight = getItemHeight(); + int count = scrollingOffset / itemHeight; + + int pos = currentItem - count; + int itemCount = viewAdapter.getItemsCount(); + + int fixPos = scrollingOffset % itemHeight; + if (Math.abs(fixPos) <= itemHeight / 2) { + fixPos = 0; + } + if (isCyclic && itemCount > 0) { + if (fixPos > 0) { + pos--; + count++; + } else if (fixPos < 0) { + pos++; + count--; + } + // fix position by rotating + while (pos < 0) { + pos += itemCount; + } + pos %= itemCount; + } else { + // + if (pos < 0) { + count = currentItem; + pos = 0; + } else if (pos >= itemCount) { + count = currentItem - itemCount + 1; + pos = itemCount - 1; + } else if (pos > 0 && fixPos > 0) { + pos--; + count++; + } else if (pos < itemCount - 1 && fixPos < 0) { + pos++; + count--; + } + } + + int offset = scrollingOffset; + if (pos != currentItem) { + setCurrentItem(pos, false); + } else { + invalidate(); + } + + // update offset + scrollingOffset = offset - count * itemHeight; + if (scrollingOffset > getHeight()) { + scrollingOffset = scrollingOffset % getHeight() + getHeight(); + } + } + + /** + * Scroll the wheel + * @param itemsToSkip items to scroll + * @param time scrolling duration + */ + public void scroll(int itemsToScroll, int time) { + int distance = itemsToScroll * getItemHeight() - scrollingOffset; + scroller.scroll(distance, time); + } + + /** + * Calculates range for wheel items + * @return the items range + */ + private ItemsRange getItemsRange() { + if (getItemHeight() == 0) { + return null; + } + + int first = currentItem; + int count = 1; + + while (count * getItemHeight() < getHeight()) { + first--; + count += 2; // top + bottom items + } + + if (scrollingOffset != 0) { + if (scrollingOffset > 0) { + first--; + } + count++; + + // process empty items above the first or below the second + int emptyItems = scrollingOffset / getItemHeight(); + first -= emptyItems; + count += Math.asin(emptyItems); + } + return new ItemsRange(first, count); + } + + /** + * Rebuilds wheel items if necessary. Caches all unused items. + * + * @return true if items are rebuilt + */ + private boolean rebuildItems() { + boolean updated = false; + ItemsRange range = getItemsRange(); + if (itemsLayout != null) { + int first = recycle.recycleItems(itemsLayout, firstItem, range); + updated = firstItem != first; + firstItem = first; + } else { + createItemsLayout(); + updated = true; + } + + if (!updated) { + updated = firstItem != range.getFirst() || itemsLayout.getChildCount() != range.getCount(); + } + + if (firstItem > range.getFirst() && firstItem <= range.getLast()) { + for (int i = firstItem - 1; i >= range.getFirst(); i--) { + if (!addViewItem(i, true)) { + break; + } + firstItem = i; + } + } else { + firstItem = range.getFirst(); + } + + int first = firstItem; + for (int i = itemsLayout.getChildCount(); i < range.getCount(); i++) { + if (!addViewItem(firstItem + i, false) && itemsLayout.getChildCount() == 0) { + first++; + } + } + firstItem = first; + + return updated; + } + + /** + * Updates view. Rebuilds items and label if necessary, recalculate items sizes. + */ + private void updateView() { + if (rebuildItems()) { + calculateLayoutWidth(getWidth(), MeasureSpec.EXACTLY); + layout(getWidth(), getHeight()); + } + } + + /** + * Creates item layouts if necessary + */ + private void createItemsLayout() { + if (itemsLayout == null) { + itemsLayout = new LinearLayout(getContext()); + itemsLayout.setOrientation(LinearLayout.VERTICAL); + } + } + + /** + * Builds view for measuring + */ + private void buildViewForMeasuring() { + // clear all items + if (itemsLayout != null) { + recycle.recycleItems(itemsLayout, firstItem, new ItemsRange()); + } else { + createItemsLayout(); + } + + // add views + int addItems = visibleItems / 2; + for (int i = currentItem + addItems; i >= currentItem - addItems; i--) { + if (addViewItem(i, true)) { + firstItem = i; + } + } + } + + /** + * Adds view for item to items layout + * @param index the item index + * @param first the flag indicates if view should be first + * @return true if corresponding item exists and is added + */ + private boolean addViewItem(int index, boolean first) { + View view = getItemView(index); + if (view != null) { + if (first) { + itemsLayout.addView(view, 0); + } else { + itemsLayout.addView(view); + } + + return true; + } + + return false; + } + + /** + * Checks whether intem index is valid + * @param index the item index + * @return true if item index is not out of bounds or the wheel is cyclic + */ + private boolean isValidItemIndex(int index) { + return viewAdapter != null && viewAdapter.getItemsCount() > 0 && + (isCyclic || index >= 0 && index < viewAdapter.getItemsCount()); + } + + /** + * Returns view for specified item + * @param index the item index + * @return item view or empty view if index is out of bounds + */ + private View getItemView(int index) { + if (viewAdapter == null || viewAdapter.getItemsCount() == 0) { + return null; + } + int count = viewAdapter.getItemsCount(); + if (!isValidItemIndex(index)) { + return viewAdapter.getEmptyItem(recycle.getEmptyItem(), itemsLayout); + } else { + while (index < 0) { + index = count + index; + } + } + + index %= count; + return viewAdapter.getItem(index, recycle.getItem(), itemsLayout); + } + + /** + * Stops scrolling + */ + public void stopScrolling() { + scroller.stopScrolling(); + } +} diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/AbstractWheelAdapter.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/AbstractWheelAdapter.java new file mode 100644 index 00000000..8d7f1447 --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/AbstractWheelAdapter.java @@ -0,0 +1,74 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * 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. + */ + +package kankan.wheel.widget.adapters; + +import android.database.DataSetObserver; +import android.view.View; +import android.view.ViewGroup; + +import java.util.LinkedList; +import java.util.List; + +/** + * Abstract Wheel adapter. + */ +public abstract class AbstractWheelAdapter implements WheelViewAdapter { + // Observers + private List datasetObservers; + + @Override + public View getEmptyItem(View convertView, ViewGroup parent) { + return null; + } + + @Override + public void registerDataSetObserver(DataSetObserver observer) { + if (datasetObservers == null) { + datasetObservers = new LinkedList(); + } + datasetObservers.add(observer); + } + + @Override + public void unregisterDataSetObserver(DataSetObserver observer) { + if (datasetObservers != null) { + datasetObservers.remove(observer); + } + } + + /** + * Notifies observers about data changing + */ + protected void notifyDataChangedEvent() { + if (datasetObservers != null) { + for (DataSetObserver observer : datasetObservers) { + observer.onChanged(); + } + } + } + + /** + * Notifies observers about invalidating data + */ + protected void notifyDataInvalidatedEvent() { + if (datasetObservers != null) { + for (DataSetObserver observer : datasetObservers) { + observer.onInvalidated(); + } + } + } +} diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/AbstractWheelTextAdapter.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/AbstractWheelTextAdapter.java new file mode 100644 index 00000000..620c8e74 --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/AbstractWheelTextAdapter.java @@ -0,0 +1,268 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * 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. + */ +package kankan.wheel.widget.adapters; + +import android.content.Context; +import android.graphics.Typeface; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +/** + * Abstract wheel adapter provides common functionality for adapters. + */ +public abstract class AbstractWheelTextAdapter extends AbstractWheelAdapter { + + /** Text view resource. Used as a default view for adapter. */ + public static final int TEXT_VIEW_ITEM_RESOURCE = -1; + + /** No resource constant. */ + protected static final int NO_RESOURCE = 0; + + /** Default text color */ + public static final int DEFAULT_TEXT_COLOR = 0xFF101010; + + /** Default text color */ + public static final int LABEL_COLOR = 0xFF700070; + + /** Default text size */ + public static final int DEFAULT_TEXT_SIZE = 24; + + // Text settings + private int textColor = DEFAULT_TEXT_COLOR; + private int textSize = DEFAULT_TEXT_SIZE; + + // Current context + protected Context context; + // Layout inflater + protected LayoutInflater inflater; + + // Items resources + protected int itemResourceId; + protected int itemTextResourceId; + + // Empty items resources + protected int emptyItemResourceId; + + /** + * Constructor + * @param context the current context + */ + protected AbstractWheelTextAdapter(Context context) { + this(context, TEXT_VIEW_ITEM_RESOURCE); + } + + /** + * Constructor + * @param context the current context + * @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views + */ + protected AbstractWheelTextAdapter(Context context, int itemResource) { + this(context, itemResource, NO_RESOURCE); + } + + /** + * Constructor + * @param context the current context + * @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views + * @param itemTextResource the resource ID for a text view in the item layout + */ + protected AbstractWheelTextAdapter(Context context, int itemResource, int itemTextResource) { + this.context = context; + itemResourceId = itemResource; + itemTextResourceId = itemTextResource; + + inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + /** + * Gets text color + * @return the text color + */ + public int getTextColor() { + return textColor; + } + + /** + * Sets text color + * @param textColor the text color to set + */ + public void setTextColor(int textColor) { + this.textColor = textColor; + } + + /** + * Gets text size + * @return the text size + */ + public int getTextSize() { + return textSize; + } + + /** + * Sets text size + * @param textSize the text size to set + */ + public void setTextSize(int textSize) { + this.textSize = textSize; + } + + /** + * Gets resource Id for items views + * @return the item resource Id + */ + public int getItemResource() { + return itemResourceId; + } + + /** + * Sets resource Id for items views + * @param itemResourceId the resource Id to set + */ + public void setItemResource(int itemResourceId) { + this.itemResourceId = itemResourceId; + } + + /** + * Gets resource Id for text view in item layout + * @return the item text resource Id + */ + public int getItemTextResource() { + return itemTextResourceId; + } + + /** + * Sets resource Id for text view in item layout + * @param itemTextResourceId the item text resource Id to set + */ + public void setItemTextResource(int itemTextResourceId) { + this.itemTextResourceId = itemTextResourceId; + } + + /** + * Gets resource Id for empty items views + * @return the empty item resource Id + */ + public int getEmptyItemResource() { + return emptyItemResourceId; + } + + /** + * Sets resource Id for empty items views + * @param emptyItemResourceId the empty item resource Id to set + */ + public void setEmptyItemResource(int emptyItemResourceId) { + this.emptyItemResourceId = emptyItemResourceId; + } + + + /** + * Returns text for specified item + * @param index the item index + * @return the text of specified items + */ + protected abstract CharSequence getItemText(int index); + + @Override + public View getItem(int index, View convertView, ViewGroup parent) { + if (index >= 0 && index < getItemsCount()) { + if (convertView == null) { + convertView = getView(itemResourceId, parent); + } + TextView textView = getTextView(convertView, itemTextResourceId); + if (textView != null) { + CharSequence text = getItemText(index); + if (text == null) { + text = ""; + } + textView.setText(text); + + if (itemResourceId == TEXT_VIEW_ITEM_RESOURCE) { + configureTextView(textView); + } + } + return convertView; + } + return null; + } + + @Override + public View getEmptyItem(View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = getView(emptyItemResourceId, parent); + } + if (emptyItemResourceId == TEXT_VIEW_ITEM_RESOURCE && convertView instanceof TextView) { + configureTextView((TextView)convertView); + } + + return convertView; + } + + /** + * Configures text view. Is called for the TEXT_VIEW_ITEM_RESOURCE views. + * @param view the text view to be configured + */ + protected void configureTextView(TextView view) { + view.setTextColor(textColor); + view.setGravity(Gravity.CENTER); + view.setTextSize(textSize); + view.setLines(1); +// view.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD); + view.setTypeface(Typeface.SANS_SERIF, Typeface.NORMAL); + } + + /** + * Loads a text view from view + * @param view the text view or layout containing it + * @param textResource the text resource Id in layout + * @return the loaded text view + */ + private TextView getTextView(View view, int textResource) { + TextView text = null; + try { + if (textResource == NO_RESOURCE && view instanceof TextView) { + text = (TextView) view; + } else if (textResource != NO_RESOURCE) { + text = (TextView) view.findViewById(textResource); + } + } catch (ClassCastException e) { + Log.e("AbstractWheelAdapter", "You must supply a resource ID for a TextView"); + throw new IllegalStateException( + "AbstractWheelAdapter requires the resource ID to be a TextView", e); + } + + return text; + } + + /** + * Loads view from resources + * @param resource the resource Id + * @return the loaded view or null if resource is not set + */ + private View getView(int resource, ViewGroup parent) { + switch (resource) { + case NO_RESOURCE: + return null; + case TEXT_VIEW_ITEM_RESOURCE: + return new TextView(context); + default: + return inflater.inflate(resource, parent, false); + } + } +} diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/AdapterWheel.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/AdapterWheel.java new file mode 100644 index 00000000..000001cd --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/AdapterWheel.java @@ -0,0 +1,62 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * 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. + */ + +package kankan.wheel.widget.adapters; + +import android.content.Context; + +import kankan.wheel.widget.WheelAdapter; + +/** + * Adapter class for old wheel adapter (deprecated WheelAdapter class). + * + * @deprecated Will be removed soon + */ +public class AdapterWheel extends AbstractWheelTextAdapter { + + // Source adapter + private WheelAdapter adapter; + + /** + * Constructor + * @param context the current context + * @param adapter the source adapter + */ + public AdapterWheel(Context context, WheelAdapter adapter) { + super(context); + + this.adapter = adapter; + } + + /** + * Gets original adapter + * @return the original adapter + */ + public WheelAdapter getAdapter() { + return adapter; + } + + @Override + public int getItemsCount() { + return adapter.getItemsCount(); + } + + @Override + protected CharSequence getItemText(int index) { + return adapter.getItem(index); + } + +} diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/ArrayWheelAdapter.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/ArrayWheelAdapter.java new file mode 100644 index 00000000..c9d430d7 --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/ArrayWheelAdapter.java @@ -0,0 +1,62 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * 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. + */ +package kankan.wheel.widget.adapters; + +import android.content.Context; + +/** + * The simple Array wheel adapter + * @param the element type + */ +public class ArrayWheelAdapter extends AbstractWheelTextAdapter { + + // items + private T items[]; + + /** + * Constructor + * @param context the current context + * @param items the items + */ + public ArrayWheelAdapter(Context context, T items[]) { + super(context); + + //setEmptyItemResource(TEXT_VIEW_ITEM_RESOURCE); + this.items = items; + } + + public void setItems(T items[]) + { + this.items = items; + } + + @Override + public CharSequence getItemText(int index) { + if (index >= 0 && index < items.length) { + T item = items[index]; + if (item instanceof CharSequence) { + return (CharSequence) item; + } + return item.toString(); + } + return null; + } + + @Override + public int getItemsCount() { + return items.length; + } +} diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/ArrayWheelAdapterColor.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/ArrayWheelAdapterColor.java new file mode 100644 index 00000000..cf4a9954 --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/ArrayWheelAdapterColor.java @@ -0,0 +1,50 @@ +package kankan.wheel.widget.adapters; + +import android.content.Context; +import android.graphics.Color; +import android.widget.TextView; + +public class ArrayWheelAdapterColor extends AbstractWheelTextAdapter { + + // items + private T items[]; + + public ArrayWheelAdapterColor(Context context, T items[]) { + super(context); + + this.items = items; + } + + @Override + public CharSequence getItemText(int index) { + if (index >= 0 && index < items.length) { + T item = items[index]; + if (item instanceof CharSequence) { + return (CharSequence) item; + } + return item.toString(); + } + return null; + } + + @Override + public int getItemsCount() { + return items.length; + } + + @Override + protected void configureTextView(TextView view) { + super.configureTextView(view); + + // if the text ends with "(red)" + // color it red. + String text = view.getText().toString(); + if (text.endsWith("(red)")) + { + text = text.replace("(red)",""); + view.setText(text); + view.setTextColor(Color.parseColor("#ff0000")); + } + } + +} \ No newline at end of file diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/NumericWheelAdapter.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/NumericWheelAdapter.java new file mode 100644 index 00000000..ec8b9c86 --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/NumericWheelAdapter.java @@ -0,0 +1,85 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * 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. + */ + +package kankan.wheel.widget.adapters; + +import android.content.Context; + +/** + * Numeric Wheel adapter. + */ +public class NumericWheelAdapter extends AbstractWheelTextAdapter { + + /** The default min value */ + public static final int DEFAULT_MAX_VALUE = 9; + + /** The default max value */ + private static final int DEFAULT_MIN_VALUE = 0; + + // Values + private int minValue; + private int maxValue; + + // format + private String format; + + /** + * Constructor + * @param context the current context + */ + public NumericWheelAdapter(Context context) { + this(context, DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE); + } + + /** + * Constructor + * @param context the current context + * @param minValue the wheel min value + * @param maxValue the wheel max value + */ + public NumericWheelAdapter(Context context, int minValue, int maxValue) { + this(context, minValue, maxValue, null); + } + + /** + * Constructor + * @param context the current context + * @param minValue the wheel min value + * @param maxValue the wheel max value + * @param format the format string + */ + public NumericWheelAdapter(Context context, int minValue, int maxValue, String format) { + super(context); + + this.minValue = minValue; + this.maxValue = maxValue; + this.format = format; + } + + @Override + public CharSequence getItemText(int index) { + if (index >= 0 && index < getItemsCount()) { + int value = minValue + index; + return format != null ? String.format(format, value) : Integer.toString(value); + } + return null; + } + + @Override + public int getItemsCount() { + return maxValue - minValue + 1; + } +} diff --git a/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/WheelViewAdapter.java b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/WheelViewAdapter.java new file mode 100644 index 00000000..db256570 --- /dev/null +++ b/platform/android/example/mupdf/src/main/java/kankan/wheel/widget/adapters/WheelViewAdapter.java @@ -0,0 +1,64 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * 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. + */ + +package kankan.wheel.widget.adapters; + +import android.database.DataSetObserver; +import android.view.View; +import android.view.ViewGroup; + +/** + * Wheel items adapter interface + */ +public interface WheelViewAdapter { + /** + * Gets items count + * @return the count of wheel items + */ + public int getItemsCount(); + + /** + * Get a View that displays the data at the specified position in the data set + * + * @param index the item index + * @param convertView the old view to reuse if possible + * @param parent the parent that this view will eventually be attached to + * @return the wheel item View + */ + public View getItem(int index, View convertView, ViewGroup parent); + + /** + * Get a View that displays an empty wheel item placed before the first or after + * the last wheel item. + * + * @param convertView the old view to reuse if possible + * @param parent the parent that this view will eventually be attached to + * @return the empty item View + */ + public View getEmptyItem(View convertView, ViewGroup parent); + + /** + * Register an observer that is called when changes happen to the data used by this adapter. + * @param observer the observer to be registered + */ + public void registerDataSetObserver(DataSetObserver observer); + + /** + * Unregister an observer that has previously been registered + * @param observer the observer to be unregistered + */ + void unregisterDataSetObserver (DataSetObserver observer); +} diff --git a/platform/java/src/kankan/wheel/widget/ItemsRange.java b/platform/java/src/kankan/wheel/widget/ItemsRange.java deleted file mode 100644 index 8b58a557..00000000 --- a/platform/java/src/kankan/wheel/widget/ItemsRange.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Android Wheel Control. - * https://code.google.com/p/android-wheel/ - * - * Copyright 2011 Yuri Kanivets - * - * 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. - */ - -package kankan.wheel.widget; - -/** - * Range for visible items. - */ -public class ItemsRange { - // First item number - private int first; - - // Items count - private int count; - - /** - * Default constructor. Creates an empty range - */ - public ItemsRange() { - this(0, 0); - } - - /** - * Constructor - * @param first the number of first item - * @param count the count of items - */ - public ItemsRange(int first, int count) { - this.first = first; - this.count = count; - } - - /** - * Gets number of first item - * @return the number of the first item - */ - public int getFirst() { - return first; - } - - /** - * Gets number of last item - * @return the number of last item - */ - public int getLast() { - return getFirst() + getCount() - 1; - } - - /** - * Get items count - * @return the count of items - */ - public int getCount() { - return count; - } - - /** - * Tests whether item is contained by range - * @param index the item number - * @return true if item is contained - */ - public boolean contains(int index) { - return index >= getFirst() && index <= getLast(); - } -} diff --git a/platform/java/src/kankan/wheel/widget/OnWheelChangedListener.java b/platform/java/src/kankan/wheel/widget/OnWheelChangedListener.java deleted file mode 100644 index baad897c..00000000 --- a/platform/java/src/kankan/wheel/widget/OnWheelChangedListener.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011 Yuri Kanivets - * - * 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. - */ - -package kankan.wheel.widget; - -/** - * Wheel changed listener interface. - *

    The onChanged() method is called whenever current wheel positions is changed: - *

  • New Wheel position is set - *
  • Wheel view is scrolled - */ -public interface OnWheelChangedListener { - /** - * Callback method to be invoked when current item changed - * @param wheel the wheel view whose state has changed - * @param oldValue the old value of current item - * @param newValue the new value of current item - */ - void onChanged(WheelView wheel, int oldValue, int newValue); -} diff --git a/platform/java/src/kankan/wheel/widget/OnWheelClickedListener.java b/platform/java/src/kankan/wheel/widget/OnWheelClickedListener.java deleted file mode 100644 index 040bfc7b..00000000 --- a/platform/java/src/kankan/wheel/widget/OnWheelClickedListener.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2011 Yuri Kanivets - * - * 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. - */ - -package kankan.wheel.widget; - -/** - * Wheel clicked listener interface. - *

    The onItemClicked() method is called whenever a wheel item is clicked - *

  • New Wheel position is set - *
  • Wheel view is scrolled - */ -public interface OnWheelClickedListener { - /** - * Callback method to be invoked when current item clicked - * @param wheel the wheel view - * @param itemIndex the index of clicked item - */ - void onItemClicked(WheelView wheel, int itemIndex); -} diff --git a/platform/java/src/kankan/wheel/widget/OnWheelScrollListener.java b/platform/java/src/kankan/wheel/widget/OnWheelScrollListener.java deleted file mode 100644 index 8571a4fe..00000000 --- a/platform/java/src/kankan/wheel/widget/OnWheelScrollListener.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2010 Yuri Kanivets - * - * 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. - */ - -package kankan.wheel.widget; - -/** - * Wheel scrolled listener interface. - */ -public interface OnWheelScrollListener { - /** - * Callback method to be invoked when scrolling started. - * @param wheel the wheel view whose state has changed. - */ - void onScrollingStarted(WheelView wheel); - - /** - * Callback method to be invoked when scrolling ended. - * @param wheel the wheel view whose state has changed. - */ - void onScrollingFinished(WheelView wheel); -} diff --git a/platform/java/src/kankan/wheel/widget/WheelAdapter.java b/platform/java/src/kankan/wheel/widget/WheelAdapter.java deleted file mode 100644 index 841c0b15..00000000 --- a/platform/java/src/kankan/wheel/widget/WheelAdapter.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2010 Yuri Kanivets - * - * 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. - */ - -package kankan.wheel.widget; - -/** - * Wheel adapter interface - * - * @deprecated Use WheelViewAdapter - */ -public interface WheelAdapter { - /** - * Gets items count - * @return the count of wheel items - */ - public int getItemsCount(); - - /** - * Gets a wheel item by index. - * - * @param index the item index - * @return the wheel item text or null - */ - public String getItem(int index); - - /** - * Gets maximum item length. It is used to determine the wheel width. - * If -1 is returned there will be used the default wheel width. - * - * @return the maximum item length or -1 - */ - public int getMaximumLength(); -} diff --git a/platform/java/src/kankan/wheel/widget/WheelRecycle.java b/platform/java/src/kankan/wheel/widget/WheelRecycle.java deleted file mode 100644 index 242fc89e..00000000 --- a/platform/java/src/kankan/wheel/widget/WheelRecycle.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Android Wheel Control. - * https://code.google.com/p/android-wheel/ - * - * Copyright 2011 Yuri Kanivets - * - * 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. - */ - -package kankan.wheel.widget; - -import android.view.View; -import android.widget.LinearLayout; - -import java.util.LinkedList; -import java.util.List; - -/** - * Recycle stores wheel items to reuse. - */ -public class WheelRecycle { - // Cached items - private List items; - - // Cached empty items - private List emptyItems; - - // Wheel view - private WheelView wheel; - - /** - * Constructor - * @param wheel the wheel view - */ - public WheelRecycle(WheelView wheel) { - this.wheel = wheel; - } - - /** - * Recycles items from specified layout. - * There are saved only items not included to specified range. - * All the cached items are removed from original layout. - * - * @param layout the layout containing items to be cached - * @param firstItem the number of first item in layout - * @param range the range of current wheel items - * @return the new value of first item number - */ - public int recycleItems(LinearLayout layout, int firstItem, ItemsRange range) { - int index = firstItem; - for (int i = 0; i < layout.getChildCount();) { - if (!range.contains(index)) { - recycleView(layout.getChildAt(i), index); - layout.removeViewAt(i); - if (i == 0) { // first item - firstItem++; - } - } else { - i++; // go to next item - } - index++; - } - return firstItem; - } - - /** - * Gets item view - * @return the cached view - */ - public View getItem() { - return getCachedView(items); - } - - /** - * Gets empty item view - * @return the cached empty view - */ - public View getEmptyItem() { - return getCachedView(emptyItems); - } - - /** - * Clears all views - */ - public void clearAll() { - if (items != null) { - items.clear(); - } - if (emptyItems != null) { - emptyItems.clear(); - } - } - - /** - * Adds view to specified cache. Creates a cache list if it is null. - * @param view the view to be cached - * @param cache the cache list - * @return the cache list - */ - private List addView(View view, List cache) { - if (cache == null) { - cache = new LinkedList(); - } - - cache.add(view); - return cache; - } - - /** - * Adds view to cache. Determines view type (item view or empty one) by index. - * @param view the view to be cached - * @param index the index of view - */ - private void recycleView(View view, int index) { - int count = wheel.getViewAdapter().getItemsCount(); - - if ((index < 0 || index >= count) && !wheel.isCyclic()) { - // empty view - emptyItems = addView(view, emptyItems); - } else { - while (index < 0) { - index = count + index; - } - index %= count; - items = addView(view, items); - } - } - - /** - * Gets view from specified cache. - * @param cache the cache - * @return the first view from cache. - */ - private View getCachedView(List cache) { - if (cache != null && cache.size() > 0) { - View view = cache.get(0); - cache.remove(0); - return view; - } - return null; - } - -} diff --git a/platform/java/src/kankan/wheel/widget/WheelScroller.java b/platform/java/src/kankan/wheel/widget/WheelScroller.java deleted file mode 100644 index 0372da1a..00000000 --- a/platform/java/src/kankan/wheel/widget/WheelScroller.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Android Wheel Control. - * https://code.google.com/p/android-wheel/ - * - * Copyright 2011 Yuri Kanivets - * - * 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. - */ - -package kankan.wheel.widget; - -import android.content.Context; -import android.os.Handler; -import android.os.Message; -import android.view.GestureDetector; -import android.view.MotionEvent; -import android.view.GestureDetector.SimpleOnGestureListener; -import android.view.animation.Interpolator; -import android.widget.Scroller; - -/** - * Scroller class handles scrolling events and updates the - */ -public class WheelScroller { - /** - * Scrolling listener interface - */ - public interface ScrollingListener { - /** - * Scrolling callback called when scrolling is performed. - * @param distance the distance to scroll - */ - void onScroll(int distance); - - /** - * Starting callback called when scrolling is started - */ - void onStarted(); - - /** - * Finishing callback called after justifying - */ - void onFinished(); - - /** - * Justifying callback called to justify a view when scrolling is ended - */ - void onJustify(); - } - - /** Scrolling duration */ - private static final int SCROLLING_DURATION = 400; - - /** Minimum delta for scrolling */ - public static final int MIN_DELTA_FOR_SCROLLING = 1; - - // Listener - private ScrollingListener listener; - - // Context - private Context context; - - // Scrolling - private GestureDetector gestureDetector; - private Scroller scroller; - private int lastScrollY; - private float lastTouchedY; - private boolean isScrollingPerformed; - - /** - * Constructor - * @param context the current context - * @param listener the scrolling listener - */ - public WheelScroller(Context context, ScrollingListener listener) { - gestureDetector = new GestureDetector(context, gestureListener); - gestureDetector.setIsLongpressEnabled(false); - - scroller = new Scroller(context); - - this.listener = listener; - this.context = context; - } - - /** - * Set the the specified scrolling interpolator - * @param interpolator the interpolator - */ - public void setInterpolator(Interpolator interpolator) { - scroller.forceFinished(true); - scroller = new Scroller(context, interpolator); - } - - /** - * Scroll the wheel - * @param distance the scrolling distance - * @param time the scrolling duration - */ - public void scroll(int distance, int time) { - scroller.forceFinished(true); - - lastScrollY = 0; - - scroller.startScroll(0, 0, 0, distance, time != 0 ? time : SCROLLING_DURATION); - setNextMessage(MESSAGE_SCROLL); - - startScrolling(); - } - - /** - * Stops scrolling - */ - public void stopScrolling() { - scroller.forceFinished(true); - } - - /** - * Handles Touch event - * @param event the motion event - * @return - */ - public boolean onTouchEvent(MotionEvent event) { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - lastTouchedY = event.getY(); - scroller.forceFinished(true); - clearMessages(); - break; - - case MotionEvent.ACTION_MOVE: - // perform scrolling - int distanceY = (int)(event.getY() - lastTouchedY); - if (distanceY != 0) { - startScrolling(); - listener.onScroll(distanceY); - lastTouchedY = event.getY(); - } - break; - } - - if (!gestureDetector.onTouchEvent(event) && event.getAction() == MotionEvent.ACTION_UP) { - justify(); - } - - return true; - } - - // gesture listener - private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() { - public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - // Do scrolling in onTouchEvent() since onScroll() are not call immediately - // when user touch and move the wheel - return true; - } - - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - lastScrollY = 0; - final int maxY = 0x7FFFFFFF; - final int minY = -maxY; - scroller.fling(0, lastScrollY, 0, (int) -velocityY, 0, 0, minY, maxY); - setNextMessage(MESSAGE_SCROLL); - return true; - } - }; - - // Messages - private final int MESSAGE_SCROLL = 0; - private final int MESSAGE_JUSTIFY = 1; - - /** - * Set next message to queue. Clears queue before. - * - * @param message the message to set - */ - private void setNextMessage(int message) { - clearMessages(); - animationHandler.sendEmptyMessage(message); - } - - /** - * Clears messages from queue - */ - private void clearMessages() { - animationHandler.removeMessages(MESSAGE_SCROLL); - animationHandler.removeMessages(MESSAGE_JUSTIFY); - } - - // animation handler - private Handler animationHandler = new Handler() { - public void handleMessage(Message msg) { - scroller.computeScrollOffset(); - int currY = scroller.getCurrY(); - int delta = lastScrollY - currY; - lastScrollY = currY; - if (delta != 0) { - listener.onScroll(delta); - } - - // scrolling is not finished when it comes to final Y - // so, finish it manually - if (Math.abs(currY - scroller.getFinalY()) < MIN_DELTA_FOR_SCROLLING) { - currY = scroller.getFinalY(); - scroller.forceFinished(true); - } - if (!scroller.isFinished()) { - animationHandler.sendEmptyMessage(msg.what); - } else if (msg.what == MESSAGE_SCROLL) { - justify(); - } else { - finishScrolling(); - } - } - }; - - /** - * Justifies wheel - */ - private void justify() { - listener.onJustify(); - setNextMessage(MESSAGE_JUSTIFY); - } - - /** - * Starts scrolling - */ - private void startScrolling() { - if (!isScrollingPerformed) { - isScrollingPerformed = true; - listener.onStarted(); - } - } - - /** - * Finishes scrolling - */ - void finishScrolling() { - if (isScrollingPerformed) { - listener.onFinished(); - isScrollingPerformed = false; - } - } -} diff --git a/platform/java/src/kankan/wheel/widget/WheelView.java b/platform/java/src/kankan/wheel/widget/WheelView.java deleted file mode 100644 index e8324e88..00000000 --- a/platform/java/src/kankan/wheel/widget/WheelView.java +++ /dev/null @@ -1,889 +0,0 @@ -/* - * Android Wheel Control. - * https://code.google.com/p/android-wheel/ - * - * Copyright 2011 Yuri Kanivets - * - * 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. - */ - -package kankan.wheel.widget; - -import android.content.Context; -import android.database.DataSetObserver; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.GradientDrawable; -import android.graphics.drawable.GradientDrawable.Orientation; -import android.media.AudioManager; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.SoundEffectConstants; -import android.view.View; -import android.view.ViewGroup.LayoutParams; -import android.view.animation.Interpolator; -import android.widget.LinearLayout; - -import com.artifex.mupdf.fitz.R; - -import java.util.LinkedList; -import java.util.List; - -import kankan.wheel.widget.adapters.WheelViewAdapter; - - - -/** - * Numeric wheel view. - * - * @author Yuri Kanivets - */ -public class WheelView extends View { - - /** Top and bottom shadows colors */ - private static final int[] SHADOWS_COLORS = new int[] { 0xFF111111, - 0x00AAAAAA, 0x00AAAAAA }; - - /** Top and bottom items offset (to hide that) */ - private static final int ITEM_OFFSET_PERCENT = 10; - - /** Left and right padding value */ - private static final int PADDING = 10; - - /** Default count of visible items */ - private static final int DEF_VISIBLE_ITEMS = 5; - - // Wheel Values - private int currentItem = 0; - - // Count of visible items - private int visibleItems = DEF_VISIBLE_ITEMS; - - // Item height - private int itemHeight = 0; - - // Center Line - private Drawable centerDrawable; - - // // Shadows drawables - private GradientDrawable topShadow; - private GradientDrawable bottomShadow; - - // Scrolling - private WheelScroller scroller; - private boolean isScrollingPerformed; - private int scrollingOffset; - - // Cyclic - boolean isCyclic = false; - - // Items layout - private LinearLayout itemsLayout; - - // The number of first item in layout - private int firstItem; - - // View adapter - private WheelViewAdapter viewAdapter; - - // Recycle - private WheelRecycle recycle = new WheelRecycle(this); - - // Listeners - private List changingListeners = new LinkedList(); - private List scrollingListeners = new LinkedList(); - private List clickingListeners = new LinkedList(); - - /** - * Constructor - */ - public WheelView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - initData(context); - } - - /** - * Constructor - */ - public WheelView(Context context, AttributeSet attrs) { - super(context, attrs); - initData(context); - } - - /** - * Constructor - */ - public WheelView(Context context) { - super(context); - initData(context); - } - - /** - * Initializes class data - * @param context the context - */ - private void initData(Context context) { - scroller = new WheelScroller(getContext(), scrollingListener); - } - - // Scrolling listener - WheelScroller.ScrollingListener scrollingListener = new WheelScroller.ScrollingListener() { - public void onStarted() { - isScrollingPerformed = true; - notifyScrollingListenersAboutStart(); - } - - public void onScroll(int distance) { - doScroll(distance); - - int height = getHeight(); - if (scrollingOffset > height) { - scrollingOffset = height; - scroller.stopScrolling(); - } else if (scrollingOffset < -height) { - scrollingOffset = -height; - scroller.stopScrolling(); - } - } - - public void onFinished() { - if (isScrollingPerformed) { - notifyScrollingListenersAboutEnd(); - isScrollingPerformed = false; - } - - scrollingOffset = 0; - invalidate(); - } - - public void onJustify() { - if (Math.abs(scrollingOffset) > WheelScroller.MIN_DELTA_FOR_SCROLLING) { - scroller.scroll(scrollingOffset, 0); - } - } - }; - - /** - * Set the the specified scrolling interpolator - * @param interpolator the interpolator - */ - public void setInterpolator(Interpolator interpolator) { - scroller.setInterpolator(interpolator); - } - - /** - * Gets count of visible items - * - * @return the count of visible items - */ - public int getVisibleItems() { - return visibleItems; - } - - /** - * Sets the desired count of visible items. - * Actual amount of visible items depends on wheel layout parameters. - * To apply changes and rebuild view call measure(). - * - * @param count the desired count for visible items - */ - public void setVisibleItems(int count) { - visibleItems = count; - } - - /** - * Gets view adapter - * @return the view adapter - */ - public WheelViewAdapter getViewAdapter() { - return viewAdapter; - } - - // Adapter listener - private DataSetObserver dataObserver = new DataSetObserver() { - @Override - public void onChanged() { - invalidateWheel(false); - } - - @Override - public void onInvalidated() { - invalidateWheel(true); - } - }; - - /** - * Sets view adapter. Usually new adapters contain different views, so - * it needs to rebuild view by calling measure(). - * - * @param viewAdapter the view adapter - */ - public void setViewAdapter(WheelViewAdapter viewAdapter) { - if (this.viewAdapter != null) { - this.viewAdapter.unregisterDataSetObserver(dataObserver); - } - this.viewAdapter = viewAdapter; - if (this.viewAdapter != null) { - this.viewAdapter.registerDataSetObserver(dataObserver); - } - - invalidateWheel(true); - } - - /** - * Adds wheel changing listener - * @param listener the listener - */ - public void addChangingListener(OnWheelChangedListener listener) { - changingListeners.add(listener); - } - - /** - * Removes wheel changing listener - * @param listener the listener - */ - public void removeChangingListener(OnWheelChangedListener listener) { - changingListeners.remove(listener); - } - - /** - * Notifies changing listeners - * @param oldValue the old wheel value - * @param newValue the new wheel value - */ - protected void notifyChangingListeners(int oldValue, int newValue) { - for (OnWheelChangedListener listener : changingListeners) { - listener.onChanged(this, oldValue, newValue); - } - - // play a sound. - // TODO: something better - this.playSoundEffect(SoundEffectConstants.CLICK); - } - - /** - * Adds wheel scrolling listener - * @param listener the listener - */ - public void addScrollingListener(OnWheelScrollListener listener) { - scrollingListeners.add(listener); - } - - /** - * Removes wheel scrolling listener - * @param listener the listener - */ - public void removeScrollingListener(OnWheelScrollListener listener) { - scrollingListeners.remove(listener); - } - - /** - * Notifies listeners about starting scrolling - */ - protected void notifyScrollingListenersAboutStart() { - for (OnWheelScrollListener listener : scrollingListeners) { - listener.onScrollingStarted(this); - } - } - - /** - * Notifies listeners about ending scrolling - */ - protected void notifyScrollingListenersAboutEnd() { - for (OnWheelScrollListener listener : scrollingListeners) { - listener.onScrollingFinished(this); - } - } - - /** - * Adds wheel clicking listener - * @param listener the listener - */ - public void addClickingListener(OnWheelClickedListener listener) { - clickingListeners.add(listener); - } - - /** - * Removes wheel clicking listener - * @param listener the listener - */ - public void removeClickingListener(OnWheelClickedListener listener) { - clickingListeners.remove(listener); - } - - /** - * Notifies listeners about clicking - */ - protected void notifyClickListenersAboutClick(int item) { - for (OnWheelClickedListener listener : clickingListeners) { - listener.onItemClicked(this, item); - } - } - - /** - * Gets current value - * - * @return the current value - */ - public int getCurrentItem() { - return currentItem; - } - - /** - * Sets the current item. Does nothing when index is wrong. - * - * @param index the item index - * @param animated the animation flag - */ - public void setCurrentItem(int index, boolean animated) { - if (viewAdapter == null || viewAdapter.getItemsCount() == 0) { - return; // throw? - } - - int itemCount = viewAdapter.getItemsCount(); - if (index < 0 || index >= itemCount) { - if (isCyclic) { - while (index < 0) { - index += itemCount; - } - index %= itemCount; - } else{ - return; // throw? - } - } - if (index != currentItem) { - if (animated) { - int itemsToScroll = index - currentItem; - if (isCyclic) { - int scroll = itemCount + Math.min(index, currentItem) - Math.max(index, currentItem); - if (scroll < Math.abs(itemsToScroll)) { - itemsToScroll = itemsToScroll < 0 ? scroll : -scroll; - } - } - scroll(itemsToScroll, 0); - } else { - scrollingOffset = 0; - - int old = currentItem; - currentItem = index; - - notifyChangingListeners(old, currentItem); - - invalidate(); - } - } - } - - /** - * Sets the current item w/o animation. Does nothing when index is wrong. - * - * @param index the item index - */ - public void setCurrentItem(int index) { - setCurrentItem(index, false); - } - - /** - * Tests if wheel is cyclic. That means before the 1st item there is shown the last one - * @return true if wheel is cyclic - */ - public boolean isCyclic() { - return isCyclic; - } - - /** - * Set wheel cyclic flag - * @param isCyclic the flag to set - */ - public void setCyclic(boolean isCyclic) { - this.isCyclic = isCyclic; - invalidateWheel(false); - } - - /** - * Invalidates wheel - * @param clearCaches if true then cached views will be clear - */ - public void invalidateWheel(boolean clearCaches) { - if (clearCaches) { - recycle.clearAll(); - if (itemsLayout != null) { - itemsLayout.removeAllViews(); - } - scrollingOffset = 0; - } else if (itemsLayout != null) { - // cache all items - recycle.recycleItems(itemsLayout, firstItem, new ItemsRange()); - } - - invalidate(); - } - - /** - * Initializes resources - */ - private void initResourcesIfNecessary() { - if (centerDrawable == null) { - centerDrawable = getContext().getResources().getDrawable(R.drawable.wheel_val); - } - - if (topShadow == null) { - topShadow = new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS); - } - - if (bottomShadow == null) { - bottomShadow = new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS); - } - - setBackgroundResource(R.drawable.wheel_bg); - } - - /** - * Calculates desired height for layout - * - * @param layout - * the source layout - * @return the desired layout height - */ - private int getDesiredHeight(LinearLayout layout) { - if (layout != null && layout.getChildAt(0) != null) { - itemHeight = layout.getChildAt(0).getMeasuredHeight(); - } - - int desired = itemHeight * visibleItems - itemHeight * ITEM_OFFSET_PERCENT / 50; - - return Math.max(desired, getSuggestedMinimumHeight()); - } - - /** - * Returns height of wheel item - * @return the item height - */ - private int getItemHeight() { - if (itemHeight != 0) { - return itemHeight; - } - - if (itemsLayout != null && itemsLayout.getChildAt(0) != null) { - itemHeight = itemsLayout.getChildAt(0).getHeight(); - return itemHeight; - } - - return getHeight() / visibleItems; - } - - /** - * Calculates control width and creates text layouts - * @param widthSize the input layout width - * @param mode the layout mode - * @return the calculated control width - */ - private int calculateLayoutWidth(int widthSize, int mode) { - initResourcesIfNecessary(); - - // TODO: make it static - itemsLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); - itemsLayout.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.UNSPECIFIED), - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - int width = itemsLayout.getMeasuredWidth(); - - if (mode == MeasureSpec.EXACTLY) { - width = widthSize; - } else { - width += 2 * PADDING; - - // Check against our minimum width - width = Math.max(width, getSuggestedMinimumWidth()); - - if (mode == MeasureSpec.AT_MOST && widthSize < width) { - width = widthSize; - } - } - - itemsLayout.measure(MeasureSpec.makeMeasureSpec(width - 2 * PADDING, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - - return width; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int heightMode = MeasureSpec.getMode(heightMeasureSpec); - int widthSize = MeasureSpec.getSize(widthMeasureSpec); - int heightSize = MeasureSpec.getSize(heightMeasureSpec); - - buildViewForMeasuring(); - - int width = calculateLayoutWidth(widthSize, widthMode); - - int height; - if (heightMode == MeasureSpec.EXACTLY) { - height = heightSize; - } else { - height = getDesiredHeight(itemsLayout); - - if (heightMode == MeasureSpec.AT_MOST) { - height = Math.min(height, heightSize); - } - } - - setMeasuredDimension(width, height); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - layout(r - l, b - t); - } - - /** - * Sets layouts width and height - * @param width the layout width - * @param height the layout height - */ - private void layout(int width, int height) { - int itemsWidth = width - 2 * PADDING; - - itemsLayout.layout(0, 0, itemsWidth, height); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (viewAdapter != null && viewAdapter.getItemsCount() > 0) { - updateView(); - - drawItems(canvas); - drawCenterRect(canvas); - } - -// drawShadows(canvas); - } - - /** - * Draws shadows on top and bottom of control - * @param canvas the canvas for drawing - */ - private void drawShadows(Canvas canvas) { - int height = (int)(1.5 * getItemHeight()); - topShadow.setBounds(0, 0, getWidth(), height); - topShadow.draw(canvas); - - bottomShadow.setBounds(0, getHeight() - height, getWidth(), getHeight()); - bottomShadow.draw(canvas); - } - - /** - * Draws items - * @param canvas the canvas for drawing - */ - private void drawItems(Canvas canvas) { - canvas.save(); - - int top = (currentItem - firstItem) * getItemHeight() + (getItemHeight() - getHeight()) / 2; - canvas.translate(PADDING, - top + scrollingOffset); - - itemsLayout.draw(canvas); - - canvas.restore(); - } - - /** - * Draws rect for current value - * @param canvas the canvas for drawing - */ - private void drawCenterRect(Canvas canvas) { - int center = getHeight() / 2; - int offset = (int) (getItemHeight() / 2 * 1.2); - centerDrawable.setBounds(0, center - offset, getWidth(), center + offset); - centerDrawable.draw(canvas); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (!isEnabled() || getViewAdapter() == null) { - return true; - } - - switch (event.getAction()) { - case MotionEvent.ACTION_MOVE: - if (getParent() != null) { - getParent().requestDisallowInterceptTouchEvent(true); - } - break; - - case MotionEvent.ACTION_UP: - if (!isScrollingPerformed) { - int distance = (int) event.getY() - getHeight() / 2; - if (distance > 0) { - distance += getItemHeight() / 2; - } else { - distance -= getItemHeight() / 2; - } - int items = distance / getItemHeight(); - if (items != 0 && isValidItemIndex(currentItem + items)) { - notifyClickListenersAboutClick(currentItem + items); - } - } - break; - } - - return scroller.onTouchEvent(event); - } - - /** - * Scrolls the wheel - * @param delta the scrolling value - */ - private void doScroll(int delta) { - scrollingOffset += delta; - - int itemHeight = getItemHeight(); - int count = scrollingOffset / itemHeight; - - int pos = currentItem - count; - int itemCount = viewAdapter.getItemsCount(); - - int fixPos = scrollingOffset % itemHeight; - if (Math.abs(fixPos) <= itemHeight / 2) { - fixPos = 0; - } - if (isCyclic && itemCount > 0) { - if (fixPos > 0) { - pos--; - count++; - } else if (fixPos < 0) { - pos++; - count--; - } - // fix position by rotating - while (pos < 0) { - pos += itemCount; - } - pos %= itemCount; - } else { - // - if (pos < 0) { - count = currentItem; - pos = 0; - } else if (pos >= itemCount) { - count = currentItem - itemCount + 1; - pos = itemCount - 1; - } else if (pos > 0 && fixPos > 0) { - pos--; - count++; - } else if (pos < itemCount - 1 && fixPos < 0) { - pos++; - count--; - } - } - - int offset = scrollingOffset; - if (pos != currentItem) { - setCurrentItem(pos, false); - } else { - invalidate(); - } - - // update offset - scrollingOffset = offset - count * itemHeight; - if (scrollingOffset > getHeight()) { - scrollingOffset = scrollingOffset % getHeight() + getHeight(); - } - } - - /** - * Scroll the wheel - * @param itemsToSkip items to scroll - * @param time scrolling duration - */ - public void scroll(int itemsToScroll, int time) { - int distance = itemsToScroll * getItemHeight() - scrollingOffset; - scroller.scroll(distance, time); - } - - /** - * Calculates range for wheel items - * @return the items range - */ - private ItemsRange getItemsRange() { - if (getItemHeight() == 0) { - return null; - } - - int first = currentItem; - int count = 1; - - while (count * getItemHeight() < getHeight()) { - first--; - count += 2; // top + bottom items - } - - if (scrollingOffset != 0) { - if (scrollingOffset > 0) { - first--; - } - count++; - - // process empty items above the first or below the second - int emptyItems = scrollingOffset / getItemHeight(); - first -= emptyItems; - count += Math.asin(emptyItems); - } - return new ItemsRange(first, count); - } - - /** - * Rebuilds wheel items if necessary. Caches all unused items. - * - * @return true if items are rebuilt - */ - private boolean rebuildItems() { - boolean updated = false; - ItemsRange range = getItemsRange(); - if (itemsLayout != null) { - int first = recycle.recycleItems(itemsLayout, firstItem, range); - updated = firstItem != first; - firstItem = first; - } else { - createItemsLayout(); - updated = true; - } - - if (!updated) { - updated = firstItem != range.getFirst() || itemsLayout.getChildCount() != range.getCount(); - } - - if (firstItem > range.getFirst() && firstItem <= range.getLast()) { - for (int i = firstItem - 1; i >= range.getFirst(); i--) { - if (!addViewItem(i, true)) { - break; - } - firstItem = i; - } - } else { - firstItem = range.getFirst(); - } - - int first = firstItem; - for (int i = itemsLayout.getChildCount(); i < range.getCount(); i++) { - if (!addViewItem(firstItem + i, false) && itemsLayout.getChildCount() == 0) { - first++; - } - } - firstItem = first; - - return updated; - } - - /** - * Updates view. Rebuilds items and label if necessary, recalculate items sizes. - */ - private void updateView() { - if (rebuildItems()) { - calculateLayoutWidth(getWidth(), MeasureSpec.EXACTLY); - layout(getWidth(), getHeight()); - } - } - - /** - * Creates item layouts if necessary - */ - private void createItemsLayout() { - if (itemsLayout == null) { - itemsLayout = new LinearLayout(getContext()); - itemsLayout.setOrientation(LinearLayout.VERTICAL); - } - } - - /** - * Builds view for measuring - */ - private void buildViewForMeasuring() { - // clear all items - if (itemsLayout != null) { - recycle.recycleItems(itemsLayout, firstItem, new ItemsRange()); - } else { - createItemsLayout(); - } - - // add views - int addItems = visibleItems / 2; - for (int i = currentItem + addItems; i >= currentItem - addItems; i--) { - if (addViewItem(i, true)) { - firstItem = i; - } - } - } - - /** - * Adds view for item to items layout - * @param index the item index - * @param first the flag indicates if view should be first - * @return true if corresponding item exists and is added - */ - private boolean addViewItem(int index, boolean first) { - View view = getItemView(index); - if (view != null) { - if (first) { - itemsLayout.addView(view, 0); - } else { - itemsLayout.addView(view); - } - - return true; - } - - return false; - } - - /** - * Checks whether intem index is valid - * @param index the item index - * @return true if item index is not out of bounds or the wheel is cyclic - */ - private boolean isValidItemIndex(int index) { - return viewAdapter != null && viewAdapter.getItemsCount() > 0 && - (isCyclic || index >= 0 && index < viewAdapter.getItemsCount()); - } - - /** - * Returns view for specified item - * @param index the item index - * @return item view or empty view if index is out of bounds - */ - private View getItemView(int index) { - if (viewAdapter == null || viewAdapter.getItemsCount() == 0) { - return null; - } - int count = viewAdapter.getItemsCount(); - if (!isValidItemIndex(index)) { - return viewAdapter.getEmptyItem(recycle.getEmptyItem(), itemsLayout); - } else { - while (index < 0) { - index = count + index; - } - } - - index %= count; - return viewAdapter.getItem(index, recycle.getItem(), itemsLayout); - } - - /** - * Stops scrolling - */ - public void stopScrolling() { - scroller.stopScrolling(); - } -} diff --git a/platform/java/src/kankan/wheel/widget/adapters/AbstractWheelAdapter.java b/platform/java/src/kankan/wheel/widget/adapters/AbstractWheelAdapter.java deleted file mode 100644 index 8d7f1447..00000000 --- a/platform/java/src/kankan/wheel/widget/adapters/AbstractWheelAdapter.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2011 Yuri Kanivets - * - * 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. - */ - -package kankan.wheel.widget.adapters; - -import android.database.DataSetObserver; -import android.view.View; -import android.view.ViewGroup; - -import java.util.LinkedList; -import java.util.List; - -/** - * Abstract Wheel adapter. - */ -public abstract class AbstractWheelAdapter implements WheelViewAdapter { - // Observers - private List datasetObservers; - - @Override - public View getEmptyItem(View convertView, ViewGroup parent) { - return null; - } - - @Override - public void registerDataSetObserver(DataSetObserver observer) { - if (datasetObservers == null) { - datasetObservers = new LinkedList(); - } - datasetObservers.add(observer); - } - - @Override - public void unregisterDataSetObserver(DataSetObserver observer) { - if (datasetObservers != null) { - datasetObservers.remove(observer); - } - } - - /** - * Notifies observers about data changing - */ - protected void notifyDataChangedEvent() { - if (datasetObservers != null) { - for (DataSetObserver observer : datasetObservers) { - observer.onChanged(); - } - } - } - - /** - * Notifies observers about invalidating data - */ - protected void notifyDataInvalidatedEvent() { - if (datasetObservers != null) { - for (DataSetObserver observer : datasetObservers) { - observer.onInvalidated(); - } - } - } -} diff --git a/platform/java/src/kankan/wheel/widget/adapters/AbstractWheelTextAdapter.java b/platform/java/src/kankan/wheel/widget/adapters/AbstractWheelTextAdapter.java deleted file mode 100644 index 620c8e74..00000000 --- a/platform/java/src/kankan/wheel/widget/adapters/AbstractWheelTextAdapter.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright 2011 Yuri Kanivets - * - * 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. - */ -package kankan.wheel.widget.adapters; - -import android.content.Context; -import android.graphics.Typeface; -import android.util.Log; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -/** - * Abstract wheel adapter provides common functionality for adapters. - */ -public abstract class AbstractWheelTextAdapter extends AbstractWheelAdapter { - - /** Text view resource. Used as a default view for adapter. */ - public static final int TEXT_VIEW_ITEM_RESOURCE = -1; - - /** No resource constant. */ - protected static final int NO_RESOURCE = 0; - - /** Default text color */ - public static final int DEFAULT_TEXT_COLOR = 0xFF101010; - - /** Default text color */ - public static final int LABEL_COLOR = 0xFF700070; - - /** Default text size */ - public static final int DEFAULT_TEXT_SIZE = 24; - - // Text settings - private int textColor = DEFAULT_TEXT_COLOR; - private int textSize = DEFAULT_TEXT_SIZE; - - // Current context - protected Context context; - // Layout inflater - protected LayoutInflater inflater; - - // Items resources - protected int itemResourceId; - protected int itemTextResourceId; - - // Empty items resources - protected int emptyItemResourceId; - - /** - * Constructor - * @param context the current context - */ - protected AbstractWheelTextAdapter(Context context) { - this(context, TEXT_VIEW_ITEM_RESOURCE); - } - - /** - * Constructor - * @param context the current context - * @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views - */ - protected AbstractWheelTextAdapter(Context context, int itemResource) { - this(context, itemResource, NO_RESOURCE); - } - - /** - * Constructor - * @param context the current context - * @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views - * @param itemTextResource the resource ID for a text view in the item layout - */ - protected AbstractWheelTextAdapter(Context context, int itemResource, int itemTextResource) { - this.context = context; - itemResourceId = itemResource; - itemTextResourceId = itemTextResource; - - inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - } - - /** - * Gets text color - * @return the text color - */ - public int getTextColor() { - return textColor; - } - - /** - * Sets text color - * @param textColor the text color to set - */ - public void setTextColor(int textColor) { - this.textColor = textColor; - } - - /** - * Gets text size - * @return the text size - */ - public int getTextSize() { - return textSize; - } - - /** - * Sets text size - * @param textSize the text size to set - */ - public void setTextSize(int textSize) { - this.textSize = textSize; - } - - /** - * Gets resource Id for items views - * @return the item resource Id - */ - public int getItemResource() { - return itemResourceId; - } - - /** - * Sets resource Id for items views - * @param itemResourceId the resource Id to set - */ - public void setItemResource(int itemResourceId) { - this.itemResourceId = itemResourceId; - } - - /** - * Gets resource Id for text view in item layout - * @return the item text resource Id - */ - public int getItemTextResource() { - return itemTextResourceId; - } - - /** - * Sets resource Id for text view in item layout - * @param itemTextResourceId the item text resource Id to set - */ - public void setItemTextResource(int itemTextResourceId) { - this.itemTextResourceId = itemTextResourceId; - } - - /** - * Gets resource Id for empty items views - * @return the empty item resource Id - */ - public int getEmptyItemResource() { - return emptyItemResourceId; - } - - /** - * Sets resource Id for empty items views - * @param emptyItemResourceId the empty item resource Id to set - */ - public void setEmptyItemResource(int emptyItemResourceId) { - this.emptyItemResourceId = emptyItemResourceId; - } - - - /** - * Returns text for specified item - * @param index the item index - * @return the text of specified items - */ - protected abstract CharSequence getItemText(int index); - - @Override - public View getItem(int index, View convertView, ViewGroup parent) { - if (index >= 0 && index < getItemsCount()) { - if (convertView == null) { - convertView = getView(itemResourceId, parent); - } - TextView textView = getTextView(convertView, itemTextResourceId); - if (textView != null) { - CharSequence text = getItemText(index); - if (text == null) { - text = ""; - } - textView.setText(text); - - if (itemResourceId == TEXT_VIEW_ITEM_RESOURCE) { - configureTextView(textView); - } - } - return convertView; - } - return null; - } - - @Override - public View getEmptyItem(View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = getView(emptyItemResourceId, parent); - } - if (emptyItemResourceId == TEXT_VIEW_ITEM_RESOURCE && convertView instanceof TextView) { - configureTextView((TextView)convertView); - } - - return convertView; - } - - /** - * Configures text view. Is called for the TEXT_VIEW_ITEM_RESOURCE views. - * @param view the text view to be configured - */ - protected void configureTextView(TextView view) { - view.setTextColor(textColor); - view.setGravity(Gravity.CENTER); - view.setTextSize(textSize); - view.setLines(1); -// view.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD); - view.setTypeface(Typeface.SANS_SERIF, Typeface.NORMAL); - } - - /** - * Loads a text view from view - * @param view the text view or layout containing it - * @param textResource the text resource Id in layout - * @return the loaded text view - */ - private TextView getTextView(View view, int textResource) { - TextView text = null; - try { - if (textResource == NO_RESOURCE && view instanceof TextView) { - text = (TextView) view; - } else if (textResource != NO_RESOURCE) { - text = (TextView) view.findViewById(textResource); - } - } catch (ClassCastException e) { - Log.e("AbstractWheelAdapter", "You must supply a resource ID for a TextView"); - throw new IllegalStateException( - "AbstractWheelAdapter requires the resource ID to be a TextView", e); - } - - return text; - } - - /** - * Loads view from resources - * @param resource the resource Id - * @return the loaded view or null if resource is not set - */ - private View getView(int resource, ViewGroup parent) { - switch (resource) { - case NO_RESOURCE: - return null; - case TEXT_VIEW_ITEM_RESOURCE: - return new TextView(context); - default: - return inflater.inflate(resource, parent, false); - } - } -} diff --git a/platform/java/src/kankan/wheel/widget/adapters/AdapterWheel.java b/platform/java/src/kankan/wheel/widget/adapters/AdapterWheel.java deleted file mode 100644 index 000001cd..00000000 --- a/platform/java/src/kankan/wheel/widget/adapters/AdapterWheel.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2011 Yuri Kanivets - * - * 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. - */ - -package kankan.wheel.widget.adapters; - -import android.content.Context; - -import kankan.wheel.widget.WheelAdapter; - -/** - * Adapter class for old wheel adapter (deprecated WheelAdapter class). - * - * @deprecated Will be removed soon - */ -public class AdapterWheel extends AbstractWheelTextAdapter { - - // Source adapter - private WheelAdapter adapter; - - /** - * Constructor - * @param context the current context - * @param adapter the source adapter - */ - public AdapterWheel(Context context, WheelAdapter adapter) { - super(context); - - this.adapter = adapter; - } - - /** - * Gets original adapter - * @return the original adapter - */ - public WheelAdapter getAdapter() { - return adapter; - } - - @Override - public int getItemsCount() { - return adapter.getItemsCount(); - } - - @Override - protected CharSequence getItemText(int index) { - return adapter.getItem(index); - } - -} diff --git a/platform/java/src/kankan/wheel/widget/adapters/ArrayWheelAdapter.java b/platform/java/src/kankan/wheel/widget/adapters/ArrayWheelAdapter.java deleted file mode 100644 index c9d430d7..00000000 --- a/platform/java/src/kankan/wheel/widget/adapters/ArrayWheelAdapter.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2011 Yuri Kanivets - * - * 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. - */ -package kankan.wheel.widget.adapters; - -import android.content.Context; - -/** - * The simple Array wheel adapter - * @param the element type - */ -public class ArrayWheelAdapter extends AbstractWheelTextAdapter { - - // items - private T items[]; - - /** - * Constructor - * @param context the current context - * @param items the items - */ - public ArrayWheelAdapter(Context context, T items[]) { - super(context); - - //setEmptyItemResource(TEXT_VIEW_ITEM_RESOURCE); - this.items = items; - } - - public void setItems(T items[]) - { - this.items = items; - } - - @Override - public CharSequence getItemText(int index) { - if (index >= 0 && index < items.length) { - T item = items[index]; - if (item instanceof CharSequence) { - return (CharSequence) item; - } - return item.toString(); - } - return null; - } - - @Override - public int getItemsCount() { - return items.length; - } -} diff --git a/platform/java/src/kankan/wheel/widget/adapters/ArrayWheelAdapterColor.java b/platform/java/src/kankan/wheel/widget/adapters/ArrayWheelAdapterColor.java deleted file mode 100644 index cf4a9954..00000000 --- a/platform/java/src/kankan/wheel/widget/adapters/ArrayWheelAdapterColor.java +++ /dev/null @@ -1,50 +0,0 @@ -package kankan.wheel.widget.adapters; - -import android.content.Context; -import android.graphics.Color; -import android.widget.TextView; - -public class ArrayWheelAdapterColor extends AbstractWheelTextAdapter { - - // items - private T items[]; - - public ArrayWheelAdapterColor(Context context, T items[]) { - super(context); - - this.items = items; - } - - @Override - public CharSequence getItemText(int index) { - if (index >= 0 && index < items.length) { - T item = items[index]; - if (item instanceof CharSequence) { - return (CharSequence) item; - } - return item.toString(); - } - return null; - } - - @Override - public int getItemsCount() { - return items.length; - } - - @Override - protected void configureTextView(TextView view) { - super.configureTextView(view); - - // if the text ends with "(red)" - // color it red. - String text = view.getText().toString(); - if (text.endsWith("(red)")) - { - text = text.replace("(red)",""); - view.setText(text); - view.setTextColor(Color.parseColor("#ff0000")); - } - } - -} \ No newline at end of file diff --git a/platform/java/src/kankan/wheel/widget/adapters/NumericWheelAdapter.java b/platform/java/src/kankan/wheel/widget/adapters/NumericWheelAdapter.java deleted file mode 100644 index ec8b9c86..00000000 --- a/platform/java/src/kankan/wheel/widget/adapters/NumericWheelAdapter.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2011 Yuri Kanivets - * - * 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. - */ - -package kankan.wheel.widget.adapters; - -import android.content.Context; - -/** - * Numeric Wheel adapter. - */ -public class NumericWheelAdapter extends AbstractWheelTextAdapter { - - /** The default min value */ - public static final int DEFAULT_MAX_VALUE = 9; - - /** The default max value */ - private static final int DEFAULT_MIN_VALUE = 0; - - // Values - private int minValue; - private int maxValue; - - // format - private String format; - - /** - * Constructor - * @param context the current context - */ - public NumericWheelAdapter(Context context) { - this(context, DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE); - } - - /** - * Constructor - * @param context the current context - * @param minValue the wheel min value - * @param maxValue the wheel max value - */ - public NumericWheelAdapter(Context context, int minValue, int maxValue) { - this(context, minValue, maxValue, null); - } - - /** - * Constructor - * @param context the current context - * @param minValue the wheel min value - * @param maxValue the wheel max value - * @param format the format string - */ - public NumericWheelAdapter(Context context, int minValue, int maxValue, String format) { - super(context); - - this.minValue = minValue; - this.maxValue = maxValue; - this.format = format; - } - - @Override - public CharSequence getItemText(int index) { - if (index >= 0 && index < getItemsCount()) { - int value = minValue + index; - return format != null ? String.format(format, value) : Integer.toString(value); - } - return null; - } - - @Override - public int getItemsCount() { - return maxValue - minValue + 1; - } -} diff --git a/platform/java/src/kankan/wheel/widget/adapters/WheelViewAdapter.java b/platform/java/src/kankan/wheel/widget/adapters/WheelViewAdapter.java deleted file mode 100644 index db256570..00000000 --- a/platform/java/src/kankan/wheel/widget/adapters/WheelViewAdapter.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2011 Yuri Kanivets - * - * 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. - */ - -package kankan.wheel.widget.adapters; - -import android.database.DataSetObserver; -import android.view.View; -import android.view.ViewGroup; - -/** - * Wheel items adapter interface - */ -public interface WheelViewAdapter { - /** - * Gets items count - * @return the count of wheel items - */ - public int getItemsCount(); - - /** - * Get a View that displays the data at the specified position in the data set - * - * @param index the item index - * @param convertView the old view to reuse if possible - * @param parent the parent that this view will eventually be attached to - * @return the wheel item View - */ - public View getItem(int index, View convertView, ViewGroup parent); - - /** - * Get a View that displays an empty wheel item placed before the first or after - * the last wheel item. - * - * @param convertView the old view to reuse if possible - * @param parent the parent that this view will eventually be attached to - * @return the empty item View - */ - public View getEmptyItem(View convertView, ViewGroup parent); - - /** - * Register an observer that is called when changes happen to the data used by this adapter. - * @param observer the observer to be registered - */ - public void registerDataSetObserver(DataSetObserver observer); - - /** - * Unregister an observer that has previously been registered - * @param observer the observer to be unregistered - */ - void unregisterDataSetObserver (DataSetObserver observer); -} -- cgit v1.2.3