def _create_list(self):        
        self._list_panel = scrolled.ScrolledPanel(self.main_panel, -1,
                                                  style=wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER, name="ListPanel")
        
        self._list = ExplorerList(self._list_panel, self)

        tb = xrcListToolbar(self._list_panel)
        tb.list = self._list
        tbsize = tb.GetToolBitmapSize()
        tb.SetToolNormalBitmap(tb.sort_by_type.GetId(), get_bitmap('icons/class.png', tbsize, self.project))
        tb.SetToolNormalBitmap(tb.sort_by_time.GetId(), get_bitmap('icons/time.png', tbsize, self.project))
        tb.SetToolNormalBitmap(tb.sort_by_name.GetId(), get_bitmap('icons/name.png', tbsize, self.project))
        tb.SetToolNormalBitmap(tb.list_icon.GetId(), get_bitmap('icons/icon_view.png', tbsize, self.project))

        if self._list.list_mode == LIST_MODE_ICON:
            tb.ToggleTool(tb.list_icon.GetId(), True)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(tb, 0, wx.EXPAND)
        sizer.Add(self._list, 1, wx.EXPAND)
        self._list_panel.SetSizer(sizer)
        
        self._list_panel.SetAutoLayout(1)
        self._list_panel.SetupScrolling()
        self._list_panel.SetInitialSize()
class ExplorerFrame(xrcExplorerFrame):
    """A frame to explorer all objects of a project, both data project and type project.

    At most 2 instances of ExplorerFrame might exists, while only one is enabled  at the same time.  
    """
    
    def __init__(self, parent, project=None):
        self._project = None            
        # [EditorFrame, ...]
        self._editor_frames = []   
        
        # {EditorFrame: wxid}  
        self._editor_to_menuid = {}
        
        # [fs_nodes, ...]
        self._path_history_pos = 0      
        self._path_history = []    
        
        # tool ids
        self._create_obj_tool_ids = [] 
             
        super(ExplorerFrame, self).__init__(parent)

        # icon
        icon = wx.EmptyIcon()
        icon_name = 'icons/setting.png' if (project and project.is_type_editor) else 'icons/table.png'
        icon.CopyFromBitmap(get_bitmap(icon_name, (64, 64), project))
        self.SetIcon(icon)
        
        # Replace tool icons
        self._initialized_toolbar()

        # XRCed can't assign variable for wxMenu correctly        
        self.menu_windows = self.menu_close_all.GetMenu()
        self.menu_new = self.menu_new_dummy.GetMenu()
        self.menu_new.Remove(self.menu_new.FindItemByPosition(0).GetId())
        
        self.menu_plugins = self.menu_plugin_dummy.GetMenu()
        self.menu_plugins.Remove(self.menu_plugins.FindItemByPosition(0).GetId())
        
        self.SetMinSize((640, 480))        
        self._create_tree()
        self._create_list()
        # self._create_status_view()
        # self._create_log_view()
        self._layout()
        
        self.Bind(wx.EVT_CHAR_HOOK, self._on_char_hook)
          
        if project:
            self.update_project(project)

    # def ProcessEvent(self, event):
    #     a = xrcExplorerFrame.ProcessEvent(self, event)
    #     b = event.GetSkipped()
    #     print 'ProcessEvent:', event, a, b
    #     return a

    @property
    def list(self):
        return self._list

    def _initialized_toolbar(self):
        project = self.project
        tbsize = self.tool_bar.GetToolBitmapSize()
        size = (tbsize.width, tbsize.height)
        self.tool_bar.SetToolNormalBitmap(self.tool_open.GetId(), get_bitmap('icons/open.png', size, project))
        self.tool_bar.SetToolNormalBitmap(self.tool_setting.GetId(), get_bitmap('icons/setting.png', size, project))
        # self.tool_bar.SetToolNormalBitmap(self.tool_repair.GetId(), get_bitmap('icons/repair.png', size, project))
        self.tool_bar.SetToolNormalBitmap(self.tool_export.GetId(), get_bitmap('icons/export.png', size, project))

        # self.tool_bar.SetToolNormalBitmap(self.tool_create_folder.GetId(), get_bitmap(ICON_FOLDER, size, project))
        # self.tool_bar.SetToolNormalBitmap(self.tool_create_filter.GetId(), get_bitmap(ICON_FILTER, size, project))

        self.Bind(wx.EVT_SIZE, self._on_size_changed)

    def _on_size_changed(self, evt):

        # adjust the width of address_box
        tb_size = self.tool_bar.GetSize()
        ab_size = self.address_box.GetSize()
        ab_pos = self.address_box.GetPosition()
        self.address_box.SetSize((tb_size[0] - ab_pos[0], ab_size[1]))
        # evt.Veto()

    def _create_tree(self):
        self._tree_panel = scrolled.ScrolledPanel(self.main_panel, -1,
                                                  style=wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER, name="TreePanel")
        
        self._tree = ExplorerTree(self._tree_panel, self)  
              
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self._tree, 1, wx.EXPAND)
        self._tree_panel.SetSizer(sizer)
        
        self._tree_panel.SetAutoLayout(1)
        self._tree_panel.SetupScrolling()
        self._tree_panel.SetInitialSize()        
    
    def _create_list(self):        
        self._list_panel = scrolled.ScrolledPanel(self.main_panel, -1,
                                                  style=wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER, name="ListPanel")
        
        self._list = ExplorerList(self._list_panel, self)

        tb = xrcListToolbar(self._list_panel)
        tb.list = self._list
        tbsize = tb.GetToolBitmapSize()
        tb.SetToolNormalBitmap(tb.sort_by_type.GetId(), get_bitmap('icons/class.png', tbsize, self.project))
        tb.SetToolNormalBitmap(tb.sort_by_time.GetId(), get_bitmap('icons/time.png', tbsize, self.project))
        tb.SetToolNormalBitmap(tb.sort_by_name.GetId(), get_bitmap('icons/name.png', tbsize, self.project))
        tb.SetToolNormalBitmap(tb.list_icon.GetId(), get_bitmap('icons/icon_view.png', tbsize, self.project))

        if self._list.list_mode == LIST_MODE_ICON:
            tb.ToggleTool(tb.list_icon.GetId(), True)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(tb, 0, wx.EXPAND)
        sizer.Add(self._list, 1, wx.EXPAND)
        self._list_panel.SetSizer(sizer)
        
        self._list_panel.SetAutoLayout(1)
        self._list_panel.SetupScrolling()
        self._list_panel.SetInitialSize()
        
    def _create_status_view(self):
        pass
    
    def _create_log_view(self):
        self._log = wx.TextCtrl(self.main_panel, -1,
                                style=wx.TE_MULTILINE | wx.TE_READONLY | wx.HSCROLL)
        wx.Log_SetActiveTarget(wx.LogTextCtrl(self._log))        
        pass
    
    def _layout(self):
        self._aui_manager = aui.AuiManager()
        self._aui_manager.SetManagedWindow(self.main_panel)
                
        # Use the aui manager to set up everything
        allow_aui_floating = False
        
