天天看点

CDT之扩展Debug视图CDT之扩展Debug视图

CDT之扩展Debug视图

IModelProxy是何时被创建的

Launch是最顶端的调试模型,一个new Launch会被添加到launchManager,launchManager是Debug视图的input对象

public class LaunchConfiguration {
    public ILaunch launch() {	// 启动Launch时由Eclipse平台调用
        launch = delegate2.getLaunch(this, mode);	// 从delegate对象拿到launch实例
        getLaunchManager().addLaunch(launch);	// 把Launch实例添加到Manager,这会触发事件
    }
}
           

当一个launch对象被add到launchManager中时,launchManager会通知所有对该add事件感兴趣的对象,其中包含launchManager的LaunchManagerProxy对象

public class LaunchManager {
	public void addLaunch(ILaunch launch) {
		fireUpdate(new ILaunch[] {launch}, ADDED); // 此处会通知到LaunchManagerProxy
	}
    
    public void notify(ILaunch[] launches, int update) {
        // 循环异步通知每一个LaunchListener,此处会通知到LaunchManagerProxy
        for (ILaunchesListener iLaunchesListener : fLaunchesListeners) {
            fListener = iLaunchesListener;
            SafeRunner.run(this);
        }
    }
}
           

LaunchManagerProxy会为该add事件创建一个ModelDelta对象,ModelDelta描述了相关model的增量变化内容(此处为新增一个node,并且标记为ADDED和INSTALL),LaunchManagerProxy会将ModelDelta通知出去

public class LaunchManagerProxy {
	public void launchesAdded(ILaunch[] launches) {
        //将Launch这个模型被添加的信息发布出去
		fireDelta(launches, IModelDelta.ADDED | IModelDelta.INSTALL);
	}
    // fLaunchManager是Debug视图的最顶层model
    protected void fireDelta(ILaunch[] launches, int launchFlags) {
		ModelDelta delta = new ModelDelta(fLaunchManager, IModelDelta.NO_CHANGE);
		for (int i = 0; i < launches.length; i++) {
            //新启动的Launch就是fLaunchManager的一个子节点
			delta.addNode(launches[i], launchFlags);
		}
		fireModelChanged(delta); // 只发布模型的增量部分事件
	}
    public void fireModelChanged(IModelDelta delta) {
		final IModelDelta root = getRootDelta(delta);
        // 会通知到对Launch模型改变感兴趣的TreeModelContentProvider
		for (IModelChangedListener iModelChangedListener : getListeners()) {
			final IModelChangedListener listener = iModelChangedListener;
			ISafeRunnable safeRunnable = new ISafeRunnable() {
				@Override
				public void handleException(Throwable exception) {
					DebugUIPlugin.log(exception);
				}
				@Override
				public void run() throws Exception {
                    // 会通知到对LaunchManager模型改变感兴趣的TreeModelContentProvider,
                    // 并且说明是哪个modelProxy生成delta
					listener.modelChanged(root, AbstractModelProxy.this);
				}

			};
			SafeRunner.run(safeRunnable);
		}
	}
}

           

注:上述ModelDelta的描述

CDT之扩展Debug视图CDT之扩展Debug视图

debug视图中的TreeModelContentProvider对象得知ModelDelta后,会对LaunchManager的改变做出处理,对子node的ADDED标志和INSTALL标志做出不同的处理。

ADDED:表示该模型被添加,此时会调用ElementContentProvider中的update

INSTALL:此时会生成Launch的modelProxy对象,然后Debug视图把自己注册到modelProxy中的监听列表中,然后调用proxy的initialize()(或init()和installed()方法),在installed是就可以自由的向viewer注册感兴趣的事件,比如该model节点对双击感兴趣,那么就可以在installed里加上。

一个Launch对应一个ModelProxy,ModelProxy主要用来代替Model处理事件、维护对该Model感兴趣的监听器,以及生成合适的delta

public class TreeModelContentProvider {
	protected void updateNodes(IModelDelta[] nodes, int mask) {
		for (int i = 0; i < nodes.length; i++) {
			IModelDelta node = nodes[i];
			int flags = node.getFlags() & mask;
			if (flags != 0) {
				if ((flags & IModelDelta.ADDED) != 0) {
					handleAdd(node);
				}
				if ((flags & IModelDelta.REMOVED) != 0) {
					handleRemove(node);
				}
                // 触发新模型也就是新建的Launch模型的安装
				if ((flags & IModelDelta.INSTALL) != 0) {
					handleInstall(node);
				}
            }
        }
    }
    
    private void installModelProxy(Object input, TreePath path) {
        //TreeModelContentProvider的根input是fLaunchManager
        //从Launch模型关联的AdapterFactory中拿到IModelProxyFactory实例
        IModelProxyFactory modelProxyFactory = ViewerAdapterService.getModelProxyFactory(element);
        if (modelProxyFactory != null) {
            proxy = modelProxyFactory.createModelProxy(element, getPresentationContext());
            if (proxy != null) {
                fModelProxies.put(element, proxy);
            }
        }
        //debug视图的TreeModelContentProvider会把自己添加到launch的modelProxy中
        proxy.addModelChangedListener(this);
        //modelProxy初始化在这里
		((IModelProxy2)proxy).initialize(getViewer());
    }
}