Patch flex framework to show preloader instantly? - apache-flex

In the Flex framework a custom preloader can be used while the site is loading.
In the Adobe docs it specifies that 'the progress bar [preloader] is displayed if less than half of the application is downloaded after 700 milliseconds of downloading.'
However I ALWAYS want the preloader to appear instantly since I know that 95% of our users are first time visitors and the site is over 500kb. I dont want people to have to wait .7 seconds for the preloader animation to appear.
I would think in theory that it is possible to 'monkey patch' the framework to remove this .7 second limitation. I dont have time to figure out how, and I've never done it before.
Anybody help?

You should just extend the DownloadProgressBar, try the following code. i've used this before and I've found jesse warden site click here usful for info on this (where I found out about it and this is a cut down version of his code)
package{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.ProgressEvent;
import mx.events.FlexEvent;
import mx.preloaders.DownloadProgressBar;
public class Preloader extends DownloadProgressBar
{
/**
* The Flash 8 MovieClip embedded as a Class.
*/
[Embed(source="yourPreloaderFile.swf")]
private var FlashPreloaderSymbol:Class;
private var clip:MovieClip;
public function Preloader()
{
super();
clip = new FlashPreloaderSymbol();
addChild(clip);
}
public override function set preloader(preloader:Sprite):void
{
preloader.addEventListener( FlexEvent.INIT_COMPLETE , onFlexInitComplete );
centerPreloader();
}
private function centerPreloader():void
{
x = (stageWidth / 2) - (clip.width / 2);
y = (stageHeight / 2) - (clip.height / 2);
}
private function onFlexInitComplete( event:FlexEvent ):void
{
dispatchEvent( new Event( Event.COMPLETE ) );
}
protected override function showDisplayForDownloading(time : int, event : ProgressEvent) : Boolean {
return true;
}
}
}
after that just change the preloader property in the main application tag to the Preloader class.

This is in mx.preloaders::DownloadProgressBar.as, line 1205 in the showDisplayForDownloading function.
Old school monkey-patching is out with AS3, but you can either edit the Flex source and compile yourself a new framework.swc (apparently a pain), or just include it in your source path (source paths override .swcs); or derive your own preloader class from DownloadProgressBar that just overrides showDisplayForDownloading and returns true.
You can find the framework source in '%PROGRAMFILES%\Adobe\Flex Builder 3[ Plug-in]\sdks\3.0.0\frameworks\projects\framework\src', then the package path. Change the sdk version if you are using 3.1, or whatever.

I'd guess that delay is there for two reasons:
You don't want the preloader to
"blink" in once the page is already
cached
The preloader itself has to
load
When I need to make absolutely sure a preloader is shown instantly I make a small wrapper swf that has just the preloader and load the main swf from there.

its not possible to make preloader show instantly , since some classes needs to be downloaded before progress can be displayed . other alternative can be that you display a progress in html and when flash movie is loaded it shows up but here .

Related

How to create new skin for `DatePicker`, javafx

I want to create a new skin class for DatePicker. Following different instructions about how to do it, e.g guigarage the right way is to extend SkinBase and load new skin class by setting -fx-skin property to the skin class name, so i did, but I got this Error:
Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: sample.myDatePickerSkin cannot be cast to com.sun.javafx.scene.control.skin.DatePickerSkin
at com.sun.javafx.scene.control.behavior.DatePickerBehavior.onAutoHide(DatePickerBehavior.java:103)
and if you look at DatePickerBehavior.java:103:
#Override public void onAutoHide() {
// when we click on some non-interactive part of the
// calendar - we do not want to hide.
DatePicker datePicker = (DatePicker)getControl();
DatePickerSkin cpSkin = (DatePickerSkin)datePicker.getSkin();
cpSkin.syncWithAutoUpdate();
// if the DatePicker is no longer showing, then invoke the super method
// to keep its show/hide state in sync.
if (!datePicker.isShowing()) super.onAutoHide();
}
So did I do anything wrong? or I should also write myDatePickerBehavior?
The official way to implement a Skin is to either
extend javafx.scene.control.SkinBase (since JavaFX 8.0)
or
implement Skin directly.
com.sun.javafx.scene‌​.control.skin.BaseSki‌​n is not a published API.
Please note that with Java SE 9 and Jigsaw, DatePickerSkin as well as the other default skins will become published APIs, AFAIK. Then it should be safe to extend them if it meets your requirements.
I should extend DatePickerSkin :
package sample;
import com.sun.javafx.scene.control.skin.DatePickerSkin;
import javafx.scene.control.DatePicker;
public class customDatePickerSkin extends DatePickerSkin {
public customDatePickerSkin(DatePicker datePicker) {
super(datePicker);
}
}

