Journaling Coding a Journal | Part 3

See part 1 and part 2.

This one is a bit of an interlude.

As I explained last time, I had sorted out the basic functionality for terminal output. This means that if I wanted to say, write some text in red someplace else in the program, I just have to call:

TextFormat.colorWrite("text to write", "Red");

I also did a couple of others, including one to do a complete line (the one above doesn't skip to a new line, which allows for multiple colors in a line), and one for centering. This last was also nice and simple: all it had to do was figure out how long the text to be written was, figure out how wide the window was, and from that it's easy enough to calculate how much whitespace is needed on the left to make things line up. (This of course supports color as well.) I was then able to add an optional width, meaning it'll center text within an imaginary bounding box (which is useful for “windows” within the console).

Where I got bogged down was in actual editing. It's trivial to just have the user start typing and show it, but as soon as even basic functionality, like word wrap, comes into the occasion, things become much more complicated.

I won't bore you with the details, but I was getting stuck with trying to keep track of where everything is and display it properly. I think I have a method now that will work, but I haven't been able to put it into practice just yet.

In the meantime, I decided to put some work into the interface, which also meant figuring out what kinds of functionality I actually wanted to include. I also haven't had much time to devote to this project this week, thanks to various other things demanding my attention. But I've managed to get a basic idea for a layout, and have some helper functions to draw the full window border and sub-panels.

The sub panel code was an interesting challenge, but I definitely learned some things. It works as a function that I call, giving it a starting X and Y, how wide it should be (either in absolute columns or a percentage of the window), as well as some further attributes like a title, border style and color, etc. Soon I'll add code for background colors too, but that needs some changes elsewhere (such as in my colored text methods).

The first sub-panel I'm putting together is a calendar, which will show when previous entries have been made and allow the user to jump to them for viewing or editing. I won't be able to do much of this until I have the actual editing code in, of course, but I can at least do some basics. The last thing I've implemented so far was getting it put the first week of the current month into a grid. This is harder than it sounds.

Case Study

Remember, the computer doesn't know anything about anything. It can only do what I've told it to do, and can only use new information that I've told it to figure out.

All it can bring to the party is a date. So that's my starting point.

In C#, there's what's known as a DateTime object. This is its own category of variable, and it can hold various parts of a date and time (from years to milliseconds). So my method works like this.

First: get today's year, month, and day, since the first thing to be displayed is the current month (and scrolling through months later will need a starting point). It then isolates the month, and gets its name (so I can use that as the heading). Then there's a built-in method that returns a number from 0-6 based on what day of the week a given date is (with 0 being Sunday and 6 being Saturday).

This proved to be perfect. From there, I just built a 7-element array, with each element representing a day of the month for a week. Like in most languages, arrays in C# are zero-indexed, which means that the first element is at place 0 rather than 1. Since I also have a 0-6 number associated with the day of the week, I can put the first of the month in its proper place just by assigning it:

arrayOfDays[dayOfWeek] = 1;

The bit in brackets tells the computer which specific element should equal 1.

From there, it's a simple matter of getting the number of days in the previous month (and there's another built-in method for that). That one goes in arrayOfDays[dayOfWeek - 1], then keeps adding smaller numbers until we get to 0. Then it starts at wherever the 1 is and adds in 2-whatever. There's some additional logic to check for edge cases (like I can't tell it to use dayOfWeek - 1 when dayOfWeek is 0, since there is no element at -1).

So now I have an array with 7 numbers, but it needs to be output. That too is easy enough: just go through each element of the array, converting it to a string (since it's stored as an integer) and adding a couple spaces so that it'll print properly:

string weekText = "";
foreach (int day in arrayOfDays) {

     weekText = String.Concat(weekText + "  " + day.toString());

}

From there, it's a simple matter of putting the cursor in the correct place, then using my centered text function with a width of 2 columns less than the width of the box (so that it doesn't overwrite the box's borders). Done!

This was definitely the hard part, since I had to deal with finding the beginning of the month. From there I can just build groups of 7 days until I get to the end, then start over at 1 to fill out the row.

But even then, I'm not quite done. I have two more main to-dos for this piece:

  1. Update my centered writing function to allow printing more than one color. This is something I wanted to do anyway, and for the calendar it'll let me dim the dates that aren't in the current month, which is a nice aesthetic touch.

  2. Have some logic that will keep track of certain dates as including an entry. I don't have file reading stuff in yet, but I can use some test code to make sure that the pieces will be in place so that when I do, and can load a list of dates when journal entries were done, the calendar will be ready to handle them.

This part shouldn't actually be too hard. C# allows a function to take an unknown number of variables. Although as I think about it, since I'll need to be able to pick random/arbitrary numbers to output this way (i.e. it won't always be the first and third numbers in the row, for example), it'll probably be better to have a separate function within my calendar drawing framework rather than trying to force the more general one into the role.

Phew. I'm sure that was far too much information, but it's certainly helpful for me to put my thinking down into some kind of order so that I don't go in 100 tangents at once.

#coding #journalApp