The Code at This Point


XNLNotepad.cs

 using System; 
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using NUnit.Framework;
using System.Collections; using System.Text.RegularExpressions;
namespace Notepad {
class NotepadMenuItem : MenuItem {
private TextModel.Tags command;
public NotepadMenuItem (String menuString, EventHandler handler,
TextModel.Tags tag)
:base(menuString, handler){
command = tag;
}
public TextModel.Tags Command {
get { return command; }
}
}
class XMLNotepad : Form {
public TestableTextBox textbox;
private TextModel model;
private MenuItem insertPre;
private MenuItem insertSection;
private MenuItem insertUnorderedList;
private MenuItem insertOrderedList;
private MenuItem openFile;
private MenuItem saveFile;
private ModelAction enterAction;
private ModelAction shiftEnterAction;
private ModelAction saveAction;
private ModelAction loadAction;
private String fileName;
private Boolean displayDialog = true;
public delegate void ModelAction();
public MenuItem MenuForAccelerator(string accelerator) {
if (accelerator == "&S") return insertSection;
if (accelerator == "&P") return insertPre;
if (accelerator == "&U") return insertUnorderedList;
if (accelerator == "&O") return insertOrderedList;
if (accelerator == "^O") return openFile;
if (accelerator == "^S") return saveFile;
return null;
}
[STAThread]
static void Main(string[] args) {
Application.Run(new XMLNotepad());
}
public XMLNotepad() {
initialize(new TextModel());
}
public XMLNotepad(TextModel model) {
initialize(model);
} private void initialize(TextModel model) {
InitializeDelegates(model);
this.model = model;
this.Text = "XML Notepad";
MenuItem fileMenu = new MenuItem("&File");
MenuItem newFile = new MenuItem("&New");
newFile.Click += new EventHandler(MenuFileNewOnClick);
newFile.Shortcut = Shortcut.CtrlN;
fileMenu.MenuItems.Add(newFile);
openFile = new MenuItem("&Open...");
openFile.Click += new EventHandler(MenuFileOpenOnClick);
openFile.Shortcut = Shortcut.CtrlO;
fileMenu.MenuItems.Add(openFile);
saveFile = new MenuItem("&Save");
saveFile.Click += new EventHandler(MenuFileSaveOnClick);
saveFile.Shortcut = Shortcut.CtrlS;
fileMenu.MenuItems.Add(saveFile);
MenuItem saveAsFile = new MenuItem("Save &As...");
saveAsFile.Click += new EventHandler(MenuFileSaveAsOnClick);
fileMenu.MenuItems.Add(saveAsFile);
insertSection = new NotepadMenuItem (
"Insert &Section",
new EventHandler(MenuInsertTags),
TextModel.Tags.Section);
insertPre = new NotepadMenuItem (
"Insert &Pre",
new EventHandler(MenuInsertTags),
TextModel.Tags.Pre );
insertUnorderedList = new NotepadMenuItem (
"Insert &UL",
new EventHandler(MenuInsertTags),
TextModel.Tags.UnorderedList );
insertOrderedList = new NotepadMenuItem (
"Insert &OL",
new EventHandler(MenuInsertTags),
TextModel.Tags.OrderedList );
this.Menu = new MainMenu(new MenuItem[]
{fileMenu, insertPre, insertSection, insertUnorderedList,
insertOrderedList} );
this.textbox = new TestableTextBox();
this.textbox.Parent = this;
this.textbox.Dock = DockStyle.Fill;
this.textbox.BorderStyle = BorderStyle.None;
this.textbox.Multiline = true;
this.textbox.ScrollBars = ScrollBars.Both;
this.textbox.AcceptsTab = true;
this.textbox.KeyDown += new KeyEventHandler(XMLKeyDownHandler);
this.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";
}
private void InitializeDelegates(TextModel model) {
enterAction = new ModelAction(model.Enter);
shiftEnterAction = new ModelAction(model.InsertReturn);
saveAction = new ModelAction(this.SaveFile);
loadAction = new ModelAction(this.LoadFile);
}
void MenuInsertTags(object obj, EventArgs ea) {
NotepadMenuItem item = (NotepadMenuItem) obj;
GetText();
model.InsertTags(item.Command);
PutText(textbox, model.LinesArray(), model.SelectionStart);
}
void MenuFileNewOnClick(object obj, EventArgs ea) {
}
void MenuFileSaveOnClick(object obj, EventArgs ea) {
CallModel(saveAction);
}
void MenuFileOpenOnClick(object obj, EventArgs ea) {
FileOperation(new OpenFileDialog(), loadAction);
}
void MenuFileSaveAsOnClick(object obj, EventArgs ea) {
FileOperation(new SaveFileDialog(), saveAction);
}
private void FileOperation(FileDialog dialog, ModelAction action) {
if (displayDialog) {
DialogFileAction(dialog, action);
}
else {
CallModel(action);
}
displayDialog = true;
}
private void DialogFileAction(FileDialog dialog, ModelAction action) {
dialog.Filter = "xml files (*.xml)*.xmlAll files (*.*)*.*";
dialog.FilterIndex = 2 ;
dialog.RestoreDirectory = true ;
if(dialog.ShowDialog() == DialogResult.OK) {
fileName = dialog.FileName;
CallModel(action);
}
} void SaveFile() {
using ( StreamWriter writer = File.CreateText(fileName) ) {
model.Save(writer);
}
}
void LoadFile() {
using ( StreamReader reader = File.OpenText(fileName) ) {
model.Load(reader);
}
}
public void XMLKeyPressHandler(object objSender, KeyPressEventArgs kea) {
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.
}
}

private void CallModel(ModelAction modelAction) {
GetText();
modelAction();
PutText(textbox, model.LinesArray(), model.SelectionStart);
}
public void XMLKeyDownHandler(object objSender, KeyEventArgs kea) {
if (kea.KeyCode == Keys.Enter && kea.Modifiers == Keys.None) {
CallModel(enterAction);
kea.Handled = true;
}
else if (kea.KeyCode == Keys.Enter && kea.Modifiers == Keys.Shift) {
CallModel(shiftEnterAction);
kea.Handled = true;
}
}
internal void PutText(ITestTextBox textbox, string[] lines,
int selectionStart) {
// this is Feature Envy big time.
textbox.Lines = lines;
textbox.SelectionStart = selectionStart;
textbox.ScrollToCaret();
}
private void GetText() {
model.SetLines(textbox.Lines);
model.SelectionStart = textbox.SelectionStart;
}
internal void CustomerTestPutText() {
PutText(textbox, model.LinesArray(), model.SelectionStart);
}
internal void SetFileName(String name) {
fileName = name;
}
internal void SetNoFileDialog() {
displayDialog = false;
}
}
}