Handling error conditions on Flex

I have the following AS code.I have noticed that if an Application i s using the webcamera then it cannot be used by any secondary applications until unless the primary application is closed.
My question is that from the following code 1.can we capture that condition
2.If no camera is detected how to give the alert since it is an AS code
EDIT:
Filename is cldAS.as
Now how to call cldAS() from any.mxml file .Some example would be appreciated
package org.com
{
import flash.display.Sprite;
import flash.media.*;
import flash.net.*;
public class cldAS extends Sprite
{
public function cldAS()
{
var cam:Camera = Camera.getCamera();
if(cam != null)
{
cam.setMode(640, 480, 30);
var video:Video = new Video(300, 450);
video.attachCamera(cam);
addChild(video);
}
else
{
trace("No Camera Detected");
//How to give an alert here
}
}
}
}
Alert.show("You don't seem to have a webcam.");
instead of
trace(...) ?
Alert is available in Flex only , in AS3 you should really implement your own solution, on the other hand , since Alert is a Javascript function , you could also use ExternalInterface to call it.
As far as implementing your own solution is concerned, at the minimum you need a TextField to display your message, which text you could provide by sending a CustomEvent with a message property that will simply take a String. It wouldn't take too much work to create your own Alert class.It would sit on top of your App , you could toggle visibility when receiving a CustomEvent and have a Close button to hide it.
You should be able to call your AS3 class within script tags , other than that I'll leave a more detailed answer to Flex experts. I'm not sure if you can add a Sprite directly into Flex , for all I remember an object in Flex must inherit from UIComponent in order to be added to the stage but check with the other guys here, I haven't used Flex in quite some time...
<mx:Script>
import org.com.cldAS;
public cld:cldAS = new cldAS();
</mx:Script>

How can I add controls to the title bar of a flex panel?

