November 20, 2013

Interview Question - Mergesort in C#

public List<int> MergeSort(List<int> m) {
if (m.Count() <= 1) return m;
int mid = m.Count() / 2;
List<int> left = new List<int>(), right = new List<int>();

for (int i = 0; i < mid; i++) left.Add(m[i]);
for (int i = mid; i < m.Count(); i++) right.Add(m[i]);

left = MergeSort(left);
right = MergeSort(right);
return Merge(left, right);
}

public List<int> Merge(List<int> a, List<int> b) {
int aCount = 0, bCount = 0;
List<int> m = new List<int>();

while (m.Count() < a.Count() + b.Count()) {
if (aCount < a.Count() && bCount < b.Count())
m.Add(a[aCount] < b[bCount] ? a[aCount++] : b[bCount++]);
else
m.Add(aCount < a.Count() ? a[aCount++] : b[bCount++]);
}

return m;
}

I realize that nowadays when I practice interview questions I'm tending less towards readability and convention (using var for local variables in C#) in favor of less lines of code (using var means you have to declare each variable on a separate line of code) - when doing interview practice you just wanna get the answer on the page and move on.  I could have refactored the while loop in my Merge function into many more lines of code but opted for the a cryptic version instead, which makes me feel like a boss but may be more confusing to readers the first time through.  So I apologize for that

November 18, 2013

Interview Question - Write an algorithm to determine if n is a power of 2

If I have the idea correctly, you can actually do this in constant time.

First piece of useful information: Any power of 2 is represented in memory as 0...010...0

Examples:
2 is 00000010
4 is 00000100
8 is 00001000
16 is 00010000

Second piece of useful information: x & (x - 1) is a neat little hack that will return x with its least significant bit cleared out.
What does that do for the examples above?  Just makes them all 0!

So here's the code I wrote:

bool IsPowerOf2(int x) {
   return x > 0 && (x & (x - 1)) == 0;
}

///Update: Crap. This was on stackoverflow already.  Oh well

November 06, 2013

Good News :)

After months and months of studying, interviewing, and (mostly) getting rejected from many, various, companies, I finally feel like all of this was worth it.

I just accepted an offer from Microsoft, although I also passed my Google interviews and would be in "Google limbo" where I would get matched up with a potential future team.  Getting this close to a Google offer is certainly very enticing, but I'm really drawn to the Microsoft Explore program where I would get to experience all three roles of software (development, testing, and program management).  It's a program that I haven't seen implemented in other companies and it's a once-in-a-lifetime opportunity; after this year I would no longer be eligible for it.

I can't even put into words how good it finally feels to have an (awesome!!) internship in tow for the summer.  After averaging 3 interviews a week for about two months, stressing out before hand, ditching class in the hope that an extra few hours of studying would pay off during interviews, or thinking about this summer and not having a place to call home - it's finally all done and I have an offer I am so very proud of, in my favorite city in this country.  So often I have imagined myself living in Seattle among all of the other tech geeks, now it's finally going to happen.

This post has no benefit to anyone else, just me.  It's my self-congratulatory message to myself.  After months and months of difficulty I feel like I am allowed to pat myself on the back, just this once.  Thanks to my family, friends, and friendly Microsoft recruiters for their support :)

October 31, 2013

This is what happens when Google and Pixar work together

http://www.wired.com/business/2013/10/motorola-google-mouse/

It's.. I don't even know.  I read about it before I saw it in person today.  The descriptions don't do it justice.  I was shrieking with joy as I panned my friend's phone across all 360 degrees and watched the virtual reality of a mouse losing his hat unfold.


October 25, 2013

Ice Cream Delegates

Because programming concepts are always so much more delicious when you add ice cream to them.

delegate string IceCreamShop(string iceCreamFlavor);

static string Jenis(string iceCreamFlavor)
{
    string betterFlavor = "no jenis for you";

    switch (iceCreamFlavor.ToLower()) {
        case "chocolate":
            betterFlavor = "Askinosie Dark Chocolate";
            break;
        case "vanilla":
            betterFlavor = "Ugandan Vanilla Bean";
            break;
        case "peanut butter":
            betterFlavor = "Buckeye State";
            break;
    }

    return betterFlavor;
}

static string CheapIceCreamStore(string iceCreamFlavor)
{
    string ickyFlavor = "no cheap ice cream for you but that's probably not a bad thing";

    switch (iceCreamFlavor.ToLower())
    {
        case "chocolate":
            ickyFlavor = "mysterious brown stuff";
            break;
        case "vanilla":
            ickyFlavor = "mayonnaise";
            break;
        case "peanut butter":
            ickyFlavor = "dirt";
            break;
    }

    return ickyFlavor;
}

And this is how you use it:

static void Main(string[] args)
{
    IceCreamShop iceCreamShop = Jenis;
    Console.WriteLine(iceCreamShop("chocolate"));

    iceCreamShop = CheapIceCreamStore;
    Console.WriteLine(iceCreamShop("chocolate"));
}

The output is, predictably:

Askinosie Dark Chocolate
mysterious brown stuff

I can also pass in my ice cream shop delegate as a parameter!

static void PrintMenu(List<string> flavors, IceCreamShop iceCreamShop)
{
    foreach (string flavor in flavors)
    {
        Console.WriteLine(iceCreamShop(flavor));
    }
}

static void Main(string[] args)
{
    var flavors = new List<string> { "chocolate", "vanilla", "peanut butter"};

    IceCreamShop iceCreamShop = Jenis;
    Console.WriteLine("Delicious Jeni's menu:");
    PrintMenu(flavors, iceCreamShop);

    Console.WriteLine();

    iceCreamShop = CheapIceCreamStore;
    Console.WriteLine("icky other ice cream store menu:");
    PrintMenu(flavors, iceCreamShop);
}

With the output:

Delicious Jeni's menu:
Askinosie Dark Chocolate
Ugandan Vanilla Bean
Buckeye State

icky other ice cream store menu:
mysterious brown stuff
mayonnaise
dirt

Columbus natives will appreciate the Jeni's reference. If you don't know what Jeni's is, I'm sorry to know that but it's such a good ice cream store that it's spreading across the country and you will hopefully soon know what I am talking about.  I recommend Salty Caramel to all Jeni's first timers.

Cool websites

http://www.lifehack.org/articles/technology/25-killer-websites-that-make-you-cleverer-2.html

October 23, 2013

Interview Question - Get Permutations of a String

My algorithm follows the same idea as Gayle's in Cracking the Coding Interview, I've just implemented it iteratively instead of recursively

public static List<string> GetPermutations(string input)
{
   var permutes = new List<string>();
   for (int i = 0; i < input.Length; i++)
   {
      if (i == 0)
      {
         permutes.Add(input[i].ToString());
      }
      else
      {
          var newPermutes = new List<string>();
          foreach (string word in permutes)
          {
             AddCharToEveryPosition(input[i], word, newPermutes);
          }
          permutes = newPermutes;
      }
  }
  return permutes;
}

