kotlin-graphics / imgui

Bloat-free Immediate Mode Graphical User interface for JVM with minimal dependencies (rewrite of dear imgui)
MIT License
594 stars 37 forks source link

Introduce type-safe Flags and FlagArray to no longer use raw ints #186

Closed kyay10 closed 1 year ago

kyay10 commented 1 year ago

This is quite a big refactoring...

Building on the previous work of using a Flag interface, this PR changes all the XFlags type aliases from being Int to being Flag<XFlags>. That, combined with a private value class Flags and a value class FlagArray, allows using type-safe flag combinations everywhere, while still having the ever-useful and, or, wo, has, etc methods.

While implementing this, I genuinely found multiple places where the code was using the wrong enum type of Flag or was checking if flags of totally separate types were equal. It was hence helpful in catching those bugs and remedying them quickly. This also removed a lot of unnecessary range checks we were doing on ints.

The only downside of using this PR is that checking flags for equality using == and != is broken. This is because you can't override equals in enums nor in value classes. For now, I added infix fun eq/notEq to mitigate that problem. However, a more intrusive solution (that will fix == checks) is to convert all the Flag enums to sealed classes (This is simply an IDE intention and so it's very automatic) with a base class that has equals overridden, and change value class Flags to a non-value class. Note that in Kotlin 1.9.0 value classes will be able to override equals. I'm not sure whether the current eq/notEq approach is too finicky, but it surely is less error-prone than comparing raw Ints.

Finally, this PR also introduces a useful MutableReference type that extends KMutableProperty0. That type might be the beginning of relying less on global mutable vars like _b and friends, and instead created MutableReferences locally., but that shall come in another PR.

elect86 commented 1 year ago

Awesome, thanks!