editor control

This commit is contained in:
Xuan Sang LE 2018-09-13 20:21:07 +02:00
parent 18e0db7253
commit a033ea21c5
8 changed files with 780 additions and 52 deletions

View File

@ -1,7 +1,36 @@
<afx-app-window apptitle="Open Page" width="600" height="500" data-id="OpenPage"> <afx-app-window apptitle="Open Page" width="650" height="500" data-id="OpenPage">
<afx-hbox > <afx-hbox >
<afx-vbox>
<afx-hbox data-id="toolbox" data-height="28">
<div data-width="5"></div>
<afx-button data-width = "25" data-id="btundo" iconclass = "fa fa-undo"></afx-button>
<afx-button data-width = "25" data-id="btredo" iconclass = "fa fa-rotate-right" ></afx-button>
<afx-button data-width = "25" data-id="btbold" iconclass = "fa fa-bold"></afx-button>
<afx-button data-width = "25" data-id="btitalic" iconclass = "fa fa-italic"></afx-button>
<afx-button data-width = "25" data-id="btunderline" iconclass = "fa fa-underline"></afx-button>
<afx-button data-width = "25" data-id="btstrike" iconclass = "fa fa-strikethrough"></afx-button>
<afx-button data-width = "25" data-id="btnote" iconclass = "fa fa-sticky-note"></afx-button>
<afx-button data-width = "25" data-id="btlink" iconclass = "fa fa-link"></afx-button>
<afx-button data-width = "25" data-id="btunlink" iconclass = "fa fa-unlink"></afx-button>
<afx-button data-width = "25" data-id="btimage" iconclass = "fa fa-image"></afx-button>
<afx-button data-width = "25" data-id="btac" iconclass = "fa fa-align-center"></afx-button>
<afx-button data-width = "25" data-id="btal" iconclass = "fa fa-align-left" ></afx-button>
<afx-button data-width = "25" data-id="btar" iconclass = "fa fa-align-right"></afx-button>
<afx-button data-width = "25" data-id="btaj" iconclass = "fa fa-align-justify"></afx-button>
<afx-button data-width = "25" data-id="btindent" iconclass = "fa fa-indent"></afx-button>
<afx-button data-width = "25" data-id="btoutdent" iconclass = "fa fa-outdent"></afx-button>
<afx-list-view dropdown = "true" data-width="80" data-id="format-list"></afx-list-view>
<div data-width="5"></div>
<afx-nspinner data-width = "50" data-id="font-size" ></afx-nspinner>
<div data-width="5"></div>
<afx-list-view dropdown = "true" data-width="150" data-id="font-list"></afx-list-view>
<div data-width="5"></div>
</afx-hbox>
<div data-height="5"></div>
<div data-id="container"> <div data-id="container">
<div data-id="odfcanvas"></div> <div data-id="odfcanvas"></div>
</div> </div>
</afx-vbox>
</afx-hbox> </afx-hbox>
</afx-app-window> </afx-app-window>

View File

@ -2,6 +2,42 @@
afx-app-window[data-id="OpenPage"] div[data-id="container"] afx-app-window[data-id="OpenPage"] div[data-id="container"]
{ {
overflow: auto; overflow: auto;
margin:0 auto; margin:0px;
padding:0px padding:0px;
padding-top: 10px;
padding-bottom: 10px;
text-align: center;
background-color: #f2f1f0;
}
afx-app-window[data-id="OpenPage"] div[data-id="odfcanvas"]
{
cursor: text;
margin:auto;
box-shadow: 1px 1px 3px 3px #9f9F9F;
}
afx-app-window[data-id="OpenPage"] afx-hbox[data-id="toolbox"]
{
background-color: #f5f5f5;
border: 1px solid #eaeaea;
box-shadow: 3px 3px 3px #9f9F9F;
}
afx-app-window[data-id="HyperLinkDialog"] afx-label.header span
{
font-weight: bold;
}
afx-app-window[data-id="OpenPage"] afx-hbox[data-id="toolbox"] afx-button button{
border: 1px solid #f5f5f5;
background-color: transparent;
width:100%;
height: 100%;
}
afx-app-window[data-id="OpenPage"] afx-hbox[data-id="toolbox"] afx-button button:hover, afx-app-window[data-id="OpenPage"] afx-hbox[data-id="toolbox"] afx-button.btactive button
{
border: 1px solid #759DC0;
background-color: transparent;
border-radius:5px;
color:#759DC0;
} }

View File