private static void AddCharToEveryPosition(char c, string word, List<string> newPermutes)
{
   for (int i = 0; i <= word.Length; i++)
   {
      string newWord = word.Insert(i, c.ToString());
      newPermutes.Add(newWord);
   }
}

I'll run through the algorithm a bit since it helps me to understand what's going on.

Say input is "meh"
We take the first letter 'm'
Then we take the second letter 'e' and add it wherever we can to the first letter.  For now we can't go too crazy, we just get { "em", "me" }
Third letter is slightly more interesting, since we now get { "hem", "ehm", "emh", "hme", "mhe", "meh" }
You can imagine how crazy it gets with more letters.

Yay permutations!

Interview Question - Add two integers without using + sign

This seems simple enough but to those not too comfortable with bits, it's a bit tricky (ha...)

public int AddWithBits(int a, int b) {
   while (b > 0) {
      var sum = a ^ b;
      var carry = (a & b) << 1;
      a = sum;
      b = carry;
   }

   return a;
}

September 19, 2013

Interview Question - Determine if a Tree is a Binary Search Tree

Well it's interview season.  That basically means it's the time of year I spend way more time studying for interviews than I do for actual class work.  Which doesn't bode well for my next week of midterms but I guess getting a summer internship is more important in the long run than acing one midterm.

Here's a question I remember I attempted a year ago, gave up, tried again recently, and got a working solution:

Determine if a binary tree is a binary search tree.
Solution in C#.  I defined previous and current as ints above because I didn't want to distract from the logic of the code.

const int previous = 1;
const int current = 0;

static bool IsBSTHelper(BSTNode node, int[] a)
{
    if (node == null) return true;

    var isValidBST = IsBSTHelper(node.left,
a);

   
a[previous] = a[current];
   
a[current] = node.data;

    if (
a[current] < a[previous])
    {
        return false;
    }

    return isValidBST && IsBSTHelper(node.right,
a);
}

static bool IsBST(BSTNode root)
{
    return IsBSTHelper(root, new int[] {int.MinValue, int.MinValue});
}

I started out with the classic pre-order tree traversal.  Since it prints out the elements in the right order, I figured I would save the last printed element in the recursive call and compare it with the next printed element.  I was running into problems with that until I decided to use an array of two ints to store the values instead.  And now.. it works for all of my test cases.

Here I assume the tree is nice.  This wouldn't return false if a tree has more than two children per node, or if the tree has a loop.

July 06, 2013

Implementing IEnumerable

I've found myself needing to implement IEnumerable time and time again, so I'm just putting up a fun reference for myself to follow in the future.

My data:
public class IceCream {
  string _flavor;
  public string Flavor {
    get { return _flavor; }
    set {
      _flavor = value;
    }
  }

  public IceCream(string flavor) {
    _flavor = flavor;
  }

  public override string ToString() {
    return _flavor;
  }
}

The class that implements IEnumerable:
public class Menu<T> : IEnumerable<T> {
  List<T> rep = new List<T>();

  public Menu() { }

  public void Add(T item) {
    rep.Add(item);
  }

  public Menu(IEnumerable<T> collection) {
    foreach (T item in collection)
      rep.Add(item);
  }

  public IEnumerator<T> GetEnumerator() {
    foreach (T item in collection)
      yield return item;

    // return rep.GetEnumerator() works as well
  }

  IEnumerator IEnumerable.GetEnumerator() {
    return GetEnumerator();
  }
}

And now for the fun:
static void Main() {
  var Vanilla = new IceCream("vanilla");
  var Chocolate = new IceCream("chocolate");
  var CookieDough = new IceCream("cookie dough");
  var SaltyCaramel = new IceCream("salty caramel");

  var menu = new Menu<IceCream>() { Vanilla, Chocolate, CookieDough, SaltyCaramel };

  foreach (var i in menu)
    Console.WriteLine(i.ToString());
}

With the awesome output:
vanilla
chocolate
cookie dough
salty caramel

yay

June 30, 2013

Lessons from work

In light of my first work experience, I've been grappling with the question - what makes a good programmer?  I know there have been so many articles written on this subject, by people much more knowledgeable than I am, but I'm still trying to figure out the answer.

Of course being smart helps.  Having good knowledge of algorithms, being able to optimize your code for time and space.  That's what most interviews test.

But, at least at my internship, I've rarely had to code optimized solutions for space or time, so maybe I'm not qualified yet to conclude anything.  But I have noticed traits of my co-workers that I admire and would like to emulate.

One of the interns I'm working with is one of those people who has a host of time-saving programs and techniques at his fingertips - I've never heard of Auto Hot Key before this internship, but it's a program that almost makes your mouse obsolete.  You can type in any customized shortcut and open any program you want.  Think of all the productivity gains!  It's just one example of the many techniques he uses to save time and make navigating around a computer easier.  I think that's one of the traits of a great programmer - constantly looking for ways to reduce tedious manual work, and generally making things easier.

Good people skills are much more important for programmers than most would think.  More than almost any other profession, programmers get the rep for being introverted to the core and socially inept.  But I honestly have not met this person yet.  Ultimately, the job of a programmer is to produce good code - and maybe that's where the stereotypical programmer excels.  But in the real world, people must work in a team and therefore must be tolerable at minimum to work with.  My co-workers are more than tolerable - they are delightful, and it makes coming into work every day that much easier.  They are always happy to help me, willing to point out my mistakes, and quick to give praise.  You just want to work with people you like.  You're happier when you work with people you like.  And you don't want to let them down, so you really try your hardest.

And I guess - self-sacrifice?  I've been doing a bit of that.  Interns are specifically told to work 40 hours a week and go home after that.  I know I put in more than 40 hours a week - I was the last intern put on my project so I've had a lot of catch-up to do - I came to work earlier than most and left later than most for the past two weeks.  There's another intern I know - she stayed til 9 a couple nights last week to finish all of her work.  I heard of another developer who once put in 120 hours a week during project development.  That's 17 hours a day, including weekends!  I heard that the project he was responsible for had only two bugs in production.  While I feel like putting in 120 hours a week is extreme, and not a sustainable way to live, I admire that programmer's determination to pursue quality.

There's another developer I've heard of that everybody says is one of the best ones.  He's very introverted, but on the few occasions I've had to talk to him he was very nice.  Everyone says he's very nice.  I want to know what makes him such a good developer, and if I'm missing any of those characteristics on my list I'll add them.  I feel like, as a developer, I'm at the most malleable stage of my career and most receptive to new ideas - I'm still at the point where I'm in awe of how much everyone around me knows.  I hope I never lose that.

edit // I feel like this will be a continuously growing list, and will update whenever I see fit.  Seems like these edits are more geared towards being a good employee in general, but it relates to the theme of this post

