Instantly share code, notes, and snippets.
Last active
August 29, 2015 14:16
-
Save nodamushi/1bac56d339d62a1631c2 to your computer and use it in GitHub Desktop.
an utility class of ToggleButton
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package nodamushi.jfx.util; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.nio.file.Files; | |
import java.nio.file.Paths; | |
import java.util.List; | |
import javafx.beans.InvalidationListener; | |
import javafx.beans.Observable; | |
import javafx.beans.binding.Bindings; | |
import javafx.beans.property.IntegerProperty; | |
import javafx.beans.property.SimpleIntegerProperty; | |
import javafx.collections.FXCollections; | |
import javafx.collections.ListChangeListener; | |
import javafx.collections.ObservableList; | |
import javafx.geometry.Pos; | |
import javafx.scene.Node; | |
import javafx.scene.control.ContentDisplay; | |
import javafx.scene.control.RadioButton; | |
import javafx.scene.control.Toggle; | |
import javafx.scene.control.ToggleButton; | |
import javafx.scene.control.ToggleGroup; | |
import javafx.scene.image.Image; | |
import javafx.scene.image.ImageView; | |
import javafx.scene.layout.FlowPane; | |
import javafx.scene.layout.HBox; | |
import javafx.scene.layout.TilePane; | |
import javafx.scene.layout.VBox; | |
/** | |
* 複数のToggleButtonを簡単に扱うためのユーティリティ。 | |
* 選択されているToggleは番号(インデックス)で管理される。 | |
* @author nodamushi | |
* | |
*/ | |
public class ToggleButtons{ | |
public ToggleButtons(){ | |
final InvalidationListener bind = new InvalidationListener(){ | |
boolean b = true; | |
@Override | |
public void invalidated(final Observable o){ | |
if(b){ | |
b = false; | |
if( o == selectedProperty){ | |
final int s = getSelected(); | |
if(buttons.size()<=s){ | |
setSelected(-1); | |
}else{ | |
final Toggle t = buttons.get(getSelected()); | |
t.setSelected(true); | |
} | |
}else{ | |
final int i = buttons.indexOf(group.getSelectedToggle()); | |
setSelected(i); | |
} | |
b = true; | |
} | |
} | |
}; | |
group.selectedToggleProperty().addListener(bind); | |
selectedProperty.addListener(bind); | |
buttons.addListener(new ListChangeListener<ToggleButton>(){ | |
@Override | |
public void onChanged(final Change<? extends ToggleButton> c){ | |
while(c.next()){ | |
if(c.wasPermutated()) { | |
continue; | |
} | |
if(c.wasRemoved()){ | |
for(final ToggleButton t:c.getRemoved()){ | |
if(t.getToggleGroup()==group){ | |
t.setToggleGroup(null); | |
} | |
} | |
} | |
if(c.wasAdded()){ | |
final List<String> sC=styleClass; | |
for(final ToggleButton t:c.getAddedSubList()){ | |
t.setToggleGroup(group); | |
final ObservableList<String> sc = t.getStyleClass(); | |
for(final String s:sC){ | |
if(!sc.contains(s)){ | |
sc.add(s); | |
} | |
} | |
}//end for ToggleButton | |
}//end if c.wasAdded | |
}//end while | |
final Toggle s = group.getSelectedToggle(); | |
final int i = buttons.indexOf(s); | |
final int si = getSelected(); | |
if(i!=si){ | |
setSelected(i); | |
} | |
}}); | |
styleClass.addListener(new ListChangeListener<String>(){ | |
@Override | |
public void onChanged(final Change<? extends String> c){ | |
while(c.next()){ | |
if(c.wasPermutated()) { | |
continue; | |
} | |
if(c.wasRemoved()){ | |
final List<? extends String> removed = c.getRemoved(); | |
for(final ToggleButton t:buttons){ | |
t.getStyleClass().removeAll(removed); | |
} | |
} | |
if(c.wasAdded()){ | |
final List<? extends String> added = c.getAddedSubList(); | |
for(final ToggleButton t:buttons){ | |
t.getStyleClass().addAll(added); | |
} | |
} | |
} | |
}}); | |
} | |
/** | |
* 保持しているToggleButtonのリスト | |
* @return | |
*/ | |
public ObservableList<ToggleButton> getToggleButtons(){ | |
return buttons; | |
} | |
/** | |
* ToggleButtonに付加するStleClass名のリスト | |
* @return | |
*/ | |
public ObservableList<String> getStyleClass(){ | |
return styleClass; | |
} | |
/** | |
* ToggleButtonに付加するStleClass名を追加する | |
* @param name | |
*/ | |
public void addStyleClass(final String name){ | |
styleClass.add(name); | |
} | |
/** | |
* ToggleButtonのリストと渡されたlistの内容を束縛する | |
* @param list | |
* @see ToggleButtons#getToggleButtons() | |
* @see Bindings#bindContent(List, ObservableList) | |
*/ | |
public void bindContent(final List<? super ToggleButton> list){ | |
Bindings.bindContent(list, buttons); | |
} | |
/** | |
* RadioButtonを生成する | |
* @param text | |
*/ | |
public void createItem(final String text){ | |
final RadioButton r = new RadioButton(text); | |
buttons.add(r); | |
} | |
/** | |
* graphicに画像を持つRadioButtonを生成する | |
* @param text | |
* @param image | |
*/ | |
public void createItem(final String text,final Image image){ | |
if(image !=null){ | |
createItem(text,new ImageView(image),ContentDisplay.BOTTOM,Pos.TOP_LEFT); | |
}else{ | |
createItem(text); | |
} | |
} | |
/** | |
* graphicに画像を持つRadioButtonを生成する | |
* @param text | |
* @param imageStream 画像データ | |
*/ | |
public void createItem(final String text,final InputStream imageStream){ | |
if(imageStream!=null){ | |
final Image img = new Image(imageStream); | |
createItem(text,img); | |
}else{ | |
createItem(text); | |
} | |
} | |
/** | |
* graphicに画像を持つRadioButtonを生成する | |
* @param text | |
* @param imagePath 画像のパス | |
* @throws IOException imagePathを開けなかった場合 | |
*/ | |
public void createItem(final String text,final String imagePath) throws IOException{ | |
try(InputStream in = Files.newInputStream(Paths.get(imagePath));){ | |
createItem(text, in); | |
} | |
} | |
/** | |
* graphicを指定してRadioButtonを生成する | |
* @param text | |
* @param graphic | |
* @param display | |
* @see RadioButton#setGraphic(Node) | |
* @see RadioButton#setContentDisplay(ContentDisplay) | |
*/ | |
public void createItem(final String text,final Node graphic,final ContentDisplay display){ | |
createItem(text, graphic, display,null); | |
} | |
/** | |
* graphicを指定してRadioButtonを生成する | |
* @param text | |
* @param graphic | |
* @param display | |
* @param alignment | |
* @see RadioButton#setGraphic(Node) | |
* @see RadioButton#setContentDisplay(ContentDisplay) | |
* @see RadioButton#setAlignment(Pos) | |
*/ | |
public void createItem(final String text,final Node graphic,final ContentDisplay display,final Pos alignment){ | |
final RadioButton r = new RadioButton(text); | |
if(graphic!=null){ | |
r.setGraphic(graphic); | |
if(display!=null){ | |
r.setContentDisplay(display); | |
} | |
if(alignment!=null){ | |
r.setAlignment(alignment); | |
} | |
} | |
buttons.add(r); | |
} | |
/** | |
* 子要素をこのインスタンスが持つToggleButtonのリストに束縛したTilePaneを生成します | |
* @param hgap | |
* @param vgap | |
* @return | |
*/ | |
public TilePane asTilePane(final double hgap,final double vgap){ | |
final TilePane p = new TilePane(hgap, vgap); | |
bindContent(p.getChildren()); | |
return p; | |
} | |
/** | |
* 子要素をこのインスタンスが持つToggleButtonのリストに束縛したTilePaneを生成します。 | |
* hgap,vgapは10とします。 | |
* @return | |
*/ | |
public TilePane asTitlePane(){ | |
return asTilePane(10, 10); | |
} | |
/** | |
* 子要素をこのインスタンスが持つToggleButtonのリストに束縛したFlowPaneを生成します | |
* @param hgap | |
* @param vgap | |
* @return | |
*/ | |
public FlowPane asFlowPane(final double hgap,final double vgap){ | |
final FlowPane p = new FlowPane(hgap, vgap); | |
bindContent(p.getChildren()); | |
return p; | |
} | |
/** | |
* 子要素をこのインスタンスが持つToggleButtonのリストに束縛したTilePaneを生成します。 | |
* hgap,vgapは10とします。 | |
* @return | |
*/ | |
public FlowPane asFlowPane(){ | |
return asFlowPane(10,10); | |
} | |
/** | |
* 子要素をこのインスタンスが持つToggleButtonのリストに束縛したVBoxを生成します | |
* @param spacing | |
* @return | |
*/ | |
public VBox asVBox(final double spacing){ | |
final VBox p = new VBox(spacing); | |
bindContent(p.getChildren()); | |
return p; | |
} | |
/** | |
* 子要素をこのインスタンスが持つToggleButtonのリストに束縛したVBoxを生成します。 | |
* spacingは10とします。 | |
* @return | |
*/ | |
public VBox asVBox(){ | |
return asVBox(10); | |
} | |
/** | |
* 子要素をこのインスタンスが持つToggleButtonのリストに束縛したHBoxを生成します | |
* @param spacing | |
* @return | |
*/ | |
public HBox asHBox(final double spacing){ | |
final HBox p = new HBox(spacing); | |
bindContent(p.getChildren()); | |
return p; | |
} | |
/** | |
* 子要素をこのインスタンスが持つToggleButtonのリストに束縛したHBoxを生成します。 | |
* spacingは10とします | |
* @return | |
*/ | |
public HBox asHBox(){ | |
return asHBox(10); | |
} | |
private ToggleGroup group = new ToggleGroup(); | |
private ObservableList<ToggleButton> buttons = FXCollections.observableArrayList(); | |
private ObservableList<String> styleClass = FXCollections.observableArrayList(); | |
/** | |
* 選択されているToggleButtonのインデックス | |
* @return 現在選択されているToggleButtonのインデックス。選択されていないときは-1。 | |
*/ | |
public final IntegerProperty selectedProperty(){ | |
return selectedProperty; | |
} | |
public final int getSelected(){ | |
return selectedProperty.get(); | |
} | |
public final void setSelected(final int value){ | |
selectedProperty.set(value); | |
} | |
private final IntegerProperty selectedProperty= new SimpleIntegerProperty(this, "selected", -1){ | |
@Override | |
public void set(final int newValue){ | |
if(newValue < -1 || buttons.size() <= newValue) { | |
return; | |
} | |
super.set(newValue); | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment