Delphi深度探索-To do list的增强


  Delphi 5在IDE中还引入了新的特性: To-Do item和To-Do list。To-Do item 描述了项目中的一个需要完成的编码任务。它相当于一个备忘录提醒你不要忘记打算作的事情。一个To-Do item包括描述,优先级,负责人和分类。To-Do item被记录在源代码中,以TODO关键词注释。To-Do list相当于项目中所有的To-Do item的列表管理器,可以用来很方便的察看所有需要完成的任务。我们可以通过点任务标题栏按字母或优先级排序项目。也可以调用右键菜单中的filter设定根据负责人,分类,项目类型等来定制项目显示。除此之外,To-Do List 我们还可以调用右键菜单的Copy As命令以文本或网页形式输出任务列表的状况。

  添加To-Do item

  我们可以通过调用代码编辑窗口中的右键菜单命令Add To-Do Item命令来添加To-Do Item。

   任务的属性"Priority"(优先级)通过1到5的数字表明任务的重要性。"Owner"(负责人)意思是谁负责完成这个任务。"Category"代表任务的类型(比如, 是用户界面部分,还是事件处理)。下图3.14演示了一个填好了信息的任务:

图3.14

  如上土那样填好信息后,点OK按钮就会添加任务到列表中去,同时会在源码中自动生成下面所示意的注释: { TODO 2 -ohubdog –c算法 : 需要实现一个复杂的算法 }

  要注意的是除了可以添加同源码文件相关的任务,我们还可以添加全局的To-Do item。调用View|To-Do List命令调出编辑对话框,点Add按钮后添加的就是全局的To-Do Item。由下图我们可以看出两者的区别:两者图标不一样,其次,全局的任务不会在源码中添加注释,而是被储存在project.To-Do文件中。同时全局的To-Do Item的module属性是空的,而同文件关联的To-Do Item的Module属性为被注释的源码文件。我们双击局部To-Do Item会自动定位到源码中被注释的部分。

图3.15

   注意:所有To-Do Item都有一个点选框,点中后,就表明这个任务已经实现。

  增强To-Do List

  虽然IDE提供了强大的To-Do List定制,但用户有时可能还需要在已有的To-Do List基础上实现一些特定的功能,为此在Delphi 5中,borland提供了扩展To-Do List的接口,它们是IOTAToDoServices, IOTAToDoManager和INTAToDoItem接口:

  IOTAToDoServices

  To-Do List的服务接口,用来维护系统中的全部To-Do Item的列表,同时我们可以利用它的AddManager函数来添加自定义的To-Do List Manager。

  IOTAToDoManager

  To-Do List的管理接口,用来维护自定义的To-Do Item的列表,我们可以使用这个接口来添加自定义的To-Do Item。

  INTAToDoItem

  To-Do Item的接口,包含很多方法描述和管理To-Do Item的属性。

  下面就让我们来演示一下如何扩展To-Do List特性。假设我们现在在做一个项目,项目规划中要求每到周末,我们就需要打印一份程序开发进度。为了防止程序员遗忘这项任务,

  我们可以设计一个定制的To-Do Item,每到周末的时候,它就会被自动添加到To-Do List中去提醒程序员。

  要想添加一个这样的To-Do Item,我们首先应该实现一个特殊的ToDoManager,它负责检查时间,如果时间符合要求,就会自动添加一个提示性的To-Do Item到列表中去。下面就是我们的ToDoManager的类定义,它实现了IOTAToDoManager和INTAToDoItem接口。

TToDoManager = class(TInterfacedObject, IOTAToDoManager, INTAToDoItem)

private

FName: string;

public

constructor Create;

{ IOTAToDoManager methods }

function GetName: string;

procedure SetName(const AName: string);

function GetItem(Index: Integer): INTAToDoItem;

function GetItemCount: Integer;

procedure ProjectChanged;

{ INTAToDoItem methods }

function CanDelete: Boolean;

function CanEdit: Boolean;

function CanShow: Boolean;

procedure Delete;

procedure DrawImage(const Canvas: TCanvas; const Rect: TRect);

procedure DoubleClicked;

procedure Edit;

function GetText: string;

function GetPriority: TOTAToDoPriority;

function GetCategory: string;

function GetChecked: Boolean;

function GetModuleName: string;

function GetKind: string;

function GetData: Integer;

function GetOwner: string;

function IsValid: Boolean;

procedure SetChecked(const Value: Boolean);

procedure Show;

end;

  我们首先来实现IOTAToDoManager接口的方法,下面代码在GetName的方法中返回一个唯一的字符串用来标示ToDoManager。SetName方法只要简单的把Aname付值给Fname就可以了。

constructor TToDoManager.Create;

begin

inherited Create;

FName := 'Project Progress ToDo Manager';

end;

function TToDoManager.GetName: string;

begin

Result := FName;

end;

procedure TToDoManager.SetName(const AName: string);

begin

FName := AName;

end;

  由于需要添加的To-Do Item只有一个,同时只有当周五的时候,才需要显示,所以我们要在GetItemCount方法中判断日期,如果为周末,就返回1,否则返回0。

function TToDoManager.GetItemCount: Integer;

begin

if DayOfWeek(Now)=5{周五} then

Result:=1

else

Result:=0;

end;

  如果GetItemCount大于0,IDE会调用GetItem(index)来获得To-Do Item,我们只需要用As操作符返回实现的INTAToDoItem的实例就可以了,代码如下:

function TToDoManager.GetItem(Index: Integer): INTAToDoItem;

begin

