com.google.gwt.sample.showcase.client.content.cell.ContactTreeViewModel.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.sample.showcase.client.content.cell.ContactTreeViewModel.java

Source

/*
 * 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;
    }
}