686 Commits

Author SHA1 Message Date
fd8d7b22f4 de 2025-12-19 14:44:24 +01:00
b40235db0f update deploy script
# Conflicts:
#	Pilz.Net/Pilz.Net.csproj
#	Pilz/Pilz.csproj
2025-12-19 14:29:24 +01:00
6b0b19fcfb update deploy script
# Conflicts:
#	Pilz.Net/Pilz.Net.csproj
#	Pilz/Pilz.csproj
2025-12-19 14:27:31 +01:00
Pilzinsel64
b940686cdd fix 2025-12-09 10:17:29 +01:00
Pilzinsel64
528c97094c ui 2025-12-09 09:58:41 +01:00
Pilzinsel64
c2d13876f6 improve 2025-12-09 09:33:29 +01:00
Pilzinsel64
ce3be11e16 another fix 2025-12-09 09:26:57 +01:00
Pilzinsel64
f5ee557812 fix 2025-12-09 09:20:01 +01:00
Pilzinsel64
08f55f2a99 rc 2025-12-09 08:57:13 +01:00
Pilzinsel64
33c422264a update 2025-12-09 08:55:32 +01:00
Pilzinsel64
7e21064b8b version 2025-12-09 08:52:40 +01:00
Pilzinsel64
061eccf846 fix 2025-12-03 12:10:44 +01:00
Pilzinsel64
222dd7ea8a fixes 2025-12-03 09:22:34 +01:00
Pilzinsel64
3381e5cbf0 version bumpo 2025-12-03 09:02:49 +01:00
Pilzinsel64
ffa6c647f8 final fix 2025-12-03 08:54:28 +01:00
Pilzinsel64
06f2fcaddd support raw messages on apiclient->apiserver 2025-12-03 07:58:39 +01:00
2bc2352cb1 version bump 2025-11-30 09:40:58 +01:00
249de93df7 finish 2025-11-30 09:40:45 +01:00
c2dcc88e22 wip 2025-11-30 09:34:46 +01:00
18c77aacbe version bump 2025-11-30 09:04:53 +01:00
25e918ceea HeaderMenuItem 2025-11-30 09:04:38 +01:00
Pilzinsel64
01920b68d7 final fix 2025-11-21 10:46:33 +01:00
Pilzinsel64
125d76e5f2 item result on execute 2025-11-21 10:42:55 +01:00
Pilzinsel64
f72ddd71e9 improve regex 2025-11-21 10:18:02 +01:00
Pilzinsel64
666126808d jobs fixes 2025-11-21 10:01:55 +01:00
Pilzinsel64
f53145d62e version bump 2025-11-21 08:45:31 +01:00
Pilzinsel64
7c6c216b02 return IOrderedQueryable and order by id by default 2025-11-21 08:45:09 +01:00
42bb1f884a formatting 2025-11-17 16:01:35 +01:00
734be9ee21 add missing spacing 2025-11-17 16:01:25 +01:00
32fcff1dfc hasclosed 2025-11-17 07:08:19 +01:00
a02e8dc67b minor fixes 2025-11-17 07:05:30 +01:00
9de2242aaf async fix 2025-11-17 06:26:29 +01:00
7f40da8e20 async PluginFunction 2025-11-17 06:21:04 +01:00
2858346c00 label 2025-11-16 13:34:34 +01:00
72a8830891 styles 2025-11-16 13:29:22 +01:00
5a8322f5b7 fix 2025-11-16 09:32:24 +01:00
e969533dc0 fixes 2025-11-16 08:46:56 +01:00
40a28aecf3 another fix 2025-11-16 08:44:04 +01:00
f0057ccad2 fixes 2025-11-16 08:42:15 +01:00
14d8e83a64 Task<T> as result type 2025-11-12 10:52:17 +01:00
efebfc3c9d avalonia: DefaultPadding 2025-11-12 10:16:38 +01:00
71d27c1061 complete avalonia flyouts 2025-11-11 16:43:21 +01:00
Pilzinsel64
593cdfb92c update 2025-11-11 14:50:32 +01:00
Pilzinsel64
40b753062a fixes & testapp 2025-11-11 09:37:37 +01:00
Pilzinsel64
1fb16d56c2 xmlns definition 2025-11-11 09:03:43 +01:00
Pilzinsel64
9988b1b19b minor fixes for dialog & imagebutton 2025-11-11 09:00:14 +01:00
18a549be57 version bump 2025-11-10 18:15:39 +01:00
5fd8bcba28 add deploy for linux 2025-11-10 18:14:43 +01:00
c19c858de1 add Avalonia Dialogs 2025-11-10 15:57:51 +01:00
Pilzinsel64
1ab775aa3e ImageButton & ImageSplitButton 2025-11-07 10:48:36 +01:00
Pilzinsel64
0e11a0f9c4 Pilz.UI.AvaloniaUI.Features 2025-11-06 12:49:05 +01:00
Pilzinsel64
42ff61bf91 fix? 2025-11-06 11:59:55 +01:00
Pilzinsel64
d4e76dc1a8 version bump 2025-11-06 11:51:46 +01:00
Pilzinsel64
fb42b0675b rename Pilz.Plugins.Advanced to Pilz.Features 2025-11-06 11:51:05 +01:00
Pilzinsel64
8bc09d9a59 remove Gtk projects 2025-11-06 11:43:38 +01:00
Pilzinsel64
5650cb8fd6 AvaloniaUI 2025-11-06 06:21:35 +01:00
Pilzinsel64
ba59f7df79 ApiStreamMessage 2025-10-31 11:36:28 +01:00
Pilzinsel64
d8b89379cc minor improvement 2025-10-31 09:41:41 +01:00
Pilzinsel64
53377485bb naming fix 2025-10-31 09:32:34 +01:00
Pilzinsel64
6ae5cd51b0 jobs api 2025-10-31 09:29:28 +01:00
Pilzinsel64
e2a337a7aa GalleryIconListViewVisualItem 2025-10-29 06:09:43 +01:00
Pilzinsel64
3f5153c497 INamedObject 2025-10-29 06:07:48 +01:00
Pilzinsel64
4922f0a516 version bump 2025-10-22 08:03:56 +02:00
Pilzinsel64
82b204aa1f fix 2025-10-22 07:53:53 +02:00
Pilzinsel64
9ea34dcc95 remove LoadOwnPlugins and listener for AppDomain.AssemblyLoad 2025-10-22 07:47:37 +02:00
Pilzinsel64
a25077e989 fix 2025-10-22 07:45:15 +02:00
Pilzinsel64
75b5f7ddd5 jobs 2025-10-22 07:39:32 +02:00
Pilzinsel64
ef1b6bad2e api: bad request on fail 2025-10-22 07:13:33 +02:00
Pilzinsel64
b27fe9362a loading indicator 2025-10-21 13:16:51 +02:00
Pilzinsel64
6fb68f282a assembly whitelist 2025-10-20 05:57:17 +02:00
Pilzinsel64
cfdb31fe80 target netstandard2.0 for Pilz.Configuration 2025-10-16 07:31:24 +02:00
Pilzinsel64
98e9076f1b update 2025-10-15 11:47:06 +02:00
Pilzinsel64
a675835ad4 nullable fix 2025-10-15 11:38:25 +02:00
Pilzinsel64
823990afdc replace OpenTK.WinForms with OpenTK.GLControl 2025-10-15 11:03:38 +02:00
Pilzinsel64
c4c62e958f disable aspose3d due compatibility issues 2025-10-15 10:51:07 +02:00
Pilzinsel64
4b5f2bfddf version bump 2025-10-15 10:28:29 +02:00
Pilzinsel64
320ef51bfd do not invoke on parent context on create 2025-10-10 10:06:00 +02:00
Pilzinsel64
bcad7597a2 add better initialization 2025-10-09 07:29:35 +02:00
Pilzinsel64
ccb9f8350e add better initialization 2025-10-09 07:26:42 +02:00
Pilzinsel64
5e035b43df version bump 2025-10-07 14:56:06 +02:00
Pilzinsel64
4e0f4999a0 enure handle created on load data complete 2025-10-07 14:52:53 +02:00
Pilzinsel64
eca4844792 update nuget packages 2025-10-07 14:41:46 +02:00
Pilzinsel64
0512cdd711 bump version 2025-09-02 13:24:06 +02:00
Pilzinsel64
508c464efe fix ids shit 2025-09-02 13:23:53 +02:00
Pilzinsel64
5262ee11da array, please 2025-08-21 11:02:28 +02:00
Pilzinsel64
6c09eb15ff add missing overload to interface 2025-08-21 11:01:49 +02:00
Pilzinsel64
388977fe04 fix name 2025-08-21 08:00:12 +02:00
Pilzinsel64
834f5e8de5 version bump 2025-08-21 07:58:39 +02:00
Pilzinsel64
7a080280f5 version bump 2025-08-21 07:58:06 +02:00
Pilzinsel64
9a0f645e01 symbol proxy 2025-08-21 07:56:29 +02:00
Pilzinsel64
dc25063ca1 check for abstract types 2025-08-21 07:08:21 +02:00
Pilzinsel64
f3658e466f rename ItemMessages 2025-08-08 10:06:49 +02:00
Pilzinsel64
3f356c0004 fix build 2025-08-08 09:13:03 +02:00
Pilzinsel64
d51647a4b5 use default value of parameter if available 2025-08-08 09:11:05 +02:00
Pilzinsel64
8078e41ed4 add TableLayoutPanel extension methods for add/remove rows 2025-07-31 14:41:02 +02:00
Pilzinsel64
2c8c307cdd update 2025-07-31 11:08:13 +02:00
Pilzinsel64
839f90d16a update 2025-07-31 10:56:48 +02:00
Pilzinsel64
41da460bfc update 2025-07-31 10:39:21 +02:00
Pilzinsel64
3f68f0dd21 update 2025-07-31 10:35:19 +02:00
Pilzinsel64
c6ef91fde7 file exists 2025-07-31 09:13:48 +02:00
Pilzinsel64
f4530aee4f Thread safety 2025-07-31 06:37:25 +02:00
Pilzinsel64
231546facd update 2025-07-31 06:14:42 +02:00
Pilzinsel64
876f42c59e update 2025-07-31 05:57:14 +02:00
Pilzinsel64
6d35a30ae2 add CopyTo method & cleanup 2025-07-29 09:17:05 +02:00
Pilzinsel64
8acd7c8925 Add object store & json data manager/container 2025-07-29 07:05:13 +02:00
Pilzinsel64
05e5427144 remove handlecreated again 2025-07-24 08:32:54 +02:00
Pilzinsel64
2435daab64 add invoke, if required 2025-07-24 08:22:27 +02:00
Pilzinsel64
b0e32dffaf add missing intialization of bgw 2025-07-24 08:10:59 +02:00
Pilzinsel64
c21cbe7299 add argument overload 2025-07-24 07:36:26 +02:00
Pilzinsel64
92f19d4646 add background worker to radflyoutbase 2025-07-24 07:30:40 +02:00
a8c1fd0df1 api: implement entity converters 2025-07-20 09:36:06 +02:00
Pilzinsel64
907a902c69 remove unused variable 2025-07-11 10:19:03 +02:00
Pilzinsel64
4bf700c4ff ISettings.Logger 2025-07-10 07:00:56 +02:00
Pilzinsel64
c7b2a07dd0 logging 2025-07-10 06:57:09 +02:00
Pilzinsel64
b9c6054185 and it wasn't possible for me to see that before? 2025-07-10 06:34:43 +02:00
Pilzinsel64
c012e33ef4 remove unneeded set 2025-07-10 06:32:55 +02:00
Pilzinsel64
94df8b3f79 version bump 2025-07-10 06:32:11 +02:00
Pilzinsel64
542467ccea rename IChildSettings to ISettingsNode & update Settings.Get<T>() 2025-07-10 06:31:43 +02:00
Pilzinsel64
bdeb098dc4 modernize minecraft utils 2025-07-10 06:18:03 +02:00
Pilzinsel64
b4d77667bc better form start position detection 2025-07-02 13:39:00 +02:00
Pilzinsel64
d615aaecc5 rename to EnsureGet 2025-07-02 07:45:06 +02:00
Pilzinsel64
02fd8246cd add generic Get and GetAll methods 2025-07-02 07:42:23 +02:00
Pilzinsel64
bc590923ad response collection on ForEach 2025-06-27 10:47:28 +02:00
Pilzinsel64
e2cfdb37e7 version bump 2025-06-27 08:19:37 +02:00
Pilzinsel64
9081c66b85 version bump 2025-06-27 08:17:31 +02:00
Pilzinsel64
10e97019a8 version bump 2025-06-27 08:15:11 +02:00
Pilzinsel64
3e05290fe9 don't insert splitter on first prio 2025-06-27 08:14:48 +02:00
Pilzinsel64
9eb9cad315 add GetAll for ids filtering to BaseClient 2025-06-24 08:24:00 +02:00
Pilzinsel64
76d385e235 add ids filter 2025-06-24 07:36:06 +02:00
c3a137aebd version bump 2025-06-22 13:51:52 +02:00
466fde4885 fix constructors 2025-06-22 13:51:37 +02:00
310178a5ca add Pilz.Plugins.Advanced.UI.Gtk 2025-06-21 21:02:40 +02:00
Pilzinsel64
f89a01e4ad version bump 2025-06-18 13:33:46 +02:00
Pilzinsel64
d08a235d23 add ToString(fieldCount) & ToShortString() 2025-06-18 10:10:07 +02:00
Pilzinsel64
2a4e26a817 add support for entry assembly version placeholder 2025-06-18 09:53:49 +02:00
Pilzinsel64
93bdbd0e73 version bump 2025-06-18 06:24:06 +02:00
Pilzinsel64
1d14e80624 add Version property to IPlugin 2025-06-18 06:23:45 +02:00
Pilzinsel64
6a066415eb GetAppVersion uses assembly version if empty 2025-06-18 06:23:29 +02:00
d06ff5888c fix plugins 2025-06-17 13:01:46 +02:00
c76243839f fix flyout event 2025-06-17 12:56:01 +02:00
f40f2a001a code cleanup 2025-06-17 12:43:45 +02:00
8be005ced0 fix build 2025-06-17 12:42:18 +02:00
7415ee2434 fix dialog namespaces 2025-06-17 12:41:28 +02:00
bbaf620297 add GetPixbuf 2025-06-16 19:28:34 +02:00
a49a3b2beb more work on gtk & code cleanup 2025-06-16 15:30:56 +02:00
6f7bb5d92c add Pilz.UI & Pilz.UI.Gtk 2025-06-16 12:19:28 +02:00
299867a910 change UI to UI.WinForms 2025-06-16 11:50:17 +02:00
Pilzinsel64
fa3a9da07e use SymbolPacks 2025-06-16 11:35:26 +02:00
Pilzinsel64
16cf7d8bda version bump 2025-06-13 10:43:28 +02:00
Pilzinsel64
be61994ae7 hopefully fix sorting 2025-06-13 10:42:56 +02:00
Pilzinsel64
1da2e2183c version bump 2025-06-13 10:30:21 +02:00
Pilzinsel64
0ff158b46e sorting 2025-06-13 10:30:09 +02:00
Pilzinsel64
ee1ea2f0b0 version bump 2025-06-13 10:26:48 +02:00
Pilzinsel64
d7e592180b fixes for capabilities 2025-06-13 10:26:33 +02:00
Pilzinsel64
b9e633a0ff wip maintenance endpoint 2025-06-13 09:55:20 +02:00
Pilzinsel64
ca8df29dd9 version bump 2025-06-13 09:21:28 +02:00
Pilzinsel64
6f44ab32f0 add server status & capabilities 2025-06-13 09:21:04 +02:00
Pilzinsel64
00bd2e62e8 introduce API-VERSION header 2025-06-13 08:21:29 +02:00
Pilzinsel64
b1716837b5 version bump 2025-06-12 11:15:18 +02:00
Pilzinsel64
8ae981b121 version bump 2025-06-12 11:13:38 +02:00
Pilzinsel64
042922a9cd add some missing symbols 2025-06-12 11:13:29 +02:00
Pilzinsel64
75cdcc1e4d bump version 2025-06-12 07:23:18 +02:00
Pilzinsel64
aabcf29326 prevent canceling control events 2025-06-12 07:22:57 +02:00
Pilzinsel64
bbd0017b33 version bump 2025-06-12 07:01:34 +02:00
Pilzinsel64
2f9dcb42e6 get type of object instead from type parameter 2025-06-12 07:01:16 +02:00
Pilzinsel64
68133f5fe6 bump version 2025-06-05 09:17:03 +02:00
Pilzinsel64
4cb015615a remove RequiresAuth property 2025-06-05 09:16:46 +02:00
Pilzinsel64
097847d286 version bump 2025-06-05 09:00:22 +02:00
Pilzinsel64
494484ee0b permit by default 2025-06-05 08:59:55 +02:00
Pilzinsel64
d3e18d6567 version bump 2025-06-04 13:29:10 +02:00
Pilzinsel64
8752f33464 add missing symbol definitions 2025-06-04 13:28:55 +02:00
Pilzinsel64
815da2b24c now!! 2025-06-04 12:54:31 +02:00
Pilzinsel64
de592ee65b but finally now! 2025-06-04 12:43:48 +02:00
Pilzinsel64
47c78e94fe fix loading symbols 2025-06-04 12:35:56 +02:00
Pilzinsel64
c1e3853eca fix namespace 2025-06-04 12:27:37 +02:00
Pilzinsel64
a9690576de add symbol enums 2025-06-04 12:27:03 +02:00
Pilzinsel64
a5a8a0b71c version bump 2025-06-04 12:19:49 +02:00
Pilzinsel64
404a2a4b4f update nuget packages 2025-06-04 12:19:38 +02:00
Pilzinsel64
3ea128ccb0 version bump 2025-06-04 12:14:50 +02:00
Pilzinsel64
d5c0d5c19f use dynamic 2025-06-04 12:14:38 +02:00
Pilzinsel64
86bda7772b fuck you 2025-06-04 12:05:43 +02:00
Pilzinsel64
e9f68fe427 version bump 2025-06-04 12:03:36 +02:00
Pilzinsel64
335046418e prevent initialization if not used 2025-06-04 12:03:19 +02:00
Pilzinsel64
e8ba2b218c version bump 2025-06-04 09:33:35 +02:00
Pilzinsel64
be8f9ea544 insert prio splitters 2025-06-04 09:33:18 +02:00
Pilzinsel64
ed8c2edb15 version bump 2025-06-04 09:22:13 +02:00
Pilzinsel64
8aa562afee always check authentication 2025-06-04 09:21:58 +02:00
Pilzinsel64
a02332745b bump version 2025-06-03 05:46:32 +02:00
bcbadd5a20 version bump 2025-05-28 10:31:59 +02:00
9557e105b9 api: add events to control api requests via context 2025-05-28 10:31:16 +02:00
c10fca45e6 native amount/offset handling 2025-05-23 11:17:48 +02:00
6712751141 version bump 2025-05-21 07:40:35 +02:00
be33f30425 use RESTful style for GET & POST to child entity endpoints 2025-05-21 07:40:09 +02:00
108d7a2d5e version bump 2025-05-20 13:54:38 +02:00
033a1c48b5 allow passthrow query parameters 2025-05-20 13:54:10 +02:00
c7990947dd version bump 2025-05-20 13:10:33 +02:00
711f4a8d11 remove recent patch again 2025-05-20 13:10:02 +02:00
58bb22df90 ensure remove picture box also on the same image 2025-05-20 11:15:09 +02:00
247033dbeb fix merge conflict 2025-05-20 07:57:34 +02:00
08ec940831 version bump 2025-05-20 07:56:31 +02:00
88921d2a4e add patch for stretching issue on AutoSize of RadTextBoxControl 2025-05-20 07:56:05 +02:00
91751886f3 fix name of file 2025-05-16 06:48:56 +02:00
6f0bf4194b add Harmony patches for Telerik UI 2025-05-16 06:48:12 +02:00
570e49ad76 thread-safety while GetManager 2025-05-15 06:45:52 +02:00
15d723ea38 version bump 2025-05-14 15:03:02 +02:00
c46b968562 passthrow HttpListenerContext 2025-05-14 15:02:52 +02:00
07f4dd2dca version bump 2025-05-14 14:27:32 +02:00
e673483ef5 lazy-get parent on PUT 2025-05-14 14:27:18 +02:00
f16bbf51c6 version bump 2025-05-14 12:10:58 +02:00
19efc1c69e GetAll also for child client 2025-05-14 12:10:44 +02:00
0a86856876 version bump 2025-05-14 09:56:23 +02:00
b494f2fb8d add more virtual methods for base handler 2025-05-14 09:56:05 +02:00
9d826892eb merge 2025-05-14 09:55:43 +02:00
Pilzinsel64
02ef0da374 use ChildEntityUpdate also on PUT 2025-04-30 14:16:54 +02:00
Pilzinsel64
1b92549b34 update 2025-04-30 13:41:17 +02:00
Pilzinsel64
71d407bb88 version bump 2025-04-30 13:35:39 +02:00
Pilzinsel64
624f232b6b ChildUpdateEntity object on POST 2025-04-30 13:35:26 +02:00
Pilzinsel64
c6e5e19a3a version bump 2025-04-30 13:24:58 +02:00
Pilzinsel64
83da51bf89 enhance UpdateEntity singature 2025-04-30 13:24:43 +02:00
Pilzinsel64
71eed097a6 remove empty Data folder 2025-04-30 13:24:17 +02:00
Pilzinsel64
eac53eca60 version bump 2025-04-25 10:30:46 +02:00
Pilzinsel64
50796391f9 minor fixes 2025-04-25 10:30:38 +02:00
Pilzinsel64
c232b856b9 convert to T before converting to T? 2025-04-25 10:25:11 +02:00
Pilzinsel64
7deec49219 version bump 2025-04-25 09:47:52 +02:00
Pilzinsel64
ec22181750 add SettingsValueOption 2025-04-25 09:47:36 +02:00
Pilzinsel64
e6340b4894 version bump 2025-04-24 06:35:00 +02:00
Pilzinsel64
6c6752fe82 disable auto update 2025-04-24 06:34:45 +02:00
Pilzinsel64
9c97d84a6f don't add duplicated validation rules 2025-04-23 12:35:30 +02:00
Pilzinsel64
e10eaab5e3 it hasn't rebuilt again, version bump ... 2025-04-23 12:28:56 +02:00
Pilzinsel64
22aaec2fa6 more cstrs and overloadds 2025-04-23 12:25:12 +02:00
Pilzinsel64
48bfe1ec00 optimizations 2025-04-23 12:14:20 +02:00
Pilzinsel64
5d0c4cd21a version bump 2025-04-23 12:03:29 +02:00
Pilzinsel64
e2d6d98002 dialog validation support 2025-04-23 12:02:59 +02:00
Pilzinsel64
b65af65a26 add Pilz.UI.Telerik.Symbols 2025-04-16 14:06:41 +02:00
Pilzinsel64
3a266c0e51 no nocontent 2025-04-10 11:27:12 +02:00
Pilzinsel64
008b1e9893 die 2025-04-10 11:02:27 +02:00
Pilzinsel64
cc58e77760 fix 2025-04-10 10:12:21 +02:00
Pilzinsel64
a917f4359c version bump 2025-04-10 10:10:54 +02:00
Pilzinsel64
a72bd75907 save as new on save with parent id 2025-04-10 10:10:36 +02:00
Pilzinsel64
a464ada95d version bump 2025-04-09 19:35:32 +02:00
Pilzinsel64
93fc5e860c only use prefered size if not empty 2025-04-09 19:34:55 +02:00
Pilzinsel64
4b5b90bd68 version bump 2025-04-09 16:34:29 +02:00
Pilzinsel64
8a31685ccf just forget it, back to roots but better 2025-04-09 16:34:16 +02:00
Pilzinsel64
267618ccc5 version bump 2025-04-09 15:39:57 +02:00
Pilzinsel64
22f206d939 fix closing flyout a last time 2025-04-09 15:39:15 +02:00
Pilzinsel64
bb4e1a7994 version bump 2025-04-08 12:35:59 +02:00
Pilzinsel64
9ad9d4744c and now a more safe way via refleciton 2025-04-08 12:35:47 +02:00
Pilzinsel64
9c2fd4e046 version bump 2025-04-08 12:29:26 +02:00
Pilzinsel64
baca77f701 ignore possible exceptions on closing flyout (thank you telerik...) 2025-04-08 12:29:10 +02:00
Pilzinsel64
3844099acf version bump 2025-04-08 08:32:51 +02:00
Pilzinsel64
3292c09a5f ensure the flyout is closed before opening a new one 2025-04-08 08:32:28 +02:00
Pilzinsel64
b60f8541f2 some stauts codes 2025-04-02 09:50:13 +02:00
Pilzinsel64
7a5db49cfb version bump 2025-04-02 08:14:34 +02:00
Pilzinsel64
7e213539ca version bump 2025-04-02 07:54:20 +02:00
Pilzinsel64
8050a4c2f5 add missing find method 2025-04-02 07:54:00 +02:00
Pilzinsel64
96ee827239 fix pilz.net building 2025-04-02 07:27:15 +02:00
Pilzinsel64
7369c776dd version bump 2025-04-02 07:26:32 +02:00
Pilzinsel64
9a17cd4e9e add PropertyObject & PropertyValue, move to Pilz, make everything .net 8 only 2025-04-02 07:25:41 +02:00
Pilzinsel64
91e1987d75 version bump 2025-04-01 13:51:24 +02:00
Pilzinsel64
36499dc868 set type name handling 2025-04-01 13:51:09 +02:00
Pilzinsel64
76da9a1461 version bump 2025-04-01 09:50:39 +02:00
Pilzinsel64
ca20e0ce12 pass throw update message for CreateNewEntity 2025-04-01 09:50:26 +02:00
Pilzinsel64
6d6f780b91 version BUMP 2025-04-01 09:50:11 +02:00
Pilzinsel64
c7caf356e0 version bump because it is incredible bad 2025-04-01 08:25:10 +02:00
Pilzinsel64
d7cb947fff version bump 2025-04-01 07:45:10 +02:00
Pilzinsel64
c63b0a9fd2 add another missing ToClient 2025-04-01 07:44:51 +02:00
Pilzinsel64
bfd48578aa version bump 2025-04-01 06:59:45 +02:00
Pilzinsel64
41d8d34c79 add tooltip to item 2025-04-01 06:59:33 +02:00
Pilzinsel64
f487504fd3 version bump 2025-04-01 06:42:40 +02:00
Pilzinsel64
361f55198d add description property for plugin feature 2025-04-01 06:42:28 +02:00
Pilzinsel64
17212da67a version bump 2025-04-01 06:36:44 +02:00
Pilzinsel64
413669a68f fix typo 2025-04-01 06:36:24 +02:00
Pilzinsel64
bae8539f82 version bump 2025-03-28 11:09:01 +01:00
Pilzinsel64
81c0d51417 only allow reference types on the server side 2025-03-28 11:08:48 +01:00
Pilzinsel64
b3e24d7fdc version bump 2025-03-28 10:41:02 +01:00
Pilzinsel64
8de643b7d1 add some default types to de-duplicate similar implmentations 2025-03-28 10:40:48 +01:00
Pilzinsel64
9a652a343c version bump 2025-03-18 15:09:54 +01:00
Pilzinsel64
ca06ed3da6 expose registerhandler method with attribute parameter 2025-03-18 15:09:40 +01:00
Pilzinsel64
5c636597d2 version bump 2025-03-18 15:02:03 +01:00
Pilzinsel64
4a732cb3ac add IApiHandlerInitializer 2025-03-18 15:01:48 +01:00
Pilzinsel64
9be00475c7 version bump 2025-03-18 10:59:04 +01:00
Pilzinsel64
307092cfc2 ignore IsEmpty property of ApiMessage 2025-03-18 10:58:47 +01:00
Pilzinsel64
1fd0b61408 version bump 2025-03-18 08:56:57 +01:00
Pilzinsel64
24cde0bd03 better support of raw data transfer 2025-03-18 08:56:08 +01:00
86154e93af fix paramter type mismatch 2025-03-04 06:33:42 +01:00
b60593dfca add missing instance flag 2025-03-04 06:20:27 +01:00
694066286b version bump 2025-03-03 11:18:15 +01:00
d7ba63a642 add IPluginFeatureConstructor as alternative provider option 2025-03-03 11:17:53 +01:00
7b38286642 use better hash method 2025-02-11 07:29:18 +01:00
07ab60666a make some projects compatible with netframework4.8 again 2025-02-11 07:18:14 +01:00
f08c94908a version bump 2025-02-06 15:01:14 +01:00
ab67023ea4 another improvement 2025-02-06 15:00:46 +01:00
Pilzinsel64
295644087f version bump 2025-02-04 15:03:15 +01:00
Pilzinsel64
4e849845c6 minor adjustments 2025-02-04 15:02:59 +01:00
Pilzinsel64
a80e972460 version bump 2025-02-04 14:36:06 +01:00
Pilzinsel64
22c962bec7 minimal improvements for autorestart and slot handling 2025-02-04 14:35:22 +01:00
c0a422ca71 version bump 2025-02-03 14:44:19 +01:00
9ff34c44b2 try improve sensitive error handling 2025-02-03 14:43:51 +01:00
Pilzinsel64
49b5ebddb1 don't error when stopping 2025-01-28 08:47:55 +01:00
Pilzinsel64
b92eb24438 version bump 2025-01-28 08:42:43 +01:00
Pilzinsel64
49f0f63338 it's RegEx, nothing else!!! 2025-01-28 08:42:22 +01:00
Pilzinsel64
43f7684074 more performant check 2025-01-28 08:27:09 +01:00
Pilzinsel64
f17fea31e8 version bump 2025-01-28 08:25:49 +01:00
Pilzinsel64
5d941506f6 improve TryGetHandler to find direct matches before checking via RegEx 2025-01-28 08:25:26 +01:00
Pilzinsel64
1b1f92dea5 version bump 2025-01-28 07:40:09 +01:00
Pilzinsel64
c7f343544d last fix 2025-01-28 07:39:58 +01:00
Pilzinsel64
58794e5872 version bump 2025-01-28 07:37:58 +01:00
Pilzinsel64
c02763ae9a release semaphore only if requied 2025-01-28 07:37:43 +01:00
Pilzinsel64
2414f2f7c5 version bump 2025-01-28 06:52:20 +01:00
Pilzinsel64
f8bce850d5 try solving a softlock 2025-01-28 06:52:00 +01:00
Pilzinsel64
b05b18b1a6 version bump 2025-01-24 06:11:08 +01:00
Pilzinsel64
232c94c61f use SemaphoreSlim to limit the amount of parallel http requests 2025-01-24 06:10:43 +01:00
Pilzinsel64
fcd23152e2 dedicated autorestart method 2025-01-22 15:23:59 +01:00
Pilzinsel64
9a0f3f5878 version bump 2025-01-22 15:20:56 +01:00
Pilzinsel64
d948ba4135 auto-restart on fatal http error 2025-01-22 15:20:39 +01:00
Pilzinsel64
2018969009 version bump 2025-01-20 10:55:34 +01:00
Pilzinsel64
8e22be7d9f check StatusCode is between 200 and 299 2025-01-20 10:55:18 +01:00
Pilzinsel64
bf5dbdef00 version bump 2025-01-20 09:10:32 +01:00
Pilzinsel64
4701de0bdc add more pre-defined ApiResult methods 2025-01-20 09:10:17 +01:00
Pilzinsel64
b9075eb2f3 version bump 2025-01-14 09:35:59 +01:00
Pilzinsel64
8092e37312 don't add panels in DesignMode 2025-01-14 09:35:46 +01:00
Pilzinsel64
45c85e4ced verison bump 2025-01-14 09:32:00 +01:00
Pilzinsel64
4de074b098 disable cancel dialog result (we handle it ourself already) 2025-01-14 09:27:27 +01:00
Pilzinsel64
e44e4e15a6 setshow title panel 2025-01-14 09:19:07 +01:00
Pilzinsel64
d95b12facb version bump 2025-01-14 09:11:48 +01:00
Pilzinsel64
dc5beb09de send to back 2025-01-14 09:11:23 +01:00
Pilzinsel64
5342c25db8 version bump 2025-01-14 08:52:41 +01:00
Pilzinsel64
29fddff6f6 some more publics 2025-01-14 08:52:15 +01:00
Pilzinsel64
2d10424d13 version bump 2025-01-14 08:38:59 +01:00
Pilzinsel64
91eeab7aeb add controls on load
- hopefully fixes initial focus being on confirm button
2025-01-14 08:38:40 +01:00
Pilzinsel64
cfce855c2c version bump 2025-01-14 07:51:18 +01:00
Pilzinsel64
cb2831ce4a refactor flyoutbase and radflyoutbase
- hopefully fix problems with child classes and tabindex problems
2025-01-14 07:50:47 +01:00
Pilzinsel64
0e2f393334 version bump 2024-12-18 10:42:34 +01:00
Pilzinsel64
69e0900f7d match whole string 2024-12-18 10:41:57 +01:00
Pilzinsel64
3fa4d18f77 version bump 2024-12-17 14:40:44 +01:00
Pilzinsel64
7c6b30aa7b make httpclient public 2024-12-17 14:40:24 +01:00
Pilzinsel64
e369497537 version bump 2024-12-12 13:35:17 +01:00
Pilzinsel64
93cea9fea3 return raw response 2024-12-12 13:34:48 +01:00
Pilzinsel64
c8915423fd version bump 2024-12-12 12:58:39 +01:00
Pilzinsel64
441b4a0494 move GetClient to IApiClient 2024-12-12 12:58:25 +01:00
Pilzinsel64
0b82e76734 version bump 2024-12-12 11:38:16 +01:00
Pilzinsel64
ddc0f33e90 passthrow raw content 2024-12-12 11:37:52 +01:00
Pilzinsel64
2e68e6802b version bump 2024-12-12 07:33:47 +01:00
Pilzinsel64
ab6411fe39 improvements 2024-12-12 07:31:25 +01:00
Pilzinsel64
2b0b094731 basic sub-client implementation 2024-12-12 07:30:10 +01:00
4bdeaadbcb version bump 2024-12-10 06:03:34 +01:00
a6e38dd59d ApiParameterCollection: allow null 2024-12-10 06:03:09 +01:00
3f582dc634 version bump 2024-12-09 07:47:27 +01:00
45b58aa5a2 use wrapped dictionary as api params collection 2024-12-09 07:46:58 +01:00
cdd7915142 improve logging 2024-12-09 06:29:05 +01:00
b5edc53623 version bump 2024-12-07 08:22:11 +01:00
917e9edd80 add support for parameter building on ApiClient 2024-12-07 08:21:50 +01:00
Pilzinsel64
d333710a8f version bump 2024-12-06 11:53:38 +01:00
Pilzinsel64
6c60d271ad support queries 2024-12-06 11:52:57 +01:00
Pilzinsel64
98e3217df3 version bump 2024-12-03 12:57:56 +01:00
Pilzinsel64
cfaeeb8aa0 trying to optimize tabindex on childs again 2024-12-03 12:57:41 +01:00
Pilzinsel64
0cca672bd7 another build fix 2024-12-03 08:48:59 +01:00
Pilzinsel64
804ba9f9a0 fix build 2024-12-03 08:48:32 +01:00
Pilzinsel64
669393559b version bump 2024-12-03 08:47:51 +01:00
Pilzinsel64
a2b89e4fef more lightwel control listener 2024-12-03 08:47:36 +01:00
Pilzinsel64
b9ba58324b version bump 2024-12-03 06:20:45 +01:00
Pilzinsel64
8ef03235fe another minor register handler fix for handlers with parameters 2024-12-03 06:20:09 +01:00
af162a887b version bump 2024-12-02 15:57:47 +01:00
2bd241c7a9 fix inverted condition 2024-12-02 15:57:30 +01:00
Pilzinsel64
3fea994e93 remove invalid attribute parameter 2024-11-29 11:33:17 +01:00
Pilzinsel64
342e9ed0d8 version bump 2024-11-29 07:59:39 +01:00
Pilzinsel64
df264ac20d overhaul ThemeHelper 2024-11-29 07:58:35 +01:00
Pilzinsel64
55bf37619b make methods virtual 2024-11-29 07:58:15 +01:00
Pilzinsel64
a3a256395f version bump 2024-11-28 09:04:06 +01:00
Pilzinsel64
9dcaa7e507 add support for REST-ful API building
- allow parameters within url
- allow different methods other then just POST
-> still needs to be tested!
2024-11-28 09:03:48 +01:00
Pilzinsel64
74ebbbca7b version bump 2024-11-28 07:24:31 +01:00
Pilzinsel64
44ab301c24 refactor settings load/save
- load using LINUQ
- load on child settings on demond
- prevent error when plugin has been removed
- prevent settings loose when plugin has been removed
2024-11-28 07:23:29 +01:00
Pilzinsel64
3070fab91b resolve merge confligts? 2024-11-20 12:41:39 +01:00
Pilzinsel64
55d221cb81 remove more references 2024-11-20 12:38:21 +01:00
Pilzinsel64
bff48227d1 version bump 2024-11-20 12:37:48 +01:00
Pilzinsel64
ede26291ec version bump 2024-11-20 12:36:42 +01:00
Pilzinsel64
b8c0086e82 version bump & remove unused references from Pilz.Drawing 2024-11-20 12:35:10 +01:00
Pilzinsel64
7d5935c5d1 fix recursive 2024-11-20 12:33:56 +01:00
Pilzinsel64
7ebad522bd version bump 2024-11-18 15:30:05 +01:00
Pilzinsel64
25c6aa4c30 only receive if listening 2024-11-18 15:29:51 +01:00
Pilzinsel64
93e8cf3219 version bump 2024-11-18 13:28:14 +01:00
Pilzinsel64
2866661539 version bump 2024-11-15 11:34:39 +01:00
Pilzinsel64
0cb7a15909 minor ajustments 2024-11-15 11:34:30 +01:00
Pilzinsel64
f70e07bd2c version bump 2024-11-15 11:03:59 +01:00
Pilzinsel64
6abaa8615a add control manager for plugins 2024-11-15 11:03:58 +01:00
Pilzinsel64
b7acc6f0a4 version bump 2024-11-15 11:03:57 +01:00
Pilzinsel64
7c39f2778f add like operator 2024-11-15 11:03:56 +01:00
6668a45893 version bump 2024-11-14 06:03:12 +01:00
81b8426b41 improve api server error handling 2024-11-14 06:03:01 +01:00
Pilzinsel64
1480485438 preven tabindex conflict for flyouts/dialogs 2024-11-13 07:50:26 +01:00
Pilzinsel64
96b6536a7a separete parameters collection 2024-11-11 12:53:58 +01:00
Pilzinsel64
bf2ec306cc version bump 2024-11-11 08:46:39 +01:00
Pilzinsel64
eca1a4c7ca simplify PluginManager a bit more 2024-11-11 08:46:24 +01:00
Pilzinsel64
9b7c38ea85 version bump 2024-11-11 08:18:26 +01:00
Pilzinsel64
b9c390f645 add optional namespace filter 2024-11-11 08:18:25 +01:00
8e9314365e version bump 2024-11-08 10:53:24 +01:00
dcb4e1c1cf add ILoadContentAsync 2024-11-08 10:52:24 +01:00
e884666225 version bump 2024-11-08 07:38:06 +01:00
9482e64fd9 fix setting handler 2024-11-08 07:37:41 +01:00
2e420ad902 add check context events 2024-11-08 07:36:46 +01:00
Pilzinsel64
a7a3cfa683 version bump 2024-10-28 09:21:42 +01:00
Pilzinsel64
55db979ebf version bump 2024-10-28 09:21:07 +01:00
Pilzinsel64
11c0711726 add handler to authentication check 2024-10-28 09:20:50 +01:00
Pilzinsel64
24482ccb85 add extension for adding enum values 2024-10-28 06:45:10 +01:00
Pilzinsel64
9a03945246 version bump 2024-10-25 10:24:40 +02:00
Pilzinsel64
65d2c8d6de Fix ApiResponse.IsOk beeing wrong 2024-10-25 10:24:27 +02:00
Pascal Schedel
2d52315d68 version bump 2024-10-25 07:35:26 +02:00
Pascal Schedel
25a8cd48be add statuscode to apiexception 2024-10-25 07:35:03 +02:00
e3ce952cbc version bump 2024-10-24 10:29:46 +02:00
cc8757b61e add toggle to for processing multiple requests 2024-10-24 10:29:24 +02:00
c26be92734 version bump 2024-10-24 09:12:06 +02:00
b2a1cc2da8 minimal optimizations 2024-10-24 09:11:45 +02:00
24266789e8 version bump 2024-10-24 08:25:00 +02:00
48ae689a34 improve parameter detection 2024-10-24 08:24:26 +02:00
d5f40cad2f version bump 2024-10-24 06:16:06 +02:00
8f7d8839bf add some debug logging 2024-10-24 06:15:45 +02:00
Pascal Schedel
88c2817f7e v2.0.7 2024-10-23 14:57:06 +02:00
Pascal Schedel
cd64a2ee53 make ApiMessgae.Empty static 2024-10-23 14:56:49 +02:00
Pascal Schedel
0d742be81d version bump 2024-10-23 12:51:52 +02:00
Pascal Schedel
59e9499d92 minimal improvements for ApiResponse 2024-10-23 12:51:36 +02:00
Pascal Schedel
3cec6983b8 version bump 2024-10-23 11:38:32 +02:00
Pascal Schedel
75ce1575fc version bump 2024-10-21 09:23:12 +02:00
Pascal Schedel
547359ecf3 add extension method to move an item within an collection 2024-10-21 09:22:02 +02:00
Pascal Schedel
34c4f1c727 convert Pilz.Collections to c# 2024-10-21 09:12:54 +02:00
Pascal Schedel
66b270fc17 version bump 2024-10-21 08:43:57 +02:00
Pascal Schedel
8960dac951 make all private flyout methods protected virtual 2024-10-21 08:43:56 +02:00
8a8407d86e rename MessageSerializer to ApiMessageSerializer 2024-10-17 10:10:19 +02:00
Pascal Schedel
9c1723cb0e version bump 2024-10-16 15:04:42 +02:00
Pascal Schedel
95cb8772ea version bump 2024-10-16 14:41:16 +02:00
5f69c780a9 version bump 2024-10-15 11:45:02 +02:00
7f785cb0c3 fix RadButtonItem -=> RadButtonElement 2024-10-15 11:44:42 +02:00
3d75bb23c5 version bump 2024-10-15 11:36:45 +02:00
d61e47f900 allow creating RadButtonItem instead of RadMenuItem 2024-10-15 11:36:14 +02:00
Pilzinsel64
64dc7c776a api: allow no parameter on server 2024-09-30 14:38:18 +02:00
03af05a8e9 version bump 2024-09-06 20:06:21 +02:00
e56f573d9c version bump 2024-09-06 19:56:31 +02:00
627fe525fa passthrow autosize to parent form 2024-09-06 19:55:59 +02:00
Pilzinsel64
2c85125338 make GetProcessExecuteable obsolete
-> use Environment.GetProcessPath instead
2024-09-02 15:43:56 +02:00
Pilzinsel64
5a6f8e207e version bump 2024-09-02 15:16:57 +02:00
Pilzinsel64
95cfafcad2 version bump 2024-09-02 15:06:45 +02:00
Pilzinsel64
90aea58d71 better svg coloring 2024-09-02 15:06:44 +02:00
7a94fcf360 migrate Pilz.Win32 & optimize Pilz & Pilz.IO 2024-09-01 08:54:57 +02:00
Pilzinsel64
f370642354 remove using 2024-08-30 12:09:20 +02:00
Pilzinsel64
fb2f80faba version bump 2024-08-30 12:02:07 +02:00
Pilzinsel64
fd77deb494 add AssemblyAppVersionAttribute 2024-08-30 12:01:52 +02:00
Pilzinsel64
11889dac61 version bump 2024-08-30 11:44:36 +02:00
Pilzinsel64
f230fb823b convert Pilz to c# & add AppVersion to there 2024-08-30 11:43:32 +02:00
Pilzinsel64
54fadfbe8d add method IsDarkTheme 2024-08-28 11:30:03 +02:00
Pilzinsel64
2dfeab36d0 version bump 2024-08-28 11:13:35 +02:00
Pilzinsel64
dac2fa74c1 add ThemeHelper 2024-08-28 11:13:06 +02:00
95fa96228d version bump 2024-08-22 14:38:53 +02:00
ab268e6584 add more helper methods 2024-08-22 14:38:32 +02:00
Pilzinsel64
519c292a1f add missing reference 2024-08-22 05:53:47 +02:00
Pilzinsel64
97c0c9d754 remove some old nuget packages 2024-08-22 05:52:27 +02:00
df59de177a Pilz.Net: remove useless references 2024-08-20 11:45:24 +02:00
aed2cc4d88 minor fixes for api 2024-08-17 10:12:44 +02:00
Pilzinsel64
f509c53836 minor fixes 2024-08-16 10:01:57 +02:00
Pilzinsel64
a58bd055b5 remove IMessageSerializer from basic request methods 2024-08-16 09:54:00 +02:00
Pilzinsel64
2bbab92246 version bump 2024-08-16 09:53:02 +02:00
Pilzinsel64
8f3f572c28 more work on api 2024-08-16 09:52:48 +02:00
Pilzinsel64
3502efc7f6 version bump 2024-08-16 09:19:25 +02:00
Pilzinsel64
df4adb8435 some more work on api 2024-08-16 09:19:03 +02:00
Pilzinsel64
6f5e012cb6 fix build of OcsApi 2024-08-16 07:25:22 +02:00
Pilzinsel64
4b47abfbbe version bump 2024-08-16 07:23:35 +02:00
Pilzinsel64
e24e6e5bca add logging & plish up 2024-08-16 07:22:29 +02:00
Pilzinsel64
2efb4f141c more work on api & rename to Pilz.Net 2024-08-16 06:59:39 +02:00
f57aef5f4f more work on api 2024-08-15 15:51:23 +02:00
c24b460a0d more work on api 2024-08-15 13:03:24 +02:00
4df972c7a4 some work work on api 2024-08-15 09:19:21 +02:00
Pilzinsel64
02a6c3bf6a begin developing a basic message based web api 2024-08-14 14:59:05 +02:00
Pilzinsel64
1932443a20 convert to C# 2024-08-14 13:49:46 +02:00
Pilzinsel64
8c76d5a486 version bump 2024-08-09 07:51:39 +02:00
Pilzinsel64
c49d63be98 add static GenerateNew methods for UniquieID 2024-08-09 07:50:53 +02:00
Pilzinsel64
195e2682f9 version bump 2024-07-29 09:59:42 +02:00
Pilzinsel64
2ba7088290 add missing quotation mark 2024-07-29 09:59:37 +02:00
Pilzinsel64
eba14dc2b7 fixes 2024-07-29 09:56:06 +02:00
Pilzinsel64
1142c6d48d version bump 2024-07-29 09:55:02 +02:00
Pilzinsel64
c334ef99c6 more extensions 2024-07-29 09:54:37 +02:00
Pilzinsel64
9826af9b45 version bump 2024-07-29 09:41:03 +02:00
Pilzinsel64
9e7e890d5b allow nullables 2024-07-29 09:40:52 +02:00
Pilzinsel64
29615ed47d version bump 2024-07-29 07:36:00 +02:00
Pilzinsel64
58e5d09099 fixes 2024-07-29 07:35:51 +02:00
Pilzinsel64
d99652b059 version bump 2024-07-29 07:21:04 +02:00
Pilzinsel64
a57d58c02c extensions for DialogResult 2024-07-29 07:20:35 +02:00
Pilzinsel64
8bf4bb1f32 version bump 2024-07-22 14:56:26 +02:00
Pilzinsel64
69c44d53c0 increase TabIndex of cancel and ok buttons 2024-07-22 14:55:49 +02:00
Pilzinsel64
170d88b247 version bump 2024-07-16 10:17:49 +02:00
Pilzinsel64
90a7bfe38d fix Ordered extension method name 2024-07-16 10:17:39 +02:00
Pilzinsel64
b053274226 versoin bump 2024-07-16 10:15:10 +02:00
Pilzinsel64
3f4eb82273 more extension methods using priority 2024-07-16 10:15:04 +02:00
Pilzinsel64
4bb72c63b2 correct constructor parameter names for plugin features 2024-07-16 10:14:45 +02:00
Schedel Pascal
8043d1fcf3 version bump 2024-07-15 14:23:48 +02:00
Schedel Pascal
6a16010d17 ignore changes while executing event 2024-07-15 14:23:24 +02:00
636e80f54b version bump 2024-07-11 12:03:27 +02:00
94e2360701 fix overload on RadFlyoutBase.Show<T>(Control, object) 2024-07-11 12:02:55 +02:00
Schedel Pascal
f3ac65f897 version bump 2024-07-08 06:56:57 +02:00
Schedel Pascal
c7ca6f5702 more large symbol sizes 2024-07-08 06:56:33 +02:00
Schedel Pascal
0bfe470349 version bump 2024-07-08 06:40:47 +02:00
Schedel Pascal
fe24bb48c7 add missing method 2024-07-08 06:40:26 +02:00
Schedel Pascal
022c5637a7 version bump 2024-07-08 06:27:16 +02:00
Schedel Pascal
1b448c3838 rework SymbolFactory
- rename & move to Pilz.UI..Telerik.Symbols.RadSymbolFactory
- make default implementaiton available at Pilz.UI.Symbols.SymbolFactory
- add interfaces
2024-07-08 06:26:05 +02:00
Schedel Pascal
f1204f686a it doesn't need to be an enum 2024-07-08 06:08:35 +02:00
2076ea663c version bump 2024-07-02 12:06:49 +02:00
05fbbc9414 fix inverted logic 2024-07-02 12:06:17 +02:00
784ea17c7d version bump 2024-07-02 11:32:37 +02:00
251b55dba5 add a uniquie event for plugin function execution 2024-07-02 11:32:16 +02:00
Schedel Pascal
d13fe67b37 version bump 2024-07-01 13:24:56 +02:00
Schedel Pascal
8d2406037b rename extension methods 2024-07-01 13:24:42 +02:00
Schedel Pascal
eb36214ffa version bump 2024-07-01 13:17:41 +02:00
Schedel Pascal
374eadd526 check if feature enabled 2024-07-01 13:17:12 +02:00
Schedel Pascal
aec3da98d1 enforce dialogPanel not be empty 2024-07-01 13:03:28 +02:00
Schedel Pascal
db8331afcd add script for nuget package publication 2024-06-24 14:51:22 +02:00
Schedel Pascal
3ba4701df8 version bump 2024-06-24 14:04:49 +02:00
Schedel Pascal
7412bdc404 update telerik ui & use universal package 2024-06-24 09:14:41 +02:00
Schedel Pascal
f9c4dc9bbe fix wrong version of Pilz.UI & deps 2024-06-13 08:43:40 +02:00
Schedel Pascal
59de2e54c5 use primary constructor 2024-06-13 08:10:17 +02:00
Schedel Pascal
6072ebdcf8 add missing reference 2024-06-13 08:08:54 +02:00
Schedel Pascal
7b85b5f85d version bump 2024-06-13 08:07:54 +02:00
Schedel Pascal
ea63866481 small improvements to RadFlyoutBase & RadDialogBase 2024-06-13 08:07:15 +02:00
Schedel Pascal
cd3b6b4ec3 use variable instead of eventargs 2024-06-13 07:18:43 +02:00
f9e8bd1dd1 show ui also for PluginModule 2024-06-12 22:02:50 +02:00
bb52c57c3c remove project backup 2024-06-12 22:02:20 +02:00
dc9f407450 ignore CS1591 2024-06-12 21:54:43 +02:00
26a40aac70 make ILoadContent as unicat 2024-06-11 06:03:03 +02:00
9593bb0223 fixes & version bump 2024-06-10 13:30:11 +02:00
e212f4021a fixes & version bump 2024-06-10 13:15:24 +02:00
df8266fc40 some improvements 2024-06-10 13:04:53 +02:00
3cd0f8dce8 fix recent commit 2024-06-10 12:30:21 +02:00
5c6f0c8bfc Pilz.UI: convert to C# 2024-06-10 12:29:56 +02:00
b9be604f0d version bump 2024-06-10 12:06:22 +02:00
94aeca2ca1 set title panel visibility 2024-06-10 12:05:39 +02:00
a8c14d65c0 fix icon property 2024-06-10 10:05:31 +02:00
6a9b686a09 version bump 2024-06-10 10:01:14 +02:00
efed817610 version bump 2024-06-10 10:00:43 +02:00
af6f4c07fa RadFlyoutBase: add title 2024-06-10 09:59:34 +02:00
9e8ca9140f prefix Telerik-based type names with "Rad" 2024-06-10 09:48:53 +02:00
99a327f4ed version bump 2024-06-05 19:36:04 +02:00
af23a06c50 backward compatibility 2024-06-05 19:35:30 +02:00
b613db1386 parameter for PluginModule 2024-06-05 19:31:00 +02:00
b6e5b8b6e4 update package project url & move to Directory.Build.props 2024-06-05 19:20:25 +02:00
1b49c54822 code optimization 2024-06-05 19:15:32 +02:00
d4be7d0566 parameter 2024-05-16 11:52:34 +02:00
bf463b6e7b r.ws igdfsaug 2024-05-16 11:37:41 +02:00
138ae6fb5f asdfasdfasdf 2024-05-16 11:30:52 +02:00
98cb5023ec arg 2024-05-16 11:29:51 +02:00
8ec931278b version bump 2024-05-16 11:16:15 +02:00
217616db7c exception 2024-05-16 11:15:52 +02:00
c3819457e5 separate bindinglfags 2024-05-07 07:01:50 +02:00
0dbddbf1d2 version bump 2024-05-07 06:56:34 +02:00
4c0aecdf73 allow including nonpublic constructors 2024-05-07 06:56:08 +02:00
488c79d825 version bump 2024-05-06 07:11:07 +02:00
c297286782 SettingsManager: ignore missing types & add error event 2024-05-06 07:10:32 +02:00
125e878103 version bump 2024-05-04 09:43:47 +02:00
dd1116bf63 make protected plugin load virtual 2024-05-04 09:43:17 +02:00
64cabd912b version bump 2024-05-03 06:53:29 +02:00
44557b66c6 add IPluginLateInitialization interface 2024-05-03 06:52:52 +02:00
2004ba4b30 version bump 2024-05-02 14:19:28 +02:00
64238dc010 version bump 2024-05-02 14:12:26 +02:00
9ffed42e1a more load plugins methods 2024-05-02 14:11:57 +02:00
c09eb42245 use Directory.props for general configs 2024-05-02 12:26:59 +02:00
575df473be generate serialization assemblies 2024-05-02 08:33:46 +02:00
fe43811aca version bump 2024-05-02 08:23:30 +02:00
bda33e1c8a comments & fixes 2024-05-02 08:23:01 +02:00
d56d1d1851 version bump 2024-05-01 09:19:21 +02:00
9560e4991c register all from my assembly 2024-05-01 09:19:06 +02:00
72f1148a64 version bump 2024-05-01 09:16:09 +02:00
7936052279 add RegisterAll(Assembly) method 2024-05-01 09:09:06 +02:00
554103781a version bump 2024-04-30 06:38:22 +02:00
270b8cac3e don't use yield return 2024-04-30 06:37:45 +02:00
571cfc1d0c version bump 2024-04-29 06:37:44 +02:00
db28476067 version bump 2024-04-29 06:20:15 +02:00
3031f7196d rename to FlyoutBase and DialogBase 2024-04-29 06:19:50 +02:00
fce33f1e35 whatever? 2024-04-29 06:19:25 +02:00
0c1e9ebec8 separate plugin ui & make Pilz.Plugins.Advanced package platform independent 2024-04-26 08:56:02 +02:00
841f3b41ae instance yuhay + bump version 2024-04-18 07:43:08 +02:00
3fba8c00b7 build version 2024-04-18 07:18:57 +02:00
9b43b02543 Merge branch 'master' of https://gitlab.com/Pilzinsel64/pilz-framework 2024-04-18 07:13:47 +02:00
41f9e67546 version bump 2024-04-18 07:13:31 +02:00
57bde835a1 arg 2024-04-18 07:13:00 +02:00
schedpas
eb764da56f improve plugin load 2024-04-18 06:28:40 +02:00
schedpas
efb0636312 more methods to load plugins 2024-04-17 15:05:32 +02:00
schedpas
e91e016f32 update nuget packages 2024-04-17 09:38:23 +02:00
fb605ca2d9 update package infos and license 2024-04-15 09:12:24 +02:00
6a19401083 version bump 2024-04-15 09:02:10 +02:00
7db3b4d48f minor optimizations 2024-04-15 09:01:22 +02:00
3f5f9ddb87 fix: add custom event handler if not default 2024-04-15 09:00:39 +02:00
8f4294783b ignore telerik packages again 2024-01-23 10:56:42 +01:00
c659b7ce09 bump version 2024-01-23 10:51:14 +01:00
5b435f1cad method for inserting a plugin features collection to an telerik items collection 2024-01-23 10:50:48 +01:00
cc84215d73 remove legacy plugin system 2024-01-23 09:16:50 +01:00
1be6200c58 fix build & update Telerik 2024-01-22 09:45:32 +01:00
cf6353112a bump version 2024-01-22 09:41:37 +01:00
013acc7a98 fix dialog button anchor on high dpi screens 2024-01-22 09:40:54 +01:00
0988657c91 bump version 2024-01-19 16:58:56 +01:00
223687cacb skip check 2024-01-19 16:58:34 +01:00
a0d72dd36f nope, not net6.0 2024-01-10 11:50:25 +01:00
9afce46cf0 Reset settings when creating instance 2024-01-10 11:49:36 +01:00
0c0c5e82bc convert to C# & update config system 2024-01-10 09:07:40 +01:00
26d56f3e88 change GET to POST for login flow v2 2024-01-09 16:09:21 +01:00
688c70f3f7 more protected for SettingsManager 2024-01-04 12:51:18 +01:00
2b17cef71a make mySettings protected 2024-01-04 12:37:37 +01:00
127332d6c8 add SettingsManager.RegisterProvider() 2024-01-04 12:30:10 +01:00
6c98288690 asdf 2024-01-04 12:16:43 +01:00
6b81c67b76 minor interface adjustments 2024-01-04 12:16:12 +01:00
488cdbcaef minor interface adjustments 2024-01-04 12:15:31 +01:00
f8d13dcc92 add missing return type for ISettingsProvider.CreateInstance 2024-01-04 11:49:32 +01:00
da5de9ecf7 rework Settings in Pilz.Configuration 2024-01-04 11:45:54 +01:00
ff2a221bfa v2.1 2024-01-03 09:16:28 +01:00
942fd82ca0 TablesClient: add views api calls 2024-01-03 09:16:03 +01:00
6e6eb6b8f6 add feature identifier 2023-12-14 07:55:59 +01:00
e1618da170 update nuget packages 2023-12-12 08:28:51 +01:00
b51d020704 v2.3 2023-12-08 09:10:56 +01:00
2322c04ca3 event for ui creation 2023-12-08 09:10:37 +01:00
7b04f6592c plugin feature events 2023-12-08 09:04:39 +01:00
d2c8986d51 wrapper for features & reduce dup code 2023-12-06 07:40:32 +01:00
0ecbde3fd7 PluginFeature 2023-12-05 13:52:35 +01:00
066d5a1a81 update nugets & cleanup 2023-11-21 08:56:03 +01:00
e358b0e419 add Pilz.Gaming.Minecraft (generate offline player uuid) 2023-11-20 11:10:56 +01:00
9ed52d30d6 version bump 2023-11-20 11:09:43 +01:00
dc3b180e5b version bump 2023-11-20 11:09:36 +01:00
cde27fdcc2 version bump 2023-11-15 08:08:54 +01:00
d560325a72 more GetAsItem() overloads 2023-11-15 08:07:39 +01:00
ff9af1e46c version bump 2023-11-14 14:39:56 +01:00
1652339295 PluginManager: make static methods to instance methods 2023-11-14 14:39:14 +01:00
16b8a227fc bump version 2023-11-14 14:22:04 +01:00
9b7eb40cfc add a simple plugin system 2023-11-14 14:20:26 +01:00
1c4d7554e2 version bump 2023-11-14 08:30:48 +01:00
0f610d5a81 add DialogBaseForm.Show() 2023-11-14 08:30:21 +01:00
62b28315b3 bump version 2023-11-13 14:56:49 +01:00
313020e468 ModelPreview: fix WASD (use Pilz.Win32.Keyboard) 2023-11-13 14:55:50 +01:00
e27a0e9511 bump version 2023-11-13 14:49:55 +01:00
f79939413b Win32: add Keyboard 2023-11-13 14:49:44 +01:00
75c916b0b6 version bump 2023-10-27 08:51:48 +02:00
984cc46224 prevent resizing on moving painting object 2023-10-27 08:51:05 +02:00
3f875f1dfc version bump 2023-10-23 14:57:04 +02:00
bef03f1271 use tablelayoutpanel & add CancelButtonVisible 2023-10-23 14:56:02 +02:00
4be8a8036c version bump 2023-10-23 12:54:20 +02:00
2ff26a8e2b Revert "fix checks for key down & up"
This reverts commit 5931b1476b.
2023-10-23 12:39:32 +02:00
c3765f9729 version bump 2023-10-23 12:31:30 +02:00
5931b1476b fix checks for key down & up 2023-10-23 12:30:05 +02:00
972f4ef41d remove legacy nuget files 2023-10-23 12:29:52 +02:00
4412990dac do not logout on server by default 2023-10-22 15:40:00 +02:00
b27ff00c16 version bump 2023-10-19 11:47:36 +02:00
019a91b5fe version bump 2023-10-19 11:47:10 +02:00
45ce141d9e add ability to show DialogBaseForm with custom created content 2023-10-19 11:47:03 +02:00
4a4398ed84 version bump 2023-10-13 09:01:21 +02:00
5b3c9a2d2a invoke sync again 2023-10-13 09:00:20 +02:00
12ecacd649 flag for register accept & cancel 2023-10-13 08:51:22 +02:00
912424efb0 use BeginInvoke for FlyoutClose 2023-10-10 10:11:52 +02:00
32c94d62a4 allow null row update values 2023-10-05 15:25:41 +02:00
0bd526d30a update Pilz.cryptography to net6.0 2023-10-05 11:22:09 +02:00
105a70d6c2 update version 2023-10-03 15:22:25 +02:00
e60b3a0fcb fix missing HasJob takeover 2023-10-03 15:21:16 +02:00
ea9e157abd update version 2023-10-03 11:53:24 +02:00
1e3d6f3752 update readme 2023-10-03 11:52:27 +02:00
ba069d56fd finish tables api 2023-10-03 11:44:53 +02:00
7ad077d0cf delete row & delete column & fix tables code in api base 2023-10-02 17:34:56 +02:00
549d284c54 begin implementing Tables API 2023-10-02 17:28:41 +02:00
459660c35a rename OCS to Ocs 2023-10-02 15:40:26 +02:00
fc50ebb3d5 re-organize Nextcloud project structure 2023-10-02 15:38:58 +02:00
b2ef1e5cce fixes for Nextcloud 2023-10-02 15:25:16 +02:00
c7f5de4974 fix incorect http method 2023-10-01 16:51:30 +02:00
16ca4ecbb6 huge work for nextcloud api 2023-10-01 16:51:10 +02:00
c87c117c94 fix parameter join 2023-09-27 14:43:31 +02:00
2c28feacb5 introduce a very simple Nextcloud API 2023-09-27 14:12:55 +02:00
7ea59cddb1 add overload for defining BufferUsageHint 2023-09-27 09:05:24 +02:00
cd39da1df4 Merge branch 'net6' into 'master'
Migrate to .NET 6

