Showing posts with label quick tip. Show all posts
Showing posts with label quick tip. Show all posts

Monday, 24 October 2011

Quick Tip: Flex 4.5 Form Spacing

Users of the new Flex 4.5 Form will notice that the vertical spacing between FormItems is quite significant. A quick fix to this is to alter the gap of the layout, e.g.:

<s:Form>
  <s:layout>
    <s:FormLayout gap="-14"/> 
  </s:layout>

...

</s:Form>

Do note, however, that this will cause layout issues when adding controls to the Form that are not wrapped in FormItems. An alternative solution is to roll a custom FormItem skin which alters the  row constraint declaration as follows:

<s:constraintRows>
  <!--- @private -->
  <s:ConstraintRow id="row1" baseline="maxAscent:0" height="100%"/>
</s:constraintRow>

instead of the default

<s:constraintRows>
  <!--- @private -->
  <s:ConstraintRow id="row1" baseline="maxAscent:10" height="100%"/>
</s:constraintRow>

Sunday, 25 September 2011

Quick Tip: Ignoring XML Namespaces

This is another small follow up to Common Mistakes: XML Namespaces and E4X: sometimes you may wish to completely ignore the namespace information, rather than explicitly traverse it. Consider the following example:

var xml: XML = <root xmlns:space="http://www.something.com">
 <space:tag>
  <node>Hello, world!</node>
 </space:tag>
</root>;

It is possible to reference node containing Hello, world! using the following:

var node: XML = xml.*::space.node;

Sunday, 14 August 2011

Quick Tip: Checking for XML nodes with a namespace

This is a small follow up to Common Mistakes: XML Namespaces and E4X: when working with namespaces, calling hasOwnProperty() may not work as expected. Consider the following example:

var xml: XML = <root xmlns:space="http://www.something.com">
 <space:tag>
  <node>Hello, world!</node>
 </space:tag>
</root>;

trace( xml.hasOwnProperty( "tag" ) );

In this case, hasOwnProperty() will return false as the 'tag' tag is part of the 'space' namespace. In order to overcome this, use the QName construct, e.g.:

xml.hasOwnProperty( new QName( "http://www.something.com", "tag" ) )

Alternatively, if you have declared a namespace previously, you can do the following:

namespace space = "http://www.something.com"; 

// ...

xml.hasOwnProperty( new QName( space, "tag" ) )

Thursday, 11 August 2011

Quick Tip: FlashBuilder 4.5 Premium Upgrade Download

Just a really quick one: Adobe's consumer site (in Australia, at least) does not have the option to allow the FlashBuilder 4 Premium to FlashBuilder 4.5 Premium Upgrade to be purchased as a download - it's only available as a shipped box. if you need it quicker than that, the solution is to purchase it from the Adobe Business site instead: http://volumelicensing.adobe.com/AU Note that a serial and download link is not provided immediately; after roughly 24 hours you will receive access to the Adobe Volume Licensing site where you can access these details.

Thursday, 21 July 2011

Quick Tip: Passing Varargs Parameters

Occasionally the need arises to pass the varargs parameters of a function directly onto another function that accepts varargs, such as if you are writing a wrapper or using a Composite or Decorator pattern to add complimentary behaviour. Suppose we have the following interface:

package
{
 public interface IMyInterface
 {
  function myFunction( singular: String, ... varargs ): void;
 }
}

If we're implementing a basic Decorator-style pattern to extend some functionality, we're going to want to pass the parameters on to the child unaffected. If we tried the following:

package
{
 public class NewFeature implements IMyInterface
 {
  private var _child: IMyInterface;

  public function NewFeature( child: IMyInterface )
  {
   _child = child;
  }

  public function myFunction( singular: String, ... varargs ): void
  {
   _child.myFunction( singular, varargs );
  }
 }
}

Then the varargs will get passed to the child function's varargs parameter as a single array, rather than the unrolled varargs. That is, assuming we had the following:

package
{
 public class CoreFeature implements IMyInterface
 {
  public function myFunction( singular: String, ... varargs ): void
  {
   trace( "Singular: " + singular );
   trace( "Varargs: " + varargs );
  }
 }
}

and then made a call as per:

var feature: IMyInterface = new NewFeature( new CoreFeature(  ) );

feature.myFunction( "foo", "bar", "qwerty", "asdf" );

Then the debug console would contain the following output:

Singular: foo
Varargs: [ [ bar, qwerty, asdf ] ]

That is, when passing the varargs variable to a function call, it is treated as an array. Thus, when it is passed on to a varargs parameter, it becomes the first element of the subsequent varargs array.

The fix here is to use some basic runtime reflection to call the function, rather than invoking it directly. By using the Function.apply() method, we're able to pass an array of parameters into the function call. AVM2 will correctly match up the explicit parameters, and then group the rest into the varargs variable. For example:

package
{
 public class NewFeature
 {
  private var _child: IMyInterface;

  public function myFunction( singular: String, ... varargs ): void
  {
   varargs.unshift( singular );
   _child.myFunction.apply( _child, varargs );
  }
 }
}

In this example, we need to stick singular at the start of the array, so that it is correctly applied to the child function.

Calling the function as per the example above, would now result in the following debug console output:

Singular: foo
Varargs: [ bar, qwerty, asdf ]