需要以下的對象:
LoginDialog,用于展示狀態(tài),
LoginListener,用于監(jiān)聽登錄狀態(tài),并根據(jù)不同的情況改變LoginDialog的顯示
LoginAction,用于執(zhí)行登錄的業(yè)務邏輯,并且根據(jù)不同的結果來fire不同的動作。
狀態(tài)一共有以下幾種:
1。登錄中
2。登錄成功
3。登錄失敗
? 3.1 連接失敗
? 3.2 用戶名密碼錯誤
? 3.3 .....
4。用戶取消登錄
下面是代碼片段:
Application;
public?class?Application?implements?IPlatformRunnable?{
? ???
????/*
?????*?(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?interface?LoginListener?extends?EventListener{
????public?void?loginError(String?message);
????public?void?loginComplete();
????public?void?loginCanceled();
????
????public?void?loginStarted();
????
}
LoginAction:這里要用到Job,因為登錄的邏輯處理必須要在異步線程中來做,否則UI就會停住的。
public?class?LoginAction?extends?Job?{
????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?(//網(wǎng)絡連接失敗)?{
??????????? fireLoginError(Messages.getString("Session.connectionFailed"));
????????}?else?{
????????????if?(//登錄失敗)?{
??????????? fireLoginError(Messages.getString("Session.loginFailed"));
????????????}?else?{
????????????????session.setAuthenticated(true);
????????????????fireLoginComplete();
??? ??? ??? ??? //處理登錄動作
????????????}
????????}
????????return?session.isAuthenticated();
????}
}
LoginDialog:
這里用到了StackLayout,因為在登錄的過程中,需要在顯示用戶名/密碼的位置上,顯示gif動畫,所以在createDialogArea的時候,要創(chuàng)建一個主Composite,然后將其layout設置為StackLayout,然后創(chuàng)建兩個Composite,將其parent都設置為主Composite,新創(chuàng)建的兩個我將其命名為loginInfoComposite和loginAnimaComposite,顧名思義,一個用來顯示登錄信息,一個用來顯示登錄動畫。
關于如何顯示gif,我在這里就不多說了,因為SWT Snippet和Eclipse的SWT Example里面都有對應的例子,我在這里推薦大家去參考一下SWT Example,因為那里面是用Canvas來繪圖的,這也是我們所需要的。
在使用StackLayout的時候要注意,當我們使用stackLayout.topControl = xxx的時候,還要調(diào)用stackLayout.layout()方法,否則會不起作用。
還有就是因為在登錄的過程中,按鈕欄應該是不可見的,但是Dialog的getButtonBar方法是protected的,所以就重寫了這個方法,聲明為public,返回super.getButtonBar(),雖然源碼的注釋中寫著這個方法不應該重寫,但是我想,這樣子應該沒問題吧。
另外,在繪制gif的下方添加一個按鈕,并且addSelectionListener,當SelectionEvent發(fā)生的時候,就去觸發(fā)loginAction的fireCancel方法就可以了。
細節(jié)就不描述了,下面是一些個人認為比較關鍵的代碼片段:
????/*
?????*?to?create?login?button?
?????*/
????public?static?int?LOGIN_ID?=?9527;
????protected?void?createButtonsForButtonBar(Composite?parent)?{
????????createButton(parent,?LOGIN_ID,?Messages
????????????????.getString("LoginDialog.loginbutton"),?true);?]
????????createButton(parent,?IDialogConstants.CANCEL_ID,?Messages
????????????????.getString("LoginDialog.cancelbutton"),?false);
????}
????@Override
????protected?void?buttonPressed(int?buttonId)?{
????????if?(buttonId?==?LOGIN_ID)?{
????????????loginPressed();
????????}
????????super.buttonPressed(buttonId);
????}
??? protected?void?loginPressed()?{
??? ??? //...
????????loginAction.schedule();
????}
然后是LoginListener的實現(xiàn)類:
public?class?LoginListenerImpl?implements?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()方法已經(jīng)被廢棄,但是暫時沒想到什么方法來中止
??? ??? ??? ??? //就暫時這樣子用了,還請大家指教!
????????????????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);
????????????}
????????});
????}