See merge request Pilzinsel64/pilz-framework!3
2023-09-18 09:13:45 +00:00
094528b1b8 allow deserialization for IUniquieID 2023-09-18 08:48:33 +02:00
fb752da740 jsonconverter for IUniquieID 2023-09-18 08:39:41 +02:00
a2f986e666 fix Telerik reference for Pilz.UI.Telerik.SymbolFactory 2023-09-14 20:00:14 +02:00
e4a2fefabc fix empty size 2023-09-01 19:35:10 +02:00
d0ac4e3b84 add Pilz.UI.Telerik & Pilz.UI.Telerik.SymbolFactory 2023-08-29 13:25:11 +02:00
743bd7f19c Pilz.IO: change target framework to net6.0-windows 2023-08-26 20:36:28 +02:00
cec14841f7 Merge branch 'master' into net6 2023-08-26 20:35:21 +02:00
77cbcd0dcb add GetExecutablePath() 2023-08-26 20:34:42 +02:00
926951e268 PaintingControl: Zoom with Alt instead of Control 2023-08-09 09:26:33 +02:00
79168466bc Merge branch 'master' into net6 2023-06-12 10:06:37 +02:00
fa96e2cf3e Merge branch 'master' into net6 2023-01-02 15:07:04 +01:00
9b7e4f1c6d Merge branch 'master' into net6 2023-01-02 14:46:02 +01:00
f2611e3f05 Merge branch 'master' into net6 2023-01-02 14:43:03 +01:00
e269c16521 Merge branch 'master' into net6 2023-01-02 14:36:27 +01:00
efb522d842 fix highlighter 2022-06-27 21:33:24 +02:00
68f26c6c9f Merge branch 'master' into net6 2022-06-27 20:33:30 +02:00
39ea821fee upgrade to .net6 part 2 2022-06-07 12:54:35 +02:00
0d4322c2b3 ref opentk3 2022-06-07 12:50:39 +02:00
446bd0111c upgrade to .net6 part 1 2022-06-07 12:47:34 +02:00
518 changed files with 20211 additions and 7223 deletions