7/1/2013 - I forgot to add "following directions" to my list earlier.  I had an instance a couple weeks ago where I was downloading material for tutorials and I spent a day working with the wrong version and wondering why NOTHING was working.  Although it was confusing because I was required to download an outdated version of the software, I was still told which version to download and I somehow missed it.  I forced myself to stay later at the office and come in earlier all week - it wasn't overtime, it was making up for a mistake that I couldn't blame on anyone but myself.  Just reading the directions would have saved me so much time and trouble.  I've always had a hard time following tutorials because I always think I've got the idea and go off on my own - I often regret this impulsiveness and I'm learning to be patient and read every line thoroughly, as someone out there thought it was important enough to include.

7/2/2013 - I also forgot to add a technique that I use multiple times, every day.  When asking a question or a favor, I've learned to always start it with, "Hey, when you get a free moment ... " instead of "Hey, help me right now".  Of course the bluntness of the second is exaggerated but it illustrates my point - approaching someone directly for help often forces them to drop everything they are doing because they feel bad saying no, most times.  I learned this at my previous part-time job at school - I noticed that when I phrased my questions differently my team lead was much more receptive to helping me.  Indicating that you understand the other person's priorities - that your request for help comes AFTER the current task they are working on - seems much more respectful.

7/6/2013 - Self-commenting code and good variable names!  I enjoyed this article - especially this sentence: "[Write-Only-Code (as opposed to Really Obvious Code)] is, effectively, a love letter between the coder and the computer - full of inside jokes and pet phrases that are meaningless to those not part of the relationship."  I can say that when foraging through millions of files (not really but that's what it feels like), good variable names can make deciphering the madness a lot easier.

June 29, 2013

expense tracker - part 9

Hitting some snags trying to implement the edit functionality.  The MessageBox control is very limited, and I'm sure it was intended that way, but there is no way to create fields to allow for user input.  I actually had to use Xna's MessageBox in order to create buttons with custom text - I needed a "remove" button, and possibly later on, an "edit" button.  There's a problem with that - although I'll need three buttons in the future - "edit", "remove", "cancel", the MessageBox only allows for a maximum of 2 buttons.

So right now the user is allowed to remove single fields from clicking on a name in the display list, but they can't edit it.  I could direct the user to a separate edit page but that seems clunky.  I like the consistency and look of the MessageBox, but it looks like I'll have to implement my own to get the functionality I want.

And actually, deleting a single field was difficult enough.  I couldn't get the Binding Command to work on a single field in my ItemsControl so I had to go with Click event handlers in the code-behind.  Unlike Binding Commands, I can't pass on a parameter so that was tricky - I had to do some shenanigans to get it to work.

Anyway, say you want to remove a field from your list - you just click it and a MessageBox pops up, allowing you to remove it or cancel.  A second MessageBox pops up confirming that you did, in fact, remove it.  That might get annoying if you use it a lot so I'm thinking about taking it out.


And now no more lunch.  Although it bothers me that Other still shows up even when it's 0, I'm going to change that.  Also, if you look carefully, you can see that the "Lunch" button and its text is brighter than the rest of the fields, due to it being focused.  I didn't implement that, it comes with the Button, but I like how it looks.

I had to play around with Focus stuff in order to get it to work, as Click events can't pass parameters and I couldn't bind to a specific item that is contained in an ItemsControl.  Ideally I would use a Binding Command, where you can pass on a parameter, but I was having a lot of trouble implementing that.  Anyhow, here is the click event in my code:
private void List_Button_Click(object sender, RoutedEventArgs e) {
  string name = "";
  decimal cost = 0;
  GetFocusedNameCost(out name, out cost);
  vm.MouseClick(name, cost); // where vm is an instance of my ViewModel
}

private static void GetFocusedNameCost(out string name, out decimal cost) {
  var focusedElement = FocusManager.GetFocusedElement();
  StackPanel s = (StackPanel)(((Button)focusedElement).Content);
  name = ((TextBlock)(s.Children[0])).Text;
  Decimal.TryParse(((TextBlock)s.Children[2]).Text, out cost);
}

And in my ViewModel for this page:
public void MouseClick(string name, decimal cost) {
  string title = String.Format("{0}: ${1}", name, cost.ToString());
  var result = Guide.BeginShowMessageBox(title, " ", new string[] { "remove", "cancel" }, 0, MessageBoxIcon.None, null, null);

  int? user_choice = Guide.EndShowMessageBox(result);
  if (user_choise == 0) {
    theyclickedremove(name, cost);
  }
}

Where theyclickedremove(name, cost) just goes and removes the appropriate items from storage and the display list.  Right now the variable names are confusing and I need to do some minor refactoring so I'll just leave it out for now.

So now my app is mainly functional, if not totally intuitive.  Right now, if the user wants to subtract, say, $5 from a field, they'll have to remove it from the list and re-enter the field with the new value.  At least it's better than clearing the entire list, but I want to make that process easier.  Also I want to implement an option that clears the list at the beginning of every month.  Shouldn't be too hard.

June 24, 2013

expense tracker - part 8

Here is my app now.  No more ugly huge add button!

I finally decided to go with the pivot app.  It makes it a lot easier to navigate around, and it's a lot clearer now how to toggle between views.  I wasn't able to implement this using pure MVVM because the app bar is being annoying but it's close enough.

The running tally is semi-bold.  I didn't know that existed!  It kind of looked weird the way it was, but turning it bold made the text really aggressive.  Semi-bold was a nice compromise.

Now what I am working on:
Yes I legit did spend $11 on cupcakes
last week.  The rest is made up

Each row is actually a button, with a child element StackPanel.  The StackPanel contains three TextBoxes - one for the name, one for the dollar sign, one for the amount.  I did it this way so the user can just click on the button to edit the fields.  I haven't implemented the edit functionality yet, but when using this app I've already found myself needing one.  Now I have to clear all values and enter everything again if I want to remove from a single field, which gets annoying.  Plus having them all be buttons is cool because clicking on each row turns the text white.  And you'll notice the Running Tally row is grayed out, I couldn't think of any uses why the user would want to edit the Running Tally field as it depends on the values of every other field so I disabled the IsEnabled property.  I rather like the way it looks - it's kind of telling you "Go away don't touch me" so you know it'll just ignore you if you try to bother it.

I know the two columns kind of look odd.  I wanted to dynamically bind the widths so that each field is on its respective extreme end but my app resisted very much and I decided to move on to other things.  Maybe I'll understand Silverlight enough later on to implement that, I think right now the number field will take up to six digits (allows for up to the thousands place, accounting for cents).  Any more than that and it'll wrap around to the next line.  It looks horrendous, but that's what the user gets for spending too much money.

After I add the edit functionality this app should be pretty much done.  My friend suggested adding dates, and with my pseudo-MVVM pattern it shouldn't be too hard to add a date field.  I was also thinking that it might be convenient to let the user choose whether the app should be cleared the first of each month, or if they want to manually clear the values themselves.  That shouldn't be too hard either - it's a nice little extra feature.

Good design

I don't think I realized til recently how important good user interface design is.  Apple is a famous example.. have you noticed how in movies, if anyone is ever using a laptop it's ALWAYS a mac?  I asked my brother and he said it's because they just look better.. and it's true.  I prefer Windows and I'm a big fan of Unix/Linux but I do appreciate the simplicity and elegance of Apple products.

For a while, as I browsed through various programming blogs, I wondered why some blogs just seemed more legit than others.  Some of the material in those blogs I dismissed was probably very good, very thorough, and the authors were probably very knowledgeable.  So it's an unfortunate fact for them that I, and probably many other people judge the quality of a blog (or app, program, etc, anything really) by its design.  I generally don't like pages that are too busy, I don't like clashing/weird color schemes, I don't like the look of default html tables, I don't like gratuitous pictures/icons that pop up everywhere.  Yes I am picky but the look of an application is much more important than many programmers are willing to admit.

I know I'm one to talk.  My blog isn't very professional looking and sometimes my thoughts aren't coherent.  And, from browsing other sites, I can see it's common to format code a different way, to maybe wrap it in a table, to highlight and bold certain keywords, to have good spacing, and most of these things I don't follow well.  But as this is a blog mainly for my own learning purposes, I'm fine with what I have.  I like how the orange goes with the blue.

Just some thoughts.. I'm interning with a company that produces some very beautifully designed products.  I've been to a few lectures presented by our creative team and their Powerpoints are always very well put together, make full use of color harmonies, and have perfect font sizes and spacing.  Before this internship, I never thought I could describe a Powerpoint as "pretty".  And whenever tech makes powerpoints, they just throw everything together.  It's really kind of amusing to see the differences.

I should note that good design and beautiful design aren't necessarily the same things, and a product that incorporates both is commendable.

June 23, 2013

expense tracker - part 7

Gosh, when I started this project I had no idea it would be this complicated.  The concept seems so simple, doesn't it?  A working prototype took maybe a day, and that's with me barely knowing XAML or WPF or Silverlight at all.  But doing it RIGHT, and doing it so it's USABLE, can get complicated so fast.

I completed reorganized my code again.  I'm a huge fan of folders.. I made a folder for all of my converter classes, for variables, even a folder for little helper functions.  I tried segmenting my code even more.  And I separated the two Default fields in my app - the Other field and the Running tally field, as they operate a little differently than every other <name, value> pair the user types in so they might as well be separated into yet another class.  I'm still playing around with how all of the data and its corresponding logic should be organized.

I kind of hated the huge "Add" button in my previous implementation, even though it enables Command binding and so implements MVVM.  I looked up BindableApplicationBar and was excited to use it, but I don't think it works with Windows 8.  Sad face.  I think in this instance I'm willing to give up pure MVVM implementation in return for a better user interface, as I don't like using my app with the huge "Add" button, but I do like looking at it with everything neatly contained in the app bar.  As I've tried to be careful to use good coding practices in the rest of my app, I don't think it'll hurt too much to break MVVM here.

I'd only learned about singleton design patterns in school, this is actually the first time I've ever used one (well, knowingly).  My dilemma was - how do you implement INotifyPropertyChanged for a static class?  Sometimes you want to access a field that is used across multiple files in your application.  So this field must be static - but now you can't make it implement INotifyPropertyChanged.  Ahh, but here is where you can use the singleton pattern to implement that functionality.  I can't fully explain the details - but INotifyPropertyChanged only works for an instance of a class.  So you just create one instance of that class, and it can implement all of the INotifyPropertyChanged functionality you need.  As I said earlier, I decided to separate out the variables into separate classes - so I have a class for all of the text fields called Changing (since I have another class called Default that holds all of the variables that don't change).  Here is the implementation for that class:

public sealed class Changing : INotifyPropertyChanged {

  #region Singleton stuff

  private static readonly Changing _Instance = new Changing();
  private Changing() { }
  public static Changing Instance {
    get { return _Instance; }
  }

  #endregion

  #region Text Information

  private string _CurrentTxt = Default.DEFAULT_TXT;
  public string CurrentTxt {
    get { return _CurrentTxt; }
    set {
      _CurrentTxt = value;
      OnPropertyChanged("CurrentTxt");
    }
  }

  private bool _IsTxtDefault = Default.DEFAULT_SETTINGS;
  public bool IsTxtDefault {
    get { return _IsTxtDefault; }
    set {
      _IsTxtDefault = value;
      OnPropertyChanged("IsTxtDefault");
    }
  }

  #endregion

  #region Num Information

  private decimal _CurrentNum = Default.DEFAULT_NUM;
  public decimal CurrentNum {
    get { return _CurrentNum; }
    set {
      _CurrentNum = value;
      OnPropertyChanged("CurrentNum");
    }
  }

  private bool _IsNumDefault = Default.DEFAULT_SETTINGS;
  public bool IsNumDefault {
    get { return _IsNumDefault; }
    set {
      _IsNumDefault = value;
      OnPropertyChanged("IsNumDefault");
    }
  }

  #endregion

  #region INotifyPropertyChanged Implementation

  private void OnPropertyChanged(string p) {
    if (PropertyChanged != null) {
      PropertyChanged(this, new PropertyChangedEventArgs(p));
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  #endregion
 
}

Yay and now I have static variables that can work with data binding.

Another small change is that I changed the numbers from being int to double to decimal.  Int was a bad choice because not everything you buy falls perfectly into an int value.  I wouldn't mind adding only int values to my phone but if you go through the trouble of adding a number with a decimal point, the TryParse just silently fails and drops the user's input.  Double seemed like overkill, I think decimal is more appropriate for this purpose.

Another thing I noticed was that I previously was loading all of the data in a ViewModel for my Display Expenses user control, but I don't think that was the place for it.  A lot of my debugging efforts were stymied by this code dependency.  So I just loaded the data in a separate class and called it in the constructor for my MainPage, I don't know if that's good practice or not but I know that separating those two different functionalities makes my life a lot easier when trying to debug code, and a lot less confusing when trying to navigate around.

Yeah.. a lot of changes.. My next problem to tackle is that fact that TextBoxes don't lose focus when you tap on an appbar item.  With my previous implementation, with the huge "Add" button, the TextBoxes would lose focus and the corresponding fields were correctly updated.  But appbars are annoying to work with and they keep the focus on the TextBoxes, which means my app has a bug now and I have to do some fanagling to make it right again.

June 19, 2013

I should really learn how to use Mercurial

I realized I'm using this as a sort of version control repository.. lolz.  I'm learning how to use Mercurial so hopefully that will help.  My code looks prettier here though.  And the threat of being ridiculed by the programming community lends to a certain level of code quality.  It's why I barely posted any code from my previous attempt at writing this app.

expense tracker - part 6

Made more progress with my AddExpenses UserControl - made a ViewModel class called AddExpenseViewModel that implements all of the logic whenever a user clicks the Add button.  I was able to figure out how to bind my add button functionality in the ViewModel, so my code behind for AddExpenses is clean for now.  Also, I just made the list of expenses a separate ViewModel class, but it is contained in my ExpenseViewModel class.

So here is my new class, my ExpensesCollection class:
public static class ExpensesCollection {
  public static ObservableCollection<Expenses> AllExpenses = new ObservableCollection<Expenses>();
  static IsolatedStorageSettings storage = IsolatedStorageSettings.ApplicationSettings;

  public static bool ContainsExpense(string s) {
    foreach (Expenses e in AllExpenses) {
      if (e.Expense == s) { return true; }
    }
    return false;
  }

  public static Expenses Remove(string s) {
    foreach (Expenses e in AllExpenses) {
      if (e.Expense == s) {
        AllExpenses.Remove(e);
        storage.Remove(s);
        storage.Save();
        return e;
      }
    }
    string message = String.Format("{0} is not in your list", s);
    MessageBox.Show(message);
    return null;
  }

  public static void Add(string s, double d) {
    AllExpenses.Add(new Expenses() { Expense = s, Cost = d });
    if (!storage.Contains(s)) {
      storage.Add(s, d);
    } else {
      storage[s] = d;
    }
    storage.Save();
  }
}
I think there's some room for improvement here but I'll let it be for now.

As a result of this new class I made some changes to my ExpenseViewModel -
Replaced my AllExpenses with ExpensesCollection.AllExpenses, named ExpenseList in my file,
and my new GetSavedExpenses:
private void GetSavedExpenses() {
  foreach (string s in storage.Keys) {
    double d;
    if (Double.TryParse(storage[s].ToString(), out d)) {
      var expense = new Expenses() { Expense = s, Cost = d; };
      ExpenseList.Add(expenses);
    }
  }
}
Yes I realize the if statement is probably unnecessary - the expense, cost pair wouldn't be allowed to be added in the first place if it was an invalid double.  But I have to call TryParse anyway so might as well add a tiny check.

The only changes I made to my AddExpenses.xaml file is binding the text property of my textboxes to properties in my ViewModel -
for txtInput:
Text="{Binding CurrentTxt, Mode=TwoWay}"
and for numInput:
Text="{Binding CurrentNum, Mode=TwoWay}"
And binding my button Command to my AddCommand property in the ViewModel:
Command="{Binding AddCommand}"

Here's the code for the ViewModel itself:
public class AddExpenseViewModel : INotifyPropertyChanged {
  IsolatedStorageSettings storage = IsolatedStorageSettings.ApplicationSettings;

  public AddExpenseViewModel() {
    InitializeCommand();
  }

  #region AddCommand

  private ICommand _AddCommand;
  public ICommand AddCommand {
    get { return _AddCommand; }
    set {
      _AddCommand = value;
      OnPropertyChanged("AddCommand");
    }
  }

  private void InitializeCommand() {
    AddCommand = new AddCommand(UpdateExpensePair);
  }

  private void UpdateExpensePair() {
    var ExpenseStorage = ExpenseViewModel.AllExpenses;

    string s = CurrentTxt;
    double d;
    if (double.TryParse(CurrentNum, out d)) {
      if (ExpensesCollection.ContainsExpense(CurrentTxt) {
        Expenses e = ExpensesCollection.Remove(s);
        d += e.Cost;
      }
      ExpensesCollection.Add(s, d);
    } else {
      MessageBox.Show("Integers and decimals only, please");
    }
  }

  #endregion

  #region Text(Expense) Setting

  const string DEFAULT_TXT = "expense";

  private string _CurrentTxt = "";
  public string CurrentTxt {
    get { return _CurrentTxt; }
    set {
      _CurrentTxt = value;
      OnPropertyChanged("CurrentTxt");
    }
  }

  private bool _DefaultTxtSettings = true;
  public bool DefaultTxtSettings {
    get { return _DefaultTxtSettings; }
    set {
      _DefaultTxtSettings = value;
      OnPropertyChanged("DefaultTxtSettings");
    }
  }

  #endregion

  #region Number(Cost) Settings

  const double DEFAULT_NUM = 0;

  private string _CurrentNum = "";
  public string CurrentNum {
    get { return _CurrentNum; }
    set {
      _CurrentNum = value;
      OnPropertyChanged("CurrentNum");
    }
  }

  private bool _DefaultNumSettings = true;
  public bool DefaultNumSettings {
    get { return _DefaultNumSettings; }
    set {
      _DefaultNumSettings = true;
      OnPropertyChanged("DefaultNumSettings");
    }
  }

  #endregion

  #region INotify Implementation

  private void OnPropertyChanged(string p) {
    if (PropertyChanged != null) {
      PropertyChanged(this, new PropertyChangedEventArgs(p));
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  #endregion
}

#region AddCommand Class

public class AddCommand : ICommand {
  Action _executeMethod;

  public bool CanExecute(object parameter) {
    return true;
  }

  public event EventHandler CanExecuteChanged;

  public void Execute(object parameter) {
    _executeMethod.Invoke();
  }

  public AddCommand(Action updateExpensePair) {
    _executeMethod = updateExpensePair;
  }
}

#endregion

Whew.  It's still not complete, I have some more work to do with the AddCommand class, like actually putting in logic for CanExecute.  I noticed there are two functions that do similar things - the Add command in my ExpensesCollection class and my UpdateExpensePair() that is called with the Add button is clicked.  In ExpensesCollection, the Add method assumes that the double value is already the correct value - what I mean is that if you add to an expense that already exists, you leave the string alone but update the double value.  That logic is done in UpdateExpensePair(), but I  suppose I could have moved the logic to my Add class.  My question is, where is it better to implement that logic?  Already there are assumptions in my code about the values it is being passed, what if something weird happens and those assumptions end up being wrong?  But I don't want to do unnecessary checking, either.  In school we just cleaned the input in the calling function, and the callee assumes it is being given valid input so that's just what I did here.  Is that convention?  It's probably better to comment the code, warning that this particular function assumes things about its input.  I could probably implement some error handling too, I guess.

Anyway..

Finally, in the MainPage codebehind, I had to instantiate a new AddExpenseViewModel and set AddExpenseViewOnPage.DataContext to that ViewModel.

So I think the basic logic is complete.  Codewise, it's better than my previous version of this app but it doesn't work as seamlessly when the user is interacting with the app itself.  I might have to add codebehind in my AddExpenses UserControl to control the visual appearance of my TextBoxes, but for now I'm ok with that.

I'd also like to add that while I completely revamped the logic - the functionality and appearance still stayed the same and I only had one bug while making these changes, and it was pretty easy to fix.  I was surprised at how seamless these changes were - I guess that's the point of going through all this trouble to implement this pattern!

June 16, 2013

expense tracker - part 5

I've been busy with stuff, but I was able to devote some time this weekend to getting my butt kicked by MVVM.  I know that it's supposed to make things easier, but how can something that is supposed to simplify things be so hard to understand?  I get the concepts - separate your data from your logic from your views, but quite honestly that's easier said than done.

I separated my data into Model, ViewModel, and View folders, as shown:

And I expect to be adding more items, as I've only implemented the very basics of my app (again). Just trying to get things working and responsive, for now.

The Model contains my Expenses class with the following code:
public class Expenses : INotifyPropertyChanged {
  public string Expense { get; set; }
  private double _cost;
  public double Cost {
    get { return _cost; }
    set {
      _cost += value;
      OnPropertyChanged("Cost");
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  private void OnPropertyChanged(string p) {
    if (PropertyChanged != null) {
      PropertyChanged(this, new PropertyChangedEventArgs(p));
    }
  }
}

So basically what my Model is - it's each key, value pair that will eventually be displayed.  Like, <"Shoes", 50>.  In my previous implementation the Cost was represented by an int, but why not let people put in a decimal value.  When parsing the values, any values with a decimal value would be ignored and I realized that probably isn't a good thing.

I only have one ViewModel so far, my ExpenseViewModel but I'll probably add more as I continue developing this app.  Here's the code:
public class ExpenseViewModel {
  IsolatedStorageSettings storage = IsolatedStorageSettings.ApplicationSettings;
  public static ObservableCollection<Expenses> AllExpenses = new ObservableCollection<Expenses>();

  public ExpenseViewModel() { GetExpenses(); }

  public void GetExpenses() {
    if (storage.Count > 0) { GetSavedExpenses(); }
    else { GetDefaultExpenses(); }
  }

  private void GetDefaultExpenses() {
    AllExpenses.Add(new Expenses() { Expense = "Running Tally", Cost = 0 }));
    storage.Add("Running Tally", 0);

    AllExpenses.Add(new Expenses() { Expense = "Other", Cost = 0 }));
    storage.Add("Other", 0);

    storage.Save();
  }

  private void GetSavedExpenses() {
    foreach (string s in storage.Keys) {
      double d;
      if (Double.TryParse(storage[s].ToString(), out d)) {
        var expense = new Expenses() { Expense = s, Cost = d };
        AllExpenses.Add(expense);
      }
    }
  }

  public void Add(string s, double f) {
    AllExpenses.Add(new Expenses() { Expense = s, Cost = f});
    if (!storage.Contains(s)) {
      storage.Add(s, f);
      storage.Save();
    }
  }
}

I wish there was a better way of displaying the data than loading it every single time the app starts, but that's what I have so far.  I took some ideas from Microsoft's Implementing the Model-View-ViewModel tutorial.  Instead of implementing the INotifyPropertyChanged interface I used the ObservableCollection, which notifies whoever is interested that new items have been added or removed from the current list of data.

Now on to the views.  Here's my ExpenseView.xaml file (with nothing added in the code-behind, yay!)
<UserControl.Resources>
  <DataTemplate x:Key="MyPrettyTemplate">
      <StackPanel Orientation="Horizontal"
                         Background="{StaticResource PhoneAccentBrush}" Margin="5">
        <TextBlock Text="{Binding Expense}:
                          Style="{StaticResource PhoneTextSubtleStyle}"
                          Margin="10" Width="300" />
        <TextBlock Text="$ "
                          Style="{StaticResource PhoneTextSubtleStyle"}
                          Margin="10,10,0,10" />
        <TextBlock Text="{Binding Cost}"
                          Style="{StaticResource PhoneTextSubtleStyle}"
                          Margin="0,10,10,10" />
      </StackPanel>
  </DataTemplate>
</UserControl.Resources>

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  <LisBox x:Name="ExpenseViewOnPage"
               ItemsSource="{Binding}"
               ItemTemplate="{StaticResource MyPrettyTemplate}" />
</Grid>
MyPrettyTemplate just specifies how the items are to be presented, in ExpenseViewOnPage I give the TextBlock fields a DataContext to go on, and a DataTemplate so they can be pretty.  The DataContext is my ExpenseViewModel's AllExpenses - remember the ObservableCollection<Expenses>?

Here's how it looks.  For some reason I couldn't get the LongListSelector to work with a UserControl, so I used a ListBox but now the TextBlocks don't stretch out like they used to, so I'll have to play around with that:


Here's the code for my AddExpenses.xaml:
<Grid x:Name="LayoutRoot">
  <StackPanel x:Name="AddExpenseViewOnPage">
    <TextBox x:Name="txtInput" Width="438"
                   InputScope="Text" />
    <TextBox x:Name="numInput" Width="438"
                   InputScope="Digits" Margin="0,-10,0,0" />
    <Button x:Name="addBtn" Content="Add" Width="438"
                 Background="{StaticResource PhoneChromeBrush}"
                 Margin="0,-10,0,0" Click="addBtn_Click" />
  </StackPanel>
</Grid>

I didn't do any of the fancy tricks I was so proud of before - greying out default values in the fields and stuff.  I just want to get this working first.

Unfortunately I had to add stuff in my code-behind.  I know that to deal with commands such as Save commands or Add commands and the like, you're supposed to do that in the ViewModel with a RelayCommand but I'll add that later.  So for right now I have a Click handler for my button, but I plan on making a ViewModel for my AddExpenses view and implementing the Command in there.

So here it is:
public partial class AddExpenses : UserControl {
  IsolatedStorageSettings storage = IsolatedStorageSettings.ApplicationSettings;
  public AddExpenses() {
    InitializeComponent();
  }

  private void addBtn_Click(object sender, RoutedEventArgs e) {
    var ExpenseStorage = ExpenseViewModel.AllExpenses;

    string s = txtInput.Text;
    double d;
    if (double.TryParse(numInput.Text, out d)) {
      ExpenseStorage.Add(new Expenses() { Expense = s, Cost = d });
      if (!storage.Contains(s)) {
        storage.Add(s, d);
        storage.Save();
      }
    }
  }
}

Now, for the MainPage.xaml - I'd like to point out here that, in my previous app, I had made two pages for the two main components of my app - the add page and the display page.  Here, I only have one page, but two UserControls for the add and the display functionality.  Now it's starting to remind me a lot of the Pivot template so I'll probably just use that later.
Here's where I import the views:
xmlns:views="clr-namespace:expense_thing_test.View"

And where I bring in the views:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="'12,0,12,0">
  <StackPanel>
    <views:AddExpenses x:Name="AddExpenseViewOnPage" Visibility="Visible"/>
    <views:ExpenseView x:Name="ExpenseViewOnPage" Visibility="Collapsed"/>
  </StackPanel>
</Grid>

I have code for an app bar but it's all non-functional except for my toggle button, so I won't include it.  Also, I can't explain all the technical details, but basically the app bar is a special control that you can't bind a Command to, so you can't implement pure MVVM with it.  There are ways around this but as I don't even understand RelayCommand yet I'm not going to mess with that yet.

Here is my code-behind in my Mainpage class:
public partial class Mainpage : PhoneApplicationpage {
  private ExpenseViewModel vm;
  public Mainpage() {
    InitializeComponent();
 
    vm = new ExpenseViewModel();
    ExpenseViewOnPage.DataContext = ExpenseViewModel.AllExpenses;
  }

  private void display_button_Click(object sender, EventArgs e) {
    if (AddExpenseViewOnPage.Visibility == Visibility.Visible) {
      AddExpenseViewOnPage.Visibility = Visibility.Collapsed;
      ExpenseViewOnPage.Visibility = Visibility.Visible;
    } else {
      ExpenseViewOnPage.Visibility = Visibility.Collapsed;
      AddExpenseViewOnPage.Visibility = Visibility.Visible;
    }
  }
}

June 13, 2013

CSS is actually kind of cool

I've been revamping my blog over the past two days. I actually wouldn't call it revamping.. that implies that I did a full-on makeover and added lots of spiffy stuff. No, I've just been tweaking on what I've had so far, and now I feel that it's easier to navigate and looks cleaner.  I never bothered to learn CSS until I was forced to dabble in it at work, and I can say that it's helped majorly. The last time I tried a full-on revamping on blogger I got lost in all the CSS but now I get to use it to my advantage. What I never realized before is that it enables a separation of presentation and content, just like what I'm trying to do in my app. An example is how I made any code I post on here a CSS class, so instead of manually formatting it every time I just go in the HTML and set it to a div class. That approach bears an odd resemblence to DataTemplates in WPF.

It's just like my dad told me when I took my first few CSE classes - "The more you know, well, the more you know". That is so true in computer science. And a bit discouraging to novice programmers - the amount of information that you know you don't know is just overwhelming.  But I've found that basic principles are common to all flavors  of coding.  I had previously dismissed HTML and CSS as mindless tools used to quickly patch up a website, unaware that the two used together are characteristic of the functionality and simplicity of a powerful and well-known programming paradigm.

June 10, 2013

Stupid code

Has anyone ever seen code that literally makes you laugh?

I was doing some practice problems earlier today, one of them was implementing addition using only bit operators.  After that I implemented addition that only uses increment/decrement operators, just for fun:


int dumb_addition(int a, int b) {

  int temp_a = a, temp_b = b, sum = 0;
  while (temp_a > 0) {
    sum++;
    temp_a--;
  }
  while (temp_b > 0) {
    sum++;
    temp_b--;
  }
  return sum;
}

Nevermind the useless temp variables or the fact that this won't work for negative numbers.


Here's some code I ran comparing dumb_addition with my bit_addition function, just to illustrate how terrible my dumb_addition function was:


static void Main() {

  string s = "Elapsed ticks for {0} is: {1}";
  var stopwatch = new Stopwatch();
  stopwatch.Start();
  int x = bit_addition(int.MaxValue, int.MaxValue);
  stopwatch.Stop();
  Console.WriteLine(String.Format(s, "bit_addition", stopwatch.ElapsedTicks));

  stopwatch.Reset();

  stopwatch.Start();
  x = dumb_addition(int.MaxValue, int.MaxValue);
  stopwatch.Stop();
  Console.WriteLine(String.Format(s, "dumb_addition", stopwatch.ElapsedTicks));
}

With the output:

Elapsed ticks for bit_addition is: 769
Elapsed ticks for dumb_addition is: 31337684

Brute force isn't always the answer, kids :(


Speaking of code that makes you laugh, I remember seeing some kid's program where he commented EVERY single line of code.  Most amusing was the fact that he commented the statement "return x" with "//return x".  I had a chuckle over that one after shaking my head disapprovingly.

June 09, 2013

Trying to learn MVVM

I realized the code for my expense app was very messy, and although so far it works, I know that's no excuse for having bad code.. so I've been trying to learn about MVVM but it's trickier to learn and implement than it seems.

Undoubtedly, there are good tutorials about MVVM out there but a lot of them seem very complicated.  I don't want to bother with threading when I am learning about MVVM, I have plenty of other things to worry about!  As usual, the best way to learn is to just get your hands dirty and code the thing yourself.

Here is my stupid example of an MVVM app: The Doggy class is my Model which contains a string for Name, and a bool for IsGoodDoggy.  The ViewModel uses the Model to instantiate a Doggy named Toby and IsGoodDoggy is set to true for now, until I hear that he diarrhea'd on the carpet again.  The View displays the Name of the Doggy and IsGoodDoggy, which displays the text in Yellow if the Doggy is being good, and Red if the Doggy is being bad.

This is the code for my Model:
public class Doggy : INotifyPropertyChanged {
  private string _name;
  public string Name {
    get { return _name; }
    set {
      _name = value;
      OnPropertyChanged("Name");
    }
  }

  private bool _isGoodDoggy;

  public bool IsGoodDoggy {
    get { return _isGoodDoggy; }
    set {
      _isGoodDoggy = value;
      OnPropertyChanged("IsGoodDoggy");
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  public void OnPropertyChanged(string property) {
    if (PropertyChanged != null) {
      PropertyChanged("this, new PropertyChangedEventArgs(property));
    }
  }
}

This is the code for my ViewModel:
public class MainViewModel : INotifyPropertyChanged {
  private Doggy _goodDoggy;
  public Doggy GoodDoggy {
    get { return _goodDoggy; }
    set {
      _goodDoggy = value;
      OnPropertyChanged("GoodDoggy");
    }
  }

  public MainViewModel() {

    LoadDoggy();
  }

  private void LoadDoggy() {

    GoodDoggy = new Doggy() {
      Name = "Toby";
      IsGoodDoggy = true
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  public void OnPropertyChanged(string property) {
    if (PropertyChanged != null) {
      PropertyChanged(this, new PropertyChangedEventArgs(property);
    }
  }
}

Just my ColorConverter class:
public object ColorConverter : IValueConverter {
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
    return (bool)value ? new SolidColorBrush(Colors.Yellow) : new SolidColorBrush(Colors.Red);
  }

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {

  return (((string)value).ToLower() == "true") ? true : false;
  }
}

In App.xaml, I have defined a few resources to be used application wide, (although I only used these resources in my MainPage.xaml) but whatever
<Application.Resources>
  <local:LocalizedString x:Key="LocalizedStrings" />
  <local:MainViewModel  x:Key="MainViewModel" />
  <local:ColorConverter x:Key="ColorConverter" />
</Application.Resources>

And finally, the MainPage.xaml (the code-behind is unnecessary because I didn't add anything to it yay!!)
Not adding the automatically generated code, just what I added:
<StackPanel DataContext="{StaticResource MainViewModel}">
  <StackPanel Orientation="Horizontal">
    <TextBlock Text="Name: " Margin="5,0,0,20" Width="150"/>
    <TextBlock Text="{Binding GoodDoggy.Name}" Margin="5,0,0,20" Width="150"/>
  </StackPanel>

  <StackPanel Orientation="Horizontal">
    <TextBlock Text="Is Good Dog:" Width="150"/>
    <TextBox Foreground="{Binding GoodDoggy.IsGoodDoggy, Converter={StaticResource ColorConverter}}" Text="{Binding GoodDoggy.IsGoodDoggy, Mode=TwoWay}" Width="150"/>
  </StackPanel>
</StackPanel>

So the default of my app would look like this:


But say Toby decided to take a crap in the house, then my app would look like this:

Entering a string into the TextBox first gets changed by my Converter class into a bool value.  So the string value in the TextBox really represents the bool value of IsGoodDoggy.  Whenever IsGoodDoggy is changed, it tells whoever is interested, and it turns out that the TextBox Foreground color is interested and changes its color accordingly.

By the way, this is real life Toby:
rawr

June 06, 2013

expense tracker - part 4

Here's my app now.  Looks better


But for now the code still looks messy.  Now that I've got the basic functionality I want and I'm starting to learn more about MVVM, I think I'm gonna start moving my code around so it follows those principles.  I've been experimenting with data binding and the IConverter interface as well - I'm binding both Textbox Foreground colors to a Boolean value and using a Converter class, so now I don't have to manually update the color in my code because it automatically fires depending whether the Boolean satisifies the default settings or not.

Here's a neat little MessageBox trick I discovered:

Timing it so the purple shows was quite tricky

Now when the user clicks delete, the app verifies the action before removing all the data.  I'm sure there would have been instances where I accidentally brush the trash can and inadvertently remove all of my data.  At least now this is slightly more idiot proof.  Here's the code used to implement that:

private void clear_button_Click(object sender, EventArgs e) {
  MessageBoxButton button = MessageBoxButton.OKCancel;
  string s = "";
  MessageBoxResult result = MessageBox.Show("Are you sure you want to clear all values?", s, button);
  if (result == MessageBoxResult.OK)
     my_storage.Clear();
}

The pencil button on the app bar is the edit button, which I haven't implemented yet.  When you click it all it does is display a MessageBox informing you that you clicked it.  It's not very helpful yet but I'll make it so the user can remove single fields that they no longer need.  And I'll probably keep the app bar at four buttons, any more and it'll start to look too busy.

Another nifty feature - the "running tally" text at the bottom of the main page, and the LongListSelector used to display all of the name, value pairs are data bound to the user's current accent color, so it's not my fault it the user doesn't like the color.  I'm just starting to get used to this data binding stuff but I've found I can simplify the code and add many more cool features with it.

June 02, 2013

Big lessons for a tiny app.

This very simple app has really taught me the values of source code repositories, good design patterns, reusable code, regression testing, modularity, and good user interface design, because I think I violated all of them.  Dang.

May 31, 2013

expense tracker app - part 3

I've made some changes since my last update, but they were minor changes, and still related to the two Textbox input fields that I am for some reason extremely picky about.

Comparing the functionality of my previous changes to the Microsoft provided bing app again, I noticed some subtle changes.  I won't go into all of the details here because it's boring and tedious, but I changed my Textboxes so that they wouldn't clear out the values every time they were clicked (unless the values shown are the default values).  Rather, upon clicking, they highlight the entire box for easy editing.  Also, the default format is greyed out while any user submitted input is black.  The changes are a big deal to me but probably very boring to anyone else reading this.

Just to illustrate, now here are screenshots:



I removed any EventRaisers in my XAML code and moved it all to the code-behind.  I'm starting to develop more of an understanding of EventRaisers, Events, EventHandlers, Delegates, etc., enough to get my implementation working, but I still feel like I'm not doing things the "proper" way or following good design patterns in my code (MVVM????)  For right now, I'm just trying to get the thing working and as I understand more as I go along, I can clean it up and do things the "proper" way.

However, I'm glad to say that when it comes to entering user input and deleting user input in the Textboxes, my app works the same as the bing app.  (Yes, I tested for null input too.  It works!)

Here are some snippets of my code that implement the text input.

In my MainPage class:
const string DEFAULT_TXT = "Expense";
static string current_txt = DEFAULT_TXT;
static bool txt_default_settings = true;


In the constructor for my MainPage class:
txtInput.GotFocus += txtInput_GotFocus;
txtInput.LostFocus += txtInput_LostFocus;

And some event handlers:
private void txtInput_GotFocus(object sender, RoutedEventArgs e) {
   txtInput.Foreground = new SolidColorBrus(Colors.Black);
  
   if (txt_default_settings) {
      txtInput.Text = "";
   }
   else {
      txtInput.SelectAll();
   }
}

private void txtInput_LostFocus(object arg1, RoutedEventArgs arg2) {
   if (txtInput.Text == String.Empty) {
      txtInput.Foreground = new SolidColorBrush(Colors.Gray);
      txtInput.Text = DEFAULT_TXT;
      current_txt = DEFAULT_TXT;
      txt_default_settings = true;
   }
   else {
      txtInput.Foreground = new SolidColorBrush(Colors.Black);
      txt_default_settings = false;
      current_txt = txtInput.Text.Trim();
   }
}


I think now my next goal is to display a separate page that lists the expenses when the "Display" button is clicked, instead of tons of MessageBoxes flashing across the screen like it does now.

May 28, 2013

expense tracker app - part 2

Just to give an idea of what I've been working on.




These images show a problem I've been trying to fix, which isn't terribly obvious.  But think about trying to use this app, and clicking on the Expense field to enter in new input.  Clicking on the textbox only moves the blinking cursor to the right of the word, which means you have to manually delete the string, which sucks.  It might take only a few seconds but it's annoying if you use it a lot.

In contrast, here are the same set of images, with the same set of actions, done for my bing app:



And notice that clicking on the textbox automatically clears the field for you, which really helps the usability  (I also like how they've dimmed the rest of the app).

Well, I tried all sorts of things, experimented with eventhandlers and delegates, and finally settled on this:

private void txtInput_Click(object sender, MouseButtonEventArgs e) {
   txtInput.Text = "";
}

private void txtInput_LostFocus(object arg1, RoutedEventArgs arg2) {
   txtInput.Text = DEFAULT_TXT;
}

private void numInput_Click(object sender, MouseButtonEventArgs e) {
   numInput.Text = "";
}

private void numInput_LostFocus(object arg1, RoutedEventArgs arg2) {
   numInput.Text = DEFAULT_INT.ToString();
}

With the above in the code-behind, and the below in the XAML (with many things left out):

<TextBox Name="txtInput"
                 InputScope="Text"
                 MouseLeftButtonDown="txtInput_Click"
                 LostFocus="txtInput_LostFocus" />

<TextBox Name="numInput"
                 InputScope="Digits"
                 MouseLeftButtonDown="numInput_Click"
                 LostFocus="numInput_LostFocus" />

I'd like to point out the InputScope field, which specifies the appropriate keyboard to be used.  The "Text" input scope provides a keyboard supplied with characters, and an automatic spellchecker (sometimes I feel guilty about all the functionality that is provided - I thought adding a custom keyboard and a spellchecker would be really complicated).  The "Digits" input scope just provides the digits, obviously, which is all that is needed to add the monetary amount.

And now this is what I have: