editor: plugins/core support for Node.object.describesParent
[fnpeditor.git] / src / editor / modules / rng / rng.js
1 define([
2 './documentSummary',
3 'libs/underscore',
4 'fnpjs/layout',
5 'fnpjs/vbox',
6 'fnpjs/logging/logging',
7 'views/tabs/tabs',
8 'libs/text!./mainLayout.html',
9 'libs/text!./editingLayout.html',
10 'libs/text!./diffLayout.html',
11 ], function(documentSummary, _, layout, vbox, logging, tabs, mainLayoutTemplate, visualEditingLayoutTemplate, diffLayoutTemplate) {
12
13 'use strict';
14
15 return function(sandbox) {
16
17     /* globals gettext */
18
19     var logger = logging.getLogger('editor.modules.rng');
20     
21     function addMainTab(title, slug, view) {
22         views.mainTabs.addTab(title, slug, view);
23     }
24      
25     var commands = {
26         jumpToDocumentElement: function(element) {
27             sandbox.getModule('documentCanvas').jumpToElement(element);
28         },
29         refreshCanvasSelection: function(selection) {
30             var fragment = selection.toDocumentFragment(),
31                 elementParent;
32             
33             sandbox.getModule('documentToolbar').setDocumentFragment(fragment);
34             
35             if(fragment && fragment.node) {
36                 elementParent = fragment.node.getNearestElementNode();
37                 sandbox.getModule('nodeBreadCrumbs').setNodeElement(elementParent);
38                 sandbox.getModule('metadataEditor').setNodeElement(elementParent);
39             } else {
40                 sandbox.getModule('nodeBreadCrumbs').setNodeElement(null);
41                 sandbox.getModule('metadataEditor').setNodeElement(null);
42             }
43         },
44     };
45     
46
47     var views = {
48         mainLayout: new layout.Layout(mainLayoutTemplate),
49         mainTabs: (new tabs.View()).render(),
50         visualEditing: new layout.Layout(visualEditingLayoutTemplate),
51         visualEditingSidebar: (new tabs.View({stacked: true})).render(),
52         currentNodePaneLayout: new vbox.VBox(),
53         diffLayout: new layout.Layout(diffLayoutTemplate)
54     };
55     
56     views.visualEditing.setView('rightColumn', views.visualEditingSidebar.getAsView());
57     addMainTab(gettext('Editor'), 'editor', views.visualEditing.getAsView());
58     addMainTab(gettext('Source'), 'sourceEditor',  '');
59     addMainTab(gettext('History'), 'history', views.diffLayout.getAsView());
60     
61     sandbox.getDOM().append(views.mainLayout.getAsView());
62     
63     views.visualEditingSidebar.addTab({icon: 'pencil'}, 'edit', views.currentNodePaneLayout.getAsView());
64
65     var wlxmlDocument, documentIsDirty;
66     
67     /* Events handling */
68     
69     var eventHandlers = {};
70      
71     eventHandlers.sourceEditor = {
72         ready: function() {
73             addMainTab(gettext('Source'), 'sourceEditor',  sandbox.getModule('sourceEditor').getView());
74             sandbox.getModule('sourceEditor').setDocument(sandbox.getModule('data').getDocument());
75         }
76     };
77     
78     eventHandlers.data = {
79         ready: function(usingDraft, draftTimestamp) {
80             wlxmlDocument = sandbox.getModule('data').getDocument();
81
82             views.mainLayout.setView('mainView', views.mainTabs.getAsView());
83             
84             documentSummary.init(sandbox.getConfig().documentSummaryView, wlxmlDocument);
85             documentSummary.render();
86             documentSummary.setDraftField(usingDraft ? (draftTimestamp || '???') : '-');
87             views.currentNodePaneLayout.appendView(documentSummary.dom);
88
89             sandbox.getModule('mainBar').setCommandEnabled('drop-draft', usingDraft);
90             sandbox.getModule('mainBar').setCommandEnabled('save', usingDraft);
91
92             _.each(['sourceEditor', 'documentCanvas', 'documentToolbar', 'metadataEditor', 'nodeBreadCrumbs', 'mainBar', 'indicator', 'documentHistory', 'diffViewer', 'statusBar'], function(moduleName) {
93                 sandbox.getModule(moduleName).start();
94             });
95             
96             documentIsDirty = false;
97             wlxmlDocument.on('change', function() {
98                 documentIsDirty = true;
99                 sandbox.getModule('mainBar').setCommandEnabled('save', true);
100             });
101             wlxmlDocument.on('contentSet', function() {
102                 documentIsDirty = true;
103             });
104         },
105         draftDropped: function() {
106             documentSummary.setDraftField('-');
107             sandbox.getModule('mainBar').setCommandEnabled('drop-draft', false);
108             sandbox.getModule('mainBar').setCommandEnabled('save', false);
109         },
110         savingStarted: function(what) {
111             var msg = {
112                 remote: gettext('Saving document'),
113                 local: gettext('Saving local copy')
114             };
115             sandbox.getModule('mainBar').setCommandEnabled('save', false);
116             sandbox.getModule('indicator').showMessage(msg[what] + '...');
117         },
118         savingEnded: function(status, what, data) {
119             void(status);
120             var msg = {
121                 remote: gettext('Document saved'),
122                 local: gettext('Local copy saved')
123             };
124             documentIsDirty = false;
125             
126             sandbox.getModule('indicator').clearMessage({message: msg[what]});
127             if(status === 'success' && what === 'remote') {
128                 documentSummary.setDraftField('-');
129                 sandbox.getModule('mainBar').setCommandEnabled('drop-draft', false);
130                 sandbox.getModule('mainBar').setCommandEnabled('save', false);
131             }
132             if(what === 'local') {
133                 documentSummary.setDraftField(data.timestamp);
134                 sandbox.getModule('mainBar').setCommandEnabled('drop-draft', true);
135                 sandbox.getModule('mainBar').setCommandEnabled('save', true);
136             }
137         },
138         restoringStarted: function(event) {
139             sandbox.getModule('mainBar').setCommandEnabled('save', false);
140             sandbox.getModule('indicator').showMessage(gettext('Restoring version ') + event.version + '...');
141         },
142         historyItemAdded: function(item) {
143             sandbox.getModule('documentHistory').addHistory([item], {animate: true});
144         },
145         diffFetched: function(diff) {
146             sandbox.getModule('diffViewer').setDiff(diff);
147         },
148         documentReverted: function(version) {
149             documentIsDirty = false;
150             sandbox.getModule('indicator').clearMessage({message:'Wersja ' + version + ' przywrócona'});
151         }
152     };
153     
154     eventHandlers.mainBar = {
155         ready: function() {
156             views.mainLayout.setView('topPanel', sandbox.getModule('mainBar').getView());
157         },
158         'cmd.save': function() {
159             var sourceEditor = sandbox.getModule('sourceEditor');
160             if(!sourceEditor.changesCommited()) {
161                 logger.debug('Source editor has uncommited changes, commiting...');
162                 sourceEditor.commitChanges();
163             }
164             sandbox.getModule('data').saveDocument();
165         },
166         'cmd.drop-draft': function() {
167             sandbox.getModule('data').dropDraft();
168         }
169     };
170     
171     eventHandlers.indicator = {
172         ready: function() {
173             views.mainLayout.setView('messages', sandbox.getModule('indicator').getView());
174         }
175     };
176     
177
178     
179     eventHandlers.documentCanvas = {
180         ready: function() {
181             sandbox.getModule('documentCanvas').setDocument(sandbox.getModule('data').getDocument());
182             views.visualEditing.setView('leftColumn', sandbox.getModule('documentCanvas').getView());
183         },
184         
185         nodeHovered: function(canvasNode) {
186             commands.highlightDocumentNode(canvasNode);
187         },
188         
189         nodeBlured: function(canvasNode) {
190             commands.dimDocumentNode(canvasNode);
191         },
192
193         selectionChanged: function(selection) {
194             commands.refreshCanvasSelection(selection);
195         }
196     };
197     
198     eventHandlers.metadataEditor = {
199         ready: function() {
200             sandbox.getModule('metadataEditor').setDocument(sandbox.getModule('data').getDocument());
201             views.visualEditingSidebar.addTab({icon: 'info-sign'}, 'metadataEditor', sandbox.getModule('metadataEditor').getView());
202         }
203     };
204     
205     eventHandlers.documentToolbar = {
206         ready: function() {
207             views.visualEditing.setView('toolbar', sandbox.getModule('documentToolbar').getView());
208             sandbox.getModule('documentToolbar').setCanvas(sandbox.getModule('documentCanvas').getCanvas());
209         },
210         actionExecuted: function(action, ret) {
211             sandbox.getModule('documentCanvas').onAfterActionExecuted(action, ret);
212         }
213     };
214     
215     eventHandlers.nodeBreadCrumbs = {
216         ready: function() {
217             views.visualEditing.setView('statusBar', sandbox.getModule('nodeBreadCrumbs').getView());
218         },
219         elementClicked: function(element) {
220             commands.jumpToDocumentElement(element);
221         }
222     };
223     
224     eventHandlers.documentHistory = {
225         ready: function() {
226             sandbox.getModule('documentHistory').addHistory(sandbox.getModule('data').getHistory());
227             views.diffLayout.setView('left', sandbox.getModule('documentHistory').getView());
228         },
229         compare: function(ver1, ver2) {
230             sandbox.getModule('data').fetchDiff(ver1, ver2);
231         },
232         restoreVersion: function(version) {
233             sandbox.getModule('data').restoreVersion(version);
234         },
235         displayVersion: function(event) {
236             /* globals window */
237             window.open('/' + gettext('editor') + '/' + sandbox.getModule('data').getDocumentId() + '?version=' + event.version, _.uniqueId());
238         }
239     };
240     
241     eventHandlers.diffViewer = {
242         ready: function() {
243             views.diffLayout.setView('right', sandbox.getModule('diffViewer').getView());
244         }
245     };
246
247     eventHandlers.statusBar = {
248         ready: function() {
249             views.mainLayout.setView('bottomPanel', sandbox.getModule('statusBar').getView());
250         }
251     };
252
253     eventHandlers.__all__ = {
254         actionHovered: function(action) {
255             sandbox.getModule('statusBar').showAction(action);
256         },
257         actionOff: function() {
258             sandbox.getModule('statusBar').clearAction();
259         }
260     };
261
262     window.addEventListener('beforeunload', function(event) {
263         var txt = gettext('Do you really want to exit?');
264         if(documentIsDirty) {
265             txt += ' ' + gettext('Document contains unsaved changes!');
266         }
267         event.returnValue = txt; // FF
268         return txt; // Chrome
269     });
270     
271     /* api */
272     
273     return {
274         start: function() {
275             sandbox.registerActionsAppObject({
276                 getUser: function() {
277                     return sandbox.getConfig().user;
278                 }
279             });
280             sandbox.getModule('data').start();
281         },
282         handleEvent: function(moduleName, eventName, args) {
283             var eventRepr = moduleName + '.' + eventName;
284             if(eventHandlers[moduleName] && eventHandlers[moduleName][eventName]) {
285                 logger.debug('Handling event ' + eventRepr);
286                 eventHandlers[moduleName][eventName].apply(eventHandlers, args);
287                 return;
288             }
289
290             if(eventHandlers.__all__[eventName]) {
291                 logger.debug('Handling event ' + eventRepr);
292                 eventHandlers.__all__[eventName].apply(eventHandlers.__all__, args);
293                 return;
294             }
295
296             logger.warning('No event handler for ' + eventRepr);
297         }
298     };
299 };
300
301 });