10
Directory.Build.props Normal file
View File

@@ -0,0 +1,10 @@
<Project>
<PropertyGroup>
<PackageProjectUrl>https://git.pilzinsel64.de/pilz-framework</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<GenerateSerializationAssemblies>False</GenerateSerializationAssemblies>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<NoWarn>1591</NoWarn>
</PropertyGroup>
</Project>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
</startup>
</configuration>

View File

@@ -1,13 +0,0 @@
'------------------------------------------------------------------------------
' <auto-generated>
' Dieser Code wurde von einem Tool generiert.
' Laufzeitversion:4.0.30319.42000
'
' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
' der Code erneut generiert wird.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MySubMain>true</MySubMain>
<MainForm>Form1</MainForm>
<SingleInstance>false</SingleInstance>
<ShutdownMode>0</ShutdownMode>
<EnableVisualStyles>true</EnableVisualStyles>
<AuthenticationMode>0</AuthenticationMode>
<ApplicationType>0</ApplicationType>
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
</MyApplicationData>

View File

@@ -1,63 +0,0 @@
'------------------------------------------------------------------------------
' <auto-generated>
' Dieser Code wurde von einem Tool generiert.
' Laufzeitversion:4.0.30319.42000
'
' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
' der Code erneut generiert wird.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Imports System
Namespace My.Resources
'Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
'-Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
'Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
'mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
'''<summary>
''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
'''</summary>
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0"), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
Friend Module Resources
Private resourceMan As Global.System.Resources.ResourceManager
Private resourceCulture As Global.System.Globalization.CultureInfo
'''<summary>
''' Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
Get
If Object.ReferenceEquals(resourceMan, Nothing) Then
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("Pilz.Collections.Resources", GetType(Resources).Assembly)
resourceMan = temp
End If
Return resourceMan
End Get
End Property
'''<summary>
''' Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
''' Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend Property Culture() As Global.System.Globalization.CultureInfo
Get
Return resourceCulture
End Get
Set
resourceCulture = value
End Set
End Property
End Module
End Namespace

View File

@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<StartupObject />
<TargetFrameworks>net8.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<Version>2.1.1</Version>
</PropertyGroup>
</Project>

View File

@@ -1,86 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<StartupObject />
<MyType>Windows</MyType>
<TargetFramework>netstandard2.0</TargetFramework>
<DocumentationFile>Pilz.Collections.xml</DocumentationFile>
<DefineTrace>true</DefineTrace>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DefineDebug>true</DefineDebug>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022,40008</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DefineDebug>false</DefineDebug>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<RemoveIntegerChecks>true</RemoveIntegerChecks>
</PropertyGroup>
<PropertyGroup>
<OptionExplicit>On</OptionExplicit>
</PropertyGroup>
<PropertyGroup>
<OptionCompare>Binary</OptionCompare>
</PropertyGroup>
<PropertyGroup>
<OptionStrict>Off</OptionStrict>
</PropertyGroup>
<PropertyGroup>
<OptionInfer>On</OptionInfer>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DefineDebug>true</DefineDebug>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022,40008</NoWarn>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<UseVSHostingProcess>true</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<RemoveIntegerChecks>true</RemoveIntegerChecks>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
</ItemGroup>
<ItemGroup>
<Import Include="Microsoft.VisualBasic" />
<Import Include="System" />
<Import Include="System.Collections" />
<Import Include="System.Collections.Generic" />
<Import Include="System.Data" />
<Import Include="System.Drawing" />
<Import Include="System.Linq" />
<Import Include="System.Xml.Linq" />
<Import Include="System.Threading.Tasks" />
</ItemGroup>
<ItemGroup>
<Compile Update="My Project\Application.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Application.myapp</DependentUpon>
</Compile>
<Compile Update="My Project\Resources.Designer.vb">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="My Project\Resources.resx">
<Generator>VbMyResourcesResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
<CustomToolNamespace>My.Resources</CustomToolNamespace>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="My Project\Application.myapp">
<Generator>MyApplicationCodeGenerator</Generator>
<LastGenOutput>Application.Designer.vb</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<Compile Remove="SimpleHistory\Enums.vb" />
</ItemGroup>
</Project>

View File

@@ -1,12 +0,0 @@
Namespace SimpleHistory
''' <summary>
''' Specify which member types you would include.
''' </summary>
Public Enum ObjectValueType
None = 0
Field = 1
[Property] = 2
End Enum
End Namespace

View File

