correct more app

This commit is contained in:
Xuan Sang LE 2020-05-21 21:56:16 +02:00
parent 04225e74fb
commit d62bafae48
32 changed files with 710 additions and 383 deletions

View File

@ -1,4 +1,5 @@
(function() {
void 0;
var DataViewer, LuaPlayground, PointCloudViewer;
DataViewer = class DataViewer {
@ -175,7 +176,7 @@
}
// point clound render
// point clound render
render() {
var end, j, len, path, ref, start, v;
this.drawGrid(20, "#DBDBDB"); // 20 px
@ -204,42 +205,44 @@
}
main() {
var me;
me = this;
this.datarea = this.find("editorea");
this.output = this.find("output");
this.editor = ace.edit(this.datarea);
this.editor.setOptions({
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
fontSize: "10pt"
highlightActiveLine: true,
highlightSelectedWord: true,
behavioursEnabled: true,
wrap: true,
fontSize: "11pt",
showInvisibles: true
});
this.editor.getSession().setUseWrapMode(true);
this.editor.session.setMode("ace/mode/lua");
this.editor.setTheme("ace/theme/monokai");
this.on("vboxchange", function() {
return me.editor.resize();
this.on("vboxchange", () => {
return this.editor.resize();
});
(this.find("log-clear")).set("onbtclick", function(e) {
return me.log("clean");
(this.find("log-clear")).set("onbtclick", (e) => {
return this.log("clean");
});
(this.find("code-run")).set("onbtclick", function(e) {
return me.run();
(this.find("code-run")).set("onbtclick", (e) => {
return this.run();
});
(this.find("code-stop")).set("onbtclick", function(e) {
if (me.socket) {
return me.socket.close();
(this.find("code-stop")).set("onbtclick", (e) => {
if (this.socket) {
return this.socket.close();
}
});
this.socket = null;
return this.bindKey("CTRL-R", function() {
return me.run();
return this.bindKey("CTRL-R", () => {
return this.run();
});
}
menu() {
var me, menu;
me = this;
var menu;
menu = [
{
text: "__(Code)",
@ -250,8 +253,8 @@
shortcut: "C-R"
}
],
onmenuselect: function(e) {
return me.run();
onchildselect: (e) => {
return this.run();
}
}
];
@ -270,39 +273,42 @@
}
run() {
var me, value;
me = this;
var value;
value = this.editor.getValue().trim();
if (!(value && value !== "")) {
return;
}
this.socket = this.stream();
this.socket.onopen = function() {
//send data to server
return me.socket.send(JSON.stringify({
code: value
}));
};
this.socket.onmessage = function(e) {
var err, obj;
if (!e.data) {
return;
}
try {
obj = JSON.parse(e.data);
if (!me.view(obj)) {
return me.log("INFO", e.data);
return this.stream().then((s) => {
this.socket = s;
this.socket.onopen = () => {
//send data to server
return this.socket.send(JSON.stringify({
code: value
}));
};
this.socket.onmessage = (e) => {
var err, obj;
if (!e.data) {
return;
}
} catch (error) {
err = error;
me.log("INFO", e.data);
return console.log(err);
}
};
return this.socket.onclose = function() {
me.socket = null;
return console.log("socket closed");
};
try {
obj = JSON.parse(e.data);
if (!this.view(obj)) {
return this.log("INFO", e.data);
}
} catch (error) {
err = error;
this.log("INFO", e.data);
return console.log(err);
}
};
return this.socket.onclose = () => {
this.socket = null;
return console.log("socket closed");
};
}).catch((e) => {
return this.error(__("Unable to get websocket stream"));
});
}
view(obj) {
@ -330,7 +336,7 @@
};
LuaPlayground.dependencies = ["ace/ace"];
LuaPlayground.dependencies = ["os://scripts/ace/ace.js"];
this.OS.register("LuaPlayground", LuaPlayground);

Binary file not shown.

View File

@ -147,38 +147,41 @@ class LuaPlayground extends this.OS.GUI.BaseApplication
super "LuaPlayground", args
main: () ->
me = @
@datarea = @find "editorea"
@output = @find "output"
@.editor = ace.edit @datarea
@.editor.setOptions {
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
fontSize: "10pt"
highlightActiveLine: true,
highlightSelectedWord: true,
behavioursEnabled: true,
wrap: true,
fontSize: "11pt",
showInvisibles: true
}
@editor.getSession().setUseWrapMode true
@editor.session.setMode "ace/mode/lua"
@editor.setTheme "ace/theme/monokai"
@on "vboxchange", () ->
me.editor.resize()
(@find "log-clear").set "onbtclick", (e) ->
me.log "clean"
(@find "code-run").set "onbtclick", (e) ->
me.run()
@on "vboxchange", () =>
@editor.resize()
(@find "log-clear").set "onbtclick", (e) =>
@log "clean"
(@find "code-run").set "onbtclick", (e) =>
@run()
(@find "code-stop").set "onbtclick", (e) ->
me.socket.close() if me.socket
(@find "code-stop").set "onbtclick", (e) =>
@socket.close() if @socket
@socket = null
@bindKey "CTRL-R", () -> me.run()
@bindKey "CTRL-R", () => @run()
menu: () ->
me = @
menu = [{
text: "__(Code)",
child: [
{ text: "__(Run)", dataid: "#{@name}-Run", shortcut: "C-R" }
],
onmenuselect: (e) -> me.run()
onchildselect: (e) => @run()
}]
menu
@ -190,26 +193,27 @@ class LuaPlayground extends this.OS.GUI.BaseApplication
($ @output).scrollTop @output.scrollHeight
run: () ->
me = @
value = @editor.getValue().trim()
return unless value and value isnt ""
@socket = @stream()
@socket.onopen = () ->
#send data to server
me.socket.send( JSON.stringify { code: value } )
@stream().then (s) =>
@socket = s
@socket.onopen = () =>
#send data to server
@socket.send( JSON.stringify { code: value } )
@socket.onmessage = (e) ->
return unless e.data
try
obj = JSON.parse e.data
me.log "INFO", e.data unless me.view obj
catch err
me.log "INFO", e.data
console.log err
@socket.onmessage = (e) =>
return unless e.data
try
obj = JSON.parse e.data
@log "INFO", e.data unless @view obj
catch err
@log "INFO", e.data
console.log err
@socket.onclose = () ->
me.socket = null
console.log "socket closed"
@socket.onclose = () =>
@socket = null
console.log "socket closed"
.catch (e) => @error __("Unable to get websocket stream")
view: (obj) ->
return false unless obj and obj.type and @[obj.type]
@ -226,5 +230,5 @@ class LuaPlayground extends this.OS.GUI.BaseApplication
cleanup: (e)->
@socket.close() if @socket
LuaPlayground.dependencies = ["ace/ace"]
LuaPlayground.dependencies = ["os://scripts/ace/ace.js"]
this.OS.register "LuaPlayground", LuaPlayground

View File

@ -1 +0,0 @@
{"name":"LuaPlayground","root":"home://myws/antosdk-apps/LuaPlayground","css":["css/main.css"],"javascripts":["javascripts/paper-core.min.js"],"coffees":["coffees/main.coffee"],"copies":["assets/scheme.html","package.json","README.md"]}

View File

@ -0,0 +1,8 @@
{
"name": "LuaPlayground",
"root": "home://workspace/antosdk-apps/LuaPlayground",
"css": ["css/main.css"],
"javascripts": ["javascripts/paper-core.min.js"],
"coffees": ["coffees/main.coffee"],
"copies": ["assets/scheme.html", "package.json", "README.md"]
}

View File

@ -1,24 +1,14 @@
# OpenPage
This is an example project, generated by AntOS Development Kit
![](https://os.lxsang.me/repo/OpenPage/OpenPage.png)
# OpenPage: ODT (Open Document Text) editor alpha
**OpenPage** is an AntOS application developed in-browser using AntOSDK. It is a Pure Javascript based rich text editor compatible with Open Document Format.
## Howto
**Feature:**
* Open, view and edit *.odt* documents
* Offer various formatting style to text
* Define and apply paragraph styles
* Insert link, image
* Embeded fonts
* Save documents as ODF format so that it can be compatible with desktop applications like Open Office
1. Open the project.apj file with AntOSDK (simply double Click on it)
2. Modify the UI in *assets/scheme.html*
3. Modify application code in *coffees/main.coffee*
4. Modify CSS style in *css/main.css*
5. Other files need to be copied: put in to assets
## Set up build target
Click **Menu> Build > Build Option** or simply hit **ALT-Y**
In the build options dialog, add or remove files that need to be
included into the build
Click **Save**
## Build application
* To build: **Menu > Build > Build** or **ALT-C**
* To build and run: **Menu > Build > Build and Run** or **CTRL-R**
* To release: **Menu > Build > Build release** or **ALT-P**
**Credit:**
OpenPage is heavily based on the WebODF javascript library: https://webodf.org

View File

@ -1,14 +0,0 @@
![](https://os.lxsang.me/repo/OpenPage/OpenPage.png)
# OpenPage: ODT (Open Document Text) editor alpha
**OpenPage** is an AntOS application developed in-browser using AntOSDK. It is a Pure Javascript based rich text editor compatible with Open Document Format.
**Feature:**
* Open, view and edit *.odt* documents
* Offer various formatting style to text
* Define and apply paragraph styles
* Insert link, image
* Embeded fonts
* Save documents as ODF format so that it can be compatible with desktop applications like Open Office
**Credit:**
OpenPage is heavily based on the WebODF javascript library: https://webodf.org

File diff suppressed because one or more lines are too long

View File

@ -66,6 +66,7 @@ class OpenPage extends this.OS.GUI.BaseApplication
newdoc: () ->
blank = "#{@meta().path}/blank.odt"
@open blank, true
open: (p,b) ->
me = @
@pathAsDataURL(p)

View File

@ -1 +0,0 @@
{"name":"OpenPage","root":"home://workspace/OpenPage","css":["css/main.css","css/dialog.css"],"javascripts":["javascripts/webodf.js","javascripts/EditorSession.js"],"coffees":["coffees/main.coffee","coffees/dialogs.coffee"],"copies":["assets/scheme.html","package.json","assets/OpenPage.md","assets/icon.png","assets/blank.odt"]}

8
OpenPage/project.json Normal file
View File

@ -0,0 +1,8 @@
{
"name": "OpenPage",
"root": "home://workspace/antosdk-apps/OpenPage",
"css": ["css/main.css", "css/dialog.css"],
"javascripts": ["javascripts/webodf.js", "javascripts/EditorSession.js"],
"coffees": ["coffees/main.coffee", "coffees/dialogs.coffee"],
"copies": ["assets/scheme.html", "package.json", "assets/icon.png", "assets/blank.odt"]
}

View File

@ -8,20 +8,26 @@ afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div[data-i
background-repeat: repeat;
}
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div[data-id = "status"]
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] afx-hbox[data-id = "statcontainer"]
{
background-color: transparent;
border-top: 1px solid #cbcbcb;
padding-left: 10px;
padding-top: 3px;
border-bottom: 1px solid #cbcbcb;
}
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] afx-hbox[data-id = "statcontainer"] button,
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] afx-hbox[data-id = "statcontainer"] input
{
height: 24px;
}
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] canvas{
margin-left: auto;
margin-right: auto;
display: block;
}
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div.pdf-page {
margin-bottom: 5px;
}
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div[data-id = "view"].image
{
display: flex;

View File

@ -25,18 +25,62 @@
}
main() {
this.currfile = void 0;
if (this.args && this.args.length > 0) {
this.currfile = this.args[0].path.asFileHandle();
}
this.view = this.find("view");
this.status = this.find("status");
this.zoom = this.find("zoom");
this.btnext = this.find("btnext");
this.btprev = this.find("btprev");
this.btreset = this.find("btreset");
this.txtpage = this.find("txtpage");
this.zoom.set("onchange", (e) => {
return this.setViewScale(e.data);
});
this.btreset.set("onbtclick", (e) => {
this.zoom.set("value", 100);
return this.setViewScale(100);
});
this.btnext.set("onbtclick", (e) => {
var val;
val = parseInt($(this.txtpage).val());
if (isNaN(val)) {
return;
}
$(this.txtpage).val(val + 1);
return this.gotoPage();
});
this.btprev.set("onbtclick", (e) => {
var val;
val = parseInt($(this.txtpage).val());
if (isNaN(val)) {
return;
}
$(this.txtpage).val(val - 1);
return this.gotoPage();
});
$(this.txtpage).keyup((e) => {
if (e.which !== 13) {
return;
}
if (!this.pdf) {
return;
}
return this.gotoPage();
});
PDFJS.workerSrc = `${this.path()}/pdf.worker.js`.asFileHandle().getlink();
this.pdf = void 0;
this.img = void 0;
this.bindKey("ALT-O", () => {
return this.actionFile(`${this.name}-Open`);
});
this.bindKey("CTRL-X", () => {
return this.actionFile(`${this.name}-Close`);
});
this.zoom.set("max", 200);
this.zoom.set("value", 100);
return this.open(this.currfile);
}
@ -49,25 +93,46 @@
}
return file.onready().then(() => {
file.info.size = (file.info.size / 1024).toFixed(2);
return this.renderFile(file);
return this.renderFile();
}).catch((err) => {
return this.error(__("File not found {0}", file.path), err);
});
}
renderFile(file) {
var mime;
mime = file.info.mime;
if (!mime) {
gotoPage() {
var val;
if (!this.pdf) {
return;
}
val = parseInt($(this.txtpage).val());
if (isNaN(val)) {
return;
}
if (val <= 0 || val > this.pdf.numPages) {
return;
}
($(this.view)).empty();
return this.renderPDFPages(val, this.zoom.get("value") / 100, false).catch((e) => {
return this.error(__("Unable to render page {0}", val), e);
});
}
renderFile() {
var mime;
mime = this.currfile.info.mime;
if (!mime) {
return;
}
this.pdf = void 0;
this.img = void 0;
($(this.view)).empty();
this.zoom.set("value", 100);
if (mime.match(/^[^\/]+\/.*pdf.*/g)) {
return this.renderPDF(file);
return this.renderPDF();
} else if (mime.match(/image\/.*svg.*/g)) {
return this.renderSVG(file);
return this.renderSVG();
} else if (mime.match(/image\/.*/g)) {
return this.renderImage(file);
return this.renderImage();
} else {
return this.notify(__("Mime type {0} is not supported", file.info.mime));
}
@ -77,44 +142,92 @@
return ($(this.status)).html(t);
}
renderPDF(file) {
return this.load(new Promise((resolve, reject) => {
setViewScale(value) {
var canvas, context, h, mime, scale, w;
if (!this.currfile) {
return;
}
mime = this.currfile.info.mime;
scale = value / 100;
if (mime.match(/^[^\/]+\/.*pdf.*/g)) {
if (!this.pdf) {
return;
}
($(this.view)).empty();
return this.load(this.renderPDFPages(1, scale)).catch((e) => {
return this.error(__("Unable to set view scale"), e);
});
} else if (mime.match(/image\/.*svg.*/g)) {
return $($(this.view).children()[0]).css("width", `${Math.round(value)}%`).css("height", `${Math.round(value)}%`);
} else if (mime.match(/image\/.*/g)) {
if (!this.img) {
return;
}
canvas = $(this.view).children()[0];
context = canvas.getContext('2d');
w = this.img.width * scale;
h = this.img.height * scale;
canvas.height = h;
canvas.width = w;
context.clearRect(0, 0, canvas.width, canvas.height);
context.scale(scale, scale);
return context.drawImage(this.img, 0, 0);
}
}
renderPDFPages(n, scale, recursive) {
return new Promise((resolve, reject) => {
var status;
status = `${file.info.name} (${file.info.size} Kb)`;
return file.read("binary").then((d) => {
status = `${this.currfile.info.name} (${this.currfile.info.size} Kb)`;
if (n > this.pdf.numPages) {
return resolve();
}
return this.pdf.getPage(n).then((page) => {
var canvas, context, div, renderContext, viewport;
viewport = page.getViewport(scale);
div = ($("<div/>")).attr("id", "page-" + (page.pageIndex + 1)).attr("scale", scale).addClass("pdf-page");
($(this.view)).append(div);
canvas = ($("<canvas>"))[0];
div.append(canvas);
context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
page._canvas = canvas;
this.setStatus(`${status} - page ${n}/${this.pdf.numPages} loaded`);
if (recursive) {
return this.renderPDFPages(n + 1, scale, recursive).then(function() {
return resolve();
}).catch(function(e) {
return reject(e);
});
} else {
return resolve();
}
}).catch(function(e) {
return reject(e);
});
});
}
renderPDF() {
return this.load(new Promise((resolve, reject) => {
return this.currfile.read("binary").then((d) => {
($(this.view)).removeClass();
return PDFJS.getDocument({
data: d
}).then((pdf) => {
var fn;
fn = (p) => {
if (p > pdf.numPages) {
this.setStatus(`${status} - loaded`);
return resolve();
}
return pdf.getPage(p).then((page) => {
var canvas, context, div, renderContext, scale, viewport;
scale = 1.5;
viewport = page.getViewport(scale);
div = ($("<div/>")).attr("id", "page-" + (page.pageIndex + 1));
($(this.view)).append(div);
canvas = ($("<canvas>"))[0];
div.append(canvas);
context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
this.setStatus(`${status} - ${p}/${pdf.numPages} loaded`);
return fn(p + 1);
}).catch(function(e) {
return reject(e);
});
};
return fn(1);
this.pdf = pdf;
return this.renderPDFPages(1, 1, false).then(() => {
$(this.txtpage).val("1");
return resolve();
}).catch(function(e) {
return reject(e);
});
}).catch(function(e) {
return reject(e);
});
@ -122,23 +235,23 @@
return reject(e);
});
})).catch((e) => {
return this.error(__("Unable to view file: {}", file.path), e);
return this.error(__("Unable to view file: {0}", this.currfile.path), e);
});
}
renderSVG(file) {
renderSVG() {
($(this.view)).attr("class", "image");
return file.read().then((d) => {
return this.currfile.read().then((d) => {
this.view.innerHTML = d;
return $($(this.view).children()[0]).css("width", "100%").css("height", "100%");
}).catch((e) => {
return this.error(__("Unable to read file: {}", file.path), e);
return this.error(__("Unable to read file: {0}", this.currfile.path), e);
});
}
renderImage(file) {
renderImage() {
($(this.view)).attr("class", "image");
return file.read("binary").then((d) => {
return this.currfile.read("binary").then((d) => {
var blob, canvas, img;
img = new Image();
canvas = ($("<canvas/>"))[0];
@ -149,16 +262,17 @@
context = canvas.getContext('2d');
canvas.height = img.height;
canvas.width = img.width;
this.img = img;
//console.log canvas.width, canvas.height
context.drawImage(img, 0, 0);
return this.setStatus(`${file.info.name} (${file.info.size} Kb) - ${img.width}x${img.height}`);
return this.setStatus(`${this.currfile.info.name} (${this.currfile.info.size} Kb) - ${img.width}x${img.height}`);
};
blob = new Blob([d], {
type: file.info.mime
type: this.currfile.info.mime
});
return img.src = URL.createObjectURL(blob);
}).catch((e) => {
return this.error(__("Unable to read file: {}", file.path), e);
return this.error(__("Unable to read file: {0}", this.currfile.path), e);
});
}

View File

@ -6,7 +6,7 @@
"author": "Xuan Sang LE",
"email": "xsang.le@gmail.com"
},
"version":"0.0.2-a",
"version":"0.0.3-a",
"category":"Utils",
"iconclass":"fa fa-eye",
"mimes":["[^\/]*/.*pdf", "image/.*"]

View File

@ -1,6 +1,17 @@
<afx-app-window data-id = "preview-win" apptitle="Preview" width="600" height="400">
<afx-vbox data-id = "container">
<afx-hbox data-height = "25" data-id = "statcontainer" >
<div data-width = "5" ></div>
<afx-button data-width="20" iconclass="fa fa-chevron-left" data-id="btprev"></afx-button>
<input type="text" data-width="30" data-id="txtpage" />
<afx-button data-width="20" iconclass="fa fa-chevron-right" data-id="btnext"></afx-button>
<div data-width = "5" ></div>
<afx-button data-width="20" iconclass="fa fa-arrows-alt" data-id="btreset"></afx-button>
<div data-width = "5" ></div>
<afx-slider data-width="150" data-id="zoom" ></afx-slider>
<div data-id = "status" style="text-align: right;"></div>
<div data-width = "10" ></div>
</afx-hbox>
<div data-id="view" ></div>
<div data-id = "status" data-height = "20"></div>
</afx-vbox>
</afx-app-window>

Binary file not shown.

View File

@ -21,14 +21,46 @@ class Preview extends this.OS.GUI.BaseApplication
super "Preview", args
main: () ->
@currfile = undefined
@currfile = @args[0].path.asFileHandle() if @args and @args.length > 0
@view = @find "view"
@status = @find "status"
@zoom = @find "zoom"
@btnext = @find "btnext"
@btprev = @find "btprev"
@btreset = @find "btreset"
@txtpage = @find "txtpage"
@zoom.set "onchange", (e) => @setViewScale e.data
@btreset.set "onbtclick", (e) =>
@zoom.set "value", 100
@setViewScale 100
@btnext.set "onbtclick", (e) =>
val = parseInt $(@txtpage).val()
return if isNaN val
$(@txtpage).val val + 1
@gotoPage()
@btprev.set "onbtclick", (e) =>
val = parseInt $(@txtpage).val()
return if isNaN val
$(@txtpage).val val - 1
@gotoPage()
$(@txtpage).keyup (e) =>
return unless e.which is 13
return unless @pdf
@gotoPage()
PDFJS.workerSrc = "#{@path()}/pdf.worker.js".asFileHandle().getlink()
@pdf = undefined
@img = undefined
@bindKey "ALT-O", () => @actionFile "#{@name}-Open"
@bindKey "CTRL-X", () => @actionFile "#{@name}-Close"
@zoom.set "max", 200
@zoom.set "value", 100
@open @currfile
@ -37,72 +69,125 @@ class Preview extends this.OS.GUI.BaseApplication
@currfile = file unless @currfile is file
file.onready().then () =>
file.info.size = (file.info.size / 1024).toFixed(2)
@renderFile file
@renderFile()
.catch (err) =>
@error __("File not found {0}", file.path), err
renderFile: (file) ->
mime = file.info.mime
return unless mime
gotoPage: () ->
return unless @pdf
val = parseInt $(@txtpage).val()
return if isNaN(val)
return if val <= 0 or val > @pdf.numPages
($ @view).empty()
@renderPDFPages val, (@zoom.get("value") / 100), false
.catch (e) => @error __("Unable to render page {0}", val), e
renderFile: () ->
mime = @currfile.info.mime
return unless mime
@pdf = undefined
@img = undefined
($ @view).empty()
@zoom.set "value", 100
if mime.match /^[^\/]+\/.*pdf.*/g
@renderPDF file
@renderPDF()
else if mime.match /image\/.*svg.*/g
@renderSVG file
@renderSVG()
else if mime.match /image\/.*/g
@renderImage file
@renderImage()
else
@notify __("Mime type {0} is not supported", file.info.mime)
setStatus: (t) ->
($ @status).html t
renderPDF: (file) ->
setViewScale: (value) ->
return unless @currfile
mime = @currfile.info.mime
scale = (value / 100)
if mime.match /^[^\/]+\/.*pdf.*/g
return unless @pdf
($ @view).empty()
@load @renderPDFPages 1, scale
.catch (e) => @error __("Unable to set view scale"), e
else if mime.match /image\/.*svg.*/g
$($(@view).children()[0])
.css "width", "#{Math.round(value)}%"
.css "height", "#{Math.round(value)}%"
else if mime.match /image\/.*/g
return unless @img
canvas = $(@view).children()[0]
context = canvas.getContext '2d'
w = @img.width * scale
h = @img.height * scale
canvas.height = h
canvas.width = w
context.clearRect(0, 0, canvas.width, canvas.height)
context.scale scale, scale
context.drawImage @img, 0, 0
renderPDFPages: (n, scale, recursive) ->
new Promise (resolve, reject) =>
status = "#{@currfile.info.name} (#{@currfile.info.size} Kb)"
return resolve() if n > @pdf.numPages
@pdf.getPage(n).then (page) =>
viewport = page.getViewport scale
div = ($ "<div/>")
.attr("id", "page-" + (page.pageIndex + 1))
.attr("scale", scale)
.addClass "pdf-page"
($ @view).append div
canvas = ($ "<canvas>")[0]
div.append canvas
context = canvas.getContext '2d'
canvas.height = viewport.height
canvas.width = viewport.width
renderContext =
canvasContext: context
viewport: viewport
page.render renderContext
page._canvas = canvas
@setStatus "#{status} - page #{n}/#{@pdf.numPages} loaded"
if recursive
@renderPDFPages n + 1, scale, recursive
.then () -> resolve()
.catch (e) -> reject e
else
resolve()
.catch (e) -> reject e
renderPDF: () ->
@load new Promise (resolve, reject) =>
status = "#{file.info.name} (#{file.info.size} Kb)"
file.read("binary").then (d) =>
@currfile.read("binary").then (d) =>
($ @view).removeClass()
PDFJS.getDocument { data: d }
.then (pdf) =>
fn = (p) =>
if p > pdf.numPages
@setStatus "#{status} - loaded"
return resolve()
pdf.getPage(p).then (page) =>
scale = 1.5
viewport = page.getViewport scale
div = ($ "<div/>").attr("id", "page-" + (page.pageIndex + 1))
($ @view).append div
canvas = ($ "<canvas>")[0]
div.append canvas
context = canvas.getContext '2d'
canvas.height = viewport.height
canvas.width = viewport.width
renderContext =
canvasContext: context
viewport: viewport
page.render renderContext
@setStatus "#{status} - #{p}/#{pdf.numPages} loaded"
fn(p+1)
@pdf = pdf
@renderPDFPages 1, 1, false
.then () =>
$(@txtpage).val("1")
resolve()
.catch (e) -> reject e
fn(1)
.catch (e) -> reject e
.catch (e) -> reject e
.catch (e) => @error __("Unable to view file: {}", file.path), e
.catch (e) => @error __("Unable to view file: {0}", @currfile.path), e
renderSVG: (file) ->
renderSVG: () ->
($ @view).attr("class", "image")
file.read().then (d) =>
@currfile.read().then (d) =>
@view.innerHTML = d
$($(@view).children()[0])
.css "width", "100%"
.css "height", "100%"
.catch (e) => @error __("Unable to read file: {}", file.path), e
.catch (e) => @error __("Unable to read file: {0}", @currfile.path), e
renderImage: (file) ->
renderImage: () ->
($ @view).attr("class", "image")
file.read("binary").then (d) =>
@currfile.read("binary").then (d) =>
img = new Image()
canvas = ($ "<canvas/>")[0]
($ @view).append canvas
@ -112,13 +197,14 @@ class Preview extends this.OS.GUI.BaseApplication
context = canvas.getContext '2d'
canvas.height = img.height
canvas.width = img.width
@img = img
#console.log canvas.width, canvas.height
context.drawImage img, 0, 0
@setStatus "#{file.info.name} (#{file.info.size} Kb) - #{img.width}x#{img.height}"
@setStatus "#{@currfile.info.name} (#{@currfile.info.size} Kb) - #{img.width}x#{img.height}"
blob = new Blob [d], { type: file.info.mime }
blob = new Blob [d], { type: @currfile.info.mime }
img.src = URL.createObjectURL blob
.catch (e) => @error __("Unable to read file: {}", file.path), e
.catch (e) => @error __("Unable to read file: {0}", @currfile.path), e
menu: () ->
menu = [{

View File

@ -7,20 +7,26 @@ afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div[data-i
background-repeat: repeat;
}
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div[data-id = "status"]
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] afx-hbox[data-id = "statcontainer"]
{
background-color: transparent;
border-top: 1px solid #cbcbcb;
padding-left: 10px;
padding-top: 3px;
border-bottom: 1px solid #cbcbcb;
}
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] afx-hbox[data-id = "statcontainer"] button,
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] afx-hbox[data-id = "statcontainer"] input
{
height: 24px;
}
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] canvas{
margin-left: auto;
margin-right: auto;
display: block;
}
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div.pdf-page {
margin-bottom: 5px;
}
afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div[data-id = "view"].image
{
display: flex;

View File

@ -6,7 +6,7 @@
"author": "Xuan Sang LE",
"email": "xsang.le@gmail.com"
},
"version":"0.0.2-a",
"version":"0.0.3-a",
"category":"Utils",
"iconclass":"fa fa-eye",
"mimes":["[^\/]*/.*pdf", "image/.*"]

View File

@ -1,6 +1,17 @@
<afx-app-window data-id = "preview-win" apptitle="Preview" width="600" height="400">
<afx-vbox data-id = "container">
<afx-hbox data-height = "25" data-id = "statcontainer" >
<div data-width = "5" ></div>
<afx-button data-width="20" iconclass="fa fa-chevron-left" data-id="btprev"></afx-button>
<input type="text" data-width="30" data-id="txtpage" />
<afx-button data-width="20" iconclass="fa fa-chevron-right" data-id="btnext"></afx-button>
<div data-width = "5" ></div>
<afx-button data-width="20" iconclass="fa fa-arrows-alt" data-id="btreset"></afx-button>
<div data-width = "5" ></div>
<afx-slider data-width="150" data-id="zoom" ></afx-slider>
<div data-id = "status" style="text-align: right;"></div>
<div data-width = "10" ></div>
</afx-hbox>
<div data-id="view" ></div>
<div data-id = "status" data-height = "20"></div>
</afx-vbox>
</afx-app-window>

View File

@ -1,24 +1,3 @@
# TinyEditor
This is the example project for the tutorial: [https://blog.lxsang.me/post/id/20](https://blog.lxsang.me/post/id/20)
## Howto
1. Open the project.apj file with AntOSDK (simply double Click on it)
2. Modify the UI in *assets/scheme.html*
3. Modify application code in *coffees/main.coffee*
4. Modify CSS style in *css/main.css*
5. Other files need to be copied: put in to assets
## Set up build target
Click **Menu> Build > Build Option** or simply hit **ALT-Y**
In the build options dialog, add or remove files that need to be
included into the build
Click **Save**
## Build application
* To build: **Menu > Build > Build** or **ALT-C**
* To build and run: **Menu > Build > Build and Run** or **CTRL-R**
* To release: **Menu > Build > Build release** or **ALT-P**

View File

@ -1,24 +1,3 @@
# TinyEditor
This is the example project for the tutorial: [https://blog.lxsang.me/post/id/20](https://blog.lxsang.me/post/id/20)
## Howto
1. Open the project.apj file with AntOSDK (simply double Click on it)
2. Modify the UI in *assets/scheme.html*
3. Modify application code in *coffees/main.coffee*
4. Modify CSS style in *css/main.css*
5. Other files need to be copied: put in to assets
## Set up build target
Click **Menu> Build > Build Option** or simply hit **ALT-Y**
In the build options dialog, add or remove files that need to be
included into the build
Click **Save**
## Build application
* To build: **Menu > Build > Build** or **ALT-C**
* To build and run: **Menu > Build > Build and Run** or **CTRL-R**
* To release: **Menu > Build > Build release** or **ALT-P**

View File

@ -1,8 +1,6 @@
afx-app-window[data-id="TinyEditor"] textarea[data-id="editor"]
{
background-color: #272822;
color:white;
margin: 0;
padding:10px;
border: 0;

View File

@ -1,4 +1,5 @@
(function() {
void 0;
var TinyEditor;
TinyEditor = class TinyEditor extends this.OS.GUI.BaseApplication {
@ -7,32 +8,29 @@
}
main() {
var me;
me = this;
this.editor = this.find("editor");
this.bindKey("ALT-N", function() {
return me.newFile();
this.bindKey("ALT-N", () => {
return this.newFile();
});
this.bindKey("ALT-O", function() {
return me.openFile();
this.bindKey("ALT-O", () => {
return this.openFile();
});
this.bindKey("CTRL-S", function() {
return me.saveFile();
this.bindKey("CTRL-S", () => {
return this.saveFile();
});
this.filehandler = this.args && this.args.length > 0 ? this.args[0].asFileHandler() : null;
$(this.editor).on('input', function(e) {
if (me.filehandler.dirty === true) {
this.filehandle = this.args && this.args.length > 0 ? this.args[0].asFileHandle() : null;
$(this.editor).on('input', (e) => {
if (this.filehandle.dirty === true) {
return;
}
me.filehandler.dirty = true;
return me.scheme.set("apptitle", `${me.filehandler.path}*`);
this.filehandle.dirty = true;
return this.scheme.set("apptitle", `${this.filehandle.path}*`);
});
return this.read();
}
menu() {
var m, me;
me = this;
var m;
m = [
{
text: "__(File)",
@ -53,14 +51,14 @@
shortcut: 'C-S'
}
],
onmenuselect: function(e) {
switch (e.item.data.dataid) {
onchildselect: (e) => {
switch (e.data.item.get("data").dataid) {
case "new":
return me.newFile();
return this.newFile();
case "open":
return me.openFile();
return this.openFile();
case "save":
return me.saveFile();
return this.saveFile();
}
}
}
@ -69,71 +67,73 @@
}
newFile() {
this.filehandler = null;
this.filehandle = null;
return this.read();
}
openFile() {
var me;
me = this;
return this.openDialog("FileDiaLog", function(dir, fname, d) {
me.filehandler = `${dir}/${fname}`.asFileHandler();
return me.read();
}, __("Open file"));
return this.openDialog("FileDialog", {
title: __("Open file")
}).then((d) => {
this.filehandle = d.file.path.asFileHandle();
return this.read();
});
}
saveFile() {
var me;
me = this;
this.filehandler.cache = this.editor.value;
if (this.filehandler.path !== "Untitled") {
this.filehandle.cache = this.editor.value;
if (this.filehandle.path !== "Untitled") {
return this.write();
}
return this.openDialog("FileDiaLog", function(dir, fname, d) {
me.filehandler.setPath(`${dir}/${fname}`);
return me.write();
}, __("Save as"), {
file: me.filehandler
return this.openDialog("FileDialog", {
title: __("Save as"),
file: this.filehandle
}).then((f) => {
var d;
d = f.file.path.asFileHandle();
if (f.file.type === "file") {
d = d.parent();
}
this.filehandle.setPath(`${d.path}/${f.name}`);
return this.write();
});
}
read() {
var me;
me = this;
this.editor.value = "";
if (this.filehandler === null) {
this.filehandler = "Untitled".asFileHandler();
if (this.filehandle === null) {
this.filehandle = "Untitled".asFileHandle();
this.scheme.set("apptitle", "Untitled");
return;
}
return this.filehandler.read(function(d) {
me.scheme.set("apptitle", me.filehandler.path);
return me.editor.value = d;
return this.filehandle.read().then((d) => {
this.scheme.set("apptitle", this.filehandle.path);
return this.editor.value = d;
}).catch((e) => {
return this.error(__("Unable to read file content"));
});
}
write() {
var me;
me = this;
return this.filehandler.write("text/plain", function(d) {
if (d.error) {
return me.error(__("Error saving file {0}", me.filehandler.path));
}
me.filehandler.dirty = false;
return me.scheme.set("apptitle", `${me.filehandler.path}`);
return this.filehandle.write("text/plain").then((d) => {
this.filehandle.dirty = false;
return this.scheme.set("apptitle", `${this.filehandle.path}`);
}).catch((e) => {
return this.error(__("Error saving file {0}", this.filehandle.path), e);
});
}
cleanup(e) {
var me;
if (!this.filehandler.dirty) {
if (!this.filehandle.dirty) {
return;
}
me = this;
e.preventDefault();
return this.ask("__(Quit)", "__(Quit without saving?)", function() {
me.filehandler.dirty = false;
return me.quit();
return this.ask({
title: "__(Quit)",
text: "__(Quit without saving?)"
}).then(() => {
this.filehandle.dirty = false;
return this.quit();
});
}

View File

@ -1,10 +1,10 @@
{
"app":"TinyEditor",
"name":"TinyEditor",
"description":"",
"name":"Tiny editor",
"description":"Basic plain text file editor",
"info":{
"author": "",
"email": ""
"author": "Xuan Sang LE",
"email": "xsang.le@gmail.com"
},
"version":"0.0.1-a",
"category":"Other",

Binary file not shown.

View File

@ -3,20 +3,18 @@ class TinyEditor extends this.OS.GUI.BaseApplication
super "TinyEditor", args
main: () ->
me = @
@editor = @find "editor"
@bindKey "ALT-N", () -> me.newFile()
@bindKey "ALT-O", () -> me.openFile()
@bindKey "CTRL-S", () -> me.saveFile()
@filehandler = if @args and @args.length > 0 then @args[0].asFileHandler() else null
$(@editor).on 'input', (e) ->
return if me.filehandler.dirty is true
me.filehandler.dirty = true
me.scheme.set "apptitle", "#{me.filehandler.path}*"
@bindKey "ALT-N", () => @newFile()
@bindKey "ALT-O", () => @openFile()
@bindKey "CTRL-S", () => @saveFile()
@filehandle = if @args and @args.length > 0 then @args[0].asFileHandle() else null
$(@editor).on 'input', (e) =>
return if @filehandle.dirty is true
@filehandle.dirty = true
@scheme.set "apptitle", "#{@filehandle.path}*"
@read()
menu: () ->
me = @
m = [
{
text: "__(File)",
@ -25,60 +23,62 @@ class TinyEditor extends this.OS.GUI.BaseApplication
{ text: "__(Open)", dataid :"open", shortcut: 'A-O' },
{ text: "__(Save)", dataid :"save", shortcut: 'C-S' }
],
onmenuselect: (e) ->
switch e.item.data.dataid
when "new" then me.newFile()
when "open" then me.openFile()
when "save" then me.saveFile()
onchildselect: (e) =>
switch e.data.item.get("data").dataid
when "new" then @newFile()
when "open" then @openFile()
when "save" then @saveFile()
}
]
m
newFile: () ->
@filehandler = null
@filehandle = null
@read()
openFile: () ->
me = @
@openDialog "FileDiaLog", ( dir, fname, d ) ->
me.filehandler = "#{dir}/#{fname}".asFileHandler()
me.read()
, __("Open file")
@openDialog "FileDialog", { title: __("Open file") }
.then (d) =>
@filehandle = d.file.path.asFileHandle()
@read()
,
saveFile: () ->
me = @
@filehandler.cache = @editor.value
return @write() unless @filehandler.path is "Untitled"
@openDialog "FileDiaLog", (dir, fname, d) ->
me.filehandler.setPath "#{dir}/#{fname}"
me.write()
, __("Save as"), { file: me.filehandler }
@filehandle.cache = @editor.value
return @write() unless @filehandle.path is "Untitled"
@openDialog("FileDialog", {
title: __("Save as"),
file: @filehandle
}).then (f) =>
d = f.file.path.asFileHandle()
d = d.parent() if f.file.type is "file"
@filehandle.setPath "#{d.path}/#{f.name}"
@write()
read: () ->
me = @
@editor.value = ""
if @filehandler is null
@filehandler = "Untitled".asFileHandler()
if @filehandle is null
@filehandle = "Untitled".asFileHandle()
@scheme.set "apptitle", "Untitled"
return
@filehandler.read (d) ->
me.scheme.set "apptitle", me.filehandler.path
me.editor.value = d
@filehandle.read().then (d) =>
@scheme.set "apptitle", @filehandle.path
@editor.value = d
.catch (e) => @error __("Unable to read file content")
write: () ->
me = @
@filehandler.write "text/plain", (d) ->
return me.error __("Error saving file {0}", me.filehandler.path) if d.error
me.filehandler.dirty = false
me.scheme.set "apptitle", "#{me.filehandler.path}"
@filehandle.write("text/plain").then (d) =>
@filehandle.dirty = false
@scheme.set "apptitle", "#{@filehandle.path}"
.catch (e) => @error __("Error saving file {0}", @filehandle.path), e
cleanup: (e) ->
return unless @filehandler.dirty
me = @
return unless @filehandle.dirty
e.preventDefault()
@ask "__(Quit)", "__(Quit without saving?)", () ->
me.filehandler.dirty = false
me.quit()
@ask { title: "__(Quit)", text: "__(Quit without saving?)" }
.then () =>
@filehandle.dirty = false
@quit()
this.OS.register "TinyEditor", TinyEditor

View File

@ -1,7 +1,5 @@
afx-app-window[data-id="TinyEditor"] textarea[data-id="editor"]
{
background-color: #272822;
color:white;
margin: 0;
padding:10px;
border: 0;

View File

@ -1,10 +1,10 @@
{
"app":"TinyEditor",
"name":"TinyEditor",
"description":"",
"name":"Tiny editor",
"description":"Basic plain text file editor",
"info":{
"author": "",
"email": ""
"author": "Xuan Sang LE",
"email": "xsang.le@gmail.com"
},
"version":"0.0.1-a",
"category":"Other",

View File

@ -1 +0,0 @@
{"name":"TinyEditor","root":"home://workspace/TinyEditor","css":["css/main.css"],"javascripts":[],"coffees":["coffees/main.coffee"],"copies":["assets/scheme.html","package.json","README.md"]}

8
TinyEditor/project.json Normal file
View File

@ -0,0 +1,8 @@
{
"name": "TinyEditor",
"root": "home://workspace/antosdk-apps/TinyEditor",
"css": ["css/main.css"],
"javascripts": [],
"coffees": ["coffees/main.coffee"],
"copies": ["assets/scheme.html", "package.json", "README.md"]
}

View File

@ -17,6 +17,15 @@
"version": "0.0.1-a",
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/ActivityMonitor/build/release/ActivityMonitor.zip"
},
{
"pkgname": "LuaPlayground",
"name": "LuaPlayground",
"description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/LuaPlayground/README.md",
"category": "System",
"author": "Xuan Sang LEs",
"version": "0.0.1-a",
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/LuaPlayground/build/release/LuaPlayground.zip"
},
{
"pkgname": "MarkOn",
"name": "Markdown editor",
@ -32,7 +41,7 @@
"description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Preview/README.md",
"category": "Utils",
"author": "Xuan Sang LE",
"version": "0.0.2-a",
"version": "0.0.3-a",
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Preview/build/release/Preview.zip"
},
{
@ -44,6 +53,15 @@
"version": "0.0.2-a",
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/ShowCase/build/release/ShowCase.zip"
},
{
"pkgname": "TinyEditor",
"name": "Tiny editor",
"description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/TinyEditor/README.md",
"category": "Other",
"author": "Xuan Sang LE",
"version": "0.0.1-a",
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/TinyEditor/build/release/TinyEditor.zip"
},
{
"pkgname": "wTerm",
"name": "Terminal",