InDesign SDK : Drag'n'Drop from a Flex Panel - apache-flex

I have a Flex panel, in InDesign, from which I drag an URL. If I drop this URL on a text editor or a web browser, it works. But when I try to drop it on my InDesign document, it's a little bit harder.
I have implemented a subclass of CDragDropTargetFlavorHelper. The drop works perfectly on Windows. But on mac, I have problems in the method CouldAcceptTypes :
DragDrop::TargetResponse AutocatDNDCustomFlavorHelper::CouldAcceptTypes(const DragDropTarget* target, DataObjectIterator* dataIter, const IDragDropSource* fromSource, const IDragDropController* controller) const
{
if (0 != dataIter && 0 != target)
{
DataExchangeResponse response = dataIter->FlavorExistsWithPriorityInAllObjects(kURLDExternalFlavor);
if (response.CanDo())
{
...
}
}
}
The problem is that response.canDo() answers kTrue on Windows, but kFalse on Mac. I tried to explore the content of dataIter, but a call on dataIter->First() returns nil. I tried a controller->GetItemCount(), which returns 1. But if I try a controller->GetDragItem(1), I get a nil pointer. I have the impress there is no item. Though, the drop works on another app than InDesign, as I said.
Is it a problem of internalization ? Or something else ? It let me dry.
Thanks in advance
-------------------------- EDIT -----------------------------------
I solved this problem, but discovered another one. The flavor sent by the flex panel has been changed, so that it's a text flavor instead of an URL flavor. My method couldAcceptType works now :
DragDrop::TargetResponse AutocatDNDCustomFlavorHelper::CouldAcceptTypes(const DragDropTarget* target, DataObjectIterator* dataIter, const IDragDropSource* fromSource, const IDragDropController* controller) const
{
if (0 != dataIter && 0 != target)
{
// Check for URL Flavor in the drag
DataExchangeResponse response = dataIter->FlavorExistsWithPriorityInAllObjects(kTEXTExternalFlavor);
if (response.CanDo())
{
return DragDrop::TargetResponse(response, DragDrop::kDropWillCopy);
}
}
return DragDrop::kWontAcceptTargetResponse;
}
The problem is now in the ProcessDragDropCommand method. Here is the code :
ErrorCode AutocatDNDCustomFlavorHelper::ProcessDragDropCommand(IDragDropTarget* target, IDragDropController* controller, DragDrop::eCommandType action)
{
// retrieve drop data
IPMDataObject* dragDataObject = controller->GetDragItem(1);
uint32 dataSize = dragDataObject->GetSizeOfFlavorData(kTEXTExternalFlavor) ;
...
}
The problem is the IMPDataObject I get is nil. There is no item in the controller. However, there were items in the CouldAcceptTypes method, in the DataObjectIterator. So, where are my items ?
I tried using a custom CDataExchangeHandlerFor, but could not really understand what its usage was for. It didn't work anyway.
Has anyone an idea ?
Regards,
RĂ©mi

The problem is the argument of the GetDragItem. It is 1 on PC. It is a strange value on Mac (something like 719853). The only dirty solution I found is doing a memcpy from the object retrieved drom the dataIter in the CouldAcceptTypes method, and use it in the ProcessDragDropCommand method.

Related

What could cause .wasm to load images so slowly?

