0x52
0x52

Reputation: 115

Switch add-on with push, vaadin

I have a simple example of the add-on switch with vaadin, what I want is to keep the state of the switch even when I update the UI, that is, I support multiple tabs, but I can not do it, this push example is very similar to What I want to do but with a textField.

https://github.com/vaadin-marcus/push-example/blob/master/src/main/java/com/vaadin/training/ScrumBoardLayout.java

https://github.com/rucko24/MVP/blob/testingSwitchPushTemu/src/main/java/com/Core/vaadin/pushServer/ejemploPushMarkus/ScrumBoard.java

To my example I add a bulb so that when another accesses the application can see the current state of the bulb. My example in github is this with only 3 classes

https://github.com/rucko24/MVP/tree/testingSwitchPushTemu/src/main/java/com/Core/vaadin/pushServer/ejemploPushMarkus

bombilla

This is the swithc listener that changes my bulb, but when I get the boolean value (true, or false), I still do not understand the right way to push the other switch

switchTemu.addValueChangeListener(new Property.ValueChangeListener() {
        private static final long serialVersionUID = 1L;

@Override
public void valueChange(Property.ValueChangeEvent event) {
        boolean estado = (boolean) event.getProperty().getValue();
        ScrumBoard.addSwitch(estado);
        switchTemu.removeValueChangeListener(this);
        if(estado == Boolean.TRUE) {
                bombilla.setIcon(bombillaON);

        }else {
                bombilla.setIcon(bombillaOFF);

        }
        switchTemu.addValueChangeListener(this);

        }
});

Update

In my example github achievement, change the state of all switches to all UI, but I still do not know how to get the state of the switches

Upvotes: 0

Views: 236

Answers (2)

0x52
0x52

Reputation: 115

I could see that with the ThemeResource () class, changing the bulb to its ON / OFF effect is strange, but I solve it as follows

.bombillo-on {
    @include valo-animate-in-fade($duration: 1s);
    width: 181px;
    height: 216px;
    background: url(img/on.png) no-repeat;
}
.bombillo-off {
    @include valo-animate-in-fade($duration: 1s);
    width: 181px;
 height: 216px;
    background: url(img/off.png) no-repeat;
}

public enum Sstate {

ON(true,"bombillo-on"),
OFF(false,"bombillo-off");

private boolean value;
private String style;

Sstate(boolean value, String style) {
    this.value = value;
    this.style = style;
}

public boolean getValue() { return value;}
public String getStyle() { return style;}
public static Sstate from(boolean value) { return value ? ON:OFF;}
}

And the handleChangeEvent It stays like this

 @Override
 public void handleChangeEvent(Sstate state) {
    ui.access(() -> {
        bombilla.setStyleName(state.getStyle());
        s.setValue(state.getValue());
        System.out.println(state+" values "+s);
    });
 }

UPDATE:

I notice an issue, that when I add a new view, or change using the buttonMenuToggle, it loses the synchronization, and update the bulb quite strange, clear with the themeResource does not happen that.

Solution:

to avoid UiDetachedException when using the Navigator try this, It works very well

@Override
 public void handleChangeEvent(Sstate state) {
    if(!ui.isAttached()) {
       BroadcastesSwitch.removeListener(this);
       return;
    }
    ui.access(() -> {
        bombilla.setStyleName(state.getStyle());
        s.setValue(state.getValue());
        System.out.println(state+" values "+s);
    });
 }

Upvotes: 0

Morfic
Morfic

Reputation: 15518

I made a couple of changes to your sources (still basic, but it gets you started):

  • only 1 common shared state
  • switch value change listeners now just trigger a state changed event
  • state changed listeners now update the UI elements when triggered
  • upon registration, a state changed listeners is informed (triggered) about the current state

The main idea is to have just a single shared state and any change is communicated to all the listeners (including the one where the change originated).

Below you can find the code: (P.S. I did not recompile my widgetset so the nice switch icon falls back to the default check box style)

1) SwitchState - represents the state of the switch shared between all the app instances

public enum SwitchState {
    ON(true, new ThemeResource("img/on.png")), OFF(false, new ThemeResource("img/off.png"));

    private final boolean value;
    private final ThemeResource icon;

    SwitchState(boolean value, ThemeResource icon) {
        this.value = value;
        this.icon = icon;
    }

    public boolean getValue() {
        return value;
    }

    public ThemeResource getIcon() {
        return icon;
    }

    public static SwitchState from(boolean value) {
        return value ? ON : OFF;
    }
}

2) ScrumBoard common state and listeners manager

public class ScrumBoard {

    // list of listeners    
    private static List<SwitchChangeListener> LISTENERS = new ArrayList<>();
    // initial state
    private static SwitchState STATE = SwitchState.OFF;

    // state change listener contract
    public interface SwitchChangeListener {
        void handleStateChange(SwitchState state);
    }

    // handle a a state change request
    public static synchronized void updateState(boolean value) {
        STATE = SwitchState.from(value);
        fireChangeEvent(STATE);
    }

    // register a new state listener
    public static synchronized void addSwitchChangeListener(SwitchChangeListener listener) {
        System.out.println("Added listener for " + listener);
        LISTENERS.add(listener);
        // when a new listener is registered, also inform it of the current state
        listener.handleStateChange(STATE);
    }

    // remove a state listener
    public static synchronized void removeSwitchListener(SwitchChangeListener listener) {
        LISTENERS.remove(listener);
    }

    // fire a change event to all registered listeners
    private static void fireChangeEvent(SwitchState state) {
        for (SwitchChangeListener listener : LISTENERS) {
            listener.handleStateChange(state);
        }
    }
}

3) ScrumBoardLayout - UI layout and components

public class ScrumBoardLayout extends VerticalLayout implements ScrumBoard.SwitchChangeListener {

    private Label icon = new Label();
    private Switch mySwitch = new Switch();

    public ScrumBoardLayout() {
        setMargin(true);
        setSpacing(true);
        addHeader();

        // listen for state changes
        ScrumBoard.addSwitchChangeListener(this);
    }

    private void addHeader() {
        mySwitch.setImmediate(true);
        icon.setSizeUndefined();

        // notify of state change
        mySwitch.addValueChangeListener((Property.ValueChangeListener) event -> ScrumBoard.updateState((Boolean) event.getProperty().getValue()));

        VerticalLayout layout = new VerticalLayout();
        layout.setHeight("78%");
        layout.addComponents(icon, mySwitch);

        layout.setComponentAlignment(icon, Alignment.BOTTOM_CENTER);
        layout.setComponentAlignment(mySwitch, Alignment.BOTTOM_CENTER);
        layout.setExpandRatio(mySwitch, 1);
        addComponents(layout);
    }

    @Override
    public void handleStateChange(SwitchState state) {
        // update UI on state change
        UI.getCurrent().access(() -> {
            mySwitch.setValue(state.getValue());
            icon.setIcon(state.getIcon());
            Notification.show(state.name(), Type.ASSISTIVE_NOTIFICATION);
        });
    }

    @Override
    public void detach() {
        super.detach();
        ScrumBoard.removeSwitchListener(this);
    }
}

4) Result Light bulbs

Upvotes: 1

Related Questions