Build Your Own Blogging Application, Part 1
Pages: 1, 2
Building the Front End
Understanding Tcl/Tk and XHTML now empowers us to actually build the front end for our blogging app. We know that at a minimum, our GUI should allow the user to write entries to the blog app and exit. Since we'd like to be able to use XHTML with as little effort as possible, a menu with basic markups is also a nice convenience as well as the ability to insert images into our blog. Interestingly, the steps involved in accomplishing these basic tasks generalizes to virtually any XHTML markup we'd ever want to use. Now that you're armed with the tools to build this front end, let's get our hands dirty.
In your favorite editor, copy the following lines of code.
################################################
#Matthew Russell 30 Sep 04
################################################
#A Tcl/Tk front end for a blogging application
#that will write XHTML to the iDisk.
#This script relies on script updateBlog.sh
################################################
#create & title a frame for the widgets
frame .fr -width 10c -height 5c
wm title . "Blogging App v0.1"
pack .fr
#configure menubar on top
frame .menubar -relief raised -bd 2
pack .menubar -in .fr -fill x
#put a text widget (our editor) with y scroll
text .fr.ed -width 80 -height 20 -bg white \
-yscrollcommand ".fr.scroll set" \
-wrap word
scrollbar .fr.scroll -command ".fr.ed yview"
pack .fr.scroll -side right -fill y
pack .fr.ed -side left -fill both -expand true
pack .fr -side top -fill both -expand true
#create a file menu
menubutton .menubar.file -text File \
-underline 0 \
-menu .menubar.file.menu
menu .menubar.file.menu
#items in file menu
.menubar.file.menu add command \
-label "Write To Blog" \
-command WriteToBlog
.menubar.file.menu add command \
-label "Write To Blog and Quit" \
-command WriteToBlogQuit
.menubar.file.menu add command \
-label "Quit" \
-command exit
#create a markup menu button
menubutton .menubar.markup -text Markup \
-underline 0 \
-menu .menubar.markup.menu
menu .menubar.markup.menu
#items in the markup menu
.menubar.markup.menu add command \
-label Bold \
-command {MarkupSelection "strong"}
.menubar.markup.menu add command \
-label Italic \
-command {MarkupSelection "em"}
#create a menu for inserting images
menubutton .menubar.insertImage \
-text "Insert Image" \
-underline 0 \
-menu .menubar.insertImage.menu
menu .menubar.insertImage.menu
#item in the image menu
.menubar.insertImage.menu add command \
-label "Find Image" \
-command InsertImageFile
pack .menubar.file -side left
pack .menubar.markup -side left
pack .menubar.insertImage -side left
pack .menubar -side top -fill x
#start the focus in the editor
focus .fr.ed
#a clean way of displaying error messages
proc ShowMessage {mess} {
toplevel .messpop \
-width 10c \
-height 4c
grab .messpop
wm title .messpop "Warning"
message .messpop.msg \
-relief raised \
-bd 2 \
-text $mess
button .messpop.okb \
-text OK \
-command {destroy .messpop ;
return 0}
pack .messpop.msg .messpop.okb -side top
}
# place markup tags around the selection
proc MarkupSelection {markupTag} {
set theSel [selection get STRING]
set selLen [string length $theSel]
#if true, then the selection done right to left
if {[string equal \
$theSel \
[.fr.ed get insert "insert +$selLen chars"]]} {
.fr.ed delete \
insert "insert + $selLen chars"
.fr.ed insert \
insert "<$markupTag>$theSel</$markupTag>"
} else {
.fr.ed delete \
"insert -$selLen chars" insert
.fr.ed insert \
insert "<$markupTag>$theSel</$markupTag>"
}
}
#Write the blog entry to file
#Then execute a script to post the entry
proc WriteToBlog {} {
set err [catch {set f [open "newentry" w]} \
errormessage]
if {$err == 0} {
puts $f [.fr.ed get 1.0 end]
close $f
#the shell script that updates the blog
exec ./updateBlog.sh
} else {
set ok [ShowMessage "No filename given"]
}
}
proc InsertImageFile {} {
set typelist {
{"All Files" {*}}
{"GIF Image" {".gif"}}
{"JPEG Image" {".jpg"}}
}
global env
set fullName \
[tk_getOpenFile -title "Find Image File" \
-initialdir $env(HOME) \
-filetypes $typelist]
#use the full filename for the tag in the editor
#abbreviate it once it's copied to the iDisk
.fr.ed insert \
insert \
"<img src='$fullName' width= height= />"
}
proc WriteToBlogQuit {} {
WriteToBlog
exit
}
In order to fire up the editor, type wish editor.tcl into your
terminal window, while in the same directory as the file you just copied. Most
of the front end should be fairly straightforward, based on our previous discussion
of Tcl/Tk. We set up a frame, title it, and then add in a menubar. Once that's
done we add in the actual menus themselves and define their actions. We also
insert a text widget that allows us to enter our writing. That's all mechanical
enough. The interesting parts of the editor involve what the menu choices
actually accomplish.

