之前,我们已经通过RssMainPanel里的 ItemGrid来显示一个feed数据。现在,我们将要使用TabPanel去管理多个TabItem——其中每一个TabItem包含一个 ItemGrid,一个ItemGrid负责显示一个feed数据的多个Items内容。
private final TabPanel tabPanel = new TabPanel();
public void addTab(TabItem tabItem) { tabItem.setLayout(new FitLayout()); tabItem.setIcon(Resources.ICONS.rss()); tabItem.setScrollMode(Scroll.AUTO); }
public void addTab(TabItem tabItem) { tabItem.setLayout(new FitLayout()); tabItem.setIcon(Resources.ICONS.rss()); tabItem.setScrollMode(Scroll.AUTO); String tabId = tabItem.getId(); TabItem existingTab = tabPanel.findItem(tabId, false); if (existingTab == null) { tabPanel.add(tabItem); tabPanel.setSelection(tabItem); } else { tabPanel.setSelection(existingTab); } }
public FeedPanel() { setHeading("Main"); setLayout(new FitLayout()); add(tabPanel); }
我们可以根据用户的选择事件操作,将其选择的ModelDate在不同的components之间传递。同样的,也可以通过数据的加载事件,将ModelData在不同的components之间传递。
大致思路如下:
Implements:
public static final EventType FeedSelected = new EventType(); public static final EventType ItemSelected = new EventType(); public static final EventType TabSelected = new EventType();
package com.danielvaughan.rssreader.client.lists; import java.util.List; import com.danielvaughan.rssreader.client.RSSReaderConstants; import com.danielvaughan.rssreader.client.mvc.events.AppEvents; import com.danielvaughan.rssreader.client.services.FeedServiceAsync; import com.danielvaughan.rssreader.shared.model.Feed; import com.extjs.gxt.ui.client.Registry; import com.extjs.gxt.ui.client.data.BaseListLoader; import com.extjs.gxt.ui.client.data.BeanModel; import com.extjs.gxt.ui.client.data.BeanModelReader; import com.extjs.gxt.ui.client.data.ListLoadResult; import com.extjs.gxt.ui.client.data.ListLoader; import com.extjs.gxt.ui.client.data.LoadEvent; import com.extjs.gxt.ui.client.data.RpcProxy; import com.extjs.gxt.ui.client.event.LoadListener; import com.extjs.gxt.ui.client.event.SelectionChangedEvent; import com.extjs.gxt.ui.client.event.SelectionChangedListener; import com.extjs.gxt.ui.client.mvc.Dispatcher; import com.extjs.gxt.ui.client.store.ListStore; import com.extjs.gxt.ui.client.widget.LayoutContainer; import com.extjs.gxt.ui.client.widget.form.ListField; import com.extjs.gxt.ui.client.widget.layout.FitLayout; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.rpc.AsyncCallback; public class FeedList extends LayoutContainer { final ListField<BeanModel> feedList = new ListField<BeanModel>(); public FeedList() { setLayout(new FitLayout()); } private String getTemplate() { StringBuilder sb = new StringBuilder(); sb.append("<tpl for=\".\">"); sb.append("<div class='x-combo-list-item'><b>{title}</b> -{description}</div>"); sb.append("</tpl>"); return sb.toString(); } @Override protected void onRender(Element parent, int index) { super.onRender(parent, index); // 0:从Registry里获得Service final FeedServiceAsync feedService = (FeedServiceAsync) Registry .get(RSSReaderConstants.FEED_SERVICE); // 1:定义proxy在load方法里掉用Serivce里的方法 RpcProxy<List<Feed>> proxy = new RpcProxy<List<Feed>>() { @Override protected void load(Object loadConfig, AsyncCallback<List<Feed>> callback) { feedService.loadFeedList(false, callback); } }; // 2:定义Reader BeanModelReader reader = new BeanModelReader(); // 3:将proxy和reader传入,定义loader ListLoader<ListLoadResult<BeanModel>> loader = new BaseListLoader<ListLoadResult<BeanModel>>( proxy, reader); // 4:传入loader,生成store,此时还没有load数据 final ListStore<BeanModel> feedStore = new ListStore<BeanModel>(loader); // 5:将stroe绑定到data-backed component身上 feedList.setStore(feedStore); feedList.setTemplate(getTemplate()); feedList.addSelectionChangedListener(new SelectionChangedListener<BeanModel>() { @Override public void selectionChanged(SelectionChangedEvent<BeanModel> se) { Feed feed = se.getSelectedItem().getBean(); if (feed != null) { Dispatcher.forwardEvent(AppEvents.FeedSelected, feed);//关键在这里~~~ } } }); // 6:真正的load数据,load成功之后,data-backed component会自动的显示出来。 loader.load(); add(feedList); } }
public FeedController() { registerEventTypes(AppEvents.Init); registerEventTypes(AppEvents.FeedSelected); }
private final Feed feed; public ItemGrid(Feed feed) { setLayout(new FitLayout()); this.feed = feed; }
private Grid<ModelData> grid; @Override protected void onRender(Element parent, int index) { … grid = new Grid<ModelData>(itemStore, columnModel); }
final String TEST_DATA_FILE = "http://localhost:8888/rss2sample.xml";
RpcProxy<List<Item>> proxy = new RpcProxy<List<Item>>() { @Override protected void load(Object loadConfig, AsyncCallback<List<Item>> callback) { feedService.loadItems(feed.getUuid(), callback); } };
public void resetSelection() { grid.getSelectionModel().deselectAll(); }
private void onFeedSelected(AppEvent event) { Feed feed = event.getData(); final ItemGrid itemGrid = new ItemGrid(feed); TabItem tabItem = new TabItem(feed.getTitle()); tabItem.setId(feed.getUuid()); tabItem.setData("feed", feed); tabItem.add(itemGrid); tabItem.addListener(Events.Select, new Listener<TabPanelEvent>() {//选中之后的tab会清空item selection @Override public void handleEvent(TabPanelEvent be) { itemGrid.resetSelection(); } }); tabItem.setClosable(true); feedPanel.addTab(tabItem); }
@Override protected void handleEvent(AppEvent event) { EventType eventType = event.getType(); if (eventType.equals(AppEvents.Init)) { onInit(event); }else if (eventType.equals(AppEvents.FeedSelected)) { onFeedSelected(event); } }
grid.getSelectionModel().addListener(Events.SelectionChange, new Listener<SelectionChangedEvent<Item>>() { @Override public void handleEvent(SelectionChangedEvent<Item> be) { Item item = be.getSelectedItem(); if(item!=null) Dispatcher.forwardEvent(AppEvents.ItemSelected, item); } });
public ItemController() { registerEventTypes(AppEvents.Init); registerEventTypes(AppEvents.ItemSelected); }
private void onItemSelected(AppEvent event) { Item item = (Item) event.getData(); itemPanel.displayItem(item); }
@Override protected void handleEvent(AppEvent event) { EventType eventType = event.getType(); if (eventType.equals(AppEvents.Init)) { Dispatcher.forwardEvent(new AppEvent(AppEvents.ItemPanelReady, itemPanel)); } else if (eventType.equals(AppEvents.ItemSelected)) { onItemSelected(event); } }