[rcp系列]用RCP实现MSN风格的登录窗口 (转)

需要以下的对象:
LoginDialog,用于展示状态,
LoginListener,用于监听登录状态,并根据不同的情况改变LoginDialog的显示
LoginAction,用于执行登录的业务逻辑,并且根据不同的结果来fire不同的动作。

状态一共有以下几种:
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  ( //网络连接失败) {
           
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 ;


     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的实现类:

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()方法已经被废弃,但是暂时没想到什么方法来中止
                //就暂时这样子用了,还请大家指教!
                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 );
            }
        });
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值