Guest User

Untitled

a guest
Dec 8th, 2009
614
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.18 KB | None | 0 0
  1. /*
  2.  * ----------------------------------------------------------------------------
  3.  * "THE BEER-WARE LICENSE" (Revision 42):
  4.  * <kool.name at gmail.com> wrote this file. As long as you retain this notice you
  5.  * can do whatever you want with this stuff. If we meet some day, and you think
  6.  * this stuff is worth it, you can buy me a beer in return.  Justin "kool.name" Lee
  7.  * ----------------------------------------------------------------------------
  8.  */
  9.  
  10.  
  11. package org.dean;
  12.  
  13. import android.R;
  14. import android.app.AlertDialog;
  15. import android.content.Context;
  16. import android.content.DialogInterface;
  17. import android.content.res.TypedArray;
  18. import android.preference.DialogPreference;
  19. import android.util.AttributeSet;
  20. import android.util.Log;
  21. import android.widget.Toast;
  22.  
  23. public class MultiListPreference extends DialogPreference {
  24.     /** Tag for logging! */
  25.     public static final String TAG = "MultiListPreference";
  26.  
  27.     /** How the "choices" will be delimeted. */
  28.     public static final String CHOICE_DELIMITER = ";";
  29.     /** Truth regex thing. */
  30.     public static final String TRUTH_REGEX = "^(?i:t(?:rue)?)";
  31.     /** "Using default." message incase of dialog error. */
  32.     public static final String USING_DEFAULT = "Using default.";
  33.  
  34.     /** Contains the boolean state of each entry. */
  35.     private boolean[] state = null;
  36.     /** Contains textual representations of the entries. */
  37.     private CharSequence[] entry = null;
  38.     /** Contains the default value, if any. */
  39.     private String defaultValue = null;
  40.  
  41.  
  42.     /** Parse character sequence array into boolean array using regex.
  43.         @param state Character sequence array to parse.
  44.         @return Boolean array or null. */
  45.     private static boolean[] cs2b(CharSequence[] state) {
  46.         Log.d(TAG, "cs2b()");
  47.  
  48.         boolean[] out = null;
  49.        
  50.         if (state != null) {
  51.             out = new boolean[state.length];
  52.  
  53.             for (int e = 0; e < state.length; e++) {
  54.                 out[e] = state[e].toString().matches(TRUTH_REGEX);
  55.             }
  56.         }
  57.  
  58.         return (out);
  59.     }
  60.  
  61.     /** Parse delimited numbers into a boolean array.
  62.         @param state The states given here will be true.
  63.         @param size The array size.
  64.         @return Boolean array of given size or null. */
  65.     private static boolean[] ds2b(CharSequence state, int size) {
  66.         Log.d(TAG, "ds2b(): " + state + " (" + size + ")");
  67.  
  68.         boolean[] out = null;
  69.  
  70.         if (state != null) {
  71.             out = new boolean[size];
  72.  
  73.             String[] s = state.toString().split(CHOICE_DELIMITER);
  74.    
  75.             for (int e = 0; e < s.length; e++) {
  76.                 int index = Integer.parseInt(s[e]);
  77.    
  78.                 if (index < out.length) {
  79.                     out[e] = true;
  80.                 } else {
  81.                     out = null;
  82.                     break;
  83.                 }
  84.             }
  85.         }
  86.  
  87.         return (out);
  88.     }
  89.  
  90.     /** Turn boolean array into delimited numbers.
  91.         @param state State array.
  92.         @return Delimited number thing or null. */
  93.     private static CharSequence b2ds(boolean[] state) {
  94.         Log.d(TAG, "b2ds()");
  95.  
  96.         String out = null;
  97.  
  98.         if (state != null) {
  99.             for (int e = 0; e < state.length; e++) {
  100.                 if (state[e]) {
  101.                     if (out == null) {
  102.                         out = "" + e;
  103.                     } else {
  104.                         out += CHOICE_DELIMITER + e;
  105.                     }
  106.                 }
  107.             }
  108.  
  109.             if (out == null) {
  110.                 out = "";
  111.             }
  112.         }
  113.  
  114.         return (out);
  115.     }
  116.  
  117.  
  118.     /** Set the entries to something new.
  119.         @param entry New entry array.
  120.         @return Success or failure flag. */
  121.     public boolean setEntries(CharSequence[] entry) {
  122.         Log.d(TAG, "setEntries()");
  123.  
  124.         boolean updated = false;
  125.  
  126.         if (this.entry == null) {
  127.             if (this.state == null) {
  128.                 updated = true;
  129.             } else if (entry.length == this.state.length) {
  130.                 updated = true;
  131.             }
  132.         } else if (entry.length == this.entry.length) {
  133.             updated = true;
  134.         }
  135.  
  136.         if (updated) {
  137.             this.entry = entry;
  138.         }
  139.  
  140.         return (updated);
  141.     }
  142.  
  143.     /** Fetch a copy of the current entry array.
  144.         @return Current entry array clone. */
  145.     public CharSequence[] getEntries() {
  146.         Log.d(TAG, "getEntries()");
  147.  
  148.         return (this.entry.clone());
  149.     }
  150.  
  151.     /** Set the state to something new.
  152.         @param state New state array.
  153.         @return Success or failure flag. */
  154.     public boolean setValue(boolean[] state) {
  155.         Log.d(TAG, "setValue()");
  156.  
  157.         boolean updated = false;
  158.  
  159.         if (this.state == null) {
  160.             if (this.entry == null) {
  161.                 updated = true;
  162.             } else if (state.length == this.entry.length) {
  163.                 updated = true;
  164.             }
  165.         } else if (state.length == this.state.length) {
  166.             updated = true;
  167.         }
  168.  
  169.         if (updated) {
  170.             this.state = state;
  171.         }
  172.  
  173.         return (updated);
  174.     }
  175.  
  176.     /** Set the state to something new, state must be previously initialized.
  177.         @param state New state, given by delimeted index.
  178.         @return Success or failure flag. */
  179.     public boolean setValue(CharSequence state) {
  180.         Log.d(TAG, "setValue(): " + state);
  181.  
  182.         boolean updated = false;
  183.  
  184.         if (this.state != null) {
  185.             boolean[] newState = ds2b(state, this.state.length);
  186.  
  187.             if (newState != null) {
  188.                 this.state = newState;
  189.                 updated = true;
  190.             }
  191.         }
  192.  
  193.         return (updated);
  194.     }
  195.  
  196.     /** Fetch a copy of the current state array.
  197.         @return Current state array clone. */
  198.     public boolean[] getValue() {
  199.         Log.d(TAG, "getValue()");
  200.  
  201.         return (this.state.clone());
  202.     }
  203.  
  204.  
  205.     public MultiListPreference(Context context, AttributeSet attrs) {
  206.         super(context, attrs); Log.d(TAG, "MultiListPreference()");
  207.  
  208.         TypedArray in = context.obtainStyledAttributes(
  209.             attrs,
  210.             new int[]{
  211.                 // "android:entries", just like ListPreference
  212.                 R.attr.entries,
  213.                 // "android:entryValues", these are defaults ONLY
  214.                 R.attr.entryValues,
  215.                 // "android:defaultValue"
  216.                 R.attr.defaultValue
  217.             }
  218.         );
  219.  
  220.         this.entry = in.getTextArray(0);
  221.         this.defaultValue = in.getString(2);
  222.  
  223.         if (this.entry == null) {
  224.             Log.d(TAG, "MultiListPreference(): Could not restore entry.");
  225.         } else {
  226.             Log.d(TAG, "MultiListPreference(): Entry from defaults.");
  227.  
  228.             if (this.defaultValue != null) {
  229.                 this.state = ds2b(this.defaultValue, this.entry.length);
  230.             }
  231.  
  232.             if (this.state == null) {
  233.                 this.state = cs2b(in.getTextArray(1));
  234.  
  235.                 if (this.state == null) {
  236.                     Log.d(TAG, "MultiListPreference(): Could not restore state.");
  237.                 } else {
  238.                     Log.d(TAG, "MultiListPreference(): Restored state from entryValues.");
  239.                 }
  240.             } else {
  241.                 Log.d(TAG, "MultiListPreference(): Restored state from defaultValue.");
  242.             }
  243.         }
  244.  
  245.         in.recycle();
  246.     }
  247.  
  248.  
  249.     @Override // here we set the multichoiceitem content
  250.     public void onPrepareDialogBuilder(AlertDialog.Builder builder) {
  251.         Log.d(TAG, "onPrepareDialogBuilder()");
  252.  
  253.         // try to restore state from persisted value
  254.         if (this.entry != null || this.state != null) {
  255.             int size = (
  256.                 (this.entry == null)
  257.                     ? this.state.length
  258.                     : this.entry.length
  259.             );
  260.            
  261.             boolean[] persistedState = ds2b(this.getPersistedString(null), size);
  262.  
  263.             if (persistedState != null) {
  264.                 this.state = persistedState;
  265.  
  266.                 Log.d(TAG, "onPrepareDialogBuilder(): Persisted state restored.");
  267.             }
  268.         }
  269.  
  270.  
  271.         // build the dialog
  272.         builder
  273.             .setCancelable(false)
  274.  
  275.             .setMultiChoiceItems(
  276.                 this.entry, // entries pulled from XML
  277.                 this.state,
  278.  
  279.                 new DialogInterface.OnMultiChoiceClickListener() {
  280.                     // make a "convenience" pointer, cause I'm lazy
  281.                     private final MultiListPreference that = MultiListPreference.this;
  282.  
  283.                     @Override
  284.                     public void onClick(DialogInterface dialog, int which, boolean isChecked) {
  285.                         Log.d(TAG, "listItem_" + which + ".onClick(): " + isChecked);
  286.  
  287.                         that.state[which] = isChecked;
  288.                     }
  289.                 }
  290.             )
  291.         ;
  292.     }
  293.  
  294.  
  295.     @Override // called when OK (true) or Cancel (false) are pushed
  296.     public void onDialogClosed(boolean positiveResult) {
  297.         Log.d(TAG, "onDialogClosed(): " + positiveResult);
  298.  
  299.         if (positiveResult) {
  300.             // only commit if my change listener says so
  301.             if (this.callChangeListener(this.state)) {
  302.                 String out = (String) b2ds(this.state);
  303.  
  304.                 // check if the value is OK
  305.                 if (out == null || out == "") {
  306.                     Toast.makeText(
  307.                         this.getContext(),
  308.                         USING_DEFAULT,
  309.                         Toast.LENGTH_SHORT
  310.                     ).show();
  311.                        
  312.                     out = (
  313.                         (this.defaultValue == null)
  314.                             ? "0" // XXX: lol, hax
  315.                             : this.defaultValue
  316.                     );
  317.                 }
  318.  
  319.                 Log.d(TAG, "onDialogClosed(): Saving: " + out);
  320.  
  321.                 if (this.persistString(out)) {
  322.                     this.notifyChanged();
  323.                 } else {
  324.                     Log.d(TAG, "onDialogClosed(): Saving failed.");
  325.                 }
  326.             }
  327.         }
  328.     }
  329. }
Advertisement
Add Comment
Please, Sign In to add comment