├── .gitignore
├── Delphi
├── DelphiCtrlTab_D$(DV).hhdproj
├── DelphiCtrlTab_D23.dpk
├── DelphiCtrlTab_D23.dproj
├── DelphiCtrlTab_D26.dpk
├── DelphiCtrlTab_D26.dproj
├── DelphiCtrlTab_D27.dpk
├── DelphiCtrlTab_D27.dproj
├── DelphiCtrlTab_D28.dpk
├── DelphiCtrlTab_D28.dproj
└── DelphiCtrlTab_Extensions.xml
├── DelphiCtrlTab_D$(DV).hhgroupproj
├── DelphiCtrlTab_D23.groupproj
├── DelphiCtrlTab_D26.groupproj
├── DelphiCtrlTab_D27.groupproj
├── DelphiCtrlTab_D28.groupproj
├── LICENSE
├── README.md
├── Source
├── CtrlTab.Consts.pas
├── CtrlTab.DesignNotification.pas
├── CtrlTab.EditorNotifierBase.pas
├── CtrlTab.EditorServicesNotifier.pas
├── CtrlTab.FileLogger.pas
├── CtrlTab.FormEditorNotifier.pas
├── CtrlTab.FrmOpenDocs.dfm
├── CtrlTab.FrmOpenDocs.pas
├── CtrlTab.IdeNotifier.pas
├── CtrlTab.IdePlugin.pas
├── CtrlTab.Interfaces.pas
├── CtrlTab.Main.pas
├── CtrlTab.Settings.pas
├── CtrlTab.SettingsManager.pas
├── CtrlTab.SourceEditorNotifier.pas
└── CtrlTab.ViewManager.pas
├── binaries
└── Release
│ ├── DelphiCtrlTab_D23.bpl
│ ├── DelphiCtrlTab_D26.bpl
│ ├── DelphiCtrlTab_D27.bpl
│ └── DelphiCtrlTab_D28.bpl
├── docs
└── images
│ └── DelphiCtrlTab.jpg
└── msbuild
├── .targets
└── DelphiCtrlTab.Compile.targets
├── DelphiCtrlTab.proj
└── buildAll.bat
/.gitignore:
--------------------------------------------------------------------------------
1 | # Uncomment these types if you want even more clean repository. But be careful.
2 | # It can make harm to an existing project source. Read explanations below.
3 | #
4 | # Resource files are binaries containing manifest, project icon and version info.
5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files.
6 | #*.res
7 | #
8 | # Type library file (binary). In old Delphi versions it should be stored.
9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored.
10 | #*.tlb
11 | #
12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7.
13 | # Uncomment this if you are not using diagrams or use newer Delphi version.
14 | #*.ddp
15 | #
16 | # Visual LiveBindings file. Added in Delphi XE2.
17 | # Uncomment this if you are not using LiveBindings Designer.
18 | #*.vlb
19 | #
20 | # Deployment Manager configuration file for your project. Added in Delphi XE2.
21 | # Uncomment this if it is not mobile development and you do not use remote debug feature.
22 | #*.deployproj
23 | #
24 | # C++ object files produced when C/C++ Output file generation is configured.
25 | # Uncomment this if you are not using external objects (zlib library for example).
26 | #*.obj
27 | #
28 |
29 | # Delphi compiler-generated binaries (safe to delete)
30 | *.exe
31 | *.dll
32 | *.bpi
33 | *.dcp
34 | *.so
35 | *.apk
36 | *.drc
37 | *.map
38 | *.dres
39 | *.rsm
40 | *.tds
41 | *.dcu
42 | *.lib
43 | *.a
44 | *.o
45 | *.ocx
46 |
47 | # Delphi autogenerated files (duplicated info)
48 | *.cfg
49 | *.hpp
50 | *Resource.rc
51 |
52 | # Delphi local files (user-specific info)
53 | *.local
54 | *.identcache
55 | *.projdata
56 | *.tvsconfig
57 | *.dsk
58 |
59 | # Delphi history and backups
60 | __history/
61 | __recovery/
62 | *.~*
63 |
64 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi)
65 | *.stat
66 |
67 | # Boss dependency manager vendor folder https://github.com/HashLoad/boss
68 | modules/
69 | Delphi/*.res
70 | binaries/Debug/
71 | build/
72 |
--------------------------------------------------------------------------------
/Delphi/DelphiCtrlTab_D$(DV).hhdproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | rtl.dcp
4 | designide.dcp
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | false
26 | ..\build\bin\$(Config)\
27 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
28 | true
29 | All
30 | true
31 | .\$(Platform)\$(Config)
32 | ..\binaries\$(Config)\
33 | false
34 | false
35 | false
36 | false
37 | false
38 | c:\Program Files (x86)\Embarcadero\Studio\20.0\bin\
39 |
40 |
41 |
42 | rtl;$(DCC_UsePackage)
43 | 1033
44 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
45 | CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)
46 | true
47 |
48 |
49 |
53 |
54 | rtl;$(DCC_UsePackage)
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/Delphi/DelphiCtrlTab_D23.dpk:
--------------------------------------------------------------------------------
1 | {* *****************************************************************
2 |
3 | IMPORTANT !!!! WARNING !!!!
4 |
5 | This file is automatically generated by HHProjectMaker
6 | any changes made to this file will be lost !!!!!
7 | Edit this files instead:
8 | c:\Source\DelphiCtrlTab\Delphi\DelphiCtrlTab_D$(DV).hhdproj
9 | respectively the suitable of the related *.hhlibrary files.
10 |
11 | ***************************************************************** *}
12 |
13 | package DelphiCtrlTab_D23;
14 |
15 | {$R *.res}
16 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
17 | {$ENDIF IMPLICITBUILDING}
18 | {$IMPLICITBUILD OFF}
19 |
20 | requires
21 | rtl,
22 | designide;
23 |
24 | contains
25 | CtrlTab.Main in '..\Source\CtrlTab.Main.pas',
26 | CtrlTab.FrmOpenDocs in '..\Source\CtrlTab.FrmOpenDocs.pas' {FormOpenDocs},
27 | CtrlTab.ViewManager in '..\Source\CtrlTab.ViewManager.pas',
28 | CtrlTab.SourceEditorNotifier in '..\Source\CtrlTab.SourceEditorNotifier.pas',
29 | CtrlTab.FormEditorNotifier in '..\Source\CtrlTab.FormEditorNotifier.pas',
30 | CtrlTab.IdeNotifier in '..\Source\CtrlTab.IdeNotifier.pas',
31 | CtrlTab.IdePlugin in '..\Source\CtrlTab.IdePlugin.pas',
32 | CtrlTab.Interfaces in '..\Source\CtrlTab.Interfaces.pas',
33 | CtrlTab.DesignNotification in '..\Source\CtrlTab.DesignNotification.pas',
34 | CtrlTab.FileLogger in '..\Source\CtrlTab.FileLogger.pas',
35 | CtrlTab.EditorNotifierBase in '..\Source\CtrlTab.EditorNotifierBase.pas',
36 | CtrlTab.SettingsManager in '..\Source\CtrlTab.SettingsManager.pas',
37 | CtrlTab.Settings in '..\Source\CtrlTab.Settings.pas',
38 | CtrlTab.Consts in '..\Source\CtrlTab.Consts.pas',
39 | CtrlTab.EditorServicesNotifier in '..\Source\CtrlTab.EditorServicesNotifier.pas';
40 |
41 | end.
42 |
--------------------------------------------------------------------------------
/Delphi/DelphiCtrlTab_D23.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {798f78b3-a8df-4c8b-9d81-7e0544414330}
4 | DelphiCtrlTab_D23.dpk
5 | True
6 | Debug
7 | 3
8 | Package
9 | VCL
10 | 18.1
11 | Win32
12 | ..\
13 |
14 |
15 | true
16 |
17 |
18 | true
19 | Base
20 | true
21 |
22 |
23 | true
24 | Base
25 | true
26 |
27 |
28 | true
29 | Base
30 | true
31 |
32 |
33 | true
34 | Base
35 | true
36 |
37 |
38 | true
39 | Cfg_2
40 | true
41 | true
42 |
43 |
44 | true
45 | Cfg_2
46 | true
47 | true
48 |
49 |
50 | false
51 | DelphiCtrlTab_D23
52 | 00400000
53 | true
54 | 3
55 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0
56 | false
57 | true
58 | false
59 | 1031
60 | DelphiCtrlTab_D23
61 | ..\binaries\$(Config)\
62 | true
63 | false
64 | false
65 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
66 | false
67 | false
68 | false
69 | true
70 | $(OutDir)$(RelPath)dcp\
71 | false
72 | true
73 | 4
74 | false
75 | false
76 | .\$(Platform)\$(Config)
77 | $(OutDir)$(RelPath)obj\
78 | $(OutDir)$(RelPath)dcp\;$(DCC_UnitSearchPath)
79 | 2
80 | 2
81 | true
82 | false
83 | true
84 | true
85 | c:\Program Files (x86)\Embarcadero\Studio\20.0\bin\
86 | All
87 |
88 |
89 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
90 | rtl;$(DCC_UsePackage)
91 | 1033
92 | CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)
93 | true
94 |
95 |
96 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
97 | true
98 | rtl;$(DCC_UsePackage)
99 |
100 |
101 | true
102 | _HH_StaticallyLinkLibraries;RELEASE;$(DCC_Define)
103 |
104 |
105 | _HH_StaticallyLinkLibraries;DEBUG;$(DCC_Define)
106 |
107 |
108 | true
109 | true
110 | true
111 | true
112 |
113 |
114 | true
115 | true
116 |
117 |
118 |
119 | MainSource
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 | Base
142 |
143 |
144 | Cfg_1
145 | Base
146 |
147 |
148 | Cfg_2
149 | Base
150 |
151 |
152 | Cfg_3
153 | Cfg_2
154 |
155 |
156 | Cfg_4
157 | Cfg_2
158 |
159 |
160 | Delphi.Personality.12
161 | Package
162 |
163 |
164 |
165 | DelphiCtrlTab_D23.dpk
166 |
167 |
168 | True
169 | False
170 | 1
171 | 0
172 | 0
173 | 0
174 | False
175 | False
176 | False
177 | False
178 | False
179 | 1031
180 | 1252
181 |
182 |
183 |
184 | Ide Plugin
185 | 1.0.0.0
186 |
187 |
188 |
189 |
190 | DelphiCtrlTab
191 | 1.0.0.0
192 |
193 |
194 |
195 |
196 |
197 | True
198 | True
199 |
200 |
201 | 12
202 |
--------------------------------------------------------------------------------
/Delphi/DelphiCtrlTab_D26.dpk:
--------------------------------------------------------------------------------
1 | {* *****************************************************************
2 |
3 | IMPORTANT !!!! WARNING !!!!
4 |
5 | This file is automatically generated by HHProjectMaker
6 | any changes made to this file will be lost !!!!!
7 | Edit this files instead:
8 | c:\Source\DelphiCtrlTab\Delphi\DelphiCtrlTab_D$(DV).hhdproj
9 | respectively the suitable of the related *.hhlibrary files.
10 |
11 | ***************************************************************** *}
12 |
13 | package DelphiCtrlTab_D26;
14 |
15 | {$R *.res}
16 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
17 | {$ENDIF IMPLICITBUILDING}
18 | {$IMPLICITBUILD OFF}
19 |
20 | requires
21 | rtl,
22 | designide;
23 |
24 | contains
25 | CtrlTab.Main in '..\Source\CtrlTab.Main.pas',
26 | CtrlTab.FrmOpenDocs in '..\Source\CtrlTab.FrmOpenDocs.pas' {FormOpenDocs},
27 | CtrlTab.ViewManager in '..\Source\CtrlTab.ViewManager.pas',
28 | CtrlTab.SourceEditorNotifier in '..\Source\CtrlTab.SourceEditorNotifier.pas',
29 | CtrlTab.FormEditorNotifier in '..\Source\CtrlTab.FormEditorNotifier.pas',
30 | CtrlTab.IdeNotifier in '..\Source\CtrlTab.IdeNotifier.pas',
31 | CtrlTab.IdePlugin in '..\Source\CtrlTab.IdePlugin.pas',
32 | CtrlTab.Interfaces in '..\Source\CtrlTab.Interfaces.pas',
33 | CtrlTab.DesignNotification in '..\Source\CtrlTab.DesignNotification.pas',
34 | CtrlTab.FileLogger in '..\Source\CtrlTab.FileLogger.pas',
35 | CtrlTab.EditorNotifierBase in '..\Source\CtrlTab.EditorNotifierBase.pas',
36 | CtrlTab.SettingsManager in '..\Source\CtrlTab.SettingsManager.pas',
37 | CtrlTab.Settings in '..\Source\CtrlTab.Settings.pas',
38 | CtrlTab.Consts in '..\Source\CtrlTab.Consts.pas',
39 | CtrlTab.EditorServicesNotifier in '..\Source\CtrlTab.EditorServicesNotifier.pas';
40 |
41 | end.
42 |
--------------------------------------------------------------------------------
/Delphi/DelphiCtrlTab_D26.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {798f78b3-a8df-4c8b-9d81-7e0544414330}
4 | DelphiCtrlTab_D26.dpk
5 | True
6 | Debug
7 | 3
8 | Package
9 | VCL
10 | 18.8
11 | Win32
12 | ..\
13 |
14 |
15 | true
16 |
17 |
18 | true
19 | Base
20 | true
21 |
22 |
23 | true
24 | Base
25 | true
26 |
27 |
28 | true
29 | Base
30 | true
31 |
32 |
33 | true
34 | Base
35 | true
36 |
37 |
38 | true
39 | Cfg_2
40 | true
41 | true
42 |
43 |
44 | true
45 | Cfg_2
46 | true
47 | true
48 |
49 |
50 | false
51 | DelphiCtrlTab_D26
52 | 00400000
53 | true
54 | 3
55 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0
56 | false
57 | true
58 | false
59 | 1031
60 | DelphiCtrlTab_D26
61 | ..\binaries\$(Config)\
62 | true
63 | false
64 | false
65 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
66 | false
67 | false
68 | false
69 | true
70 | $(OutDir)$(RelPath)dcp\
71 | false
72 | true
73 | 4
74 | false
75 | false
76 | .\$(Platform)\$(Config)
77 | $(OutDir)$(RelPath)obj\
78 | $(OutDir)$(RelPath)dcp\;$(DCC_UnitSearchPath)
79 | 2
80 | 2
81 | true
82 | false
83 | true
84 | c:\Program Files (x86)\Embarcadero\Studio\20.0\bin\
85 | true
86 | All
87 |
88 |
89 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
90 | rtl;$(DCC_UsePackage)
91 | 1033
92 | CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)
93 | true
94 |
95 |
96 | Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
97 | true
98 | rtl;$(DCC_UsePackage)
99 |
100 |
101 | true
102 | _HH_StaticallyLinkLibraries;RELEASE;$(DCC_Define)
103 |
104 |
105 | _HH_StaticallyLinkLibraries;DEBUG;$(DCC_Define)
106 |
107 |
108 | true
109 | true
110 | true
111 | true
112 |
113 |
114 | true
115 | true
116 |
117 |
118 |
119 | MainSource
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 | Base
142 |
143 |
144 | Cfg_1
145 | Base
146 |
147 |
148 | Cfg_2
149 | Base
150 |
151 |
152 | Cfg_3
153 | Cfg_2
154 |
155 |
156 | Cfg_4
157 | Cfg_2
158 |
159 |
160 | Delphi.Personality.12
161 | Package
162 |
163 |
164 |
165 | DelphiCtrlTab_D26.dpk
166 |
167 |
168 | True
169 | False
170 | 1
171 | 0
172 | 0
173 | 0
174 | False
175 | False
176 | False
177 | False
178 | False
179 | 1031
180 | 1252
181 |
182 |
183 |
184 | Ide Plugin
185 | 1.0.0.0
186 |
187 |
188 |
189 |
190 | DelphiCtrlTab
191 | 1.0.0.0
192 |
193 |
194 |
195 |
196 |
197 | True
198 | True
199 |
200 |
201 | 12
202 |
--------------------------------------------------------------------------------
/Delphi/DelphiCtrlTab_D27.dpk:
--------------------------------------------------------------------------------
1 | {* *****************************************************************
2 |
3 | IMPORTANT !!!! WARNING !!!!
4 |
5 | This file is automatically generated by HHProjectMaker
6 | any changes made to this file will be lost !!!!!
7 | Edit this files instead:
8 | c:\Source\DelphiCtrlTab\Delphi\DelphiCtrlTab_D$(DV).hhdproj
9 | respectively the suitable of the related *.hhlibrary files.
10 |
11 | ***************************************************************** *}
12 |
13 | package DelphiCtrlTab_D27;
14 |
15 | {$R *.res}
16 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
17 | {$ENDIF IMPLICITBUILDING}
18 | {$IMPLICITBUILD OFF}
19 |
20 | requires
21 | rtl,
22 | designide;
23 |
24 | contains
25 | CtrlTab.Main in '..\Source\CtrlTab.Main.pas',
26 | CtrlTab.FrmOpenDocs in '..\Source\CtrlTab.FrmOpenDocs.pas' {FormOpenDocs},
27 | CtrlTab.ViewManager in '..\Source\CtrlTab.ViewManager.pas',
28 | CtrlTab.SourceEditorNotifier in '..\Source\CtrlTab.SourceEditorNotifier.pas',
29 | CtrlTab.FormEditorNotifier in '..\Source\CtrlTab.FormEditorNotifier.pas',
30 | CtrlTab.IdeNotifier in '..\Source\CtrlTab.IdeNotifier.pas',
31 | CtrlTab.IdePlugin in '..\Source\CtrlTab.IdePlugin.pas',
32 | CtrlTab.Interfaces in '..\Source\CtrlTab.Interfaces.pas',
33 | CtrlTab.DesignNotification in '..\Source\CtrlTab.DesignNotification.pas',
34 | CtrlTab.FileLogger in '..\Source\CtrlTab.FileLogger.pas',
35 | CtrlTab.EditorNotifierBase in '..\Source\CtrlTab.EditorNotifierBase.pas',
36 | CtrlTab.SettingsManager in '..\Source\CtrlTab.SettingsManager.pas',
37 | CtrlTab.Settings in '..\Source\CtrlTab.Settings.pas',
38 | CtrlTab.Consts in '..\Source\CtrlTab.Consts.pas',
39 | CtrlTab.EditorServicesNotifier in '..\Source\CtrlTab.EditorServicesNotifier.pas';
40 |
41 | end.
42 |
--------------------------------------------------------------------------------
/Delphi/DelphiCtrlTab_D27.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {798f78b3-a8df-4c8b-9d81-7e0544414330}
4 | DelphiCtrlTab_D27.dpk
5 | True
6 | Debug
7 | 3
8 | Package
9 | VCL
10 | 19
11 | Win32
12 | ..\
13 |
14 |
15 | true
16 |
17 |
18 | true
19 | Base
20 | true
21 |
22 |
23 | true
24 | Base
25 | true
26 |
27 |
28 | true
29 | Base
30 | true
31 |
32 |
33 | true
34 | Base
35 | true
36 |
37 |
38 | true
39 | Cfg_2
40 | true
41 | true
42 |
43 |
44 | true
45 | Cfg_2
46 | true
47 | true
48 |
49 |
50 | false
51 | DelphiCtrlTab_D27
52 | 00400000
53 | true
54 | 3
55 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0
56 | false
57 | true
58 | false
59 | 1031
60 | DelphiCtrlTab_D27
61 | ..\binaries\$(Config)\
62 | true
63 | false
64 | false
65 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
66 | false
67 | false
68 | false
69 | true
70 | $(OutDir)$(RelPath)dcp\
71 | false
72 | true
73 | 4
74 | false
75 | false
76 | .\$(Platform)\$(Config)
77 | $(OutDir)$(RelPath)obj\
78 | $(OutDir)$(RelPath)dcp\;$(DCC_UnitSearchPath)
79 | 2
80 | 2
81 | true
82 | false
83 | true
84 | c:\Program Files (x86)\Embarcadero\Studio\20.0\bin\
85 | true
86 | All
87 |
88 |
89 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
90 | rtl;$(DCC_UsePackage)
91 | 1033
92 | CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)
93 | true
94 |
95 |
96 | Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
97 | true
98 | rtl;$(DCC_UsePackage)
99 |
100 |
101 | true
102 | _HH_StaticallyLinkLibraries;RELEASE;$(DCC_Define)
103 |
104 |
105 | _HH_StaticallyLinkLibraries;DEBUG;$(DCC_Define)
106 |
107 |
108 | true
109 | true
110 | true
111 | true
112 |
113 |
114 | true
115 | true
116 |
117 |
118 |
119 | MainSource
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 | Base
142 |
143 |
144 | Cfg_1
145 | Base
146 |
147 |
148 | Cfg_2
149 | Base
150 |
151 |
152 | Cfg_3
153 | Cfg_2
154 |
155 |
156 | Cfg_4
157 | Cfg_2
158 |
159 |
160 | Delphi.Personality.12
161 | Package
162 |
163 |
164 |
165 | DelphiCtrlTab_D27.dpk
166 |
167 |
168 | True
169 | False
170 | 1
171 | 0
172 | 0
173 | 0
174 | False
175 | False
176 | False
177 | False
178 | False
179 | 1031
180 | 1252
181 |
182 |
183 |
184 | Ide Plugin
185 | 1.0.0.0
186 |
187 |
188 |
189 |
190 | DelphiCtrlTab
191 | 1.0.0.0
192 |
193 |
194 |
195 |
196 |
197 | True
198 | True
199 |
200 |
201 | 12
202 |
--------------------------------------------------------------------------------
/Delphi/DelphiCtrlTab_D28.dpk:
--------------------------------------------------------------------------------
1 | {* *****************************************************************
2 |
3 | IMPORTANT !!!! WARNING !!!!
4 |
5 | This file is automatically generated by HHProjectMaker
6 | any changes made to this file will be lost !!!!!
7 | Edit this files instead:
8 | c:\Source\DelphiCtrlTab\Delphi\DelphiCtrlTab_D$(DV).hhdproj
9 | respectively the suitable of the related *.hhlibrary files.
10 |
11 | ***************************************************************** *}
12 |
13 | package DelphiCtrlTab_D28;
14 |
15 | {$R *.res}
16 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
17 | {$ENDIF IMPLICITBUILDING}
18 | {$IMPLICITBUILD OFF}
19 |
20 | requires
21 | rtl,
22 | designide;
23 |
24 | contains
25 | CtrlTab.Main in '..\Source\CtrlTab.Main.pas',
26 | CtrlTab.FrmOpenDocs in '..\Source\CtrlTab.FrmOpenDocs.pas' {FormOpenDocs},
27 | CtrlTab.ViewManager in '..\Source\CtrlTab.ViewManager.pas',
28 | CtrlTab.SourceEditorNotifier in '..\Source\CtrlTab.SourceEditorNotifier.pas',
29 | CtrlTab.FormEditorNotifier in '..\Source\CtrlTab.FormEditorNotifier.pas',
30 | CtrlTab.IdeNotifier in '..\Source\CtrlTab.IdeNotifier.pas',
31 | CtrlTab.IdePlugin in '..\Source\CtrlTab.IdePlugin.pas',
32 | CtrlTab.Interfaces in '..\Source\CtrlTab.Interfaces.pas',
33 | CtrlTab.DesignNotification in '..\Source\CtrlTab.DesignNotification.pas',
34 | CtrlTab.FileLogger in '..\Source\CtrlTab.FileLogger.pas',
35 | CtrlTab.EditorNotifierBase in '..\Source\CtrlTab.EditorNotifierBase.pas',
36 | CtrlTab.SettingsManager in '..\Source\CtrlTab.SettingsManager.pas',
37 | CtrlTab.Settings in '..\Source\CtrlTab.Settings.pas',
38 | CtrlTab.Consts in '..\Source\CtrlTab.Consts.pas',
39 | CtrlTab.EditorServicesNotifier in '..\Source\CtrlTab.EditorServicesNotifier.pas';
40 |
41 | end.
42 |
--------------------------------------------------------------------------------
/Delphi/DelphiCtrlTab_D28.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {798f78b3-a8df-4c8b-9d81-7e0544414330}
4 | DelphiCtrlTab_D28.dpk
5 | True
6 | Debug
7 | 3
8 | Package
9 | VCL
10 | 20
11 | Win32
12 | ..\
13 |
14 |
15 | true
16 |
17 |
18 | true
19 | Base
20 | true
21 |
22 |
23 | true
24 | Base
25 | true
26 |
27 |
28 | true
29 | Base
30 | true
31 |
32 |
33 | true
34 | Base
35 | true
36 |
37 |
38 | true
39 | Cfg_2
40 | true
41 | true
42 |
43 |
44 | true
45 | Cfg_2
46 | true
47 | true
48 |
49 |
50 | false
51 | DelphiCtrlTab_D28
52 | 00400000
53 | true
54 | 3
55 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0
56 | false
57 | true
58 | false
59 | 1031
60 | DelphiCtrlTab_D28
61 | ..\binaries\$(Config)\
62 | true
63 | false
64 | false
65 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
66 | false
67 | false
68 | false
69 | true
70 | $(OutDir)$(RelPath)dcp\
71 | false
72 | true
73 | 4
74 | false
75 | false
76 | .\$(Platform)\$(Config)
77 | $(OutDir)$(RelPath)obj\
78 | $(OutDir)$(RelPath)dcp\;$(DCC_UnitSearchPath)
79 | 2
80 | 2
81 | true
82 | false
83 | true
84 | c:\Program Files (x86)\Embarcadero\Studio\20.0\bin\
85 | true
86 | All
87 |
88 |
89 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
90 | rtl;$(DCC_UsePackage)
91 | 1033
92 | CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)
93 | true
94 |
95 |
96 | Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
97 | true
98 | rtl;$(DCC_UsePackage)
99 |
100 |
101 | true
102 | _HH_StaticallyLinkLibraries;RELEASE;$(DCC_Define)
103 |
104 |
105 | _HH_StaticallyLinkLibraries;DEBUG;$(DCC_Define)
106 |
107 |
108 | true
109 | true
110 | true
111 | true
112 |
113 |
114 | true
115 | true
116 |
117 |
118 |
119 | MainSource
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 | Base
142 |
143 |
144 | Cfg_1
145 | Base
146 |
147 |
148 | Cfg_2
149 | Base
150 |
151 |
152 | Cfg_3
153 | Cfg_2
154 |
155 |
156 | Cfg_4
157 | Cfg_2
158 |
159 |
160 | Delphi.Personality.12
161 | Package
162 |
163 |
164 |
165 | DelphiCtrlTab_D28.dpk
166 |
167 |
168 | True
169 | False
170 | 1
171 | 0
172 | 0
173 | 0
174 | False
175 | False
176 | False
177 | False
178 | False
179 | 1031
180 | 1252
181 |
182 |
183 |
184 | Ide Plugin
185 | 1.0.0.0
186 |
187 |
188 |
189 |
190 | DelphiCtrlTab
191 | 1.0.0.0
192 |
193 |
194 |
195 |
196 |
197 | True
198 | True
199 |
200 |
201 | 12
202 |
--------------------------------------------------------------------------------
/Delphi/DelphiCtrlTab_Extensions.xml:
--------------------------------------------------------------------------------
1 |
2 | Delphi.Personality.12
3 | $(ProjectType)
4 |
5 |
6 |
7 | $(MainSource)
8 |
9 |
10 | True
11 | False
12 | 1
13 | 0
14 | 0
15 | 0
16 | False
17 | False
18 | False
19 | False
20 | False
21 | 1031
22 | 1252
23 |
24 |
25 |
26 | Ide Plugin
27 | 1.0.0.0
28 |
29 |
30 |
31 |
32 | DelphiCtrlTab
33 | 1.0.0.0
34 |
35 |
36 |
37 |
38 |
39 | True
40 | True
41 | $${UnitTesting)
42 |
43 | 12
44 |
--------------------------------------------------------------------------------
/DelphiCtrlTab_D$(DV).hhgroupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/DelphiCtrlTab_D23.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {b2d95930-33d5-11e9-95d4-8c85906055c0}
4 |
5 |
6 |
7 |
8 |
9 | Default.Personality.12
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/DelphiCtrlTab_D26.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {b2d95930-33d5-11e9-95d4-8c85906055c0}
4 |
5 |
6 |
7 |
8 |
9 | Default.Personality.12
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/DelphiCtrlTab_D27.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {b2d95930-33d5-11e9-95d4-8c85906055c0}
4 |
5 |
6 |
7 |
8 |
9 | Default.Personality.12
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/DelphiCtrlTab_D28.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {b2d95930-33d5-11e9-95d4-8c85906055c0}
4 |
5 |
6 |
7 |
8 |
9 | Default.Personality.12
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 santiagoIT
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DelphiCtrlTab
2 | Plugin for Delphi IDE. Allows open tab navigation based on activity instead of tab oder.
3 |
4 | I am a heavy user of the Ctrl+Tab shortcut. I always found the way the Ctrl+Tab behaves in the Delphi IDE to be very inconvenient.
5 | In all other IDE's I am familiar with, hitting Ctrl+Tab will take you back to the previously active tab, but in Delphi navigation order depends on the order in which the tabs are arranged in the editor.
6 |
7 | Whenever Ctrl+Tab or Ctrl+Shift+Tab is pressed a dialog displaying all open files is displayed.
8 | Files are listed in the order in which they have been activated.
9 |
10 | To navigate between files simply keep the Ctrl key pressed down and hit the tab key. Holding the shift key down naviagtes in the opposite direction.
11 |
12 | Refer to wiki on instructions how to install the plugin.
13 |
14 | 
15 |
16 |
--------------------------------------------------------------------------------
/Source/CtrlTab.Consts.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.Consts
5 |
6 | Info : This Unit contains constant definitions
7 |
8 | Copyright (c) 2020 - Santiago Burbano
9 | ===============================================================================}
10 | unit CtrlTab.Consts;
11 |
12 | interface
13 |
14 | const
15 | // modules such as the Welcome Page carry this prefix before the fileName.
16 | c_BdsSpecialPrefix = 'bds:/';
17 |
18 | // welcome page
19 | c_WelcomePage = 'default.htm';
20 | c_WelcomePageDisplayName = 'Welcome Page';
21 |
22 | implementation
23 |
24 | end.
--------------------------------------------------------------------------------
/Source/CtrlTab.DesignNotification.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.DesignNotification
5 |
6 | Info : This Unit contains the class TDesignNotification.
7 | This class is notified of various designer events.
8 |
9 | Copyright (c) 2020 Santiago Burbano
10 | ===============================================================================}
11 | unit CtrlTab.DesignNotification;
12 |
13 | interface
14 |
15 | uses
16 | Classes, SysUtils, ToolsAPI, CtrlTab.Interfaces, DesignIntf;
17 |
18 | type
19 | TDesignNotification = class(TInterfacedObject, IDesignNotification)
20 | procedure DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean);
21 | procedure DesignerOpened(const ADesigner: IDesigner; AResurrecting: Boolean);
22 | procedure ItemDeleted(const ADesigner: IDesigner; AItem: TPersistent);
23 | procedure ItemInserted(const ADesigner: IDesigner; AItem: TPersistent);
24 | procedure ItemsModified(const ADesigner: IDesigner);
25 | procedure SelectionChanged(const ADesigner: IDesigner; const ASelection: IDesignerSelections);
26 | end;
27 |
28 | implementation
29 |
30 | uses
31 | CtrlTab.IdePlugin;
32 |
33 | {-------------------------------------------------------------------------------
34 | Name : DesignerClosed
35 | Info : This method is called when a form designer is closed.
36 | Input : ADesigner =
37 | AGoingDormant =
38 | Output :
39 | Result : None
40 | -------------------------------------------------------------------------------}
41 | procedure TDesignNotification.DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean);
42 | var
43 | FormFileName: string;
44 | ImplFileName: string;
45 | IntfFileName: string;
46 | begin
47 | // ideally we could have used IOTAFormNotifier to know when a designer is closed. But no notifications
48 | // were triggered :-(
49 | // So ended up using this is a workaround.
50 | ADesigner.ModuleFileNames(ImplFileName, IntfFileName, FormFileName);
51 | Plugin.DesignerClosed(FormFileName);
52 | end;
53 |
54 | {-------------------------------------------------------------------------------
55 | Name : DesignerOpened
56 | Info :
57 | Input : ADesigner =
58 | AResurrecting =
59 | Output :
60 | Result : None
61 | -------------------------------------------------------------------------------}
62 | procedure TDesignNotification.DesignerOpened(const ADesigner: IDesigner; AResurrecting: Boolean);
63 | begin
64 | end;
65 |
66 | {-------------------------------------------------------------------------------
67 | Name : ItemDeleted
68 | Info :
69 | Input : ADesigner =
70 | AItem =
71 | Output :
72 | Result : None
73 | -------------------------------------------------------------------------------}
74 | procedure TDesignNotification.ItemDeleted(const ADesigner: IDesigner; AItem: TPersistent);
75 | begin
76 |
77 | end;
78 |
79 | {-------------------------------------------------------------------------------
80 | Name : ItemInserted
81 | Info :
82 | Input : ADesigner =
83 | AItem =
84 | Output :
85 | Result : None
86 | -------------------------------------------------------------------------------}
87 | procedure TDesignNotification.ItemInserted(const ADesigner: IDesigner; AItem: TPersistent);
88 | begin
89 |
90 | end;
91 |
92 | {-------------------------------------------------------------------------------
93 | Name : ItemsModified
94 | Info :
95 | Input : ADesigner =
96 | Output :
97 | Result : None
98 | -------------------------------------------------------------------------------}
99 | procedure TDesignNotification.ItemsModified(const ADesigner: IDesigner);
100 | begin
101 |
102 | end;
103 |
104 | {-------------------------------------------------------------------------------
105 | Name : SelectionChanged
106 | Info :
107 | Input : ADesigner =
108 | ASelection =
109 | Output :
110 | Result : None
111 | -------------------------------------------------------------------------------}
112 | procedure TDesignNotification.SelectionChanged(const ADesigner: IDesigner; const ASelection: IDesignerSelections);
113 | begin
114 | end;
115 |
116 | end.
117 |
118 |
--------------------------------------------------------------------------------
/Source/CtrlTab.EditorNotifierBase.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.EditorNotifierBase
5 |
6 | Info : This Unit contains the class TEditorBase.
7 | This class contains the base functionallity for Source and Form
8 | EditorNotifiers.
9 |
10 | Copyright (c) 2020 - Santiago Burbano
11 | ===============================================================================}
12 | unit CtrlTab.EditorNotifierBase;
13 |
14 | interface
15 |
16 | uses
17 | ToolsAPI, CtrlTab.Interfaces;
18 |
19 | type
20 | TEditorNotifierBase = class(TNotifierObject, IOTANotifier, IEditorNotifier)
21 | private
22 | function GetFileName: string;
23 | protected
24 | FEditor: IOTAEditor;
25 | FIndex: Integer;
26 | FFileName: string;
27 | procedure CleanUp;
28 | procedure Destroyed;
29 | public
30 | constructor Create(aEditor: IOTAEditor); reintroduce;
31 | destructor Destroy; override;
32 | end;
33 |
34 | implementation
35 |
36 | uses
37 | CtrlTab.IdePlugin, System.SysUtils;
38 |
39 | {-------------------------------------------------------------------------------
40 | Name : Create
41 | Info : Constructor
42 | Input : aEditor = Editor
43 |
44 | Output :
45 | Result : None
46 | -------------------------------------------------------------------------------}
47 | constructor TEditorNotifierBase.Create(aEditor: IOTAEditor);
48 | begin
49 | inherited Create;
50 | FEditor := aEditor;
51 | FFileName := FEditor.FileName;
52 | end;
53 |
54 | {-------------------------------------------------------------------------------
55 | Name : Destroy
56 | Info :
57 | Input :
58 | Output :
59 | Result : None
60 | -------------------------------------------------------------------------------}
61 | destructor TEditorNotifierBase.Destroy;
62 | begin
63 | Plugin.EditorNotifierAboutToBeDestroyed(Self);
64 | Cleanup;
65 | inherited;
66 | end;
67 |
68 | {-------------------------------------------------------------------------------
69 | Name : CleanUp
70 | Info : Performs clean up once the notifier is about to be released.
71 | Input :
72 | Output :
73 | Result : None
74 | -------------------------------------------------------------------------------}
75 | procedure TEditorNotifierBase.CleanUp;
76 | begin
77 | if FIndex >= 0 then
78 | begin
79 | if Assigned(FEditor) then
80 | begin
81 | Plugin.Logger.LogMessage(Format('TEditorNotifierBase. notifier removed. [%s]', [FFileName]));
82 | FEditor.RemoveNotifier(FIndex);
83 | end;
84 | FIndex := -1;
85 | end;
86 | FEditor := nil;
87 | end;
88 |
89 | {-------------------------------------------------------------------------------
90 | Name : Destroyed
91 | Info : The associated item is being destroyed so all references should be dropped.
92 | Exceptions are ignored.
93 | Input :
94 | Output :
95 | Result : None
96 | -------------------------------------------------------------------------------}
97 | procedure TEditorNotifierBase.Destroyed;
98 | begin
99 | Plugin.Logger.LogMessage(Format('TEditorNotifierBase.Destroyed. [%s]', [FFileName]));
100 | CleanUp;
101 | end;
102 |
103 |
104 | {-------------------------------------------------------------------------------
105 | Name : GetFileName
106 | Info :
107 | Input :
108 | Output :
109 | Result : string
110 | -------------------------------------------------------------------------------}
111 | function TEditorNotifierBase.GetFileName: string;
112 | begin
113 | Result := FFileName;
114 | end;
115 |
116 |
117 | end.
118 |
119 |
--------------------------------------------------------------------------------
/Source/CtrlTab.EditorServicesNotifier.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.EditorServicesNotifier
5 |
6 | Info : This Unit contains the class TCtrlTabEditorServicesNotifier.
7 | DockFormUpdated is called whenever a Tab is activated.
8 | This is the only way I have to know when special modules such
9 | as the Welcome Page are activated.
10 |
11 | Copyright (c) 2020 - Santiago Burbano
12 | ===============================================================================}
13 | unit CtrlTab.EditorServicesNotifier;
14 |
15 | interface
16 |
17 | uses
18 | ToolsApi, System.Classes, DockForm;
19 |
20 | type
21 | TCtrlTabEditorServicesNotifier = Class(TNotifierObject, INTAEditServicesNotifier)
22 | public
23 | // INTAEditorServicesNotifier
24 | procedure DockFormRefresh(Const EditWindow: INTAEditWindow; DockForm: TDockableForm);
25 | procedure DockFormUpdated(Const EditWindow: INTAEditWindow; DockForm: TDockableForm);
26 | procedure DockFormVisibleChanged(Const EditWindow: INTAEditWindow; DockForm: TDockableForm);
27 | procedure EditorViewActivated(Const EditWindow: INTAEditWindow; Const EditView: IOTAEditView);
28 | procedure EditorViewModified(Const EditWindow: INTAEditWindow; Const EditView: IOTAEditView);
29 | procedure WindowActivated(Const EditWindow: INTAEditWindow);
30 | procedure WindowCommand(Const EditWindow: INTAEditWindow; Command: Integer; Param: Integer; Var Handled: Boolean);
31 | procedure WindowNotification(Const EditWindow: INTAEditWindow; Operation: TOperation);
32 | procedure WindowShow(Const EditWindow: INTAEditWindow; Show: Boolean; LoadedFromDesktop: Boolean);
33 | end;
34 |
35 | implementation
36 |
37 | uses
38 | CtrlTab.IdePlugin, System.SysUtils, CtrlTab.Consts;
39 |
40 | procedure TCtrlTabEditorServicesNotifier.DockFormRefresh(Const EditWindow: INTAEditWindow; DockForm: TDockableForm);
41 | begin
42 | end;
43 |
44 | {-------------------------------------------------------------------------------
45 | Name : DockFormUpdated
46 | Info : This method is called whenever a tab is activated.
47 | It is the only way I have found to be able to detect that the Welcome Page
48 | has been activated.
49 | Input : EditWindow =
50 | DockForm =
51 |
52 | Output :
53 | Result : None
54 | -------------------------------------------------------------------------------}
55 | procedure TCtrlTabEditorServicesNotifier.DockFormUpdated(Const EditWindow: INTAEditWindow; DockForm: TDockableForm);
56 | var
57 | Caption: string;
58 | begin
59 | if Assigned(EditWindow.Form) then
60 | begin
61 | Caption := EditWindow.Form.Caption;
62 | // only interested in special pages such as Welcome Page
63 | if Caption.StartsWith(c_BdsSpecialPrefix) then
64 | begin
65 | // register view without bds prefix
66 | Plugin.ViewManager.ViewActivated(Caption.Substring(5));
67 | end;
68 | end;
69 | end;
70 |
71 | procedure TCtrlTabEditorServicesNotifier.DockFormVisibleChanged(Const EditWindow: INTAEditWindow; DockForm: TDockableForm);
72 | begin
73 | end;
74 |
75 | procedure TCtrlTabEditorServicesNotifier.EditorViewActivated(Const EditWindow: INTAEditWindow; Const EditView: IOTAEditView);
76 | begin
77 | end;
78 |
79 | procedure TCtrlTabEditorServicesNotifier.EditorViewModified(Const EditWindow: INTAEditWindow; Const EditView: IOTAEditView);
80 | begin
81 | end;
82 |
83 | procedure TCtrlTabEditorServicesNotifier.WindowActivated(Const EditWindow: INTAEditWindow);
84 | begin
85 | end;
86 |
87 | procedure TCtrlTabEditorServicesNotifier.WindowCommand(Const EditWindow: INTAEditWindow; Command: Integer; Param: Integer; Var Handled: Boolean);
88 | begin
89 | end;
90 |
91 | procedure TCtrlTabEditorServicesNotifier.WindowNotification(Const EditWindow: INTAEditWindow; Operation: TOperation);
92 | begin
93 | end;
94 |
95 | procedure TCtrlTabEditorServicesNotifier.WindowShow(Const EditWindow: INTAEditWindow; Show: Boolean; LoadedFromDesktop: Boolean);
96 | begin
97 | end;
98 |
99 | end.
--------------------------------------------------------------------------------
/Source/CtrlTab.FileLogger.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.FileLogger
5 |
6 | Info : This Unit contains the class TFileLogger.
7 | This class is used for debugging purposes only.
8 | It writes output to:
9 | \Appdata\Roaming\ControlTab\log.txt
10 |
11 | Copyright (c) 2020 Santiago Burbano
12 | ===============================================================================}
13 | unit CtrlTab.FileLogger;
14 |
15 | interface
16 |
17 | uses
18 | CtrlTab.Interfaces;
19 |
20 | type
21 | TFileLogger = class(TInterfacedObject, ILogger)
22 | procedure ClearLog;
23 | procedure LogMessage(aMessage: string);
24 | private
25 | FLogFile: string;
26 | procedure OpenLogLocation;
27 | public
28 | constructor Create;
29 | end;
30 |
31 | implementation
32 |
33 | uses
34 | System.IOUtils, System.SysUtils, CtrlTab.IdePlugin, ShellApi, Winapi.Windows;
35 |
36 | {-------------------------------------------------------------------------------
37 | Name : Create
38 | Info :
39 | Input :
40 | Output :
41 | Result : None
42 | -------------------------------------------------------------------------------}
43 | constructor TFileLogger.Create;
44 | var
45 | LogDirectory: string;
46 | begin
47 | inherited;
48 | LogDirectory := System.SysUtils.GetHomePath;
49 | LogDirectory := TPath.Combine(LogDirectory, 'ControlTab');
50 | FLogFile := TPath.Combine(LogDirectory, 'log.txt');
51 |
52 | Plugin.PrintMessage(Format('Log file: %s', [FLogFile]));
53 |
54 | // ensure directory exists
55 | if not TDirectory.Exists(LogDirectory) then
56 | TDirectory.CreateDirectory(LogDirectory);
57 | end;
58 |
59 | {-------------------------------------------------------------------------------
60 | Name : ClearLog
61 | Info : Deletes the log file, if it exists
62 | Input :
63 | Output :
64 | Result : None
65 | -------------------------------------------------------------------------------}
66 | procedure TFileLogger.ClearLog;
67 | begin
68 | if TFile.Exists(FLogFile) then
69 | TFile.Delete(FLogFile);
70 | end;
71 |
72 | {-------------------------------------------------------------------------------
73 | Name : LogMessage
74 | Info : Appends a message to the log file
75 | Input : aMessage =
76 |
77 | Output :
78 | Result : None
79 | -------------------------------------------------------------------------------}
80 | procedure TFileLogger.LogMessage(aMessage: string);
81 | begin
82 | TFile.AppendAllText(FLogFile, aMessage + sLineBreak, TEncoding.UTF8);
83 | end;
84 |
85 | {-------------------------------------------------------------------------------
86 | Name : OpenLogLocation
87 | Info : Spwans the windows explorer to open the log file directory
88 | Input :
89 | Output :
90 | Result : None
91 | -------------------------------------------------------------------------------}
92 | procedure TFileLogger.OpenLogLocation;
93 | begin
94 | ShellExecute(0,'open', PChar(ExtractFilePath(FLogFile)), nil, nil, SW_SHOWNORMAL) ;
95 | end;
96 |
97 | end.
98 |
99 |
--------------------------------------------------------------------------------
/Source/CtrlTab.FormEditorNotifier.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.FormEditorNotifier
5 |
6 | Info : This Unit contains the class TFormEditorNotifier.
7 |
8 | Copyright (c) 2020 Santiago Burbano
9 | ===============================================================================}
10 | unit CtrlTab.FormEditorNotifier;
11 |
12 | interface
13 |
14 | uses
15 | Classes, SysUtils, ToolsAPI, CtrlTab.Interfaces, CtrlTab.EditorNotifierBase;
16 |
17 | type
18 | TFormEditorNotifier = class(TEditorNotifierBase, IOTANotifier, IOTAFormNotifier, IEditorNotifier)
19 | private
20 | { Called when a component on this form was renamed }
21 | procedure ComponentRenamed(ComponentHandle: TOTAHandle; const OldName, NewName: string);
22 | { IOTAEditorNotifier }
23 | procedure FormActivated;
24 | { This is called immediately prior to the form being streamed out. This
25 | may be called without first getting a BeforeSave as in the case of
26 | the project being compiled. }
27 | procedure FormSaving;
28 | protected
29 | public
30 | constructor Create(aEditor: IOTAFormEditor);
31 | end;
32 |
33 | implementation
34 |
35 | uses
36 | CtrlTab.IdePlugin;
37 |
38 | {-------------------------------------------------------------------------------
39 | Name : Create
40 | Info : Constructor. Register myself as a notifier for AEditor
41 | Input : aEditor = form editor
42 | Output :
43 | Result : None
44 | -------------------------------------------------------------------------------}
45 | constructor TFormEditorNotifier.Create(aEditor: IOTAFormEditor);
46 | begin
47 | inherited Create(aEditor);
48 | FIndex := FEditor.AddNotifier(Self);
49 | end;
50 |
51 | {-------------------------------------------------------------------------------
52 | Name : ComponentRenamed
53 | Info :
54 | Input : ComponentHandle =
55 | OldName =
56 | NewName =
57 |
58 | Output :
59 | Result : None
60 | -------------------------------------------------------------------------------}
61 | procedure TFormEditorNotifier.ComponentRenamed(ComponentHandle: TOTAHandle; const OldName, NewName: string);
62 | begin
63 | end;
64 |
65 | {-------------------------------------------------------------------------------
66 | Name : FormActivated
67 | Info : This method is called when a form is activated.
68 | Input :
69 | Output :
70 | Result : None
71 | -------------------------------------------------------------------------------}
72 | procedure TFormEditorNotifier.FormActivated;
73 | begin
74 | // notify view manager
75 | Plugin.ViewManager.ViewActivated(FFileName);
76 | end;
77 |
78 | {-------------------------------------------------------------------------------
79 | Name : FormSaving
80 | Info :
81 | Input :
82 | Output :
83 | Result : None
84 | -------------------------------------------------------------------------------}
85 | procedure TFormEditorNotifier.FormSaving;
86 | begin
87 | end;
88 |
89 | end.
90 |
91 |
--------------------------------------------------------------------------------
/Source/CtrlTab.FrmOpenDocs.dfm:
--------------------------------------------------------------------------------
1 | object FormOpenDocs: TFormOpenDocs
2 | Left = 0
3 | Top = 0
4 | BorderIcons = [biSystemMenu]
5 | BorderStyle = bsSizeToolWin
6 | Caption = 'Go to...'
7 | ClientHeight = 361
8 | ClientWidth = 678
9 | Color = clBtnFace
10 | Constraints.MinHeight = 250
11 | Constraints.MinWidth = 300
12 | Font.Charset = DEFAULT_CHARSET
13 | Font.Color = clWindowText
14 | Font.Height = -11
15 | Font.Name = 'Tahoma'
16 | Font.Style = []
17 | KeyPreview = True
18 | OldCreateOrder = False
19 | Position = poMainFormCenter
20 | OnClose = FormClose
21 | OnCreate = FormCreate
22 | OnDeactivate = FormDeactivate
23 | OnKeyUp = FormKeyUp
24 | PixelsPerInch = 96
25 | TextHeight = 13
26 | object GroupBoxOpenUnits: TGroupBox
27 | AlignWithMargins = True
28 | Left = 5
29 | Top = 3
30 | Width = 668
31 | Height = 353
32 | Margins.Left = 5
33 | Margins.Right = 5
34 | Margins.Bottom = 5
35 | Align = alClient
36 | Caption = 'Open Files'
37 | TabOrder = 0
38 | object Label_SelectedFile: TLabel
39 | AlignWithMargins = True
40 | Left = 5
41 | Top = 18
42 | Width = 658
43 | Height = 19
44 | Align = alTop
45 | Caption = 'Label_SelectedFile'
46 | Font.Charset = DEFAULT_CHARSET
47 | Font.Color = clWindowText
48 | Font.Height = -16
49 | Font.Name = 'Tahoma'
50 | Font.Style = [fsBold]
51 | ParentFont = False
52 | ExplicitWidth = 153
53 | end
54 | object Label_FullPath: TLabel
55 | Left = 2
56 | Top = 338
57 | Width = 664
58 | Height = 13
59 | Align = alBottom
60 | Caption = 'Label_FullPath'
61 | ExplicitWidth = 69
62 | end
63 | object ListViewOpenFiles: TListView
64 | AlignWithMargins = True
65 | Left = 5
66 | Top = 43
67 | Width = 658
68 | Height = 292
69 | Align = alClient
70 | Columns = <
71 | item
72 | AutoSize = True
73 | end>
74 | ColumnClick = False
75 | ReadOnly = True
76 | RowSelect = True
77 | ShowColumnHeaders = False
78 | TabOrder = 0
79 | ViewStyle = vsReport
80 | OnChange = ListViewOpenFilesChange
81 | OnDblClick = ListViewOpenFilesDblClick
82 | end
83 | end
84 | end
85 |
--------------------------------------------------------------------------------
/Source/CtrlTab.FrmOpenDocs.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.FrmOpenDocs
5 |
6 | Info : This Unit contains the class TFormOpenDocs.
7 |
8 | Copyright (c) 2020 Santiago Burbano
9 | ===============================================================================}
10 | unit CtrlTab.FrmOpenDocs;
11 |
12 | interface
13 |
14 | uses
15 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
16 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls;
17 |
18 | type
19 | TFormOpenDocs = class(TForm)
20 | GroupBoxOpenUnits: TGroupBox;
21 | Label_SelectedFile: TLabel;
22 | Label_FullPath: TLabel;
23 | ListViewOpenFiles: TListView;
24 | procedure FormClose(Sender: TObject; var Action: TCloseAction);
25 | procedure FormCreate(Sender: TObject);
26 | procedure FormDeactivate(Sender: TObject);
27 | procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
28 | function GetDisplayNameFor(const aModuleFileName: string): string;
29 | procedure ListViewOpenFilesChange(Sender: TObject; Item: TListItem; Change: TItemChange);
30 | procedure ListViewOpenFilesDblClick(Sender: TObject);
31 | private
32 | class var
33 | FIsShowing: Boolean;
34 | var
35 | FClosing: Boolean;
36 | // keep track of whether KeyUp was detected to the Tab-Key
37 | FTabKeyUpCalled: Boolean;
38 | procedure RefreshLabels;
39 | public
40 | class property IsShowing: Boolean read FIsShowing;
41 | end;
42 |
43 | var
44 | Form1: TFormOpenDocs;
45 |
46 | implementation
47 |
48 | {$R *.dfm}
49 |
50 | uses
51 | CtrlTab.IdePlugin, ToolsApi, CtrlTab.ViewManager, CtrlTab.Consts,
52 | System.Generics.Collections;
53 |
54 |
55 | {-------------------------------------------------------------------------------
56 | Name : FormClose
57 | Info :
58 | Input : Sender =
59 | Action =
60 |
61 | Output :
62 | Result : None
63 | -------------------------------------------------------------------------------}
64 | procedure TFormOpenDocs.FormClose(Sender: TObject; var Action: TCloseAction);
65 | var
66 | FileToActivateIndex: Integer;
67 | begin
68 | FClosing := True;
69 | if ModalResult = mrOk then
70 | begin
71 | // if Ctrl+Tab was pressed and released very quickly, then no KeyUp event for the Tab is registered
72 | // in this case we will set the item index to 1.
73 | if not FTabKeyUpCalled then
74 | begin
75 | if Plugin.ViewManager.ViewCount > 1 then
76 | FileToActivateIndex := 1
77 | else
78 | FileToActivateIndex := 0;
79 | end
80 | else
81 | FileToActivateIndex := ListViewOpenFiles.ItemIndex;
82 |
83 | if FileToActivateIndex > 0 then
84 | Plugin.ViewManager.ShowSourceView(FileToActivateIndex);
85 | end;
86 | Action := caFree;
87 | FIsShowing := False;
88 |
89 | // enable keyboard hook
90 | Plugin.ActivateKeyboardHook;
91 |
92 | // store size
93 | Plugin.Settings.DialogWidth := Self.Width;
94 | Plugin.Settings.DialogHeight := Self.Height;
95 | end;
96 |
97 | {-------------------------------------------------------------------------------
98 | Name : FormCreate
99 | Info :
100 | Input : Sender =
101 |
102 | Output :
103 | Result : None
104 | -------------------------------------------------------------------------------}
105 | procedure TFormOpenDocs.FormCreate(Sender: TObject);
106 | var
107 | FileDisplayName: string;
108 | i: Integer;
109 | EditorModified: Boolean;
110 | FileNameOnly: string;
111 | j: Integer;
112 | ModifiedEditorMap: TDictionary;
113 | ModuleEditor: IOTAEditor;
114 | ModuleServices: IOTAModuleServices;
115 | OpenModule: IOTAModule;
116 | View: string;
117 | begin
118 | AlphaBlend := True;
119 | AlphaBlendValue := 0;
120 | FIsShowing := True;
121 | FTabKeyUpCalled := False;
122 |
123 | // apply size
124 | if Plugin.Settings.DialogWidth > 0 then
125 | Width := Plugin.Settings.DialogWidth;
126 | if Plugin.Settings.DialogHeight > 0 then
127 | Height := Plugin.Settings.DialogHeight;
128 |
129 |
130 | ModifiedEditorMap := TDictionary.Create;
131 | try
132 | // list of all modified modules
133 | ModuleServices := BorlandIDEServices as IOTAModuleServices;
134 | for i := 0 to ModuleServices.ModuleCount - 1 do
135 | begin
136 | OpenModule := ModuleServices.Modules[i];
137 | for j := 0 to OpenModule.ModuleFileCount - 1 do
138 | begin
139 | ModuleEditor := OpenModule.ModuleFileEditors[j];
140 | if ModuleEditor.Modified then
141 | ModifiedEditorMap.AddOrSetValue(ModuleEditor.FileName, 1);
142 | end;
143 | end;
144 |
145 | // add files to ListView
146 | for i := 0 to Plugin.ViewManager.ViewCount -1 do
147 | begin
148 | View := Plugin.ViewManager.GetViewAt(i);
149 | EditorModified := ModifiedEditorMap.ContainsKey(View);
150 | FileDisplayName := GetDisplayNameFor(Plugin.ViewManager.GetViewAt(i));
151 | FileNameOnly := ExtractFileName(FileDisplayName);
152 |
153 | // append an asterisk to file name if file is marked as modified.
154 | if EditorModified then
155 | FileNameOnly := FileNameOnly + ' *';
156 |
157 | ListViewOpenFiles.AddItem(FileNameOnly, nil);
158 | end;
159 |
160 | if ListViewOpenFiles.Items.Count > 0 then
161 | ListViewOpenFiles.ItemIndex := 0;
162 |
163 | finally
164 | FreeAndNil(ModifiedEditorMap);
165 | end;
166 | end;
167 |
168 |
169 |
170 | {-------------------------------------------------------------------------------
171 | Name : FormDeactivate
172 | Info :
173 | Input : Sender =
174 |
175 | Output :
176 | Result : None
177 | -------------------------------------------------------------------------------}
178 | procedure TFormOpenDocs.FormDeactivate(Sender: TObject);
179 | begin
180 | if not FClosing then Close;
181 | end;
182 |
183 | {-------------------------------------------------------------------------------
184 | Name : FormKeyUp
185 | Info :
186 | Input : Sender =
187 | Key =
188 | Shift =
189 |
190 | Output :
191 | Result : None
192 | -------------------------------------------------------------------------------}
193 | procedure TFormOpenDocs.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
194 | var
195 | Index: Integer;
196 | begin
197 | if Key = VK_CONTROL then
198 | begin
199 | ModalResult := mrOk;
200 | Close;
201 | end
202 | else if (Key = VK_TAB) or (Key = VK_SPACE) then
203 | begin
204 | AlphaBlend := False;
205 | FTabKeyUpCalled := True;
206 |
207 | // if shift is pressed move the opposite direction
208 | if GetKeyState(VK_SHIFT) < 0 then
209 | begin
210 | Index := ListViewOpenFiles.ItemIndex - 1;
211 | if Index< 0 then
212 | Index := ListViewOpenFiles.Items.Count - 1;
213 | end
214 | else
215 | begin
216 | Index := ListViewOpenFiles.ItemIndex + 1;
217 | if Index >= ListViewOpenFiles.Items.Count then
218 | Index := 0;
219 | end;
220 | ListViewOpenFiles.ItemIndex := Index;
221 | end
222 |
223 | else if Key = VK_ESCAPE then
224 | begin
225 | ListViewOpenFiles.ItemIndex := 0; // no action
226 | ModalResult := mrCancel;
227 | Close;
228 | end;
229 | end;
230 |
231 | {-------------------------------------------------------------------------------
232 | Name : GetDisplayNameFor
233 | Info : Returns proper display name for BDS special pages such as the welcome page.
234 | Input : aFileName = Module File Name
235 | Output :
236 | Result : string
237 | -------------------------------------------------------------------------------}
238 | function TFormOpenDocs.GetDisplayNameFor(const aModuleFileName: string): string;
239 | begin
240 | if aModuleFileName = c_WelcomePage then
241 | Result := c_WelcomePageDisplayName
242 | else
243 | Result := aModuleFileName;
244 | end;
245 |
246 | {-------------------------------------------------------------------------------
247 | Name : ListViewOpenFilesChange
248 | Info :
249 | Input : Sender =
250 | Item =
251 | Change =
252 |
253 | Output :
254 | Result : None
255 | -------------------------------------------------------------------------------}
256 | procedure TFormOpenDocs.ListViewOpenFilesChange(Sender: TObject; Item: TListItem; Change: TItemChange);
257 | begin
258 | RefreshLabels;
259 | end;
260 |
261 | {-------------------------------------------------------------------------------
262 | Name : ListViewOpenFilesDblClick
263 | Info :
264 | Input : Sender =
265 |
266 | Output :
267 | Result : None
268 | -------------------------------------------------------------------------------}
269 | procedure TFormOpenDocs.ListViewOpenFilesDblClick(Sender: TObject);
270 | begin
271 | ModalResult := mrOk;
272 | Close;
273 | end;
274 |
275 | {-------------------------------------------------------------------------------
276 | Name : RefreshLabels
277 | Info :
278 | Input :
279 | Output :
280 | Result : None
281 | -------------------------------------------------------------------------------}
282 | procedure TFormOpenDocs.RefreshLabels;
283 | var
284 | FileName: string;
285 | begin
286 | if ListViewOpenFiles.ItemIndex >= 0 then
287 | begin
288 | FileName := GetDisplayNameFor(Plugin.ViewManager.GetViewAt(ListViewOpenFiles.ItemIndex));
289 | Label_FullPath.Caption := FileName;
290 | Label_SelectedFile.Caption := ExtractFileName(FileName);
291 | end
292 | else
293 | begin
294 | Label_FullPath.Caption := '--';
295 | Label_SelectedFile.Caption := '--';
296 | end;
297 |
298 | // make sure selected item is always visible
299 | if Assigned(ListViewOpenFiles.Selected) then
300 | ListViewOpenFiles.Selected.MakeVisible(False);
301 | end;
302 |
303 | end.
304 |
--------------------------------------------------------------------------------
/Source/CtrlTab.IdeNotifier.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.IdeNotifier
5 |
6 | Info : This Unit contains the class TIDENotifier.
7 | This class receives notifications whenever a file is opened/closed.
8 | When a file is opened we attach a editor notifier to it. The editor
9 | notifier is removed once the file is closed.
10 |
11 | Copyright (c) 2020 Santiago Burbano
12 | ===============================================================================}
13 | unit CtrlTab.IdeNotifier;
14 |
15 | interface
16 |
17 | uses
18 | ToolsAPI;
19 |
20 | type
21 | TIDENotifier = class(TNotifierObject, IOTANotifier, IOTAIDENotifier)
22 | private
23 | { IOTAIDENotifier }
24 | procedure FileNotification(NotifyCode: TOTAFileNotification; const FileName: string; var Cancel: Boolean);
25 | procedure BeforeCompile(const Project: IOTAProject; var Cancel: Boolean); overload;
26 | procedure AfterCompile(Succeeded: Boolean); overload;
27 | end;
28 |
29 | implementation
30 |
31 | uses
32 | CtrlTab.IdePlugin, SysUtils, System.Rtti;
33 |
34 |
35 | {-------------------------------------------------------------------------------
36 | Name : AfterCompile
37 | Info :
38 | Input : Succeeded =
39 | Output :
40 | Result : None
41 | -------------------------------------------------------------------------------}
42 | procedure TIDENotifier.AfterCompile(Succeeded: Boolean);
43 | begin
44 | // do nothing
45 | end;
46 |
47 |
48 | {-------------------------------------------------------------------------------
49 | Name : BeforeCompile
50 | Info :
51 | Input : Project =
52 | Cancel =
53 |
54 | Output :
55 | Result : None
56 | -------------------------------------------------------------------------------}
57 | procedure TIDENotifier.BeforeCompile(const Project: IOTAProject; var Cancel: Boolean);
58 | begin
59 | // do nothing
60 | end;
61 |
62 |
63 | {-------------------------------------------------------------------------------
64 | Name : FileNotification
65 | Info :
66 | Input : NotifyCode =
67 | FileName =
68 | Cancel =
69 |
70 | Output :
71 | Result : None
72 | -------------------------------------------------------------------------------}
73 | procedure TIDENotifier.FileNotification(NotifyCode: TOTAFileNotification; const FileName: string; var Cancel: Boolean);
74 | var
75 | ModuleServices: IOTAModuleServices;
76 | Module: IOTAModule;
77 | begin
78 | case NotifyCode of
79 | ofnFileOpened:
80 | begin
81 | ModuleServices := BorlandIDEServices as IOTAModuleServices;
82 | Module := ModuleServices.FindModule(FileName);
83 | if Assigned(Module) then
84 | Plugin.InstallSourceEditorNotifiers(Module);
85 | end;
86 |
87 | ofnFileClosing:
88 | begin
89 | Plugin.FileClosing(FileName);
90 | end;
91 | end;
92 | end;
93 |
94 | end.
95 |
96 |
--------------------------------------------------------------------------------
/Source/CtrlTab.IdePlugin.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.IdePlugin
5 |
6 | Info : This Unit contains the class TIdePlugin.
7 | This class manages all relevant services for this plugin.
8 | It is a singleton.
9 | It is also responsible to hooking/unhooking the keyboard.
10 |
11 | Copyright (c) 2020 Santiago Burbano
12 | ===============================================================================}
13 | unit CtrlTab.IdePlugin;
14 |
15 | interface
16 |
17 | uses
18 | CtrlTab.Interfaces;
19 |
20 | function Plugin: IIdePlugin;
21 |
22 | implementation
23 |
24 | uses
25 | System.Generics.Defaults, Classes, SysUtils, ToolsAPI, CtrlTab.FormEditorNotifier,
26 | CtrlTab.ViewManager, CtrlTab.SourceEditorNotifier, CtrlTab.IdeNotifier, DesignIntf,
27 | CtrlTab.DesignNotification, Vcl.Forms, windows, messages, CtrlTab.FrmOpenDocs, System.IOUtils, CtrlTab.FileLogger, CtrlTab.SettingsManager,
28 | CtrlTab.EditorServicesNotifier;
29 |
30 | type
31 | TIdePlugin = class(TSingletonImplementation, IIdePlugin)
32 | procedure ActivateKeyboardHook;
33 | procedure BootUp;
34 | procedure ClearSourceEditorNotifiers;
35 | procedure DesignerClosed(aFormFile: string);
36 | procedure DisableKeyBoardHook;
37 | procedure EditorNotifierAboutToBeDestroyed(aNotifier: IEditorNotifier);
38 | procedure FileClosing(aUnitFile: string);
39 | function GetLogger: ILogger;
40 | function GetSettings: ISettings;
41 | function GetViewManager: IViewManager;
42 | procedure InstallSourceEditorNotifiers(Module: IOTAModule);
43 | procedure PrintMessage(const aMsg: string);
44 | procedure RemoveIDENotifier;
45 | procedure ShutDown;
46 | private
47 | FDesignNotification: IDesignNotification;
48 | FEditorNotifierId: Integer;
49 | FEditorNotifiers: IInterfaceList;
50 | FIDENotifierIndex: Integer;
51 | FLogger: ILogger;
52 | FViewManager: IViewManager;
53 | FSettingsManager: ISettingsManager;
54 | class function KeyboardHookProc(Code: Integer; WordParam: Word; LongParam: LongInt): LongInt; static; stdcall;
55 | public
56 | class var
57 | KBHook: HHook;
58 | constructor Create;
59 | property Logger: ILogger read GetLogger;
60 | end;
61 |
62 | // the singleton instance
63 | var
64 | PluginSingleton : TIdePlugin;
65 |
66 | {-------------------------------------------------------------------------------
67 | Name : Create
68 | Info :
69 | Input :
70 | Output :
71 | Result : None
72 | -------------------------------------------------------------------------------}
73 | constructor TIdePlugin.Create;
74 | begin
75 | inherited;
76 | FEditorNotifiers := TInterfaceList.Create;
77 | FViewManager := TViewManager.Create;
78 | FDesignNotification := TDesignNotification.Create;
79 | FSettingsManager := TSettingsManager.Create;
80 | FIDENotifierIndex := -1;
81 | KBHook := 0;
82 | end;
83 |
84 | {-------------------------------------------------------------------------------
85 | Name : ActivateKeyboardHook
86 | Info :
87 | Input :
88 | Output :
89 | Result : None
90 | -------------------------------------------------------------------------------}
91 | procedure TIdePlugin.ActivateKeyboardHook;
92 | begin
93 | // test if already active
94 | if KBHook <> 0 then Exit;
95 |
96 | // set hook
97 | KBHook :=SetWindowsHookEx(WH_KEYBOARD,
98 | {callback >} @KeyboardHookProc,
99 | HInstance,
100 | GetCurrentThreadId()) ;
101 | end;
102 |
103 | {-------------------------------------------------------------------------------
104 | Name : BootUp
105 | Info : Initializes the plugin.
106 | Input :
107 | Output :
108 | Result : None
109 | -------------------------------------------------------------------------------}
110 | procedure TIdePlugin.BootUp;
111 | var
112 | Services: IOTAServices;
113 | ModuleServices: IOTAModuleServices;
114 | i: Integer;
115 | OpenModule: IOTAModule;
116 | begin
117 | {$IFDEF DEBUG}
118 | // clear logs
119 | // Logger.ClearLog;
120 | // Logger.OpenLogLocation;
121 | {$ENDIF}
122 |
123 | // install IDE notifier so that we can install editor notifiers for any newly opened module
124 | Services := BorlandIDEServices as IOTAServices;
125 | FIDENotifierIndex := Services.AddNotifier(TIDENotifier.Create);
126 |
127 | // install editor notifiers for all currently open modules
128 | ModuleServices := BorlandIDEServices as IOTAModuleServices;
129 | for i := 0 to ModuleServices.ModuleCount - 1 do
130 | begin
131 | OpenModule := ModuleServices.Modules[i];
132 | InstallSourceEditorNotifiers(OpenModule);
133 | end;
134 |
135 | // install editor services notifier. This is the only way to know when special windows have
136 | // been activated
137 | FEditorNotifierId := (BorlandIDEServices As IOTAEditorServices).AddNotifier(TCtrlTabEditorServicesNotifier.Create);
138 |
139 | RegisterDesignNotification(FDesignNotification);
140 |
141 | ActivateKeyboardHook;
142 |
143 | FSettingsManager.BootUp;
144 | end;
145 |
146 | {-------------------------------------------------------------------------------
147 | Name : ClearSourceEditorNotifiers
148 | Info :
149 | Input :
150 | Output :
151 | Result : None
152 | -------------------------------------------------------------------------------}
153 | procedure TIdePlugin.ClearSourceEditorNotifiers;
154 | var
155 | I: Integer;
156 | Notifier: IEditorNotifier;
157 | begin
158 | if Assigned(FEditorNotifiers) then
159 | begin
160 | for I := FEditorNotifiers.Count - 1 downto 0 do
161 | begin
162 | // Destroyed calls RemoveNotifier which in turn releases the instance
163 | if Supports(FEditorNotifiers[i], IEditorNotifier, Notifier) then
164 | Notifier.CleanUp;
165 | end;
166 | FEditorNotifiers.Clear;
167 | end;
168 | end;
169 |
170 | {-------------------------------------------------------------------------------
171 | Name : DesignerClosed
172 | Info :
173 | Input : aFormFile =
174 |
175 | Output :
176 | Result : None
177 | -------------------------------------------------------------------------------}
178 | procedure TIdePlugin.DesignerClosed(aFormFile: string);
179 | var
180 | EditorNotifier: IEditorNotifier;
181 | FormNotifier: IOTAFormNotifier;
182 | i: Integer;
183 | begin
184 | FViewManager.ViewClosed(aFormFile);
185 |
186 | for i := 0 to FEditorNotifiers.Count -1 do
187 | begin
188 | if Supports(FEditorNotifiers[i], IOTAFormNotifier, FormNotifier) then
189 | begin
190 | if Supports(FEditorNotifiers[i], IEditorNotifier, EditorNotifier) and (EditorNotifier.FileName = aFormFile) then
191 | begin
192 |
193 | FEditorNotifiers.Delete(i);
194 | EditorNotifier.CleanUp;
195 | break;
196 | end;
197 | end;
198 | end;
199 | end;
200 |
201 | {-------------------------------------------------------------------------------
202 | Name : DisableKeyBoardHook
203 | Info :
204 | Input :
205 | Output :
206 | Result : None
207 | -------------------------------------------------------------------------------}
208 | procedure TIdePlugin.DisableKeyBoardHook;
209 | begin
210 | {unhook the keyboard interception}
211 | if KBHook <> 0 then
212 | begin
213 | UnHookWindowsHookEx(KBHook);
214 | KBHook := 0;
215 | end;
216 | end;
217 |
218 | {-------------------------------------------------------------------------------
219 | Name : EditorNotifierAboutToBeDestroyed
220 | Info :
221 | Input : aNotifier =
222 |
223 | Output :
224 | Result : None
225 | -------------------------------------------------------------------------------}
226 | procedure TIdePlugin.EditorNotifierAboutToBeDestroyed(aNotifier: IEditorNotifier);
227 | var
228 | Index: Integer;
229 | begin
230 | Index := FEditorNotifiers.IndexOf(aNotifier as IInterface);
231 | if Index >= 0 then
232 | FEditorNotifiers.Delete(Index);
233 | end;
234 |
235 | {-------------------------------------------------------------------------------
236 | Name : FileClosing
237 | Info :
238 | Input : aUnitFile =
239 |
240 | Output :
241 | Result : None
242 | -------------------------------------------------------------------------------}
243 | procedure TIdePlugin.FileClosing(aUnitFile: string);
244 | var
245 | EditorNotifier: IEditorNotifier;
246 | FormNotifier: IOTAEditorNotifier;
247 | i: Integer;
248 | begin
249 | FViewManager.ViewClosed(aUnitFile);
250 |
251 | for i := 0 to FEditorNotifiers.Count -1 do
252 | begin
253 | if Supports(FEditorNotifiers[i], IOTAEditorNotifier, FormNotifier) then
254 | begin
255 | if Supports(FEditorNotifiers[i], IEditorNotifier, EditorNotifier) and (EditorNotifier.FileName = aUnitFile) then
256 | begin
257 | FEditorNotifiers.Delete(i);
258 | EditorNotifier.CleanUp;
259 | break;
260 | end;
261 | end;
262 | end;
263 | end;
264 |
265 | {-------------------------------------------------------------------------------
266 | Name : GetLogger
267 | Info :
268 | Input :
269 | Output :
270 | Result : ILogger
271 | -------------------------------------------------------------------------------}
272 | function TIdePlugin.GetLogger: ILogger;
273 | begin
274 | if not Assigned(FLogger) then
275 | FLogger := TFileLogger.Create;
276 | Result := FLogger;
277 | end;
278 |
279 | {-------------------------------------------------------------------------------
280 | Name : GetSettings
281 | Info :
282 | Input :
283 | Output :
284 | Result : ISettings
285 | -------------------------------------------------------------------------------}
286 | function TIdePlugin.GetSettings: ISettings;
287 | begin
288 | Result := FSettingsManager.Settings;
289 | end;
290 |
291 | {-------------------------------------------------------------------------------
292 | Name : GetViewManager
293 | Info :
294 | Input :
295 | Output :
296 | Result : IViewManager
297 | -------------------------------------------------------------------------------}
298 | function TIdePlugin.GetViewManager: IViewManager;
299 | begin
300 | Result := FViewManager;
301 | end;
302 |
303 | {-------------------------------------------------------------------------------
304 | Name : InstallSourceEditorNotifiers
305 | Info :
306 | Input : Module =
307 |
308 | Output :
309 | Result : None
310 | -------------------------------------------------------------------------------}
311 | procedure TIdePlugin.InstallSourceEditorNotifiers(Module: IOTAModule);
312 | var
313 | FormEditor: IOTAFormEditor;
314 | i: Integer;
315 | ModuleEditor: IOTAEditor;
316 | OtaServices: IOTAServices;
317 | SourceEditor: IOTASourceEditor;
318 | begin
319 | OtaServices := BorlandIDEServices as IOTAServices;
320 |
321 | // if module has no module files, it is a special module such as the welcome page.
322 | if Module.ModuleFileCount = 0 then
323 | begin
324 | // exclude .groupproj
325 | // register open file
326 | if not OtaServices.IsProjectGroup(Module.FileName) then
327 | Plugin.ViewManager.ViewActivated(Module.FileName);
328 | Exit;
329 | end;
330 |
331 | // attach a notifier
332 | for i := 0 to Module.ModuleFileCount - 1 do
333 | begin
334 | ModuleEditor := Module.ModuleFileEditors[i];
335 |
336 | if Supports(ModuleEditor, IOTASourceEditor, SourceEditor) then
337 | begin
338 | // add notifier
339 | // view manager will be notified only once a view is inserted.
340 | // otherwise we would end up with several entries for open modules
341 | // that do not have a file tab associated with them (dpk, dpr files).
342 | FEditorNotifiers.Add(TSourceEditorNotifier.Create(SourceEditor) as IInterface);
343 | end
344 | else if Supports(ModuleEditor, IOTAFormEditor, FormEditor) then
345 | begin
346 | // add notifier
347 | FEditorNotifiers.Add(TFormEditorNotifier.Create(FormEditor) as IInterface);
348 | // do not register file with view manager. File must be registered only when
349 | // IEditorNotifier.ViewNotification = opInsert
350 | // otherwise modules which have been implicetely opened in the background will be
351 | // listed (visual form inheritance)
352 | end;
353 | end;
354 | end;
355 |
356 | {-------------------------------------------------------------------------------
357 | Name : KeyboardHookProc
358 | Info : Keyboard hook callback. This method is called whenever a key is pressed in the IDE.
359 | Input : Code =
360 | WordParam =
361 | LongParam =
362 |
363 | Output :
364 | Result : LongInt
365 | -------------------------------------------------------------------------------}
366 | class function TIdePlugin.KeyboardHookProc(Code: Integer; WordParam: Word; LongParam: LongInt): LongInt;
367 | var
368 | Form: TFormOpenDocs;
369 | begin
370 | // Code = HC_ACTION -> The wParam and lParam parameters contain information about a keystroke message.
371 | if (Code = HC_ACTION) then
372 | begin
373 | case WordParam of
374 | VK_TAB:
375 | begin
376 | if GetKeyState(VK_CONTROL) < 0 then
377 | begin
378 | // make sure only one instance can be displayed
379 | if not TFormOpenDocs.IsShowing and (Plugin.ViewManager.ViewCount > 1) then
380 | begin
381 | // create form
382 | Application.CreateForm(TFormOpenDocs, Form);
383 | Form.Show;
384 |
385 | // If the hook procedure processed the message, it may return a nonzero value to prevent the system from
386 | // passing the message to the rest of the hook chain or the target window procedure.
387 | Result := 1;
388 |
389 | // disable keyboard hook
390 | Plugin.DisableKeyBoardHook;
391 | Exit;
392 | end;
393 | end;
394 | end;
395 | end;
396 | end;
397 |
398 | // be a good citizen, if procedure did not process the message, it is highly recommended
399 | // that you call CallNextHookEx and return the value it returns
400 | Result := CallNextHookEx(KBHook, Code, WordParam, LongParam);;
401 | end;
402 |
403 | {-------------------------------------------------------------------------------
404 | Name : PrintMessage
405 | Info : Prints a message to the Messages View.
406 | Input : aMsg =
407 |
408 | Output :
409 | Result : None
410 | -------------------------------------------------------------------------------}
411 | procedure TIdePlugin.PrintMessage(const aMsg: string);
412 | begin
413 | (BorlandIDEServices as IOTAMessageServices).AddTitleMessage(aMsg);
414 | end;
415 |
416 | {-------------------------------------------------------------------------------
417 | Name : RemoveIDENotifier
418 | Info :
419 | Input :
420 | Output :
421 | Result : None
422 | -------------------------------------------------------------------------------}
423 | procedure TIdePlugin.RemoveIDENotifier;
424 | var
425 | Services: IOTAServices;
426 | begin
427 | Services := BorlandIDEServices as IOTAServices;
428 | if Assigned(Services) then
429 | Services.RemoveNotifier(FIDENotifierIndex);
430 | end;
431 |
432 | {-------------------------------------------------------------------------------
433 | Name : ShutDown
434 | Info :
435 | Input :
436 | Output :
437 | Result : None
438 | -------------------------------------------------------------------------------}
439 | procedure TIdePlugin.ShutDown;
440 | begin
441 | DisableKeyBoardHook;
442 |
443 | FSettingsManager.ShutDown;
444 | FViewManager.ShutDown;
445 | ClearSourceEditorNotifiers;
446 | RemoveIDENotifier;
447 |
448 | // remove editor services notifier
449 | if FEditorNotifierId > -1 then
450 | (BorlandIDEServices As IOTAEditorServices).RemoveNotifier(FEditorNotifierId);
451 |
452 | UnRegisterDesignNotification(FDesignNotification);
453 |
454 | FreeAndNil(PluginSingleton);
455 | end;
456 |
457 | {-------------------------------------------------------------------------------
458 | Name : Plugin
459 | Info :
460 | Input :
461 | Output :
462 | Result : IIdePlugin
463 | -------------------------------------------------------------------------------}
464 | function Plugin: IIdePlugin;
465 | begin
466 | Result := PluginSingleton;
467 | end;
468 |
469 | initialization
470 | PluginSingleton := TIdePlugin.Create;
471 | end.
472 |
473 |
--------------------------------------------------------------------------------
/Source/CtrlTab.Interfaces.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.Interfaces
5 |
6 | Info : This Unit contains the class None.
7 |
8 | Copyright (c) 2020 Santiago Burbano
9 | ===============================================================================}
10 | unit CtrlTab.Interfaces;
11 |
12 | interface
13 |
14 | uses
15 | ToolsApi;
16 |
17 | type
18 | IEditorNotifier = interface;
19 | ILogger = interface;
20 | ISettings = interface;
21 |
22 | IViewManager = interface
23 | ['{53A0592B-86F9-42AF-9ABF-00A1B47E3081}']
24 | function GetViewAt(aIndex: Integer): string;
25 | function GetViewCount: Integer;
26 | procedure ShowSourceView(aIndex: Integer);
27 | procedure ShutDown;
28 | procedure ViewActivated(const aFileName: string);
29 | procedure ViewClosed(const aViewName: string);
30 | property ViewCount: Integer read GetViewCount;
31 | end;
32 |
33 | IIdePlugin = interface
34 | ['{1DFF971B-BE77-48D2-90E8-5F507ADA128C}']
35 | procedure ActivateKeyboardHook;
36 | procedure BootUp;
37 | procedure DesignerClosed(aFormFile: string);
38 | procedure DisableKeyBoardHook;
39 | procedure FileClosing(aFormFile: string);
40 | function GetLogger: ILogger;
41 | function GetViewManager: IViewManager;
42 | procedure InstallSourceEditorNotifiers(Module: IOTAModule);
43 | procedure PrintMessage(const aMsg: string);
44 | procedure ShutDown;
45 | procedure EditorNotifierAboutToBeDestroyed(aNotifier: IEditorNotifier);
46 | function GetSettings: ISettings;
47 | property Logger: ILogger read GetLogger;
48 | property Settings: ISettings read GetSettings;
49 | property ViewManager: IViewManager read GetViewManager;
50 | end;
51 |
52 | IEditorNotifier = interface
53 | ['{3F5EBCA8-162C-467F-A21D-4EB5800F450B}']
54 | procedure CleanUp;
55 | function GetFileName: string;
56 | property FileName: string read GetFileName;
57 | end;
58 |
59 | ILogger = interface
60 | ['{B4510A5D-AD1F-4E08-A85B-D1CE1A115D50}']
61 | procedure ClearLog;
62 | procedure LogMessage(aMessage: string);
63 | procedure OpenLogLocation;
64 | end;
65 |
66 | ISettings = interface
67 | ['{FCC89212-18AC-4B9A-BC86-41FF2845061E}']
68 | function GetDialogHeight: Integer;
69 | function GetDialogWidth: Integer;
70 | procedure SetDialogHeight(const Value: Integer);
71 | procedure SetDialogWidth(const Value: Integer);
72 | property DialogHeight: Integer read GetDialogHeight write SetDialogHeight;
73 | property DialogWidth: Integer read GetDialogWidth write SetDialogWidth;
74 |
75 | end;
76 |
77 | ISettingsManager = interface
78 | ['{DB19CACB-AD8A-4A9E-9CFA-986E77B62BD8}']
79 | procedure BootUp;
80 | function GetSettings: ISettings;
81 | procedure ShutDown;
82 | property Settings: ISettings read GetSettings;
83 | end;
84 |
85 | implementation
86 |
87 | end.
88 |
89 |
--------------------------------------------------------------------------------
/Source/CtrlTab.Main.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.Main
5 |
6 | Info : This Unit contains the Register function. It is the entry point for
7 | this plugin.
8 |
9 | Copyright (c) 2020 Santiago Burbano
10 | ===============================================================================}
11 | unit CtrlTab.Main;
12 |
13 | interface
14 |
15 | procedure Register;
16 |
17 | implementation
18 |
19 | uses
20 | CtrlTab.IdePlugin, ToolsAPI;
21 |
22 | {-------------------------------------------------------------------------------
23 | Name : Register
24 | Info : Entry point for design time component
25 | Input :
26 | Output :
27 | Result :
28 | -------------------------------------------------------------------------------}
29 | procedure Register;
30 | begin
31 | Plugin.BootUp;
32 | end;
33 |
34 | initialization
35 |
36 | finalization
37 | Plugin.ShutDown;
38 | end.
39 |
40 |
--------------------------------------------------------------------------------
/Source/CtrlTab.Settings.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.Settings
5 |
6 | Info : This Unit contains the class TViewManager.
7 |
8 | Copyright (c) 2020 - Santiago Burbano
9 | ===============================================================================}
10 | unit CtrlTab.Settings;
11 |
12 | interface
13 |
14 | uses
15 | CtrlTab.Interfaces, System.Classes;
16 |
17 | type
18 | TPluginSettings = class(TInterfacedObject, ISettings)
19 | private
20 | FDialogHeight: Integer;
21 | FDialogWidth: Integer;
22 | function GetDialogHeight: Integer;
23 | function GetDialogWidth: Integer;
24 | procedure SetDialogHeight(const Value: Integer);
25 | procedure SetDialogWidth(const Value: Integer);
26 | public
27 | constructor Create;
28 | end;
29 |
30 | implementation
31 |
32 | uses
33 | System.SysUtils;
34 |
35 | constructor TPluginSettings.Create;
36 | begin
37 | inherited;
38 | FDialogHeight := 0;
39 | FDialogWidth := 0;
40 | end;
41 |
42 | function TPluginSettings.GetDialogHeight: Integer;
43 | begin
44 | Result := FDialogHeight;
45 | end;
46 |
47 | function TPluginSettings.GetDialogWidth: Integer;
48 | begin
49 | Result := FDialogWidth;
50 | end;
51 |
52 | procedure TPluginSettings.SetDialogHeight(const Value: Integer);
53 | begin
54 | FDialogHeight := Value;
55 | end;
56 |
57 | procedure TPluginSettings.SetDialogWidth(const Value: Integer);
58 | begin
59 | FDialogWidth := Value;
60 | end;
61 |
62 |
63 | end.
64 |
--------------------------------------------------------------------------------
/Source/CtrlTab.SettingsManager.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab
3 |
4 | Name : CtrlTab.SettingsManager
5 |
6 | Info : This Unit contains the class TSettingsManager. Handles storage of
7 | plugin settings.
8 |
9 | Copyright (c) 2020 - Santiago Burbano
10 | ===============================================================================}
11 | unit CtrlTab.SettingsManager;
12 |
13 | interface
14 |
15 | uses
16 | CtrlTab.Interfaces, System.Classes, ToolsApi;
17 |
18 | type
19 | TSettingsManager = class(TInterfacedObject, ISettingsManager)
20 | private
21 | FSettings: ISettings;
22 | procedure BootUp;
23 | function GetSettings: ISettings;
24 | procedure LoadSettings;
25 | procedure PersistSettings;
26 | procedure ShutDown;
27 | public
28 | constructor Create;
29 | destructor Destroy; override;
30 | end;
31 |
32 | implementation
33 |
34 | uses
35 | System.SysUtils, CtrlTab.Settings, System.Win.Registry, WinApi.Windows, CtrlTab.IdePlugin;
36 |
37 | const
38 | c_CtrlTabRegistryKey = 'Software\CtrlTab';
39 | c_Value_Height = 'height';
40 | c_Value_Width = 'width';
41 |
42 | constructor TSettingsManager.Create;
43 | begin
44 | inherited;
45 | FSettings := TPluginSettings.Create;
46 | end;
47 |
48 | destructor TSettingsManager.Destroy;
49 | begin
50 | inherited;
51 | end;
52 |
53 | {-------------------------------------------------------------------------------
54 | Name : BootUp
55 | Info : Called when Plugin is loading
56 | Input :
57 | Output :
58 | Result : None
59 | -------------------------------------------------------------------------------}
60 | procedure TSettingsManager.BootUp;
61 | begin
62 | LoadSettings;
63 | end;
64 |
65 | function TSettingsManager.GetSettings: ISettings;
66 | begin
67 | Result := FSettings;
68 | end;
69 |
70 | {-------------------------------------------------------------------------------
71 | Name : ShutDown
72 | Info : Called when Ide is shutting down
73 | Input :
74 | Output :
75 | Result : None
76 | -------------------------------------------------------------------------------}
77 | procedure TSettingsManager.ShutDown;
78 | begin
79 | PersistSettings;
80 | end;
81 |
82 | {-------------------------------------------------------------------------------
83 | Name : LoadSettings
84 | Info :
85 | Input :
86 | Output :
87 | Result : None
88 | -------------------------------------------------------------------------------}
89 | procedure TSettingsManager.LoadSettings;
90 | var
91 | Registry: TRegistry;
92 | begin
93 | Registry := TRegistry.Create(KEY_READ);
94 | try
95 | try
96 | Registry.RootKey := HKEY_CURRENT_USER;
97 |
98 | // do not want to create it if it doesn't exist
99 | if not Registry.OpenKey(c_CtrlTabRegistryKey, False) then Exit;
100 |
101 | if Registry.ValueExists(c_Value_Height) then
102 | FSettings.DialogHeight := Registry.ReadInteger(c_Value_Height);
103 |
104 | if Registry.ValueExists(c_Value_Height) then
105 | FSettings.DialogWidth := Registry.ReadInteger(c_Value_Width);
106 | finally
107 | Registry.Free;
108 | end;
109 | except
110 | on E:Exception do
111 | Plugin.PrintMessage(Format('Failed to restore settings: %s', [E.Message]));
112 | end;
113 | end;
114 |
115 |
116 | procedure TSettingsManager.PersistSettings;
117 | var
118 | Registry: TRegistry;
119 | begin
120 | Registry := TRegistry.Create(KEY_WRITE);
121 | try
122 | try
123 | Registry.RootKey := HKEY_CURRENT_USER;
124 |
125 | // create it if it doesn't exist
126 | if not Registry.OpenKey(c_CtrlTabRegistryKey, True) then
127 | begin
128 | Plugin.PrintMessage('Failed to persist settings.');
129 | Exit;
130 | end;
131 |
132 | Registry.WriteInteger(c_Value_Height, FSettings.DialogHeight);
133 | Registry.WriteInteger(c_Value_Width, FSettings.DialogWidth);
134 | finally
135 | Registry.Free;
136 | end;
137 | except
138 | on E:Exception do
139 | Plugin.PrintMessage(Format('Failed to persist settings: %s', [E.Message]));
140 | end;
141 | end;
142 |
143 |
144 | end.
145 |
--------------------------------------------------------------------------------
/Source/CtrlTab.SourceEditorNotifier.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.SourceEditorNotifier
5 |
6 | Info : This Unit contains the class TSourceEditorNotifier.
7 |
8 | Copyright (c) 2020 Santiago Burbano
9 | ===============================================================================}
10 | unit CtrlTab.SourceEditorNotifier;
11 |
12 | interface
13 |
14 | uses
15 | Classes, SysUtils, ToolsAPI, CtrlTab.Interfaces, CtrlTab.EditorNotifierBase;
16 |
17 | type
18 | TSourceEditorNotifier = class(TEditorNotifierBase, IOTANotifier, IOTAEditorNotifier, IEditorNotifier)
19 | private
20 | procedure ViewActivated(const View: IOTAEditView);
21 | procedure ViewNotification(const View: IOTAEditView; Operation: TOperation);
22 | protected
23 | public
24 | constructor Create(AEditor: IOTAEditor); reintroduce;
25 | end;
26 |
27 | implementation
28 |
29 | uses
30 | CtrlTab.IdePlugin;
31 |
32 | {-------------------------------------------------------------------------------
33 | Name : Create
34 | Info : Constructor. Register myself as a notifier for AEditor
35 | Input : AEditor = source editor
36 | Output :
37 | Result : None
38 | -------------------------------------------------------------------------------}
39 | constructor TSourceEditorNotifier.Create(AEditor: IOTAEditor);
40 | begin
41 | inherited;
42 | FIndex := FEditor.AddNotifier(Self);
43 | end;
44 |
45 |
46 | {-------------------------------------------------------------------------------
47 | Name : ViewActivated
48 | Info : This is called when the associated view is activated in the editor.
49 | Input : View = view which was activated.
50 | Output :
51 | Result : None
52 | -------------------------------------------------------------------------------}
53 | procedure TSourceEditorNotifier.ViewActivated(const View: IOTAEditView);
54 | begin
55 | // notify view manager that a view was activated.
56 | Plugin.ViewManager.ViewActivated(View.Buffer.FileName);
57 | end;
58 |
59 | {-------------------------------------------------------------------------------
60 | Name : ViewNotification
61 | Info : Called when a new edit view is created(opInsert) or destroyed(opRemove)
62 | Input : View =
63 | Operation = remove of insert
64 | Output :
65 | Result : None
66 | -------------------------------------------------------------------------------}
67 | procedure TSourceEditorNotifier.ViewNotification(const View: IOTAEditView; Operation: TOperation);
68 | begin
69 | if Operation = opRemove then
70 | begin
71 | // notify unit manager that a view has been closed.
72 | Plugin.FileClosing(View.Buffer.FileName);
73 | end
74 | else if Operation = opInsert then
75 | begin
76 | // register open file
77 | Plugin.ViewManager.ViewActivated(View.Buffer.FileName);
78 | end;
79 | end;
80 |
81 | end.
82 |
83 |
--------------------------------------------------------------------------------
/Source/CtrlTab.ViewManager.pas:
--------------------------------------------------------------------------------
1 | {===============================================================================
2 | Project : DelphiCtrlTab_D27
3 |
4 | Name : CtrlTab.ViewManager
5 |
6 | Info : This Unit contains the class TViewManager.
7 |
8 | Copyright (c) 2020 - Santiago Burbano
9 | ===============================================================================}
10 | unit CtrlTab.ViewManager;
11 |
12 | interface
13 |
14 | uses
15 | CtrlTab.Interfaces, System.Classes, ToolsApi;
16 |
17 | type
18 | TViewManager = class(TInterfacedObject, IViewManager)
19 | function GetViewAt(aIndex: Integer): string;
20 | function GetViewCount: Integer;
21 | procedure ShutDown;
22 | procedure ViewActivated(const aFileName: string);
23 | procedure ViewClosed(const aViewName: string);
24 | private
25 | FUnits: TStringList;
26 | procedure ShowSourceView(aIndex: Integer);
27 | public
28 | constructor Create;
29 | destructor Destroy; override;
30 | end;
31 |
32 | implementation
33 |
34 | uses
35 | System.SysUtils;
36 |
37 | constructor TViewManager.Create;
38 | begin
39 | inherited;
40 | FUnits := TStringList.Create;
41 | end;
42 |
43 | destructor TViewManager.Destroy;
44 | begin
45 | inherited;
46 | FreeAndNil(FUnits);
47 | end;
48 |
49 | function TViewManager.GetViewAt(aIndex: Integer): string;
50 | begin
51 | Result := FUnits[aIndex];
52 | end;
53 |
54 | function TViewManager.GetViewCount: Integer;
55 | begin
56 | Result := FUnits.Count;
57 | end;
58 |
59 | procedure TViewManager.ShowSourceView(aIndex: Integer);
60 | var
61 | FileToShow: string;
62 | i: Integer;
63 | j: Integer;
64 | ModuleEditor: IOTAEditor;
65 | ModuleServices: IOTAModuleServices;
66 | OpenModule: IOTAModule;
67 | SpecialModule: IOTAModule;
68 | begin
69 | FileToShow := FUnits[aIndex];
70 | SpecialModule := nil;
71 |
72 | // find open module and show it
73 | ModuleServices := BorlandIDEServices as IOTAModuleServices;
74 | for i := 0 to ModuleServices.ModuleCount - 1 do
75 | begin
76 | OpenModule := ModuleServices.Modules[i];
77 |
78 | // loop editors
79 | for j := 0 to OpenModule.ModuleFileCount - 1 do
80 | begin
81 | ModuleEditor := OpenModule.ModuleFileEditors[j];
82 | if ModuleEditor.FileName = FileToShow then
83 | begin
84 | ModuleEditor.Show;
85 | Exit;
86 | end;
87 | end;
88 |
89 | // Could be a special module (Welcome Page)
90 | if OpenModule.FileName = FileToShow then
91 | begin
92 | SpecialModule := OpenModule;
93 | end;
94 | end;
95 |
96 | // Could be a special module (Welcome Page)
97 | if Assigned(SpecialModule) then
98 | SpecialModule.Show;
99 | end;
100 |
101 | procedure TViewManager.ShutDown;
102 | begin
103 | FUnits.Clear;
104 | end;
105 |
106 |
107 | procedure TViewManager.ViewActivated(const aFileName: string);
108 | var
109 | Index: Integer;
110 | begin
111 | Index := FUnits.IndexOf(aFileName);
112 | if Index = 0 then Exit;
113 | // remove if already in list
114 | if Index >= 0 then
115 | FUnits.Delete(Index);
116 | // add to top
117 | FUnits.Insert(0, aFileName);
118 | end;
119 |
120 | procedure TViewManager.ViewClosed(const aViewName: string);
121 | var
122 | Index: Integer;
123 | begin
124 | Index := FUnits.IndexOf(aViewName);
125 | if Index >= 0 then
126 | FUnits.Delete(Index);
127 | end;
128 |
129 | end.
130 |
--------------------------------------------------------------------------------
/binaries/Release/DelphiCtrlTab_D23.bpl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/santiagoIT/DelphiCtrlTab/f9f547b810af70e22c9009a7d36da79b38145f6f/binaries/Release/DelphiCtrlTab_D23.bpl
--------------------------------------------------------------------------------
/binaries/Release/DelphiCtrlTab_D26.bpl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/santiagoIT/DelphiCtrlTab/f9f547b810af70e22c9009a7d36da79b38145f6f/binaries/Release/DelphiCtrlTab_D26.bpl
--------------------------------------------------------------------------------
/binaries/Release/DelphiCtrlTab_D27.bpl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/santiagoIT/DelphiCtrlTab/f9f547b810af70e22c9009a7d36da79b38145f6f/binaries/Release/DelphiCtrlTab_D27.bpl
--------------------------------------------------------------------------------
/binaries/Release/DelphiCtrlTab_D28.bpl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/santiagoIT/DelphiCtrlTab/f9f547b810af70e22c9009a7d36da79b38145f6f/binaries/Release/DelphiCtrlTab_D28.bpl
--------------------------------------------------------------------------------
/docs/images/DelphiCtrlTab.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/santiagoIT/DelphiCtrlTab/f9f547b810af70e22c9009a7d36da79b38145f6f/docs/images/DelphiCtrlTab.jpg
--------------------------------------------------------------------------------
/msbuild/.targets/DelphiCtrlTab.Compile.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/msbuild/DelphiCtrlTab.proj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/msbuild/buildAll.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | SET batPath=%~dp0..
4 |
5 | echo BATPATH: %batPath%
6 |
7 |
8 |
9 |
10 | REM MS BUILD
11 | SET MSB=C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin
12 | IF NOT EXIST "%MSB%" SET MSB=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin
13 | IF NOT EXIST "%MSB%" SET MSB=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin
14 |
15 | REM Delphi 11 - Alexandria
16 | SET BDSVERSION=22.0
17 | SET BDS=C:\Program Files (x86)\Embarcadero\Studio\%BDSVERSION%
18 | IF NOT EXIST "%BDS%" SET BDS=C:\Program Files (x86)\Embarcadero\Studio\%BDSVERSION%
19 |
20 | SET BDSCOMMONDIR=C:\Users\Public\Documents\Embarcadero\Studio\%BDSVERSION%
21 | "%MSB%\MSBuild.exe" DelphiCtrlTab.proj /t:CompileD28 /p:OutDir=%batPath%\build\bin\
22 |
23 | REM Delphi Sydney
24 | SET BDSVERSION=21.0
25 | SET BDS=C:\Program Files (x86)\Embarcadero\Studio\%BDSVERSION%
26 | IF NOT EXIST "%BDS%" SET BDS=C:\Program Files (x86)\Embarcadero\Studio\%BDSVERSION%
27 |
28 | SET BDSCOMMONDIR=C:\Users\Public\Documents\Embarcadero\Studio\%BDSVERSION%
29 | "%MSB%\MSBuild.exe" DelphiCtrlTab.proj /t:CompileD27 /p:OutDir=%batPath%\build\bin\
30 |
31 | REM Delphi Rio
32 | SET BDSVERSION=20.0
33 | SET BDS=C:\Program Files (x86)\Embarcadero\Studio\%BDSVERSION%
34 | IF NOT EXIST "%BDS%" SET BDS=C:\Program Files (x86)\Embarcadero\Studio\%BDSVERSION%
35 |
36 | SET BDSCOMMONDIR=C:\Users\Public\Documents\Embarcadero\Studio\%BDSVERSION%
37 | "%MSB%\MSBuild.exe" DelphiCtrlTab.proj /t:CompileD26 /p:OutDir=%batPath%\build\bin\
38 |
39 | REM Delphi Seattle
40 | SET BDSVERSION=17.0
41 | SET BDS=C:\Program Files (x86)\Embarcadero\Studio\%BDSVERSION%
42 | IF NOT EXIST "%BDS%" SET BDS=C:\Program Files (x86)\Embarcadero\Studio\%BDSVERSION%
43 |
44 | SET BDSCOMMONDIR=C:\Users\Public\Documents\Embarcadero\Studio\%BDSVERSION%
45 | "%MSB%\MSBuild.exe" DelphiCtrlTab.proj /t:CompileD23 /p:OutDir=%batPath%\build\bin\
46 |
47 |
48 | IF "%4" NEQ "NOPAUSE" pause
--------------------------------------------------------------------------------