First pass at the PathControl.
[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
12 goog.require('armadillo.PathControl');
13 goog.require('goog.array');
14 goog.require('goog.dom');
15 goog.require('goog.events');
16 goog.require('goog.positioning.ClientPosition');
17 goog.require('goog.positioning.Corner');
18 goog.require('goog.ui.Dialog');
19 goog.require('goog.ui.Popup');
20
21 /**
22 * The Actor is a popup that displays the various actions that can be performed
23 * on a given File.
24 * @param {armadillo.File} file The file to act on.
25 * @constructor
26 */
27 armadillo.Actor = function(file) {
28 goog.Disposable.call(this);
29 this.file_ = file;
30 this.element_ = this.createElement_();
31 this.popup_ = new goog.ui.Popup(this.element_);
32 armadillo.Actor.actors_.push(this);
33 }
34 goog.inherits(armadillo.Actor, goog.Disposable);
35
36 /**
37 * An array of all the Actors that have been created.
38 */
39 armadillo.Actor.actors_ = new Array();
40
41 /**
42 * The different options that the Actor can perform.
43 */
44 armadillo.Actor.options_ = {
45 OPEN : 'open',
46 MOVE : 'move',
47 RENAME : 'rename',
48 DELETE : 'delete'
49 };
50
51 /**
52 * String values for the options.
53 */
54 armadillo.Actor.optionStrings_ = {
55 'open' : 'Open',
56 'move' : 'Move',
57 'rename' : 'Rename',
58 'delete' : 'Delete'
59 };
60
61 /**
62 * A global property that should be checked to see if an actor is present,
63 * creating a modal session.
64 */
65 armadillo.Actor.isModal = function() {
66 var isVisible = false;
67 goog.array.forEach(armadillo.Actor.actors_, function (e) {
68 isVisible |= e.popup_.isVisible();
69 });
70 return isVisible;
71 };
72
73 /**
74 * Disposer
75 * @protected
76 */
77 armadillo.Actor.prototype.disposeInternal = function() {
78 armadillo.Actor.superClass_.disposeInternal.call(this);
79
80 // Unlisten the tiles.
81 var tiles = goog.dom.getElementsByClassName('tile', this.element_);
82 goog.array.forEach(tiles, function (tile) {
83 goog.events.unlistenByKey(tile.actorListener);
84 });
85
86 // Remove the actor display element.
87 goog.dom.removeNode(this.element_);
88 this.element_ = null;
89
90 // Kill the popup.
91 this.popup_.dispose();
92 this.popup_ = null;
93
94 // Remove the actor from the list.
95 goog.array.remove(armadillo.Actor.actors_, this);
96
97 this.file_ = null;
98 };
99
100 /**
101 * Shows the popup.
102 * @param {int} x The X position to show at
103 * @param {int} y The Y position to show at
104 */
105 armadillo.Actor.prototype.show = function(x, y) {
106 if (armadillo.Actor.isModal())
107 return;
108 var firstBodyElement = goog.dom.getFirstElementChild(document.body);
109 goog.dom.insertSiblingBefore(this.element_, firstBodyElement);
110 this.popup_.setPinnedCorner(goog.positioning.Corner.TOP_LEFT);
111 this.popup_.setPosition(new goog.positioning.ClientPosition(x, y));
112 this.popup_.setHideOnEscape(true);
113 this.popup_.setVisible(true);
114 };
115
116 /**
117 * Hides the popup.
118 */
119 armadillo.Actor.prototype.hide = function() {
120 this.popup_.setVisible(false);
121 };
122
123 /**
124 * Creates the DOM Element that is inserted into the popup.
125 * @returns Element
126 */
127 armadillo.Actor.prototype.createElement_ = function() {
128 var root = goog.dom.createDom('div', 'actor');
129 for (var option in armadillo.Actor.options_) {
130 var tile = goog.dom.createDom('div', 'tile');
131 var value = armadillo.Actor.options_[option];
132 // Cannot open non-directory files.
133 if (value == armadillo.Actor.options_.OPEN && !this.file_.isDirectory()) {
134 continue;
135 }
136 var title = goog.dom.createDom('span', 'title',
137 armadillo.Actor.optionStrings_[value]);
138 goog.dom.appendChild(tile, title);
139 goog.dom.appendChild(root, tile);
140 tile.actorOption = value;
141 tile.actorListener = goog.events.listen(tile, goog.events.EventType.CLICK,
142 this.tileClickHandler_, false, this);
143 }
144 return root;
145 };
146
147 /**
148 * Click handler for individual tiles.
149 * @param {Event} e
150 */
151 armadillo.Actor.prototype.tileClickHandler_ = function(e) {
152 var option = e.target.actorOption;
153 if (option == armadillo.Actor.options_.OPEN) {
154 // TODO: assert that this.file_.isDirectory().
155 app.navigate(this.file_.getName());
156 this.hide();
157 } else if (option == armadillo.Actor.options_.MOVE) {
158 this.performMove_();
159 } else if (option == armadillo.Actor.options_.DELETE) {
160 this.performDelete_();
161 }
162 };
163
164 /**
165 * Subroutine to handle bringing up the move confirmation UI.
166 * @private
167 */
168 armadillo.Actor.prototype.performMove_ = function() {
169 var dialog = this.createActionDialog_();
170 dialog.setTitle('Move File');
171
172 var container = dialog.getContentElement();
173
174 var editor = new armadillo.PathControl(this.file_.getFullPath());
175 editor.render(container);
176
177 /*
178 goog.dom.appendChild(container,
179 goog.dom.createDom('p', null,
180 'Enter a new, absolute path for this file.'));
181 var field = goog.dom.createElement('input');
182 field.type = 'text';
183 field.value = this.file_.getFullPath();
184 goog.dom.appendChild(container, field)
185 // TODO: Suck less.
186 goog.dom.appendChild(container,
187 goog.dom.createDom('p', 'smallfont',
188 '(Please pardon this interface. Armadillo is a work-in-progress.)'));
189
190 field.focus();
191 */
192 dialog.setVisible(true);
193 };
194
195 /**
196 * Subroutine to handle bringing up the delete confirmation UI.
197 * @private
198 */
199 armadillo.Actor.prototype.performDelete_ = function() {
200 var confirm = this.createActionDialog_();
201 confirm.setTitle('Confirm Delete');
202
203 var container = confirm.getContentElement();
204 var content = goog.dom.createDom('span', null,
205 'Are you sure you want to delete:',
206 goog.dom.createElement('br'),
207 goog.dom.createDom('strong', null, this.file_.getName()));
208 goog.dom.appendChild(container, content);
209
210 var closeCallback = function(e) {
211 if (e.key != goog.ui.Dialog.DefaultButtonKeys.CANCEL) {
212 this.file_.remove();
213 }
214 };
215 // Will be removed when the event source closes.
216 goog.events.listen(confirm, goog.ui.Dialog.SELECT_EVENT,
217 closeCallback, false, this);
218
219 confirm.setVisible(true);
220 };
221
222 /**
223 * Creates a new instance of a Dialog that has some basic properties set that
224 * are common to performing actions.
225 * @private
226 */
227 armadillo.Actor.prototype.createActionDialog_ = function() {
228 var confirm = new goog.ui.Dialog();
229 confirm.setDisposeOnHide(true);
230 confirm.setEscapeToCancel(true);
231 confirm.setModal(true);
232 confirm.setDraggable(false);
233 confirm.setHasTitleCloseButton(false);
234 return confirm;
235 };