Noah W.'s blog is full of technological exploration, findings, programming, and the life of a young developer.
Glen Deveron 20 Highland Single Malt Scotch Whiskey, 40% ABV
Price per 1L at YYZ - Toronto-Pearson International Airport, Canada: $135CAD (~$99USD)
This is a pretty decent scotch (don't interoperate 62/100 as a grade 'D'), albeit a bit pricey. I'm glad I bought a bottle, but once it's gone, I doubt I'd ever buy this again.
I had a trip to Canada recently and decided to peruse the Duty Free store at YYZ before my flight. I saw this bottle priced curiously low for a 20-year vintage. I'd also never heard of it before. Liquor laws in Ohio are pretty conservative and assumed it just wasn't something available in Ohio. I bought a bottle and figured it couldn't be too bad. Luckily it wasn't, but it's not a sleeper either.
Published: 12/21/2018 6:53 PM
Article by: Noah Wood
I know it's been a bit quiet here the last few weeks and I've been quite busy working on a few updates to Furthermark and to my website. In the meantime, I've introduced a new dark mode theme to Noah W.org. It works by toggling between two CSS themes and determining which one to use by storing a cookie.
Access the new feature by toggling modes by clicking (or tapping) on the sun or moon icon in the top-right of the page.
Note: The cookie stored is only used to identify the theme and not used to track you at all. I'm not smart enough to try to track someone anyway.
Published: 12/15/2018 7:42 PM
Article by: Noah Wood
In a recent blog post on my website redesign, I remarked that I had been using Markdown to write my blog posts. I have come to quite like Markdown as a format to use to write sine it keeps my hands on the keyboard and enables an easy way to format my posts without the need to use a full-featured work processing application.
I have been using MarkdownPad as my markdown editor as it appeared to be the only good editor available on Windows (side note: why is it that all of the interesting markdown development is happening on macOS?). The problem with MarkdownPad is that it hasn't been updated in some time (it seems new development has stopped) and on Windows 10 it requires some very specific developer library to be installed in order to get the live preview functionality to work. I haven't seen any good UWP markdown editors in the Windows Store, so I thought: why don't I make one myself?
Enter Furthermark. I created Furthermark as a simple UWP markdown editor that uses some of my favorite features of MarkdownPad. Namely:
I think I came pretty close. There's still a long road ahead, but I think I have a pretty good version 1.0.
UWP is an interesting platform to develop for; the sandboxing and the built-in controls don't have the flexibility that Win32 or traditional .NET development allow for. As an application that will only target desktop platforms, Furthermark had to sacrifice some "traditional" application paradigms in order to get the results I wanted.
The biggest example is the resize slider for the preview window. Most windows control libraries (WinForms, WPF, MFC) have a control for a resize panel or a slider. UWP does not. I could (and would like to in a future version) implement my own control that behaves similarly to a resize panel, but it would take a lot of extra effort. So for now, I implemented a slider control to change the size. Not ideal, but it works.
The other example is the status bar. I wanted a status bar to show
These are things that a lot of people expect from a text editor. Common editors from Notepad to Microsoft Word have some variation of these features. Should be pretty easy, right? As it turns out the status bar became the hardest part to implement. Getting the bar with no content was easy. Furthermark uses a single frame with a UWP Grid control, so my "status bar" is just the last row in my grid. Done.
The hard part were the items inside the status bar. In my first out of (hopefully) many posts, I want to outline how I got the status bar working the way I wanted it to. I plan to opensource Furthermark once I get it working the way I want and clean up some of the code.
Also, I want to warn you all, I wanted to brush up on some of my modern .NET Syntax, and I was lacking in the VB.NET arena, so as a challenge to myself, I wrote Furthermark in VB.NET. If you don't like it, you certainly don't have to keep reading.
This was probably one of the easier ones. I made a read-only property for wordcount that I raise a property changed notification for when the text changes. This property calls a RegEx match to split out on certain types of whitespace. It's fast and fairly accurate.
Public ReadOnly Property WordCount As String
Get
Dim EditorString As String, Count As Integer = 0
Editor.Document.GetText(Windows.UI.Text.TextGetOptions.None, EditorString)
If Not String.IsNullOrWhiteSpace(EditorString) Then
Dim col As MatchCollection = Regex.Matches(EditorString, "[\S]+")
Count = col.Count
End If
Return Count.ToString("N0")
End Get
End Property
These two were the easiest. The RichEditBox control I'm using for the editor has methods to get the line count (and strings have a length property). All I do is set a private Integer
variable to the line count and length and have read-only public properties to call ToString("N0")
on these in order to give myself the comma separator for when we go over one thousand lines or characters.
When you save the document or copy the HTML of the Markdown, you get a notification that fades in and out temporarily from the status bar. I have a method to raise a notification:
Private Async Sub ShowStatusNotification(ByVal Text As String)
StatusText = Text
RaisePropertyChanged(NameOf(StatusText))
RaiseStatusText.Begin()
Await Task.Delay(4000)
ExitStatusText.Begin()
End Sub
I have a storyboard in the XAML to fade in and out over a duration of 1000ms (one second). This method sets the status text, brings in the text, waits for 4000ms (four seconds) and then fades it back out.
<StackPanel.Resources>
<Storyboard x:Name="RaiseStatusText">
<FadeInThemeAnimation TargetName="StatusTextTextBlock" Duration="1000"/>
</Storyboard>
<Storyboard x:Name="ExitStatusText">
<FadeOutThemeAnimation TargetName="StatusTextTextBlock" Duration="1000"/>
</Storyboard>
</StackPanel.Resources>
This one wasn't a complete necessary, but I really wanted to have this implemented. The most simple text editor on Windows (Notepad) has this feature (event if it wasn't as simple as it seemed) and I wanted it too. My problem was overthinking the math behind trying to figure this out, and the inconsistent nature of pulling the text from the RichEditBox. The most important thing I learned was getting the text and replacing the line endings to use Lf
rather than the Windows default of CrLf
.
The next step was splitting the text and getting the cursor position to determine where in the line the cursor was.
Dim Col As Integer, LastNewLine As Integer, Text As String
ThisEditor.Document.GetText(TextGetOptions.UseLf, Text)
Col = ThisEditor.Document.Selection.EndPosition
While Col > Text.Length And Col > 0
Col -= 1
End While
Text = Text.Substring(0, Col)
LastNewLine = Text.LastIndexOf(vbLf)
Me.Col = Col - LastNewLine
RaisePropertyChanged(NameOf(Col))
_Line = Text.Count(Function(a) a = CChar(vbLf)) + 1
RaisePropertyChanged(NameOf(Line))
What I do here is:
This is the one item I actually really didn't want to have, but unfortunaly the RichEditBox control supports using the Insert key to change the text typing mode from insert to overwrite, and I wanted a way to show the user how the editor was going to behave. This wasn't super hard to implement in the end. It turns out the RichEditBox control will show what the type mode is as a enumeration flag when looking at the Document's Options
property. So I have an event handler on the PreviewKeyDown
event of the edit box (regular KeyDown
doesn't register the "Insert" key) to set a private variable.
_IsOverwrite = Not ThisTextBox.Document.Selection.Options.HasFlag(SelectionOptions.Overtype)
RaisePropertyChanged(NameOf(InsOvr))
Then a read-only string property will get the text result of the status.
Public ReadOnly Property InsOvr As String
Get
Dim Result As String = "INS"
If _IsOverwrite Then
Result = "OVR"
End If
Return Result
End Get
End Property
Like I mentioned above, I'd like to make the application opensource at some point, but I'm not quite ready for the world to see my mess of code. I will also post an update once the application is available on the Windows store, it's currently going through the certification process. I will post updates here on my blog as well as on the official website Furthermark.com.
Published: 7/9/2018 9:04 PM
Article by: Noah Wood