def _setup_file_tree(self):
        self.file_tree_frame = Frame(self.content)
        self.file_tree_frame.grid(column=0, row=0, sticky=(N, S, E, W))

        self.file_tree = FileView(self.file_tree_frame, normalizer=self.filename_normalizer)
        self.file_tree.grid(column=0, row=0, sticky=(N, S, E, W))

        # # The tree's vertical scrollbar
        self.file_tree_scrollbar = Scrollbar(self.file_tree_frame, orient=VERTICAL)
        self.file_tree_scrollbar.grid(column=1, row=0, sticky=(N, S))

        # # Tie the scrollbar to the text views, and the text views
        # # to each other.
        self.file_tree.config(yscrollcommand=self.file_tree_scrollbar.set)
        self.file_tree_scrollbar.config(command=self.file_tree.yview)

        # Setup weights for the "file_tree" tree
        self.file_tree_frame.columnconfigure(0, weight=1)
        self.file_tree_frame.columnconfigure(1, weight=0)
        self.file_tree_frame.rowconfigure(0, weight=1)

        # Handlers for GUI events
        self.file_tree.bind('<<TreeviewSelect>>', self.on_file_selected)

        self.content.add(self.file_tree_frame)
class MainWindow(object):
    def __init__(self, root, options):
        '''
        -----------------------------------------------------
        | main button toolbar                               |
        -----------------------------------------------------
        |       < ma | in content area >                    |
        |            |                                      |
        | File list  | File name                            |
        |            |                                      |
        -----------------------------------------------------
        |     status bar area                               |
        -----------------------------------------------------

        '''

        # Obtain and expand the current working directory.
        base_path = os.path.abspath(os.getcwd())
        base_path = os.path.normcase(base_path) + '/'

        # Create a filename normalizer based on the CWD.
        self.filename_normalizer = filename_normalizer(base_path)

        # Root window
        self.root = root
        self.root.title('{{ cookiecutter.formal_name }}')
        self.root.geometry('1024x768')

        # Prevent the menus from having the empty tearoff entry
        self.root.option_add('*tearOff', FALSE)
        # Catch the close button
        self.root.protocol("WM_DELETE_WINDOW", self.cmd_quit)
        # Catch the "quit" event.
        self.root.createcommand('exit', self.cmd_quit)

        # Setup the menu
        self._setup_menubar()

        # Set up the main content for the window.
        self._setup_button_toolbar()
        self._setup_main_content()
        self._setup_status_bar()

        # Now configure the weights for the root frame
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=0)
        self.root.rowconfigure(1, weight=1)
        self.root.rowconfigure(2, weight=0)

    ######################################################
    # Internal GUI layout methods.
    ######################################################

    def _setup_menubar(self):
        # Menubar
        self.menubar = Menu(self.root)

        # self.menu_Apple = Menu(self.menubar, name='Apple')
        # self.menubar.add_cascade(menu=self.menu_Apple)

        self.menu_file = Menu(self.menubar)
        self.menubar.add_cascade(menu=self.menu_file, label='File')

        self.menu_help = Menu(self.menubar)
        self.menubar.add_cascade(menu=self.menu_help, label='Help')

        # self.menu_Apple.add_command(label='Test', command=self.cmd_dummy)

        # self.menu_file.add_command(label='New', command=self.cmd_dummy, accelerator="Command-N")
        # self.menu_file.add_command(label='Close', command=self.cmd_dummy)

        self.menu_help.add_command(label='Open Documentation', command=self.cmd_{{ cookiecutter.repo_name }}_docs)
        self.menu_help.add_command(label='Open {{ cookiecutter.formal_name }} project page', command=self.cmd_{{ cookiecutter.repo_name }}_page)
        self.menu_help.add_command(label='Open {{ cookiecutter.formal_name }} on GitHub', command=self.cmd_{{ cookiecutter.repo_name }}_github)
        self.menu_help.add_command(label='Open BeeWare project page', command=self.cmd_beeware_page)

        # last step - configure the menubar
        self.root['menu'] = self.menubar

    def _setup_button_toolbar(self):
        '''
        The button toolbar runs as a horizontal area at the top of the GUI.
        It is a persistent GUI component
        '''

        # Main toolbar
        self.toolbar = Frame(self.root)
        self.toolbar.grid(column=0, row=0, sticky=(W, E))

        # Buttons on the toolbar
        self.run_button = Button(self.toolbar, text='Run', command=self.cmd_run)
        self.run_button.grid(column=0, row=0)

        self.toolbar.columnconfigure(0, weight=0)
        self.toolbar.rowconfigure(0, weight=0)

    def _setup_main_content(self):
        '''
        Sets up the main content area. It is a persistent GUI component
        '''

        # Main content area
        self.content = PanedWindow(self.root, orient=HORIZONTAL)
        self.content.grid(column=0, row=1, sticky=(N, S, E, W))

        # Create subregions of the content
        self._setup_file_tree()
        self._setup_code_area()

        # Set up weights for the left frame's content
        self.content.columnconfigure(0, weight=1)
        self.content.rowconfigure(0, weight=1)

        self.content.pane(0, weight=1)
        self.content.pane(1, weight=2)

    def _setup_file_tree(self):
        self.file_tree_frame = Frame(self.content)
        self.file_tree_frame.grid(column=0, row=0, sticky=(N, S, E, W))

        self.file_tree = FileView(self.file_tree_frame, normalizer=self.filename_normalizer)
        self.file_tree.grid(column=0, row=0, sticky=(N, S, E, W))

        # # The tree's vertical scrollbar
        self.file_tree_scrollbar = Scrollbar(self.file_tree_frame, orient=VERTICAL)
        self.file_tree_scrollbar.grid(column=1, row=0, sticky=(N, S))

        # # Tie the scrollbar to the text views, and the text views
        # # to each other.
        self.file_tree.config(yscrollcommand=self.file_tree_scrollbar.set)
        self.file_tree_scrollbar.config(command=self.file_tree.yview)

        # Setup weights for the "file_tree" tree
        self.file_tree_frame.columnconfigure(0, weight=1)
        self.file_tree_frame.columnconfigure(1, weight=0)
        self.file_tree_frame.rowconfigure(0, weight=1)

        # Handlers for GUI events
        self.file_tree.bind('<<TreeviewSelect>>', self.on_file_selected)

        self.content.add(self.file_tree_frame)

    def _setup_code_area(self):
        self.code_frame = Frame(self.content)
        self.code_frame.grid(column=1, row=0, sticky=(N, S, E, W))

        # Label for current file
        self.current_file = StringVar()
        self.current_file_label = Label(self.code_frame, textvariable=self.current_file)
        self.current_file_label.grid(column=0, row=0, sticky=(W, E))

        # Code display area
        self.code = CodeView(self.code_frame)
        self.code.grid(column=0, row=1, sticky=(N, S, E, W))

        # Set up weights for the code frame's content
        self.code_frame.columnconfigure(0, weight=1)
        self.code_frame.rowconfigure(0, weight=0)
        self.code_frame.rowconfigure(1, weight=1)

        self.content.add(self.code_frame)

    def _setup_status_bar(self):
        # Status bar
        self.statusbar = Frame(self.root)
        self.statusbar.grid(column=0, row=2, sticky=(W, E))

        # Current status
        self.run_status = StringVar()
        self.run_status_label = Label(self.statusbar, textvariable=self.run_status)
        self.run_status_label.grid(column=0, row=0, sticky=(W, E))
        self.run_status.set('Not running')

        # Main window resize handle
        self.grip = Sizegrip(self.statusbar)
        self.grip.grid(column=1, row=0, sticky=(S, E))

        # Set up weights for status bar frame
        self.statusbar.columnconfigure(0, weight=1)
        self.statusbar.columnconfigure(1, weight=0)
        self.statusbar.rowconfigure(0, weight=0)

    ######################################################
    # Utility methods for controlling content
    ######################################################

    def show_file(self, filename, line=None, breakpoints=None):
        """Show the content of the nominated file.

        If specified, line is the current line number to highlight. If the
        line isn't currently visible, the window will be scrolled until it is.

        breakpoints is a list of line numbers that have current breakpoints.

        If refresh is true, the file will be reloaded and redrawn.
        """
        # Set the filename label for the current file
        self.current_file.set(self.filename_normalizer(filename))

        # Update the code view; this means changing the displayed file
        # if necessary, and updating the current line.
        if filename != self.code.filename:
            self.code.filename = filename

        self.code.line = line

    ######################################################
    # TK Main loop
    ######################################################

    def mainloop(self):
        self.root.mainloop()

    ######################################################
    # TK Command handlers
    ######################################################

    def cmd_quit(self):
        "Quit the program"
        self.root.quit()

    def cmd_run(self, event=None):
        "Run ... whatever that means"

    def cmd_{{ cookiecutter.repo_name }}_page(self):
        "Show the {{ cookiecutter.formal_name }} project page"
        webbrowser.open_new('http://pybee.org/{{ cookiecutter.repo_name }}')