Developer’s Narrative
Project RocketDock Vista Fix 2 (GUI Edition)
Start Date March 20, 2009
End Date March 21, 2009
Developer Bryan G. Neilson
Rationale:
I started developing the older brother of this application while trying to use the
“Single-User Mode” feature in an application called RocketDock on Windows
Vista. While struggling with the application and looking up information on forums,
I discovered that Windows Vista (in some cases) would not allow the RocketDock
application to create a needed file (settings.ini).
For this new version, I thought it would be nice to add a GUI to this application
and update the code and commenting style to allow easy documentation.
Synopsis:
As mentioned before, this application was developed to bring a GUI (Graphical
User Interface) and a new commenting style to my previous version of the
RocketDock Vista Fix application that is currently and has been available on
SourceForge.net for some time.
For both the reason of this application being relatively small to begin with as well
as the fact my original code was a little messier than I would have liked, I decided
that I would start from scratch and build a completely new application.
The GUI of this application, as it is being programmed in PERL to begin with, has
been coded in PERL/Tk. It is true that there are some stability issues with the
PERL Tk module under Windows Vista (some that remain even after the
application has been compiled), however, I chose to use PERL/Tk to build the
GUI as it has always been and continues to be a very simple to use and light
weight in its implementation.
The commenting convention I chose to use for this application is a combination
of a comment style that will be accepted by NaturalDocs (an application for
building documentation from source code files) with a hint of my own
commenting methods. For an example of this style see Snippet One.
Snippet One:
262 #################################################
263 =nd
264
265 Function: wrongdir
266 Pre:
267 $dir is not a valid directory
268
269 Post:
270 Alg:
271 - Create new window for $wrongdir
272 - Set window $wrongdir to non-resizable
273 - Print to window $wrongdir "Wrong Directory" using
Label
274 - Print to window $wrongdir $dir using Label
275 - Build Button for window @wrongdir with text "Close"
276
277 Close Button Alg:
278 Destroy window $wrongdir
279
280 =cut
281 #
282 #
283 #
As you can see from Snippet One, the commenting convention I chose to use for
this application (also what I use for most of my PERL projects) gives the function
name, Preconditions, Postconditions and Algorithms.
Journal:
Line 001:
I declared /usr/bin/perl as my interpreter for this application with the option –w.
Snippet Two:
1 #!/usr/bin/perl -w
Lines 003 – 013:
This portion of the code designated options for the NaturalDocs documentation
application.
Lines 015 - 056:
In this portion of the code, I designated information to be included in
documentation. This information includes: Title of project, files included in the
project, author, language/s, modules, interpreter, description, legal information
and licensing information.
Lines 058 – 060:
In this portion of the code I included the required modules for the following code.
Snippet Three:
58 use strict;
59 use FileHandle;
60 use Tk;
Lines 062 – 130:
In this section of the code I chose to define all the variables in comments for the
documenting process. As you will see there is a very set form as to how I define
these variables for the NaturalDocs application, see Snippet Four.
Snippet Four:
72 Variable: $dir
73 my $dir = "";
74
75 Post:
76 $dir is initialized to ""
77
78
79 Variable: $main
80 my $main = MainWindow->new();
81
82 Post:
83 A new window named $main has been created.
As you can see I define the variables for the documenting application by stating
“Variable:” then the variable symbol. After that I write the exact code that can be
found for defining that variable later in the applications code. After that I list a
postcondition of what the variable will be after it is defined. As you can see in the
variable stated on line 72 $dir is initialized to “” while the variable stated on line
79 ($main) is used to identify with a new Tk window.
Lines 132 & 133:
In these lines I define the two variables that do not associate with Tk windows
($file and $dir). These variables are defined globally and will be used for the rest
of this application.
Snippet Five:
132 my $file = "";
133 my $dir = "";
Both variables $file and $dir are initialized to “” holding true to the Postcondition
defined earlier in lines 75 and 76.
Lines 135 – 166:
Here I chose to comment on the function “welcome” which also happens to be
the next thing listed in the source code (Lines 173 – 216).
Snippet Six:
135 #################################################
136 =nd
137
138 Function: welcome
139 Post:
140 Welcome window has been generated to the screen.
141 Alg:
142 - Create new window for $main
143 - Set geometry of window $main to 250x92
144 - Set window $main to non-resizable
145 - Print title to window $main in Label
146 - Print "RocketDock Directory:" to $main in Label
147 - Build Entry text box ($dirstr) on $main with a
default value
148 C:\Program Files\RocketDock\ and a width of 35
149 - Build Button on left of window $main with text
"Patch"
150 - Build Button on right of window $main with text
"Exit"
151 - Build Button on right of window $main with text
"About"
As you can see in Snippet Six (Lines 135 – 151) the function is listed with the
postcondition and algorithm associated with the function.
Snippet Seven:
153 Patch Button Alg:
154 - Set $dir to the contents of $dirstr
155 - Check to see if $dir exists
156 - If $dir exists set $file to "$dir\settings.ini"
157 otherwise invoke wrongdir function
158 - Check to see if settings.ini already exists
159 - If $file exists invoke function fae otherwise
160 destroy window $main and invoke function run
161
162 Exit Button Alg:
163 Invoke exit (Exit Application)
164
165 About Button Alg:
166 Invoke function about
In Snippet Seven, you can see that I listed the algorithms for the subroutines
found for each button in this windows ($main).
Lines 173 – 216:
And finally we come to the code for the first function (the welcome function). The
function is defined by the code “sub welcome” and the first thing I do is build the
windows that that will be identified by the variable $main.
Snippet Eight:
173 sub welcome
174 {
175
176 my $main = MainWindow->new();
177 $main->geometry( "250x92");
178 $main->resizable(0, 0);
179 $main->Label(-text => "RocketDock Windows Vista Fix 2\n(GUI
Edition)")->pack;
180 $main->Label(-text => "RocketDock Directory:")->pack;
181 my $dirstr = $main->Entry(
182 -text => "C:\\Program Files\\RocketDock",
183 -width => 35
184 )->pack;
185 $main->Button(
186 -text => "Patch...",
187 -command => sub{
188 $dir = $dirstr->get;
189 if(-e $dir)
190 {
191 $file = "$dir\\settings.ini";
192 if (-e $file)
193 {
194 fae();
195 }
196 else
197 {
198 $main->destroy;
199 run();
200 }
201 }
202 else
203 {
204 wrongdir();
205 }
206 }
207 )->pack(-side => "left");
208 $main->Button(
209 -text => "Exit",
210 -command => sub{exit}
211 )->pack(-side => "right");
212 $main->Button(
213 -text => "About",
214 -command => sub{about()}
215 )->pack(-side => "right");
216 }
As you can see in Snippet Eight, all the code for the welcome function sticks to
the postconditions and algorithms from the comments in line 135 – 166. This first
thing is to generate the $main window and set its geometry and resize settings.
After that I printed to the $main window “RocketDock Windows Vista Fix 2\nGUI
Edition)” using the Label command. After that I print “RocketDock Directory:”
label and generate an Entry widget for window $main. After this, I built the button
widgets. A button was constructed for “Patch…” (placed on the left side of
window $main), “Exit” (placed on the right side of window $main) and “About”
(also placed on the right side of window $main.
The “Patch…” button has a subroutine that results in either one of a number of
functions based on the return of two conditionals. The first thing done is to see if
the director imputed into the Entry widget exists. If this is not the case, the
“wrongdir” function is invoked. If the directory does exist then the code will move
onto the next conditional. In this next conditional I check to see if the file
“settings.ini” already exists. If this is the case, I invoke the “fae” function
otherwise the program is allowed to continue. If this is the case then window
$main is destroyed and the “run” function is invoked.
The “Exit” button has a subroutine that results in the PERL exit function thus
closing all open windows and terminating the application.
The “About” button has a subroutine that results in the “about” function being
invoked. This does not terminate the application nor does it destroy any active
windows or widgets.
Lines 218 – 240:
Here I wrote the comments for the next function in the code (the “run” function).
This function is written in the code between lines 242 and 260. Again the
comments were written in a style to be easily converted to documentation using
NaturalDocs.
Snippet Nine:
218 #################################################
219 =nd
220
221 Function: run
222 Pre:
223 Function run has been called from function welcome
224
225 Post:
226 Alg:
227 - Create new window for $run
228 - Set window $run to non-resizable
229 - Print "Patching..." to window $run using Label
230 - Open/Create file $file (FileHandle: FILE)
231 - Close file $file (FileHandle: FILE)
232 - Destroy window $run
233 - Check if $file exists
234 - If $file exists invoke function done
235 otherwise invoke function error
236
237 =cut
238 #
239 #
240 #
As seen in Snippet Nine, the “run” function has a precondition. The algorithm for
this function is also defined in the postcondition section of the comments for this
function.
Lines 242 – 260:
The function expressed in this part of the source code (the “run” function)
generates one Tk window ($run) and creates settings.ini and finally check to see
if settings.ini exists after it has been created.
Snippet Ten:
242 sub run
243 {
244 my $run = MainWindow->new;
245 $run->resizable (0, 0);
246 $run->Label(
247 -text => "Patching..."
248 )->pack;
249 open FILE, ">$file";
250 close FILE;
251 $run->destroy;
252 if (-e $file)
253 {
254 done();
255 }
256 else
257 {
258 error();
259 }
260 }
This function starts with the code “sub run” to define the function. After that a
new windows is generated for $run and it is set to non-resizable. Next a label is
printed to window $run with the text “Patching…”
After window $run has been generated and filled, the open function is called on
$file ([location]\settings.ini) to create the file in the location imputed from the
Entry widget in window $main. After that the file is closed and window $run is
destroyed.
The next thing done in the function is to check for existence of the file ($file /
settings.ini) that was hopefully created using the open function. If the file does
now exist the “done” function is invoked, otherwise the “error” function is invoked.
Lines 262 – 283:
In this portion of the code I listed all the documentation and comment data for the
“wrongdir” function.
Snippet Eleven:
262 #################################################
263 =nd
264
265 Function: wrongdir
266 Pre:
267 $dir is not a valid directory
268
269 Post:
270 Alg:
271 - Create new window for $wrongdir
272 - Set window $wrongdir to non-resizable
273 - Print to window $wrongdir "Wrong Directory" using
Label
274 - Print to window $wrongdir $dir using Label
275 - Build Button for window @wrongdir with text "Close"
276
277 Close Button Alg:
278 Destroy window $wrongdir
279
280 =cut
281 #
282 #
283 #
Snippet Eleven shows preconditions, postconditions and algorithm performed in
the “wrongdir” function. This also shows the algorithm for the subroutine of the
“Close” button for window $wrongdir.
The Precondition for the “wrongdir” function is that the directory the user supplied
in the Entry widget of the $main window was not a valid Windows directory.
Lines 285 – 296:
These lines of the code express the function commented above (function
“wrongdir”).
Snippet Twelve:
285 sub wrongdir
286 {
287 #Generate Wrong Dir Window
288 my $wrongdir = MainWindow->new();
289 $wrongdir->resizable (0, 0);
290 $wrongdir->Label(-text => "Wrong Directory")->pack;
291 $wrongdir->Label(-text => $dir)->pack;
292 $wrongdir->Button(
293 -text => "Close",
294 -command => sub{$wrongdir->destroy}
295 )->pack;
296 }
The first action in the function is to create a new Tk window ($wrongdir) and set it
to non-resizable. After that a label is printed to $wrongdir with the text “Wrong
Directory” and another label printed beneath it with the variable $dir printed in
plain text. After that a button widget is built with the text “Close.” The subroutine
of this widget destroys the window $wrongdir.
Lines 298 – 319
In these lines of the code, I commented on the following function (the “fae”
function) found in lines 321 – 332. This function is invoked when the directory
entered by the user in the Entry widget of window $main already has a file called
settings.ini within it. If / when this function is invoke, the $main window is not
destroyed and the “run” function is not invoked.
Snippet Thirteen:
298 #################################################
299 =nd
300
301 Function: fae
302 Pre:
303 $file already exists
304
305 Post:
306 Alg:
307 - Create new window for $fea
308 - Set window $fea to non-resizable
309 - Print "Settings.ini already exists." to window $fea
using Label
310 - Print "No need to run patch..." to window $fea with
Lavel
311 - Build Button for window $fea with text "Close"
312
313 Close Button Alg:
314 Destroy window $fea
315
316 =cut
317 #
318 #
319 #
Snippet Thirteen shows the precondition ($file already exists), postconditions and
algorithms found in the “fae” function.
Lines 321 – 332:
In these lines of code I wrote the code for the function described in the comments
above (Lines 298 – 319). This function is opened by the code “sub fae”
Snippet Fourteen:
321 sub fae
322 {
323 #Generate File Already Exists window
324 my $fae = MainWindow->new();
325 $fae->resizable (0, 0);
326 $fae->Label(-text => "Settings.ini already exists.")->pack;
327 $fae->Label(-text => "No need to run patch...")->pack;
328 $fae->Button(
329 -text => "Close",
330 -command => sub{$fae->destroy}
331 )->pack;
332 }
The first thing done within this function is to generate a new window ($fae) that is
not resizable. Next two labels are printed to the window ($fae), the first one with
the text of “Settings.ini already exists.” And the second one with the text “No
need to run patch…” Finally a button widget is generated on window $fae with
the text “Close” and subroutine of destroying window $fae.
Lines 334 – 357:
In this section of the source code I wrote comments, again with a style that
NaturalDocs accepts, the preconditions, postconditions and algorithms of the
“done” function (Lines 359 – 369).
Snippet Fifteen:
334 #################################################
335 =nd
336
337 Function: done
338 Pre:
339 Patching process has finished without any errors.
340
341 Post:
342 Alg:
343 - Create new windows for $done
344 - Set window $done to non-resizable
345 - Print "Patch Complete. Please restart your
computer." to
346 window $done using Label
347 - Print "If you continue to have problems, try
disabling
348 Windows User Account Control." to window $done using
Label
349 - Build Button for window $done with text "Exit"
350
351 Exit Button Alg:
352 Invoke exit (Exit Application)
353
354 =cut
355 #
356 #
357 #
The precondition of function “done” is that the patching process has completed
without any errors (settings.ini has been proven to exist after the process
creating the file has completed).
Lines 359 – 369:
After commenting on function “done” I opened this function by stating “sub done”
Snippet Sixteen:
359 sub done
360 {
361 my $done = MainWindow->new();
362 $done->resizable (0, 0);
363 $done->Label(-text => "Patching Complete. Please restart your
computer.")->pack;
364 $done->Label(-text => "If you continue to have problems, try
disabling\nWindows User Account Control.")->pack;
365 $done->Button(
366 -text => "Exit",
367 -command => sub{exit}
368 )->pack;
369 }
The first thing done in the coding for this application after opening the function
was to generate a new window ($done) and set it to non-resizable. Once window
$done is generated a Label is printed to window $done with the text “Patching
Complete. Please restart your computer.” Another label is printed to window
$done with the text “If you continue to have problems, try disabling\nWindows
User Account Control.” Finally a button widget is generated with the text “Exit”
and contains a subroutine that invokes the PERL exit function.
Lines 371 – 395:
The next thing I wrote in the source code was the comments for the “error”
function found on lines 397 – 408. Within these comments you can find the
preconditions, postconditions and algorithms of everything happening within the
function.
Snippet Seventeen:
371 #################################################
372 =nd
373
374 Function: error
375 Pre:
376 There has been an error and $file does not
377 exist after being created.
378
379 Post:
380 Alg:
381 - Create new window for $error
382 - Set window $error to non-resizable
383 - Print "An error occurred during patching."
384 to window $error using Label
385 - Print "Please contact the developer." to
386 window $error using Label
387 - Print "Developer Info abailable via About
388 section." to window $error using Label
389 - Build Button on left of window $error with
390 text "Exit"
391
392 Exit Button Alg:
393 Invoke exit (Exit Application)
394
395 =cut
As you can see the preconditions for the function “error” are that there has been
an error during file creation in the function “run” and settings.ini ($file) has been
proven to not exist even after created using the PERL FileHandle open function.
Lines 397 – 408:
In this portion of the code I created and coded the function described in the
above comments (lines 371 – 395).
Snippet Eighteen:
397 sub error
398 {
399 my $error = MainWindow->new();
400 $error->resizable (0, 0);
401 $error->Label(-text => "An error occurred during patching.")-
>pack;
402 $error->Label(-text => "Please contact the developer.")->pack;
403 $error->Label(-text => "Developer Info available via About
section.")->pack;
404 $error->Button(
405 -text => "Exit",
406 -command => sub{exit}
407 )->pack(-side => "left");
408 }
The first thing done in this function, like in many others within this project, is to
generate a new window ($error) and set it to non-resizable. Next three Labels
were printed to the windows ($error) with the text “An error occurred during
patching.”, “Please contact the developer.” and “Developer Info available via
About section.” After this a button widget is generated on window $error with the
text “Exit” and the subroutine of invoking the PERL exit function. This button
widget is placed on the “left” side of the $error window.
Lines 410 – 429:
Working our way to the final part of this project, in this section, I wrote the
comments for the “about” function. This section of the code holds all the
preconditions, postconditions and algorithms for the “about” function.
Snippet Nineteen:
410 #################################################
411 =nd
412
413 Function: about
414 Pre:
415 about function has been called from welcome function.
416
417 Post:
418 Alg:
419 - Create new window for $about
420 - Set geometry of window $about to 400x390
421 - Set window $about to non-resizable
422 - Print about / developer / license / contact
information
423 to window $about using Label
424 - Build Button for window $about with text "Close"
425
426 Close Button Alg:
427 Destroy window $about
428
429 =cut
The precondition of this function is that the “about” function has been called from
within the “welcome” function.
Lines 431 – 454:
In this portion of this application I started to code the final function (the “about”
function) of this program. This function is opened by the code “sub about” and is
defined with full preconditions, postconditions and algorithms in lines 410 – 429.
Snippet Twenty:
431 sub about
432 {
433 my $about = MainWindow->new();
434 $about->geometry ( "400x390" );
435 $about->resizable (0, 0);
436 $about->Label(-text => "RocketDock Windows Vista Fix 2")->pack;
437 $about->Label(-text => "(GUI Edition)")->pack;
438 $about->Label(-text => " \n")->pack;
439 $about->Label(-text => "This application has been developed to
fix an error that occurs with some\ninstallations of RocketDock on
Windows Vista causing the user to have trouble\nenabling \"Single-User
Mode.\"")->pack;
440 $about->Label(-text => "This application will create a file
that Windows Vista will not allow the\nRocketDock application to create
on its own.")->pack;
441 $about->Label(-text => "Though this application is created to
fix this issue, some users may still\nhave problems if Microsoft
Windows User Account Control is enabled.")->pack;
442 $about->Label(-text => " \n")->pack;
443 $about->Label(-text => "License: BSD License")->pack;
444 $about->Label(-text => " \n")->pack;
445 $about->Label(-text => "Developer: Bryan G. Neilson")->pack;
446 $about->Label(-text => "E-Mail Questions and Comments to:
bgneilson\@devsoft.ath.cx")->pack;
447 $about->Label(-text => " \n")->pack;
448 $about->Label(-text => "Please visit my development site:")-
>pack;
449 $about->Label(-text => "http://devsoft.ath.cx")->pack;
450 $about->Button(
451 -text => "Close",
452 -command => sub{$about->destroy}
453 )->pack;
454 }
The first thing I did in this function was to generate a new window for $about and
set it to non-resizable. This window ($about) contains no widgets besides Label
elements. These Label elements print to window $about information about the
application and myself as the developer.
Lines 455 & 456
Coming to the final two lines of this application, all that was left to do was to
invoke the “welcome” function and include the required “MainLoop” element from
the Tk module.
Snippet Twenty-one:
455 welcome();
456 MainLoop;
Once the “welcome” function and “MainLoop” elements have been included the
application is finished and ready to be tested, compiled and distributed.
Conclusion:
This project took me not even two days complete. I was able to utilize the both
the FileHandle and Tk modules. The FileHandle module was used to create the
settings.ini file within the “run” function. The Tk module was utilized to be able to
generate stable a simple GUI (Graphic User Interface) environments.
When I started the coding for this project, I decided to start from scratch and
build a completely separate application. This application is developed to fix an
issues that comes up from some installation of the popular RocketDock software
on a Windows Vista machine.
For any questions or comments on this application, the source code or any part
of the documentation please feel free to contact me at bgneilson@devsoft.ath.cx