I am trying to programmatically add images to a list/array and access them in a for each loop to change their source image - xamarin.forms

I have been trying to add images to an array and then access their properties to change their source image in a loop.
Detailed: I create a grid with a layout for each for each grid element, in that layout there is a GridImage, who's source folder is set to "ClosedFolder.png", when I click one of the layouts it should change the clicked layouts folder to "OpenFolder.png".
for (int eachCount = 0; eachCount <= MaxRows / MaxCols; eachCount++)
{
Selectedrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(80, GridUnitType.Absolute) });
for (int newCol = 0; newCol <= MaxCols; newCol++)
{
for (int newRow = 0; newRow <= MaxRows / MaxCols; newRow++)
{
if (folderIndex >= DirectoryArrayList.Count) { break; }
var folder = DirectoryArrayList[folderIndex];
var label = new Label()
{
Text = folder.Name,
FontSize = 12,
VerticalTextAlignment = TextAlignment.Center,
HorizontalTextAlignment = TextAlignment.Center
};
var GridImage = new Image() { Source = "ClosedFolder.png", StyleId = "Image" };
var GridTap = new TapGestureRecognizer();
var Layout = new StackLayout() { StyleId = "StackContent" };
var folderSelection = _mainFolder + "/" + folder.Name;
GridTap.Tapped += async(object sender, EventArgs e) =>
{
FileHandler.CreateTextFiles(folderSelection, "File_" + FileID + ".txt");
files = FolderOptions.AddFilesToList(folderSelection);
lst.ItemsSource = files;
//foreach (Image img in ImageList) I know this i incorrect, just an example of what I think!
//{
// img.Source = "ClosedFolder.png";
//}
GridImage.Source = "OpenFolder.png"; // clicked layout gets its openfolder.png
};
Layout.Children.Add(label);
Layout.Children.Add(GridImage);
Layout.GestureRecognizers.Add(GridTap);
Selectedrid.Children.Add(Layout, newCol, newRow);
folderIndex += 1;
FileID += 1;
}
}
}
Not sure on the declaration of the array and how to implement it.

I added the following into my BasicGrid method ...
var GridImage = new Image() { Source = "ClosedFolder.png", StyleId = "Image" };
var ImageList = new List<Image>{};
ImageList.Add( GridImage );
for (var i = 0; i < ImageList.Count; i++)
{
var img = ImageList[i];
img.Source = "ClosedFolder.png";
} GridImage.Source = "OpenFolder.png"
Just adding to say that Jason's information is the most likely direction I will go in, but as I am still learning it will take me time and I dint want to keep this open while I do that :-)

Related

load symbol of flash in flex at runtime

