Ứng dụng Eclipse RCP 3 đơn giản - Tương tác View và Editor
1. Giới thiệu
Tài liệu được viết dựa trên:
Eclipse: 4.4 (LUNA)
Trong tài liệu này tôi sẽ tạo một ứng dụng RCP với các chức năng nâng cao. Các kiến thức cơ bản của RCP sẽ không được nhắc lại. Vì vậy nếu bạn mà một người mới làm quen với RCP bạn nên xem trước tài liệu "RCP cho những người mới bắt đầu" trước khi thực hành bài hướng dẫn này.
Các vấn đề được đề cập:
- Mỗi khi có thay đổi dữ liệu trên Editor, nút SAVE sẽ sáng lên cho phép người dùng click để lưu dữ liệu. Xử lý việc lưu dữ liệu của Editor.
- View hiển thị danh sách các phòng ban. Người dùng click chọn 1 phòng ban trên View này nó sẽ được hiển thị trên Editor.
- Cập nhập lại View khi dữ liệu trên Editor thay đổi.
2. Tạo Project RCPTarget
Chúng ta tạo nhanh một project RCPTarget, dùng để khai báo các thư viện RCP và môi trường chạy.
- File/New/Project
- File/New/Other...
Nhập vào:
- Name: Eclipse RCP
- Location: http://download.eclipse.org/eclipse/updates/4.4/
Nhấn "Set as Target Platform" để các thư viện có tác dụng trên toàn bộ các project nằm trong workspace.
3. Tạo RCP Project
Tạo nhanh một RCP Workbench project.
- File/New/Other...
Nhập vào:
- Project Name: RCPApplication
Nhập vào:
- Activator: org.o7planning.tutorial.rcpapplication.Activator
Nhập vào:
- Package Name: org.o7planning.tutorial.rcpapplication
Project đã được tạo ra:
Bạn có thể chạy thử bằng cách nhấn phải chuột vào project, và chọn Run As/Eclipse Application.
5. Menu, Toolbar và Action
Thông thường bạn có thể tạo Menu Item, Toolbar Item từ các Command, khai báo trong plugin.xml. Tuy nhiên bạn cũng có thể tạo chúng thông qua các class Action tùy biến, hoặc các Action có sẵn trong thư viện RCP Workbench.
ApplicationActionBarAdvisor.java
package org.o7planning.tutorial.rcpapplication;
import org.eclipse.jface.action.ICoolBarManager;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.swt.SWT;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.IActionBarConfigurer;
public class ApplicationActionBarAdvisor extends ActionBarAdvisor {
private IWorkbenchAction saveAction;
private IWorkbenchAction exitAction;
private IWorkbenchAction aboutAction;
public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) {
super(configurer);
}
@Override
protected void makeActions(IWorkbenchWindow window) {
saveAction = ActionFactory.SAVE.create(window);
this.register(saveAction);
exitAction = ActionFactory.QUIT.create(window);
this.register(exitAction);
aboutAction = ActionFactory.ABOUT.create(window);
this.register(aboutAction);
super.makeActions(window);
}
@Override
protected void fillMenuBar(IMenuManager menuBar) {
// File
MenuManager fileMenu = new MenuManager("&File", "file");
menuBar.add(fileMenu);
fileMenu.add(exitAction);
// Help
MenuManager helpMenu = new MenuManager("&Help", "help");
menuBar.add(helpMenu);
helpMenu.add(aboutAction);
super.fillMenuBar(menuBar);
}
@Override
protected void fillCoolBar(ICoolBarManager coolBar) {
IToolBarManager toolBar1 = new ToolBarManager(SWT.FLAT | SWT.RIGHT );
toolBar1.add(saveAction);
coolBar.add(toolBar1);
IToolBarManager toolBar2 = new ToolBarManager(SWT.FLAT | SWT.RIGHT );
toolBar2.add(exitAction);
coolBar.add(toolBar2);
}
}
6. Toàn bộ Code của Project
Data Model:
Department.java
package org.o7planning.tutorial.rcpapplication.model;
public class Department {
private Integer deptId;
private String deptNo;
private String deptName;
private String location;
public Department() {
}
public Department(Integer deptId, String deptNo, String deptName,
String location) {
this.deptId = deptId;
this.deptNo = deptNo;
this.deptName = deptName;
this.deptName = deptName;
}
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public String getDeptNo() {
return deptNo;
}
public void setDeptNo(String deptNo) {
this.deptNo = deptNo;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
DepartmentDAO.java
package org.o7planning.tutorial.rcpapplication.model;
import java.util.ArrayList;
import java.util.List;
public class DepartmentDAO {
private static final List<Department> list = new ArrayList<Department>();
static {
list.add(new Department(10, "D10", "ACCOUNTING", "NEW YORK"));
list.add(new Department(20, "D20", "RESEARCH", "DALLAS"));
list.add(new Department(30, "D30", "SALES", "CHICAGO"));
list.add(new Department(40, "D40", "OPERATIONS", "BOSTON"));
}
public static List<Department> listDepartment() {
return list;
}
public static int getMaxDeptId() {
int max = 0;
for (Department dept : list) {
if (dept.getDeptId() > max) {
max = dept.getDeptId();
}
}
return max;
}
public static Department findDepartment(int deptId) {
for (Department dept : list) {
if (dept.getDeptId() == deptId) {
return dept;
}
}
return null;
}
public static Department findDepartment(String deptNo) {
for (Department dept : list) {
if (dept.getDeptNo().equals(deptNo)) {
return dept;
}
}
return null;
}
public static void deleteDepartment(int deptId) {
Department dept = findDepartment(deptId);
if (dept == null) {
return;
}
list.remove(dept);
}
public static Department updateDepartment(int deptId, String deptNo,
String deptName, String location) throws DataException {
Department dept = findDepartment(deptId);
if (dept == null) {
return null;
}
Department dept2 = findDepartment(deptNo);
if (dept2 != null && dept2.getDeptId().intValue() != dept.getDeptId()) {
throw new DataException("Unique Constraints error - deptNo: "
+ deptNo);
}
dept.setDeptNo(deptNo);
dept.setDeptName(deptName);
dept.setLocation(location);
return dept;
}
public static Department insertDepartment(String deptNo, String deptName,
String location) throws DataException {
Department dept = findDepartment(deptNo);
if (dept != null) {
throw new DataException("Unique Constraints error - deptNo: "
+ deptNo);
}
dept = new Department();
int deptId = getMaxDeptId() + 1;
dept.setDeptId(deptId);
dept.setDeptNo(deptNo);
dept.setDeptName(deptName);
dept.setLocation(location);
list.add(dept);
return dept;
}
}
DataException.java
package org.o7planning.tutorial.rcpapplication.model;
public class DataException extends Exception {
private static final long serialVersionUID = 7155764478659670087L;
public DataException(String message) {
super(message);
}
}
Command:
DeptCommand.java
package org.o7planning.tutorial.rcpapplication.command;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.handlers.HandlerUtil;
import org.o7planning.tutorial.rcpapplication.editor.DeptEditor;
import org.o7planning.tutorial.rcpapplication.editor.DeptEditorInput;
import org.o7planning.tutorial.rcpapplication.model.Department;
public class DeptCommand extends AbstractHandler {
public static final String ID = "command.dept";
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
// get the page
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event);
IWorkbenchPage page = window.getActivePage();
// get the selection
ISelection selection = HandlerUtil.getCurrentSelection(event);
Object selectObj = null;
// Có lựa chọn trên DeptListView
if (selection != null && !selection.isEmpty() && selection instanceof IStructuredSelection ) {
selectObj = ((IStructuredSelection) selection).getFirstElement();
}
// Không có lựa chọn trên DeptListView
// (Coi như tạo mới một Deptpartment).
else {
// Tạo mới Department.
selectObj = new Department();
}
Department dept = (Department) selectObj;
DeptEditorInput input = new DeptEditorInput(dept);
boolean found = false;
// Các Editor refrence đang mở.
IEditorReference[] eRefs = page.getEditorReferences();
for (IEditorReference ref : eRefs) {
IEditorPart editor = ref.getEditor(false);
if (editor != null && editor instanceof DeptEditor) {
// Restore
DeptEditor deptEditor = (DeptEditor) ref.getEditor(true);
found = true;
boolean saved = true;
// Nếu editor có thay đổi, save lại.
if (deptEditor.isDirty()) {
saved = page.saveEditor(deptEditor, true);
}
if (saved) {
// Sét đặt Input mới cho DeptEditor.
page.reuseEditor(deptEditor, input);
deptEditor.showData();
}
}
}
if (!found) {
try {
page.openEditor(input, DeptEditor.ID);
} catch (PartInitException e) {
throw new RuntimeException(e);
}
}
return null;
}
}
MyConstants.java
package org.o7planning.tutorial.rcpapplication.constant;
public class MyConstants {
public static final int EDITOR_DATA_CHANGED = 999999;
}
Editor
AbstractBaseEditor.java
package org.o7planning.tutorial.rcpapplication.editor;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;
import org.o7planning.tutorial.rcpapplication.constant.MyConstants;
import org.o7planning.tutorial.rcpapplication.other.DirtyListener;
import org.o7planning.tutorial.rcpapplication.other.DirtyUtils;
public abstract class AbstractBaseEditor extends EditorPart {
private boolean dirty;
// Will be called before createPartControl
// Được gọi trước createPartControl
@Override
public void init(IEditorSite site, IEditorInput input)
throws PartInitException {
// Very Important!!
setSite(site);
setInput(input);
}
// Khi thuộc tính PROP_DIRTY thay đổi, method này sẽ được gọi bởi Workbench.
// Workbench kiểm tra Editor có thay đổi gì không.
// Nếu method trả về true, nút SAVE sẽ sáng, ngược lại nút SAVE tối.
@Override
public boolean isDirty() {
return this.dirty;
}
protected void setDirty(boolean dirty) {
if (this.dirty != dirty) {
this.dirty = dirty;
// Thông báo có thuộc tính PROP_DIRTY thay đổi cho Workbench.
this.firePropertyChange(IEditorPart.PROP_DIRTY);
}
}
@Override
public void doSaveAs() {
}
@Override
public boolean isSaveAsAllowed() {
return false;
}
@Override
public void setFocus() {
}
// Write code in createPartControl2(Composite)
@Override
public final void createPartControl(Composite parent) {
this.createPartControl2(parent);
this.showData();
this.setDirty(false);
this.firePropertyChange(MyConstants.EDITOR_DATA_CHANGED);
Control[] controls = this.registryDirtyControls();
DirtyListener listener = new DirtyListenerImpl();
DirtyUtils.registryDirty(listener, controls);
}
public abstract void showData( );
// Create controls in this method.
protected abstract void createPartControl2(Composite parent);
// If data in Control changed, it fire to Workbench.
// Đăng ký các Control, nếu các Control này thay đổi, nó sẽ thông báo lên Workbench.
protected abstract Control[] registryDirtyControls();
class DirtyListenerImpl implements DirtyListener {
@Override
public void fireDirty() {
// If has any change, fire to Editor.
AbstractBaseEditor.this.setDirty(true);
}
}
}
DeptEditor.java
package org.o7planning.tutorial.rcpapplication.editor;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.IWorkbenchPartConstants;
import org.o7planning.tutorial.rcpapplication.constant.MyConstants;
import org.o7planning.tutorial.rcpapplication.model.Department;
import org.o7planning.tutorial.rcpapplication.model.DepartmentDAO;
import org.o7planning.tutorial.rcpapplication.other.DirtyUtils;
// IReusableEditor có thể sét đặt giá trị input mới cho Editor này.
public class DeptEditor extends AbstractBaseEditor implements IReusableEditor {
public static final String ID = "deptEditor";
private Integer deptId;
private Text text_deptNo;
private Text text_deptName;
private Text text_location;
public DeptEditor() {
}
/**
* Create contents of the editor part.
*
* @param parent
*/
@Override
public void createPartControl2(Composite parent) {
Composite container = new Composite(parent, SWT.NONE);
container.setLayout(new GridLayout(2, false));
Label lblDeptNo = new Label(container, SWT.NONE);
lblDeptNo.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
false, 1, 1));
lblDeptNo.setText("Dept No");
text_deptNo = new Text(container, SWT.BORDER);
text_deptNo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
false, 1, 1));
Label lblDeptName = new Label(container, SWT.NONE);
lblDeptName.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
false, 1, 1));
lblDeptName.setText("Dept Name");
text_deptName = new Text(container, SWT.BORDER);
text_deptName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
false, 1, 1));
Label lblLocation = new Label(container, SWT.NONE);
lblLocation.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
false, 1, 1));
lblLocation.setText("Location");
text_location = new Text(container, SWT.BORDER);
text_location.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
false, 1, 1));
new Label(container, SWT.NONE);
DirtyListenerImpl dirtyListener = new DirtyListenerImpl();
DirtyUtils.registryDirty(dirtyListener, this.text_deptName,
this.text_deptNo, this.text_location);
}
@Override
public void doSave(IProgressMonitor monitor) {
try {
String deptNo = this.text_deptNo.getText();
String deptName = this.text_deptName.getText();
String location = this.text_location.getText();
if (this.deptId != null) {
Department dept = DepartmentDAO.updateDepartment(deptId,
deptNo, deptName, location);
this.setInput(new DeptEditorInput(dept));
this.setDirty(false);
this.firePropertyChange(MyConstants.EDITOR_DATA_CHANGED);
} else {
Department dept = DepartmentDAO.insertDepartment(deptNo,
deptName, location);
this.setInput(new DeptEditorInput(dept));
this.setDirty(false);
this.firePropertyChange(MyConstants.EDITOR_DATA_CHANGED);
}
} catch (Exception e) {
MessageDialog.openError(this.getSite().getShell(), "Error",
e.getMessage());
e.printStackTrace();
}
}
@Override
protected Control[] registryDirtyControls() {
return new Control[] { this.text_deptName, this.text_deptNo,
this.text_location };
}
@Override
public void showData() {
DeptEditorInput ip = (DeptEditorInput) this.getEditorInput();
Department dept = ip.getDept();
this.deptId = dept.getDeptId();
this.text_deptName.setText(dept.getDeptName() == null ? "" : dept
.getDeptName());
this.text_deptNo.setText(dept.getDeptNo() == null ? "" : dept
.getDeptNo());
this.text_location.setText(dept.getLocation() == null ? "" : dept
.getLocation());
// Clear dirty.
this.setDirty(false);
}
// Làm setInput(..) thành public (IReusableEditor)
@Override
public void setInput(IEditorInput input) {
super.setInput(input);
firePropertyChange(IWorkbenchPartConstants.PROP_INPUT);
}
public String getDeptInfo() {
DeptEditorInput input = (DeptEditorInput) this.getEditorInput();
Department dept = input.getDept();
if (dept == null) {
return "";
}
String info = dept.getDeptNo() + " - " + dept.getDeptName() + " - "
+ dept.getLocation();
return info;
}
}
DeptEditorInput.java
package org.o7planning.tutorial.rcpapplication.editor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IPersistableElement;
import org.o7planning.tutorial.rcpapplication.model.Department;
public class DeptEditorInput implements IEditorInput {
private Department dept;
public DeptEditorInput(Department dept) {
this.dept = dept;
}
public Department getDept() {
return dept;
}
@SuppressWarnings("rawtypes")
@Override
public Object getAdapter(Class adapter) {
return null;
}
@Override
public boolean exists() {
return false;
}
@Override
public ImageDescriptor getImageDescriptor() {
return null;
}
@Override
public String getName() {
// Required!!
return "Department";
}
@Override
public IPersistableElement getPersistable() {
return null;
}
@Override
public String getToolTipText() {
// Required!!
return "Department";
}
}
Dirty Manager
DirtyListener.java
package org.o7planning.tutorial.rcpapplication.other;
public interface DirtyListener {
public void fireDirty();
}
DirtyUtils.java
package org.o7planning.tutorial.rcpapplication.other;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Text;
public class DirtyUtils {
public static void registryDirty(DirtyListener listener,
Control... controls) {
if (controls == null) {
return;
}
for (Control control : controls) {
if (control instanceof Text) {
Text text = (Text) control;
text.addVerifyListener(new VerifyListenerImpl(listener));
}
// Checkbox or Radio button
else if (control instanceof Button) {
Button button = (Button) control;
button.addSelectionListener(new SelectionListenerImpl(listener));
}
// Not support
else {
throw new UnsupportedOperationException("Not support for "
+ control.getClass().getSimpleName());
}
}
}
static class VerifyListenerImpl implements VerifyListener {
private DirtyListener listener;
public VerifyListenerImpl(DirtyListener listener) {
this.listener = listener;
}
@Override
public void verifyText(VerifyEvent arg0) {
listener.fireDirty();
}
}
// For Button (Checkbox, Radio).
static class SelectionListenerImpl implements SelectionListener {
private DirtyListener listener;
public SelectionListenerImpl(DirtyListener listener) {
this.listener = listener;
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
@Override
public void widgetSelected(SelectionEvent e) {
listener.fireDirty();
}
}
}
Content Provider & Label Provider:
AbstractTableContentLabelProvider.java
package org.o7planning.tutorial.rcpapplication.provider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;
public abstract class AbstractTableContentLabelProvider implements
ITableLabelProvider, IStructuredContentProvider {
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
@Override
public void addListener(ILabelProviderListener listener) {
}
@Override
public boolean isLabelProperty(Object element, String property) {
return false;
}
@Override
public void removeListener(ILabelProviderListener listener) {
}
@Override
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
}
ApplicationWorkbenchWindowAdvisor.java
package org.o7planning.tutorial.rcpapplication;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.IActionBarConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;
import org.o7planning.tutorial.rcpapplication.editor.DeptEditor;
import org.o7planning.tutorial.rcpapplication.view.DeptListView;
import org.o7planning.tutorial.rcpapplication.view.DeptView;
public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {
public ApplicationWorkbenchWindowAdvisor(
IWorkbenchWindowConfigurer configurer) {
super(configurer);
}
public ActionBarAdvisor createActionBarAdvisor(
IActionBarConfigurer configurer) {
return new ApplicationActionBarAdvisor(configurer);
}
public void preWindowOpen() {
IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
configurer.setInitialSize(new Point(400, 300));
configurer.setShowCoolBar(true);
configurer.setShowStatusLine(true);
configurer.setShowPerspectiveBar(true);
configurer.setTitle("Hello RCP");
}
@Override
public void postWindowOpen() {
Shell shell = getWindowConfigurer().getWindow().getShell();
shell.setMaximized(true);
// Đăng ký khi có sự kiện liên quan đến các thành phần của trang
// (View, Editor,..)
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
.addPartListener(new IPartListener2() {
@Override
public void partActivated(IWorkbenchPartReference partRef) {
}
@Override
public void partBroughtToTop(IWorkbenchPartReference partRef) {
}
@Override
public void partClosed(IWorkbenchPartReference partRef) {
}
@Override
public void partDeactivated(IWorkbenchPartReference partRef) {
}
@Override
public void partHidden(IWorkbenchPartReference partRef) {
}
@Override
public void partVisible(IWorkbenchPartReference partRef) {
}
@Override
public void partInputChanged(IWorkbenchPartReference partRef) {
}
// Khi một View hoặc một Editor được mở.
@Override
public void partOpened(IWorkbenchPartReference partRef) {
System.out.println("Part OPENED: "
+ partRef.getPartName());
IWorkbenchPart part = partRef.getPart(false);
if (part instanceof DeptListView) {
DeptListView deptListView = (DeptListView) part;
DeptEditor deptEditor = (DeptEditor) partRef
.getPage().findView(DeptEditor.ID);
// DeptListView lắng nghe thay đổi các thuộc tính từ
// DeptEditor.
if (deptEditor != null) {
deptEditor.addPropertyListener(deptListView);
}
} else if (part instanceof DeptView) {
DeptView deptView = (DeptView) part;
DeptEditor deptEditor = (DeptEditor) partRef
.getPage().findView(DeptEditor.ID);
// DeptView lắng nghe thay đổi các thuộc tính từ
// DeptEditor.
if (deptEditor != null) {
deptEditor.addPropertyListener(deptView);
}
} else if (part instanceof DeptEditor) {
DeptEditor deptEditor = (DeptEditor) part;
DeptView deptView = (DeptView) partRef.getPage()
.findView(DeptView.ID);
// DeptView lắng nghe thay đổi các thuộc tính từ
// DeptEditor.
if (deptView != null) {
deptEditor.addPropertyListener(deptView);
}
DeptListView deptListView = (DeptListView) partRef
.getPage().findView(DeptListView.ID);
// DeptListView lắng nghe thay đổi các thuộc tính từ
// DeptEditor.
if (deptListView != null) {
deptEditor.addPropertyListener(deptListView);
}
}
}
});
}
}
- plugin.xml
plugin.xml
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<extension
id="application"
point="org.eclipse.core.runtime.applications">
<application>
<run
class="org.o7planning.tutorial.rcpapplication.Application">
</run>
</application>
</extension>
<extension
point="org.eclipse.ui.perspectives">
<perspective
name="RCP Perspective"
class="org.o7planning.tutorial.rcpapplication.Perspective"
id="RCPApplication.perspective">
</perspective>
</extension>
<extension
point="org.eclipse.ui.views">
<view
class="org.o7planning.tutorial.rcpapplication.view.DeptView"
id="view.dept"
name="Dept"
restorable="true">
</view>
<view
class="org.o7planning.tutorial.rcpapplication.view.DeptListView"
id="view.deptList"
name="Dept List"
restorable="true">
</view>
</extension>
<extension
point="org.eclipse.ui.editors">
<editor
class="org.o7planning.tutorial.rcpapplication.editor.DeptEditor"
default="false"
id="deptEditor"
name="Dept Editor">
</editor>
</extension>
<extension
point="org.eclipse.ui.commands">
<command
defaultHandler="org.o7planning.tutorial.rcpapplication.command.DeptCommand"
id="command.dept"
name="Dept Command">
</command>
</extension>
<extension
point="org.eclipse.ui.perspectiveExtensions">
<perspectiveExtension
targetID="*">
<view
id="view.deptList"
minimized="false"
relationship="left"
relative="org.eclipse.ui.editorss"
visible="true">
</view>
<view
id="view.dept"
minimized="false"
relationship="right"
relative="org.eclipse.ui.editorss"
visible="true">
</view>
</perspectiveExtension>
</extension>
<extension
point="org.eclipse.ui.menus">
<menuContribution
allPopups="false"
locationURI="menu:org.eclipse.ui.main.menu">
<menu
label="Functions">
<command
commandId="command.dept"
label="Open Dept"
style="push">
</command>
</menu>
</menuContribution>
</extension>
</plugin>
7. Các thành phần trong Project và giải thích
Đăng ký lắng nghe các thay đổi từ Editor, View
Khi DeptEditor thay đổi, nó cần thông báo tới DeptListView và DeptView để update lại thông tin. DeptListView & DeptView cần implements IPropertyListener. View & Editor lắng nghe các sự kiện của nhau, bạn có thể viết code trong method postWindowOpen của ApplicationWorkbenchWindowAdvisor:
deptEditor.addPropertyListener(deptView);
deptEditor.addPropertyListener(deptListView);
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
.addPartListener(new IPartListener2() {
.....
// Khi một View hoặc một Editor được mở.
@Override
public void partOpened(IWorkbenchPartReference partRef) {
IWorkbenchPart part = partRef.getPart(false);
if (part instanceof DeptListView) {
DeptListView deptListView = (DeptListView) part;
DeptEditor deptEditor = (DeptEditor) partRef
.getPage().findView(DeptEditor.ID);
// DeptListView lắng nghe thay đổi các thuộc tính từ
// DeptEditor.
if (deptEditor != null) {
deptEditor.addPropertyListener(deptListView);
}
} else if (part instanceof DeptView) {
DeptView deptView = (DeptView) part;
DeptEditor deptEditor = (DeptEditor) partRef
.getPage().findView(DeptEditor.ID);
// DeptView lắng nghe thay đổi các thuộc tính từ
// DeptEditor.
if (deptEditor != null) {
deptEditor.addPropertyListener(deptView);
}
} else if (part instanceof DeptEditor) {
DeptEditor deptEditor = (DeptEditor) part;
DeptView deptView = (DeptView) partRef.getPage()
.findView(DeptView.ID);
// DeptView lắng nghe thay đổi các thuộc tính từ
// DeptEditor.
if (deptView != null) {
deptEditor.addPropertyListener(deptView);
}
DeptListView deptListView = (DeptListView) partRef
.getPage().findView(DeptListView.ID);
// DeptListView lắng nghe thay đổi các thuộc tính từ
// DeptEditor.
if (deptListView != null) {
deptEditor.addPropertyListener(deptListView);
}
}
}
});
DeptListView
DeptListViewer: Chứa danh sách các phòng ban, khi kích đúp chuột vào một phòng ban nó sẽ được hiển thị trên DeptEditor.
Màn hình thiết kế:
Trên DeptListView bạn cần sét đặt SelectionProvider:
// Đăng ký Selection Provider.
// (Mục đích để tại các nơi khác biết View này đang chọn gì).
this.getSite().setSelectionProvider(tableViewer);
Chú ý:Bạn có thể tìm hiểu thêm về cách sử dụng các class này tại:
- TableViewer, TreeViewer,.. là các class thi hành interface ISelectionProvider
DeptEditor
- AbstractBaseEditor.java (DeptEditor extends AbstractBaseEditor).
private boolean dirty;
// Khi thuộc tính PROP_DIRTY thay đổi, method này sẽ được gọi bởi Workbench.
// Workbench kiểm tra Editor có thay đổi gì không.
// Nếu method trả về true, nút SAVE sẽ sáng, ngược lại nút SAVE tối.
@Override
public boolean isDirty() {
return this.dirty;
}
// Khi editor thay đổi dữ liệu, gọi method này để thông báo lên Workbench.
protected void setDirty(boolean dirty) {
if (this.dirty != dirty) {
this.dirty = dirty;
// Thông báo có thuộc tính PROP_DIRTY thay đổi cho Workbench.
this.firePropertyChange(IEditorPart.PROP_DIRTY);
}
}
DeptCommand
DeptCommand là command sử dụng để mở ra DeptEditor.
Thông thường một command sẽ tạo một đối tượng IEditorInput, mở ra một Editor mới và truyền Input vào. Bạn cũng có thể tìm kiếm các Editor đang mở sẵn trên trang, và truyền mới IEditorInput, các editor này là các Editor có thể tái sử dụng (với một Input mới), và nó cần implements IReusableEditor.
Thông thường một command sẽ tạo một đối tượng IEditorInput, mở ra một Editor mới và truyền Input vào. Bạn cũng có thể tìm kiếm các Editor đang mở sẵn trên trang, và truyền mới IEditorInput, các editor này là các Editor có thể tái sử dụng (với một Input mới), và nó cần implements IReusableEditor.
Lấy ra trang hiện tại trên workbench window:
// Get the page
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event);
IWorkbenchPage page = window.getActivePage();
Department dept = (Department) selectObj;
DeptEditorInput input = new DeptEditorInput(dept);
boolean found = false;
// Các Editor refrence đang mở.
IEditorReference[] eRefs = page.getEditorReferences();
for (IEditorReference ref : eRefs) {
IEditorPart editor = ref.getEditor(false);
if (editor != null && editor instanceof DeptEditor) {
// Restore
DeptEditor deptEditor = (DeptEditor) ref.getEditor(true);
found = true;
boolean saved = true;
// Nếu editor có thay đổi, save lại.
if (deptEditor.isDirty()) {
saved = page.saveEditor(deptEditor, true);
}
if (saved) {
// Sét đặt Input mới cho DeptEditor.
page.reuseEditor(deptEditor, input);
deptEditor.showData();
}
}
}
Eclipse RCP
- Các nền tảng nào bạn nên chọn để lập trình ứng dụng Java Desktop?
- Lập trình ứng dụng Java Desktop sử dụng SWT
- Hướng dẫn lập trình Eclipse RCP 4 cho người mới bắt đầu - Ứng dụng e4 Workbench
- Đóng gói và triển khai ứng dụng Desktop SWT/RCP
- Hướng dẫn lập trình Eclipse RCP 3 cho người mới bắt đầu - Ứng dụng Workbench
- Cài đặt e4 Tools Developer Resources cho Eclipse
- Ứng dụng Eclipse RCP 3 đơn giản - Tương tác View và Editor
Show More
Công nghệ của Eclipse
- Làm sao để có các thư viện mã nguồn mở Java dưới dạng OSGi
- Cài đặt Tycho cho Eclipse
- Hướng dẫn lập trình Java OSGi cho người mới bắt đầu
- Tạo dự án Java OSGi với Maven và Tycho
- Cài đặt WindowBuilder cho Eclipse
- Các nền tảng nào bạn nên chọn để lập trình ứng dụng Java Desktop?
- Lập trình ứng dụng Java Desktop sử dụng SWT
- Hướng dẫn và ví dụ Eclipse JFace
- Cài đặt e4 Tools Developer Resources cho Eclipse
- Đóng gói và triển khai ứng dụng Desktop SWT/RCP
- Cài đặt Eclipse RAP Target Platform
- Cài đặt EMF cho Eclipse
- Cài đặt RAP e4 Tooling cho Eclipse
- Tạo Eclipse RAP Widget từ ClientScripting widget
- Cài đặt GEF cho Eclipse
- Hướng dẫn lập trình Eclipse RAP cho người mới bắt đầu - Ứng dụng Workbench (trước e4)
- Hướng dẫn lập trình Eclipse RCP 3 cho người mới bắt đầu - Ứng dụng Workbench
- Ứng dụng Eclipse RCP 3 đơn giản - Tương tác View và Editor
- Hướng dẫn lập trình Eclipse RCP 4 cho người mới bắt đầu - Ứng dụng e4 Workbench
- Cài đặt RAP Tools cho Eclipse
- Hướng dẫn lập trình Eclipse RAP cho người mới bắt đầu - Ứng dụng cơ bản
- Hướng dẫn lập trình Eclipse RAP cho người mới bắt đầu - Ứng dụng e4 Workbench
- Đóng gói và triển khai ứng dụng Eclipse RAP
Show More