Skip to content
March 1, 2012 / Daniel Freeman

MadComponents + StageVideo, StageWebView, StageText. ExtendedMadness callouts

Version 0.7.1 of MadComponents, and version 0.1.3 of ExtendedMadness are available to download now.  These lightweight, free, and open-source UI frameworks are primarily for building AIR mobile and tablet applications.

Recently, another app using MadComponents has appeared on Apple’s app store:

http://itunes.apple.com/us/app/actionary/id486589156?ls=1&mt=8

This FREE app, by Andrew Wilson, was authored in Flash CS5.5, and uses MadComponents.  One of the great things about MadComponents is that it is IDE agnostic.  You don’t have to use Flash Builder.  You can use Flash Professional, ADT, FlashDevelop, etc.

MadComponents, Display List and Stage

MadComponents is built around a conventional display-list approach.  While I briefly considered a starling or Stage3D approach, the challenges and hurdles in doing this would have outweighed the benefits.  But it can be advantageous to mix MadComponents with StageVideo, StageText, StageWebView, and Stage3D.

stageRect()

MadComponents version 0.7.1 includes stageRect() methods, to help you out.

We’ve often used <image> as a placeholder.  To define an empty region inside the UI, where you might addChild() something custom.  Mixing MadComponents with Stage classes can also utilise an <image> placeholder.  But instead of addChild(), we obtain the stage coordinates of the <image> region, and put our Stage content there – so it seems integrated with the rest of the MadComponents UI.

This is where stageRect() comes in.

Consider the following layout:

<rows heights=”20,100%,50″>
     <label id=”label” alignH=”centre”>Stage Video Demo</label>
     <image id=”placeHolder”/>
     <button id=”button” width=”200″ alignH=”centre”>start</button>
</rows>

We have some text at the top of the screen, a button at the bottom.  Both centre aligned.  And between them, there’s a placeHolder for video, web, or stage3D graphics.  For example:-

To align your Stage class with the placeholder within the MadComponents UI, you just need to do this:

protected var _placeHolder:UIImage;

_placeHolder = UIImage( UI.findViewById(“placeHolder”) );

Obviously.  And then,

_stageVideo.viewPort = _placeHolder.stageRect();

The placeholder/stageRect()/viewPort approach can be utilised for StageText, Stage3D, or StageWebView, but let’s continue with this StageVideo example.

A video will have a certain aspect ratio.  But the placeholder size will depend on the size of the screen, and its orientation.  So, there’s an optional aspect ratio parameter.

_stageVideo.viewPort = _placeHolder.stageRect(ASPECT_RATIO);

This will return a rectangle viewport, of the desired aspect ratio, that fits inside the placeholder rectangle.  Neat huh?

Here’s a code sample:

package
{
	import com.danielfreeman.madcomponents.*;

	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.NetStatusEvent;
	import flash.events.StageVideoAvailabilityEvent;
	import flash.events.StageVideoEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.media.SoundTransform;
	import flash.media.StageVideo;
	import flash.media.StageVideoAvailability;
	import flash.media.Video;
	import flash.net.NetConnection;
	import flash.net.NetStream;

	public class MadVideo extends Sprite
	{
		protected static const ASPECT_RATIO:Number = 1.0;
		protected static const FILENAME:String = "gizmo.mp4";

		protected static const LAYOUT:XML =

	<rows heights="20,100%,30">
		<label id="label" alignH="centre">Stage Video Demo</label>
		<image id="placeHolder"/>
		<button id="button" width="280" alignH="centre">start</button>
	</rows>;

		protected var _label:UILabel;
		protected var _placeHolder:UIImage;
		protected var _button:UIButton;
		protected var _stageVideo:StageVideo;
		protected var _netConnection:NetConnection;
		protected var _netStream:NetStream;
		protected var _playing:Boolean = false;

		public function MadVideo(screen:Sprite = null) {
			if (screen)
				screen.addChild(this);

			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;

			UI.create(this, LAYOUT);
			addEventListener(UI.RESIZED, positionVideo);

			initialise();
			addEventListeners();
		}

		protected function initialise():void {
			_label = UILabel( UI.findViewById("label") );
			_placeHolder = UIImage( UI.findViewById("placeHolder") );
			_button = UIButton( UI.findViewById("button") );

			_netConnection = new NetConnection();
			_netConnection.connect(null);
			_netStream = new NetStream(_netConnection);
			_netStream.client = this;
		}

		protected function addEventListeners():void {
			_button.addEventListener(UIButton.CLICKED, startStopHandler);
			stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, onStageVideoState);
			_netStream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
		}

		protected function onStageVideoState(event:StageVideoAvailabilityEvent):void {
			if (event.availability == StageVideoAvailability.AVAILABLE) {
				_stageVideo = stage.stageVideos[0];
				_stageVideo.attachNetStream(_netStream);
			}
			else {
				_label.text = "Video not available";
				_button.visible = false;
			}
		}

		protected function positionVideo(event:Event = null):void {
			_stageVideo.viewPort = _placeHolder.stageRect(ASPECT_RATIO);
		}

		protected function startStopHandler(event:Event):void {
			if (_playing) {
				_netStream.pause();
				_button.text = "start";
				_playing = false;
			}
			else {
				_netStream.play(FILENAME);
				positionVideo();
				_button.text = "stop";
				_playing = true;
			}
		}

		protected function onNetStatus(event:NetStatusEvent):void {

		}

		// These are the methods required by _netstream.client delegate callback
		public function onCuePoint(value:Object):void {}
		public function onImageData(value:Object):void {}
		public function onMetaData(value:Object):void {}
		public function onSeekPoint(value:Object):void {}
		public function onTextData(value:Object):void {}
		public function onXMPData(value:Object):void {}
		public function onPlayStatus(value:Object):void {
			if(value.code == "NetStream.Play.Complete"){
				_netStream.seek(0);
			}
		}
	}
}

