- Show simulation progress with or with out 3D view.
- Synchronize file list between browsers.
- Increased max simulation time to 24hrs.
+ - Added button to download current GCode file.
## v0.4.2
- Suppress ``Auto-creating missing tool`` warning.
function is_object(o) {return o !== null && typeof o == 'object'}
+function is_array(o) {return Array.isArray(o)}
+
+
+function update_array(dst, src) {
+ while (dst.length) dst.pop()
+ for (var i = 0; i < src.length; i++)
+ Vue.set(dst, i, src[i]);
+}
function update_object(dst, src, remove) {
key = props[index];
value = src[key];
- if (is_object(value) && dst.hasOwnProperty(key) && is_object(dst[key]))
+ if (is_array(value) && dst.hasOwnProperty(key) && is_array(dst[key]))
+ update_array(dst[key], value);
+
+ else if (is_object(value) && dst.hasOwnProperty(key) && is_object(dst[key]))
update_object(dst[key], value, remove);
else Vue.set(dst, key, value);
},
- 'state.selected': function () {this.load()}
+ 'state.selected': function () {this.load()},
+ 'state.files': function () {
+ console.log('Files changed: ' + JSON.stringify(this.state.files))}
},
load: function () {
var file = this.state.selected;
- if (this.last_file == file || typeof file == 'undefined' ||
- typeof file == 'null') return;
+ if (this.last_file == file) return;
this.last_file = file;
- if (typeof file != 'undefined') this.$broadcast('gcode-load', file);
+ this.$broadcast('gcode-load', file);
this.$broadcast('gcode-line', this.state.line);
this.toolpath_progress = 0;
this.load_toolpath(file);
load_toolpath: function (file) {
this.toolpath = {};
- if (typeof file == 'undefined' || typeof file == 'null') return;
+ if (!file) return;
api.get('path/' + file).done(function (toolpath) {
if (this.last_file != file) return;
rows: [],
scrollElem: $(this.$el).find('.clusterize-scroll')[0],
contentElem: $(this.$el).find('.clusterize-content')[0],
- no_data_text: 'Loading GCode...',
+ no_data_text: 'GCode viewer...',
callbacks: {clusterChanged: this.highlight}
});
},
methods: {
load: function (file) {
- if (file == this.file || typeof file == 'undefined' ||
- typeof file == 'null') return;
+ if (file == this.file) return;
this.clear();
this.file = file;
+ if (!file) return;
+
var xhr = new XMLHttpRequest();
xhr.open('GET', '/api/file/' + file + '?' + Math.random(), true);
xhr.responseType = 'text';
methods: {
update: function () {
- if (!this.toolpath.filename && !this.loading) {
+ if (!this.state.selected) {
+ this.dirty = true;
+ this.scene = new THREE.Scene();
+
+ } else if (!this.toolpath.filename && !this.loading) {
this.loading = true;
this.dirty = true;
this.draw_loading();
input(type="file", @change="upload", :disabled="!is_ready",
accept="text/*,.nc,.gcode,.gc,.ngc,.txt,.tap,.cnc")
+ a.pure-button(:disabled="!state.selected", download,
+ :href="'/api/file/' + state.selected",
+ title="Download the selected GCode program.")
+ .fa.fa-download
+
button.pure-button(title="Delete current GCode program.",
@click="deleteGCode = true",
:disabled="!state.selected || !is_ready")
v-model="state.selected", @change="load", :disabled="!is_ready")
option(v-for="file in state.files", :value="file") {{file}}
- .progress(v-if="toolpath_progress && toolpath_progress < 1")
+ .progress(v-if="toolpath_progress && toolpath_progress < 1",
+ title="Simulating GCode to check for errors, calculate ETA and " +
+ "generate 3D view. You can run GCode before the simulation " +
+ "finishes.")
div(:style="'width:' + (toolpath_progress || 0) * 100 + '%'")
- label Simulating run {{(toolpath_progress || 0) | percent}}
+ label Simulating {{(toolpath_progress || 0) | percent}}
path-viewer(:toolpath="toolpath", :state="state", :config="config")
gcode-viewer
import html
import logging
from tornado import gen
+from tornado.web import HTTPError
log = logging.getLogger('FileHandler')
else:
# Delete a single file
- safe_remove('upload' + filename)
+ filename = os.path.basename(filename)
+ safe_remove('upload/' + filename)
self.ctrl.preplanner.delete_plans(filename)
self.ctrl.state.remove_file(filename)
- def put_ok(self, path):
+ def put_ok(self, *args):
gcode = self.request.files['gcode'][0]
- filename = gcode['filename']
+ filename = os.path.basename(gcode['filename'])
if not os.path.exists('upload'): os.mkdir('upload')
- path ='upload/' + filename
-
- with open(path, 'wb') as f:
+ with open('upload/' + filename, 'wb') as f:
f.write(gcode['body'])
self.ctrl.preplanner.invalidate(filename)
self.ctrl.state.add_file(filename)
- log.info('GCode updated: ' + filename)
+ log.info('GCode received: ' + filename)
@gen.coroutine
def get(self, filename):
- filename = filename[1:] # Remove /
+ if not filename: raise HTTPError(400, 'Missing filename')
+ filename = os.path.basename(filename)
with open('upload/' + filename, 'r') as f:
self.write(f.read())
def clear_files(self):
self.select_file('')
self.files = []
- self.set('files', self.files)
+ self.changes['files'] = self.files
def add_file(self, filename):
- if filename not in self.files:
+ if not filename in self.files:
self.files.append(filename)
self.files.sort()
- self.set('files', self.files)
+ self.changes['files'] = self.files
self.select_file(filename)
def remove_file(self, filename):
- if self.get('selected', '') == filename: self.select_file('')
-
if filename in self.files:
self.files.remove(filename)
- self.set('files', self.files)
+ self.changes['files'] = self.files
+
+ if self.get('selected', filename) == filename:
+ if len(self.files): self.select_file(self.files[0])
+ else: self.select_file('')
def select_file(self, filename): self.set('selected', filename)
(r'/api/config/reset', ConfigResetHandler),
(r'/api/firmware/update', FirmwareUpdateHandler),
(r'/api/upgrade', UpgradeHandler),
- (r'/api/file(/[^/]+)', bbctrl.FileHandler),
+ (r'/api/file(/[^/]+)?', bbctrl.FileHandler),
(r'/api/path/([^/]+)((/positions)|(/speeds))?', PathHandler),
(r'/api/home(/[xyzabcXYZABC]((/set)|(/clear))?)?', HomeHandler),
(r'/api/start', StartHandler),
height 12em
> select, > input:not([type=checkbox])
- min-width 13em
+ min-width 11em
> tt
min-width 15.25em
clear both
> *
- margin 0.25em
+ margin 0.25em 0.125em
select
- max-width 13em
+ max-width 11em
.progress
display inline-block
line-height 2em
border 1px solid #aaa
border-radius 3px
- width 327px
+ width 300px
vertical-align middle
text-align center