Adding CtrlS - Almost


Adding Ctrl+S ”Almost

We added Ctrl+S code to the GUI, just to see it work, and to cement in our minds that we needed to do it. It looks like this:

 void XMLKeyDownHandler(object objSender, KeyEventArgs kea) { 
model.SetLines(textbox.Lines);
model.SelectionStart = textbox.SelectionStart;
if (kea.KeyCode == Keys.Enter) {
model.Enter();
kea.Handled = true;
}
if (kea.KeyCode == Keys.S && kea.Alt) {
model.AltS();
kea.Handled = true;
} PutText(textbox, model.LinesArray(), model.SelectionStart);
}

Note that it says AltS, not ControlS. Chet noticed that Ctrl+S is usually used for Save, and he suggested that we didn t want to overload that meaning. So we switched to AltS throughout. Here s the code in TextModel:

 public void AltS() { 
InsertSectionTags();
}
public void InsertSectionTags() {
if ( lines.Count == 0 ) {
lines.Add( "<sect1><title></title>" );
lines.Add( "</sect1>");
selectionStart = 14;
return;
}
}

With this implementation, the notepad correctly displays the section at the beginning of the window, which is the only place it s implemented. However, the notepad is ringing the bell on every Alt+S. We re not sure what s causing that. We made a note of it and are moving on.

Test for More of Alt+S

The current implementation of Alt+S works only when the text buffer is empty. We ll write a Programmer Unit Test to handle the other case:

 [Test] public void AltSWithText() { 
model.SetLines (new String[1] {"<P></P>"});
model.SelectionStart = 7;
model.AltS();
AssertEquals("<sect1><title></title>", model.Lines[1]);
AssertEquals("</sect1>", model.Lines[2]);
AssertEquals(23, model.SelectionStart);
}

Only at this point did I remember a simplifying assumption I d been making. In this first implementation, I m assuming that the user will position the cursor at the end of the current sect1 before asking for another one. I m doing that because the sect1 tag is multiple lines long and I don t want to worry about finding the end of the current one as part of what I m doing now. Let me comment on that a bit more.

Lesson  

I find that working in tiny little bites makes things go better. By the end of this subject ”perhaps in this chapter, perhaps in the next ”I think you ll agree that we re in a good place in both features and code. It would be possible to include the setting to the end of the sect1 tag as part of this phase of the implementation, but then I d have to solve two problems: getting the stuff inserted and the cursor set, and also finding where to insert. I want to solve one problem at a time, and I want to see the program do something useful, so my next step is insert the section tag at the current location so that it will work right if the users sets the location first.

The test above therefore takes the smaller step, assuming that the user sets the location for us. Easy does it. It adds a P tag, just to have something there, and then sets the cursor to the end of it. Then it calls for an Alt+S and checks to see if the lines are right and the cursor is set right. Note the 23 as cursor position. That s the 7 characters of the first line plus the CrLf, plus 14 characters into the second line (Lines[1]). I actually got that wrong the first time I wrote the test, and used 21, forgetting the CrLf. Except for this little comment, I ll save you that detail.

Implementing More of Alt+S

Here s how the code for the P tag looks:

 public void InsertParagraphTag() { 
//
// On Enter, we change the TextModel lines to insert, after the line
// containing the cursor, a blank line, and a line with <P></P>.
// We set the new cursor
// location to be between the P tags: <P></P>.
//
// handle empty array special case (yucch)
if ( lines.Count == 0 ) {
lines.Add( "<P></P>" );
selectionStart = 3;
return; }
lines.InsertRange(LineContainingCursor()+1, NewParagraph());
selectionStart = NewParaSelectionStart(LineContainingCursor() + 2);
}
private int NewParaSelectionStart(int cursorLine) {
int length = 0;
for (int i = 0; i < cursorLine; i++)
length += ((String)lines[i]).Length + Environment.NewLine.Length;
return length + "<p>".Length;
}
public ArrayList NewParagraph() {
ArrayList temp = new ArrayList();
temp.Add("");
temp.Add("<P></P>");
return temp;
}

Note those comments, especially the yucch. We hate that special case for lines.Count == 0, and in a minute we re going to hate it more. Watch what happens. For now, look at what happens in the non-zero case, which is what we need to implement for the section tag. If there are lines, we insert the lines in NewParagraph() ”namely a blank line and a P-tag line ”into the TextModel lines, right after the line containing the cursor. Then we set the selectionStart.

The NewParaSelectionStart code is almost straightforward. It adds up the length of all the lines up to the line that should contain the cursor (including the CrLfs), and then it adds in the width of the <P> tag. That will position the cursor right after that tag. You might think that lacks generality. So do we, and we re going to go after it. But we re going to go after it in a special way, so hold on and see what happens.

We implement the Alt+S feature in almost exactly the same way. Here s the code for Alt+S:

 public void AltS() { 
InsertSectionTags();
}
public void InsertSectionTags() {
if ( lines.Count == 0 ) {
lines.Add( "<sect1><title></title>" );
lines.Add( "</sect1>");
selectionStart = 14;
return;
}
lines.InsertRange(LineContainingCursor()+1, NewSection()); selectionStart = NewSectionSelectionStart(LineContainingCursor() + 1);
}
public ArrayList NewSection() {
ArrayList temp = new ArrayList();
temp.Add("<sect1><title></title>");
temp.Add("</sect1>");
return temp;
}
private int NewSectionSelectionStart(int cursorLine) {
int length = 0;
for (int i = 0; i < cursorLine; i++)
length += ((String)lines[i]).Length + Environment.NewLine.Length;
return length + "<sect1><title>".Length;
}

See that we basically cut and pasted the code for the P tag here and modified it with the new strings we wanted to use for the section tag. Isn t cut and paste bad? Yes, but only if we leave the code that way. We re not going to do that, as you ll see in a moment.

It s time to compile and test. And the tests all run! OK, now let s see about this ugly code.




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