Sei sulla pagina 1di 14

Tutorial 4 - Creating a custom property sheet

Copyright

2009 SAP AG. All rights reserved.SAP, R/3, SAP NetWeaver, Duet, PartnerEdge, ByDesign, SAP Business ByDesign, and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of SAP AG in Germany and other countries. Business Objects and the Business Objects logo, BusinessObjects, Crystal Reports, Crystal Decisions, Web Intelligence, Xcelsius, and other Business Objects products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of Business Objects S.A. in the United States and in other countries. Business Objects is an SAP company.All other product and service names mentioned are the trademarks of their respective companies. Data contained in this document serves informational purposes only. National product specifications may vary.These materials are subject to change without notice. These materials are provided by SAP AG and its affiliated companies ("SAP Group") for informational purposes only, without representation or warranty of any kind, and SAP Group shall not be liable for errors or omissions with respect to the materials. The only warranties for SAP Group products and services are those that are set forth in the express warranty statements accompanying such products and services, if any. Nothing herein should be construed as constituting an additional warranty. 2009-11-03

Tutorial 4 - Creating a custom property sheet Introduction

Introduction
This tutorial assumes that you have at least some knowledge of Cascading Style Sheet (CSS), ActionScript 3.0, and MXML, the XML-based markup language introduced by Adobe Flex. The concentration of the tutorial is creating a custom property sheet for those who do not want to use the default property sheet. We will include Flex controls in the property sheet so that all of the properties and styles of the custom component can be exposed. We will also use a sample CSS definition to style the property sheet to look more like the Xcelsius color scheme. Download the source code for the custom component so that you could see what properties and styles it has. You will need to reference the names of the properties/styles inside the property sheet source code. For demonstration purposes, only the basic controls for the layout of custom property sheet are mentioned. Please see the CustomPropSheetHorizon talSlider sample source code for a more advanced layout.

Task 1: Creating a basic Flex project


1. Create a basic Flex project for the custom property sheet. . For details on creating a project and adding the framework, refer to the Xcelsius 2008 Component SDK SP1 User Guide section Create a visual component. 2. Open the Flex project application MXML file. 3. Inside of the <mx:Application> tag, add applicationCom plete="init();".

Task 2: Designing the layout for the property sheet


1. Switch to Design mode by pressing the Design button located next to the Source button. 2. Design the layout of the custom property sheet. Add the following controls to the layout:

Tutorial 4 - Creating a custom property sheet

Tutorial 4 - Creating a custom property sheet Task 2: Designing the layout for the property sheet

Viewstack: id=viewstack1, creationPolicy=all, left=0, right=0, y=45, height=100%, width=100%, minWidth=268, minHeight=350 Canvas: id=general, label=General, minWidth=268, minHeight=350, width=100%, height=100% Label: text=Title, x=23, y=24, width=119 HRule: y=28, height=10, right=28, left=59 TextInput: id=titleEditor, change=proxy.setProperty('title', titleEditor.text), y=52, right=69, left=37 Label: text=Value, x=23, y=116, width=119 HRule: y=118, height=10, right=28, left=66 TextInput: id=valueEditor, change=proxy.seProperty('value', Number(valueEditor.text)), y=144, right=69, left=37 Button: click=initiateBind('value'), icon=@Embed('resources/bind to cell.png'), y=143, right=37, width=24 Canvas: id=appearance, label=Appearance, minWidth=268, minHeight=350, width=100%, height=100% Label: text=Text, x=23, y=23, text=Text, width=119 HRule: y=28, height=10, right=28, left=56 CheckBox: id=showTitleEditor, label=Show Title, change=proxy.setProperty('showTitle', showTitleEditor.selected), selected=true, x=43, y=54 ComboBox: id=titleFontFamilyEditor, dataProvider={_fontNames}, change=proxy.setStyle('titleFontFamily', titleFontFamilyEditor.value), x=94, y=79, width=129 ComboBox: id=titleFontSizeEditor, dataProvider={_fontSizes}, change=proxy.setStyle('titleFontSize', titleFontSizeEditor.value), x=231 y=79 width=55 Label: text=Color, x=23, y=136, width=119 HRule: y=141, height=10, right=28, left=62 Label: text=Title Color, x=43, y=169, text=Title Color:, width=116 ColorPicker: id=titleColorEditor, change=proxy.setStyle('titleFontColor', uint(titleColorEditor.selectedColor)), x=137, y=169

