# 2.6 Adding File Menu Functionality

The next task is to interact with the user to implement the menu functionality. Dialogs are used to get immediate input from the user. Dialogs are application modal, i.e. you can not use any other windows in the current application until the dialogue is closed.

- Dialogs are placed directly into the source code. They are not placed into the Designer. They are placed with the editor. In the Frame1.py source code, go to the event handler for the open event. This method is called OnMenuFileOpenMenu. We are going to place the 'File Open' dialogue into this method. Place the keyboard cursor directly before 'event.Skip()'. We are going to insert our new code here.
- On the palette, select the 'Dialogs' pane. Select the 'wx.FileDialog' button. When you press on the wx.FileDialog button Boa Constructor will paste skeleton code directly into your Event Handler method.
- Note the code 'dlg.Destroy()', it is very important that dialogs get destroyed!
- The source code section should now look as follows:

def OnMenuFileOpenMenu(self, event): dlg = wx.FileDialog(self, "Choose a file", ".", "", "*.*", wx.OPEN) try: if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath() # Your code finally: dlg.Destroy() event.Skip()

- This skeleton code creates a dialog. It interacts with the user. When the dialog is finished it is destroyed.
- The words '# Your code' mark the position where we are to insert our own code. This code is triggered when the dialog returns 'wx.ID_OK, i.e. when the user clicked on the 'Open' button. We will insert our code here. The wx.TextCtrl has a method which we will use to load a file into the edit window, for this we use the method 'LoadFile'.
- You can delete the trailing 'event.Skip()' as no other event will need to be called in this case. The 'event.Skip()' name is a bit confusing, you should call 'event.Skip()' in events were other event handlers should ALSO be executed.

- It was needed when the code was generated because Python reports an error if there is a method with no body.

- As part of the functionality of our application we must be able to access the file name so that the 'Save' menu option can save to this file, therefore we added the line 'self.FileName=filename'.
- The 'self.SetTitle(('Notebook - %s') % filename)' line changes the title to show what file is being worked on.
- The listing below shows our new code.

def OnMenuFileOpenMenu(self, event): dlg = wx.FileDialog(self, "Choose a file", ".", "", "*.*", wx.OPEN) try: if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath() # Your code self.textEditor.LoadFile(filename) self.FileName=filename self.SetTitle(('Notebook - %s') % filename) finally: dlg.Destroy()

- We must repeat the exercise to provide the 'Save As' functionality. Insert a file dialog into the body of 'OnFileSaveasMenu'.
- This is a File Save dialog. Change the prompt, parameter 2 to the wx.FileDialog to "Save File As". Change the style, parameter 6 to wx.SAVE. The method to save the file is called SaveFile.
- Again, we save the filename value for use by the 'Save' menu option.
- The listing below shows the code.

def OnMenuFileSaveasMenu(self, event): dlg = wx.FileDialog(self, "Save file as", ".", "", "*.*", wx.SAVE) try: if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath() # Your code self.textEditor.SaveFile(filename) self.FileName=filename self.SetTitle(('Notebook - %s') % filename) finally: dlg.Destroy()

- Next we will implement the 'Close' menu option. In this method, we simply clear the textEditor control, the FileName member variable and reset the title..

def OnMenuFileCloseMenu(self, event): self.FileName = None self.textEditor.Clear() self.SetTitle('Notebook')

- Next we will implement the 'Exit' menu option. In this method we need to terminate the application. All wxPython applications are terminated by closing the toplevel window. In our case we only have the Frame1 window. To terminate the application we invoke the Close() method for Frame1.

def OnMenuFileExitMenu(self, event): self.Close()

- Next we will implement the 'Save' menu item. This menu item will save the file using the current name, which is stored in the variable self.FileName.
- When there is no current file, the self.FileName variable is set to None. In this case the 'Save' menu option must act as the 'Save As' menu option.
- The variable FileName must be created when Frame1 is constructed. We must add it to the constructor. You can add your application code to the end of the default constructor (__init__).

def __init__(self, parent): self._init_ctrls(parent) self.FileName=None

- Now, we are safe to implement the Save functionality. We check if there is a current filename. If there is we can save the contents to that filename. Otherwise, we just call the 'Save As' method.

def OnMenuFileSaveMenu(self, event): if self.FileName == None: return self.OnFileSaveasMenu(event) else: self.textEditor.SaveFile(self.FileName)

- We have now implemented the functionality of the editor. We can open files, edit, and save them.
- Your editor should look similar to what is shown on the image below.

- The file App1.py was opened
- Then the menu option 'File/Save as' was selected