22// Distributed under the terms of the Modified BSD License.
33
44import {
5- DOMWidgetModel , DOMWidgetView , ISerializers
5+ DOMWidgetModel , DOMWidgetView , ISerializers , Dict
66} from '@jupyter-widgets/base' ;
77
88import {
@@ -33,19 +33,61 @@ class CanvasModel extends DOMWidgetModel {
3333 initialize ( attributes : any , options : any ) {
3434 super . initialize ( attributes , options ) ;
3535
36- this . commandsCache = [ ] ;
36+ this . canvas = document . createElement ( 'canvas' ) ;
37+ this . ctx = this . canvas . getContext ( '2d' ) ;
3738
38- this . on ( 'msg:custom' , ( command ) => {
39- if ( command instanceof Array ) {
40- this . commandsCache = this . commandsCache . concat ( command ) ;
41- } else {
42- this . commandsCache . push ( command ) ;
43- }
39+ this . resizeCanvas ( ) ;
40+
41+ this . on ( 'change:size' , this . resizeCanvas . bind ( this ) ) ;
42+ this . on ( 'msg:custom' , this . onCommand . bind ( this ) ) ;
43+ }
44+
45+ private onCommand ( command : any ) {
46+ this . processCommand ( command ) ;
47+
48+ this . forEachView ( ( view : CanvasView ) => {
49+ view . updateCanvas ( ) ;
4450 } ) ;
4551 }
4652
47- cleanCache ( command : any ) {
48- this . commandsCache = this . commandsCache . slice ( this . commandsCache . indexOf ( command ) + 1 ) ;
53+ private processCommand ( command : any ) {
54+ if ( command instanceof Array ) {
55+ for ( const subcommand of command ) {
56+ this . processCommand ( subcommand ) ;
57+ }
58+ return ;
59+ }
60+
61+ if ( command . name == 'set' ) {
62+ this . ctx [ command . attr ] = command . value ;
63+ return ;
64+ }
65+
66+ if ( command . name == 'clear' ) {
67+ this . forEachView ( ( view : CanvasView ) => {
68+ view . clear ( ) ;
69+ } ) ;
70+ this . ctx . clearRect ( 0 , 0 , this . canvas . width , this . canvas . height ) ;
71+
72+ return ;
73+ }
74+
75+ this . ctx [ command . name ] ( ...command . args ) ;
76+ }
77+
78+ private forEachView ( callback : ( view : CanvasView ) => void ) {
79+ for ( const view_id in this . views ) {
80+ this . views [ view_id ] . then ( ( view : CanvasView ) => {
81+ callback ( view ) ;
82+ } ) ;
83+ }
84+ }
85+
86+ private resizeCanvas ( ) {
87+ const size = this . get ( 'size' ) ;
88+
89+ this . canvas . setAttribute ( 'width' , size [ 0 ] ) ;
90+ this . canvas . setAttribute ( 'height' , size [ 1 ] ) ;
4991 }
5092
5193 static model_name = 'CanvasModel' ;
@@ -55,69 +97,43 @@ class CanvasModel extends DOMWidgetModel {
5597 static view_module = MODULE_NAME ;
5698 static view_module_version = MODULE_VERSION ;
5799
58- commandsCache : Array < any > ;
100+ canvas : HTMLCanvasElement ;
101+ ctx : any ;
102+ views : Dict < Promise < CanvasView > > ;
59103}
60104
61105
62106export
63107class CanvasView extends DOMWidgetView {
64108 render ( ) {
65109 this . canvas = document . createElement ( 'canvas' ) ;
66- this . canvas . width = '100%' ;
67- this . canvas . height = '100%' ;
68110
69111 this . el . appendChild ( this . canvas ) ;
70-
71112 this . ctx = this . canvas . getContext ( '2d' ) ;
72113
73- this . resize_canvas ( ) ;
74-
75- this . firstDraw ( ) ;
114+ this . resizeCanvas ( ) ;
115+ this . model . on ( 'change:size' , this . resizeCanvas . bind ( this ) ) ;
76116
77- this . modelEvents ( ) ;
117+ this . updateCanvas ( ) ;
78118 }
79119
80- firstDraw ( ) {
81- // Replay all the commands that were received until this view was created
82- for ( const command of this . model . commandsCache ) {
83- this . _processCommand ( command ) ;
84- }
85- }
86-
87- modelEvents ( ) {
88- this . model . on ( 'msg:custom' , this . _processCommand . bind ( this ) ) ;
120+ clear ( ) {
121+ this . ctx . clearRect ( 0 , 0 , this . canvas . width , this . canvas . height ) ;
89122 }
90123
91- private _processCommand ( command : any ) {
92- if ( command instanceof Array ) {
93- for ( const subcommand of command ) {
94- this . _processCommand ( subcommand ) ;
95- }
96- return ;
97- }
98-
99- if ( command . name == 'clear' ) {
100- this . ctx . clearRect ( 0 , 0 , this . canvas . width , this . canvas . height ) ;
101- this . model . cleanCache ( command ) ;
102- return ;
103- }
104-
105- if ( command . name == 'set' ) {
106- this . ctx [ command . attr ] = command . value ;
107- return ;
108- }
109-
110- this . ctx [ command . name ] ( ...command . args ) ;
124+ updateCanvas ( ) {
125+ this . ctx . drawImage ( this . model . canvas , 0 , 0 ) ;
111126 }
112127
113- resize_canvas ( ) {
128+ private resizeCanvas ( ) {
114129 const size = this . model . get ( 'size' ) ;
115130
116131 this . canvas . setAttribute ( 'width' , size [ 0 ] ) ;
117132 this . canvas . setAttribute ( 'height' , size [ 1 ] ) ;
118133 }
119134
120- canvas : any ;
135+ canvas : HTMLCanvasElement ;
121136 ctx : any ;
137+
122138 model : CanvasModel ;
123139}
0 commit comments