antosdk-apps/OpenPage/coffees/main.coffee
2018-09-29 09:19:26 +00:00

500 lines
21 KiB
CoffeeScript

class OpenPage extends this.OS.GUI.BaseApplication
constructor: ( args ) ->
super "OpenPage", args
main: () ->
# load session class
#if not OpenPage.EditorSession
# require ["webodf/editor/EditorSession"], (ES) ->
# OpenPage.EditorSession = ES
me =@
@eventSubscriptions = new core.EventSubscriptions()
@initToolbox()
@userid = "#{@systemsetting.user.username}@#{@pid}"
#file = "home://welcome.odt"
#file = "#{@_api.handler.get}/home://welcome.odt"
#@canvas.load file
#odfContainer = new odf.OdfContainer file, (c) ->
# me.canvas.setOdfContainer c, false
@currentStyle = ""
if @args and @args.length > 0 then @open @args[0] else @newdoc()
@resource =
fonts: []
formats: []
@bindKey "ALT-N", () -> me.actionFile "#{me.name}-New"
@bindKey "ALT-O", () -> me.actionFile "#{me.name}-Open"
@bindKey "CTRL-S", () -> me.actionFile "#{me.name}-Save"
@bindKey "ALT-W", () -> me.actionFile "#{me.name}-Saveas"
menu: () ->
me = @
menu = [{
text: "__(File)",
child: [
{ text: "__(New)", dataid: "#{@name}-New", shortcut: "A-N" },
{ text: "__(Open)", dataid: "#{@name}-Open", shortcut: "A-O" },
{ text: "__(Save)", dataid: "#{@name}-Save", shortcut: "C-S" },
{ text: "__(Save as)", dataid: "#{@name}-Saveas", shortcut: "A-W" }
],
onmenuselect: (e) -> me.actionFile e.item.data.dataid
}]
menu
actionFile: (e) ->
me = @
saveas = () ->
me.openDialog "FileDiaLog", (d, n, p) ->
me.currfile.setPath "#{d}/#{n}"
me.save()
, __("Save as"), { file: me.currfile }
switch e
when "#{@name}-Open"
@openDialog "FileDiaLog", ( d, f , p) ->
me.open p
, __("Open file"), { mimes: me.meta().mimes }
when "#{@name}-Save"
#@currfile.cache = @editor.value()
return @save() if @currfile.basename
saveas()
when "#{@name}-Saveas"
saveas()
when "#{@name}-New"
@newdoc()
newdoc: () ->
blank = "#{@meta().path}/blank.odt"
@open blank, true
open: (p,b) ->
me = @
@pathAsDataURL(p)
.then (r) ->
me.closeDocument() if me.editorSession
me.initCanvas()
OdfContainer = new odf.OdfContainer r.data, (c) ->
me.canvas.setOdfContainer c, false
return me.currfile = "Untitled".asFileHandler() if b
if me.currfile then me.currfile.setPath p else me.currfile = p.asFileHandler()
me.scheme.set "apptitle", me.currfile.basename
me.notify __("File {0} opened", p)
.catch (e) ->
me.error __("Problem read file {0}", e)
save: () ->
me = @
return unless @editorSession
container = @canvas.odfContainer()
return @error __("No document container found") unless container
container.createByteArray (ba) ->
# create blob
me.currfile.cache = new Blob [ba], { type: "application/vnd.oasis.opendocument.text" }
me.currfile.write "application/vnd.oasis.opendocument.text", (r) ->
return me.error __("Cannot save file: {0}", r.error) if r.error
me.notify __("File {0} saved", me.currfile.basename)
me.scheme.set "apptitle", me.currfile.basename
me.currfile.dirty = false
me.editorFocus()
, (err) ->
@error __("Cannot create byte array from container: {0}", err|| "")
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"),
styles: @find("format-list"),
zoom: @find("slzoom")
format: @find("btformat")
fn = (name, el) ->
if name is "fonts" or name is "styles"
act = "onlistselect"
else if name is "fontsize" or name is "zoom"
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
(@find "btzoomfix").set "onbtclick", (e) -> me.zoom 100
@basictool.zoom.set "onchanging", (e) ->
zlb = me.find "lbzoom"
zlb.set "text", Math.floor(e) + "%"
initCanvas: () ->
el = @find "odfcanvas"
me = @
el.setAttribute "translate", "no"
el.classList.add "notranslate"
@canvas = new odf.OdfCanvas(el)
@documentChanged = (e) ->
return if me.currfile.dirty
me.currfile.dirty = true
me.scheme.set "apptitle", me.currfile.basename + "*"
#console.log e
@metaChanged = (e) ->
return if me.currfile.dirty
me.currfile.dirty = true
me.scheme.set "apptitle", me.currfile.basename + "*"
#console.log e
@textStylingChanged = (e) ->
me.updateToolbar e
@paragrahStyleChanged = (e) ->
return unless e.type is "style"
items = me.basictool.styles.get "items"
item = i for v, i in items when v.name is e.styleName
me.currentStyle = e.styleName
me.basictool.styles.set "selected", item
@styleAdded = (e) ->
return unless e.family is 'paragraph'
items = me.basictool.styles.get "items"
item = v for v in items when v.name is e.name
return if item
stylens = "urn:oasis:names:tc:opendocument:xmlns:style:1.0"
el = me.editorSession.getParagraphStyleElement e.name
dtext = el.getAttributeNS stylens, 'display-name'
me.basictool.styles.push { text: dtext , name: e.name }, true
#me.resource.formats.push {text: dtext, name:e.name}
@updateSlider = (v) ->
value = Math.floor v*100
me.basictool.zoom.set "value", value
zlb = me.find "lbzoom"
zlb.set "text", value+"%"
#me.canvas.enableAnnotations true, true
@canvas.addListener "statereadychange", ()->
me.session = new ops.Session(me.canvas)
viewOptions =
editInfoMarkersInitiallyVisible: false,
caretAvatarsInitiallyVisible: false,
caretBlinksOnRangeSelect: true
me.editorSession = new OpenPage.EditorSession(me.session,me.userid, {
viewOptions: viewOptions,
directTextStylingEnabled: true,
directParagraphStylingEnabled: true,
paragraphStyleSelectingEnabled: true,
paragraphStyleEditingEnabled: true,
imageEditingEnabled: true,
hyperlinkEditingEnabled: true,
annotationsEnabled: true,
zoomingEnabled: true,
reviewModeEnabled: false
})
me.initFontList me.editorSession.getDeclaredFonts()
me.initStyles me.editorSession.getAvailableParagraphStyles()
#fix annotation problem on canvas
#console.log $("office:body").css "background-color", "red"
# basic format
me.directFormattingCtl = me.editorSession.sessionController.getDirectFormattingController()
me.directFormattingCtl.subscribe gui.DirectFormattingController.textStylingChanged, me.textStylingChanged
me.directFormattingCtl.subscribe gui.DirectFormattingController.paragraphStylingChanged, me.textStylingChanged
me.editorSession.subscribe OpenPage.EditorSession.signalParagraphChanged, me.paragrahStyleChanged
# 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()
#annotation controller
me.annotationController = me.editorSession.sessionController.getAnnotationController()
#image controller
me.imageController = me.editorSession.sessionController.getImageController()
#imageController.subscribe(gui.ImageController.enabledChanged, enableButtons)
#text controller
me.textController = me.editorSession.sessionController.getTextController()
# zoom controller
me.zoomHelper = me.editorSession.getOdfCanvas().getZoomHelper()
me.zoomHelper.subscribe gui.ZoomHelper.signalZoomChanged, me.updateSlider
me.updateSlider me.zoomHelper.getZoomLevel()
# format controller
me.editorSession.subscribe OpenPage.EditorSession.signalCommonStyleCreated, me.styleAdded
me.editorSession.sessionController.setUndoManager new gui.TrivialUndoManager()
me.editorSession.sessionController.getUndoManager().subscribe gui.UndoManager.signalDocumentModifiedChanged, me.documentChanged
me.editorSession.sessionController.getMetadataController().subscribe gui.MetadataController.signalMetadataChanged, me.metaChanged
op = new ops.OpAddMember()
op.init {
memberid: me.userid,
setProperties:{
"fullName": me.userid,
"color": "blue"
}
}
me.session.enqueue([op])
me.editorSession.sessionController.insertLocalCursor()
me.editorSession.sessionController.startEditing()
#console.log me.editorSession.getDeclaredFonts()
#
initFontList: (list) ->
v.text = v.name for v in list
@resource.fonts.push { text: v.text, name: v.family } for v in list
@basictool.fonts.set "items", list
initStyles: (list) ->
list.unshift {name:"", displayName: 'Default style' }
v.text = v.displayName for v in list
@resource.formats.push { text: v.text, name: v.name } for v in list
@basictool.styles.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()
note: (e) ->
@annotationController.addAnnotation()
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()
undo: (e) ->
@editorSession.undo()
redo: (e) ->
@editorSession.redo()
pathAsDataURL: (p) ->
return new Promise (resolve, error) ->
fp = p.asFileHandler()
fp.read (data) ->
blob = new Blob [data], { type: fp.info.mime }
reader = new FileReader()
reader.onloadend = () ->
return error(p) if reader.readyState isnt 2
resolve {data: reader.result, fp: fp }
reader.readAsDataURL blob
, "binary"
###
if not isText
else
fp.read (data) ->
# convert to base64
b64 = btoa data
dataurl = "data:#{fp.info.mime};base64," + b64
resolve { reader: {result: dataurl}, fp:fp }
###
image: (e) ->
me = @
@openDialog "FileDiaLog", (d, n, p) ->
me.pathAsDataURL(p)
.then (r) ->
hiddenImage = new Image()
hiddenImage.style.position = "absolute"
hiddenImage.style.left = "-99999px"
document.body.appendChild hiddenImage
hiddenImage.onload = () ->
content = r.data.substring(r.data.indexOf(",") + 1)
#insert image
me.textController.removeCurrentSelection()
me.imageController.insertImage r.fp.info.mime, content, hiddenImage.width, hiddenImage.height
document.body.removeChild hiddenImage
hiddenImage.src = r.data
.catch () ->
me.error __("Couldnt load image {0}", p)
, __("Select image file"), { mimes: ["image/.*"] }
styles: (e) ->
return if e.data.name is @currentStyle
@editorSession.setCurrentParagraphStyle e.data.name
zoom: (e) ->
#console.log "zooming", e
return unless @zoomHelper
@zoomHelper.setZoomLevel e/100.0
format: (e) ->
@openDialog new FormatDialog(), (d) ->
return
, __("Add/Modify paragraph format"), @resource
closeDocument: (f) ->
# 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 {0}", 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
me.editorSession.unsubscribe OpenPage.EditorSession.signalParagraphChanged, me.paragrahStyleChanged
me.zoomHelper.unsubscribe gui.ZoomHelper.signalZoomChanged, me.updateSlider
me.editorSession.unsubscribe OpenPage.EditorSession.signalCommonStyleCreated, me.styleAdded
# destry editorSession
me.editorSession.destroy (e) ->
return me.error __("Cannot destroy editor session {0}", e) if e
me.editorSession = undefined
# destroy session
me.session.destroy (e) ->
return me.error __("Cannot destroy document session {0}", e) if e
core.Async.destroyAll [me.canvas.destroy], (e) ->
return me.error __("Cannot destroy canvas {0}", e) if e
me.notify "Document closed"
f() if f
me.session = undefined
me.annotationController = undefined
me.directFormattingCtl = undefined
me.textController = undefined
me.imageController = undefined
me.ZoomHelper = undefined
me.metaChanged = undefined
me.documentChanged = undefined
me.textStylingChanged = undefined
me.paragrahStyleChanged = undefined
me.updateSlider = undefined
me.styleAdded = undefined
me.basictool.fonts.set "selected", -1
me.basictool.styles.set "selected", -1
#
cleanup: (e) ->
me = @
if @editorSession
e.preventDefault()
me.closeDocument ()->
me.quit()
this.OS.register "OpenPage", OpenPage