I have a DataGrid with a custom itemRenderer(Canvas) which has a context menu on its right click. I am trying to get the data of the itemRenderer.
I tried to find something in event & variables. I also tried with FlexNativeMenu on RIGHT_MOUSE_CLICK. But I didn't find any way out.
Please help me in getting the data of the itemrenderer or its instance.
contextMenuOwner property of the ContextMenuEvent dispatched by the ContextMenu would point to the itemRenderer of interest.
var renderer:Canvas = Canvas(event.contextMenuOwner);
trace(renderer.data);
trace(renderer.data.something);
Use ContextMenuEvent.mouseTarget:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" initialize="init();">
<fx:Script>
<![CDATA[
import mx.core.IDataRenderer;
private function init():void
{
var dataGridContextMenu:ContextMenu = new ContextMenu();
dataGridContextMenu.hideBuiltInItems();
dataGridContextMenu.addEventListener(ContextMenuEvent.MENU_SELECT,
menuSelectHandler);
dataGrid.contextMenu = dataGridContextMenu;
}
private function menuSelectHandler(event:ContextMenuEvent):void
{
var displayObject:DisplayObject = event.mouseTarget as DisplayObject;
while (!(displayObject is IDataRenderer) && !(displayObject == dataGrid))
{
displayObject = displayObject.parent;
}
var data:Object;
if (displayObject is IDataRenderer)
data = IDataRenderer(displayObject).data;
var customItems:Array = [];
if (data)
{
var contextMenuItem:ContextMenuItem = new ContextMenuItem(data.name, false, false);
customItems.push(contextMenuItem);
}
var menu:ContextMenu = ContextMenu(event.target);
menu.customItems = customItems;
}
]]>
</fx:Script>
<mx:DataGrid id="dataGrid">
<mx:dataProvider>
<s:ArrayCollection>
<fx:Object name="Mike" age="21"/>
<fx:Object name="Juss" age="19"/>
</s:ArrayCollection>
</mx:dataProvider>
</mx:DataGrid>
</s:Application>
Related
I had a code like this
var str:string = "GeoCode: 3";
in this code I want ":" to be in bold.
How can I do that and this should be done in spark
Please help me
Thanks!
The simplest approach is to use TextFlowUtil.importFromString() and assign the resulting TextFlow object to a RichText component, like this:
<s:RichText id="textDisplay"/>
textDisplay.textFlow =
TextFlowUtil.importFromString('GeoCode<span fontWeight="bold">:</span> 3');
If you'd like to keep your original Strings intact, you can do a replace on them to add the span:
var str:String = "GeoCode: 3";
str = str.replace(/:/, '<span fontWeight="bold">:</span>');
textDisplay.textFlow = TextFlowUtil.importFromString(str);
I would do something like this:
The text property of the component is splitted into parts by means of ":" symbol. Then each part is added into a HGroup like a Label. Colons are added bold.
//Application
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="955" minHeight="600" xmlns:com="com.*">
<s:VGroup left="20" top="20">
<com:GeoLabel text="GeoCode: 3"/>
<com:GeoLabel text="GeoCode: 5: Some Info: 123"/>
</s:VGroup>
</s:Application>
//GeoLabel component
<?xml version="1.0" encoding="utf-8"?>
<s:HGroup xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="120" height="25" gap="0">
<fx:Script>
<![CDATA[
import spark.components.Label;
private var _text:String;
public function get text():String
{
return _text;
}
public function set text(value:String):void
{
_text = value;
createMembers();
}
private function insertLabel(str:String, bold:Boolean):void
{
var la:Label = new Label();
la.text = str;
if (bold)
la.setStyle("fontWeight", "bold");
this.addElement(la);
}
private function createMembers():void
{
this.removeAllElements();
var arr:Array = text.split(":");
for (var i:int = 0; i < arr.length; i++)
{
if (i != 0)
insertLabel(":", true);
insertLabel(arr[i], false);
}
}
]]>
</fx:Script>
</s:HGroup>
I just started working with Flex. I know it's pathetic but it's a long story.
Now, the problem I am facing is that I have a list component which has a dataprovider on it. What I would like to do is when an item on the list is clicked I would like to have a check sign right next to the label.
Below is the component:
<s:List id="tabList" width="100%"
borderVisible="false" click="tabList_clickHandler(event)"
selectedIndex="{this.hostComponent.selectedIndex}"
itemRenderer="MultiTabListRenderer" />
Below is the Itemrenderer code:
protected function AddCheck_clickHandler(event:MouseEvent):void {
// TODO Auto-generated method stub
var checkLabel:Label;
checkLabel = new Label();
checkLabel.text = "checkMark";
var e: ItemClickEvent = new ItemClickEvent(ItemClickEvent.ITEM_CLICK, true);
e.item = data;
e.index = itemIndex;
dispatchEvent(e);
this.checkRectGroup.addElementAt(checkLabel, e.index);
}
<s:Label id="customMultitabList" text="{data.label}"
left="10" right="0" top="6" bottom="6" click="AddCheck_clickHandler(event)"/>
My code inside the function is wrong which is mainly due to the fact that I do not understand each and everything in flex. I am not in a mood to learn the language in detail because it's not a long term work for me. Also, in the renderer file when I use s:List instead of s:label I do not see the labels anymore. Of course I replace the attribute text with dataprovider={data.selectedItem}.
One way to approach this is to add a field to the objects in your dataProvider that tracks whether or not the item has been selected.
Then, in your item renderer, you inspect this field and decide whether or not to display the checkmark. Here's a working example app and renderer:
Application:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:local="*"
creationComplete="application1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
import mx.events.FlexEvent;
import mx.events.PropertyChangeEvent;
import mx.events.PropertyChangeEventKind;
private var collection:ArrayCollection;
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
collection = new ArrayCollection([
{ label: 1, selected: false },
{ label: 2, selected: false },
{ label: 3, selected: false }]);
listbert.dataProvider=collection;
}
protected function listbert_clickHandler(event:MouseEvent):void
{
var index:int = listbert.selectedIndex;
var item:Object = listbert.selectedItem;
item.selected = !item.selected;
// Create these events because the items in the ArrayCollection
// are generic objects. It shouldn't be necessary if items in
// your collection are a Class that extends EventDispatcher
// see ArrayList::startTrackUpdates()
var e:PropertyChangeEvent = new PropertyChangeEvent(
PropertyChangeEvent.PROPERTY_CHANGE, false,false,
PropertyChangeEventKind.UPDATE, 'selected', !item.selected,
item.selected, item);
collection.dispatchEvent(new CollectionEvent(
CollectionEvent.COLLECTION_CHANGE, false,false,
CollectionEventKind.UPDATE, index, index, [e]));
}
]]>
</fx:Script>
<s:List id="listbert" click="listbert_clickHandler(event)" itemRenderer="TestRenderer"/>
</s:Application>
Item Renderer:
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" >
<fx:Script>
<![CDATA[
override public function set data(value:Object):void
{
super.data = value;
labelDisplay.text = value.label;
if (value.selected)
checkMarkLabel.text = "✓";
else
checkMarkLabel.text = "";
}
]]>
</fx:Script>
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<s:Label id="labelDisplay" />
<s:Label id="checkMarkLabel" />
</s:ItemRenderer>
Please help
I can save the data from the three components as xml and it works, but now I am struggling with the code to read that data back into the components when the user opens. This is a local file that is created by the user. I need help with the open event handler.
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="734" height="389"
creationComplete="init();">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
[Bindable]
public var xmlData:XML=<ROOTS></ROOTS>;
private function fnAddItem():void
{
var fr:FileReference = new FileReference();
var ba:ByteArray = new ByteArray();
var newXmlRow:XML=<ROOTS>
<TXT>{txt1.text}</TXT>
<TXTA>{txt2.text}</TXTA>
<DTF>{txt3.text}</DTF>
</ROOTS>;
ba.writeMultiByte(newXmlRow, 'utf-8');
fr.save(ba);
}
protected function oped_clickHandler(event:MouseEvent):void
{
var fr:FileReference = new FileReference();
var ba:ByteArray = new ByteArray();
var newXmlRow:XML=<ROOTS>
<TXT>{txt1.text}</TXT>
<TXTA>{txt2.text}</TXTA>
<DTF>{txt3.text}</DTF>
</ROOTS>;
ba.readMultiByte(xmlData, 'utf-8');
fr.load(ba);
}
]]>
</fx:Script>
<s:Label x="108" y="80" text="Name"/>
<s:Label x="91" y="222" text="Remarks"/>
<s:Label x="108" y="116" text="text"/>
<s:TextInput id="txt1" x="167" y="78"/>
<s:TextArea id="txt2" x="167" y="218" height="86"/>
<s:TextArea id="txt3" x="167" y="108" height="77"/>
<s:Button x="53" y="242" label="save" width="90" click="fnAddItem()"/>
<s:Button id="oped" x="73" y="271" label="open" click="oped_clickHandler(event)"/>
</s:WindowedApplication>
first if you want a dialog you have to wait for the user to make a selection. The selection throws an event that you can catch. Within the handler you can do the file handling. Try if the following code works for you.
private var openedFile:File;
private function oped_clickHandler(event:MouseEvent):void {
openedFile = new File();
openedFile.addEventListener(Event.SELECT, file_select);
openedFile.browseForOpen("Please select a file...");
}
private function file_select(event:Event):void {
if(openedFile != null && openedFile.exists){
var fileStream:FileStream = new FileStream();
fileStream.open(openedFile, FileMode.READ);
var readXML:XML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
fileStream.close();
trace(readXML.toString());
txt1.text = readXML.TXT;
txt2.text = readXML.TXTA;
txt3.text = readXML.DTF;
}
trace(event);
}
cheers,
rob
I have a datagrid which contains a Spark dropdownlist that needs to obtain dynamic data. The datagrid uses a separate dataProvider.
When I use a static ArrayCollection within my ItemRenderer, it works (please see listing 1).
However, when I use Swiz to mediate a 'list complete' event to load the ArrayCollection, the dropdownlist does not show the new data (please see listing 2).
Using the debugger, I inspected the dropdownlist ItemRenderer and have confirmed the new data is being loaded into the ArrayCollection. The new data is not shown in the UI control. I have tried invalidateProperties() + validateNow() and dispatching events on both the control and the renderer (this), but nothing seems to make the new data appear in the control on the datagrid.
Please help !!!
Listing 1: Datagrid and static ArrayCollection (this works):
<mx:DataGrid x="10" y="25" width="98%" id="dgInventory" paddingLeft="25" paddingRight="25" paddingTop="25" paddingBottom="25"
editable="true"
itemClick="dgInventory_itemClickHandler(event)" dataProvider="{acInventory}"
creationComplete="dgInventory_creationCompleteHandler(event)"
height="580">
<mx:columns>
<mx:DataGridColumn headerText="Item" dataField="itemName" itemRenderer="components.ItemRendererItem"
rendererIsEditor="true" editorDataField="selection" editable="true"/>
<mx:DataGridColumn headerText="Quantity Required" dataField="quantityReq" itemRenderer="components.ItemRendererQuantityRequired"
rendererIsEditor="true" editorDataField="selection" editable="true"/>
</mx:columns>
</mx:DataGrid>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import spark.events.IndexChangeEvent;
public var selection:int;
[Bindable]
protected var acItem:ArrayCollection = new ArrayCollection(
[ { itemName: "Item1"},
{ itemName: "Item2"},
{ itemName: "Item3"},
]);
//
protected function dropdownlist1_changeHandler(e:IndexChangeEvent):void
{
selection = e.newIndex;
}
]]>
</fx:Script>
<s:DropDownList id="ddlItem" prompt="Select Item" dataProvider="{acItem}" labelField="itemName"
selectedIndex="{int(dataGridListData.label)}"
change="dropdownlist1_changeHandler(event)"
width="80%" top="5" bottom="5" left="5" right="5"/>
Listing 2: Dynamic ArrayCollection (does not work):
<?xml version="1.0" encoding="utf-8"?>
<s:MXDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
focusEnabled="true">
<fx:Script>
<![CDATA[
import event.ItemEvent;
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
import spark.events.IndexChangeEvent;
public var selection:int;
//
[Bindable]
protected var acItem:ArrayCollection = new ArrayCollection();
//
protected function dropdownlist1_changeHandler(e:IndexChangeEvent):void
{
selection = e.newIndex;
}
//
protected function ddlItem_creationCompleteHandler(event:FlexEvent):void
{
var eve : ItemEvent = new ItemEvent( ItemEvent.LIST_ITEM_REQUESTED );
dispatchEvent( eve );
}
//
[Mediate( event="ItemEvent.LIST_ITEM_COMPLETE", properties="acItem" )]
public function refreshness( _acItem : ArrayCollection ):void
{
acItem.removeAll();
var len:int = _acItem.length;
if (len > 0)
{
for (var i:int=0; i < len; i++)
{
var newItem:Object = new Object;
newItem["itemName"] = _acItem[i].itemName;
acItem.addItem(newItem);
}
}
this.invalidateProperties();
this.validateNow();
//dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
}
]]>
</fx:Script>
<s:DropDownList id="ddlItem" prompt="Select Item" dataProvider="{acItem}" labelField="itemName"
selectedIndex="{int(dataGridListData.label)}"
creationComplete="ddlItem_creationCompleteHandler(event)"
change="dropdownlist1_changeHandler(event)"
width="80%" top="5" bottom="5" left="5" right="5"/>
</s:MXDataGridItemRenderer>
After re-reading Peter Ent's ItemRenderer series, this turned out to be quite simple.
I extended DataGrid to have the ArrayCollection property I needed, then added this to my renderer:
[Bindable]
protected var acItem:ArrayCollection = new ArrayCollection();
//
override public function set data( value:Object ) : void
{
super.data = value;
acItem = (listData.owner as MyDataGrid).itemList; // get the data from the renderer's container (by extending it to add a property, if necessary)
}
I load image to control than I applie some effects, and when I save image it's saving without effects. What should i do?
Here is the code:
private var byteArr2:ByteArray;
private var fileRef:FileReference = new FileReference();
public function process():void
{
var ct:ColorTransform = new ColorTransform();
ct.redOffset = 99;
ct.blueOffset = 11;
ct.greenOffset = 22;
currImg.transform.colorTransform = ct;
callLater(toByteArray);
}
public function toByteArray():void
{
var data:BitmapData = new BitmapData(currImg.width, currImg.width);
data.draw(currImg);
var encod:JPEGEncoder = new JPEGEncoder(100);
byteArr2 = encod.encode(data);
}
public function saveFile():void
{
fileRef.save(byteArr2,"NewFileName1.jpg");
}
<mx:HBox>
<mx:VBox>
<s:Button x="69" y="98" label="open" click="open()()"/>
<s:Button label="show" click="show()"/>
<s:Button label="process" click="process()"/>
<s:Button label="save" click="saveFile()"/>
</mx:VBox>
<mx:Image id="currImg" width="200" height="300"/>
</mx:HBox>
UPDATE Appears new problem as I am using var data:BitmapData = new BitmapData(currImg.width, currImg.width); saved image is small(size like image control) but I need to save image with original size.
With var data:BitmapData = Bitmap(currImg.content).bitmapData; it worked
I would draw the component into a new BitmapData object rather than use the content of the currImg. This should give you what's drawn on the screen rather than the unmodified content. Something like so:
var data:BitmapData = new BitmapData(currImg.width, currImg.width);
data.draw(currImg);
Hope that helps.
Alright this isn't a great solution cause I don't know why it works but if you put a container around the image then save the results of drawing that it seems to work.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.graphics.codec.JPEGEncoder;
private var byteArr2:ByteArray;
private var fileRef:FileReference = new FileReference();
public function process():void
{
var ct:ColorTransform = new ColorTransform();
ct.redOffset = 99;
ct.blueOffset = 11;
ct.greenOffset = 22;
currImg.transform.colorTransform = ct;
callLater(toByteArray);
}
public function toByteArray():void
{
var data:BitmapData = new BitmapData(everything.width, everything.width);
data.draw(everything);
var encod:JPEGEncoder = new JPEGEncoder(100);
byteArr2 = encod.encode(data);
}
public function saveFile():void
{
fileRef.save(byteArr2,"NewFileName1.jpg");
}
]]>
</fx:Script>
<mx:HBox>
<mx:VBox>
<!--<s:Button x="69" y="98" label="open" click="open()"/>-->
<!--<s:Button label="show" click="show()"/> -->
<s:Button label="process" click="process()"/>
<s:Button label="save" click="saveFile()"/>
</mx:VBox>
<mx:Box id="everything">
<mx:Image id="currImg" width="200" height="300" source="http://www.google.com/images/logos/ps_logo2.png"/>
</mx:Box>
</mx:HBox>
</s:Application>
Shaun