TabBar: dataProvider=viewstack1

Tutorial 4 - Creating a custom property sheet

Tutorial 4 - Creating a custom property sheet Task 2: Designing the layout for the property sheet

3. After laying out the controls, switch to Source mode, you should have the following code: <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="ab solute" applicationComplete="init();"> <mx:ViewStack id="viewstack1" creationPolicy="all" left="0" right="0" y="45" height="100%" width="100%" minWidth="268" minHeight="350"> <mx:Canvas id="general" label="General" min Width="268" minHeight="350" width="100%" height="100%"> <mx:Label x="23" y="24" text="Title" width="119"/> <mx:HRule y="28" height="10" right="28" left="59"/> <mx:TextInput id="titleEditor" y="52" right="69" left="37" change="proxy.setProperty('ti tle',titleEditor.text)"/> <mx:Label x="23" y="116" text="Value" width="119"/> <mx:HRule y="118" height="10" right="28" left="66"/> <mx:TextInput id="valueEditor" y="144" right="69" left="37" change="proxy.setProperty('value', Number(valueEditor.text))"/> <mx:Button y="143" right="37" width="24" click="initiateBind('value');" icon="@Embed('re sources/bind to cell.png')"/> </mx:Canvas> <mx:Canvas id="appearance" label="Appearance" minWidth="268" minHeight="350" width="100%" height="100%"> <mx:Label x="23" y="23" text="Text" width="119"/> <mx:HRule y="28" height="10" right="28" left="56"/> <mx:CheckBox id="showTitleEditor" x="43" y="54" label="Show Title" change="proxy.setProper ty('showTitle', showTitleEditor.selected)" select ed="true"/> <mx:ComboBox id="titleFontFamilyEditor" dataProvider="{_fontNames}" x="94" y="79" width="129" change="proxy.setStyle('titleFontFamily', titleFont FamilyEditor.value)" /> <mx:ComboBox id="titleFontSizeEditor" dataProvider="{_fontSizes}" x="231" y="79" width="55" change="proxy.setStyle('titleFontSize', titleFont

Tutorial 4 - Creating a custom property sheet

Tutorial 4 - Creating a custom property sheet Task 3: Creating a CSS File

SizeEditor.value)" /> <mx:Label x="23" y="136" text="Color" width="119"/> <mx:HRule y="141" height="10" right="28" left="62"/> <mx:Label x="43" y="169" text="Title Col or:" width="116"/> <mx:ColorPicker id="titleColorEditor" x="137" y="169" change="proxy.setStyle('titleFontCol or', uint(titleColorEditor.selectedColor))" /> </mx:Canvas> </mx:ViewStack> <mx:TabBar x="0" y="0" dataProvider="viewstack1"> </mx:TabBar> </mx:Application>

Task 3: Creating a CSS File


1. Immediately after <mx:Application> and before <mx:ViewStack>, add the following tags: <mx:Style /> <mx:Script> <![CDATA[ ]]> </mx:Script> 2. Right click on the project folder in the Navigation window and create a new folder named style; then import PSStyle.css, located in the SDK install folder: SDK\samples\CustomPropSheetHorizontalSlid er\CustomPropSheetHorizontalSliderPropertySheet\style\. This CSS definition file contains several tags that define the styles for each of them. These styles definitions were chosen because they closely match Xcelsius property sheet styles: background color is #F4F3EE, fontFamily is Tahoma, text color is black, etc. 3. Modify the source of <mx:Style> tag to include PSStyle.css: <mx:Style source="style\PSStyle.css"/>

Tutorial 4 - Creating a custom property sheet

Tutorial 4 - Creating a custom property sheet Task 4: Handling communication between property sheet and the component

Task 4: Handling communication between property sheet and the component


Task 4 is divided into five subtasks, 4a through 4e. In the first subtask, you will import classes from the Xcelsius SDK framework. In the remaining subtasks, you will implement the following functions: init():void initializes the property sheet on load getPropertyBindDisplayName(propertyName:String):String returns the bind display name or null if not Bound. initiateBind(propertyName:String):void allows the user of the component to bind the Excel spreadsheet cell to an Xcelsius custom component property/style. continueBind(bindingID:String):void completes the binding when the user has finished selecting the cell to bind to or cleared the binding.

Subtask 4a: Importing classes and creating local variables


Inside CData section, include the following segments of code: import import import import mx.containers.*; mx.controls.*; mx.core.Container; mx.events.FlexEvent;