Your nice-looking editor that was almost too easy to make.
Let's start with the markup menu. Following good software design principles, you and I have produced some procedures to accomplish functionality based upon varying parameters.
In the editor, procedure MarkupSelection handles marking up the selection
based upon a parameter that indicates the content of the tag. There's a bit
of a nuisance you have to work around when dealing with selection in Tcl/Tk.
What you can find out easily is where the insertion cursor is located and the
length of the selection. What you have to do some detective work to discover
is whether the act of selecting the text was accomplished right to left or left to right. If selection was accomplished left to right,
then we'd just delete the characters from the insertion cursor (at the right
of the selection) back to the beginning of the selection. If it was accomplished
right to left, then we'd delete characters from the insertion cursor (at the
left end of the selection) to the end of the selection.
Fortunately, we can compare the selection itself to sequences of characters
defined relatively to the insertion cursor to determine which way the selection
occurred. (Say that three times as fast as you can.) Based on one of these
conditions, the procedure just sends an insert and delete command to the
editor along with a range of characters for its arguments.
Next, let's have a look at the image menu. To insert an image, a procedure executes that displays a dialog box to the user. The user navigates through their directory, finds the image to insert, and when the user clicks OK, the tag specifying the location of the image gets inserted.
The actual process of rendering the image is a job for the viewer of the
blog's browser once the entry is posted to the web. We'll work through the
process of copying the image file to the iDisk and changing the absolute path
in the image tag to one relative to the iDisk's directory structure in the
next article. For now, trust that we're doing the right thing here. The interesting
part of the InsertImageFile procedure involves the special variable env.
global is a special, top-level scope that is outside of any procedure.
In order to get the values of our environment variables, we can declare a
special global variable env and use it to access any variable obtained by
typing env in our terminal window. We'll use the $HOME environment variable
to specify a suitable location for directory browsing. A final detail to notice
is that the dialog box will return paths that contain space characters. For
now, this is fine, but keep in mind that we'll need to account for it when
we actually try to copy the file to the iDisk later.
Before closing today's work, let's examine the WriteToBlog procedure. You'll
notice that there's a line that references a shell script that you haven't
written yet. The script involves several exciting new tools and concepts, so
we need to save that one for next time.
For now, take note that the script exists and will ensure the grunt work
of updating the blog that takes place at the back end. We can still understand
the rest of the procedure, however, without knowing the details of this script.
The idea is that we take the information stored in the text widget and store
it to a file entitled newentry. The updateBlog.sh script uses this file to
do its work. There's also a bit of basic error-checking we do to make sure
the file opens successfully. Notice that getting the contents of the text editor
is as simple as using the get command as an argument to the text widget and
specifying that we want all of the text.
For Next Time
Consider implementing a markup for inserting links into your blog entry and
review procedures ShowMessage and WriteToBlogQuit. There are many options,
but think about the pros and cons of your choices before making a design decision.
You might also look into XHTML's specification for aligning text. Using the existing editor's functionality and the XHTML reference at w3schools.com, you should have all of the technical prowess you need to accomplish this task.
You'll find that a little bit of knowledge goes a long way in an app like this one. If you're really ambitious, dig into the text widget's tagging capabilities and try to add basic syntax highlighting for the XHTML commands you've included in your editor. We can only do so much here, but given sufficient time and effort, you can create truly amazing applications with Tcl/Tk. The best way to learn is to practice!
In the next lesson, you'll learn how to write the scripts we need to make
procedure WriteToBlog functional, how to copy the image files from our local
disk to our iDisk, and how to wrap some of that into a bash script that allows
a measure of configurability. Once that's done, your blog will be ready for
the world. The question is whether the world will be ready for your
blog.
Matthew Russell is a computer scientist from middle Tennessee; and serves Digital Reasoning Systems as the Director of Advanced Technology. Hacking and writing are two activities essential to his renaissance man regimen.
Return to MacDevCenter.com.
- Trackback from http://sweb.uky.edu/~mbive2/index.php?p=69
MacDevCenter.com: Build Your Own Blogging Application, Part 1
2004-11-10 04:35:15 [View]