Hey people, I've this huge problem loading a symbol from a swf file in the application at runtime. I want to load it and pass it as a argument to another class where it could be used further. The symbol name is passed on from the array collection from the "o" object. Can anybody please tell me what's the right way to go about it.. Thanks in advance..!!
Following is the code for reference..
public override function Show(o:ObjectProxy):void
{
var _this:Weather;
var _super:ContentItem;
var item:WeatherItem;
var items:ArrayCollection;
var widgetCount:Number;
var headlineFontSize:int;
var conditionsIconThemeLoader:Loader;
this.m_weatherWidgetContainer = new HBox();
super.Show(o);
_this = this;
_super = super;
(undefined == o["HeadlineFontSize"]) ? headlineFontSize = 20 : headlineFontSize = o["HeadlineFontSize"];
if (undefined != o["direction"])
this.m_textDirection = o["direction"];
if (o.LargeUrl.Forecast is ArrayCollection)
items = ArrayCollection(o.LargeUrl.Forecast);
else
items = new ArrayCollection([o.LargeUrl.Forecast]);
widgetCount = this.m_computeWidgetSpace(items.length);
conditionsIconThemeLoader = new Loader();
conditionsIconThemeLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void
{
for(var i:uint = 0; i < widgetCount; i++)
{
var symbolClass:Class = e.currentTarget.loader.contentLoaderInfo.applicationDomain.currentDomain.getDefinition(int(items[i].condition)) as Class;
var symbolInstance:Sprite = new symbolClass();
item = new WeatherItem();
item.Show(items[i], headlineFontSize, symbolInstance, widgetCount);
_this.m_weatherWidgetContainer.addChild(item);
}
});
conditionsIconThemeLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, function(e:IOErrorEvent):void
{
Alert.show("Failure loading " + WidgetStylesheet.instance.Weather_Widget_Theme + ".swf");
});
// Attempt to load theme weather icon file
conditionsIconThemeLoader.load(new URLRequest("assets/animation/" + WidgetStylesheet.instance.Weather_Widget_Theme + ".swf"));
super.media.addChild(this.m_weatherWidgetContainer);
}
Heres the answer
public override function Show(o:ObjectProxy):void
{
var _this:Weather;
var _super:ContentItem;
var conditionsIconThemeLoader:Loader;
var loaderContext:LoaderContext;
this.m_weatherWidgetContainer = new HBox();
this.m_weatherWidgetContainer.percentHeight = 100;
this.m_weatherWidgetContainer.percentWidth = 100;
super.Show(o);
_this = this;
(undefined == o["HeadlineFontSize"]) ? this.m_headlineFontSize = 20 : this.m_headlineFontSize = o["HeadlineFontSize"];
if (undefined != o["direction"])
this.m_textDirection = o["direction"];
if (o.LargeUrl.Forecast is ArrayCollection)
this.m_items = o.LargeUrl.Forecast;
else
this.m_items = new ArrayCollection([o.LargeUrl.Forecast]);
conditionsIconThemeLoader = new Loader();
loaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
conditionsIconThemeLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, this.m_loaderSuccess);
conditionsIconThemeLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, this.m_loaderFail);
// Attempt to load theme weather icon file
conditionsIconThemeLoader.load(new URLRequest("assets/animation/" + WidgetStylesheet.instance.Weather_Widget_Theme + ".swf"), loaderContext);
this.m_weatherWidgetContainer.addEventListener(FlexEvent.CREATION_COMPLETE, this.m_drawHorizontalLine);
super.media.addChild(this.m_weatherWidgetContainer);
}

How to get a substring from a string variable which is having HTML tags

I have a string variable assigned with some Content in HTML format.
Some thing like this var strLabel:String = "This is <b>Test</b>;
But in run time i have get the first 10 characters of the string and display it in another control.
For this, what did was
txtLabelName.Text = String(strLabel).substr(0,10) + ' ...';
But in the output i am getting as This is <b. Basically it considering HTML related tags also as text. But my code has to omit the HTML tags while calculating sub string.
Please anybody help me to do this?
Use this regexp to strip html tags (more or less):
txtLabelName.text = strLabel.replace(/\<.+?\>/g, '').substr(0, 10) + ' ...';
It's a very simple regexp to strip all tags so it won't work on more complex tags (probably).
I got this code from some blog. This is working Perfectly
public static function stripHtmlTags(html:String, tags:String = ""):String
{
var tagsToBeKept:Array = new Array();
if (tags.length > 0)
tagsToBeKept = tags.split(new RegExp("\\s*,\\s*"));
var tagsToKeep:Array = new Array();
for (var i:int = 0; i < tagsToBeKept.length; i++)
{
if (tagsToBeKept[i] != null && tagsToBeKept[i] != "")
tagsToKeep.push(tagsToBeKept[i]);
}
var toBeRemoved:Array = new Array();
var tagRegExp:RegExp = new RegExp("<([^>\\s]+)(\\s[^>]+)*>", "g");
var foundedStrings:Array = html.match(tagRegExp);
for (i = 0; i < foundedStrings.length; i++)
{
var tagFlag:Boolean = false;
if (tagsToKeep != null)
{
for (var j:int = 0; j < tagsToKeep.length; j++)
{
var tmpRegExp:RegExp = new RegExp("<\/?" + tagsToKeep[j] + "( [^<>]*)*>", "i");
var tmpStr:String = foundedStrings[i] as String;
if (tmpStr.search(tmpRegExp) != -1)
tagFlag = true;
}
}
if (!tagFlag)
toBeRemoved.push(foundedStrings[i]);
}
for (i = 0; i < toBeRemoved.length; i++)
{
var tmpRE:RegExp = new RegExp("([\+\*\$\/])","g");
var tmpRemRE:RegExp = new RegExp((toBeRemoved[i] as String).replace(tmpRE, "\\$1"),"g");
html = html.replace(tmpRemRE, "");
}
return html;
}