@@ -0,0 +1,615 @@
using System.Data;
using System.Reflection;
namespace Pilz.Collections.SimpleHistory;
/// <summary>
/// Represent some Object States and Actions.
/// </summary>
public class HistoryPoint
{
/// <summary>
/// Represents the Name of this History Point
/// </summary>
/// <returns></returns>
public string Name { get; set; } = string.Empty;
/// <summary>
/// A List of Object States and Actions.
/// </summary>
/// <returns></returns>
public List<ObjectBase> Entries { get; } = [];
/// <summary>
/// Some data can be refered on this HistoryPoint. Don't know, in some situations this can be helpful.
/// </summary>
public readonly object? Tag = null;
public bool HasEntries<T>() where T : ObjectBase
{
return Entries.Where(n => n is T).Any();
}
internal void Undo()
{
foreach (var s in Entries.OrderBy(n => n.UndoPriority))
{
switch (s)
{
case ObjectState state:
state.Patch();
break;
case ObjectAction action:
action.Undo();
break;
}
}
}
internal void Redo()
{
foreach (var s in Entries.OrderBy(n => n.RedoPriority))
{
switch (s)
{
case ObjectState state:
state.Patch();
break;
case ObjectAction action:
action.Redo();
break;
}
}
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="whiteList">Specify which members to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, MemberWhiteList whiteList)
{
return FromObject([obj], ObjectValueType.None, (object)whiteList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="blackList">Specify which members to exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, MemberBlackList blackList)
{
return FromObject([obj], ObjectValueType.None, (object)blackList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, params string[] memberName)
{
return FromObject(obj, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], ObjectValueType.None, (object)new MemberWhiteList(memberName), BindingFlags.Default);
else
return FromObject([obj], ObjectValueType.None, (object)new MemberBlackList(memberName), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, ObjectValueType membersToStore, params string[] memberName)
{
return FromObject(obj, membersToStore, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, ObjectValueType membersToStore, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], membersToStore, (object)new MemberWhiteList(memberName), BindingFlags.Default);
else
return FromObject([obj], membersToStore, (object)new MemberBlackList(memberName), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, BindingFlags flags, params string[] memberName)
{
return FromObject(obj, flags, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, BindingFlags flags, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], ObjectValueType.None, (object)new MemberWhiteList(memberName), flags);
else
return FromObject([obj], ObjectValueType.None, (object)new MemberBlackList(memberName), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, ObjectValueType membersToStore, BindingFlags flags, params string[] memberName)
{
return FromObject(obj, flags, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, ObjectValueType membersToStore, BindingFlags flags, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], membersToStore, (object)new MemberWhiteList(memberName), flags);
else
return FromObject([obj], membersToStore, (object)new MemberBlackList(memberName), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="whiteList">Specify which members to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, MemberWhiteList whiteList)
{
return FromObject([obj], ObjectValueType.None, (object)whiteList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="blackList">Specify which members to exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, MemberBlackList blackList)
{
return FromObject([obj], ObjectValueType.None, (object)blackList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, params string[] memberName)
{
return FromObject(obj, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], ObjectValueType.None, (object)new MemberWhiteList(memberName), BindingFlags.Default);
else
return FromObject([obj], ObjectValueType.None, (object)new MemberBlackList(memberName), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, params string[] memberName)
{
return FromObject(obj, membersToStore, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], membersToStore, (object)new MemberWhiteList(memberName), BindingFlags.Default);
else
return FromObject([obj], membersToStore, (object)new MemberBlackList(memberName), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, BindingFlags flags, params string[] memberName)
{
return FromObject(obj, flags, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, BindingFlags flags, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], ObjectValueType.None, (object)new MemberWhiteList(memberName), flags);
else
return FromObject([obj], ObjectValueType.None, (object)new MemberBlackList(memberName), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, BindingFlags flags, params string[] memberName)
{
return FromObject(obj, flags, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, BindingFlags flags, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], membersToStore, (object)new MemberWhiteList(memberName), flags);
else
return FromObject([obj], membersToStore, (object)new MemberBlackList(memberName), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj)
{
return FromObject([obj], ObjectValueType.None, default(object), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore)
{
return FromObject([obj], membersToStore, default(object), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="whiteList">Specify which members to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, MemberWhiteList whiteList)
{
return FromObject([obj], membersToStore, (object)whiteList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="blackList">Specify which members to exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, MemberBlackList blackList)
{
return FromObject([obj], membersToStore, (object)blackList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, BindingFlags flags)
{
return FromObject([obj], ObjectValueType.None, default(object), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, BindingFlags flags)
{
return FromObject([obj], membersToStore, default(object), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="whiteList">Specify which members to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, MemberWhiteList whiteList, BindingFlags flags)
{
return FromObject([obj], membersToStore, (object)whiteList, flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="blackList">Specify which members to exclude.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, MemberBlackList blackList, BindingFlags flags)
{
return FromObject([obj], membersToStore, (object)blackList, flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs)
{
return FromObject(objs, ObjectValueType.None, default(object), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore)
{
return FromObject(objs, membersToStore, default(object), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="whiteList">Specify which members to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore, MemberWhiteList whiteList)
{
return FromObject(objs, membersToStore, (object)whiteList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="blackList">Specify which members to exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore, MemberBlackList blackList)
{
return FromObject(objs, membersToStore, (object)blackList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, BindingFlags flags)
{
return FromObject(objs, ObjectValueType.None, default(object), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore, BindingFlags flags)
{
return FromObject(objs, membersToStore, default(object), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="whiteList">Specify which members to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore, MemberWhiteList whiteList, BindingFlags flags)
{
return FromObject(objs, membersToStore, (object)whiteList, flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="blackList">Specify which members to exclude.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore, MemberBlackList blackList, BindingFlags flags)
{
return FromObject(objs, membersToStore, (object)blackList, flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="whiteOrBlackList">Specify which members to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
private static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore, object? whiteOrBlackList, BindingFlags flags)
{
var hp = new HistoryPoint();
whiteOrBlackList ??= new MemberBlackList();
var isWhiteList = whiteOrBlackList is MemberWhiteList;
if (flags == BindingFlags.Default)
flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
if (membersToStore == ObjectValueType.None)
membersToStore = ObjectValueType.Field | ObjectValueType.Property;
foreach (var obj in objs)
{
if ((membersToStore & ObjectValueType.Field) == ObjectValueType.Field)
{
foreach (var fi in obj.GetType().GetFields(flags))
{
var contains = ((List<string>)whiteOrBlackList).Contains(fi.Name);
if (isWhiteList ? contains : !contains)
{
var os = new ObjectState
{
Object = obj,
MemberName = fi.Name,
MemberType = ObjectValueType.Field,
MemberFlags = flags,
ValueToPatch = fi.GetValue(obj)
};
hp.Entries.Add(os);
}
}
}
if ((membersToStore & ObjectValueType.Property) == ObjectValueType.Property)
{
foreach (var pi in obj.GetType().GetProperties(flags))
{
var contains = ((List<string>)whiteOrBlackList).Contains(pi.Name);
if (isWhiteList ? contains : !contains)
{
var os = new ObjectState
{
Object = obj,
MemberName = pi.Name,
MemberType = ObjectValueType.Property,
MemberFlags = flags,
ValueToPatch = pi.GetValue(obj)
};
hp.Entries.Add(os);
}
}
}
}
return hp;
}
/// <summary>
/// Combines some History Points to one.
/// </summary>
/// <param name="hps">An array of History Points to combine.</param>
/// <returns>One History Point that contains all Data of inputted History Points.</returns>
public static HistoryPoint Concat(params HistoryPoint[] hps)
{
return Concat(null, hps);
}
/// <summary>
/// Combines some History Points to one.
/// </summary>
/// <param name="hps">An array of History Points to combine.</param>
/// <param name="newName">The new name for the History Point after concating.</param>
/// <returns>One History Point that contains all Data of inputted History Points.</returns>
public static HistoryPoint Concat(string? newName, params HistoryPoint[] hps)
{
var hp = new HistoryPoint();
foreach (var _hp in hps)
hp.Entries.AddRange(_hp.Entries);
if (newName != null)
hp.Name = newName;
else
hp.Name = hps.FirstOrDefault()?.Name ?? string.Empty;
return hp;
}
}

View File

@@ -1,543 +0,0 @@
Imports System.Reflection
Namespace SimpleHistory
''' <summary>
''' Represent some Object States and Actions.
''' </summary>
Public Class HistoryPoint
''' <summary>
''' Represents the Name of this History Point
''' </summary>
''' <returns></returns>
Public Property Name As String = ""
''' <summary>
''' A List of Object States and Actions.
''' </summary>
''' <returns></returns>
Public ReadOnly Property Entries As New List(Of ObjectBase)
''' <summary>
''' Some data can be refered on this HistoryPoint. Don't know, in some situations this can be helpful.
''' </summary>
Public ReadOnly Tag As Object = Nothing
Public Function HasEntries(Of T As ObjectBase)() As Boolean
Return Entries.Where(Function(n) TypeOf n Is T).Count > 0
End Function
Friend Sub Undo()
For Each s As ObjectBase In Entries.OrderBy(Function(n) n.UndoPriority)
If TypeOf s Is ObjectState Then
CType(s, ObjectState).Patch()
ElseIf TypeOf s Is ObjectAction Then
CType(s, ObjectAction).Undo()
End If
Next
End Sub
Friend Sub Redo()
For Each s As ObjectBase In Entries.OrderBy(Function(n) n.RedoPriority)
If TypeOf s Is ObjectState Then
CType(s, ObjectState).Patch()
ElseIf TypeOf s Is ObjectAction Then
CType(s, ObjectAction).Redo()
End If
Next
End Sub
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The objects that should be included.</param>
''' <param name="whiteList">Specify which members to include.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object(), whiteList As MemberWhiteList) As HistoryPoint
Return FromObject({obj}, ObjectValueType.None, CObj(whiteList), BindingFlags.Default)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The objects that should be included.</param>
''' <param name="blackList">Specify which members to exclude.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object(), blackList As MemberBlackList) As HistoryPoint
Return FromObject({obj}, ObjectValueType.None, CObj(blackList), BindingFlags.Default)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The objects that should be included.</param>
''' <param name="memberName">The member names to include.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object(), ParamArray memberName As String()) As HistoryPoint
Return FromObject(obj, True, memberName)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The objects that should be included.</param>
''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
''' <param name="memberName">The member names to include/exclude.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object(), isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
If isWhiteList Then
Return FromObject({obj}, ObjectValueType.None, CObj(New MemberWhiteList(memberName)), BindingFlags.Default)
Else
Return FromObject({obj}, ObjectValueType.None, CObj(New MemberBlackList(memberName)), BindingFlags.Default)
End If
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The objects that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="memberName">The member names to include.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object(), membersToStore As ObjectValueType, ParamArray memberName As String()) As HistoryPoint
Return FromObject(obj, membersToStore, True, memberName)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The objects that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
''' <param name="memberName">The member names to include/exclude.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object(), membersToStore As ObjectValueType, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
If isWhiteList Then
Return FromObject({obj}, membersToStore, CObj(New MemberWhiteList(memberName)), BindingFlags.Default)
Else
Return FromObject({obj}, membersToStore, CObj(New MemberBlackList(memberName)), BindingFlags.Default)
End If
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The objects that should be included.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <param name="memberName">The member names to include.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object(), flags As BindingFlags, ParamArray memberName As String()) As HistoryPoint
Return FromObject(obj, flags, True, memberName)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The objects that should be included.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
''' <param name="memberName">The member names to include/exclude.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object(), flags As BindingFlags, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
If isWhiteList Then
Return FromObject({obj}, ObjectValueType.None, CObj(New MemberWhiteList(memberName)), flags)
Else
Return FromObject({obj}, ObjectValueType.None, CObj(New MemberBlackList(memberName)), flags)
End If
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The objects that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <param name="memberName">The member names to include.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object(), membersToStore As ObjectValueType, flags As BindingFlags, ParamArray memberName As String()) As HistoryPoint
Return FromObject(obj, flags, True, memberName)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The objects that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
''' <param name="memberName">The member names to include/exclude.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object(), membersToStore As ObjectValueType, flags As BindingFlags, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
If isWhiteList Then
Return FromObject({obj}, membersToStore, CObj(New MemberWhiteList(memberName)), flags)
Else
Return FromObject({obj}, membersToStore, CObj(New MemberBlackList(memberName)), flags)
End If
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="whiteList">Specify which members to include.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, whiteList As MemberWhiteList) As HistoryPoint
Return FromObject({obj}, ObjectValueType.None, CObj(whiteList), BindingFlags.Default)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="blackList">Specify which members to exclude.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, blackList As MemberBlackList) As HistoryPoint
Return FromObject({obj}, ObjectValueType.None, CObj(blackList), BindingFlags.Default)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="memberName">The member names to include/exclude.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, ParamArray memberName As String()) As HistoryPoint
Return FromObject(obj, True, memberName)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
''' <param name="memberName">The member names to include/exclude.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
If isWhiteList Then
Return FromObject({obj}, ObjectValueType.None, CObj(New MemberWhiteList(memberName)), BindingFlags.Default)
Else
Return FromObject({obj}, ObjectValueType.None, CObj(New MemberBlackList(memberName)), BindingFlags.Default)
End If
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="memberName">The member names to include.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, ParamArray memberName As String()) As HistoryPoint
Return FromObject(obj, membersToStore, True, memberName)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
''' <param name="memberName">The member names to include/exclude.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
If isWhiteList Then
Return FromObject({obj}, membersToStore, CObj(New MemberWhiteList(memberName)), BindingFlags.Default)
Else
Return FromObject({obj}, membersToStore, CObj(New MemberBlackList(memberName)), BindingFlags.Default)
End If
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <param name="memberName">The member names to include.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, flags As BindingFlags, ParamArray memberName As String()) As HistoryPoint
Return FromObject(obj, flags, True, memberName)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
''' <param name="memberName">The member names to include/exclude.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, flags As BindingFlags, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
If isWhiteList Then
Return FromObject({obj}, ObjectValueType.None, CObj(New MemberWhiteList(memberName)), flags)
Else
Return FromObject({obj}, ObjectValueType.None, CObj(New MemberBlackList(memberName)), flags)
End If
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <param name="memberName">The member names to include.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, flags As BindingFlags, ParamArray memberName As String()) As HistoryPoint
Return FromObject(obj, flags, True, memberName)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
''' <param name="memberName">The member names to include/exclude.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, flags As BindingFlags, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
If isWhiteList Then
Return FromObject({obj}, membersToStore, CObj(New MemberWhiteList(memberName)), flags)
Else
Return FromObject({obj}, membersToStore, CObj(New MemberBlackList(memberName)), flags)
End If
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object) As HistoryPoint
Return FromObject({obj}, ObjectValueType.None, CObj(Nothing), BindingFlags.Default)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType) As HistoryPoint
Return FromObject({obj}, membersToStore, CObj(Nothing), BindingFlags.Default)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="whiteList">Specify which members to include.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, whiteList As MemberWhiteList) As HistoryPoint
Return FromObject({obj}, membersToStore, CObj(whiteList), BindingFlags.Default)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="blackList">Specify which members to exclude.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, blackList As MemberBlackList) As HistoryPoint
Return FromObject({obj}, membersToStore, CObj(blackList), BindingFlags.Default)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, flags As BindingFlags) As HistoryPoint
Return FromObject({obj}, ObjectValueType.None, CObj(Nothing), flags)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, flags As BindingFlags) As HistoryPoint
Return FromObject({obj}, membersToStore, CObj(Nothing), flags)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="whiteList">Specify which members to include.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, whiteList As MemberWhiteList, flags As BindingFlags) As HistoryPoint
Return FromObject({obj}, membersToStore, CObj(whiteList), flags)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="obj">The object that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="blackList">Specify which members to exclude.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, blackList As MemberBlackList, flags As BindingFlags) As HistoryPoint
Return FromObject({obj}, membersToStore, CObj(blackList), flags)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="objs">The objects that should be included.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(objs As Object()) As HistoryPoint
Return FromObject(objs, ObjectValueType.None, CObj(Nothing), BindingFlags.Default)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="objs">The objects that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType) As HistoryPoint
Return FromObject(objs, membersToStore, CObj(Nothing), BindingFlags.Default)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="objs">The objects that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="whiteList">Specify which members to include.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType, whiteList As MemberWhiteList) As HistoryPoint
Return FromObject(objs, membersToStore, CObj(whiteList), BindingFlags.Default)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="objs">The objects that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="blackList">Specify which members to exclude.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType, blackList As MemberBlackList) As HistoryPoint
Return FromObject(objs, membersToStore, CObj(blackList), BindingFlags.Default)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="objs">The objects that should be included.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(objs As Object(), flags As BindingFlags) As HistoryPoint
Return FromObject(objs, ObjectValueType.None, CObj(Nothing), flags)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="objs">The objects that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType, flags As BindingFlags) As HistoryPoint
Return FromObject(objs, membersToStore, CObj(Nothing), flags)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="objs">The objects that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="whiteList">Specify which members to include.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType, whiteList As MemberWhiteList, flags As BindingFlags) As HistoryPoint
Return FromObject(objs, membersToStore, CObj(whiteList), flags)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="objs">The objects that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="blackList">Specify which members to exclude.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <returns>A History Point with Object States.</returns>
Public Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType, blackList As MemberBlackList, flags As BindingFlags) As HistoryPoint
Return FromObject(objs, membersToStore, CObj(blackList), flags)
End Function
''' <summary>
''' Creates an History Point with Object States automaticly from input.
''' </summary>
''' <param name="objs">The objects that should be included.</param>
''' <param name="membersToStore">Specify what member types to include.</param>
''' <param name="whiteOrBlackList">Specify which members to include.</param>
''' <param name="flags">The Binding Flags that the members should have.</param>
''' <returns>A History Point with Object States.</returns>
Private Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType, whiteOrBlackList As Object, flags As BindingFlags) As HistoryPoint
Dim hp As New HistoryPoint
If whiteOrBlackList Is Nothing Then whiteOrBlackList = New MemberBlackList
Dim isWhiteList As Boolean = TypeOf whiteOrBlackList Is MemberWhiteList
If flags = BindingFlags.Default Then
flags = BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic
End If
If membersToStore = ObjectValueType.None Then
membersToStore = ObjectValueType.Field Or ObjectValueType.Property
End If
For Each obj As Object In objs
If (membersToStore And ObjectValueType.Field) = ObjectValueType.Field Then
For Each fi As FieldInfo In obj.GetType.GetFields(flags)
Dim contains As Boolean = CType(whiteOrBlackList, List(Of String)).Contains(fi.Name)
If If(isWhiteList, contains, Not contains) Then
Dim os As New ObjectState
os.Object = obj
os.MemberName = fi.Name
os.MemberType = ObjectValueType.Field
os.MemberFlags = flags
os.ValueToPatch = fi.GetValue(obj)
hp.Entries.Add(os)
End If
Next
End If
If (membersToStore And ObjectValueType.Property) = ObjectValueType.Property Then
For Each pi As PropertyInfo In obj.GetType.GetProperties(flags)
Dim contains As Boolean = CType(whiteOrBlackList, List(Of String)).Contains(pi.Name)
If If(isWhiteList, contains, Not contains) Then
Dim os As New ObjectState
os.Object = obj
os.MemberName = pi.Name
os.MemberType = ObjectValueType.Property
os.MemberFlags = flags
os.ValueToPatch = pi.GetValue(obj)
hp.Entries.Add(os)
End If
Next
End If
Next
Return hp
End Function
''' <summary>
''' Combines some History Points to one.
''' </summary>
''' <param name="hps">An array of History Points to combine.</param>
''' <returns>One History Point that contains all Data of inputted History Points.</returns>
Public Shared Function Concat(ParamArray hps As HistoryPoint()) As HistoryPoint
Return Concat(hps.FirstOrDefault?.Name, hps)
End Function
''' <summary>
''' Combines some History Points to one.
''' </summary>
''' <param name="hps">An array of History Points to combine.</param>
''' <returns>One History Point that contains all Data of inputted History Points.</returns>
Public Shared Function Concat(newName As String, ParamArray hps As HistoryPoint()) As HistoryPoint
Dim hp As New HistoryPoint
For Each _hp As HistoryPoint In hps
hp.Entries.AddRange(_hp.Entries)
Next
Return hp
End Function
End Class
End Namespace

View File

@@ -0,0 +1,31 @@
namespace Pilz.Collections.SimpleHistory;
/// <summary>
/// List contianing member names to include.
/// </summary>
public class MemberWhiteList : List<string>
{
public MemberWhiteList() : base()
{
}
public MemberWhiteList(string[] entries) : base(entries)
{
}
}
/// <summary>
/// List contianing member names to exclude
/// </summary>
public class MemberBlackList : List<string>
{
public MemberBlackList() : base()
{
}
public MemberBlackList(string[] entries) : base(entries)
{
}
}

View File

@@ -1,33 +0,0 @@
Namespace SimpleHistory
''' <summary>
''' List contianing member names to include.
''' </summary>
Public Class MemberWhiteList
Inherits List(Of String)
Public Sub New()
MyBase.New
End Sub
Public Sub New(entries As String())
MyBase.New(entries)
End Sub
End Class
''' <summary>
''' List contianing member names to exclude
''' </summary>
Public Class MemberBlackList
Inherits List(Of String)
Public Sub New()
MyBase.New
End Sub
Public Sub New(entries As String())
MyBase.New(entries)
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,176 @@
using System.Reflection;
namespace Pilz.Collections.SimpleHistory;
public class ObjectAction : ObjectBase
{
public object? Object { get; set; } = null;
public List<object> ParametersUndo { get; } = [];
public List<object> ParametersRedo { get; } = [];
public MethodInfo? MethodUndo { get; set; } = null;
public MethodInfo? MethodRedo { get; set; } = null;
public bool AutogenerateObject { get; set; } = true;
/// <summary>
/// Creates a new Instance of Object Action.
/// </summary>
public ObjectAction()
{
}
/// <summary>
/// Creates a new Instance of Object Action.
/// </summary>
/// <param name="obj">The Objects that contains the methodes to call.</param>
/// <param name="methodNameUndo">The name of the methode to call on Undo.</param>
/// <param name="methodNameRedo">The name of the methode to call on Redo.</param>
public ObjectAction(object obj, string methodNameUndo, string methodNameRedo) : this(obj, methodNameUndo, methodNameRedo, [], [], BindingFlags.Default, BindingFlags.Default)
{
}
/// <summary>
/// Creates a new Instance of Object Action.
/// </summary>
/// <param name="obj">The Objects that contains the methodes to call.</param>
/// <param name="methodNameUndo">The name of the methode to call on Undo.</param>
/// <param name="methodNameRedo">The name of the methode to call on Redo.</param>
/// <param name="paramsUndo">The parameters for calling the methode on Undo.</param>
/// <param name="paramsRedo">The parameters for calling the methode on Redo.</param>
public ObjectAction(object obj, string methodNameUndo, string methodNameRedo, object[] paramsUndo, object[] paramsRedo) : this(obj, methodNameUndo, methodNameRedo, paramsUndo, paramsRedo, BindingFlags.Default, BindingFlags.Default)
{
}
/// <summary>
/// Creates a new Instance of Object Action.
/// </summary>
/// <param name="obj">The Objects that contains the methodes to call.</param>
/// <param name="methodNameUndo">The name of the methode to call on Undo.</param>
/// <param name="methodNameRedo">The name of the methode to call on Redo.</param>
/// <param name="paramsUndo">The parameters for calling the methode on Undo.</param>
/// <param name="paramsRedo">The parameters for calling the methode on Redo.</param>
/// <param name="methodFlagsUndo">The Binding Flags of Methode on Undo.</param>
/// <param name="methodFlagsRedo">The Binding Flags of Methode on Redo.</param>
public ObjectAction(object obj, string methodNameUndo, string methodNameRedo, object[] paramsUndo, object[] paramsRedo, BindingFlags methodFlagsUndo, BindingFlags methodFlagsRedo)
{
Object = obj;
ParametersUndo.AddRange(paramsUndo);
ParametersRedo.AddRange(paramsRedo);
MethodUndo = GetMethodInfo(obj, methodNameUndo, GetFlags(methodFlagsUndo));
MethodRedo = GetMethodInfo(obj, methodNameRedo, GetFlags(methodFlagsRedo));
}
/// <summary>
/// Creates a new Instance of Object Action.
/// </summary>
/// <param name="obj">The Objects that contains the methodes to call.</param>
/// <param name="methodNameUndo">The name of the methode to call on Undo.</param>
/// <param name="methodNameRedo">The name of the methode to call on Redo.</param>
/// <param name="methodFlagsUndo">The Binding Flags of Methode on Undo.</param>
/// <param name="methodFlagsRedo">The Binding Flags of Methode on Redo.</param>
public ObjectAction(object obj, string methodNameUndo, string methodNameRedo, BindingFlags methodFlagsUndo, BindingFlags methodFlagsRedo) : this(obj, methodNameUndo, methodNameRedo, [], [], methodFlagsUndo, methodFlagsRedo)
{
}
/// <summary>
/// Creates a new Instance of Object Action.
/// </summary>
/// <param name="obj">The Objects that contains the methodes to call.</param>
/// <param name="methodUndo">The MethodInfo of the methode to call on Undo.</param>
/// <param name="methodRedo">The MethodInfo of the methode to call on Redo.</param>
public ObjectAction(object obj, MethodInfo methodUndo, MethodInfo methodRedo)
{
Object = obj;
MethodUndo = methodUndo;
MethodRedo = methodRedo;
}
/// <summary>
/// Creates a new Instance of Object Action.
/// </summary>
/// <param name="obj">The Objects that contains the methodes to call.</param>
/// <param name="methodUndo">The MethodInfo of the methode to call on Undo.</param>
/// <param name="methodRedo">The MethodInfo of the methode to call on Redo.</param>
/// <param name="paramsUndo">The parameters for calling the methode on Undo.</param>
/// <param name="paramsRedo">The parameters for calling the methode on Redo.</param>
public ObjectAction(object obj, MethodInfo methodUndo, MethodInfo methodRedo, object[] paramsUndo, object[] paramsRedo) : this(obj, methodUndo, methodRedo)
{
ParametersUndo.AddRange(paramsUndo);
ParametersRedo.AddRange(paramsRedo);
}
/// <summary>
/// Creates a new Instance of Object Action.
/// </summary>
/// <param name="obj">The Objects that contains the methodes to call.</param>
/// <param name="methodUndo">The Delegate of the methode to call on Undo.</param>
/// <param name="methodRedo">The Delegate of the methode to call on Redo.</param>
public ObjectAction(object obj, Delegate methodUndo, Delegate methodRedo)
{
Object = obj;
MethodUndo = methodUndo.Method;
MethodRedo = methodRedo.Method;
}
/// <summary>
/// Creates a new Instance of Object Action.
/// </summary>
/// <param name="obj">The Objects that contains the methodes to call.</param>
/// <param name="methodUndo">The Delegate of the methode to call on Undo.</param>
/// <param name="methodRedo">The Delegate of the methode to call on Redo.</param>
/// <param name="paramsUndo">The parameters for calling the methode on Undo.</param>
/// <param name="paramsRedo">The parameters for calling the methode on Redo.</param>
public ObjectAction(object obj, Delegate methodUndo, Delegate methodRedo, object[] paramsUndo, object[] paramsRedo) : this(obj, methodUndo, methodRedo)
{
ParametersUndo.AddRange(paramsUndo);
ParametersRedo.AddRange(paramsRedo);
}
/// <summary>
/// Creates a new Instance of Object Action.
/// </summary>
/// <param name="obj">The Objects that contains the methodes to call.</param>
/// <param name="methodUndo">The Action of the methode to call on Undo.</param>
/// <param name="methodRedo">The Action of the methode to call on Redo.</param>
public ObjectAction(object obj, Action methodUndo, Action methodRedo)
{
Object = obj;
MethodUndo = methodUndo.Method;
MethodRedo = methodRedo.Method;
}
private static BindingFlags GetFlags(BindingFlags flags)
{
if (flags == BindingFlags.Default)
flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
return flags;
}
private static MethodInfo? GetMethodInfo(object obj, string name, BindingFlags flags)
{
return obj.GetType().GetMethod(name, flags);
}
internal void Undo()
{
CheckIfObjIsNothing(MethodUndo);
MethodUndo?.Invoke(Object, ParametersUndo.ToArray());
}
internal void Redo()
{
CheckIfObjIsNothing(MethodRedo);
MethodRedo?.Invoke(Object, ParametersRedo.ToArray());
}
private void CheckIfObjIsNothing(MethodInfo? mi)
{
if (mi is not null && !mi.IsStatic && AutogenerateObject)
{
if ((Object is null || Object.GetType() != mi.ReflectedType) && !mi.IsStatic)
{
var constructor = mi.ReflectedType?.GetConstructor(Type.EmptyTypes);
var classObject = constructor?.Invoke([]);
Object = classObject;
}
}
}
}

View File

@@ -1,165 +0,0 @@
Imports System.Reflection
Imports System.Runtime.InteropServices
Namespace SimpleHistory
Public Class ObjectAction
Inherits ObjectBase
Public Property [Object] As Object = Nothing
Public ReadOnly Property ParametersUndo As New List(Of Object)
Public ReadOnly Property ParametersRedo As New List(Of Object)
Public Property MethodUndo As MethodInfo = Nothing
Public Property MethodRedo As MethodInfo = Nothing
Public Property AutogenerateObject As Boolean = True
''' <summary>
''' Creates a new Instance of Object Action.
''' </summary>
Public Sub New()
End Sub
Private Function GetMethodInfo(obj As Object, name As String, flags As BindingFlags)
Return obj.GetType.GetMethod(name, flags)
End Function
''' <summary>
''' Creates a new Instance of Object Action.
''' </summary>
''' <param name="obj">The Objects that contains the methodes to call.</param>
''' <param name="methodNameUndo">The name of the methode to call on Undo.</param>
''' <param name="methodNameRedo">The name of the methode to call on Redo.</param>
Public Sub New(obj As Object, methodNameUndo As String, methodNameRedo As String)
Me.New(obj, methodNameUndo, methodNameRedo, {}, {}, BindingFlags.Default, BindingFlags.Default)
End Sub
''' <summary>
''' Creates a new Instance of Object Action.
''' </summary>
''' <param name="obj">The Objects that contains the methodes to call.</param>
''' <param name="methodNameUndo">The name of the methode to call on Undo.</param>
''' <param name="methodNameRedo">The name of the methode to call on Redo.</param>
''' <param name="paramsUndo">The parameters for calling the methode on Undo.</param>
''' <param name="paramsRedo">The parameters for calling the methode on Redo.</param>
Public Sub New(obj As Object, methodNameUndo As String, methodNameRedo As String, paramsUndo As Object(), paramsRedo As Object())
Me.New(obj, methodNameUndo, methodNameRedo, paramsUndo, paramsRedo, BindingFlags.Default, BindingFlags.Default)
End Sub
''' <summary>
''' Creates a new Instance of Object Action.
''' </summary>
''' <param name="obj">The Objects that contains the methodes to call.</param>
''' <param name="methodNameUndo">The name of the methode to call on Undo.</param>
''' <param name="methodNameRedo">The name of the methode to call on Redo.</param>
''' <param name="paramsUndo">The parameters for calling the methode on Undo.</param>
''' <param name="paramsRedo">The parameters for calling the methode on Redo.</param>
''' <param name="methodFlagsUndo">The Binding Flags of Methode on Undo.</param>
''' <param name="methodFlagsRedo">The Binding Flags of Methode on Redo.</param>
Public Sub New(obj As Object, methodNameUndo As String, methodNameRedo As String, paramsUndo As Object(), paramsRedo As Object(), methodFlagsUndo As BindingFlags, methodFlagsRedo As BindingFlags)
[Object] = obj
ParametersUndo.AddRange(paramsUndo)
ParametersRedo.AddRange(paramsRedo)
MethodUndo = GetMethodInfo(obj, methodNameUndo, GetFlags(methodFlagsUndo))
MethodRedo = GetMethodInfo(obj, methodNameRedo, GetFlags(methodFlagsRedo))
End Sub
''' <summary>
''' Creates a new Instance of Object Action.
''' </summary>
''' <param name="obj">The Objects that contains the methodes to call.</param>
''' <param name="methodNameUndo">The name of the methode to call on Undo.</param>
''' <param name="methodNameRedo">The name of the methode to call on Redo.</param>
''' <param name="methodFlagsUndo">The Binding Flags of Methode on Undo.</param>
''' <param name="methodFlagsRedo">The Binding Flags of Methode on Redo.</param>
Public Sub New(obj As Object, methodNameUndo As String, methodNameRedo As String, methodFlagsUndo As BindingFlags, methodFlagsRedo As BindingFlags)
Me.New(obj, methodNameUndo, methodNameRedo, {}, {}, methodFlagsUndo, methodFlagsRedo)
End Sub
''' <summary>
''' Creates a new Instance of Object Action.
''' </summary>
''' <param name="obj">The Objects that contains the methodes to call.</param>
''' <param name="methodUndo">The MethodInfo of the methode to call on Undo.</param>
''' <param name="methodRedo">The MethodInfo of the methode to call on Redo.</param>
Public Sub New(obj As Object, methodUndo As MethodInfo, methodRedo As MethodInfo)
[Object] = obj
Me.MethodUndo = methodUndo
Me.MethodRedo = methodRedo
End Sub
''' <summary>
''' Creates a new Instance of Object Action.
''' </summary>
''' <param name="obj">The Objects that contains the methodes to call.</param>
''' <param name="methodUndo">The MethodInfo of the methode to call on Undo.</param>
''' <param name="methodRedo">The MethodInfo of the methode to call on Redo.</param>
''' <param name="paramsUndo">The parameters for calling the methode on Undo.</param>
''' <param name="paramsRedo">The parameters for calling the methode on Redo.</param>
Public Sub New(obj As Object, methodUndo As MethodInfo, methodRedo As MethodInfo, paramsUndo As Object(), paramsRedo As Object())
Me.New(obj, methodUndo, methodRedo)
ParametersUndo.AddRange(paramsUndo)
ParametersRedo.AddRange(paramsRedo)
End Sub
''' <summary>
''' Creates a new Instance of Object Action.
''' </summary>
''' <param name="obj">The Objects that contains the methodes to call.</param>
''' <param name="methodUndo">The Delegate of the methode to call on Undo.</param>
''' <param name="methodRedo">The Delegate of the methode to call on Redo.</param>
Public Sub New(obj As Object, methodUndo As [Delegate], methodRedo As [Delegate])
[Object] = obj
Me.MethodUndo = methodUndo.Method
Me.MethodRedo = methodRedo.Method
End Sub
''' <summary>
''' Creates a new Instance of Object Action.
''' </summary>
''' <param name="obj">The Objects that contains the methodes to call.</param>
''' <param name="methodUndo">The Delegate of the methode to call on Undo.</param>
''' <param name="methodRedo">The Delegate of the methode to call on Redo.</param>
''' <param name="paramsUndo">The parameters for calling the methode on Undo.</param>
''' <param name="paramsRedo">The parameters for calling the methode on Redo.</param>
Public Sub New(obj As Object, methodUndo As [Delegate], methodRedo As [Delegate], paramsUndo As Object(), paramsRedo As Object())
Me.New(obj, methodUndo, methodRedo)
ParametersUndo.AddRange(paramsUndo)
ParametersRedo.AddRange(paramsRedo)
End Sub
''' <summary>
''' Creates a new Instance of Object Action.
''' </summary>
''' <param name="obj">The Objects that contains the methodes to call.</param>
''' <param name="methodUndo">The Action of the methode to call on Undo.</param>
''' <param name="methodRedo">The Action of the methode to call on Redo.</param>
Public Sub New(obj As Object, methodUndo As Action, methodRedo As Action)
[Object] = obj
Me.MethodUndo = methodUndo.Method
Me.MethodRedo = methodRedo.Method
End Sub
Private Function GetFlags(flags As BindingFlags) As BindingFlags
If flags = BindingFlags.Default Then
flags = BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic
End If
Return flags
End Function
Friend Sub Undo()
CheckIfObjIsNothing(MethodUndo)
MethodUndo?.Invoke([Object], ParametersUndo.ToArray)
End Sub
Friend Sub Redo()
CheckIfObjIsNothing(MethodRedo)
MethodRedo?.Invoke([Object], ParametersRedo.ToArray)
End Sub
Private Sub CheckIfObjIsNothing(mi As MethodInfo)
If mi IsNot Nothing AndAlso Not mi.IsStatic AndAlso AutogenerateObject Then
If (Me.Object Is Nothing OrElse Me.Object.GetType <> mi.ReflectedType) AndAlso Not mi.IsStatic Then
Dim constructor As ConstructorInfo = mi.ReflectedType.GetConstructor(Type.EmptyTypes)
Dim classObject As Object = constructor.Invoke({})
Me.Object = classObject
End If
End If
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,10 @@
namespace Pilz.Collections.SimpleHistory;
public class ObjectBase
{
public static int DefaultPriorityValue { get; set; } = 1000;
public int UndoPriority { get; set; } = DefaultPriorityValue;
public int RedoPriority { get; set; } = DefaultPriorityValue;
}

View File

@@ -1,13 +0,0 @@
Namespace SimpleHistory
Public Class ObjectBase
Public Shared Property DefaultPriorityValue As Integer = 1000
Public Property UndoPriority As Integer = DefaultPriorityValue
Public Property RedoPriority As Integer = DefaultPriorityValue
End Class
End Namespace

View File

@@ -0,0 +1,88 @@
using System.Reflection;
namespace Pilz.Collections.SimpleHistory;
public class ObjectState : ObjectBase
{
/// <summary>
/// The Object including the members to patch.
/// </summary>
/// <returns></returns>
public object? Object { get; set; } = null;
/// <summary>
/// The name of the Member to patch.
/// </summary>
/// <returns></returns>
public string MemberName { get; set; } = "";
/// <summary>
/// The Value that should be patched.
/// </summary>
/// <returns></returns>
public object? ValueToPatch { get; set; } = null;
/// <summary>
/// The member types to include at searching for the member.
/// </summary>
/// <returns></returns>
public ObjectValueType MemberType { get; set; } = ObjectValueType.Field;
/// <summary>
/// The Binding Flags that are used at searching for the member.
/// </summary>
/// <returns></returns>
public BindingFlags MemberFlags { get; set; } = BindingFlags.Default;
/// <summary>
/// Creates a new Instance of ObjectState from input.
/// </summary>
/// <param name="obj">The Object including the members to patch.</param>
/// <param name="valname">The name of the Member to patch.</param>
/// <param name="valToPatch">The member types to include at searching for the member.</param>
/// <param name="valtype">The Binding Flags that are used at searching for the member.</param>
public ObjectState(object obj, string valname, object valToPatch, ObjectValueType valtype)
{
Object = obj;
MemberName = valname;
ValueToPatch = valToPatch;
MemberType = valtype;
}
/// <summary>
/// Creates a new Instance of ObjectState.
/// </summary>
public ObjectState()
{
}
internal void Patch()
{
if (Object is null)
return;
var t = Object.GetType();
switch (MemberType)
{
case ObjectValueType.Field:
if (t.GetField(MemberName, MemberFlags) is FieldInfo f)
{
var temp = f.GetValue(Object);
f.SetValue(Object, ValueToPatch);
ValueToPatch = temp;
}
break;
case ObjectValueType.Property:
if (t.GetProperty(MemberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static) is PropertyInfo p)
{
var temp = p.GetValue(Object);
p.SetValue(Object, ValueToPatch);
ValueToPatch = temp;
}
break;
default:
throw new Exception("ValueType is invalid!");
}
}
}

View File

@@ -1,84 +0,0 @@
Imports System.Reflection
Namespace SimpleHistory
Public Class ObjectState
Inherits ObjectBase
''' <summary>
''' The Object including the members to patch.
''' </summary>
''' <returns></returns>
Public Property [Object] As Object = Nothing
''' <summary>
''' The name of the Member to patch.
''' </summary>
''' <returns></returns>
Public Property MemberName As String = ""
''' <summary>
''' The Value that should be patched.
''' </summary>
''' <returns></returns>
Public Property ValueToPatch As Object = Nothing
''' <summary>
''' The member types to include at searching for the member.
''' </summary>
''' <returns></returns>
Public Property MemberType As ObjectValueType = ObjectValueType.Field
''' <summary>
''' The Binding Flags that are used at searching for the member.
''' </summary>
''' <returns></returns>
Public Property MemberFlags As BindingFlags = BindingFlags.Default
''' <summary>
''' Creates a new Instance of ObjectState from input.
''' </summary>
''' <param name="obj">The Object including the members to patch.</param>
''' <param name="valname">The name of the Member to patch.</param>
''' <param name="valToPatch">The member types to include at searching for the member.</param>
''' <param name="valtype">The Binding Flags that are used at searching for the member.</param>
Public Sub New(obj As Object, valname As String, valToPatch As Object, valtype As ObjectValueType)
[Object] = obj
MemberName = valname
ValueToPatch = valToPatch
MemberType = valtype
End Sub
''' <summary>
''' Creates a new Instance of ObjectState.
''' </summary>
Public Sub New()
End Sub
Friend Sub Patch()
Dim t As Type = [Object].GetType
Select Case MemberType
Case ObjectValueType.Field
Dim f As FieldInfo = t.GetField(MemberName, MemberFlags)
Dim temp As Object = Nothing
If f IsNot Nothing Then
temp = f.GetValue([Object])
f.SetValue([Object], ValueToPatch)
ValueToPatch = temp
End If
Case ObjectValueType.Property
Dim p As PropertyInfo = t.GetProperty(MemberName, BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Static)
Dim temp As Object = Nothing
If p IsNot Nothing Then
temp = p.GetValue([Object])
p.SetValue([Object], ValueToPatch)
ValueToPatch = temp
End If
Case Else
Throw New Exception("ValueType is invalid!")
End Select
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,11 @@
namespace Pilz.Collections.SimpleHistory;
/// <summary>
/// Specify which member types you would include.
/// </summary>
public enum ObjectValueType
{
None = 0,
Field = 1,
Property = 2,
}

View File

@@ -1,12 +0,0 @@
Namespace SimpleHistory
''' <summary>
''' Specify which member types you would include.
''' </summary>
Public Enum ObjectValueType
None = 0
Field = 1
[Property] = 2
End Enum
End Namespace

View File

@@ -0,0 +1,101 @@
namespace Pilz.Collections.SimpleHistory;
public class HistoryStack
{
private readonly Stack<HistoryPoint> stackPast = new();
private readonly Stack<HistoryPoint> stackFuture = new();
/// <summary>
/// Gets the count of history points.
/// </summary>
/// <returns></returns>
public int ChangesCount => stackPast.Count;
/// <summary>
/// Gets the current stack of all past HistoryPoints that are used for the Undo function.
/// </summary>
/// <returns></returns>
public HistoryPoint[] PastHistoryPoints => [.. stackPast];
/// <summary>
/// Gets the current stack of all future HistoryPoints that are used for the Redo function.
/// </summary>
/// <returns></returns>
public HistoryPoint[] FutureHistoryPoints => [.. stackFuture];
/// <summary>
/// Checks if the History has past changes.
/// </summary>
/// <returns></returns>
public bool HasChanges() => stackPast.Count > 0;
/// <summary>
/// Patch Object States and call Undo Actions.
/// </summary>
public HistoryPoint? Undo()
{
HistoryPoint? ret;
if (stackPast.Count > 0)
{
var hp = stackPast.Pop();
hp.Undo();
stackFuture.Push(hp);
ret = hp;
}
else
ret = null;
return ret;
}
/// <summary>
/// Patch Object States and call Redo Actions.
/// </summary>
public HistoryPoint? Redo()
{
HistoryPoint? ret;
if (stackFuture.Count > 0)
{
var hp = stackFuture.Pop();
hp.Redo();
stackPast.Push(hp);
ret = hp;
}
else
ret = null;
return ret;
}
/// <summary>
/// Clear the History.
/// </summary>
public void Clear()
{
stackPast.Clear();
stackFuture.Clear();
}
/// <summary>
/// Store a History Point.
/// </summary>
/// <param name="point">The History Point to add to the past changes.</param>
/// <param name="newName">The name to set for the History Point.</param>
public void Store(HistoryPoint point, string newName)
{
point.Name = newName;
Store(point);
}
/// <summary>
/// Store a History Point.
/// </summary>
/// <param name="point">The History Point to add to the past changes.</param>
public void Store(HistoryPoint point)
{
stackPast.Push(point);
stackFuture.Clear();
}
}

View File

@@ -1,113 +0,0 @@
Imports System.Reflection
Namespace SimpleHistory
Public Class HistoryStack
Private stackPast As New Stack(Of HistoryPoint)
Private stackFuture As New Stack(Of HistoryPoint)
''' <summary>
''' Gets the count of history points.
''' </summary>
''' <returns></returns>
Public ReadOnly Property ChangesCount As Boolean
Get
Return stackPast.Count
End Get
End Property
''' <summary>
''' Gets the current stack of all past HistoryPoints that are used for the Undo function.
''' </summary>
''' <returns></returns>
Public ReadOnly Property PastHistoryPoints As HistoryPoint()
Get
Return stackPast.ToArray
End Get
End Property
''' <summary>
''' Gets the current stack of all future HistoryPoints that are used for the Redo function.
''' </summary>
''' <returns></returns>
Public ReadOnly Property FutureHistoryPoints As HistoryPoint()
Get
Return stackFuture.ToArray
End Get
End Property
''' <summary>
''' Checks if the History has past changes.
''' </summary>
''' <returns></returns>
Public Function HasChanges() As Boolean
Return stackPast.Count > 0
End Function
''' <summary>
''' Patch Object States and call Undo Actions.
''' </summary>
Public Function Undo() As HistoryPoint
Dim ret As HistoryPoint
If stackPast.Count > 0 Then
Dim hp As HistoryPoint = stackPast.Pop
hp.Undo()
stackFuture.Push(hp)
ret = hp
Else
ret = Nothing
End If
Return ret
End Function
''' <summary>
''' Patch Object States and call Redo Actions.
''' </summary>
Public Function Redo() As HistoryPoint
Dim ret As HistoryPoint
If stackFuture.Count > 0 Then
Dim hp As HistoryPoint = stackFuture.Pop
hp.Redo()
stackPast.Push(hp)
ret = hp
Else
ret = Nothing
End If
Return ret
End Function
''' <summary>
''' Clear the History.
''' </summary>
Public Sub Clear()
stackPast.Clear()
stackFuture.Clear()
End Sub
''' <summary>
''' Store a History Point.
''' </summary>
''' <param name="point">The History Point to add to the past changes.</param>
''' <param name="newName">The name to set for the History Point.</param>
Public Sub Store(point As HistoryPoint, newName As String)
point.Name = newName
Store(point)
End Sub
''' <summary>
''' Store a History Point.
''' </summary>
''' <param name="point">The History Point to add to the past changes.</param>
Public Sub Store(point As HistoryPoint)
stackPast.Push(point)
stackFuture.Clear()
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,86 @@
using System;
namespace Pilz.Configuration;
public class AutoSaveConfigurationManager : ConfigurationManager
{
private bool addedHandler = false;
private bool enableAutoSave = false;
private string _ConfigFilePath = string.Empty;
private bool _AutoLoadConfigOnAccess = false;
public string ConfigFilePath
{
get => _ConfigFilePath;
set
{
_ConfigFilePath = value;
if (AutoLoadConfigOnAccess)
Load();
}
}
public bool AutoLoadConfigOnAccess
{
get => _AutoLoadConfigOnAccess;
set
{
_AutoLoadConfigOnAccess = value;
if (value)
Load();
}
}
public bool AutoSaveConfigOnExit
{
get => enableAutoSave;
set
{
if (enableAutoSave != value)
{
enableAutoSave = value;
if (enableAutoSave)
AddAutoSaveHandler();
else
RemoveAutoSaveHandler();
}
}
}
private void AddAutoSaveHandler()
{
if (!addedHandler)
{
AppDomain.CurrentDomain.ProcessExit += AutoSaveSettingsOnExit;
addedHandler = true;
}
}
private void RemoveAutoSaveHandler()
{
AppDomain.CurrentDomain.ProcessExit -= AutoSaveSettingsOnExit;
addedHandler = false;
}
private void AutoSaveSettingsOnExit(object sender, EventArgs e)
{
Save();
}
private void Save()
{
if (!string.IsNullOrEmpty(ConfigFilePath) && Configuration is not null)
Configuration.WriteToFile(ConfigFilePath);
}
private void Load()
{
if (!string.IsNullOrEmpty(ConfigFilePath))
Configuration.ReadFromFile(ConfigFilePath);
}
~AutoSaveConfigurationManager()
{
RemoveAutoSaveHandler();
}
}

View File

@@ -1,78 +0,0 @@
Public Class AutoSaveConfigurationManager
Inherits ConfigurationManager
Private addedHandler As Boolean = False
Private enableAutoSave As Boolean = False
Private _ConfigFilePath As String = String.Empty
Private _AutoLoadConfigOnAccess As Boolean = False
Public Property ConfigFilePath As String
Get
Return _ConfigFilePath
End Get
Set
_ConfigFilePath = Value
If AutoLoadConfigOnAccess Then Load()
End Set
End Property
Public Property AutoLoadConfigOnAccess As Boolean
Get
Return _AutoLoadConfigOnAccess
End Get
Set
_AutoLoadConfigOnAccess = Value
If Value Then Load()
End Set
End Property
Public Property AutoSaveConfigOnExit As Boolean
Get
Return enableAutoSave
End Get
Set
If enableAutoSave <> Value Then
enableAutoSave = Value
Select Case enableAutoSave
Case True
AddAutoSaveHandler()
Case False
RemoveAutoSaveHandler()
End Select
End If
End Set
End Property
Private Sub AddAutoSaveHandler()
If Not addedHandler Then
AddHandler AppDomain.CurrentDomain.ProcessExit, AddressOf AutoSaveSettingsOnExit
addedHandler = True
End If
End Sub
Private Sub RemoveAutoSaveHandler()
RemoveHandler AppDomain.CurrentDomain.ProcessExit, AddressOf AutoSaveSettingsOnExit
addedHandler = False
End Sub
Private Sub AutoSaveSettingsOnExit(sender As Object, e As EventArgs)
Save()
End Sub
Private Sub Save()
If Not String.IsNullOrEmpty(ConfigFilePath) AndAlso Configuration IsNot Nothing Then
Configuration.WriteToFile(ConfigFilePath)
End If
End Sub
Private Sub Load()
If Not String.IsNullOrEmpty(ConfigFilePath) Then
Configuration.ReadFromFile(ConfigFilePath)
End If
End Sub
Protected Overrides Sub Finalize()
RemoveAutoSaveHandler()
End Sub
End Class

View File

@@ -0,0 +1,11 @@
namespace Pilz.Configuration;
public abstract class ConfigurationManager
{
public SimpleConfiguration Configuration { get; private set; }
internal void SetConfiguration(SimpleConfiguration configuration)
{
Configuration = configuration;
}
}

View File

@@ -1,9 +0,0 @@
Public MustInherit Class ConfigurationManager
Public ReadOnly Property Configuration As SimpleConfiguration
Friend Sub SetConfiguration(configuration As SimpleConfiguration)
_Configuration = configuration
End Sub
End Class

View File

@@ -0,0 +1,87 @@
using Pilz.GeneralEventArgs;
using System.Collections;
using System.Collections.Generic;
namespace Pilz.Configuration;
public class ConfigurationManagerList : IList<ConfigurationManager>
{
public event GettingParentManagerEventHandler GettingParentManager;
public delegate void GettingParentManagerEventHandler(object sender, GetValueEventArgs<SimpleConfiguration> e);
private readonly List<ConfigurationManager> myList = [];
private object GetParentManager()
{
var args = new GetValueEventArgs<SimpleConfiguration>();
GettingParentManager?.Invoke(this, args);
return args.Value;
}
public ConfigurationManager this[int index]
{
get => myList[index];
set => myList[index] = value;
}
public int Count => myList.Count;
public bool IsReadOnly => false;
public void Insert(int index, ConfigurationManager item)
{
myList.Insert(index, item);
item.SetConfiguration((SimpleConfiguration)GetParentManager());
}
public void RemoveAt(int index)
{
}
public void Add(ConfigurationManager item)
{
item.SetConfiguration((SimpleConfiguration)GetParentManager());
}
public void Clear()
{
foreach (ConfigurationManager item in myList)
item.SetConfiguration(null);
myList.Clear();
}
public void CopyTo(ConfigurationManager[] array, int arrayIndex)
{
myList.CopyTo(array, arrayIndex);
}
public int IndexOf(ConfigurationManager item)
{
return myList.IndexOf(item);
}
public bool Contains(ConfigurationManager item)
{
return myList.Contains(item);
}
public bool Remove(ConfigurationManager item)
{
item.SetConfiguration(null);
return myList.Remove(item);
}
public IEnumerator<ConfigurationManager> GetEnumerator()
{
return (IEnumerator<ConfigurationManager>)IEnumerable_GetEnumerator();
}
private IEnumerator IEnumerable_GetEnumerator()
{
return myList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() => IEnumerable_GetEnumerator();
}

View File

@@ -1,83 +0,0 @@
Imports Pilz.Configuration
Imports Pilz.GeneralEventArgs
Public Class ConfigurationManagerList
Implements IList(Of ConfigurationManager)
Public Event GettingParentManager(sender As Object, e As GetValueEventArgs(Of SimpleConfiguration))
Private ReadOnly myList As New List(Of ConfigurationManager)
Private Function GetParentManager()
Dim args As New GetValueEventArgs(Of SimpleConfiguration)
RaiseEvent GettingParentManager(Me, args)
Return args.Value
End Function
Default Public Property Item(index As Integer) As ConfigurationManager Implements IList(Of ConfigurationManager).Item
Get
Return myList(index)
End Get
Set(value As ConfigurationManager)
myList(index) = value
End Set
End Property
Public ReadOnly Property Count As Integer Implements ICollection(Of ConfigurationManager).Count
Get
Return myList.Count
End Get
End Property
Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of ConfigurationManager).IsReadOnly
Get
Return False
End Get
End Property
Public Sub Insert(index As Integer, item As ConfigurationManager) Implements IList(Of ConfigurationManager).Insert
myList.Insert(index, item)
item.SetConfiguration(GetParentManager)
End Sub
Public Sub RemoveAt(index As Integer) Implements IList(Of ConfigurationManager).RemoveAt
End Sub
Public Sub Add(item As ConfigurationManager) Implements ICollection(Of ConfigurationManager).Add
item.SetConfiguration(GetParentManager)
End Sub
Public Sub Clear() Implements ICollection(Of ConfigurationManager).Clear
For Each item As ConfigurationManager In myList
item.SetConfiguration(Nothing)
Next
myList.Clear()
End Sub
Public Sub CopyTo(array() As ConfigurationManager, arrayIndex As Integer) Implements ICollection(Of ConfigurationManager).CopyTo
myList.CopyTo(array, arrayIndex)
End Sub
Public Function IndexOf(item As ConfigurationManager) As Integer Implements IList(Of ConfigurationManager).IndexOf
Return myList.IndexOf(item)
End Function
Public Function Contains(item As ConfigurationManager) As Boolean Implements ICollection(Of ConfigurationManager).Contains
Return myList.Contains(item)
End Function
Public Function Remove(item As ConfigurationManager) As Boolean Implements ICollection(Of ConfigurationManager).Remove
item.SetConfiguration(Nothing)
Return myList.Remove(item)
End Function
Public Function GetEnumerator() As IEnumerator(Of ConfigurationManager) Implements IEnumerable(Of ConfigurationManager).GetEnumerator
Return IEnumerable_GetEnumerator()
End Function
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return myList.GetEnumerator
End Function
End Class

View File

@@ -0,0 +1,138 @@
using Newtonsoft.Json;
using Pilz.GeneralEventArgs;
using System.IO;
namespace Pilz.Configuration;
public static class ConfigurationSerializer
{
public static event GettingJsonSerializerEventHandler GettingJsonSerializer;
public delegate void GettingJsonSerializerEventHandler(object instance, GetValueEventArgs<JsonSerializer> e);
private static JsonSerializer GetJsonSerializer(SimpleConfiguration instance)
{
var args = new GetValueEventArgs<JsonSerializer>(JsonSerializer.CreateDefault());
GettingJsonSerializer?.Invoke(instance, args);
return args.Value;
}
/// <summary>
/// Writes the given instance to a string and return it.
/// </summary>
/// <param name="instance">The configuration instance that should be serialized.</param>
/// <returns>The content of the configuration instance as string.</returns>
public static string WriteToString(SimpleConfiguration instance)
{
var tw = new StringWriter();
GetJsonSerializer(instance).Serialize(tw, instance);
string txt = tw.ToString();
tw.Close();
return txt;
}
/// <summary>
/// Write the given instance to a given stream.
/// </summary>
/// <param name="instance">The configuration instance that should be serialized.</param>
/// <param name="stream">The stream where the content should be written to.</param>
public static void WriteToStream(SimpleConfiguration instance, Stream stream)
{
var sr = new StreamWriter(stream);
sr.Write(WriteToString(instance));
}
/// <summary>
/// Writes the given instance to the given filePath as text file.
/// </summary>
/// <param name="instance">The configuration instance that should be serialized.</param>
/// <param name="filePath">The file path where the content should be written to. The file will be created or overwritten.</param>
public static void WriteToFile(SimpleConfiguration instance, string filePath)
{
var fs = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
WriteToStream(instance, fs);
fs.Close();
}
/// <summary>
/// Reads a configuratin from the given string and returns an instance of it.
/// </summary>
/// <typeparam name="T">The type of the configuration class to instance.</typeparam>
/// <param name="content">The content of the configuration as string.</param>
/// <returns></returns>
public static T ReadFromString<T>(string content) where T : SimpleConfiguration
{
var sr = new StringReader(content);
T instance = (T)GetJsonSerializer(null).Deserialize(sr, typeof(T));
sr.Close();
return instance;
}
/// <summary>
/// Read a configuration from the given string and put them to the given instance.
/// </summary>
/// <param name="instance">The instance to populate with the configuration.</param>
/// <param name="content">The content of the configuration as string.</param>
public static void ReadFromString(SimpleConfiguration instance, string content)
{
var sr = new StringReader(content);
GetJsonSerializer(null).Populate(sr, content);
sr.Close();
}
/// <summary>
/// Reads a configuratin from the given string and returns an instance of it.
/// </summary>
/// <typeparam name="T">The type of the configuration class to instance.</typeparam>
/// <param name="stream">The stream with the content of the configuration.</param>
/// <returns></returns>
public static T ReadFromStream<T>(Stream stream) where T : SimpleConfiguration
{
return ReadFromString<T>(GetContentOfStream(stream));
}
/// <summary>
/// Read a configuration from the given string and put them to the given instance.
/// </summary>
/// <param name="instance">The instance to populate with the configuration.</param>
/// <param name="stream">The stream with the content of the configuration.</param>
public static void ReadFromStream(SimpleConfiguration instance, Stream stream)
{
ReadFromString(instance, GetContentOfStream(stream));
}
/// <summary>
/// Reads a configuratin from the given string and returns an instance of it.
/// </summary>
/// <typeparam name="T">The type of the configuration class to instance.</typeparam>
/// <param name="filePath">The path to the file with the content of the configuration.</param>
/// <returns></returns>
public static T ReadFromFile<T>(string filePath) where T : SimpleConfiguration
{
return ReadFromString<T>(GetContentOfFile(filePath));
}
/// <summary>
/// Read a configuration from the given string and put them to the given instance.
/// </summary>
/// <param name="instance">The instance to populate with the configuration.</param>
/// <param name="filePath">The path to the file with the content of the configuration.</param>
public static void ReadFromFile(SimpleConfiguration instance, string filePath)
{
ReadFromString(instance, GetContentOfFile(filePath));
}
private static string GetContentOfStream(Stream stream)
{
var sr = new StreamReader(stream);
return sr.ReadToEnd();
}
private static string GetContentOfFile(string filePath)
{
var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
string content = GetContentOfStream(fs);
fs.Close();
return content;
}
}

View File

@@ -1,123 +0,0 @@
Imports System.IO
Imports Newtonsoft.Json
Imports Pilz.GeneralEventArgs
Public Module ConfigurationSerializer
Public Event GettingJsonSerializer(instance As Object, e As GetValueEventArgs(Of JsonSerializer))
Private Function GetJsonSerializer(instance As SimpleConfiguration) As JsonSerializer
Dim args As New GetValueEventArgs(Of JsonSerializer)(JsonSerializer.CreateDefault)
RaiseEvent GettingJsonSerializer(instance, args)
Return args.Value
End Function
''' <summary>
''' Writes the given instance to a string and return it.
''' </summary>
''' <param name="instance">The configuration instance that should be serialized.</param>
''' <returns>The content of the configuration instance as string.</returns>
Public Function WriteToString(instance As SimpleConfiguration) As String
Dim tw As New StringWriter
GetJsonSerializer(instance).Serialize(tw, instance)
Dim txt = tw.ToString
tw.Close()
Return txt
End Function
''' <summary>
''' Write the given instance to a given stream.
''' </summary>
''' <param name="instance">The configuration instance that should be serialized.</param>
''' <param name="stream">The stream where the content should be written to.</param>
Public Sub WriteToStream(instance As SimpleConfiguration, stream As Stream)
Dim sr As New StreamWriter(stream)
sr.Write(WriteToString(instance))
End Sub
''' <summary>
''' Writes the given instance to the given filePath as text file.
''' </summary>
''' <param name="instance">The configuration instance that should be serialized.</param>
''' <param name="filePath">The file path where the content should be written to. The file will be created or overwritten.</param>
Public Sub WriteToFile(instance As SimpleConfiguration, filePath As String)
Dim fs As New FileStream(filePath, FileMode.Create, FileAccess.ReadWrite)
WriteToStream(instance, fs)
fs.Close()
End Sub
''' <summary>
''' Reads a configuratin from the given string and returns an instance of it.
''' </summary>
''' <typeparam name="T">The type of the configuration class to instance.</typeparam>
''' <param name="content">The content of the configuration as string.</param>
''' <returns></returns>
Public Function ReadFromString(Of T As SimpleConfiguration)(content As String) As T
Dim sr As New StringReader(content)
Dim instance As T = GetJsonSerializer(Nothing).Deserialize(sr, GetType(T))
sr.Close()
Return instance
End Function
''' <summary>
''' Read a configuration from the given string and put them to the given instance.
''' </summary>
''' <param name="instance">The instance to populate with the configuration.</param>
''' <param name="content">The content of the configuration as string.</param>
Public Sub ReadFromString(instance As SimpleConfiguration, content As String)
Dim sr As New StringReader(content)
GetJsonSerializer(Nothing).Populate(sr, content)
sr.Close()
End Sub
''' <summary>
''' Reads a configuratin from the given string and returns an instance of it.
''' </summary>
''' <typeparam name="T">The type of the configuration class to instance.</typeparam>
''' <param name="stream">The stream with the content of the configuration.</param>
''' <returns></returns>
Public Function ReadFromStream(Of T As SimpleConfiguration)(stream As Stream) As T
Return ReadFromString(Of T)(GetContentOfStream(stream))
End Function
''' <summary>
''' Read a configuration from the given string and put them to the given instance.
''' </summary>
''' <param name="instance">The instance to populate with the configuration.</param>
''' <param name="stream">The stream with the content of the configuration.</param>
Public Sub ReadFromStream(instance As SimpleConfiguration, stream As Stream)
ReadFromString(instance, GetContentOfStream(stream))
End Sub
''' <summary>
''' Reads a configuratin from the given string and returns an instance of it.
''' </summary>
''' <typeparam name="T">The type of the configuration class to instance.</typeparam>
''' <param name="filePath">The path to the file with the content of the configuration.</param>
''' <returns></returns>
Public Function ReadFromFile(Of T As SimpleConfiguration)(filePath As String) As T
Return ReadFromString(Of T)(GetContentOfFile(filePath))
End Function
''' <summary>
''' Read a configuration from the given string and put them to the given instance.
''' </summary>
''' <param name="instance">The instance to populate with the configuration.</param>
''' <param name="filePath">The path to the file with the content of the configuration.</param>
Public Sub ReadFromFile(instance As SimpleConfiguration, filePath As String)
ReadFromString(instance, GetContentOfFile(filePath))
End Sub
Private Function GetContentOfStream(stream As Stream) As String
Dim sr As New StreamReader(stream)
Return sr.ReadToEnd
End Function
Private Function GetContentOfFile(filePath As String) As String
Dim fs As New FileStream(filePath, FileMode.Open, FileAccess.Read)
Dim content = GetContentOfStream(fs)
fs.Close()
Return content
End Function
End Module

View File

@@ -0,0 +1,16 @@
using Castle.Core.Logging;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace Pilz.Configuration;
public interface ISettings
{
IReadOnlyCollection<ISettingsNode> Childs { get; }
ILogger Logger { get; set; }
T Get<T>() where T : ISettingsNode, ISettingsIdentifier;
void Reset();
string Save(JsonSerializerSettings serializer);
bool Load(JsonSerializerSettings serializer, string raw);
}

View File

@@ -0,0 +1,8 @@
namespace Pilz.Configuration;
public interface ISettingsIdentifier
{
#if NET8_0_OR_GREATER
static abstract string Identifier { get; }
#endif
}

View File

@@ -0,0 +1,10 @@
namespace Pilz.Configuration;
public interface ISettingsManager
{
ISettings Instance { get; }
void Save();
void Load();
void Reset();
}

View File

@@ -1,6 +0,0 @@
Public Interface ISettingsManager
Property ConfigFilePath As String
Sub Save()
Sub Load()
Sub Reset()
End Interface

View File

@@ -0,0 +1,11 @@
using System;
namespace Pilz.Configuration;
public interface ISettingsNode
{
void Reset();
}
[Obsolete("Use ISettingsNode instead!")]
public interface IChildSettings : ISettingsNode;

View File

@@ -0,0 +1,6 @@
namespace Pilz.Configuration;
internal interface ISettingsValueOptionValueAccessor
{
public object ValueRaw { get; set; }
}

View File

@@ -1,13 +0,0 @@
'------------------------------------------------------------------------------
' <auto-generated>
' Dieser Code wurde von einem Tool generiert.
' Laufzeitversion:4.0.30319.42000
'
' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
' der Code erneut generiert wird.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MySubMain>false</MySubMain>
<SingleInstance>false</SingleInstance>
<ShutdownMode>0</ShutdownMode>
<EnableVisualStyles>true</EnableVisualStyles>
<AuthenticationMode>0</AuthenticationMode>
<ApplicationType>1</ApplicationType>
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
</MyApplicationData>

View File

@@ -1,63 +0,0 @@
'------------------------------------------------------------------------------
' <auto-generated>
' Dieser Code wurde von einem Tool generiert.
' Laufzeitversion:4.0.30319.42000
'
' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
' der Code erneut generiert wird.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Imports System
Namespace My.Resources
'Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
'-Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
'Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
'mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
'''<summary>
''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
'''</summary>
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0"), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
Friend Module Resources
Private resourceMan As Global.System.Resources.ResourceManager
Private resourceCulture As Global.System.Globalization.CultureInfo
'''<summary>
''' Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
Get
If Object.ReferenceEquals(resourceMan, Nothing) Then
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("Pilz.Configuration.Resources", GetType(Resources).Assembly)
resourceMan = temp
End If
Return resourceMan
End Get
End Property
'''<summary>
''' Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
''' Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend Property Culture() As Global.System.Globalization.CultureInfo
Get
Return resourceCulture
End Get
Set
resourceCulture = value
End Set
End Property
End Module
End Namespace

View File

@@ -1,117 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0;netstandard2.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<Nullable>disable</Nullable>
</PropertyGroup>
<PropertyGroup>
<Version>3.2.8</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Castle.Core" Version="5.2.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Pilz\Pilz.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,73 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<MyType>Windows</MyType>
<TargetFramework>netstandard2.0</TargetFramework>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<DocumentationFile>Pilz.Configuration.xml</DocumentationFile>
<DefineTrace>true</DefineTrace>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DefineDebug>true</DefineDebug>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DefineDebug>false</DefineDebug>
</PropertyGroup>
<PropertyGroup>
<OptionExplicit>On</OptionExplicit>
</PropertyGroup>
<PropertyGroup>
<OptionCompare>Binary</OptionCompare>
</PropertyGroup>
<PropertyGroup>
<OptionStrict>Off</OptionStrict>
</PropertyGroup>
<PropertyGroup>
<OptionInfer>On</OptionInfer>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
<ItemGroup>
<Import Include="Microsoft.VisualBasic" />
<Import Include="System" />
<Import Include="System.Collections" />
<Import Include="System.Collections.Generic" />
<Import Include="System.Data" />
<Import Include="System.Diagnostics" />
<Import Include="System.Linq" />
<Import Include="System.Xml.Linq" />
<Import Include="System.Threading.Tasks" />
</ItemGroup>
<ItemGroup>
<Compile Update="My Project\Application.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Application.myapp</DependentUpon>
</Compile>
<Compile Update="My Project\Resources.Designer.vb">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="My Project\Resources.resx">
<Generator>VbMyResourcesResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
<CustomToolNamespace>My.Resources</CustomToolNamespace>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="My Project\Application.myapp">
<Generator>MyApplicationCodeGenerator</Generator>
<LastGenOutput>Application.Designer.vb</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Pilz\Pilz.vbproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,143 @@
using Castle.Core.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
namespace Pilz.Configuration;
public class Settings : ISettings
{
protected readonly Dictionary<string, JObject> settingsJson = [];
protected readonly Dictionary<string, ISettingsNode> settings = [];
protected JsonSerializerSettings serializerSettings;
public virtual IReadOnlyCollection<ISettingsNode> Childs => settings.Values;
public virtual ILogger Logger { get; set; } = NullLogger.Instance;
public virtual T Get<T>() where T : ISettingsNode, ISettingsIdentifier
{
// Find existing one
if (settings.TryGetValue(GetIdentifier<T>(), out var valueExisting) && valueExisting is T settingsExisting)
return settingsExisting;
// Create new & reset
if (Activator.CreateInstance<T>() is T settingsNew)
settingsNew.Reset();
else
{
settingsNew = default;
Logger.WarnFormat("Not able to create new settings node instance {0}.", GetIdentifier<T>());
}
// Try deserialize
if (settingsJson.TryGetValue(GetIdentifier<T>(), out var valueRaw))
{
var serializer = JsonSerializer.CreateDefault(serializerSettings);
// Populate
if (settingsNew != null)
{
try
{
serializer.Populate(valueRaw.CreateReader(), settingsNew);
Logger.InfoFormat("Populated settings node {0}.", GetIdentifier<T>());
}
catch (Exception ex)
{
Logger.Error("Error populating settings node instance.", ex);
}
}
// Deserialize (fallback)
else if (valueRaw.ToObject<T>() is T settingsDeserialized)
{
try
{
settingsNew = settingsDeserialized;
Logger.WarnFormat("Deserialied settings node {0} via fallback variant.", GetIdentifier<T>());
}
catch (Exception ex)
{
Logger.Error("Error deserializing settings node instance.", ex);
}
}
}
// Remember
if (settingsNew != null)
settings[GetIdentifier<T>()] = settingsNew;
// Return
return settingsNew;
}
public void Reset()
{
foreach (var s in settings.Values)
s.Reset();
}
public virtual string Save(JsonSerializerSettings serializerSettings)
{
this.serializerSettings = serializerSettings;
var serializer = JsonSerializer.CreateDefault(serializerSettings);
foreach (var kvp in settings)
{
var raw = JObject.FromObject(kvp.Value, serializer);
settingsJson[kvp.Key] = raw;
}
var objList = new JObject();
foreach (var kvp in settingsJson)
objList.Add(kvp.Key, kvp.Value);
var objSettings = new JObject
{
{ "Settings", objList }
};
return objSettings.ToString(serializer.Formatting);
}
public virtual bool Load(JsonSerializerSettings serializerSettings, string raw)
{
this.serializerSettings = serializerSettings;
var objSettings = JObject.Parse(raw);
if (!objSettings.TryGetValue("Settings", out var tokenList) || tokenList is not JObject objList)
return false;
settingsJson.Clear();
settings.Clear();
foreach (var child in objList)
{
if (child.Value is not JObject value)
continue;
settingsJson.Add(child.Key, value);
}
return true;
}
protected virtual JToken Serialize(object o, JsonSerializer jsonSerializer)
{
using JTokenWriter jTokenWriter = new JTokenWriter();
jsonSerializer.Serialize(jTokenWriter, o, o.GetType());
return jTokenWriter.Token;
}
protected static string GetIdentifier<T>() where T : ISettingsIdentifier
{
#if NET8_0_OR_GREATER
return T.Identifier;
#else
return typeof(T).GetProperty("Identifier", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public).GetValue(null) as string;
#endif
}
}

View File

@@ -1,20 +0,0 @@
Imports Newtonsoft.Json
Public MustInherit Class SettingsBase
Public Sub New()
ResetValues()
End Sub
<JsonIgnore>
Friend _settingsManager As ISettingsManager
<JsonIgnore>
Public ReadOnly Property SettingsManager As ISettingsManager
Get
Return _settingsManager
End Get
End Property
Public MustOverride Sub ResetValues()
End Class

View File

@@ -0,0 +1,145 @@
using Newtonsoft.Json;
using System;
using System.IO;
using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
namespace Pilz.Configuration;
public class SettingsManager : ISettingsManager
{
public event EventHandler AutoSavingSettings;
public event EventHandler SavingSettings;
public event EventHandler SavedSettings;
public event EventHandler<ErrorEventArgs> OnSerializationError;
protected ISettings defaultInstance = null;
protected bool enableAutoSave = false;
protected bool addedHandler = false;
public string ConfigFilePath { get; set; }
public ISettings Instance
{
get
{
if (defaultInstance is null)
Load();
return defaultInstance;
}
}
public bool AutoSaveOnExit
{
get => enableAutoSave;
set
{
if (enableAutoSave != value)
{
enableAutoSave = value;
if (enableAutoSave)
{
if (!addedHandler)
AddAutoSaveHandler();
}
else
{
if (addedHandler)
RemoveAutoSaveHandler();
}
}
}
}
public SettingsManager()
{
}
public SettingsManager(string fileName, bool autoSaveOnExit) : this()
{
ConfigFilePath = fileName;
AutoSaveOnExit = autoSaveOnExit;
}
protected void AddAutoSaveHandler()
{
AppDomain.CurrentDomain.ProcessExit += AutoSaveSettingsOnExit;
addedHandler = true;
}
protected void RemoveAutoSaveHandler()
{
AppDomain.CurrentDomain.ProcessExit -= AutoSaveSettingsOnExit;
addedHandler = false;
}
private void AutoSaveSettingsOnExit(object sender, EventArgs e)
{
AutoSavingSettings?.Invoke(this, new EventArgs());
Save();
}
public void Save()
{
if (!string.IsNullOrEmpty(ConfigFilePath) && defaultInstance is not null)
SaveInternal();
}
public void Load()
{
if (!string.IsNullOrEmpty(ConfigFilePath) && File.Exists(ConfigFilePath))
LoadInternal();
else
CreateNewInstance();
}
public void Reset()
{
Instance.Reset();
}
protected virtual ISettings CreateInstance()
{
return new Settings();
}
protected virtual void CreateNewInstance()
{
defaultInstance = CreateInstance();
defaultInstance.Reset();
}
protected virtual void LoadInternal()
{
defaultInstance = CreateInstance();
defaultInstance.Load(CreateJsonSerializerSettings(), File.ReadAllText(ConfigFilePath));
}
protected virtual void SaveInternal()
{
SavingSettings?.Invoke(this, EventArgs.Empty);
File.WriteAllText(ConfigFilePath, defaultInstance.Save(CreateJsonSerializerSettings()));
SavedSettings?.Invoke(this, EventArgs.Empty);
}
public virtual JsonSerializerSettings CreateJsonSerializerSettings()
{
return new JsonSerializerSettings
{
Formatting = Formatting.Indented,
TypeNameHandling = TypeNameHandling.Auto,
Error = JsonSerializer_OnError,
};
}
protected virtual void JsonSerializer_OnError(object sender, ErrorEventArgs e)
{
const string errorResolvingType = "Error resolving type specified in JSON";
// Invoke event
OnSerializationError?.Invoke(sender, e);
// Handle ourself
if (!e.ErrorContext.Handled && e.ErrorContext.Error is JsonSerializationException serializationException && serializationException.Message.StartsWith(errorResolvingType))
e.ErrorContext.Handled = true;
}
}

View File

@@ -1,119 +0,0 @@
Imports System.IO
Imports System.Reflection
Imports Newtonsoft.Json.Linq
Public NotInheritable Class SettingsManager(Of T As SettingsBase)
Implements ISettingsManager
Public Event AutoSavingSettings As EventHandler
Public Event SavingSettings As EventHandler
Public Event SavedSettings As EventHandler
Private defaultInstance As T = Nothing
Private enableAutoSave As Boolean = False
Private addedHandler As Boolean = False
Public Property ConfigFilePath As String Implements ISettingsManager.ConfigFilePath
Public Property AutoSaveOnExit As Boolean
Get
Return enableAutoSave
End Get
Set
If enableAutoSave <> Value Then
enableAutoSave = Value
Select Case enableAutoSave
Case True
If Not addedHandler Then
AddAutoSaveHandler()
End If
Case False
If addedHandler Then
RemoveAutoSaveHandler()
End If
End Select
End If
End Set
End Property
Private Sub AddAutoSaveHandler()
AddHandler AppDomain.CurrentDomain.ProcessExit, AddressOf AutoSaveSettingsOnExit
addedHandler = True
End Sub
Private Sub RemoveAutoSaveHandler()
RemoveHandler AppDomain.CurrentDomain.ProcessExit, AddressOf AutoSaveSettingsOnExit
addedHandler = False
End Sub
Public ReadOnly Property Instance As T
Get
If defaultInstance Is Nothing Then
Load()
End If
Return defaultInstance
End Get
End Property
Public Sub New()
ConfigFilePath = ""
AutoSaveOnExit = False
End Sub
Public Sub New(fileName As String, autoSaveOnExit As Boolean)
ConfigFilePath = fileName
Me.AutoSaveOnExit = autoSaveOnExit
End Sub
Private Sub AutoSaveSettingsOnExit(sender As Object, e As EventArgs)
RaiseEvent AutoSavingSettings(Me, New EventArgs)
Save()
End Sub
Public Sub Save() Implements ISettingsManager.Save
If Not String.IsNullOrEmpty(ConfigFilePath) AndAlso defaultInstance IsNot Nothing Then
SavePrivate()
End If
End Sub
Public Sub Load() Implements ISettingsManager.Load
If Not String.IsNullOrEmpty(ConfigFilePath) AndAlso File.Exists(ConfigFilePath) Then
LoadPrivate()
Else
CreateNewInstance()
End If
If defaultInstance IsNot Nothing Then
defaultInstance._settingsManager = Me
End If
End Sub
Public Sub Reset() Implements ISettingsManager.Reset
Instance.ResetValues()
End Sub
Private Sub CreateNewInstance()
Dim ctor As ConstructorInfo = GetType(T).GetConstructor({})
If ctor IsNot Nothing Then
defaultInstance = ctor.Invoke({})
defaultInstance.ResetValues()
Else
Throw New Exception("The base type has no constructor with no parameters.")
End If
End Sub
Private Sub LoadPrivate()
defaultInstance = JObject.Parse(File.ReadAllText(ConfigFilePath)).ToObject(Of T)
End Sub
Private Sub SavePrivate()
RaiseEvent SavingSettings(Me, New EventArgs)
Dim obj As JObject = JObject.FromObject(defaultInstance)
If obj IsNot Nothing Then
File.WriteAllText(ConfigFilePath, obj.ToString)
End If
RaiseEvent SavedSettings(Me, New EventArgs)
End Sub
End Class

View File

@@ -0,0 +1,56 @@
using Newtonsoft.Json;
using System;
namespace Pilz.Configuration;
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(SettingsValueOptionJsonConverter))]
public class SettingsValueOption<T> : ISettingsValueOptionValueAccessor where T : struct
{
protected T? value;
public T DefaultValue { get; }
public virtual bool IsDefault => value == null;
public SettingsValueOption()
{
}
public SettingsValueOption(T value)
{
DefaultValue = value;
}
public virtual T Value
{
get => value ?? DefaultValue;
set => this.value = value;
}
public static implicit operator T(SettingsValueOption<T> option)
{
return option.Value;
}
object ISettingsValueOptionValueAccessor.ValueRaw
{
get => value;
set
{
if (value is not null)
this.value = Convert.ChangeType(value, typeof(T)) as T?;
else
this.value = null;
}
}
public virtual void Reset()
{
value = null;
}
public override string ToString()
{
return Value.ToString();
}
}

View File

@@ -0,0 +1,27 @@
using Newtonsoft.Json;
using System;
namespace Pilz.Configuration;
public class SettingsValueOptionJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (existingValue is ISettingsValueOptionValueAccessor option)
option.ValueRaw = reader.Value;
return existingValue;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is ISettingsValueOptionValueAccessor option)
writer.WriteValue(option.ValueRaw);
else
writer.WriteNull();
}
}

View File

@@ -0,0 +1,109 @@
using Newtonsoft.Json;
using Pilz.GeneralEventArgs;
using System.IO;
namespace Pilz.Configuration;
public class SimpleConfiguration
{
[JsonIgnore]
public readonly ConfigurationManagerList Managers = [];
public SimpleConfiguration()
{
Managers.GettingParentManager += Managers_GettingParentManager;
}
private void Managers_GettingParentManager(object sender, GetValueEventArgs<SimpleConfiguration> e)
{
if (ReferenceEquals(sender, Managers))
e.Value = this;
}
/// <summary>
/// Writes this instance to a string and return it.
/// </summary>
/// <returns>The content of the configuration instance as string.</returns>
public string WriteToString()
{
return ConfigurationSerializer.WriteToString(this);
}
/// <summary>
/// Write this instance to a given stream.
/// </summary>
/// <param name="stream">The stream where the content should be written to.</param>
public void WriteToStream(Stream stream)
{
ConfigurationSerializer.WriteToStream(this, stream);
}
/// <summary>
/// Writes this instance to the given filePath as text file.
/// </summary>
/// <param name="filePath">The file path where the content should be written to. The file will be created or overwritten.</param>
public void WriteToFile(string filePath)
{
ConfigurationSerializer.WriteToFile(this, filePath);
}
/// <summary>
/// Reads a configuratin from the given string and returns an instance of it.
/// </summary>
/// <typeparam name="T">The type of the configuration class to instance.</typeparam>
/// <param name="content">The content of the configuration as string.</param>
/// <returns></returns>
public static T ReadFromString<T>(string content) where T : SimpleConfiguration
{
return ConfigurationSerializer.ReadFromString<T>(content);
}
/// <summary>
/// Read a configuration from the given string and put them to this instance.
/// </summary>
/// <param name="content">The content of the configuration as string.</param>
public void ReadFromString(string content)
{
ConfigurationSerializer.ReadFromString(this, content);
}
/// <summary>
/// Reads a configuratin from the given string and returns an instance of it.
/// </summary>
/// <typeparam name="T">The type of the configuration class to instance.</typeparam>
/// <param name="stream">The stream with the content of the configuration.</param>
/// <returns></returns>
public static T ReadFromStream<T>(Stream stream) where T : SimpleConfiguration
{
return ConfigurationSerializer.ReadFromStream<T>(stream);
}
/// <summary>
/// Read a configuration from the given string and put them to this instance.
/// </summary>
/// <param name="stream">The stream with the content of the configuration.</param>
public void ReadFromStream(Stream stream)
{
ConfigurationSerializer.ReadFromStream(this, stream);
}
/// <summary>
/// Reads a configuratin from the given string and returns an instance of it.
/// </summary>
/// <typeparam name="T">The type of the configuration class to instance.</typeparam>
/// <param name="filePath">The path to the file with the content of the configuration.</param>
/// <returns></returns>
public static T ReadFromFile<T>(string filePath) where T : SimpleConfiguration
{
return ConfigurationSerializer.ReadFromFile<T>(filePath);
}
/// <summary>
/// Read a configuration from the given string and put them to this instance.
/// </summary>
/// <param name="filePath">The path to the file with the content of the configuration.</param>
public void ReadFromFile(string filePath)
{
ConfigurationSerializer.ReadFromFile(this, filePath);
}
}

View File

@@ -1,99 +0,0 @@
Imports System.IO
Imports Newtonsoft.Json
Imports Pilz.Configuration
Imports Pilz.GeneralEventArgs
Public Class SimpleConfiguration
<JsonIgnore>
Public ReadOnly Managers As New ConfigurationManagerList
Public Sub New()
AddHandler Managers.GettingParentManager, AddressOf Managers_GettingParentManager
End Sub
Private Sub Managers_GettingParentManager(sender As Object, e As GetValueEventArgs(Of SimpleConfiguration))
If sender Is Managers Then
e.Value = Me
End If
End Sub
''' <summary>
''' Writes this instance to a string and return it.
''' </summary>
''' <returns>The content of the configuration instance as string.</returns>
Public Function WriteToString() As String
Return ConfigurationSerializer.WriteToString(Me)
End Function
''' <summary>
''' Write this instance to a given stream.
''' </summary>
''' <param name="stream">The stream where the content should be written to.</param>
Public Sub WriteToStream(stream As Stream)
ConfigurationSerializer.WriteToStream(Me, stream)
End Sub
''' <summary>
''' Writes this instance to the given filePath as text file.
''' </summary>
''' <param name="filePath">The file path where the content should be written to. The file will be created or overwritten.</param>
Public Sub WriteToFile(filePath As String)
ConfigurationSerializer.WriteToFile(Me, filePath)
End Sub
''' <summary>
''' Reads a configuratin from the given string and returns an instance of it.
''' </summary>
''' <typeparam name="T">The type of the configuration class to instance.</typeparam>
''' <param name="content">The content of the configuration as string.</param>
''' <returns></returns>
Public Shared Function ReadFromString(Of T As SimpleConfiguration)(content As String) As T
Return ConfigurationSerializer.ReadFromString(Of T)(content)
End Function
''' <summary>
''' Read a configuration from the given string and put them to this instance.
''' </summary>
''' <param name="content">The content of the configuration as string.</param>
Public Sub ReadFromString(content As String)
ConfigurationSerializer.ReadFromString(Me, content)
End Sub
''' <summary>
''' Reads a configuratin from the given string and returns an instance of it.
''' </summary>
''' <typeparam name="T">The type of the configuration class to instance.</typeparam>
''' <param name="stream">The stream with the content of the configuration.</param>
''' <returns></returns>
Public Shared Function ReadFromStream(Of T As SimpleConfiguration)(stream As Stream) As T
Return ConfigurationSerializer.ReadFromStream(Of T)(stream)
End Function
''' <summary>
''' Read a configuration from the given string and put them to this instance.
''' </summary>
''' <param name="stream">The stream with the content of the configuration.</param>
Public Sub ReadFromStream(stream As Stream)
ConfigurationSerializer.ReadFromStream(Me, stream)
End Sub
''' <summary>
''' Reads a configuratin from the given string and returns an instance of it.
''' </summary>
''' <typeparam name="T">The type of the configuration class to instance.</typeparam>
''' <param name="filePath">The path to the file with the content of the configuration.</param>
''' <returns></returns>
Public Shared Function ReadFromFile(Of T As SimpleConfiguration)(filePath As String) As T
Return ConfigurationSerializer.ReadFromFile(Of T)(filePath)
End Function
''' <summary>
''' Read a configuration from the given string and put them to this instance.
''' </summary>
''' <param name="filePath">The path to the file with the content of the configuration.</param>
Public Sub ReadFromFile(filePath As String)
ConfigurationSerializer.ReadFromFile(Me, filePath)
End Sub
End Class

View File

@@ -0,0 +1,51 @@
using System;
using System.ComponentModel;
using System.Management;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
namespace Pilz.Cryptography;
[EditorBrowsable(EditorBrowsableState.Never)]
public static class Helpers
{
private static string clientSecret = null;
public static string CalculateClientSecret()
{
// Try getting serial number of C drive
if (clientSecret == null && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
ManagementObjectSearcher searcher = new("SELECT * FROM Win32_PhysicalMedia");
string sn = null;
foreach (var entry in searcher.Get())
{
if (entry is ManagementObject wmi_HD && string.IsNullOrEmpty(sn) && wmi_HD["SerialNumber"] != null)
sn = wmi_HD["SerialNumber"].ToString()?.Trim();
}
clientSecret = sn;
}
// Fallback to Mashine name
clientSecret ??= Environment.MachineName;
return clientSecret;
}
public static string GenerateUniquieID<T>(string var)
{
var sn = CalculateClientSecret();
var dateTime = DateTime.UtcNow.ToString("yyyyMMddHHmmssfffffff");
var type = typeof(T).ToString();
var together = sn + dateTime + type + var;
#if NET5_0_OR_GREATER
var hash = BitConverter.ToString(MD5.HashData(Encoding.Default.GetBytes(together))).Replace("-", string.Empty);
#else
var hash = BitConverter.ToString(MD5.Create().ComputeHash(Encoding.Default.GetBytes(together))).Replace("-", string.Empty);
#endif
return hash;
}
}

View File

@@ -1,14 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Cryptography;
namespace Pilz.Cryptography
public interface ICrypter
{
public interface ICrypter
{
string Encrypt(string plainValue);
string Decrypt(string encryptedValue);
}
string Encrypt(string plainValue);
string Decrypt(string encryptedValue);
}

View File

@@ -1,16 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
namespace Pilz.Cryptography
namespace Pilz.Cryptography;
[JsonConverter(typeof(Json.Converters.UniquieIDStringJsonConverter))]
public interface IUniquieID
{
public interface IUniquieID
{
bool HasID { get; }
string ID { get; }
bool HasID { get; }
string ID { get; }
void GenerateIfNull();
void Generate();
bool Equals(object obj);
}
void GenerateIfNull();
void Generate();
bool Equals(object obj);
}

View File

@@ -1,14 +1,9 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Pilz.Cryptography;
namespace Pilz.Cryptography
/// <summary>
/// Can be implemented on objects that provides an UniquieID.
/// </summary>
public interface IUniquieIDHost
{
/// <summary>
/// Can be implemented on objects that provides an UniquieID.
/// </summary>
public interface IUniquieIDHost
{
UniquieID ID { get; }
}
UniquieID ID { get; }
}

View File

@@ -1,38 +1,35 @@
using Newtonsoft.Json;
using Pilz.Cryptography;
using System;
using System.Collections.Generic;
using System.Text;
namespace Pilz.Json.Converters
namespace Pilz.Json.Converters;
public class UniquieIDStringJsonConverter : JsonConverter
{
public class UniquieIDStringJsonConverter : JsonConverter
public static bool EnableCheckForDepricatedTypes { get; set; } = true;
public override bool CanConvert(Type objectType)
{
public static bool EnableCheckForDepricatedTypes { get; set; } = true;
return typeof(IUniquieID).IsAssignableFrom(objectType);
}
public override bool CanConvert(Type objectType)
{
return typeof(UniquieID).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var idString = serializer.Deserialize<string>(reader);
UniquieID id;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var idString = serializer.Deserialize<string>(reader);
UniquieID id;
if (existingValue is UniquieID existingID && (!EnableCheckForDepricatedTypes || existingID.GetType() == typeof(UniquieID)))
id = existingID;
else
id = new UniquieID();
if (existingValue is UniquieID existingID && (!EnableCheckForDepricatedTypes || existingID.GetType() == typeof(UniquieID)))
id = existingID;
else
id = new UniquieID();
id.ID = idString;
id.ID = idString;
return id;
}
return id;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, ((UniquieID)value).ID);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, ((UniquieID)value).ID);
}
}

View File

@@ -1,17 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyTitle>Pilz.Cryptography</AssemblyTitle>
<Product>Pilz.Cryptography</Product>
<Copyright>Copyright © 2020</Copyright>
<TargetFrameworks>net8.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup>
<Version>2.1.3</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Management" Version="4.7.0" />
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="System.Management" Version="9.0.9" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices;
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von

View File

@@ -1,78 +1,72 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Cryptography
namespace Pilz.Cryptography;
[JsonConverter(typeof(Json.Converters.SecureStringJsonConverter))]
public class SecureString
{
[JsonConverter(typeof(Json.Converters.SecureStringJsonConverter))]
public class SecureString
public static ICrypter DefaultCrypter { get; set; }
public ICrypter Crypter { get; set; }
public string EncryptedValue { get; set; }
public string Value
{
public static ICrypter DefaultCrypter { get; set; }
public ICrypter Crypter { get; set; }
public string EncryptedValue { get; set; }
public string Value
{
get => GetCrypter()?.Decrypt(EncryptedValue);
set => EncryptedValue = GetCrypter().Encrypt(value);
}
[JsonConstructor]
private SecureString(JsonConstructorAttribute dummyAttribute)
{
}
public SecureString() :
this(string.Empty, true)
{
}
public SecureString(string value, bool isEncrypted) :
this(value, isEncrypted, null)
{
}
public SecureString(string value, bool isEncrypted, ICrypter crypter)
{
Crypter = crypter;
if (isEncrypted)
EncryptedValue = value;
else
Value = value;
}
private ICrypter GetCrypter()
{
if (Crypter == null)
{
if (DefaultCrypter == null)
DefaultCrypter = new SimpleStringCrypter(string.Empty);
Crypter = DefaultCrypter;
}
return Crypter;
}
public override string ToString() => Value;
public override bool Equals(object obj)
{
var @string = obj as SecureString;
return @string != null &&
EncryptedValue == @string.EncryptedValue;
}
public override int GetHashCode()
{
return -2303024 + EqualityComparer<string>.Default.GetHashCode(EncryptedValue);
}
public static implicit operator string(SecureString value) => value?.Value;
public static implicit operator SecureString(string value) => new SecureString(value, false);
public static bool operator ==(SecureString left, SecureString right) => left?.EncryptedValue == right?.EncryptedValue;
public static bool operator !=(SecureString left, SecureString right) => left?.EncryptedValue != right?.EncryptedValue;
get => GetCrypter()?.Decrypt(EncryptedValue);
set => EncryptedValue = GetCrypter().Encrypt(value);
}
[JsonConstructor]
private SecureString(JsonConstructorAttribute dummyAttribute)
{
}
public SecureString() :
this(string.Empty, true)
{
}
public SecureString(string value, bool isEncrypted) :
this(value, isEncrypted, null)
{
}
public SecureString(string value, bool isEncrypted, ICrypter crypter)
{
Crypter = crypter;
if (isEncrypted)
EncryptedValue = value;
else
Value = value;
}
private ICrypter GetCrypter()
{
if (Crypter == null)
{
DefaultCrypter ??= new SimpleStringCrypter(string.Empty);
Crypter = DefaultCrypter;
}
return Crypter;
}
public override string ToString() => Value;
public override bool Equals(object obj)
{
var @string = obj as SecureString;
return @string != null &&
EncryptedValue == @string.EncryptedValue;
}
public override int GetHashCode()
{
return -2303024 + EqualityComparer<string>.Default.GetHashCode(EncryptedValue);
}
public static implicit operator string(SecureString value) => value?.Value;
public static implicit operator SecureString(string value) => new(value, false);
public static bool operator ==(SecureString left, SecureString right) => left?.EncryptedValue == right?.EncryptedValue;
public static bool operator !=(SecureString left, SecureString right) => left?.EncryptedValue != right?.EncryptedValue;
}

View File

@@ -1,41 +1,34 @@
using Newtonsoft.Json;
using Pilz.Cryptography;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Json.Converters
namespace Pilz.Json.Converters;
public class SecureStringJsonConverter : JsonConverter
{
public class SecureStringJsonConverter : JsonConverter
public override bool CanConvert(Type objectType)
{
public override bool CanConvert(Type objectType)
return typeof(SecureString).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var idString = serializer.Deserialize<string>(reader);
SecureString id;
if (existingValue is SecureString)
{
return typeof(SecureString).IsAssignableFrom(objectType);
id = (SecureString)existingValue;
id.EncryptedValue = idString;
}
else
id = new SecureString(idString, true);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var idString = serializer.Deserialize<string>(reader);
SecureString id;
return id;
}
if (existingValue is SecureString)
{
id = (SecureString)existingValue;
id.EncryptedValue = idString;
}
else
id = new SecureString(idString, true);
return id;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, ((SecureString)value).EncryptedValue);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, ((SecureString)value).EncryptedValue);
}
}

View File

@@ -1,80 +1,77 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.IO;
namespace Pilz.Cryptography
using System.Security.Cryptography;
using System.Text;
namespace Pilz.Cryptography;
public class SimpleStringCrypter : ICrypter
{
public class SimpleStringCrypter : ICrypter
private readonly TripleDES TripleDes;
public Encoding TextEncoding { get; private set; } = Encoding.Default;
public SimpleStringCrypter() : this(string.Empty)
{
private TripleDESCryptoServiceProvider TripleDes;
public Encoding TextEncoding { get; private set; } = Encoding.Default;
}
public SimpleStringCrypter() : this(string.Empty)
{
}
public SimpleStringCrypter(string key) : this(key, Encoding.Default)
{
}
public SimpleStringCrypter(string key) : this(key, Encoding.Default)
{
}
public SimpleStringCrypter(string key, Encoding textEncoding)
{
TextEncoding = textEncoding;
TripleDes = TripleDES.Create();
TripleDes.Key = TruncateHash(key, TripleDes.KeySize / 8);
TripleDes.IV = TruncateHash(string.Empty, TripleDes.BlockSize / 8);
}
public SimpleStringCrypter(string key, Encoding textEncoding)
{
TextEncoding = textEncoding;
TripleDes = new TripleDESCryptoServiceProvider();
TripleDes.Key = TruncateHash(key,TripleDes.KeySize / 8);
TripleDes.IV = TruncateHash(string.Empty, TripleDes.BlockSize / 8);
}
private byte[] TruncateHash(string key, int length)
{
SHA1 sha1CryptoServiceProvider = SHA1.Create();
var bytes = TextEncoding.GetBytes(key);
var array = sha1CryptoServiceProvider.ComputeHash(bytes);
private byte[] TruncateHash(string key, int length)
{
SHA1CryptoServiceProvider sha1CryptoServiceProvider = new SHA1CryptoServiceProvider();
byte[] bytes = TextEncoding.GetBytes(key);
byte[] array = sha1CryptoServiceProvider.ComputeHash(bytes);
var output = new byte[length];
var lowerLength = Math.Min(array.Length, output.Length);
var output = new byte[length];
var lowerLength = Math.Min(array.Length, output.Length);
for (int i = 0; i < lowerLength; i++)
output[i] = array[i];
for (int i = 0; i < lowerLength; i++)
output[i] = array[i];
return output;
}
return output;
}
private string EncryptData(string plaintext)
{
var bytes = TextEncoding.GetBytes(plaintext);
using var memoryStream = new MemoryStream();
using var cryptoStream = new CryptoStream(memoryStream, TripleDes.CreateEncryptor(), CryptoStreamMode.Write);
cryptoStream.Write(bytes, 0, bytes.Length);
cryptoStream.FlushFinalBlock();
return Convert.ToBase64String(memoryStream.ToArray());
}
private string EncryptData(string plaintext)
{
byte[] bytes = TextEncoding.GetBytes(plaintext);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, TripleDes.CreateEncryptor(), CryptoStreamMode.Write);
cryptoStream.Write(bytes, 0, bytes.Length);
cryptoStream.FlushFinalBlock();
return Convert.ToBase64String(memoryStream.ToArray());
}
private string DecryptData(string encryptedtext)
{
var array = Convert.FromBase64String(encryptedtext);
using var memoryStream = new MemoryStream();
using var cryptoStream = new CryptoStream(memoryStream, TripleDes.CreateDecryptor(), CryptoStreamMode.Write);
cryptoStream.Write(array, 0, array.Length);
cryptoStream.FlushFinalBlock();
return TextEncoding.GetString(memoryStream.ToArray());
}
private string DecryptData(string encryptedtext)
{
byte[] array = Convert.FromBase64String(encryptedtext);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, TripleDes.CreateDecryptor(), CryptoStreamMode.Write);
cryptoStream.Write(array, 0, array.Length);
cryptoStream.FlushFinalBlock();
return TextEncoding.GetString(memoryStream.ToArray());
}
public string Encrypt(string plainValue)
{
return EncryptData(plainValue ?? string.Empty);
}
public string Encrypt(string plainValue)
{
return EncryptData(plainValue ?? string.Empty);
}
public string Decrypt(string encryptedValue)
{
if (string.IsNullOrEmpty(encryptedValue))
return string.Empty;
else
return DecryptData(encryptedValue);
}
public string Decrypt(string encryptedValue)
{
if (string.IsNullOrEmpty(encryptedValue))
return string.Empty;
else
return DecryptData(encryptedValue);
}
}

View File

@@ -1,172 +1,140 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Management;
using System.Security.Cryptography;
using System.Text;
namespace Pilz.Cryptography
namespace Pilz.Cryptography;
[JsonConverter(typeof(Json.Converters.UniquieIDStringJsonConverter))]
public class UniquieID : IUniquieID
{
[JsonConverter(typeof(Json.Converters.UniquieIDStringJsonConverter))]
public class UniquieID : IUniquieID
protected static ulong currentSimpleID = 0;
[JsonProperty(nameof(ID))]
protected string _iD;
[JsonIgnore]
public virtual bool SimpleMode { get; }
[JsonIgnore]
public virtual bool GenerateOnGet { get; }
[JsonIgnore]
public virtual bool HasID => !string.IsNullOrEmpty(_iD);
[JsonIgnore]
public virtual string ID
{
protected static ulong currentSimpleID = 0;
[JsonProperty(nameof(ID))]
protected string _iD;
[JsonIgnore]
public virtual bool SimpleMode { get; }
[JsonIgnore]
public virtual bool GenerateOnGet { get; }
[JsonIgnore]
public virtual bool HasID => !string.IsNullOrEmpty(_iD);
[JsonIgnore]
public virtual string ID
get
{
get
{
if (GenerateOnGet)
GenerateIfNull();
return _iD;
}
internal set
=> _iD = value;
}
public UniquieID() : this(UniquieIDGenerationMode.None)
{
}
public UniquieID(UniquieIDGenerationMode mode) : this(mode, false)
{
}
public UniquieID(UniquieIDGenerationMode mode, bool simpleMode)
{
SimpleMode = simpleMode;
if (mode == UniquieIDGenerationMode.GenerateOnInit)
if (GenerateOnGet)
GenerateIfNull();
else if (mode == UniquieIDGenerationMode.GenerateOnGet)
GenerateOnGet = true;
return _iD;
}
[Obsolete]
public UniquieID(bool autoGenerate) : this(autoGenerate ? UniquieIDGenerationMode.GenerateOnInit : UniquieIDGenerationMode.None)
{
}
public virtual void Generate()
{
if (SimpleMode)
ID = GenerateSimple();
else
ID = GenerateDefault();
}
protected virtual string GenerateSimple()
{
return new Random().Next().ToString() + DateTime.Now.ToString("yyyyMMddHHmmssfffffff") + currentSimpleID++.ToString();
}
protected virtual string GenerateDefault()
{
return GenerateUniquieID<UniquieID>(currentSimpleID++.ToString());
}
public virtual void GenerateIfNull()
{
if (!HasID) Generate();
}
public override string ToString()
{
return ID;
}
public override int GetHashCode()
{
return -1430039477 + EqualityComparer<string>.Default.GetHashCode(_iD);
}
public override bool Equals(object obj)
{
if (obj is UniquieID iD)
{
if (ReferenceEquals(obj, iD))
return true;
else
{
var leftHasID = iD.HasID;
var rightHasID = HasID;
if (!leftHasID && iD.GenerateOnGet)
{
iD.Generate();
leftHasID = iD.HasID;
}
if (!rightHasID && GenerateOnGet)
{
Generate();
rightHasID = HasID;
}
if (leftHasID && rightHasID)
return _iD.Equals(iD._iD);
}
}
return base.Equals(obj);
}
#region Statics for Generation
protected static string GenerateUniquieID<T>(string var)
{
var sn = TryGetSerialNumberOfFirstHardDrive();
var dateTime = DateTime.UtcNow.ToString("yyyyMMddHHmmssfffffff");
var type = typeof(T).ToString();
var together = sn + dateTime + type + var;
var md5 = MD5.Create();
var hash = BitConverter.ToString(md5.ComputeHash(Encoding.Default.GetBytes(together))).Replace("-", string.Empty);
md5.Dispose();
return hash;
}
private static string Win32_PhysicalMedia_SerialNumber = null;
private static string TryGetSerialNumberOfFirstHardDrive()
{
if (Win32_PhysicalMedia_SerialNumber == null)
{
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
var sn = string.Empty;
foreach (ManagementObject wmi_HD in searcher.Get())
{
if (string.IsNullOrEmpty(sn) && wmi_HD["SerialNumber"] != null)
sn = wmi_HD["SerialNumber"].ToString().Trim();
}
Win32_PhysicalMedia_SerialNumber = sn;
}
return Win32_PhysicalMedia_SerialNumber;
}
#endregion
public static implicit operator string(UniquieID id) => id.ID;
public static implicit operator UniquieID(string id) => new UniquieID() { ID = id };
public static implicit operator UniquieID(int id) => new UniquieID() { ID = Convert.ToString(id) };
public static bool operator ==(UniquieID left, UniquieID right) => left.ID.Equals(right.ID);
public static bool operator !=(UniquieID left, UniquieID right) => !left.ID.Equals(right.ID);
internal set
=> _iD = value;
}
public UniquieID() : this(UniquieIDGenerationMode.None)
{
}
public UniquieID(UniquieIDGenerationMode mode) : this(mode, false)
{
}
public UniquieID(UniquieIDGenerationMode mode, bool simpleMode)
{
SimpleMode = simpleMode;
if (mode == UniquieIDGenerationMode.GenerateOnInit)
GenerateIfNull();
else if (mode == UniquieIDGenerationMode.GenerateOnGet)
GenerateOnGet = true;
}
[Obsolete("Use the enum 'UniquieIDGenerationMode' instead of a simple boolean.")]
public UniquieID(bool autoGenerate) : this(autoGenerate ? UniquieIDGenerationMode.GenerateOnInit : UniquieIDGenerationMode.None)
{
}
public virtual void Generate()
{
if (SimpleMode)
ID = GenerateSimple();
else
ID = GenerateDefault();
}
protected virtual string GenerateSimple()
{
return new Random().Next().ToString() + DateTime.Now.ToString("yyyyMMddHHmmssfffffff") + currentSimpleID++.ToString();
}
protected virtual string GenerateDefault()
{
return Helpers.GenerateUniquieID<UniquieID>(currentSimpleID++.ToString());
}
public virtual void GenerateIfNull()
{
if (!HasID) Generate();
}
public override string ToString()
{
return ID;
}
public override int GetHashCode()
{
return -1430039477 + EqualityComparer<string>.Default.GetHashCode(_iD);
}
public override bool Equals(object obj)
{
if (obj is UniquieID iD)
{
if (ReferenceEquals(obj, iD))
return true;
else
{
var leftHasID = iD.HasID;
var rightHasID = HasID;
if (!leftHasID && iD.GenerateOnGet)
{
iD.Generate();
leftHasID = iD.HasID;
}
if (!rightHasID && GenerateOnGet)
{
Generate();
rightHasID = HasID;
}
if (leftHasID && rightHasID)
return _iD.Equals(iD._iD);
}
}
return base.Equals(obj);
}
public static UniquieID GenerateNew()
{
return new UniquieID(UniquieIDGenerationMode.GenerateOnInit);
}
public static UniquieID GenerateNew(bool simpleMode)
{
return new UniquieID(UniquieIDGenerationMode.GenerateOnInit, simpleMode);
}
public static implicit operator string(UniquieID id) => id.ID;
public static implicit operator UniquieID(string id) => new() { ID = id };
public static implicit operator UniquieID(int id) => new() { ID = Convert.ToString(id) };
public static bool operator ==(UniquieID left, UniquieID right) => left.ID.Equals(right.ID);
public static bool operator !=(UniquieID left, UniquieID right) => !left.ID.Equals(right.ID);
}

View File

@@ -1,13 +1,8 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Pilz.Cryptography;
namespace Pilz.Cryptography
public enum UniquieIDGenerationMode
{
public enum UniquieIDGenerationMode
{
None,
GenerateOnGet,
GenerateOnInit
}
None,
GenerateOnGet,
GenerateOnInit
}

View File

@@ -1,5 +1,6 @@
Imports System.Windows.Forms
Imports OpenTK
Imports OpenTK.Mathematics
Namespace CameraN
@@ -119,7 +120,7 @@ Namespace CameraN
Private Sub OrientateCam(ang As Single, ang2 As Single)
Dim CamLX As Single = CSng(Math.Sin(ang)) * CSng(Math.Sin(-ang2))
Dim CamLY As Single = CSng(Math.Cos(ang2))
Dim CamLY As Single = Math.Cos(ang2)
Dim CamLZ As Single = CSng(-Math.Cos(ang)) * CSng(Math.Sin(-ang2))
myLookat.X = pos.X + (-CamLX) * 100.0F
@@ -130,11 +131,11 @@ Namespace CameraN
Private Sub OffsetCam(xAmt As Integer, yAmt As Integer, zAmt As Integer)
Dim pitch_Renamed As Double = CamAngleY - (Math.PI / 2)
Dim CamLX As Single = CSng(Math.Sin(CamAngleX)) * CSng(Math.Cos(-pitch_Renamed))
Dim CamLY As Single = CSng(Math.Sin(pitch_Renamed))
Dim CamLY As Single = Math.Sin(pitch_Renamed)
Dim CamLZ As Single = CSng(-Math.Cos(CamAngleX)) * CSng(Math.Cos(-pitch_Renamed))
pos.X = pos.X + xAmt * (CamLX) * CamSpeedMultiplier
pos.Y = pos.Y + yAmt * (CamLY) * CamSpeedMultiplier
pos.Z = pos.Z + zAmt * (CamLZ) * CamSpeedMultiplier
pos.X += xAmt * (CamLX) * CamSpeedMultiplier
pos.Y += yAmt * (CamLY) * CamSpeedMultiplier
pos.Z += zAmt * (CamLZ) * CamSpeedMultiplier
End Sub
Public Sub Move(y As Single, ByRef camMtx As Matrix4)
@@ -153,7 +154,7 @@ Namespace CameraN
Dim x_diff As Single = myLookat.X - pos.X
Dim y_diff As Single = myLookat.Y - pos.Y
Dim z_diff As Single = myLookat.Z - pos.Z
Dim dist As Single = CSng(Math.Sqrt(x_diff * x_diff + y_diff * y_diff + z_diff * z_diff))
Dim dist As Single = Math.Sqrt(x_diff * x_diff + y_diff * y_diff + z_diff * z_diff)
If z_diff = 0 Then
z_diff = 0.001F
End If
@@ -209,32 +210,32 @@ Namespace CameraN
currentLookDirection = dir
Select Case currentLookDirection
Case LookDirection.Top
pos = lookPositions(CInt(LookDirection.Top))
pos = lookPositions(LookDirection.Top)
myLookat = New Vector3(pos.X, -25000, pos.Z - 1)
UpdateMatrix(cameraMatrix)
SetRotationFromLookAt()
Case LookDirection.Bottom
pos = lookPositions(CInt(LookDirection.Bottom))
pos = lookPositions(LookDirection.Bottom)
myLookat = New Vector3(pos.X, 25000, pos.Z + 1)
UpdateMatrix(cameraMatrix)
SetRotationFromLookAt()
Case LookDirection.Left
pos = lookPositions(CInt(LookDirection.Left))
pos = lookPositions(LookDirection.Left)
myLookat = New Vector3(25000, pos.Y, pos.Z)
UpdateMatrix(cameraMatrix)
SetRotationFromLookAt()
Case LookDirection.Right
pos = lookPositions(CInt(LookDirection.Right))
pos = lookPositions(LookDirection.Right)
myLookat = New Vector3(-25000, pos.Y, pos.Z)
UpdateMatrix(cameraMatrix)
SetRotationFromLookAt()
Case LookDirection.Front
pos = lookPositions(CInt(LookDirection.Front))
pos = lookPositions(LookDirection.Front)
myLookat = New Vector3(pos.X, pos.Y, -25000)
UpdateMatrix(cameraMatrix)
SetRotationFromLookAt()
Case LookDirection.Back
pos = lookPositions(CInt(LookDirection.Back))
pos = lookPositions(LookDirection.Back)
myLookat = New Vector3(pos.X, pos.Y, 25000)
UpdateMatrix(cameraMatrix)
SetRotationFromLookAt()
@@ -312,9 +313,9 @@ Namespace CameraN
Dim pitch_Renamed As Double = CamAngleY - (Math.PI / 2)
Dim yaw_Renamed As Double = CamAngleX - (Math.PI / 2)
Dim CamLX As Single = CSng(Math.Sin(yaw_Renamed))
Dim CamLY As Single = CSng(Math.Cos(pitch_Renamed))
Dim CamLZ As Single = CSng(-Math.Cos(yaw_Renamed))
Dim CamLX As Single = Math.Sin(yaw_Renamed)
Dim CamLY As Single = Math.Cos(pitch_Renamed)
Dim CamLZ As Single = -Math.Cos(yaw_Renamed)
Dim m As Single = 8.0F
@@ -323,36 +324,36 @@ Namespace CameraN
pos.X = orgPos.X - ((MousePosX * CamSpeedMultiplier) * (CamLX) * m) - ((MousePosY * CamSpeedMultiplier) * (CamLZ) * m)
pos.Z = orgPos.Z - ((MousePosX * CamSpeedMultiplier) * (CamLZ) * m) - ((MousePosY * CamSpeedMultiplier) * (CamLX) * m)
cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X, pos.Y - 1000, pos.Z - 1, 0, 1, 0)
lookPositions(CInt(currentLookDirection)) = pos
lookPositions(currentLookDirection) = pos
Case LookDirection.Bottom
pos.X = orgPos.X - ((MousePosX * CamSpeedMultiplier) * (CamLX) * m) + ((MousePosY * CamSpeedMultiplier) * (CamLZ) * m)
pos.Z = orgPos.Z - ((MousePosX * CamSpeedMultiplier) * (CamLZ) * m) + ((MousePosY * CamSpeedMultiplier) * (CamLX) * m)
cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X, pos.Y + 1000, pos.Z + 1, 0, 1, 0)
lookPositions(CInt(currentLookDirection)) = pos
lookPositions(currentLookDirection) = pos
Case LookDirection.Left
pos.X = orgPos.X - ((MousePosX * CamSpeedMultiplier) * (CamLX) * m)
pos.Y = orgPos.Y - ((MousePosY * CamSpeedMultiplier) * (-1.0F) * m)
pos.Z = orgPos.Z - ((MousePosX * CamSpeedMultiplier) * (CamLZ) * m)
cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X + 12500, pos.Y, pos.Z, 0, 1, 0)
lookPositions(CInt(currentLookDirection)) = pos
lookPositions(currentLookDirection) = pos
Case LookDirection.Right
pos.X = orgPos.X - ((MousePosX * CamSpeedMultiplier) * (CamLX) * m)
pos.Y = orgPos.Y - ((MousePosY * CamSpeedMultiplier) * (-1.0F) * m)
pos.Z = orgPos.Z - ((MousePosX * CamSpeedMultiplier) * (CamLZ) * m)
cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X - 12500, pos.Y, pos.Z, 0, 1, 0)
lookPositions(CInt(currentLookDirection)) = pos
lookPositions(currentLookDirection) = pos
Case LookDirection.Front
pos.X = orgPos.X - ((MousePosX * CamSpeedMultiplier) * (CamLX) * m)
pos.Y = orgPos.Y - ((MousePosY * CamSpeedMultiplier) * (-1.0F) * m)
pos.Z = orgPos.Z - ((MousePosX * CamSpeedMultiplier) * (CamLZ) * m)
cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X, pos.Y, pos.Z - 12500, 0, 1, 0)
lookPositions(CInt(currentLookDirection)) = pos
lookPositions(currentLookDirection) = pos
Case LookDirection.Back
pos.X = orgPos.X - ((MousePosX * CamSpeedMultiplier) * (CamLX) * m)
pos.Y = orgPos.Y - ((MousePosY * CamSpeedMultiplier) * (-1.0F) * m)
pos.Z = orgPos.Z - ((MousePosX * CamSpeedMultiplier) * (CamLZ) * m)
cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X, pos.Y, pos.Z + 12500, 0, 1, 0)
lookPositions(CInt(currentLookDirection)) = pos
lookPositions(currentLookDirection) = pos
End Select
RaisePerspectiveChanged()
@@ -371,7 +372,7 @@ Namespace CameraN
End If
Dim MousePosX As Integer = mouseX - lastMouseX
Dim MousePosY As Integer = mouseY - lastMouseY
CamAngleX = CamAngleX + (0.01F * MousePosX)
CamAngleX += (0.01F * MousePosX)
' This next part isn't neccessary, but it keeps the Yaw rotation value within [0, 2*pi] which makes debugging simpler.
If CamAngleX > TAU Then
CamAngleX -= TAU
@@ -418,9 +419,9 @@ Namespace CameraN
'Console.WriteLine(MousePosX+","+ MousePosY);
Dim pitch_Renamed As Double = CamAngleY - (Math.PI / 2)
Dim yaw_Renamed As Double = CamAngleX - (Math.PI / 2)
Dim CamLX As Single = CSng(Math.Sin(yaw_Renamed))
Dim CamLX As Single = Math.Sin(yaw_Renamed)
' float CamLY = (float)Math.Cos(pitch);
Dim CamLZ As Single = CSng(-Math.Cos(yaw_Renamed))
Dim CamLZ As Single = -Math.Cos(yaw_Renamed)
pos.X += ((horz_amount * CamSpeedMultiplier) * (CamLX))
pos.Y += ((vert_amount * CamSpeedMultiplier) * (-1.0F))
pos.Z += ((horz_amount * CamSpeedMultiplier) * (CamLZ))

