Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
hierlist.py368 linesDownload Raw Back to tools
1# hierlist2#3# IMPORTANT - Please read before using.4 5# This module exposes an API for a Hierarchical Tree Control.6# Previously, a custom tree control was included in Pythonwin which7# has an API very similar to this.8 9# The current control used is the common "Tree Control".  This module exists now10# to provide an API similar to the old control, but for the new Tree control.11 12# If you need to use the Tree Control, you may still find this API a reasonable13# choice.  However, you should investigate using the tree control directly14# to provide maximum flexibility (but with extra work).15 16import sys17 18import commctrl19import win32api20import win32con21import win32ui22from pywin.mfc import dialog, docview, object, window23from win32api import RGB24 25 26# helper to get the text of an arbitary item27def GetItemText(item):28    if type(item) == type(()) or type(item) == type([]):29        use = item[0]30    else:31        use = item32    if type(use) == type(""):33        return use34    else:35        return repr(item)36 37 38class HierDialog(dialog.Dialog):39    def __init__(40        self,41        title,42        hierList,43        bitmapID=win32ui.IDB_HIERFOLDERS,44        dlgID=win32ui.IDD_TREE,45        dll=None,46        childListBoxID=win32ui.IDC_LIST1,47    ):48        dialog.Dialog.__init__(self, dlgID, dll)  # reuse this dialog.49        self.hierList = hierList50        self.dlgID = dlgID51        self.title = title52 53    # 		self.childListBoxID = childListBoxID54    def OnInitDialog(self):55        self.SetWindowText(self.title)56        self.hierList.HierInit(self)57        return dialog.Dialog.OnInitDialog(self)58 59 60class HierList(object.Object):61    def __init__(62        self, root, bitmapID=win32ui.IDB_HIERFOLDERS, listBoxId=None, bitmapMask=None63    ):  # used to create object.64        self.listControl = None65        self.bitmapID = bitmapID66        self.root = root67        self.listBoxId = listBoxId68        self.itemHandleMap = {}69        self.filledItemHandlesMap = {}70        self.bitmapMask = bitmapMask71 72    def __getattr__(self, attr):73        try:74            return getattr(self.listControl, attr)75        except AttributeError:76            return object.Object.__getattr__(self, attr)77 78    def ItemFromHandle(self, handle):79        return self.itemHandleMap[handle]80 81    def SetStyle(self, newStyle):82        hwnd = self.listControl.GetSafeHwnd()83        style = win32api.GetWindowLong(hwnd, win32con.GWL_STYLE)84        win32api.SetWindowLong(hwnd, win32con.GWL_STYLE, (style | newStyle))85 86    def HierInit(self, parent, listControl=None):  # Used when window first exists.87        # this also calls "Create" on the listbox.88        # params - id of listbbox, ID of bitmap, size of bitmaps89        if self.bitmapMask is None:90            bitmapMask = RGB(0, 0, 255)91        else:92            bitmapMask = self.bitmapMask93        self.imageList = win32ui.CreateImageList(self.bitmapID, 16, 0, bitmapMask)94        if listControl is None:95            if self.listBoxId is None:96                self.listBoxId = win32ui.IDC_LIST197            self.listControl = parent.GetDlgItem(self.listBoxId)98        else:99            self.listControl = listControl100            lbid = listControl.GetDlgCtrlID()101            assert self.listBoxId is None or self.listBoxId == lbid, (102                "An invalid listbox control ID has been specified (specified as %s, but exists as %s)"103                % (self.listBoxId, lbid)104            )105            self.listBoxId = lbid106        self.listControl.SetImageList(self.imageList, commctrl.LVSIL_NORMAL)107        # 		self.list.AttachObject(self)108 109        ## ??? Need a better way to do this - either some way to detect if it's compiled with UNICODE110        ##  defined, and/or a way to switch the constants based on UNICODE ???111        if sys.version_info[0] < 3:112            parent.HookNotify(self.OnTreeItemExpanding, commctrl.TVN_ITEMEXPANDINGA)113            parent.HookNotify(self.OnTreeItemSelChanged, commctrl.TVN_SELCHANGEDA)114        else:115            parent.HookNotify(self.OnTreeItemExpanding, commctrl.TVN_ITEMEXPANDINGW)116            parent.HookNotify(self.OnTreeItemSelChanged, commctrl.TVN_SELCHANGEDW)117        parent.HookNotify(self.OnTreeItemDoubleClick, commctrl.NM_DBLCLK)118        self.notify_parent = parent119 120        if self.root:121            self.AcceptRoot(self.root)122 123    def DeleteAllItems(self):124        self.listControl.DeleteAllItems()125        self.root = None126        self.itemHandleMap = {}127        self.filledItemHandlesMap = {}128 129    def HierTerm(self):130        # Dont want notifies as we kill the list.131        parent = self.notify_parent  # GetParentFrame()132        if sys.version_info[0] < 3:133            parent.HookNotify(None, commctrl.TVN_ITEMEXPANDINGA)134            parent.HookNotify(None, commctrl.TVN_SELCHANGEDA)135        else:136            parent.HookNotify(None, commctrl.TVN_ITEMEXPANDINGW)137            parent.HookNotify(None, commctrl.TVN_SELCHANGEDW)138        parent.HookNotify(None, commctrl.NM_DBLCLK)139 140        self.DeleteAllItems()141        self.listControl = None142        self.notify_parent = None  # Break a possible cycle143 144    def OnTreeItemDoubleClick(self, info, extra):145        (hwndFrom, idFrom, code) = info146        if idFrom != self.listBoxId:147            return None148        item = self.itemHandleMap[self.listControl.GetSelectedItem()]149        self.TakeDefaultAction(item)150        return 1151 152    def OnTreeItemExpanding(self, info, extra):153        (hwndFrom, idFrom, code) = info154        if idFrom != self.listBoxId:155            return None156        action, itemOld, itemNew, pt = extra157        itemHandle = itemNew[0]158        if itemHandle not in self.filledItemHandlesMap:159            item = self.itemHandleMap[itemHandle]160            self.AddSubList(itemHandle, self.GetSubList(item))161            self.filledItemHandlesMap[itemHandle] = None162        return 0163 164    def OnTreeItemSelChanged(self, info, extra):165        (hwndFrom, idFrom, code) = info166        if idFrom != self.listBoxId:167            return None168        action, itemOld, itemNew, pt = extra169        itemHandle = itemNew[0]170        item = self.itemHandleMap[itemHandle]171        self.PerformItemSelected(item)172        return 1173 174    def AddSubList(self, parentHandle, subItems):175        for item in subItems:176            self.AddItem(parentHandle, item)177 178    def AddItem(self, parentHandle, item, hInsertAfter=commctrl.TVI_LAST):179        text = self.GetText(item)180        if self.IsExpandable(item):181            cItems = 1  # Trick it !!182        else:183            cItems = 0184        bitmapCol = self.GetBitmapColumn(item)185        bitmapSel = self.GetSelectedBitmapColumn(item)186        if bitmapSel is None:187            bitmapSel = bitmapCol188        ## if type(text) is str:189        ##	text = text.encode("mbcs")190        hitem = self.listControl.InsertItem(191            parentHandle,192            hInsertAfter,193            (None, None, None, text, bitmapCol, bitmapSel, cItems, 0),194        )195        self.itemHandleMap[hitem] = item196        return hitem197 198    def _GetChildHandles(self, handle):199        ret = []200        try:201            handle = self.listControl.GetChildItem(handle)202            while 1:203                ret.append(handle)204                handle = self.listControl.GetNextItem(handle, commctrl.TVGN_NEXT)205        except win32ui.error:206            # out of children207            pass208        return ret209 210    def Refresh(self, hparent=None):211        # Attempt to refresh the given item's sub-entries, but maintain the tree state212        # (ie, the selected item, expanded items, etc)213        if hparent is None:214            hparent = commctrl.TVI_ROOT215        if hparent not in self.filledItemHandlesMap:216            # This item has never been expanded, so no refresh can possibly be required.217            return218        root_item = self.itemHandleMap[hparent]219        old_handles = self._GetChildHandles(hparent)220        old_items = list(map(self.ItemFromHandle, old_handles))221        new_items = self.GetSubList(root_item)222        # Now an inefficient technique for synching the items.223        inew = 0224        hAfter = commctrl.TVI_FIRST225        for iold in range(len(old_items)):226            inewlook = inew227            matched = 0228            while inewlook < len(new_items):229                if old_items[iold] == new_items[inewlook]:230                    matched = 1231                    break232                inewlook = inewlook + 1233            if matched:234                # Insert the new items.235                # 				print "Inserting after", old_items[iold], old_handles[iold]236                for i in range(inew, inewlook):237                    # 					print "Inserting index %d (%s)" % (i, new_items[i])238                    hAfter = self.AddItem(hparent, new_items[i], hAfter)239 240                inew = inewlook + 1241                # And recursively refresh iold242                hold = old_handles[iold]243                if hold in self.filledItemHandlesMap:244                    self.Refresh(hold)245            else:246                # Remove the deleted items.247                # 				print "Deleting %d (%s)" % (iold, old_items[iold])248                hdelete = old_handles[iold]249                # First recurse and remove the children from the map.250                for hchild in self._GetChildHandles(hdelete):251                    del self.itemHandleMap[hchild]252                    if hchild in self.filledItemHandlesMap:253                        del self.filledItemHandlesMap[hchild]254                self.listControl.DeleteItem(hdelete)255            hAfter = old_handles[iold]256        # Fill any remaining new items:257        for newItem in new_items[inew:]:258            # 			print "Inserting new item", newItem259            self.AddItem(hparent, newItem)260 261    def AcceptRoot(self, root):262        self.listControl.DeleteAllItems()263        self.itemHandleMap = {commctrl.TVI_ROOT: root}264        self.filledItemHandlesMap = {commctrl.TVI_ROOT: root}265        subItems = self.GetSubList(root)266        self.AddSubList(0, subItems)267 268    def GetBitmapColumn(self, item):269        if self.IsExpandable(item):270            return 0271        else:272            return 4273 274    def GetSelectedBitmapColumn(self, item):275        return 0276 277    def CheckChangedChildren(self):278        return self.listControl.CheckChangedChildren()279 280    def GetText(self, item):281        return GetItemText(item)282 283    def PerformItemSelected(self, item):284        try:285            win32ui.SetStatusText("Selected " + self.GetText(item))286        except win32ui.error:  # No status bar!287            pass288 289    def TakeDefaultAction(self, item):290        win32ui.MessageBox("Got item " + self.GetText(item))291 292 293##########################################################################294#295# Classes for use with seperate HierListItems.296#297#298class HierListWithItems(HierList):299    def __init__(300        self, root, bitmapID=win32ui.IDB_HIERFOLDERS, listBoxID=None, bitmapMask=None301    ):  # used to create object.302        HierList.__init__(self, root, bitmapID, listBoxID, bitmapMask)303 304    def DelegateCall(self, fn):305        return fn()306 307    def GetBitmapColumn(self, item):308        rc = self.DelegateCall(item.GetBitmapColumn)309        if rc is None:310            rc = HierList.GetBitmapColumn(self, item)311        return rc312 313    def GetSelectedBitmapColumn(self, item):314        return self.DelegateCall(item.GetSelectedBitmapColumn)315 316    def IsExpandable(self, item):317        return self.DelegateCall(item.IsExpandable)318 319    def GetText(self, item):320        return self.DelegateCall(item.GetText)321 322    def GetSubList(self, item):323        return self.DelegateCall(item.GetSubList)324 325    def PerformItemSelected(self, item):326        func = getattr(item, "PerformItemSelected", None)327        if func is None:328            return HierList.PerformItemSelected(self, item)329        else:330            return self.DelegateCall(func)331 332    def TakeDefaultAction(self, item):333        func = getattr(item, "TakeDefaultAction", None)334        if func is None:335            return HierList.TakeDefaultAction(self, item)336        else:337            return self.DelegateCall(func)338 339 340# A hier list item - for use with a HierListWithItems341class HierListItem:342    def __init__(self):343        pass344 345    def GetText(self):346        pass347 348    def GetSubList(self):349        pass350 351    def IsExpandable(self):352        pass353 354    def GetBitmapColumn(self):355        return None  # indicate he should do it.356 357    def GetSelectedBitmapColumn(self):358        return None  # same as other359 360    # for py3k/rich-comp sorting compatibility.361    def __lt__(self, other):362        # we want unrelated items to be sortable...363        return id(self) < id(other)364 365    # for py3k/rich-comp equality compatibility.366    def __eq__(self, other):367        return False368 
codekingpro/portable-devtools · Team Ai