import xcelsius.binding.BindingDirection; import xcelsius.binding.tableMaps.input.In putBindings; import xcelsius.binding.tableMaps.output.Out putBindings; import xcelsius.propertySheets.impl.Proper

Tutorial 4 - Creating a custom property sheet

Tutorial 4 - Creating a custom property sheet Task 4: Handling communication between property sheet and the component

tySheetExternalProxy; import xcelsius.propertySheets.inter faces.PropertySheetFunctionNamesSDK; [Bindable] private var _fontNames:Array = []; [Bindable] protected var _fontSizes:Array = new Ar ray("8", "9", "10", "11", "12", "14", "16", "18", "20", "22"); protected var proxy:PropertySheetExternal Proxy = new PropertySheetExternalProxy(); protected var propertyToBind:String; protected var currentBindingID:String; _fontNames will contain system fonts that the user can choose from. _fontSizes is the list of selectable font sizes.

Both of these variables need to be bindable since we bind them to the data providers of the combo boxes on the "Appearance" tab. Variable proxy is the Xcelsius proxy that enables communication between the property sheet and the custom component. The package xcel sius.propertySheets.impl.PropertySheetExternalProxy for the proxy is the implementation of the interface xcelsius.proper tySheets.interfaces.IPropertySheetProxy, which are both included in the xcelsiusframework.swc. Variable propertyToBind stores the name of the property that the user is binding, and currentBindingID stores the current binding id (null if there's no binding) for the property.

Subtask 4b: Implementing init() function


The function init() sets the callback to continueBind method when the user is picking Excel cell(s) to bind to, and then notifies Xcelsius that it has finished loading the property sheet. Refer to the API Documentation for the list of function name constants. The retrieval of the list of system fonts is

Tutorial 4 - Creating a custom property sheet

Tutorial 4 - Creating a custom property sheet Task 4: Handling communication between property sheet and the component

implemented here. Lastly, it makes a call to initValues method that initializes the property sheet on load with default property/style values. protected function init():void { proxy.addCallback(PropertySheetFunction NamesSDK.RESPONSE_BINDING_ID, this.continueBind); proxy.callContainer(PropertySheetFunction NamesSDK.INIT_COMPLETE_FUNCTION); var allFonts:Array = Font.enumerate Fonts(true); allFonts.sortOn("fontName", Array.CASEIN SENSITIVE); var numFonts:int = allFonts.length; for (var i:int=0; i<numFonts; i++) { var font:Font = allFonts[i]; _fontNames.push(font.fontName); } initValues(); }

Subtask 4c: Implementing initValues() function


In initValues(), we first get the array of values for the Xcelsius custom component properties using proxy.getProperties method, then the array of values for the styles using proxy. getStyles method. Both methods need a list of property or style names passed in as an array of strings. Next, we process through the arrays retrieving the name and value of each property and style, and either displaying that value to the corresponding control's default value or the cell address(es) if bound to the Excel spreadsheet. If a property has binding capability, make use of getProper tyBindDisplayName method and add an if-else statement to handle that correctly. protected function initValues():void { // Process the array of values for the Xcelsius custom component properties. var propertyValues:Array = proxy.getProp erties(["title", "value","showTitle"]); var propertyValuesLength:int = (property

Tutorial 4 - Creating a custom property sheet

Tutorial 4 - Creating a custom property sheet Task 4: Handling communication between property sheet and the component

Values != null ? propertyValues.length : 0); for (var i:int=0; i < propertyVal uesLength; i++) { var propertyObject:Object = property Values[i]; var propertyName:String = propertyOb ject.name; var propertyValue:* = propertyOb ject.value; var bindingText:String = ""; switch (propertyName) { case "title": titleEditor.text = String(propertyValue); break; case "value": bindingText = getPropertyBind DisplayName(propertyName); if (bindingText != null) { valueEditor.enabled = false; valueEditor.text = bind ingText; } else { valueEditor.text = prop ertyValue; } break; case "showTitle": showTitleEditor.selected = Boolean(propertyValue); break; default: break; } } // Process the array of values for the custom component styles. var styleValues:Array = proxy.get Styles(["titleFontFamily", "titleFontColor", "titleFont Size"]); var styleValuesLength:int = (styleValues != null ? styleValues.length : 0);

10

Tutorial 4 - Creating a custom property sheet

