source: trunk/fl5/src/com/longtailvideo/jwplayer/view/components/ControlbarComponentV4.as @ 609

Revision 609, 19.3 KB checked in by pablo, 4 years ago (diff)

Exit fullscreen caused controlbar to fade

Line 
1package com.longtailvideo.jwplayer.view.components {
2        import com.longtailvideo.jwplayer.events.MediaEvent;
3        import com.longtailvideo.jwplayer.events.PlayerEvent;
4        import com.longtailvideo.jwplayer.events.PlayerStateEvent;
5        import com.longtailvideo.jwplayer.events.PlaylistEvent;
6        import com.longtailvideo.jwplayer.events.ViewEvent;
7        import com.longtailvideo.jwplayer.player.IPlayer;
8        import com.longtailvideo.jwplayer.player.PlayerState;
9        import com.longtailvideo.jwplayer.plugins.PluginConfig;
10        import com.longtailvideo.jwplayer.utils.Animations;
11        import com.longtailvideo.jwplayer.utils.Draw;
12        import com.longtailvideo.jwplayer.utils.Logger;
13        import com.longtailvideo.jwplayer.utils.Stacker;
14        import com.longtailvideo.jwplayer.utils.Strings;
15        import com.longtailvideo.jwplayer.view.PlayerLayoutManager;
16        import com.longtailvideo.jwplayer.view.interfaces.IControlbarComponent;
17       
18        import flash.accessibility.AccessibilityProperties;
19        import flash.display.DisplayObject;
20        import flash.display.MovieClip;
21        import flash.display.Sprite;
22        import flash.events.MouseEvent;
23        import flash.geom.ColorTransform;
24        import flash.geom.Rectangle;
25        import flash.text.TextField;
26        import flash.ui.Mouse;
27        import flash.utils.clearTimeout;
28        import flash.utils.setTimeout;
29
30
31        public class ControlbarComponentV4 extends CoreComponent implements IControlbarComponent {
32                /** Reference to the original skin **/
33                private var skin:Sprite;
34                /** A list with all controls. **/
35                private var stacker:Stacker;
36                /** Timeout for hiding the  **/
37                private var hiding:Number;
38                /** When scrubbing, icon shouldn't be set. **/
39                private var scrubber:MovieClip;
40                /** Color object for frontcolor. **/
41                private var front:ColorTransform;
42                /** Color object for lightcolor. **/
43                private var light:ColorTransform;
44                /** The actions for all controlbar buttons. **/
45                private var BUTTONS:Object;
46                /** The actions for all sliders **/
47                private var SLIDERS:Object = {timeSlider: ViewEvent.JWPLAYER_VIEW_SEEK,
48                                volumeSlider: ViewEvent.JWPLAYER_VIEW_VOLUME};
49                /** The button to clone for all custom buttons. **/
50                private var clonee:MovieClip;
51                /** Saving the block state of the controlbar. **/
52                private var blocking:Boolean;
53                /** Controlbar config **/
54                private var controlbarConfig:PluginConfig;
55                /** Animations handler **/
56                private var animations:Animations;
57
58
59                public function ControlbarComponentV4(player:IPlayer) {
60                        super(player, "controlbar");
61                        animations = new Animations(this);
62                        controlbarConfig = _player.config.pluginConfig("controlbar");
63                        if (!controlbarConfig['margin']) controlbarConfig['margin'] = 0;       
64                        // TODO: Remove Link button
65                        BUTTONS = {playButton: ViewEvent.JWPLAYER_VIEW_PLAY,
66                                        pauseButton: ViewEvent.JWPLAYER_VIEW_PAUSE,
67                                        stopButton: ViewEvent.JWPLAYER_VIEW_STOP,
68                                        prevButton: ViewEvent.JWPLAYER_VIEW_PREV,
69                                        nextButton: ViewEvent.JWPLAYER_VIEW_NEXT,
70                                        fullscreenButton: ViewEvent.JWPLAYER_VIEW_FULLSCREEN,
71                                        normalscreenButton: ViewEvent.JWPLAYER_VIEW_FULLSCREEN,
72                                        muteButton: ViewEvent.JWPLAYER_VIEW_MUTE,
73                                        unmuteButton: ViewEvent.JWPLAYER_VIEW_MUTE};
74                        skin = _player.skin.getSWFSkin().getChildByName('controlbar') as Sprite;
75                        skin.x = 0;
76                        skin.y = 0;
77                        addChild(skin);
78                        _player.addEventListener(PlayerStateEvent.JWPLAYER_PLAYER_STATE, stateHandler);
79                        _player.addEventListener(MediaEvent.JWPLAYER_MEDIA_TIME, timeHandler);
80                        _player.addEventListener(MediaEvent.JWPLAYER_MEDIA_MUTE, muteHandler);
81                        _player.addEventListener(MediaEvent.JWPLAYER_MEDIA_VOLUME, volumeHandler);
82                        _player.addEventListener(MediaEvent.JWPLAYER_MEDIA_BUFFER, bufferHandler);
83                        _player.addEventListener(PlaylistEvent.JWPLAYER_PLAYLIST_LOADED, itemHandler);
84                        _player.addEventListener(PlaylistEvent.JWPLAYER_PLAYLIST_UPDATED, itemHandler);
85                        _player.addEventListener(PlaylistEvent.JWPLAYER_PLAYLIST_ITEM, itemHandler);
86                        stacker = new Stacker(skin as MovieClip);
87                        try {
88                                getSkinComponent("linkButton").visible = false;
89                        } catch (e:Error) {}
90                       
91                        setButtons();
92                        setColors();
93                        itemHandler();
94                        muteHandler();
95                        stateHandler();
96                        timeHandler();
97                        volumeHandler();
98                }
99
100
101                /**
102                 * Add a new button to the control
103                 *
104                 * @param icn   A graphic to show as icon
105                 * @param nam   Name of the button
106                   getSkinComponent('* @param hdl       The function to call when clicking the Button').
107                 **/
108                public function addButton(icon:DisplayObject, name:String, handler:Function=null):MovieClip {
109                        var btn:MovieClip;
110                        if (getSkinComponent('linkButton') && getSkinElementChild('linkButton', 'back')) {
111                                btn = Draw.clone(getSkinComponent('linkButton') as MovieClip) as MovieClip;
112                                btn.name = name + 'Button';
113                                btn.visible = true;
114                                btn.tabEnabled = true;
115                                btn.tabIndex = 6;
116                                var acs:AccessibilityProperties = new AccessibilityProperties();
117                                acs.name = name + 'Button';
118                                btn.accessibilityProperties = acs;
119                                skin.addChild(btn);
120                                var off:Number = Math.round((btn.height - icon.height) / 2);
121                                Draw.clear(btn['icon']);
122                                btn['icon'].addChild(icon);
123                                icon.x = icon.y = 0;
124                                btn['icon'].x = btn['icon'].y = off;
125                                btn['back'].width = icon.width + 2 * off;
126                                btn.buttonMode = true;
127                                btn.mouseChildren = false;
128                                btn.addEventListener(MouseEvent.CLICK, handler);
129                                if (front) {
130                                        btn['icon'].transform.colorTransform = front;
131                                        btn.addEventListener(MouseEvent.MOUSE_OVER, overHandler);
132                                        btn.addEventListener(MouseEvent.MOUSE_OUT, outHandler);
133                                }
134                                stacker.insert(btn, getSkinComponent('linkButton') as MovieClip);
135                        }
136                        return btn;
137                }
138
139
140                public function removeButton(name:String):void {
141                        skin.removeChild(getSkinComponent(name));
142                }
143
144
145                public function resize(width:Number, height:Number):void {
146                        if (!(PlayerLayoutManager.testPosition(controlbarConfig['position']) || controlbarConfig['position'] == "over")) {
147                                skin.visible = false;
148                                return;
149                        }
150
151                        var wid:Number = width;
152                        if (controlbarConfig['position'] == 'over' || _player.fullscreen == true) {
153                                skin.x = controlbarConfig['margin'];
154                                skin.y = height - skin.height - controlbarConfig['margin'];
155                                wid = width - 2 * controlbarConfig['margin'];
156                        } else {
157                                skin.x = 0;
158                                skin.y = 0;
159                        }
160                        try {
161                                getSkinComponent('fullscreenButton').visible = false;
162                                getSkinComponent('normalscreenButton').visible = false;
163                                if (stage['displayState'] && _player.config.height > 40) {
164                                        if (_player.fullscreen) {
165                                                getSkinComponent('fullscreenButton').visible = false;
166                                                getSkinComponent('normalscreenButton').visible = true;
167                                        } else {
168                                                getSkinComponent('fullscreenButton').visible = true;
169                                                getSkinComponent('normalscreenButton').visible = false;
170                                        }
171                                }
172                        } catch (err:Error) {
173                        }
174                        stacker.rearrange(wid);
175                        stopFader();
176                        stateHandler();
177                        fixTime();
178                }
179
180
181                public function getButton(buttonName:String):DisplayObject {
182                        return null;
183                }
184
185
186                /** Hide the controlbar **/
187                public function block(stt:Boolean):void {
188                        blocking = stt;
189                        timeHandler();
190                }
191
192
193                /** Handle clicks from all buttons. **/
194                private function clickHandler(evt:MouseEvent):void {
195                        var act:String = BUTTONS[evt.target.name];
196                        var data:Object = null;
197                        if (blocking != true || act == ViewEvent.JWPLAYER_VIEW_FULLSCREEN || act == ViewEvent.JWPLAYER_VIEW_MUTE) {
198                                switch (act) {
199                                        case ViewEvent.JWPLAYER_VIEW_FULLSCREEN:
200                                                data = Boolean(!_player.fullscreen);
201                                                break;
202                                        case ViewEvent.JWPLAYER_VIEW_PAUSE:
203                                                data = Boolean(_player.state == PlayerState.IDLE || _player.state == PlayerState.PAUSED);
204                                                break;
205                                        case ViewEvent.JWPLAYER_VIEW_MUTE:
206                                                data = Boolean(!_player.mute);
207                                                break;
208                                }
209                                var event:ViewEvent = new ViewEvent(act, data);
210                                dispatchEvent(event);
211                        }
212                }
213
214
215                /** Handle mouse presses on sliders. **/
216                private function downHandler(evt:MouseEvent):void {
217                        if (!_player.locked) {
218                                scrubber = MovieClip(evt.target);
219                                if (blocking != true || scrubber.name == 'volumeSlider') {
220                                        var rct:Rectangle = new Rectangle(scrubber.rail.x, scrubber.icon.y, scrubber.rail.width - scrubber.icon.width, 0);
221                                        scrubber.icon.startDrag(true, rct);
222                                        stage.addEventListener(MouseEvent.MOUSE_UP, upHandler);
223                                } else {
224                                        scrubber = undefined;
225                                }
226                        }
227                }
228
229
230                /** Handle a change in the current item **/
231                private function itemHandler(evt:PlaylistEvent=null):void {
232                        try {
233                                if (_player.playlist && _player.playlist.length > 1) {
234                                        getSkinComponent('prevButton').visible = getSkinComponent('nextButton').visible = true;
235                                } else {
236                                        getSkinComponent('prevButton').visible = getSkinComponent('nextButton').visible = false;
237                                }
238                        } catch (err:Error) {
239                        }
240                        timeHandler();
241                        stacker.rearrange();
242                        fixTime();
243                }
244
245
246                /** Show above controlbar on mousemove. **/
247                private function moveHandler(evt:MouseEvent=null):void {
248                        if (alpha == 0) {
249                                animations.fade(1);
250                        }
251                        clearTimeout(hiding);
252                        hiding = setTimeout(moveTimeout, 2000);
253                        Mouse.show();
254                }
255
256
257                /** Hide above controlbar again when move has timed out. **/
258                private function moveTimeout():void {
259                        animations.fade(0);
260                        Mouse.hide();
261                }
262
263
264                /** Show a mute icon if playing. **/
265                private function muteHandler(evt:MediaEvent=null):void {
266                        if (_player.mute == true) {
267                                try {
268                                        getSkinComponent('muteButton').visible = false;
269                                        getSkinComponent('unmuteButton').visible = true;
270                                } catch (err:Error) {
271                                }
272                                try {
273                                        getSkinElementChild('volumeSlider', 'mark').visible = false;
274                                        getSkinElementChild('volumeSlider', 'icon').x = getSkinElementChild('volumeSlider', 'rail').x;
275                                } catch (err:Error) {
276                                }
277                        } else {
278                                try {
279                                        getSkinComponent('muteButton').visible = true;
280                                        getSkinComponent('unmuteButton').visible = false;
281                                } catch (err:Error) {
282                                }
283                                try {
284                                        getSkinElementChild('volumeSlider', 'mark').visible = true;
285                                        volumeHandler();
286                                } catch (err:Error) {
287                                }
288                        }
289                }
290
291
292                /** Handle mouseouts from all buttons **/
293                private function outHandler(evt:MouseEvent):void {
294                        if (front && evt.target['icon']) {
295                                evt.target['icon'].transform.colorTransform = front;
296                        } else {
297                                evt.target.gotoAndPlay('out');
298                        }
299                }
300
301
302                /** Handle clicks from all buttons **/
303                private function overHandler(evt:MouseEvent):void {
304                        if (front && evt.target['icon']) {
305                                evt.target['icon'].transform.colorTransform = light;
306                        } else {
307                                evt.target.gotoAndPlay('over');
308                        }
309                }
310
311
312                /** Clickhandler for all buttons. **/
313                private function setButtons():void {
314                        for (var btn:String in BUTTONS) {
315                                if (getSkinComponent(btn)) {
316                                        (getSkinComponent(btn) as MovieClip).mouseChildren = false;
317                                        (getSkinComponent(btn) as MovieClip).buttonMode = true;
318                                        getSkinComponent(btn).addEventListener(MouseEvent.CLICK, clickHandler);
319                                        getSkinComponent(btn).addEventListener(MouseEvent.MOUSE_OVER, overHandler);
320                                        getSkinComponent(btn).addEventListener(MouseEvent.MOUSE_OUT, outHandler);
321                                }
322                        }
323                        for (var sld:String in SLIDERS) {
324                                if (getSkinComponent(sld)) {
325                                        (getSkinComponent(sld) as MovieClip).mouseChildren = false;
326                                        (getSkinComponent(sld) as MovieClip).buttonMode = true;
327                                        getSkinComponent(sld).addEventListener(MouseEvent.MOUSE_DOWN, downHandler);
328                                        getSkinComponent(sld).addEventListener(MouseEvent.MOUSE_OVER, overHandler);
329                                        getSkinComponent(sld).addEventListener(MouseEvent.MOUSE_OUT, outHandler);
330                                }
331                        }
332                }
333
334
335                /** Init the colors. **/
336                private function setColors():void {
337                        if (_player.config.backcolor && getSkinElementChild('playButton', 'icon')) {
338                                var clr:ColorTransform = new ColorTransform();
339                                clr.color = _player.config.backcolor.color;
340                                getSkinComponent('back').transform.colorTransform = clr;
341                        }
342                        if (_player.config.frontcolor) {
343                                try {
344                                        front = new ColorTransform();
345                                        front.color = _player.config.frontcolor.color;
346                                        for (var btn:String in BUTTONS) {
347                                                if (getSkinComponent(btn)) {
348                                                        getSkinElementChild(btn, 'icon').transform.colorTransform = front;
349                                                }
350                                        }
351                                        for (var sld:String in SLIDERS) {
352                                                if (getSkinComponent(sld)) {
353                                                        getSkinElementChild(sld, 'icon').transform.colorTransform = front;
354                                                        getSkinElementChild(sld, 'mark').transform.colorTransform = front;
355                                                        getSkinElementChild(sld, 'rail').transform.colorTransform = front;
356                                                }
357                                        }
358                                        (getSkinComponent('elapsedText') as TextField).textColor = front.color;
359                                        (getSkinComponent('totalText') as TextField).textColor = front.color;
360                                } catch (err:Error) {
361                                }
362                        }
363                        if (_player.config.lightcolor) {
364                                light = new ColorTransform();
365                                light.color = _player.config.lightcolor.color;
366                        } else {
367                                light = front;
368                        }
369                        if (light) {
370                                try {
371                                        getSkinElementChild('timeSlider', 'done').transform.colorTransform = light;
372                                        getSkinElementChild('volumeSlider', 'mark').transform.colorTransform = light;
373                                } catch (err:Error) {
374                                }
375                        }
376                }
377
378                private function startFader():void {
379                        if (controlbarConfig['position'] == 'over' || (_player.fullscreen && controlbarConfig['position'] != 'none')) {
380                                if (!isNaN(hiding)) {
381                                        clearTimeout(hiding);
382                                }
383                                hiding = setTimeout(moveTimeout, 2000);
384                                _player.controls.display.addEventListener(MouseEvent.MOUSE_MOVE, moveHandler);
385                        }
386                }
387               
388                private function stopFader():void {
389                        if (!isNaN(hiding)) {
390                                clearTimeout(hiding);
391                                try {
392                                        _player.controls.display.removeEventListener(MouseEvent.MOUSE_MOVE, moveHandler);
393                                } catch (e:Error) {}
394                        }
395                        Mouse.show();
396                        animations.fade(1);
397                }
398
399                /** Process state changes **/
400                private function stateHandler(evt:PlayerEvent=undefined):void {
401                        // TODO: Fix non-working fading
402                        clearTimeout(hiding);
403                        try {
404                                var dps:String = stage['displayState'];
405
406                                switch (_player.state) {
407                                        case PlayerState.PLAYING:
408                                                getSkinComponent('playButton').visible = false;
409                                                getSkinComponent('pauseButton').visible = true;
410                                                startFader();
411                                                break;
412                                        case PlayerState.PAUSED:
413                                                getSkinComponent('playButton').visible = true;
414                                                getSkinComponent('pauseButton').visible = false;
415                                                stopFader();
416                                                break;
417                                        case PlayerState.BUFFERING:
418                                                getSkinComponent('playButton').visible = false;
419                                                getSkinComponent('pauseButton').visible = true;
420                                                stopFader();
421                                                break;
422                                        case PlayerState.IDLE:
423                                                getSkinComponent('playButton').visible = true;
424                                                getSkinComponent('pauseButton').visible = false;
425                                                timeHandler();
426                                                stopFader();
427                                                break;
428                                }
429                        } catch (e:Error) {
430                        }
431                }
432
433
434                /** Process time updates given by the model. **/
435                private function timeHandler(evt:MediaEvent=null):void {
436                        var dur:Number = 0;
437                        var pos:Number = 0;
438                        if (evt) {
439                                if (evt.duration >= 0) {
440                                        dur = evt.duration;
441                                }
442                                if (evt.position >= 0) {
443                                        pos = evt.position;
444                                }
445                        } else if (_player.playlist.length > 0 && _player.playlist.currentItem) {
446                                if (_player.playlist.currentItem.duration >= 0) {
447                                        dur = _player.playlist.currentItem.duration;
448                                }
449                        }
450                        var pct:Number = pos / dur;
451                        if (isNaN(pct)) {
452                                pct = 1;
453                        }
454                        try {
455                                (getSkinComponent('elapsedText') as TextField).text = Strings.digits(pos);
456                                (getSkinComponent('totalText') as TextField).text = Strings.digits(dur);
457                        } catch (err:Error) {
458                                Logger.log(err);
459                        }
460                        try {
461                                var xps:Number = Math.round(pct * (getSkinElementChild('timeSlider', 'rail').width - getSkinElementChild('timeSlider', 'icon').width));
462                                if (dur > 0) {
463                                        getSkinElementChild('timeSlider', 'icon').visible = _player.state != PlayerState.IDLE;
464                                        getSkinElementChild('timeSlider', 'mark').visible = _player.state != PlayerState.IDLE;
465                                        if (!scrubber) {
466                                                getSkinElementChild('timeSlider', 'icon').x = xps;
467                                                getSkinElementChild('timeSlider', 'done').width = xps;
468                                        }
469                                        bufferHandler(evt);
470                                        getSkinElementChild('timeSlider', 'done').visible = _player.state != PlayerState.IDLE;
471                                } else {
472                                        if (_player.state != PlayerState.PLAYING) {
473                                                getSkinElementChild('timeSlider', 'icon').visible = false;
474                                                getSkinElementChild('timeSlider', 'mark').visible = false;
475                                                getSkinElementChild('timeSlider', 'done').visible = false;
476                                        }
477                                }
478                        } catch (err:Error) {
479                        }
480                }
481
482
483                private function bufferHandler(evt:MediaEvent):void {
484                        if (evt.bufferPercent < 0)
485                                return;
486
487                        var mark:DisplayObject = getSkinElementChild('timeSlider', 'mark');
488                        var railWidth:Number = getSkinElementChild('timeSlider', 'rail').width;
489                        var markWidth:Number = _player.state == PlayerState.IDLE ? 0 : Math.round((evt.bufferPercent / 100) * railWidth);
490                        var offsetRatio:Number = evt.offset / evt.duration;
491
492                        try {
493                                mark.x = evt.duration > 0 ? Math.round(railWidth * offsetRatio) : 0;
494                                mark.width = markWidth * (1 - offsetRatio);
495                                mark.visible = _player.state != PlayerState.IDLE;
496                        } catch (e:Error) {
497                        }
498                }
499
500
501                /** Fix the timeline display. **/
502                private function fixTime():void {
503                        try {
504                                var scp:Number = getSkinComponent('timeSlider').scaleX;
505                                getSkinComponent('timeSlider').scaleX = 1;
506                                getSkinElementChild('timeSlider', 'icon').x = scp * getSkinElementChild('timeSlider', 'icon').x;
507                                getSkinElementChild('timeSlider', 'mark').x = scp * getSkinElementChild('timeSlider', 'mark').x;
508                                getSkinElementChild('timeSlider', 'mark').width = scp * getSkinElementChild('timeSlider', 'mark').width;
509                                getSkinElementChild('timeSlider', 'rail').width = scp * getSkinElementChild('timeSlider', 'rail').width;
510                                getSkinElementChild('timeSlider', 'done').x = scp * getSkinElementChild('timeSlider', 'done').x;
511                                getSkinElementChild('timeSlider', 'done').width = scp * getSkinElementChild('timeSlider', 'done').width;
512                        } catch (err:Error) {
513                        }
514                }
515
516
517                /** Handle mouse releases on sliders. **/
518                private function upHandler(evt:MouseEvent):void {
519                        var mpl:Number = 0;
520                        var sliderType:String = scrubber.name;
521
522                        stage.removeEventListener(MouseEvent.MOUSE_UP, upHandler);
523                        scrubber.icon.stopDrag();
524                        if (sliderType == 'timeSlider' && _player.playlist) {
525                                mpl = _player.playlist.currentItem.duration;
526                        } else if (sliderType == 'volumeSlider') {
527                                if (_player.mute)
528                                        return;
529                                else
530                                        mpl = 100;
531                        }
532                        var pct:Number = (scrubber.icon.x - scrubber.rail.x) / (scrubber.rail.width - scrubber.icon.width) * mpl;
533                        scrubber = undefined;
534                        if (sliderType == 'volumeSlider') {
535                                var volumeEvent:MediaEvent = new MediaEvent(MediaEvent.JWPLAYER_MEDIA_VOLUME);
536                                volumeEvent.volume = Math.round(pct);
537                                volumeHandler(volumeEvent);
538                        }
539                        dispatchEvent(new ViewEvent(SLIDERS[sliderType], Math.round(pct)));
540                }
541
542
543                /** Reflect the new volume in the controlbar **/
544                private function volumeHandler(evt:MediaEvent=null):void {
545                        try {
546                                var vsl:MovieClip = getSkinComponent('volumeSlider') as MovieClip;
547                                vsl.mark.width = _player.config.volume * (vsl.rail.width - vsl.icon.width / 2) / 100;
548                                vsl.icon.x = vsl.mark.x + _player.config.volume * (vsl.rail.width - vsl.icon.width) / 100;
549                        } catch (err:Error) {
550                        }
551                }
552
553
554                private function getSkinComponent(element:String):DisplayObject {
555                        return skin.getChildByName(element) as DisplayObject;
556                }
557
558
559                private function getSkinElementChild(element:String, child:String):DisplayObject {
560                        return (skin.getChildByName(element) as MovieClip).getChildByName(child);
561                }
562        }
563}
Note: See TracBrowser for help on using the repository browser.