Fix the download action to work through MFE
[armadillo.git] / web_frontend / actor.js
1 //
2 // Armadillo File Manager
3 // Copyright (c) 2010, Robert Sesek <http://www.bluestatic.org>
4 //
5 // This program is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free Software
7 // Foundation, either version 3 of the License, or any later version.
8 //
9
10 goog.provide('armadillo.Actor');
11 goog.provide('armadillo.Actor.TileControlRenderer_');
12
13 goog.require('armadillo.PathControl');
14 goog.require('armadillo.TVRenamer');
15 goog.require('goog.array');
16 goog.require('goog.dom');
17 goog.require('goog.events');
18 goog.require('goog.events.EventHandler');
19 goog.require('goog.style');
20 goog.require('goog.ui.Button');
21 goog.require('goog.ui.Container');
22
23 /**
24 * The Actor is a popup that displays the various actions that can be performed
25 * on a given File.
26 * @param {armadillo.File} file The file to act on.
27 * @param {goog.dom.DomHelper} opt_domHelper
28 * @constructor
29 */
30 armadillo.Actor = function(file, opt_domHelper) {
31 goog.ui.Container.call(this, null, null, opt_domHelper);
32
33 this.setFocusable(false);
34 this.setFocusableChildrenAllowed(true);
35
36 /**
37 * The file object on which this acts.
38 * @type {armadillo.File}
39 */
40 this.file_ = file;
41
42 /**
43 * Registrar for all the Actor's events.
44 * @type {goog.events.EventHandler}
45 */
46 this.eh_ = new goog.events.EventHandler();
47
48 /**
49 * The UI element used for a specific action.
50 * @type {goog.Disposable}
51 */
52 this.actionObject_ = null;
53
54 /**
55 * Controls for the current action.
56 * @type {goog.ui.Control}
57 */
58 this.controlContainer_ = null;
59 }
60 goog.inherits(armadillo.Actor, goog.ui.Container);
61
62 /**
63 * The different options that the Actor can perform.
64 */
65 armadillo.Actor.options_ = {
66 OPEN : 'open',
67 MOVE : 'move',
68 DELETE : 'delete',
69 TV_RENAME : 'tv-rename',
70 DOWNLOAD : 'download'
71 };
72
73 /**
74 * String values for the options.
75 */
76 armadillo.Actor.optionStrings_ = {
77 'open' : 'Open',
78 'move' : 'Move',
79 'delete' : 'Delete',
80 'tv-rename' : 'Rename TV Episode',
81 'download' : 'Download'
82 };
83
84 /**
85 * Disposer
86 * @protected
87 */
88 armadillo.Actor.prototype.disposeInternal = function() {
89 armadillo.Actor.superClass_.disposeInternal.call(this);
90
91 this.eh_.dispose();
92
93 if (this.controlContainer_)
94 this.controlContainer_.dispose();
95 this.controlContainer_ = null;
96
97 // Remove the actor display element.
98 goog.dom.removeNode(this.element_);
99 this.element_ = null;
100
101 if (this.actionObject_) {
102 this.actionObject_.dispose();
103 this.actionObject_ = null;
104 }
105
106 this.file_ = null;
107 };
108
109 armadillo.Actor.prototype.createDom = function() {
110 this.setElementInternal(this.dom_.createDom('div'));
111 this.decorate(this.getElement());
112 };
113
114 /**
115 * Decorates the given element into a path control.
116 * @param {Element} element
117 */
118 armadillo.Actor.prototype.decorateInternal = function(element) {
119 this.element_ = element;
120 goog.dom.classes.add(this.element_, 'actor');
121 this.dom_.removeChildren(this.element_);
122 for (var option in armadillo.Actor.options_) {
123 var tile = this.createTile_(option);
124 if (tile) {
125 this.addChild(tile, true);
126 }
127 }
128 this.controlContainer_ = new goog.ui.Control();
129 this.controlContainer_.setSupportedState(goog.ui.Component.State.FOCUSED, false);
130 this.addChild(this.controlContainer_, true);
131 };
132
133 /**
134 * Creates the DOM Element that is inserted into the popup.
135 * @param {armadillo.Actor.options_} Key of the option to create
136 * @returns {goog.ui.Control}
137 */
138 armadillo.Actor.prototype.createTile_ = function(option) {
139 var value = armadillo.Actor.options_[option];
140
141 // Create the title element.
142 var title = this.dom_.createDom('span', 'title',
143 armadillo.Actor.optionStrings_[value]);
144
145 var tile = new goog.ui.Control(title, new armadillo.Actor.TileControlRenderer_());
146 tile.actorOption = value;
147
148 // Cannot open non-directory files.
149 if (value == armadillo.Actor.options_.OPEN && !this.file_.isDirectory()) {
150 return null;
151 }
152
153 this.eh_.listen(tile, goog.ui.Component.EventType.ACTION,
154 this.tileClickHandler_, false, this);
155 return tile;
156 };
157
158 /**
159 * Click handler for individual tiles.
160 * @param {Event} e
161 */
162 armadillo.Actor.prototype.tileClickHandler_ = function(e) {
163 var option = e.target.actorOption;
164 this.controlContainer_.removeChildren(true);
165 this.controlContainer_.setVisible(true);
166 if (option == armadillo.Actor.options_.OPEN) {
167 // TODO: assert that this.file_.isDirectory().
168 app.navigate(this.file_.getName());
169 } else if (option == armadillo.Actor.options_.MOVE) {
170 this.performMove_();
171 } else if (option == armadillo.Actor.options_.DELETE) {
172 this.performDelete_();
173 } else if (option == armadillo.Actor.options_.TV_RENAME) {
174 this.performTVRename_();
175 } else if (option == armadillo.Actor.options_.DOWNLOAD) {
176 this.performDownload_();
177 }
178 };
179
180 /**
181 * Subroutine to handle bringing up the move confirmation UI.
182 * @private
183 */
184 armadillo.Actor.prototype.performMove_ = function() {
185 var editor = new armadillo.PathControl(this.file_.getFullPath(), true);
186 this.controlContainer_.addChild(editor, true);
187
188 var okCallback = function(e) {
189 var newPath = editor.getPath();
190 this.file_.move(newPath);
191 };
192 this.createOkCancel_(goog.bind(okCallback, this), null);
193 };
194
195 /**
196 * Subroutine to handle bringing up the delete confirmation UI.
197 * @private
198 */
199 armadillo.Actor.prototype.performDelete_ = function() {
200 var content = goog.dom.createDom('span', null,
201 'Are you sure you want to delete:',
202 goog.dom.createElement('br'),
203 goog.dom.createDom('strong', null, this.file_.getName()));
204 this.controlContainer_.addChild(new goog.ui.Control(content), true);
205
206 var okCallback = function(e) {
207 this.file_.remove();
208 };
209 this.createOkCancel_(goog.bind(okCallback, this), null);
210 };
211
212 /**
213 * Subroutine that renames a file to it's title based on season and episode.
214 * @private
215 */
216 armadillo.Actor.prototype.performTVRename_ = function() {
217 var renamer = new armadillo.TVRenamer(this.file_);
218 renamer.run();
219 };
220
221 /**
222 * Subroutine that streams a file.
223 * @private
224 */
225 armadillo.Actor.prototype.performDownload_ = function() {
226 window.location = 'download?path=' + this.file_.getFullPath();
227 };
228
229 /**
230 * Creates two buttons: one for OK one for Cancel and attahes them to the
231 * |controlContainer_|.
232 * @param {function(Event)?} okCallback
233 * @param {function(Event)?} cancelCallback
234 */
235 armadillo.Actor.prototype.createOkCancel_ = function(okCallback, cancelCallback) {
236 var ok = new goog.ui.Button('OK');
237 if (okCallback)
238 this.eh_.listen(ok, goog.ui.Component.EventType.ACTION, okCallback);
239 var cancel = new goog.ui.Button('Cancel');
240 if (!cancelCallback)
241 cancelCallback = goog.bind(this.defaultCancelCallback_, this);
242 this.eh_.listen(cancel, goog.ui.Component.EventType.ACTION, cancelCallback);
243 this.controlContainer_.addChild(ok, true);
244 this.controlContainer_.addChild(cancel, true);
245 };
246
247 /**
248 * The default cancel callback for the above createOkCancel_().
249 * @param {event} e
250 * @private
251 */
252 armadillo.Actor.prototype.defaultCancelCallback_ = function(e) {
253 this.controlContainer_.removeChildren(true);
254 };
255
256 /**
257 * Tile Control Renderer
258 * @constructor
259 */
260 armadillo.Actor.TileControlRenderer_ = function() {
261 goog.ui.ControlRenderer.call(this);
262 };
263 goog.inherits(armadillo.Actor.TileControlRenderer_, goog.ui.ControlRenderer);
264
265 /**
266 * Returns the control's contents wrapped in a DIV, with the renderer's own
267 * CSS class and additional state-specific classes applied to it.
268 * @param {goog.ui.Control} control Control to render.
269 * @return {Element} Root element for the control.
270 */
271 armadillo.Actor.TileControlRenderer_.prototype.createDom = function(control) {
272 // Create and return DIV wrapping contents.
273 return control.getDomHelper().createDom('div', 'tile', control.getContent());
274 };