repeatedly call AddImageUrl(url) to assemble pdf document

I'm using abcpdf and I'm curious if we can we recursively call AddImageUrl() function to assemble pdf document that compile multiple urls?
something like:
int pageCount = 0;
int theId = theDoc.AddImageUrl("http://stackoverflow.com/search?q=abcpdf+footer+page+x+out+of+", true, 0, true);
//assemble document
while (theDoc.Chainable(theId))
{
theDoc.Page = theDoc.AddPage();
theId = theDoc.AddImageToChain(theId);
}
pageCount = theDoc.PageCount;
Console.WriteLine("1 document page count:" + pageCount);
//Flatten document
for (int i = 1; i <= pageCount; i++)
{
theDoc.PageNumber = i;
theDoc.Flatten();
}
//now try again
theId = theDoc.AddImageUrl("http://stackoverflow.com/questions/1980890/pdf-report-generation", true, 0, true);
//assemble document
while (theDoc.Chainable(theId))
{
theDoc.Page = theDoc.AddPage();
theId = theDoc.AddImageToChain(theId);
}
Console.WriteLine("2 document page count:" + theDoc.PageCount);
//Flatten document
for (int i = pageCount + 1; i <= theDoc.PageCount; i++)
{
theDoc.PageNumber = i;
theDoc.Flatten();
}
pageCount = theDoc.PageCount;
edit:
code that seems to work based on 'hunter' solution:
static void Main(string[] args)
{
Test2();
}
static void Test2()
{
Doc theDoc = new Doc();
// Set minimum number of items a page of HTML should contain.
theDoc.HtmlOptions.ContentCount = 10;// Otherwise the page will be assumed to be invalid.
theDoc.HtmlOptions.RetryCount = 10; // Try to obtain html page 10 times
theDoc.HtmlOptions.Timeout = 180000;// The page must be obtained in less then 10 seconds
theDoc.Rect.Inset(0, 10); // set up document
theDoc.Rect.Position(5, 15);
theDoc.Rect.Width = 602;
theDoc.Rect.Height = 767;
theDoc.HtmlOptions.PageCacheEnabled = false;
IList<string> urls = new List<string>();
urls.Add("http://stackoverflow.com/search?q=abcpdf+footer+page+x+out+of+");
urls.Add("http://stackoverflow.com/questions/1980890/pdf-report-generation");
urls.Add("http://yahoo.com");
urls.Add("http://stackoverflow.com/questions/4338364/recursively-call-addimageurlurl-to-assemble-pdf-document");
foreach (string url in urls)
AddImage(ref theDoc, url);
//Flatten document
for (int i = 1; i <= theDoc.PageCount; i++)
{
theDoc.PageNumber = i;
theDoc.Flatten();
}
theDoc.Save("batchReport.pdf");
theDoc.Clear();
Console.Read();
}
static void AddImage(ref Doc theDoc, string url)
{
int theId = theDoc.AddImageUrl(url, true, 0, true);
while (theDoc.Chainable(theId))
{
theDoc.Page = theDoc.AddPage();
theId = theDoc.AddImageToChain(theId); // is this right?
}
Console.WriteLine(string.Format("document page count: {0}", theDoc.PageCount.ToString()));
}
edit 2:unfortunately calling AddImageUrl multiple times when generating pdf documents doesn't seem to work...
Finally found reliable solution.
Instead of executing AddImageUrl() function on the same underlying document, we should execute AddImageUrl() function on it's own Doc document and build collection of documents that at the end we will assemble into one document using Append() method.
Here is the code:
static void Main(string[] args)
{
Test2();
}
static void Test2()
{
Doc theDoc = new Doc();
var urls = new Dictionary<int, string>();
urls.Add(1, "http://www.asp101.com/samples/server_execute_aspx.asp");
urls.Add(2, "http://stackoverflow.com/questions/4338364/repeatedly-call-addimageurlurl-to-assemble-pdf-document");
urls.Add(3, "http://www.google.ca/");
urls.Add(4, "http://ca.yahoo.com/?p=us");
var theDocs = new List<Doc>();
foreach (int key in urls.Keys)
theDocs.Add(GetReport(urls[key]));
foreach (var doc in theDocs)
{
if (theDocs.IndexOf(doc) == 0)
theDoc = doc;
else
theDoc.Append(doc);
}
theDoc.Save("batchReport.pdf");
theDoc.Clear();
Console.Read();
}
static Doc GetReport(string url)
{
Doc theDoc = new Doc();
// Set minimum number of items a page of HTML should contain.
theDoc.HtmlOptions.ContentCount = 10;// Otherwise the page will be assumed to be invalid.
theDoc.HtmlOptions.RetryCount = 10; // Try to obtain html page 10 times
theDoc.HtmlOptions.Timeout = 180000;// The page must be obtained in less then 10 seconds
theDoc.Rect.Inset(0, 10); // set up document
theDoc.Rect.Position(5, 15);
theDoc.Rect.Width = 602;
theDoc.Rect.Height = 767;
theDoc.HtmlOptions.PageCacheEnabled = false;
int theId = theDoc.AddImageUrl(url, true, 0, true);
while (theDoc.Chainable(theId))
{
theDoc.Page = theDoc.AddPage();
theId = theDoc.AddImageToChain(theId);
}
//Flatten document
for (int i = 1; i <= theDoc.PageCount; i++)
{
theDoc.PageNumber = i;
theDoc.Flatten();
}
return theDoc;
}
}