TextModel.cs

 using System; 
using System.IO;
using System.Collections;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
namespace Notepad {
class TextModel {
private ArrayList lines;
private int selectionStart;
private static string[] newParagraph = { "<P></P>" };
private static string[] paragraphSkip = { "<P>" };
private static string[] newListItem = { "<LI></LI>" };
private static string[] listItemSkip = { "<LI>" };
private static string[] emptyLine = { "" };
private static string[] emptyLineSkip = { "" };
private static string[] newSection = {"<sect1><title></title>",
"</sect1>" };
private static string[] sectionSkip = { "<sect1><title>" };
private static string[] newUnorderedList = {"<UL>","<LI></LI>","</UL>"};
private static string[] unorderedListSkip = { "<UL>", "<LI>" };
private static string[] newOrderedList = {"<OL>","<LI></LI>","</OL>"};
private static string[] orderedListSkip = { "<OL>", "<LI>" };
private static string[] newPre = { "<pre></pre>" };
private static string[] preSkip = { "<pre>" };
public enum Tags {
Pre = 1,
Section = 2,
UnorderedList = 3,
ListItem = 4,
Paragraph = 5,
OrderedList = 6
}
private static string[] InsertStrings(Tags tag) {
if (tag == Tags.Pre) return newPre;
else if (tag == Tags.Section) return newSection;
else if (tag == Tags.UnorderedList) return newUnorderedList;
else if (tag == Tags.OrderedList) return newOrderedList;
else if (tag == Tags.ListItem) return newListItem;
else return newParagraph;
}
private static string[] SkipStrings(Tags tag) {
if (tag == Tags.Pre) return preSkip; else if (tag == Tags.Section) return sectionSkip;
else if (tag == Tags.UnorderedList) return unorderedListSkip;
else if (tag == Tags.OrderedList) return orderedListSkip;
else if (tag == Tags.ListItem) return listItemSkip;
else return paragraphSkip;
}
public TextModel() {
lines = new ArrayList();
}
public ArrayList Lines {
get {
return lines;
}
set {
lines = value;
}
}
public void SetLines(String[] lines) {
this.Lines = new ArrayList(lines);
}
public String[] LinesArray() {
return (string[])lines.ToArray(typeof(string));
}
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() {
if (InListItem())
InsertTags(Tags.ListItem);
else
InsertTags(Tags.Paragraph);
}
private Boolean InListItem() {
if (LineContainingCursor() < 0 ) return false;
return ((string) lines[LineContainingCursor()]).StartsWith("<LI>");
}
public void InsertReturn() {
string front = FrontOfCursorLine();
string back = BackOfCursorLine();
lines[LineContainingCursor()] = front;
lines.Insert(LineContainingCursor()+1, back);
selectionStart += Environment.NewLine.Length;
}
public string FrontOfCursorLine() {
string line = (string) lines[LineContainingCursor()];
int position = PositionOfCursorInLine();
return line.Substring(0, position);
}
public string BackOfCursorLine() {
string line = (string) lines[LineContainingCursor()];
int position = PositionOfCursorInLine();
return line.Substring(position);
}
public int PositionOfCursorInLine() {
return selectionStart - FirstPositionOfLine(LineContainingCursor());
}
public void InsertTags(Tags command) {
int cursorLine = LineContainingCursor();
lines.InsertRange(cursorLine+1, InsertStrings(command));
selectionStart = NewSelectionStart(cursorLine + 1, SkipStrings(command));
}
private int NewSelectionStart(int cursorLine, string[] tags) {
return FirstPositionOfLine(cursorLine) + TotalTagLength(tags);
}
private int TotalTagLength(string[] tags) {
int result = (tags.Length -1) * Environment.NewLine.Length;
foreach (string tag in tags) {
result += tag.Length;
}
return result;
}
private int FirstPositionOfLine(int cursorLine) {
int length = 0;
for (int i = 0; i < cursorLine; i++)
length += ((String)lines[i]).Length + Environment.NewLine.Length;
return length;
} public void ChangeToH2() {
ArrayList linesList = Lines;
String oldLine = (String) linesList[LineContainingCursor()];
Regex r = new Regex("<(?<prefix>.*)>(?<body>.*)</(?<suffix>.*)>");
Match m = r.Match(oldLine);
String newLine = "<H2>" + m.Groups["body"] + "</H2>";
linesList[LineContainingCursor()] = newLine;
Lines = linesList;
}
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 void Save(TextWriter w) {
foreach (string line in lines )
w.WriteLine(line);
}
public void Load(TextReader r) {
String line;
lines = new ArrayList();
while((line = r.ReadLine()) != null) {
lines.Add(line);
}
}
}
}

