Duplicating custom nodes in JavaFX - javafx

As far as I understand, duplicating nodes in JavaFX should be done with the Duplicator.duplicate function.
It works fine when duplicating nodes whose types are included in JavaFX library, for example
def dup = Duplicator.duplicate(Rectangle{x:30 y:30 width:100 height:100});
dup.translateX = 10;
insert dup into content;
would insert a black rectangle to the scene.
However if I define a new class in the following way:
class MyRect extends Rectangle {}
Or
class MyRect extends CustomNode {
override function create() {Rectangle{x:30 y:30 width:10 height:10}}
}
It gives me the following runtime error
Type 'javafxapplication1.NumberGrid$MyRect' not found.
Where of course javafxapplication1.NumberGrid are the package and file the MyRect class is in.
This guy at Sun's forums had the same problem, but I don't see any answer in there.
Or maybe I'm doing that the wrong way, and there's a better approach for duplicating custom nodes?
update: Trying to duplicate Group worked, but trying to duplicate Stack yields the same error.
According to the documentation, it's supposed to support all types supported in FXD including Node, but maybe it supports only some of Node's descendants?

I know its an old question, but did you try the following?
public class MyRect extends CustomNode, Cloneable {
override public function clone(): MyRect {
super.clone() as MyRect;
}
...
}
Which works for me via
var newRect = rect.clone();
Which is not a deep copy (but in my case I didn't need this)

Related

EF5 code first - You cannot use Ignore method on the property

This question has been asked all over the place, but the SUPPOSED workaround on CodePlex does not work.
I'm hoping someone has some updated information.
I have an EF5 Code First project where I have dozens of entities directly derived from an abstract base class. After creating some new entities that are derived from a class derived from that base class, when my database is initially created I get the following error:
You cannot use Ignore method on the property 'DisplayString' on type
'Doctor' because this type inherits from the type
'Contact' where this property is mapped. To exclude
this property from your model, use NotMappedAttribute or Ignore
method on the base type.
Here's my classes:
public abstract class AbsoluteBaseClass
{
[NotMapped]
public abstract string DisplayString { get; set; }
...
}
public class Contact : AbsoluteBaseClass
{
[NotMapped]
public override string DisplayString
{
get { return string.Format("{0} {1}", FirstName, LastName); }
set { throw new System.NotImplementedException(); }
}
...
}
public class Doctor : Contact
{
...
}
I have other cases like this (class derived from a class derived from the base) and I've got things working, but adding these new classes broke things again.
I've also tried add .Ignore directives (derived class before base) in OnModelCreating and that does not make any difference either.
modelBuilder.Entity<Doctor>().Ignore(p => p.DisplayString);
modelBuilder.Entity<Contact>().Ignore(p => p.DisplayString);
I have several cases where I have entities derived from AbsoluteBaseClass and most times things work, but then I would add another derived class and things would break again. There appears to be no rhyme or reason to this.
I'd REALLY appreciate some advice on how I can definitively get this to work as I add classes. There appears mention around of a fix applied to the EF5 source,then you build the source. Has anyone tried that and got it to work?
Thanks for any advice!
Corey.
In my case, when using Code First (EF6) on an existing database, I created some base classes to handle the common properties like ID.
(Note: the following are inside the OnModelCreating(DbModelBuilder mb) method)
I then needed to ignore the base classes entirely with:
mb.Ignore(new[] {
typeof(BaseClassA),
typeof(BaseClassB)
});
Then, somewhat counterintuitively, I needed to register the base model properties with:
mb.Entity<BaseClassA>().HasKey(m => m.ID);
mb.Entity<BaseClassB>().Whatever...
One of my derived classes needed to ignore one of the base properties (call it NormallyNotIgnored). I used EntityTypeConfiguration, but I assume you could do the same with regular Fluent:
mb.Entity<DerivedClassB1>().Ignore(m => m.NormallyNotIgnored);
This at least has compiled/migrated (with -IgnoreChanges on the migration, since the tables already exist) and resolved the error in question.

Can I control multiple instances of movieclips in a loaded swf at once?

I am loading an swf created in flash professional cs5 via the loader class into a flex 4.1 application. The flash file contains multiple movieclips that are exported for actionscript and those movieclips exist in many instances throughout the movie.
Iterating through everything, comparing class types seems to be the most easy but also the most redundant way to solve this. Is there any way of using the class name as a kind of global selector to access the clips?
I could also make the sub-clips in the flash listen for an event on which they perform an action, but I am not really sure what might be best.
In cases like these, I find that a good way to solve the problem is to create a statically accessable class that manages instances of other classes that are registered with it on instantiation. As an example...
public class GlobalStopper{
private static var clips:Array = [];
public static function add(mc:MovieClip):void{
clips.push(mc);
}
public static function stop():void{
var mc:MovieClip;
for(var i:int = 0, ilen:int = clips.length ; i < ilen ; i++){
mc = clips[i] as MovieClip;
if (mc) mc.stop();
}
}
}
and...
public class GloballyStoppableMovieClip extends MovieClip{
public function GloballyStoppableMovieClip(){
GlobalStopper.add(this);
}
}
Any and all instances of GloballyStoppableMovieClip are instantly registered with the GlobalStopper, so calling
GlobalStopper.stop();
...will stop all registered movieclips.
You can add in any other functions you want. Furthermore, instead of having add accept MovieClip instances, you could have it accept IStoppable or IPlayable objects that implement public functions stop() and play() that your movieclip subclass (or non-movieclip object that also might need to stop and play!) then implements.
But as for jQuery-like selectors? Not really the way I'd handle this particular issue.
i guess typing it out did the trick. i used the event solution:
in the root timeline i placed a function like this:
function cause():void {
dispatchEvent(new Event("do stuff",true));
}
and in the library clip's main timeline goes:
DisplayObject(root).addEventListener("do stuff", function (e:Event=null) {
... whatever ...
});
this is dirty but you get the idea.

groovy swingbuilder bindable list and tables

Is there a way to bind data to a list and/or a table using the groovy swing builder bind syntax? I could only find simple examples that bind simple properties like strings and numbers to a text field, label, or button text.
Had a look round, and the best I could see was using GlazedLists rather than standard Swing lists
http://www.jroller.com/aalmiray/entry/glazedlists_groovy_not_your_regular
There is a GlazedList plugin. And this article is very helpful. The Griffon guys swear by GlazedLists.
I just did something like this--it's really not that hard to do manually. It's still a work in progress, but if it helps anyone I can give what I have. So far it binds the data in both directions (Updating the data updates the component, editing the table updates the data and sends a notification to any propertyChangeListeners of the "Row")
I used a class to define one row of a table. You create this class to define the nature of your table. It looks something like this:
class Row
{
// allows the table to listen for changes and user code to see when the table is edited
#Bindable
// The name at the top of the column
#PropName("Col 1")
String c1
#Bindable
// In the annotation I set the default editable to "false", here I'll make c2 editable.
// This annotation can (and should) be expanded to define more column properties.
#PropName(value="Col 2", editable=true)
String c2
}
Note that once the rest of the code is packaged up in a class, this "Row" class is the ONLY thing that needs to be created to create a new table. You create instances of this class for each row, add them to the table and you are completely done--no other gui work aside from getting the table into a frame.
This class could include quite a bit more code--I intend to have it contain a thread that polls a database and updates the bound properties, then the table should pick up the changes instantly.
In order to provide custom column properties I defined an annotation that looks like this (I plan to add more):
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface PropName {
String value();
boolean editable() default false
}
The rest is a class that builds the table. I keep it in a separate class so it can be reused (by instantiating it with a different "Row" class)
NOTE: I butchered this as I pasted it in so it may not run without a little work (braces probably). It used to include a frame which I removed to just include the table. You need to wrap the table returned from getTable() in a frame..
public class AutoTable<T>
{
SwingBuilder builder // This way external code can access the table
def values=[] // holds the "Row" objects
PropertyChangeListener listener={repaint()} as PropertyChangeListener
def AutoTable(Class<T> clazz)
{
builder = new SwingBuilder()
builder.build{
table(id:'table') {
tableModel(id:'tableModel') {
clazz.declaredFields.findAll{
it.declaredAnnotations*.annotationType().contains(PropName.class)}.each {
def annotation=it.declaredAnnotations.find{it.annotationType()==PropName.class
}
String n=annotation.value()
propertyColumn(header:n, propertyName:it.name, editable:annotation.editable())
}
}
tableModel.rowsModel.value=values
}
}
// Use this to get the table so it can be inserted into a container
def getTable() {
return builder.table
}
def add(T o) {
values.add(o)
o.addPropertyChangeListener(listener)
}
def remove(T o) {
o.removePropertyChangeListener(listener)
values.remove(o)
}
def repaint() {
builder.doLater{
builder.table.repaint();
}
}
}
There is probably a way to do this without the add/remove by exposing a bindable list but it seemed like more work without a lot of benifit.
At some point I'll probably put the finished class up somewhere--if you have read this far and are still interested, reply in a comment and I'll be sure to do it sooner rather than later.

How do I reference a Global class from a class with the same name in ActionScript?

Due to requirements outside of my control (don't ask, it's ridiculous) I need to create an AS3 class called 'Math' that references the Global AS Math class. So, for example:
package my.package
{
public class Math
{
public static function pow( a:Number, b:Number ):Number {
// How do I call the Global.as$Math#pow(..) function?
return Math.pow(a,b);
}
}
}
The code above is clearly wrong - results in infinite recursion. I'm not sure how to say that I want to delegate to the Global.as$Math class and not this Math class...
My current awkward solution is to delegate to another class (not named Math) that passes through to the Global Math class. Is there a better way to do this?
Thanks!
Here is another way that popped into my mind after reading Josh Tynjala's post about how package in actionscript are just an abstraction layer over namespaces:
public class Math
{
namespace globalNs = "";
public static function pow( a:Number, b:Number ):Number
{
return globalNs::Math.pow(a, b);
}
}
The globalNs::Math.pow explicitly refer to the top level Math Class.
Save a static reference to the flash player Math object and use it throughout your static methods:
package test
{
import flash.utils.getDefinitionByName;
public class Math
{
private static var _flashMath:Class = Class(getDefinitionByName("Math"));
public static function pow( a:Number, b:Number ):Number
{
return _flashMath.pow(a, b);
}
}
}
Try using the AS3 namespace to refer to the AS3 Math object. Or your class could simply extend the Math object and it would automatically have all of the Math object's functionality without you having to rewrite all those wrapper functions.
As a small follow up on apphackers reply, you can not simple extends the AS3 Math object and have all it's functionality as was suggeested. Static methods are lost when extending an object since they are statically tied to the object which defines them. Additionally you can't extends a class with the same name. You might have some success with the namespace solution however, though I'm not sure if it'll work with static methods, I'd be interested to see your results.
Math is a special case in AS3 because really it shouldn't be global but it is. So it has no namespace as far as I can tell. The solution you came up with to route through another class is actually very clever. But you know that really the solution is to name the class Math2 or MathHelper or MathUtils rather than Math. Please tell me what the reason beyond your control is! The not knowing is killing me!!!

Is it possible to add behavior to a non-dynamic ActionScript 3 class without inheriting the class?

What I'd like to do is something like the following:
FooClass.prototype.method = function():String
{
return "Something";
}
var foo:FooClass = new FooClass();
foo.method();
Which is to say, I'd like to extend a generated class with a single method, not via inheritance but via the prototype.
The class is generated from a WSDL, it's not a dynamic class, and I don't want to touch the generated code because it will be overwritten anyway.
Long story short, I'd like to have the moral equivalent of C# 3:s Extension Methods for AS3.
Edit: I accepted aib's answer, because it fits what I was asking best -- although upon further reflection it doesn't really solve my problem, but that's my fault for asking the wrong question. :) Also, upmods for the good suggestions.
Yes, such a thing is possible.
In fact, your example is very close to the solution.
Try
foo["method"]();
instead of
foo.method();
#Theo: How would you explain the following working in 3.0.0.477 with the default flex-config.xml (<strict>true</strict>) and even a -compiler.strict parameter passed to mxmlc?
Foo.as:
package
{
public class Foo
{
public var foo:String;
public function Foo()
{
foo = "foo!";
}
}
}
footest.as:
package
{
import flash.display.Sprite;
public class footest extends Sprite
{
public function footest()
{
Foo.prototype.method = function():String
{
return "Something";
}
var foo:Foo = new Foo();
trace(foo["method"]());
}
}
}
Note that the OP said inheritance was unacceptable, as was modifying the generated code. (If that weren't the case, adding "dynamic" to the class definition would probably be the easiest solution.)
Depending on how many methods your class has, this may work:
Actual Class:
public class SampleClass
{
public function SampleClass()
{
}
public function method1():void {
Alert.show("Hi");
}
Quick Wrapper:
var actualClass:SampleClass = new SampleClass();
var QuickWrapper:Object = {
ref: actualClass,
method1: function():void {
this.ref.method1();
},
method2: function():void {
Alert.show("Hello!");
}
};
QuickWrapper.method1();
QuickWrapper.method2();
#aib is unfortunately incorrect. Assuming strict mode (the default compiler mode) it is not possible to modify the prototype of non-dynamic class types in ActionScript 3. I'm not even sure that it's possible in non-strict mode.
Is wrapping an option? Basically you create a class that takes one of the objects you get from the web service and just forwards all method calls to that, but also has methods of its own:
public class FooWrapper extends Foo {
private var wrappedFoo : Foo;
public function FooWrapper( foo : Foo ) {
wrappedFoo = foo;
}
override public function methodFromFoo( ) : void {
wrappedFoo.methodFromFoo();
}
override public function anotherMethodFromFoo( ) : void {
wrappedFoo.anotherMethodFromFoo();
}
public function newMethodNotOnFoo( ) : String {
return "Hello world!"
}
}
When you want to work with a Foo, but also have the extra method you need you wrap the Foo instance in a FooWrapper and work with that object instead.
It's not the most convenient solution, there's a lot of typing and if the generated code changes you have to change the FooWrapper class by hand, but unless you can modify the generated code either to include the method you want or to make the class dynamic I don't see how it can be done.
Another solution is to add a step to your build process that modifies the source of the generated classes. I assume that you already have a step that generates the code from a WSDL, so what you could do is to add a step after that that inserts the methods you need.
Monkey patching is an (inelegant) option.
For example, suppose you don't like the fact that Flex 3 SpriteAsset.as returns a default border metrics of [7,7,7,7] (unlike flex 2). To fix this, you can:
Create a copy of SpriteAsset.as and add it to your project at /mx/core/SpriteAsset.as
Edit your local copy to fix any problems you find
Run your ap
Google "flex monkey patch" for more examples and instructions.

Resources