Preparing the Ground


OK, enough preaching. Let s try the menu idea and see what happens. Here s my prediction on what will happen, given my reading of some examples:

  • The menu code will be long, but not particularly difficult. I plan to start with an incredibly simple menu and go from there.

  • The menu code will contain substantial duplication, which will irritate us as time goes on.

  • The menu code will require me to link the menu item to a separate handler, which will originally duplicate code in the keyboard handler.

  • It should be possible to remove the code from the keyboard handler after the menu works.

  • The breakout of the menu handler will make the code a bit nicer. This may lead to further improvement using the same technique.

This is all speculation, of course. I m sharing it with you so that you ll know that in XP we do speculate, and so that we can see how it turns out. Let s look at the code we re starting with for the Form:

 using System; 
using System.Drawing;
using System.Windows.Forms;
using NUnit.Framework;
using System.Collections;
using System.Text.RegularExpressions;
namespace Notepad
{ class XMLNotepad : Form {
public TestableTextBox textbox;
private TextModel model;

static void Main(string[] args)
{
Application.Run(new XMLNotepad());
}
public XMLNotepad() {
Text = "XML Notepad";
textbox = new TestableTextBox();
textbox.Parent = this;
textbox.Dock = DockStyle.Fill;
textbox.BorderStyle = BorderStyle.None;
textbox.Multiline = true;
textbox.ScrollBars = ScrollBars.Both;
textbox.AcceptsTab = true;
textbox.KeyDown += new KeyEventHandler(XMLKeyDownHandler);
textbox.KeyPress +=
new KeyPressEventHandler(XMLKeyPressHandler);
model = new TextModel();
}
private void InitializeComponent() {
this.SuspendLayout();
//
// textbox
//
this.textbox.Visible = true;
//
// XMLNotepad
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.textbox});
this.Name = "XMLNotepad";
this.ResumeLayout(false);
}
void XMLKeyPressHandler(object objSender, KeyPressEventArgs kea) {
Console.WriteLine(
"KeyPress\n char {0}\n int {1}",
kea.KeyChar,
(int) kea.KeyChar);
if ((int) kea.KeyChar == (int) Keys.Enter) {
kea.Handled = true;
// this code is here to avoid putting extra enters
// in the window.
// if removed, when you hit enter, the new <P> line breaks
// in two: // <P>
// </P> like that.
}
}
void XMLKeyDownHandler(object objSender, KeyEventArgs kea) {
Console.WriteLine(
"KeyDown char {0} int {1}", kea.KeyCode, (int) kea.KeyCode);
model.SetLines(textbox.Lines);
model.SelectionStart = textbox.SelectionStart;
if (kea.KeyCode == Keys.Enter) {
model.Enter();
kea.Handled = true;
}
if (kea.KeyCode == Keys.X)
kea.Handled = true;
if (kea.KeyCode == Keys.S && kea.Alt) {
model.AltS();
kea.Handled = true;
}
PutText(textbox, model.LinesArray(), model.SelectionStart);
}
public void PutText(ITestTextBox textbox, string[] lines,
int selectionStart) {
// this is Feature Envy big time.
textbox.Lines = lines;
textbox.SelectionStart = selectionStart;
textbox.ScrollToCaret();
}
}
}

I ve left the Console.WriteLines in there so that you can see where I put them. I also think that when the menu goes in, we might see something interesting in the key handlers. You might also notice that I ve taken out the inheritance of this Form from the earlier NotepadCloneNoMenu Form. I just moved the textbox stuff down to this class, because the other Form wasn t helping and seemed to be making things hard to understand.

Furthermore, based on my reading of code that Microsoft Visual Studio generates, there s a bit of confusion between creating and initializing things like the textbox in the object constructor (XMLNotepad()) and in the InitializeComponent() method. Visual Studio .NET seems to put most of the stuff in the InitializeComponent. Petzold, on the other hand, puts everything in the constructor. I consider our current mixed approach to be a bit of a code smell, but I m not going to worry about it yet. Well, on the other hand, why not. Let s experiment; that s what this book is about. I m going to move all the code from the InitializeComponent up to the constructor and remove the method. My reading says that the SuspendLayout calls are probably a red herring, so I m going to remove that altogether. The result, after a little rearrangement , looks like this:

 public XMLNotepad() { 
model = new TextModel();
Text = "XML Notepad";
textbox = new TestableTextBox();
textbox.Parent = this;
textbox.Dock = DockStyle.Fill;
textbox.BorderStyle = BorderStyle.None;
textbox.Multiline = true;
textbox.ScrollBars = ScrollBars.Both;
textbox.AcceptsTab = true;
textbox.KeyDown += new KeyEventHandler(XMLKeyDownHandler);
textbox.KeyPress += new KeyPressEventHandler(XMLKeyPressHandler);
this.textbox.Visible = true;
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.AddRange(new System.Windows.Forms.Control[]
{ this.textbox});
this.Name = "XMLNotepad";
}

This compiles, and the tests all run. I know that the GUI testing is still a little weak, though, so I m going to run the actual application...and it works fine.

Lesson  

I don t like this feeling of fear. When we run our tests, we should feel almost completely confident that the system is going to work correctly. Something will have to be done about this. Right now, however, we re working on the menu.




Extreme Programming Adventures in C#
Javaв„ў EE 5 Tutorial, The (3rd Edition)
ISBN: 735619492
EAN: 2147483647
Year: 2006
Pages: 291

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net