/* * Ext GWT - Ext for GWT * Copyright(c) 2007-2009, Ext JS, LLC. * licensing@extjs.com * * http://extjs.com/license */ package com.extjs.gxt.ui.client.widget; import java.util.List; import com.extjs.gxt.ui.client.Style.SelectionMode; import com.extjs.gxt.ui.client.binder.DataViewBinder; import com.extjs.gxt.ui.client.core.Template; import com.extjs.gxt.ui.client.core.XDOM; import com.extjs.gxt.ui.client.event.BaseEvent; import com.extjs.gxt.ui.client.event.ComponentEvent; import com.extjs.gxt.ui.client.event.ContainerEvent; import com.extjs.gxt.ui.client.event.DataViewEvent; import com.extjs.gxt.ui.client.store.ListStore; import com.extjs.gxt.ui.client.util.Params; import com.extjs.gxt.ui.client.widget.menu.Menu; import com.extjs.gxt.ui.client.widget.selection.AbstractSelectionModel; import com.extjs.gxt.ui.client.widget.selection.Selectable; import com.google.gwt.dom.client.NodeList; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; /** * A mechanism for displaying data using custom layout templates. DataView uses * an {@link Template} as its internal templating mechanism. * * <p /> * A {@link #itemSelector} MUST be provided for the DataView to determine what * nodes it will be working with. * * <dl> * <dt><b>Events:</b></dt> * * <dd><b>BeforeAdd</b> : DataViewEvent(view, item, index)<br> * <div>Fires before an item is added or inserted. Listeners can cancel the * action by calling {@link BaseEvent#setCancelled(boolean)}.</div> * <ul> * <li>view : this</li> * <li>item : the item being added</li> * <li>index : the index at which the item will be added</li> * </ul> * </dd> * * <dd><b>BeforeRemove</b> : DataViewEvent(view, item)<br> * <div>Fires before an item is removed. Listeners can cancel the action by * calling {@link BaseEvent#setCancelled(boolean)}.</div> * <ul> * <li>view : this</li> * <li>item : the item being removed</li> * </ul> * </dd> * * <dd><b>Add</b> : DataViewEvent(view, item, index)<br> * <div>Fires after an item has been added or inserted.</div> * <ul> * <li>view : this</li> * <li>item : the item that was added</li> * <li>index : the index at which the item will be added</li> * </ul> * </dd> * * <dd><b>Remove</b> : DataViewEvent(view, item)<br> * <div>Fires after an item has been removed.</div> * <ul> * <li>view : this</li> * <li>item : the item that was removed</li> * </ul> * </dd> * * <dd><b>SelectionChange</b> : DataViewEvent(view, selected)<br> * <div>Fires after the selection changes.</div> * <ul> * <li>view : this</li> * <li>selected : the selected items</li> * </ul> * </dd> * * <dd><b>ContextMenu</b> : DataViewEvent(view)<br> * <div>Fires before the view's context menu is shown. Listeners can cancel the * action by calling {@link BaseEvent#setCancelled(boolean)}.</div> * <ul> * <li>view : this</li> * <li>menu : menu</li> * </ul> * </dd> * </dl> * * <dl> * <dt>Inherited Events:</dt> * <dd>ScrollContainer Scroll</dd> * <dd>BoxComponent Move</dd> * <dd>BoxComponent Resize</dd> * <dd>Component Enable</dd> * <dd>Component Disable</dd> * <dd>Component BeforeHide</dd> * <dd>Component Hide</dd> * <dd>Component BeforeShow</dd> * <dd>Component Show</dd> * <dd>Component Attach</dd> * <dd>Component Detach</dd> * <dd>Component BeforeRender</dd> * <dd>Component Render</dd> * <dd>Component BrowserEvent</dd> * <dd>Component BeforeStateRestore</dd> * <dd>Component StateRestore</dd> * <dd>Component BeforeStateSave</dd> * <dd>Component SaveState</dd> * </dl> * * @deprecated see {@link ListView} */ public class DataView extends ScrollContainer<DataViewItem> implements Selectable<DataViewItem> { /** * Data view selection model. */ public class DataViewSelectionModel extends AbstractSelectionModel<DataView, DataViewItem> { public DataViewSelectionModel() { super(); } public DataViewSelectionModel(SelectionMode mode) { super(mode); } } /** * The view's selection model. */ protected DataViewSelectionModel sm; private String itemSelector = ".x-view-item"; private String selectStyle = "x-view-item-sel"; private String overStyle = "x-view-item-over"; private Template template; private String defaultTemplate = "<div class=x-view-item>{text}</div>"; private DataViewBinder<?> binder; private boolean selectOnHover; private String containerTagName = "div"; /** * Creates a new data view. */ public DataView() { baseStyle = "x-view"; setSelectionMode(SelectionMode.SINGLE); } /** * Creates a new data view with the given template. * * @param template the template */ public DataView(Template template) { this(); this.template = template; } @Override public boolean add(DataViewItem component) { return super.add(component); } /** * Returns the view's binder. Only applies when set * {@link #setStore(ListStore)} is used. * * @return the binder */ public DataViewBinder<?> getBinder() { return binder; } /** * Returns the container's tag name. * * @return the container tag name */ public String getContainerTagName() { return containerTagName; } @Override public Menu getContextMenu() { return super.getContextMenu(); } /** * Returns the default template. * * @return the default template */ public String getDefaultTemplate() { return defaultTemplate; } /** * Returns the item selector. * * @return the selector */ public String getItemSelector() { return itemSelector; } /** * Returns the over style. * * @return the over style */ public String getOverStyle() { return overStyle; } public DataViewItem getSelectedItem() { return (DataViewItem) sm.getSelectedItem(); } public List<DataViewItem> getSelectedItems() { return sm.getSelectedItems(); } /** * Returns the view's selection mode. * * @return the selection mode. */ public SelectionMode getSelectionMode() { return sm.getSelectionMode(); } /** * Returns the view's selection model. * * @return the selection model */ public DataViewSelectionModel getSelectionModel() { return sm; } /** * Returns true if select on hover is enabled. * * @return the select on hover state */ public boolean getSelectOnOver() { return selectOnHover; } /** * Returns the select style. * * @return the select style */ public String getSelectStyle() { return selectStyle; } /** * Returns the view's template. * * @return the template */ public Template getTemplate() { return template; } @Override public boolean insert(DataViewItem item, int index) { boolean added = super.insert(item, index); if (added) { if (rendered) { renderItem(item, index); } } return added; } public void onComponentEvent(ComponentEvent ce) { DataViewItem item = findItem(ce.getTarget()); if (item != null) { switch (ce.getEventTypeInt()) { case Event.ONMOUSEOVER: onMouseOver(item); break; case Event.ONMOUSEOUT: onMouseOut(item); break; } item.onComponentEvent(ce); } } public void onSelectChange(DataViewItem item, boolean select) { item.el().setStyleName(selectStyle, select); } @Override public boolean remove(DataViewItem component) { return super.remove(component); } /** * Sets the container's tag name (defaults to 'div', pre-render). * * @param containerTagName */ public void setContainerTagName(String containerTagName) { assertPreRender(); this.containerTagName = containerTagName; } @Override public void setContextMenu(Menu menu) { super.setContextMenu(menu); } /** * Sets the default template. * * @param defaultTemplate the default template */ public void setDefaultTemplate(String defaultTemplate) { this.defaultTemplate = defaultTemplate; } /** * This is a required setting. A simple CSS selector (e.g. div.some-class or * span:first-child) that will be used to determine what nodes this DataView * will be working with (defaults to 'x-view-item'). * * @param itemSelector the item selector */ public void setItemSelector(String itemSelector) { this.itemSelector = itemSelector; } /** * Sets the style name to be applied on mouse over (defaults to * 'x-view-item-over'). * * @param overStyle the over style */ public void setOverStyle(String overStyle) { this.overStyle = overStyle; } public void setSelectedItem(DataViewItem item) { sm.select(item, false); } public void setSelectedItems(List<DataViewItem> items) { sm.select(items, false); } /** * Sets the list's selection mode. * * @param mode the selection mode */ public void setSelectionMode(SelectionMode mode) { setSelectionModel(new DataViewSelectionModel(mode)); } /** * True to select the item when mousing over a element (defaults to false). * * @param selectOnHover true to select on mouse over */ public void setSelectOnOver(boolean selectOnHover) { this.selectOnHover = selectOnHover; } /** * The style to be applied to each selected item (defaults to * 'x-view-item-sel'). * * @param selectStyle the select style */ public void setSelectStyle(String selectStyle) { this.selectStyle = selectStyle; } /** * Convenience method that create a new {@link DataViewBinder} using the given * store. * * @param store the store */ @SuppressWarnings("unchecked") public void setStore(ListStore store) { binder = new DataViewBinder(this, store); binder.init(); } /** * Sets the view's template. * * @param html the HTML fragment */ public void setTemplate(String html) { setTemplate(new Template(html)); } /** * Sets the view's template. * * @param template the template */ public void setTemplate(Template template) { this.template = template; } protected String bulkRenderItem(DataViewItem item) { return template.applyTemplate(new Params(item.getValues())); } @Override protected ComponentEvent createComponentEvent(Event event) { return new DataViewEvent(this, (event == null) ? null : findItem(DOM.eventGetTarget(event))); } @SuppressWarnings("unchecked") @Override protected ContainerEvent createContainerEvent(DataViewItem item) { return new DataViewEvent(this, item); } protected void onMouseOut(DataViewItem item) { item.el().removeStyleName(overStyle); } protected void onMouseOver(DataViewItem item) { if (el() != null) { if (selectOnHover) { setSelectedItem(item); } else { item.el().addStyleName(overStyle); } } } protected void onRender(Element target, int index) { setElement(DOM.createElement(containerTagName), target, index); setStyleAttribute("overflow", "auto"); renderAll(); el().addEventsSunk( Event.ONCLICK | Event.ONDBLCLICK | Event.MOUSEEVENTS | Event.KEYEVENTS); } protected void renderAll() { if (template == null) { template = new Template(defaultTemplate); } StringBuffer sb = new StringBuffer(); for (DataViewItem item : getItems()) { sb.append(bulkRenderItem(item)); } getElement().setInnerHTML(sb.toString()); NodeList<Element> elems = el().select(itemSelector); for (int i = 0; i < elems.getLength(); i++) { DataViewItem item = getItem(i); item.setElement(elems.getItem(i)); } } protected void renderItem(DataViewItem item, int index) { item.setElement(XDOM.create(template.applyTemplate(new Params(item.getValues())))); el().insertChild(item.getElement(), index); } protected void setSelectionModel(DataViewSelectionModel sm) { assert sm != null; if (this.sm != null) { this.sm.bind(null); } this.sm = sm; sm.bind(this); } }