#         self.SetToolBar(None)        
#         self._aui_manager.AddPane(self.tool_bar, aui.AuiPaneInfo().
#                       Name("Toolbar").Caption("Toolbar").
#                       ToolbarPane().Top().Floatable(allow_aui_floating).
#                       LeftDockable(False).RightDockable(False))        

        self._aui_manager.AddPane(self._tree_panel,
                                  aui.AuiPaneInfo().
                                  Left().Layer(2).BestSize((240, -1)).
                                  MinSize((160, -1)).
                                  Floatable(allow_aui_floating).FloatingSize((240, 700)).
                                  Caption(u"Object Explorer").
                                  CloseButton(False).
                                  Name("ResourceTree"))
        self._aui_manager.AddPane(self._list_panel, aui.AuiPaneInfo().CenterPane().Name("FileList"))
#         self._aui_manager.AddPane(self._log,
#                          aui.AuiPaneInfo().
#                          Bottom().BestSize((-1, 60)).
#                          MinSize((-1, 60)).Name("Log").Caption("Log") )
        # self._aui_cfgs[DEFAULT_PERSPECTIVE] = self._aui_manager.SavePerspective()
        self._aui_manager.Update()
        # self._aui_manager.SetFlags(self._aui_manager.GetFlags() ^ aui.AUI_MGR_TRANSPARENT_DRAG)
        pass
    
    def _on_char_hook(self, evt):
        keystr = hotkey.build_keystr(evt)
        
        if hotkey.check(hotkey.EXPLORER_UP_LEVEL, keystr):
            self.go_up()
            return
        
        if hotkey.check(hotkey.EXPLORER_HISTORY_PREV, keystr):
            self.go_back()
            return

        if hotkey.check(hotkey.EXPLORER_HISTORY_NEXT, keystr):
            self.go_forward()
            return

        evt.Skip()

    @property
    def project(self):
        return self._project
    
    @property
    def list(self):
        return self._list
    
    @property
    def tree(self):
        return self._tree
    
    @property
    def is_type_editor(self):
        return bool(self._project and self._project.is_type_editor)
    
    def update_project(self, project): 
        # Less elegant but more convenience than ExplorerFrame.get_frame(project)        
        project.explorer = self
        
        self._project = project
        self.SetTitle("%s - [%s]" % (project.name, project.path))
                    
        if not project.is_type_editor and project.get_editor_project().has_error():
            wx.MessageBox("Invalid types, please fix!")
            self.set_status_msg('Can not edit because types are invalid. Open Settings to fix!')            
        
        self._tree.update_project()
        self._list.update_project()
        
        # Create buttons for Creating clazzes
        for tid in self._create_obj_tool_ids:
            self.tool_bar.DeleteTool(tid)
            
        # tbsize = self.tool_bar.GetToolBitmapSize()
        # size = (tbsize.width, tbsize.height)
        # clazzes = project.type_manager.get_clazzes()
        # clazzes.sort(key=lambda x: x.name)
        # for clazz in clazzes:
        #     tool = self.tool_bar.AddTool(wx.NewId(), get_clazz_bitmap(clazz, size, project),
        # shortHelpString=clazz.name)
        #     self._bind_tool_create(clazz, tool.GetId())
        #     self._create_obj_tool_ids.append(tool.GetId())
        # self.tool_bar.Realize()
                
        self.set_path(project.fs_manager.root)
        
        # Update frame icon
        icon = get_icon('table.png', FRAME_ICON_SIZE, project)
        if icon:
            self.SetIcon(icon)
            
        self.init_plugins()
    
    def init_plugins(self):
        # Remove current plugins
        while 1:
            # noinspection PyBroadException
            try:
                item = self.menu_plugins.FindItemByPosition(0)                
                self.menu_plugins.Remove(item.GetId())
            except:
                break
            
        from structerui.plugin_manager import PluginManager
        pm = PluginManager()      
        pm.load_plugins()      

        def get_callback(plugin_):
            def callback(evt):
                _ = evt
                try:
                    plugin_.execute(self.project)
                except Exception, e:
                    log.error('PluginError: %s', e)
                    wx.MessageBox('PluginError: %s' % e)
            return callback

        # add all        
        for plugin in pm.iter_plugins():            
            mi = wx.MenuItem(self.menu_plugins, wx.NewId(), plugin.label)
            self.menu_plugins.Bind(wx.EVT_MENU, get_callback(plugin), mi)
            self.menu_plugins.AppendItem(mi)