Let s continue to clean up the TextModel. How good can this get? When I opened the file, here s what the window happened to open on for me:
public void InsertSectionTags() {
int cursorLine = LineContainingCursor();
lines.InsertRange(cursorLine+1, NewSection());
selectionStart = NewSelectionStart(cursorLine + 1, "<sect1><title>");
}
public ArrayList NewSection() {
ArrayList temp = new ArrayList();
temp.Add("<sect1><title></title>");
temp.Add("</sect1>");
return temp;
}
That NewSection code is pretty ugly. It s left over from a time earlier in our learning of C#, when we didn t understand arrays and ArrayList very well. I think we can get that down to a data declaration, but let s do it step by step to be sure that we understand how things work. We ll cement our understanding of arrays and ArrayList a bit as well. First, let s create the ArrayList in one step by using a literal string array:
public ArrayList NewSection() {
return new ArrayList(
new String[] {" < sect1 >< title >< /title > "," < /sect1 > " });
}
That works. Now, why do we need an ArrayList? It looks like InsertRange will take any collection, so let s just return an array of strings:
public string[] NewSection() {
return new String[] {" < sect1 >< title >< /title > "," < /sect1 > " };
}
That works just fine also. If that s the case, we should be able to just create that string array as a constant member in the class. We ll make it static, so there will be only one array created. And we ll rename it newSection, because fields are typically lowercase in C#:
public void InsertSectionTags() {
int cursorLine = LineContainingCursor();
lines.InsertRange(cursorLine+1, newSection );
selectionStart = NewSelectionStart(cursorLine + 1, "<sect1><title>");
}
private static string[] newSection =
{" < sect1 >< title >< /title > "," < /sect1 > " };
That works just fine as well. Now we re noticing that the string passed in to the NewSelectionStart looks a lot like the first element of our input array ”but we don t see what would be good to do about it yet. At least I don t. Instead, I m going to make the same change to the InsertParagraphTag method, from
public void InsertParagraphTag() {
int cursorLine = LineContainingCursor();
lines.InsertRange(cursorLine+1, NewParagraph());
selectionStart = NewSelectionStart(cursorLine + 1, "<P>");
}
public ArrayList NewParagraph() {
ArrayList temp = new ArrayList();
temp.Add("<P></P>");
return temp;
}
to this:
public void InsertParagraphTag() {
int cursorLine = LineContainingCursor();
lines.InsertRange(cursorLine+1, newParagraph );
selectionStart = NewSelectionStart(cursorLine + 1, "<P>");
}
private static string[] newParagraph = { " < P >< /P > " };
That works just fine as well. Let s see what still needs improving. The class now looks like this:
using System;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
namespace Notepad {
class TextModel {
private static string[] newParagraph = { "<P></P>" };
private static string[] newSection =
{"<sect1><title></title>","</sect1>" };
private ArrayList lines;
private int selectionStart;
public TextModel() {
lines = new ArrayList();
}
private int LineContainingCursor() {
if (lines.Count == 0)
return -1;
int length = 0;
int lineNr = 0;
int cr = Environment.NewLine.Length;
foreach ( String s in lines) {
if (length < = selectionStart
&& selectionStart < length+s.Length + cr )
break;
length += s.Length + cr;
lineNr++;
}
return lineNr;
}
public ArrayList Lines {
get {
return lines;
}
set {
lines = value;
}
}
public void SetLines(String[] lines) {
this.Lines = new ArrayList(lines);
}
public String[] LinesArray() {
String[] result = new String[lines.Count];
lines.CopyTo(result);
return result; }
public String TestText {
get {
StringBuilder b = new StringBuilder();
foreach(String s in lines) {
b.Append(s);
b.Append(System.Environment.NewLine);
}
b.Insert(SelectionStart,"");
return b.ToString();
}
}
public int SelectionStart {
get {
return selectionStart;
}
set {
selectionStart = value;
}
}
public void Enter() {
InsertParagraphTag();
}
public void InsertParagraphTag() {
int cursorLine = LineContainingCursor();
lines.InsertRange(cursorLine+1, newParagraph);
selectionStart = NewSelectionStart(cursorLine + 1, " < P > ");
}
public void AltS() {
InsertSectionTags();
}
public void InsertSectionTags() {
int cursorLine = LineContainingCursor();
lines.InsertRange(cursorLine+1, newSection);
selectionStart = NewSelectionStart(cursorLine + 1, " < sect1 >< title > ");
}
private int NewSelectionStart(int cursorLine, string tags) {
return SumLineLengths(cursorLine) + tags.Length;
}
private int SumLineLengths(int cursorLine) {
int length = 0;
for (int i = 0; i < cursorLine; i++)
length += ((String)lines[i]).Length + Environment.NewLine.Length;
return length;
}
}
}