Flex, Problem when jpegencoding two bitmaps in sequence

I am creating this "drawing application", where the user can click "preview" and it will take what they made, draw a bitmap, and then I want to split that bitmap into left and right images. I create the first bitmap, encode it as a jpeg, and then use that to cut the left and right out using copypixels. I then reform the images together with a space inbetween in one canvas, and draw that canvas. Everything works fine up there.
When I go to encode the new bitmap, and then offer it to save out, the saved image is blank. I have tested everything up to that point and it all works fine. I see the images on screen, I can save out the first bitmap fine.. but the second one is always blank. Here is some sample code, possibly someone can help me out.
_mainBmd = new BitmapData(_jacketWidth, _jacketHeight);
_mainBmd.draw(_imageHolder);
startEncode(_mainBmd);
private function startEncode(imageBitmapData:BitmapData):void
{
var encoder:JPEGAsyncEncoder = new JPEGAsyncEncoder(100);
encoder.PixelsPerIteration = 150;
encoder.addEventListener(JPEGAsyncCompleteEvent.JPEGASYNC_COMPLETE, encodeDone);
encoder.encode(imageBitmapData);
}
private function encodeDone(event:JPEGAsyncCompleteEvent):void
{
_leftBmd = new BitmapData(sideWidth, sideHeight);
var lRect:Rectangle = new Rectangle(0,0, sideWidth, sideHeight);
var lPoint:Point = new Point(0,0);
_leftBmd.copyPixels(_mainBmd, lRect, lPoint);
_rightBmd = new BitmapData(sideWidth, sideHeight);
var bWidth:Number = 200;
var sWidth:Number = 111;
var rRectWidth:Number = (bWidth/2 + sWidth) * Constants.print_dpi;
var rRect:Rectangle = new Rectangle(rRectWidth, 0, sideWidth, sideHeight);
var rPoint:Point = new Point(0, 0);
_rightBmd.copyPixels(_mainBmd, rRect, rPoint);
var lbm:Bitmap = new Bitmap(_leftBmd);
var rbm:Bitmap = new Bitmap(_rightBmd);
//now combine the two images into one holder with a space in the middle
//left Image
var l_Image:Image = new Image();
l_Image.source = lbm;
//right image
var r_Image:Image = new Image();
r_Image.source = rbm;
var newRender:Canvas = new Canvas();
newRender.clipContent = false;
newRender.minHeight = 0;
newRender.minWidth = 0;
newRender.addChild(l_Image);
r_Image.x = 500;
newRender.addChild(r_Image);
fcBMD = new BitmapData(renderW, renderH);
fcBMD.draw(newRender);
startEncode2(fcBMD);
}
private function startEncode2(imageBitmapData:BitmapData):void
{
var encoder:JPEGAsyncEncoder = new JPEGAsyncEncoder(100);
encoder.PixelsPerIteration = 150;
encoder.addEventListener(JPEGAsyncCompleteEvent.JPEGASYNC_COMPLETE, encode2Done);
encoder.encode(imageBitmapData);
}
private function encode2Done(event:JPEGAsyncCompleteEvent):void
{
_data = event.ImageData;
}
private function onSaveRenderClick(e:MouseEvent):void //save button listener
{
var fileRef:FileReference = new FileReference();
fileRef.addEventListener(Event.SELECT, onSaveComplete);
fileRef.save(_data, 'testImage.jpg');
}
Is there a special reason why you go trough all the loops of creating a Canvas holder and adding Images?
Why not use copyPixels directly on the final BitmapData that you want to encode:
var backgroundColor:uint = 0xffffff;
fcBMD = new BitmapData(renderW, renderH, false, backgroundColor);
var lPoint:Point = new Point(0,0);
var lRect:Rectangle = new Rectangle(0,0, sideWidth, sideHeight);
fcBMD.copyPixels(_mainBmd, lRect, lPoint);
var rRect:Rectangle = new Rectangle(rRectWidth, 0, sideWidth, sideHeight);
var rPoint:Point = new Point(renderW - sideWidth, 0);
fcBMD.copyPixels(_mainBmd, rRect, rPoint);
startEncode2(fcBMD);

