| /* |
| * Copyright 2010 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.gwt.sample.showcase.client.content.cell; |
| |
| import com.google.gwt.cell.client.AbstractCell; |
| import com.google.gwt.cell.client.Cell; |
| import com.google.gwt.cell.client.CheckboxCell; |
| import com.google.gwt.cell.client.CompositeCell; |
| import com.google.gwt.cell.client.FieldUpdater; |
| import com.google.gwt.cell.client.HasCell; |
| import com.google.gwt.core.client.GWT; |
| import com.google.gwt.dom.client.Element; |
| import com.google.gwt.resources.client.ClientBundle; |
| import com.google.gwt.resources.client.ImageResource; |
| import com.google.gwt.safehtml.shared.SafeHtmlBuilder; |
| import com.google.gwt.sample.showcase.client.content.cell.ContactDatabase.Category; |
| import com.google.gwt.sample.showcase.client.content.cell.ContactDatabase.ContactInfo; |
| import com.google.gwt.sample.showcase.client.content.cell.CwCellList.ContactCell; |
| import com.google.gwt.user.client.ui.AbstractImagePrototype; |
| import com.google.gwt.view.client.DefaultSelectionEventManager; |
| import com.google.gwt.view.client.ListDataProvider; |
| import com.google.gwt.view.client.SelectionModel; |
| import com.google.gwt.view.client.TreeViewModel; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.TreeMap; |
| |
| /** |
| * The {@link TreeViewModel} used to organize contacts into a hierarchy. |
| */ |
| public class ContactTreeViewModel implements TreeViewModel { |
| |
| /** |
| * The images used for this example. |
| */ |
| static interface Images extends ClientBundle { |
| ImageResource contact(); |
| |
| ImageResource contactsGroup(); |
| } |
| |
| /** |
| * The cell used to render categories. |
| */ |
| private static class CategoryCell extends AbstractCell<Category> { |
| |
| /** |
| * The html of the image used for contacts. |
| */ |
| private final String imageHtml; |
| |
| public CategoryCell(ImageResource image) { |
| this.imageHtml = AbstractImagePrototype.create(image).getHTML(); |
| } |
| |
| @Override |
| public void render(Context context, Category value, SafeHtmlBuilder sb) { |
| if (value != null) { |
| sb.appendHtmlConstant(imageHtml).appendEscaped(" "); |
| sb.appendEscaped(value.getDisplayName()); |
| } |
| } |
| } |
| |
| /** |
| * Tracks the number of contacts in a category that begin with the same |
| * letter. |
| */ |
| private static class LetterCount implements Comparable<LetterCount> { |
| private final Category category; |
| private final char firstLetter; |
| private int count; |
| |
| /** |
| * Construct a new {@link LetterCount} for one contact. |
| * |
| * @param category the category |
| * @param firstLetter the first letter of the contacts name |
| */ |
| public LetterCount(Category category, char firstLetter) { |
| this.category = category; |
| this.firstLetter = firstLetter; |
| this.count = 1; |
| } |
| |
| public int compareTo(LetterCount o) { |
| return (o == null) ? -1 : (firstLetter - o.firstLetter); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| return compareTo((LetterCount) o) == 0; |
| } |
| |
| @Override |
| public int hashCode() { |
| return firstLetter; |
| } |
| |
| /** |
| * Increment the count. |
| */ |
| public void increment() { |
| count++; |
| } |
| } |
| |
| /** |
| * A Cell used to render the LetterCount. |
| */ |
| private static class LetterCountCell extends AbstractCell<LetterCount> { |
| |
| @Override |
| public void render(Context context, LetterCount value, SafeHtmlBuilder sb) { |
| if (value != null) { |
| sb.appendEscaped(value.firstLetter + " (" + value.count + ")"); |
| } |
| } |
| } |
| |
| /** |
| * The static images used in this model. |
| */ |
| private static Images images; |
| |
| private final ListDataProvider<Category> categoryDataProvider; |
| private final Cell<ContactInfo> contactCell; |
| private final DefaultSelectionEventManager<ContactInfo> selectionManager = |
| DefaultSelectionEventManager.createCheckboxManager(); |
| private final SelectionModel<ContactInfo> selectionModel; |
| |
| public ContactTreeViewModel(final SelectionModel<ContactInfo> selectionModel) { |
| this.selectionModel = selectionModel; |
| if (images == null) { |
| images = GWT.create(Images.class); |
| } |
| |
| // Create a data provider that provides categories. |
| categoryDataProvider = new ListDataProvider<Category>(); |
| List<Category> categoryList = categoryDataProvider.getList(); |
| for (Category category : ContactDatabase.get().queryCategories()) { |
| categoryList.add(category); |
| } |
| |
| // Construct a composite cell for contacts that includes a checkbox. |
| List<HasCell<ContactInfo, ?>> hasCells = new ArrayList<HasCell<ContactInfo, ?>>(); |
| hasCells.add(new HasCell<ContactInfo, Boolean>() { |
| |
| private CheckboxCell cell = new CheckboxCell(true, false); |
| |
| public Cell<Boolean> getCell() { |
| return cell; |
| } |
| |
| public FieldUpdater<ContactInfo, Boolean> getFieldUpdater() { |
| return null; |
| } |
| |
| public Boolean getValue(ContactInfo object) { |
| return selectionModel.isSelected(object); |
| } |
| }); |
| hasCells.add(new HasCell<ContactInfo, ContactInfo>() { |
| |
| private ContactCell cell = new ContactCell(images.contact()); |
| |
| public Cell<ContactInfo> getCell() { |
| return cell; |
| } |
| |
| public FieldUpdater<ContactInfo, ContactInfo> getFieldUpdater() { |
| return null; |
| } |
| |
| public ContactInfo getValue(ContactInfo object) { |
| return object; |
| } |
| }); |
| contactCell = new CompositeCell<ContactInfo>(hasCells) { |
| @Override |
| public void render(Context context, ContactInfo value, SafeHtmlBuilder sb) { |
| sb.appendHtmlConstant("<table><tbody><tr>"); |
| super.render(context, value, sb); |
| sb.appendHtmlConstant("</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, ContactInfo value, |
| SafeHtmlBuilder sb, HasCell<ContactInfo, X> hasCell) { |
| Cell<X> cell = hasCell.getCell(); |
| sb.appendHtmlConstant("<td>"); |
| cell.render(context, hasCell.getValue(value), sb); |
| sb.appendHtmlConstant("</td>"); |
| } |
| }; |
| } |
| |
| public <T> NodeInfo<?> getNodeInfo(T value) { |
| if (value == null) { |
| // Return top level categories. |
| return new DefaultNodeInfo<Category>(categoryDataProvider, |
| new CategoryCell(images.contactsGroup())); |
| } else if (value instanceof Category) { |
| // Return the first letters of each first name. |
| Category category = (Category) value; |
| List<ContactInfo> contacts = ContactDatabase.get().queryContactsByCategory( |
| category); |
| Map<Character, LetterCount> counts = new TreeMap<Character, LetterCount>(); |
| for (ContactInfo contact : contacts) { |
| Character first = contact.getFirstName().charAt(0); |
| LetterCount count = counts.get(first); |
| if (count == null) { |
| count = new LetterCount(category, first); |
| counts.put(first, count); |
| } else { |
| count.increment(); |
| } |
| } |
| List<LetterCount> orderedCounts = new ArrayList<LetterCount>( |
| counts.values()); |
| return new DefaultNodeInfo<LetterCount>( |
| new ListDataProvider<LetterCount>(orderedCounts), |
| new LetterCountCell()); |
| } else if (value instanceof LetterCount) { |
| // Return the contacts with the specified character and first name. |
| LetterCount count = (LetterCount) value; |
| List<ContactInfo> contacts = ContactDatabase.get().queryContactsByCategoryAndFirstName( |
| count.category, count.firstLetter + ""); |
| ListDataProvider<ContactInfo> dataProvider = new ListDataProvider<ContactInfo>( |
| contacts, ContactInfo.KEY_PROVIDER); |
| return new DefaultNodeInfo<ContactInfo>( |
| dataProvider, contactCell, selectionModel, selectionManager, null); |
| } |
| |
| // Unhandled type. |
| String type = value.getClass().getName(); |
| throw new IllegalArgumentException("Unsupported object type: " + type); |
| } |
| |
| public boolean isLeaf(Object value) { |
| return value instanceof ContactInfo; |
| } |
| } |