ArcGIS API for Flex : dynamic InfoSymbols - actionscript-3

I am trying to add some InfoSymbols in my map, here is what I did :
<esri:InfoSymbol id="infoSymbol1">
<esri:infoRenderer>
<fx:Component>
<s:DataRenderer>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:Image id="eventImg" source="{imgSource}"/>
<s:Label id="eventName" text="{eventTitle}"/>
</s:DataRenderer>
</fx:Component>
</esri:infoRenderer>
</esri:InfoSymbol>
And I am filling a list from the data passed to the view, ( the application is a mobile view based app)
public function fillDataGrid():void {
for each(var object:Object in data) {
initDG.addItem(object);
drawEvent(object);
}
}
Finally I add the InfoSymbols the drawEvent(objt) method :
private function drawEvent(object:Object):void{
var myGraphicText:Graphic = new Graphic(new WebMercatorMapPoint(
object.local.longitude, object.local.latitude));
var event:InfoSymbol = new InfoSymbol();
imgSource = "http://192.168.0.22:3000" + object.logo_thumb_url;
eventTitle = object.name;
event = infoSymbol1;
myGraphicText.symbol = event;
myGraphicsLayer.add(myGraphicText);
}
of course imgSource and eventTitle are Bindable,
The issue is that I am getting
Description Resource Path Location Type
1120: Access of undefined property eventTitle.
And the same message for imgSource,
Any help would be much appreciated !!

You need to declare eventTitle before you assign a value to it.
var eventTitle:String = object.name;

Related

How to Use Xamarin.Forms and GoogleMaps/GeoLocation

