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的功能,其实完全可以编写更复杂的专家来实现工作计划,系统流程等方面的工作。
|