• R/O
  • SSH
  • HTTPS

denkzettelcompanion: Commit


Commit MetaInfo

Revision45 (tree)
Zeit2017-10-29 18:56:59
Autortwm

Log Message

0.0.4 release

Ändern Zusammenfassung

Diff

--- tags/DenkzettelCompanion_0.0.4/src/u_dzformutils.pas (nonexistent)
+++ tags/DenkzettelCompanion_0.0.4/src/u_dzformutils.pas (revision 45)
@@ -0,0 +1,400 @@
1+{.GXFormatter.config=twm}
2+///<summary>
3+/// Implements functions which work on components but are not methods.
4+/// @author twm </summary>
5+unit u_dzformutils;
6+
7+interface
8+
9+uses
10+ Classes,
11+ Windows,
12+ SysUtils,
13+ Controls,
14+ Forms,
15+ Graphics,
16+ Types;
17+
18+///<summary>
19+/// The same as TForm.Monitor, but it works.
20+/// @returns the monitor on wich the center point of the form is located.
21+/// Warning: The result might be nil if the form is outside the visible area. </summary>
22+function TForm_GetMonitor(_frm: TForm): TMonitor;
23+
24+///<summary> centers a form on the given point, but makes sure the form is fully visible </summary>
25+procedure TForm_CenterOn(_frm: TForm; _Center: TPoint); overload;
26+///<summary> centers a form on the given component, but makes sure the form is fully visible </summary>
27+procedure TForm_CenterOn(_frm: TForm; _Center: TWinControl); overload;
28+
29+type
30+ TFormPlacementEnum = (fpePositionOnly, fpeSizeOnly, fpePosAndSize);
31+
32+///<summary> Stores the form's current position and size to the registry
33+/// @param frm is the form whose placement is to be stored
34+/// @param Which determines whether the Position and/or the size is to be stored
35+/// @param RegistryPath gives the full path, including the value name to write to,
36+/// not yet implemented: defaults to '<Company_name>\<executable>\<frm.Classname>\NormPos'
37+/// where <Company_name> is read from the version resources
38+/// and <frm.Classname is the form's ClassName without the T-Prefix
39+/// @param HKEY is the root key, defaults to HKEY_CURRENT_USER
40+/// @returns false, if anything goes wrong, including any exceptions that might
41+/// occur, true if it worked.
42+function TForm_StorePlacement(_frm: TForm; _Which: TFormPlacementEnum; const _RegistryPath: string;
43+ _HKEY: HKEY = HKEY_CURRENT_USER): boolean; overload;
44+
45+///<summary> Stores the form's current position and size to the registry
46+/// under Software\<executable>\<frm.name>\NormPos'
47+/// @param frm is the form whose placement is to be stored
48+/// @param Which determines whether the Position and/or the size is to be stored
49+/// @param HKEY is the root key, defaults to HKEY_CURRENT_USER
50+/// @returns false, if anything goes wrong, including any exceptions that might
51+/// occur, true if it worked.
52+function TForm_StorePlacement(_frm: TForm; _Which: TFormPlacementEnum;
53+ _HKEY: HKEY = HKEY_CURRENT_USER): boolean; overload;
54+
55+///<summary> Reads the form's position and size from the registry
56+/// @param frm is the form whose placement is to be read
57+/// @param Which determines whether the Position and/or the size is to be read
58+/// @param RegistryPath gives the full path, including the value name to write to,
59+/// not yet implemented: defaults to '<Company_name>\<executable>\<frm.Classname>\NormPos'
60+/// where <Company_name> is read from the version resources
61+/// and <frm.Classname is the form's ClassName without the T-Prefix
62+/// @param HKEY is the root key, defaults to HKEY_CURRENT_USER
63+/// @returns false, if anything goes wrong, including any exceptions that might
64+/// occur, true if it worked.
65+function TForm_ReadPlacement(_frm: TForm; _Which: TFormPlacementEnum; const _RegistryPath: string;
66+ _HKEY: HKEY = HKEY_CURRENT_USER): boolean; overload;
67+
68+///<summary> Reads the form's position and size from the registry
69+/// under Software\<executable>\<frm.name>\NormPos'
70+/// @param frm is the form whose placement is to be stored
71+/// @param Which determines whether the Position and/or the size is to be stored
72+/// @param HKEY is the root key, defaults to HKEY_CURRENT_USER
73+/// @returns false, if anything goes wrong, including any exceptions that might
74+/// occur, true if it worked.
75+function TForm_ReadPlacement(_frm: TForm; _Which: TFormPlacementEnum;
76+ _HKEY: HKEY = HKEY_CURRENT_USER): boolean; overload;
77+
78+///<summary> Generates the registry path for storing a form's placement as used in
79+/// TForm_Read/StorePlacement. </summary>
80+function TForm_GetPlacementRegistryPath(_frm: TForm): string; overload;
81+
82+///<summary> Generates the registry path for storing a form's placement as used in
83+/// TForm_Read/StorePlacement. </summary>
84+function TForm_GetPlacementRegistryPath(const _FrmName: string): string; overload;
85+
86+///<summary> Generates the registry path for storing a form's configuration. </summary>
87+function TForm_GetConfigRegistryPath(_frm: TForm): string; overload;
88+function TForm_GetConfigRegistryPath(const _FrmName: string): string; overload;
89+
90+implementation
91+
92+uses
93+ registry,
94+ strutils;
95+
96+procedure TMonitor_MakeFullyVisible(_MonitorRect: TRect; var _Left, _Top, _Width, _Height: integer);
97+begin
98+ if _Left + _Width > _MonitorRect.Right then
99+ _Left := _MonitorRect.Right - _Width;
100+ if _Left < _MonitorRect.Left then
101+ _Left := _MonitorRect.Left;
102+ if _Top + _Height > _MonitorRect.Bottom then
103+ _Top := _MonitorRect.Bottom - _Height;
104+ if _Top < _MonitorRect.Top then
105+ _Top := _MonitorRect.Top;
106+end;
107+
108+procedure TMonitor_MakeFullyVisible(_Monitor: TMonitor; var _Left, _Top, _Width, _Height: integer);
109+begin
110+ TMonitor_MakeFullyVisible(_Monitor.WorkareaRect, _Left, _Top, _Width, _Height);
111+end;
112+
113+procedure TMonitor_MakeFullyVisible(_MonitorRect: TRect; var _Rect: TRect; out _Width, _Height: integer);
114+var
115+ Left: integer;
116+ Top: integer;
117+begin
118+ Left := _Rect.Left;
119+ Top := _Rect.Top;
120+ _Width := _Rect.Right - Left;
121+ _Height := _Rect.Bottom - Top;
122+ TMonitor_MakeFullyVisible(_MonitorRect, Left, Top, _Width, _Height);
123+ _Rect.Left := Left;
124+ _Rect.Top := Top;
125+ _Rect.Right := Left + _Width;
126+ _Rect.Bottom := Top + _Height;
127+end;
128+
129+procedure TMonitor_MakeFullyVisible(_Monitor: TMonitor; var _Rect: TRect; out _Width, _Height: integer);
130+begin
131+ if Assigned(_Monitor) then
132+ TMonitor_MakeFullyVisible(_Monitor.WorkareaRect, _Rect, _Width, _Height);
133+end;
134+
135+procedure TMonitor_MakeFullyVisible(_Monitor: TMonitor; var _Rect: TRect);
136+var
137+ Width: integer;
138+ Height: integer;
139+begin
140+ TMonitor_MakeFullyVisible(_Monitor, _Rect, Width, Height);
141+end;
142+
143+procedure TMonitor_MakeFullyVisible(_Monitor: TMonitor; _frm: TForm);
144+var
145+ re: TRect;
146+begin
147+ re := _frm.BoundsRect;
148+ TMonitor_MakeFullyVisible(_Monitor, re);
149+ _frm.BoundsRect := re;
150+end;
151+
152+function TScreen_MonitorFromPoint(_pnt: TPoint): TMonitor;
153+var
154+ i: integer;
155+ WaRect: TRect;
156+begin
157+ for i := 0 to Screen.MonitorCount - 1 do begin
158+ Result := Screen.Monitors[i];
159+ WaRect := Result.WorkareaRect;
160+ if (WaRect.Top <= _pnt.Y) and (WaRect.Bottom >= _pnt.Y)
161+ and (WaRect.Left <= _pnt.X) and (WaRect.Right >= _pnt.X) then
162+ Exit;
163+ end;
164+ Result := nil;
165+end;
166+
167+function TForm_GetMonitor(_frm: TForm): TMonitor;
168+var
169+ Center: TPoint;
170+begin
171+ Center.X := _frm.Left + _frm.Width div 2;
172+ Center.Y := _frm.Top + _frm.Height div 2;
173+ Result := TScreen_MonitorFromPoint(Center);
174+end;
175+
176+procedure TForm_CenterOn(_frm: TForm; _Center: TPoint);
177+var
178+ Monitor: TMonitor;
179+begin
180+ _frm.Position := poDesigned;
181+ _frm.DefaultMonitor := dmDesktop;
182+ _frm.Left := _Center.X - _frm.Width div 2;
183+ _frm.Top := _Center.Y - _frm.Height div 2;
184+
185+ Monitor := TScreen_MonitorFromPoint(_Center);
186+ TMonitor_MakeFullyVisible(Monitor, _frm);
187+end;
188+
189+procedure TForm_CenterOn(_frm: TForm; _Center: TWinControl);
190+begin
191+ if not Assigned(_Center) then
192+ _Center := Application.MainForm;
193+ if not Assigned(_Center) then begin
194+ if Screen.FormCount > 0 then
195+ _Center := Screen.Forms[0];
196+ end;
197+ if Assigned(_Center) then begin
198+ if Assigned(_Center.Parent) then
199+ TForm_CenterOn(_frm, _Center.ClientToScreen(Point(_Center.Width div 2, _Center.Height div 2)))
200+ else
201+ TForm_CenterOn(_frm, Point(_Center.Left + _Center.Width div 2, _Center.Top + _Center.Height div 2));
202+ end else begin
203+ TForm_CenterOn(_frm, Point(Screen.Width div 2, Screen.Height div 2));
204+ end;
205+end;
206+
207+function TApplication_GetRegistryPath: string;
208+begin
209+ Result := 'Software\' + ChangeFileExt(ExtractFileName(Application.ExeName), '');
210+end;
211+
212+function TApplication_GetConfigRegistryPath: string;
213+begin
214+ Result := TApplication_GetRegistryPath + '\Config';
215+end;
216+
217+function TForm_GetPlacementRegistryPath(const _FrmName: string): string;
218+begin
219+ Result := TApplication_GetRegistryPath + '\' + _FrmName + '\NormPos';
220+end;
221+
222+function TForm_GetPlacementRegistryPath(_frm: TForm): string;
223+begin
224+ Result := TForm_GetPlacementRegistryPath(_frm.Name);
225+end;
226+
227+function TForm_GetConfigRegistryPath(const _FrmName: string): string;
228+begin
229+ Result := TApplication_GetRegistryPath + '\' + _FrmName + '\Config';
230+end;
231+
232+function TForm_GetConfigRegistryPath(_frm: TForm): string;
233+begin
234+ Result := TForm_GetConfigRegistryPath(_frm.Name);
235+end;
236+
237+procedure TRegistry_WriteString(const _Path: string; const _Value: string;
238+ _HKEY: HKEY = HKEY_CURRENT_USER);
239+var
240+ reg: TRegistry;
241+begin
242+ reg := TRegistry.Create;
243+ try
244+ reg.RootKey := _HKEY;
245+ if reg.OpenKey(ExtractFileDir(_Path), True) then begin
246+ try
247+ reg.WriteString(ExtractFileName(_Path), _Value);
248+ finally
249+ reg.CloseKey;
250+ end;
251+ end;
252+ finally
253+ FreeAndNil(reg);
254+ end;
255+end;
256+
257+function TForm_StorePlacement(_frm: TForm; _Which: TFormPlacementEnum; const _RegistryPath: string;
258+ _HKEY: HKEY = HKEY_CURRENT_USER): boolean;
259+var
260+ L, t, w, h: integer;
261+begin
262+ Result := False;
263+ try
264+ L := _frm.Left;
265+ t := _frm.Top;
266+ w := _frm.Width;
267+ h := _frm.Height;
268+ case _Which of
269+ fpePositionOnly: begin
270+ w := -1;
271+ h := -1;
272+ end;
273+ fpeSizeOnly: begin
274+ L := -1;
275+ t := -1;
276+ end;
277+ // fpePosAndSize: ;
278+ end;
279+ TRegistry_WriteString(_RegistryPath, Format('%d,%d,%d,%d', [L, t, w, h]));
280+ Result := True;
281+ except
282+ // Result stays false
283+ end;
284+end;
285+
286+function TForm_StorePlacement(_frm: TForm; _Which: TFormPlacementEnum;
287+ _HKEY: HKEY = HKEY_CURRENT_USER): boolean;
288+begin
289+ Result := TForm_StorePlacement(_frm, _Which, TForm_GetPlacementRegistryPath(_frm), _HKEY);
290+end;
291+
292+function TRegistry_TryReadString(const _Path: string; out _Value: string;
293+ _HKEY: HKEY = HKEY_CURRENT_USER): boolean;
294+var
295+ reg: TRegistry;
296+begin
297+ Result := False;
298+ reg := TRegistry.Create;
299+ try
300+ reg.RootKey := _HKEY;
301+ if reg.OpenKeyReadOnly(ExtractFileDir(_Path)) then begin
302+ try
303+ _Value := reg.ReadString(ExtractFileName(_Path));
304+ Result := True;
305+ finally
306+ reg.CloseKey;
307+ end;
308+ end;
309+ finally
310+ FreeAndNil(reg);
311+ end;
312+end;
313+
314+function TailStr(const _s: string; _Start: integer): string;
315+begin
316+ if _Start > Length(_s) then
317+ Result := ''
318+ else
319+ Result := Copy(_s, _Start, Length(_s) - _Start + 1);
320+end;
321+
322+function ExtractStr(var _Source: string; _Delimiter: char): string;
323+var
324+ p: integer;
325+begin
326+ p := Pos(_Delimiter, _Source);
327+ if p = 0 then begin
328+ Result := _Source;
329+ _Source := '';
330+ end else begin
331+ Result := LeftStr(_Source, p - 1);
332+ _Source := TailStr(_Source, p + 1);
333+ end;
334+end;
335+
336+function TForm_ReadPlacement(_frm: TForm; _Which: TFormPlacementEnum; const _RegistryPath: string;
337+ _HKEY: HKEY = HKEY_CURRENT_USER): boolean;
338+var
339+ s: string;
340+ PosStr: string;
341+ L, t, w, h: integer;
342+begin
343+ try
344+ Result := TRegistry_TryReadString(_RegistryPath, PosStr, _HKEY);
345+ if Result then begin
346+ s := ExtractStr(PosStr, ',');
347+ if not TryStrToInt(s, L) then
348+ Exit;
349+ s := ExtractStr(PosStr, ',');
350+ if not TryStrToInt(s, t) then
351+ Exit;
352+ s := ExtractStr(PosStr, ',');
353+ if not TryStrToInt(s, w) then
354+ Exit;
355+ s := PosStr;
356+ if not TryStrToInt(s, h) then
357+ Exit;
358+
359+ case _Which of
360+ fpePositionOnly: begin
361+ if L <> -1 then
362+ _frm.Left := L;
363+ if t <> -1 then
364+ _frm.Top := t;
365+ end;
366+ fpeSizeOnly: begin
367+ if w <> -1 then
368+ _frm.Width := w;
369+ if h <> -1 then
370+ _frm.Height := h;
371+ end;
372+ fpePosAndSize: begin
373+ if L <> -1 then
374+ _frm.Left := L;
375+ if t <> -1 then
376+ _frm.Top := t;
377+ if w <> -1 then
378+ _frm.Width := w;
379+ if h <> -1 then
380+ _frm.Height := h;
381+ end;
382+ else
383+ Exit;
384+ end;
385+ _frm.Position := poDesigned;
386+ _frm.MakeFullyVisible(nil);
387+ end;
388+ except
389+ Result := False;
390+ end;
391+end;
392+
393+function TForm_ReadPlacement(_frm: TForm; _Which: TFormPlacementEnum;
394+ _HKEY: HKEY = HKEY_CURRENT_USER): boolean; overload;
395+begin
396+ Result := TForm_ReadPlacement(_frm, _Which, TForm_GetPlacementRegistryPath(_frm), _HKEY);
397+end;
398+
399+
400+end.
--- tags/DenkzettelCompanion_0.0.4/src/w_denkzettelcompanion.pas (nonexistent)
+++ tags/DenkzettelCompanion_0.0.4/src/w_denkzettelcompanion.pas (revision 45)
@@ -0,0 +1,116 @@
1+unit w_DenkzettelCompanion;
2+
3+{$mode objfpc}{$H+}
4+
5+interface
6+
7+uses
8+ Windows,
9+ Classes,
10+ SysUtils,
11+ Forms,
12+ Controls,
13+ Menus,
14+ wf_Categories;
15+
16+type
17+
18+ { Tf_DenkzettelCompanion }
19+
20+ Tf_DenkzettelCompanion = class(TForm)
21+ procedure FormCloseQuery(Sender: TObject; var CanClose: boolean);
22+ procedure FormKeyUp(Sender: TObject; var Key: word; Shift: TShiftState);
23+ private
24+ FBasePath: string;
25+ FCategoriesFrame: Tfr_Categories;
26+ public
27+ constructor Create(_Owner: TComponent); override;
28+ destructor Destroy; override;
29+ end;
30+
31+var
32+ f_DenkzettelCompanion: Tf_DenkzettelCompanion;
33+
34+implementation
35+
36+{$R *.lfm}
37+
38+uses
39+ IniFiles,
40+ u_dzLazUtils,
41+ u_dzformutils,
42+ w_Settings;
43+
44+{ Tf_DenkzettelCompanion }
45+
46+constructor Tf_DenkzettelCompanion.Create(_Owner: TComponent);
47+var
48+ Ini: TIniFile;
49+begin
50+ inherited Create(_Owner);
51+
52+ TForm_ReadPlacement(self, fpePosAndSize);
53+ Ini := TIniFile.Create(TApplication_GetDefaultIniFile);
54+ try
55+ FBasePath := Ini.ReadString('common', 'BasePath', TApplication_GetExeDirBS + 'Notes');
56+ finally
57+ FreeAndNil(Ini);
58+ end;
59+
60+ if not DirectoryExists(FBasePath) then begin
61+ if not Tf_Settings.Execute(Self, FBasePath) then
62+ Abort;
63+ if not DirectoryExists(FBasePath) then begin
64+ if not CreateDir(FBasePath) then
65+ raise Exception.Create('Could not create directory.');
66+ end;
67+ end;
68+
69+ FCategoriesFrame := Tfr_Categories.Create(Self);
70+ FCategoriesFrame.Parent := Self;
71+ FCategoriesFrame.Align := alClient;
72+ FCategoriesFrame.Init(FBasePath);
73+end;
74+
75+destructor Tf_DenkzettelCompanion.Destroy;
76+var
77+ Ini: TIniFile;
78+begin
79+ try
80+ Ini := TIniFile.Create(TApplication_GetDefaultIniFile);
81+ try
82+ Ini.WriteString('common', 'BasePath', FBasePath);
83+ finally
84+ FreeAndNil(Ini);
85+ end;
86+ except
87+ // ignore exceptions in destructor
88+ end;
89+ TForm_StorePlacement(self, fpePosAndSize);
90+ inherited Destroy;
91+end;
92+
93+procedure Tf_DenkzettelCompanion.FormCloseQuery(Sender: TObject; var CanClose: boolean);
94+begin
95+ FCategoriesFrame.OnCloseQuery(Sender, CanClose);
96+end;
97+
98+procedure Tf_DenkzettelCompanion.FormKeyUp(Sender: TObject; var Key: word; Shift: TShiftState);
99+begin
100+ if not Assigned(FCategoriesFrame) then
101+ Exit; //==>
102+ if Key = VK_F10 then begin
103+ if shift = [] then begin
104+ FCategoriesFrame.ShowMenu;
105+ Key := 0;
106+ end;
107+ end else if Key = VK_LEFT then begin
108+ if shift = [ssAlt] then
109+ FCategoriesFrame.GoBack;
110+ end else if Key = VK_RIGHT then begin
111+ if shift = [ssAlt] then
112+ FCategoriesFrame.OpenSelected;
113+ end;
114+end;
115+
116+end.
--- tags/DenkzettelCompanion_0.0.4/src/w_selectcolor.pas (nonexistent)
+++ tags/DenkzettelCompanion_0.0.4/src/w_selectcolor.pas (revision 45)
@@ -0,0 +1,120 @@
1+unit w_SelectColor;
2+
3+{$mode objfpc}{$H+}
4+
5+interface
6+
7+uses
8+ Classes,
9+ SysUtils,
10+ FileUtil,
11+ Forms,
12+ Controls,
13+ Graphics,
14+ Dialogs,
15+ ExtCtrls,
16+ u_DenkzettelUtils;
17+
18+type
19+
20+ { Tf_SelectColor }
21+
22+ Tf_SelectColor = class(TForm)
23+ p_White: TPanel;
24+ procedure FormKeyPress(Sender: TObject; var Key: char);
25+ procedure p_WhiteClick(Sender: TObject);
26+ private
27+ FSelectedColor: TDenkzettelColor;
28+ procedure GetValue(out _Color: TDenkzettelColor);
29+ public
30+ class function Execute(_Owner: TWinControl; var _Color: TDenkzettelColor): boolean;
31+ constructor Create(_Owner: TComponent); override;
32+ end;
33+
34+implementation
35+
36+{$R *.lfm}
37+
38+uses
39+ u_dzLazUtils;
40+
41+{ Tf_SelectColor }
42+
43+class function Tf_SelectColor.Execute(_Owner: TWinControl; var _Color: TDenkzettelColor): boolean;
44+var
45+ frm: Tf_SelectColor;
46+begin
47+ frm := Tf_SelectColor.Create(_Owner);
48+ try
49+ TForm_CenterOn(frm, _Owner);
50+ Result := (frm.ShowModal = mrOk);
51+ if Result then
52+ frm.GetValue(_Color);
53+ finally
54+ FreeAndNil(frm);
55+ end;
56+end;
57+
58+constructor Tf_SelectColor.Create(_Owner: TComponent);
59+var
60+ dc: TDenkzettelColor;
61+ pnl: TPanel;
62+ h: integer;
63+ t: integer;
64+begin
65+ inherited Create(_Owner);
66+ p_White.Caption := NoteColorToChar(dcWhite);
67+ p_White.Color := NoteColorToColor(dcWhite, False);
68+
69+ t := p_White.Top;
70+ h := t + p_White.Height;
71+ for dc := Succ(Low(TDenkzettelColor)) to high(TDenkzettelColor) do begin
72+ t := t + h;
73+ pnl := TPanel.Create(Self);
74+ pnl.Parent := Self;
75+ pnl.Top := t;
76+ pnl.Height := p_White.Height;
77+ pnl.Left := p_White.Left;
78+ pnl.Width := p_White.Width;
79+ pnl.Caption := NoteColorToChar(dc);
80+ pnl.Name := '';
81+ pnl.Color := NoteColorToColor(dc, False);
82+ pnl.Tag := Ord(dc);
83+ pnl.OnClick := p_White.OnClick;
84+ end;
85+ Self.Height := t + h;
86+end;
87+
88+procedure Tf_SelectColor.p_WhiteClick(Sender: TObject);
89+begin
90+ FSelectedColor := TDenkzettelColor((Sender as TPanel).Tag);
91+ ModalResult := mrOk;
92+end;
93+
94+procedure Tf_SelectColor.FormKeyPress(Sender: TObject; var Key: char);
95+var
96+ ctrl: TControl;
97+ pnl: TPanel;
98+ i: integer;
99+ c: char;
100+begin
101+ c := UpCase(Key);
102+ for i := 0 to ControlCount - 1 do begin
103+ ctrl := Controls[i];
104+ if ctrl is TPanel then begin
105+ pnl := TPanel(ctrl);
106+ if pnl.Caption = c then begin
107+ pnl.OnClick(pnl);
108+ Exit; //==>
109+ end;
110+ end;
111+ end;
112+end;
113+
114+procedure Tf_SelectColor.GetValue(out _Color: TDenkzettelColor);
115+begin
116+ _Color := FSelectedColor;
117+end;
118+
119+
120+end.
--- tags/DenkzettelCompanion_0.0.4/src/u_dzlazutils.pas (nonexistent)
+++ tags/DenkzettelCompanion_0.0.4/src/u_dzlazutils.pas (revision 45)
@@ -0,0 +1,216 @@
1+unit u_dzLazUtils;
2+
3+{$mode objfpc}{$H+}
4+
5+interface
6+
7+uses
8+ SysUtils,
9+ Types,
10+ Classes,
11+ Controls,
12+ StdCtrls,
13+ Menus,
14+ Forms,
15+ Dialogs;
16+
17+const
18+ TRICOLON = #$E2#$81#$9D; // UTF-8 for #$205D tricolon unicode character
19+
20+procedure EnumDirectories(const _Base: string; _Dirs: TStrings;
21+ _Sorted: boolean = True; _FullName: boolean = True; const _Mask: string = '*');
22+procedure EnumFiles(const _Base: string; const _Mask: string; _Files: TStrings; _Sorted: boolean = True;
23+ _FullName: boolean = True; _AdditionalAttribs: integer = 0); overload;
24+procedure EnumFiles(const _FullMask: string; _Files: TStrings; _Sorted: boolean = True;
25+ _FullName: boolean = True; _AdditionalAttribs: integer = 0); overload;
26+///<summary>
27+/// Find a file matching the mask and return its name. If there are more than one matches, return
28+/// the first.
29+/// @param Mask is the mask the filen name must match
30+/// @param fn is the first file that was found, if any. Only valid if Result >0
31+/// @returns the number of matching files found. </summary>
32+function FindMatchingFile(const _Mask: string; out _fn: string; _FullName: boolean = True): integer;
33+
34+function IsValidFileName(const _Filename: string): boolean;
35+
36+procedure TForm_CenterOn(_frm: TForm; _Owner: TWinControl); overload;
37+function TForm_GetCenter(_frm: TForm): TPoint;
38+
39+function TControl_GetParentFormCenter(_ctrl: TControl): TPoint;
40+
41+procedure TWinControl_SetFocus(_ctrl: TWinControl);
42+
43+function TApplication_GetDefaultIniFile: string;
44+function TApplication_GetExeDir: string;
45+function TApplication_GetExeDirBS: string;
46+
47+procedure TButton_DrowpdownMenu(_btn: TButton; _pm: TPopupMenu);
48+
49+function MessageDlgCentered(_Owner: TWinControl; const aMsg: string; DlgType: TMsgDlgType;
50+ Buttons: TMsgDlgButtons; HelpCtx: longint = 0): TModalResult;
51+
52+implementation
53+
54+function TApplication_GetDefaultIniFile: string;
55+begin
56+ Result := ChangeFileExt(Application.ExeName, '.ini');
57+end;
58+
59+function TApplication_GetExeDir: string;
60+begin
61+ Result := ExtractFileDir(Application.ExeName);
62+end;
63+
64+function TApplication_GetExeDirBS: string;
65+begin
66+ Result := IncludeTrailingPathDelimiter(TApplication_GetExeDir);
67+end;
68+
69+procedure EnumDirectories(const _Base: string; _Dirs: TStrings;
70+ _Sorted: boolean = True; _FullName: boolean = True; const _Mask: string = '*');
71+var
72+ Base: string;
73+ SearchRec: TRawByteSearchRec;
74+ Dirs: TStringList;
75+begin
76+ _Dirs.Clear;
77+ Base := IncludeTrailingPathDelimiter(_Base);
78+ if FindFirst(Base + _Mask, faDirectory, SearchRec) = 0 then begin
79+ Dirs := TStringList.Create;
80+ try
81+ if not _FullName then
82+ base := '';
83+ repeat
84+ if (SearchRec.Attr and faDirectory) <> 0 then
85+ if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then begin
86+ Dirs.Add(Base + SearchRec.Name);
87+ end;
88+ until FindNext(SearchRec) <> 0;
89+ if _Sorted then
90+ Dirs.Sort;
91+ _Dirs.Assign(Dirs);
92+ finally
93+ FreeAndNil(Dirs);
94+ FindClose(SearchRec);
95+ end;
96+ end;
97+end;
98+
99+procedure EnumFiles(const _Base: string; const _Mask: string; _Files: TStrings; _Sorted: boolean = True;
100+ _FullName: boolean = True; _AdditionalAttribs: integer = 0);
101+begin
102+ EnumFiles(IncludeTrailingPathDelimiter(_Base) + _Mask, _Files, _Sorted, _FullName, _AdditionalAttribs);
103+end;
104+
105+procedure EnumFiles(const _FullMask: string; _Files: TStrings; _Sorted: boolean = True;
106+ _FullName: boolean = True; _AdditionalAttribs: integer = 0);
107+var
108+ SearchRec: TRawbyteSearchRec;
109+ Files: TStringList;
110+ Base: string;
111+begin
112+ _Files.Clear;
113+ if FindFirst(_FullMask, faArchive + _AdditionalAttribs, SearchRec) = 0 then begin
114+ Files := TStringList.Create;
115+ try
116+ if _FullName then begin
117+ Base := ExtractFileDir(_FullMask);
118+ Base := IncludeTrailingPathDelimiter(Base);
119+ end else
120+ base := '';
121+ repeat
122+ if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then begin
123+ Files.Add(Base + SearchRec.Name);
124+ end;
125+ until FindNext(SearchRec) <> 0;
126+ if _Sorted then
127+ Files.Sort;
128+ _Files.Assign(Files);
129+ finally
130+ FreeAndNil(Files);
131+ FindClose(SearchRec);
132+ end;
133+ end;
134+end;
135+
136+function FindMatchingFile(const _Mask: string; out _fn: string; _FullName: boolean = True): integer;
137+var
138+ Files: TStringList;
139+begin
140+ Files := TStringList.Create;
141+ try
142+ EnumFiles(_Mask, Files, True, _FullName);
143+ Result := Files.Count;
144+ if Result > 0 then
145+ _fn := Files[0];
146+ finally
147+ FreeAndNil(Files);
148+ end;
149+end;
150+
151+procedure TForm_CenterOn(_frm: TForm; _Owner: TWinControl);
152+var
153+ Center: TPoint;
154+begin
155+ Center := _Owner.ClientToScreen(Point(_Owner.Width div 2, _Owner.Height div 2));
156+ _frm.Left := Center.X - _frm.Width div 2;
157+ _frm.Top := Center.Y - _frm.Height div 2;
158+end;
159+
160+function TForm_GetCenter(_frm: TForm): TPoint;
161+begin
162+ Result := _frm.ClientToScreen(Point(_frm.Width div 2, _frm.Height div 2));
163+end;
164+
165+function TControl_GetParentFormCenter(_ctrl: TControl): TPoint;
166+begin
167+ Result := _ctrl.ClientToScreen(Point(_ctrl.Width div 2, _ctrl.Height div 2));
168+end;
169+
170+procedure TWinControl_SetFocus(_ctrl: TWinControl);
171+begin
172+ try
173+ if _ctrl.CanSetFocus then
174+ _ctrl.SetFocus
175+ except
176+ on e: EInvalidOperation do
177+ ; // ignore
178+ end;
179+end;
180+
181+procedure TButton_DrowpdownMenu(_btn: TButton; _pm: TPopupMenu);
182+var
183+ pnt: Types.TPoint;
184+begin
185+ pnt := _btn.ClientToScreen(Point(0, _btn.Height));
186+ _pm.PopUp(pnt.x, pnt.y);
187+end;
188+
189+function MessageDlgCentered(_Owner: TWinControl; const aMsg: string; DlgType: TMsgDlgType;
190+ Buttons: TMsgDlgButtons; HelpCtx: longint): TModalResult;
191+var
192+ Center: TPoint;
193+begin
194+ Center := TControl_GetParentFormCenter(_Owner);
195+ Result := MessageDlgPos(aMsg, DlgType, Buttons, HelpCtx, Center.x, Center.y);
196+end;
197+
198+function IsValidFileName(const _Filename: string): boolean;
199+const
200+ InvalidCharacters: set of char = ['\', '/', ':', '*', '?', '"', '<', '>', '|', #9, #13, #10];
201+var
202+ c: char;
203+begin
204+ Result := _Filename <> '';
205+
206+ if Result then begin
207+ for c in _Filename do begin
208+ Result := not (c in InvalidCharacters);
209+ if not Result then break;
210+ end;
211+ end;
212+end;
213+
214+end.
215+
216+
--- tags/DenkzettelCompanion_0.0.4/src/wf_categories.pas (nonexistent)
+++ tags/DenkzettelCompanion_0.0.4/src/wf_categories.pas (revision 45)
@@ -0,0 +1,234 @@
1+unit wf_Categories;
2+
3+{$mode objfpc}{$H+}
4+
5+interface
6+
7+uses
8+ Classes,
9+ SysUtils,
10+ FileUtil,
11+ Forms,
12+ Controls,
13+ StdCtrls,
14+ ExtCtrls,
15+ Menus,
16+ wf_Notes,
17+ Types;
18+
19+type
20+
21+ { Tfr_Categories }
22+
23+ Tfr_Categories = class(TFrame)
24+ b_Menu: TButton;
25+ b_NewCategory: TButton;
26+ lb_Categories: TListBox;
27+ l_NoNotes: TLabel;
28+ mi_About: TMenuItem;
29+ mi_Configure: TMenuItem;
30+ mi_NewCategory: TMenuItem;
31+ pm_Main: TPopupMenu;
32+ P_Categories: TPanel;
33+ p_Main: TPanel;
34+ p_NoCategories: TPanel;
35+ procedure b_MenuClick(Sender: TObject);
36+ procedure FrameEnter(Sender: TObject);
37+ procedure FrameResize(Sender: TObject);
38+ procedure lb_CategoriesDrawItem(Control: TWinControl; Index: integer;
39+ ARect: TRect; State: TOwnerDrawState);
40+ procedure mi_AboutClick(Sender: TObject);
41+ procedure mi_NewCategoryClick(Sender: TObject);
42+ procedure mi_ConfigureClick(Sender: TObject);
43+ procedure lb_CategoriesDblClick(Sender: TObject);
44+ procedure lb_CategoriesKeyPress(Sender: TObject; var Key: char);
45+ private
46+ FBasePath: ^string;
47+ FNotesFrame: Tfr_Notes;
48+ function BasePathBS: string;
49+ function TryGetCategory(out _Category: string): boolean;
50+ procedure OnCloseCategory(_Sender: TObject);
51+ public
52+ constructor Create(_Owner: TComponent); override;
53+ procedure Init(var _BasePath: string);
54+ procedure GoBack;
55+ procedure OpenSelected;
56+ procedure ShowMenu;
57+ procedure OnCloseQuery(_Sender: TObject; var _CanClose: boolean);
58+ end;
59+
60+implementation
61+
62+{$R *.lfm}
63+
64+uses
65+ Graphics,
66+ LCLType,
67+ u_dzLazUtils,
68+ u_DenkzettelUtils,
69+ w_NewCategory,
70+ w_Settings,
71+ w_About;
72+
73+{ Tfr_Categories }
74+
75+constructor Tfr_Categories.Create(_Owner: TComponent);
76+begin
77+ inherited Create(_Owner);
78+
79+ b_Menu.Caption := TRICOLON;
80+
81+ FNotesFrame := Tfr_Notes.Create(Self);
82+ FNotesFrame.Visible := False;
83+ FNotesFrame.Parent := Self;
84+ FNotesFrame.Align := alClient;
85+ FNotesFrame.OnClose := @OnCloseCategory;
86+end;
87+
88+procedure Tfr_Categories.Init(var _BasePath: string);
89+begin
90+ FBasePath := @_BasePath;
91+
92+ EnumDirectories(BasePathBS, lb_Categories.Items, True, False);
93+ p_NoCategories.Visible := (lb_Categories.Count = 0);
94+ TWinControl_SetFocus(lb_Categories);
95+end;
96+
97+procedure Tfr_Categories.OnCloseQuery(_Sender: TObject; var _CanClose: boolean);
98+begin
99+ if not FNotesFrame.Visible then
100+ Exit; //==>
101+ FNotesFrame.FormCloseQuery(_Sender, _CanClose);
102+end;
103+
104+procedure Tfr_Categories.OpenSelected;
105+var
106+ Category: string;
107+begin
108+ if not Assigned(FNotesFrame) then
109+ Exit; //==>
110+ if FNotesFrame.Visible then
111+ FNotesFrame.OpenSelected
112+ else begin
113+ if not TryGetCategory(Category) then
114+ Exit; //==>
115+ FNotesFrame.Init(Category, BasePathBS + Category, lb_Categories.Items);
116+ FNotesFrame.Visible := True;
117+ p_Main.Visible := False;
118+ end;
119+end;
120+
121+procedure Tfr_Categories.lb_CategoriesDblClick(Sender: TObject);
122+begin
123+ OpenSelected;
124+end;
125+
126+procedure Tfr_Categories.lb_CategoriesKeyPress(Sender: TObject; var Key: char);
127+begin
128+ if Key in [#13, #10] then
129+ OpenSelected;
130+end;
131+
132+procedure Tfr_Categories.mi_AboutClick(Sender: TObject);
133+begin
134+ Tf_About.Execute(Self);
135+end;
136+
137+procedure Tfr_Categories.GoBack;
138+begin
139+ if Assigned(FNotesFrame) and FNotesFrame.Visible then
140+ FNotesFrame.GoBack;
141+end;
142+
143+procedure Tfr_Categories.ShowMenu;
144+begin
145+ if Assigned(FNotesFrame) and FNotesFrame.Visible then
146+ FNotesFrame.ShowMenu
147+ else begin
148+ TButton_DrowpdownMenu(b_Menu, pm_Main);
149+ end;
150+end;
151+
152+procedure Tfr_Categories.b_MenuClick(Sender: TObject);
153+begin
154+ ShowMenu;
155+end;
156+
157+procedure Tfr_Categories.FrameEnter(Sender: TObject);
158+begin
159+ TWinControl_SetFocus(lb_Categories);
160+ if lb_Categories.ItemIndex = -1 then
161+ if lb_Categories.Items.Count > 0 then
162+ lb_Categories.ItemIndex := 0;
163+end;
164+
165+procedure Tfr_Categories.FrameResize(Sender: TObject);
166+var
167+ w, h: integer;
168+begin
169+ w := lb_Categories.Width;
170+ w := w - p_NoCategories.Width;
171+ p_NoCategories.Left := lb_Categories.Left + w div 2;
172+ h := lb_Categories.Height;
173+ h := h - p_NoCategories.Height;
174+ p_NoCategories.Top := lb_Categories.Top + h div 2;
175+end;
176+
177+procedure Tfr_Categories.lb_CategoriesDrawItem(Control: TWinControl;
178+ Index: integer; ARect: TRect; State: TOwnerDrawState);
179+var
180+ lb: TListBox absolute Control;
181+ cnv: TCanvas;
182+ s: string;
183+begin
184+ s := lb.Items[Index];
185+ cnv := lb.Canvas;
186+
187+ cnv.Brush.Color := NoteColorToColor(dcWhite, (odSelected in State));
188+ cnv.FillRect(ARect);
189+ if odSelected in State then
190+ cnv.TextRect(ARect, arect.Left, arect.Top, '>');
191+ cnv.TextRect(ARect, ARect.Left + 10, ARect.Top, s);
192+
193+ // Focus rect is drawn automatically
194+end;
195+
196+procedure Tfr_Categories.mi_NewCategoryClick(Sender: TObject);
197+var
198+ NewCategory: string;
199+begin
200+ if Tf_NewCategory.Execute(Self, BasePathBS, NewCategory) then
201+ Init(FBasePath^);
202+end;
203+
204+procedure Tfr_Categories.mi_ConfigureClick(Sender: TObject);
205+begin
206+ if Tf_Settings.Execute(self, FBasePath^) then
207+ Init(FBasePath^);
208+end;
209+
210+function Tfr_Categories.BasePathBS: string;
211+begin
212+ Result := IncludeTrailingPathDelimiter(FBasePath^);
213+end;
214+
215+function Tfr_Categories.TryGetCategory(out _Category: string): boolean;
216+var
217+ Idx: integer;
218+begin
219+ Result := False;
220+ Idx := lb_Categories.ItemIndex;
221+ if Idx = -1 then
222+ Exit; //==>
223+ _Category := lb_Categories.Items[Idx];
224+ Result := (_Category <> '');
225+end;
226+
227+procedure Tfr_Categories.OnCloseCategory(_Sender: TObject);
228+begin
229+ FNotesFrame.Visible := False;
230+ p_Main.Visible := True;
231+ TWinControl_SetFocus(lb_Categories);
232+end;
233+
234+end.
--- tags/DenkzettelCompanion_0.0.4/src/wf_notes.pas (nonexistent)
+++ tags/DenkzettelCompanion_0.0.4/src/wf_notes.pas (revision 45)
@@ -0,0 +1,358 @@
1+unit wf_Notes;
2+
3+{$mode objfpc}{$H+}
4+
5+interface
6+
7+uses
8+ Classes,
9+ SysUtils,
10+ Types,
11+ FileUtil,
12+ Forms,
13+ Controls,
14+ StdCtrls,
15+ ExtCtrls,
16+ Menus,
17+ wf_NoteEditor;
18+
19+type
20+
21+ { Tfr_Notes }
22+
23+ Tfr_Notes = class(TFrame)
24+ b_NewChecklist: TButton;
25+ b_NewNote: TButton;
26+ b_Menu: TButton;
27+ l_NoNotes: TLabel;
28+ mi_Move: TMenuItem;
29+ mi_Delete: TMenuItem;
30+ mi_NewChecklist: TMenuItem;
31+ p_NoNotes: TPanel;
32+ pm_Main: TPopupMenu;
33+ mi_About: TMenuItem;
34+ mi_NewNote: TMenuItem;
35+ b_Back: TButton;
36+ lb_Notes: TListBox;
37+ p_Main: TPanel;
38+ p_Top: TPanel;
39+ procedure FrameEnter(Sender: TObject);
40+ procedure FrameResize(Sender: TObject);
41+ procedure lb_NotesDrawItem(Control: TWinControl; Index: integer;
42+ ARect: TRect; State: TOwnerDrawState);
43+ procedure mi_AboutClick(Sender: TObject);
44+ procedure b_BackClick(Sender: TObject);
45+ procedure b_MenuClick(Sender: TObject);
46+ procedure mi_DeleteClick(Sender: TObject);
47+ procedure mi_NewChecklistClick(Sender: TObject);
48+ procedure mi_NewNoteClick(Sender: TObject);
49+ procedure lb_NotesDblClick(Sender: TObject);
50+ procedure lb_NotesKeyPress(Sender: TObject; var Key: char);
51+ private
52+ FCategory: string;
53+ FCategoryPathBS: string;
54+ FOnClose: TNotifyEvent;
55+ FEditFrame: Tfr_NoteEditor;
56+ FCategories: TStrings;
57+ procedure doOnClose;
58+ procedure mi_MoveToCategoryClick(_Sender: TObject);
59+ procedure OnCloseNote(_Sender: TObject);
60+ function TryGetNoteFn(out _fn: string): boolean;
61+ public
62+ constructor Create(_Owner: TComponent); override;
63+ destructor Destroy; override;
64+ procedure Init(const _Category: string; const _CategoryPath: string; _Categories: TStrings);
65+ procedure FormCloseQuery(_Sender: TObject; var _CanClose: boolean);
66+ procedure GoBack;
67+ procedure OpenSelected;
68+ procedure ShowMenu;
69+ property OnClose: TNotifyEvent read FOnClose write FOnClose;
70+ end;
71+
72+implementation
73+
74+{$R *.lfm}
75+
76+uses
77+ Graphics,
78+ Dialogs,
79+ LCLType,
80+ u_dzLazUtils,
81+ u_DenkzettelUtils,
82+ w_About;
83+
84+{ Tfr_Notes }
85+
86+constructor Tfr_Notes.Create(_Owner: TComponent);
87+begin
88+ inherited Create(_Owner);
89+
90+ b_Menu.Caption := TRICOLON;
91+
92+ FCategories := TStringList.Create;
93+
94+ FEditFrame := Tfr_NoteEditor.Create(Self);
95+ FEditFrame.Visible := False;
96+ FEditFrame.Parent := Self;
97+ FEditFrame.Align := alClient;
98+ FEditFrame.OnClose := @OnCloseNote;
99+end;
100+
101+destructor Tfr_Notes.Destroy;
102+begin
103+ FreeAndNil(FCategories);
104+ inherited Destroy;
105+end;
106+
107+procedure Tfr_Notes.Init(const _Category: string; const _CategoryPath: string; _Categories: TStrings);
108+var
109+ Files: TStringList;
110+ i: integer;
111+ fn, Title: string;
112+ IsChecklist: boolean;
113+ NoteColor: TDenkzettelColor;
114+ mi: TMenuItem;
115+begin
116+ FCategory := _Category;
117+ FCategoryPathBS := IncludeTrailingPathDelimiter(_CategoryPath);
118+ if Assigned(_Categories) then begin
119+ FCategories.Assign(_Categories);
120+ mi_Move.Clear;
121+ for i := 0 to FCategories.Count - 1 do begin
122+ mi := TMenuItem.Create(mi_Move);
123+ mi.Caption := FCategories[i];
124+ mi.OnClick := @mi_MoveToCategoryClick;
125+ mi_Move.Add(mi);
126+ end;
127+ end;
128+
129+
130+ p_Top.Caption := _Category;
131+
132+ lb_Notes.Items.Clear;
133+ Files := TStringList.Create;
134+ try
135+ EnumFiles(FCategoryPathBS, '*.txt', Files, True, False);
136+ for i := 0 to Files.Count - 1 do begin
137+ fn := files[i];
138+ if not DecodeFilename(fn, Title, IsChecklist, NoteColor) then
139+ Title := fn;
140+ lb_Notes.Items.AddObject(Title, TObject(PropertiesToPointer(NoteColor, IsChecklist)));
141+ end;
142+ p_NoNotes.Visible := (Files.Count = 0);
143+ finally
144+ FreeAndNil(Files);
145+ end;
146+ TWinControl_SetFocus(lb_Notes);
147+end;
148+
149+procedure Tfr_Notes.OnCloseNote(_Sender: TObject);
150+begin
151+ FEditFrame.Visible := False;
152+ p_Main.Visible := True;
153+ Init(FCategory, FCategoryPathBS, nil);
154+end;
155+
156+procedure Tfr_Notes.FormCloseQuery(_Sender: TObject; var _CanClose: boolean);
157+begin
158+ if not FEditFrame.Visible then
159+ Exit; //==>
160+ FEditFrame.FormCloseQuery(_Sender, _CanClose);
161+end;
162+
163+function Tfr_Notes.TryGetNoteFn(out _fn: string): boolean;
164+var
165+ Idx: integer;
166+ s: string;
167+begin
168+ Result := False;
169+ Idx := lb_Notes.ItemIndex;
170+ if Idx = -1 then
171+ Exit; //==>
172+ s := lb_Notes.Items[Idx];
173+ if s = '' then
174+ Exit; //==>
175+ Result := FindMatchingFile(FCategoryPathBS + s + '*.*', _fn, False) > 0;
176+end;
177+
178+procedure Tfr_Notes.doOnClose;
179+begin
180+ if Assigned(FOnClose) then
181+ FOnClose(Self);
182+end;
183+
184+procedure Tfr_Notes.OpenSelected;
185+var
186+ fn: string;
187+begin
188+ if not Assigned(FEditFrame) then
189+ Exit; //==>
190+ if not TryGetNoteFn(fn) then
191+ Exit; //==>
192+ FEditFrame.Init(FCategoryPathBS, fn);
193+ FEditFrame.Visible := True;
194+ p_Main.Visible := False;
195+end;
196+
197+procedure Tfr_Notes.lb_NotesDblClick(Sender: TObject);
198+begin
199+ OpenSelected;
200+end;
201+
202+procedure Tfr_Notes.lb_NotesKeyPress(Sender: TObject; var Key: char);
203+begin
204+ if Key in [#13, #10] then
205+ OpenSelected;
206+end;
207+
208+procedure Tfr_Notes.b_BackClick(Sender: TObject);
209+begin
210+ doOnClose;
211+end;
212+
213+procedure Tfr_Notes.GoBack;
214+begin
215+ if Assigned(FEditFrame) and FEditFrame.Visible then
216+ FEditFrame.GoBack
217+ else begin
218+ doOnClose;
219+ end;
220+end;
221+
222+procedure Tfr_Notes.ShowMenu;
223+begin
224+ if Assigned(FEditFrame) and FEditFrame.Visible then
225+ FEditFrame.ShowMenu
226+ else begin
227+ TButton_DrowpdownMenu(b_Menu, pm_Main);
228+ end;
229+end;
230+
231+procedure Tfr_Notes.b_MenuClick(Sender: TObject);
232+begin
233+ ShowMenu;
234+end;
235+
236+procedure Tfr_Notes.mi_DeleteClick(Sender: TObject);
237+var
238+ Note: string;
239+begin
240+ if not TryGetNoteFn(Note) then
241+ Exit; //==>
242+ if mrYes = MessageDlgCentered(Self, 'Delete this note?', mtConfirmation, [mbYes, mbCancel], 0) then begin
243+ if not DeleteFile(FCategoryPathBS + Note) then
244+ raise Exception.Create('Failed to delete file.');
245+ Init(FCategory, FCategoryPathBS, nil);
246+ end;
247+end;
248+
249+procedure Tfr_Notes.mi_NewChecklistClick(Sender: TObject);
250+begin
251+ FEditFrame.Init(FCategoryPathBS, '#L#');
252+ FEditFrame.Visible := True;
253+ p_Main.Visible := False;
254+end;
255+
256+procedure Tfr_Notes.mi_NewNoteClick(Sender: TObject);
257+begin
258+ FEditFrame.Init(FCategoryPathBS, '');
259+ FEditFrame.Visible := True;
260+ p_Main.Visible := False;
261+end;
262+
263+procedure Tfr_Notes.mi_AboutClick(Sender: TObject);
264+begin
265+ Tf_About.Execute(Self);
266+end;
267+
268+// for whatever reason menus.pp does not have StripHotKey
269+// (even though it was added in may 2016, but that's probably not the main repository
270+// https://github.com/alrieckert/lazarus/commit/8919d979e8cd628d1af2035fd9d230c69150c3cf
271+function StripHotkey(const Text: string): string;
272+var
273+ I, R: integer;
274+begin
275+ SetLength(Result, Length(Text));
276+ I := 1;
277+ R := 1;
278+ while I <= Length(Text) do begin
279+ if Text[I] = cHotkeyPrefix then begin
280+ if (I < Length(Text)) and (Text[I + 1] = cHotkeyPrefix) then begin
281+ Result[R] := Text[I];
282+ Inc(R);
283+ Inc(I, 2);
284+ end else
285+ Inc(I);
286+ end else begin
287+ Result[R] := Text[I];
288+ Inc(R);
289+ Inc(I);
290+ end;
291+ end;
292+ SetLength(Result, R - 1);
293+end;
294+
295+procedure Tfr_Notes.mi_MoveToCategoryClick(_Sender: TObject);
296+var
297+ Category: string;
298+ Path, fn: string;
299+begin
300+ if not TryGetNoteFn(fn) then
301+ Exit; //==>
302+
303+ Category := (_Sender as tMenuItem).Caption;
304+ Category := StripHotkey(Category);
305+
306+ Path := ExcludeTrailingPathDelimiter(FCategoryPathBS);
307+ Path := ExtractFileDir(path);
308+ Path := IncludeTrailingPathDelimiter(Path) + Category;
309+ Path := IncludeTrailingPathDelimiter(Path);
310+ if not RenameFile(FCategoryPathBS+fn, Path+fn) then
311+ raise Exception.Create('Moving the note failed.');
312+ Init(FCategory, FCategoryPathBS, nil);
313+end;
314+
315+procedure Tfr_Notes.FrameEnter(Sender: TObject);
316+begin
317+ TWinControl_SetFocus(lb_Notes);
318+ if lb_Notes.ItemIndex = -1 then
319+ if lb_Notes.Items.Count > 0 then
320+ lb_Notes.ItemIndex := 0;
321+end;
322+
323+procedure Tfr_Notes.FrameResize(Sender: TObject);
324+var
325+ w, h: integer;
326+begin
327+ w := lb_Notes.Width;
328+ w := w - p_NoNotes.Width;
329+ p_NoNotes.Left := lb_Notes.Left + w div 2;
330+ h := lb_Notes.Height;
331+ h := h - p_NoNotes.Height;
332+ p_NoNotes.Top := lb_Notes.Top + h div 2;
333+end;
334+
335+procedure Tfr_Notes.lb_NotesDrawItem(Control: TWinControl; Index: integer;
336+ ARect: TRect; State: TOwnerDrawState);
337+var
338+ lb: TListBox absolute Control;
339+ NoteColor: TDenkzettelColor;
340+ IsChecklist: boolean;
341+ cnv: TCanvas;
342+ s: string;
343+begin
344+ s := lb.Items[Index];
345+ PointerToProperties(lb.Items.Objects[Index], NoteColor, IsChecklist);
346+ cnv := lb.Canvas;
347+
348+ cnv.Brush.Color := NoteColorToColor(NoteColor, odSelected in State);
349+ cnv.FillRect(ARect);
350+
351+ if odSelected in State then
352+ cnv.TextRect(ARect, arect.Left, arect.Top, '>');
353+ cnv.TextRect(ARect, ARect.Left + 10, ARect.Top, s);
354+
355+ // Focus rect is drawn automatically
356+end;
357+
358+end.
--- tags/DenkzettelCompanion_0.0.4/src/wf_noteeditor.pas (nonexistent)
+++ tags/DenkzettelCompanion_0.0.4/src/wf_noteeditor.pas (revision 45)
@@ -0,0 +1,420 @@
1+unit wf_NoteEditor;
2+
3+{$mode objfpc}{$H+}
4+
5+interface
6+
7+uses
8+ Classes,
9+ SysUtils,
10+ FileUtil,
11+ Forms,
12+ Controls,
13+ StdCtrls,
14+ ExtCtrls,
15+ Menus,
16+ CheckLst,
17+ u_DenkzettelUtils;
18+
19+type
20+ TNoteDisplay = (ndMemo, ndChecklist);
21+
22+ { Tfr_NoteEditor }
23+
24+ Tfr_NoteEditor = class(TFrame)
25+ b_AddChecklistItem: TButton;
26+ b_Back: TButton;
27+ b_Menu: TButton;
28+ clb_Content: TCheckListBox;
29+ ed_NewChecklistItem: TEdit;
30+ ed_Title: TEdit;
31+ l_Message: TLabel;
32+ mi_Delete: TMenuItem;
33+ mi_Line: TMenuItem;
34+ mi_Revert: TMenuItem;
35+ mi_Save: TMenuItem;
36+ mi_ChangeColor: TMenuItem;
37+ mi_ToggleChecklist: TMenuItem;
38+ m_Content: TMemo;
39+ Panel1: TPanel;
40+ p_Checklist: TPanel;
41+ pm_Main: TPopupMenu;
42+ p_Top: TPanel;
43+ procedure b_AddChecklistItemClick(Sender: TObject);
44+ procedure b_BackClick(Sender: TObject);
45+ procedure b_MenuClick(Sender: TObject);
46+ procedure ed_NewChecklistItemEnter(Sender: TObject);
47+ procedure ed_NewChecklistItemExit(Sender: TObject);
48+ procedure ed_TitleChange(Sender: TObject);
49+ procedure FrameEnter(Sender: TObject);
50+ procedure mi_ChangeColorClick(Sender: TObject);
51+ procedure mi_DeleteClick(Sender: TObject);
52+ procedure mi_RevertClick(Sender: TObject);
53+ procedure mi_SaveClick(Sender: TObject);
54+ procedure mi_ToggleChecklistClick(Sender: TObject);
55+ private
56+ FControls: array[TNoteDisplay] of TControl;
57+ FPathBS: string;
58+ FFilenameOnly: string;
59+ FOnClose: TNotifyEvent;
60+ FOrigContent: string;
61+ FNoteColor: TDenkzettelColor;
62+ function BuildFilename: string;
63+ function IsChecklist: boolean;
64+ function ContentHasChanged: boolean;
65+ procedure doOnClose;
66+ procedure GetContent(out _s: string);
67+ procedure SetContent(const _s: string);
68+ procedure SaveNote;
69+ procedure SwitchDisplay(_Display: TNoteDisplay);
70+ public
71+ constructor Create(_Owner: TComponent); override;
72+ procedure Init(const _Path: string; const _FilenameOnly: string);
73+ procedure FormCloseQuery(_Sender: TObject; var _CanClose: boolean);
74+ procedure GoBack;
75+ procedure ShowMenu;
76+ property OnClose: TNotifyEvent read FOnClose write FOnClose;
77+ end;
78+
79+implementation
80+
81+{$R *.lfm}
82+
83+uses
84+ Dialogs,
85+ Graphics,
86+ strutils,
87+ u_dzLazUtils,
88+ w_SelectColor;
89+
90+{ Tfr_NoteEditor }
91+
92+constructor Tfr_NoteEditor.Create(_Owner: TComponent);
93+begin
94+ inherited Create(_Owner);
95+
96+ b_Menu.Caption := TRICOLON;
97+ FControls[ndMemo] := m_Content;
98+ FControls[ndChecklist] := p_Checklist;
99+end;
100+
101+procedure Tfr_NoteEditor.Init(const _Path: string; const _FilenameOnly: string);
102+var
103+ Title: string;
104+ lIsCheckList: boolean;
105+ sl: TStringList;
106+ cl: TColor;
107+ s: string;
108+begin
109+ s := ExcludeTrailingPathDelimiter(_Path);
110+ Assert(s <> '');
111+ l_Message.Visible := False;
112+ FPathBS := IncludeTrailingPathDelimiter(s);
113+ FFilenameOnly := _FilenameOnly;
114+ DecodeFilename(FFilenameOnly, Title, lIsCheckList, FNoteColor);
115+ if Title <> '' then begin
116+ ed_Title.Text := Title;
117+ cl := NoteColorToColor(FNoteColor, False);
118+ ed_Title.Color := cl;
119+ m_Content.Color := cl;
120+ if lIsCheckList then
121+ SwitchDisplay(ndChecklist)
122+ else
123+ SwitchDisplay(ndMemo);
124+ sl := TStringList.Create;
125+ try
126+ sl.LoadFromFile(FPathBS + FFilenameOnly);
127+ FOrigContent := sl.Text;
128+ SetContent(FOrigContent);
129+ finally
130+ FreeAndNil(sl);
131+ end;
132+ end else begin
133+ if lIsCheckList then begin
134+ ed_Title.Text := 'New Checklist';
135+ SwitchDisplay(ndChecklist);
136+ end else begin
137+ ed_Title.Text := 'New Note';
138+ SwitchDisplay(ndMemo);
139+ end;
140+ SetContent('');
141+ end;
142+end;
143+
144+procedure Tfr_NoteEditor.doOnClose;
145+var
146+ CanClose: boolean;
147+begin
148+ CanClose := True;
149+ FormCloseQuery(Self, CanClose);
150+ if CanClose then begin
151+ if Assigned(FOnClose) then
152+ FOnClose(Self);
153+ end;
154+end;
155+
156+procedure Tfr_NoteEditor.b_BackClick(Sender: TObject);
157+begin
158+ GoBack;
159+end;
160+
161+procedure Tfr_NoteEditor.b_AddChecklistItemClick(Sender: TObject);
162+var
163+ s: TCaption;
164+begin
165+ s := ed_NewChecklistItem.Text;
166+ clb_Content.Items.Add(s);
167+ ed_NewChecklistItem.Text := '';
168+ TWinControl_SetFocus(ed_NewChecklistItem);
169+end;
170+
171+procedure Tfr_NoteEditor.b_MenuClick(Sender: TObject);
172+begin
173+ ShowMenu;
174+end;
175+
176+procedure Tfr_NoteEditor.ed_NewChecklistItemEnter(Sender: TObject);
177+begin
178+ b_AddChecklistItem.Default := True;
179+end;
180+
181+procedure Tfr_NoteEditor.ed_NewChecklistItemExit(Sender: TObject);
182+begin
183+ b_AddChecklistItem.Default := False;
184+end;
185+
186+procedure Tfr_NoteEditor.ed_TitleChange(Sender: TObject);
187+var
188+ fn: string;
189+begin
190+ l_Message.Visible := False;
191+ if ed_Title.Text = '' then
192+ Exit;//==>
193+ fn := BuildFilename;
194+ if not IsValidFileName(fn) then begin
195+ l_Message.Caption := 'Warning: This note title is not a valid file name.';
196+ l_Message.Visible := True;
197+ Exit; //==>
198+ end;
199+ if FFilenameOnly = '' then begin
200+ if FileExists(FPathBS + fn) then begin
201+ l_Message.Caption := 'Warning: A note with this title already exists.';
202+ l_Message.Visible := True;
203+ Exit; //==>
204+ end;
205+ end;
206+ // todo: Maybe create the file in order to be sure it is a valid file name?
207+end;
208+
209+procedure Tfr_NoteEditor.FrameEnter(Sender: TObject);
210+begin
211+ if FFilenameOnly <> '' then
212+ TWinControl_SetFocus(m_Content)
213+ else
214+ TWinControl_SetFocus(ed_Title);
215+end;
216+
217+procedure Tfr_NoteEditor.mi_ChangeColorClick(Sender: TObject);
218+var
219+ dc: TDenkzettelColor;
220+ cl: TColor;
221+begin
222+ dc := dcWhite;
223+ if Tf_SelectColor.Execute(Self, dc) then begin
224+ FNoteColor := dc;
225+ cl := NoteColorToColor(dc, False);
226+ ed_Title.Color := cl;
227+ m_Content.Color := cl;
228+ end;
229+end;
230+
231+procedure Tfr_NoteEditor.mi_DeleteClick(Sender: TObject);
232+begin
233+ if FFilenameOnly = '' then
234+ Exit; //==>
235+ if mrYes = MessageDlgCentered(Self, 'Delete this note?', mtConfirmation, [mbYes, mbCancel], 0) then begin
236+ if not DeleteFile(FPathBS + FFilenameOnly) then
237+ raise Exception.Create('Failed to delete file.');
238+ if Assigned(FOnClose) then
239+ FOnClose(Self);
240+ end;
241+end;
242+
243+procedure Tfr_NoteEditor.mi_RevertClick(Sender: TObject);
244+begin
245+ if ContentHasChanged then
246+ if mrYes = MessageDlgCentered(Self, 'Revert your changes?', mtConfirmation, [mbYes, mbCancel], 0) then begin
247+ Init(FPathBS, FFilenameOnly);
248+ end;
249+end;
250+
251+procedure Tfr_NoteEditor.mi_SaveClick(Sender: TObject);
252+begin
253+ SaveNote;
254+end;
255+
256+procedure Tfr_NoteEditor.SwitchDisplay(_Display: TNoteDisplay);
257+var
258+ s: string;
259+begin
260+ GetContent(s);
261+ m_Content.Visible := False;
262+ p_Checklist.Visible := False;
263+ FControls[_Display].Visible := True;;
264+ SetContent(s);
265+
266+ TWinControl_SetFocus(m_Content);
267+end;
268+
269+procedure Tfr_NoteEditor.GetContent(out _s: string);
270+var
271+ i: integer;
272+ s: string;
273+ sl: TStringList;
274+begin
275+ sl := TStringList.Create;
276+ try
277+ if m_Content.Visible then begin
278+ sl.Assign(m_Content.Lines);
279+ end else if p_Checklist.Visible then begin
280+ for i := 0 to clb_Content.Items.Count - 1 do begin
281+ s := clb_Content.Items[i];
282+ if clb_Content.Checked[i] then
283+ s := '- ' + s
284+ else
285+ s := '+ ' + s;
286+ sl.Add(s);
287+ end;
288+ end else
289+ raise Exception.Create('Either the memo or the checklist must be visible');
290+ _s := sl.Text;
291+ finally
292+ FreeAndNil(sl)
293+ end;
294+end;
295+
296+procedure Tfr_NoteEditor.SetContent(const _s: string);
297+var
298+ i, Idx: integer;
299+ s: string;
300+ sl: TStringList;
301+begin
302+ sl := TStringList.Create;
303+ try
304+ sl.Text := _s;
305+ if m_Content.Visible then begin
306+ m_Content.Lines.Assign(sl);
307+ end else if p_Checklist.Visible then begin
308+ clb_Content.Items.Clear;
309+ for i := 0 to sl.Count - 1 do begin
310+ s := sl[i];
311+ if s <> '' then begin
312+ if AnsiStartsText('+ ', s) then begin
313+ Idx := clb_Content.Items.Add(Copy(s, 3));
314+ end else if AnsiStartsText('- ', s) then begin
315+ Idx := clb_Content.Items.Add(Copy(s, 3));
316+ clb_Content.Checked[Idx] := True;
317+ end else begin
318+ clb_Content.Items.Add(s);
319+ end;
320+ end;
321+ end;
322+ end else
323+ raise Exception.Create('Either the memo or the checklist must be visible');
324+ finally
325+ FreeAndNil(sl);
326+ end;
327+end;
328+
329+procedure Tfr_NoteEditor.mi_ToggleChecklistClick(Sender: TObject);
330+begin
331+ if IsChecklist then
332+ SwitchDisplay(ndMemo)
333+ else
334+ SwitchDisplay(ndChecklist);
335+end;
336+
337+procedure Tfr_NoteEditor.GoBack;
338+begin
339+ doOnClose;
340+end;
341+
342+procedure Tfr_NoteEditor.ShowMenu;
343+begin
344+ TButton_DrowpdownMenu(b_Menu, pm_Main);
345+end;
346+
347+function Tfr_NoteEditor.IsChecklist: boolean;
348+begin
349+ Result := p_Checklist.Visible;
350+end;
351+
352+function Tfr_NoteEditor.BuildFilename: string;
353+var
354+ ext: string;
355+begin
356+ Result := EncodeFilename(ed_Title.Text, IsChecklist, FNoteColor);
357+ ext := ExtractFileExt(FFilenameOnly);
358+ if ext = '' then
359+ ext := DEFAULT_EXTENSION;
360+ Result := Result + ext;
361+end;
362+
363+function Tfr_NoteEditor.ContentHasChanged: boolean;
364+var
365+ fn, s: string;
366+begin
367+ fn := BuildFilename;
368+ Result := True;
369+ if fn <> FFilenameOnly then
370+ Exit; //==>
371+ GetContent(s);
372+ Result := (s <> FOrigContent);
373+end;
374+
375+procedure Tfr_NoteEditor.SaveNote;
376+var
377+ fn: string;
378+ sl: TStringList;
379+begin
380+ fn := BuildFilename;
381+ if FFilenameOnly <> '' then begin
382+ if FFilenameOnly <> fn then begin
383+ if not RenameFile(FPathBS + FFilenameOnly, FPathBS + fn) then begin
384+ MessageDlgCentered(Self, 'Renaming the file failed. Please make sure that your title is a valid file name!',
385+ mtError, [mbOK]);
386+ SysUtils.Abort;
387+ end;
388+ end;
389+ end;
390+ FFilenameOnly := fn;
391+ sl := TStringList.Create;
392+ try
393+ GetContent(FOrigContent);
394+ sl.Text := FOrigContent;
395+ sl.SaveToFile(FPathBS + FFilenameOnly);
396+ finally
397+ FreeAndNil(sl);
398+ end;
399+end;
400+
401+procedure Tfr_NoteEditor.FormCloseQuery(_Sender: TObject; var _CanClose: boolean);
402+var
403+ Res: TModalResult;
404+begin
405+ if not ContentHasChanged then
406+ Exit; //==>
407+
408+ Res := MessageDlgCentered(Self, 'You have unsaved changes. Do you want to save them?',
409+ mtConfirmation, [mbYes, mbNo, mbCancel]);
410+ case Res of
411+ mrYes: begin
412+ SaveNote;
413+ end;
414+ mrNo: ;
415+ else
416+ _CanClose := False;
417+ end;
418+end;
419+
420+end.
--- tags/DenkzettelCompanion_0.0.4/src/u_denkzettelutils.pas (nonexistent)
+++ tags/DenkzettelCompanion_0.0.4/src/u_denkzettelutils.pas (revision 45)
@@ -0,0 +1,230 @@
1+unit u_DenkzettelUtils;
2+
3+{$mode objfpc}{$H+}
4+
5+interface
6+
7+uses
8+ Windows,
9+ SysUtils,
10+ Classes,
11+ Graphics;
12+
13+const
14+ DEFAULT_EXTENSION = '.txt';
15+
16+type
17+ TDenkzettelColor = (dcWhite, dcRed, dcOrange, dcYellow, dcMagenta, dcViolet, dcBlue, dcGreen);
18+
19+
20+function DecodeFilename(const _fn: string;
21+ out _Title: string; out _IsChecklist: boolean; out _Color: TDenkzettelColor): boolean;
22+
23+function EncodeFilename(const _Title: string; _IsChecklist: boolean; _Color: TDenkzettelColor): string;
24+
25+function PropertiesToPointer(_Color: TDenkzettelColor; _IsChecklist: boolean): Pointer;
26+procedure PointerToProperties(_Ptr: Pointer; out _Color: TDenkzettelColor; out _IsChecklist: boolean);
27+
28+function NoteColorToColor(_NoteColor: TDenkzettelColor; _IsSelected: boolean): TColor;
29+function DarkenColor(_Color: TColor; _Percent: byte): TColor;
30+function BrightenColor(_Color: TColor; _Percent: byte): TColor;
31+function NoteColorToChar(_dc: TDenkzettelColor): char;
32+function CharToNoteColor(_c: char): TDenkzettelColor;
33+
34+implementation
35+
36+uses
37+ strutils;
38+
39+type
40+ TPropEncoderRec = packed record
41+ case boolean of
42+ True: (AsPointer: Pointer);
43+ False: (
44+ Color: TDenkzettelColor;
45+ IsChecklist: boolean);
46+ end;
47+
48+function PropertiesToPointer(_Color: TDenkzettelColor; _IsChecklist: boolean): Pointer;
49+var
50+ rec: TPropEncoderRec;
51+begin
52+ ZeroMemory(@rec, SizeOf(rec));
53+ rec.Color := _Color;
54+ rec.IsChecklist := _IsChecklist;
55+ Result := rec.AsPointer;
56+end;
57+
58+procedure PointerToProperties(_Ptr: Pointer; out _Color: TDenkzettelColor; out _IsChecklist: boolean);
59+var
60+ rec: TPropEncoderRec;
61+begin
62+ ZeroMemory(@rec, SizeOf(rec));
63+ rec.AsPointer := _Ptr;
64+ _Color := rec.Color;
65+ _IsChecklist := rec.IsChecklist;
66+end;
67+
68+function DarkenColor(_Color: TColor; _Percent: byte): TColor;
69+var R, G, B: byte;
70+begin
71+ R := GetRValue(_Color);
72+ G := GetGValue(_Color);
73+ B := GetBValue(_Color);
74+ R := Round(R * _Percent / 100);
75+ G := Round(G * _Percent / 100);
76+ B := Round(B * _Percent / 100);
77+ Result := RGB(R, G, B);
78+end;
79+
80+function BrightenColor(_Color: TColor; _Percent: byte): TColor;
81+var R, G, B: byte;
82+begin
83+ R := GetRValue(_Color);
84+ G := GetGValue(_Color);
85+ B := GetBValue(_Color);
86+ R := Round(R * _Percent / 100) + Round(255 - _Percent / 100 * 255);
87+ G := Round(G * _Percent / 100) + Round(255 - _Percent / 100 * 255);
88+ B := Round(B * _Percent / 100) + Round(255 - _Percent / 100 * 255);
89+ Result := RGB(R, G, B);
90+end;
91+
92+
93+
94+function NoteColorToColor(_NoteColor: TDenkzettelColor; _IsSelected: boolean): TColor;
95+var
96+ clDenkzettelRed: TColor;
97+ clDenkzettelOrange: TColor;
98+ clDenkzettelYellow: TColor;
99+ clDenkzettelMagenta: TColor;
100+ clDenkzettelViolet: TColor;
101+ clDenkzettelBlue: TColor;
102+ clDenkzettelGreen: TColor;
103+begin
104+ clDenkzettelRed := RGBToColor(255, 180, 180); //RGBToColor(255, 128, 128);
105+ clDenkzettelOrange := RGBToColor(250, 192, 86); //RGBToColor(255, 170, 130);
106+ clDenkzettelYellow := RGBToColor(255, 255, 128);
107+ clDenkzettelMagenta := RGBToColor(255, 170, 255);
108+ clDenkzettelViolet := RGBToColor(217, 179, 255);
109+ clDenkzettelBlue := RGBToColor(152, 218, 254);
110+ clDenkzettelGreen := RGBToColor(193, 255, 193);
111+
112+ case _NoteColor of
113+ dcRed: Result := clDenkzettelRed;
114+ dcOrange: Result := clDenkzettelOrange;
115+ dcYellow: Result := clDenkzettelYellow;
116+ dcMagenta: Result := clDenkzettelMagenta;
117+ dcViolet: Result := clDenkzettelViolet;
118+ dcBlue: Result := clDenkzettelBlue;
119+ dcGreen: Result := clDenkzettelGreen;
120+ else // dcWhite:
121+ if _IsSelected then
122+ Result := clHighlight
123+ else
124+ Result := clWindow;
125+ Exit; //==>
126+ end;
127+ if _IsSelected then
128+ Result := DarkenColor(Result, 80);
129+end;
130+
131+function ExtractHashSuffix(var _s: string; out _Suffix: string): boolean;
132+var
133+ len: integer;
134+ i: integer;
135+begin
136+ Result := False;
137+ if _s = '' then
138+ Exit; //==>
139+ Len := Length(_s);
140+ if _s[Len] <> '#' then
141+ Exit; //==>
142+ i := Len - 1;
143+ while i > 0 do begin
144+ if _s[i] = '#' then begin
145+ _Suffix := Copy(_s, i);
146+ _s := LeftStr(_s, i - 1);
147+ Result := True;
148+ Exit; //==>
149+ end;
150+ Dec(i);
151+ end;
152+end;
153+
154+function NoteColorToChar(_dc: TDenkzettelColor): char;
155+begin
156+ case _dc of
157+ dcRed: Result := 'R';
158+ dcOrange: Result := 'O';
159+ dcYellow: Result := 'Y';
160+ dcMagenta: Result := 'M';
161+ dcViolet: Result := 'V';
162+ dcBlue: Result := 'B';
163+ dcGreen: Result := 'G';
164+ else
165+ Result := 'W';
166+ end;
167+end;
168+
169+function CharToNoteColor(_c: char): TDenkzettelColor;
170+begin
171+ case _c of
172+ 'R': Result := dcRed;
173+ 'O': Result := dcOrange;
174+ 'Y': Result := dcYellow;
175+ 'M': Result := dcMagenta;
176+ 'V': Result := dcViolet;
177+ 'B': Result := dcBlue;
178+ 'G': Result := dcGreen;
179+ else
180+ Result := dcWhite;
181+ end;
182+end;
183+
184+function DecodeFilename(const _fn: string;
185+ out _Title: string; out _IsChecklist: boolean; out _Color: TDenkZettelColor): boolean;
186+var
187+ s: string;
188+ Suffix: string;
189+ Option: string;
190+ Value: string;
191+begin
192+ s := ChangeFileExt(ExtractFileName(_fn), '');
193+ Result := False;
194+ _IsChecklist := False;
195+ _Color := dcWhite;
196+ _Title := s;
197+ while ExtractHashSuffix(s, Suffix) do begin
198+ if LeftStr(Suffix, 1) <> '#' then
199+ Exit; //==>
200+ if RightStr(Suffix, 1) <> '#' then
201+ Exit; //==>
202+ Option := Copy(Suffix, 2, Length(Suffix) - 2);
203+ Value := UpCase(Copy(Option, 2));
204+ Option := UpCase(LeftStr(Option, 1));
205+ case Option[1] of
206+ 'C': begin
207+ // Color
208+ if Length(Value) <> 1 then
209+ Exit; //==>
210+ _Color := CharToNoteColor(Value[1]);
211+ end;
212+ 'L': begin
213+ _IsChecklist := True;
214+ end;
215+ end;
216+ end;
217+ _Title := s;
218+ Result := True;
219+end;
220+
221+function EncodeFilename(const _Title: string; _IsChecklist: boolean; _Color: TDenkzettelColor): string;
222+begin
223+ Result := _Title;
224+ if _IsChecklist then
225+ Result := Result + '#L#';
226+ if _Color <> dcWhite then
227+ Result := Result + '#C' + NoteColorToChar(_Color) + '#';
228+end;
229+
230+end.
--- tags/DenkzettelCompanion_0.0.4/src/w_about.pas (nonexistent)
+++ tags/DenkzettelCompanion_0.0.4/src/w_about.pas (revision 45)
@@ -0,0 +1,58 @@
1+unit w_About;
2+
3+{$mode objfpc}{$H+}
4+
5+interface
6+
7+uses
8+ Classes,
9+ SysUtils,
10+ FileUtil,
11+ Forms,
12+ Controls,
13+ Graphics,
14+ Dialogs, ExtCtrls, StdCtrls;
15+
16+type
17+
18+ { Tf_About }
19+
20+ Tf_About = class(TForm)
21+ b_Close: TButton;
22+ im_Logo: TImage;
23+ l_ProgInfo1: TLabel;
24+ l_ProgInfo2: TLabel;
25+ l_ProgInfo3: TLabel;
26+ l_ProgInfo5: TLabel;
27+ l_ProgName: TLabel;
28+ l_Copyright: TLabel;
29+ l_ProgInfo4: TLabel;
30+ private
31+ public
32+ class procedure Execute(_Owner: TWinControl);
33+ end;
34+
35+
36+implementation
37+
38+{$R *.lfm}
39+
40+uses
41+ u_dzLazUtils;
42+
43+{ Tf_About }
44+
45+class procedure Tf_About.Execute(_Owner: TWinControl);
46+var
47+ frm: Tf_About;
48+begin
49+ frm := Tf_About.Create(_Owner);
50+ try
51+ TForm_CenterOn(frm, _Owner);
52+ frm.ShowModal;
53+ finally
54+ FreeAndNil(frm);
55+ end;
56+end;
57+
58+end.
--- tags/DenkzettelCompanion_0.0.4/src/w_newcategory.pas (nonexistent)
+++ tags/DenkzettelCompanion_0.0.4/src/w_newcategory.pas (revision 45)
@@ -0,0 +1,84 @@
1+unit w_NewCategory;
2+
3+{$mode objfpc}{$H+}
4+
5+interface
6+
7+uses
8+ Classes,
9+ SysUtils,
10+ FileUtil,
11+ Forms,
12+ Controls,
13+ Graphics,
14+ Dialogs,
15+ StdCtrls;
16+
17+type
18+
19+ { Tf_NewCategory }
20+
21+ Tf_NewCategory = class(TForm)
22+ b_Cancel: TButton;
23+ b_Create: TButton;
24+ ed_Category: TEdit;
25+ l_Blurb: TLabel;
26+ l_Category: TLabel;
27+ procedure b_CreateClick(Sender: TObject);
28+ private
29+ FBaseDir: string;
30+ procedure SetData(const _BaseDir: string; const _CategoryName: string);
31+ procedure GetData(out _CategoryName: string);
32+ public
33+ class function Execute(_Owner: TWinControl; const _BaseDir: string; var _CategoryName: string): boolean;
34+ end;
35+
36+implementation
37+
38+uses
39+ u_dzLazUtils;
40+
41+{$R *.lfm}
42+
43+{ Tf_NewCategory }
44+
45+class function Tf_NewCategory.Execute(_Owner: TWinControl; const _BaseDir: string;
46+ var _CategoryName: string): boolean;
47+var
48+ frm: Tf_NewCategory;
49+begin
50+ frm := Tf_NewCategory.Create(_Owner);
51+ try
52+ TForm_CenterOn(frm, _Owner);
53+ frm.SetData(_BaseDir, _CategoryName);
54+ Result := (mrOk = frm.ShowModal);
55+ if Result then
56+ frm.GetData(_CategoryName);
57+
58+ finally
59+ FreeAndNil(frm);
60+ end;
61+end;
62+
63+procedure Tf_NewCategory.b_CreateClick(Sender: TObject);
64+var
65+ NewDir: string;
66+begin
67+ NewDir := FBaseDir + ed_Category.Text;
68+ if not CreateDir(newdir) then
69+ raise Exception.Create('Could not create directory.');
70+ ModalResult := mrOk;
71+end;
72+
73+procedure Tf_NewCategory.SetData(const _BaseDir: string; const _CategoryName: string);
74+begin
75+ FBaseDir := IncludeTrailingPathDelimiter(_BaseDir);
76+ ed_Category.Text := _CategoryName;
77+end;
78+
79+procedure Tf_NewCategory.GetData(out _CategoryName: string);
80+begin
81+ _CategoryName := ed_Category.Text;
82+end;
83+
84+end.
--- tags/DenkzettelCompanion_0.0.4/src/w_settings.pas (nonexistent)
+++ tags/DenkzettelCompanion_0.0.4/src/w_settings.pas (revision 45)
@@ -0,0 +1,70 @@
1+unit w_Settings;
2+
3+{$mode objfpc}{$H+}
4+
5+interface
6+
7+uses
8+ Classes,
9+ SysUtils,
10+ FileUtil,
11+ Forms,
12+ Controls,
13+ Graphics,
14+ Dialogs,
15+ StdCtrls,
16+ EditBtn;
17+
18+type
19+
20+ { Tf_Settings }
21+
22+ Tf_Settings = class(TForm)
23+ b_OK: TButton;
24+ b_Cancel: TButton;
25+ de_BaseDirectory: TDirectoryEdit;
26+ l_BaseDirectory: TLabel;
27+ private
28+ procedure SetData(const _BaseDir: string);
29+ procedure GetData(out _BaseDir: string);
30+ public
31+ class function Execute(_Owner: TWinControl; var _BaseDir: string): boolean;
32+ end;
33+
34+
35+implementation
36+
37+{$R *.lfm}
38+
39+uses
40+ u_dzLazUtils;
41+
42+{ Tf_Settings }
43+
44+class function Tf_Settings.Execute(_Owner: TWinControl; var _BaseDir: string): boolean;
45+var
46+ frm: Tf_Settings;
47+begin
48+ frm := Tf_Settings.Create(_Owner);
49+ try
50+ TForm_CenterOn(frm, _Owner);
51+ frm.SetData(_BaseDir);
52+ Result := frm.ShowModal = mrOk;
53+ if Result then
54+ frm.GetData(_BaseDir);
55+ finally
56+ FreeAndNil(frm);
57+ end;
58+end;
59+
60+procedure Tf_Settings.SetData(const _BaseDir: string);
61+begin
62+ de_BaseDirectory.Directory := _BaseDir;
63+end;
64+
65+procedure Tf_Settings.GetData(out _BaseDir: string);
66+begin
67+ _BaseDir := de_BaseDirectory.Directory;
68+end;
69+
70+end.
--- tags/DenkzettelCompanion_0.0.4/!readme.txt (nonexistent)
+++ tags/DenkzettelCompanion_0.0.4/!readme.txt (revision 45)
@@ -0,0 +1,15 @@
1+Suffixes for the file name are apparently used to encode the way how Denkzettel displays the
2+notes:
3+* #C?# is the background color, where ? is one of:
4+ + R -> Red
5+ + O -> Orange
6+ + Y -> Yellow
7+ + M -> Magenta
8+ + V -> Violet
9+ + B -> Blue
10+ + G -> Green
11+ If there is no #C?# suffix the background color is white
12+
13+* #L# means that the note is a checklist
14+
15+* Sometimes there is a #N?# suffix (I have only seen #N1# yet, so maybe that's the only value)
\ No newline at end of file
Show on old repository browser