Sunday, May 17, 2009

Adding a wxPerl GUI to the twitter script: part 4 - Putting it all together

Note: this article is part of a series.

Today I've finished version 1.0.0 of twit_GUI.pl. Nothing fancy, I just added the Net:Twitter part from the console version of twit.pl to the existing User Interface. I can now post to twitter.com or identi.ca from a graphical interface Perl program. That's how cool I am.

New since version 0.0.2
I removed the event handling on EVT_TEXT_MAXLEN because I realized that I didn't need to display a message when I reached 140 characters. The fact that you cannot type anything after the limit is enough. Keeping the message would have been annoying in fact...

A "gentle" analysis from Perl::Critic made me change the way I was calling the open function.
Before:
open(LOGINFILE, $password_file)
After:
open(my $logfile_handle, '<', $password_file)

Explanation:
- The LOGINFILE file handle is dangerous because as such, LOGINFILE is declared as a global. It could already be used as another file's handle.
- The '<' second argument indicates that the file is open in read-only mode. It is easier to see that than in the previous writing and it avoids bugs for file names starting with '<' or '>' (see the full explanation).

I also replaced the double quotes (") by single quotes (') everywhere variable interpolation was not needed.
Speaking about quotes, I removed those surrounding the identifiers of the hash elements.
Speaking about hashes, I really enjoy how flexible they can be used for structuring your data. Take for example the %login hash in $this->{login}. It lets me organize data as such:

%login = {
user_name => { twitter => "Twitter.com user name",
identica => "Identica user name"
},
password => { twitter => "Twitter.com password",
identica => "Identica password"
}
}
And I can add to the hash construct as I need it. Of course, if not documented, I can see that hashes contructed in this manner could get pretty tough to maintain.

What's next?
There are improvements to be made to the twit_GUI script, especially concerning the password handling. Today I have a hard-coded path inside the script which is very ugly. I am not proud of myself but the Perl Iron Man's deadline is arriving soon and I want to stay in the contest ;)
I will apply the finishing touch in a next post.

I am not sure if I should keep the POD comments. I was thinking about throwing it all inside an "About" menu item. Maybe I can display the POD info directly in a MessageBox, in a reentrant fashion.

I will not plaster the walls of this blog with yet another listing but as always you can find all script versions on the DamienLearnsPerl's companion site.


Adding a wxPerl GUI to the twitter script: part 4 - Putting it all together

Note: this article is part of a series.

Today I've finished version 1.0.0 of twit_GUI.pl. Nothing fancy, I just added the Net:Twitter part from the console version of twit.pl to the existing User Interface. I can now post to twitter.com or identi.ca from a graphical interface Perl program. That's how cool I am.

New since version 0.0.2
I removed the event handling on EVT_TEXT_MAXLEN because I realized that I didn't need to display a message when I reached 140 characters. The fact that you cannot type anything after the limit is enough. Keeping the message would have been annoying in fact...

A "gentle" analysis from Perl::Critic made me change the way I was calling the open function.
Before:
open(LOGINFILE, $password_file)
After:
open(my $logfile_handle, '<', $password_file)

Explanation:
- The LOGINFILE file handle is dangerous because as such, LOGINFILE is declared as a global. It could already be used as another file's handle.
- The '<' second argument indicates that the file is open in read-only mode. It is easier to see that than in the previous writing and it avoids bugs for file names starting with '<' or '>' (see the full explanation).

I also replaced the double quotes (") by single quotes (') everywhere variable interpolation was not needed.
Speaking about quotes, I removed those surrounding the identifiers of the hash elements.
Speaking about hashes, I really enjoy how flexible they can be used for structuring your data. Take for example the %login hash in $this->{login}. It lets me organize data as such:

%login = {
user_name => { twitter => "Twitter.com user name",
identica => "Identica user name"
},
password => { twitter => "Twitter.com password",
identica => "Identica password"
}
}
And I can add to the hash construct as I need it. Of course, if not documented, I can see that hashes contructed in this manner could get pretty tough to maintain.

What's next?
There are improvements to be made to the twit_GUI script, especially concerning the password handling. Today I have a hard-coded path inside the script which is very ugly. I am not proud of myself but the Perl Iron Man's deadline is arriving soon and I want to stay in the contest ;)
I will apply the finishing touch in a next post.

I am not sure if I should keep the POD comments. I was thinking about throwing it all inside an "About" menu item. Maybe I can display the POD info directly in a MessageBox, in a reentrant fashion.

I will not plaster the walls of this blog with yet another listing but as always you can find all script versions on the DamienLearnsPerl's companion site.


Saturday, May 9, 2009

Adding a wxPerl GUI to the twitter script: part 3 - Polishing up the UI

Last time I wrote about the WxPerl twitter GUI, I made a nice little drawing about what I wanted to achieve.
The first try wasn't too far off but a few functionalities are still missing. One of them is the real-time updating of the remaining text characters (from a limit of 140). Obviously, what I need is an event on a key stroke to update the number of characters.

WxEvents documentation
Command events can be handled by macros listed in the WxWidget/WxPerl's manual under the wxCommandEvent page.
Of interest to the twitter GUI script are:

EVT_TEXT(id, func) Process a wxEVT_COMMAND_TEXT_UPDATED command, which is generated by a wxTextCtrl control.
EVT_TEXT_MAXLEN(id, func) Process a wxEVT_COMMAND_TEXT_MAXLEN command, which is generated by a wxTextCtrl control when the user tries to enter more characters into it than the limit previously set with SetMaxLength.

The first macro (EVT_TEXT) can be linked to the TextControl box where the message is being typed. Whenever a character is added or removed to the update message, the event handler will compute and display the remaining characters left before hitting the 140 limit.
The EVT_TEXT_MAXLEN macro will link the update message's TextControl to a subroutine that will be called when 140 characters have been inputted.

Code
When using WxPerl constants, the first thing to remember is to declare them at the beginning of the package.

use Wx::Event qw(EVT_BUTTON EVT_CLOSE EVT_TEXT EVT_TEXT_MAXLEN);

To find out the complete list of symbols, you can check the Wx source code in the lib/Wx/Wx_Exp.pm file located in your Perl directory. In this file, you will also be able to see all existing tags created to group related constants. For example, 'statictext' is defined as:

$EXPORT_TAGS{'statictext'} = [ qw(wxALIGN_LEFT
wxALIGN_CENTRE
wxALIGN_CENTER
wxALIGN_RIGHT
wxST_NO_AUTORESIZE
wxST_ELLIPSIZE_START
wxST_ELLIPSIZE_MIDDLE
wxST_ELLIPSIZE_END
wxST_MARKUP) ];

Writing the following line in your program:

use Wx qw(:statictext);

will import all nine constants listed above.

Coming back to our problem at hand, if we create a TextControl and StaticText objects like this

#
# Text control to enter message to twit
#
$this->{update_text} = Wx::TextCtrl->new(
$this, # parent window
-1, # control identifier
"Type your message here", # default text value
[20, $ylines[3]], # text control position [x, y]
[435, 35], # text control size [width, height]
wxTE_MULTILINE # style: wxTE_MULTILINE=The text control allows multiple lines
);

# A EVT_TEXT_MAXLEN event is generated when the number of characters in the update_text control
# reaches the maximum passed value.
$this->{update_text}->SetMaxLength(MAX_POST_LENGTH);

#
# Static text placed at the top-right position of the text control
#
Wx::StaticText->new(
$this, # parent
-1, # id
'characters left', # label
[$form_width - 95, $ylines[2]] # position [x, y]
);

#
# Static text displaying number of characters left before reaching the max amount
#
$this->{static_text}{'CharsLeft'} = Wx::StaticText->new(
$this, # parent
-1, # id
MAX_POST_LENGTH - $this->{update_text}->GetLastPosition, # label
[$form_width - 115, $ylines[2]], # position [x, y]
wxDefaultSize, # size
Wx::wxALIGN_RIGHT # style. Not implemented yet?
);

then calling the following event handlers

# Events associated to the update_text Control
# EVT_TEXT_MAXLEN is generated when the length of the Text control
# becomes larger than the value set by SetMaxLength
EVT_TEXT_MAXLEN($this, $this->{update_text}, \&MaxTextReached);

# EVT_TEXT is generated when a character is typed inside the Text control
# We use it to update the display of characters left for message
EVT_TEXT($this, $this->{update_text}, \&CountCharsLeft);

with the subroutines definition being:

sub CountCharsLeft {
my($this, $event) = @_;

# Update number of remaining characters = MAX - current text size
my $chars_left = MAX_POST_LENGTH - $this->{update_text}->GetLastPosition;
$this->{static_text}{'CharsLeft'}->SetLabel($chars_left);
}

sub MaxTextReached {
my($this, $event) = @_;

Wx::MessageBox(
"You have reached the maximum number of characters", # text
"Update too big", # title bar
wxOK, # buttons to display on form
$this # parent
);
}
then every time that {update_text} is edited, CountCharsLeft() will be called and will reset the label for {static_text}{'CharsLeft'} with the new value computed from {update_text}->GetLastPosition.
I couldn't achieve right-aligning the number of characters. From reading the Wx::Perl::Dialog source, I do not think that the style argument is supported yet.

The result?

Now one step further to accomplish my goal of being able to understand Padre's code once I put my nose in it...


Adding a wxPerl GUI to the twitter script: part 3 - Polishing up the UI

Last time I wrote about the WxPerl twitter GUI, I made a nice little drawing about what I wanted to achieve.
The first try wasn't too far off but a few functionalities are still missing. One of them is the real-time updating of the remaining text characters (from a limit of 140). Obviously, what I need is an event on a key stroke to update the number of characters.

WxEvents documentation
Command events can be handled by macros listed in the WxWidget/WxPerl's manual under the wxCommandEvent page.
Of interest to the twitter GUI script are:

EVT_TEXT(id, func) Process a wxEVT_COMMAND_TEXT_UPDATED command, which is generated by a wxTextCtrl control.
EVT_TEXT_MAXLEN(id, func) Process a wxEVT_COMMAND_TEXT_MAXLEN command, which is generated by a wxTextCtrl control when the user tries to enter more characters into it than the limit previously set with SetMaxLength.

The first macro (EVT_TEXT) can be linked to the TextControl box where the message is being typed. Whenever a character is added or removed to the update message, the event handler will compute and display the remaining characters left before hitting the 140 limit.
The EVT_TEXT_MAXLEN macro will link the update message's TextControl to a subroutine that will be called when 140 characters have been inputted.

Code
When using WxPerl constants, the first thing to remember is to declare them at the beginning of the package.

use Wx::Event qw(EVT_BUTTON EVT_CLOSE EVT_TEXT EVT_TEXT_MAXLEN);

To find out the complete list of symbols, you can check the Wx source code in the lib/Wx/Wx_Exp.pm file located in your Perl directory. In this file, you will also be able to see all existing tags created to group related constants. For example, 'statictext' is defined as:

$EXPORT_TAGS{'statictext'} = [ qw(wxALIGN_LEFT
wxALIGN_CENTRE
wxALIGN_CENTER
wxALIGN_RIGHT
wxST_NO_AUTORESIZE
wxST_ELLIPSIZE_START
wxST_ELLIPSIZE_MIDDLE
wxST_ELLIPSIZE_END
wxST_MARKUP) ];

Writing the following line in your program:

use Wx qw(:statictext);

will import all nine constants listed above.

Coming back to our problem at hand, if we create a TextControl and StaticText objects like this

#
# Text control to enter message to twit
#
$this->{update_text} = Wx::TextCtrl->new(
$this, # parent window
-1, # control identifier
"Type your message here", # default text value
[20, $ylines[3]], # text control position [x, y]
[435, 35], # text control size [width, height]
wxTE_MULTILINE # style: wxTE_MULTILINE=The text control allows multiple lines
);

# A EVT_TEXT_MAXLEN event is generated when the number of characters in the update_text control
# reaches the maximum passed value.
$this->{update_text}->SetMaxLength(MAX_POST_LENGTH);

#
# Static text placed at the top-right position of the text control
#
Wx::StaticText->new(
$this, # parent
-1, # id
'characters left', # label
[$form_width - 95, $ylines[2]] # position [x, y]
);

#
# Static text displaying number of characters left before reaching the max amount
#
$this->{static_text}{'CharsLeft'} = Wx::StaticText->new(
$this, # parent
-1, # id
MAX_POST_LENGTH - $this->{update_text}->GetLastPosition, # label
[$form_width - 115, $ylines[2]], # position [x, y]
wxDefaultSize, # size
Wx::wxALIGN_RIGHT # style. Not implemented yet?
);

then calling the following event handlers

# Events associated to the update_text Control
# EVT_TEXT_MAXLEN is generated when the length of the Text control
# becomes larger than the value set by SetMaxLength
EVT_TEXT_MAXLEN($this, $this->{update_text}, \&MaxTextReached);

# EVT_TEXT is generated when a character is typed inside the Text control
# We use it to update the display of characters left for message
EVT_TEXT($this, $this->{update_text}, \&CountCharsLeft);

with the subroutines definition being:

sub CountCharsLeft {
my($this, $event) = @_;

# Update number of remaining characters = MAX - current text size
my $chars_left = MAX_POST_LENGTH - $this->{update_text}->GetLastPosition;
$this->{static_text}{'CharsLeft'}->SetLabel($chars_left);
}

sub MaxTextReached {
my($this, $event) = @_;

Wx::MessageBox(
"You have reached the maximum number of characters", # text
"Update too big", # title bar
wxOK, # buttons to display on form
$this # parent
);
}
then every time that {update_text} is edited, CountCharsLeft() will be called and will reset the label for {static_text}{'CharsLeft'} with the new value computed from {update_text}->GetLastPosition.
I couldn't achieve right-aligning the number of characters. From reading the Wx::Perl::Dialog source, I do not think that the style argument is supported yet.

The result?

Now one step further to accomplish my goal of being able to understand Padre's code once I put my nose in it...


Sunday, May 3, 2009

AdSense integration to Google analytics and other news

AdSense
If you are a blogger with AdSense revenues, you can now integrate the AdSense stats to your Google Analytics account.
To do so, just follow those very simple instructions.

DamienLearnsPerl's April Analytics stats
  • Thanks to the Perl::Critic post appearing on Hacker News, there was a peak at 661 visits on the 28th of April!
  • The United States (728), France (98) and the UK (93) are the leading trio of visiting countries in April.
  • 2/3 of visitors use Firefox, IE (8.8%) is in third place behind Safari (10%)
  • 56% of visits originate from Windows, 21.5% from Linux and 20% from a Mac
Strawberry Perl
New versions are freshly available for both Perl 5.8.9 and 5.10.0.
Check out what's new!

The Perl Review

The last issue is already 2-week old. Get it there!

Perl IronMan
I entered the IronMan challenge, the brainchild of Matt Trout from Enlightened Perl. Check out all participating blogs in Planet Perl Iron Man!

Padre v0.34
Version 0.34 has been released. See the changelog here.

AdSense integration to Google analytics and other news

AdSense
If you are a blogger with AdSense revenues, you can now integrate the AdSense stats to your Google Analytics account.
To do so, just follow those very simple instructions.

DamienLearnsPerl's April Analytics stats
  • Thanks to the Perl::Critic post appearing on Hacker News, there was a peak at 661 visits on the 28th of April!
  • The United States (728), France (98) and the UK (93) are the leading trio of visiting countries in April.
  • 2/3 of visitors use Firefox, IE (8.8%) is in third place behind Safari (10%)
  • 56% of visits originate from Windows, 21.5% from Linux and 20% from a Mac
Strawberry Perl
New versions are freshly available for both Perl 5.8.9 and 5.10.0.
Check out what's new!

The Perl Review

The last issue is already 2-week old. Get it there!

Perl IronMan
I entered the IronMan challenge, the brainchild of Matt Trout from Enlightened Perl. Check out all participating blogs in Planet Perl Iron Man!

Padre v0.34
Version 0.34 has been released. See the changelog here.