|
@@ -143,6 +143,7 @@ var configuratorApp = (function(){
|
143
|
143
|
$config = $('#config_text pre'),
|
144
|
144
|
$config_adv = $('#config_adv_text pre'),
|
145
|
145
|
define_list = [[],[]],
|
|
146
|
+ define_section = {},
|
146
|
147
|
boards_list = {},
|
147
|
148
|
therms_list = {},
|
148
|
149
|
total_config_lines,
|
|
@@ -308,16 +309,21 @@ var configuratorApp = (function(){
|
308
|
309
|
/**
|
309
|
310
|
* Get all the unique define names
|
310
|
311
|
*/
|
311
|
|
- getDefinesFromText: function(txt) {
|
312
|
|
- var leave_out_defines = ['CONFIGURATION_H', 'CONFIGURATION_ADV_H', 'STRING_VERSION', 'STRING_URL', 'STRING_VERSION_CONFIG_H', 'STRING_CONFIG_H_AUTHOR', 'STRING_SPLASH_LINE1', 'STRING_SPLASH_LINE2'];
|
313
|
|
- // Get all the unique #define's and save them in an array
|
314
|
|
- var r, define_obj = {}, findDef = new RegExp('#define[ \\t]+(\\w+)', 'gm');
|
|
312
|
+ updateDefinesFromText: function(index, txt) {
|
|
313
|
+ var section = 'machine',
|
|
314
|
+ leave_out_defines = ['CONFIGURATION_H', 'CONFIGURATION_ADV_H', 'STRING_VERSION', 'STRING_URL', 'STRING_VERSION_CONFIG_H', 'STRING_CONFIG_H_AUTHOR', 'STRING_SPLASH_LINE1', 'STRING_SPLASH_LINE2'],
|
|
315
|
+ define_sect = {},
|
|
316
|
+ r, findDef = new RegExp('(@section|#define)[ \\t]+(\\w+)', 'gm');
|
315
|
317
|
while((r = findDef.exec(txt)) !== null) {
|
316
|
|
- if ($.inArray(r[1], leave_out_defines) < 0 && !(r[1] in define_obj))
|
317
|
|
- define_obj[r[1]] = null;
|
|
318
|
+ var name = r[2];
|
|
319
|
+ if (r[1] == '@section')
|
|
320
|
+ section = name;
|
|
321
|
+ else if ($.inArray(name, leave_out_defines) < 0 && !(name in define_sect))
|
|
322
|
+ define_sect[name] = section;
|
318
|
323
|
}
|
319
|
|
- this.log(Object.keys(define_obj), 2);
|
320
|
|
- return Object.keys(define_obj);
|
|
324
|
+ define_list[index] = Object.keys(define_sect);
|
|
325
|
+ $.extend(define_section, define_sect);
|
|
326
|
+ this.log(define_list[index], 2);
|
321
|
327
|
},
|
322
|
328
|
|
323
|
329
|
/**
|
|
@@ -327,24 +333,48 @@ var configuratorApp = (function(){
|
327
|
333
|
var e = adv ? 1 : 0, n = 0;
|
328
|
334
|
var fail_list = [];
|
329
|
335
|
$.each(define_list[e], function(i,name) {
|
330
|
|
- if (!$('#'+name).length) {
|
331
|
|
- var $ff = $('#more'),
|
332
|
|
- inf = self.getDefineInfo(name, adv);
|
|
336
|
+ var section = define_section[name];
|
|
337
|
+ if (section != 'hidden' && !$('#'+name).length) {
|
|
338
|
+ var inf = self.getDefineInfo(name, adv);
|
|
339
|
+
|
333
|
340
|
if (inf) {
|
334
|
|
- var $newlabel = $('<label>',{for:name}).text(name.toLabel());
|
|
341
|
+
|
|
342
|
+ var $ff = $('#'+section), $newfield,
|
|
343
|
+ $newlabel = $('<label>',{for:name,class:'added'}).text(name.toLabel());
|
|
344
|
+
|
335
|
345
|
// if (!(++n % 3))
|
336
|
346
|
$newlabel.addClass('newline');
|
337
|
347
|
|
338
|
|
- var $newfield;
|
339
|
|
- if (inf.options !== undefined) {
|
340
|
|
- $newfield = $('<select>'); //.addOptions(inf.options);
|
|
348
|
+ $ff.append($newlabel);
|
|
349
|
+
|
|
350
|
+ // Multiple fields?
|
|
351
|
+ if (inf.type == 'list') {
|
|
352
|
+ for (var i=0; i<inf.size; i++) {
|
|
353
|
+ var fieldname = i > 0 ? name+'-'+i : name;
|
|
354
|
+ $newfield = $('<input>',{type:'text',size:6,maxlength:10,id:fieldname,name:fieldname,class:'subitem added'}).prop({defineInfo:inf});
|
|
355
|
+ $ff.append($newfield);
|
|
356
|
+ }
|
341
|
357
|
}
|
342
|
358
|
else {
|
343
|
|
- $newfield = inf.type == 'switch' ? $('<input>',{type:'checkbox'}) : $('<input>',{type:'text',size:10,maxlength:40});
|
|
359
|
+ // Items with options, either toggle or select
|
|
360
|
+ // TODO: Radio buttons for other values
|
|
361
|
+ if (inf.options !== undefined) {
|
|
362
|
+ if (inf.type == 'toggle') {
|
|
363
|
+ $newfield = $('<input>',{type:'checkbox'});
|
|
364
|
+ }
|
|
365
|
+ else {
|
|
366
|
+ // Otherwise selectable
|
|
367
|
+ $newfield = $('<select>');
|
|
368
|
+ }
|
|
369
|
+ // ...Options added when field initialized
|
|
370
|
+ }
|
|
371
|
+ else {
|
|
372
|
+ $newfield = inf.type == 'switch' ? $('<input>',{type:'checkbox'}) : $('<input>',{type:'text',size:10,maxlength:40});
|
|
373
|
+ }
|
|
374
|
+ $newfield.attr({id:name,name:name,class:'added'}).prop({defineInfo:inf});
|
|
375
|
+ // Add the new field to the form
|
|
376
|
+ $ff.append($newfield);
|
344
|
377
|
}
|
345
|
|
- $newfield.attr({id:name,name:name}).prop({defineInfo:inf});
|
346
|
|
- // Add the new field to the form
|
347
|
|
- $ff.append($newlabel, $newfield);
|
348
|
378
|
}
|
349
|
379
|
else
|
350
|
380
|
fail_list.push(name);
|
|
@@ -410,10 +440,9 @@ var configuratorApp = (function(){
|
410
|
440
|
// When a config file loads defines might change
|
411
|
441
|
if (init_index != null) {
|
412
|
442
|
var adv = init_index == 1;
|
413
|
|
- define_list[init_index] = this.getDefinesFromText(txt);
|
414
|
|
- this.log(define_list[init_index], 2);
|
415
|
|
- this.purgeDefineInfo(adv);
|
416
|
|
- this.createFieldsForDefines(init_index);
|
|
443
|
+ this.purgeAddedFields(init_index);
|
|
444
|
+ this.updateDefinesFromText(init_index, txt);
|
|
445
|
+ this.createFieldsForDefines(adv);
|
417
|
446
|
this.refreshConfigForm(init_index);
|
418
|
447
|
this.activateDownloadLink(adv);
|
419
|
448
|
}
|
|
@@ -446,13 +475,14 @@ var configuratorApp = (function(){
|
446
|
475
|
});
|
447
|
476
|
|
448
|
477
|
// Get all 'switchable' class items and add a checkbox
|
449
|
|
- $form.find('.switchable').each(function(){
|
450
|
|
- $(this).after(
|
451
|
|
- $('<input>',{type:'checkbox',value:'1',class:'enabler'}).prop('checked',true)
|
452
|
|
- .attr('id',this.id + '-switch')
|
453
|
|
- .change(self.handleSwitch)
|
454
|
|
- );
|
455
|
|
- });
|
|
478
|
+ // $form.find('.switchable').each(function(){
|
|
479
|
+ // $(this).after(
|
|
480
|
+ // $('<input>',{type:'checkbox',value:'1',class:'enabler added'})
|
|
481
|
+ // .prop('checked',true)
|
|
482
|
+ // .attr('id',this.id + '-switch')
|
|
483
|
+ // .change(self.handleSwitch)
|
|
484
|
+ // );
|
|
485
|
+ // });
|
456
|
486
|
|
457
|
487
|
// Add options to the popup menus
|
458
|
488
|
// $('#SERIAL_PORT').addOptions([0,1,2,3,4,5,6,7]);
|
|
@@ -516,7 +546,7 @@ var configuratorApp = (function(){
|
516
|
546
|
/**
|
517
|
547
|
* Any manually-created form elements will remain
|
518
|
548
|
* where they are. Unknown defines (currently most)
|
519
|
|
- * are added to the "More..." tab for now.
|
|
549
|
+ * are added to tabs based on section
|
520
|
550
|
*
|
521
|
551
|
* Specific exceptions can be managed by applying
|
522
|
552
|
* classes to the associated form fields.
|
|
@@ -550,11 +580,7 @@ var configuratorApp = (function(){
|
550
|
580
|
if (inf == null)
|
551
|
581
|
inf = elm.defineInfo = this.getDefineInfo(name, adv);
|
552
|
582
|
|
553
|
|
- // Set options on the field if there are any
|
554
|
|
- if (inf.options !== undefined)
|
555
|
|
- $elm.html('').addOptions(inf.options);
|
556
|
|
-
|
557
|
|
- // Create a tooltip if there is one
|
|
583
|
+ // Create a tooltip on the label if there is one
|
558
|
584
|
if (inf.tooltip) {
|
559
|
585
|
var $tipme = $elm.prev('label');
|
560
|
586
|
if ($tipme.length) {
|
|
@@ -583,8 +609,34 @@ var configuratorApp = (function(){
|
583
|
609
|
}
|
584
|
610
|
}
|
585
|
611
|
|
586
|
|
- $elm.unbind('input change');
|
587
|
|
- $elm.on($elm.attr('type') == 'text' ? 'input' : 'change', this.handleChange);
|
|
612
|
+ // Make the element(s) respond to events
|
|
613
|
+ if (inf.type == 'list') {
|
|
614
|
+ // Multiple fields need to respond
|
|
615
|
+ for (var i=0; i<inf.size; i++) {
|
|
616
|
+ if (i > 0) $elm = $('#'+name+'-'+i);
|
|
617
|
+ $elm.unbind('input');
|
|
618
|
+ $elm.on('input', this.handleChange);
|
|
619
|
+ }
|
|
620
|
+ }
|
|
621
|
+ else {
|
|
622
|
+ var elmtype = $elm.attr('type');
|
|
623
|
+ // Set options on single fields if there are any
|
|
624
|
+ if (inf.options !== undefined && elmtype === undefined)
|
|
625
|
+ $elm.html('').addOptions(inf.options);
|
|
626
|
+ $elm.unbind('input change');
|
|
627
|
+ $elm.on(elmtype == 'text' ? 'input' : 'change', this.handleChange);
|
|
628
|
+ }
|
|
629
|
+
|
|
630
|
+ // Add an enabler checkbox if it needs one
|
|
631
|
+ if (inf.switchable && $('#'+name+'-switch').length == 0) {
|
|
632
|
+ // $elm = the last element added
|
|
633
|
+ $elm.after(
|
|
634
|
+ $('<input>',{type:'checkbox',value:'1',class:'enabler added'})
|
|
635
|
+ .prop('checked',self.defineIsEnabled(name))
|
|
636
|
+ .attr({id: name+'-switch'})
|
|
637
|
+ .change(self.handleSwitch)
|
|
638
|
+ );
|
|
639
|
+ }
|
588
|
640
|
|
589
|
641
|
// Set the field's initial value from the define
|
590
|
642
|
this.setFieldFromDefine(name);
|
|
@@ -592,17 +644,31 @@ var configuratorApp = (function(){
|
592
|
644
|
|
593
|
645
|
/**
|
594
|
646
|
* Handle any value field being changed
|
|
647
|
+ * this = the field
|
595
|
648
|
*/
|
596
|
649
|
handleChange: function() { self.updateDefineFromField(this.id); },
|
597
|
650
|
|
598
|
651
|
/**
|
599
|
652
|
* Handle a switch checkbox being changed
|
|
653
|
+ * this = the switch checkbox
|
600
|
654
|
*/
|
601
|
655
|
handleSwitch: function() {
|
602
|
|
- var $elm = $(this), $prev = $elm.prev();
|
603
|
|
- var on = $elm.prop('checked') || false;
|
604
|
|
- $prev.attr('disabled', !on);
|
605
|
|
- self.setDefineEnabled($prev[0].id, on);
|
|
656
|
+ var $elm = $(this),
|
|
657
|
+ name = $elm[0].id.replace(/-.+/,''),
|
|
658
|
+ inf = $('#'+name)[0].defineInfo,
|
|
659
|
+ on = $elm.prop('checked') || false;
|
|
660
|
+
|
|
661
|
+ self.setDefineEnabled(name, on);
|
|
662
|
+
|
|
663
|
+ if (inf.type == 'list') {
|
|
664
|
+ // Multiple fields?
|
|
665
|
+ for (var i=0; i<inf.size; i++) {
|
|
666
|
+ $('#'+name+(i?'-'+i:'')).attr('disabled', !on);
|
|
667
|
+ }
|
|
668
|
+ }
|
|
669
|
+ else {
|
|
670
|
+ $elm.prev().attr('disabled', !on);
|
|
671
|
+ }
|
606
|
672
|
},
|
607
|
673
|
|
608
|
674
|
/**
|
|
@@ -656,11 +722,15 @@ var configuratorApp = (function(){
|
656
|
722
|
*/
|
657
|
723
|
updateDefineFromField: function(name) {
|
658
|
724
|
this.log('updateDefineFromField:'+name,4);
|
|
725
|
+
|
|
726
|
+ // Drop the suffix on sub-fields
|
|
727
|
+ name = name.replace(/-\d+$/, '');
|
|
728
|
+
|
659
|
729
|
var $elm = $('#'+name), inf = $elm[0].defineInfo;
|
660
|
730
|
if (inf == null) return;
|
661
|
731
|
|
662
|
732
|
var isCheck = $elm.attr('type') == 'checkbox',
|
663
|
|
- val = isCheck ? $elm.prop('checked') : $elm.val();
|
|
733
|
+ val = isCheck ? $elm.prop('checked') : $elm.val().trim();
|
664
|
734
|
|
665
|
735
|
var newline;
|
666
|
736
|
switch(inf.type) {
|
|
@@ -668,12 +738,19 @@ var configuratorApp = (function(){
|
668
|
738
|
var slash = val ? '' : '//';
|
669
|
739
|
newline = inf.line.replace(inf.repl, '$1'+slash+'$3');
|
670
|
740
|
break;
|
|
741
|
+ case 'list':
|
671
|
742
|
case 'quoted':
|
672
|
743
|
case 'plain':
|
673
|
|
- if (isCheck)
|
674
|
|
- this.setMessage(name + ' should not be a checkbox!', 'error');
|
675
|
|
- else
|
676
|
|
- newline = inf.line.replace(inf.repl, '$1'+val.replace('$','\\$')+'$3');
|
|
744
|
+ if (isCheck) this.setMessage(name + ' should not be a checkbox!', 'error');
|
|
745
|
+ case 'toggle':
|
|
746
|
+ if (isCheck) {
|
|
747
|
+ val = val ? inf.options[1] : inf.options[0];
|
|
748
|
+ }
|
|
749
|
+ else {
|
|
750
|
+ if (inf.type == 'list')
|
|
751
|
+ for (var i=1; i<inf.size; i++) val += ', ' + $('#'+name+'-'+i).val().trim();
|
|
752
|
+ }
|
|
753
|
+ newline = inf.line.replace(inf.repl, '$1'+(''+val).replace('$','\\$')+'$3');
|
677
|
754
|
break;
|
678
|
755
|
}
|
679
|
756
|
this.setDefineLine(name, newline);
|
|
@@ -725,31 +802,40 @@ var configuratorApp = (function(){
|
725
|
802
|
* Set a form field to the current #define value in the config text
|
726
|
803
|
*/
|
727
|
804
|
setFieldFromDefine: function(name) {
|
728
|
|
- var $elm = $('#'+name), val = this.defineValue(name);
|
|
805
|
+ var $elm = $('#'+name), inf = $elm[0].defineInfo,
|
|
806
|
+ val = this.defineValue(name);
|
729
|
807
|
|
730
|
808
|
this.log('setFieldFromDefine:' + name + ' to ' + val, 2);
|
731
|
809
|
|
732
|
|
- // Set the field value
|
733
|
|
- $elm.attr('type') == 'checkbox' ? $elm.prop('checked', val) : $elm.val(''+val);
|
734
|
|
-
|
735
|
810
|
// If the item has a checkbox then set enabled state too
|
736
|
|
- var $cb = $('#'+name+'-switch');
|
|
811
|
+ var $cb = $('#'+name+'-switch'), on = true;
|
737
|
812
|
if ($cb.length) {
|
738
|
|
- var on = self.defineIsEnabled(name);
|
|
813
|
+ on = self.defineIsEnabled(name);
|
|
814
|
+ $cb.prop('checked', on);
|
|
815
|
+ }
|
|
816
|
+
|
|
817
|
+ if (inf.type == 'list') {
|
|
818
|
+ $.each(val.split(','),function(i,v){
|
|
819
|
+ var $e = i > 0 ? $('#'+name+'-'+i) : $elm;
|
|
820
|
+ $e.val(v.trim());
|
|
821
|
+ $e.attr('disabled', !on);
|
|
822
|
+ });
|
|
823
|
+ }
|
|
824
|
+ else {
|
|
825
|
+ if (inf.type == 'toggle') val = val == inf.options[1];
|
|
826
|
+ $elm.attr('type') == 'checkbox' ? $elm.prop('checked', val) : $elm.val(''+val);
|
739
|
827
|
$elm.attr('disabled', !on); // enable/disable the form field (could also dim it)
|
740
|
|
- $cb.prop('checked', on); // check/uncheck the checkbox
|
741
|
828
|
}
|
742
|
829
|
},
|
743
|
830
|
|
744
|
831
|
/**
|
745
|
|
- * Purge #define information for one of the config files
|
|
832
|
+ * Purge added fields and all their define info
|
746
|
833
|
*/
|
747
|
|
- purgeDefineInfo: function(adv) {
|
748
|
|
- if (adv === undefined) adv = false;
|
749
|
|
- $('[name]').each(function() {
|
750
|
|
- var inf = this.defineInfo;
|
751
|
|
- if (inf && adv === inf.adv) $(this).removeProp('defineInfo');
|
|
834
|
+ purgeAddedFields: function(index) {
|
|
835
|
+ $.each(define_list[index], function(){
|
|
836
|
+ $('#'+this + ",[id^='"+this+"-'],label[for='"+this+"']").filter('.added').remove();
|
752
|
837
|
});
|
|
838
|
+ define_list[index] = [];
|
753
|
839
|
},
|
754
|
840
|
|
755
|
841
|
/**
|
|
@@ -805,6 +891,7 @@ var configuratorApp = (function(){
|
805
|
891
|
line: result[0],
|
806
|
892
|
pre: result[1] === undefined ? '' : result[1].replace('//',''),
|
807
|
893
|
define: result[2],
|
|
894
|
+ size: result[3].split(',').length,
|
808
|
895
|
post: result[4] === undefined ? '' : result[4]
|
809
|
896
|
});
|
810
|
897
|
info.regex = new RegExp('([ \\t]*//)?[ \\t]*' + info.define.regEsc() + '\{([^\}]*)\}' + info.post.regEsc(), 'm');
|
|
@@ -837,6 +924,10 @@ var configuratorApp = (function(){
|
837
|
924
|
define: result[2],
|
838
|
925
|
post: result[4] === undefined ? '' : result[4]
|
839
|
926
|
});
|
|
927
|
+ if (result[3].match(/false|true/)) {
|
|
928
|
+ info.type = 'toggle';
|
|
929
|
+ info.options = ['false','true'];
|
|
930
|
+ }
|
840
|
931
|
info.regex = new RegExp('([ \\t]*//)?[ \\t]*' + info.define.regEsc() + '(\\S*)' + info.post.regEsc(), 'm');
|
841
|
932
|
info.repl = new RegExp('(([ \\t]*//)?[ \\t]*' + info.define.regEsc() + ')\\S*(' + info.post.regEsc() + ')', 'm');
|
842
|
933
|
}
|
|
@@ -854,31 +945,41 @@ var configuratorApp = (function(){
|
854
|
945
|
|
855
|
946
|
// Get all the comments immediately before the item
|
856
|
947
|
var r, s;
|
857
|
|
- findDef = new RegExp('(([ \\t]*(//|#)[^\n]+\n){1,4})([ \\t]*\n){0,1}' + info.line.regEsc(), 'g');
|
|
948
|
+ findDef = new RegExp('(([ \\t]*(//|#)[^\n]+\n){1,4})([ \\t]*\n)?' + info.line.regEsc(), 'g');
|
858
|
949
|
if (r = findDef.exec(txt)) {
|
|
950
|
+ // Get the text of the found comments
|
859
|
951
|
findDef = new RegExp('^[ \\t]*//+[ \\t]*(.*)[ \\t]*$', 'gm');
|
860
|
952
|
while((s = findDef.exec(r[1])) !== null) {
|
861
|
|
- if (s[1].match(/^#define[ \\t]/) != null) {
|
862
|
|
- tooltip = '';
|
863
|
|
- break;
|
864
|
|
- }
|
865
|
|
- // JSON data? Save as select options
|
866
|
|
- if (s[1].match(/:[\[{]/) != null) {
|
867
|
|
- // TODO
|
868
|
|
- // :[1-6] = value limits
|
869
|
|
- eval('info.options = ' + s[1].substr(1));
|
870
|
|
- }
|
871
|
|
- else {
|
872
|
|
- // Other lines added to the tooltip
|
873
|
|
- tooltip += ' ' + s[1] + '\n';
|
|
953
|
+ var tip = s[1].replace(/[ \\t]*(={5,}|@section[ \\t]+\w+)[ \\t]*/g, '');
|
|
954
|
+ if (tip.length) {
|
|
955
|
+ if (tip.match(/^#define[ \\t]/) != null) {
|
|
956
|
+ tooltip = '';
|
|
957
|
+ break;
|
|
958
|
+ }
|
|
959
|
+ // JSON data? Save as select options
|
|
960
|
+ if (!info.options && tip.match(/:[\[{]/) != null) {
|
|
961
|
+ // TODO
|
|
962
|
+ // :[1-6] = value limits
|
|
963
|
+ var o; eval('o=' + tip.substr(1));
|
|
964
|
+ info.options = o;
|
|
965
|
+ if (Object.prototype.toString.call(o) == "[object Array]" && o.length == 2 && !eval(''+o[0]))
|
|
966
|
+ info.type = 'toggle';
|
|
967
|
+ }
|
|
968
|
+ else {
|
|
969
|
+ // Other lines added to the tooltip
|
|
970
|
+ tooltip += ' ' + tip + '\n';
|
|
971
|
+ }
|
874
|
972
|
}
|
875
|
973
|
}
|
876
|
974
|
}
|
877
|
975
|
|
878
|
|
- findDef = new RegExp('^'+name); // To strip the name from the start
|
|
976
|
+
|
|
977
|
+ // Add .tooltip and .lineNum properties to the info
|
|
978
|
+ findDef = new RegExp('^'+name); // Strip the name from the tooltip
|
879
|
979
|
$.extend(info, {
|
880
|
980
|
tooltip: '<strong>'+name+'</strong> '+tooltip.trim().replace(findDef,'').toHTML(),
|
881
|
|
- lineNum: this.getLineNumberOfText(info.line, txt)
|
|
981
|
+ lineNum: this.getLineNumberOfText(info.line, txt),
|
|
982
|
+ switchable: (info.type != 'switch' && info.line.match(/^[ \t]*\/\//)) || false // Disabled? Mark as "switchable"
|
882
|
983
|
});
|
883
|
984
|
}
|
884
|
985
|
else
|