Result := Self as INTAToDoItem;

end;

  IOTAToDoManager接口的ProjectChanged过程会在项目变化时被调用,但这里不会用到,我们只要放一个空的实现就可以了。

procedure TToDoManager.ProjectChanged;

begin

end;

  接下来就该实现INTAToDoItem接口了,下面是实现部分的代码,注释对实现部分进行了说明:

// INTAToDoItem 接口

// CanDelete函数返回False是为了避免To-Do Item被误删除

//当结果为false时,Item对应的右键菜单的Delete命令变灰,无法选取

function TToDoManager.CanDelete: Boolean;

begin

Result := False;

end;

// CanEdit函数返回False,表明这个项目无须编辑

function TToDoManager.CanEdit: Boolean;

begin

Result := False;

end;

// CanShow返回False表述这个项目无法Open(注意只有和文件关联的项目

//才支持Open命令,缺省条件下调用Open,会打开相应Module,定位到注释位置。

function TToDoManager.CanShow: Boolean;

begin

Result := False;

end;

//当项目将被删除时被调用,这里无须实现 procedure TToDoManager.Delete;

begin

end;

//可以用来画定制的图像,这里没有实现

procedure TToDoManager.DrawImage(const Canvas: TCanvas; const Rect: TRect);

begin

end;

//双击项目,会调用这个过程,这里我们只是显示一下提示信息

procedure TToDoManager.DoubleClicked;

begin

ShowMessage('一定要在今天把工作计划打印出来,否则小心炒你的鱿鱼');

end;

//编辑过程中会被调用,这里无须实现

procedure TToDoManager.Edit;

begin

end;

//返回项目的标题

function TToDoManager.GetText: string;

begin

Result := '务必要在今天把工作进展打出来';

end;

//返回优先级别

function TToDoManager.GetPriority: TOTAToDoPriority;

begin

Result := 1; //我们这里假定1是最大优先级

end;

//返回项目类别

function TToDoManager.GetCategory: string;

begin

Result := '进度管理';

end;

//返回是否已经完成的信息,这里不实现

function TToDoManager.GetChecked: Boolean;

begin

end;

// 返回模块名

function TToDoManager.GetModuleName: string;

begin

Result := '管理';

end;

// 用唯一的字符串标示项目类型

function TToDoManager.GetKind: string;

begin

Result := '打印报表';

end;

// 返回一个数值,但是我不知道是干什么用的:(

function TToDoManager.GetData: Integer;

begin

Result := 0;

end;

// 返回负责人

function TToDoManager.GetOwner: string;

begin

Result := '该死的老板';

end;

// 是否有效,简单的返回true,如果返回false,项目就不会出现在列表中

function TToDoManager.IsValid: Boolean;

begin

Result := True;

end;

// 无须实现,因为我们的这个项目是只读的

procedure TToDoManager.SetChecked(const Value: Boolean);

begin

end;

//无须实现,因为我们这个项目不允许打开

procedure TToDoManager.Show;

begin

end;

  现在我们已经把核心代码写完了,剩下的就是编写一个专家把自定义的ToDoManager注册到系统中。这部分比较简单,只需要在Expert的Create方法中调用IOTAToDoServices接口的AddManager添加ToDoManager,并在Destroy方法中释放ToDoManager即可,代码如下:

unit TToDoMain;

interface

uses ToolsAPI, Windows, Menus, Graphics, Classes;

type

TToDoExpert = class(TInterfacedObject, IOTANotifier, IOTAWizard)

private

FIndex: Integer;

public

constructor Create;

destructor Destroy; override;

{ IOTANotifier methods }

procedure AfterSave;

procedure BeforeSave;

procedure Destroyed;

procedure Modified;

{ IOTAWizard methods }

function GetIDString: string;

function GetName: string;

function GetState: TWizardState;

procedure Execute;

end;

procedure Register;

implementation

uses SysUtils, Forms, Dialogs, ImgList;

procedure Register;

begin

RegisterPackageWizard(TToDoExpert.Create as IOTAWizard);

end;

constructor TToDoExpert.Create;

begin

inherited Create;

//利用BorlandIDEServices获得IOTAToDoServices接口,

//然后调用AddManager方法添加自定义的ToDoManager

//并保存返回的Index,以便后面删除用。

FIndex := (BorlandIDEServices as IOTAToDoServices).AddManager(

TToDoManager.Create);

end;

destructor TToDoExpert.Destroy;

begin

//利用先前保存的Manager Index删除ToDoManager

(BorlandIDEServices as IOTAToDoServices).RemoveManager(FIndex);

inherited Destroy;

end;

procedure TToDoExpert.AfterSave;

begin

end;

procedure TToDoExpert.BeforeSave;

begin

end;

procedure TToDoExpert.Destroyed;

begin

end;

function TToDoExpert.GetIDString: string;

begin

Result := 'ProjectProgress ToDoExpert';

end;

function TToDoExpert.GetName: string;

begin

Result := 'ToDo Demo Expert';

end;

function TToDoExpert.GetState: TWizardState;

begin

Result := [];

end;

procedure TToDoExpert.Modified;

begin

end;

procedure TToDoExpert.Execute;

begin

end;

安装后的结果如下图3.16所示,实验一下双击Item的效果如何吧。

图3.16

  上面的例子只是简单的演示了一下如何扩展To-Do List的功能,其实完全可以编写更复杂的专家来实现工作计划,系统流程等方面的工作。



本站原创及翻译内容保留版权,欢迎转贴,转贴时请注明转自Delphi深度探索