Handling del/ctrl-x (wip)
[fnpeditor.git] / modules / rng / rng.js
1 define([
2 'fnpjs/layout',
3 'fnpjs/vbox',
4 'views/tabs/tabs',
5 'libs/text!./mainLayout.html',
6 'libs/text!./editingLayout.html',
7 'libs/text!./diffLayout.html',
8 ], function(layout, vbox, tabs, mainLayoutTemplate, visualEditingLayoutTemplate, diffLayoutTemplate) {
9
10 'use strict';
11
12 return function(sandbox) {
13     
14     function addMainTab(title, slug, view) {
15         views.mainTabs.addTab(title, slug, view);
16     }
17     
18     var dirty = {
19         sourceEditor: false,
20         documentCanvas: false,
21         metadataEditor: false,
22     };
23     
24     var synchronizeTab = function(slug) {
25         function tabIsDirty(slug) {
26             if(slug === 'editor' && (dirty.documentCanvas || dirty.metadataEditor))
27                 return true;
28             if(slug === 'sourceEditor' && dirty.sourceEditor)
29                 return true;
30             return false;
31         }
32     
33         if(tabIsDirty(slug)) {
34             var reason, doc;
35             if(slug === 'sourceEditor') {
36                 doc = sandbox.getModule('sourceEditor').getDocument();
37                 reason = 'source_edit';
38                 dirty.sourceEditor = false;
39             }
40             if(slug === 'editor') {
41                 doc = dirty.documentCanvas ? sandbox.getModule('documentCanvas').getDocument() : sandbox.getModule('data').getDocument();
42                 if(dirty.metadataEditor) {
43                     doc = sandbox.getModule('metadataEditor').attachMetadata(doc);
44                 }
45                 reason = 'edit';
46                 dirty.documentCanvas = dirty.metadataEditor = false;
47             }
48             sandbox.getModule('data').commitDocument(doc, reason);
49         }
50     };
51     
52     var commands = {
53         highlightDocumentElement: function(element, origin) {
54             ///'nodeBreadCrumbs', 'nodeFamilyTree'
55             ['documentCanvas', ].forEach(function(moduleName) {
56                 if(!origin || moduleName != origin)
57                     sandbox.getModule(moduleName).highlightElement(element);
58             });
59         },
60         dimDocumentElement: function(element, origin) {
61             //'nodeBreadCrumbs', 'nodeFamilyTree'
62             ['documentCanvas'].forEach(function(moduleName) {
63                 if(!origin || moduleName != origin)
64                     sandbox.getModule(moduleName).dimElement(element);
65             });
66         },
67         jumpToDocumentElement: function(element) {
68             sandbox.getModule('documentCanvas').jumpToElement(element);
69         },
70         updateCurrentNodeElement: function(nodeElement) {
71             sandbox.getModule('nodePane').setNodeElement(nodeElement);
72             sandbox.getModule('nodeFamilyTree').setElement(nodeElement);
73             sandbox.getModule('nodeBreadCrumbs').setNodeElement(nodeElement);
74         },
75         updateCurrentTextElement: function(textElement) {
76             sandbox.getModule('nodeFamilyTree').setElement(textElement);
77         },
78         resetDocument: function(document, reason) {
79             var modules = [];
80             if(reason === 'source_edit')
81                 modules = ['documentCanvas', 'metadataEditor'];
82             else if (reason === 'edit')
83                 modules = ['sourceEditor'];
84             else if (reason === 'revert')
85                 modules = ['documentCanvas', 'metadataEditor', 'sourceEditor'];
86                 
87             modules.forEach(function(moduleName) {
88                 sandbox.getModule(moduleName).setDocument(document);
89             });
90         }
91     };
92     
93
94     var views = {
95         mainLayout: new layout.Layout(mainLayoutTemplate),
96         mainTabs: (new tabs.View()).render(),
97         visualEditing: new layout.Layout(visualEditingLayoutTemplate),
98         visualEditingSidebar: (new tabs.View({stacked: true})).render(),
99         currentNodePaneLayout: new vbox.VBox(),
100         diffLayout: new layout.Layout(diffLayoutTemplate)
101     };
102     
103     views.visualEditing.setView('rightColumn', views.visualEditingSidebar.getAsView());
104     addMainTab('Edytor', 'editor', views.visualEditing.getAsView());
105     addMainTab(gettext('Source'), 'sourceEditor',  '');
106     addMainTab('Historia', 'history', views.diffLayout.getAsView());
107     
108     sandbox.getDOM().append(views.mainLayout.getAsView());
109     
110     views.visualEditingSidebar.addTab({icon: 'pencil'}, 'edit', views.currentNodePaneLayout.getAsView());
111
112     views.mainTabs.on('tabSelected', function(event) {
113         if(event.prevSlug) {
114             synchronizeTab(event.prevSlug);
115         }
116     });
117     
118     /* Events handling */
119     
120     var eventHandlers = {};
121      
122     eventHandlers.sourceEditor = {
123         ready: function() {
124             addMainTab(gettext('Source'), 'sourceEditor',  sandbox.getModule('sourceEditor').getView());
125             sandbox.getModule('sourceEditor').setDocument(sandbox.getModule('data').getDocument());
126         },
127         xmlChanged: function() {
128             dirty.sourceEditor = true;
129         },
130         documentSet: function() {
131             dirty.sourceEditor = false;
132         }
133     };
134     
135     eventHandlers.data = {
136         ready: function() {
137             views.mainLayout.setView('mainView', views.mainTabs.getAsView());
138             
139             _.each(['sourceEditor', 'documentCanvas', 'documentToolbar', 'nodePane', 'metadataEditor', 'nodeFamilyTree', 'nodeBreadCrumbs', 'mainBar', 'indicator', 'documentHistory', 'diffViewer'], function(moduleName) {
140                 sandbox.getModule(moduleName).start();
141             });
142         },
143         documentChanged: function(document, reason) {
144             commands.resetDocument(document, reason);
145         },
146         savingStarted: function() {
147             sandbox.getModule('mainBar').setCommandEnabled('save', false);
148             sandbox.getModule('indicator').showMessage(gettext('Saving...'));
149         },
150         savingEnded: function(status) {
151             sandbox.getModule('mainBar').setCommandEnabled('save', true);
152             sandbox.getModule('indicator').clearMessage({message:'Dokument zapisany'});
153         },
154         restoringStarted: function(event) {
155             sandbox.getModule('mainBar').setCommandEnabled('save', false);
156             sandbox.getModule('indicator').showMessage(gettext('Restoring version ') + event.version + '...');
157         },
158         historyItemAdded: function(item) {
159             sandbox.getModule('documentHistory').addHistory([item], {animate: true});
160         },
161         diffFetched: function(diff) {
162             sandbox.getModule('diffViewer').setDiff(diff);
163         },
164         documentReverted: function(event) {
165             commands.resetDocument(event.document, 'revert');
166             sandbox.getModule('mainBar').setCommandEnabled('save', true);
167             sandbox.getModule('indicator').clearMessage({message:'Wersja ' + event.reverted_version + ' przywrócona'});
168             sandbox.getModule('mainBar').setVersion(event.current_version);
169         }
170     };
171     
172     eventHandlers.mainBar = {
173         ready: function() {
174             sandbox.getModule('mainBar').setVersion(sandbox.getModule('data').getDocumentVersion());
175             views.mainLayout.setView('topPanel', sandbox.getModule('mainBar').getView());
176         },
177         'cmd.save': function() {
178             synchronizeTab(views.mainTabs.getCurrentSlug());
179             sandbox.getModule('data').saveDocument();
180         }
181     };
182     
183     eventHandlers.indicator = {
184         ready: function() {
185             views.mainLayout.setView('messages', sandbox.getModule('indicator').getView());
186         }
187     };
188     
189
190     
191     eventHandlers.documentCanvas = {
192         ready: function() {
193             sandbox.getModule('documentCanvas').setDocument(sandbox.getModule('data').getDocument());
194             views.visualEditing.setView('leftColumn', sandbox.getModule('documentCanvas').getView());
195         },
196         documentSet: function() {
197             dirty.documentCanvas = false;
198         },
199         
200         currentTextElementSet: function(textElement) {
201             commands.updateCurrentTextElement(textElement);
202         },
203
204         currentNodeElementSet: function(nodeElement) {
205             commands.updateCurrentNodeElement(nodeElement);
206         },
207         
208         currentNodeElementChanged: function(nodeElement) {
209             commands.updateCurrentNodeElement(nodeElement);
210             dirty.documentCanvas = true;
211         },
212
213         contentChanged: function() {
214             dirty.documentCanvas = true;
215         },
216
217         nodeHovered: function(canvasNode) {
218             commands.highlightDocumentNode(canvasNode);
219         },
220         
221         nodeBlured: function(canvasNode) {
222             commands.dimDocumentNode(canvasNode);
223         }
224     };
225
226     eventHandlers.nodePane = {
227         ready: function() {
228             views.currentNodePaneLayout.appendView(sandbox.getModule('nodePane').getView());
229         },
230         
231         nodeElementChange: function(attr, value) {
232             sandbox.getModule('documentCanvas').modifyCurrentNodeElement(attr, value);
233         }
234     };
235     
236     eventHandlers.metadataEditor = {
237         ready: function() {
238             sandbox.getModule('metadataEditor').setDocument(sandbox.getModule('data').getDocument());
239             views.visualEditingSidebar.addTab({icon: 'info-sign'}, 'metadataEditor', sandbox.getModule('metadataEditor').getView());
240         },
241         metadataChanged: function(metadata) {
242             dirty.metadataEditor = true;
243         },
244         metadataSet: function() {
245             dirty.metadataEditor = false;
246         },
247     };
248     
249     eventHandlers.nodeFamilyTree = {
250         ready: function() {
251             views.currentNodePaneLayout.appendView(sandbox.getModule('nodeFamilyTree').getView());
252         },
253         elementEntered: function(element) {
254             commands.highlightDocumentElement(element, 'nodeFamilyTree');
255         },
256         elementLeft: function(element) {
257             commands.dimDocumentElement(element, 'nodeFamilyTree');
258         },
259         elementClicked: function(element) {
260             commands.jumpToDocumentElement(element);
261         }
262     };
263     
264     eventHandlers.documentToolbar = {
265         ready: function() {
266             views.visualEditing.setView('toolbar', sandbox.getModule('documentToolbar').getView());
267         },
268         command: function(cmd, params) {
269             sandbox.getModule('documentCanvas').command(cmd, params);
270         }
271     };
272     
273     eventHandlers.nodeBreadCrumbs = {
274         ready: function() {
275             views.visualEditing.setView('statusBar', sandbox.getModule('nodeBreadCrumbs').getView());
276         },
277         elementEntered: function(element) {
278             commands.highlightDocumentElement(element, 'nodeBreadCrumbs');
279         },
280         elementLeft: function(element) {
281             commands.dimDocumentElement(element, 'nodeBreadCrumbs');
282         },
283         elementClicked: function(element) {
284             commands.jumpToDocumentElement(element);
285         }        
286     };
287     
288     eventHandlers.documentHistory = {
289         ready: function() {
290             sandbox.getModule('documentHistory').addHistory(sandbox.getModule('data').getHistory());
291             views.diffLayout.setView('left', sandbox.getModule('documentHistory').getView());
292         },
293         compare: function(ver1, ver2) {
294             sandbox.getModule('data').fetchDiff(ver1, ver2);
295         },
296         restoreVersion: function(event) {
297             sandbox.getModule('data').restoreVersion(event);
298         },
299         displayVersion: function(event) {
300             window.open('/' + gettext('editor') + '/' + sandbox.getModule('data').getDocumentId() + '?version=' + event.version, _.uniqueId());
301         }
302     };
303     
304     eventHandlers.diffViewer = {
305         ready: function() {
306             views.diffLayout.setView('right', sandbox.getModule('diffViewer').getView());
307         }
308     };
309     
310     /* api */
311     
312     return {
313         start: function() {
314             sandbox.getModule('data').start();
315         },
316         handleEvent: function(moduleName, eventName, args) {
317             if('')
318                 wysiwigHandler.handleEvent(moduleName, eventName, args);
319             else if(eventHandlers[moduleName] && eventHandlers[moduleName][eventName]) {
320                 eventHandlers[moduleName][eventName].apply(eventHandlers, args);
321             }
322         }
323     };
324 };
325
326 });