0
点赞
收藏
分享

微信扫一扫

GXT之旅:第七章:MVC——Navigation,Main和Item区域交互(1)


(刚干了一个多月的flex项目,一时半会还无法转过神来专注于GXT的东东,有好多东西自己都忘的差不多了。。。。

我得好好屡屡




使用TabPanel显示feeds

之前,我们已经通过RssMainPanel里的 ItemGrid来显示一个feed数据。现在,我们将要使用TabPanel去管理多个TabItem——其中每一个TabItem包含一个 ItemGrid,一个ItemGrid负责显示一个feed数据的多个Items内容。

  • 编辑com.danielvaughan.rssreader.client.components.FeedPanel,新建field——TabPanel

private final TabPanel tabPanel = new TabPanel();

  • 新建一个方法——addTab,传入TabItem参数。设置一些属性,如下:

public void addTab(TabItem tabItem) {
tabItem.setLayout(new FitLayout());
tabItem.setIcon(Resources.ICONS.rss());
tabItem.setScrollMode(Scroll.AUTO);
}

  • 因为我们只是想让一个TabItem负责显示一个feed数据内容,所以当一个TabItem已经拥有feed数据显示到TabPanel的时候,就直接跳转到此TabItem,否则就创建一个新的TabItem

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);
}
}

  • 重构FeedPanel构造函数:

public FeedPanel() {
setHeading("Main");
setLayout(new FitLayout());
add(tabPanel);
}


连接起来

我们现在几乎已经准备好了所有的UI,现在我们需要将它们连接起来——当用户在Main(FeedPanel)区域选择了某条feed,则在Item(ItemPanel)区域显示出具体的内容。

我们可以根据用户的选择事件操作,将其选择的ModelDate在不同的components之间传递。同样的,也可以通过数据的加载事件,将ModelData在不同的components之间传递。

大致思路如下:

  • 当用户在FeedList选中了一个Feed(link)的时候,一个FeedSelected AppEvent就会搭载其Feed被派发出去。
  • 当FeedSelected AppEvent被派发出来之后,FeedView接收到此事件,然后负责页面跳转到或新建一个ItemGrid来显示Feed

  • 当用户在ItemGrid选中了一个Item的时候,一个ItemSelected AppEvent就会搭载其Item被派发出去。
  • 当ItemSelected AppEvent被派发出来之后,ItemView接收到此事件,然后负责页面使用ItemPanel来显示Item

  • 当用户在TabPanel选中某个tab的时候,一个TabSelected AppEvent就会搭载其Feed被派发出去。
  • 当TabSelectedAppEvent被派发出来之后,FeedList接收到此事件,然后负责联动选中到对应的Feed。

Implements:

  • AppEvents类,新定义三个EventType

public static final EventType FeedSelected = new EventType();
public static final EventType ItemSelected = new EventType();
public static final EventType TabSelected = new EventType();

  • 找到com.danielvaughan.rssreader.client.lists.FeedList类,在其onRender方法里,添加 SelectionChange监听——当用户选择不同的Feed的时候,就会触发SelectionChangedEvent事件,其操作过程,是将传入的selectedItem,派发出去。

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);
}
}


  • 如果想要程序能够对FeedSelected事件作出响应,就必须在关联的Controller注册——FeedController

public FeedController() {
registerEventTypes(AppEvents.Init);

registerEventTypes(AppEvents.FeedSelected);
}


  • 重构ItemGrid的构造函数,增加一个参数为Feed——用来接收FeedSelected事件传递过来的Feed

private final Feed feed;
public ItemGrid(Feed feed) {
setLayout(new FitLayout());
this.feed = feed;
}

  • 继续在ItemGrid类,将onRender方法里面局部变量的grid,提取到方法外面,作为ItemGrid类的属性存在。

private Grid<ModelData> grid;

@Override
protected void onRender(Element parent, int index) {

grid = new Grid<ModelData>(itemStore, columnModel);
}

  • 继续在ItemGrid类的onRender方法里。删除如下局部变量的定义

final String TEST_DATA_FILE = "http://localhost:8888/rss2sample.xml";

  • 取而代之,是使用Feed对象的UUID属性替换之前的TEST_DATA_FILE

RpcProxy<List<Item>> proxy = new RpcProxy<List<Item>>() {
@Override
protected void load(Object loadConfig,
AsyncCallback<List<Item>> callback) {
feedService.loadItems(feed.getUuid(), callback);
}
};


  • 继续在ItemGrid类里,定义一个新的方法——resetSelection,用来重设Grid的选中状态。

public void resetSelection() {
grid.getSelectionModel().deselectAll();
}

  • 在FeedView类,新建一个方法(onFeedSelected)用来响应,接收到的 FeedSelected事件:通过传入的event获得Feed对象;将Feed对象作为参数创建一个ItemGrid;新建TabItem,并设置一些属性,将先前新建的ItemGrid加入到Tabitem里;最后,将tabItem加入到feedPanel里。

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);
}

  • 在FeedView类的handleEvent方法里,加入对FeedSelected事件的跳转。到此FeedSelected事件的处理流程完成

@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);
}
}


  • 在ItemGrid的onRender方法里,添加一个SelectionChange的监听,当用户选择不同的Item的时候,就会触发SelectionChangedEvent事件,其操作过程,是将传入的selectedItem,派发出去。

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);
}
});


  • 同样的,对于ItemSelected方法,我们要在ItemController里注册

public ItemController() {
registerEventTypes(AppEvents.Init);

registerEventTypes(AppEvents.ItemSelected);
}


  • 在ItemView类里,针对ItemSelected AppEvent处理的方法——onItemSelected()

private void onItemSelected(AppEvent event) {
Item item = (Item) event.getData();
itemPanel.displayItem(item);
}

  • 在ItemView类里,handleEvent方法里加入针对ItemSelected事件的处理方法跳转。到此ItemSelected事件的处理流程完成

@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);
}
}


  • 现在我们还少一个事件处理流程——TabSelected ,但是我们先来看看程序运行效果哈~~~

GXT之旅:第七章:MVC——Navigation,Main和Item区域交互(1)_string



举报

相关推荐

第七章

第七章:集合

第七章:事务

第七章 集合

第七章 数组

第七章 类

第七章 测试

第七章总结

0 条评论