Phi: Initial draft for plugins and instruments
Gauge with ticks
This commit is contained in:
parent
62b7946a0a
commit
a9bd141153
7 changed files with 255 additions and 21 deletions
126
webgui/instruments/DualArcGauge.js
Normal file
126
webgui/instruments/DualArcGauge.js
Normal file
|
@ -0,0 +1,126 @@
|
|||
define([
|
||||
'jquery', 'knockout', 'text!./DualArcGauge.svg', 'sprintf'
|
||||
], function(jquery, ko, svgString, sprintf) {
|
||||
|
||||
function getXY(positionNorm, r) {
|
||||
var a = (120*positionNorm-60)/180*Math.PI;
|
||||
return {
|
||||
'x': 50+r*Math.sin(a),
|
||||
'y': 52-r*Math.cos(a)
|
||||
}
|
||||
}
|
||||
|
||||
function Tick( width, positionNorm, color ) {
|
||||
var self = this;
|
||||
|
||||
self.width = width;
|
||||
self.color = color;
|
||||
|
||||
var xy = getXY( positionNorm, 45 );
|
||||
self.getStartXY = xy.x.toString()+","+ xy.y.toString();
|
||||
|
||||
xy = getXY( positionNorm, 50 );
|
||||
self.getEndXY = xy.x.toString()+","+ xy.y.toString();
|
||||
}
|
||||
|
||||
function Marker( label, positionNorm, color ) {
|
||||
var self = this;
|
||||
|
||||
self.label = label;
|
||||
self.color = color;
|
||||
|
||||
var xy = getXY( positionNorm, 52 );
|
||||
self.getX = xy.x;
|
||||
self.getY = xy.y;
|
||||
|
||||
self.anchor = 'middle';
|
||||
if( positionNorm < 0.4 ) self.anchor = 'end';
|
||||
if( positionNorm > 0.6 ) self.anchor = 'start';
|
||||
}
|
||||
|
||||
function Arc( color, start, end ) {
|
||||
var self = this;
|
||||
self.color = color;
|
||||
|
||||
if( start == end ) {
|
||||
start -= 0.005;
|
||||
end += 0.005;
|
||||
}
|
||||
|
||||
var xy = getXY( start, 47.5 );
|
||||
self.getStartXY = xy.x.toString()+","+ xy.y.toString();
|
||||
|
||||
xy = getXY( end, 47.5 );
|
||||
self.getEndXY = xy.x.toString()+","+ xy.y.toString();
|
||||
}
|
||||
|
||||
function ViewModel(params) {
|
||||
var self = this;
|
||||
|
||||
self.config = {
|
||||
label : params.label || '',
|
||||
min : params.min || 0,
|
||||
max : params.max || 1,
|
||||
left : {
|
||||
value : params.left.value || 0,
|
||||
format : params.left.format || '%d',
|
||||
},
|
||||
right : {
|
||||
value : params.right.value || 0,
|
||||
format : params.right.format || '%d',
|
||||
},
|
||||
}
|
||||
|
||||
function getRotationNorm(value) {
|
||||
if (value < self.config.min)
|
||||
return 0;
|
||||
if (value > self.config.max)
|
||||
return 1;
|
||||
return (value - self.config.min) / (self.config.max - self.config.min);
|
||||
}
|
||||
|
||||
self.leftRotationNorm = ko.pureComputed(function() {
|
||||
return getRotationNorm(ko.utils.unwrapObservable(self.config.left.value));
|
||||
});
|
||||
|
||||
self.rightRotationNorm = ko.pureComputed(function() {
|
||||
return getRotationNorm(ko.utils.unwrapObservable(self.config.right.value));
|
||||
});
|
||||
|
||||
self.leftText = ko.pureComputed(function() {
|
||||
return sprintf.sprintf(self.config.left.format, ko.utils.unwrapObservable(self.config.left.value));
|
||||
});
|
||||
|
||||
self.rightText = ko.pureComputed(function() {
|
||||
return sprintf.sprintf(self.config.right.format, ko.utils.unwrapObservable(self.config.right.value));
|
||||
});
|
||||
|
||||
self.label = self.config.label;
|
||||
|
||||
self.markers = [];
|
||||
self.ticks = [];
|
||||
self.arcs = [];
|
||||
|
||||
for ( var pos in params.marker) {
|
||||
var m = params.marker[pos];
|
||||
self.markers.push( new Marker( pos, getRotationNorm(Number(pos)), m) );
|
||||
}
|
||||
|
||||
for ( var pos in params.ticks) {
|
||||
var t = params.ticks[pos];
|
||||
self.ticks.push( new Tick( t.width || 1, getRotationNorm(Number(pos)), t.color || 'white' ) );
|
||||
}
|
||||
|
||||
if( params.arcs ) params.arcs.forEach(function(arc) {
|
||||
var end = arc.end || arc.start;
|
||||
self.arcs.push( new Arc(arc.color,getRotationNorm(Number(arc.start)),getRotationNorm(Number(end))));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Return component definition
|
||||
return {
|
||||
viewModel : ViewModel,
|
||||
template : svgString
|
||||
};
|
||||
});
|
62
webgui/instruments/DualArcGauge.svg
Normal file
62
webgui/instruments/DualArcGauge.svg
Normal file
|
@ -0,0 +1,62 @@
|
|||
<!-- don't add the xml-declaration here -->
|
||||
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" class="dualarcgauge"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="-10 -10 120 55"
|
||||
preserveAspectRatio="xMinYMin meet">
|
||||
|
||||
<text class="dualarcgauge-label" x="50" y="35" stroke="black"
|
||||
font-size="5" text-anchor="middle" data-bind="text: label"></text>
|
||||
|
||||
<g data-bind="foreach: markers">
|
||||
<text class="dualarcgauge-marker"
|
||||
data-bind="attr: { x: getX, y: getY, 'text-anchor': anchor, 'fill': color }, text: label"
|
||||
font-size="5"></text>
|
||||
</g>
|
||||
|
||||
<g data-bind="foreach: arcs">
|
||||
<path class="dualarcgauge-scale-arc" stroke-linecap="butt"
|
||||
data-bind="attr: { stroke: color, d: 'M' + getStartXY + ' A 47.5 47.5 0 0 1 ' + getEndXY }"
|
||||
stroke-width="5" fill="none" />
|
||||
</g>
|
||||
|
||||
<g data-bind="foreach: ticks">
|
||||
<path class="dualarcgauge-scale-tick" stroke-linecap="butt"
|
||||
data-bind="attr: { stroke: color, 'stroke-width': width, d: 'M' + getStartXY + ' L ' + getEndXY }" fill="none" />
|
||||
</g>
|
||||
|
||||
<!-- Scale Outline -->
|
||||
<path class="dualarcgauge-scale-stroke"
|
||||
d="M11,29.5 a 45,45 0 0 1 78,0 L93.3,27 A 50,50 0 0 0 6.7,27 z"
|
||||
stroke="black" stroke-width="0.5" fill="none" />
|
||||
|
||||
<!-- Needle 1 -->
|
||||
<g
|
||||
data-bind="attr { transform: 'rotate('+ (rightRotationNorm()*120-60) +',50,52)' }">
|
||||
<path d="M45,25 l4.5,-8.66 v-10 h1 v10 l4.5,8.66z" stroke="black"
|
||||
stroke-width="0.5" fill="white" />
|
||||
<text x="50" y="23.7" stroke="none" fill="black" font-size="6"
|
||||
text-anchor="middle">R</text>
|
||||
</g>
|
||||
|
||||
<!-- Needle 2 -->
|
||||
<g
|
||||
data-bind="attr { transform: 'rotate('+ (leftRotationNorm()*120-60) +',50,52)' }">
|
||||
<path d="M45,16 l5,-8.66 l5,8.66z" stroke="black" stroke-width="0.5"
|
||||
fill="white" />
|
||||
<text x="50" y="14.7" stroke="none" fill="black" font-size="6"
|
||||
text-anchor="middle">L</text>
|
||||
</g>
|
||||
|
||||
<!-- Left Label -->
|
||||
<g class="dualarcgauge-value">
|
||||
<rect x="-9" y="-9" width="20" height="10" rx="2" ry="2" />
|
||||
<text x="10" y="-1" stroke="black" font-size="8" text-anchor="end"
|
||||
data-bind="text: leftText"></text>
|
||||
</g>
|
||||
|
||||
<!-- Right Label -->
|
||||
<g class="dualarcgauge-value">
|
||||
<rect x="89" y="-9" width="20" height="10" rx="2" ry="2" />
|
||||
<text x="108" y="-1" stroke="black" font-size="8" text-anchor="end"
|
||||
data-bind="text: rightText"></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
|
@ -13,7 +13,8 @@ require.config({
|
|||
flottime : '3rdparty/flot/jquery.flot.time',
|
||||
fgcommand : 'lib/fgcommand',
|
||||
props : 'lib/props2',
|
||||
sammy: '3rdparty/sammy-latest.min'
|
||||
sammy: '3rdparty/sammy-latest.min',
|
||||
aircraft: '../aircraft-dir',
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -135,6 +136,14 @@ require([
|
|||
return self;
|
||||
}
|
||||
|
||||
koObservable.fgPropertyPath = path;
|
||||
koObservable.fgBaseDispose = koObservable.dispose;
|
||||
koObservable.dispose = function() {
|
||||
if( this.fgPropertyPath ) {
|
||||
self.removeListener( this.fgPropertyPath, this );
|
||||
}
|
||||
this.fgBaseDispose.call(this);
|
||||
}
|
||||
listeners.push(koObservable);
|
||||
|
||||
if (1 == listeners.length) {
|
||||
|
@ -165,19 +174,21 @@ require([
|
|||
return self.props[prop];
|
||||
}
|
||||
|
||||
var p = (self.props[prop] = ko.pureComputed({
|
||||
read : target,
|
||||
write : function(newValue) {
|
||||
if (newValue == target())
|
||||
return (self.props[prop] = self.observedProperty( target, prop ));
|
||||
}
|
||||
|
||||
self.observedProperty = function( target, prop ) {
|
||||
var reply = ko.pureComputed({
|
||||
read: target,
|
||||
write: function(newValue) {
|
||||
if( newValue == target() )
|
||||
return;
|
||||
target(newValue);
|
||||
target.notifySubscribers(newValue);
|
||||
}
|
||||
}));
|
||||
|
||||
self.addListener(prop, p);
|
||||
|
||||
return p;
|
||||
});
|
||||
self.addListener(prop, reply);
|
||||
return reply;
|
||||
}
|
||||
|
||||
self.write = function(prop, value) {
|
||||
|
@ -186,6 +197,11 @@ require([
|
|||
console.log("can't write " + prop + ": unknown alias.");
|
||||
return;
|
||||
}
|
||||
|
||||
self.setPropertyValue(path,value);
|
||||
}
|
||||
|
||||
self.setPropertyValue = function(path, value) {
|
||||
this.ws.send(JSON.stringify({
|
||||
command : 'set',
|
||||
node : path,
|
||||
|
@ -212,6 +228,10 @@ require([
|
|||
ko.extenders.fgprop = function(target, prop) {
|
||||
return ko.utils.knockprops.get(target, prop);
|
||||
};
|
||||
|
||||
ko.extenders.observedProperty = function(target,prop) {
|
||||
return ko.utils.knockprops.observedProperty(target,prop);
|
||||
};
|
||||
|
||||
ko.extenders.fgPropertyGetSet = function(target,option) {
|
||||
|
||||
|
@ -440,6 +460,10 @@ require([
|
|||
ko.components.register('Stopwatch', {
|
||||
require : 'widgets/Stopwatch'
|
||||
});
|
||||
|
||||
ko.components.register('dualarcgauge', {
|
||||
require: 'instruments/DualArcGauge'
|
||||
})
|
||||
|
||||
ko.bindingHandlers.flotchart = {
|
||||
init : function(element, valueAccessor, allBindings) {
|
||||
|
|
|
@ -9,4 +9,5 @@
|
|||
click: $parent.selectTopic"></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="vtabs-content" data-bind="component: { name: selectedComponent }"></div>
|
||||
<div id="vtabs-content" data-bind="component: { name: selectedComponent }">
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
define([
|
||||
'knockout', 'text!./Aircraft.html', './SubtopicViewmodel'
|
||||
], function(ko, htmlString, SubtopicViewmodel) {
|
||||
'jquery', 'knockout', 'text!./Aircraft.html', './SubtopicViewmodel'
|
||||
], function(jquery, ko, htmlString, SubtopicViewmodel) {
|
||||
ko.components.register('Aircraft/Select', {
|
||||
require : 'topics/Aircraft/Select'
|
||||
});
|
||||
|
@ -21,11 +21,34 @@ define([
|
|||
require : 'topics/Aircraft/Panel'
|
||||
});
|
||||
|
||||
function Viewmodel(topics, prefix, params) {
|
||||
var self = this;
|
||||
SubtopicViewmodel.call(self, topics, prefix, params);
|
||||
|
||||
self.config = ko.observable({});
|
||||
|
||||
jquery.get('/aircraft-dir/Phi/config.json', null, function(config) {
|
||||
self.config(config);
|
||||
|
||||
if (config && config.plugins && config.plugins.Aircraft) {
|
||||
for ( var p in config.plugins.Aircraft) {
|
||||
var plugin = config.plugins.Aircraft[p];
|
||||
if (plugin.component && plugin.component.key && plugin.component.lib) {
|
||||
if (false == ko.components.isRegistered(plugin.component.key)) {
|
||||
ko.components.register(plugin.component.key, { require: plugin.component.lib });
|
||||
}
|
||||
}
|
||||
self.topics.push(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Return component definition
|
||||
return {
|
||||
viewModel : {
|
||||
createViewModel : function(params, componentInfo) {
|
||||
return new SubtopicViewmodel([
|
||||
return new Viewmodel([
|
||||
'Help', 'Mass & Balance', 'Checklists', 'Failures', 'Panel', 'Select'
|
||||
], "Aircraft", params);
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
define([
|
||||
'jquery', 'knockout', 'text!./Screenshot.html', 'kojqui/spinner'
|
||||
], function(jquery, ko, htmlString, fgcommand ) {
|
||||
], function(jquery, ko, htmlString ) {
|
||||
|
||||
function ViewModel(params) {
|
||||
var self = this;
|
||||
|
@ -18,11 +18,9 @@ define([
|
|||
if( id != self.updateId )
|
||||
return;
|
||||
self.imageUrl("/screenshot?type=jpg&t=" + Date.now());
|
||||
console.log(self.updateInterval(), self.imageUrl());
|
||||
|
||||
setTimeout( function() { self.update(id); }, self.updateInterval()*1000);
|
||||
};
|
||||
|
||||
|
||||
self.update(++self.updateId);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
function SubtopicViewModel(topics, prefix, params) {
|
||||
var self = this;
|
||||
|
||||
self.topics = topics;
|
||||
self.topics = ko.observableArray(topics);
|
||||
|
||||
self.selectedTopic = ko.observable();
|
||||
|
||||
|
@ -24,9 +24,9 @@
|
|||
self.selectedTopic(topic);
|
||||
}
|
||||
|
||||
var topic = (params && params.topic) ? ko.unwrap(params.topic) : self.topics[0];
|
||||
var topic = (params && params.topic) ? ko.unwrap(params.topic) : self.topics()[0];
|
||||
if( self.topics.indexOf(topic) == -1 )
|
||||
topic = self.topics[0];
|
||||
topic = self.topics()[0];
|
||||
self.selectTopic(topic);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue