chapter 5 Starting The Hyperbola Prototype
5.1 Continuing from the shell
Lst's fix the resize and positiong bug;
5.1.1 Saving Window Location and Size
the Workbench contains code that saves settings for open windows.
to enable it,first override the WorkbenchAdvisor.initialize() method from within ApplicationWorkbenchAdvisor ,
一个快捷方法是输入ini 然后Alt+/
public void initialize(IWorkbenchConfigurer configurer) {
// TODO Auto-generated method stub
//super.initialize(configurer);
configurer.setSaveAndRestore(true);
}
This method is called by Eclipse to mark the beginning of the advisor‘s lifecycle。
5.2 Adding a Contacts View
In Eclipse,users interact with applications through views and editors.
Perspectives are a mechanism for arranging views and editors and supporting scalable UIs.
A view is added by contributing a view extension to the org.eclipse.ui.views extension point.
Open plug.xml and go to the Extensions page.
Click Add.. and create an extension of type org.eclipse.ui.views , ClickFinish.
Right-click on the extension and add a view attribute using New -> View from the context menu .
点击生成滴view,右面有详细内容,点击class类的链接,将名字改成ContactsView,点击Finish
public class ContactsView extends ViewPart {
// 在新生成滴View里设置一个id
public static final String ID = "org.eclipsercp.hyperbola.views.contacts";
}
5.2.1 Adding the contacts view to a perspective
Every IWorkbenchWindow has one page. 这个页面包括他自己的编辑器,视图和用那个活动的透视图。透视图具体描述哪?是否展示这个编辑器和视图。
The initial perspective is identified by WorkbenchAdvisor.getInitialWindowPerspectiveId()
public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor {
//定义了plugin.xml文件里扩展perspective的ID
private static final String PERSPECTIVE_ID = "org.eclipse.hyperbolaT.perspective";
public String getInitialWindowPerspectiveId() {
return PERSPECTIVE_ID;
}
}
Notice that the extension defines an ID and identifies a class for the perspective.----plugin.xml文件
public class Perspective implements IPerspectiveFactory {
// 需要透视图的时候IPerspectiveFactory就创建一个,并将一个IPageLayout传递到方法里
public void createInitialLayout(IPageLayout layout) {
}
}
默认生成的模板代码是一个空的透视图,下面增加内容
public class Perspective implements IPerspectiveFactory {
public void createInitialLayout(IPageLayout layout) {
layout.setEditorAreaVisible(false);
//联系人视图被添加到IPageLayout layout的左边区域,定义比例1.0f(between 0.0f只显示标题 and 1.0f占据整个窗口)
layout.addView(ContactsView.ID, IPageLayout.LEFT,1.0f, layout.getEditorArea());
}
}
IPageLayout contains several methods for defining the layout of a perspective.
通过IPageLayout.addView()方法添加到透视图当中的视图,继承了各种默认的行为--移动,移除,关闭,最小化,最大化。
通过layout.addStandaloneView()方法,添加一个独立的视图,隐藏了标题区,从而防止视图被关闭,移动等。
public class Perspective implements IPerspectiveFactory {
public void createInitialLayout(IPageLayout layout) {
layout.setEditorAreaVisible(false);
// layout.addView(ContactsView.ID, IPageLayout.LEFT,1.0f, layout.getEditorArea());
layout.addStandaloneView(ContactsView.ID, false, IPageLayout.LEFT,1.0f, layout.getEditorArea());
}
}
对于修改代码运行没有变化的问题,是因为透视图,视图工厂一旦创建,下一次将不再创建,保持上次状态。RUN->run configuration-> main 选项卡,选择 clear workspace ;uncheck Ask for confirmation before clearing ;完成
5.3 The Chat Model
拷贝model目录到项目中
5.4 Filling in the Contacts View
5.4.1 The Contactsview
When the Workbench creates the Contacts views,通过 调用方法createPartControl(),在这个方法里调用自己的控件
public void createPartControl(Composite parent) {
// TODO Auto-generated method stub
}
编程内容如下,第一行调用了一个fake model 通过方法 initializeSession()
public void createPartControl(Composite parent) {
initializeSession(); // temporary tweak to build a fake model
treeViewer = new TreeViewer(parent, SWT.BORDER | SWT.MULTI| SWT.V_SCROLL);
getSite().setSelectionProvider(treeViewer);
Platform.getAdapterManager().registerAdapters(adapterFactory, Contact.class);
// LabelProvider 提供树的节点 ContentProvider 提供节点图片和是否在线
treeViewer.setLabelProvider(new WorkbenchLabelProvider());
treeViewer.setContentProvider(new BaseWorkbenchContentProvider());
treeViewer.setInput(session.getRoot());
session.getRoot().addContactsListener(new IContactsListener() {
public void contactsChanged(ContactsGroup contacts,ContactsEntry entry) {
treeViewer.refresh();
}
});
}
5.4.2 Content Providers Overview
treeViewer.setContentProvider(new BaseWorkbenchContentProvider());
此行代码中org.eclipse.ui.model.BaseWorkbenchContentProvider;
public class BaseWorkbenchContentProvider implements ITreeContentProvider
treeViewer要求设置ContentProvider提供树滴节点,ContentProvider来源于ITreeContentProvider
org.eclipse.jface/ITreeContentProvider
public interface ITreeContentProvider extends IStructuredContentProvider {
public Object[] getElements(Object inputElement);
public Object[] getChildren(Object parentElement);
public Object getParent(Object element);
public boolean hasChildren(Object element);
}
As shown in Figure,TreeViewer.setInput(Object) is called when ContactsView is created.
This in turn uses the configured ITreeContentProvider.getChildren(Object) method to find the first level of elements to display.
Notice that this means the root input object just provides the staring point from the visible tree, this TreeViewr root is never display.
This Figure shows how viewers and providers work together,but not how providers and input model objects interact.
5.4.2.1 Adding the IWorkbenchAdapters
Let's look at this in more detail.There are four things you have to do to use the adapter technique:
1.Configure the TreeViewer to use an instance of BaseWorkbenchContentProvider as its content provider.
eclipse的适配机制可以扩展model的行为。Workbench定义了一个标准的内容提供程序,通过BaseWorkbenchContentProvider ,它知道如何浏览IWorkbenchAdaptable:
org.eclipse.ui.workbench/IWorkbenchAdapter
public interface IWorkbenchAdapter{
}public Object[] getChildren(Object o );
public ImageDescriptor getImageDescriptor(Object o );
public String getLabel(Object o);
public Object getParent(Object o );
2.Implement IWorkbenchAdapters for the chat model elements that need to be displayed.
3.Implement an adapter factory that returns an IWorkbenchAdapter for each model element.
工厂里实现了两个私有的适配器类,groupAdapter对ContactsGroup,entryAdapter对ContactsEntry,他们两个是IWorkbenchAdapter的内部工具类,
类中的方法参数都是Object,所以适用于所有模型对象,当getAdapter(Object,Class)被调用时,工厂挑选一个适配器来返回。
public class HyperbolaAdapterFactory implements IAdapterFactory {
private IWorkbenchAdapter groupAdapter = new IWorkbenchAdapter() {
public Object getParent(Object o) {
return ((ContactsGroup) o).getParent();
}
public String getLabel(Object o) {
return ((ContactsGroup)o).getName();
}
public ImageDescriptor getImageDescriptor(Object object) {
return null;
}
public Object[] getChildren(Object o) {
return ((ContactsGroup) o).getEntries();
}
};
private IWorkbenchAdapter entryAdapter = new IWorkbenchAdapter() {
public Object getParent(Object o) {
return ((ContactsEntry) o).getParent();
}
public String getLabel(Object o) {
ContactsEntry entry = ((ContactsEntry) o);
return entry.getName() + " -"+entry.getServer();
}
public ImageDescriptor getImageDescriptor(Object object) {
return null;
}
public Object[] getChildren(Object o) {
return new Object[0];
}
};
public Object getAdapter(Object adaptableObject, Class adapterType) {
if (adapterType == IWorkbenchAdapter.class && adaptableObject instanceof ContactsGroup)
return groupAdapter;
if (adapterType == IWorkbenchAdapter.class && adaptableObject instanceof ContactsEntry)
return entryAdapter;
return null;
}
public Class[] getAdapterList() {
return new Class[] { IWorkbenchAdapter.class };
}
}
4.Register the Hyperbola adapter factory with Eclipse.
向eclipse注册适配器工厂
ContactsView类中:The last step is to register the adapter factory with Eclipse when the ContactsView is created and unregister it when the view is closed.
private IAdapterFactory adapterFactory = new HyperbolaAdapterFactory();
public void createPartControl(Composite parent) {
...............................................................
Platform.getAdapterManager().registerAdapters(adapterFactory, Contact.class);
...............................................................
}
public void dispose() {
Platform.getAdapterManager().unregisterAdapters(adapterFactory);
super.dispose();
}
5.4.3 the Label Provider
当ContactsView被创建时,WorkbenchLabelProvider被配置为treeViewer的标签提供程序。像BaseWorkbenchContentProvider那样,他也使用IWorkbenchAdapter来确定树中显示的标签和图像。
public void createPartControl(Composite parent) {
...............................................................
treeViewer.setLabelProvider(new WorkbenchLabelProvider());
treeViewer.setContentProvider(new BaseWorkbenchContentProvider());
...............................................................
}
更改适配工厂实现私有类中的getLabel方法,两个都要更改!
5.5 Adding Images
16*16像素的GIF。transparency(透明背景的图片,抠图)
使用源代码来关联图像,一个标准方法是用接口来记录图片位置:
public interface IImageKeys {
public static final String ONLINE = "icons/online.gif";
public static final String OFFLINE = "icons/offline.gif";
public static final String DO_NOT_DISTURB = "icons/dnd.gif";
public static final String GROUP = "icons/groups.gif";
public static final String AWAY = "icons/away.gif";
}
通过更新IWorkbenchAdapters,便可以为树中相应项目提供图像。Images:重量级对象,不用时要释放掉,保留底部系统资源的句柄
ImageDescriptions:轻量级对象。
这种关系像java File轻量级,FileInputStream重量级;在使用重量级之前先用轻量级表示。