diff --git a/CSE/App.config b/CSE/App.config index e6bcccabcc7bc70ee676c9ae05863f510546989f..6a5baf876d17bd733a10ad6393f02dda1ecaf1b5 100644 --- a/CSE/App.config +++ b/CSE/App.config @@ -1,5 +1,10 @@ <?xml version="1.0" encoding="utf-8" ?> <configuration> + <configSections> + <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > + <section name="CSE.My.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" /> + </sectionGroup> + </configSections> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> @@ -12,4 +17,11 @@ <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client" /> </startup> + <userSettings> + <CSE.My.MySettings> + <setting name="F_Main_location" serializeAs="String"> + <value>0, 0</value> + </setting> + </CSE.My.MySettings> + </userSettings> </configuration> \ No newline at end of file diff --git a/CSE/ApplicationEvents.vb b/CSE/ApplicationEvents.vb index cb66a913c6deb5617bcf0e8058890cd506e1e974..8d6cfe808d462bfa4f1134bc1847fd3f608cf141 100644 --- a/CSE/ApplicationEvents.vb +++ b/CSE/ApplicationEvents.vb @@ -30,6 +30,8 @@ ' Declaration Dim fiAss As New IO.FileInfo(joinPaths(Application.Info.DirectoryPath, Application.Info.AssemblyName & ".exe")) + AppPreferences = New cPreferences(, True) ' !!!Skip schema-validation here, or else app hangs as zombie! (do it instead when creating new for Dialog) + ' Path to the *.exe MyPath = My.Application.Info.DirectoryPath & "\" PreferencesPath = joinPaths(MyPath, "config", "preferences.json") @@ -41,8 +43,6 @@ ' compile date AppDate = fiAss.LastWriteTime.Date - AppPreferences = New cPreferences(, True) ' !!!Skip schema-validation here, or else app hangs as zombie! (do it instead when creating new for Dialog) - ' Licencemodul Lic.FilePath = joinPaths(MyPath, "License.dat") Lic.AppVersion = AppVers diff --git a/CSE/CSE.vbproj b/CSE/CSE.vbproj index 65a2463afa30b1dbea50003ab60d14bd1d88c6bd..81eb3e92069c5717a1224323626cf39b986a075b 100644 --- a/CSE/CSE.vbproj +++ b/CSE/CSE.vbproj @@ -201,6 +201,7 @@ </EmbeddedResource> </ItemGroup> <ItemGroup> + <None Include="App.config" /> <None Include="My Project\Application.myapp"> <Generator>MyApplicationCodeGenerator</Generator> <LastGenOutput>Application.Designer.vb</LastGenOutput> diff --git a/CSE/Classes/cJsonFile.vb b/CSE/Classes/cJsonFile.vb index fbf18e6db537c72865a4163050ee1769581dc94e..8db384943e4dc2bacedfa2e23b93f60ffb605ff5 100644 --- a/CSE/Classes/cJsonFile.vb +++ b/CSE/Classes/cJsonFile.vb @@ -14,6 +14,8 @@ Imports System.Globalization ''' so it can be used to debug input-files by manually setting it to 'true' with a text-editor. ''' </remarks> Public MustInherit Class cJsonFile + Implements ICloneable + Shared dateFrmt As String = "yyyy/MM/dd HH:mm:ss zzz" ''' <summary>The json-content for a json-file structured in Header/Body</summary> @@ -23,16 +25,17 @@ Public MustInherit Class cJsonFile "Header": { "Title": null, "FileVersion": null, - "AppVersion": null, - "ModifiedDate": null, - "Strict": false, + "AppVersion": null, + "ModifiedDate": null, + "StrictBody": false, }, - "Body": {} + "Body": null }</json>.Value End Function ''' <summary>The schema for a json-file structured in Header/Body</summary> - Protected Shared Function JSchemaStr_File() As String + Protected Shared Function JSchemaStr_Header(ByVal isStrict As Boolean) As String + Dim requireAll As String = IIf(isStrict, "true", "false") Return <json>{ "title": "vecto header/body json-file", "type": "object", "additionalProperties": false, @@ -43,6 +46,7 @@ Public MustInherit Class cJsonFile "properties": { "Title": { "type": "string", + "required": <%= requireAll %>, }, "FileVersion": { "type": "string", @@ -50,18 +54,24 @@ Public MustInherit Class cJsonFile }, "AppVersion": { "type": "string", - "required": true, + "required": <%= requireAll %>, }, "ModifiedDate": { "type": "string", - "required": true, - "description": "Last modified date", + "description": "Last-modification date", + "required": <%= requireAll %>, }, - "Strict": { + "StrictBody": { "title": "Validate body strictly", "type": "boolean", - "required": false, "description": "When True, the 'Body' does not accept unknown properties.", + "default": false, + }, + "BodySchema": { + "title": "Body schema", + "type": ["boolean", "object"], + "description": "When set to True, it is replaced by the Body's schema on the next save, so as to provide users with documentation on the file.", + "default": false, }, } }, @@ -72,15 +82,19 @@ Public MustInherit Class cJsonFile ''' <summary>When a new file is Created or Stored, the contents return from this method is overlayed on /Header/*</summary> ''' <remarks>The result json must be valid overlaying this header.</remarks> - Protected MustOverride ReadOnly Property HeaderOverlay() As JObject + Protected MustOverride Function HeaderOverlay() As JObject ''' <summary>When a instance_with_defauls is Created, it gets its /Body from this method</summary> ''' <remarks>The result json must be valid after replacing with this body.</remarks> - Protected MustOverride ReadOnly Property BodyContent() As JObject + Protected MustOverride Function BodyContent() As JObject - ''' <summary>The schema used to validate the /Body</summary> + ''' <summary>When a instance_with_defauls is Created, it gets its /Body from this method</summary> + ''' <remarks>The result json must be valid after replacing with this body.</remarks> + Protected MustOverride Function BodySchema() As JObject + + ''' <summary>Invoked by this class for subclasses to validate file</summary> ''' <remarks>To signify validation-failure it can throw an exception or add err-messages into the supplied list</remarks> - Protected MustOverride Sub ValidateVersionAndBody(ByVal fileVersion As String, ByVal body As JObject, ByVal allowsAdditionalProps As Boolean, ByVal validateMsgs As IList(Of String)) + Protected MustOverride Sub ValidateBody(ByVal isStrict As Boolean, ByVal validateMsgs As IList(Of String)) Protected Json_Contents As JObject @@ -94,6 +108,8 @@ Public MustInherit Class cJsonFile ''' <param name="skipValidation">When false (the default), validates json-contents in both cases (reading or creating-defaults)</param> ''' <remarks></remarks> Protected Sub New(Optional ByVal inputFilePath As String = Nothing, Optional ByVal skipValidation As Boolean = False) + Dim strictHeader = True + If (inputFilePath Is Nothing) Then Dim jstr = JsonStr_FileContents() Me.Json_Contents = JObject.Parse(jstr) @@ -103,66 +119,91 @@ Public MustInherit Class cJsonFile Else fInfWarErrBW(5, False, format("Reading JSON-file({0})...", inputFilePath)) Me.Json_Contents = ReadJsonFile(inputFilePath) + strictHeader = False '' Try to read even bad headers. End If If Not skipValidation Then - Me.Validate() + Me.Validate(strictHeader) End If End Sub - Protected Sub UpdateHeader() + ''' <summary>Validates and Writing to the config file</summary> + Sub Store(ByVal fpath As String) + Me.UpdateHeader() + + Me.Validate(Me.StrictBody) + WriteJsonFile(fpath, Json_Contents) + End Sub + + + Sub UpdateHeader() Dim h As JObject = Me.Header h("ModifiedDate") = DateTime.Now.ToString(dateFrmt) h("AppVersion") = AppVers - If h("Strict") is Nothing then - h("Strict") = False + If h("StrictBody") Is Nothing Then + h("StrictBody") = False End If + '' Add schema for documenting file according to its boolean(/Header/BodySchema) if any or failback to global prefs:/Body/IncludeSchemas. + '' + Dim bodySchema = h("BodySchema") + Dim includeSchema = False + If bodySchema Is Nothing AndAlso AppPreferences IsNot Nothing Then + includeSchema = AppPreferences.IncludeSchemas + ElseIf bodySchema IsNot Nothing AndAlso bodySchema.Type = JTokenType.Boolean Then + includeSchema = bodySchema + End If + If includeSchema Then + h("BodySchema") = Me.BodySchema + End If + + '' Overlay subclass's properties. + '' For Each child As KeyValuePair(Of String, JToken) In Me.HeaderOverlay h(child.Key) = child.Value Next End Sub - ''' <summary>Validates and Writing to the config file</summary> - Sub Store(ByVal fpath As String) - UpdateHeader() - - Validate(Me.Strict) - WriteJsonFile(fpath, Json_Contents) - End Sub - - - ''' <exception cref="SystemException">includes all validation errors</exception> - ''' <param name="isStrict">when True, no additional json-properties allowed in the data, when nothing, use value from Header</param> - Friend Sub Validate(Optional ByVal isStrict As Boolean? = Nothing) + ''' <exception cref="FormatException">includes all validation errors</exception> + ''' <param name="strictHeader">when false, relaxes Header's schema (used on Loading to be more accepting)</param> + Friend Sub Validate(Optional ByVal strictHeader As Boolean = False) Dim validateMsgs As IList(Of String) = New List(Of String) - Dim fileSchema = JsonSchema.Parse(JSchemaStr_File()) ' TODO: Lazily create this schema once + + Dim fileSchema = JsonSchema.Parse(JSchemaStr_Header(strictHeader)) '' Validate Header '' ValidateJson(Me.Json_Contents, fileSchema, validateMsgs) If (validateMsgs.Any()) Then - Throw New SystemException(format("Invalid File-format due to: {0}", String.Join(vbCrLf, validateMsgs))) + Throw New FormatException(format("Validating /Header failed due to: {0}", String.Join(vbCrLf, validateMsgs))) End If + Dim dummy = New cSemanticVersion(Me.FileVersion) '' Just to ensure its syntax. - '' Validate Body - '' - Dim allowsAdditionalProps As Boolean = Not IIf(isStrict Is Nothing, Me.Strict, isStrict) - Me.ValidateVersionAndBody(Me.FileVersion, Me.Body, allowsAdditionalProps, validateMsgs) + '' Validate Body by subclass + Dim hsb = Me.Header("StrictBody") + Dim strictBody As Boolean = IIf(hsb Is Nothing, AppPreferences.StrictBodies, hsb) + Me.ValidateBody(strictBody, validateMsgs) If (validateMsgs.Any()) Then - Throw New SystemException(format("Invalid Body-format due to: {0}", String.Join(vbCrLf, validateMsgs))) + Throw New FormatException(format("Validating /Body failed due to: {0}", String.Join(vbCrLf, validateMsgs))) End If End Sub + Public Function Clone() As Object Implements ICloneable.Clone + Dim nobj As cJsonFile = Me.MemberwiseClone() + nobj.Json_Contents = Me.Json_Contents.DeepClone() + + Return nobj + End Function + Public Overrides Function Equals(ByVal obj As Object) As Boolean If obj Is Nothing OrElse Not Me.GetType().Equals(obj.GetType()) Then Return False Else - Return Me.Json_Contents.Equals(DirectCast(obj, cJsonFile).Json_Contents) + Return JToken.DeepEquals(Me.Json_Contents, DirectCast(obj, cJsonFile).Json_Contents) End If End Function @@ -201,11 +242,13 @@ Public MustInherit Class cJsonFile End Get End Property - Public ReadOnly Property Strict As Boolean + Public ReadOnly Property StrictBody As Boolean Get - Return Me.Header("Strict") + Dim value = Me.Body("StrictBody") + Return IIf(value Is Nothing, False, value) End Get End Property + #End Region ' "json props" End Class diff --git a/CSE/Classes/cPreferences.vb b/CSE/Classes/cPreferences.vb index f08c71c268ddefb803127dc11b32d21c6f897067..78d0c77c16291a6bead8807cbf0488e1fbca5893 100644 --- a/CSE/Classes/cPreferences.vb +++ b/CSE/Classes/cPreferences.vb @@ -6,30 +6,30 @@ Imports Newtonsoft.Json.Schema Public Class cPreferences Inherits cJsonFile - Protected Overrides ReadOnly Property HeaderOverlay() As JObject - Get - Return JObject.Parse(<json>{ + Protected Overrides Function HeaderOverlay() As JObject + Return JObject.Parse(<json>{ "Title": "vecto-cse PREFERENCES", "FileVersion": "1.0.0", }</json>.Value) - End Get - End Property + End Function ' Default-prefs specified here. - Protected Overrides ReadOnly Property BodyContent() As JObject - Get - Return JObject.Parse(<json>{ + Protected Overrides Function BodyContent() As JObject + Return JObject.Parse(<json>{ "WorkingDir": null, "WriteLog": true, "LogSize": 2, "LogLevel": 5, "Editor": "notepad.exe", }</json>.Value) - End Get - End Property + End Function + + Protected Overrides Function BodySchema() As JObject + Return JObject.Parse(JSchemaStr()) + End Function ''' <param name="allowAdditionalProps">when false, more strict validation</param> - Protected Function JSchemaStr(ByVal allowAdditionalProps As Boolean) As String + Protected Function JSchemaStr(Optional ByVal allowAdditionalProps As Boolean = True) As String Dim allowAdditionalProps_str As String = IIf(allowAdditionalProps, "true", "false") Return <json>{ "title": "Schema for vecto-cse PREFERENCES", @@ -40,7 +40,7 @@ Public Class cPreferences "type": ["string", "null"], "required": false, "default": null, - "description": "Last used Working Directory Path for input/output files, when null/empty, uses app's dir (default: null)", + "description": "Last used Working Directory Path for input/output files, when null/empty, uses app's dir", }, "WriteLog": { "type": "boolean", @@ -62,11 +62,23 @@ Public Class cPreferences "required": true, "description": "Path (or filename if in PATH) of some (text or JSON) editor (default: 'notepad.exe')", }, + "StrictBodies": { + "type": "boolean", + "default": false, + "description": "The global-default to use when reading JSON-files without a /Header/StrictBody property.", + }, + "IncludeSchemas": { + "type": "boolean", + "default": true, + "description": "When true, provides documentation to json-files by populating their Header/BodySchema element when storing them, unless it is already set to false.", + }, } }</json>.Value End Function + + ''' <summary>Reads from file or creates defaults</summary> ''' <param name="inputFilePath">If unspecifed, default prefs used, otherwise data read from file</param> ''' <remarks>See cJsonFile() constructor</remarks> @@ -76,21 +88,21 @@ Public Class cPreferences ''' <exception cref="SystemException">includes all validation errors</exception> - ''' <param name="allowAdditionalProps">when False, no additional json-properties allowed in the data, when nothing, use value from Header</param> - Protected Overrides Sub ValidateVersionAndBody(ByVal fileVersion As String, ByVal body As JObject, ByVal allowAdditionalProps As Boolean, ByVal validateMsgs As IList(Of String)) + ''' <param name="strictBody">when True, no additional json-properties allowed in the data, when nothing, use value from Header</param> + Protected Overrides Sub ValidateBody(ByVal strictBody As Boolean, ByVal validateMsgs As IList(Of String)) '' Check version '' Dim fromVersion = "1.0.0--" Dim toVersion = "2.0.0--" ' The earliest pre-release. - If Not IsSemanticVersionsSupported(fileVersion, fromVersion, toVersion) Then - validateMsgs.Add(format("Unsupported FileVersion({0}, was not in between [{1}, {2})", fileVersion, fromVersion, toVersion)) + If Not IsSemanticVersionsSupported(Me.FileVersion, fromVersion, toVersion) Then + validateMsgs.Add(format("Unsupported FileVersion({0}, was not in between [{1}, {2})", FileVersion, fromVersion, toVersion)) Return End If '' Check schema '' - Dim schema = JsonSchema.Parse(JSchemaStr(allowAdditionalProps)) ' TODO: Lazily create schemas once - ValidateJson(body, schema, validateMsgs) + Dim schema = JsonSchema.Parse(JSchemaStr(Not strictBody)) + ValidateJson(Me.Body, schema, validateMsgs) End Sub @@ -191,5 +203,26 @@ Public Class cPreferences Me.Body("Editor") = value End Set End Property + + Public Property StrictBodies As Boolean + Get + Dim value = Me.Body("StrictBodies") + Return IIf(value Is Nothing, False, value) + End Get + Set(ByVal value As Boolean) + Me.Body("StrictBodies") = value + End Set + End Property + + Public Property IncludeSchemas As Boolean + Get + Dim value = Me.Body("IncludeSchemas") + Return IIf(value Is Nothing, False, value) + End Get + Set(ByVal value As Boolean) + Me.Body("IncludeSchemas") = value + End Set + End Property + #End Region ' "json props" End Class diff --git a/CSE/Classes/cSemanticVersion.vb b/CSE/Classes/cSemanticVersion.vb index cf3195e02ab5c3d21963fbbe6e3be109b25122eb..c1944642fd76f2afa3cfcc2c353feb5a63252ce1 100644 --- a/CSE/Classes/cSemanticVersion.vb +++ b/CSE/Classes/cSemanticVersion.vb @@ -64,6 +64,18 @@ Public NotInheritable Class cSemanticVersion "^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(-(?<prerelease>[A-Za-z0-9\-\.]+))?(\+(?<build>[A-Za-z0-9\-\.]+))?$", _ RegexOptions.Compiled Or RegexOptions.Singleline) + ' ''' <summary> + ' ''' A utility regex used to parse loose version-strings to semantic-versions. + ' ''' </summary> + ' ''' <remarks>See http://search.cpan.org/dist/SemVer/lib/SemVer.pm</remarks> + 'Private Shared ReadOnly regex_1stPart As New Regex( _ + ' "^\s*(?:v(?:e(?:r(?:s(?:i(?:o(?:n)?)?)?)?)?)?)?\s*(?<major>\d+)(?:\.(?<nums>\d+))*(?<prerelease>[^+ ]+)?(\+(?<build>\S+))?", _ + ' RegexOptions.Compiled Or RegexOptions.Singleline, RegexOptions.IgnoreCase`) + + 'Public Shared Function parse(ByVal version As String) As cSemanticVersion + 'End Function + + ''' <summary> ''' Initializes a new instance of the <see cref="cSemanticVersion"/> class. ''' </summary> diff --git a/CSE/GUI/F_Main.Designer.vb b/CSE/GUI/F_Main.Designer.vb index fafda317a06acf5f67cf44994dfda7c58ae93a0c..2cee62b6f48fb6ed707c98bf4eec05fe7d871b6c 100644 --- a/CSE/GUI/F_Main.Designer.vb +++ b/CSE/GUI/F_Main.Designer.vb @@ -335,19 +335,19 @@ Partial Class F_Main ' Me.ToolStripMenuItemLog.Image = Global.CSE.My.Resources.Resources.Log_File Me.ToolStripMenuItemLog.Name = "ToolStripMenuItemLog" - Me.ToolStripMenuItemLog.Size = New System.Drawing.Size(152, 22) + Me.ToolStripMenuItemLog.Size = New System.Drawing.Size(144, 22) Me.ToolStripMenuItemLog.Text = "Open LogFile" ' 'ToolStripSeparator3 ' Me.ToolStripSeparator3.Name = "ToolStripSeparator3" - Me.ToolStripSeparator3.Size = New System.Drawing.Size(149, 6) + Me.ToolStripSeparator3.Size = New System.Drawing.Size(141, 6) ' 'ToolStripMenuItemOption ' Me.ToolStripMenuItemOption.Image = Global.CSE.My.Resources.Resources.Optionen Me.ToolStripMenuItemOption.Name = "ToolStripMenuItemOption" - Me.ToolStripMenuItemOption.Size = New System.Drawing.Size(152, 22) + Me.ToolStripMenuItemOption.Size = New System.Drawing.Size(144, 22) Me.ToolStripMenuItemOption.Text = "Preferences" ' 'InfoToolStripMenuItem @@ -2409,7 +2409,7 @@ Partial Class F_Main Me.TBDeltaXMax.Text = "10" Me.TBDeltaXMax.TextAlign = System.Windows.Forms.HorizontalAlignment.Right ' - 'CSEMain + 'F_Main ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font @@ -2419,10 +2419,12 @@ Partial Class F_Main Me.Controls.Add(Me.Label1) Me.Controls.Add(Me.PictureBox1) Me.Controls.Add(Me.MenuStrip1) + Me.DataBindings.Add(New System.Windows.Forms.Binding("Location", Global.CSE.My.MySettings.Default, "F_Main_location", True, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)) Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon) + Me.Location = Global.CSE.My.MySettings.Default.F_Main_location Me.MainMenuStrip = Me.MenuStrip1 Me.MinimumSize = New System.Drawing.Size(686, 717) - Me.Name = "CSEMain" + Me.Name = "F_Main" Me.Text = "VECTO Constant Speed Evaluator" Me.MenuStrip1.ResumeLayout(False) Me.MenuStrip1.PerformLayout() diff --git a/CSE/GUI/F_Preferences.designer.vb b/CSE/GUI/F_Preferences.designer.vb index b13b991b0c3d47f9e444a5c404918f7fbc82ac91..cf3bb3ea61d437c44365b5741d0b8ed4ff04a494 100644 --- a/CSE/GUI/F_Preferences.designer.vb +++ b/CSE/GUI/F_Preferences.designer.vb @@ -40,6 +40,7 @@ Partial Class F_Preferences Me.GroupBoxNotepad = New System.Windows.Forms.GroupBox() Me.ButtonSelectNotepad = New System.Windows.Forms.Button() Me.TextBoxNotepad = New System.Windows.Forms.TextBox() + Me.ButtonReload = New System.Windows.Forms.Button() Me.GroupBoxWorDir.SuspendLayout() Me.GroupBoxInterface.SuspendLayout() Me.TabControl1.SuspendLayout() @@ -78,7 +79,7 @@ Partial Class F_Preferences 'ButtonOK ' Me.ButtonOK.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) - Me.ButtonOK.Location = New System.Drawing.Point(356, 235) + Me.ButtonOK.Location = New System.Drawing.Point(436, 235) Me.ButtonOK.Name = "ButtonOK" Me.ButtonOK.Size = New System.Drawing.Size(75, 23) Me.ButtonOK.TabIndex = 0 @@ -89,7 +90,7 @@ Partial Class F_Preferences ' Me.ButtonCancel.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) Me.ButtonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel - Me.ButtonCancel.Location = New System.Drawing.Point(436, 235) + Me.ButtonCancel.Location = New System.Drawing.Point(99, 235) Me.ButtonCancel.Name = "ButtonCancel" Me.ButtonCancel.Size = New System.Drawing.Size(75, 23) Me.ButtonCancel.TabIndex = 1 @@ -215,6 +216,16 @@ Partial Class F_Preferences Me.TextBoxNotepad.Size = New System.Drawing.Size(444, 20) Me.TextBoxNotepad.TabIndex = 1 ' + 'ButtonReload + ' + Me.ButtonReload.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) + Me.ButtonReload.Location = New System.Drawing.Point(18, 235) + Me.ButtonReload.Name = "ButtonReload" + Me.ButtonReload.Size = New System.Drawing.Size(75, 23) + Me.ButtonReload.TabIndex = 0 + Me.ButtonReload.Text = "Reload" + Me.ButtonReload.UseVisualStyleBackColor = True + ' 'F_Preferences ' Me.AcceptButton = Me.ButtonOK @@ -224,6 +235,7 @@ Partial Class F_Preferences Me.ClientSize = New System.Drawing.Size(515, 270) Me.Controls.Add(Me.TabControl1) Me.Controls.Add(Me.ButtonCancel) + Me.Controls.Add(Me.ButtonReload) Me.Controls.Add(Me.ButtonOK) Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon) @@ -260,4 +272,5 @@ Partial Class F_Preferences Friend WithEvents ButtonSelectNotepad As System.Windows.Forms.Button Friend WithEvents TextBoxNotepad As System.Windows.Forms.TextBox Friend WithEvents LabelInfo As System.Windows.Forms.Label + Friend WithEvents ButtonReload As System.Windows.Forms.Button End Class diff --git a/CSE/GUI/F_Preferences.vb b/CSE/GUI/F_Preferences.vb index 6597f9905b83c53984ade84d92746c90c23ca501..c1f7094b555f5f1230918620a4d19ac4423c1b15 100644 --- a/CSE/GUI/F_Preferences.vb +++ b/CSE/GUI/F_Preferences.vb @@ -3,13 +3,13 @@ Public Class F_Preferences ' Load confic Private Sub F03_Options_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load ' Allocate the data from the confic file (Only by the start) - prefs_PopulateFrom(AppPreferences) + UI_PopulateFrom(AppPreferences) ' Define the Infolable TextBoxMSG_TextChanged(sender, e) End Sub - Private Sub prefs_PopulateFrom(ByVal value As cPreferences) + Private Sub UI_PopulateFrom(ByVal value As cPreferences) ' Allocate the data from the confic file (Only by the start) Me.TextBoxWorDir.Text = value.WorkingDir Me.TextBoxNotepad.Text = value.Editor @@ -18,17 +18,14 @@ Public Class F_Preferences Me.TextBoxLogSize.Text = value.LogSize End Sub - Private Function prefs_PopulateTo() As cPreferences - Dim value = New cPreferences() - + Private Sub UI_PopulateTo(ByVal value As cPreferences) value.WorkingDir = Me.TextBoxWorDir.Text value.Editor = Me.TextBoxNotepad.Text value.WriteLog = Me.CheckBoxWriteLog.Checked value.LogLevel = Me.TextBoxMSG.Text value.LogSize = Me.TextBoxLogSize.Text - Return value - End Function + End Sub ' Open the filebrowser for selecting the working dir Private Sub ButtonWorDir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSelectWorDir.Click @@ -38,30 +35,41 @@ Public Class F_Preferences End Sub ' Ok button - Private Sub ButtonOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonOK.Click - ' Write new prefs only if changed. - ' - Dim newPrefs = prefs_PopulateTo() - If (Not AppPreferences.Equals(newPrefs) Or Not System.IO.File.Exists(PreferencesPath)) Then + Private Sub StorePrefs(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonOK.Click + Try + Dim newPrefs As cPreferences = AppPreferences.Clone() + UI_PopulateTo(newPrefs) + ' Write the config file - Try - newPrefs.Store(PreferencesPath) ' Also create 'config' dir if not exists - AppPreferences = newPrefs - - ' Message for the restart of VECTO - RestartN = True - fInfWarErr(7, False, "Preferences have changed. Ask to restart.") ' XXX: Why double-log for restartng-vecto here?? - fInfWarErr(7, True, format("Preferences have changed.\n Do you want to restart VECTO now?")) - - Catch ex As Exception - fInfWarErr(9, False, format("Failed storing Preferences({0}) due to: {1} \n Preferences left unmodified!", PreferencesPath, ex.Message), ex) - End Try - End If + newPrefs.Store(PreferencesPath) + AppPreferences = newPrefs ' Replace active prefs if successful. + + ' Message for the restart of VECTO + RestartN = True + fInfWarErr(7, False, "Preferences have changed. Ask to restart.") + fInfWarErr(7, True, format("Preferences have changed.\nDo you want to restart VECTO now?")) + Catch ex As Exception + fInfWarErr(9, False, format("Failed storing Preferences({0}) due to: {1} \n Preferences left unmodified!", PreferencesPath, ex.Message), ex) + End Try ' Close the window Me.Close() End Sub + ' Ok button + Private Sub ReloadPrefs(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonReload.Click + Try + AppPreferences = New cPreferences(PreferencesPath) + UI_PopulateFrom(AppPreferences) + + ' Define the Infolable + TextBoxMSG_TextChanged(sender, e) + Catch ex As Exception + fInfWarErr(9, False, format("Failed loading Preferences({0}) due to: {1}", _ + PreferencesPath, ex.Message), ex) + End Try + End Sub + ' Close button Private Sub ButtonCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonCancel.Click Me.Close() diff --git a/CSE/My Project/Settings.Designer.vb b/CSE/My Project/Settings.Designer.vb index 1eae091cc3de99b68b1aede8db34ee66ee4b60c1..7dad854a95ce9e6dd90d61705bfc0e3264b0e730 100644 --- a/CSE/My Project/Settings.Designer.vb +++ b/CSE/My Project/Settings.Designer.vb @@ -53,6 +53,18 @@ Namespace My Return defaultInstance End Get End Property + + <Global.System.Configuration.UserScopedSettingAttribute(), _ + Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _ + Global.System.Configuration.DefaultSettingValueAttribute("0, 0")> _ + Public Property F_Main_location() As Global.System.Drawing.Point + Get + Return CType(Me("F_Main_location"),Global.System.Drawing.Point) + End Get + Set + Me("F_Main_location") = value + End Set + End Property End Class End Namespace diff --git a/CSE/My Project/Settings.settings b/CSE/My Project/Settings.settings index 85b890b3c66b9beee248abaddd2ec71f8b1df2b2..0fe4a001e405f6037d0cfd69b9defb489742185e 100644 --- a/CSE/My Project/Settings.settings +++ b/CSE/My Project/Settings.settings @@ -1,7 +1,9 @@ <?xml version='1.0' encoding='utf-8'?> -<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" UseMySettingsClassName="true"> - <Profiles> - <Profile Name="(Default)" /> - </Profiles> - <Settings /> -</SettingsFile> +<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="My" GeneratedClassName="MySettings" UseMySettingsClassName="true"> + <Profiles /> + <Settings> + <Setting Name="F_Main_location" Type="System.Drawing.Point" Scope="User"> + <Value Profile="(Default)">0, 0</Value> + </Setting> + </Settings> +</SettingsFile> \ No newline at end of file diff --git a/CSE/Settings.vb b/CSE/Settings.vb new file mode 100644 index 0000000000000000000000000000000000000000..94ac0c7ac39c3d8a1a715b7dd1c99f9e6dcb9514 --- /dev/null +++ b/CSE/Settings.vb @@ -0,0 +1,11 @@ + +Namespace My + + 'This class allows you to handle specific events on the settings class: + ' The SettingChanging event is raised before a setting's value is changed. + ' The PropertyChanged event is raised after a setting's value is changed. + ' The SettingsLoaded event is raised after the setting values are loaded. + ' The SettingsSaving event is raised before the setting values are saved. + Partial Friend NotInheritable Class MySettings + End Class +End Namespace