需要以下的對象:
LoginDialog,用於展示狀態,
LoginListener,用於監聽登錄狀態,並根據不同的情況改變LoginDialog的顯示
LoginAction,用於執行登錄的業務邏輯,並且根據不同的結果來fire不同的動作。
狀態一共有以下幾種:
1。登錄中
2。登錄成功
3。登錄失敗
3.1 連接失敗
3.2 用戶名密碼錯誤
3.3 .....
4。用戶取消登錄
下面是代碼片段:
Application;
/*
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.IPlatformRunnable#run(java.lang.Object)
*/
public Object run(Object args) throws Exception {
try {
TestLoginDialog dialog = new TestLoginDialog(Display.getCurrent()
.getActiveShell());
LoginListener loginListener = new LoginListenerImpl(dialog);
LoginAction action = new LoginAction("login");
action.addLoginListener(loginListener);
dialog.setLoginAction(action);
if (dialog.open() != Window.OK) {
return IPlatformRunnable.EXIT_OK;
}
int returnCode = PlatformUI.createAndRunWorkbench(display,
new ApplicationWorkbenchAdvisor());
if (returnCode == PlatformUI.RETURN_RESTART) {
return IPlatformRunnable.EXIT_RESTART;
}
return IPlatformRunnable.EXIT_OK;
} finally {
display.dispose();
}
}
}
LoginListener:
public void loginError(String message);
public void loginComplete();
public void loginCanceled();
public void loginStarted();
}
LoginAction:這裏要用到Job,因爲登錄的邏輯處理必須要在異步線程中來做,否則UI就會停住的。
private LoginListener loginListener;
private Session session = Session.getInstance();
public LoginAction(String name) {
super(name);
}
public void addLoginListener(LoginListener listener) {
this.loginListener = listener;
}
public void fireLoginComplete() {
loginListener.loginComplete();
}
public void fireLoginStarted() {
loginListener.loginStarted();
}
public void fireLoginError(String message) {
loginListener.loginError(message);
}
public void fireLoginCanceled() {
//write cancel login logic here
loginListener.loginCanceled();
}
@Override
protected IStatus run(IProgressMonitor monitor) {
login();
return Status.OK_STATUS;
}
public boolean login() {
fireLoginStarted();
if (//網絡連接失敗) {
fireLoginError(Messages.getString("Session.connectionFailed"));
} else {
if (//登錄失敗) {
fireLoginError(Messages.getString("Session.loginFailed"));
} else {
session.setAuthenticated(true);
fireLoginComplete();
//處理登錄動作
}
}
return session.isAuthenticated();
}
}
LoginDialog:
這裏用到了StackLayout,因爲在登錄的過程中,需要在顯示用戶名/密碼的位置上,顯示gif動畫,所以在createDialogArea的時候,要創建一個主Composite,然後將其layout設置爲StackLayout,然後創建兩個Composite,將其parent都設置爲主Composite,新創建的兩個我將其命名爲loginInfoComposite和loginAnimaComposite,顧名思義,一個用來顯示登錄信息,一個用來顯示登錄動畫。
關於如何顯示gif,我在這裏就不多說了,因爲SWT Snippet和Eclipse的SWT Example裏面都有對應的例子,我在這裏推薦大家去參考一下SWT Example,因爲那裏面是用Canvas來繪圖的,這也是我們所需要的。
在使用StackLayout的時候要注意,當我們使用stackLayout.topControl = xxx的時候,還要調用stackLayout.layout()方法,否則會不起作用。
還有就是因爲在登錄的過程中,按鈕欄應該是不可見的,但是Dialog的getButtonBar方法是protected的,所以就重寫了這個方法,聲明爲public,返回super.getButtonBar(),雖然源碼的註釋中寫着這個方法不應該重寫,但是我想,這樣子應該沒問題吧。
另外,在繪製gif的下方添加一個按鈕,並且addSelectionListener,當SelectionEvent發生的時候,就去觸發loginAction的fireCancel方法就可以了。
細節就不描述了,下面是一些個人認爲比較關鍵的代碼片段:
* to create login button
*/
public static int LOGIN_ID = 9527;
createButton(parent, LOGIN_ID, Messages
.getString("LoginDialog.loginbutton"), true); ]
createButton(parent, IDialogConstants.CANCEL_ID, Messages
.getString("LoginDialog.cancelbutton"), false);
}
protected void buttonPressed(int buttonId) {
if (buttonId == LOGIN_ID) {
loginPressed();
}
super.buttonPressed(buttonId);
}
//...
loginAction.schedule();
}
然後是LoginListener的實現類:
private Display display;
//login dialog
private TestLoginDialog dialog;
//image to show on login failed
private Image errorMessageImage = AbstractUIPlugin
.imageDescriptorFromPlugin(Application.PLUGIN_ID,
IImageKeys.crodoTitleImage).createImage();
//error message area background
private Color errorMessageBackground = new Color(null, 255, 255, 0);
public LoginListenerImpl(TestLoginDialog dialog) {
this.dialog = dialog;
display = Display.getCurrent();
}
//因爲這裏需要在非UI線程中更新UI,所以要用display.syncExec()方法。
public void loginCanceled() {
display.syncExec(new Runnable() {
public void run() {
dialog.getStackLayout().topControl = dialog
.getLoginInfoComposite();
dialog.getStackLayoutComposite().layout();
dialog.animate();
dialog.getButtonBar().setVisible(true);
}
});
}
public void loginComplete() {
display.syncExec(new Runnable() {
@SuppressWarnings("deprecation")
public void run() {
//我知道Thread.stop()方法已經被廢棄,但是暫時沒想到什麼方法來中止
//就暫時這樣子用了,還請大家指教!
dialog.getAnimateThread().stop();
dialog.okPressed();
}
});
}
public void loginError(final String message) {
display.syncExec(new Runnable() {
public void run() {
dialog.getErrorMessageLabel().setText(message);
dialog.getErrorMessageLabel().setImage(errorMessageImage);
dialog.getErrorMessageLabel().setBackground(
errorMessageBackground);
dialog.getStackLayout().topControl = dialog
.getLoginInfoComposite();
dialog.getStackLayoutComposite().layout();
dialog.animate();
dialog.getButtonBar().setVisible(true);
}
});
}
public void loginStarted() {
display.syncExec(new Runnable() {
public void run() {
dialog.getStackLayout().topControl = dialog
.getLoginAnimaComposite();
dialog.getStackLayoutComposite().layout();
dialog.animate();
dialog.getButtonBar().setVisible(false);
}
});
}