@ -1,5 +1,5 @@
(function() { (function() {
var OpenPage; var HyperLinkDialog, OpenPage;
OpenPage = class OpenPage extends this.OS.GUI.BaseApplication { OpenPage = class OpenPage extends this.OS.GUI.BaseApplication {
constructor(args) { constructor(args) {
@ -7,19 +7,89 @@
} }
main() { main() {
var el, me, userid; // load session class
if (!OpenPage.editorSession) {
require(["webodf/editor/EditorSession"], function(ES) {
return OpenPage.EditorSession = ES;
});
}
this.eventSubscriptions = new core.EventSubscriptions();
this.initToolbox();
this.initCanvas();
return this.canvas.load(`${this._api.handler.get}/home://welcome.odt`);
}
initToolbox() {
var el, fn, me, name, ref, results;
me = this;
this.basictool = {
undo: this.find("btundo"),
redo: this.find("btredo"),
bold: this.find("btbold"),
italic: this.find("btitalic"),
underline: this.find("btunderline"),
strike: this.find("btstrike"),
note: this.find("btnote"),
link: this.find("btlink"),
unlink: this.find("btunlink"),
image: this.find("btimage"),
ac: this.find("btac"),
al: this.find("btal"),
ar: this.find("btar"),
aj: this.find("btaj"),
indent: this.find("btindent"),
outdent: this.find("btoutdent"),
fonts: this.find("font-list"),
fontsize: this.find("font-size")
};
fn = function(name, el) {
var act;
if (name === "fonts") {
act = "onlistselect";
} else if (name === "fontsize") {
act = "onchange";
} else {
act = "onbtclick";
}
return el.set(act, function(e) {
if (!me.directFormattingCtl) {
return;
}
if (!me[name]) {
return;
}
me[name](e);
return me.editorFocus();
});
};
ref = this.basictool;
results = [];
for (name in ref) {
el = ref[name];
results.push(fn(name, el));
}
return results;
}
initCanvas() {
var el, me;
el = this.find("odfcanvas"); el = this.find("odfcanvas");
me = this; me = this;
el.setAttribute("translate", "no"); el.setAttribute("translate", "no");
el.classList.add("notranslate"); el.classList.add("notranslate");
this.eventNotifier = new core.EventNotifier(["unknown-error", "documentModifiedChanged", "metadataChanged"]); this.userid = "localuser";
userid = "localuser";
require(["webodf/editor/EditorSession"], function(ES) {
return OpenPage.EditorSession = ES;
});
this.canvas = new odf.OdfCanvas(el); this.canvas = new odf.OdfCanvas(el);
this.documentChanged = function(e) {
return console.log(e);
};
this.metaChanged = function(e) {
return console.log(e);
};
this.textStylingChanged = function(e) {
return me.updateToolbar(e);
};
//@canvas.enableAnnotations(true, true) //@canvas.enableAnnotations(true, true)
this.canvas.addListener("statereadychange", function() { return this.canvas.addListener("statereadychange", function() {
var op, viewOptions; var op, viewOptions;
me.session = new ops.Session(me.canvas); me.session = new ops.Session(me.canvas);
viewOptions = { viewOptions = {
@ -27,7 +97,7 @@
caretAvatarsInitiallyVisible: false, caretAvatarsInitiallyVisible: false,
caretBlinksOnRangeSelect: true caretBlinksOnRangeSelect: true
}; };
me.editorSession = new OpenPage.EditorSession(me.session, userid, { me.editorSession = new OpenPage.EditorSession(me.session, me.userid, {
viewOptions: viewOptions, viewOptions: viewOptions,
directTextStylingEnabled: true, directTextStylingEnabled: true,
directParagraphStylingEnabled: true, directParagraphStylingEnabled: true,
@ -39,36 +109,331 @@
zoomingEnabled: true, zoomingEnabled: true,
reviewModeEnabled: false reviewModeEnabled: false
}); });
// basic format
me.directFormattingCtl = me.editorSession.sessionController.getDirectFormattingController();
me.directFormattingCtl.subscribe(gui.DirectFormattingController.textStylingChanged, me.textStylingChanged);
me.directFormattingCtl.subscribe(gui.DirectFormattingController.paragraphStylingChanged, me.textStylingChanged);
// hyper link controller
me.hyperlinkController = me.editorSession.sessionController.getHyperlinkController();
me.eventSubscriptions.addFrameSubscription(me.editorSession, OpenPage.EditorSession.signalCursorMoved, function() {
return me.updateHyperlinkButtons();
});
me.eventSubscriptions.addFrameSubscription(me.editorSession, OpenPage.EditorSession.signalParagraphChanged, function() {
return me.updateHyperlinkButtons();
});
me.eventSubscriptions.addFrameSubscription(me.editorSession, OpenPage.EditorSession.signalParagraphStyleModified, function() {
return me.updateHyperlinkButtons();
});
me.editorSession.sessionController.setUndoManager(new gui.TrivialUndoManager()); me.editorSession.sessionController.setUndoManager(new gui.TrivialUndoManager());
me.editorSession.sessionController.getUndoManager().subscribe(gui.UndoManager.signalDocumentModifiedChanged, function(mod) { me.editorSession.sessionController.getUndoManager().subscribe(gui.UndoManager.signalDocumentModifiedChanged, me.documentChanged);
return me.eventNotifier.emit("documentModifiedChanged", mod); me.editorSession.sessionController.getMetadataController().subscribe(gui.MetadataController.signalMetadataChanged, me.metaChanged);
});
me.editorSession.sessionController.getMetadataController().subscribe(gui.MetadataController.signalMetadataChanged, function(changes) {
return me.eventNotifier.emit("metadataChanged", changes);
});
op = new ops.OpAddMember(); op = new ops.OpAddMember();
op.init({ op.init({
memberid: userid, memberid: me.userid,
setProperties: { setProperties: {
"fullName": "Xuan Sang LE", "fullName": "Xuan Sang LE",
"color": "blue" "color": "blue"
} }
}); });
me.session.enqueue([op]); me.session.enqueue([op]);
me.initFontList(me.editorSession.getDeclaredFonts());
me.editorSession.sessionController.insertLocalCursor(); me.editorSession.sessionController.insertLocalCursor();
me.editorSession.sessionController.startEditing(); return me.editorSession.sessionController.startEditing();
return me.editorSession.sessionController.getEventManager().focus();
}); });
this.canvas.load(`${this._api.handler.get}/home://Downloads/welcome.odt`); }
return this.eventNotifier.subscribe("documentModifiedChanged", function(d) {
return console.log("document is modified"); //console.log me.editorSession.getDeclaredFonts()
initFontList(list) {
var j, len, v;
for (j = 0, len = list.length; j < len; j++) {
v = list[j];
v.text = v.name;
}
return this.basictool.fonts.set("items", list);
}
updateToolbar(changes) {
if (changes.hasOwnProperty('isBold')) {
// basic style
this.basictool.bold.set("selected", changes.isBold);
}
if (changes.hasOwnProperty('isItalic')) {
this.basictool.italic.set("selected", changes.isItalic);
}
if (changes.hasOwnProperty('hasUnderline')) {
this.basictool.underline.set("selected", changes.hasUnderline);
}
if (changes.hasOwnProperty('hasStrikeThrough')) {
this.basictool.strike.set("selected", changes.hasStrikeThrough);
}
if (changes.hasOwnProperty("fontSize")) {
this.basictool.fontsize.set("value", changes.fontSize);
}
if (changes.hasOwnProperty("fontName")) {
this.selectFont(changes.fontName);
}
if (changes.hasOwnProperty("isAlignedLeft")) {
//pharagraph style
this.basictool.al.set("selected", changes.isAlignedLeft);
}
if (changes.hasOwnProperty("isAlignedRight")) {
this.basictool.ar.set("selected", changes.isAlignedRight);
}
if (changes.hasOwnProperty("isAlignedCenter")) {
this.basictool.ac.set("selected", changes.isAlignedCenter);
}
if (changes.hasOwnProperty("isAlignedJustified")) {
return this.basictool.aj.set("selected", changes.isAlignedJustified);
}
}
updateHyperlinkButtons(e) {
var selectedLinks;
selectedLinks = this.editorSession.getSelectedHyperlinks();
return this.basictool.unlink.set("enable", selectedLinks.length > 0);
}
selectFont(name) {
var i, item, items, j, len, v;
items = this.basictool.fonts.get("items");
for (i = j = 0, len = items.length; j < len; i = ++j) {
v = items[i];
if (v.name === name) {
item = i;
}
}
return this.basictool.fonts.set("selected", item);
}
editorFocus() {
return this.editorSession.sessionController.getEventManager().focus();
}
bold(e) {
//console.log @, e
return this.directFormattingCtl.setBold(!this.basictool.bold.get("selected"));
}
italic(e) {
return this.directFormattingCtl.setItalic(!this.basictool.italic.get("selected"));
}
underline(e) {
return this.directFormattingCtl.setHasUnderline(!this.basictool.underline.get("selected"));
}
strike(e) {
return this.directFormattingCtl.setHasStrikethrough(!this.basictool.strike.get("selected"));
}
fonts(e) {
return this.directFormattingCtl.setFontName(e.data.name);
}
fontsize(e) {
return this.directFormattingCtl.setFontSize(e);
}
al(e) {
return this.directFormattingCtl.alignParagraphLeft();
}
ar(e) {
return this.directFormattingCtl.alignParagraphRight();
}
ac(e) {
return this.directFormattingCtl.alignParagraphCenter();
}
aj(e) {
return this.directFormattingCtl.alignParagraphJustified();
}
indent(e) {
return this.directFormattingCtl.indent();
}
outdent(e) {
return this.directFormattingCtl.outdent();
}
link(e) {
var data, linkTarget, linksInSelection, me, selection, textSerializer;
// get the link first
me = this;
textSerializer = new odf.TextSerializer();
selection = this.editorSession.getSelectedRange();
linksInSelection = this.editorSession.getSelectedHyperlinks();
linkTarget = linksInSelection[0] ? odf.OdfUtils.getHyperlinkTarget(linksInSelection[0]) : "http://";
data = {
link: linkTarget,
text: "",
readonly: true,
action: "new"
};
if (selection && selection.collapsed && linksInSelection.length === 1) {
// selection is collapsed within a single link
// text in this case is read only
data.text = textSerializer.writeToString(linksInSelection[0]);
data.action = "edit";
} else if (selection && !selection.collapsed) {
// user select part of link or a block of text
// user convert a selection to a link
data.text = textSerializer.writeToString(selection.cloneContents());
} else {
data.readonly = false;
}
return this.openDialog(new HyperLinkDialog(), function(d) {
var selectedLinkRange, selectionController;
selectionController = me.editorSession.sessionController.getSelectionController();
if (d.readonly) {
// edit the existing link
if (d.action === "edit") {
selectedLinkRange = selection.cloneRange();
selectedLinkRange.selectNode(linksInSelection[0]);
selectionController.selectRange(selectedLinkRange, true);
}
me.hyperlinkController.removeHyperlinks();
return me.hyperlinkController.addHyperlink(d.link);
} else {
me.hyperlinkController.addHyperlink(d.link, d.text);
linksInSelection = me.editorSession.getSelectedHyperlinks();
selectedLinkRange = selection.cloneRange();
selectedLinkRange.selectNode(linksInSelection[0]);
return selectionController.selectRange(selectedLinkRange, true);
}
}, "__(Insert/edit link)", data);
}
unlink(e) {
return this.hyperlinkController.removeHyperlinks();
}
closeDocument() {
var me, op;
// finish editing
if (!(this.editorSession && this.session)) {
return;
}
me = this;
this.eventSubscriptions.unsubscribeAll();
this.editorSession.sessionController.endEditing();
this.editorSession.sessionController.removeLocalCursor();
// remove user
op = new ops.OpRemoveMember();
op.init({
memberid: this.userid
}); });
this.session.enqueue([op]);
// close the session
return this.session.close(function(e) {
if (e) {
return me.error("Cannot close session " + e);
}
me.editorSession.sessionController.getMetadataController().unsubscribe(gui.MetadataController.signalMetadataChanged, me.metaChanged);
me.editorSession.sessionController.getUndoManager().unsubscribe(gui.UndoManager.signalDocumentModifiedChanged, me.documentChanged);
me.directFormattingCtl.unsubscribe(gui.DirectFormattingController.textStylingChanged, me.textStylingChanged);
me.directFormattingCtl.unsubscribe(gui.DirectFormattingController.paragraphStylingChanged, me.textStylingChanged);
// destry editorSession
return me.editorSession.destroy(function(e) {
if (e) {
return me.error("Cannot destroy editor session " + e);
}
me.editorSession = void 0;
// destroy session
return me.session.destroy(function(e) {
if (e) {
return me.error("Cannot destroy document session " + e);
}
core.Async.destroyAll([me.canvas.destroy], function(e) {
if (e) {
return me.error("Cannot destroy canvas" + e);
}
return me.notify("Document closed");
});
me.session = void 0;
return me.directFormattingCtl = void 0;
});
});
});
}
cleanup(e) {
return this.closeDocument();
} }
}; };
this.OS.register("OpenPage", OpenPage); this.OS.register("OpenPage", OpenPage);
HyperLinkDialog = class HyperLinkDialog extends this.OS.GUI.BasicDialog {
constructor() {
super("HyperLinkDialog", {
tags: [
{
tag: "afx-label",
att: 'text="__(Text)" data-height="23" class="header"'
},
{
tag: "input",
att: 'data-height="30"'
},
{
tag: "afx-label",
att: 'text="__(Link)" data-height="23" class="header"'
},
{
tag: "input",
att: 'data-height="30"'
},
{
tag: "div",
att: ' data-height="5"'
}
],
width: 350,
height: 150,
resizable: false,
buttons: [
{
label: "Ok",
onclick: function(d) {
var data;
data = {
text: (d.find("content1")).value,
link: (d.find("content3")).value,
readonly: d.data.readonly,
action: d.data.action
};
if (d.handler) {
d.handler(data);
}
return d.quit();
}
},
{
label: "__(Cancel)",
onclick: function(d) {
return d.quit();
}
}
],
filldata: function(d) {
if (!d.data) {
return;
}
(d.find("content1")).value = d.data.text;
(d.find("content3")).value = d.data.link;
return $(d.find("content1")).prop('disabled', d.data.readonly);
}
});
}
};
}).call(this); }).call(this);
/* /*

View File

@ -1,7 +1,36 @@
<afx-app-window apptitle="Open Page" width="600" height="500" data-id="OpenPage"> <afx-app-window apptitle="Open Page" width="650" height="500" data-id="OpenPage">
<afx-hbox > <afx-hbox >
<afx-vbox>
<afx-hbox data-id="toolbox" data-height="28">
<div data-width="5"></div>
<afx-button data-width = "25" data-id="btundo" iconclass = "fa fa-undo"></afx-button>
<afx-button data-width = "25" data-id="btredo" iconclass = "fa fa-rotate-right" ></afx-button>
<afx-button data-width = "25" data-id="btbold" iconclass = "fa fa-bold"></afx-button>
<afx-button data-width = "25" data-id="btitalic" iconclass = "fa fa-italic"></afx-button>
<afx-button data-width = "25" data-id="btunderline" iconclass = "fa fa-underline"></afx-button>
<afx-button data-width = "25" data-id="btstrike" iconclass = "fa fa-strikethrough"></afx-button>
<afx-button data-width = "25" data-id="btnote" iconclass = "fa fa-sticky-note"></afx-button>
<afx-button data-width = "25" data-id="btlink" iconclass = "fa fa-link"></afx-button>
<afx-button data-width = "25" data-id="btunlink" iconclass = "fa fa-unlink"></afx-button>
<afx-button data-width = "25" data-id="btimage" iconclass = "fa fa-image"></afx-button>
<afx-button data-width = "25" data-id="btac" iconclass = "fa fa-align-center"></afx-button>
<afx-button data-width = "25" data-id="btal" iconclass = "fa fa-align-left" ></afx-button>
<afx-button data-width = "25" data-id="btar" iconclass = "fa fa-align-right"></afx-button>
<afx-button data-width = "25" data-id="btaj" iconclass = "fa fa-align-justify"></afx-button>
<afx-button data-width = "25" data-id="btindent" iconclass = "fa fa-indent"></afx-button>
<afx-button data-width = "25" data-id="btoutdent" iconclass = "fa fa-outdent"></afx-button>
<afx-list-view dropdown = "true" data-width="80" data-id="format-list"></afx-list-view>
<div data-width="5"></div>
<afx-nspinner data-width = "50" data-id="font-size" ></afx-nspinner>
<div data-width="5"></div>
<afx-list-view dropdown = "true" data-width="150" data-id="font-list"></afx-list-view>
<div data-width="5"></div>
</afx-hbox>
<div data-height="5"></div>
<div data-id="container"> <div data-id="container">
<div data-id="odfcanvas"></div> <div data-id="odfcanvas"></div>
</div> </div>
</afx-vbox>
</afx-hbox> </afx-hbox>
</afx-app-window> </afx-app-window>

View File

@ -0,0 +1,32 @@
class HyperLinkDialog extends this.OS.GUI.BasicDialog
constructor: () ->
super "HyperLinkDialog", {
tags: [
{ tag: "afx-label", att: 'text="__(Text)" data-height="23" class="header"' },
{ tag: "input", att: 'data-height="30"' },
{ tag: "afx-label", att: 'text="__(Link)" data-height="23" class="header"' },
{ tag: "input", att: 'data-height="30"' },
{ tag: "div", att: ' data-height="5"' }
],
width: 350,
height: 150,
resizable: false,
buttons: [
{
label: "Ok", onclick: (d) ->
data =
text: (d.find "content1").value,
link: (d.find "content3").value,
readonly: d.data.readonly,
action: d.data.action
d.handler data if d.handler
d.quit()
},
{ label: "__(Cancel)", onclick: (d) -> d.quit() }
],
filldata: (d) ->
return unless d.data
(d.find "content1").value = d.data.text
(d.find "content3").value = d.data.link
$(d.find "content1").prop('disabled', d.data.readonly)
}

View File

@ -3,19 +3,64 @@ class OpenPage extends this.OS.GUI.BaseApplication
super "OpenPage", args super "OpenPage", args
main: () -> main: () ->
# load session class
if not OpenPage.editorSession
require ["webodf/editor/EditorSession"], (ES) ->
OpenPage.EditorSession = ES
@eventSubscriptions = new core.EventSubscriptions()
@initToolbox()
@initCanvas()
@canvas.load "#{@_api.handler.get}/home://welcome.odt"
initToolbox: () ->
me = @
@basictool =
undo: @find("btundo"),
redo: @find("btredo"),
bold: @find("btbold"),
italic:@find("btitalic"),
underline:@find("btunderline"),
strike: @find("btstrike"),
note: @find("btnote"),
link: @find("btlink"),
unlink: @find("btunlink"),
image:@find("btimage"),
ac: @find("btac"),
al: @find("btal"),
ar: @find("btar"),
aj: @find("btaj"),
indent: @find("btindent"),
outdent: @find("btoutdent"),
fonts: @find("font-list"),
fontsize: @find("font-size")
fn = (name, el) ->
if name is "fonts"
act = "onlistselect"
else if name is "fontsize"
act = "onchange"
else
act = "onbtclick"
el.set act, (e) ->
return unless me.directFormattingCtl
return unless me[name]
me[name](e)
me.editorFocus()
for name, el of @basictool
fn name, el
initCanvas: () ->
el = @find "odfcanvas" el = @find "odfcanvas"
me = @ me = @
el.setAttribute "translate", "no" el.setAttribute "translate", "no"
el.classList.add "notranslate" el.classList.add "notranslate"
@eventNotifier = new core.EventNotifier [ @userid = "localuser"
"unknown-error",
"documentModifiedChanged",
"metadataChanged"
]
userid = "localuser"
require ["webodf/editor/EditorSession"], (ES) ->
OpenPage.EditorSession = ES
@canvas = new odf.OdfCanvas(el) @canvas = new odf.OdfCanvas(el)
@documentChanged = (e) ->
console.log e
@metaChanged = (e) ->
console.log e
@textStylingChanged = (e) ->
me.updateToolbar e
#@canvas.enableAnnotations(true, true) #@canvas.enableAnnotations(true, true)
@canvas.addListener "statereadychange", ()-> @canvas.addListener "statereadychange", ()->
me.session = new ops.Session(me.canvas) me.session = new ops.Session(me.canvas)
@ -24,7 +69,7 @@ class OpenPage extends this.OS.GUI.BaseApplication
caretAvatarsInitiallyVisible: false, caretAvatarsInitiallyVisible: false,
caretBlinksOnRangeSelect: true caretBlinksOnRangeSelect: true
me.editorSession = new OpenPage.EditorSession(me.session,userid, { me.editorSession = new OpenPage.EditorSession(me.session,me.userid, {
viewOptions: viewOptions, viewOptions: viewOptions,
directTextStylingEnabled: true, directTextStylingEnabled: true,
directParagraphStylingEnabled: true, directParagraphStylingEnabled: true,
@ -36,25 +81,181 @@ class OpenPage extends this.OS.GUI.BaseApplication
zoomingEnabled: true, zoomingEnabled: true,
reviewModeEnabled: false reviewModeEnabled: false
}) })
# basic format
me.directFormattingCtl = me.editorSession.sessionController.getDirectFormattingController()
me.directFormattingCtl.subscribe gui.DirectFormattingController.textStylingChanged, me.textStylingChanged
me.directFormattingCtl.subscribe gui.DirectFormattingController.paragraphStylingChanged, me.textStylingChanged
# hyper link controller
me.hyperlinkController = me.editorSession.sessionController.getHyperlinkController()
me.eventSubscriptions.addFrameSubscription me.editorSession, OpenPage.EditorSession.signalCursorMoved, ()-> me.updateHyperlinkButtons()
me.eventSubscriptions.addFrameSubscription me.editorSession, OpenPage.EditorSession.signalParagraphChanged, ()-> me.updateHyperlinkButtons()
me.eventSubscriptions.addFrameSubscription me.editorSession, OpenPage.EditorSession.signalParagraphStyleModified, ()-> me.updateHyperlinkButtons()
me.editorSession.sessionController.setUndoManager new gui.TrivialUndoManager() me.editorSession.sessionController.setUndoManager new gui.TrivialUndoManager()
me.editorSession.sessionController.getUndoManager().subscribe gui.UndoManager.signalDocumentModifiedChanged, (mod) -> me.editorSession.sessionController.getUndoManager().subscribe gui.UndoManager.signalDocumentModifiedChanged, me.documentChanged
me.eventNotifier.emit "documentModifiedChanged", mod me.editorSession.sessionController.getMetadataController().subscribe gui.MetadataController.signalMetadataChanged, me.metaChanged
me.editorSession.sessionController.getMetadataController().subscribe gui.MetadataController.signalMetadataChanged, (changes) ->
me.eventNotifier.emit "metadataChanged", changes
op = new ops.OpAddMember() op = new ops.OpAddMember()
op.init { op.init {
memberid: userid, memberid: me.userid,
setProperties:{ setProperties:{
"fullName": "Xuan Sang LE", "fullName": "Xuan Sang LE",
"color": "blue" "color": "blue"
} }
} }
me.session.enqueue([op]) me.session.enqueue([op])
me.initFontList me.editorSession.getDeclaredFonts()
me.editorSession.sessionController.insertLocalCursor() me.editorSession.sessionController.insertLocalCursor()
me.editorSession.sessionController.startEditing() me.editorSession.sessionController.startEditing()
me.editorSession.sessionController.getEventManager().focus() #console.log me.editorSession.getDeclaredFonts()
@canvas.load "#{@_api.handler.get}/home://Downloads/welcome.odt" #
@eventNotifier.subscribe "documentModifiedChanged", (d) ->
console.log "document is modified" initFontList: (list) ->
v.text = v.name for v in list
@basictool.fonts.set "items", list
updateToolbar: (changes) ->
# basic style
(@basictool.bold.set "selected", changes.isBold) if changes.hasOwnProperty 'isBold'
(@basictool.italic.set "selected", changes.isItalic) if changes.hasOwnProperty 'isItalic'
(@basictool.underline.set "selected", changes.hasUnderline) if changes.hasOwnProperty 'hasUnderline'
(@basictool.strike.set "selected", changes.hasStrikeThrough) if changes.hasOwnProperty 'hasStrikeThrough'
(@basictool.fontsize.set "value", changes.fontSize) if changes.hasOwnProperty "fontSize"
@selectFont changes.fontName if changes.hasOwnProperty "fontName"
#pharagraph style
@basictool.al.set "selected", changes.isAlignedLeft if changes.hasOwnProperty "isAlignedLeft"
@basictool.ar.set "selected", changes.isAlignedRight if changes.hasOwnProperty "isAlignedRight"
@basictool.ac.set "selected", changes.isAlignedCenter if changes.hasOwnProperty "isAlignedCenter"
@basictool.aj.set "selected", changes.isAlignedJustified if changes.hasOwnProperty "isAlignedJustified"
updateHyperlinkButtons: (e) ->
selectedLinks = @editorSession.getSelectedHyperlinks()
@basictool.unlink.set "enable", selectedLinks.length > 0
selectFont: (name) ->
items = @basictool.fonts.get "items"
item = i for v, i in items when v.name is name
@basictool.fonts.set "selected", item
editorFocus: () ->
@editorSession.sessionController.getEventManager().focus()
bold: (e) ->
#console.log @, e
@directFormattingCtl.setBold (not @basictool.bold.get "selected")
italic: (e) ->
@directFormattingCtl.setItalic (not @basictool.italic.get "selected")
underline: (e) ->
@directFormattingCtl.setHasUnderline (not @basictool.underline.get "selected")
strike: (e) ->
@directFormattingCtl.setHasStrikethrough (not @basictool.strike.get "selected")
fonts: (e) ->
@directFormattingCtl.setFontName e.data.name
fontsize: (e) ->
@directFormattingCtl.setFontSize e
al: (e) ->
@directFormattingCtl.alignParagraphLeft()
ar: (e) ->
@directFormattingCtl.alignParagraphRight()
ac: (e) ->
@directFormattingCtl.alignParagraphCenter()
aj: (e) ->
@directFormattingCtl.alignParagraphJustified()
indent: (e) ->
@directFormattingCtl.indent()
outdent: (e) ->
@directFormattingCtl.outdent()
link: (e) ->
# get the link first
me = @
textSerializer = new odf.TextSerializer()
selection = @editorSession.getSelectedRange()
linksInSelection = @editorSession.getSelectedHyperlinks()
linkTarget = if linksInSelection[0] then odf.OdfUtils.getHyperlinkTarget(linksInSelection[0]) else "http://"
data =
link: linkTarget,
text: "",
readonly: true,
action: "new"
if selection and selection.collapsed and linksInSelection.length == 1
# selection is collapsed within a single link
# text in this case is read only
data.text = textSerializer.writeToString linksInSelection[0]
data.action = "edit"
else if selection and !selection.collapsed
# user select part of link or a block of text
# user convert a selection to a link
data.text = textSerializer.writeToString selection.cloneContents()
else
data.readonly = false
@openDialog new HyperLinkDialog(), (d) ->
selectionController = me.editorSession.sessionController.getSelectionController()
if d.readonly
# edit the existing link
if d.action is "edit"
selectedLinkRange = selection.cloneRange()
selectedLinkRange.selectNode(linksInSelection[0])
selectionController.selectRange(selectedLinkRange, true)
me.hyperlinkController.removeHyperlinks()
me.hyperlinkController.addHyperlink d.link
else
me.hyperlinkController.addHyperlink d.link, d.text
linksInSelection = me.editorSession.getSelectedHyperlinks()
selectedLinkRange = selection.cloneRange()
selectedLinkRange.selectNode(linksInSelection[0])
selectionController.selectRange(selectedLinkRange, true)
, "__(Insert/edit link)", data
unlink: (e) ->
@hyperlinkController.removeHyperlinks()
closeDocument: () ->
# finish editing
return unless @editorSession and @session
me = @
@eventSubscriptions.unsubscribeAll()
@editorSession.sessionController.endEditing()
@editorSession.sessionController.removeLocalCursor()
# remove user
op = new ops.OpRemoveMember()
op.init {
memberid: @userid
}
@session.enqueue [op]
# close the session
@session.close (e) ->
return (me.error "Cannot close session " + e) if e
me.editorSession.sessionController.getMetadataController().unsubscribe gui.MetadataController.signalMetadataChanged, me.metaChanged
me.editorSession.sessionController.getUndoManager().unsubscribe gui.UndoManager.signalDocumentModifiedChanged, me.documentChanged
me.directFormattingCtl.unsubscribe gui.DirectFormattingController.textStylingChanged, me.textStylingChanged
me.directFormattingCtl.unsubscribe gui.DirectFormattingController.paragraphStylingChanged, me.textStylingChanged
# destry editorSession
me.editorSession.destroy (e) ->
return (me.error "Cannot destroy editor session " + e) if e
me.editorSession = undefined
# destroy session
me.session.destroy (e) ->
return (me.error "Cannot destroy document session " + e) if e
core.Async.destroyAll [me.canvas.destroy], (e) ->
return me.error "Cannot destroy canvas" + e if e
me.notify "Document closed"
me.session = undefined
me.directFormattingCtl = undefined
#
cleanup: (e) ->
@closeDocument()
this.OS.register "OpenPage", OpenPage this.OS.register "OpenPage", OpenPage

View File

@ -1,6 +1,42 @@
afx-app-window[data-id="OpenPage"] div[data-id="container"] afx-app-window[data-id="OpenPage"] div[data-id="container"]
{ {
overflow: auto; overflow: auto;
margin:0 auto; margin:0px;
padding:0px padding:0px;
padding-top: 10px;
padding-bottom: 10px;
text-align: center;
background-color: #f2f1f0;
}
afx-app-window[data-id="OpenPage"] div[data-id="odfcanvas"]
{
cursor: text;
margin:auto;
box-shadow: 1px 1px 3px 3px #9f9F9F;
}
afx-app-window[data-id="OpenPage"] afx-hbox[data-id="toolbox"]
{
background-color: #f5f5f5;
border: 1px solid #eaeaea;
box-shadow: 3px 3px 3px #9f9F9F;
}
afx-app-window[data-id="HyperLinkDialog"] afx-label.header span
{
font-weight: bold;
}
afx-app-window[data-id="OpenPage"] afx-hbox[data-id="toolbox"] afx-button button{
border: 1px solid #f5f5f5;
background-color: transparent;
width:100%;
height: 100%;
}
afx-app-window[data-id="OpenPage"] afx-hbox[data-id="toolbox"] afx-button button:hover, afx-app-window[data-id="OpenPage"] afx-hbox[data-id="toolbox"] afx-button.btactive button
{
border: 1px solid #759DC0;
background-color: transparent;
border-radius:5px;
color:#759DC0;
} }

View File

@ -1 +1 @@
{"name":"OpenPage","root":"home://Documents/workspace/antosdk-apps/OpenPage","css":["css/main.css"],"javascripts":["javascripts/webodf.js","javascripts/EditorSession.js"],"coffees":["coffees/main.coffee"],"copies":["assets/scheme.html","package.json","README.md"]} {"name":"OpenPage","root":"home://myws/antosdk-apps/OpenPage","css":["css/main.css"],"javascripts":["javascripts/webodf.js","javascripts/EditorSession.js"],"coffees":["coffees/main.coffee","coffees/dialogs.coffee"],"copies":["assets/scheme.html","package.json","README.md"]}