Monday, June 28, 2010

Flex 4 Spark Resizable Controls

Please go here for Flex 3 Resizable Containers.

I've created a bunch of skins for many of the common Spark components that allows them to be resized. Each of these skins contains a resizeHandle that when dragged allows the control to be resized. There are two resize handle classes that you can use, the default is called flex.utils.spark.resize.ResizeHandleLines. You can replace every occurrence of that class with flex.utils.spark.resize.ResizeHandleDots if you prefer.

Here are a list of resize skins:

With the exception of the ResizableLabel class, all the others are Skins, and as such can be used very simply by setting the skinClass="flex.utils.spark.resize.___Skin" property to the appropriate skin.

Another option is to create a CSS style for ALL spark.components.Scroller classes to use the flex.utils.spark.resize.ResizableScrollerSkin class like this:
<fx:Style>
@namespace "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";
@namespace spark "flex.utils.spark.*";
@namespace resize "flex.utils.spark.resize.*";

/* Make all Scroller's use the resizable scroller skin. */
s|Scroller {
  skin-class: ClassReference("flex.utils.spark.resize.ResizableScrollerSkin");

</fx:Style>

** Note that I've renamed the Flex3 package flex.utils.ui.resize.* to the new Flex4/Spark package name flex.utils.spark.resize.*.

The most used skin is the ResizableScrollerSkin, it is used on TextAreas, Lists, DataGrids, Trees, ComboBoxes, DropDownLists, and anything else that uses a Scroller component. The way it works is to use a skin for the Scroller that adds the resize handle and uses custom HScrollBar and VScrollBar classes which leave room for the resize handle (the simplest way I could think to do it). Each of the resizable skins uses the ResizeManager class to handle the mouse events and resize the appropriate control.

The resizable ComboBox and DropDownList skins are slightly different in that they both save the size of the drop down list since it gets destroyed and re-created each time. It also sets the popUpWidthMatchesAnchorWidth="false" after resizing since the width no longer matches the anchor.

I've also added support for restricting the resize in only the vertical or horizontal direction. There are many ways you can do this, you can either set a style on the resize component:
.resizePanel {
  resize-direction: vertical; /* or horizontal */
}
Or you can call a static method on the ResizeManager class:
ResizeManager.setResizeDirection(resizePanel, "vertical"); // or "horizontal"
Or if you can access the ResizeManager class (usually stored in the skin class), then you can set the resizeDirection property on the manager like this:
resizeManager.resizeDirection = "vertical"; // or "horizontal";
There are constants defined in the ResizeManager class for "vertical", "horizontal", and "both" (default).

September 30th, 2010 Update:
I've added a new skin called ResizableDraggableTitleWindowSkin that uses the MoveManager class to allow dragging the TitleWindow around the screen. It also adds a small drag handle in the titlebar too.
The same could be done for other classes (e.g. Panel) by following the same procedure. All that is required is a dragComponent (the component that listens for mouse drag events) and a moveComponent (the component that gets moved - in this case it is the TitleWindow).

Here is an example of most of the skins, view-source enabled.

Tuesday, June 1, 2010

TitledBorderBox (Flex 4/Spark)

I've re-written my original TitledBorderBox class (Flex 3) to use Spark/Flex 4 components. It is slightly simpler, and hopefully more lightweight. It extends the SkinnableContainer class, and uses it's own skin (flex.utils.ui.TitledBorderBoxSkin).

Here are the properties on the component:
  • backgroundAlpha - the background alpha for the box (default: 1)
  • backgroundColor - the background color for the box (default: white)
  • backgroundVisible - if the background should be shown (default: true)
  • borderAlpha - the border alpha for the box (default: 1)
  • borderColor - the border color for the box (default: black)
  • borderWeight - the thickness of the border (default: 1)
  • borderVisible - if the border should be shown (default: true)
  • cornerRadius - the corner radius for rounded corners (default: 0)
  • dropShadowVisible - if a drop shadow is shown (default: false)
  • titleStyleName - the style name for the title label (default "windowStyles")
  • title - the title to show in the border
It also supports most of the layout properties too as styles (paddingLeft/Right/Top/Bottom, gap/horizontalGap/verticalGap, horizontal/verticalAlign, etc) for convenience.

The way the border is drawn is to simply draw a line over top of the border, but underneath the title that is the same color as the background. If you set borderVisible="false", then it will attempt to find the background color of the parent and use that instead.

Here it is in action (view source enabled, right click):