c0a383efc0f368c001a3761a63b551b6e8c41ec8
[PlinnDocument.git] / skins / layout_controlers.js
1 // (c) BenoƮt PIN 2006-2007
2 // http://plinn.org
3 // Licence GPL
4
5 // Global variables
6 var CURRENT_LAYER;
7 var LAYER_MANAGER;
8 var XML_OUTPUT;
9 var PLINN_DOCUMENT_URL;
10 var GLOBAL_DD_CONTROLER;
11
12 function initPlinn(root_container, xmlDataUrl) {
13 PLINN_DOCUMENT_URL = document.getElementById("PlinnDocumentUrl").innerHTML;
14 form_path = PLINN_DOCUMENT_URL+'/'; // for epoz
15 initElementsPool();
16 initWidgets();
17 var imp = new XMLImport(xmlDataUrl, root_container);
18 GLOBAL_DD_CONTROLER = new GlobalPlinnDDControler(root_container);
19 }
20
21
22 function initWidgets() {
23 // Global control widgets
24 XML_OUTPUT = document.getElementById("xml_output")
25 }
26
27 function initLayerManager(root_container) {
28 LAYER_MANAGER = new LayerManager(root_container, new ColorIterator(240, 80, 60, 83)); // todo : move in config file
29 }
30
31 function Point(x, y) {
32 this.x = x;
33 this.y = y;
34 }
35 Point.prototype.difference = function(point) { return new Point(this.x - point.x, this.y - point.y); };
36 Point.prototype.addition = function(point) { return new Point(this.x + point.x, this.y + point.y); };
37 Point.prototype.toString = function() { return "(" + String(this.x) + ", " + String(this.y) + ")"; };
38
39
40 function GlobalPlinnDDControler(root_container) {
41 this.root_container = root_container;
42 this.dragInProgress = false;
43
44 this.currentRect = null;
45 this.dragAllowed = null;
46 this.resizeAllowed = null;
47 this.scalable = null;
48 this.deleteAllowed = null;
49
50
51 //Constants
52 this.DRAG_MODE = 0;
53 this.RESIZE_MODE = 1;
54
55 this.mode = this.DRAG_MODE;
56 this.ddEventCaptureElmt = document;
57
58 // event listeners
59 var thisControler = this;
60 with (this.root_container) {
61 onmouseover = function(evt){thisControler.onmouseover(evt);};
62 onmouseout = function(evt){thisControler.onmouseout(evt);};
63 }
64 with (this.ddEventCaptureElmt) {
65 onmousedown = function(evt){thisControler.onmousedown(evt);};
66 onmousemove = function(evt){thisControler.onmousemove(evt);};
67 onmouseup = function(evt){thisControler.onmouseup(evt);};
68 }
69 }
70
71 GlobalPlinnDDControler.prototype.onmouseover = function(evt) {
72 if (this.dragInProgress) return;
73 var ob = getTargetedObject(evt);
74 var rect = ob.rectangle;
75 if (!rect) return;
76 rect.showHandles();
77 };
78
79 GlobalPlinnDDControler.prototype.onmouseout = function(evt) {
80 if (this.dragInProgress) return;
81 var ob = getTargetedObject(evt);
82 var rect = ob.rectangle;
83 if (!rect) return;
84 rect.hideHandles();
85 };
86
87 GlobalPlinnDDControler.prototype.onmousedown = function(evt) {
88 var ob = getTargetedObject(evt);
89 var rect = ob.rectangle;
90
91 if (!rect) return;
92
93 this.currentRect = rect;
94 this.setDDOptions(rect.ddOptions);
95
96 var evt = getEventObject(evt);
97 if (this.deleteAllowed && (
98 (evt.shiftKey && evt.altKey) ||
99 (ob.tagName == "IMG" && ob.className=="rectangle_delimg")) ) {
100 if (confirm(PlinnLang["Do you realy want to delete ?"])) {
101 var hostDiv = rect.hostDiv;
102 hostDiv.parentNode.removeChild(hostDiv);
103 }
104 return;
105 }
106
107 this.originalClickPoint = new Point(evt.screenX, evt.screenY);
108 this.originalSize = new Point(rect.width, rect.height);
109 this.offsetPoint = rect.upperLeftCorner.difference(this.originalClickPoint);
110
111 if (evt.shiftKey || (ob.tagName == "SPAN" && ob.className=="resize_handle")) {
112 this.mode = this.RESIZE_MODE;
113 this.startDrag(evt, rect);
114 }
115 else if(evt.altKey || (ob.tagName == "DIV" && ob.className=="rectangle_header")){
116 this.mode = this.DRAG_MODE;
117 this.startDrag(evt, rect);
118 }
119 };
120
121 GlobalPlinnDDControler.prototype.onmousemove = function(evt) {
122 var evt = getEventObject(evt);
123 if (this.dragInProgress) {
124 var rectangle = this.currentRect;
125 if (this.dragAllowed && (this.mode == this.DRAG_MODE)) {
126 var relativeEvtPoint = new Point(evt.screenX, evt.screenY).addition(this.offsetPoint);
127 rectangle.moveTo(relativeEvtPoint);
128 }
129 else if (this.resizeAllowed && (this.mode == this.RESIZE_MODE)) {
130 var delta = new Point(evt.screenX, evt.screenY).difference(this.originalClickPoint);
131 var size = this.originalSize.addition(delta);
132 if (this.scalable) {
133 size = new Point(size.x, Math.round(size.x * rectangle.ratio));
134 }
135
136 rectangle.resizeTo(size);
137 }
138 if (browser.isIE) {
139 try {document.selection.clear();}
140 catch (e){return;}
141 }
142 }
143 };
144
145 GlobalPlinnDDControler.prototype.onmouseup = function(evt) {
146 this.drop()
147 var rectangle = this.currentRect;
148 if (rectangle && rectangle.ondrop)
149 rectangle.ondrop();
150 };
151
152
153 GlobalPlinnDDControler.prototype.startDrag = function(evt, rect) {
154 disablePropagation(evt);
155 disableDefault(evt);
156 this.dragInProgress = true;
157 };
158
159 GlobalPlinnDDControler.prototype.drop = function() {this.dragInProgress = false;};
160
161 GlobalPlinnDDControler.prototype.setDDOptions = function(options){
162 this.dragAllowed = (options & 1) == 1;
163 this.resizeAllowed = (options & 2) == 2;
164 this.scalable = (options & 4) == 4;
165 this.deleteAllowed = (options & 8) == 8;
166 };
167
168
169
170 function LayerManager(main_space, colorIterator) {
171 this.space = main_space;
172 this.layers = new Array();
173 this.defaultLayerWidth = 800;
174 this.defaultLayerHeight = 600;
175 this.colorIterator = colorIterator;
176 this.layerSelector = document.getElementById('layerSelector');
177 var thisManager = this;
178
179 // add layer selector commands
180 // separator between layers list and layer commandes
181 var sepOpt = document.createElement("option");
182 sepOpt.innerHTML = "--------";
183 sepOpt.disabled = "disabled";
184 sepOpt.style.color = "#888";
185
186 // new layer command
187 var addLayerOpt = document.createElement("option");
188 addLayerOpt.value = "add";
189 addLayerOpt.innerHTML = PlinnLang["New layer"];
190 addLayerOpt.style.color = "#000";
191
192 // remove layer command
193 var removeLayerOpt = document.createElement("option");
194 removeLayerOpt.value = "rm";
195 removeLayerOpt.innerHTML = PlinnLang["Remove layer"];
196 removeLayerOpt.disabled = "disabled";
197
198 with (this.layerSelector) {
199 appendChild(sepOpt);
200 appendChild(addLayerOpt);
201 appendChild(removeLayerOpt);
202 }
203 addListener(this.layerSelector, 'change', function(){thisManager.activateLayer();});
204 }
205
206 LayerManager.prototype.addLayer = function(position) {
207 var color = this.colorIterator.next();
208 var mode = 6; // resize and delete
209 if (this.layers.length <= 1)
210 mode = 2; // resize only
211 var l = new Rectangle(new Point(0, 0), this.defaultLayerWidth, this.defaultLayerHeight, "DIV_ELEMENT", 2);
212 setBorderColor(l, color.toRGBString());
213 l.onresize = resizeOnMouseMove;
214 l.ondrop = resizeOnDrop;
215 l.style.overflow = "hidden";
216 l.draw(this.space, position);
217 var index = this.layers.push(l) - 1;
218
219 var opt = document.createElement("option");
220 strId = String(index);
221 opt.value = strId;
222 opt.id = "layer_" + strId;
223 opt.innerHTML = PlinnLang["Layer "] + strId;
224 opt.style.color = color.toRGBString();
225 this.layerSelector.insertBefore(opt, this.layerSelector.childNodes[this.layers.length-1]);
226
227 // If there's only one layer, the remove command is disabled.
228 if (this.layers.length > 1) {
229 var rmCommand = this.layerSelector.childNodes[this.layerSelector.length -1]
230 rmCommand.removeAttribute("disabled");
231 rmCommand.style.color="#000";
232 }
233 this.activateLayer(index);
234 };
235
236 LayerManager.prototype.activateLayer = function(index) {
237 var layerSelector = this.layerSelector;
238 var index = (index != null) ? index : layerSelector.value;
239 // handle commands
240 index = ( Number(index) || Number(index ) == 0 ) ? Number(index) : index
241
242 if (typeof(index) == typeof('')) {
243 switch (index) {
244 case "add" :
245 this.addLayer();
246 break;
247 case "rm" :
248 this.removeCurrentLayer();
249 break;
250 };
251 return;
252 }
253
254 CURRENT_LAYER = this.layers[index];
255 this._syncLayerStatusImage();
256 var opt = document.getElementById("layer_" + String(index));
257 layerSelector.selectedIndex = opt.index;
258 layerSelector.style.color = opt.style.color;
259 this.putCurrentLayerOnTop();
260 };
261
262
263 LayerManager.prototype.putCurrentLayerOnTop = function() {
264 for(var i = 0 ; i < this.layers.length ; i++) {
265 layer = this.layers[i];
266 if (layer == CURRENT_LAYER)
267 layer.style.zIndex = String(this.layers.length);
268 else
269 layer.style.zIndex = String(i);
270 }
271 };
272
273 LayerManager.prototype.toggleLayerVisibility = function(){
274 var currentVisibility = CURRENT_LAYER.style.visibility;
275 if (currentVisibility == "hidden")
276 CURRENT_LAYER.style.visibility = "visible";
277 else
278 CURRENT_LAYER.style.visibility = "hidden";
279
280 this._syncLayerStatusImage();
281 };
282
283 LayerManager.prototype._syncLayerStatusImage = function() {
284 var layerStatusImage = document.getElementById("layer_status");
285 if (CURRENT_LAYER.style.visibility == "hidden") {
286 layerStatusImage.src = "plinn_icons/hidden_layer.gif";
287 layerStatusImage.title = PlinnLang["Show layer"];
288 }
289 else {
290 layerStatusImage.src = "plinn_icons/visible_layer.gif";
291 layerStatusImage.title = PlinnLang["Hide layer"];
292 }
293 };
294
295 LayerManager.prototype.removeCurrentLayer = function() {
296 var layersLength = this.layers.length;
297 var layerSelector = this.layerSelector;
298 var layer, deletedLayerIndex;
299 for (var i = 0 ; i < layersLength ; i++) {
300 layer = this.layers[i];
301 if (layer == CURRENT_LAYER) {
302 if (confirm(PlinnLang["confirm_layer_delete"] + i + "\" ?")) {
303 this.space.removeChild(layer.hostDiv);
304 this.layers.splice(i, 1);
305 layerSelector.removeChild(layerSelector.childNodes[i]);
306 deletedLayerIndex = i;
307 break;
308 }
309 else {
310 this.activateLayer(i);
311 return;
312 }
313 }
314 }
315
316 // update layer indexes
317 for (var i = 0 ; i < this.layers.length ; i++) {
318 layerSelector.childNodes[i].value = String(i);
319 layerSelector.childNodes[i].id = "layer_" + String(i);
320 layerSelector.childNodes[i].innerHTML = PlinnLang["Layer "] + String(i);
321 }
322
323 if (this.layers.length == 1) {
324 var removeCmdOpt = layerSelector.childNodes[layerSelector.childNodes.length - 1];
325 removeCmdOpt.disabled = "disabled";
326 removeCmdOpt.style.color = "#888";
327 }
328
329 if (deletedLayerIndex == 0)
330 this.layers[0].style.position = "relative";
331
332 // activate previous layer
333 this.activateLayer((deletedLayerIndex > 0) ? --deletedLayerIndex : 0);
334
335 };
336
337 function resizeOnMouseMove() {
338 if (LAYER_MANAGER.layers.length > 5)
339 return; // to expensive
340 else
341 _resizeAllLayers(this);
342 }
343
344 function resizeOnDrop() { _resizeAllLayers(this);}
345
346 function _resizeAllLayers(layer) {
347 var layers = LAYER_MANAGER.layers;
348 var size = new Point(layer.width, layer.height);
349 var l;
350 for(var i = 0 ; i < layers.length ; i++) {
351 l = layers[i];
352 if (layer != l)
353 l.resizeTo(size, true);
354 }
355 LAYER_MANAGER.defaultLayerWidth = size.x;
356 LAYER_MANAGER.defaultLayerHeight = size.y;
357 }
358
359 function CreateAttachmentLink(data) {
360 // data like that : "title[attachment/a_file]
361 var title = data.split("\[", 1)[0];
362 var url =data.match(/\[(.*)\]/)[1];
363 var link ="<a href=\"" + url + "\">" + title + "</a>";
364 InsertHTML(link);
365 }