`
bmqnc
  • 浏览: 127540 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

eclipse 的redo undo功能中operation history的dispose函数分析

    博客分类:
  • java
阅读更多
原来是做一个类似清空回收站的功能。
即在回收站中清除某个节点后必须将该节点对应的redo undo操作删除,即从操作历史堆栈中将对应的记录删除。

开始觉得operation history的dispose函数可能能实现这样的功能,看代码的注解说当operation的context与指定的context相符合时从操作堆栈删除记录,后半句关于引用的那句话一开始没看懂。

于是自定义了CustomUndoContext,然后利用dispose函数过滤,但是好像并没有删除。

于是看这部分的源代码,如下:
public void dispose(IUndoContext context, boolean flushUndo,
			boolean flushRedo, boolean flushContext) {
		// dispose of any limit that was set for the context if it is not to be
		// used again.
		if (flushContext) {
			if (DEBUG_OPERATION_HISTORY_DISPOSE) {
				Tracing.printTrace("OPERATIONHISTORY", "Flushing context " //$NON-NLS-1$//$NON-NLS-2$
						+ context);
			}
			flushUndo(context);
			flushRedo(context);
			limits.remove(context);
			return;
		}
		if (flushUndo) {
			flushUndo(context);
		}
		if (flushRedo) {
			flushRedo(context);
		}

	}


里面调用了flushUndo与flushRedo,拿flushUndo作为例子来说,继续看flushUndo的代码:
private void flushUndo(IUndoContext context) {
		if (DEBUG_OPERATION_HISTORY_DISPOSE) {
			Tracing.printTrace("OPERATIONHISTORY", "Flushing undo history for " //$NON-NLS-1$ //$NON-NLS-2$
					+ context);
		}

		// Get all operations that have the context (or one that matches)
		Object[] filtered = filter(undoList, context);
		for (int i = 0; i < filtered.length; i++) {
			IUndoableOperation operation = (IUndoableOperation) filtered[i];
			if (context == GLOBAL_UNDO_CONTEXT
					|| operation.getContexts().length == 1) {
				// remove the operation if it only has the context or we are
				// flushing all
				undoList.remove(operation);
				internalRemove(operation);
			} else {
				// remove the reference to the context.
				// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=161786
				// It is not enough to simply remove the context. There could
				// be one or more contexts that match the one we are trying to
				// dispose.
				IUndoContext[] contexts = operation.getContexts();
				for (int j = 0; j < contexts.length; j++) {
					if (contexts[j].matches(context)) {
						operation.removeContext(contexts[j]);
					}
				}
				if (operation.getContexts().length == 0) {
					undoList.remove(operation);
					internalRemove(operation);
				}
			}
		}
				ICompositeOperation endedComposite = null;
		synchronized (openCompositeLock) {
			if (openComposite != null) {
				if (openComposite.hasContext(context)) {
					if (context == GLOBAL_UNDO_CONTEXT
							|| openComposite.getContexts().length == 1) {
						endedComposite = openComposite;
						openComposite = null;
					} else {
						openComposite.removeContext(context);
					}
				}
			}
		}
		// notify outside of the synchronized block.
		if (endedComposite != null) {
			notifyNotOK(endedComposite);
		}
	}


这里应该好好看看,if-else中说出了原来注解后半句话的意思。原来在operation中有多个context的情况下,如果该operation中含有指定的context,如果operation的context中只有唯一的该context,则才将operation从操作历史记录删除。而context有多个时,只是在operation的context中将指定的该context移除。

继续跟进filter函数:
private IUndoableOperation[] filter(List list, IUndoContext context) {
     List filtered = new ArrayList();
		Iterator iterator = list.iterator();
		synchronized (undoRedoHistoryLock) {
			while (iterator.hasNext()) {
				IUndoableOperation operation = (IUndoableOperation) iterator
						.next();
				if (operation.hasContext(context)) {
					filtered.add(operation);
				}
			}
		}
		return (IUndoableOperation[]) filtered
				.toArray(new IUndoableOperation[filtered.size()]);
	}


filter函数无非是遍历操作历史堆栈,看各个operation是否包含指定的context。operation是否包含这里用到了hasContext方法,实际上调用的是operation中的contexts(是个list)的逐项比较。

注意,以上源代码分析基于DefaultOperationHistory和AbstractOperation类。

这样,实现回收站删除相应节点对应的历史记录的代码为:
//在操作栈中删除对应的历史记录
				IWorkbench workbench = getSite().getWorkbenchWindow().getWorkbench();
				IUndoContext context=StudioView.getCustomUndoContext(studio.getName());
				IOperationHistory operationHistory=workbench.getOperationSupport().getOperationHistory();
				IUndoableOperation[] operations=operationHistory.getUndoHistory(context);
				for(IUndoableOperation operation:operations){
					IUndoContext[] undoContexts=operation.getContexts();
					for(IUndoContext undoContext:undoContexts){
						if(!undoContext.matches(context)){
							operation.removeContext(undoContext);
						}
					}
				}
				workbench.getOperationSupport().getOperationHistory().
				dispose(context, true, true, true);


这样做有点暴力,但至少功能实现了。做法是:先获取满足指定的context的operation,然后在将operation中除该指定的context除外的context移除,然后调用dispose函数就能实现相应的功能。

最后,总结一下IBM的代码,个人觉得IBM程序员写出来的代码没什么特别的,有些地方效率未必很高,我觉得我很他们在写代码的差距上不大,或者我觉得没什么差距。我现在发现优秀的软件之所以优秀主要是在于软件的架构。突然想起了微软的.NET之父,当初ms将其从Borland挖过来的时候就花了不少钱,那个丹麦人软件架构能力确实很厉害。据说微软从不缺底层写代码的优秀程序员,而高层的架构师微软是将其作为人才极力挽留的。Got it!
分享到:
评论

相关推荐

    C#做的简单的Undo、Redo功能的实现

    在编程领域,撤销(Undo)和重做(Redo)功能是用户界面中常见的操作,它们允许用户取消或恢复最近的更改。在C#中,我们可以利用.NET框架提供的事件驱动和面向对象特性来实现这样的功能。这篇实验主要探讨了如何在...

    redo undo framework source code

    在IT行业中,"redo undo"框架是用于实现撤销/重做功能的核心技术,常见于各种软件和应用程序中,如文本编辑器、图像处理软件、数据库系统等。它允许用户取消最近的操作并恢复先前的状态,提供了对用户交互的强大支持...

    ORACLE redo undo.docx

    Oracle redo undo 是 Oracle 数据库中的一种机制,用于确保事务的可恢复性和撤销性。下面是对 redo undo 机制的详细解释。 redo 机制 redo 机制是 Oracle 数据库中的一种机制,用于记录事务的所有操作,以便在...

    QT撤消操作(undo/redo)例子

    本工程用vs2008打开,但需要qt库的支持,需要先安装qt-in-vs2008,才可通过编译。或者直接将里面的代码拷贝出来,然后在自己的环境中编译也行。代码中应用了QUndoCommand来实现撤销与反撤销操作。

    实现Redo Undo的一个简单实例,包含源码

    在IT行业中,"Redo"和"Undo"功能是用户界面设计中的重要组成部分,尤其是在文本编辑器、图形编辑软件或任何允许用户进行可逆操作的应用程序中。它们为用户提供了一种方便的方式来撤销或恢复之前的改动,增加了用户...

    C# undo\redo框架

    在C#中实现这样的框架可以帮助开发者更轻松地为各种编辑控件(如TextBox、RichTextBox、ComboBox等)添加这类功能。本文将深入探讨“C# undo/redo框架”的核心概念、设计模式以及如何实现。 1. **命令模式**: ...

    C#实现的undo/redo的window窗体

    针对一个window窗体实现了undo/redo功能,包括textBox,checkBox, listBox, comboBox, radioButton以及按钮焦点变化的实现。可能有些小bug思路仅供参考。完整的工程文件,VS打开即可运行,欢迎评论~ 详细说明参见...

    Oracle_Undo与Redo的通俗

    Oracle中的Undo和Redo是两个非常重要的概念,它们都是Oracle数据库中事务管理和恢复机制的关键组件。Undo和Redo都是为了确保数据库的一致性和可靠性。 什么是REDO? REDO记录transaction logs,分为online和...

    undo redo 原型设计

    cpp文件 undo redo 原型设计 部分代码 class Command { public: virtual BOOL UnDo() = 0; virtual BOOL ReDo() = 0; };

    GIS软件中undo与redo的设计与实现

    本文深入分析了GIS软件中Undo与Redo操作的设计与实现,其主要内容包括Undo与Redo操作的原理、机制、流程以及实现方法。 1. Undo与Redo操作的原理: Undo与Redo操作是基于命令模式实现的。在这种模式下,每次用户...

    多步Undo_Redo的实现

    在本篇文章中,我们将深入探讨如何在MFC(Microsoft Foundation Classes)框架下的绘图程序中实现多步Undo/Redo功能。 #### 二、基础知识回顾 在讨论具体实现之前,我们先简要回顾一下Undo/Redo的基本概念: - **...

    撤消操作(undo/redo)

    在编程领域,撤销/重做(Undo/Redo)功能是许多应用程序不可或缺的一部分,它允许用户取消或恢复之前的操作。在Qt框架中,Qt提供了一种高效且灵活的方式来实现这一功能,那就是通过QUndoCommand类。QUndoCommand是Qt...

    oracle_redo_undo

    Oracle 中的 redo 和 undo 机制是数据库的核心组件,它们一起协作以确保数据库的事务一致性和可靠性。在本文中,我们将深入探讨 redo 和 undo 机制的工作原理和协作机制。 Undo Mechanism Undo 机制是 Oracle 中的...

    mfc support redo/undo

    本文将深入探讨如何在MFC应用中实现撤销(Undo)和重做(Redo)功能,这对于任何具有用户交互性的软件都是至关重要的特性。 撤销/重做功能是许多应用程序的标准组成部分,允许用户取消他们的最近操作,并在需要时...

    今年实习做的MFC画图程序(实现了undo redo功能)

    在本项目中,“今年实习做的MFC画图程序(实现了undo redo功能)”,我们可以看到实习生使用MFC框架开发了一个具有撤销/重做功能的图形绘制应用。 撤销/重做功能在许多软件中都是一个重要的用户交互特性,它允许...

    Simple Undo/redo library for C#/.NET

    在.NET框架和C#编程中,撤销/重做(Undo/Redo)功能是一个常见的需求,特别是在那些允许用户进行多步操作的应用程序中,如文本编辑器、绘图软件或数据库管理系统。一个“Simple Undo/redo library for C#/.NET”就是...

    Undo_Redo机制在CAD中的应用

    Undo_Redo机制在CAD中的应用, 摘要:为了增强CAD系统的灵活性,提高设计的效率,本文引入设计模式概念,通过对数据对象的持久化.设计出一套支 持无限Undo/Redo和批量化操作的CAD图形绘制系统,文章介绍了各模块的...

    Arcgis Engine Undo和Redo 功能实现

    在ArcGIS Engine中,撤销(Undo)和重做(Redo)功能是用户交互中不可或缺的部分,尤其在编辑地理数据时。这两个功能允许用户在错误操作后恢复到之前的正确状态,提供了对数据编辑过程的控制。 在提供的代码片段中...

    oracle的undo与redo

    在Oracle中,日志文件发挥着关键作用,其中Undo日志和Redo日志是最核心的两种日志类型。 Undo日志,也称为撤销日志,主要用于事务处理中。它的主要作用是记录事务执行之前的数据库状态,即数据块在被修改之前的所有...

Global site tag (gtag.js) - Google Analytics