      1 /*
      2 Script:
      3 	Deluge.OptionsManager.js
      4
      5 Copyright:
      6 	(C) Damien Churchill 2009 <damoxc@gmail.com>
      7 	This program is free software; you can redistribute it and/or modify
      8 	it under the terms of the GNU General Public License as published by
      9 	the Free Software Foundation; either version 3, or (at your option)
     10 	any later version.
     11
     12 	This program is distributed in the hope that it will be useful,
     13 	but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 	GNU General Public License for more details.
     16
     17 	You should have received a copy of the GNU General Public License
     18 	along with this program.  If not, write to:
     19 		The Free Software Foundation, Inc.,
     20 		51 Franklin Street, Fifth Floor
     21 		Boston, MA  02110-1301, USA.
     22
     23     In addition, as a special exception, the copyright holders give
     24     permission to link the code of portions of this program with the OpenSSL
     25     library.
     26     You must obey the GNU General Public License in all respects for all of
     27     the code used other than OpenSSL. If you modify file(s) with this
     28     exception, you may extend this exception to your version of the file(s),
     29     but you are not obligated to do so. If you do not wish to do so, delete
     30     this exception statement from your version. If you delete this exception
     31     statement from all source files in the program, then also delete it here.
     32 */
     33
     34 /**
     35  * @description A class that can be used to manage options throughout the ui.
     36  * @namespace Deluge
     37  * @class Deluge.OptionsManager
     38  */
     39 Deluge.OptionsManager = Ext.extend(Ext.util.Observable, {
     40
     41 	constructor: function(config) {
     42 		this.binds = {};
     43 		this.changed = {};
     44 		this.defaults = config['defaults'] || {};
     45 		this.options = {};
     46 		this.currentId = null;
     47
     48 		this.addEvents({
     49 			'add': true,
     50 			'changed': true,
     51 			'reset': true
     52 		});
     53 		this.on('changed', this.onChange, this);
     54
     55 		Deluge.OptionsManager.superclass.constructor.call(this);
     56 	},
     57
     58 	/**
     59 	 * Add a set of default options and values to the options manager
     60 	 * @param {String} id
     61 	 * @param {Object} options The default options.
     62 	 */
     63 	addOptions: function(id, options) {
     64 		this.options[id] = options;
     65 	},
     66
     67 	/**
     68 	 * Binds a form field to the specified option.
     69 	 * @param {String} option
     70 	 * @param {Ext.form.Field} field
     71 	 */
     72 	bind: function(option, field) {
     73 		this.binds[option] = field;
     74 		this.binds[field] = option;
     75
     76 		switch (field.getXType()) {
     77 			case 'checkbox':
     78 			case 'radiogroup':
     79 				field.on('check', this.onFieldChange, this);
     80 				break;
     81 			case 'uxspinner':
     82 				field.on('spin', this.onFieldChange, this);
     83 				field.on('keypress', this.onFieldChange, this);
     84 				break;
     85 			default:
     86 				break;
     87 		}
     88 	},
     89
     90 	/**
     91 	 * Changes bound fields to use the specified id.
     92 	 * @param {String} id
     93 	 */
     94 	changeId: function(id) {
     95 		this.currentId = id;
     96 		for (var option in this.defaults) {
     97 			if (!this.binds[option]) continue;
     98 			this.binds[option].setValue(this.get(id, option));
     99 		}
    100 	},
    101
    102 	/**
    103 	 * Get the value for an option
    104 	 * @param {String} id
    105 	 * @param {String|Array} [option] A single option or an array of options to return.
    106 	 * @returns {Object} the options value.
    107 	 */
    108 	get: function(id, option) {
    109 		if (!option) {
    110 			var values = {};
    111 			for (var key in this.defaults) {
    112 				values[key] = this.get(id, key);
    113 			}
    114 			return values;
    115 		} else {
    116 			return (this.hasChanged(id, option)) ? this.changed[id][option] : this.getDefault(id, option);
    117 		}
    118 	},
    119
    120 	/**
    121 	 * Returns the changed values.
    122 	 * @param {String} id
    123 	 * @returns {Object} the changed options
    124 	 */
    125 	getChanged: function(id) {
    126 		return (this.changed[id]) ? this.changed[id] : {};
    127 	},
    128
    129 	/**
    130 	 * Get the default value for an option.
    131 	 * @param {String} id
    132 	 * @param {String|Array} [option] A single option or an array of options to return.
    133 	 * @returns {Object} the value of the option
    134 	 */
    135 	getDefault: function(id, option) {
    136 		return (this.hasOption(id, option)) ? this.options[id][option] : this.defaults[option];
    137 	},
    138
    139 	/**
    140 	 * Check to see if the option has been changed.
    141 	 * @param {String} id
    142 	 * @param {String} option
    143 	 * @returns {Boolean} true if the option has been changed, else false.
    144 	 */
    145 	hasChanged: function(id, option) {
    146 		return (this.changed[id] && !Ext.isEmpty(this.changed[id][option]));
    147 	},
    148
    149 	/**
    150 	 * Check to see if an id has had an option set to something other than the
    151 	 * default value.
    152 	 * @param {String} id
    153 	 * @param {String} option
    154 	 * @returns {Boolean} true if the id has an option, else false.
    155 	 */
    156 	hasOption: function(id, option) {
    157 		return (this.options[id] && !Ext.isEmpty(this.options[id][option]));
    158 	},
    159
    160 	/**
    161 	 * Reset the options back to the default values for the specified id.
    162 	 * @param {String} id
    163 	 */
    164 	reset: function(id) {
    165 		if (!this.changed[id]) return;
    166 		delete this.changed[id];
    167 	},
    168
    169 	/**
    170 	 * Sets the value of specified option for the passed in id.
    171 	 * @param {String} id
    172 	 * @param {String} option
    173 	 * @param {Object} value The value for the option
    174 	 */
    175 	set: function(id, option, value) {
    176 		if (typeof value === undefined) {
    177 			for (var key in option) {
    178 				this.set(id, key, option[key]);
    179 			}
    180 		} else {
    181 			if (!this.options[id]) this.options[id] = {};
    182 			this.options[id][option] = value;
    183 		}
    184 	},
    185
    186 	/**
    187 	 * Update the value for the specified option and id.
    188 	 * @param {String} id
    189 	 * @param {String|Object} option or options to update
    190 	 * @param {Object} [value];
    191 	 */
    192 	update: function(id, option, value) {
    193 		if (typeof value === undefined) {
    194 			for (var key in option) {
    195 				this.update(id, key, option[key]);
    196 			}
    197 		} else {
    198 			if (!this.changed[id]) this.changed[id] = {};
    199
    200 			var oldValue = this.get(id, option);
    201 			if (oldValue == value) return;
    202
    203 			var defaultValue = this.getDefault(id, option);
    204 			if (defaultValue == value) {
    205 				if (this.hasChanged(id, option)) delete this.changed[id][option];
    206 				this.fireEvent('changed', id, option, value, oldValue);
    207 				return;
    208 			}
    209
    210 			if (Ext.type(defaultValue) != Ext.type(value)) {
    211 				switch (Ext.type(defaultValue)) {
    212 					case 'string':
    213 						value = String(value);
    214 						break;
    215 					case 'number':
    216 						value = Number(value);
    217 						break;
    218 					case 'boolean':
    219 						value = Boolean(value);
    220 						break;
    221 				}
    222 			}
    223
    224 			this.changed[id][option] = value;
    225 			this.fireEvent('changed', id, option, value, oldValue);
    226 		}
    227 	},
    228
    229 	/* Event Handlers */
    230
    231 	/**
    232 	 * Stops a form fields value from being blocked by the change functions
    233 	 * @param {Ext.form.Field} field
    234 	 * @private
    235 	 */
    236 	onFieldChange: function(field) {
    237 		var option = this.binds[field];
    238 		this.update(this.currentId, option, field.getValue());
    239 	},
    240
    241 	onChange: function(id, option, newValue, oldValue) {
    242 		// If we don't have a bind there's nothing to do.
    243 		if (Ext.isEmpty(this.binds[option])) return;
    244
    245 		// Set the form field to the new value.
    246 		this.binds[option].setValue(newValue);
    247 	}
    248 });
    249