( Don’t forget <renderMode>direct</renderMode> in your application.xml file. You may also need some compiler options: -swf-version=14 )

Because StageVideo is only supported for Android HoneyComb 3.0 +, (and it doesn’t work at all simulated in ADL) it is always good to fall back to the conventional display list Video class if StageVideo is unavailable. You can addChild() the Video instance to the placeholder under these circumstances.

UIInput and stageRect()

There’s also a stageRect() method within UIInput, intended for use with StageText.  You could set up a listener for input focus, and if the user is about to enter text input, you can ensure that the user actually types into a StageText area over the <input> area.

	var input:UIInput = UIInput( UI.findViewById("input") );

	var stageTextInitOptions:StageTextInitOptions = new StageTextInitOptions(false);
	var stageText:StageText = new StageText();
	stageText.softKeyboardType = SoftKeyboardType.NUMBER;
	stageText.returnKeyLabel = ReturnKeyLabel.DONE;
//	stageText.autoCorrect = true;
	stageText.fontSize = 20;
	stageText.color = 0x0000FF;
	stageText.stage = this.stage;
	stageText.viewPort = input.stageRect();

(There seems to be a bug in ADL, that the rectangle may be too wide, but on a real device everything seems ok ).

ExtendedMadness Callouts

ExtendedMadness has a new callouts feature.  There are two kinds of callout.  A segmented control callout like this:-

And a form callout like this:-

It can be more sophisticated than just a couple of buttons if you like.  You declare the form as a MadComponents layout.

The layout for a segmented control layout looks like this:-

<data arrowPosition=”-30″>
    <new/>
    <open/>
    <save/>
</data>

Notice the arrowPosition attribute.  This specifies the horizontal position of the arrow.  A negative value is an arrow pointing up, a positive value is an arrow pointing down from the bottom of the segmented control.

The layout for the form callout looks like this:-

<vertical alignH=”fill” width=”180″ height=”90″>
        <button colour=”#669966″ id=”cancel”>cancel</button>
        <button colour=”#996666″ id=”ok”>ok</button>
</vertical>;
 

Notice that you have to specify the width and height of the callout form.  You may also specify an arrowPosition, although only positive values are allowed here, and the arrow always points upwards.  You can specify the colour of a callout with a background attribute.  eg: background=”#112211″.

So that’s the layout.  How do we put a callout on top of the UI?

For the segmented control callout do this:-

var callout:UICutCopyPaste = UICutCopyPaste( UIe.showCallOut(DATA, x, y) );

Where x,y are the coordinates of the tip of the arrow.  To handle button clicks, listen for UICutCopyPaste.CLICKED, and read callout.index for the index of the clicked segment.

Here’s the code for the form callout:-

var callout:UIDropWindow = UIDropWindow( UIe.showCallOut(LAYOUT, x, y) );

