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