/* * Copyright (C) 2012 The CyanogenMod Project * * 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 com.cyanogenmod.filemanager.ui.preferences; import android.content.Context; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.cyanogenmod.filemanager.R; import com.cyanogenmod.filemanager.ui.ThemeManager.Theme; import java.util.List; /** * A view that allow view all installed themes by scrolling horizontally. */ public class ThemeRoulette extends HorizontalScrollView { /** * An interface for raise theme selection events */ public interface OnThemeScrollSelectionListener { /** * Method invoked when the scroll selection of a theme start */ void onScrollSelectionStart(); /** * Method invoked when a new scroll selection of a theme was made * * @param theme The new theme */ void onScrollSelectionChanged(Theme theme); } /** * @hide */ ViewGroup mRouletteLayout; private View mSpacer1; private View mSpacer2; /** * @hide */ int mSpacerWidth; /** * @hide */ int mThemeWidth; /** * @hide */ int mCurrentThemePosition; /** * @hide */ OnThemeScrollSelectionListener mOnThemeScrollSelectionListener; /** * Constructor of <code>ThemeRoulette</code>. * * @param context The current context */ public ThemeRoulette(Context context) { super(context); init(); } /** * Constructor of <code>ThemeRoulette</code>. * * @param context The current context * @param attrs The attributes of the XML tag that is inflating the view. */ public ThemeRoulette(Context context, AttributeSet attrs) { super(context, attrs); init(); } /** * Constructor of <code>ThemeRoulette</code>. * * @param context The current context * @param attrs The attributes of the XML tag that is inflating the view. * @param defStyle The default style to apply to this view. If 0, no style * will be applied (beyond what is included in the theme). This may * either be an attribute resource, whose value will be retrieved * from the current theme, or an explicit style resource. */ public ThemeRoulette(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } /** * Method that initializes the view */ private void init() { this.mRouletteLayout = (ViewGroup)inflate(getContext(), R.layout.theme_roulette, null); this.mRouletteLayout.setLayoutParams( new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT)); this.mSpacer1 = this.mRouletteLayout.findViewById(R.id.spacer1); this.mSpacer2 = this.mRouletteLayout.findViewById(R.id.spacer2); addView(this.mRouletteLayout); this.mCurrentThemePosition = -1; setSmoothScrollingEnabled(false); } /** * Method that sets the listener where return theme scroll selection changes * * @param onThemeScrollSelectionListener The listener */ public void setOnThemeScrollSelectionListener( OnThemeScrollSelectionListener onThemeScrollSelectionListener) { this.mOnThemeScrollSelectionListener = onThemeScrollSelectionListener; } /** * {@inheritDoc} */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int parentWidth = MeasureSpec.getSize(widthMeasureSpec); int parentHeight = MeasureSpec.getSize(heightMeasureSpec); this.setMeasuredDimension(parentWidth, parentHeight); super.onMeasure(widthMeasureSpec, heightMeasureSpec); int mw = (int)getResources().getDimension(R.dimen.theme_max_width); int w = (int)(getWidth() / 1.5); this.mSpacerWidth = (getWidth() - Math.min(w, mw)) / 2; this.mSpacer1.getLayoutParams().width = this.mSpacerWidth; this.mSpacer2.getLayoutParams().width = this.mSpacerWidth; } /** * {@inheritDoc} */ @Override public boolean onTouchEvent(MotionEvent ev) { // Detect the motion int action = ev.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: if (this.mOnThemeScrollSelectionListener != null) { this.mOnThemeScrollSelectionListener.onScrollSelectionStart(); } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: post(new Runnable() { @Override public void run() { int themeViewPosition = getVisibleThemeViewPosition(); if (themeViewPosition >= 1) { ThemeRoulette.this.mCurrentThemePosition = themeViewPosition; scrollToThemePosition(themeViewPosition, true); } } }); break; } return super.onTouchEvent(ev); } /** * Method that sets the themes of this roulette * * @param themes The themes of this roulette * @param currentTheme The current theme * @param scrollTo The theme to scroll to */ public void setThemes(List<Theme> themes, Theme currentTheme, final int scrollTo) { int cc = themes.size(); int pos = -1; for (int i = 0; i < cc; i++) { Theme theme = themes.get(i); addTheme(this.mRouletteLayout, theme); if (theme.compareTo(currentTheme) == 0) { pos = i + 1; } } // If the theme is found if (pos != -1) { final int childPos = pos; post(new Runnable() { @Override public void run() { ThemeRoulette.this.mCurrentThemePosition = (scrollTo > 0) ? scrollTo : childPos; scrollToThemePosition(ThemeRoulette.this.mCurrentThemePosition, false); markThemeAsDefault(childPos); } }); } } /** * Method that adds a theme to the roulette * * @param root The root view * @param theme The theme to add */ private void addTheme(ViewGroup root, Theme theme) { // Create the layout and assign its theme ThemeView v = (ThemeView)inflate(getContext(), R.layout.theme_view, null); int mw = (int)getResources().getDimension(R.dimen.theme_max_width); int w = (int)(getWidth() / 1.5); this.mThemeWidth = Math.min(w, mw); v.setLayoutParams( new LinearLayout.LayoutParams( this.mThemeWidth, ViewGroup.LayoutParams.MATCH_PARENT)); v.setTag(theme); // Set the view info TextView name = (TextView)v.findViewById(R.id.theme_name); name.setText(theme.getName()); TextView author = (TextView)v.findViewById(R.id.theme_author); author.setText(theme.getAuthor()); TextView desc = (TextView)v.findViewById(R.id.theme_desc); desc.setText(theme.getDescription()); ImageView preview = (ImageView)v.findViewById(R.id.theme_preview); preview.setContentDescription(theme.getName()); Drawable dw = theme.getPreviewImage(getContext()); if (dw != null) { preview.setImageDrawable(dw); } else { dw = theme.getNoPreviewImage(getContext()); preview.setImageDrawable(dw); } // Add to the end of the roulette root.addView(v, root.getChildCount()-1); } /** * Method that returns the visible theme view position, based on the position * on the screen (the most centered is the current view) * * @return int The visible theme view position * @hide */ int getVisibleThemeViewPosition() { int[] rouletteSize = new int[2]; this.getLocationOnScreen(rouletteSize); int x = rouletteSize[0] + (this.getWidth() / 2); int width = 0; int[] location = new int[2]; int cc = this.mRouletteLayout.getChildCount()-1; for (int i = 1; i < cc; i++) { View v = this.mRouletteLayout.getChildAt(i); if (v instanceof ThemeView) { v.getLocationOnScreen(location); width = v.getWidth(); if (location[0] <= x && x <= (location[0] + width)) { return i; } } } return -1; } /** * Method that scroll to the theme position * * @param position The position where to scroll * @param smooth Use a smooth scroll to position * @hide */ void scrollToThemePosition(int position, boolean smooth) { if (position <= 0) return; int x = 0; if (position > 1) { x += ThemeRoulette.this.mThemeWidth * (position - 1); } if (smooth) { smoothScrollTo(x, 0); } else { scrollTo(x, 0); } // Notify the change if (ThemeRoulette.this.mOnThemeScrollSelectionListener != null) { ThemeView v = (ThemeView)ThemeRoulette.this.mRouletteLayout. getChildAt(position); ThemeRoulette.this. mOnThemeScrollSelectionListener. onScrollSelectionChanged((Theme)v.getTag()); } } /** * Method that mark the current visible theme as the default */ void markCurrentVisibleThemeAsDefault() { int position = getVisibleThemeViewPosition(); if (position >= 1) { markThemeAsDefault(position); } } /** * Method that mark the theme as the default * * @param position The position of the theme */ void markThemeAsDefault(int position) { int cc = this.mRouletteLayout.getChildCount()-1; for (int i = 1; i < cc; i++) { ThemeView v = (ThemeView)ThemeRoulette.this.mRouletteLayout. getChildAt(i); if (i == position) { v.getName().setPaintFlags( v.getName().getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); } else { v.getName().setPaintFlags( v.getName().getPaintFlags() & ~Paint.UNDERLINE_TEXT_FLAG); } } } }