TestTextModel.cs

 using System; 
using System.IO;
using System.Collections;
using NUnit.Framework;
namespace Notepad { [TestFixture] public class TestTextModel : Assertion {
private TextModel model;
[SetUp] public void CreateModel() {
model = new TextModel();
}
[Test] public void TestNoLines() {
ClearModel();
VerifyClear();
}
private void VerifyClear() {
AssertEquals(0, model.Lines.Count);
}
private void ClearModel() {
model.SetLines(new String[0]);
}
[Test] public void TestNoProcessing() {
GiveModelContents();
VerifyContents();
}
private void VerifyContents() {
AssertEquals(3, model.Lines.Count);
AssertEquals("hi", model.Lines[0]);
AssertEquals("there", model.Lines[1]);
AssertEquals("chet", model.Lines[2]);
}
private void GiveModelContents() {
model.SetLines(new String[3] { "hi", "there", "chet"});
}
[Test] public void TestOneEnter() {
model.SetLines(new String[1] {"hello world" });
model.SelectionStart = 5;
model.InsertTags(TextModel.Tags.Paragraph);
AssertEquals(2, model.Lines.Count);
AssertEquals(16, model.SelectionStart);
}
[Test] public void TestEmptyText() {
model.Lines = new ArrayList(new String[0]);
model.InsertTags(TextModel.Tags.Paragraph);
AssertEquals(1, model.Lines.Count);
AssertEquals(3, model.SelectionStart);
}
[Test] public void InsertWithCursorAtLineStart () {
model.Lines = new ArrayList(new String[3] { "<P>one</P>", "",
"<P>two</P>"});
model.SelectionStart = 14;
model.InsertTags(TextModel.Tags.Paragraph);
AssertEquals("<P>two</P>", model.Lines[2]);
} [Test] public void TestLineContainingCursorDirectly() {
// todo?
}
[Test] public void ControlTwo() {
model.SetLines(new String[1] {"<P>The Heading</P>" });
model.ChangeToH2();
AssertEquals("<H2>The Heading</H2>", model.Lines[0]);
}
[Test] public void AltS() {
model.Lines = new ArrayList(new String[0]);
model.InsertTags(TextModel.Tags.Section);
AssertEquals("<sect1><title></title>", model.Lines[0]);
AssertEquals("</sect1>", model.Lines[1]);
AssertEquals(14, model.SelectionStart);
}
[Test] public void AltSWithText() {
model.SetLines (new String[1] {"<P></P>"});
model.SelectionStart = 7;
model.InsertTags(TextModel.Tags.Section);
AssertEquals("<sect1><title></title>", model.Lines[1]);
AssertEquals("</sect1>", model.Lines[2]);
AssertEquals(23, model.SelectionStart);
}
[Test] public void UnorderedList() {
model.SetLines (new String[1] {"<P></P>"});
model.SelectionStart = 3;
model.InsertTags(TextModel.Tags.UnorderedList);
AssertEquals("<UL>", model.Lines[1]);
AssertEquals("<LI></LI>", model.Lines[2]);
AssertEquals("</UL>", model.Lines[3]);
AssertEquals(19, model.SelectionStart);
model.Enter();
AssertEquals("<LI></LI>", model.Lines[3]);
}
[Test] public void InsertPre() {
model.SetLines (new String[1] {"<P></P>"}); model.SelectionStart = 7;
model.InsertTags(TextModel.Tags.Pre);
AssertEquals("<pre></pre>", model.Lines[1]);
AssertEquals(14, model.SelectionStart);
model.InsertReturn();
AssertEquals("<pre>", model.Lines[1]);
AssertEquals("</pre>", model.Lines[2]);
AssertEquals(16, model.SelectionStart);
}
[Test] public void ShiftEnter() {
model.SetLines (new String[1] {"<pre></pre>"});
model.SelectionStart = 5;
model.InsertReturn();
AssertEquals("<pre>", model.Lines[0]);
AssertEquals("</pre>", model.Lines[1]);
AssertEquals(7, model.SelectionStart);
}
[Test]
[Ignore("New Para in mid-Pre Bug")]
public void ShiftEnterMultipleLines() {
model.SetLines (new String[] {"<pre>code1", "code2","code3</pre>"});
model.SelectionStart = 14; // after 'co' in 'code2'
model.InsertTags(TextModel.Tags.Paragraph);
AssertEquals("code3</pre>", model.Lines[2]);
AssertEquals("<P></P>", model.Lines[3]);
}
[Test] public void CursorPosition() {
model.SetLines (new String[] { "<P></P>", "<pre></pre>" });
model.SelectionStart = 14; // after <pre>
AssertEquals(5, model.PositionOfCursorInLine());
AssertEquals("<pre>", model.FrontOfCursorLine());
AssertEquals("</pre>", model.BackOfCursorLine());
}
[Test] public void WriteStream() {
model.SetLines (new String[] { "<P></P>"});
StringWriter w = new StringWriter();
model.Save(w);
AssertEquals("<P></P>\r\n", w.ToString());
}
[Test] public void WriteAndReadFile() {
ClearModel();
VerifyClear();
GiveModelContents();
VerifyContents();
SaveModelToFile();
ClearModel();
VerifyClear();
LoadModelFromFile();
VerifyContents();
}
public void SaveModelToFile() {
using (StreamWriter writer = File.CreateText("savedmodel.xml")) {
model.Save(writer);
}
}
public void LoadModelFromFile() {
using (StreamReader reader = File.OpenText("savedmodel.xml")) {
model.Load(reader);
}
}
}
}

