from __future__ import annotations
import logging
from typing import TYPE_CHECKING, List, Tuple
import wx
from wbBase.document import FileNameFromPath
from wx import aui
from wx.lib.mixins import treemixin
if TYPE_CHECKING:
    from wbBase.application import App
    from wbBase.document import Document
    from wbBase.document.manager import DocumentManager
__version__ = "0.0.3"
log = logging.getLogger(__name__)
name = "DocBrowser"
[docs]
class DocTreeModel:
    """
    TreeModel holds the domain objects that are shown in the tree control.
    """
    @property
    def app(self) -> App:
        """
        :return: The running Workbench application.
        """
        return wx.GetApp()
    @property
    def documentManager(self) -> DocumentManager:
        """
        :return: The document manager of the running application.
        """
        return self.app.documentManager
    @property
    def items(self) -> List[Tuple[str, tuple, str]]:
        result = []
        doc: Document
        for doc in self.documentManager.documents:
            result.append(
                (
                    FileNameFromPath(doc.path),
                    tuple((v.frame.title, (), v.typeName) for v in list(doc.views)),
                    doc.typeName,
                )
            )
        return result
[docs]
    def GetItem(self, indices: Tuple[int, ...]):
        # log.warning("GetItem(%r)", indices)
        text, children, typeName = "Hidden root", self.items, ""
        for index in indices:
            text, children, typeName = children[index]
        # log.warning("GetItem -> text: %r, children: %r", text, children)
        return text, children, typeName 
[docs]
    def GetText(self, indices: Tuple[int, ...]) -> str:
        return self.GetItem(indices)[0] 
[docs]
    def GetChildren(self, indices: Tuple[int, ...]):
        return self.GetItem(indices)[1] 
[docs]
    def GetChildrenCount(self, indices: Tuple[int, ...]) -> int:
        return len(self.GetChildren(indices)) 
 
[docs]
class DocTreeMixin(treemixin.VirtualTree):
    """
    Mixin class for virtual TreeCtrl.
    """
[docs]
    def __init__(self, *args, **kwargs):
        self.model = DocTreeModel()
        super().__init__(*args, **kwargs) 
        # self.createImageList()
    @property
    def app(self) -> App:
        """
        :return: The running Workbench application.
        """
        return wx.GetApp()
    @property
    def documentManager(self) -> DocumentManager:
        """
        :return: The document manager of the running application.
        """
        return self.app.documentManager
[docs]
    def createImageList(self) -> None:
        """
        Create an image list from all known document and view icons.
        """
        size = (16, 16)
        self.imageDict = {}
        self.imageList = wx.ImageList(*size)
        imageIndex = 0
        for template in self.documentManager.templates:
            if template.documentTypeName not in self.imageDict:
                self.imageList.Add(template.icon)
                self.imageDict[template.documentTypeName] = imageIndex
                imageIndex += 1
                for viewtype in template.viewTypes:
                    if viewtype.typeName not in self.imageDict:
                        icon = viewtype.getIcon()
                        if icon.IsOk():
                            self.imageList.Add(icon)
                            self.imageDict[viewtype.typeName] = imageIndex
                            imageIndex += 1
        self.AssignImageList(self.imageList) 
[docs]
    def OnGetItemText(self, indices: Tuple[int, ...], column: int = 0) -> str:
        """
        :return: The string for the item specified by indices
        """
        return self.model.GetText(indices) 
[docs]
    def OnGetChildrenCount(self, indices: Tuple[int, ...]) -> int:
        """
        :return: the number of child items of the item with the
            provided indices.
        """
        return self.model.GetChildrenCount(indices) 
[docs]
    def OnGetItemImage(
        self,
        indices: Tuple[int, ...],
        which: int = wx.TreeItemIcon_Normal,
        column: int = 0,
    ) -> int:
        """
        :return: The index in the image list of the image to be used
        """
        text, children, typeName = self.model.GetItem(indices)
        return self.imageDict.get(typeName, -1) 
 
[docs]
class DocTreeCtrl(DocTreeMixin, wx.TreeCtrl):
    """
    TreeCtrl to show all open documents and the associated views.
    """
[docs]
    def __init__(
        self,
        parent,
        id=wx.ID_ANY,
        pos=wx.DefaultPosition,
        size=wx.DefaultSize,
        style=wx.TR_DEFAULT_STYLE | wx.TR_SINGLE | wx.TR_TWIST_BUTTONS,
    ):
        super().__init__(parent=parent, id=id, pos=pos, size=size, style=style)
        self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.on_itemActivated)
        self.Bind(wx.EVT_UPDATE_UI, self.on_updateUI)
        self.oldItems = None 
[docs]
    def on_itemActivated(self, event: wx.TreeEvent):
        """
        Handle double click on item in tree control.
        """
        item = event.GetItem()
        indices = self.GetIndexOfItem(item)
        if len(indices) == 1:
            # it is a document
            return
        elif len(indices) == 2:
            # it is a view
            doc_index, view_index = indices
            self.documentManager.documents[doc_index].views[view_index].Activate() 
[docs]
    def on_updateUI(self, event):
        newItems = self.model.items
        if newItems == self.oldItems:
            return
        self.RefreshItems()
        self.oldItems = newItems 
 
info = aui.AuiPaneInfo()
info.Name(name)
info.Caption(name)
info.Dock()
info.Bottom()
info.Resizable()
info.MaximizeButton(True)
info.MinimizeButton(True)
info.CloseButton(False)
info.FloatingSize(wx.Size(300, 400))
info.BestSize(wx.Size(300, 400))
info.MinSize(wx.Size(100, 100))
if wx.GetApp():
    # todo: define unique icon for DocBrowser
    info.Icon(wx.ArtProvider.GetBitmap("FILE_BROWSER", wx.ART_FRAME_ICON))
panels = [(DocTreeCtrl, info)]
[docs]
def makeImageList(app: App):
    docTreeCtrl = app.panelManager.getWindowByCaption("DocBrowser")
    docTreeCtrl.createImageList() 
wx.GetApp().AddPostInitAction(makeImageList)