Thursday, March 28, 2019

Fixing RichTextBox's ContentsResized boundaries with NBSPs

Previous I noticed that RichTextBox does not count trailing spaces as part of the contents when determining the needed size for the ContentsResized event. It does, however, count non-breaking spaces (NBSPs), which look identical to normal spaces. When the text in the text box is changed, I check whether the text contains a space, and if so, replace them all with NBSPs (character U+00A0). The selection/position needs to be saved before altering the text and restored afterward, otherwise the cursor will jump to the beginning. When using the text for other purposes, the NBSPs are first replaced with normal spaces.

The ContentsResized event is more accurate than GetPreferredSize

I'm trying to make a RichTextBox in a Windows Forms application grow and shrink to exactly contain its text. At first I tried TextRenderer.MeasureText, but it gave somewhat larger measurements than the text actually took. Calling GetPreferredSize on the control produced similarly wrong sizes. A Stack Overflow answer suggested listening for the ContentsResized event and using the provided rectangle. That indeed works after disabling WordWrap and scrollbars on the text box. The only downfall is that this measurer doesn't count trailing spaces in the rectangle, so as the user types a new word at the end the text jitters a bit.

Thursday, March 21, 2019

Testing SharedPreferences with Robolectric

I was looking for a way to simulate SharedPreferences for a Robolectric-tested application. It seems that the suggested way to do this involves AndroidX, a separate testing framework, which needs to be added as a dependency:

testImplementation 'androidx.test:core:1.1.0'

Then the application context can be retrieved with ApplicationProvider.getApplicationContext(), and a SharedPreferences can be obtained from getSharedPreferences as usual.

Wednesday, March 20, 2019

AutoScrollPosition coordinates need to be negated when restored

One of my Windows Forms applications has a Panel that auto-scrolls to contain many dynamically inserted controls. Sometimes its controls are cleared and regenerated. I want that to be seamless for the user, so the scroll position should be preserved. I tried recording the Value of HorizontalScroll and VerticalScroll and restoring those afterward, and that partially worked but didn't render the scrollbars in the correct place. I also tried saving/restoring AutoScrollPosition but that just left the scroll view in the upper left. I eventually found a Microsoft forum thread somewhere that said AutoScrollPosition is the property to use in this case, but the point set after the reset must be the negation (both X and Y coordinates made negative) of the original point. I'm not sure why that works, but it does.

Sunday, March 17, 2019

When Robolectric tests crash with "window creation failed"

Some students found that Robolectric tests on their Android project crashed with "window creation failed." This seems to be caused by trying to use findViewById before the view tree is ready. Most likely that's going on in an initializer on the same line as an instance variable declaration in an activity class.

Making Android Studio forget Git credentials

If the credentials used for Git are changed and Android Studio (or IntelliJ) has the old ones saved, Git operations will fail. If the repository is private, the error message may say that the repository doesn't exist. To fix this, the old Git credentials need to be removed. On Windows, this is done in the Credential Manager section of Control Panel. Once the Git-related "generic credential" entries are removed, Android Studio should re-prompt for credentials on the next repository operation.

Tuesday, March 12, 2019

Robolectric's spaces-in-profile-path bug is getting fixed

I previous reported a bug in Robolectric, that tests would fail to start if the path to the user profile directory contained a space. Today I received a notification about a GitHub comment stating that the issue has been fixed. The change will be released in version 4.2.1!

Sunday, March 10, 2019

MouseEventArgs coordinates are relative to the visible region

Today I did some tinkering involving a Windows Forms Panel that can be scrolled. To allow dragging things rendered on it, I had a MouseMove handler that used the coordinates given in the event arguments to figure out what and where to drag. I found that the drag-and-drop feature developed bizarre behavior as soon as the panel was scrolled away from the origin. Apparently, the coordinate in the event arguments are relative to the upper-left of the visible region of the panel, not the entire panel area.

Saturday, March 9, 2019

Unique constraints in the database guard against excessive insertions from the application

I'd been wondering for a while why my app was seeming slower than it used to be. Today I was looking around its database for unrelated reasons when I noticed that one table that was used by every request had ~170,000 rows, the vast majority of which were duplicates. It looks like the application has concurrency issues that sometimes led to it inserting another row inappropriately. The relevant column of the table was missing an index, so the query really hurt performance as the size grew. And as queries took longer, it looks like the concurrency problem was exacerbated, compounding the issue. I purged the extra entries and added a unique constraint. The app is now much faster!

Tuesday, March 5, 2019

When Android Studio starts treating Java files as plain text

Several students have somehow accidentally made Android Studio start treating specific Java source files as plain text. This can be fixed by removing the association:

  1. Open the Android Studio settings, File | Settings (or Android Studio | Preferences on Mac)
  2. Go to the Editor | File Types section
  3. Select Text in the Recognized File Types pane (top)
  4. In the Registered Patters pane (bottom), select and remove any entries ending in .java