Resizing MonoTouch.Dialog StyledMultilineElement after an async call - xamarin.ios

I'm playing with MonoTouch.Dialog and written some code to show some tweets. The problem is that the table cells are too small and the cells are all bunched up when I load the StyledMultilineElements asynchronously. They look absolutely perfect when I load them synchronously (i.e. without the QueueUserWorkItem/InvokeOnMainThread part)
Is there a way of getting the table cells to recalculate their height?
// This method is invoked when the application has loaded its UI and its ready to run
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
window.AddSubview(navigation.View);
var tweetsSection = new Section("MonoTouch Tweets"){
new StringElement("Loading...") //placeholder
};
var menu = new RootElement("Demos"){
tweetsSection,
};
var dv = new DialogViewController(menu) { Autorotate = true };
navigation.PushViewController(dv, true);
window.MakeKeyAndVisible();
// Load tweets async
UIApplication.SharedApplication.NetworkActivityIndicatorVisible = true;
ThreadPool.QueueUserWorkItem(delegate {
var doc = XDocument.Load("http://search.twitter.com/search.atom?q=%23MonoTouch");
var atom = (XNamespace)"http://www.w3.org/2005/Atom";
var tweets =
from node in doc.Root.Descendants(atom + "entry")
select new {
Author = node.Element(atom + "author").Element(atom + "name").Value,
Text = node.Element(atom + "title").Value
};
var newElements =
from tweet in tweets
select new StyledMultilineElement(
tweet.Author,
tweet.Text);
InvokeOnMainThread(delegate {
UIApplication.SharedApplication.NetworkActivityIndicatorVisible = false;
tweetsSection.Remove(0);
tweetsSection.Add(newElements.Cast<Element>().ToList());
});
});
return true;
}

Try setting the UnevenRows property on your top level Root element of your Dialog View Controller, in this case "menu":
menu.UnevenRows = true

Related

To change bg through extendscript, import an image into "Background composition" of after effects project

I wants to change image from bg composition through extendscript. Reason behind this, is to reduce time to every time to go into pre-comp(BG) and manually change image.
I have tried to modify "Smart Import.jsx"(provided with AE), but this script is specially for image sequences. And modified script is not working me
function myImport()
{
var targetFile = File.openDialog ("Import your file", "*.jpg", multiSelect = false);
function processFile(theFile)
{
try {
var importOptions = new ImportOptions(theFile);
importSafeWithError(importOptions);
} catch (error) {
}
}
function processFolder(theFolder)
{
var files = theFolder.getFiles();
var sequenceStartFile = testForSequence(files);
}
processFolder(targetFile);
}
myImport();
}
I am expecting to import an image not only to the project library, but also it needs to be added into bg comp to change bg.
You can change the source of an existing file and this will effect all comps that use that file. Source files in the project window are footageItem objects and they have an attribute called mainSource which is a file object. So simply change the mainSource attribute of the bg footage. More in the docs here.
Here in this script, after click on 'Import File' button, I got required result.
var selComp;
for (var i = 1; i <= app.project.numItems; i ++)
{
if ((app.project.item(i) instanceof CompItem) && (app.project.item(i).name === 'MOVIE IMAGE')) {
selComp = app.project.item(i);
}
}
selComp.openInViewer(); // View Your Comp opened in after effects
{
var w = new Window ("dialog");
var importFile = w.add ("button", undefined, "Import File");
importFile.onClick = ImportFile ;
importFromFolder.onClick = ImportFilesFromFolder ;
function ImportFile () {
app.beginUndoGroup("Import File");
var targetFile = File.openDialog("Import File");
if (targetFile) {
var importOptions = new ImportOptions (targetFile);
var newLayer = app.project.importFile (importOptions);
var insertLayer = selComp.layers.add(newLayer);
}
$.writeln(newLayer.name);
app.endUndoGroup();
}
w.show ();
}

PIXI getting image width,height

