#1429 adding a new swt library - package issues

peter Wed 2 Mar 2011

I am trying to make a pod to wrap swtchart, to make it work within fwt, but I've run into some issues with package access in the Java code.

I've succeeded in that I can create a Window and show an empty Chart inside it. I have a (fantom) class Chart, built on top of a (java) ChartPeer which extends WidgetPeer (following the example of a Label). However, the Java code needs access to WidgetPeer.self, the StrProp class and methods, etc. To make this work, I have had to change access privileges and rebuild the fwt Java implementations to make some things public.

Is there a way to make this approach work without modifying the existing fwt code? I tried putting the Java code into package fan.fwt, which would compile against the original fwt code so I could build the pod, but then ChartPeer could not be found at runtime, as fantom looks for Chart's peer as chart::ChartPeer. (Can I change the mapping from class to peer?)

Or perhaps there's a better strategy to use? All I'm doing is the following, building the pod as chart.

The fantom class looks like:

using fwt
using gfx

@Serializable
class Chart : Canvas
{
  native Str title
}

and the Java code looks like:

package fan.chart;

import fan.fwt.*;
import fan.sys.*;
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.widgets.Widget;
import org.swtchart.*;
import org.swtchart.Chart;

public class ChartPeer extends CanvasPeer {

  public static ChartPeer make (fan.chart.Chart self) throws Exception {
    ChartPeer peer = new ChartPeer();
    ((fan.fwt.Widget)self).peer = peer;
    peer.self = self;
    return peer;
  }

  public Widget create (Widget parent) {
    return new Chart((Composite)parent, SWT.NONE);
  }

  // Str title := ""
  public String title (fan.chart.Chart self) { return title.get(); }
  public void title (fan.chart.Chart self, String v) { title.set(v); }
  public final Prop.StrProp title = new Prop.StrProp(this, "")
  {
    public String get(Widget w) { return title.val; }
    public void set(Widget w, String v) { 
      title.val = v; 
      ((Chart)w).getTitle().setText(v);
    }
  };
}

and my hello graph program is:

using fwt
using chart

class Main
{
  public static Void main ()
  {
    Window
    {
      title = "empty chart"
      Chart { title = "My first chart" },
    }.open
  }
}

brian Wed 2 Mar 2011

I can make those classes public (although with the caveat they are really an implementation detail, nothing I would consider part of the locked down public API).

Just to make sure can you list the classes you need public?

peter Wed 2 Mar 2011

Thanks Brian, I feared that might be the only way. I'll press forward with writing the rest of the bindings, and send you a complete list of what I needed to change in fwt.

peter Sun 6 Mar 2011

Hi Brian,

You'll see I posted a link to my chart pod. About the changes, there were only 3 files to alter in fwt/java:

  1. Prop: although I only used some of the classes, I think all the child classes could be made public, including the constuctors, syncToControl, syncFromControl and the get/'set' methods without the Widget parameter.
  2. TreePeer: the four methods in Prop.Custom (line 84) need public access (because of changes to Prop).
  3. WidgetPeer: I had to make the fields control and self public.

I'm not sure if what I did was the best way - it just seemed the easiest way to get something working. I think the classes in Prop are useful to implement extensions to fwt. The fields in WidgetPeer may need the protection of accessors, but also seem to need accessing.

Thanks.

brian Mon 7 Mar 2011

Peter,

Can you double check this changeset and see if that works for you?

I was unclear on the for setter access to control and self, so I just exposed a getter.

Brian

peter Mon 7 Mar 2011

Thanks for this Brian. It's nearly there!

WidgetPeer also needs a setter for self, for use in constructors, e.g.:

public static ChartPeer make (fan.chart.Chart self) throws Exception {
  ChartPeer peer = new ChartPeer ();
  ((fan.fwt.Widget)self).peer = peer;
  peer.self(self);   // -> peer.self = self             
  return peer;
}

Also, Prop.java needs three further changes:

  1. accessor for peer in the parent class, Prop, i.e.
    public abstract class Prop 
    {
      public WidgetPeer peer () { return peer; }
      ...
    }
  2. the constructors to the classes need to be public.
  3. give protected access to the variable val in all classes. (Concrete property classes often need to view/modify their own values - sorry, forgot this one first time around.)

(Let me know if it's easier for me to email you the files.)

brian Tue 8 Mar 2011

okay, try this patch

peter Wed 9 Mar 2011

Thanks brian, it all works now.

Login or Signup to reply.