Reputation: 589
I have used CellTree
in which I have used CompositeCell
containing CheckBoxCell
on each parent node as well as child node.
Now I want to select all the child nodes on select of parent node. How can I achieve this?
Following is my code.
public class CellTreeExample implements EntryPoint {
/**
* A list of songs.
*/
private static class Playlist {
private final String name;
private final List<String> songs = new ArrayList<String>();
public Playlist(String name) {
this.name = name;
}
/**
* Add a song to the playlist.
*
* @param name
* the name of the song
*/
public void addSong(String name) {
songs.add(name);
}
public String getName() {
return name;
}
/**
* Return the list of songs in the playlist.
*/
public List<String> getSongs() {
return songs;
}
}
/**
* A composer of classical music.
*/
private static class Composer {
private final String name;
private final List<Playlist> playlists = new ArrayList<Playlist>();
public Composer(String name) {
this.name = name;
}
/**
* Add a playlist to the composer.
*
* @param playlist
* the playlist to add
*/
public Playlist addPlaylist(Playlist playlist) {
playlists.add(playlist);
return playlist;
}
public String getName() {
return name;
}
/**
* Return the rockin' playlist for this composer.
*/
public List<Playlist> getPlaylists() {
return playlists;
}
}
/**
* The model that defines the nodes in the tree.
*/
private static class CustomTreeModel implements TreeViewModel {
private final List<Composer> composers;
/**
* This selection model is shared across all leaf nodes. A selection
* model can also be shared across all nodes in the tree, or each set of
* child nodes can have its own instance. This gives you flexibility to
* determine how nodes are selected.
*/
private MultiSelectionModel<String> selectionModel = new MultiSelectionModel<String>();
private MultiSelectionModel<Playlist> playlistSelectionModel = new MultiSelectionModel<Playlist>();
private MultiSelectionModel<Composer> composerSelectionModel = new MultiSelectionModel<Composer>();
private final Cell<String> contactCell;
static List<HasCell<String, ?>> hasCells = new ArrayList<HasCell<String, ?>>();
private final Cell<Playlist> playlistCell;
static List<HasCell<Playlist, ?>> playlistHasCells = new ArrayList<HasCell<Playlist, ?>>();
private final Cell<Composer> composerCell;
static List<HasCell<Composer, ?>> composerHasCells = new ArrayList<HasCell<Composer, ?>>();
public CustomTreeModel(final MultiSelectionModel<String> selectionModel,final MultiSelectionModel<Playlist> playlistSelectionModel,final MultiSelectionModel<Composer> composerSelectionModel) {
this.selectionModel = selectionModel;
this.playlistSelectionModel = playlistSelectionModel;
this.composerSelectionModel = composerSelectionModel;
// Create a database of information.
composers = new ArrayList<Composer>();
// Add compositions by Beethoven.
{
Composer beethoven = new Composer("Beethoven");
composers.add(beethoven);
Playlist concertos = beethoven.addPlaylist(new Playlist("Concertos"));
concertos.addSong("No. 1 - C");
concertos.addSong("No. 2 - B-Flat Major");
concertos.addSong("No. 3 - C Minor");
concertos.addSong("No. 4 - G Major");
concertos.addSong("No. 5 - E-Flat Major");
Playlist quartets = beethoven.addPlaylist(new Playlist("Quartets"));
quartets.addSong("Six String Quartets");
quartets.addSong("Three String Quartets");
quartets.addSong("Grosse Fugue for String Quartets");
Playlist sonatas = beethoven.addPlaylist(new Playlist("Sonatas"));
sonatas.addSong("Sonata in A Minor");
sonatas.addSong("Sonata in F Major");
Playlist symphonies = beethoven.addPlaylist(new Playlist("Symphonies"));
symphonies.addSong("No. 2 - D Major");
symphonies.addSong("No. 2 - D Major");
symphonies.addSong("No. 3 - E-Flat Major");
symphonies.addSong("No. 4 - B-Flat Major");
symphonies.addSong("No. 5 - C Minor");
symphonies.addSong("No. 6 - F Major");
symphonies.addSong("No. 7 - A Major");
symphonies.addSong("No. 8 - F Major");
symphonies.addSong("No. 9 - D Minor");
}
// Add compositions by Brahms.
{
Composer brahms = new Composer("Brahms");
composers.add(brahms);
Playlist concertos = brahms.addPlaylist(new Playlist("Concertos"));
concertos.addSong("Violin Concerto");
concertos.addSong("Double Concerto - A Minor");
concertos.addSong("Piano Concerto No. 1 - D Minor");
concertos.addSong("Piano Concerto No. 2 - B-Flat Major");
Playlist quartets = brahms.addPlaylist(new Playlist("Quartets"));
quartets.addSong("Piano Quartet No. 1 - G Minor");
quartets.addSong("Piano Quartet No. 2 - A Major");
quartets.addSong("Piano Quartet No. 3 - C Minor");
quartets.addSong("String Quartet No. 3 - B-Flat Minor");
Playlist sonatas = brahms.addPlaylist(new Playlist("Sonatas"));
sonatas.addSong("Two Sonatas for Clarinet - F Minor");
sonatas.addSong("Two Sonatas for Clarinet - E-Flat Major");
Playlist symphonies = brahms.addPlaylist(new Playlist("Symphonies"));
symphonies.addSong("No. 1 - C Minor");
symphonies.addSong("No. 2 - D Minor");
symphonies.addSong("No. 3 - F Major");
symphonies.addSong("No. 4 - E Minor");
}
// Add compositions by Mozart.
{
Composer mozart = new Composer("Mozart");
composers.add(mozart);
Playlist concertos = mozart.addPlaylist(new Playlist("Concertos"));
concertos.addSong("Piano Concerto No. 12");
concertos.addSong("Piano Concerto No. 17");
concertos.addSong("Clarinet Concerto");
concertos.addSong("Violin Concerto No. 5");
concertos.addSong("Violin Concerto No. 4");
}
hasCells.add(new HasCell<String, Boolean>() {
private CheckboxCell cell = new CheckboxCell(true, false){
/* (non-Javadoc)
* @see com.google.gwt.cell.client.CheckboxCell#render(com.google.gwt.cell.client.Cell.Context, java.lang.Boolean, com.google.gwt.safehtml.shared.SafeHtmlBuilder)
*/
@Override
public void render(Context context, Boolean value, SafeHtmlBuilder sb) {
// TODO Auto-generated method stub
super.render(context, value, sb);
}
};
public Cell<Boolean> getCell() {
return cell;
}
public FieldUpdater<String, Boolean> getFieldUpdater() {
return null;
}
public Boolean getValue(String object) {
return selectionModel.isSelected(object);
}
});
contactCell = new CompositeCell<String>(hasCells){
/* @Override
public void render(Context context, String value, SafeHtmlBuilder sb) {
System.out.println("STRING...."+value+" ....");
//sb.appendHtmlConstant("<table><tbody><tr>");
sb.appendHtmlConstant(value);
super.render(context, value, sb);
//sb.appendHtmlConstant(value+"</tr></tbody></table>");
}*/
@Override
protected Element getContainerElement(Element parent) {
// Return the first TR element in the table.
return parent.getFirstChildElement().getFirstChildElement().getFirstChildElement();
}
@Override
protected <X> void render(Context context, String value,
SafeHtmlBuilder sb, HasCell<String, X> hasCell) {
Cell<X> cell = hasCell.getCell();
cell.render(context, hasCell.getValue(value), sb);
sb.appendHtmlConstant(value);
//sb.appendHtmlConstant("</td>");
}
};
playlistHasCells.add(new HasCell<Playlist, Boolean>() {
private CheckboxCell cell = new CheckboxCell(true, false){
/* (non-Javadoc)
* @see com.google.gwt.cell.client.CheckboxCell#render(com.google.gwt.cell.client.Cell.Context, java.lang.Boolean, com.google.gwt.safehtml.shared.SafeHtmlBuilder)
*/
@Override
public void render(Context context, Boolean value, SafeHtmlBuilder sb) {
// TODO Auto-generated method stub
super.render(context, value, sb);
}
};
public Cell<Boolean> getCell() {
return cell;
}
public FieldUpdater<Playlist, Boolean> getFieldUpdater() {
return null;
}
public Boolean getValue(Playlist object) {
return playlistSelectionModel.isSelected(object);
}
});
playlistCell = new CompositeCell<Playlist>(playlistHasCells){
@Override
protected Element getContainerElement(Element parent) {
// Return the first TR element in the table.
return parent.getFirstChildElement().getFirstChildElement().getFirstChildElement();
}
@Override
protected <X> void render(Context context, Playlist value,
SafeHtmlBuilder sb, HasCell<Playlist, X> hasCell) {
Cell<X> cell = hasCell.getCell();
cell.render(context, hasCell.getValue(value), sb);
sb.appendHtmlConstant(value.getName());
//sb.appendHtmlConstant("</td>");
}
};
composerHasCells.add(new HasCell<Composer, Boolean>() {
private CheckboxCell cell = new CheckboxCell(true, false){
/* (non-Javadoc)
* @see com.google.gwt.cell.client.CheckboxCell#render(com.google.gwt.cell.client.Cell.Context, java.lang.Boolean, com.google.gwt.safehtml.shared.SafeHtmlBuilder)
*/
@Override
public void render(Context context, Boolean value, SafeHtmlBuilder sb) {
// TODO Auto-generated method stub
super.render(context, value, sb);
}
};
public Cell<Boolean> getCell() {
return cell;
}
public FieldUpdater<Composer, Boolean> getFieldUpdater() {
return null;
}
public Boolean getValue(Composer object) {
return composerSelectionModel.isSelected(object);
}
});
composerCell = new CompositeCell<Composer>(composerHasCells){
@Override
protected Element getContainerElement(Element parent) {
// Return the first TR element in the table.
return parent.getFirstChildElement().getFirstChildElement().getFirstChildElement();
}
@Override
protected <X> void render(Context context, Composer value,
SafeHtmlBuilder sb, HasCell<Composer, X> hasCell) {
Cell<X> cell = hasCell.getCell();
cell.render(context, hasCell.getValue(value), sb);
sb.appendHtmlConstant(value.getName());
//sb.appendHtmlConstant("</td>");
}
};
}
/**
* Get the {@link NodeInfo} that provides the children of the specified
* value.
*/
public <T> NodeInfo<?> getNodeInfo(T value) {
if (value == null) {
// LEVEL 0.
// We passed null as the root value. Return the composers.
// Create a data provider that contains the list of composers.
ListDataProvider<Composer> dataProvider = new ListDataProvider<CellTreeExample.Composer>(composers);
// Create a cell to display a composer.
Cell<Composer> cell = new AbstractCell<Composer>() {
@Override
public void render(Context context, Composer value, SafeHtmlBuilder sb) {
if (value != null) {
sb.appendEscaped(value.getName());
}
}
};
// Return a node info that pairs the data provider and the cell.
return new DefaultNodeInfo<Composer>(dataProvider, composerCell);
} else if (value instanceof Composer) {
// LEVEL 1.
// We want the children of the composer. Return the playlists.
ListDataProvider<Playlist> dataProvider = new ListDataProvider<Playlist>(((Composer) value)
.getPlaylists());
Cell<Playlist> cell = new AbstractCell<Playlist>() {
@Override
public void render(Context context, Playlist value, SafeHtmlBuilder sb) {
if (value != null) {
sb.appendEscaped(value.getName());
}
}
};
return new DefaultNodeInfo<Playlist>(dataProvider, playlistCell);
} else if (value instanceof Playlist) {
// LEVEL 2 - LEAF.
// We want the children of the playlist. Return the songs.
ListDataProvider<String> dataProvider = new ListDataProvider<String>(((Playlist) value).getSongs());
/*CellList<String> cellList = new CellList<String>(contactCell);
dataProvider.addDataDisplay(cellList);*/
// Use the shared selection model.
return new DefaultNodeInfo<String>(dataProvider, contactCell, selectionModel, null);
}
return null;
}
/**
* Check if the specified value represents a leaf node. Leaf nodes
* cannot be opened.
*/
public boolean isLeaf(Object value) {
// The leaf nodes are the songs, which are Strings.
if (value instanceof String) {
return true;
}
return false;
}
}
public void onModuleLoad() {
final MultiSelectionModel<String> selectionModel =
new MultiSelectionModel<String>();
final MultiSelectionModel<Playlist> playlistSelectionModel =
new MultiSelectionModel<Playlist>();
final MultiSelectionModel<Composer> composerSelectionModel =
new MultiSelectionModel<Composer>();
// Create a model for the tree.
TreeViewModel model = new CustomTreeModel(selectionModel,playlistSelectionModel,composerSelectionModel);
/*
* Create the tree using the model. We use <code>null</code> as the
* default value of the root node. The default value will be passed to
* CustomTreeModel#getNodeInfo();
*/
CellTree tree = new CellTree(model, null);
tree.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
// Open the first playlist by default.
TreeNode rootNode = tree.getRootTreeNode();
TreeNode firstPlaylist = rootNode.setChildOpen(0, true);
firstPlaylist.setChildOpen(0, true);
// Add the tree to the root layout panel.
RootLayoutPanel.get().add(tree);
}
}
My handler code here is:
playlistSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
@Override
public void onSelectionChange(SelectionChangeEvent event) {
Set<Playlist> playlistSet = playlistSelectionModel.getSelectedSet();
Iterator<Playlist> itr = playlistSet.iterator();
while (itr.hasNext()) {
Playlist selectedPlaylist = itr.next();
System.out.println("sel: " + selectedPlaylist.getName());
if (selectedPlaylist != null){
for (String song : selectedPlaylist.getSongs()) {
selectionModel.setSelected(song, true);
}
}
}
}
});
composerSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
@Override
public void onSelectionChange(SelectionChangeEvent event) {
Set<Composer> composerSet = composerSelectionModel.getSelectedSet();
Iterator<Composer> itr = composerSet.iterator();
while (itr.hasNext()) {
Composer selectedComposer = itr.next();
if (selectedComposer != null) {
for (Playlist playlist : selectedComposer.getPlaylists()) {
playlistSelectionModel.setSelected(playlist, true);
}
}
}
}
});
}
Upvotes: 2
Views: 2350
Reputation: 17489
You need two SelectionModel
s.
Add a SelectionChangeHandler
to the SelectionModel
of your parent nodes and in the Handler retrieve all child objects for the parent object and call MultiSelectionModel.setSelected(Obj,true) on them.
Something like this for Playlist and Songs:
Update: based on comments:
playListSelectionModel.addSelectionChangerHandler(new SelectionChangeEvent.Handler(SelectionChangeEvent event) {
ArrayList<PlayList> playLists; // all playlists
for (PlayList playlist:playlists) {
boolean isSelected = playlistSelectionModel.isSelected(playlist);
for (String song : selectedPlaylist.getSongs()) {
selectionModel.setSelected(song, isSelected);
}
}
}};
This works when playListSelectionModel is a SingleSelectionModel
. In case it is a MultiSelectionModel
you need two loops.
Upvotes: 2