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:



May 27, 2013

expense tracker app - part 1

I've been working on another app, that actually serves some functionality besides my "Is It Christmas Yet?" app that happens to say yes on the wrong day..  Yes, I get a lot of crap for that, not enough to change it.  I really did think Christmas was on the 24th when I was writing it.

I'm in the process of implementing a budget tracker because I'm floored every time I see my VISA bill.. I realized it would be nice to have some advance warning.  While I have a very crude version of it, it's actually been helping me to curb my spending.

Here's what I have so far!

(Windows Phone FTW)

Basically the user enters in expenses for the month, although filling in the "Expense" field is optional (the new entry gets filed under "Other").  My display button functionality is a bit awkward, like I said it's a very crude version.  Clicking the display unleashes a torrent of message boxes for each category, here's one:

My drive from Cleveland to Columbus this weekend :(
But I plan on making it more user friendly as I add more functionality.

I think the hardest part initially was figuring out how to store all of the info.  After some research I found out about the IsolatedStorageSettings class, which was perfect for what I needed.

This app definitely needs work.. but it's been a lot of fun to write!  And very useful, I wish I had the idea to make this sooner!

March 18, 2013

first app?

Question mark because all I pretty much did was follow the directions on here, and all that amounted to was dragging a textbox, dragging a button, and dragging a webBrowser control onto a blank app and copying and pasting four lines of code.  Guess we all gotta start somewhere eh?

So here's the code that Microsoft provided for us:
    private void Go_Click(object sender, RoutedEventArgs e)
    {
        string site = URL.Text;
        MiniBrowser.Navigate(new Uri(site, UriKind.Absolute));
    }
I also tried
MiniBrowser.Navigate(new Uri(site));
MiniBrowser.Navigate(new Uri(site, UriKind.Relative) // this hated me
MiniBrowser.Navigate(new Uri(site, UriKind.RelativeOrAbsolute))

I noticed, that for (site, UriKind.Absolute) and just (site), if I removed the "http://" from the website address ("www.bing.com" instead of "http://www.bing.com") then the emulator would take me to an Application_UnhandledException.  But removing the "www" didn't produce errors ("http://bing.com"), while removing both the "www" and "http://" produced errors, but that's because the "http://" was missing.  (site, UriKind.Relative) didn't work for anything, but when I removed the "http://" then it rewrote the MiniBrowser with a "We're having trouble displaying this page" instead of throwing an exception.  So when I tried the (site, UriKind.RelativeOrAbsolute) for the above options, it didn't throw an exception but went into the "We're having trouble displaying this page", which I prefer.  Of course when a null address was input, then it threw an exception for all of the cases.

So taking these into account, here is a more robust version:
    private void Go_Click(object sender, RoutedEventArgs e)
    {
        string site = URL.Text;
        if (String.IsNullOrEmpty(site)) return;
        if (!site.StartsWith("http://") && !site.StartsWith("https://"))
            site = "http://" + site;
        MiniBrowser.Navigate(new Uri(site, UriKind.RelativeOrAbsolute));
    }

And here is a picture:
(bing gets jealous when I use this app and launches itself in full page version.  I took this screenshot in a two-second window.  This app works for other sites though.)

March 16, 2013

Overhaul

Except not.  I tried to rewrite my template from scratch, thinking it would be fun.  And it would have been.. I just don't have the time to learn all of this extra stuff on top of everything else I'm trying to get done.  Then I realized blogger provides templates for a reason - other people doing work that I can mooch off of so I don't have to do as much.  It's what they're teaching me in my CSE curriculum anyway - the best programmers are the laziest ones.

This will have to do for now.

March 03, 2013

Updating

Website is undergoing a makeover.  Plan:
  • Combine "art", "computer science", and "musings" blog into one
  • Links to aforementioned pages on top frame
  • Colors that aren't awful
  • Some organization of blog posts
  • Frame on the side to display timeline of posts
On the plus side, I understand pointerz now.  I look at the posts below and shake my head.

December 15, 2012

more pointerz

Seems like I'll never get the hang of pointers.

In my defense, we've been learning java in class where you never really deal explicitly with pointers.  And java doesn't even call pointers pointers, they have to call it references.  I guess it's a slightly less scary term than pointers, but it's still the same thing.

But now I get to go back to c++ since we're out for break, teaching myself various things again so I don't feel like a bum.

And I just wanted to write a simple program that would traverse the elements of an array and add up all the terms. Simple right?  Except that I'm pointer illiterate and it took me a while.

Anywayz here's what I got:
#include <iostream>
using namespace std;

int main() {
   #define SIZE 3;
   int x[SIZE] = {1, 2, 3);

   int* xptr = x;
   int i = 0, sum = 0;

   cout << "ze array is: ";
   while (i < SIZE) {
      cout << *(xptr + i) << ' ';
      sum += *(xptr + i);
      i++;
   }

   cout << '\n' << x[0] is: " << x[0];
   cout << '\n' << "*x is: " << *x;
   cout << '\n' << *(x + 1) is: " << *(x + 1);
   cout << '\n' << *(x + 2) is: " << *(x + 2);

   return 0;
}

And this is what it outputs:
ze array is: 1 2 3
x[0] is: 1
*x is: 1
*(x + 1) is: 2
*(x + 2) is: 3
sum is: 6

Something I wasn't too happy about is that, for the while loop, I wanted the condition to be while (*(xptr + i) != NULL) but the code wasn't correct for some reason.. It would print out everything I wanted but then print out a bunch of gibberish at the end.

But as always, I learned something new while doing this.  Such as, when you declare an array:
   int x[10]
And you write this:
   *x
Then *x just points to x[0]!  Which is why, in the code above, I was allowed to do shenanigans like
   *(xptr + i)
Since xptr always just points to x, which is really just x[0]!  And (xptr + i) is x[i], and deferencing this just gets you *(xptr + i) = the value at x[i]!

Anyways, yes, easy example, but I'm still recovering from an awful week of finals