blob: 276147aa364aa0aec2b264791cbe0b188364ccb5 [file] [log] [blame]
<?xml version="1.0" encoding="utf-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:c="com.flexcapacitor.controls.*"
xmlns:handlers="com.flexcapacitor.handlers.*"
xmlns:collections="com.flexcapacitor.effects.collections.*"
minWidth="200"
minHeight="100"
creationComplete="group1_creationCompleteHandler(event)"
>
<!--
TODO:
-->
<fx:Script>
<![CDATA[
import com.flexcapacitor.controller.Radiate;
import com.flexcapacitor.events.RadiateEvent;
import com.flexcapacitor.model.EventMetaData;
import com.flexcapacitor.model.MetaData;
import com.flexcapacitor.utils.ClassUtils;
import com.flexcapacitor.utils.InspectorUtils;
import com.flexcapacitor.utils.TypeUtils;
import mx.collections.XMLListCollection;
import mx.core.IDataRenderer;
import mx.core.UIComponent;
import mx.effects.effectClasses.PropertyChanges;
import mx.events.FlexEvent;
import mx.utils.ObjectUtil;
import spark.collections.Sort;
import spark.collections.SortField;
import spark.components.gridClasses.DefaultGridItemEditor;
import spark.components.gridClasses.GridColumn;
import spark.events.GridItemEditorEvent;
import spark.events.GridSelectionEvent;
import spark.events.TextOperationEvent;
import flashx.textLayout.operations.SplitParagraphOperation;
public var CUSTOM_ITEM_SORT_CHARACTER:String = "~";
private var allItems:XMLListCollection = new XMLListCollection();
private var objectPropertiesList:XMLListCollection = new XMLListCollection();
private var _dataProviderProperties:XMLListCollection;
public var describedTypeXML:XML;
protected function group1_creationCompleteHandler(event:FlexEvent):void {
radiate = Radiate.getInstance();
if (!showHeader) {
//propertiesGrid.columnHeaderGroup.visible = showHeader;
eventsGrid.columnHeaderGroup.height = hiddenHeaderHeight;
}
radiate.addEventListener(RadiateEvent.TARGET_CHANGE, handleTargetChange);
radiate.addEventListener(RadiateEvent.PROPERTY_CHANGED, propertyChangeHandler);
if (radiate.target) {
target = radiate.target;
}
}
protected function handleTargetChange(event:RadiateEvent):void {
target = event.selectedItem;
}
public function get dataProviderProperties():XMLListCollection {
return _dataProviderProperties;
}
[Bindable]
public function set dataProviderProperties(value:XMLListCollection):void {
if (_dataProviderProperties) {
_dataProviderProperties = new XMLListCollection(new XMLList());
}
value.sort = new Sort();
value.sort.fields = [ new SortField("@name", false)];
value.refresh();
_dataProviderProperties = value;
}
/**
* Get Name or ID of target object
* */
public function getName(element:Object):String {
var id:String;
if (element is UIComponent && element.id != null) {
id = UIComponent(element).id;
}
else if (element.hasOwnProperty("id") && element.id != null) {
id = element.id;
}
else if (element.hasOwnProperty("name") && element.name != null) {
id = element.name;
}
else {
id = "";
}
return id;
}
/**
* Populates the datagrid with all the properties that describe type returns for the given object
* */
public function populatePropertiesGrid(target:Object):void {
var eventsList:XMLListCollection;
var propertyName:String;
var fontLookup:String;
var fontFamily:String;
var renderingMode:String;
var properties:String;
var inheritingStyles:Object;
var nonInheritingStyles:Object;
var property:String;
var item:XML;
if (target != null) {
//describedTypeXML = describeType(target);
//var type:Type = Type.forInstance(target);
//var type2:Type = Type.forName(type.extendsClasses[0]);
//describedTypeXML = describeType(getDefinitionByName(type.extendsClasses[0]));
//var describedType:XML = ClassUtils.describeTypeCache(target);
var data:XMLList = ClassUtils.concatenateMetaDataXMLItems(target, "Event", new XMLList());
//describedTypeXML = describeType(target);
eventsList = new XMLListCollection(data);
// ADD ACCESSORS LIST
allItems.addAll(eventsList);
// if item is an object enumerate
/*if (describedTypeXML.@name=="Object") {
for (property in target) {
item = createXMLItem(property, target[property], true, true);
objectPropertiesList.addItem(item); // we could use allItems.addItem();
}
}*/
//allItems.addAll(objectPropertiesList);
/* var blah:Object = getMemberNames(this, true);
blah = getMemberNames(this);
blah = nonInheritingStyles;
blah = styleDeclaration;
blah = styleName;
blah = styleManager.inheritingStyles;
blah = styleManager.qualifiedTypeSelectors;
blah = styleManager.selectors;
blah = styleManager.stylesRoot;
blah = styleManager.typeHierarchyCache;
blah = styleManager.typeSelectorCache;
blah = styleManager.hasAdvancedSelectors(); */
if (filterInput) filterInput.text = "";
// we check for the text flow property so we can see if fonts are embedded
if (target.hasOwnProperty("textFlow")) {
/* if (target.textFlow.computedFormat) {
fontLookup = target.textFlow.computedFormat.fontLookup;
fontFamily = target.textFlow.computedFormat.fontFamily;
renderingMode = target.textFlow.computedFormat.renderingMode;
fontLookup = "<accessor name='fontLookup' value='" + fontLookup + "'/>";
fontFamily = "<accessor name='fontFamily' value='" + fontFamily + "'/>";
renderingMode = "<accessor name='renderingMode' value='" + renderingMode + "'/>";
properties = fontLookup + fontFamily + renderingMode + propertiesList.toString();
propertiesList = new XMLList(properties);
} */
}
//allItems.addAll(propertiesList);
// attempts to get the values of the properties on the current target
for each (var node:XML in allItems) {
propertyName = node.@name;
if (node.@access != "writeonly") {
if (propertyName in target) {
try {
node.@value = target[propertyName];
node.@isObject = (target[propertyName] is Object);
}
catch (error:Error) {
node.@value = error.message;
node.@valueError = true;
}
}
}
}
// Add in inheriting styles
/*if ("inheritingStyles" in target) {
inheritingStyles = target.inheritingStyles as Object;
for (property in inheritingStyles) {
item = createXMLItem(property, inheritingStyles[property], true, true);
inheritingStylesList.addItem(item);
}
//trace("Inheriting style count", inheritingStylesList.length);
//allItems.addAll(inheritingStylesList);
}*/
// Add in non inheriting styles -
/*if (target.hasOwnProperty("nonInheritingStyles")) {
nonInheritingStyles = target.nonInheritingStyles as Object;
for (property in nonInheritingStyles) {
item = createXMLItem(property, nonInheritingStyles[property], true, false);
nonInheritingStylesList.addItem(item);
}
//trace("Non-Inheriting style count", nonInheritingStylesList.length);
//allItems.addAll(nonInheritingStylesList);
}*/
// create an item for unnamed style
var customItem:XML = createXMLItem(CUSTOM_ITEM_SORT_CHARACTER, "");
customItem.@search = true;
//allItems.addItem(customItem);
dataProviderProperties = allItems;
}
else {
dataProviderProperties = new XMLListCollection();
}
}
private var _target:Object;
public function get target():Object {
return _target;
}
[Bindable]
public function set target(value:Object):void {
_target = value;
if (_target) {
clear();
populatePropertiesGrid(_target);
}
else {
clear();
}
}
public function createXMLItem(name:String, value:*, style:Boolean=false, inheriting:Boolean=false):XML {
var xml:XML = <accessor />;
xml.@name = name;
xml.@style = style;
xml.@inheriting = inheriting;
xml.@access = "readwrite";
xml.@type = InspectorUtils.getValueType(value);
xml.@value = String(value);
return xml;
}
protected function filterDisplayObjectChangeHandler(item:XML):Boolean {
var itemName:String = item.attribute("name") ? item.attribute("name") : "";
var value:String = filterInput.text;
if (itemName.toLowerCase().indexOf(value) != -1) {
return true;
}
return false;
}
/**
* Filters the property list
* if we type a period or a space at the end of the word then
* the value and the name have to match exactly (case-insensitive)
* */
protected function filterPropertyChangeHandler(item:XML):Boolean {
var itemName:String = item.attribute("name") ? item.attribute("name") : "";
var value:String = filterInput.text;
var valueLength:int = value.length;
var itemNameLength:int = itemName.length;
var valueLowerCase:String = value.toLowerCase();
var itemNameLowerCase:String = itemName.toLowerCase();
// show all items if search is empty
if (valueLength==0) {
return true;
}
// show custom item in case of style
/*if (item.@search=="true") {
item.@name = CUSTOM_ITEM_SORT_CHARACTER + value;
filteredPropertiesCollection.enableAutoUpdate();
return true;
}
else {
filteredPropertiesCollection.disableAutoUpdate();
}*/
// if we type a period or a space at the end of the word then
// the value and the name have to match exactly (case-insensitive)
if (value.lastIndexOf(".")==valueLength-1 || value.lastIndexOf(" ")==valueLength-1) {
if (itemNameLowerCase+"."==valueLowerCase || itemNameLowerCase+" "==valueLowerCase) {
return true;
}
else {
return false;
}
}
// we filter from any index
if (itemNameLowerCase.indexOf(valueLowerCase) != -1) {
return true;
}
return false;
}
protected function findPropertyChangeHandler(event:TextOperationEvent):void {
filteredPropertiesCollection.refresh();
}
/**
* Attempts to drill into the selected property
* */
protected function gridDoubleClickHandler(event:MouseEvent):void {
return;
// if the user switches applications and the editor is not closed
// we get the text control of the editor. we don't want that so return
if (!(event.target is IDataRenderer)) return;
var instance:Object = event.currentTarget;
var itemRenderer:IDataRenderer = IDataRenderer(event.target);
var data:XML = itemRenderer.data as XML;
// this is a check for double click on dataGridColumn
if (data==null) return;
var currentValue:String = String(data.@value);
var propertyName:String = data.@name;
var type:String = String(data.@type);
var something:*;
if (propertyName in target) {
something = target[propertyName];
// if object set new target
if (!ObjectUtil.isSimple(something)) {
target = something;
radiate.dispatchTargetChangeEvent(something);
//InspectorUtils.dispatchTargetChangeEvent(something, this);
}
}
}
protected function propertiesGrid_itemEditEndHandler(oldValue:Object, newValue:Object, editor:DefaultGridItemEditor):void {
throw new Error("Is this used?");
var instance:Object = editor.column.itemEditor;
if (instance==null) return;
var data:XML = editor.column.grid.selectedItem as XML; //event.itemRenderer.data as XML;
var currentValue:String = String(data[editor.column.dataField]);
var propertyName:String = data.@name;
var searchField:String = data.@search;
var isSearchField:Boolean = searchField=="" || searchField==null ? false : searchField as Boolean;;
var type:String = String(data.@type);
var styleAttribute:String = data.@style;
var isStyle:Boolean = styleAttribute=="" || styleAttribute==null ? false : styleAttribute as Boolean;
var newAssignedValue:*;
var isChanged:Boolean;
if (isSearchField) {
propertyName = propertyName.replace(CUSTOM_ITEM_SORT_CHARACTER, "");
isStyle = true;
}
if (target) {
newAssignedValue = TypeUtils.getTypedValue(newValue, type)
InspectorUtils.setTargetProperty(target, propertyName, newAssignedValue, type, isStyle);
}
callLater(maintainFocus);
}
private function maintainFocus():void {
//propertiesGrid.editedItemPosition = null;
}
protected function filterInput_enterHandler(event:FlexEvent):void {
var searchText:String = filterInput.text;
var item:XML;
if (filteredPropertiesCollection.length==1) {
item = filteredPropertiesCollection.getItemAt(0) as XML;
if (item) {
item.@value = target is UIComponent ? UIComponent(target).getStyle(searchText) : "";
filteredPropertiesCollection.itemUpdated(item, "@value");
filteredPropertiesCollection.refresh();
}
}
}
/**
* Called when...
* */
protected function changeHandler(event:GridItemEditorEvent):void {
// This could probably all be rewritten
// we could use inspector utils setProperty
// ...
//trace("");
var column:GridColumn = event.column;
if (column.grid.dataGrid.itemEditorInstance==null) return;
var data:XML = event.currentTarget.selectedItem as XML; //event.itemRenderer.data as XML;
var currentValue:String = String(data[column.dataField]);
var propertyName:String = data.@name;
var searchField:String = data.@search;
var isSearchField:Boolean = searchField=="" || searchField==null ? false : searchField as Boolean;;
var type:String = String(data.@type);
var styleAttribute:String = data.@style;
var isStyle:Boolean = styleAttribute=="" || styleAttribute==null ? false : styleAttribute as Boolean;
var newValue:* = DefaultGridItemEditor(column.grid.dataGrid.itemEditorInstance).value;
if (isSearchField) {
propertyName = propertyName.replace(CUSTOM_ITEM_SORT_CHARACTER, "");
isStyle = true;
}
if (target) {
newValue = TypeUtils.getTypedValue(newValue, type)
InspectorUtils.setTargetProperty(target, propertyName, newValue, type, isStyle);
}
}
[Bindable]
public var showSearchBox:Boolean = true;
[Bindable]
public var showValueBox:Boolean = true;
[Bindable]
public var showHeader:Boolean = false;
/**
* Reference to Radiate
* */
public var radiate:Radiate;
/**
* Height of the header when not show (to allow resizing of columns)
* */
public var hiddenHeaderHeight:uint = 0;
/**
*
* */
public function clear():void {
allItems.removeAll();
allItems.refresh();
filterInput.text = "";
targetValueText.text = "";
dataProviderProperties = new XMLListCollection();
}
/*
protected function saveSessionHandler(event:GridItemEditorEvent):void {
//trace("Save session");
var item:XML = eventsGrid.dataProvider.getItemAt(event.rowIndex) as XML;
var value:String = String(item.@value);
var property:String = String(item.@name);
//trace("New Value= ", value);
Radiate.setProperty(target, property, value);
}*/
/*
protected function startSessionHandler(event:GridItemEditorEvent):void {
//trace("Start session");
}
*//*
protected function savingSessionHandler(event:GridItemEditorEvent):void
{
//trace("Saving session");
}*/
/*
protected function startingSessionHandler(event:GridItemEditorEvent):void
{
//trace("Starting session");
var item:XML = eventsGrid.dataProvider.getItemAt(event.rowIndex) as XML;
if (String(item.@access).indexOf("write")<0) {
// event.preventDefault();
// NOTIFY OF READ ONLY
}
}*/
protected function propertyChangeHandler(event:RadiateEvent):void
{
// radiate property change event
updatePropertyChangeValue(event.changes);
}
protected function targetValueText_keyUpHandler(event:KeyboardEvent):void {
if (event.keyCode==Keyboard.ENTER) {
updateTargetValue();
event.preventDefault();
}
else if (event.keyCode==Keyboard.ESCAPE) {
var item:XML = eventsGrid.selectedItem as XML;
var value:String = String(item.@value);
targetValueText.text = value;
event.preventDefault();
}
}
/**
* Set the property to the value in the textarea.
* */
public function updateTargetValue():void {
var item:XML = eventsGrid.selectedItem as XML;
var actualValue:*;
if (item) {
var value:String = String(item.@value);
var property:String = String(item.@name);
var propertyType:String = String(item.@type);
if (value!=targetValueText.text) {
actualValue = Radiate.getTypedValue(targetValueText.text, propertyType);
//trace("New Value= ", value);
Radiate.setProperty(target, property, actualValue);
}
}
}
protected function targetValueText_changingHandler(event:TextOperationEvent):void {
// prevent line breaks
if(event.operation is SplitParagraphOperation) {
event.preventDefault();
}
}
/**
* Update the property value in the datagrid when it changes
* without reloading all the properties.
* */
public function updatePropertyChangeValue(changes:Array):void {
var length:int = allItems.length;
var itemList:XMLList;
var propertyName:String;
if (length>0 && changes.length>0) {
//itemList = allItems.source;
for each (var node:XML in allItems) {
propertyName = node.@name;
// TypeError: Error #1034: Type Coercion failed: cannot convert mx.states::AddItems@1132558c9 to mx.effects.effectClasses.PropertyChanges.
// for each (var change:PropertyChanges in changes) {
for each (var change:Object in changes) {
if (change is mx.effects.effectClasses.PropertyChanges) {
var changeObject:Object = change.end;
for (var property:String in changeObject) {
if (propertyName==property) {
//node.@value = changeObject[property] ? Object(changeObject[property]) : "";
node.@value = Object(changeObject[property]).toString();
filteredPropertiesCollection.itemUpdated(node, "@value");
filteredPropertiesCollection.refresh();
}
}
}
}
}
}
}
protected function filterInput_clearTextHandler(event:TextOperationEvent):void {
}
/**
* Dispatch a property selected event
* */
protected function eventsGrid_clickHandler(event:MouseEvent):void {
dispatchPropertySelected();
}
protected function eventsGrid_selectionChangeHandler(event:GridSelectionEvent):void {
dispatchPropertySelected();
}
private function dispatchPropertySelected():void {
var item:XML = eventsGrid.selectedItem as XML;
var propertyObject:MetaData;
var property:String;
var nodename:String;
if (item) {
nodename = item.name();
propertyObject = new EventMetaData(item, target);
radiate.dispatchPropertySelectedEvent(property, propertyObject);
}
}
]]>
</fx:Script>
<fx:Declarations>
<s:NumberFormatter id="formatter"
useGrouping="false"/>
<s:ArrayCollection id="filteredPropertiesCollection"
list="{dataProviderProperties}"/>
<!-- SORT BY NAME -->
<handlers:EventHandler eventName="creationComplete" >
<collections:SortCollection target="{filteredPropertiesCollection}"
fields="{['@name']}" />
</handlers:EventHandler>
<!-- FILTER BY NAME -->
<handlers:EventHandler eventName="change"
targets="{[filterInput,showAllItemsOnEmpty,caseSensitive,searchAtStart]}"
>
<collections:FilterCollection target="{filteredPropertiesCollection}"
source="{filterInput}"
sourcePropertyName="text"
fieldName="@name"
showAllItemsOnEmpty="{showAllItemsOnEmpty.selected}"
caseSensitive="{caseSensitive.selected}"
searchAtStart="{searchAtStart.selected}"
/>
</handlers:EventHandler>
</fx:Declarations>
<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
@namespace c "com.flexcapacitor.controls.*";
@namespace mx "library://ns.adobe.com/flex/mx";
@namespace collections "com.flexcapacitor.effects.collections.*";
@namespace handlers "com.flexcapacitor.handlers.*";
.eventsGrid {
}
</fx:Style>
<mx:VDividedBox id="verticalContainer"
width="100%" height="100%"
top="0"
left="8"
right="8"
bottom="8"
>
<s:Group height="24" width="100%">
<c:SearchTextInput id="filterInput"
top="0"
width="100%"
minWidth="60"
borderAlpha=".2"
color="#2F3030"
focusAlpha="0"
fontWeight="normal"
prompt="Search"
enter="filterInput_enterHandler(event)"
clearText="filterInput_clearTextHandler(event)"
/>
<s:HGroup width="100%" top="32" paddingLeft="2">
<s:CheckBox id="showAllItemsOnEmpty" label="All" selected="true"/>
<s:CheckBox id="caseSensitive" label="Case" selected="false"/>
<s:CheckBox id="searchAtStart" label="At start" selected="false"/>
</s:HGroup>
</s:Group>
<c:DataGrid id="eventsGrid"
styleName="eventsGrid"
borderAlpha=".2"
height="100%"
width="100%"
minWidth="80"
minHeight="48"
rowHeight="18"
variableRowHeight="true"
click="eventsGrid_clickHandler(event)"
selectionChange="eventsGrid_selectionChangeHandler(event)"
dataProvider="{filteredPropertiesCollection}"
>
<c:columns>
<s:ArrayCollection>
<s:GridColumn dataField="@name"
minWidth="50"
editable="false"
resizable="true"
headerText="Name"/>
<s:GridColumn dataField="@className"
editable="false"
resizable="true"
headerText="DISPATCHED BY"
visible="false"/>
</s:ArrayCollection>
</c:columns>
<!--
<c:columns>
<s:ArrayCollection>
<s:GridColumn dataField="@name"
minWidth="50"
editable="false"
resizable="true"
headerText="PROPERTY">
<s:itemRenderer>
<fx:Component className="defaultItemRenderer">
<s:GridItemRenderer minHeight="14">
<s:Label id="labelDisplay"
verticalCenter="1" left="0" right="0" top="0" bottom="0"
fontSize="12"
paddingTop="3"
paddingBottom="3"
paddingLeft="3"
paddingRight="3"
textAlign="start"
verticalAlign="middle"
width="100%"
maxDisplayedLines="1"
showTruncationTip="true"/>
</s:GridItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:GridColumn>
<s:GridColumn dataField="@value"
minWidth="50"
editable="false"
resizable="true"
headerText="VALUE">
<s:itemRenderer>
<fx:Component >
<s:GridItemRenderer minHeight="14">
<s:Label id="labelDisplay"
verticalCenter="1" left="0" right="0" top="0" bottom="0"
fontSize="12"
paddingTop="3"
paddingBottom="3"
paddingLeft="3"
paddingRight="3"
textAlign="start"
verticalAlign="middle"
maxDisplayedLines="1"
showTruncationTip="true" />
</s:GridItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:GridColumn>
<s:GridColumn headerText=""
minWidth="30"
width="30"
editable="false"
labelFunction="{function(data:Object, column:GridColumn):String{return'...';}}">
</s:GridColumn>
</s:ArrayCollection>
</c:columns>-->
</c:DataGrid>
<s:TextArea id="targetValueText"
text="{XML(eventsGrid.selectedItem).@value}"
width="100%"
heightInLines="2"
skinClass="spark.skins.spark.TextAreaSkin"
minHeight="10"
visible="false"
includeInLayout="false"
keyUp="targetValueText_keyUpHandler(event)"
changing="targetValueText_changingHandler(event)">
</s:TextArea>
</mx:VDividedBox>
</s:Group>