Other New beta 4.2 of b4j - Question about creating a view-wrapper-lib

DonManfred

Expert
Licensed User
Longtime User
Hello,

i´m just trying to do my first view wrapper for b4j using the new beta with the new CustomviewDesignerProperties.

I´m facing some problems.

1. I can not figure out on what i need to do in this wrapper to add a listener to get notified when the user change the state of the Toggle.
I tried using the mouseclick event but the event i defined did not fire.

2. From principle it works but the view do have an - for me unexpected - border. I guess it has something to do with the Style of the view.

toggleswitch0081.png


3. Additional i got the following logoutput when running my example

Program started.
Jan 24, 2016 10:44:51 AM com.sun.javafx.css.StyleConverterImpl getInstance
SEVERE: StyleConverterImpl : converter Class is null for : com.sun.javafx.scene.layout.region.CornerRadiiConverter
Jan 24, 2016 10:44:51 AM com.sun.javafx.css.StyleConverterImpl readBinary
SEVERE: could not deserialize com.sun.javafx.scene.layout.region.CornerRadiiConverter
could not deserialize com.sun.javafx.scene.layout.region.CornerRadiiConverter


The java code i am using is

B4X:
package anywheresoftware.b4j.objects;

import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;

import org.controlsfx.control.ToggleSwitch;
import org.controlsfx.control.BreadCrumbBar.BreadCrumbActionEvent;

import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.DependsOn;
import anywheresoftware.b4a.BA.DesignerProperties;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.Hide;
import anywheresoftware.b4a.BA.Property;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.objects.collections.Map;
import anywheresoftware.b4j.objects.CustomViewWrapper.DesignerCustomView;
import anywheresoftware.b4j.objects.LabelWrapper;
import anywheresoftware.b4j.objects.NodeWrapper.ControlWrapper;
import anywheresoftware.b4j.objects.PaneWrapper;
import anywheresoftware.b4j.objects.PaneWrapper.ConcretePaneWrapper;

@Version(1.00f)
@ShortName("ToggleSwitch")
@Author(value = "DonManfred (wrapper)")
//@Permissions(values={"android.permission.INTERNET", "android.permission.ACCESS_NETWORK_STATE"})
@Events(values={"selectedChanged(selected As boolean)"})
@DependsOn(values={"controlsfx-8"})
@DesignerProperties(values={
        @Property(key="Selected", displayName="Checked", fieldType="boolean", defaultValue="false"),
        @Property(key="WrapText", displayName="Wrap Text", fieldType="boolean", defaultValue="false"),
        @Property(key="Text", displayName="Text", fieldType="String", defaultValue="",description="default Text"),
        @Property(key="Style", displayName="Style", fieldType="String", defaultValue="toggle-switch",description="Style")

       
})

public class ToggleSwitchWrapper extends ControlWrapper<ToggleSwitch> implements DesignerCustomView{
   
    @Override
    public void DesignerCreateView(final ConcretePaneWrapper base, LabelWrapper label,
            Map args) {
        base.AddNode(getObject(), 0, 0, base.getWidth(), base.getHeight());
        getObject().setWrapText((Boolean)args.Get("WrapText"));
        getObject().setSelected((Boolean)args.Get("Selected"));
        getObject().setStyle((String)args.Get("Style"));
        new PaneWrapper.ResizeEventManager(base.getObject(), null, new Runnable() {
               
            @Override
            public void run() {
                SetLayoutAnimated(0, 0, 0, base.getWidth(), base.getHeight());
            }
        });
    }
    @Hide
    @Override
    public void _initialize(BA ba, Object arg1, String EventName) {
        innerInitialize(ba, EventName.toLowerCase(BA.cul), false);
    }
    @Override
    @Hide
    public void innerInitialize(final BA ba, final String eventName, boolean keepOldObject) {
        if (!keepOldObject)
            setObject(new ToggleSwitch());
        super.innerInitialize(ba, eventName, true);
        //if (ba.subExists(eventName + "_selectedchanged")) {
            getObject().setOnMouseClicked(new EventHandler<MouseEvent>() {

                @Override
                public void handle(MouseEvent event) {
                    ba.raiseEventFromUI(getObject(), eventName + "_selectedchanged", getObject().isSelected());
                    //event.consume();
                }
            });

        //}

    }
    /**
     * Gets or sets the default label text value.
     */
    public String getText() {
        return getObject().getText();
    }
    public void setText(String s) {
        getObject().setText(s);
    }
   
    public boolean getSelected() {
        return getObject().isSelected();
    }
    public void setSelected(boolean selected) {
        getObject().setSelected(selected);
    }

   
    public Boolean isWrapText() {
        return getObject().isWrapText();
    }
    public void setWrapText(boolean wrap) {
        getObject().setWrapText(wrap);
    }

    public void setLayoutX(double x) {
        getObject().setLayoutX(x);;
    }
    public void setLayoutY(double x) {
        getObject().setLayoutY(x);;
    }
   
