-
-
Notifications
You must be signed in to change notification settings - Fork 345
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initialize checkboxes to desired value at creation #2184
Conversation
GUI/MainModList.cs
Outdated
: mod.IsInstalled | ||
} : new DataGridViewTextBoxCell() { | ||
Value = mod.IsAutodetected ? "AD" : "-", | ||
ReadOnly = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line causes an exception (Windows):
Unhandled exception:
System.InvalidOperationException: ReadOnly property of a cell cannot be set before it is added to a row.
at System.Windows.Forms.DataGridViewCell.set_ReadOnly(Boolean value)
at CKAN.MainModList.ConstructModList(IEnumerable1 modules, List
1 mc, Boolean refreshAll, Boolean hideEpochs) in S:\KSP\CKAN\CKAN\GUI\MainModList.cs:line 537
at CKAN.Main._UpdateModsList(Boolean repo_updated, List1 mc) in S:\KSP\CKAN\CKAN\GUI\MainModList.cs:line 186 at CKAN.Main.<>c__DisplayClass233_0.<UpdateModsList>b__0() in S:\KSP\CKAN\CKAN\GUI\MainModList.cs:line 143 at CKAN.Util.Invoke[T](T obj, Action action) in S:\KSP\CKAN\CKAN\GUI\Util.cs:line 28 at CKAN.Main.UpdateModsList(Boolean repo_updated, List
1 mc) in S:\KSP\CKAN\CKAN\GUI\MainModList.cs:line 143
at CKAN.Main.CurrentInstanceUpdated() in S:\KSP\CKAN\CKAN\GUI\Main.cs:line 441
at CKAN.Main.OnLoad(EventArgs e) in S:\KSP\CKAN\CKAN\GUI\Main.cs:line 347
at System.Windows.Forms.Form.OnCreateControl()
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.WmShowWindow(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Form.WmShowWindow(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
GUI/MainModList.cs
Outdated
: false | ||
} : new DataGridViewTextBoxCell() { | ||
Value = "-", | ||
ReadOnly = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line causes an exception (Windows) - see details in previous comment.
GUI/MainModList.cs
Outdated
@@ -547,9 +554,6 @@ public IEnumerable<DataGridViewRow> ConstructModList(IEnumerable<GUIMod> modules | |||
|
|||
item.Cells.AddRange(selecting, updating, name, author, installVersion, latestVersion, compat, size, desc); | |||
|
|||
selecting.ReadOnly = !mod.IsInstallable(); | |||
updating.ReadOnly = !mod.IsInstallable() || !mod.HasUpdate; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These lines are still required given the exceptions thrown above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UPDATE
After a recompile I can no longer reproduce the below.
Also, I'm not sure why we set "ReadOnly" at all - if you try double-clicking on the cell, it ends up throwing a core exception (not in managed code), regardless of whether or not it's set as ReadOnly.
Unhandled exception:
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'Main'.
at System.Windows.Forms.Control.CreateHandle()
at System.Windows.Forms.Form.CreateHandle()
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.Control.SetVisibleCore(Boolean value)
at System.Windows.Forms.Form.SetVisibleCore(Boolean value)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at CKAN.Main..ctor(String[] cmdlineArgs, GUIUser user, Boolean showConsole) in S:\KSP\CKAN\CKAN\GUI\Main.cs:line 249
at CKAN.GUI.Main_(String[] args, Boolean showConsole) in S:\KSP\CKAN\CKAN\GUI\Program.cs:line 37
at CKAN.GUI.Main(String[] args) in S:\KSP\CKAN\CKAN\GUI\Program.cs:line 17
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, on further inspection I don't think we need to set ReadOnly. The entire rest of the row consists of DataGridViewTextBoxCell
objects without ReadOnly set, so that should be fine for these cells as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh, just re-tested without setting ReadOnly, and yes we do. Not sure why the other cells don't enter text-edit mode (perhaps it's a column-setting?) on double-click, but these ones do and it causes issues if you start typing into them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, good point. The columns probably have to be editable to allow the user to change the checkboxes. I just deleted that commit, so now it's back to how you had it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here we go, in Main.Designer.cs:469-534 all columns except the first two are set to read-only.
97e7e46
to
0becd7b
Compare
0becd7b
to
0c3f708
Compare
This is a possible fix for #2162, and an alternative to #2183.
That issue happens because after a failed install/upgrade attempt,
Main.PostInstallMods
rebuilds the mod list and then re-applies theModChanges
object's changes to the checkboxes. But one of the checkboxes may no longer be a checkbox, and trying to access it as one causes a null reference exception.This pull request eliminates the possibility of this happening. Rather than generating the check boxes in a default state and then applying a
ModChanges
after the fact, we now pass theModChanges
directly toMain.ConstructModList
and use it to control the initial checkbox state, so the row object starts out consistent with theModChanges
.ConstructModList
is cleaned up a bit to make this happen. Previously it created the checkbox cells, set their values, and potentially set them as read-only in three separate statements per checkbox. Each of those lines has to have its own Boolean check for whether to show a checkbox or a "-" for actions that aren't allowed (incompatible mods, for example). If those checks ever got out of sync, we would risk the same kind of exceptions that were happening in this issue by treating a non-checkbox as a checkbox. And they sort of were out of sync! The creation of the Update checkbox depended onmod.HasUpdate && !mod.IsAutodetected
, but the setting of its value used!mod.Isinstallable() || !mod.HasUpdate
, which, in addition to being confusing, is not exactly the same condition.Now each checkbox is set up in one single step; we create the checkbox and set its value property simultaneously using the {Property=value} syntax, under one single Boolean check, so there is no risk of them executing out of sync. (
ReadOnly
still has to be set separately due to .NET raising an exception, see review comments for details.)As for the reason why the update checkbox was no longer a checkbox, @mwerle reports that
AvailableModule.module_versions
sometimes flipped its sort order, which caused it to consider the wrong mod version as the most recent, and therefore miss an available upgrade. This object is aSortedDictionary
initialized to sort in descending order, but it's also aninternal [JsonProperty]
, so it's possible that the deserializer (or some other object) might replace it with aSortedDictionary
that uses ascending order instead (which is the default), which could cause such issues.Since we can't force all objects everywhere to initialize their
SortedDictionary
objects to descending order before assigning them toAvailableModule.module_versions
,AvailableModule
is updated to use an ascending order sort instead. This way it will work even if some other object replaces the dictionary.In addition, some weird or confusing things are cleaned up:
GUIMod.IsInstalled()
was implemented as an extension method inUtil.cs
, which made it harder to find without doing a find-in-files, and is not necessary because we own theGUIMod
class and can do whatever we like with it. This method is now moved to being a normal public instance method ofGUIMod
.GUIMod.IsInstalled()
was also fairly hard to understand, consisting of an OR of an OR expression and an AND expression, sharing one term, one of which had a NOT on the outside, and the other had a NOT on the inside. If you could tell what it did by glancing at it, I salute you. Now it's simplified to an equivalent sequence of checks that I think is much easier to read, with explanatory comments and XML documentation.