|
1 <?xml version="1.0"?> |
|
2 |
|
3 <!-- This Source Code Form is subject to the terms of the Mozilla Public |
|
4 - License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> |
|
6 |
|
7 <bindings xmlns="http://www.mozilla.org/xbl" |
|
8 xmlns:xbl="http://www.mozilla.org/xbl" |
|
9 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" |
|
10 xmlns:html="http://www.w3.org/1999/xhtml"> |
|
11 <binding id="circular-progress-indicator"> |
|
12 <resources> |
|
13 <stylesheet src="chrome://browser/skin/circularprogress.css"/> |
|
14 </resources> |
|
15 |
|
16 <content> |
|
17 <xul:stack> |
|
18 <xul:toolbarbutton anonid="progressButton" |
|
19 class="circularprogressindicator-progressButton"/> |
|
20 <html:div anonid="progressTrack" |
|
21 xbl:inherits="progress" |
|
22 class="circularprogressindicator-progressTrack"> |
|
23 </html:div> |
|
24 <html:canvas anonid="progressRing" |
|
25 xbl:inherits="progress" |
|
26 class="circularprogressindicator-progressRing" |
|
27 width="40" |
|
28 height="40"> |
|
29 </html:canvas> |
|
30 <html:div anonid="progressNotification" |
|
31 xbl:inherits="progress" |
|
32 class="circularprogressindicator-progressNotification"> |
|
33 </html:div> |
|
34 </xul:stack> |
|
35 </content> |
|
36 |
|
37 <implementation> |
|
38 <field name="_progressCanvas"> |
|
39 document.getAnonymousElementByAttribute(this, "anonid", "progressRing"); |
|
40 </field> |
|
41 <field name="_progressNotification"> |
|
42 document.getAnonymousElementByAttribute(this, "anonid", |
|
43 "progressNotification"); |
|
44 </field> |
|
45 <field name="_progressCircleCtx">null</field> |
|
46 <field name="_img">null</field> |
|
47 <constructor> |
|
48 <![CDATA[ |
|
49 this._progressCircleCtx = this._progressCanvas.getContext('2d'); |
|
50 ]]> |
|
51 </constructor> |
|
52 <method name="updateProgress"> |
|
53 <parameter name="percentComplete"/> |
|
54 <body> |
|
55 <![CDATA[ |
|
56 const PROGRESS_RING_IMG = "chrome://browser/skin/images/progresscircle.png"; |
|
57 |
|
58 // show ring background even if % is 0. |
|
59 this.setAttribute("progress", percentComplete); |
|
60 |
|
61 let startAngle = 1.5 * Math.PI; |
|
62 let endAngle = startAngle + (2 * Math.PI * (percentComplete / 100)); |
|
63 |
|
64 if (!this._img) { |
|
65 this._img = new Image(); |
|
66 this._img.onload = () => { |
|
67 this.updateProgress(this.getAttribute("progress")) |
|
68 } |
|
69 this._img.src = PROGRESS_RING_IMG; |
|
70 } |
|
71 else if (this._img.complete) { |
|
72 let ctx = this._progressCircleCtx; |
|
73 ctx.clearRect(0, 0, |
|
74 this._progressCanvas.width, this._progressCanvas.height); |
|
75 |
|
76 // Save the state, so we can undo the clipping |
|
77 ctx.save(); |
|
78 |
|
79 ctx.beginPath(); |
|
80 let center = this._progressCanvas.width / 2; |
|
81 ctx.arc(center, center, center, startAngle, endAngle, false); |
|
82 ctx.lineTo(center, center); |
|
83 ctx.closePath(); |
|
84 ctx.clip(); |
|
85 |
|
86 // Draw circle image. |
|
87 ctx.translate(center, center); |
|
88 ctx.rotate(endAngle); |
|
89 ctx.drawImage(this._img, -center, -center); |
|
90 |
|
91 ctx.restore(); |
|
92 } else { |
|
93 // Image is still loading |
|
94 } |
|
95 return [startAngle, endAngle]; |
|
96 ]]> |
|
97 </body> |
|
98 </method> |
|
99 <method name="reset"> |
|
100 <body> |
|
101 <![CDATA[ |
|
102 if(this._img && !this._img.complete) { |
|
103 // cancel any pending updateProgress |
|
104 this._img.onload = () => {}; |
|
105 } |
|
106 this._progressCircleCtx.clearRect(0, 0, |
|
107 this._progressCanvas.width, this._progressCanvas.height); |
|
108 this.removeAttribute("progress"); |
|
109 ]]> |
|
110 </body> |
|
111 </method> |
|
112 <method name="notify"> |
|
113 <body> |
|
114 <![CDATA[ |
|
115 this.addEventListener("transitionend", this._onNotificationEnd); |
|
116 |
|
117 this._progressNotification.classList.add( |
|
118 "progressNotification-active"); |
|
119 ]]> |
|
120 </body> |
|
121 </method> |
|
122 <method name="_onNotificationEnd"> |
|
123 <body> |
|
124 <![CDATA[ |
|
125 this.removeEventListener("transitionend", this._onNotificationEnd); |
|
126 |
|
127 this._progressNotification.classList.remove( |
|
128 "progressNotification-active"); |
|
129 ]]> |
|
130 </body> |
|
131 </method> |
|
132 </implementation> |
|
133 </binding> |
|
134 </bindings> |