Azureus源码剖析(五)

      这篇说说GUI方面,就以打开种子文件这个窗口为例,我对其代码进行了精简,拿出了一个基本的骨架。

 

首先来看基本的消息主循环部分:

     final  Display display  =   new  Display();
        invoke(
null ); // 创建窗口的主代码
    
        
while  (stTorrentWindow  !=   null   &&   ! stTorrentWindow.bClosed)
        {
// 窗口创建完成且没有关闭
             if  ( ! display.readAndDispatch())
            {
                display.sleep();
            }
        }
        display.dispose();

 

这里运用了单例模式来表示窗口,考虑到线程同步性,在静态工厂方法中使用了synchronized 关键字

private   static  TorrentWindow stTorrentWindow  =   null ;

    
public   synchronized   static   final   void  invoke(Shell parent)
    {
        
if  (stTorrentWindow  ==   null )
        {
// 第一次创建窗口
            stTorrentWindow  =   new  TorrentWindow(parent);
        }
        
else
        {
// 激活已经创建的窗口
             if  (stTorrentWindow.shell  !=   null )
            {
                stTorrentWindow.shell.forceActive();
            }
        }
    }
    
private  TorrentWindow( final  Shell parent)
    {
        openWindow(parent);
    }

 

      真正的窗口创建工作是在openWindow方法中完成的,下面给出部分核心代码:

private   void  openWindow(Shell parent)
    {
        GridData gridData;
        
        shell 
=  ShellFactory.createShell(parent, SWT.RESIZE  |  SWT.DIALOG_TRIM);
        shell.setText(
" 打开 Torrent " );
        
        GridLayout layout 
=   new  GridLayout();
        shell.setLayout(layout);
        shell.addListener(SWT.Resize, 
new  Listener()
        {
            
public   void  handleEvent(Event e) {
                    
            }
        });
        
//  Torrents
        
//  ========

        Composite cButtons 
=   new  Composite(shell, SWT.NONE);
        RowLayout rLayout 
=   new  RowLayout(SWT.HORIZONTAL);
        rLayout.marginBottom 
=   0 ;
        rLayout.marginLeft 
=   0 ;
        rLayout.marginRight 
=   0 ;
        rLayout.marginTop 
=   0 ;
        cButtons.setLayout(rLayout);
        
        
//  Buttons for tableTorrents
        Button browseTorrent  =   new  Button(cButtons, SWT.PUSH);
        browseTorrent.setText(
" 添加文件 " );
        browseTorrent.addListener(SWT.Selection, 
new  Listener(){
            
public   void  handleEvent(Event arg0) {
                FileDialog fDialog 
=   new  FileDialog(shell, SWT.OPEN  |  SWT.MULTI);
                fDialog.setFilterExtensions(
new  String[]{
                        
" *.torrent " ,
                        
" *.tor " ,
                        FILE_WILDCARD
                });
                fDialog.setFilterNames(
new  String[]{
                        
" *.torrent " ,
                        
" *.tor " ,
                        FILE_WILDCARD
                });
                fDialog.setText(
" 选择 Torrent文件 " );
                String fileName 
=  fDialog.open();
                
if  (fileName  !=   null )
                {
                    
// addTorrents(fDialog.getFilterPath(), fDialog.getFileNames());
                }
            }
        });
        setGridData(cButtons, GridData.FILL_HORIZONTAL, browseTorrent, MIN_BUTTON_HEIGHT);
        
        Button browseURL 
=   new  Button(cButtons, SWT.PUSH);
        browseURL.setText(
" 从URL添加 " );
        browseURL.addListener(SWT.Selection, 
new  Listener(){
            
public   void  handleEvent(Event e) {
                browseURL();
            }
        });
        
        Button browseFolder 
=   new  Button(cButtons, SWT.PUSH);
        browseFolder.setText(
" 从文件夹添加 " );
        browseFolder.addListener(SWT.Selection, 
new  Listener(){
            
public   void  handleEvent(Event e)
            {
                DirectoryDialog fDialog 
=   new  DirectoryDialog(shell, SWT.NULL);
                fDialog.setMessage(
" 选择 Torrent 文件所在目录 " );
                String path 
=  fDialog.open();
                
if  (path  !=   null )
                {
                    addTorrents(path, 
null );
                }
            }
        });
        
        Group gTorrentsArea 
=   new  Group(shell, SWT.NONE);
        gridData 
=   new  GridData(GridData.FILL_HORIZONTAL);
        gTorrentsArea.setLayoutData(gridData);
        layout 
=   new  GridLayout();
        gTorrentsArea.setLayout(layout);
        gTorrentsArea.setText(
" Torrent文件 " );
        
        Composite cTorrentList 
=   new  Composite(gTorrentsArea, SWT.NONE);
        gridData 
=   new  GridData(GridData.FILL_HORIZONTAL);
        cTorrentList.setLayoutData(gridData);
        createTorrentListArea(cTorrentList);
        
// 关闭窗口
        shell.addDisposeListener( new  DisposeListener() 
        {
            
public   void  widgetDisposed(DisposeEvent e)
            {
                
if  ( ! bClosed)
                    close(
false true );
            }
        });

        shell.addListener(SWT.Traverse, 
new  Listener() 
        {
            
public   void  handleEvent(Event e) 
            {
                
if  (e.detail  ==  SWT.TRAVERSE_ESCAPE) 
                {
                    close(
true true );
                }
            }
        });
        shell.open();
// 显示窗口
    }

 