View File

@@ -22,7 +22,7 @@ Namespace My.Resources
'''<summary>
''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
'''</summary>
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0"), _
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0"), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _

View File

@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<MyType>Windows</MyType>
<TargetFramework>net48</TargetFramework>
<TargetFrameworks>net8.0-windows</TargetFrameworks>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<DocumentationFile>Pilz.Drawing.Drawing3D.OpenGLFactory.xml</DocumentationFile>
<DefineTrace>true</DefineTrace>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DefineDebug>true</DefineDebug>
@@ -24,18 +25,16 @@
<PropertyGroup>
<OptionInfer>On</OptionInfer>
</PropertyGroup>
<PropertyGroup>
<Version>2.0.4</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="OpenTK.Input" Version="4.9.4" />
<PackageReference Include="OpenTK.GLControl" Version="4.0.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="OpenTK" Version="3.2" />
<PackageReference Include="OpenTK.GLControl" Version="3.1.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualBasic" />
<Reference Include="System.Windows.Forms" />
<PackageReference Include="OpenTK" Version="4.9.4" />
<PackageReference Include="System.Numerics.Vectors" Version="4.6.1" />
</ItemGroup>
<ItemGroup>
<Import Include="Microsoft.VisualBasic" />
@@ -52,9 +51,7 @@
<Compile Update="Preview\ModelPreview.Designer.vb">
<DependentUpon>ModelPreview.vb</DependentUpon>
</Compile>
<Compile Update="Preview\ModelPreview.vb">
<SubType>Form</SubType>
</Compile>
<Compile Update="Preview\ModelPreview.vb" />
<Compile Update="My Project\Application.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Application.myapp</DependentUpon>
@@ -94,6 +91,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Pilz.Simple3DFileParser\Pilz.Simple3DFileParser.vbproj" />
<ProjectReference Include="..\Pilz.Win32\Pilz.Win32.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Remove="ModelPreview.Designer.vb" />

