update webodf

This commit is contained in:
Tobias Hintze 2013-08-06 10:46:47 +02:00
parent fc7c1e02a5
commit 8c71d3a436
9 changed files with 3231 additions and 1977 deletions

View File

@ -59,8 +59,9 @@ define("webodf/editor/Editor", [
* cursorRemovedCallback:function(!string)=,
* registerCallbackForShutdown:function(!function())= }} args
* @param {!ops.Server=} server
* @param {!ServerFactory=} serverFactory
*/
function Editor(args, server) {
function Editor(args, server, serverFactory) {
var self = this,
// Private
@ -102,7 +103,8 @@ define("webodf/editor/Editor", [
inviteButton,
viewOptions = {
editInfoMarkersInitiallyVisible: networked,
caretAvatarsInitiallyVisible: networked
caretAvatarsInitiallyVisible: networked,
caretBlinksOnRangeSelect: true
},
peopleListDiv = document.getElementById('peopleList');
@ -153,6 +155,8 @@ define("webodf/editor/Editor", [
editorSession.startEditing();
return;
}
// Allow annotations
odfCanvas.enableAnnotations(true);
if (!memberid) {
// legacy - memberid should be passed in the constructor
@ -266,10 +270,10 @@ define("webodf/editor/Editor", [
self.loadSession = function (sessionId, editorReadyCallback) {
initGuiAndDoc(server.getGenesisUrl(sessionId), function () {
// get router and user model
opRouter = opRouter || server.createOperationRouter(sessionId, memberid);
opRouter = opRouter || serverFactory.createOperationRouter(sessionId, memberid, server);
session.setOperationRouter(opRouter);
userModel = userModel || server.createUserModel();
userModel = userModel || serverFactory.createUserModel(server);
session.setUserModel(userModel);
opRouter.requestReplay(function done() {

View File

@ -45,11 +45,12 @@ define("webodf/editor/EditorSession", [
runtime.loadClass("ops.OdtDocument");
runtime.loadClass("ops.Session");
runtime.loadClass("odf.OdfCanvas");
runtime.loadClass("gui.CaretFactory");
runtime.loadClass("gui.CaretManager");
runtime.loadClass("gui.Caret");
runtime.loadClass("gui.SessionController");
runtime.loadClass("gui.SessionView");
runtime.loadClass("gui.TrivialUndoManager");
runtime.loadClass("gui.StyleHelper");
runtime.loadClass("core.EventNotifier");
/**
@ -67,6 +68,7 @@ define("webodf/editor/EditorSession", [
odtDocument = session.getOdtDocument(),
textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
formatting = odtDocument.getFormatting(),
styleHelper = new gui.StyleHelper(formatting),
eventNotifier = new core.EventNotifier([
EditorSession.signalUserAdded,
EditorSession.signalUserRemoved,
@ -79,7 +81,7 @@ define("webodf/editor/EditorSession", [
this.sessionController = new gui.SessionController(session, memberid);
this.sessionView = new gui.SessionView(config.viewOptions, session, new gui.CaretFactory(self.sessionController));
this.sessionView = new gui.SessionView(config.viewOptions, session, new gui.CaretManager(self.sessionController));
this.availableFonts = [];
/*
@ -188,6 +190,7 @@ define("webodf/editor/EditorSession", [
if (info.paragraphElement !== currentParagraphNode) {
return;
}
self.emit(EditorSession.signalParagraphChanged, info);
checkParagraphStyleName();
}
@ -276,18 +279,40 @@ define("webodf/editor/EditorSession", [
return formatting.getAvailableParagraphStyles();
};
this.getCurrentSelectionStyle = function () {
var cursor = odtDocument.getCursor(memberid),
selectedRange;
this.isBold = function () {
var cursor = odtDocument.getCursor(memberid);
// no own cursor yet/currently added?
if (!cursor) {
return [];
return false;
}
selectedRange = cursor.getSelectedRange();
if (selectedRange.collapsed) {
return [formatting.getAppliedStylesForElement(cursor.getNode())];
return styleHelper.isBold(cursor.getSelectedRange());
};
this.isItalic = function () {
var cursor = odtDocument.getCursor(memberid);
// no own cursor yet/currently added?
if (!cursor) {
return false;
}
return formatting.getAppliedStyles(selectedRange);
return styleHelper.isItalic(cursor.getSelectedRange());
};
this.hasUnderline = function () {
var cursor = odtDocument.getCursor(memberid);
// no own cursor yet/currently added?
if (!cursor) {
return false;
}
return styleHelper.hasUnderline(cursor.getSelectedRange());
};
this.hasStrikeThrough = function () {
var cursor = odtDocument.getCursor(memberid);
// no own cursor yet/currently added?
if (!cursor) {
return false;
}
return styleHelper.hasStrikeThrough(cursor.getSelectedRange());
};
this.getCurrentParagraphStyle = function () {
@ -295,13 +320,35 @@ define("webodf/editor/EditorSession", [
};
this.formatSelection = function (value) {
var op = new ops.OpApplyStyle(),
var op = new ops.OpApplyDirectStyling(),
selection = self.getCursorSelection();
op.init({
memberid: memberid,
position: selection.position,
length: selection.length,
info: value
setProperties: value
});
session.enqueue(op);
};
/**
* Adds an annotation to the document based on the current selection
* @return {undefined}
*/
this.addAnnotation = function () {
var op = new ops.OpAddAnnotation(),
selection = self.getCursorSelection(),
length = selection.length,
position = selection.position;
position = length >= 0 ? position : position + length;
length = Math.abs(length);
op.init({
memberid: memberid,
position: position,
length: length,
name: memberid + Date.now()
});
session.enqueue(op);
};
@ -379,14 +426,30 @@ define("webodf/editor/EditorSession", [
*/
this.cloneParagraphStyle = function (styleName, newStyleDisplayName) {
var newStyleName = uniqueParagraphStyleNCName(newStyleDisplayName),
op;
styleNode = odtDocument.getParagraphStyleElement(styleName),
formatting = odtDocument.getFormatting(),
op, setProperties, attributes, i;
op = new ops.OpCloneParagraphStyle();
setProperties = formatting.getStyleAttributes(styleNode);
// copy any attributes directly on the style
attributes = styleNode.attributes;
for (i = 0; i < attributes.length; i += 1) {
// skip...
// * style:display-name -> not copied, set to new string below
// * style:name -> not copied, set from op by styleName property
// * style:family -> "paragraph" always, set by op
if (!/^(style:display-name|style:name|style:family)/.test(attributes[i].name)) {
setProperties[attributes[i].name] = attributes[i].value;
}
}
setProperties['style:display-name'] = newStyleDisplayName;
op = new ops.OpAddParagraphStyle();
op.init({
memberid: memberid,
styleName: styleName,
newStyleName: newStyleName,
newStyleDisplayName: newStyleDisplayName
styleName: newStyleName,
setProperties: setProperties
});
session.enqueue(op);

View File

@ -54,7 +54,11 @@ function SessionListView(sessionList, sessionListDiv, cb) {
sessionDiv.appendChild(fullnameTextNode);
sessionDiv.sessionId = sessionDetails.id; // TODO: namespace?
sessionDiv.style.cursor = "pointer"; // TODO: do not set on each element, use CSS
sessionDiv.onclick = function () {
// HACK: stop pulling, so that does not mess up the logs
// Remove before merging to master
if (sessionList.stopPulling) { sessionList.stopPulling(); }
cb(sessionDetails.id);
};

View File

@ -47,7 +47,7 @@
*
*/
/*global runtime, require, document, alert, net, window, NowjsSessionList, PullBoxSessionList, SessionListView, ops */
/*global runtime, require, document, alert, net, window, SessionListView, ops */
// define the namespace/object we want to provide
// this is the first line of API, the user gets.
@ -62,6 +62,7 @@ var webodfEditor = (function () {
};
var editorInstance = null,
serverFactory = null,
server = null,
booting = false,
loadedFilename;
@ -78,22 +79,31 @@ var webodfEditor = (function () {
* @return {undefined}
*/
function connectNetwork(backend, callback) {
if (backend === "pullbox") {
runtime.loadClass("ops.PullBoxServer");
server = new ops.PullBoxServer();
} else if (backend === "nowjs") {
runtime.loadClass("ops.NowjsServer");
server = new ops.NowjsServer();
} else if (backend === "owncloud") {
runtime.loadClass("ops.PullBoxServer");
server = new ops.PullBoxServer({url: "./office/ajax/otpoll.php"});
server.getGenesisUrl = function(sid) {
return "/owncloud/index.php/apps/files/download/welcome.odt";
};
} else {
callback("unavailable");
function createServer(ServerFactory) {
serverFactory = new ServerFactory();
server = serverFactory.createServer();
server.connect(8000, callback);
}
switch (backend) {
case "pullbox":
require({ }, ["webodf/editor/server/pullbox/serverFactory"], createServer);
break;
case "nowjs":
require({ }, ["webodf/editor/server/nowjs/serverFactory"], createServer);
break;
case "owncloud":
require({ }, ["webodf/editor/server/pullbox/serverFactory"], function (ServerFactory) {
serverFactory = new ServerFactory();
server = serverFactory.createServer({url: "./office/ajax/otpoll.php"});
server.getGenesisUrl = function(sid) {
return "/owncloud/index.php/apps/files/download/welcome.odt";
};
server.connect(8000, callback);
});
default:
callback("unavailable");
}
server.connect(8000, callback);
}
/**
@ -261,7 +271,7 @@ var webodfEditor = (function () {
function (Editor) {
// TODO: the networkSecurityToken needs to be retrieved via now.login
// (but this is to be implemented later)
editorInstance = new Editor(editorOptions, server);
editorInstance = new Editor(editorOptions, server, serverFactory);
// load the document and get called back when it's live
editorInstance.loadSession(sessionId, function (editorSession) {
@ -299,8 +309,7 @@ var webodfEditor = (function () {
function showSessions() {
var sessionListDiv = document.getElementById("sessionList"),
// sessionList = new NowjsSessionList(server),
sessionList = new PullBoxSessionList(server),
sessionList = new serverFactory.createSessionList(server),
sessionListView = new SessionListView(sessionList, sessionListDiv, enterSession);
// hide login view

View File

@ -55,7 +55,7 @@ define("webodf/editor/widgets", [
], function (ready, MenuItem, DropDownMenu, Button, DropDownButton, Toolbar) {
ready(function () {
var loadButton, saveButton, dropDownMenu, menuButton, paragraphStylesMenuItem, dialog, toolbar, simpleStyles, currentStyle, zoomSlider,
undoRedoMenu;
undoRedoMenu, annotateButton;
dropDownMenu = new DropDownMenu({});
paragraphStylesMenuItem = new MenuItem({
@ -136,6 +136,16 @@ define("webodf/editor/widgets", [
}
});
menuButton.placeAt(toolbar);
annotateButton = new Button({
label: translator('annotate'),
showLabel: false,
iconClass: 'dijitIconBookmark',
onClick: function () {
editorSession.addAnnotation();
}
});
annotateButton.placeAt(toolbar);
});
});
};

View File

@ -65,12 +65,90 @@ define("webodf/editor/widgets/paragraphStylesDialog", [], function () {
deleteButton,
cloneTooltip,
cloneDropDown,
newStyleName = null;
newStyleName = null,
/**
* Mapping of the properties from edit pane properties to the attributes of style:text-properties
* @const@type{Array.<!{propertyName:string,attributeName:string,unit:string}>}
*/
textPropertyMapping = [
{
propertyName: 'fontSize',
attributeName: 'fo:font-size',
unit: 'pt'
}, {
propertyName: 'fontName',
attributeName: 'style:font-name'
}, {
propertyName: 'color',
attributeName: 'fo:color'
}, {
propertyName: 'backgroundColor',
attributeName: 'fo:background-color'
}, {
propertyName: 'fontWeight',
attributeName: 'fo:font-weight'
}, {
propertyName: 'fontStyle',
attributeName: 'fo:font-style'
}, {
propertyName: 'underline',
attributeName: 'style:text-underline-style'
}, {
propertyName: 'strikethrough',
attributeName: 'style:text-line-through-style'
}],
/**
* Mapping of the properties from edit pane properties to the attributes of style:paragraph-properties
* @const@type{Array.<!{propertyName:string,attributeName:string,unit:string}>}
*/
paragraphPropertyMapping = [
{
propertyName: 'topMargin',
attributeName: 'fo:margin-top',
unit: 'mm'
}, {
propertyName: 'bottomMargin',
attributeName: 'fo:margin-bottom',
unit: 'mm'
}, {
propertyName: 'leftMargin',
attributeName: 'fo:margin-left',
unit: 'mm'
}, {
propertyName: 'rightMargin',
attributeName: 'fo:margin-right',
unit: 'mm'
}, {
propertyName: 'textAlign',
attributeName: 'fo:text-align'
}];
/**
* Sets attributes of a node by the properties of the object properties,
* based on the mapping defined in propertyMapping.
* @param {!Object} properties
* @param {!Array.<!{propertyName:string,attributeName:string,unit:string}>} propertyMapping
* @return {undefined}
*/
function mappedProperties(properties, propertyMapping) {
var i, m, value,
result = {};
for (i = 0; i < propertyMapping.length; i += 1) {
m = propertyMapping[i];
value = properties[m.propertyName];
// Set a value as the attribute of a node, if that value is defined.
// If there is a unit specified, it is suffixed to the value.
if (value !== undefined) {
result[m.attributeName] = (m.unit !== undefined) ? value + m.unit : value;
}
}
return result;
}
function accept() {
editorSession.updateParagraphStyle(stylePicker.value(), {
paragraphProperties: alignmentPane.value(),
textProperties: fontEffectsPane.value()
"style:paragraph-properties": mappedProperties(alignmentPane.value(), paragraphPropertyMapping),
"style:text-properties": mappedProperties(fontEffectsPane.value(), textPropertyMapping)
});
dialog.hide();

View File

@ -106,30 +106,12 @@ define("webodf/editor/widgets/simpleStyles",
});
function checkStyleButtons() {
var fontWeight, fontStyle, underline, strikethrough, appliedStyles;
appliedStyles = editorSession.getCurrentSelectionStyle();
fontWeight = false;
fontStyle = false;
underline = false;
strikethrough = false;
appliedStyles.forEach(function(appliedStyle) {
var textProperties = appliedStyle['style:text-properties'];
if (textProperties) {
fontWeight = fontWeight || textProperties['fo:font-weight'] === 'bold';
fontStyle = fontStyle || textProperties['fo:font-style'] === 'italic';
underline = underline || textProperties['style:text-underline-style'] === 'solid';
strikethrough = strikethrough || textProperties['style:text-line-through-style'] === 'solid';
}
});
// The 3rd parameter is false to avoid firing onChange when setting the value
// programmatically.
boldButton.set('checked', fontWeight, false);
italicButton.set('checked', fontStyle, false);
underlineButton.set('checked', underline, false);
strikethroughButton.set('checked', strikethrough, false);
boldButton.set('checked', editorSession.isBold(), false);
italicButton.set('checked', editorSession.isItalic(), false);
underlineButton.set('checked', editorSession.hasUnderline(), false);
strikethroughButton.set('checked', editorSession.hasStrikeThrough(), false);
}
editorSession.subscribe(EditorSession.signalCursorMoved, checkStyleButtons);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long