Tutorial 4 - Creating a custom property sheet Task 4: Handling communication between property sheet and the component

for (var j:int=0; j < styleValuesLength; j++) { var styleObject:Object = styleVal ues[j]; var styleName:String = styleOb ject.name; var styleValue:* = styleObject.value; var bindingTextStyle:String = ""; switch (styleName) { case "titleFontColor": titleColorEditor.selectedCol or = uint(styleValue); break; case "titleFontFamily": titleFontFamilyEditor.selecte dIndex = _fontNames.indexOf(styleValue); break; case "titleFontSize": titleFontSizeEditor.selecte dIndex = _fontSizes.indexOf(styleValue); var index:int; index = _fontSizes.index Of(styleValue.toString()); if (index != -1) { titleFontSizeEditor.se lectedIndex = index; } else if (!isNaN(styleValue)) { titleFontSizeEditor.text = styleValue.toString(); } else { titleFontSizeEditor.se lectedIndex = -1; } break; default: break; } } }

Tutorial 4 - Creating a custom property sheet

11

Tutorial 4 - Creating a custom property sheet Task 4: Handling communication between property sheet and the component

Subtask 4d: Implementing getPropertyBindDisplayName and initiateBind functions


Given a property name, getPropertyBindDisplayName gets the array of bindings for that property by calling proxy.getBindings method. If we have at least one binding for that property then pick the first one. protected function getPropertyBindDisplay Name(propertyName:String):String { var propertyBindings:Array = proxy.get Bindings([propertyName]); if ((propertyBindings != null) && (prop ertyBindings.length > 0) && (propertyBindings[0].length > 0)) { var bindingID:String = propertyBind ings[0][0]; return proxy.getBindingDisplay Name(bindingID); } return null; } Given a property name, initiateBind allows the user to select the Excel spreadsheet cell(s) to bind to an Xcelsius custom component property. If there is an existing binding for that property, show that in the Excel binding selection window and store the currentBindingID (null if there is no current binding) in case we "continueBinding". Use the function proxy.re questUserSelection method to let the user choose where to bind to in the Excel spreadsheet. protected function initiateBind(property Name:String):void { currentBindingID = null; var propertyBindings:Array = proxy.get Bindings([propertyName]); if ((propertyBindings != null) && (prop ertyBindings.length > 0)) { currentBindingID = propertyBind

12

Tutorial 4 - Creating a custom property sheet

Tutorial 4 - Creating a custom property sheet Task 4: Handling communication between property sheet and the component

ings[0]; } propertyToBind = propertyName; proxy.requestUserSelection(current BindingID); }

Subtask 4e: Implementing continueBind function


continueBind method completes the binding when the user has finished selecting the cell(s) to bind to or cleared the binding. Again, we process through each property that has binding capability to do the following: filling the control with current value and set property when the user explicitly clears binding, disabling the option to manually enter a value once the component if the property is bound, displaying the range address, and the actual binding using proxy.bind method. BindingDirection.BOTH updates the custom component property when the spreadsheet changes and also updates the spreadsheet when the custom component changes. InputBindings.SIN GLETON writes to a single cell in the spreadsheet. OutputBindings.SIN GLETON reads a single cell in the spreadsheet. For more information on bindings and the custom property sheet API, refer to Appendix B in the Xcelsius 2008 Component SDK SP1 User Guide. protected function continue Bind(bindingID:String):void { var propertyName:String = propertyToBind; var propertyValues:Array; var propertyObject:Object; var bindingAddresses:Array; if (currentBindingID != null) { proxy.unbind(currentBindingID); currentBindingID = null; } switch (propertyName) { case "value": if ((bindingID == null) || (bindingID == ""))

Tutorial 4 - Creating a custom property sheet

13

Tutorial 4 - Creating a custom property sheet Task 4: Handling communication between property sheet and the component

{ valueEditor.enabled = true; propertyValues = proxy.get Properties([propertyName]); propertyObject = propertyVal ues[0]; valueEditor.text = property Object.value; proxy.setProperty(property Name, propertyObject.value); return; } valueEditor.enabled = false; valueEditor.text = proxy.getBind ingDisplayName(bindingID); proxy.bind("value", null, bindingID, BindingDirection.BOTH, InputBindings.SINGLE TON, OutputBindings.SINGLETON); break; default: break; } } Save and build.

14

Tutorial 4 - Creating a custom property sheet

Potrebbero piacerti anche