View File

@@ -1,15 +1,30 @@
Imports System.Drawing
' Nicht gemergte Änderung aus Projekt "Pilz.Drawing.Drawing3D.OpenGLFactory (net6.0-windows)"
' Vor:
' Imports System.Windows.Forms
' Imports Pilz.Drawing.Drawing3D.OpenGLFactory.CameraN
' Nach:
' Imports System.Windows.Forms
'
' Imports OpenTK
' Imports OpenTK.Graphics.OpenGL
' Imports OpenTK.Mathematics
' Imports OpenTK.WinForms
'
' Imports Pilz.Drawing.Drawing3D.OpenGLFactory.CameraN
Imports System.Windows.Forms
Imports OpenTK.GLControl
Imports OpenTK.Graphics.OpenGL
Imports OpenTK.Mathematics
Imports Pilz.Drawing.Drawing3D.OpenGLFactory.CameraN
Imports Pilz.Drawing.Drawing3D.OpenGLFactory.RenderingN
Imports OpenTK
Imports OpenTK.Graphics.OpenGL
Imports Pilz.S3DFileParser
Imports Point = System.Drawing.Point
Imports KeyboardState = OpenTK.Input.KeyboardState
Imports Keyboard = OpenTK.Input.Keyboard
Imports Key = OpenTK.Input.Key
Imports Pilz.Win32.Mapped
Imports Color = System.Drawing.Color
Imports Point = System.Drawing.Point
Namespace PreviewN
@@ -81,15 +96,13 @@ Namespace PreviewN
Private ReadOnly Property IsStrgPressed As Boolean
Get
Dim state As KeyboardState = Keyboard.GetState()
Return state(Key.ControlLeft) OrElse state(Key.ControlRight)
Return Keyboard.IsKeyDown(Keys.Control)
End Get
End Property
Private ReadOnly Property IsShiftPressed As Boolean
Get
Dim state As KeyboardState = Keyboard.GetState()
Return state(Key.ShiftLeft) OrElse state(Key.ShiftRight)
Return Keyboard.IsKeyDown(Keys.Shift)
End Get
End Property
@@ -122,17 +135,17 @@ Namespace PreviewN
DoubleBuffered = True
'glControl1
Me.glControl1 = New GLControl
Me.glControl1.BackColor = Color.Black
Me.glControl1.Location = New Point(0, 0)
Me.glControl1.MinimumSize = New Size(600, 120)
Me.glControl1.Name = "glControl1"
Me.glControl1.Anchor = AnchorStyles.Left Or AnchorStyles.Top Or AnchorStyles.Right Or AnchorStyles.Bottom
Me.glControl1 = New GLControl With {
.BackColor = Color.Black,
.Location = New Point(0, 0),
.MinimumSize = New Size(600, 120),
.Name = "glControl1",
.Anchor = AnchorStyles.Left Or AnchorStyles.Top Or AnchorStyles.Right Or AnchorStyles.Bottom
}
Me.glControl1.Location = New Point(0, 0)
Me.glControl1.Size = Me.ClientSize
Me.glControl1.TabIndex = 0
Me.glControl1.TabStop = False
Me.glControl1.VSync = False
Me.Controls.Add(Me.glControl1)
Me.ResumeLayout(False)
@@ -247,7 +260,7 @@ Namespace PreviewN
End Sub
Private Sub glControl1_Resize(sender As Object, e As EventArgs) Handles glControl1.Resize
glControl1.Context.Update(glControl1.WindowInfo)
'glControl1.Context.Update(glControl1.WindowInfo)
GL.Viewport(0, 0, glControl1.Width, glControl1.Height)
ProjMatrix = Matrix4.CreatePerspectiveFieldOfView(FOV, glControl1.Width / glControl1.Height, 100.0F, 100000.0F)
glControl1.Invalidate()
@@ -255,7 +268,7 @@ Namespace PreviewN
Private Sub glControl1_Wheel(sender As Object, e As MouseEventArgs)
MyCamera.ResetMouseStuff()
MyCamera.UpdateCameraMatrixWithScrollWheel(CInt(Math.Truncate(e.Delta * (If(IsShiftPressed, 3.5F, 1.5F)))), camMtx)
MyCamera.UpdateCameraMatrixWithScrollWheel(Math.Truncate(e.Delta * (If(IsShiftPressed, 3.5F, 1.5F))), camMtx)
savedCamPos = MyCamera.Position
glControl1.Invalidate()
End Sub
@@ -286,32 +299,24 @@ Namespace PreviewN
Dim allowCamMove As Boolean = Not (IsMouseDown AndAlso IsShiftPressed)
If allowCamMove Then
Dim state As KeyboardState = Keyboard.GetState
If state(Key.W) Then
'camera.Move(moveSpeed, moveSpeed, camMtx)
If Keyboard.IsKeyDown(Keys.W) Then
MyCamera.UpdateCameraMatrixWithScrollWheel(moveSpeed, camMtx)
savedCamPos = MyCamera.Position
End If
If state(Key.S) Then
'camera.Move(-moveSpeed, -moveSpeed, camMtx)
If Keyboard.IsKeyDown(Keys.S) Then
MyCamera.UpdateCameraMatrixWithScrollWheel(-moveSpeed, camMtx)
savedCamPos = MyCamera.Position
End If
If state(Key.A) Then
'camera.Move(-moveSpeed, 0, camMtx)
If Keyboard.IsKeyDown(Keys.A) Then
MyCamera.UpdateCameraOffsetDirectly(-moveSpeed, 0, camMtx)
End If
If state(Key.D) Then
'camera.Move(moveSpeed, 0, camMtx)
If Keyboard.IsKeyDown(Keys.D) Then
MyCamera.UpdateCameraOffsetDirectly(moveSpeed, 0, camMtx)
End If
If state(Key.E) Then
'camera.Move(0, -moveSpeed, camMtx)
If Keyboard.IsKeyDown(Keys.E) Then
MyCamera.UpdateCameraOffsetDirectly(0, -moveSpeed, camMtx)
End If
If state(Key.Q) Then
'camera.Move(0, moveSpeed, camMtx)
If Keyboard.IsKeyDown(Keys.Q) Then
MyCamera.UpdateCameraOffsetDirectly(0, moveSpeed, camMtx)
End If
End If