I need to get size of image that I just added to stage and set it to defaultX and defaultY before I call the autorenderer, but I can't seem to grab the size.
How do I grab the size?
Also, from what I got so far, I think the best way to set the size is including with autorenderer. But what would be the implication here if I resize() later?
Any help will be appreciated. Thank you.
my code:
this.stage = new PIXI.Container();
var texture = PIXI.Texture.fromImage('background.png'); //1610x640
var spr = new PIXI.Sprite(texture);
this.stage.addChild(spr);
defaultX = texture.width;
defaultY = texture.height;
this.renderer = PIXI.autoDetectRenderer(defaultX, defaultY); //640x690
this.renderer.resize(x,y); // I know this works with other values
// eg if I hardcode with 1610,640
// but texture.width doesn't work and
// I don't want to hardcode it
Your image can not be loaded when you call texture.width.
I use next construction:
this.stage = new PIXI.Container();
this.renderer = PIXI.autoDetectRenderer(640, 690); //640x690
var baseTexture = new PIXI.BaseTexture('background.png');
// can be loaded from cache
if (baseTexture .hasLoaded) {
createSprite(baseTexture);
} else {
baseTexture .on('loaded', function() {
createSprite(baseTexture); // or this
});
}
function createSprite(baseTexture) {
var texture = new PIXI.Texture(baseTexture);
var spr = new PIXI.Sprite(texture);
this.stage.addChild(spr);
defaultX = texture.width;
defaultY = texture.height;
this.renderer.resize(defaultX,defaultY);
}

FabricJS double click on objects

I am trying to perform a special action whenever the user double clicks any object located inside the canvas. I have read the docs and not found any mouse:dblclick-like event in the documentation. I tried doing something like:
fabric.util.addListener(fabric.document, 'dblclick', callback);
Which does trigger the dblclick event but does not give specific information about the actual object that is being clicked on the canvas.
Any ideas of the most FabricJS-y way of doing this?
The more elegant way is to override fabric.Canvas._initEventListeners to add the dblclick support
_initEventListeners: function() {
var self = this;
self.callSuper('_initEventListeners');
addListener(self.upperCanvasEl, 'dblclick', self._onDoubleClick);
}
_onDoubleClick: function(e) {
var self = this;
var target = self.findTarget(e);
self.fire('mouse:dblclick', {
target: target,
e: e
});
if (target && !self.isDrawingMode) {
// To unify the behavior, the object's double click event does not fire on drawing mode.
target.fire('object:dblclick', {
e: e
});
}
}
I've also developed a library to implement more events missed in fabricjs : https://github.com/mazong1123/fabric.ext
This is similar to #LeoCreer's answer but actually gets access to the targeted object
fabric.util.addListener(canvas.upperCanvasEl, 'dblclick', function (e) {
var target = canvas.findTarget(e);
});
The Correct way to add custom events to Fabric.js
window.fabric.util.addListener(canvas.upperCanvasEl, 'dblclick', function (event, self) {
yourFunction(event);
});
or use fabric.ext
I'm using this workaround:
var timer = 0;
canvas.item(0).on('mouseup', function() {
var d = new Date();
timer = d.getTime();
});
canvas.item(0).on('mousedown', function() {
var d = new Date();
if ((d.getTime() - timer) < 300) {
console.log('double click')
}
});
Here is a quick and easy way to add a double click event handler to Fabric JS -
Include following code snippet to your html file. Just ensure this is loaded after the main fabric.js library
<script type="text/javascript">
fabric = (function(f) { var nativeOn = f.on; var dblClickSubscribers = []; var nativeCanvas = f.Canvas; f.Canvas = (function(domId, options) { var canvasDomElement = document.getElementById(domId); var c = new nativeCanvas(domId, options); c.dblclick = function(handler) { dblClickSubscribers.push(handler) }; canvasDomElement.nextSibling.ondblclick = function(ev){ for(var i = 0; i < dblClickSubscribers.length; i++) { console.log(ev); dblClickSubscribers[i]({ e :ev }); } }; return c; }); return f; }(fabric));
</script>
Then add this code to listen a double click event:
canvas.dblclick(function(e) {
});
To get information about the actual object that is being clicked on the canvas, use following method -
canvas.getActiveObject();
eg.
canvas.dblclick(function(e) {
activeObject = canvas.getActiveObject();
});
I am late but now fabricjs has mousedblclick event.
Listed at: http://fabricjs.com/docs/fabric.Object.html
See all events:
http://fabricjs.com/events

