Our next step will be to build a table of objects like the list I showed in the The Plan section and to build the menu from that. I expect this to be a bit tricky, because I foresee that we ll have to change the code for everyone who is now using that Tags enum:
public enum Tags {
Pre = 1,
Section = 2,
UnorderedList = 3,
ListItem = 4,
Paragraph = 5,
OrderedList = 6
}
We ll allow the compiler to tell us what to do, and we ll rely on the tests to get things working. First, let s build a little class. This class is so dull that it could even be a struct, but we ll use a class anyway:
class InsertAction {
private string menuString;
private string[] tagsToInsert;
private string[] tagsToSkip;
public InsertAction(string menu, string[] inserts, string[] skips) {
menuString = menu;
tagsToInsert = inserts;
tagsToSkip = skips;
}
public string MenuString {
get { return menuString; }
}
public string[] TagsToInsert {
get { return tagsToInsert; }
}
public string[] TagsToSkip {
get { return tagsToSkip; }
}
}
There s nothing special here; this is just a simple no-behavior structure class. For now, it s actually inside the TextModel.cs file, but we might move it out later. Now let s make a table of these objects in TextModel class:
private static InsertAction[] insertActions = new InsertAction[] {
new InsertAction("Insert &Pre",
new string[] { "<pre></pre>" },
new string[] { "<pre>" }),
new InsertAction("Insert &Section",
new string[] {"<sect1><title></title>","</sect1>" },
new string[] {"<sect1><title>" }),
new InsertAction("Insert &UL",
new string[] {"<UL>","<LI></LI>","</UL>"},
new string[] {"<UL>", "<LI>" }),
new InsertAction("Insert &OL",
new string[] {"<OL>","<LI></LI>","</OL>"},
new string[] {"<OL>", "<LI>" })
};
I m not sure why, but Microsoft Visual Studio can t seem to figure out how to format those lines. The code compiles just fine but formats all over to the right side, the way it does when it thinks there s something wrong. Anyway, that s the table. We ll add a property to get it:
public InsertAction[] InsertActions {
get { return insertActions; }
}
Now comes the tricky part. We want to use this table to create our menus . When we do that, some things are likely to break. Let s just go ahead and do it:
foreach (InsertAction action in model.InsertActions) {
insertMenus.Add(new NotepadMenuItem (
action.MenuString,
new EventHandler(MenuInsertTags),
action));
}
That s certainly what we want to say: just create a new menu item with the action s string and attach the action to the menu item. Our NotepadMenuItem constructor won t like that. It looks like this:
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; }
}
}
It needs to look like this:
class NotepadMenuItem : MenuItem {
private InsertAction action;
public NotepadMenuItem (String menuString, EventHandler handler,
InsertAction act)
:base(menuString, handler){
action = act;
}
public InsertAction Action {
get { return action; }
}
}
We change it that way and compile to see who complains. The compiler points here:
void MenuInsertTags(object obj, EventArgs ea) {
NotepadMenuItem item = (NotepadMenuItem) obj;
GetText();
model.InsertTags(item.Command);
PutText(textbox, model.LinesArray(), model.SelectionStart);
}
The NotepadMenuItem no longer understands Command. Here, we ll just pass the action back to the TextModel and require TextModel to deal with it. We start here:
public void InsertTags(Tags command) {
int cursorLine = LineContainingCursor();
lines.InsertRange(cursorLine+1, InsertStrings(command));
selectionStart = NewSelectionStart(cursorLine + 1, SkipStrings(command));
}
That needs to become this:
public void InsertTags( InsertAction action ) {
int cursorLine = LineContainingCursor();
lines.InsertRange(cursorLine+1, action.TagsToInsert );
selectionStart = NewSelectionStart(cursorLine + 1, action.TagsToSkip );
}
I m adding that method, not replacing it, because I know that some methods are calling the InsertTags() method that uses a Tags variable. This change makes the compiler messages go away. And the tests run!