View File

@@ -1,5 +1,14 @@
Imports System.Drawing
Imports OpenTK
' Nicht gemergte Änderung aus Projekt "Pilz.Drawing.Drawing3D.OpenGLFactory (net6.0-windows)"
' Vor:
' Imports System.Drawing
' Imports OpenTK
' Nach:
' Imports System.Drawing
'
' Imports OpenTK
Imports System.Drawing
Imports OpenTK.Graphics.OpenGL
Namespace RenderingN

View File

@@ -1,8 +1,8 @@
Imports System
Imports OpenTK
Imports OpenTK.Graphics.OpenGL
Imports System.Drawing
Imports System.Drawing
Imports System.Drawing.Imaging
Imports OpenTK.Graphics.OpenGL
Imports Bitmap = System.Drawing.Bitmap
Namespace RenderingN

View File

@@ -1,9 +1,8 @@
Imports System.Drawing
Imports System.Threading
Imports System.Windows.Forms
Imports OpenTK
Imports OpenTK.Graphics.OpenGL
Imports OpenTK.Graphics.OpenGL
Imports OpenTK.Mathematics
Imports Pilz.S3DFileParser
Imports Bitmap = System.Drawing.Bitmap
Imports Color = System.Drawing.Color
Imports Image = System.Drawing.Image
@@ -137,6 +136,14 @@ Namespace RenderingN
''' Creates the Buffers and store the requied Data.
''' </summary>
Public Sub RenderModel()
RenderModel(BufferUsageHint.StaticDraw)
End Sub
''' <summary>
''' Creates the Buffers and store the requied Data.
''' </summary>
''' <param name="bufferUsage">The hint how the graphics card should handle the data.</param>
Public Sub RenderModel(bufferUsage As BufferUsageHint)
ReleaseBuffers()
For Each mesh As Mesh In obj3d.Meshes

View File

@@ -1,15 +1,14 @@
Imports System.Drawing
Imports System.Drawing.Drawing2D
Public Module HelpfulDrawingFunctions
Public Function IsPointInRectangle(p As PointF, rect As RectangleF) As Boolean
Dim bList As New List(Of Boolean)
bList.Add(p.X > rect.Left)
bList.Add(p.X < rect.Right)
bList.Add(p.Y > rect.Top)
bList.Add(p.Y < rect.Bottom)
Dim bList As New List(Of Boolean) From {
p.X > rect.Left,
p.X < rect.Right,
p.Y > rect.Top,
p.Y < rect.Bottom
}
Return Not bList.Contains(False)
End Function

View File

@@ -22,7 +22,7 @@ Namespace My.Resources
'''<summary>
''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
'''</summary>
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0"), _
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0"), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _

View File

@@ -1,10 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<MyType>Windows</MyType>
<TargetFramework>net48</TargetFramework>
<TargetFrameworks>net8.0-windows</TargetFrameworks>
<LangVersion>latest</LangVersion>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<DocumentationFile>Pilz.Drawing.xml</DocumentationFile>
<DefineTrace>true</DefineTrace>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DefineDebug>true</DefineDebug>
@@ -24,10 +26,9 @@
<PropertyGroup>
<OptionInfer>On</OptionInfer>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
</ItemGroup>
<PropertyGroup>
<Version>2.0.2</Version>
</PropertyGroup>
<ItemGroup>
<Import Include="Microsoft.VisualBasic" />
<Import Include="System" />

View File

@@ -0,0 +1,18 @@
namespace Pilz.Extensions.Collections;
public static class IEnumerableExtensions
{
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> @this, Action<T> action)
{
foreach (var t in @this)
action(t);
return @this;
}
public static IQueryable<T> ForEach<T>(this IQueryable<T> @this, Action<T> action)
{
foreach (var t in @this)
action(t);
return @this;
}
}

View File

@@ -0,0 +1,30 @@
namespace Pilz.Extensions.Collections;
public static class IListExtensions
{
public static bool Move<T>(this IList<T> @this, T item, int amount)
{
var oldIndex = @this.IndexOf(item);
if (oldIndex == -1)
return false;
var newIndex = oldIndex + amount;
if (newIndex < 0)
newIndex = 0;
else if (newIndex >= @this.Count)
newIndex = @this.Count;
if (newIndex == oldIndex)
return false;
if (newIndex > 0 && newIndex > oldIndex)
newIndex -= 1;
@this.RemoveAt(oldIndex);
@this.Insert(newIndex, item);
return true;
}
}

View File

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<Version>2.1.2</Version>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,24 @@
using System.Linq.Expressions;
using System.Reflection;
namespace Pilz.Extensions.Reflection;
public static class MethodInfoExtensions
{
/// <summary>
/// Source: https://stackoverflow.com/questions/940675/getting-a-delegate-from-methodinfo
/// </summary>
/// <param name="methodInfo"></param>
/// <param name="target"></param>
/// <returns></returns>
public static Delegate CreateDelegate(this MethodInfo methodInfo, object? target)
{
var parmTypes = methodInfo.GetParameters().Select(parm => parm.ParameterType);
var parmAndReturnTypes = parmTypes.Append(methodInfo.ReturnType).ToArray();
var delegateType = Expression.GetDelegateType(parmAndReturnTypes);
if (methodInfo.IsStatic)
return methodInfo.CreateDelegate(delegateType);
return methodInfo.CreateDelegate(delegateType, target);
}
}

View File

@@ -0,0 +1,3 @@
namespace Pilz.Features;
public delegate void PluginFeatureExecuteEventHandler(object sender, PluginFeatureExecuteEventArgs e);

View File

@@ -0,0 +1,5 @@
namespace Pilz.Features.Exceptions;
public class PluginFeatureException : Exception;
public class PluginFeatureNotFoundException : PluginFeatureException;

View File

@@ -0,0 +1,34 @@
namespace Pilz.Features;
public static class Extensions
{
public static T? ExecuteIfEnabled<T>(this PluginFunction @this, params object?[]? @params)
{
return @this.Enabled ? @this.Execute<T>(@params) : default;
}
public static object? ExecuteIfEnabled(this PluginFunction @this, params object?[]? @params)
{
return @this.Enabled ? @this.Execute(@params) : default;
}
public static T? ExecuteIfEnabled<T>(this PluginFunction @this, PluginFunctionSimpleParamter? @params)
{
return @this.Enabled ? @this.Execute<T>(@params) : default;
}
public static object? ExecuteIfEnabled(this PluginFunction @this, PluginFunctionParameter? @params)
{
return @this.Enabled ? @this.Execute(@params) : default;
}
public static IEnumerable<T> Enabled<T>(this IEnumerable<T> @this) where T : PluginFeature
{
return @this.Where(n => n.Enabled);
}
public static IEnumerable<T> Ordered<T>(this IEnumerable<T> @this) where T : PluginFeature
{
return @this.OrderByDescending(n => n.Prioritization);
}
}

View File

@@ -0,0 +1,8 @@
namespace Pilz.Features;
public enum FeaturePrioritization
{
Low = -1,
Default = 0,
High = 1,
}

View File

@@ -0,0 +1,5 @@
namespace Pilz.Features;
public interface IPluginFeatureConstructor
{
}

View File

@@ -0,0 +1,12 @@
namespace Pilz.Features;
public interface IPluginFeatureProvider
{
static abstract PluginFeature Instance { get; }
}
public interface IPluginFeatureProvider<T> : IPluginFeatureProvider where T : PluginFeature, IPluginFeatureProvider<T>
{
static new abstract T Instance { get; }
static PluginFeature IPluginFeatureProvider.Instance => T.Instance;
}

View File

@@ -0,0 +1,6 @@
namespace Pilz.Features;
public interface IPluginFeaturesProvider
{
static abstract PluginFeature[] GetFeatures();
}

View File

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<Version>2.13.1</Version>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,110 @@
namespace Pilz.Features;
public abstract class PluginFeature
{
/// <summary>
/// Fires when the plugin feature gets used.
/// <br/>- For <see cref="PluginFunction"/> this fires on <see cref="PluginFunction.ExecuteFunction(PluginFunctionParameter?)"/>.
/// <br/>- For <see cref="T:PluginModule"/> this fires on <see cref="T:PluginModule.CreateNewUI(PluginFunctionParameter?)"/>.
/// <br/>- For any other custom feature implementation this may variate.
/// </summary>
public static event PluginFeatureExecuteEventHandler? OnExecute;
/// <summary>
/// The type of the feature defines where the feature get integrated.
/// </summary>
public string Type { get; init; }
/// <summary>
/// The identifier of the feature should be uniquie for the current <see cref="Type"/>.
/// It defines a feature within a type.
/// </summary>
public string Identifier { get; init; }
/// <summary>
/// The full identifier of the feature should be uniquie and is the combination of <see cref="Type"/> and <see cref="Identifier"/>.
/// It defines a feature across all types.
/// </summary>
public string FullIdentifier => GetFullIdentifier(Type, Identifier);
/// <summary>
/// The (display) name of the feature.
/// </summary>
public virtual string? Name { get; init; }
/// <summary>
/// The (display) description of the feature.
/// </summary>
public virtual string? Description { get; init; }
/// <summary>
/// The symbol for the feature.
/// </summary>
public virtual object? Icon { get; set; }
/// <summary>
/// Sets the prioritization of the feature.
/// This will be respected on abfragen features and on inserting as items using the extension methods"/>.
/// Some applications might implement a way to regonize feature prioritization via its own way.
/// </summary>
public virtual FeaturePrioritization Prioritization { get; set; }
/// <summary>
/// Defines if the feature is enabled/visible.
/// </summary>
public virtual bool Enabled { get; set; } = true;
protected PluginFeature(string type, string identifier)
{
Identifier = identifier;
Type = type;
}
protected PluginFeature(string type, string identifier, string? name) : this(type, identifier)
{
Name = name;
}
public static string GetFullIdentifier(string featureType, string identifier)
{
return $"{featureType}:{identifier}";
}
/// <summary>
/// Fires the <see cref="OnExecute"/> event with the status <see cref="PluginFeatureExecuteEventType.PostEvent"/>.
/// </summary>
/// <param name="params">The present <see cref="PluginFunctionParameter"/>.</param>
/// <param name="result">The resulting object that will be returned.</param>
/// <returns>Returns true if the original function should be executed.</returns>
protected bool OnPreExecute(PluginFunctionParameter? @params, ref object? result)
{
if (OnExecute != null)
{
var args = new PluginFeatureExecuteEventArgs(PluginFeatureExecuteEventType.PreEvent, @params);
OnExecute.Invoke(this, args);
if (args.Handled)
{
result = args.Result;
return false;
}
}
return true;
}
/// <summary>
/// Fires the <see cref="OnExecute"/> event with the status <see cref="PluginFeatureExecuteEventType.PostEvent"/>.
/// </summary>
/// <param name="params">The present <see cref="PluginFunctionParameter"/>.</param>
/// <param name="result">The resulting object that will be returned.</param>
protected void OnPostExecute(PluginFunctionParameter? @params, ref object? result)
{
if (OnExecute != null)
{
var args = new PluginFeatureExecuteEventArgs(PluginFeatureExecuteEventType.PostEvent, @params)
{
Result = result
};
OnExecute.Invoke(this, args);
if (args.Handled)
result = args.Result;
}
}
}

View File

@@ -0,0 +1,302 @@
using Pilz.Features.Exceptions;
using System.Reflection;
namespace Pilz.Features;
public class PluginFeatureController
{
// D e l e g a t e s
public delegate void PluginFeatureEventHandler(PluginFeatureController controller, PluginFeature feature);
// S t a t i c E v e n t s
/// <summary>
/// Fires when a new <see cref="PluginFeature"/> has been registred.
/// </summary>
public static event PluginFeatureEventHandler? OnPluginFeatureReistred;
/// <summary>
/// Fires when a <see cref="PluginFeature"/> has been unregistred.
/// </summary>
public static event PluginFeatureEventHandler? OnPluginFeatureUnregistred;
// S t a t i c M e m b e r s
protected static readonly string nameGetFeatures = $"{nameof(IPluginFeaturesProvider.GetFeatures)}";
protected static readonly string nameGetFeaturesExplicit = $"{typeof(IPluginFeaturesProvider).FullName}.{nameof(IPluginFeaturesProvider.GetFeatures)}";
protected static readonly string nameInstance = $"get_{nameof(IPluginFeatureProvider.Instance)}";
protected static readonly string nameInstnaceExplicit = $"{typeof(IPluginFeaturesProvider).FullName}.get_{nameof(IPluginFeatureProvider.Instance)}";
/// <summary>
/// The default public instance that can be used by plugins and the interface providing software.
/// </summary>
public static PluginFeatureController Instance { get; private set; } = new();
// I n s t a n c e M e m e b e r s
private readonly HashSet<PluginFeature> features = [];
/// <summary>
/// A wrapper of all registred <see cref="PluginFeature"/> instances.
/// </summary>
public FeatureController Features { get; init; }
/// <summary>
/// A wrapper for all registred <see cref="PluginModule"/> instances.
/// </summary>
public ModuleController Modules { get; init; }
/// <summary>
/// A wrapper for all registred <see cref="PluginFunction"/> instances.
/// </summary>
public FunctionController Functions { get; init; }
public PluginFeatureController()
{
Features = new(this);
Functions = new(this);
Modules = new(this);
}
/// <summary>
/// Registers all features found in the currently executing Assembly via <see cref="IPluginFeatureProvider"/>, <see cref="IPluginFeatureProvider{T}"/> and <see cref="IPluginFeaturesProvider"/>.
/// <para><b>Note:</b><br/>Explicit implementations of <see cref="IPluginFeatureProvider{T}.Instance"/> can not be detected. For this case just implement <see cref="IPluginFeatureProvider.Instance"/> instead.</para>
/// </summary>
public void RegisterAllOwn(string? @namespace = null)
{
RegisterAll(Assembly.GetCallingAssembly());
}
/// <summary>
/// Registers all features found in the given <see cref="Assembly[]"/> via <see cref="IPluginFeatureProvider"/>, <see cref="IPluginFeatureProvider{T}"/> and <see cref="IPluginFeaturesProvider"/>.
/// <para><b>Note:</b><br/>Explicit implementations of <see cref="IPluginFeatureProvider{T}.Instance"/> can not be detected. For this case just implement <see cref="IPluginFeatureProvider.Instance"/> instead.</para>
/// </summary>
/// <param name="assemblies">The assemblies to query for types.</param>
/// <param name="namespace">If not null, only types within the given namespace will be registered.</param>
public void RegisterAll(Assembly[] assemblies, string? @namespace = null)
{
foreach (var assembly in assemblies)
RegisterAll(assembly);
}
/// <summary>
/// Registers all features found in the given <see cref="Assembly"/> via <see cref="IPluginFeatureProvider"/>, <see cref="IPluginFeatureProvider{T}"/> and <see cref="IPluginFeaturesProvider"/>.
/// <para><b>Note:</b><br/>Explicit implementations of <see cref="IPluginFeatureProvider{T}.Instance"/> can not be detected. For this case just implement <see cref="IPluginFeatureProvider.Instance"/> instead.</para>
/// </summary>
/// <param name="assembly">The assembly to query for types.</param>
/// <param name="namespace">If not null, only types within the given namespace will be registered.</param>
public void RegisterAll(Assembly assembly, string? @namespace = null)
{
RegisterAll(assembly.GetTypes());
}
/// <summary>
/// Registers all features found from the given <see cref="Type[]"/> via <see cref="IPluginFeatureProvider"/>, <see cref="IPluginFeatureProvider{T}"/> and <see cref="IPluginFeaturesProvider"/>.
/// <para><b>Note:</b><br/>Explicit implementations of <see cref="IPluginFeatureProvider{T}.Instance"/> can not be detected. For this case just implement <see cref="IPluginFeatureProvider.Instance"/> instead.</para>
/// </summary>
/// <param name="types">The types to query for providers.</param>
/// <param name="namespace">If not null, the types will only be processed if they're within the given namespace.</param>
public void RegisterAll(Type[] types, string? @namespace = null)
{
foreach (var type in types)
RegisterAll(type);
}
/// <summary>
/// Registers all features found from the given <see cref="Type"/> via <see cref="IPluginFeatureProvider"/>, <see cref="IPluginFeatureProvider{T}"/> and <see cref="IPluginFeaturesProvider"/>.
/// <para><b>Note:</b><br/>Explicit implementations of <see cref="IPluginFeatureProvider{T}.Instance"/> can not be detected. For this case just implement <see cref="IPluginFeatureProvider.Instance"/> instead.</para>
/// </summary>
/// <param name="type">The type to query for providers.</param>
/// <param name="namespace">If not null, the type will only be processed if it's within the given namespace.</param>
public void RegisterAll(Type type, string? @namespace = null)
{
if (@namespace != null && type.Namespace != null && type.Namespace != @namespace && !type.Namespace.StartsWith(@namespace + ".") || type.IsAbstract)
return;
if (type.IsAssignableTo(typeof(IPluginFeaturesProvider)))
{
var methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var method = methods.FirstOrDefault(n => n.Name == nameGetFeaturesExplicit || n.Name == nameGetFeatures);
if (method != null && method.Invoke(null, null) is PluginFeature[] features)
{
foreach (var feature in features)
Register(feature);
}
}
else if (type.IsAssignableTo(typeof(IPluginFeatureProvider)))
{
var methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var method = methods.FirstOrDefault(n => n.Name == nameInstnaceExplicit || n.Name == nameInstance);
if (method != null && method.Invoke(null, null) is PluginFeature feature)
Register(feature);
}
else if (type.IsAssignableTo(typeof(IPluginFeatureConstructor)))
{
if (type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, [typeof(PluginFeatureController)]) is ConstructorInfo ctor1)
{
if (ctor1.Invoke([this]) is PluginFeature feature)
Register(feature);
}
else if (type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, []) is ConstructorInfo ctor)
{
if (ctor.Invoke([]) is PluginFeature feature)
Register(feature);
}
}
}
/// <summary>
/// Registers a feature via the given <see cref="IPluginFeatureProvider"/> or <see cref="IPluginFeatureProvider{T}"/>.
/// </summary>
public void Register<TProvider>() where TProvider : IPluginFeatureProvider
{
Register(TProvider.Instance);
}
/// <summary>
/// Registers all features via the given <see cref="IPluginFeaturesProvider"/>.
/// </summary>
public void RegisterAll<TProvider>() where TProvider : IPluginFeaturesProvider
{
foreach (var feature in TProvider.GetFeatures())
Register(feature);
}
/// <summary>
/// Registers the given feature.
/// </summary>
/// <param name="module"></param>
public void Register(PluginFeature module)
{
if (features.Add(module))
OnPluginFeatureReistred?.Invoke(this, module);
}
/// <summary>
/// Unregisters the given feature.
/// </summary>
/// <param name="module"></param>
public void Unregister(PluginFeature module)
{
features.Remove(module);
OnPluginFeatureUnregistred?.Invoke(this, module);
}
public class FeatureController(PluginFeatureController controller)
{
protected readonly PluginFeatureController controller = controller;
public virtual IEnumerable<PluginFeature> GetAll()
{
return [.. controller.features];
}
public virtual IEnumerable<T> GetAll<T>() where T : PluginFeature
{
return controller.features.OfType<T>();
}
public virtual T? Get<T>() where T : PluginFeature
{
return GetAll<T>().FirstOrDefault();
}
public virtual T EnsureGet<T>() where T : PluginFeature
{
if (Get<T>() is T feature)
return feature;
throw new PluginFeatureNotFoundException();
}
public virtual IEnumerable<PluginFeature> Get(string featureType)
{
return controller.features.Where(n => n.Type == featureType);
}
public virtual PluginFeature? GetFirst(string featureType)
{
return controller.features.FirstOrDefault(n => n.Type == featureType);
}
public virtual PluginFeature? GetByIdentifier(string fullIdentifier)
{
return controller.features.FirstOrDefault(n => n.FullIdentifier == fullIdentifier);
}
public virtual PluginFeature? GetByIdentifier(string featureType, string identifier)
{
return controller.features.FirstOrDefault(n => n.Type == featureType && n.Identifier == identifier);
}
}
public class FeatureController<T>(PluginFeatureController controller) : FeatureController(controller) where T : PluginFeature
{
public override IEnumerable<T> GetAll()
{
return GetAll<T>();
}
public override IEnumerable<T> Get(string moduleType)
{
return GetAll().Where(n => n.Type == moduleType);
}
public override T? GetFirst(string moduleType)
{
return base.GetFirst(moduleType) as T;
}
public override T? GetByIdentifier(string fullIdentifier)
{
return base.GetByIdentifier(fullIdentifier) as T;
}
public override T? GetByIdentifier(string featureType, string identifier)
{
return base.GetByIdentifier(featureType, identifier) as T;
}
}
public class ModuleController(PluginFeatureController controller) : FeatureController<PluginModuleBase>(controller)
{
}
public class FunctionController(PluginFeatureController controller) : FeatureController<PluginFunction>(controller)
{
public void ExecuteAll(string functionType)
{
foreach (var function in Get(functionType))
function.Execute();
}
public void ExecuteAll(string functionType, params object?[]? @params)
{
foreach (var function in Get(functionType))
function.Execute(@params);
}
public void ExecuteAll(string functionType, PluginFunctionParameter @params)
{
foreach (var function in Get(functionType))
function.Execute(@params);
}
public IEnumerable<object?> ExcuteAndGetResults(string functionType)
{
return Get(functionType).Select(n => n.Execute());
}
public IEnumerable<object?> ExcuteAndGetResults(string functionType, params object?[]? @params)
{
return Get(functionType).Select(n => n.Execute(@params));
}
public IEnumerable<object?> ExcuteAndGetResults(string functionType, PluginFunctionParameter @params)
{
return Get(functionType).Select(n => n.Execute(@params));
}
}
}