I'm trying to implement a collapsible TitleWindow popup by adding a handle to the top right corner of a Panel control. Unfortunately, the image that I add as the handle doesn't show up when the control is drawn. I can trigger a redraw by changing the source of the image, so apparently it's there, but it's somehow hidden.
Is there a way to make this Image control visible to the user?
Here's the code for the window:
package
{
import mx.containers.Panel;
import mx.controls.Image;
public class CollapsableWindow extends Panel
{
public function CollapsableWindow()
{
super();
}
public var close:Image;
protected override function createChildren():void
{
super.createChildren();
close = new Image();
close.source = "/assets/close.png";
close.x = this.width - 20;
close.y = 8;
this.titleBar.addChildAt(close, 0);
}
}
}
You need to create your button in the createChildren method, then position it in the updateDisplayList method:
/**
* Creates the button and adds it to the titlebar
*/
override protected function createChildren():void
{
super.createChildren();
this.myButton = new Button();
this.myButton.addEventListener(MouseEvent.CLICK, onButtonClick);
this.titleBar.addChild(this.myButton);
}
/**
* Sizes and positions the button on the titlebar
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
this.myButton.setActualSize(myButton.getExplicitOrMeasuredWidth(),
myButton.getExplicitOrMeasuredHeight());
// Position the button
var y:int = 4;
var x:int = this.width - this.myButton.width - 2;
this.myButton.move(x, y);
}
I've had issues with PNG's not showing up in our app. Every once in a while, all our PNG's disappear. To test whether you're code suffers the same problem, try using a test image that's a GIF or other format. If it works then you're having the same issue I've run into dozens of times.
On our project, we solve this in two ways:
A workaround. Toggle your project's SDK version and, for some odd reason, that fixes it
So, for example, we use SDK 3.6
I right click on the project, chose properties and go to the Flex SDK section
From there I switch to ANY OTHER SDK version (say Flex 3.2) and choose ok
This triggers an automatic build (with some kind of mysterious PNG-fixing power)
Then I go back into the project properties and return it to our version.
8 times out of 10 this restores the PNG images
This worked even when we were using Flex SDK 3.4 and 3.5
A fix. Change your PNG format to PNG-24
It seems the root problem is related to using the PNG-8 format
For our images, I open the original in Photoshop press CMD-Shft-Ctrl-S, invoking "Save For Web..."
Then I choose PNG-24 for the format, instead of PNG-8
A similar process should work in any other image editing program
I hope that helps in some way,
-- gMale

How do I manage library symbols with linked classes in Flash CS4 to compile/debug in Flash Builder 4?

I'm building a video player using Flash CS4 (hereby referred to as "Flash") to create the graphic symbols and compiling and debugging with Flash Builder 4 ("FB4"). Here are the steps I take in my current workflow:
--Create the graphic symbols in Flash. I've created a few different symbols for the player, but I'll focus on just the play/pause button ("ppbutton") here.
--In the Library panel, I go to the ppbutton symbol's Linkage properties and link to a class named assets.PlayPauseButtonAsset that extends MovieClip. I do not actually have an assets package nor do I have a class file for PlayPauseButtonAsset as Flash will create them for me when I publish.
--In Flash's Publish settings, I set the project to export a SWC that will be used in FB4, called VideoPlayerAssets.swc.
--After the SWC is created, I create my FB4 project called "VideoPlayer" and add the SWC to my path. FB4 creates the class VideoPlayer in the default package automatically.
--In VideoPlayer.as, I import assets.*, which imports all of the symbol classes I created in Flash and are available via VideoPlayerAssets.swc. I can now instantiate the ppbutton and add to the stage, like this:
var ppbutton:PlayPauseButtonAsset = new PlayPauseButtonAsset();
addChild(ppbutton);
At this point ppbutton doesn't have any functionality because I didn't create any code for it. So I create a new class called video.controls.PlayPauseButtonLogic which extends assets.PlayPauseButtonAsset. I add some logic, and now I can use that new class to put a working ppbutton on the stage:
var ppbutton:PlayPauseButtonLogic = new PlayPauseButtonLogic();
addChild(ppbutton);
This works fine, but you may be asking why I didn't just link the ppbutton symbol in Flash to the video.controls.PlayPauseButtonLogic class in the first place. The reason is that I have a designer creating the UI in Flash and I don't want to have to re-publish the SWC from Flash every time I make a change in the logic. Basically, I want my designer to be able to make a symbol in Flash, link that symbol to a logically named class in Linkage properties, and export the SWC. I do not want to have to touch that .fla file again unless the designer makes changes to the symbols or layout. I'm using a versioning system for the project as well and it's cleaner to make sure only the designer is touching the .fla file.
So, finally, here's the issue I'm running into:
--As the design gets more complex, the designer is nesting symbols to position the video controls on the control bar. He creates a controlbar symbol and links it to assets.ControlBarAsset. The controlbar symbol contains the ppbutton symbol.
--The designer publishes the SWC and ControlBarAsset is now available in FB4. I create new class called video.controls.ControlBarLogic that extends assets.ControlBarAsset so I can add some logic to the controlbar, and I add the controlbar to the stage:
var controlbar:ControlBarLogic = new ControlBarLogic();
addChild(controlbar);
--This works, but the ppbutton doesn't do anything. That's because ppbutton, while inside controlbar, is still only linked to PlayPauseButtonAsset, which doesn't have any logic. I'm no longer instantiating a ppbutton object because it's part of controlbar.
That's where I'm stuck today. I can't seem to simply re-cast controlbar's ppbutton as PlayPauseButtonLogic as I get a Type error. And I don't want to have to make a class that has to instantiate each of the video player controls, the place them at their x and y values on the stage according to how the designer placed them, as that would require me to open the .fla and check the various properties of a symbol, then add those values to the code. If the designer made a change, I'd have to go into the code each time just to update those properties each time. Not good.
How do I re-cast nested symbols to use the logic classes that I create that extend the asset classes? Remember, the solution is not to link Flash symbols to actual classes so I don't have to keep recompiling the SWC, unless there's a way to do that without having to re-compile the SWC. I want the designer to do his thing, publish the SWC, and be done with it. Then I can take his SWC, apply my logic to his assets, and be able to debug and compile the final SWF.
Here is the solution that i use sometimes:
Instead of making PlayPauseButtonLogic extends PlayPauseButtonAsset, use this class as a warpper of PalyPauseButtonAsset, use composition instead of inheritance ! ; ).
You will get something like this in your ControlBarLogic class:
//constructor exemple
public function ControlBarLogic(){
//all logic of PPButton is inside PlayPauseButtonLogic
//you just pass a reference to the PlayPauseButtonAsset button contained inside ControlBarAsset
var ppButtonLogic: PlayPauseButtonLogic=new PlayPauseButtonLogic(refToButtonAsset)
//the warper class can extends EventDispatcher so you will be able to listen to custom or redisatched events
ppButtonLogic.addEventListener("ppPause",onPause)
}
hope it will help you
You can have two classes, one holding functionality and the other providing its graphical implementation (asset/skin)
Have PlayPauseButtonLogic extend AssetWrapper.
A simple way to solve your issue regarding event listeners, you can do the following:
package {
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.events.IEventDispatcher;
public class AssetWrapper implements IEventDispatcher {
private var _skin:DisplayObjectContainer;
public function AssetWrapper( skin:DisplayObjectContainer = null ) {
if ( skin ) setSkin(skin);
}
public function setSkin(skin:DisplayObjectContainer):void{
_skin = skin;
}
public function dispatchEvent(event:Event):Boolean{
_skin.dispatchEvent(event);
}
public function hasEventListener(type:String):Boolean{
return _skin.hasEventListener(type);
}
public function willTrigger(type:String):Boolean{
return _skin.willTrigger(type);
}
public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void{
_skin.removeEventListener(type, listener, useCapture);
}
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void{
_skin.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
}
}
EDIT:
You can then, of course, just add as many properties/methods to AssetWrapper that delegate to the DisplayObject (skin) as you need. It also gives you more control onto those properties/methods.
i.e:
public function get x( ):Number {
return _skin.x;
}
public function set x( v:Number ):void {
if ( _skin.x = v ) return;
if ( _useWholePixels ) _skin.x = Math.round(v);
else _skin.x = v;
}
That way, for instance, you can tween your AssetWrapper instance directly. Also, you can control if you want it to be placed in round numbers (x=100) or not (x=100.5)
For methods, just the same idea:
public function addChild( child:DisplayObject ):DisplayObject {
return _skin.addChild( child );
}
Then to use it, you would extend AssetWrapper and implement a concrete behavior:
package {
import flash.display.DisplayObjectContainer;
import flash.events.MouseEvent;
public class SimpleButton extends AssetWrapper {
public function SimpleButton( skin:DisplayObjectContainer = null ) {
super(skin)
}
override public function setSkin( skin:DisplayObjectContainer):void {
super.setSkin( skin );
addEventListener(MouseEvent.ROLL_OVER, _onRollOver );
addEventListener(MouseEvent.ROLL_OUT, _onRollOut );
}
protected function _onRollOver(e:MouseEvent):void {
_skin.alpha = .5;
}
...
}
And you would use it as follows:
//you can get your graphical assets in many different ways
var buttonSkin:Sprite = new LibraryButtonSkin
//or
var ButtonSkinClass:Class = this.loaderInfo.applicationDomain.getDefinition("SimpleButtonSkin") as Class;
buttonSkin = new ButtonSkinClass;
var button:SimpleButton = new SimpleButton(buttonSkin);
button.addEventListener(MouseEvent.CLICK, _handleButton);
It is just a guide, in the real implementation you want to make sure you check for things like if a skin already exists, then remove all added listeners. You would probably could listen for an ADDED_TO_STAGE event and trigger a initialize method...
Also is a great to clean up after your instance by implement a destroy() method where you make sure all added listeners are removed and null/stop things like timers, sounds, etc.
Wow all the flow and we sunk in the finish line....
well, what about something like this
AbstractButtonBehavior
PlayButtonBehavior extends...
The trick, the graphic components should all implement some interface that allow them to pass a behavior at instantiation time, or even better, at runtime. The you just plug the login in, the logic will always remain outside and the poor assets will keep asking or answering to the same interface call, allowing you to work outside them.
could be?.

Flash TextField HTML - How do I prevent the error dialogue for missing images? (Error #2044: Unhandled IOErrorEvent:. text=Error #2035: URL Not Found)

I'm using a Flash TextField control to display some HTML content inside a Flash presentation to be shown on a large touch-screen kiosk. Unfortunately, if any image tag in the displayed HTML content points to a non-existent image, a dialogue is shown with the error message
Error #2044: Unhandled IOErrorEvent:. text=Error #2035: URL Not Found.
I am trying to avoid having that dialogue pop up. The solution for loading content through a loader class is to catch IOErrorEvent.IO_ERROR, but I've tried listening for that on the TextField, on stage, Main and loaderInfo to no avail. I've tried wrapping the whole thing in a try-catch, and that also doesn't work.
Here's the simplified code I'm using to find solutions:
package {
import flash.display.Sprite;
import flash.errors.IOError;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.text.TextField;
import flash.text.TextFieldType;
public class Main extends Sprite {
public function Main():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
var html:TextField = new TextField();
html.type = TextFieldType.DYNAMIC;
html.multiline = true;
html.htmlText = "Bogus image: <img src=\"foo.jpg\" />";
addChild(html);
}
}
}
Edit: And here's the entire working code.
For dynamic content and so forth, of course, you would need a list of images and a function to generate handlers, etc.
package {
import flash.display.Loader;
import flash.display.Sprite;
import flash.errors.IOError;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.text.TextField;
import flash.text.TextFieldType;
public class Main extends Sprite {
public function Main():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
var html:TextField = new TextField();
html.type = TextFieldType.DYNAMIC;
html.multiline = true;
html.htmlText = "Bogus image: <img id=\"image\" src=\"foo.jpg\" />";
var loader:Loader = html.getImageReference("image") as Loader;
if(loader){
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, function(e:Event):void {
trace("Error loading foo.jpg!");
});
}
addChild(html);
}
}
}
You can add ID's to images
html.htmlText = "Bogus image: <img src=\"foo.jpg\" id="image" />";
And then setup IOErrorEvent handler to each image in HTML
var loader:Loader = html.getImageReference("image") as Loader;
if(loader){
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, function(e:Event):void{});
}
This is a cool problem.
I have two suggestions.
1) Don't use TextField. I'm guessing that you developed in Flash before Flex, like me. You may already know this, but it took me awhile to find out: The TextField object isn't meant to be used for regular use in Flex. Check this out from the Flex3 language ref:
The TextField class is used to create
display objects for text display and
input. All dynamic and input text
fields in a SWF file are instances of
the TextField class. You can use the
TextField class to perform low-level
text rendering. However, in Flex, you
typically use the Label, Text,
TextArea, and TextInput controls to
process text.
Obviously, there's nothing wrong with using TextField, but I've found that when I'm trying to figure out tricky problems, it's really helpful to do as much 'by the book' as I can to remove unknowns (as much as possible, at least).
2) I think I'd try either extending the Text component, or else creating a new component based on Text. In this component I'd add logic to load and insert images into the TextField object. That way, you could easily build and validate the string to insert into the TextField object prior to inserting it into the TextField.
If you get this working, please post - I could use it myself. :)
If there's a way for you to use the new FTE/TLF components, do so. Adobe is basically turning its back on the old TextField API, and this same error is a reason that I had to abandon many projects and components in the past. This error is thrown and basically cannot be caught. One of the worst aspects of Flash work in my opinion.
TLF addresses these problems and is SO much easier to work with. What would take days of experimentation in the old API now takes only a few hours. I've built a few rich text editors on the new API and it is SO very nice to use. You'll be glad you did :)
I was able to detect when an image has loaded, but I think I'll follow the TLF advice. anyways if you need to know, you have to implement an enter_frame event listener on the Loader and check for the contentInfo on the bytes property the Lenght, if the image hasn't load the length is 0xffffffff, if the image has loaded the length is the size of the file, and if there is an error the bytes properties es NULL.
var html:TextField = new TextField();
html.width=388.95;
html.height=400;
html.type = TextFieldType.DYNAMIC;
html.multiline = true;
html.htmlText = "Bogus image: <img id='image' src='foo.jpg'/>";
var loader:Loader = html.getImageReference("image") as Loader;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHan);
function completeHan(e:Event){
addChild(html);
}
This will work..
This is a problem I'm also dealing with: it's a real annoyance. I'd really like to be able to catch all the errors. I assumed you could say...
stage.addEventListener(IOError.IO_ERROR, myErrorHandler);
...but that doesn't seem to work, as you've pointed out.
Perhaps you can check to make sure the kiosk's flash player isn't the debug version. I don't think that the release version throws the dialogs (could be wrong).
Impossible! Same problem if you use the Loader to load images that doesnt exists! Flex is a framework and the Image class uses this flash Loader object but with plenty of lines of code (check out the source of SwfLoader...).
You can check your image URL before set the htmlText property or you can create your own component to display Text and Images..
I can't believe this simple & stupid bug is not still fixed by Adobe!

Resources