Loading itemTemplate for WinJS.UI.ListView from external source

I am wondering if someone can shed some light on why this does not work.
I can successfully dynamically template each WinJS.UI.ListView item if I define the templates in my html view (First Scenario). However if I load the template from a seperate html file using a $.get statement it does not work (Second Scenario).
self.selectTemplate = function (itemPromise) {
return itemPromise.then(function (item) { ...
First Scenario:
(var itemTemplate = document.getElementById(item.data.controlType + "ItemTemplate");
var container = document.createElement("div");
itemTemplate.winControl.render(item.data, container);
return container;)
Second Scenario:
(var itemTemplatePromise = ko.bindingHandlers.searchPropertyBuilder.loadTemplate(item.data.controlType);
itemTemplatePromise.done(function (itemTemplateLoaded) {
var templateContainer = document.createElement("div");
templateContainer.innerHTML = itemTemplateLoaded;
templateElement = templateContainer.firstChild;
WinJS.UI.process(templateElement);
var container = document.createElement("div");
templateElement.winControl.render(item.data, container);
return container;
});)
}
WinJS.Utilities.markSupportedForProcessing(self.selectTemplate);
WinJS.Namespace.define("TemplateSelector", {
template: self.selectTemplate
});
I can see one bug in the code. but not sure if that is the only issue here. promises needs to be chained. winjs.ui.processAll returns a promise.
itemTemplatePromise.then(function (itemTemplateLoaded) {
var templateContainer = document.createElement("div");
templateContainer.innerHTML = itemTemplateLoaded;
templateElement = templateContainer.firstChild;
return WinJS.UI.processAll(templateElement);
}).then(function onprocessall()
{
var container = document.createElement("div");
templateElement.winControl.render(item.data, container);
return container;
});

Monotouch.Dialog StyledStringElement delegate always fires for the last element added

given the following code, I am having an issue when clicking on each element. If we assume I have 5 exercises and therefore create 5 elements in the foreach() loop, when the table is rendered and I click on any element, the delegate always gets the exercise of the 5th (last) element.
The elements are displayed properly, each showing the associated exercise's name. It is just the delegate that does not work as expected.
If I do not use a foreach loop and hardcode each element instead it works as expected. However if I cannot dynamically populate the dialogViewController and use the element tapped event for each one, is not good.
private void CreateExerciseTable()
{
Section section = new Section();
foreach (var exercise in exercises)
{
var element = new StyledStringElement(exercise.ExerciseName,
delegate { AddExercise(exercise); })
{
Font = Fonts.H3,
TextColor = UIColor.White,
BackgroundColor = RGBColors.LightBlue,
Accessory = UITableViewCellAccessory.DisclosureIndicator
};
section.Elements.Add(element);
}
var root = new RootElement("Selection") {
section
};
var dv = new DialogViewController(root, true);
dv.Style = UITableViewStyle.Plain;
//Remove the extra blank table lines from the bottom of the table.
UIView footer = new UIView(new System.Drawing.RectangleF(0,0,0,0));
dv.TableView.TableFooterView = footer;
dv.TableView.SeparatorColor = UIColor.White;
dv.TableView.BackgroundColor = UIColor.White;
tableFitnessExercises.AddSubview(dv.View);
}
private void AddExercise(FitnessExercise exercise)
{
NavigationManager.FitnessRoutine.Add(exercise);
PerformSegue(UIIdentifierConstants.SegAddExerciseToFitnessRoutine, this);
}
This is a classic closure bug!
The problem is that you are accessing the loop reference.
Try:
foreach (var exercise in exercises)
{
var localRef = exercise;
var element = new StyledStringElement(exercise.ExerciseName,
delegate { AddExercise(localRef); })
{
Font = Fonts.H3,
TextColor = UIColor.White,
BackgroundColor = RGBColors.LightBlue,
Accessory = UITableViewCellAccessory.DisclosureIndicator
};
section.Elements.Add(element);
}
For more on this see http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx

Resources