View File

@@ -0,0 +1,9 @@
namespace Pilz.Features;
public class PluginFeatureExecuteEventArgs(PluginFeatureExecuteEventType eventType, PluginFunctionParameter? parameters) : EventArgs
{
public PluginFeatureExecuteEventType EventType { get; } = eventType;
public PluginFunctionParameter? Parameters { get; } = parameters;
public bool Handled { get; set; }
public object? Result { get; set; }
}

View File

@@ -0,0 +1,7 @@
namespace Pilz.Features;
public enum PluginFeatureExecuteEventType
{
PreEvent,
PostEvent,
}

View File

@@ -0,0 +1,90 @@
namespace Pilz.Features;
public abstract class PluginFunction : PluginFeature
{
protected PluginFunction(string type, string identifier) : base(type, identifier)
{
}
protected PluginFunction(string type, string identifier, string? name) : base(type, identifier, name)
{
}
public virtual object? Execute()
{
return Execute((PluginFunctionParameter?)null);
}
public virtual T? Execute<T>(params object?[]? @params)
{
return Execute<T>(new PluginFunctionSimpleParamter(@params));
}
public virtual object? Execute(params object?[]? @params)
{
return Execute(new PluginFunctionSimpleParamter(@params));
}
public virtual T? Execute<T>(PluginFunctionSimpleParamter? @params)
{
if (Execute(@params) is T result)
return result;
return default;
}
public virtual object? Execute(PluginFunctionParameter? @params)
{
object? result = null;
if (OnPreExecute(@params, ref result))
result = ExecuteFunction(@params);
OnPostExecute(@params, ref result);
return result;
}
public virtual Task<object?> ExecuteAsync()
{
return ExecuteAsync((PluginFunctionParameter?)null);
}
public virtual Task<T?> ExecuteAsync<T>(params object?[]? @params)
{
return ExecuteAsync<T>(new PluginFunctionSimpleParamter(@params));
}
public virtual Task<object?> ExecuteAsync(params object?[]? @params)
{
return ExecuteAsync(new PluginFunctionSimpleParamter(@params));
}
public virtual async Task<T?> ExecuteAsync<T>(PluginFunctionSimpleParamter? @params)
{
if (await ExecuteAsync(@params) is T result)
return result;
return default;
}
public virtual async Task<object?> ExecuteAsync(PluginFunctionParameter? @params)
{
object? result = null;
if (OnPreExecute(@params, ref result))
result = await ExecuteFunctionAsync(@params);
OnPostExecute(@params, ref result);
return result;
}
protected virtual object? ExecuteFunction(PluginFunctionParameter? @params)
{
return ExecuteFunctionAsync(@params).GetAwaiter().GetResult();
}
protected virtual Task<object?> ExecuteFunctionAsync(PluginFunctionParameter? @params)
{
return Task.FromResult(ExecuteFunction(@params));
}
}

View File

@@ -0,0 +1,5 @@
namespace Pilz.Features;
public class PluginFunctionParameter
{
}

View File

@@ -0,0 +1,11 @@
namespace Pilz.Features;
public sealed class PluginFunctionSimpleParamter : PluginFunctionParameter
{
public object?[]? Params { get; init; }
public PluginFunctionSimpleParamter(params object?[]? @params)
{
Params = @params;
}
}

View File

@@ -0,0 +1,15 @@
using System.ComponentModel;
namespace Pilz.Features;
[EditorBrowsable(EditorBrowsableState.Never)]
public abstract class PluginModuleBase : PluginFeature
{
protected PluginModuleBase(string type, string identifier) : base(type, identifier)
{
}
protected PluginModuleBase(string type, string identifier, string? name) : base(type, identifier, name)
{
}
}

View File

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<Version>2.0.1</Version>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,40 @@
using System.Security.Cryptography;
using System.Text;
namespace Pilz.Gaming.Minecraft;
public static class Utils
{
public static string GetUUID(string value)
{
//extracted from the java code:
//new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name));
var data = MD5.HashData(Encoding.ASCII.GetBytes(value));
//set the version to 3 -> Name based md5 hash
data[6] = Convert.ToByte(data[6] & 0x0f | 0x30);
//IETF variant
data[8] = Convert.ToByte(data[8] & 0x3f | 0x80);
//example: 069a79f4-44e9-4726-a5be-fca90e38aaf5
var striped = Convert.ToHexString(data);
var components = new string[] {
striped[..].Remove(8),
striped[8..].Remove(4),
striped[12..].Remove(4),
striped[16..].Remove(4),
striped[20..]
};
return string.Join('-', components).ToLower();
}
public static string GetPlayerUUID(string username, bool offlineMode)
{
using var md5 = MD5.Create();
if (!offlineMode)
throw new NotSupportedException("Getting player's online UUID via the Mojang API is not supported at this time.");
return GetUUID("OfflinePlayer:" + username);
}
}

View File

@@ -1,174 +1,167 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.IO
namespace Pilz.IO;
public class EmbeddedFilesContainer
{
public class EmbeddedFilesContainer
[JsonProperty("CompressedFiles")]
private readonly Dictionary<string, byte[]> compressedFiles = [];
/// <summary>
/// Returns the names of all embedded files.
/// </summary>
[JsonIgnore]
public IEnumerable<string> AllFileNames
{
[JsonProperty("CompressedFiles")]
private readonly Dictionary<string, byte[]> compressedFiles = new Dictionary<string, byte[]>();
get => compressedFiles.Keys;
}
/// <summary>
/// Returns the names of all embedded files.
/// </summary>
[JsonIgnore]
public IEnumerable<string> AllFileNames
{
get => compressedFiles.Keys;
}
/// <summary>
/// Embeds a file to this container.
/// </summary>
/// <param name="fileName">The name how it should be called in this container.</param>
/// <param name="filePath">The file path to the file that should be embedded.</param>
/// <returns>Returns a <see cref="bool"/> that defines if the file as been embedded successfully.</returns>
public Task<bool> AddFileAsync(string fileName, string filePath)
{
return Task.Run(() => AddFile(fileName, filePath));
}
/// <summary>
/// Embeds a file to this container.
/// </summary>
/// <param name="fileName">The name how it should be called in this container.</param>
/// <param name="filePath">The file path to the file that should be embedded.</param>
/// <returns>Returns a <see cref="bool"/> that defines if the file as been embedded successfully.</returns>
public Task<bool> AddFileAsync(string fileName, string filePath)
{
return Task.Run(() => AddFile(fileName, filePath));
}
/// <summary>
/// Embeds a file to this container.
/// </summary>
/// <param name="fileName">The name how it should be called in this container.</param>
/// <param name="filePath">The file path to the file that should be embedded.</param>
/// <returns>Returns a <see cref="bool"/> that defines if the file as been embedded successfully.</returns>
public bool AddFile(string fileName, string filePath)
{
bool success;
FileStream fs = null;
MemoryStream compressed = null;
/// <summary>
/// Embeds a file to this container.
/// </summary>
/// <param name="fileName">The name how it should be called in this container.</param>
/// <param name="filePath">The file path to the file that should be embedded.</param>
/// <returns>Returns a <see cref="bool"/> that defines if the file as been embedded successfully.</returns>
public bool AddFile(string fileName, string filePath)
{
bool success;
FileStream fs = null;
MemoryStream compressed = null;
#if !DEBUG
try
{
try
{
#endif
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
compressed = new MemoryStream();
using (var compressor = new DeflateStream(compressed, CompressionLevel.Optimal, true))
fs.CopyTo(compressor);
success = true;
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
compressed = new MemoryStream();
using (var compressor = new DeflateStream(compressed, CompressionLevel.Optimal, true))
fs.CopyTo(compressor);
success = true;
#if !DEBUG
}
catch (Exception)
{
success = false;
}
}
catch (Exception)
{
success = false;
}
#endif
if (success)
{
var compressedBytes = compressed.ToArray();
if (compressedFiles.ContainsKey(fileName))
compressedFiles[fileName] = compressedBytes;
else
compressedFiles.Add(fileName, compressedBytes);
}
compressed?.Close();
fs?.Close();
return success;
}
/// <summary>
/// Removes a file from this container.
/// </summary>
/// <param name="fileName">The name how the file is called.</param>
public void RemoveFile(string fileName)
if (success)
{
var compressedBytes = compressed.ToArray();
if (compressedFiles.ContainsKey(fileName))
compressedFiles.Remove(fileName);
compressedFiles[fileName] = compressedBytes;
else
compressedFiles.Add(fileName, compressedBytes);
}
/// <summary>
/// Checks if the given file exists in this container.
/// </summary>
/// <param name="fileName">The name how the file is called.</param>
/// <returns>Returns if the given file exists in this container.</returns>
public bool HasFile(string fileName)
compressed?.Close();
fs?.Close();
return success;
}
/// <summary>
/// Removes a file from this container.
/// </summary>
/// <param name="fileName">The name how the file is called.</param>
public void RemoveFile(string fileName)
{
if (compressedFiles.ContainsKey(fileName))
compressedFiles.Remove(fileName);
}
/// <summary>
/// Checks if the given file exists in this container.
/// </summary>
/// <param name="fileName">The name how the file is called.</param>
/// <returns>Returns if the given file exists in this container.</returns>
public bool HasFile(string fileName)
{
return compressedFiles.ContainsKey(fileName);
}
/// <summary>
/// Gets a file from this container as stream.
/// </summary>
/// <param name="fileName">The name how the file is called.</param>
/// <returns>Returns a stream of the file with the given name.</returns>
public Task<Stream> GetStreamAsync(string fileName)
{
return Task.Run(() => GetStream(fileName));
}
/// <summary>
/// Gets a file from this container as stream.
/// </summary>
/// <param name="fileName">The name how the file is called.</param>
/// <returns>Returns a stream of the file with the given name.</returns>
public Stream GetStream(string fileName)
{
Stream decompressed = null;
if (compressedFiles.ContainsKey(fileName))
{
return compressedFiles.ContainsKey(fileName);
decompressed = new MemoryStream();
DecompressToStream(decompressed, compressedFiles[fileName]);
}
/// <summary>
/// Gets a file from this container as stream.
/// </summary>
/// <param name="fileName">The name how the file is called.</param>
/// <returns>Returns a stream of the file with the given name.</returns>
public Task<Stream> GetStreamAsync(string fileName)
return decompressed;
}
/// <summary>
/// Saves a given file to the users temp directory.
/// </summary>
/// <param name="fileName">The name how the file is called.</param>
/// <returns>Returns the file path to the temp file.</returns>
public Task<string> GetLocalFilePathAsync(string fileName)
{
return Task.Run(() => GetLocalFilePath(fileName));
}
/// <summary>
/// Saves a given file to the users temp directory.
/// </summary>
/// <param name="fileName">The name how the file is called.</param>
/// <returns>Returns the file path to the temp file.</returns>
public string GetLocalFilePath(string fileName)
{
string filePath = string.Empty;
if (compressedFiles.ContainsKey(fileName))
{
return Task.Run(() => GetStream(fileName));
filePath = Path.GetTempFileName();
if (Path.HasExtension(fileName))
filePath = Path.ChangeExtension(filePath, Path.GetExtension(fileName));
var decompressed = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
DecompressToStream(decompressed, compressedFiles[fileName]);
decompressed.Flush();
decompressed.Close();
}
/// <summary>
/// Gets a file from this container as stream.
/// </summary>
/// <param name="fileName">The name how the file is called.</param>
/// <returns>Returns a stream of the file with the given name.</returns>
public Stream GetStream(string fileName)
{
Stream decompressed = null;
return filePath;
}
if (compressedFiles.ContainsKey(fileName))
{
decompressed = new MemoryStream();
DecompressToStream(decompressed, compressedFiles[fileName]);
}
return decompressed;
}
/// <summary>
/// Saves a given file to the users temp directory.
/// </summary>
/// <param name="fileName">The name how the file is called.</param>
/// <returns>Returns the file path to the temp file.</returns>
public Task<string> GetLocalFilePathAsync(string fileName)
{
return Task.Run(() => GetLocalFilePath(fileName));
}
/// <summary>
/// Saves a given file to the users temp directory.
/// </summary>
/// <param name="fileName">The name how the file is called.</param>
/// <returns>Returns the file path to the temp file.</returns>
public string GetLocalFilePath(string fileName)
{
string filePath = string.Empty;
if (compressedFiles.ContainsKey(fileName))
{
filePath = Path.GetTempFileName();
if (Path.HasExtension(fileName))
filePath = Path.ChangeExtension(filePath, Path.GetExtension(fileName));
var decompressed = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
DecompressToStream(decompressed, compressedFiles[fileName]);
decompressed.Flush();
decompressed.Close();
}
return filePath;
}
private void DecompressToStream(Stream decompressed, byte[] compressedData)
{
var compressed = new MemoryStream(compressedData);
var decompressor = new DeflateStream(compressed, CompressionMode.Decompress, true);
decompressor.CopyTo(decompressed);
decompressor.Close();
compressed.Close();
}
private void DecompressToStream(Stream decompressed, byte[] compressedData)
{
var compressed = new MemoryStream(compressedData);
var decompressor = new DeflateStream(compressed, CompressionMode.Decompress, true);
decompressor.CopyTo(decompressed);
decompressor.Close();
compressed.Close();
}
}

View File

@@ -1,14 +0,0 @@
using System;
namespace Pilz.IO
{
public class DataEventArgs : EventArgs
{
public readonly byte[] Data;
public DataEventArgs(byte[] bytes) : base()
{
Data = bytes;
}
}
}

View File

@@ -0,0 +1,6 @@
namespace Pilz.IO.EventArguments;
public class DataEventArgs(byte[] data) : EventArgs()
{
public byte[] Data { get; } = data;
}

View File

@@ -1,118 +1,114 @@
using System;
using System.IO;
namespace Pilz.IO;
namespace Pilz.IO
public partial class FileLocker : IDisposable
{
public partial class FileLocker : IDisposable
private FileStream fsLock = null;
/// <summary>
/// Defines the file path to the file that should be locked.
/// </summary>
public string FilePath { get; private set; }
/// <summary>
/// Defines the file path to the lock file that is used to identify the file lock.
/// </summary>
public string LockFile { get; private set; }
/// <summary>
/// Defines if the file is locked privatly by this instance.
/// </summary>
public bool LockedPrivate { get; private set; } = false;
/// <summary>
/// Defines if the file is locked by an other instance/program/user.
/// </summary>
public bool LockedExternal
{
private FileStream fsLock = null;
/// <summary>
/// Defines the file path to the file that should be locked.
/// </summary>
public string FilePath { get; private set; }
/// <summary>
/// Defines the file path to the lock file that is used to identify the file lock.
/// </summary>
public string LockFile { get; private set; }
/// <summary>
/// Defines if the file is locked privatly by this instance.
/// </summary>
public bool LockedPrivate { get; private set; } = false;
/// <summary>
/// Defines if the file is locked by an other instance/program/user.
/// </summary>
public bool LockedExternal
{
get
{
if (LockedPrivate)
return false;
else
{
string lockFile = FilePath + ".lock";
bool isLocked = false;
if (File.Exists(lockFile))
{
try
{
var fs = new FileStream(lockFile, FileMode.Open, FileAccess.Read);
fs.Close();
}
catch (IOException)
{
isLocked = true;
}
}
return isLocked;
}
}
}
/// <summary>
/// Generate a new instance of <see cref="FileLocker"/> and locks the given file automatically.
/// </summary>
/// <param name="filePath">The file path to the file that should be locked.</param>
public FileLocker(string filePath) : this(filePath, true)
{
}
/// <summary>
/// Generate a new instance of <see cref="FileLocker"/>
/// </summary>
/// <param name="filePath">The file path to the file that should be locked.</param>
/// <param name="autoLock">Defines if the file should be locked automatically right after creating this instance.</param>
public FileLocker(string filePath, bool autoLock)
{
FilePath = filePath;
LockFile = filePath + ".lock";
if (autoLock) Lock();
}
/// <summary>
/// Locks the file, if not already locked privatly.
/// </summary>
public void Lock()
{
if (!LockedPrivate)
{
fsLock = new FileStream(LockFile, FileMode.Create, FileAccess.ReadWrite);
LockedPrivate = true;
}
}
/// <summary>
/// Unlocks the file, if locked privatly.
/// </summary>
public void Unlock()
get
{
if (LockedPrivate)
return false;
else
{
fsLock.Close();
fsLock.Dispose();
fsLock = null;
File.Delete(LockFile);
LockedPrivate = false;
string lockFile = FilePath + ".lock";
bool isLocked = false;
if (File.Exists(lockFile))
{
try
{
var fs = new FileStream(lockFile, FileMode.Open, FileAccess.Read);
fs.Close();
}
catch (IOException)
{
isLocked = true;
}
}
return isLocked;
}
}
#region IDisposable
private bool disposedValue;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
Unlock();
}
public void Dispose()
{
Dispose(true);
disposedValue = true;
}
#endregion
}
/// <summary>
/// Generate a new instance of <see cref="FileLocker"/> and locks the given file automatically.
/// </summary>
/// <param name="filePath">The file path to the file that should be locked.</param>
public FileLocker(string filePath) : this(filePath, true)
{
}
/// <summary>
/// Generate a new instance of <see cref="FileLocker"/>
/// </summary>
/// <param name="filePath">The file path to the file that should be locked.</param>
/// <param name="autoLock">Defines if the file should be locked automatically right after creating this instance.</param>
public FileLocker(string filePath, bool autoLock)
{
FilePath = filePath;
LockFile = filePath + ".lock";
if (autoLock) Lock();
}
/// <summary>
/// Locks the file, if not already locked privatly.
/// </summary>
public void Lock()
{
if (!LockedPrivate)
{
fsLock = new FileStream(LockFile, FileMode.Create, FileAccess.ReadWrite);
LockedPrivate = true;
}
}
/// <summary>
/// Unlocks the file, if locked privatly.
/// </summary>
public void Unlock()
{
if (LockedPrivate)
{
fsLock.Close();
fsLock.Dispose();
fsLock = null;
File.Delete(LockFile);
LockedPrivate = false;
}
}
#region IDisposable
private bool disposedValue;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
Unlock();
}
public void Dispose()
{
Dispose(true);
disposedValue = true;
}
#endregion
}

View File

@@ -1,67 +1,64 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Pilz.IO.EventArguments;
namespace Pilz.IO
namespace Pilz.IO.ManagedPipes;
/// <summary>
/// stellt den Erben "Server" und "Client" 2 verschiedene
/// Message-Events zur Verfügung, und ein Event-Raisendes Dispose
/// </summary>
public abstract class ManagedPipe : IDisposable
{
public delegate void EventHandlerWithOneArgument<T0>(T0 Sender);
/// <summary>
/// stellt den Erben "Server" und "Client" 2 verschiedene
/// Message-Events zur Verfügung, und ein Event-Raisendes Dispose
/// Zur Ausgabe chat-verwaltungstechnischer Status-Informationen
/// </summary>
public abstract class ManagedPipe : IDisposable
public event EventHandler<DataEventArgs> StatusMessage;
/// <summary>Zur Ausgabe von Chat-Messages</summary>
public event EventHandler<DataEventArgs> RetriveData;
public event EventHandlerWithOneArgument<ManagedPipe> Disposed;
private bool _IsDisposed = false;
protected abstract void Dispose(bool disposing);
public abstract void Send(byte[] bytes);
public abstract Task SendAsnyc(byte[] bytes);
protected void OnStatusMessage(DataEventArgs e)
{
public delegate void EventHandlerWithOneArgument<T0>(T0 Sender);
StatusMessage?.Invoke(this, e);
}
/// <summary>
/// Zur Ausgabe chat-verwaltungstechnischer Status-Informationen
/// </summary>
public event EventHandler<DataEventArgs> StatusMessage;
/// <summary>Zur Ausgabe von Chat-Messages</summary>
public event EventHandler<DataEventArgs> RetriveData;
public event EventHandlerWithOneArgument<ManagedPipe> Disposed;
protected void OnRetriveData(DataEventArgs e)
{
RetriveData?.Invoke(this, e);
}
private bool _IsDisposed = false;
public void RemoveFrom<T>(ICollection<T> Coll) where T : ManagedPipe
{
Coll.Remove((T)this);
}
protected abstract void Dispose(bool disposing);
public abstract void Send(byte[] bytes);
public abstract Task SendAsnyc(byte[] bytes);
protected void OnStatusMessage(DataEventArgs e)
public bool IsDisposed
{
get
{
StatusMessage?.Invoke(this, e);
}
protected void OnRetriveData(DataEventArgs e)
{
RetriveData?.Invoke(this, e);
}
public void RemoveFrom<T>(ICollection<T> Coll) where T : ManagedPipe
{
Coll.Remove((T)this);
}
public bool IsDisposed
{
get
{
return _IsDisposed;
}
}
public void AddTo<T>(ICollection<T> Coll) where T : ManagedPipe
{
Coll.Add((T)this);
}
public void Dispose()
{
if (_IsDisposed)
return;
_IsDisposed = true;
Dispose(true); // rufe die erzwungenen Überschreibungen von Sub Dispose(Boolean)
Disposed?.Invoke(this);
GC.SuppressFinalize(this);
return _IsDisposed;
}
}
public void AddTo<T>(ICollection<T> Coll) where T : ManagedPipe
{
Coll.Add((T)this);
}
public void Dispose()
{
if (_IsDisposed)
return;
_IsDisposed = true;
Dispose(true); // rufe die erzwungenen Überschreibungen von Sub Dispose(Boolean)
Disposed?.Invoke(this);
GC.SuppressFinalize(this);
}
}

View File

@@ -1,90 +1,87 @@
using System;
using System.Collections.Generic;
using global::System.IO.Pipes;
using System.Threading.Tasks;
using Pilz.IO.EventArguments;
using System.IO.Pipes;
namespace Pilz.IO
namespace Pilz.IO.ManagedPipes;
public class ManagedPipeClient : ManagedPipe
{
public class ManagedPipeClient : ManagedPipe
private PipeStream pipeStream;
private byte[] _Buf = new byte[1024];
public ManagedPipeClient(string pipeName) : this(pipeName, ".")
{
private PipeStream pipeStream;
private byte[] _Buf = new byte[1024];
}
public ManagedPipeClient(string pipeName) : this(pipeName, ".")
public ManagedPipeClient(string pipeName, string serverName) : this(pipeName, serverName, -1)
{
}
public ManagedPipeClient(string pipeName, int connectionTimeout) : this(pipeName, ".", connectionTimeout)
{
}
public ManagedPipeClient(string pipeName, string serverName, int connectionTimeout)
{
var clnt = new NamedPipeClientStream(serverName, pipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
clnt.Connect(connectionTimeout);
if (!clnt.IsConnected)
{
throw new TimeoutException("Connection timeout!");
}
public ManagedPipeClient(string pipeName, string serverName) : this(pipeName, serverName, -1)
SetPipe(clnt);
}
public ManagedPipeClient(PipeStream pipe)
{
SetPipe(pipe);
}
private void SetPipe(PipeStream pipe)
{
pipeStream = pipe;
pipeStream.BeginRead(_Buf, 0, _Buf.Length, EndRead, null);
}
private void EndRead(IAsyncResult ar)
{
if (IsDisposed)
return;
int bytesCount = pipeStream.EndRead(ar);
if (bytesCount == 0) // leere Datenübermittlung signalisiert Verbindungsabbruch
{
Dispose();
return;
}
public ManagedPipeClient(string pipeName, int connectionTimeout) : this(pipeName, ".", connectionTimeout)
var list = new List<byte>();
for (int i = 0, loopTo = bytesCount - 1; i <= loopTo; i++)
list.Add(_Buf[i]);
while (bytesCount == _Buf.Length)
{
}
public ManagedPipeClient(string pipeName, string serverName, int connectionTimeout)
{
var clnt = new NamedPipeClientStream(serverName, pipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
clnt.Connect(connectionTimeout);
if (!clnt.IsConnected)
{
throw new TimeoutException("Connection timeout!");
}
SetPipe(clnt);
}
public ManagedPipeClient(PipeStream pipe)
{
SetPipe(pipe);
}
private void SetPipe(PipeStream pipe)
{
pipeStream = pipe;
pipeStream.BeginRead(_Buf, 0, _Buf.Length, EndRead, null);
}
private void EndRead(IAsyncResult ar)
{
if (IsDisposed)
return;
int bytesCount = pipeStream.EndRead(ar);
if (bytesCount == 0) // leere Datenübermittlung signalisiert Verbindungsabbruch
{
Dispose();
return;
}
var list = new List<byte>();
for (int i = 0, loopTo = bytesCount - 1; i <= loopTo; i++)
bytesCount = pipeStream.Read(_Buf, 0, _Buf.Length);
for (int i = 0, loopTo1 = bytesCount - 1; i <= loopTo1; i++)
list.Add(_Buf[i]);
while (bytesCount == _Buf.Length)
{
bytesCount = pipeStream.Read(_Buf, 0, _Buf.Length);
for (int i = 0, loopTo1 = bytesCount - 1; i <= loopTo1; i++)
list.Add(_Buf[i]);
}
var deargs = new DataEventArgs(list.ToArray());
OnRetriveData(deargs);
pipeStream.BeginRead(_Buf, 0, _Buf.Length, EndRead, null);
}
public override Task SendAsnyc(byte[] bytes)
{
return Task.Run(() => Send(bytes));
}
var deargs = new DataEventArgs(list.ToArray());
OnRetriveData(deargs);
public override void Send(byte[] data)
{
pipeStream.Write(data, 0, data.Length);
}
pipeStream.BeginRead(_Buf, 0, _Buf.Length, EndRead, null);
}
protected override void Dispose(bool disposing)
{
pipeStream.Dispose();
}
public override Task SendAsnyc(byte[] bytes)
{
return Task.Run(() => Send(bytes));
}
public override void Send(byte[] data)
{
pipeStream.Write(data, 0, data.Length);
}
protected override void Dispose(bool disposing)
{
pipeStream.Dispose();
}
}

Some files were not shown because too many files have changed in this diff Show More