    public void setStyleClass(String styleClass) {
        getObject().getStyleClass().setAll("toggle-switch");
    }
}

Any tips or hints on what i am doing wrong are highly appreciated
 

Attachments

  • jToggleSwitchEx.zip
    2 KB · Views: 185
  • jToggleSwitchLIB.zip
    4.6 KB · Views: 196

Daestrum

Expert
Licensed User
Longtime User
I just used the border value in the designer screen and set it to transparent. That got rid of the black border, as it seems to default to #000000 (black).

I also created a toggle switch, but used the easier method of just using 2 images in an imageview. It allows me to have any button look I want.
B4X:
package jOnOffSwitch;

import java.net.URL;

import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.DesignerProperties;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.Hide;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.objects.collections.Map;
import anywheresoftware.b4j.objects.CustomViewWrapper.DesignerCustomView;
import anywheresoftware.b4j.objects.LabelWrapper;
import anywheresoftware.b4j.objects.PaneWrapper;
import anywheresoftware.b4j.objects.PaneWrapper.ConcretePaneWrapper;
import javafx.event.EventHandler;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;

@ShortName("jOnOffSwitch")
@Events(values = { "SwitchChanged (Value As String)" })
@DesignerProperties(values = {})
public class jOnOffSwitch implements DesignerCustomView {

	private ImageView img = new ImageView();
	private Image swOn = null;
	private Image swOff = null;
	private boolean isOn = false;
	private Double Isize = 0.0;
	private String name = "";
	private ConcretePaneWrapper savedBase; 

	@Override
	public void DesignerCreateView(final ConcretePaneWrapper base, LabelWrapper label, Map args) {
		if (Isize == 0)
			this.Isize = base.getWidth();
		this.savedBase = base;
		base.AddNode(this.img, 0, 0, base.getWidth(), base.getHeight());
	    new PaneWrapper.ResizeEventManager(base.getObject(), null, new Runnable() {
	         
	         @Override
	         public void run() {
	            savedBase.setPrefWidth(base.getWidth());
	            savedBase.setPrefHeight(base.getHeight());
	         }
	       });
	}
	public void initialize(BA ba, Object arg1, String EventName) {
		
		savedBase = new ConcretePaneWrapper();
		savedBase.Initialize(ba, EventName);
		_initialize(ba,arg1,EventName);
		DesignerCreateView(savedBase,null,null);
	}
	@Hide
	@Override
	public void _initialize(BA ba, Object arg1, String EventName) {
		URL url = jOnOffSwitch.class.getResource("/on.png");
		this.swOn = new Image(url.toString());
		url = jOnOffSwitch.class.getResource("/off.png");
		this.swOff = new Image(url.toString());
		this.Isize = swOff.getHeight();
		this.name = EventName;
		if (ba.subExists(EventName + "_switchchanged")) {
			this.img.setOnMousePressed(new EventHandler<MouseEvent>() {
				@Override
				public void handle(MouseEvent event) {
					if (isOn) {
						img.setImage(swOff);
						isOn = false;
					} else {
						img.setImage(swOn);
						isOn = true;
					}
					ba.raiseEventFromUI(getObject(), EventName + "_switchchanged", isOn == true ? "On" : "Off");
					event.consume();
				}
			});
		}
		this.img.setImage(swOff);
		this.isOn = false;
	}
	public void base_resize(Double width, Double height){
		System.out.println("Base resize called");
		this.img.setFitWidth(width);
		this.img.setFitHeight(height);
	}
	protected Object getObject() {
		return this.name;
	}
	public ConcretePaneWrapper getPane(){
		return this.savedBase;
	}
}
This works in designer and adding from code to a scene.
 
Last edited:
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
I´ll add properties for the Border
Seems not to work... The ToggleSwitch itself does not have this property.
I guess the border propert does not comes not from the Toggle but from the basepanel or so??

Setting the border manually in designer did the trick.

But how to do in javacode?
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
You could see if ConcretePaneWrapper supports .setStyle if not try super to see if you get the underlying pane property.

You can add to DesignerCreateView
B4X:
 base.setStyle(base.getStyle() + ";-fx-border-color: transparent");
 
Last edited:
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
That's true.
Ok. This fixes my 2nd problem; problem no 1 still remains.

Any hint on how to set a listener (which raises an event in b4j) for the toggleswitch? :rolleyes:

While wrapping a view for b4a i usually needed to set an special kind of listener to get it work.
I did not understand this system in b4j respectively in java fx views...
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Something like:
B4X:
if (ba.subExists(eventName + "_checkedchange")) {
       getObject().selectedProperty().addListener(new ChangeListener<Boolean>() {

         @Override
         public void changed(ObservableValue<? extends Boolean> arg0,
             Boolean arg1, Boolean arg2) {
           ba.raiseEventFromUI(getObject(), eventName + "_checkedchange", arg2.booleanValue());
         }
       });
     }
 
Upvote 0
Top