I am writing a Xamarin.Forms PCL app, to support iOS and Android OS for my app.
In the root project, I have a view containing a ViewList and a map (from Xamarin.Forms.Maps).
I learnt I have to use CustomRenderer for each platform to add customized behavior. What I am trying to achieve to add a LocationManager/GeoLocation to identify the users position via GPS and show his position with a pin/marker. Additionally to that, I get positions from the root project of several persons which pins must also be shown within the map.
Should I have to use an interface exporting functionality or use an appropriate custom map renderer?
I have no idea to achieve that, the examples at the Xamarin.Forms website and research within Stackoverflow do not give a hint.
Here is some code I have so far (extract):
using System;
using Awesome;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using Plugin.Geolocator;
using System.Threading.Tasks;
namespace KiLa
{
public class KidsFinder : ContentPage, ITabPage
{
public string TabIcon => FontAwesome.FAMapMarker;
public string SelectedTabIcon => FontAwesome.FAMapMarker;
private Boolean _showKidsList;
private ListView _listView;
public ObservableCollection<KidsViewModel> kidsList = new ObservableCollection<KidsViewModel>();
public KidsFinder ()
{
Title = "KidsFinder";
// Define listView
// Any near/identified kids? Mockup
// TODO: get real data
Boolean kidsPresent = true;
// Initial height of map
double mapHeight = 300.0;
// coordinates of Beuth Hochschule, Haus Gauss
double latitude = 52.543100;
double longitude = 13.351450;
// Show/hide kidsList (listView)
//Boolean showKidsList = false;
_showKidsList = false;
// Define toggleButton
Button toggleButton = new Button();
toggleButton.Text = "Verstecke Liste";
toggleButton.Clicked += new EventHandler(OnClickEvent);
if(kidsPresent == true)
{
toggleButton.IsVisible = true;
mapHeight = 200.0;
_showKidsList = true;
} else
{
toggleButton.IsVisible = false;
mapHeight = 300.0;
_showKidsList = false;
}
// Mockup some kids
Position pos1 = new Position(latitude + 0.002, longitude + 0.002);
Position pos2 = new Position (latitude - 0.002, longitude - 0.002);
kidsList.Add(new KidsViewModel{Name="Tim", ActualPositon=pos1, DistanceToEducator=5.4});
kidsList.Add(new KidsViewModel{Name="Sabine", ActualPositon=pos2, DistanceToEducator=20.4});
_listView = new ListView();
_listView.ItemsSource = kidsList;
//listView.VerticalOptions = LayoutOptions.FillAndExpand;
_listView.ItemTemplate = new DataTemplate (typeof(KidsCustomCell));
_listView.RowHeight = 50;
if (_showKidsList == false) {
_listView.IsVisible = false;
} else {
_listView.IsVisible = true;
}
// Define mapView
var kidsMap = new KidsMap ();
kidsMap.MapType = MapType.Street;
kidsMap.WidthRequest = 960;
kidsMap.HeightRequest = mapHeight;
kidsMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(latitude,longitude), Distance.FromMiles(0.3)));
// Set label of pins with kids names,
foreach (KidsViewModel kvm in kidsList) {
Pin pin = new Pin() {
Label = kvm.Name,
Position = kvm.ActualPositon
};
kidsMap.Pins.Add(pin);
}
You should use GetLocation and declare the permissions necessary to use the LocationServices
[assembly: UsesPermission(Manifest.Permission.AccessFineLocation)]
[assembly: UsesPermission(Manifest.Permission.AccessCoarseLocation)]
This is not strictly necessary for obtaining the GPS coordinates of the device, but this example will attempt to provide a street address for the current location:
[assembly: UsesPermission(Manifest.Permission.Internet)]
Add a method called InitializeLocationManager to activity
void InitializeLocationManager()
{
_locationManager = (LocationManager) GetSystemService(LocationService);
Criteria criteriaForLocationService = new Criteria
{
Accuracy = Accuracy.Fine
};
IList<string> acceptableLocationProviders = _locationManager.GetProviders(criteriaForLocationService, true);
if (acceptableLocationProviders.Any())
{
_locationProvider = acceptableLocationProviders.First();
}
else
{
_locationProvider = string.Empty;
}
Log.Debug(TAG, "Using " + _locationProvider + ".");
}
The LocationManager class will listen for GPS updates from the device and notify the application by way of events. In this example we ask Android for the best location provider that matches a given set of Criteria and provide that provider to LocationManager.
For more details how to get current location using Xamarin Forms, follow this link: https://developer.xamarin.com/recipes/android/os_device_resources/gps/get_current_device_location/

Sort two columns of datagrid with checkbox flex

I have 5-6 columns in DataGrid in flex application.
<s:DataGrid id="recordGrid" dataProvider="{dxList}">
Grid:
Selected Name field2 field2 field3
In first column has CheckBox.
Second column contains Name. and So on...
Currently No checkbox is selected. Now, user select multiple checkbox randomly and Click on header(selected). then it will sort checkbox first.(I Done it).
But, My problem is Second field is also sort alphabetically.
All selected records come top with their Name alphabetically. Then after unchecked Record will be display in alphabetically sorted.
I Do following to sort record by checkbox selected:
<s:GridColumn dataField="selected" sortDescending="true">
Thanks.
Make sure you're using the sort api of the dataProvider.
Example taken from: http://www.java2s.com/Code/Flex/Grid/SortingaDataGridonmultiplecolumns.htm
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="initDP();" width="550" height="400">
<mx:Script>
import mx.events.DataGridEvent;
import mx.collections.*;
private var myDPColl:ArrayCollection;
[Bindable]
private var sortA:Sort;
private var sortByColumn1:SortField;
private var sortByColumn2:SortField;
private var sortByColumn3:SortField;
private var myDP:Array = [{Column1:'A', Column2:'AA',Column3:11.99, Column4: true},
{Column1:'B', Column2:'BB',Column3:10.99, Column4: false},
{Column1:'C', Column2:'CC',Column3:12.99, Column4: true},
{Column1:'D', Column2:'VV',Column3:11.99, Column4: false},
{Column1:'E', Column2:'EE',Column3:11.99, Column4: true},
{Column1:'F', Column2:'FF',Column3:14.99, Column4: true},
{Column1:'G', Column2:'GG',Column3:5.99, Column4: true}
];
private function initDP():void {
myDPColl = new ArrayCollection(myDP);
sortA = new Sort();
sortByColumn1 = new SortField("Column1", true, true);
sortByColumn2 = new SortField("Column2", true);
sortByColumn3 = new SortField("Column3", true);
sortA.fields=[sortByColumn1, sortByColumn2];
myDPColl.sort=sortA;
myDPColl.refresh();
myGrid.dataProvider = myDPColl;
myGrid.rowCount = myDPColl.length +1;
}
private function headRelEvt(event:DataGridEvent):void {
sortA.fields[2] = sortA.fields[1];
sortA.fields[1] = sortA.fields[0];
if (event.columnIndex==0) {
sortA.fields[0] = sortByColumn1;
} else if (event.columnIndex==1) {
sortA.fields[0] = sortByColumn2;
} else {
sortA.fields[0] = sortByColumn3;}
myDPColl.sort = sortA;
myDPColl.refresh();
event.preventDefault();
}
</mx:Script>
<mx:DataGrid id="myGrid" width="100%" headerRelease="headRelEvt(event);">
<mx:columns>
<mx:DataGridColumn minWidth="120" dataField="Column1"/>
<mx:DataGridColumn minWidth="200" dataField="Column2"/>
<mx:DataGridColumn width="75" dataField="Column3"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>

Listing huge amount files and directories include subdirectories in Adobe AIR

I am trying to list files and directories and copy all files existing into any other folder.
By the way, there are many files and directories more than 1000 000+.
Here is a part of code.
private function getFileList(sourceDir:String):void{
var file:File = File.userDirectory.resolvePath(sourceDir);
file.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
file.getDirectoryListingAsync();
}
private function directory_listing(e:FileListEvent):void{
var getfiles:Array = e.files;
for each(var item:File in e.files){
if(checkDir(item.nativePath)){
// It is a directory, more logic!
totalDirNum++;
item.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
item.getDirectoryListingAsync();
}
else{
// It is a file, more logic!
totalFileNum++;
if(analyzeFile(item) === true){
if(overwriteChk.selected === false){ // Don't overwrite same file
if(checkFile(destinationDir.nativePath + "\\" + item.name) === false){
copyInto(item, destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
copiedNum++;
}
else uncopiedNum++;
}
else{ // Overwrite same file
copyInto(item,destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
copiedNum++;
}
}
else{
skippedNum++;
}
}
}
As you see, it executes recursive directory_listing().
In case of little files and directories, it works clearly.
But, for example, in the following case it not works clearly(appear not responding.)
Root Directory : A!
A includes 500 000+ subdirectories.
Each subdirectories include 4 or 5 files and one or two subdirectories.
And also the subdirectoy include a 4 or 5 files.
So, I need to copy all files of "A" folder to the specific folder (B!).
Program is stopped in first before loop. i.e. Named "A" folder include huge subfolders, so when program run to select a "A" folder, then it is stopped just in "A" folder listing(stopped at getDirectoryListingAsyc()). So, actually it is not called recursive.
Here is my full source code.
<?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="800" height="600"
title="eveningCopier - Niao Jina"
creationComplete="initApp()">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
public var sourceDir:File;
public var destinationDir:File;
public var totalDirNum:uint;
public var totalFileNum:uint;
public var copiedNum:uint;
public var skippedNum:uint;
public var uncopiedNum:uint;
public var startTime:String;
public var finishTime:String;
/**
* Boot Function
**/
public function initApp():void{
sourceBtn.addEventListener(MouseEvent.CLICK, click_sourceBtn);
destinationBtn.addEventListener(MouseEvent.CLICK, click_destinationBtn);
startBtn.addEventListener(MouseEvent.CLICK, click_startBtn);
totalDirNum = 0;
totalFileNum = 0;
copiedNum = 0;
skippedNum = 0;
uncopiedNum = 0;
}
/**
* Event Listener when click "Source" button
**/
protected function click_sourceBtn(e:MouseEvent):void{
sourceDir = new File();
sourceDir.addEventListener(Event.SELECT, select_source);
sourceDir.browseForDirectory("Please select a source directory...");
}
private function select_source(evt:Event):void {
sourceTxt.text = sourceDir.nativePath;
}
/**
* Event Listener when click "Destination" button
**/
protected function click_destinationBtn(e:MouseEvent):void{
destinationDir = new File();
destinationDir.addEventListener(Event.SELECT, destination_select);
destinationDir.browseForDirectory("Please select a source directory...");
}
private function destination_select(evt:Event):void {
destinationTxt.text = destinationDir.nativePath;
}
/**
* Event Listener when click "Start" button
**/
protected function click_startBtn(e:MouseEvent):void{
if(sourceTxt.text == "") Alert.show("Please select a source directory", "Warning");
else if(destinationTxt.text == "") Alert.show("Please select a destination directory", "Warning");
if(checkDir(sourceTxt.text) === false) Alert.show("A selected Source folder:\n" + sourceTxt.text + "\n is not exist. Please check!", "Warning");
else if(checkDir(destinationTxt.text) === false) Alert.show("A selected Destination folder:\n" + destinationTxt.text + "\n is not exist. Please check!", "Warning");
//Alert.show(checkFile("D:\\New Folder\\f.txt").toString());
//Alert.show(checkDir("D:\\New Folder\\f.txt").toString());
workedTextArea.text = "";
currentLabel.text = "";
timeLabel.text = "";
totalDirLabel.text = "";
totalFileLabel.text = "";
copiedLabel.text = "";
skippedLabel.text = "";
uncopiedLabel.text = "";
totalDirNum = 0;
totalFileNum = 0;
copiedNum = 0;
skippedNum = 0;
uncopiedNum = 0;
startTime = getNow() + "\n";
getFileList(sourceTxt.text);
}
/**
* Get a current date and time as format - YYYY-MM-DD HH:II:SS
*
* #return String
**/
public function getNow():String{
var now:Date = new Date();
return now.getFullYear() + "-" + now.getMonth() + "-" + now.getDate() + " " + now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds();
}
/**
* Check if the directory is exist.
* #param dirName:String Path of the directory
* #return Boolean true or false
**/
private function checkDir(dirName:String):Boolean{
var dir:File = File.userDirectory.resolvePath(dirName);
return dir.isDirectory;
}
/**
* Check if the file is exist.
* #param fileName:String Path of the file
* #return Boolean true or false
**/
private function checkFile(fileName:String):Boolean{
var file:File = File.userDirectory.resolvePath(fileName);
return file.exists;
}
/**
* Ananlyze a structure of files and directory
* If is a folder, loop in its subfolder.
* If is a file, copy to the destination folder
*
* #param sourceDir:String
**/
private function getFileList(sourceDir:String):void{
var file:File = File.userDirectory.resolvePath(sourceDir);
file.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
file.getDirectoryListingAsync();
}
private function directory_listing(e:FileListEvent):void{
var getfiles:Array = e.files;
for each(var item:File in e.files){
trace(item.nativePath);
currentLabel.text = "Latest In : " + item.nativePath;
if(checkDir(item.nativePath)){
// It is a directory, more logic!
totalDirNum++;
item.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
item.getDirectoryListingAsync();
}
else{
// It is a file, more logic!
totalFileNum++;
if(analyzeFile(item) === true){
if(overwriteChk.selected === false){ // Don't overwrite same file
if(checkFile(destinationDir.nativePath + "\\" + item.name) === false){
copyInto(item, destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
copiedNum++;
}
else uncopiedNum++;
}
else{ // Overwrite same file
copyInto(item, destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
copiedNum++;
}
}
else{
skippedNum++;
}
}
}
finishTime = getNow();
timeLabel.text = startTime + finishTime;
totalDirLabel.text = "Total Dir : " + totalDirNum;
totalFileLabel.text = "Total Files : " + totalFileNum;
copiedLabel.text = "Copied Files : " + copiedNum;
skippedLabel.text = "Skipped Files : " + skippedNum;
uncopiedLabel.text = "Uncopied Files : " + uncopiedNum;
}
/**
* Copy files
* #param sourceFilePointer:File
* #param destinationDirPointer:File
* #return void
**/
private function copyInto(sourceFilePointer:File, destinationDirPointer:File):void{
sourceFilePointer.copyTo(destinationDirPointer, true);
if(logsChk.selected === true)
workedTextArea.text += sourceFilePointer.nativePath + "\n";
}
private function analyzeFile(filePointer:File):Boolean{
//Alert.show(filePointer.extension + "\n" + filePointer.size + "\n" + filePointer.name.indexOf("#"));
if((filePointer.extension) == null && (filePointer.size/1024 > 2) && (filePointer.name.indexOf("#") == -1))
return true;
else
return false;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:BorderContainer width="100%" height="100%">
<s:VGroup width="90%" height="5%" left="0">
<s:HGroup width="100%">
<s:Button id="sourceBtn" label="Source"/>
<s:TextInput id="sourceTxt" width="90%" fontSize="11"/>
</s:HGroup>
<s:HGroup width="100%">
<s:Button id="destinationBtn" label="Destination"/>
<s:TextInput id="destinationTxt" width="90%" fontSize="11"/>
</s:HGroup>
</s:VGroup>
<s:Button id="startBtn" label="Start" height="48" top="0" right="0"/>
<s:HGroup top="50" width="100%">
<s:Label id="currentLabel" width="90%" height="19" text="Latest In : "
textAlign="left" verticalAlign="middle"/>
<s:CheckBox id="overwriteChk" label="Overwrite" selected="false"/>
<s:CheckBox id="logsChk" label="Logs" selected="false"/>
</s:HGroup>
<s:TextArea id="workedTextArea" x="0" top="77" width="100%" height="90%" editable="false"/>
<s:HGroup width="100%" height="5%" bottom="0">
<s:Label id="timeLabel" width="20%" height="100%" textAlign="center" verticalAlign="middle" fontSize="11"/>
<s:Label id="totalDirLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
<s:Label id="totalFileLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
<s:Label id="copiedLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
<s:Label id="skippedLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
<s:Label id="uncopiedLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
</s:HGroup>
</s:BorderContainer>
</s:WindowedApplication>
Your problem lies within the execution time. If you're trying to perform everything in one go it will use all the CPU it can get. If one thread is being executed for longer than X seconds (usually 15), flash will abort it saying it takes too much.
Before starting your loop, take a timestamp with getTimer() and in the loop, in the beginning of your loop check if the startTimestamp - currentTimestamp is less than 5000 (5 seconds). If it is, break the array and start it over (with or without delay, flash will allow it) from the place you've left.
For this type of operations it would make sense to use workers, check this.
Here's an abstract example:
var counter:int = 0; // our progress
var startTime:int;
function increaseCounter():void
{
startTime = getTimer();
while(true) // infinite loop
{
if (getTimer() - startTime > 5000)
{
increaseCounter();
break;
}
counter++;
if (counter >= int.MAX_VALUE) // our custom loop exit
{
trace(counter);
break;
}
}
}
Though this thread seems to be quite old but I am posting a working code here which I wrote for searching files with given search string. It goes through all subfolders and pretty fast to respond in comparison to File.getDirectoryListing()
Here is my code
protected function performSearch(event:MouseEvent):void
{
searchResults = new Array(); // instance variable
foldersToBeSearched = new Array(); // instance variable
// keep file search list empty at start
fileSearchList.dataProvider = searchResults;
// instance level variable to store search string
searchString = searchText.text.toLowerCase();
// add root folder to array
foldersToBeSearched.push(File.applicationStorageDirectory);
findoutFolderNames(File.applicationStorageDirectory);
// keep and eye on folder search counter
setTimeout(checkAsyncFolderCounter, 500);
// show controls if search is on
showHideControlsAsPerSearchNeed();
}
// Because folder search is async hence use timeout to confirm if all folders are listed
private function checkAsyncFolderCounter():void
{
if(foldersToBeSearched.length === counterCapturedLast)
{
// I am done searching all folders and subfolder
// show this data now
fileSearchList.dataProvider = searchResults;
trace(searchResults.length);
}
else
{
// I am not yet done with folders...keep finding
counterCapturedLast = foldersToBeSearched.length;
setTimeout(checkAsyncFolderCounter, 500);
}
}
// Find out all folders in this folder
private function findoutFolderNames(folder:File):void
{
folder.addEventListener(FileListEvent.DIRECTORY_LISTING, directoryListingHandler);
folder.getDirectoryListingAsync();
}
// CHECK ALL FILES AND FOLDER AND FIND FOR SEARCH STRING OTHERWISE ADD FOLDER TO SEARCH FOLDERS LIST
private function directoryListingHandler(event:FileListEvent):void
{
event.target.removeEventListener(FileListEvent.DIRECTORY_LISTING, directoryListingHandler);
var list:Array = event.files;
for (var i:uint = 0; i < list.length; i++)
{
var file:File = list[i];
if(file.isDirectory)
{
foldersToBeSearched.push(file);
findoutFolderNames(file);
}
else
{
if(file.extension === "drl" && file.name.toLowerCase().indexOf(searchString) !== -1)
{
searchResults.push({label: file.name, creationDate: file.creationDate, nativePath: file.nativePath});
}
}
}
trace("Folder Count " + foldersToBeSearched.length);
}

Why Alivepdf generate double table header?

I'm attempting to create a pdf table on my flex application using AlivePdf:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:mh="mh.components.*"
layout="absolute" width="500" height="500">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import org.alivepdf.colors.RGBColor;
import org.alivepdf.display.Display;
import org.alivepdf.drawing.Caps;
import org.alivepdf.fonts.FontFamily;
import org.alivepdf.fonts.Style;
import org.alivepdf.grid.Grid;
import org.alivepdf.images.ImageFormat;
import org.alivepdf.layout.Orientation;
import org.alivepdf.layout.Resize;
import org.alivepdf.layout.Size;
import org.alivepdf.layout.Unit;
import org.alivepdf.pages.Page;
import org.alivepdf.pdf.PDF;
import org.alivepdf.saving.Method;
import org.alivepdf.visibility.Visibility;
import org.alivepdf.grid.*;
private var myPDF:PDF;
//print chart in pdf format
protected function savePDF(e:MouseEvent):void
{
var myPDF:PDF = new PDF ( Orientation.PORTRAIT, Unit.MM);
myPDF.setDisplayMode(Display.FULL_PAGE);
myPDF.addPage();
myPDF.setXY( 10, 70);
myPDF.textStyle ( new RGBColor ( 0x000000 ) );
var dp:ArrayCollection = new ArrayCollection();
dp.addItem( { firstName : "Bob Geldorf akjaskaj skajs as kajs kaj k dklfj sdkfjl sdkjf ksdj fkjs dkfj ksdj ", lastName : "Groove", city : "Paris" } );
dp.addItem( { firstName : "Bob", lastName : "Wise", city : "Paris" } );
dp.addItem( { firstName : "Bob", lastName : "Wise", city : "Paris" } );
dp.addItem( { firstName : "Bob", lastName : "Wise", city : "Paris" } );
var grid:Grid = new Grid ( dp.toArray(), 200, 100, new RGBColor (0x00DEFF));
myPDF.addGrid( grid, 0, 0, true );
myPDF.save( Method.REMOTE, "coldfusion/pdf.cfm", "inline", "test.pdf" );;
}
]]>
</mx:Script>
<mx:VBox width="100%" height="100%">
<mx:HBox width="100%" backgroundColor="#FFFFFF">
<mx:Spacer width="100%"/>
<mx:Button horizontalCenter="0" label="Save to PDF" height="22" click="savePDF(event)" id="savePDFBtn" toolTip="SAVE TO PDF"/>
</mx:HBox>
</mx:VBox>
The strange thing is that the script create a table with double header and I don't know why. You can see the pdf generated at this link: https://docs.google.com/viewer?url=prestitiinpdap.biz/pdf/myPDF.pdf
Which version of the library do you use? I have tried to compile your code with the current version 0.1.5RC and the compiler could not find some classes.
After correction of the class paths I have found that the "new Grid(...)" constructor needs 7 parameters (in your case only 4).
Another issue is "width" in "Grid(...)". I don't know, what the developers wanted to express with it. I could get I normal view only with 60.
I have got the following PDF after all:
Here is my code:
<?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" width="500" height="500">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import org.alivepdf.colors.RGBColor;
import org.alivepdf.data.Grid;
import org.alivepdf.display.Display;
import org.alivepdf.drawing.Caps;
import org.alivepdf.fonts.FontFamily;
import org.alivepdf.fonts.Style;
import org.alivepdf.images.ImageFormat;
import org.alivepdf.layout.Orientation;
import org.alivepdf.layout.Resize;
import org.alivepdf.layout.Size;
import org.alivepdf.layout.Unit;
import org.alivepdf.pages.Page;
import org.alivepdf.pdf.PDF;
import org.alivepdf.saving.Method;
import org.alivepdf.visibility.Visibility;
import org.alivepdf.layout.*;
private var myPDF:PDF;
protected function savePDF(e:MouseEvent):void
{
var myPDF:PDF = new PDF( Orientation.PORTRAIT, Unit.MM);
myPDF.setDisplayMode( Display.FULL_PAGE, Layout.SINGLE_PAGE );
var newPage:Page = new Page ( Orientation.PORTRAIT, Unit.MM);
myPDF.addPage(newPage);
myPDF.textStyle ( new RGBColor ( 0x000000 ) );
var dp:ArrayCollection = new ArrayCollection();
dp.addItem( { firstName : "Bob Geldorf akjaskaj skajs as kajs kaj k dklfj sdkfjl sdkjf ksdj fkjs dkfj ksdj ", lastName : "Groove", city : "Paris" } );
dp.addItem( { firstName : "Bob", lastName : "Wise", city : "Paris" } );
dp.addItem( { firstName : "Bob", lastName : "Wise", city : "Paris" } );
dp.addItem( { firstName : "Bob", lastName : "Wise", city : "Paris" } );
//var grid:Grid = new Grid ( dp.toArray(), 200, 100, new RGBColor (0x00DEFF));
var grid:Grid = new Grid (dp.toArray(), 60, 100, new RGBColor(0x00DEFF), new RGBColor (0xFFFFFF), false, new RGBColor (0x000000));
myPDF.addGrid( grid, 0, 0, true );
//myPDF.save( Method.REMOTE, "coldfusion/pdf.cfm", "inline", "test.pdf" );
var f:FileReference = new FileReference();
var b:ByteArray = myPDF.save(Method.LOCAL);
f.save(b, "test.pdf");
}
]]>
</fx:Script>
<mx:VBox width="100%" height="100%">
<mx:HBox width="100%" backgroundColor="#FFFFFF">
<mx:Spacer width="100%"/>
<mx:Button horizontalCenter="0" label="Save to PDF" height="22" click="savePDF(event)" id="savePDFBtn" toolTip="SAVE TO PDF"/>
</mx:HBox>
</mx:VBox>
</s:Application>
Try it, may be it will help you.
When creating a PDF with a Grid, I had the same problem of duplicate headers, as reported here. It's a few years after your problem, but since i came across it now, here's my solution...
To ensure using the latest AlivePDF version, I have downloaded the latest source code from their SVN: http://alivepdf.googlecode.com/svn/trunk/AlivePDFBeta/src
I believe this is distributed as AlivePDF 0.1.5 RC, however the distributed SWCs seem to have differences in some method signatures.
While scanning the AlivePDF source code for behaviour related with adding the Grid header, I noticed the class org.alivepdf.pdf.PDF, public method addGrid.
That method is indeed adding the Grid header 2 times, possibly by mistake.
This was fixed by commenting lines 4178 to 4180, as shown in the following source code.
Full method with the commented portion included:
public function addGrid ( grid:Grid, x:Number=0, y:Number=0, repeatHeader:Boolean=true ):void
{
if ( textColor == null )
throw new Error("Please call the setFont and textStyle method before adding a Grid.");
currentGrid = grid;
currentGrid.x = x;
currentGrid.y = y;
var i:int = 0;
var j:int = 0;
currentGrid.generateColumns(false);
columns = currentGrid.columns;
var row:Array;
columnNames = new Array();
var lngColumns:int = columns.length;
var item:*;
for (i = 0; i< lngColumns; i++)
columnNames.push ( new GridCell(columns[i].headerText, currentGrid.headerColor ) );
var rect:Rectangle = getRect ( columnNames, currentGrid.headerHeight );
if ( checkPageBreak(rect.height) )
addPage();
// Commented to avoid the duplicate header issue:
//setXY (x +currentGrid.x, y+getY() );
//addRow( columnNames,'', rect);
//endFill();
setXY ( x+getX(), y+getY() );
addRow( columnNames, GridRowType.HEADER, rect );
if (grid.cells == null)
grid.generateCells();
var buffer:Array = grid.cells;
var lngRows:int = buffer.length;
for (i = 0; i< lngRows; i++)
{
item = buffer[i];
row = new Array();
for (j = 0; j< lngColumns; j++)
{
row.push (item[columns[j].dataField] != null ? item[columns[j].dataField] : "");
nb = Math.min(nb,nbLines(columns[j].width,row[j]));
}
row = buffer[i];
rect = getRect ( row, currentGrid.rowHeight );
setX ( x + getX());
if ( checkPageBreak(rect.height) )
{
addPage();
setXY ( x+getX(),nextPageY );
//setXY ( x+getX(),y+getY() ); hacked to allow user to set the next Page Y of Grid
if ( repeatHeader )
{
addRow (columnNames, GridRowType.HEADER, getRect(columnNames, currentGrid.headerHeight) ); // header
setX ( x + getX() );
}
}
if ( grid.useAlternativeRowColor && Boolean(isEven = i&1) )
addRow( row, GridRowType.ALTERNATIVE, rect );
else addRow( row, GridRowType.NORMAL, rect );
}
}

Return ArrayCollection from SELECT query

In my AIR app i am trying to get the names from sqlite database as an ArrayCollection . Here is my code.
private function visitorName():void {
var sqlText:String = "SELECT name FROM user";
visitorNames = new SQLStatement;
visitorNames.sqlConnection = dbConn;
visitorNames.addEventListener(SQLEvent.RESULT, visitornamesResult);
visitorNames.addEventListener(SQLErrorEvent.ERROR, errorHandler);
visitorNames.text = sqlText;
visitorNames.execute();
}
private function visitornamesResult(event:SQLEvent):Array {
var result:SQLResult = visitorNames.getResult();
var namesList:Array = new Array();
namesList = result.data;
datafield3.dataProvider = namesList;
return namesList;
}
What should i do to get the results to an ArrayCollection by calling the visitorName() function?
Is it possible to get return value from a nested function?I know the visitorName function should be changed to ArrayCollection type and should declare an ArrayCollection variable inside it .. but not so sure how to proceed .. any help appreciated ..
First of all, notice that visitornamesResult is an event handler, so you won't be able to get the return value of that function.
You will want to actually put the result somewhere when you get it (in the UI? or in a model?)
Let's keep it simple, and just assign it to your datafield3.dataProvider:
private function visitorName(): { ... /* same as before */ }
private function visitornamesResult(event:SQLEvent):void {
var result:SQLResult = visitorNames.getResult();
// this is how you create an ArrayCollection with a provided Array
var visitors: ArrayCollection = new ArrayCollection( result.data );
datafield3.dataProvider = visitors;
}