Now the Menus


Now the Menus

It seems like the basic save and load capability is there now, although I foresee a need to make one change. Right now, the save and load work on an open file. I m not sure, but it seems to me that we might want to pass the file name to the TextModel and open the file there. We ll see what the code tells us, as we put the menus in.

Over a quick lunch , I read the menu section in Petzold s Programming Microsoft Windows with C# (Microsoft Press, 2001), and my plan is to lift his code almost directly.

Lesson  

Is this cheating? Well, in a poorly designed ninth grade C# programming class, it might be cheating. In the world of professional software development, it s called learning, research, and reuse. I m quite serious. There s plenty of new material to figure out in every application we re called upon to write. Where we can find code to borrow , we re wise to do so.

However, there are good ways to borrow and ways that are not so good. We shouldn t allow multiple copies of the same code, or almost the same code, to exist in our own code base. So if I m going to borrow Petzold s code, I should be sure that I put it in only one place. If I were to need it multiple times, I should turn it into an object or a method and use it multiple times rather than copy it.

In addition, when we copy and paste code, we don t understand it as well as if we type it in ourselves . Also, we understand code that we type in from another source less well than we understand code that we write based on a model or otherwise make our own. As with all things, it s a matter of judgment. Here I chose to follow Petzold s lead, and I gave him the credit so that you ll know where the idea and code came from.

A more serious challenge is the Customer Acceptance Test for this feature. Having made such a big deal about it earlier on, I am honor-bound to write some customer tests. However, I m not honor -bound to do it first, and in fact my plan is to implement the feature and then test it. We ll see if this gets me in trouble. I m fairly confident that we ll have no trouble. Here is our menu- related code now, from the XMLNotepad class:

 class XMLNotepad : Form { 
public TestableTextBox textbox;
private TextModel model;
private MenuItem insertPre;
private MenuItem insertSection;
...
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";
insertSection = new MenuItem (
"Insert & Section",
new EventHandler(MenuInsertSection));
insertPre = new MenuItem (
"Insert & Pre",
new EventHandler(MenuInsertPre));
this.Menu = new MainMenu(new MenuItem[] {insertPre, insertSection} );
this.textbox = new TestableTextBox();
...

Here, based on Petzold s example but organized to fit into our program, is our first cut at the menuing code. As soon as we get one item typed in, let s compile to check for errors. Here s what we start with:

 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);
insertSection = new MenuItem (
"Insert &Section", new EventHandler(MenuInsertSection));
insertPre = new MenuItem (
"Insert &Pre",
new EventHandler(MenuInsertPre));
this.Menu = new MainMenu(new MenuItem[] { fileMenu, insertPre,
insertSection} );
this.textbox = new TestableTextBox();

This compiles, except for the missing MenuFileNewOnClick event handler. I ll add that and test the code manually:

 void MenuFileNewOnClick(object obj, EventArgs ea) { 
}

This compiles, and when we run it, we get our familiar notepad with the new menu just as expected. Of course, it doesn t do anything, but we didn t expect it to. Let s add some more menu items and then hook them up.

 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);
MenuItem openFile = new MenuItem(" & Open...");
openFile.Click += new EventHandler(MenuFileOpenOnClick);
openFile.Shortcut = Shortcut.CtrlO; fileMenu.MenuItems.Add(openFile);
MenuItem 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 MenuItem (
"Insert &Section",
new EventHandler(MenuInsertSection));
insertPre = new MenuItem (
"Insert &Pre",
new EventHandler(MenuInsertPre));
this.Menu = new MainMenu(new MenuItem[] {fileMenu, insertPre,
insertSection} );
...
void MenuFileNewOnClick(object obj, EventArgs ea) {
}
void MenuFileOpenOnClick(object obj, EventArgs ea) {
}
void MenuFileSaveOnClick(object obj, EventArgs ea) {
}
void MenuFileSaveAsOnClick(object obj, EventArgs ea) {
}

This compiles, runs, and gives a File menu that looks right and does nothing. Things are going well so far. Let s try to make it work. We need a little think time first. The program needs to remember the name of the file that it has open, and the Save command should save on that file without comment if the name is known. The Open command should set that name, as should the Save As. If the name is not known, Save should do a Save As. In Save As, we should probably handle a file name that already exists, with a confirmation that we want to write over it. New should clear the name. The customer might ask us to put the file name in the top bar of the window, but unless it s really easy we ll leave that out, because we try always to let the customer decide how to spend our time.

I m thinking we ll have a member variable fileName to hold the string file name. Load will set it, as will Save As, which will then call Save. Save will just use the file name. New will clear it. And, of course, all these functions will also have to do things to the TextBox and the model. I think I ll start with Save As, because that way I ll have a file to Open. Any one of them would be as good as any other, so I just decided to do Save As even though that will force me to write Save as well. That should be OK. Here goes. I ll start by copying the file dialog code from that earlier test:

 void MenuFileSaveAsOnClick(object obj, EventArgs ea) { 
SaveFileDialog dialog = new SaveFileDialog();
dialog.Filter = "xml files (*.xml)*.xmlAll files (*.*)*.*";
dialog.FilterIndex = 2 ;
dialog.RestoreDirectory = true ;
if(dialog.ShowDialog() == DialogResult.OK) {
fileName = dialog.FileName;
SaveFile();
}
else {
MessageBox.Show("File not saved", "XML Notepad");
}
}
void SaveFile() {
MessageBox.Show("File saved " + fileName, "XML Notepad");
}

This is enough to get the dialog open and enter the file name. The MessageBox in SaveFile() comes up with the correct file name, with the full path , all ready to go. Now I ll enhance SaveFile to open the file and save on it:

 void SaveFile() { 
using ( StreamWriter writer = File.CreateText(fileName) ) {
model.Save(writer);
}
}

To test this manually, I typed these three lines into the XML Notepad:

 <P>one</P> 
<P>two</P>
<P>three</P>

I saved it to a file and then looked at the file. The result was this:

 <P>one</P> 
<P>two</P>
<P></P>

Not good. Clearly what has happened is that the TextModel wasn t updated at the time of the save. This gives us two problems. Naturally, we have to make it work, although we would have expected it to work already, like the other menu items do. There must be something different about how we ve set up these items. The more important problem is this: the program has a defect in it when we weren t expecting one. Our process requires me first to write a test to demonstrate that this defect exists and then to fix the defect. I do hate when that happens, but it s good discipline and I know that if I don t do it, you ll all write me nasty e- mails . Let s look around and see what to do.




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