diff --git a/behaviors/fin-hypergrid-behavior-default.html b/behaviors/fin-hypergrid-behavior-default.html index 4d658e42b..248502f20 100644 --- a/behaviors/fin-hypergrid-behavior-default.html +++ b/behaviors/fin-hypergrid-behavior-default.html @@ -321,6 +321,18 @@ return 'center'; }, + //answers the default col alignment for the fixed column data area of the grid + //
TODO:provide uniform mechanism for the fixed areas like this + getFixedColumnAlignment: function( /* x */ ) { + return this.constants.fixedColumnAlign; + }, + + + //answers the default row alignment for the fixed row data area of the grid + //
TODO:provide uniform mechanism for the fixed areas like this + getFixedRowAlignment: function( /* x */ ) { + return this.constants.fixedRowAlign; + }, //this is called by OFGrid when a fixed row cell is clicked //
see DefaultGridBehavior.delegateClick() below //
this is where we can hook in external data manipulation such as linking, diff --git a/behaviors/fin-hypergrid-behavior-qtree.html b/behaviors/fin-hypergrid-behavior-qtree.html new file mode 100644 index 000000000..fbee942fa --- /dev/null +++ b/behaviors/fin-hypergrid-behavior-qtree.html @@ -0,0 +1,363 @@ + + + + + + diff --git a/demo.html b/demo.html index 0d568cf4b..c8413bf3a 100644 --- a/demo.html +++ b/demo.html @@ -119,17 +119,18 @@ - + In Memory Default JSON Q + Q Tree Game Of Life - +
@@ -204,6 +205,18 @@

To point this example to your data

+
+
+

fin-hypergrid-behavior-qtree

This element is a custom Polymer web component that demonstrates a more complex interface to Q/KDB+ by kx systems. In order for this to work you need to run the provided t.q script found in the q directory of this project. This example shows the powerfull dynamic analytic capabilities of an external data engine. This example Q script was based on code and a paper written by Steven Apter. +
+ +
+ + + +
+
+

fin-hypergrid-behavior-gol

This element is another custom Polymer web component grid behavior showing Conway's Game of Life. The performance difference in the javascript execution environment between various browsers is very apparent with this example. For the best performance try resizing your browser window to the grid x by y size (75 X 45)
@@ -304,18 +317,18 @@

fin-hypergrid-behavior-gol