Now you can do callout.findViewById(…. etc… and treat it like any MadComponents layout.

It is up to you to remove callouts from the screen.

callout.destructor();
UI.windowLayer.removeChild(callout);

If you want a modal callout, you can utilise UI.dimUI(); to switch the UI into modal mode.  And UI.unDimUI(); to switch it back again.

Facebook Page

For community discussions about MadComponents, please join the facebook page:-

http://www.facebook.com/groups/336764056350846/

Advertisements

16 Comments

Leave a Comment
  1. TestWorks / Mar 2 2012 2:15 am

    I’d love to try out the new callout feature in my apps, but I can’t upgrade from 0.0.9 due to this issue:

    http://code.google.com/p/mad-components/issues/detail?id=19

    Do you know of any workarounds?

    • Daniel Freeman / Mar 2 2012 2:47 am

      I’ll just have some caffeine, and wake up a bit more – then I’ll look into it.

      ..later….

      Just wrap the data inside another XML tag (you can call it anything):-

      <segC><data>….etc…

      I couldn’t quite verify the rte you described – so let me know if this works for you.

      • TestWorks / Mar 3 2012 5:02 am

        Thanks – that got rid of the error, but now setting the .index property of the UISegmentedControl doesn’t fire the Event.CHANGE anymore, or highlight the selected item.

        Reading the property back returns the correct index though.

      • Daniel Freeman / Mar 3 2012 9:14 am

        I’ll have to fix the highlighting of the button when you set index. (next update – do you need it urgently?) It shouldn’t dispatch Event.CHANGE, so that’s ok.

      • TestWorks / Mar 3 2012 9:22 am

        Cool – no real hurry, I can stick with 0_0_9 in my app till it’s fixed 🙂

      • TestWorks / Apr 1 2012 3:18 am

        Hey Daniel,

        I tried ExtendedMadness 0.1.4 – the highlighting of the selected segment now works for the UISegmentedControl, but the first index of the segmented control’s text does not get populated.

        If you press one of the other segments, the text appears.

      • Daniel Freeman / Apr 1 2012 4:22 am

        That’s odd. I’ll look into it.

  2. Admin / Mar 7 2012 2:21 am

    hi Daniel,

    Have you considered to port this wonderful component sets to Stage3D/Starling ?

    • Fabio Biondi / Mar 12 2012 12:31 am

      I have the same question. No Stage3d support?
      It seems it’s not a good idea mix stage3d stuff with the display list because of performance issues.

      Anyway, thanks a lot for your work 🙂

      • Daniel Freeman / Mar 12 2012 5:21 am

        There are some things the display list does better. Like text, and vector graphics. And MadComponents relies quite heavily on both of those. I did think quite hard about whether it was possible, or advantageous to convert MadComponents to starling or Stage3D – and in the end, I decided there were no clear advantages in doing so.

        (But if someone else wants to try that’s ok)

        Previously, there were problems with setting the renderMode to gpu, but the latest versions have alleviated those issues. So the display list is fast enough for what MadComponents does.

        Performance issues? You mean how Stage3D needs rendermode=direct?, not gpu?

  3. Lance / Mar 7 2012 4:52 am

    I’m trying to implement one of the new callouts, and I’m not seeing UIDropDownWindow as an option. I’m working with the latest SWC of both MadComponents (0.7.1) and ExtendedMadness (0.1.3). I see UIDropWindow as an option, but not UIDropDownWindow. When I try to produce a callout following the example you provided in this post, I get the error:

    1118: Implicit coercion of a value with static type flash.display:DisplayObject to a possibly unrelated type com.danielfreeman.extendedMadness:UIDropWindow.

    Did the name of the callout class change since the release of the new components by chance? Thanks for your time.

    • Daniel Freeman / Mar 8 2012 2:01 am

      Apologies. I made some mistakes in the explanation. I’ve corrected it now.

      • Lance / Mar 9 2012 2:34 am

        Great, thank you! 🙂

  4. Jon Tetzlaff / May 9 2012 5:58 pm

    Is there a way to have the callout be more dynamic? What I mean is that I want it to expand to the size of the contents it contains and not set a specific height. Thanks.

  5. Malik Farhan / Nov 13 2013 12:46 pm
    • Daniel Freeman / Nov 13 2013 2:36 pm

      Apologies. WordPress corrupted the XML that I pasted in. I’ve corrected it now. (What’s odd is that you were the first person to notice, after all this time).

To discuss MadComponents/MC3D, join the Facebook group!

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: