/*
* Copyright 2010 Daniel Kurka
*
* 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.googlecode.mgwt.ui.client.widget.list.widgetlist;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.ComplexPanel;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
import com.googlecode.mgwt.dom.client.event.tap.HasTapHandlers;
import com.googlecode.mgwt.dom.client.event.tap.TapEvent;
import com.googlecode.mgwt.dom.client.event.tap.TapHandler;
import com.googlecode.mgwt.dom.client.recognizer.TapRecognizer;
import com.googlecode.mgwt.ui.client.widget.list.celllist.CellList;
import com.googlecode.mgwt.ui.client.widget.touch.TouchWidgetImpl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* A list that can contain widgets
*
* This class renders widgets into a list. The same thing is done by {@link CellList} much more
* efficient.
*
* <b>Note:</b> Normally you should be using {@link CellList}. Only if you really need Widgets
* inside the list (which won't be the case most of the time) you should be using WidgetList.
*
* The reference for styling can be found in CellList as well.
*
*
* @author Daniel Kurka
*/
public class WidgetList extends Composite implements HasWidgets, HasSelectionHandlers<Integer> {
public static class WidgetListEntry extends Composite implements AcceptsOneWidget, HasTapHandlers {
private static final TouchWidgetImpl IMPL = GWT.create(TouchWidgetImpl.class);
@UiField
public Panel container;
// UiBinder needs this field
private WidgetListAppearance appearance;
public WidgetListEntry(WidgetListAppearance appearance) {
this.appearance = appearance;
initWidget(this.appearance.uiBinderEntry().createAndBindUi(this));
IMPL.addTouchHandler(container, new TapRecognizer(this));
}
@Override
public void setWidget(IsWidget w) {
container.add(w);
}
@Override
public HandlerRegistration addTapHandler(TapHandler handler) {
return addHandler(handler, TapEvent.getType());
}
}
private static class Entry {
WidgetListEntry entry;
HandlerRegistration handlerRegistration;
public Entry(WidgetListEntry entry, HandlerRegistration handlerRegistration) {
this.entry = entry;
this.handlerRegistration = handlerRegistration;
}
}
private static final WidgetListAppearance DEFAULT_APPEARANCE = GWT.create(WidgetListAppearance.class);
private int childCount;
private List<WidgetListEntry> children = new ArrayList<WidgetListEntry>();
@UiField
public ComplexPanel container;
@UiField
public Panel headerContainer;
private Map<Widget, Entry> map;
private WidgetListAppearance appearance;
private Widget header;
public WidgetList() {
this(DEFAULT_APPEARANCE);
}
public WidgetList(WidgetListAppearance appearance) {
this.appearance = appearance;
initWidget(this.appearance.uiBinder().createAndBindUi(this));
map = new HashMap<Widget, Entry>();
}
@Override
public HandlerRegistration addSelectionHandler(SelectionHandler<Integer> handler) {
return addHandler(handler, SelectionEvent.getType());
}
@Override
public void add(Widget w) {
final WidgetListEntry widgetListEntry = new WidgetListEntry(this.appearance);
widgetListEntry.setWidget(w);
HandlerRegistration handlerRegistration = widgetListEntry.addTapHandler(new TapHandler() {
@Override
public void onTap(TapEvent event) {
SelectionEvent.fire(WidgetList.this, container.getWidgetIndex(widgetListEntry));
}
});
if (childCount == 0) {
widgetListEntry.addStyleName(this.appearance.css().widgetListEntryFirstChild());
}
map.put(w, new Entry(widgetListEntry, handlerRegistration));
container.add(widgetListEntry);
children.add(widgetListEntry);
if (childCount > 0) {
children.get(childCount - 1).removeStyleName(this.appearance.css().widgetListEntryLastChild());
}
widgetListEntry.addStyleName(this.appearance.css().widgetListEntryLastChild());
childCount++;
}
@Override
public void clear() {
container.clear();
for (Entry entry : map.values()) {
entry.handlerRegistration.removeHandler();
}
map.clear();
children.clear();
childCount = 0;
if(header!= null) {
add(header);
}
}
@Override
public Iterator<Widget> iterator() {
return map.keySet().iterator();
}
@Override
public boolean remove(Widget w) {
Entry entry = map.remove(w);
if (entry == null)
return false;
// did we remove the last child?
if (children.get(childCount - 1) == entry.entry) {
// are there others in the list?
if (childCount - 2 >= 0) {
children.get(childCount - 2).addStyleName(this.appearance.css().widgetListEntryLastChild());
}
}
// did we remove the first child
if (children.get(0) == entry.entry) {
if (children.size() > 1) {
children.get(1).addStyleName(this.appearance.css().widgetListEntryFirstChild());
}
}
childCount--;
children.remove(entry);
entry.handlerRegistration.removeHandler();
return container.remove(entry.entry);
}
/**
* Should the list be displayed with rounded corners
*
* @param round true to display with rounded corners
*/
public void setRound(boolean round) {
if (round) {
addStyleName(this.appearance.css().round());
} else {
removeStyleName(this.appearance.css().round());
}
}
public int getWidgetCount() {
return childCount;
}
public void setSelectAble(int index, boolean group) {
if (group) {
children.get(index).addStyleName(this.appearance.css().widgetListEntrySelectedable());
} else {
children.get(index).removeStyleName(this.appearance.css().widgetListEntrySelectedable());
}
}
public void setHeader(Widget header) {
headerContainer.setVisible(header != null);
headerContainer.clear();
if (header != null) {
headerContainer.add(header);
}
}
@UiFactory
public WidgetListAppearance getAppearance() {
return appearance;
}
}