This element is another custom Polymer web c d: 'simpleCellRenderer' }; - cellProvider.getCell = function(config) { - var x = config.x; - var renderer = cellProvider.cellCache[typeRendererMap[qModel.block.headers[x + 1][1]]]; - renderer = renderer || cellProvider.cellCache.simpleCellRenderer; - if (x === 11) { - renderer = cellProvider.cellCache.sliderCellRenderer; - } else if (x === 13) { - renderer = cellProvider.cellCache.sparkbarCellRenderer; - } - renderer.config = config; - return renderer; - }; + // cellProvider.getCell = function(config) { + // var x = config.x; + // var renderer = cellProvider.cellCache[typeRendererMap[qModel.block.headers[x + 1][1]]]; + // renderer = renderer || cellProvider.cellCache.simpleCellRenderer; + // if (x === 11) { + // renderer = cellProvider.cellCache.sliderCellRenderer; + // } else if (x === 13) { + // renderer = cellProvider.cellCache.sparkbarCellRenderer; + // } + // renderer.config = config; + // return renderer; + // }; }); })(); diff --git a/fin-hypergrid-cell-provider.html b/fin-hypergrid-cell-provider.html index 361931faf..cc6c3ffd9 100644 --- a/fin-hypergrid-cell-provider.html +++ b/fin-hypergrid-cell-provider.html @@ -209,6 +209,28 @@ ctx.stroke(); }, + //simple implementation of a tree cell + treeCellRenderer: function(gc, x, y, width, height) { + var val = this.config.value.data; + var indent = this.config.value.indent; + var icon = this.config.value.icon; + + if (!val || !val.length) { + return; + } + var valignOffset = Math.ceil(height / 2); + + //fill background only if our bgColor is populated or we are a selected cell + if (this.config.bgColor || this.config.isSelected) { + gc.fillStyle = this.config.isSelected ? this.config.bgSelColor : this.config.bgColor; + gc.fillRect(x, y, width, height); + } + + gc.fillStyle = this.config.isSelected ? this.config.fgSelColor : this.config.fgColor; + gc.fillText(icon + val, x + indent, y + valignOffset); + + }, + //default cellRenderers are initialized here. you can augment the visible on your cellProvider instance: field ```myCellProviderInstance.cellCache.myCellRendererName = myCellRenderer``` initializeCells: function() { this.cellCache.simpleCellRenderer = { @@ -223,6 +245,9 @@ this.cellCache.sparklineCellRenderer = { paint: this.paintSparkline }; + this.cellCache.treeCellRenderer = { + paint: this.treeCellRenderer + }; }, }); diff --git a/fin-hypergrid-renderer.html b/fin-hypergrid-renderer.html index 423fecf6f..209077912 100644 --- a/fin-hypergrid-renderer.html +++ b/fin-hypergrid-renderer.html @@ -528,11 +528,12 @@ for (var r = 0; r < numRows; r++) { var height = this.getFixedRowHeight(r); + var align = behavior.getFixedRowAlignment(r); var value = behavior.getFixedRowValue(c + scrollLeft, r); //translatedX allows us to reorder columns var translatedX = behavior.translateColumnIndex(c + scrollLeft); - var cell = cellProvider.getFixedRowCell(cellConfig(translatedX, r, value, fgColor, bgColor, fgSelColor, bgSelColor, font, isSelected, halign, hoffset, voffset)); + var cell = cellProvider.getFixedRowCell(cellConfig(translatedX, r, value, fgColor, bgColor, fgSelColor, bgSelColor, font, isSelected, align, hoffset, voffset)); cell.paint(ctx, x, y, width, height); y = y + height; } @@ -556,13 +557,14 @@ var fgSelColor = this.resolveProperty('fixedColumnFGSelColor'); var bgSelColor = this.resolveProperty('fixedColumnBGSelColor'); - var halign = constants.fixedColumnAlign; + var scrollTop = this.getScrollTop(); var cellProvider = this.getGrid().getCellProvider(); var viewHeight = this.getBounds().height(); for (var c = 0; c < numColumns; c++) { var width = this.getFixedColumnWidth(c); + var align = behavior.getFixedColumnAlignment(c); var y = offsetY; ctx.fillStyle = bgColor; @@ -575,7 +577,7 @@ break; } var value = behavior.getFixedColumnValue(c, r + scrollTop); - var cell = cellProvider.getFixedColumnCell(cellConfig(c, r + scrollTop, value, fgColor, bgColor, fgSelColor, bgSelColor, font, isSelected, halign, hoffset, voffset)); + var cell = cellProvider.getFixedColumnCell(cellConfig(c, r + scrollTop, value, fgColor, bgColor, fgSelColor, bgSelColor, font, isSelected, align, hoffset, voffset)); cell.paint(ctx, x, y, width, height); y = y + height; } diff --git a/fin-hypergrid.html b/fin-hypergrid.html index ac863539e..a17eb6371 100644 --- a/fin-hypergrid.html +++ b/fin-hypergrid.html @@ -33,6 +33,7 @@ + diff --git a/fin-hypergrid.min.html b/fin-hypergrid.min.html index a9d476dd7..68d1069c9 100644 --- a/fin-hypergrid.min.html +++ b/fin-hypergrid.min.html @@ -20,4 +20,4 @@ @group OpenFin hypergrid @element fin-hypergrid @homepage http://github.com/openfin/fin-hypergrid ---> \ No newline at end of file +--> \ No newline at end of file diff --git a/fin-hypergrid.pre.html b/fin-hypergrid.pre.html index 450ec9157..3943746aa 100644 --- a/fin-hypergrid.pre.html +++ b/fin-hypergrid.pre.html @@ -33,6 +33,7 @@ + diff --git a/q/index.html b/q/index.html new file mode 100644 index 000000000..e61bcb612 --- /dev/null +++ b/q/index.html @@ -0,0 +1,84 @@ + + + + + + diff --git a/q/t.q b/q/t.q new file mode 100644 index 000000000..a2fb5b5f9 --- /dev/null +++ b/q/t.q @@ -0,0 +1,351 @@ +\e 1 +\p 12345 +\P 14 + +// treetable + +\d .tt + +/ construct treetable +cons:{[t;g;p;a;s;h]cons_[csub[t]g,h;g;p;a;s]h} + +cons_:{[t;g;p;a;s;h] + d:dat[t;g;p;rollups[t]a]h; + d:1!(0!d)tsort[d]s; + z:get d;z_:ctl[d;g]p; + (z;z_)} + +/ column subset +csub:{[t;f]?[t;();0b;f!f]} + +/ block of rows +rows:{[r;v]take[v]. r`start`end} +take:{[v;s;e]$[s>=count v;0#v;((1+e-s)&count z)#z:s _ v]} + +/ data table +dat:{[t;g;p;a;h] + z:1!`n_ xasc root[t;g;a]block[t;g;a]/visible p; + key[z]!flip h!get[z]h} + +/ control table +ctl:{[t;g;p] + c:([]n_:key[t]`n_;l_:level t;e_:isleaf[t]g;o_:isopen[t]p); + update p_:.tt.parent n_,h_:e_{$[x;`;last y]}'n_ from c} + +/ predicates +isopen:{[t;p](0!p)[`v](get each key[p]`n)?key[t]`n_} +isleaf:{[t;g]level[t]>count g} + +/ level of each record +level:{[t]count each key[t]`n_} + +/ visible paths +visible:{[p] + q:parent n:exec n from p; + k:(reverse q scan)each til count q; + n where all each(exec v from p)k} + +/ path-list -> parent-vector +parent:{[n]n?-1_'n} + +/ instruction -> constraint +constraint:{[p]flip(=;key p;flip enlist get p)} + +/ construct root block +root:{[t;g;a](`n_,g)xcols node_[g;`]flip enlist each?[t;();();@[a;g;:;{`},'g]]} + +/ construct a block = node or leaf +block:{[t;g;a;r;p] + f:$[g~key p;leaf;node g(`,g)?last key p]; + r,(`n_,g)xcols f[t;g;a]p} + +/ construct node block +node:{[b;t;g;a;p] + c:constraint p; + a[h]:first,'h:(i:g?b)#g; + a[h]:nul,'h:(1+i)_g; + node_[g;b]get?[t;c;enlist[b]!enlist b;a]} + +/ compute n_ for node block +node_:{[g;b;t] + n:$[null[b]|not count g;enlist 0#`;(1+g?b)#/:flip flip[t]g]; + ![t;();0b;enlist[`n_]!2 enlist/n]} + +/ construct leaf block +leaf:{[t;g;a;p] + c:constraint p; + a:last each a; + a[g]:g; + leaf_[g]0!?[t;c;0b;a]} + +/ compute n_ for leaf block +leaf_:{[g;t] + i:`$string til count t; + n:$[count g;flip[flip[t]g],'i;flip enlist i]; + ![t;();0b;enlist[`n_]!2 enlist/n]} + +/ keep valid paths +paths:{[p;g] + n:key each exec n from p; + i:where til[count g]{(count[y]#x)~y}/:g?/:n; + 1!(0!p)i} + +/ open/close to group (h=` -> open to leaves) +opento:{[t;g;h] + k:(1+til count k)#\:k:(g?h)#g; + n:enlist(0#`)!0#`; + f:{y,z!/:distinct flip flip[x]z}; + m:distinct n,raze f[t;n]each k; + ([n:m]v:count[m]#1b)} + +/ open/close at a node +at:{[b;p;g;n]p,([n:enlist(count[n]#g)!n,()]v:enlist b)} + +/ treetable sort +tsort:{[t;o] + n:exec n_ from t; + i:children[parent n]except enlist(); + j:msort[0!t;key o;(`a`d!(iasc;idesc))get o]each i; + n?pmesh over n j} + +/ parent-vector -> child-list +children:{[p]@[(2+max p)#enlist();first[p],1+1_p;,;til count p]} + +/ multi-sort +msort:{[t;c;o;i]i{x y z x}/[til count i;o;flip[t i]c]} + +/ mesh nest of paths +pmesh:{i:1+x?-1_first y;(i#x),y,i _ x} + +/ first if 1=count else null (for syms, non-summable nums) +nul:{first$[1=count distinct x,();x;0#x]} + +/ discard invalid paths +valid:{[p;g] + n:key each exec n from p; + i:where til[count g]{(count[y]#x)~y}/:g?/:n; + 1!(0!p)i} + +/ cast <- type +qtype:{exec c!t from meta x} + +/ default rollups +rollups:{[t;a]@[a;k;:;((.tt.nul;sum)qtype[t][k]in"HIJEFhijef"),'k:cols[t]except key a]} + +\d . + +// websocket communications + +$[.z.K<3.3; + [.z.pc:{[w]if[w=WS;WS::0]}; + .z.po:{[w]WS::.z.w;.js.set()!()}]; + [.z.wc:{[w]if[w=WS;WS::0]}; + .z.wo:{WS::.z.w;.js.set()!()}]]; + +.z.ws:{.js.snd .js.exe .js.sym .j.k x} + +/ entry points + +.js.node:{[d]$[0=count n:d`node;d;count[Z_]=r:Z_[`n_]?n;d;[`P set .tt.at[not Z_[`o_]r;P;G]n;.js.set d]]} +.js.sorts:{[d]`S set d[`cols]!d`sorts;i:.tt.tsort[Z,'Z_]S;Z@:i;Z_@:i;.js.ret d} +.js.groups:{[d]`G set d`cols;`P set .tt.valid[P]G;.js.set d} +.js.cols:{[d]`H set d`cols;.js.set d} +.js.get:{[d]`R set`start`end!"j"$d`start`end;.js.ret d} + +/ utilities + +.js.snd:{neg[WS].j.j x} +.js.sym:{$[(t:abs type x)in 0 99h;.z.s each x;10=t;`$x;x]} +.js.exe:{.js[x`fn]x} +.js.upd:{.js.snd .js.set()!()} +.js.set:{`Z`Z_ set'.tt.cons[T;G;P;A;S]H;.js.ret x} +.js.sub:{[z]flip each(1#;1_)@\:.tt.rows[R]z} +.js.obj:{`Z`Z_`G`G_`H`H_`Q`S`R`N!(.js.sub Z;.js.sub Z_;G;where["S"=q]except G;H;cols[T]except H;q:.tt.qtype T;S;R;count Z)} +.js.ret:{x,.js.obj[]} + +// globals + +/ group by +G:0#` + +/ visible order +H::cols[T]except G + +/ rollups +A:()!() + +/ updates (update, append, delete) +U:(1#sum)!enlist`u`a`d!({x+y-z};+;-) + +/ instruction state +P:([n:enlist(0#`)!0#`]v:enlist 1b) + +/ rows -> gui +R:`start`end!0 100 + +/ sorts (a,d) +S:()!() + +// example + +holdingId:`abcde`bcdef`cdefgh`defgh`efghi`fghij`ghijk +symbol:`msft`amat`csco`intc`yhoo`aapl +trader:`chico`harpo`groucho`zeppo`moe`larry`curly`shemp`abbott`costello +sector:`energy`materials`industrials`financials`healthcare`utilities`infotech +strategy:`statarb`pairs`mergerarb`house`chart`indexarb + +n:100000 +T:1!([] + tradeId:til n; + holdingId:n?holdingId; + symbol:n?symbol; + sector:n?sector; + trader:n?trader; + strategy:n?strategy; + time:09:30:00.0+n?23000000; + price:50+.23*n?400; + quantity:(100*10+n?20)-2000; + date:2000.01.01+asc n?365; + price1:50+.23*n?400; + amount1:n?1.0; + price2:50+.23*n?400; + amount2:(20*til n)_(n*20)?100; + date2:2000.01.01+asc n?365; + price3:50+.23*n?400; + amount3:(20*til n)_(n*20)?100; + date3:2000.01.01+asc n?365; + price4:50+.23*n?400; + amount4:100*10+n?20; + date4:2000.01.01+asc n?365; + amount5:100*10+n?20) + +G:`sector`trader`strategy +H:`symbol`price`quantity + +.js.set()!(); + +\ + +/ change grouping + +m:update trader:`zelda,price:price+1,quantity:quantity+10 from 1!20#0!select tradeId,trader,price,quantity from T where sector=`financials,trader=`abbott,strategy=`pairs +m:update tradeId:100000+til 10 from m where i<10 + +\ + +.js.exe`id`fn`node!(`;`node;1#`financials) +.js.exe`id`fn`node!(`;`node;`financials`abbott) + +t:T + +update trader:`foo from `T where sector=`financials,trader=`abbott,strategy=`pairs + +\ + + +.js.set()!(); + +.js.exe`id`fn`node!(`;`node;1#`financials) +.js.exe`id`fn`node!(`;`node;`financials`harpo) +.js.exe`id`fn`node!(`;`node;`financials`harpo`statarb) + +/ update + +j:3#exec i from T where sector=`financials,trader=`harpo,strategy<>`statarb +o:1!select tradeId,price,quantity,price3,symbol from T where i in j +update price:price+1,quantity:quantity+10,price3:price+5,symbol:`AARRGGH from`T where i in j +n:1!select tradeId,price,quantity,price3,symbol from T where i in j + +t:T +z:Z;z_:Z_ +g:t[key n;G] +p:z_[`p_]\'[z_[`n_]?g] +c:cols[n]inter cols z +a:?[n;();0b;c!c] +b:?[o;();0b;c!c] +u:U[first each .tt.rollups[a;A]c]`u +b:null u +d:c where b +f:{[d;g]1!?[T;G(=;;)'enlist each g;0b;d!d]} +t:raze f[`tradeId,G,c,key S]each g +`z`z_ set'.tt.cons[t;G;P;A;S]d +Z[Z_[`n_]?z_`n_;d]:z[::;d] + +/ w/ u.u +c@:where not b +c@:where not b +u@:where not b +a:?[n;();0b;c!c] +b:?[o;();0b;c!c] +f:{[c;u;z;p;a;b]z[p;c]:flip get{[u;z;a;b]u[z;a]b}'[u;z[p]c;a]b;z} +z:f[c;u]/[Z;p;a;b] + +/ append + +z:Z;z_:Z_ +q:select from T where i in j +q:update tradeId:99999+1+til[count j]from q +`T upsert q +g:T[key q;G] +p:z_[`p_]\'[z_[`n_]?g] +c:cols[z]inter cols a:get q +u:U[first each .tt.rollups[a;A]c]`a +b:null u +d:c where b +f:{[d;g]1!?[T;G(=;;)'enlist each g;0b;d!d]} +t:raze f[`tradeId,G,c,key S]each g +h:{[g]select from P where n in raze g{y!count[y]#x}/:\:til[1+count G]#\:G} +`z`z_ set'.tt.cons[t;G;P;A;S]d +Z[Z_[`n_]?z_`n_;d]:z[::;d] + +/ w/ u.a +c@:where not b +u@:where not b +a:?[q;();0b;c!c] +f:{[c;u;z;p;a]z[p;c]:flip get{[u;z;a]u[z]a}'[u;z[p]c]a;z} +z:f[c;u]/[Z;p;a] + +/ delete + +q:select from T where i in j +g:T[key q;G] +delete from `T where i in j +p:z_[`p_]\'[z_[`n_]?g] +c:cols[z]inter cols a:get q +u:U[first each .tt.rollups[a;A]c]`d +b:null u +d:c where b +f:{[d;g]1!?[T;G(=;;)'enlist each g;0b;d!d]} +t:raze f[`tradeId,G,c,key S]each g +`z`z_ set'.tt.cons[t;G;P;A;S]d +Z[Z_[`n_]?z_`n_;d]:z[::;d] + +/ w/ u.d +c@:where not b +u@:where not b +a:?[q;();0b;c!c] +f:{[c;u;z;p;a]z[p;c]:flip get{[u;z;a]u[z]a}'[u;z[p]c]a;z} +z:f[c;u]/[Z;p;a] + +\ + +cells:{[n] + f:{z;where 0=floor x?1%y}; + r:distinct f[count T;.0001]each til n; + c:c f[count c:1_cols T;.3]each til count r; + diffs[r]c} + +diffs:{[r;c](r xfrc[incr]'c;r xfrc[{y}]'c)} +xfrc:{[f;r;c]key[T][r]!flip c!c f'(0!T)[r]c} +incr:{[c;d]$[c in key`.;count[d]?get c;d+1]} + +\t .js.exe`id`fn`node!(`;`node;1#`financials) ;Z1:Z,'Z_; P1:P +\t .js.exe`id`fn`node!(`;`node;`financials`harpo) ;Z2:Z,'Z_; P2:P +\t .js.exe`id`fn`node!(`;`node;`financials`harpo`statarb) ;Z3:Z,'Z_; P3:P +\t .js.exe`id`fn`node!(`;`node;1#`financials) ;Z4:Z,'Z_; P4:P +\t .js.exe`id`fn`node!(`;`node;1#`financials) ;Z5:Z,'Z_; P5:P +\t .js.exe`id`fn`cols`sorts!(`;`sorts;`quantity`price;`a`a) ;Z6:Z,'Z_; +\t .js.exe`id`fn`cols!(`;`groups;`sector`strategy) ;Z7:Z,'Z_; +\t .js.exe`id`fn`cols!(`;`cols;reverse H) ;Z8:Z,'Z_; +\t .js.exe`id`fn`start`end!(`;`set;5;120) ;Z9:Z,'Z_; +