Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gwt widget - mutually-exclusive toggle button

I want a hybrid of a ToggleButton and RadioButton. I want the "mutually-exclusive" part of RadioButton, and the gui look and behavior of ToggleButton(up and down states). Does one already exist?

like image 258
antony.trupe Avatar asked Aug 29 '09 23:08

antony.trupe


2 Answers

I've adapted kirushik's solution and created a simple "ToggleButtonPanel" widget that takes an arbitrary number of ToggleButtons (and possibly any other widgets you'd like to add) and a panel of your choosing (defaults to VerticalPanel) and makes the buttons mutually exclusive.

What's nice about this is that the panel itself fires ClickEvents when the buttons are clicked. This way, you can add a single ClickHandler to the ToggleGroupPanel and then determine which button was clicked using event.getSource()

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.ToggleButton;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class ToggleButtonPanel extends Composite implements HasWidgets, HasClickHandlers{

    public ToggleButtonPanel() {
        this(new VerticalPanel());
    }

    public ToggleButtonPanel(Panel panel){
        this.panel = panel;
        initWidget(panel);
    }

    @Override
    public void add(Widget w) {
        if(w instanceof ToggleButton){
            ToggleButton button = (ToggleButton) w;
            button.addClickHandler(handler);
        }
        panel.add(w);
    }

    @Override
    public void clear() {
        panel.clear();
    }

    @Override
    public Iterator<Widget> iterator() {
        return panel.iterator();
    }

    @Override
    public boolean remove(Widget w) {
        return panel.remove(w);
    }

    @Override
    public void setWidth(String width) {
        panel.setWidth(width);
    };

    @Override
    public void setHeight(String height) {
        panel.setHeight(height);
    }

    private final Panel panel;
    private ClickHandler handler = new ClickHandler(){
        @Override
        public void onClick(ClickEvent event) {
            Iterator<Widget> itr = panel.iterator();
            while(itr.hasNext()){
                Widget w = itr.next();
                if(w instanceof ToggleButton){
                    ToggleButton button = (ToggleButton) w;
                    button.setDown(false);
                    if(event.getSource().equals(button)) {
                        button.setDown(true);
                    }
                }
            }

            for(ClickHandler h : handlers){
                h.onClick(event);
            }
        }
    };

    private List<ClickHandler> handlers = new ArrayList<ClickHandler>();
    @Override
    public HandlerRegistration addClickHandler(final ClickHandler handler) {
        handlers.add(handler);
        return new HandlerRegistration() {

            @Override
            public void removeHandler() {
                handlers.remove(handler);
            }
        };
    }

}
like image 192
David Avatar answered Oct 12 '22 09:10

David


Here is my pure-gwt variant:

class ThreeStateMachine extends FlowPanel{
        // This is the main part - it will unset all the buttons in parent widget
        // and then set only clicked one.
        // One mutual handler works faster and is generally better for code reuse
        private final ClickHandler toggleToThis = new ClickHandler() {
                @Override
                public void onClick(ClickEvent clickEvent) {
                    for(Widget b: ThreeStateMachine.this.getChildren()){
                        ((ToggleButton)b).setDown(false);
                    }
                    ((ToggleButton)clickEvent.getSource()).setDown(true);
                }
            };

        private ThreeStateMachine() { // Create out widget and populat it with buttons
            super();

            ToggleButton b = new ToggleButton("one");
            b.setDown(true);
            b.addClickHandler(toggleToThis);
            this.add(b);

            b = new ToggleButton("two");
            b.addClickHandler(toggleToThis);
            this.add(b);

            b = new ToggleButton("three");
            b.addClickHandler(toggleToThis);
            this.add(b);
        }
    }

Surely, one'll need css styles for gwt-ToggleButton with variants (-up-hovering etc.)

like image 32
kirushik Avatar answered Oct 12 '22 10:10

kirushik