CustomerTests.cs

 using System; 
using System.IO;
using System.Windows.Forms;
using System.Collections;
using NUnit.Framework;
namespace Notepad
{
[TestFixture] public class CustomerTest : Assertion {
private TextModel model;
private XMLNotepad form;
[SetUp] public void CreateModel() {
model = new TextModel();
form = new XMLNotepad(model);
}
[Test] public void EmptyModel() {
form.XMLKeyDownHandler((object) this, new KeyEventArgs(Keys.Enter));
AssertEquals("<P></P>\r\n", model.TestText);
}
[Test] public void DirectMenu() {
form.MenuForAccelerator("&P").PerformClick();
AssertEquals("<pre></pre>\r\n", model.TestText);
}

[Test] public void StringInput() {
String commands =
@"*input
some line
*end
*enter
*output
some line
<P></P>";
InterpretCommands(commands, "");
}
[Test] public void FileInput() {
InterpretFileInput(@"c:\data\csharp\notepad\fileInput.test");
}
[Test] public void TestAllFiles() {
String[] testFiles = Directory.GetFiles(@"c:\data\csharp\notepad\",
"*.test");
foreach (String testFilename in testFiles) {
InterpretFileInput(testFilename);
}
}
private void InterpretFileInput(String fileName) {
StreamReader stream = File.OpenText(fileName);
String contents = stream.ReadToEnd();
stream.Close();
InterpretCommands(contents, fileName);
} private void InterpretCommands(String commands, String message) {
StringReader reader = new StringReader(commands);
String line = reader.ReadLine();
CreateModel();
while ( line != null) {
if (line.StartsWith("*alt"))
ExecuteMenu("&"+line[4]);
else if ( line == "*enter")
form.XMLKeyDownHandler((object) this, new KeyEventArgs(Keys.Enter));
else if ( line == "*shiftEnter")
form.XMLKeyDownHandler((object) this,
new KeyEventArgs(Keys.Enter Keys.Shift));
else if (line == "*display")
Console.WriteLine("display\r\n{0}\r\nend", model.TestText);
else if (line == "*output")
CompareOutput(reader, message);
else if (line == "*input")
SetInput(reader);
else if (line == "*loadfile")
LoadFile();
else if (line == "*savefile")
SaveFile();
else
Assert(line + " command not defined", false);
line = reader.ReadLine();
}
}
private void SaveFile() {
form.SetFileName("customertestxmlfile.xml");
form.SetNoFileDialog();
ExecuteMenu("^S");
}
private void LoadFile() {
form.SetFileName("customertestxmlfile.xml");
form.SetNoFileDialog();
ExecuteMenu("^O");
}
private void CompareOutput(StringReader reader, String message) {
String expected = ExpectedOutput(reader);
String result = model.TestText; if (expected != result) {
Console.WriteLine(message);
Console.WriteLine("*Expected");
Console.WriteLine(expected);
Console.WriteLine("*Result");
Console.WriteLine(result);
}
AssertEquals(message, expected, model.TestText);
}
private String ExpectedOutput(StringReader reader) {
return ReadToEnd(reader);
}
private String ReadToEnd(StringReader reader) {
String result = "";
String line = reader.ReadLine();
while (line != null && line != "*end") {
result += line;
result += System.Environment.NewLine;
line = reader.ReadLine();
}
return result;
}
private void SetInput(StringReader reader) {
InputCommand input = new InputCommand(reader);
model.Lines = input.CleanLines();
model.SelectionStart = input.SelectionStart();
form.CustomerTestPutText();
}
private void ExecuteMenu(string accelerator) {
MenuItem mi = form.MenuForAccelerator(accelerator);
mi.PerformClick();
}
}
}



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

Similar book on Amazon

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