这里最重要的如何创建Shell的:

 

shell  =  ShellFactory.createShell(parent, SWT.RESIZE  |  SWT.DIALOG_TRIM);

 

下面就来看看ShellFactory的代码,主要是在ShellManager中加入新创建的Shell,如果此Shell已经创建过,则不再次加入

public   final   class  ShellFactory 
{
    
public   static  Shell createShell( final  Shell parent,  final   int  styles)
    {
        
return  getRegistedShell( new  Shell(parent, styles));
    }
    
private   static  Shell getRegistedShell( final  Shell toRegister)
    {
        
if  ( null   ==  toRegister)
            
return   null ;
        ShellManager.sharedManager().addWindow(toRegister);
        
return  toRegister;
    }
}

      最后来看ShellManager是如何管理Shell的:

 

public   class  ShellManager
{
    
private   static  ShellManager instance;

    
private   final  Collection shells  =   new  ArrayList(); // 被管理的Shell
     private   final  List addHandlers  =   new  LinkedList(); // 加入Shell时调用
     private   final  List removeHandlers  =   new  LinkedList(); // 删除Shell时调用

    
static
    {
        instance 
=   new  ShellManager();
    }

    
/**
     * <p>Gets the application's shared shell manager</p>
     * <p>This ShellManager has no bearing on other ShellManager instances</p>
     * <p><b>Note</b>: This method must be invoked by the SWT display thread</p>
     * 
@return
     
*/
    
public   static   final  ShellManager sharedManager()
    {
// 静态工厂方法
         return  instance;
    }

    
public   static   boolean  verifyShellRect(Shell shell,  boolean  bAdjustIfInvalid) 
    {
// 验证窗口矩阵的合法性
         boolean  bMetricsOk;
        
try  {
            bMetricsOk 
=   false ;
            Point ptTopLeft 
=  shell.getLocation();

            Monitor[] monitors 
=  shell.getDisplay().getMonitors();
            
for  ( int  j  =   0 ; j  <  monitors.length  &&   ! bMetricsOk; j ++ ) {
                Rectangle bounds 
=  monitors[j].getBounds();
                bMetricsOk 
=  bounds.contains(ptTopLeft);
            }
        } 
catch  (NoSuchMethodError e) {
            Rectangle bounds 
=  shell.getDisplay().getBounds();
            bMetricsOk 
=  shell.getBounds().intersects(bounds);
        }
        
if  ( ! bMetricsOk  &&  bAdjustIfInvalid) {
            centreWindow(shell);
        }
        
return  bMetricsOk;
    }
    
    
public   static   void  centreWindow(Shell shell)
    {
// 窗口居中
        Rectangle displayArea;  //  area to center in
         try  {
            displayArea 
=  shell.getMonitor().getClientArea();
        } 
catch  (NoSuchMethodError e) {
            displayArea 
=  shell.getDisplay().getClientArea();
        }

        Rectangle shellRect 
=  shell.getBounds();

        
if  (shellRect.height  >  displayArea.height) {
            shellRect.height 
=  displayArea.height;
        }
        
if  (shellRect.width  >  displayArea.width  -   50 ) {
            shellRect.width 
=  displayArea.width;
        }

        shellRect.x 
=  displayArea.x  +  (displayArea.width  -  shellRect.width)  /   2 ;
        shellRect.y 
=  displayArea.y  +  (displayArea.height  -  shellRect.height)  /   2 ;

        shell.setBounds(shellRect);
    }
    
/**
     * Adds a shell to the shell manager. If the shell is already managed, it is not added again.
     * <p><b>Note</b>: This method must be invoked by the SWT display thread</p>
     * 
@param  shell A SWT Shell
     
*/
    
public   final   void  addWindow( final  Shell shell)
    {
// 加入新窗口
        
// Debug.out("Invoked by thread " + Thread.currentThread().getName());
         if (shells.contains(shell)) { return ;}

        shells.add(shell);
        notifyAddListeners(shell);
        shell.addDisposeListener(
new  DisposeListener()
        {
            
public   void  widgetDisposed(DisposeEvent event)
            {
                
try  
                {
                    removeWindow(shell);
                } 
                
catch  (Exception e)
                {
                    
// Logger.log(new LogEvent(LogIDs.GUI, "removeWindow", e));
                }
            }
        });
        shell.addListener(SWT.Show, 
new  Listener() 
        {
            
public   void  handleEvent(Event event) 
            {
                verifyShellRect(shell, 
false );
            }
        });
    }

    
/**
     * Removes a shell from the shell manager
     * <p><b>Note</b>: This method must be invoked by the SWT display thread</p>
     * 
@param  shell A SWT Shell
     
*/
    
public   final   void  removeWindow(Shell shell)
    {
// 删除窗口
        shells.remove(shell);
        notifyRemoveListeners(shell);
    }

    
/**
     * <p>Gets the shells managed by the manager as an Iterator</p>
     * <p>The order in which the shells were added are retained.</p>
     * <p><b>Note</b>: This method must be invoked by the SWT display thread</p>
     * 
@return  The iterator
     
*/
    
public   final  Iterator getWindows()
    {
        
return  shells.iterator();
    }

    
/**
     * Gets whether the ShellManager manages no shells
     * 
@return  True if ShellManager is empty
     
*/
    
public   final   boolean  isEmpty()
    {
        
return  shells.isEmpty();
    }

    
/**
     * Gets the number of shells the ShellManager manages
     * 
@return  The number
     
*/
    
public   final   int  getSize()
    {
        
return  shells.size();
    }

    
/**
     * <p>Invokes the handleEvent method specified by the SWT listener for each managed shell</p>
     * <p>The event's widget is set to the reference of the shell invoking it</p>
     * 
@param  command A command implemented as a SWT Listener
     
*/
    
public   final   void  performForShells( final  Listener command)
    {
        Iterator iter 
=  shells.iterator();
        
for ( int  i  =   0 ; i  <  shells.size(); i ++ )
        {
            Shell aShell 
=  (Shell)iter.next();
            Event evt 
=   new  Event();
            evt.widget 
=  aShell;
            evt.data 
=   this ;
            command.handleEvent(evt);
        }
    }

    
/**
     * Gets the set of managed shells
     * 
@return  The set
     
*/
    
protected   final  Collection getManagedShellSet()
    {
        
return  shells;
    }

    
//  events

    
/**
     * <p>Adds a listener that will be invoked when a shell has been added to the ShellManager</p>
     * <p>The listener and the shell will automatically be removed when the shell is disposed</p>
     * 
@param  listener A SWT Listener
     
*/
    
public   final   void  addWindowAddedListener(Listener listener)
    {
        addHandlers.add(listener);
    }

    
/**
     * Removes a listener that will be invoked when a shell has been added to the ShellManager
     * 
@param  listener A SWT Listener
     
*/
    
public   final   void  removeWindowAddedListener(Listener listener)
    {
        addHandlers.remove(listener);
    }

    
/**
     * Adds a listener that will be invoked when a shell has been removed from the ShellManager
     * 
@param  listener A SWT Listener
     
*/
    
public   final   void  addWindowRemovedListener(Listener listener)
    {
        removeHandlers.add(listener);
    }

    
/**
     * Removes a listener that will be invoked when a shell has been removed from the ShellManager
     * 
@param  listener A SWT Listener
     
*/
    
public   final   void  removeWindowRemovedListener(Listener listener)
    {
        removeHandlers.remove(listener);
    }

    
/**
     * Notifies the WindowAddedListener handlers
     * 
@param  sender A SWT shell that "sends" the events
     
*/
    
protected   final   void  notifyAddListeners(Shell sender)
    {
        Iterator iter 
=  addHandlers.iterator();
        
for ( int  i  =   0 ; i  <  addHandlers.size(); i ++ )
        {
            ((Listener)iter.next()).handleEvent(getSWTEvent(sender));
        }
    }

    
/**
     * Notifies the WindowRemovedListener handlers
     * 
@param  sender A SWT shell that "sends" the events
     
*/
    
protected   final   void  notifyRemoveListeners(Shell sender)
    {
        Iterator iter 
=  removeHandlers.iterator();
        
for ( int  i  =   0 ; i  <  removeHandlers.size(); i ++ )
        {
            ((Listener)iter.next()).handleEvent(getSWTEvent(sender));
        }
    }
    
/**
     * <p>Gets a generated SWT Event based on the shell</p>
     * <p>The widget field of the event should be set to the shell</p>
     * 
@param  shell A SWT Shell
     * 
@return  The event
     
*/
    
protected  Event getSWTEvent(Shell shell)
    {
        Event e 
=   new  Event();
        e.widget 
=  shell;
        e.item 
=  shell;
        
return  e;
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值