Java Question Plea for help with Java's lack of delegates

agraham

Expert
Licensed User
Longtime User
I'm so rusty on Java, having not used it for years, that I need to ask for help. In C# this would be easy using delegates but I've forgotten the way to do it in Java.

I am wrapping a view to create my ScaleImageView library and want to receive an event in B4A to accomplish a bit of custom drawing on the view.

I have two questions.

1) What mechanism can I use to pass a (sort of) delegate to the CircleView instance and how would it call it passing a Canvas object to draw on?

2) Can the the code in the B4A event Sub access the Canvas to draw on it just by executing

Dim Can as Canvas = Sender

B4X:
public class ScaleImageViewWrapper extends ViewWrapper<SubsamplingScaleImageView>
{

   private string draweventname;
   private BA savedba;
   
   @BA.Hide
   public void innerInitialize(BA ba, String eventName, boolean keepOldObject)
   {
       if (!keepOldObject) {
           setObject(new CircleView(ba.context));
       }
       super.innerInitialize(ba, eventName, true);
       draweventname = eventName + "_ondraw" ;   
       savedba = ba
       // Pass something to the CircleView so that it can call DrawEvent       
   }   
   
   private DrawEvent(Canvas canvas)
   {
       savedba.raiseEvent2(this, true, draweventname, false, new Object() { canvas));
   }

   @Hide
   private static class CircleView extends SubsamplingScaleImageView {
   

       @Override
       protected void onDraw(Canvas canvas) {
           super.onDraw(canvas);
           // ... drawing stuff           
           // Call DrawEvent somehow               
       }   
   }   
}
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Something like:
B4X:
public class ScaleImageViewWrapper extends ViewWrapper<SubsamplingScaleImageView>
{

   private string draweventname;
   private BA savedba;
   
   @BA.Hide
   public void innerInitialize(BA ba, String eventName, boolean keepOldObject)
   {
       if (!keepOldObject) {
           setObject(new CircleView(ba.context, ba, eventName));
       }
       super.innerInitialize(ba, eventName, true);
       draweventname = eventName + "_ondraw" ;   
       savedba = ba
       // Pass something to the CircleView so that it can call DrawEvent       
   }   
   
   private DrawEvent(Canvas canvas)
   {
       savedba.raiseEvent2(this, true, draweventname, false, new Object() { canvas));
   }

   @Hide
   private static class CircleView extends SubsamplingScaleImageView {
   
        public BA ba;
        public String eventName; 
        public CanvasWrapper cw;
        public CircleView (Context context, BA ba, String eventName) {
          super(context);
          this.ba = ba;
          this.eventName = eventName;
          cw = new CanvasWrapper();
          cw.Initialize2(Bitmap.createBitmap(2, 2, Config.ARGB_8888)); //the bitmap is only used to initialize CanvasWrapper. Note that Canvas.getBitmap will not return something meaningful.
 
}
       @Override
       protected void onDraw(Canvas canvas) {
           super.onDraw(canvas);
           cw.canvas = canvas
           ba.raiseEvent(cw, eventName + "_ondraw");
       }   
   }   
}
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
You were very close Erel.
Even more :)
You wanted to use the Sender keyword so I wrote an answer where the canvas is set to be the sender object.

The best answer is:
B4X:
ba.raiseEvent(ScaleImageViewWrapper.this, eventName + "_ondraw", cw);

This way the developer can access the source view with Sender.
 
Top