Passing Canvas' 2D Context in Dart - dart

I have a function that accepts CanvasRenderingContext2D as a parameter and does the drawing. Whenever I try to pass it, I get this:
CanvasRenderingContext2D is not assignable to CanvasRenderingContext2D
That function looks like this:
void draw(CanvasRenderingContext2D context) {
...
}
I thought everything is passed as a reference in Dart (just like JS), which shouldn't cause such problems. Is there a way to say I want a reference to the object and not the object it self? Or is there something else I should know?
EDIT:
The problem was that in one file I imported dart:html and in another I had dart:dom. The names for corresponding interfaces are the same but they are different.

This is likely because you are using dart:dom and dart:html in the same application. To avoid such errors you should import one of them with a namespace
#import('dart:html');
#import('dart:dom', prefix: 'dom');
then you can access code defined in both of them as
window // dart:html window
dom.window // dart:dom window
for more information see this answer

Related

The argument type 'ListOf5' can't be assigned to the parameter type 'ListOf5'

I need to implement an abstract class function, which own a an specific data type. But I need inside my logic layer to make the attribute which is going to be passed as a dynamic data type. But when i Pass it to the function, i am sure that its data type will be as needed. So, i type (product.value.pickedImages) as ListOf5) . But it does an Exception.
The Abstract Class Code Is:
Future<Either<FireStoreServerFailures, List<String>>> uploadProductImages(
{required ListOf5<File> images});
The Implementation Code Is:
Future<Option<List<String>>> _uploadImagesToFirestorage() async {
return await productRepo
.uploadProductImages(
images: (product.value.pickedImages) as ListOf5<File>) // Exception
}
The Exception Is:
The argument type 'ListOf5 < dynamic>' can't be assigned to the
parameter type 'ListOf5 < File>'.
You are trying to cast the List from List<dynamic> to List<String>.
Instead, you should cast each item, using something like this:
void main() {
List<dynamic> a = ['qwerty'];
print(List<String>.from(a));
}
Not sure about the implementation of this ListOf5 though...
The cast (product.value.pickedImages) as ListOf5<File> fails.
It fails because product.value.pickedImages is-not-a ListOf5<File>, but instead of ListOf5<dynamic> (which may or may not currently contain only File objects, but that's not what's being checked).
Unlike a language like Java, Dart retains the type arguments at run-time(it doesn't do "erasure"), so a ListOf5<dynamic> which contains only File objects is really different from a ListOf5<File> at run-time.
You need to convert the ListOf5<dynamic> to a ListOf5<File>.
How to do that depends on the type ListOf5, which I don't know.
For a normal List, the two most common options are:
(product.value.pickedImages).cast<File>(). Wraps the existing list and checks on each read that you really do read a File. It throws if you ever read a non-File from the original list. Perfectly fine if you'll only read the list once.
List<File>.of(product.value.pickedImages). Creates a new List<File> containing the values of product.value.pickedImages, and throws if any of the values are not File objects. Requires more memory (because it copies the list), but fails early in case there is a problem, and for small lists, the overhead is unlikely to be significant. If you read the resulting list many times, it'll probably be more efficient overall.
If the ListOf5 class provides similar options, you can use those. If not, you might have to build a new ListOf5 manually, casting each element of the existing ListOf5<dynamic> yourself.
(If the ListOf5 class is your own, you can choose to add such functionality to the class).

Dart js-interop and overloaded methods

How do you handle interfacing with JS libraries that have overloaded methods?
For example Leaflet.js has both of the following defined for the Map object:
openPopup(popup); // opens the given popup
openPopup(html, LatLng, popOptions); // creates a popup with the html at the location, using the popup options.
What I've come up with is:
#JS("L.Map")
class Map {
/* code */
external Map openPopup(dynamic popup, [LatLng coords, PopupOptions opts]);
/* code */
}
Is there a better way? Note: this seems to work but the analyzer complains: The method openPopup is not defined for the class Map.
Dart: 1.17.1
package:js-0.6.0
So far I have not been able to specify a different name for an instance member/method using the JS() directive which is a big issue especially for javascript object that have method names that clash with Dart keywords (such as 'catch' in a javascript Promise). I ended up using plain dart:js. And anyway even when using package/js, I ended up adding another layer to make the api more dartish (especially with callbacks and promise) especially to enforce argument types.
What I would expect would be to be able to do (in your example)
#JS("L.Map")
class Map {
JS('openPopup')
external Map openPopupHtml(String html, [LatLng coords, PopupOptions opts]);
JS('openPopup')
external Map openPopup(Popup popup);
}
but that does not seem to work. Maybe should it be considered as a feature enhancement.

Notify Observable-Watchers programmatically in Dart

Once again, a Dart/Polymer related question.
I wanted to use the Parse.com JavaScript library, but since it's not available in Dart I've written Wrapper classes which store a JsObject and delegate all calls from Dart to the corresponding JavaScript object. Basically it's like a proxy.
Guess what, it works pretty great.
However, my observables don't. To understand this, you have to take a look at the following structure of one of my "proxy"-classes.
class ParseObject extends Observable {
JsObject _jsDelegate = new JsObject(context['Parse']['ParseObject']);
void set(String key, dynamic value) {
_jsDelegate.callMethod('set', [key, jsify(value)];
}
dynamic get(String key) {
return dartify(_jsDelegate.callMethod('get', [key]));
}
}
The HTML code of my Polymer Element looks like this:
<div>Name: {{project.get('name')}}</div>
Since the data binding is only evaluate in case the parameter of the method changed, it will never be updated and thus even though the name is changed, the old one will stay in place.
The solution I came up with is to store all the values the user is setting in the ParseObject#set(String, dynamic) method into a Map which is observable. This works but I think it's quiete dirty since I have to make sure that both Maps, the one in Dart and the one in the ParseObject's JavaScript representation equal.
Thus I am looking for a better solution and I think of some kind of method to tell Polymer to reevaluate it's data bindings.
Does such a method exist or are there any other possibilities to address this problem?
Extending observable by itself does nothing yet.
You need to annotate the getters with #observable (and if you are not using Polymer, you also need to add the observable transformer to pubspec.yaml). You can't make functions observable (this works in Polymer elements but not in Observable model classes. For more details about observable see for example Implement an Observer pattern in Dart or Dart: #observable of getters

Passing an object reference to Dart script of Polymer Element

I am trying to pass an object reference to the Dart script associated with a Polymer element. I have found the element in the DOM but I can't figure out how to call a method in the Dart associated with the element or any other way to dynamically pass an object to the Polymer element to be displayed.
Basically you just get a reference by using for example querySelector('#someid') and just assign the value to a field or setter or call a method and pass it as an argument.
querySelector('#someid').someField = someValue;
querySelector('#someid').setValue(someValue);
This might produce a hint in DartEditor but should still work when the code is executed. To get rid of the hint you can "cast" like
(querySelector('#someid') as MyComponent).someField = someValue;
querySelector('#someid') as MyComponent).setValue(someValue);
You need to import MyComponent to make this work.
If this doesn't something with your code might be wrong. For example the main() method if you have one. See how to implement a main function in polymer apps for more details.
If nothing of the above works, please add code to your question that shows what you're trying to accomplish.

How does casting work and reffering back to the parent

I cant get my head around this. I was looking at the lynda.com ActionScript 3.0 in Flash Professional CS5 Essential Training. I understand all the other stuff, but this guy places a skater on the stage he has this code on the first frame on the main timeline:
import flash.display.MovieClip;
import flash.events.MouseEvent;
var boarder:MovieClip = boarder_mc;
boarder.stop();
boarder.x = 0;
boarder.y = 0;
boarder.addEventListener(MouseEvent.CLICK, clickedBoarder);
function clickedBoarder(evt:MouseEvent):void
{
boarder.gotoAndPlay(2);
}
function restart():void
{
boarder_mc.gotoAndStop(1);
boarder_mc.x = 0;
}
then on the skater he has a Display Object Container (Movie Clip) in it he has a Display Object a bitmap image of a skater and then an animation on the timeline in the skater where at the end the skater falls. On that last frame he has:
stop();
parent.restart();
He explains that this may not work and it doesnt he gets an error:
1061: Call to a possibly undefined method restart through a reference with static type flash.display:DisplayObjectContainer.
He explains that it knows there is a stop() function on the main timeline, and that it knows there is a restart function on the main timeline, but the datatype is different. He also says that the parent is the main timeline.
He says that we need to put Object(parent).restart();
My question is of what datatype and what is the main timeline (Movieclip, DisplayObject, Display Object Container)?
Why would it be a different datatype?
Thanks
The main timeline is a MovieClip, or if you have a DocumentClass, then probably a custom type that at least extends MovieClip.
However when you ask for "parent" of your skater MovieClip, you are really using the parent property that MovieClip inherits from DisplayObject (ActionScript Docs Here). This property returns the parent as type DisplayObjectContainer, regardless of the type that it actually is. Since it is the parent of a DisplayObject, it doesn't matter type it is it has to extend DisplayObjectContainer, so this is how it is returned.
So when you compile your ActionScript, the compiler looks at "parent" and sees it as type DisplayObjectContainer, looks at its definition of DisplayObjectContainer and errors because DisplayObjectContainer doesn't have a function called "restart".
What you said about the "stop" function is not really correct, since you are not calling stop on the main timeline, your are calling stop on the Skater's timeline. If you wanted to call stop on the main timeline you would need to call parent.stop(), and this would give you the same error, since DisplayObjectContainer doesn't have a method called stop.
These are both compiler errors, and are caused because the compiler is following a set of rules, and it can't make assumptions about what might actually happen when your program is running. It just knows that when you call parent.restart() it might receive a DisplayObjectContainer that won't have the method restart on it, and a run-time error will occur.
Now, by casting parent as type object, you are effectively telling that compiler that this thing can have any method or property on it, since Object is a dynamic class. So the compiler will now assume that you as the developer know that the method "restart" will exists on the "Object" that is given to that bit of code, and therefor will not error any more.
Thank you very much for you reply. This is really confusing. I thought that DisplayObjectContainer is a subclass of Display Object and it extends it? I know that Display Object Container is a Display Object and it can contain other Display objects and Display Object Containers. So the way I understand it, the maintimeline is a movieclip and therefore a DisplayObejctContainer, which can contain other Display objects (that you create in you application) and that is why parent returns Display Object Container, but that it is also a abstract class which means that it cannot have methods such as .restart and goToAndPlay() because it cannot actually be instantiated. However if its a MovieClip as you say then it can..... I dont get it.Does it mean that it is an abstract Class?

Resources