/*
* 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.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
import android.os.AsyncTask;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.cyanogenmod.filemanager.R;
import com.cyanogenmod.filemanager.ui.ThemeManager;
import com.cyanogenmod.filemanager.ui.ThemeManager.Theme;
import com.cyanogenmod.filemanager.ui.preferences.ThemeRoulette.OnThemeScrollSelectionListener;
import com.cyanogenmod.filemanager.util.AndroidHelper;
import com.cyanogenmod.filemanager.util.DialogHelper;
import java.util.ArrayList;
import java.util.List;
/**
* A preference implementation for the selection of a theme.
*/
public class ThemeSelectorPreference extends Preference implements OnClickListener {
private static final String TAG = "ThemeSelectorPreference"; //$NON-NLS-1$
/**
* @hide
*/
final AsyncTask<Void, Integer, List<Theme>> mThemeTask =
new AsyncTask<Void, Integer, List<Theme>>() {
/**
* {@inheritDoc}
*/
@Override
protected List<Theme> doInBackground(Void... params) {
List<Theme> themes = new ArrayList<Theme>();
themes.addAll(ThemeManager.getAvailableThemes(getContext()));
return themes;
}
/**
* {@inheritDoc}
*/
@Override
protected void onPostExecute(List<Theme> result) {
ThemeSelectorPreference.this.mRoulette.setThemes(
result,
ThemeManager.getCurrentTheme(getContext()),
ThemeSelectorPreference.this.mScrollTo);
ThemeSelectorPreference.this.mWaiting.setVisibility(View.GONE);
}
};
private View mRootView;
/**
* @hide
*/
Button mButton;
/**
* @hide
*/
ThemeRoulette mRoulette;
/**
* @hide
*/
ProgressBar mWaiting;
// The visible theme, selected by scrolling. This may not be the current theme.
/**
* @hide
*/
Theme mSelectedTheme;
/**
* @hide
*/
int mScrollTo = -1;
/**
* Constructor of <code>ThemeSelectorPreference</code>.
*
* @param context The current context
*/
public ThemeSelectorPreference(Context context) {
super(context);
init();
}
/**
* Constructor of <code>ThemeSelectorPreference</code>.
*
* @param context The current context
* @param attrs The attributes of the XML tag that is inflating the view.
*/
public ThemeSelectorPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
/**
* Constructor of <code>ThemeSelectorPreference</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 ThemeSelectorPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
/**
* Method that initializes the preference
*/
private void init() {
setLayoutResource(R.layout.theme_selector_preference);
}
/**
* {@inheritDoc}
*/
@Override
protected View onCreateView(ViewGroup parent) {
this.mRootView = super.onCreateView(parent);
this.mButton = (Button)this.mRootView.findViewById(R.id.theme_button);
this.mButton.setOnClickListener(this);
this.mRoulette = (ThemeRoulette)this.mRootView.findViewById(R.id.theme_roulette);
this.mRoulette.setOnThemeScrollSelectionListener(new OnThemeScrollSelectionListener() {
@Override
public void onScrollSelectionStart() {
ThemeSelectorPreference.this.mButton.setEnabled(false);
}
@Override
public void onScrollSelectionChanged(Theme theme) {
boolean enabled = ThemeManager.getCurrentTheme(getContext()).compareTo(theme) != 0;
ThemeSelectorPreference.this.mButton.setEnabled(enabled);
if (enabled) {
ThemeSelectorPreference.this.mSelectedTheme = theme;
}
}
});
this.mWaiting = (ProgressBar)this.mRootView.findViewById(R.id.theme_waiting);
return this.mRootView;
}
/**
* {@inheritDoc}
*/
@Override
protected void onBindView(final View view) {
super.onBindView(view);
view.post(new Runnable() {
@Override
public void run() {
Resources res = getContext().getResources();
Display display = ((Activity)getContext()).getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
// Set the preference height
int mh = (int)res.getDimension(R.dimen.theme_max_height);
int rowHeight = 0;
if (!AndroidHelper.isTablet(getContext())) {
rowHeight = (int)res.getDimension(R.dimen.extra_margin);
}
int[] window = new int[2];
view.getLocationInWindow(window);
view.getLayoutParams().height =
Math.min(mh, size.y - window[1] - rowHeight);
// The button width
int minWidth = (int)res.getDimension(R.dimen.themes_min_width_button);
int w = ThemeSelectorPreference.this.mButton.getWidth();
ThemeSelectorPreference.this.mButton.setWidth(Math.max(minWidth, w));
// Now display the progress and load the themes in background
ThemeSelectorPreference.this.mWaiting.setVisibility(View.VISIBLE);
ThemeSelectorPreference.this.mThemeTask.execute();
}
});
}
/**
* {@inheritDoc}
*/
@Override
public void onClick(View v) {
String newValue = this.mSelectedTheme.getComposedId();
if (ThemeManager.setCurrentTheme(getContext(), newValue)) {
if (!persistString(newValue)) {
Log.w(TAG, "can't save theme preference"); //$NON-NLS-1$
}
this.mRoulette.markCurrentVisibleThemeAsDefault();
callChangeListener(newValue);
// Now we are in the current theme
ThemeSelectorPreference.this.mSelectedTheme =
ThemeManager.getCurrentTheme(getContext());
ThemeSelectorPreference.this.mButton.setEnabled(false);
// Display a confirmation
DialogHelper.showToast(
getContext(), R.string.pref_themes_confirmation, Toast.LENGTH_SHORT);
} else {
// The theme was not found
DialogHelper.showToast(
getContext(), R.string.pref_themes_not_found, Toast.LENGTH_SHORT);
}
}
/**
* {@inheritDoc}
*/
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
final SavedState myState = new SavedState(superState);
myState.mPosition = this.mRoulette.mCurrentThemePosition;
return myState;
}
/**
* {@inheritDoc}
*/
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state == null || !state.getClass().equals(SavedState.class)) {
// Didn't save state for us in onSaveInstanceState
super.onRestoreInstanceState(state);
return;
}
SavedState myState = (SavedState) state;
super.onRestoreInstanceState(myState.getSuperState());
this.mScrollTo = myState.mPosition;
}
/**
* A saved state persistence class
*/
static class SavedState extends BaseSavedState {
int mPosition;
/**
* Constructor of <code>SavedState</code>
*
* @param source The original parcel
*/
public SavedState(Parcel source) {
super(source);
this.mPosition = source.readInt();
}
/**
* Constructor of <code>SavedState</code>
*
* @param superState The super state
*/
public SavedState(Parcelable superState) {
super(superState);
this.mPosition = -1;
}
/**
* {@inheritDoc}
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(this.mPosition);
}
/**
* A class for create the saved state
*/
@SuppressWarnings("hiding")
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}