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

form.py (19676B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\util\form.py
      2 import log
      3 import types
      4 import carbonui.const as uiconst
      5 import localization
      6 from carbon.common.script.sys.service import Service
      7 from carbonui.control.button import Button
      8 from carbonui.control.combo import Combo
      9 from carbonui.control.singlelineedits.singleLineEditFloat import SingleLineEditFloat
     10 from carbonui.control.singlelineedits.singleLineEditInteger import SingleLineEditInteger
     11 from carbonui.control.singlelineedits.singleLineEditPassword import SingleLineEditPassword
     12 from carbonui.control.singlelineedits.singleLineEditText import SingleLineEditText
     13 from carbonui.primitives.container import Container
     14 from carbonui.primitives.line import Line
     15 from eve.client.script.ui.control import eveLabel
     16 from carbonui.button.group import ButtonGroup, ButtonSizeMode
     17 from carbonui import AxisAlignment
     18 from carbonui.control.checkbox import Checkbox
     19 from carbonui.control.radioButton import RadioButton
     20 from eve.client.script.ui.control.eveEditPlainText import EditPlainText
     21 from carbonui.uicore import uicore
     22 from carbonui.control.tabGroup import TabGroup
     23 from eve.common.lib import appConst as const
     24 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     25 
     26 class Form(Service):
     27     __guid__ = 'svc.form'
     28     __exportedcalls__ = {'GetForm': [],
     29      'ProcessForm': []}
     30     __servicename__ = 'form'
     31     __displayname__ = 'Form Service'
     32     __dependencies__ = []
     33 
     34     def __init__(self):
     35         Service.__init__(self)
     36 
     37     def GetForm(self, format, parent):
     38         _form, retfields, reqresult, panels, errorcheck, refresh = self._GetForm(format, parent)
     39         if _form.align == uiconst.TOALL:
     40             _form.SetSize(0, 0)
     41             _form.SetPosition(0, 0)
     42             _form.padding = const.defaultPadding
     43         elif _form.align in (uiconst.TOTOP, uiconst.TOBOTTOM):
     44             _form.SetPosition(0, 0)
     45             _form.width = 0
     46             _form.padding = const.defaultPadding
     47         elif _form.align in (uiconst.TOLEFT, uiconst.TORIGHT):
     48             _form.SetPosition(0, 0)
     49             _form.height = 0
     50             _form.padding = const.defaultPadding
     51         else:
     52             _form.left = _form.top = const.defaultPadding
     53         return (_form,
     54          retfields,
     55          reqresult,
     56          panels,
     57          errorcheck,
     58          refresh)
     59 
     60     def _GetForm(self, format, parent, retfields = [], reqresult = [], errorcheck = None, tabpanels = [], tabgroup = [], refresh = [], wipe = 1):
     61         if not parent.IsUnder(uicore.desktop):
     62             log.LogTraceback('Form parent MUST be hooked on the desktop; it is impossible to know the real dimensions of stuff within otherwise.')
     63         self.retfields = retfields
     64         self.reqresult = reqresult
     65         self.errorcheck = errorcheck
     66         self.tabpanels = tabpanels
     67         self.tabgroup = tabgroup
     68         self.refresh = refresh
     69         if not isinstance(parent, FormWnd):
     70             log.LogTraceback('Incompatible formparent, please change it to xtriui.FormWnd')
     71         self.parent = parent
     72         self.parent.sr.panels = {}
     73         self.parent.sr.focus = None
     74         if wipe:
     75             self.retfields = []
     76             self.reqresult = []
     77             self.tabpanels = []
     78             self.tabgroup = []
     79             self.refresh = []
     80         for each in format:
     81             self.type = each
     82             typeName = self.type['type']
     83             self.leftPush = self.type.get('labelwidth', 0) or 80
     84             self.code = None
     85             if typeName == 'errorcheck':
     86                 self.AddErrorcheck()
     87                 continue
     88             elif typeName == 'data':
     89                 self.AddData()
     90                 continue
     91             elif typeName == 'tab':
     92                 self.AddTab()
     93                 continue
     94             elif typeName in ('btline', 'bbline'):
     95                 self.AddLine()
     96                 continue
     97             elif typeName == 'push':
     98                 self.AddPush()
     99             elif typeName == 'header':
    100                 self.AddHeader()
    101             elif typeName == 'labeltext':
    102                 self.AddLabeltext()
    103             elif typeName == 'text':
    104                 self.AddText()
    105             elif typeName == 'edit':
    106                 self.AddEdit()
    107             elif typeName == 'textedit':
    108                 self.AddTextedit()
    109             elif typeName == 'checkbox':
    110                 self.AddCheckbox()
    111             elif typeName == 'combo':
    112                 self.AddCombo()
    113             elif typeName == 'btnonly':
    114                 self.AddBtnonly()
    115             else:
    116                 log.LogWarn('Unknown fieldtype in form generator')
    117                 continue
    118             if 'key' in self.type:
    119                 if self.code:
    120                     self.retfields.append([self.code, self.type])
    121                     self.parent.sr.Set(self.type['key'], self.code)
    122                 else:
    123                     self.parent.sr.Set(self.type['key'], self.new)
    124             if self.type.get('required', 0) == 1:
    125                 self.reqresult.append([self.code, self.type])
    126             if self.type.get('selectall', 0) == 1 and getattr(self.code, 'SelectAll', None):
    127                 self.code.SelectAll()
    128             if self.type.get('setfocus', 0) == 1:
    129                 self.parent.sr.focus = self.code
    130             if 'stopconfirm' in self.type and hasattr(self.code, 'stopconfirm'):
    131                 self.code.stopconfirm = self.type['stopconfirm']
    132             if self.type.get('frame', 0) == 1:
    133                 idx = 0
    134                 for child in self.new.children:
    135                     if child.name.startswith('Line'):
    136                         idx += 1
    137 
    138                 Container(name='leftpush', parent=self.new, align=uiconst.TOLEFT, width=6, idx=idx)
    139                 Container(name='rightpush', parent=self.new, align=uiconst.TORIGHT, width=6, idx=idx)
    140                 Line(parent=self.new, align=uiconst.TOLEFT, idx=idx)
    141                 Line(parent=self.new, align=uiconst.TORIGHT, idx=idx)
    142 
    143         if wipe and len(self.tabgroup):
    144             tabs = TabGroup(name='tabparent', parent=self.parent, idx=0)
    145             tabs.Startup(self.tabgroup, 'hybrid')
    146             maxheight = 0
    147             for panel in self.tabpanels:
    148                 maxheight = max(maxheight, panel.height)
    149 
    150             self.parent.height = maxheight + tabs.height
    151         else:
    152             if len(self.tabpanels):
    153                 for each in self.tabpanels:
    154                     each.state = uiconst.UI_HIDDEN
    155 
    156                 self.tabpanels[0].state = uiconst.UI_PICKCHILDREN
    157             self.RefreshHeight(self.parent)
    158         uicore.registry.SetFocus(self)
    159         return (self.parent,
    160          self.retfields,
    161          self.reqresult,
    162          self.tabpanels,
    163          self.errorcheck,
    164          self.refresh)
    165 
    166     def RefreshHeight(self, w):
    167         w.height = sum([ x.height for x in w.children if x.state != uiconst.UI_HIDDEN and x.align in (uiconst.TOBOTTOM, uiconst.TOTOP) ])
    168 
    169     def AddErrorcheck(self):
    170         self.errorcheck = self.type['errorcheck']
    171 
    172     def AddData(self):
    173         self.retfields.append(self.type['data'])
    174 
    175     def AddTab(self):
    176         _form, _retfield, _required, _tabpanels, _errorcheck, _refresh = self._GetForm(self.type['format'], FormWnd(name='form', align=uiconst.TOTOP, parent=self.parent), self.retfields, self.reqresult, self.errorcheck, self.tabpanels, self.tabgroup, self.refresh, 0)
    177         if 'key' in self.type:
    178             self.parent.sr.panels[self.type['key']] = _form
    179         if self.type.get('panelvisible', 0):
    180             _form.state = uiconst.UI_PICKCHILDREN
    181         else:
    182             _form.state = uiconst.UI_HIDDEN
    183         if 'tabvisible' in self.type:
    184             if self.type['tabvisible'] == 1:
    185                 self.tabgroup.append([self.type['tabtext'],
    186                  _form,
    187                  self,
    188                  None])
    189         else:
    190             self.tabgroup.append([self.type['tabtext'],
    191              _form,
    192              self,
    193              None])
    194 
    195     def AddPush(self):
    196         self.new = Container(name='push', parent=self.parent, align=uiconst.TOTOP, height=self.type.get('height', 6))
    197 
    198     def AddLine(self):
    199         (Container(parent=self.parent, align=uiconst.TOTOP, height=16),)
    200 
    201     def AddHeader(self):
    202         self.new = Container(name='headerField', parent=self.parent, align=uiconst.TOTOP, padding=(0, 8, 0, 0))
    203         header = eveLabel.EveLabelLarge(text=self.type.get('text', ''), parent=self.new, name='header', align=uiconst.TOTOP, state=uiconst.UI_NORMAL)
    204         self.new.height = max(self.type.get('height', 17), header.textheight)
    205         self.refresh.append((self.new, header))
    206 
    207     def AddLabeltext(self):
    208         self.new = Container(name='labeltextField', parent=self.parent, align=uiconst.TOTOP, height=self.type.get('height', 20))
    209         text = eveLabel.EveLabelMedium(name='text', parent=self.new, align=uiconst.TOTOP, padding=(0, 4, 0, 0), state=uiconst.UI_NORMAL, text=self.type.get('text', ''))
    210         label = self.type.get('label', '')
    211         if label and label != '_hide':
    212             pad_top = 4 if self.type.get('text', '') else 0
    213             label = eveLabel.EveLabelSmall(name='label', parent=self.new, align=uiconst.TOTOP, padding=(8,
    214              pad_top,
    215              8,
    216              8), text=label)
    217             self.refresh.append((self.new, text, label))
    218         else:
    219             self.refresh.append((self.new, text))
    220 
    221     def AddText(self):
    222         left = self.type.get('left', 0)
    223         self.new = Container(name='textField', parent=self.parent, align=uiconst.TOTOP, height=self.type.get('height', 20), padding=(left,
    224          0,
    225          0,
    226          0))
    227         fontsize = self.type.get('fontsize', 12)
    228         text = eveLabel.Label(text=self.type.get('text', ''), parent=self.new, align=uiconst.TOTOP, name='text', padding=(0, 3, 0, 3), fontsize=fontsize, maxLines=1 if bool(self.type.get('tabstops', [])) else None, state=uiconst.UI_NORMAL, tabs=self.type.get('tabstops', []))
    229         self.new.height = max(self.new.height, int(text.textheight + 6))
    230         self.refresh.append((self.new, text))
    231 
    232     def AddEdit(self):
    233         self.new = Container(name='editField', parent=self.parent, align=uiconst.TOTOP)
    234         config = 'edit_%s' % self.type['key']
    235         ints = self.type.get('intonly', None)
    236         floats = self.type.get('floatonly', None)
    237         passwordCharacter = self.type.get('passwordChar', None)
    238         decimalPlaces = SingleLineEditFloat.default_decimalPlaces
    239         minValue = maxValue = 0
    240         singleLineEditClass = SingleLineEditText
    241         if ints:
    242             singleLineEditClass = SingleLineEditInteger
    243             minValue, maxValue = ints
    244         elif floats:
    245             singleLineEditClass = SingleLineEditFloat
    246             if len(floats) > 2:
    247                 minValue, maxValue, decimalPlaces = floats
    248             else:
    249                 minValue, maxValue = floats
    250         elif passwordCharacter:
    251             singleLineEditClass = SingleLineEditPassword
    252         self.code = singleLineEditClass(name=config, parent=self.new, setvalue=self.type.get('setvalue', ''), padding=(self.leftPush,
    253          2,
    254          0,
    255          2), align=uiconst.TOTOP, maxLength=self.type.get('maxlength', None) or self.type.get('maxLength', None), readonly=self.type.get('readonly', 0), autoselect=self.type.get('autoselect', 0), isTypeField=self.type.get('isTypeField', False), isCharacterField=self.type.get('isCharacterField', False), isCharCorpOrAllianceField=self.type.get('isCharCorpOrAllianceField', False), passwordCharacter=self.type.get('passwordChar', None), minValue=minValue, maxValue=maxValue, decimalPlaces=decimalPlaces)
    256         self.new.height = self.code.height + self.code.padTop * 4
    257         width = self.type.get('width', None)
    258         if width:
    259             self.code.SetAlign(uiconst.TOLEFT)
    260             self.code.width = width
    261         if 'OnReturn' in self.type:
    262             self.code.data = {'key': self.type['key']}
    263             self.code.OnReturn = self.type['OnReturn']
    264         if 'unusedkeydowncallback' in self.type:
    265             self.code.OnUnusedKeyDown = self.type['unusedkeydowncallback']
    266         if 'onanychar' in self.type:
    267             self.code.OnAnyChar = self.type['onanychar']
    268         label = self.type.get('label', '')
    269         text = self.type.get('text', None)
    270         caption = text or label
    271         if label == '_hide':
    272             self.code.padLeft = 0
    273         elif caption:
    274             l = eveLabel.EveLabelSmall(text=caption, align=uiconst.CENTERLEFT, parent=self.new, name='label', left=7, width=self.leftPush - 6)
    275 
    276     def AddTextedit(self):
    277         self.new = Container(name='texteditField', parent=self.parent, align=uiconst.TOTOP, height=self.type.get('height', 68))
    278         self.code = EditPlainText(setvalue=self.type.get('setvalue', '') or self.type.get('text', ''), parent=self.new, padding=(self.leftPush,
    279          2,
    280          0,
    281          2), readonly=self.type.get('readonly', 0), showattributepanel=self.type.get('showAttribPanel', 0), maxLength=self.type.get('maxlength', None) or self.type.get('maxLength', None))
    282         label = self.type.get('label', '')
    283         if label == '_hide':
    284             self.code.padLeft = 0
    285         elif label:
    286             eveLabel.EveLabelSmall(text=label, parent=self.new, name='label', left=7, width=self.leftPush - 6, top=5)
    287 
    288     def AddCheckbox(self):
    289         self.new = Container(name='checkboxCont', parent=self.parent, align=uiconst.TOTOP, pos=(0, 0, 0, 18))
    290         group = self.type.get('group', None)
    291         if group:
    292             self.code = RadioButton(text=self.type.get('text', ''), parent=self.new, settingsKey=self.type.get('name', 'none'), retval=self.type['key'], checked=self.type.get('setvalue', 0), groupname=group, callback=self.parent.OnCheckboxChange)
    293         else:
    294             self.code = Checkbox(text=self.type.get('text', ''), parent=self.new, settingsKey=self.type.get('name', 'none'), checked=self.type.get('setvalue', 0), callback=self.parent.OnCheckboxChange)
    295         self.code.data = {}
    296         onchange = self.type.get('OnChange', None) or self.type.get('onchange', None)
    297         if onchange:
    298             self.code.SetSettingsKey(self.type['key'])
    299             self.code.data = {'key': self.type['key'],
    300              'callback': onchange}
    301         if 'showpanel' in self.type:
    302             self.code.data['showpanel'] = self.type['showpanel']
    303         if self.code.sr.label:
    304             self.refresh.append((self.code, self.code.sr.label))
    305         if self.type.get('hidden', 0):
    306             self.code.state = uiconst.UI_HIDDEN
    307 
    308     def AddCombo(self):
    309         self.new = Container(name='comboField', parent=self.parent, align=uiconst.TOTOP, height=self.type.get('height', 32))
    310         options = self.type.get('options', [(localization.GetByLabel('UI/Common/None'), None)])
    311         self.code = Combo(label='', parent=self.new, options=options, name=self.type.get('key', 'combo'), select=self.type.get('setvalue', ''), padding=(self.leftPush,
    312          2,
    313          0,
    314          2), align=uiconst.TOTOP, callback=self.type.get('callback', None), labelleft=self.leftPush, prefskey=self.type.get('prefskey', None))
    315         self.new.height = self.code.height + self.code.padTop * 4
    316         width = self.type.get('width', None)
    317         if width:
    318             self.code.SetAlign(uiconst.TOLEFT)
    319             self.code.width = width
    320         label = self.type.get('label', '')
    321         if label == '_hide':
    322             self.code.padLeft = 0
    323         else:
    324             eveLabel.EveLabelSmall(text=label, parent=self.new, name='label', left=7, width=self.leftPush - 6, align=uiconst.CENTERLEFT)
    325 
    326     def AddBtnonly(self):
    327         self.new = Container(name='btnonly', parent=self.parent, align=uiconst.TOTOP, height=self.type.get('height', 20))
    328         align = uiconst.TORIGHT
    329         for wantedbtn in self.type['buttons']:
    330             if 'align' in wantedbtn:
    331                 al = {'left': uiconst.CENTERLEFT,
    332                  'right': uiconst.CENTERRIGHT}
    333                 align = al.get(wantedbtn['align'], uiconst.CENTERRIGHT)
    334 
    335         uniSize = self.type.get('uniSize', True)
    336         if uniSize:
    337             size_mode = ButtonSizeMode.EQUAL
    338         else:
    339             size_mode = ButtonSizeMode.DYNAMIC
    340         ButtonGroup(parent=self.new, align=uiconst.TOTOP, button_size_mode=size_mode, button_alignment=axis_alignment_from_legacy_align(align), buttons=[ Button(label=data['caption'], func=data['function'], args=data.get('args', 'self'), btn_modalresult=data.get('btn_modalresult', 0), btn_default=data.get('btn_default', 0), btn_cancel=data.get('btn_cancel', 0)) for data in self.type['buttons'] ])
    341 
    342     def ProcessForm(self, retfields, required, errorcheck = None):
    343         result = {}
    344         for each in retfields:
    345             if type(each) == dict:
    346                 result.update(each)
    347                 continue
    348             value = each[0].GetValue()
    349             if each[1]['type'] == 'checkbox' and 'group' in each[1] and value == 1:
    350                 result[each[1]['group']] = each[1]['key']
    351             else:
    352                 result[each[1]['key']] = value
    353 
    354         if errorcheck:
    355             hint = errorcheck(result)
    356             if hint == 'silenterror':
    357                 return
    358             if hint:
    359                 prompt_player_fsd_dialog('CustomInfo', {'info': hint})
    360                 return
    361         if len(required):
    362             for each in required:
    363                 retval = each[0].GetValue()
    364                 if retval is None or retval == '' or type(retval) in types.StringTypes and retval.strip() == '':
    365                     fieldname = ''
    366                     if 'label' in each[1]:
    367                         fieldname = each[1]['label']
    368                         if fieldname == '_hide':
    369                             fieldname = each[1]['key']
    370                     else:
    371                         fieldname = each[1]['key']
    372                     prompt_player_fsd_dialog('MissingRequiredField', {'fieldname': fieldname})
    373                     return
    374                 if each[1]['type'] == 'checkbox' and 'group' in each[1]:
    375                     if each[1]['group'] not in result:
    376                         prompt_player_fsd_dialog('MissingRequiredField', {'fieldname': each[1]['group']})
    377                         return
    378 
    379         return result
    380 
    381 
    382 def axis_alignment_from_legacy_align(align):
    383     if align in {uiconst.TOPLEFT,
    384      uiconst.BOTTOMLEFT,
    385      uiconst.CENTERLEFT,
    386      uiconst.TOLEFT}:
    387         return AxisAlignment.START
    388     elif align in {uiconst.TOPRIGHT,
    389      uiconst.BOTTOMRIGHT,
    390      uiconst.CENTERRIGHT,
    391      uiconst.TORIGHT}:
    392         return AxisAlignment.END
    393     elif align in {uiconst.CENTER, uiconst.CENTERTOP, uiconst.CENTERBOTTOM}:
    394         return AxisAlignment.CENTER
    395     else:
    396         return AxisAlignment.CENTER
    397 
    398 
    399 class FormWnd(Container):
    400     __guid__ = 'xtriui.FormWnd'
    401 
    402     def _OnClose(self):
    403         Container._OnClose(self)
    404         windowKeys = self.sr.panels.keys()
    405         for key in windowKeys:
    406             if key not in self.sr.panels:
    407                 continue
    408             wnd = self.sr.panels[key]
    409             del self.sr.panels[key]
    410             if wnd is not None and not wnd.destroyed:
    411                 wnd.Close()
    412 
    413     def ShowPanel(self, panelkey):
    414         for key in self.sr.panels:
    415             self.sr.panels[key].state = uiconst.UI_HIDDEN
    416 
    417         self.sr.panels[panelkey].state = uiconst.UI_NORMAL
    418 
    419     def OnCheckboxChange(self, sender, *args):
    420         if 'callback' in sender.data:
    421             sender.data['callback'](sender)
    422         if 'showpanel' in sender.data and sender.data['showpanel'] in self.sr.panels:
    423             self.ShowPanel(sender.data['showpanel'])
    424 
    425     def OnChange(self, *args):
    426         pass