NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

baseSingleLineEdit.py (41652B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\control\singlelineedits\baseSingleLineEdit.py
      2 import weakref
      3 import logging
      4 import sys
      5 import blue
      6 import evetypes
      7 import mathext
      8 import trinity
      9 import uthread
     10 from brennivin.itertoolsext import Bundle
     11 from carbonui.button import styling
     12 from carbonui.button.const import HEIGHT_NORMAL
     13 from carbonui.control.combo import Combo
     14 from carbonui.control.singlelineedits.caret import Caret
     15 from carbonui.control.singlelineedits.singleLineEditHistory import SingleLineEditHistory, HistoryData
     16 from carbonui.fontconst import DEFAULT_FONTSIZE
     17 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     18 from carbonui.primitives.sprite import Sprite
     19 from carbonui.text.settings import check_convert_font_size
     20 from eve.client.script.ui import eveThemeColor
     21 from carbon.common.script.util.commonutils import StripTags
     22 from carbon.common.script.util.timerstuff import AutoTimer
     23 from carbonui import Density, uiconst, Align
     24 from carbonui.control.label import LabelOverride as Label
     25 from carbonui.primitives.container import Container
     26 from carbonui.primitives.fill import Fill
     27 from carbonui.text.color import TextColor
     28 from carbonui.uianimations import animations
     29 from carbonui.uicore import uicore
     30 from carbonui.util.various_unsorted import GetBrowser, GetWindowAbove, GetClipboardData
     31 from carbonui.control.buttonIcon import ButtonIcon
     32 from eve.client.script.ui.control.eveLabel import EveLabelMedium, EveLabelSmall
     33 from carbonui.control.window import Window
     34 from carbonui.decorative.inputUnderlay import InputUnderlay
     35 from eve.client.script.ui.shared.market import GetTypeIDFromDragItem
     36 from eve.client.script.ui.tooltips.tooltipUtil import RefreshTooltipForOwner
     37 from eve.client.script.ui.util.linkUtil import GetItemIDFromTextLink
     38 from menu import MenuLabel
     39 from qtyTooltip.tooltip import LoadTooltipForNumber
     40 from carbonui.control.singlelineedits.util import GetDroppedCharCorpOrAllianceName, GetDroppedCharInfo
     41 logger = logging.getLogger(__name__)
     42 CARET_SCROLL_MARGIN = 16
     43 
     44 class BaseSingleLineEdit(Container):
     45     default_name = 'BaseSingleLineEdit'
     46     default_align = uiconst.TOPLEFT
     47     default_width = 160
     48     default_height = HEIGHT_NORMAL
     49     default_state = uiconst.UI_NORMAL
     50     default_density = Density.NORMAL
     51     default_readonly = False
     52     default_autoselect = False
     53     default_dynamicHistoryWidth = False
     54     default_caretcolor = eveThemeColor.THEME_ACCENT
     55     default_selectioncolor = tuple(eveThemeColor.THEME_FOCUSDARK[:3]) + (0.4,)
     56     default_fontcolor = TextColor.NORMAL
     57     default_textLeftMargin = 0
     58     default_textRightMargin = 0
     59     default_bold = False
     60     default_inputType = None
     61     default_adjustWidth = False
     62     default_label = ''
     63     default_setvalue = ''
     64     default_icon = None
     65     default_OnChange = None
     66     default_OnSetFocus = None
     67     default_OnFocusLost = None
     68     default_OnReturn = None
     69     default_OnInsert = None
     70     default_fontsize = DEFAULT_FONTSIZE
     71     default_fontStyle = None
     72     default_fontFamily = None
     73     default_fontPath = None
     74     default_fadeOutContent = True
     75     default_displayHistory = True
     76     registerHistory = True
     77 
     78     def ApplyAttributes(self, attributes):
     79         super(BaseSingleLineEdit, self).ApplyAttributes(attributes)
     80         self.rightAlignedButtons = weakref.WeakSet()
     81         self._clearButton = None
     82         self.caretIndex = (0, 0)
     83         self.isTabStop = 1
     84         self.selFrom = None
     85         self.selTo = None
     86         self.historyMenu = None
     87         self.displayHistory = attributes.get('displayHistory', self.default_displayHistory)
     88         self.caret = None
     89         self.selectionTimer = None
     90         self.underlay = None
     91         self.textLabel = None
     92         self.hintLabel = None
     93         self.selectionFill = None
     94         self.draggedValue = None
     95         self._textClipperInner = None
     96         self.iconSprite = None
     97         self.OnChange = None
     98         self.OnFocusLost = None
     99         self.OnReturn = None
    100         self.OnInsert = None
    101         self.text = attributes.get('text', '')
    102         self.hintText = attributes.get('hintText', '')
    103         self.readonly = attributes.get('readonly', self.default_readonly)
    104         self.fontStyle = attributes.get('fontStyle', self.default_fontStyle)
    105         self.fontFamily = attributes.get('fontFamily', self.default_fontFamily)
    106         self.fontPath = attributes.get('fontPath', self.default_fontPath)
    107         self.fontsize = attributes.get('fontsize', self.default_fontsize)
    108         self.bold = attributes.get('bold', self.default_bold)
    109         self.textLeftMargin = attributes.get('textLeftMargin', self.default_textLeftMargin)
    110         self.textRightMargin = attributes.get('textRightMargin', self.default_textRightMargin)
    111         self.icon = attributes.get('icon', self.default_icon)
    112         self.CaretColor = attributes.get('caretColor', self.default_caretcolor)
    113         self.SelectColor = attributes.get('selectColor', self.default_selectioncolor)
    114         self.fontcolor = attributes.get('fontcolor', self.default_fontcolor)
    115         self.autoselect = attributes.get('autoselect', self.default_autoselect)
    116         self.dynamicHistoryWidth = attributes.get('dynamicHistoryWidth', self.default_dynamicHistoryWidth)
    117         self.inputType = attributes.get('inputType', self.default_inputType)
    118         self.isTypeField = attributes.get('isTypeField', False)
    119         self.isCharacterField = attributes.get('isCharacterField', False)
    120         self.isCharCorpOrAllianceField = attributes.get('isCharCorpOrAllianceField', False)
    121         self.isLocationField = attributes.get('isLocationField', False)
    122         self.OnAnyChar = attributes.get('OnAnyChar', self.OnAnyChar)
    123         self.adjustWidth = attributes.get('adjustWidth', self.default_adjustWidth)
    124         self.fadeOutContent = attributes.get('fadeOutContent', self.default_fadeOutContent)
    125         self.ConstructIcon()
    126         self.ConstructTextClipper()
    127         self.ConstructBackground()
    128         self.ConstructLabels()
    129         self.SetTextColor(self.fontcolor)
    130         self.SetLabel(attributes.get('label', self.default_label))
    131         self.SetValue(attributes.get('setvalue', self.default_setvalue))
    132         self.CheckHintText()
    133         self.OnChange = attributes.get('OnChange', self.default_OnChange)
    134         self.__OnSetFocus = attributes.get('OnSetFocus', self.default_OnSetFocus)
    135         self.OnFocusLost = attributes.get('OnFocusLost', self.default_OnFocusLost)
    136         self.OnReturn = attributes.get('OnReturn', self.default_OnReturn)
    137         self.OnInsert = attributes.get('OnInsert', self.default_OnInsert)
    138         self.sendSelfAsArgument = attributes.get('sendSelfAsArgument', False)
    139         self.density = attributes.get('density', self.default_density)
    140         if self.GetAlign() == uiconst.TOALL:
    141             self.height = self.width = 0
    142         else:
    143             self.height = styling.get_height(self.density)
    144         uicore.event.RegisterForTriuiEvents(uiconst.UI_MOUSEDOWN, self.OnGlobalMouseDownCallback)
    145 
    146     def ConstructIcon(self):
    147         if self.icon:
    148             if not self.iconSprite:
    149                 iconCont = ContainerAutoSize(name='iconCont', parent=self, align=uiconst.TOLEFT, padLeft=8)
    150                 self.iconSprite = Sprite(name='iconSprite', parent=iconCont, align=Align.CENTERLEFT, color=TextColor.SECONDARY, pos=(0, 0, 16, 16))
    151             self.iconSprite.SetTexturePath(self.icon)
    152         else:
    153             self.iconSprite = None
    154 
    155     def ConstructTextClipper(self):
    156         self._textClipper = Container(name='_textClipper', parent=self, clipChildren=False, padding=(8, 0, 8, 0))
    157         self._textClipperInner = Container(parent=self._textClipper, align=uiconst.TOALL, clipChildren=True)
    158         self._textClipper._OnSizeChange_NoBlock = self.OnClipperSizeChange
    159 
    160     def ConstructBackground(self):
    161         if self.underlay:
    162             return
    163         self.underlay = InputUnderlay(bgParent=self)
    164 
    165     def ConstructLabels(self):
    166         self.textLabel = EveLabelMedium(name='textLabel', parent=self._textClipperInner, align=uiconst.CENTERLEFT, state=uiconst.UI_DISABLED, left=self.textLeftMargin, text='', maxLines=1)
    167         self.hintLabel = Label(name='hintTextLabel', parent=self._textClipperInner, align=uiconst.CENTERLEFT, state=uiconst.UI_DISABLED, left=self.textLeftMargin, text='', maxLines=1, color=TextColor.SECONDARY)
    168 
    169     def ConstructCaret(self):
    170         if self.caret or not hasattr(self, 'caret'):
    171             return
    172         self.caret = Caret(name='caret', parent=self._textClipper, align=uiconst.CENTERLEFT, idx=0, state=uiconst.UI_HIDDEN, left=self.textLeftMargin, height=1)
    173 
    174     def ConstructSelectionFill(self):
    175         _, h = self.GetAbsoluteSize()
    176         order = self.textLabel.GetOrder()
    177         if self.selectionFill:
    178             return
    179         self.selectionFill = Fill(name='selectionFill', parent=self._textClipperInner, align=uiconst.CENTERLEFT, idx=order + 1, color=self.SelectColor)
    180 
    181     def SetLabel(self, text):
    182         self.label = EveLabelSmall(parent=self, name='__caption', text=text, state=uiconst.UI_DISABLED, align=uiconst.TOPLEFT, idx=0)
    183         self.label.top = -self.label.textheight
    184         if self.adjustWidth:
    185             self.width = max(self.width, self.label.textwidth)
    186 
    187     def SetHistoryVisibility(self, status):
    188         self.displayHistory = status
    189 
    190     def SetTextColor(self, color):
    191         if not color:
    192             return
    193         self.textLabel.SetRGBA(*color)
    194 
    195     def SetHintText(self, hint):
    196         self.hintText = hint
    197         self.CheckHintText()
    198 
    199     def OnClipperSizeChange(self, newWidth, newHeight):
    200         if newWidth:
    201             self.RefreshCaretPosition()
    202             self.RefreshSelectionDisplay()
    203             self.RefreshTextClipper()
    204 
    205     def RefreshCaretPosition(self):
    206         if self.destroyed:
    207             return
    208         self.ConstructCaret()
    209         w, h = self._textClipper.GetAbsoluteSize()
    210         self.caret.left = self.textLabel.left + self.caretIndex[1]
    211         if self.textLabel.textwidth < w - self.textLeftMargin - self.textRightMargin:
    212             self.textLabel.left = self.textLeftMargin
    213         else:
    214             if self.textLabel.left + self.textLabel.textwidth < w - self.textLeftMargin - self.textRightMargin:
    215                 self.textLabel.left = w - self.textLeftMargin - self.textRightMargin - self.textLabel.textwidth
    216             if self.caret.left > w - self.textRightMargin - CARET_SCROLL_MARGIN:
    217                 diff = self.caret.left - w + self.textRightMargin + CARET_SCROLL_MARGIN
    218                 self.textLabel.left = max(self.textLabel.left - diff, w - self.textLabel.textwidth)
    219             elif self.caret.left < self.textLeftMargin + CARET_SCROLL_MARGIN:
    220                 diff = -self.caret.left + self.textLeftMargin + CARET_SCROLL_MARGIN
    221                 self.textLabel.left = min(self.textLabel.left + diff, 0)
    222         self.caret.left = mathext.clamp(value=self.textLabel.left + self.caretIndex[1], low=0, high=w - self.caret.width)
    223 
    224     def RefreshSelectionDisplay(self):
    225         selection = self.GetSelectionBounds()
    226         if selection != (None, None):
    227             self.ConstructSelectionFill()
    228             f, t = selection
    229             self.selectionFill.left = self.textLabel.left + f[1]
    230             self.selectionFill.width = t[1] - f[1]
    231             self.selectionFill.state = uiconst.UI_DISABLED
    232             fontSize = check_convert_font_size(self.fontsize)
    233             self.selectionFill.height = fontSize + 4
    234         elif self.selectionFill:
    235             self.selectionFill.state = uiconst.UI_HIDDEN
    236 
    237     def GetSelectionBounds(self):
    238         if self.selFrom and self.selTo and self.selFrom[0] != self.selTo[0]:
    239             return (min(self.selFrom, self.selTo), max(self.selFrom, self.selTo))
    240         return (None, None)
    241 
    242     def RefreshTextClipper(self):
    243         if self._clearButton:
    244             if len(self.text) >= self._clearButton.showOnLetterCount:
    245                 self._clearButton.Show()
    246             else:
    247                 self._clearButton.Hide()
    248         visible_button_count = 0
    249         left = 5
    250         for each in self.rightAlignedButtons:
    251             if not each.destroyed and each.display:
    252                 visible_button_count += 1
    253                 each.left = left
    254                 left += each.width
    255 
    256         if visible_button_count > 0:
    257             left += 4
    258         left = max(left, 8)
    259         self._textClipper.padRight = left
    260         if self.fadeOutContent:
    261             w, h = self._textClipper.GetAbsoluteSize()
    262             if self.textLabel.left + self.textLabel.textwidth > w:
    263                 self.textLabel.SetRightAlphaFade(-self.textLabel.left + w, 8)
    264             else:
    265                 self.textLabel.SetRightAlphaFade(0, 0)
    266             if self.textLabel.left < self.textLeftMargin:
    267                 self.textLabel.SetLeftAlphaFade(-self.textLabel.left + self.textLeftMargin, 8)
    268             else:
    269                 self.textLabel.SetLeftAlphaFade(0, 0)
    270 
    271     def ShowClearButton(self, icon = None, hint = None, showOnLetterCount = True):
    272         if self._clearButton:
    273             self._clearButton.Close()
    274         icon = icon or 'res:/UI/Texture/Icons/73_16_210.png'
    275         clearButton = self.AddIconButton(icon, hint)
    276         clearButton.OnClick = self.OnClearButtonClick
    277         clearButton.Hide()
    278         clearButton.showOnLetterCount = showOnLetterCount
    279         self._clearButton = clearButton
    280         return clearButton
    281 
    282     def OnGlobalMouseDownCallback(self, uiObject, *args, **kwds):
    283         if self.destroyed:
    284             return False
    285         if uiObject is not self and self.historyMenu:
    286             historyMenu = self.historyMenu()
    287             if historyMenu and not historyMenu.destroyed:
    288                 if not uiObject.IsUnder(historyMenu):
    289                     self.CloseHistoryMenu()
    290         return True
    291 
    292     def AutoFitToText(self, text = None, minWidth = None):
    293         if self.align in (uiconst.TOTOP, uiconst.TOBOTTOM, uiconst.TOALL):
    294             raise RuntimeError('Incorrect alignment for SingleLine.AutoFitToText')
    295         if text is not None:
    296             textwidth, textheight = self.textLabel.MeasureTextSize(text)
    297             autoWidth = textwidth + self.textLeftMargin * 2 + 2
    298         else:
    299             autoWidth = self.textLabel.textwidth + self.textLeftMargin * 2 + 2
    300         if minWidth:
    301             autoWidth = max(minWidth, autoWidth)
    302         self.width = autoWidth
    303         self.textLabel.left = self.textLeftMargin
    304 
    305     def CloseHistoryMenu(self):
    306         if self.historyMenu:
    307             historyMenu = self.historyMenu()
    308             if historyMenu and not historyMenu.destroyed:
    309                 self.active = None
    310                 historyMenu.Close()
    311                 self.historyMenu = None
    312 
    313     def GetValid(self):
    314         current = self.GetValue(registerHistory=False)
    315         id, mine = self.GetHistory()
    316         valid = [ HistoryData(each, each) for each in mine if each.lower().startswith(unicode(current).lower()) and each != current ]
    317         valid.sort(key=lambda x: len(x.displayText))
    318         return valid
    319 
    320     def ClearHistory(self, *args):
    321         id, mine, all = self.GetHistory(getAll=True)
    322         if id in all:
    323             del all[id]
    324             settings.user.ui.Set('editHistory', all)
    325 
    326     def RegisterHistory(self, value = None):
    327         if not self.registerHistory:
    328             return
    329         id, mine, all = self.GetHistory(getAll=True)
    330         current = (value or self.text).rstrip()
    331         if current not in mine:
    332             mine.append(current)
    333         all[id] = mine
    334         settings.user.ui.Set('editHistory', all)
    335 
    336     def AddIconButton(self, texturePath, hint = None):
    337         rightAlignedButton = self._ConstructIconButton(hint, texturePath)
    338         self.rightAlignedButtons.add(rightAlignedButton)
    339         return rightAlignedButton
    340 
    341     def _ConstructIconButton(self, hint, texturePath):
    342         return ButtonIcon(texturePath=texturePath, pos=(0, 0, 16, 16), align=uiconst.CENTERRIGHT, parent=self, hint=hint, idx=0)
    343 
    344     def OnChar(self, char, flag):
    345         if self.OnAnyChar(char):
    346             fontFamily = uicore.font.GetFontFamilyBasedOnClientLanguageID()
    347             if fontFamily != self.textLabel.fontFamily:
    348                 self.textLabel.fontFamily = fontFamily
    349                 self.hintLabel.fontFamily = fontFamily
    350             if char in [127, uiconst.VK_BACK]:
    351                 if self.GetSelectionBounds() != (None, None):
    352                     self.DeleteSelected()
    353                 else:
    354                     self.Delete(direction=False)
    355                 self.CheckHistory()
    356                 if self.OnInsert:
    357                     self.OnInsert(char, flag)
    358                 return True
    359             if char != uiconst.VK_RETURN:
    360                 self.Insert(char)
    361                 self.CheckHistory()
    362                 if self.OnInsert:
    363                     self.OnInsert(char, flag)
    364                 return True
    365         return False
    366 
    367     def Confirm(self, *args):
    368         if self.OnReturn:
    369             self.CloseHistoryMenu()
    370             if self.sendSelfAsArgument:
    371                 return uthread.new(self.OnReturn, self)
    372             else:
    373                 return uthread.new(self.OnReturn)
    374         searchFrom = GetWindowAbove(self)
    375         if searchFrom:
    376             wnds = [ w for w in searchFrom.Find('trinity.Tr2Sprite2dContainer') + searchFrom.Find('trinity.Tr2Sprite2d') if getattr(w, 'btn_default', 0) == 1 ]
    377             if len(wnds):
    378                 for wnd in wnds:
    379                     if self == wnd:
    380                         continue
    381                     if wnd.IsVisible():
    382                         if hasattr(wnd, 'OnClick'):
    383                             uthread.new(wnd.OnClick, wnd)
    384                         return True
    385 
    386         return False
    387 
    388     def OnKeyDown(self, vkey, flag):
    389         isMac = sys.platform.startswith('darwin')
    390 
    391         def k(win, mac):
    392             if isMac:
    393                 return mac
    394             return win
    395 
    396         HOME = uiconst.VK_HOME
    397         END = uiconst.VK_END
    398         CTRL = uicore.uilib.Key(uiconst.VK_CONTROL)
    399         ALT = uicore.uilib.Key(uiconst.VK_MENU)
    400         CMD = uicore.uilib.Key(uiconst.VK_LWIN)
    401         SHIFT = uicore.uilib.Key(uiconst.VK_SHIFT)
    402         if self.destroyed:
    403             return
    404         oldCaretIndex = self.caretIndex
    405         selection = self.GetSelectionBounds()
    406         index = oldCaretIndex[0]
    407         if SHIFT and vkey == uiconst.VK_DELETE:
    408             wasDeleted = self.TryDeleteFromHistory()
    409             if wasDeleted:
    410                 return
    411         if vkey == uiconst.VK_LEFT and (not isMac or not CMD):
    412             if k(win=CTRL, mac=ALT):
    413                 index = self.text.rfind(' ', 0, max(index - 1, 0)) + 1 or 0
    414             else:
    415                 index = self.MoveIndexToLeft(index)
    416         elif vkey == uiconst.VK_RIGHT and (not isMac or not CMD):
    417             if k(win=CTRL, mac=ALT):
    418                 index = self.text.find(' ', index) + 1 or len(self.textLabel.text)
    419             else:
    420                 index = self.MoveIndexToRight(index)
    421             index = min(index, len(self.textLabel.text))
    422         elif vkey == HOME or isMac and vkey == uiconst.VK_LEFT and CMD:
    423             index = 0
    424         elif vkey == END or isMac and vkey == uiconst.VK_RIGHT and CMD:
    425             index = len(self.textLabel.text)
    426         elif vkey == uiconst.VK_DELETE:
    427             if self.GetSelectionBounds() != (None, None):
    428                 self.DeleteSelected()
    429                 return
    430             else:
    431                 self.Delete(direction=True)
    432                 return
    433         else:
    434             if vkey == uiconst.VK_UP:
    435                 self.OnUpKeyPressed()
    436             elif vkey == uiconst.VK_DOWN:
    437                 self.OnDownKeyPressed()
    438             else:
    439                 self.OnUnusedKeyDown(self, vkey, flag)
    440             return
    441         self.caretIndex = self.GetCursorFromIndex(index)
    442         if vkey in (uiconst.VK_LEFT,
    443          uiconst.VK_RIGHT,
    444          HOME,
    445          END):
    446             if SHIFT:
    447                 if self.selTo is not None:
    448                     self.selTo = self.caretIndex
    449                 elif self.selTo is None:
    450                     self.selFrom = oldCaretIndex
    451                     self.selTo = self.caretIndex
    452             elif selection != (None, None):
    453                 if vkey == uiconst.VK_LEFT:
    454                     index = selection[0][0]
    455                 elif vkey == uiconst.VK_RIGHT:
    456                     index = selection[1][0]
    457                 self.caretIndex = self.GetCursorFromIndex(index)
    458             if not SHIFT or self.selFrom == self.selTo:
    459                 self.selFrom = self.selTo = None
    460             self.CloseHistoryMenu()
    461         self.RefreshCaretPosition()
    462         self.RefreshSelectionDisplay()
    463         self.RefreshTextClipper()
    464 
    465     def TryDeleteFromHistory(self):
    466         if not self.historyMenu:
    467             return False
    468         historyMenu = self.historyMenu()
    469         if not historyMenu:
    470             return False
    471         selectedEntry = historyMenu.GetSelectedEntry()
    472         return self.DeleteEntryFromHistory(selectedEntry)
    473 
    474     def DeleteEntryFromHistory(self, selectedEntry):
    475         historyMenu = self.historyMenu()
    476         if not historyMenu:
    477             return False
    478         if not selectedEntry:
    479             return False
    480         currentText = historyMenu.GetTextEntered()
    481         return self.DeleteFromHistory(currentText, selectedEntry.string)
    482 
    483     def OnDownKeyPressed(self):
    484         self.BrowseHistory(down=True)
    485 
    486     def OnUpKeyPressed(self):
    487         self.BrowseHistory(down=False)
    488 
    489     def OnUnusedKeyDown(self, *args):
    490         pass
    491 
    492     def MoveIndexToRight(self, index):
    493         index += 1
    494         return index
    495 
    496     def MoveIndexToLeft(self, index):
    497         index = max(index - 1, 0)
    498         return index
    499 
    500     def _GetSizeForHistoryMenu(self):
    501         return self.GetAbsolute()
    502 
    503     def OnSetFocus(self, *args):
    504         if self.pickState != uiconst.TR2_SPS_ON:
    505             return
    506         if not self.readonly and uicore.imeHandler:
    507             uicore.imeHandler.SetFocus(self)
    508         if self and not self.destroyed and self.parent and self.parent.name == 'inlines':
    509             if self.parent.parent and getattr(self.parent.parent.sr, 'node', None):
    510                 browser = GetBrowser(self)
    511                 if browser:
    512                     uthread.new(browser.ShowObject, self)
    513         self._OnSetFocus()
    514         self.ShowCaret()
    515         self.CheckHintText()
    516         if self.autoselect:
    517             self.SelectAll()
    518         else:
    519             self.RefreshSelectionDisplay()
    520         if hasattr(self, '__OnSetFocus') and self.__OnSetFocus:
    521             self.__OnSetFocus(*args)
    522 
    523     def _OnSetFocus(self):
    524         pass
    525 
    526     def Cut(self, *args):
    527         if self.GetSelectionBounds() != (None, None):
    528             self.Copy()
    529             self.DeleteSelected()
    530 
    531     def Copy(self, selectStart = None, selectEnd = None):
    532         if selectStart is not None and selectEnd is not None:
    533             blue.pyos.SetClipboardData(self.text[selectStart:selectEnd])
    534         else:
    535             start, end = self.GetSelectionBounds()
    536             if not start and not end:
    537                 blue.pyos.SetClipboardData(self.text)
    538             else:
    539                 blue.pyos.SetClipboardData(self.text[start[0]:end[0]])
    540 
    541     def Paste(self, paste, deleteStart = None, deleteEnd = None, forceFocus = False):
    542         if deleteStart is None or deleteEnd is None:
    543             start, end = self.GetSelectionBounds()
    544             if start is not None and end is not None:
    545                 self.DeleteSelected()
    546         else:
    547             text = self.text
    548             self.SetText(text[:deleteStart] + text[deleteEnd:])
    549             self.caretIndex = self.GetCursorFromIndex(deleteStart)
    550             self.OnTextChange()
    551         self.Insert(paste)
    552         hadFocus = uicore.registry.GetFocus() is self
    553         if (hadFocus or forceFocus) and not uicore.registry.GetFocus() == self:
    554             uicore.registry.SetFocus(self)
    555 
    556     def SelectAll(self):
    557         self.selFrom = self.GetCursorFromIndex(0)
    558         self.selTo = self.GetCursorFromIndex(-1)
    559         self.RefreshSelectionDisplay()
    560 
    561     def ShowCaret(self):
    562         self.ConstructCaret()
    563         self.RefreshCaretPosition()
    564         fontSize = check_convert_font_size(self.fontsize)
    565         self.caret.height = fontSize + 4
    566         self.caret.state = uiconst.UI_DISABLED
    567         self.caretTimer = AutoTimer(interval=uiconst.CARET_BLINK_INTERVAL_MS, method=self.BlinkCaret)
    568         self.caret.SetRGBA(*self.CaretColor)
    569 
    570     def HideCaret(self):
    571         self.caretTimer = None
    572         if self.caret:
    573             self.caret.state = uiconst.UI_HIDDEN
    574 
    575     def BlinkCaret(self):
    576         if self.destroyed:
    577             self.caretTimer = None
    578             return
    579         if self.caret:
    580             if not trinity.app.IsActive():
    581                 self.caret.state = uiconst.UI_HIDDEN
    582                 return
    583             self.caret.state = [uiconst.UI_HIDDEN, uiconst.UI_DISABLED][self.caret.state == uiconst.UI_HIDDEN]
    584 
    585     def SelectNone(self):
    586         self.selFrom = (None, None)
    587         self.selTo = (None, None)
    588         self.RefreshSelectionDisplay()
    589 
    590     def OnAnyChar(self, char, *args):
    591         return True
    592 
    593     def OnKillFocus(self, *args):
    594         if not self.readonly and uicore.imeHandler:
    595             uicore.imeHandler.KillFocus(self)
    596         if self.autoselect:
    597             self.SelectNone()
    598         self.HideCaret()
    599         self.CheckHintText()
    600         self.CloseHistoryMenu()
    601         self.ClearSelection()
    602         if self.OnFocusLost:
    603             uthread.new(self.OnFocusLost, self)
    604 
    605     def Insert(self, text):
    606         if self.readonly or text is None:
    607             return
    608         if not isinstance(text, basestring):
    609             text = unichr(text)
    610         text = text.replace(u'\r', u' ').replace(u'\n', u'')
    611         if self.GetSelectionBounds() != (None, None):
    612             self.DeleteSelected()
    613         caretIndex = self.caretIndex[0] if self.caretIndex else 0
    614         before = self.text[:caretIndex]
    615         after = self.text[caretIndex:]
    616         become = before + text + after
    617         become = self._ValidateInsert(become)
    618         self.autoselect = False
    619         self.SetText(become)
    620         if become != before:
    621             newCaretIndex = caretIndex + max(len(text), 1)
    622             self.caretIndex = self.GetCursorFromIndex(newCaretIndex)
    623         self.OnTextChange()
    624 
    625     def _ValidateInsert(self, insert):
    626         return insert
    627 
    628     def ShowHistoryMenu(self, history):
    629         hadMenu = 0
    630         if self.historyMenu and self.historyMenu():
    631             hadMenu = 1
    632         self.CloseHistoryMenu()
    633         if not history:
    634             return
    635         currentText = self.GetValue(registerHistory=False)
    636         l, t, w, h = self._GetSizeForHistoryMenu()
    637         mp = SingleLineEditHistory(parent=uicore.layer.menu, pos=(l,
    638          t + h + 2,
    639          w,
    640          0), dynamicHistoryWidth=self.dynamicHistoryWidth, mouseDownFunc=self.HEMouseDown, mouseUpFunc=self.HEMouseUp, currentText=currentText, deleteHistoryEntryFunc=self.DeleteEntryFromHistory)
    641         if not hadMenu:
    642             mp.opacity = 0.0
    643         self.PopulateHistoryMenu(mp, history)
    644         self.historyMenu = weakref.ref(mp)
    645         if not hadMenu:
    646             animations.FadeIn(mp, duration=0.25)
    647 
    648     def OnDblClick(self, *args):
    649         self.caretIndex = self.GetIndexUnderCursor()
    650         self.selFrom = self.GetCursorFromIndex(0)
    651         self.selTo = self.caretIndex = self.GetCursorFromIndex(-1)
    652         self.RefreshCaretPosition()
    653         self.RefreshSelectionDisplay()
    654         self.RefreshTextClipper()
    655 
    656     def GetIndexUnderCursor(self):
    657         l, t = self.textLabel.GetAbsolutePosition()
    658         cursorXpos = uicore.uilib.x - l
    659         return self.textLabel.GetIndexUnderPos(cursorXpos)
    660 
    661     def PopulateHistoryMenu(self, menuParent, history):
    662         historyFormatted = []
    663         for historyEntry in history:
    664             removeable = True
    665             if isinstance(historyEntry, tuple):
    666                 displayText = historyEntry[0]
    667                 editText = historyEntry[1]
    668             elif isinstance(historyEntry, HistoryData):
    669                 displayText = historyEntry.displayText
    670                 editText = historyEntry.editText
    671                 removeable = historyEntry.removeable
    672             else:
    673                 displayText = editText = historyEntry
    674             b = Bundle(displayText=displayText, editText=editText, info=None, historyEntry=historyEntry, removeable=removeable)
    675             historyFormatted.append(b)
    676 
    677         menuParent.PopulateHistoryMenu(historyFormatted)
    678 
    679     def BrowseHistory(self, down):
    680         justopened = 0
    681         if not (self.historyMenu and self.historyMenu()):
    682             if not self.CheckHistory():
    683                 return
    684             justopened = 1
    685         hm = self.historyMenu()
    686         currentIdx = None
    687         i = 0
    688         for entry in hm.sr.entries.children:
    689             if entry.selected:
    690                 currentIdx = i
    691             entry.sr.hilite.state = uiconst.UI_HIDDEN
    692             entry.selected = 0
    693             i += 1
    694 
    695         if justopened:
    696             return
    697         if currentIdx is None:
    698             if down:
    699                 currentIdx = 0
    700             else:
    701                 currentIdx = len(hm.sr.entries.children) - 1
    702         elif down:
    703             currentIdx += 1
    704             if currentIdx >= len(hm.sr.entries.children):
    705                 currentIdx = 0
    706         else:
    707             currentIdx -= 1
    708             if currentIdx < 0:
    709                 currentIdx = len(hm.sr.entries.children) - 1
    710         self.active = active = hm.sr.entries.children[currentIdx]
    711         active.sr.hilite.state = uiconst.UI_DISABLED
    712         active.selected = 1
    713         if not getattr(self, 'blockSetValue', 0):
    714             self.SetValue(active.string)
    715 
    716     def HEMouseDown(self, entry, mouseButton, *args):
    717         if mouseButton == uiconst.MOUSELEFT:
    718             self.SetValue(entry.string)
    719             self.OnHistoryClick(entry.string)
    720 
    721     def HEMouseUp(self, entry, mouseButton, *args):
    722         if mouseButton == uiconst.MOUSELEFT:
    723             self.CloseHistoryMenu()
    724 
    725     def OnHistoryClick(self, clickedString, *args):
    726         pass
    727 
    728     def OnMouseUp(self, *args):
    729         self.mouseDownCaretIndex = None
    730         self.selectionTimer = None
    731 
    732     def OnMouseDown(self, button, *etc):
    733         if uicore.uilib.mouseTravel > 10:
    734             return
    735         gettingFocus = uicore.registry.GetFocus() != self
    736         if gettingFocus:
    737             uicore.registry.SetFocus(self)
    738         leftClick = button == uiconst.MOUSELEFT
    739         if uicore.uilib.Key(uiconst.VK_SHIFT):
    740             if self.selFrom is None:
    741                 self.selFrom = self.caretIndex
    742             self.selTo = self.caretIndex = self.GetIndexUnderCursor()
    743             self.RefreshCaretPosition()
    744             self.RefreshSelectionDisplay()
    745             self.RefreshTextClipper()
    746         elif leftClick:
    747             self.caretIndex = self.mouseDownCaretIndex = self.GetIndexUnderCursor()
    748             self.selFrom = None
    749             self.selTo = None
    750             self.RefreshCaretPosition()
    751             self.RefreshSelectionDisplay()
    752             self.RefreshTextClipper()
    753             if self.autoselect and gettingFocus:
    754                 self.SelectAll()
    755             else:
    756                 self.selectionTimer = AutoTimer(50, self.UpdateSelection)
    757 
    758     def UpdateSelection(self):
    759         oldCaretIndex = self.mouseDownCaretIndex
    760         newCaretIndex = self.GetIndexUnderCursor()
    761         self.selFrom = oldCaretIndex
    762         self.selTo = newCaretIndex
    763         self.caretIndex = newCaretIndex
    764         self.RefreshCaretPosition()
    765         self.RefreshSelectionDisplay()
    766         self.RefreshTextClipper()
    767 
    768     def CheckHistory(self):
    769         if not self.displayHistory:
    770             return
    771         if self.readonly:
    772             return
    773         validHistoryEntries = self.GetValid()
    774         if validHistoryEntries:
    775             self.ShowHistoryMenu(validHistoryEntries[:5])
    776             return 1
    777         self.CloseHistoryMenu()
    778         return 0
    779 
    780     def GetHistory(self, getAll = False):
    781         historyID = self.GetHistoryID()
    782         editHistory = settings.user.ui.Get('editHistory', {})
    783         suggestions = self.GetSuggestions()
    784         if suggestions is None:
    785             suggestions = editHistory.get(historyID, [])
    786         if getAll:
    787             return (historyID, suggestions, editHistory)
    788         return (historyID, suggestions)
    789 
    790     def GetHistoryID(self):
    791         id = ''
    792         item = self
    793         while item.parent:
    794             id = '/' + item.name + id
    795             if isinstance(item, Window):
    796                 break
    797             item = item.parent
    798 
    799         return id
    800 
    801     def GetSuggestions(self):
    802         return None
    803 
    804     def DeleteFromHistory(self, currentText, historyEntry):
    805         _, history = self.GetHistory()
    806         if historyEntry in history:
    807             history.remove(historyEntry)
    808             self.CloseHistoryMenu()
    809             if not getattr(self, 'blockSetValue', 0):
    810                 self.SetValue(currentText)
    811             self.CheckHistory()
    812             return True
    813         return False
    814 
    815     def SetReadOnly(self, state):
    816         self.readonly = state
    817 
    818     def Delete(self, direction = True):
    819         if self.readonly or self.text is None:
    820             return
    821         if not self.caretIndex:
    822             logger.exception('BaseSingleLineEdit::Delete failed, caretIndex is None')
    823             return
    824         caretIndex = self.caretIndex[0] if self.caretIndex else 0
    825         if direction:
    826             begin = caretIndex
    827             end = min(caretIndex + 1, len(self.textLabel.text))
    828         else:
    829             begin = max(caretIndex - 1, 0)
    830             end = caretIndex
    831         newText = self.text[:begin] + self.text[end:]
    832         self.SetText(newText)
    833         newCaretIndex = begin
    834         self.caretIndex = self.GetCursorFromIndex(newCaretIndex)
    835         self.OnTextChange()
    836 
    837     def DeleteSelected(self, inserting = False):
    838         if self.readonly:
    839             return
    840         start, end = self.GetSelectionBounds()
    841         self.ClearSelection()
    842         text = self.text
    843         newText = text[:start[0]] + text[end[0]:]
    844         self.SetText(newText)
    845         self.caretIndex = self.GetCursorFromIndex(start[0])
    846         self.OnTextChange()
    847 
    848     def OnClearButtonClick(self):
    849         self.Clear()
    850 
    851     def OnClear(self):
    852         pass
    853 
    854     def SetValue(self, text, docallback = True):
    855         self.draggedValue = None
    856         if text is None:
    857             return
    858         text = self.SanitizeText(text)
    859         self.SetText(text)
    860         self.SendCaretToEnd()
    861         self.ClearSelection()
    862         self.OnTextChange(docallback)
    863 
    864     def Clear(self, docallback = True):
    865         self.SetText('')
    866         self.SendCaretToEnd()
    867         self.ClearSelection()
    868         self.OnTextChange(docallback)
    869         self.OnClear()
    870 
    871     def SanitizeText(self, text):
    872         isString = isinstance(text, basestring)
    873         if isString:
    874             text = StripTags(text, stripOnly=['localized'])
    875         return text
    876 
    877     def ClearSelection(self):
    878         self.selFrom = self.selTo = None
    879         self.RefreshSelectionDisplay()
    880 
    881     def GetCursorFromIndex(self, index):
    882         return self.textLabel.GetWidthToIndex(index)
    883 
    884     def SendCaretToEnd(self):
    885         self.caretIndex = self.GetCursorFromIndex(-1)
    886 
    887     def SetText(self, text):
    888         if not isinstance(text, basestring):
    889             text = str(text)
    890         text = StripTags(text, stripOnly=['localized'])
    891         self.SetDisplayText(text.replace('<', '&lt;').replace('>', '&gt;'))
    892         self.text = text
    893         self.CheckHintText()
    894 
    895     def SetDisplayText(self, text):
    896         self.textLabel.SetText(text)
    897 
    898     def OnTextChange(self, docallback = True):
    899         self.CheckHintText()
    900         self.RefreshCaretPosition()
    901         self.RefreshTextClipper()
    902         if docallback and self.OnChange:
    903             self.OnChange(self.GetText())
    904         RefreshTooltipForOwner(self)
    905 
    906     def CheckHintText(self):
    907         if self.text:
    908             self.hintLabel.display = False
    909         elif uicore.registry.GetFocus() is self:
    910             self.hintLabel.color = TextColor.DISABLED
    911             self.hintLabel.display = True
    912         else:
    913             self.hintLabel.color = TextColor.SECONDARY
    914             self.hintLabel.display = True
    915         self.hintLabel.SetText(self.hintText)
    916 
    917     def GetText(self):
    918         return self.text
    919 
    920     def GetValue(self, registerHistory = True):
    921         if registerHistory:
    922             self.RegisterHistory()
    923         return self.text
    924 
    925     def GetMenu(self):
    926         m = []
    927         start, end = self.GetSelectionBounds()
    928         if start is not None:
    929             start = start[0]
    930         if end is not None:
    931             end = end[0]
    932         m += [(MenuLabel('/Carbon/UI/Controls/Common/Copy'), self.Copy, (start, end))]
    933         if not self.readonly:
    934             paste = GetClipboardData()
    935             if paste:
    936                 m += [(MenuLabel('/Carbon/UI/Controls/Common/Paste'), self.Paste, (paste,
    937                    start,
    938                    end,
    939                    True))]
    940         return m
    941 
    942     def OnDropData(self, dragObj, nodes):
    943         if self.isTypeField:
    944             self.OnDropType(dragObj, nodes)
    945         elif self.isLocationField:
    946             self.OnDropLocation(dragObj, nodes)
    947         elif self.isCharCorpOrAllianceField:
    948             self.OndDropCharCorpOrAlliance(dragObj, nodes)
    949         elif self.isCharacterField:
    950             self.OnDropCharacter(dragObj, nodes)
    951         else:
    952             super(BaseSingleLineEdit, self).OnDropData(dragObj, nodes)
    953 
    954     def OnDropType(self, dragObj, nodes):
    955         node = nodes[0]
    956         guid = getattr(node, '__guid__', None)
    957         if guid in ('xtriui.ShipUIModule', 'xtriui.InvItem', 'listentry.InvItem', 'listentry.InvAssetItem'):
    958             typeID = getattr(node.item, 'typeID', None)
    959         elif guid in ('listentry.GenericMarketItem', 'listentry.QuickbarItem', 'listentry.Item'):
    960             typeID = getattr(node, 'typeID', None)
    961         else:
    962             typeID = GetTypeIDFromDragItem(node)
    963         if typeID and evetypes.IsPublished(typeID):
    964             typeName = evetypes.GetName(typeID)
    965             self.SetValueAfterDragging(typeName, draggedValue=typeID)
    966 
    967     def OnDropLocation(self, dragObj, nodes):
    968         node = nodes[0]
    969         guid = node.Get('__guid__', None)
    970         locationItemID = None
    971         itemID = GetItemIDFromTextLink(node, None)
    972         if self._IsLocation(itemID):
    973             locationItemID = itemID
    974         elif guid in ('xtriui.ListSurroundingsBtn', 'listentry.LocationTextEntry', 'listentry.LabelLocationTextTop', 'listentry.LocationGroup', 'listentry.LocationSearchItem'):
    975             if self._IsLocation(node.itemID):
    976                 locationItemID = node.itemID
    977         if locationItemID:
    978             self.SetValueAfterDragging(cfg.evelocations.Get(locationItemID).name, locationItemID)
    979 
    980     def _IsLocation(self, itemID):
    981         if not itemID:
    982             return False
    983         try:
    984             cfg.evelocations.Get(itemID)
    985             return True
    986         except KeyError:
    987             return False
    988 
    989     def OnDropCharacter(self, dragObj, nodes):
    990         charInfo = GetDroppedCharInfo(nodes[0])
    991         if charInfo is not None:
    992             self.SetValueAfterDragging(charInfo.charName, charInfo.charID)
    993 
    994     def OndDropCharCorpOrAlliance(self, dragObj, nodes):
    995         itemInfo = GetDroppedCharCorpOrAllianceName(nodes[0])
    996         if itemInfo is not None:
    997             self.SetValueAfterDragging(itemInfo.itemName, itemInfo.itemID)
    998 
    999     def SetValueAfterDragging(self, name, draggedValue):
   1000         self.SetValue(name)
   1001         self.draggedValue = draggedValue
   1002 
   1003     def LoadTooltipPanel(self, tooltipPanel, *args):
   1004         normalHint = self.hint
   1005         if self.inputType:
   1006             return LoadTooltipForNumber(tooltipPanel, normalHint, self.text, self.inputType)
   1007 
   1008     def Disable(self):
   1009         super(BaseSingleLineEdit, self).Disable()
   1010         self.opacity = 0.3
   1011 
   1012     def Enable(self):
   1013         super(BaseSingleLineEdit, self).Enable()
   1014         self.opacity = 1.0
   1015 
   1016     def SetMaxLength(self, newMaxLength):
   1017         pass
   1018 
   1019     def LoadCombo(self, id, options, callback = None, setvalue = None, comboIsTabStop = True):
   1020         for each in self.children[:]:
   1021             if each.name == 'combo':
   1022                 each.Close()
   1023 
   1024         combo = Combo(parent=self, label='', options=options, name=id, select=setvalue, callback=self.OnComboChange, pos=(0, 0, 16, 16), align=uiconst.BOTTOMRIGHT)
   1025         combo.sr.inputCallback = callback
   1026         combo.isTabStop = comboIsTabStop
   1027         combo.name = 'combo'
   1028         combo.Confirm = self.ComboConfirm
   1029         combo.Hide()
   1030         self.sr.combo = combo
   1031         comboButton = self.AddIconButton('res:/UI/Texture/Icons/38_16_229.png')
   1032         comboButton.name = 'combo'
   1033         comboButton.OnMouseDown = (self.ExpandCombo, combo)
   1034 
   1035     def ExpandCombo(self, combo, *args, **kwds):
   1036         if not combo._Expanded():
   1037             uthread.new(combo.Expand, self.GetAbsolute())
   1038 
   1039     def ComboConfirm(self, *args, **kwargs):
   1040         if self.sr.combo and not self.sr.combo.destroyed:
   1041             self.OnComboChange(self.sr.combo, self.sr.combo.GetKey(), self.sr.combo.GetValue())
   1042         self.sr.combo.Cleanup(setfocus=False)
   1043 
   1044     def GetComboValue(self):
   1045         if self.sr.combo:
   1046             return self.sr.combo.GetValue()
   1047 
   1048     def OnComboChange(self, combo, label, value, *args):
   1049         self.SetValue(label)
   1050         if combo.sr.inputCallback:
   1051             combo.sr.inputCallback(combo, label, value)
   1052 
   1053     def Close(self):
   1054         self.CloseHistoryMenu()
   1055         super(BaseSingleLineEdit, self).Close()
   1056 
   1057     def get_absolute_caret_position(self):
   1058         y = self.absoluteTop + 2
   1059         x = self.absoluteLeft + self.caretIndex[1] - 1 + self.textLabel.left
   1060         return (x, y)