highlight matching text?

I have flex 4 and writing my own autocomplete component (based on the popupanchor) to search for different books. In the dropdown box, how can I highlight the text that matches? For instance, a user types in "ema" and the search returns "Pet Sematary"....I want to highlight the letters "ema" within "Pet Sematary"
Wrote auto-complete a week ago :) You need to use Spark text components and pass custom TextFlow to them:
private function init():void
{
var textFlow:TextFlow = new TextFlow();
var paragraph:ParagraphElement = new ParagraphElement();
textFlow.addChild(paragraph);
var elements:Vector.<FlowElement> = highlight("Pet Sematary", "Se");
var n:int = elements.length;
for (var i:int = 0; i < n; i++)
{
paragraph.addChild(elements[i]);
}
label.textFlow = textFlow;
}
private function highlight(text:String, query:String):Vector.<FlowElement>
{
var result:Vector.<FlowElement> = new Vector.<FlowElement>();
// since we need to compare ignore-case we can not use split()
// and have to collect indexes of "query" matches in "text"
var indexes:Vector.<int> = new Vector.<int>();
var index:int = 0;
var textLowerCase:String = text.toLocaleLowerCase();
var queryLowerCase:String = query.toLocaleLowerCase();
var queryLength:int = query.length;
while (true)
{
index = textLowerCase.indexOf(queryLowerCase, index);
if (index == -1)
break;
indexes.push(index);
index += queryLength;
}
// now add SpanElement for each part of text. E.g. if we have
// text="aBc" and query is "b" then we add "a" and "c" as simple
// span and "B" as highlighted span.
var backgroundColor:uint = 0xFFCC00;
var n:int = indexes.length;
if (n == 0) // no matches
{
addSpan(result, text);
}
else
{
var startIndex:int = 0;
for (var i:int = 0; i < n; i++)
{
if (startIndex != indexes[i])
addSpan(result, text.substring(startIndex, indexes[i]));
addSpan(result, text.substr(indexes[i], queryLength),
backgroundColor);
startIndex = indexes[i] + queryLength;
}
if (startIndex != text.length)
addSpan(result, text.substr(startIndex));
}
return result;
}
private function addSpan(vector:Vector.<FlowElement>, text:String,
backgroundColor:* = "transparent"):void
{
var span:SpanElement = new SpanElement();
span.text = text;
span.backgroundColor = backgroundColor;
vector.push(span);
}
MXML code:
<s:RichEditableText editable="false" multiline="false"
selectable="false" id="label"
horizontalCenter="0" verticalCenter="0"/>
P.S: If you will have troubles with popup taking focus - add it manually to the toolTipChildren:
systemManager.toolTipChildren.addChildAt(child, 0);

Resources