In my Uno test project, it takes about 4 seconds to load 50 images into an ItemsWrapGrid on the UWP platform. The same images take 225 seconds (3 minute 45 seconds) to load into a WrapPanel. Since the only difference in the code is ItemsWrapGrid or WrapPanel, I'm thinking the problem is the WrapPanel, but I can't be sure, it could be in how the platforms implement the <Image ItemsSource=""/.
I don't have any experience with .wasm so I don't know if this is expected (is it?). Is there something I can do to Optimize for wasm?
or any other thoughts? 4- minutes is just not acceptable compared to about 4 seconds.
Thanks
Thanks for asking if I could repro in Uno Playground. I was unaware of the site.
I was NOT ABLE to repro on the playground, which led me to investigate other possibilities.
I have resolved the issue.
My design pattern was to define a single ObservableCollection without a property change notification:
public ObservableCollection<PictureViewModel> Pictures {get;set }
I would bind that to my UserControl and update by Pictures.Clear().
This is my snippet that resulted in the long render time:
List<Picture> PictList = await DataService.GetPicturesByEvent(this.SelectedEvent.EvtKey, clubkey, skipPosition, this.PagingViewModel.PageSize);
List<PictureViewModel> PictVMList = mapper.Map<List<Picture>, List<PictureViewModel>>(PictList);
if (PictVMList != null && this.SelectedEvent != null && !string.IsNullOrEmpty(SelectedEvent.FilePath))
{
this.Pictures.Clear();
foreach (PictureViewModel item in PictVMList)
{
item.Parent = this;
item.SetURL(SelectedEvent);
this.Pictures.Add(item);
}
this.SelectedPicture = PictVMList.Count > 0 ? PictVMList.First() : null;
}
To resolve the long render time. I:
Made my ObservableCollection observable.
Removed all instances of Picture.Clear();
Created a new ObservableCollection whenever it needed updating.
The Resolved code snippet is:
List<Picture> PictList = await DataService.GetPicturesByEvent(this.SelectedEvent.EvtKey, clubkey, skipPosition, this.PagingViewModel.PageSize);
List<PictureViewModel> PictVMList = mapper.Map<List<Picture>, List<PictureViewModel>>(PictList);
if (PictVMList != null && this.SelectedEvent != null && !string.IsNullOrEmpty(SelectedEvent.FilePath))
{
foreach (PictureViewModel item in PictVMList)
{
item.Parent = this;
item.SetURL(SelectedEvent);
}
this.SelectedPicture = PictVMList.Count > 0 ? PictVMList.First() : null;
}
Pictures = new ObservableCollection<PictureViewModel>(PictVMList);
I don't understand why my initial code pattern did not work as expected, but can live with adding an OnPropertyChanged("Pictures") notification.
As of Uno 3.10, ItemWrapGrid is not supported on WebAssembly. Using the WrapPanel control will force the materialization of all the items in the list, making the performance particularly slow.
You're not specifying which control you're using as a panel, but if you're using a ListView control, the virtualization will be enabled, though not with the layout wrapping that you need.
If you want virtualizing grid-like layouts, you can also use the ItemsRepeater control, and its layouts (e.g. FlowLayout, StackLayout, or WCT's WrapLayout).

Handlebars.js: how does partials gets invoked in a helper? I got: TypeError: fn is not a function

I am learning Handlebars. It still appears to be a mystery to me that how a partials gets invoked in a helper.
I read this tutorial: http://blog.teamtreehouse.com/handlebars-js-part-2-partials-and-helpers
From this example in the tutorial,
Handlebars.registerHelper("stripes", function(array, even, odd, fn) {
var buffer = "";
for (var i = 0, j = array.length; i < j; i++) {
var item = array[i];
// we'll just put the appropriate stripe class name onto the item for now
item.stripeClass = (i % 2 == 0 ? even : odd);
// show the inside of the block
buffer += fn(item); <!-- this is where a partials gets invoked -->
}
// return the finished buffer
return buffer;
});
it appears the partial is added and applied by Handlebars. However, I used this same approach in Handablebars 1.3.0 and 2.0 Alpha-2, it seems no longer the case. I always got the error:
TypeError: fn is not a function
buffer += fn(item);
I did quite online search and found a number tutorials, but none of them shows how partials is hooked up with a helper in version 1.3.0 or later.
Can someone help me out?
Thanks a lot!
OK. I believed I solved this problem. In v1.0 or later, Handlebars puts everything in a hash, not just fn. So, everything in the above post still is valid except these two lines:
Handlebars.registerHelper("stripes", function(array, even, odd, options)
...
buffer += options.fn(item);
Hope this helps someone else. Any confirmation is welcome. I feel bad that there is no direct example on this, at least I did not find it.
Regards.

TypeError: $it0.hasNext is not a function

Running a few canvases which work fine in chrome but fail in the latest version of Mozilla. I know this was an issue a while back and I thought the new processing-1.4.1.js was fixed to accommodate for the for loop failure seen here. Does anyone know if they did or if not, why this is happening and how to fix it?
edit:
Test code that will not work:
void setup() {
String names[] = {"Alexis", "Thomas", "Antoine"};
for(String name : names) {
alert(name); // doesn't on Firefox 17+, bug?
}
}
void draw() {
}
This is a problem with Processing.js and some recent changes in Firefox as discussed here.
You have two options:
Solution 1 is to hack Processing.js file as discussed by alexbbrown in the aforementioned link (a harsh and nasty solution), essentially finding the actual Processing.js file, editing it with your favourite text editor and change lines 291-292 from:
if (obj.iterator instanceof
Function) return obj.iterator();
to:
if (obj.iterator instanceof Function && obj.hasNext instanceof Function)
return obj.iterator();
Solution 2 is to change your code and live without the lovely for-each syntax (a softer, compromising solution), replacing the lines:
for (String name : names) {
alert(name); // doesn't on Firefox 17+, bug?
}
with the common for syntax:
for (int i = 0; i < names.length; i++) {
alert(names[i]);
}
whatever you do, may the for be with you...

Find broken images in page & image replace by another image

Hi I am using selenium webdriver 2.25.0 & faceing the some serious issues,
how to find broken images in a page using Selenium Webdriver
How to find the image is replace by another image having same name (This is also bug) using webdriver.
Thanks in advance for your value-able suggestions.
The accepted answer requires that you use a proxy with an extra call to each image to determine if the images are broken or not.
Fortunately, there is another way you can do this using only javascript (I'm using Ruby, but you can use the same code in any executeScript method across the WebDriver bindings):
images = #driver.find_elements(:tag_name => "img")
broken_images = images.reject do |image|
#driver.execute_script("return arguments[0].complete && typeof arguments[0].naturalWidth != \"undefined\" && arguments[0].naturalWidth > 0", image)
end
# broken_images now has an array of any images on the page with broken links
# and we want to ensure that it doesn't have any items
assert broken_images.empty?
To your other question, I would recommend just taking a screenshot of the page and having a human manually verify the resulting screenshot has the correct images. Computers can do the automation work, but humans do have to check and verify its results from time to time :)
The next lines are not optimized, but they could find broken images:
List<WebElement> imagesList = _driver.findElements(By.tagName("img"));
for (WebElement image : imagesList)
{
HttpResponse response = new DefaultHttpClient().execute(new HttpGet(image.getAttribute("src");));
if (response.getStatusLine().getStatusCode() != 200)
// Do whatever you want with broken images
}
Regarding your second issue, I think I didn't understand it correctly. Could you explain it with more detail?
Based on the other answers, the code that eventually worked for me in an angular / protractor / webdriverjs setting is:
it('should find all images', function () {
var allImgElts = element.all(by.tagName('img'));
browser.executeAsyncScript(function (callback) {
var imgs = document.getElementsByTagName('img'),
loaded = 0;
for (var i = 0; i < imgs.length; i++) {
if (imgs[i].naturalWidth > 0) {
loaded = loaded + 1;
};
};
callback(loaded);
}).then(function (loadedImagesCount) {
expect(loadedImagesCount).toBe(allImgElts.count());
});
});
The webdriver code counts the number of img elements, and the function executed within the browser context counts the number of successfully loaded elements. These numbers should be the same.

Is it possible to find the function and/or line number that caused an error in ActionScript 3.0 without using debug mode?

I'm currently trying to implement an automated bug reporter for a Flex application, and would like to return error messages to a server along with the function/line number that caused the error. Essentially, I'm trying to get the getStackTrace() information without going into debug mode, because most users of the app aren't likely to have the debug version of flash player.
My current method is using the UncaughtErrorEvent handler to catch errors that occur within the app, but the error message only returns the type of error that has occurred, and not the location (which means it's useless). I have tried implementing getStackTrace() myself using a function name-grabber such as
private function getFunctionName (callee:Function, parent:Object):String {
for each ( var m:XML in describeType(parent)..method) {
if ( this[m.#name] == callee) return m.#name;
}
return "private function!";
}
but that will only work because of arguments.callee, and so won't go through multiple levels of function calls (it would never get above my error event listener).
So! Anyone have any ideas on how to get informative error messages through the global
error event handler?
EDIT: There seems to be some misunderstanding. I'm explicitly avoiding getStackTrace() because it returns 'null' when not in debug mode. Any solution that uses this function is what I'm specifically trying to avoid.
Just noticed the part about "I don't want to use debug." Well, that's not an option, as the non-debug version of Flash does not have any concept of a stack trace at all. Sucks, don't it?
Not relevant but still cool.
The rest is just for with the debug player.
This is part of my personal debug class (strangely enough, it is added to every single project I work on). It returns a String which represents the index in the stack passed -- class and method name. Once you have those, line number is trivial.
/**
* Returns the function name of whatever called this function (and whatever called that)...
*/
public static function getCaller( index:int = 0 ):String
{
try
{
throw new Error('pass');
}
catch (e:Error)
{
var arr:Array = String(e.getStackTrace()).split("\t");
var value:String = arr[3 + index];
// This pattern matches a standard function.
var re:RegExp = /^at (.*?)\/(.*?)\(\)/ ;
var owner:Array = re.exec(value);
try
{
var cref:Array = owner[1].split('::');
return cref[ 1 ] + "." + owner[2];
}
catch( e:Error )
{
try
{
re = /^at (.*?)\(\)/; // constructor.
owner = re.exec(value);
var tmp:Array = owner[1].split('::');
var cName:String = tmp.join('.');
return cName;
}
catch( error:Error )
{
}
}
}
return "No caller could be found.";
}
As a side note: this is not set up properly to handle an event model -- sometimes events present themselves as either not having callers or as some very weird alternate syntax.
You don't have to throw an error to get the stack trace.
var myError:Error = new Error();
var theStack:String = myError.getStackTrace();
good reference on the Error class
[EDIT]
Nope after reading my own reference getStackTrace() is only available in debug versions of the flash player.
So it looks like you are stuck with what you are doing now.

Resources