|
|
f754e5 |
unit main;
|
|
|
f754e5 |
|
|
|
f754e5 |
{$mode objfpc}{$H+}
|
|
|
f754e5 |
|
|
|
f754e5 |
interface
|
|
|
f754e5 |
|
|
|
f754e5 |
uses
|
|
|
8a9c8e |
SysUtils, DateUtils, Forms, Controls, Graphics, ExtCtrls, StdCtrls;
|
|
|
f754e5 |
|
|
|
f754e5 |
type
|
|
|
f754e5 |
|
|
|
f754e5 |
PTodoHistoryItem = ^TTodoHistoryItem;
|
|
|
f754e5 |
TTodoHistoryItem = record
|
|
|
f754e5 |
date : TDate;
|
|
|
f754e5 |
done : Boolean;
|
|
|
f754e5 |
doneByOthers : Boolean;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
PTodoItem = ^TTodoItem;
|
|
|
f754e5 |
TTodoItem = record
|
|
|
f754e5 |
id : Integer;
|
|
|
f754e5 |
name : string;
|
|
|
f754e5 |
repeatDays : Integer;
|
|
|
f754e5 |
daysSinceDone : Integer;
|
|
|
f754e5 |
done : Boolean;
|
|
|
f754e5 |
doneByOthers : Boolean;
|
|
|
f754e5 |
cancelled : Boolean;
|
|
|
8a9c8e |
planned : Boolean;
|
|
|
8a9c8e |
notPlanned : Boolean;
|
|
|
f754e5 |
history : array of TTodoHistoryItem;
|
|
|
f754e5 |
panel : TPanel;
|
|
|
f754e5 |
updating : Boolean;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
PTodoList = ^TTodoList;
|
|
|
f754e5 |
TTodoList = record
|
|
|
f754e5 |
filename : string;
|
|
|
f754e5 |
name : string;
|
|
|
f754e5 |
nextId : Integer;
|
|
|
f754e5 |
date : TDate;
|
|
|
f754e5 |
items : array of TTodoItem;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
{ TfrmMain }
|
|
|
f754e5 |
|
|
|
f754e5 |
TfrmMain = class(TForm)
|
|
|
f754e5 |
bAdd: TButton;
|
|
|
f754e5 |
bNextDay: TButton;
|
|
|
f754e5 |
cbPlanned: TCheckBox;
|
|
|
f754e5 |
lDate: TLabel;
|
|
|
f754e5 |
sbTodo: TScrollBox;
|
|
|
f754e5 |
procedure bAddClick(Sender: TObject);
|
|
|
f754e5 |
procedure bNextDayClick(Sender: TObject);
|
|
|
f754e5 |
procedure cbPlannedChange(Sender: TObject);
|
|
|
f754e5 |
procedure FormActivate(Sender: TObject);
|
|
|
f754e5 |
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
|
|
|
f754e5 |
procedure OnChangeItem(Sender: TObject);
|
|
|
f754e5 |
procedure UpdateItem(var item: TTodoItem);
|
|
|
f754e5 |
procedure ClearTodoList();
|
|
|
f754e5 |
procedure RebuildTodoList();
|
|
|
f754e5 |
private
|
|
|
f754e5 |
public
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
var
|
|
|
f754e5 |
frmMain: TfrmMain;
|
|
|
f754e5 |
todoList: TTodoList;
|
|
|
f754e5 |
|
|
|
f754e5 |
implementation
|
|
|
f754e5 |
|
|
|
f754e5 |
{$R *.lfm}
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
function BoolToInt(b: Boolean): Integer;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
if b then Result := 1 else Result := 0;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
function DateToInt(date: TDate): Integer;
|
|
|
f754e5 |
var
|
|
|
f754e5 |
y, m, d: Word;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
DecodeDate(date, y, m, d);
|
|
|
f754e5 |
Result := y*10000 + m*100 + d;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
function IntToDate(i: Integer): TDate;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
Result := EncodeDate(i div 10000, (i div 100) mod 100, i mod 100);
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
function RoundDate(date: TDate): TDate;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
Result := IntToDate( DateToInt(date) );
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
8a9c8e |
function isPlanned(var item: TTodoItem): Boolean;
|
|
|
8a9c8e |
begin
|
|
|
8a9c8e |
Result := item.planned or ((item.daysSinceDone >= item.repeatDays) and not item.notPlanned);
|
|
|
8a9c8e |
end;
|
|
|
8a9c8e |
|
|
|
8a9c8e |
|
|
|
8a9c8e |
function isDone(var item: TTodoItem): Boolean;
|
|
|
8a9c8e |
begin
|
|
|
8a9c8e |
Result := item.done or item.doneByOthers;
|
|
|
8a9c8e |
end;
|
|
|
8a9c8e |
|
|
|
8a9c8e |
|
|
|
8a9c8e |
function isNeedToDo(var item: TTodoItem): Boolean;
|
|
|
8a9c8e |
begin
|
|
|
8a9c8e |
Result := isPlanned(item) and (not item.cancelled) and not isDone(item);
|
|
|
8a9c8e |
end;
|
|
|
8a9c8e |
|
|
|
8a9c8e |
|
|
|
f754e5 |
procedure ClearTodoList(var list: TTodoList);
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
list.filename := '';
|
|
|
f754e5 |
list.name := '';
|
|
|
f754e5 |
list.nextId := 0;
|
|
|
f754e5 |
setLength(list.items, 0);
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
function SaveTodoList(var list: TTodoList; filename: string): Boolean;
|
|
|
f754e5 |
var
|
|
|
f754e5 |
i: Integer;
|
|
|
f754e5 |
f: textfile;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
Result := False;
|
|
|
f754e5 |
|
|
|
f754e5 |
AssignFile(f, filename);
|
|
|
f754e5 |
Rewrite(f);
|
|
|
8a9c8e |
Writeln(f, 2); // version
|
|
|
f754e5 |
Writeln(f, list.name);
|
|
|
f754e5 |
Writeln(f, list.nextId);
|
|
|
f754e5 |
Writeln(f, DateToInt(list.date));
|
|
|
f754e5 |
Writeln(f, Length(list.items));
|
|
|
f754e5 |
for i := 0 to Length(list.items)-1 do begin
|
|
|
f754e5 |
Writeln(f, list.items[i].id);
|
|
|
f754e5 |
Writeln(f, list.items[i].name);
|
|
|
f754e5 |
Writeln(f,
|
|
|
f754e5 |
list.items[i].repeatDays, ' ',
|
|
|
f754e5 |
list.items[i].daysSinceDone, ' ',
|
|
|
f754e5 |
BoolToInt(list.items[i].done), ' ',
|
|
|
f754e5 |
BoolToInt(list.items[i].doneByOthers), ' ',
|
|
|
8a9c8e |
BoolToInt(list.items[i].cancelled), ' ',
|
|
|
f754e5 |
BoolToInt(list.items[i].planned), ' ',
|
|
|
8a9c8e |
BoolToInt(list.items[i].notPlanned) );
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
CloseFile(f);
|
|
|
f754e5 |
|
|
|
f754e5 |
Result := True;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
function SaveTodoListEx(var list: TTodoList): Boolean;
|
|
|
f754e5 |
var
|
|
|
f754e5 |
i: Integer;
|
|
|
f754e5 |
fo, fn: string;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
Result := False;
|
|
|
f754e5 |
if FileExists(list.filename) then begin
|
|
|
f754e5 |
for i := 0 to 1000 do begin
|
|
|
f754e5 |
fo := list.filename + '.old.' + IntToStr(i);
|
|
|
f754e5 |
if FileExists(fo) then fo := '' else break;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
for i := 0 to 1000 do begin
|
|
|
f754e5 |
fn := list.filename + '.new.' + IntToStr(i);
|
|
|
f754e5 |
if FileExists(fn) then fn := '' else break;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
if (fo = '') or (fn = '') then Exit;
|
|
|
f754e5 |
|
|
|
f754e5 |
if not SaveTodoList(list, fn) then begin
|
|
|
f754e5 |
DeleteFile(fn);
|
|
|
f754e5 |
Exit;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
if not RenameFile(list.filename, fo) then begin
|
|
|
f754e5 |
DeleteFile(fn);
|
|
|
f754e5 |
Exit;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
if not RenameFile(fn, list.filename) then begin
|
|
|
f754e5 |
RenameFile(fo, list.filename);
|
|
|
f754e5 |
DeleteFile(fn);
|
|
|
f754e5 |
Exit;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
DeleteFile(fn);
|
|
|
f754e5 |
DeleteFile(fo);
|
|
|
f754e5 |
end else
|
|
|
f754e5 |
if not SaveTodoList(list, list.filename) then begin
|
|
|
f754e5 |
DeleteFile(list.filename);
|
|
|
f754e5 |
Exit;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
Result := True;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
function LoadTodoList(var list: TTodoList; filename: string): Boolean;
|
|
|
f754e5 |
var
|
|
|
8a9c8e |
i, version, count: Integer;
|
|
|
8a9c8e |
i0, i1, i2, i3, i4: Integer;
|
|
|
f754e5 |
f: textfile;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
clearTodoList(list);
|
|
|
f754e5 |
list.filename := filename;
|
|
|
f754e5 |
|
|
|
f754e5 |
Result := False;
|
|
|
f754e5 |
if not FileExists(filename) then Exit;
|
|
|
f754e5 |
|
|
|
f754e5 |
AssignFile(f, filename);
|
|
|
f754e5 |
Reset(f);
|
|
|
8a9c8e |
Readln(f, version);
|
|
|
f754e5 |
Readln(f, list.name);
|
|
|
f754e5 |
Readln(f, list.nextId);
|
|
|
f754e5 |
Readln(f, i0);
|
|
|
f754e5 |
list.date := IntToDate(i0);
|
|
|
f754e5 |
Readln(f, count);
|
|
|
f754e5 |
setLength(list.items, count);
|
|
|
f754e5 |
for i := 0 to count-1 do begin
|
|
|
f754e5 |
Readln(f, list.items[i].id);
|
|
|
f754e5 |
Readln(f, list.items[i].name);
|
|
|
8a9c8e |
if version <= 1 then begin
|
|
|
8a9c8e |
Readln(f,
|
|
|
8a9c8e |
list.items[i].repeatDays,
|
|
|
8a9c8e |
list.items[i].daysSinceDone,
|
|
|
8a9c8e |
i0, i1, i2, i3 );
|
|
|
8a9c8e |
list.items[i].done := i0 <> 0;
|
|
|
8a9c8e |
list.items[i].doneByOthers := i1 <> 0;
|
|
|
8a9c8e |
list.items[i].cancelled := i3 <> 0;
|
|
|
8a9c8e |
list.items[i].planned := i2 <> 0;
|
|
|
8a9c8e |
list.items[i].notPlanned := False;
|
|
|
8a9c8e |
end else begin
|
|
|
8a9c8e |
Readln(f,
|
|
|
8a9c8e |
list.items[i].repeatDays,
|
|
|
8a9c8e |
list.items[i].daysSinceDone,
|
|
|
8a9c8e |
i0, i1, i2, i3, i4 );
|
|
|
8a9c8e |
list.items[i].done := i0 <> 0;
|
|
|
8a9c8e |
list.items[i].doneByOthers := i1 <> 0;
|
|
|
8a9c8e |
list.items[i].cancelled := i2 <> 0;
|
|
|
8a9c8e |
list.items[i].planned := i3 <> 0;
|
|
|
8a9c8e |
list.items[i].notPlanned := i4 <> 0;
|
|
|
8a9c8e |
end;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
CloseFile(f);
|
|
|
f754e5 |
Result := True;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
procedure SetTodoListDate(var list: TTodoList; date: TDate);
|
|
|
f754e5 |
var
|
|
|
f754e5 |
i, d: Integer;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
date := RoundDate(date);
|
|
|
f754e5 |
d := DaysBetween(date, list.date);
|
|
|
f754e5 |
if (date < list.date) and (d > 0) then d := -d;
|
|
|
f754e5 |
list.date := date;
|
|
|
f754e5 |
if d = 0 then Exit;
|
|
|
f754e5 |
for i := 0 to Length(list.items)-1 do begin
|
|
|
f754e5 |
Inc(list.items[i].daysSinceDone, d);
|
|
|
f754e5 |
if d < 0 then begin
|
|
|
f754e5 |
if list.items[i].daysSinceDone < 1 then
|
|
|
f754e5 |
list.items[i].daysSinceDone := 1;
|
|
|
f754e5 |
end else begin
|
|
|
8a9c8e |
if isDone(list.items[i]) then begin
|
|
|
f754e5 |
list.items[i].daysSinceDone := d;
|
|
|
f754e5 |
list.items[i].planned := False;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
list.items[i].done := False;
|
|
|
f754e5 |
list.items[i].doneByOthers := False;
|
|
|
8a9c8e |
list.items[i].cancelled := False;
|
|
|
8a9c8e |
list.items[i].notPlanned := False;
|
|
|
f754e5 |
end
|
|
|
f754e5 |
end
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
procedure AddTodoItem(var list: TTodoList);
|
|
|
f754e5 |
var
|
|
|
f754e5 |
i: Integer;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
i := Length(list.items);
|
|
|
f754e5 |
SetLength(list.items, i + 1);
|
|
|
f754e5 |
list.items[i].id := list.nextId;
|
|
|
f754e5 |
list.items[i].repeatDays := 1;
|
|
|
f754e5 |
list.items[i].daysSinceDone := 1;
|
|
|
f754e5 |
Inc(list.nextId);
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
procedure RemoveTodoItem(var list: TTodoList; i: Integer);
|
|
|
f754e5 |
var
|
|
|
f754e5 |
j: Integer;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
if (i < 0) or (i >= Length(list.items)) then Exit;
|
|
|
f754e5 |
for j := i+1 to Length(list.items)-1 do
|
|
|
f754e5 |
list.items[j-1] := list.items[j];
|
|
|
f754e5 |
SetLength(list.items, Length(list.items) - 1);
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
procedure InsertTodoItem(var list: TTodoList; i: Integer; item: TTodoItem);
|
|
|
f754e5 |
var
|
|
|
f754e5 |
j: Integer;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
if i < 0 then i := 0;
|
|
|
f754e5 |
if i > Length(list.items) then i := Length(list.items);
|
|
|
f754e5 |
SetLength(list.items, Length(list.items) + 1);
|
|
|
f754e5 |
for j := Length(list.items)-1 downto i+1 do
|
|
|
f754e5 |
list.items[j] := list.items[j-1];
|
|
|
f754e5 |
list.items[i] := item;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
procedure TfrmMain.bAddClick(Sender: TObject);
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
AddTodoItem(todoList);
|
|
|
f754e5 |
RebuildTodoList();
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
procedure TfrmMain.bNextDayClick(Sender: TObject);
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
SetTodoListDate(todoList, IncDay(todoList.date));
|
|
|
f754e5 |
RebuildTodoList();
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
procedure TfrmMain.cbPlannedChange(Sender: TObject);
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
RebuildTodoList();
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
procedure TfrmMain.FormActivate(Sender: TObject);
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
if todoList.filename <> '' then Exit;
|
|
|
f754e5 |
LoadTodoList(todoList, 'todo.list');
|
|
|
f754e5 |
SetTodoListDate(todoList, Date);
|
|
|
f754e5 |
RebuildTodoList();
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
procedure TfrmMain.FormClose(Sender: TObject; var CloseAction: TCloseAction);
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
SaveTodoListEx(todoList);
|
|
|
8a9c8e |
CloseAction := caFree;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
procedure TfrmMain.OnChangeItem(Sender: TObject);
|
|
|
f754e5 |
var
|
|
|
f754e5 |
p: TPanel;
|
|
|
f754e5 |
i: Integer;
|
|
|
f754e5 |
n: string;
|
|
|
f754e5 |
item: TTodoItem;
|
|
|
f754e5 |
|
|
|
f754e5 |
function ParseInt(s: string): Integer;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
Result := StrToInt(s);
|
|
|
f754e5 |
if Result < 1 then Result := 1;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
p := TPanel(TControl(Sender).Parent);
|
|
|
f754e5 |
i := p.Tag;
|
|
|
f754e5 |
|
|
|
f754e5 |
n := TControl(Sender).Name;
|
|
|
f754e5 |
if n = 'delete' then begin
|
|
|
f754e5 |
RemoveTodoItem(todoList, i);
|
|
|
f754e5 |
RebuildTodoList();
|
|
|
f754e5 |
end else
|
|
|
f754e5 |
if n = 'up' then begin
|
|
|
f754e5 |
item := todoList.items[i];
|
|
|
f754e5 |
RemoveTodoItem(todoList, i);
|
|
|
f754e5 |
InsertTodoItem(todoList, i-1, item);
|
|
|
f754e5 |
RebuildTodoList();
|
|
|
f754e5 |
end else
|
|
|
f754e5 |
if n = 'down' then begin
|
|
|
f754e5 |
item := todoList.items[i];
|
|
|
f754e5 |
RemoveTodoItem(todoList, i);
|
|
|
f754e5 |
InsertTodoItem(todoList, i+1, item);
|
|
|
f754e5 |
RebuildTodoList();
|
|
|
f754e5 |
end else begin
|
|
|
f754e5 |
with todoList.items[i] do begin
|
|
|
f754e5 |
if updating then Exit;
|
|
|
f754e5 |
name := TEdit( p.FindChildControl('name') ).Text;
|
|
|
f754e5 |
repeatDays := ParseInt(TEdit( p.FindChildControl('repeatDays') ).Text);
|
|
|
f754e5 |
daysSinceDone := ParseInt(TEdit( p.FindChildControl('daysSinceDone') ).Text);
|
|
|
f754e5 |
done := TCheckBox( p.FindChildControl('done') ).Checked;
|
|
|
f754e5 |
doneByOthers := TCheckBox( p.FindChildControl('doneByOthers') ).Checked;
|
|
|
f754e5 |
cancelled := TCheckBox( p.FindChildControl('cancelled') ).Checked;
|
|
|
8a9c8e |
planned := TCheckBox( p.FindChildControl('planned') ).Checked;
|
|
|
8a9c8e |
notPlanned := TCheckBox( p.FindChildControl('notPlanned') ).Checked;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
UpdateItem(todoList.items[i]);
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
SaveTodoListEx(todoList);
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
procedure TfrmMain.UpdateItem(var item: TTodoItem);
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
item.updating := True;
|
|
|
f754e5 |
with item.panel do begin
|
|
|
f754e5 |
if item.cancelled then
|
|
|
f754e5 |
item.panel.Font.StrikeThrough := True
|
|
|
f754e5 |
else
|
|
|
f754e5 |
item.panel.Font.StrikeThrough := False;
|
|
|
f754e5 |
|
|
|
8a9c8e |
if isNeedToDo(item) then
|
|
|
8a9c8e |
item.panel.Font.Color := clDefault
|
|
|
f754e5 |
else
|
|
|
8a9c8e |
item.panel.Font.Color := clGrayText;
|
|
|
f754e5 |
|
|
|
f754e5 |
TCheckBox( FindChildControl('done') ).Checked := item.done;
|
|
|
f754e5 |
TCheckBox( FindChildControl('doneByOthers') ).Checked := item.doneByOthers;
|
|
|
f754e5 |
TCheckBox( FindChildControl('cancelled') ).Checked := item.cancelled;
|
|
|
8a9c8e |
TCheckBox( FindChildControl('planned') ).Checked := item.planned;
|
|
|
8a9c8e |
TCheckBox( FindChildControl('notPlanned') ).Checked := item.notPlanned;
|
|
|
f754e5 |
TEdit( FindChildControl('daysSinceDone') ).Text := IntToStr(item.daysSinceDone);
|
|
|
f754e5 |
TEdit( FindChildControl('repeatDays') ).Text := IntToStr(item.repeatDays);
|
|
|
f754e5 |
TEdit( FindChildControl('name') ).Text := item.name;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
item.updating := False;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
procedure TfrmMain.ClearTodoList();
|
|
|
f754e5 |
var
|
|
|
f754e5 |
i: Integer;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
while sbTodo.ControlCount > 0 do
|
|
|
f754e5 |
sbTodo.Controls[0].Destroy();
|
|
|
f754e5 |
for i := 0 to Length(todoList.items)-1 do
|
|
|
f754e5 |
todoList.items[i].panel := nil;
|
|
|
f754e5 |
sbTodo.UpdateScrollbars;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
procedure TfrmMain.RebuildTodoList();
|
|
|
f754e5 |
const
|
|
|
8a9c8e |
b = 0;
|
|
|
8a9c8e |
bb = 2;
|
|
|
f754e5 |
sb = 16;
|
|
|
f754e5 |
var
|
|
|
8a9c8e |
i, j, h, t, l, ll, r: Integer;
|
|
|
f754e5 |
scroll: Integer;
|
|
|
8a9c8e |
plannedOnly: Boolean;
|
|
|
f754e5 |
p: TPanel;
|
|
|
f754e5 |
|
|
|
f754e5 |
function createCheckBox(name, title: string): TCheckBox;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
Result := TCheckBox.Create(p);
|
|
|
f754e5 |
Result.Name := name;
|
|
|
f754e5 |
Result.Caption := '';
|
|
|
f754e5 |
Result.Hint := title;
|
|
|
f754e5 |
Result.ShowHint := True;
|
|
|
f754e5 |
Result.Top := bb;
|
|
|
f754e5 |
Result.Left := l;
|
|
|
f754e5 |
Result.OnChange := @OnChangeItem;
|
|
|
f754e5 |
p.InsertControl(Result);
|
|
|
f754e5 |
Inc(l, Result.Width);
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
function createButton(name, title: string): TButton;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
Result := TButton.Create(p);
|
|
|
f754e5 |
Result.Name := name;
|
|
|
f754e5 |
Result.Caption := title;
|
|
|
f754e5 |
Result.ParentFont := True;
|
|
|
f754e5 |
Result.Top := bb;
|
|
|
f754e5 |
Result.Left := r - Result.Width;
|
|
|
f754e5 |
Result.Anchors := [akTop, akRight];
|
|
|
f754e5 |
Result.OnClick := @OnChangeItem;
|
|
|
f754e5 |
p.InsertControl(Result);
|
|
|
f754e5 |
r := Result.Left;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
function createSquareButton(name, title: string): TButton;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
Result := createButton(name, title);
|
|
|
f754e5 |
Result.Left := Result.Left + Result.Width - Result.Height;
|
|
|
f754e5 |
Result.Width := Result.Height;
|
|
|
f754e5 |
r := Result.Left;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
function createEdit(name, title: string): TEdit;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
Result := TEdit.Create(p);
|
|
|
f754e5 |
Result.Name := name;
|
|
|
f754e5 |
Result.Hint := Title;
|
|
|
f754e5 |
Result.ShowHint := True;
|
|
|
f754e5 |
Result.AutoSize := False;
|
|
|
f754e5 |
Result.BorderStyle := bsNone;
|
|
|
f754e5 |
Result.ParentFont := True;
|
|
|
f754e5 |
Result.ParentColor := True;
|
|
|
f754e5 |
Result.Width := Result.Height*2;
|
|
|
f754e5 |
Result.NumbersOnly := True;
|
|
|
f754e5 |
Result.Top := bb;
|
|
|
f754e5 |
Result.Left := r - Result.Width;
|
|
|
f754e5 |
Result.Anchors := [akTop, akRight];
|
|
|
f754e5 |
Result.OnEditingDone := @OnChangeItem;
|
|
|
f754e5 |
p.InsertControl(Result);
|
|
|
f754e5 |
r := Result.Left;
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
function createNameEdit(name, title: string): TEdit;
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
Result := createEdit(name, title);
|
|
|
f754e5 |
Result.NumbersOnly := False;
|
|
|
f754e5 |
Result.Left := l;
|
|
|
f754e5 |
Result.Width := Result.Width + r - l;
|
|
|
f754e5 |
Result.Anchors := [akLeft, akTop, akRight];
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
begin
|
|
|
f754e5 |
scroll := sbTodo.VertScrollBar.Position;
|
|
|
8a9c8e |
plannedOnly := cbPlanned.Checked;
|
|
|
f754e5 |
|
|
|
f754e5 |
ClearTodoList();
|
|
|
f754e5 |
|
|
|
f754e5 |
lDate.Caption := FormatDateTime('YYYY-MM-DD', todoList.date);
|
|
|
f754e5 |
|
|
|
f754e5 |
t := b;
|
|
|
f754e5 |
for i := 0 to Length(todoList.items)-1 do begin
|
|
|
8a9c8e |
if plannedOnly and not isPlanned(todoList.items[i]) then
|
|
|
f754e5 |
Continue;
|
|
|
f754e5 |
|
|
|
f754e5 |
p := TPanel.Create(sbTodo);
|
|
|
f754e5 |
p.Tag := i;
|
|
|
f754e5 |
p.Left := b;
|
|
|
f754e5 |
p.Width := sbTodo.Width - b*2 - sb;
|
|
|
f754e5 |
p.Top := t;
|
|
|
f754e5 |
p.Anchors := [akLeft, akTop, akRight];
|
|
|
f754e5 |
p.ParentFont := False;
|
|
|
f754e5 |
sbTodo.InsertControl(p);
|
|
|
f754e5 |
|
|
|
f754e5 |
l := bb;
|
|
|
f754e5 |
|
|
|
f754e5 |
createCheckBox('done', 'Done');
|
|
|
f754e5 |
createCheckBox('doneByOthers', 'Done by others');
|
|
|
f754e5 |
createCheckBox('cancelled', 'Cancelled');
|
|
|
8a9c8e |
ll := l;
|
|
|
8a9c8e |
Inc(l, bb);
|
|
|
8a9c8e |
Inc(l, bb);
|
|
|
f754e5 |
Inc(l, bb);
|
|
|
8a9c8e |
createCheckBox('planned', 'Planned manually').Visible := not plannedOnly;
|
|
|
8a9c8e |
createCheckBox('notPlanned', 'Remove from plan manually').Visible := not plannedOnly;
|
|
|
8a9c8e |
if plannedOnly then l := ll;
|
|
|
f754e5 |
Inc(l, bb);
|
|
|
f754e5 |
|
|
|
f754e5 |
r := p.ClientWidth - bb;
|
|
|
f754e5 |
|
|
|
f754e5 |
createButton('delete', 'delete');
|
|
|
f754e5 |
Dec(r, bb);
|
|
|
f754e5 |
createSquareButton('down', '+');
|
|
|
f754e5 |
createSquareButton('up', '-');
|
|
|
f754e5 |
Dec(r, bb);
|
|
|
f754e5 |
|
|
|
f754e5 |
createEdit('daysSinceDone', 'Days since last done');
|
|
|
f754e5 |
Dec(r, bb);
|
|
|
f754e5 |
createEdit('repeatDays', 'Repeat every N days');
|
|
|
f754e5 |
Dec(r, bb);
|
|
|
f754e5 |
createNameEdit('name', 'Task name');
|
|
|
f754e5 |
|
|
|
f754e5 |
h := 0;
|
|
|
f754e5 |
for j := 0 to p.ControlCount-1 do
|
|
|
f754e5 |
if h < p.Controls[j].Top + p.Controls[j].Height then
|
|
|
f754e5 |
h := p.Controls[j].Top + p.Controls[j].Height;
|
|
|
f754e5 |
p.Height := h + bb;
|
|
|
f754e5 |
Inc(t, p.Height + b);
|
|
|
f754e5 |
|
|
|
f754e5 |
todoList.items[i].panel := p;
|
|
|
f754e5 |
UpdateItem(todoList.items[i]);
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
sbTodo.UpdateScrollbars;
|
|
|
f754e5 |
|
|
|
f754e5 |
sbTodo.ScrollBy(0, -scroll);
|
|
|
f754e5 |
end;
|
|
|
f754e5 |
|
|
|
f754e5 |
|
|
|
f754e5 |
end.
|
|
|
f754e5 |
|