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

calculator.py (15821B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\neocom\calculator.py
      2 import sys
      3 import eveLocalization
      4 import localization
      5 from carbonui import fontconst, uiconst
      6 from carbonui.control.singlelineedits.singleLineEditText import SingleLineEditText
      7 from carbonui.primitives.container import Container
      8 from carbonui.primitives.containerAutoSize import ContainerAutoSize
      9 from carbonui.primitives.layoutGrid import LayoutGrid
     10 from carbonui.uicore import uicore
     11 from carbonui.control.window import Window
     12 from eve.client.script.ui.util import uix
     13 from carbonui.control.buttonIcon import ButtonIcon
     14 from carbonui.control.button import Button
     15 from menu import MenuLabel
     16 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     17 from decimal import Decimal
     18 MINWIDTH = 240
     19 
     20 class Calculator(Window):
     21     __guid__ = 'form.Calculator'
     22     default_windowID = 'calculator'
     23     default_width = MINWIDTH
     24     default_height = 160
     25     default_left = 0
     26     default_top = 0
     27     default_captionLabelPath = 'UI/Accessories/Calculator/Calculator'
     28     default_iconNum = 'res:/ui/Texture/WindowIcons/calculator.png'
     29     default_scope = uiconst.SCOPE_INGAME
     30 
     31     def ApplyAttributes(self, attributes):
     32         self.mainCont = None
     33         self.buttonGrid = None
     34         self.decimalSign = eveLocalization.GetDecimalSeparator(localization.SYSTEM_LANGUAGE)
     35         self.digitSign = eveLocalization.GetThousandSeparator(localization.SYSTEM_LANGUAGE)
     36         self.PopulateKnownKeys()
     37         super(Calculator, self).ApplyAttributes(attributes)
     38         self.MakeUnResizeable()
     39         self.Layout()
     40 
     41     def Layout(self):
     42         self.mainCont = ContainerAutoSize(parent=self.GetMainArea(), align=uiconst.TOTOP, callback=self._OnMainContResized)
     43         self.sr.inpt = inpt = SingleLineEditText(name='inpt', parent=ContainerAutoSize(parent=self.mainCont, align=uiconst.TOTOP, top=8, padLeft=8, padRight=8), align=uiconst.TOTOP, top=0, height=32, fontsize=fontconst.EVE_LARGE_FONTSIZE)
     44         inpt.SetHistoryVisibility(0)
     45         inpt.OnChar = self.OnCharInput
     46         inpt.Paste = self.OnInputPasted
     47         self.SetInpt('0')
     48         hist = settings.public.ui.Get('CalculatorHistory', [])
     49         if hist:
     50             ops = [ (v, v) for v in hist ]
     51         else:
     52             ops = [('0', '0')]
     53         inpt.LoadCombo('urlcombo', ops, self.OnComboChange)
     54         memoryCont = LayoutGrid(parent=ContainerAutoSize(parent=self.mainCont, align=uiconst.TOTOP, top=8, left=8, padRight=8), align=uiconst.CENTER, columns=3, cellSpacing=(8, 8))
     55         self.buttonGrid = grid = LayoutGrid(parent=ContainerAutoSize(parent=self.mainCont, align=uiconst.TOTOP, top=8, left=8, padRight=8, padBottom=8), align=uiconst.TOPLEFT, columns=7, cellSpacing=(4, 4))
     56         buttons = [('7', localization.formatters.FormatNumeric(7)),
     57          ('8', localization.formatters.FormatNumeric(8)),
     58          ('9', localization.formatters.FormatNumeric(9)),
     59          ('divide', localization.GetByLabel('UI/Accessories/Calculator/DivideSymbol')),
     60          ('clear', localization.GetByLabel('UI/Accessories/Calculator/ClearSymbol')),
     61          ('clearall', localization.GetByLabel('UI/Accessories/Calculator/ClearAllSymbol')),
     62          ('4', localization.formatters.FormatNumeric(4)),
     63          ('5', localization.formatters.FormatNumeric(5)),
     64          ('6', localization.formatters.FormatNumeric(6)),
     65          ('times', localization.GetByLabel('UI/Accessories/Calculator/MultiplySymbol')),
     66          ('bo', localization.GetByLabel('UI/Accessories/Calculator/BracketOpenSymbol')),
     67          ('bc', localization.GetByLabel('UI/Accessories/Calculator/BracketCloseSymbol')),
     68          ('1', localization.formatters.FormatNumeric(1)),
     69          ('2', localization.formatters.FormatNumeric(2)),
     70          ('3', localization.formatters.FormatNumeric(3)),
     71          ('minus', localization.GetByLabel('UI/Accessories/Calculator/SubtractSymbol')),
     72          ('percent', localization.GetByLabel('UI/Accessories/Calculator/PercentSymbol')),
     73          ('square', localization.GetByLabel('UI/Accessories/Calculator/SquareSymbol')),
     74          ('0', localization.formatters.FormatNumeric(0)),
     75          ('dot', self.decimalSign),
     76          ('equal', localization.GetByLabel('UI/Accessories/Calculator/EqualsSymbol')),
     77          ('plus', localization.GetByLabel('UI/Accessories/Calculator/AddSymbol')),
     78          ('plusminus', localization.GetByLabel('UI/Accessories/Calculator/PlusMinusSymbol')),
     79          ('root', u'\u221a\xaf')]
     80         for i, (arg, label) in enumerate(buttons):
     81             if i % 6 == 4:
     82                 Container(parent=grid, align=uiconst.TOPLEFT, width=8)
     83             Button(name=arg, parent=grid, align=uiconst.TOPLEFT, fixedwidth=32, fixedheight=32, label=label, fontsize=fontconst.EVE_MEDIUM_FONTSIZE, func=lambda c = arg: self.OnBtnClick(c), args=())
     84 
     85         for i in xrange(1, 7):
     86             MemorySlot(parent=memoryCont, align=uiconst.TOPLEFT, index=i, getInputValue=self._GetInputValue, setInputValue=lambda value: self.SetInpt(str(value).replace('.', self.decimalSign), False))
     87 
     88         self.newNumber = True
     89         self._stack = []
     90         self.opStack = []
     91         self.lastOp = 0
     92         uicore.registry.SetFocus(self.sr.inpt)
     93 
     94     def _GetInputValue(self):
     95         if self.sr.inpt.GetValue() == '':
     96             self.SetInpt('0')
     97         text = self.sr.inpt.GetValue()
     98         return Decimal(text.replace(self.decimalSign, '.'))
     99 
    100     def _OnMainContResized(self):
    101         if self.buttonGrid is None:
    102             return
    103         windowMain = self.GetMainArea()
    104         totalHeight = self.header_height + windowMain.padTop + windowMain.padBottom + self.mainCont.height
    105         totalWidth = windowMain.padLeft + windowMain.padRight + self.buttonGrid.width + self.buttonGrid.parent.left + self.buttonGrid.parent.padRight
    106         self.SetMinSize(size=(totalWidth, totalHeight), refresh=True)
    107 
    108     def SetInpt(self, value, new = True):
    109         self.sr.inpt.SetValue(value)
    110         self.newNumber = new
    111 
    112     def OnComboChange(self, combo, header, value, *args):
    113         self.SetInpt(value, False)
    114 
    115     def OnInputPasted(self, paste, deleteStart = None, deleteEnd = None, forceFocus = False):
    116         self.SetInpt('0')
    117         for char in paste:
    118             self.OnCharInput(ord(char))
    119 
    120     def OnCharInput(self, char, flag = None):
    121         _char = char
    122         text = self.sr.inpt.GetText()
    123         try:
    124             _char = unichr(char)
    125             if len(_char) == 1 and _char in '0123456789':
    126                 if text == '0' or self.newNumber:
    127                     self.sr.inpt.text = ''
    128                 self.sr.inpt.Insert(char)
    129                 self.newNumber = False
    130                 return True
    131         except:
    132             sys.exc_clear()
    133 
    134         if _char in self.knownkeys.keys():
    135             _char = self.knownkeys[_char]
    136         if _char == 'dot' or type(char) == int and unichr(char) == u'.':
    137             if self.decimalSign not in text or self.newNumber:
    138                 if text == '' or self.newNumber:
    139                     self.sr.inpt.text = '0'
    140                     self.sr.inpt.Insert(ord(self.decimalSign))
    141                     self.newNumber = False
    142                     return True
    143                 self.sr.inpt.Insert(ord(self.decimalSign))
    144                 self.newNumber = False
    145             else:
    146                 return True
    147         if _char == 'plusminus':
    148             if text.startswith('-'):
    149                 text = text[1:]
    150             else:
    151                 text = '-' + text
    152             self.SetInpt(text, False)
    153             return True
    154         if _char == 'clearall':
    155             self._stack = []
    156             self.opStack = []
    157         if _char in ('\x08', 'clear', 'clearall'):
    158             self.SetInpt('0')
    159             return True
    160         if _char in self.prio.keys():
    161             self.Operator(_char, text)
    162             if _char == 'equal':
    163                 hist = settings.public.ui.Get('CalculatorHistory', [])
    164                 hist.insert(0, text)
    165                 if len(hist) > 20:
    166                     hist.pop()
    167                 settings.public.ui.Set('CalculatorHistory', hist)
    168                 ops = [ (v, v) for v in hist ]
    169                 self.sr.inpt.LoadCombo('urlcombo', ops, self.OnComboChange, setvalue=text)
    170         return True
    171 
    172     def OnBtnClick(self, arg):
    173         try:
    174             arg = ord(arg)
    175         except Exception:
    176             sys.exc_clear()
    177 
    178         self.OnCharInput(arg)
    179 
    180     def CheckOperator(self):
    181         if str(self._stack[-1]) in self.prio.keys():
    182             return True
    183         return False
    184 
    185     def Calc(self):
    186         if len(self._stack) > 0 and self.CheckOperator():
    187             op = self._stack.pop()
    188             if op in ('equal', 'bo', 'bc'):
    189                 self.Calc()
    190             if op == 'plus':
    191                 self.Calc()
    192                 op1 = self._stack.pop()
    193                 self.Calc()
    194                 op2 = self._stack.pop()
    195                 self._stack.append(op2 + op1)
    196             if op == 'minus':
    197                 self.Calc()
    198                 op1 = self._stack.pop()
    199                 self.Calc()
    200                 op2 = self._stack.pop()
    201                 self._stack.append(op2 - op1)
    202             if op == 'times':
    203                 self.Calc()
    204                 op1 = self._stack.pop()
    205                 self.Calc()
    206                 op2 = self._stack.pop()
    207                 self._stack.append(op2 * op1)
    208             if op == 'divide':
    209                 self.Calc()
    210                 op1 = self._stack.pop()
    211                 self.Calc()
    212                 op2 = self._stack.pop()
    213                 try:
    214                     self._stack.append(op2 / op1)
    215                 except ZeroDivisionError as e:
    216                     sys.exc_clear()
    217                     prompt_player_fsd_dialog('uiwarning03')
    218                     self._stack.append(Decimal(0.0))
    219 
    220             if op == 'square':
    221                 self.Calc()
    222                 op1 = self._stack.pop()
    223                 try:
    224                     self._stack.append(op1 ** Decimal(2.0))
    225                 except OverflowError as e:
    226                     sys.exc_clear()
    227                     prompt_player_fsd_dialog('uiwarning03')
    228                     self._stack.append(Decimal(0.0))
    229 
    230             if op == 'root':
    231                 self.Calc()
    232                 op1 = self._stack.pop()
    233                 try:
    234                     self._stack.append(op1 ** Decimal(0.5))
    235                 except ValueError as e:
    236                     sys.exc_clear()
    237                     prompt_player_fsd_dialog('uiwarning03')
    238                     self._stack.append(Decimal(0.0))
    239 
    240             if op == 'percent':
    241                 self.Calc()
    242                 op1 = self._stack.pop()
    243                 if len(self._stack):
    244                     op2 = self._stack[-1]
    245                 else:
    246                     prompt_player_fsd_dialog('uiwarning03')
    247                     op2 = 0.0
    248                 self._stack.append(op2 * op1 / Decimal(100.0))
    249 
    250     def Operator(self, op, number):
    251         if not self.newNumber or len(self._stack) == 0:
    252             self._stack.append(Decimal(number.replace(self.decimalSign, '.')))
    253         elif self.lastOp in ('plus', 'minus', 'times', 'divide') and op != 'bo':
    254             self.opStack[-1] = op
    255             return
    256         if op != 'bo' and (len(self.opStack) == 0 or self.prio[op] <= self.prio[self.opStack[-1]]):
    257             while len(self.opStack) > 0 and self.prio[op] <= self.prio[self.opStack[-1]]:
    258                 self._stack.append(self.opStack.pop())
    259 
    260         if op == 'bc':
    261             while len(self.opStack) > 0 and self.opStack[-1] != 'bo':
    262                 self._stack.append(self.opStack.pop())
    263 
    264             if len(self.opStack):
    265                 self.opStack.pop()
    266         if op in ('percent', 'root', 'square', 'equal', 'bc'):
    267             self._stack.append(op)
    268         else:
    269             self.opStack.append(op)
    270         self.Calc()
    271         number = str(round(self._stack[-1], 14))
    272         self.SetInpt(number.replace('.', self.decimalSign))
    273         self.lastOp = op
    274 
    275     def PopulateKnownKeys(self):
    276         self.knownkeys = {'+': 'plus',
    277          '-': 'minus',
    278          '*': 'times',
    279          '/': 'divide',
    280          self.decimalSign: 'dot',
    281          '=': 'equal',
    282          'r': 'root',
    283          's': 'square',
    284          'p': 'percent',
    285          'm': 'plusminus',
    286          '(': 'bo',
    287          ')': 'bc',
    288          'C': 'clearall',
    289          '\r': 'equal'}
    290 
    291     prio = {'plus': 3,
    292      'minus': 3,
    293      'times': 4,
    294      'divide': 4,
    295      'square': 5,
    296      'root': 5,
    297      'bo': 1,
    298      'bc': 6,
    299      'percent': 4,
    300      'equal': 0}
    301 
    302 
    303 class MemorySlot(LayoutGrid):
    304 
    305     def __init__(self, index, getInputValue, setInputValue, parent = None, align = uiconst.TOPLEFT):
    306         self._index = index
    307         self._getInputValue = getInputValue
    308         self._setInputValue = setInputValue
    309         super(MemorySlot, self).__init__(parent=parent, align=align, colums=2)
    310         button = Button(parent=self, align=uiconst.TOPLEFT, label=localization.GetByLabel('UI/Accessories/Calculator/AbbreviatedMemory', index=self._index), func=self._OnButtonClick, args=())
    311         button.GetHint = self._GetButtonHint
    312         menu = ButtonIcon(parent=self, align=uiconst.CENTER, width=16, height=16, texturePath='res:/UI/Texture/Icons/38_16_190.png', iconSize=16)
    313         menu.expandOnLeft = True
    314         menu.GetMenu = self._GetMenuOptions
    315 
    316     def _OnButtonClick(self):
    317         stored = GetMemoryAt(self._index)
    318         if stored is not None:
    319             self._setInputValue(stored)
    320 
    321     def _GetButtonHint(self):
    322         stored = GetMemoryAt(self._index)
    323         if stored is not None:
    324             return '%s:<br>%.14G' % (GetMemoryNameAt(self._index), stored)
    325         else:
    326             return localization.GetByLabel('UI/Accessories/Calculator/EmptyBank', label=GetMemoryNameAt(self._index), empty=localization.GetByLabel('UI/Accessories/Calculator/Empty'))
    327 
    328     def _GetMenuOptions(self):
    329         m = []
    330         m.append((MenuLabel('UI/Accessories/Calculator/Set'), self._Set))
    331         stored = GetMemoryAt(self._index)
    332         if stored is not None:
    333             m.extend([(MenuLabel('UI/Accessories/Calculator/Add'), self._Add), (MenuLabel('UI/Accessories/Calculator/Subtract'), self._Sub), (MenuLabel('UI/Accessories/Calculator/Clear'), self._Clear)])
    334         m.append((MenuLabel('UI/Accessories/Calculator/Annotate'), self._Rename))
    335         return m
    336 
    337     def _Set(self):
    338         SetMemoryAt(self._index, self._getInputValue())
    339 
    340     def _Add(self):
    341         current = GetMemoryAt(self._index, default=0.0)
    342         value = self._getInputValue()
    343         SetMemoryAt(self._index, current + value)
    344 
    345     def _Sub(self):
    346         current = GetMemoryAt(self._index, default=0.0)
    347         value = self._getInputValue()
    348         SetMemoryAt(self._index, current - value)
    349 
    350     def _Clear(self):
    351         SetMemoryAt(self._index, None)
    352 
    353     def _Rename(self):
    354         retval = uix.HybridWnd(caption=localization.GetByLabel('UI/Accessories/Calculator/Annotate'), windowID='calculatorAnnotate', icon=uiconst.QUESTION, minW=300, minH=100, format=[{'type': 'edit',
    355           'setvalue': GetMemoryNameAt(self._index),
    356           'labelwidth': 48,
    357           'label': localization.GetByLabel('UI/Accessories/Calculator/Name'),
    358           'key': 'name',
    359           'maxlength': 16,
    360           'setfocus': 1}])
    361         if retval:
    362             SetMemoryNameAt(self._index, retval['name'])
    363 
    364 
    365 def GetMemoryAt(index, default = None):
    366     return settings.public.ui.Get('CalculatorMem%s' % index, default)
    367 
    368 
    369 def SetMemoryAt(index, value):
    370     settings.public.ui.Set('CalculatorMem%s' % index, value)
    371 
    372 
    373 def GetMemoryNameAt(index):
    374     return settings.public.ui.Get('CalculatorMem%sName' % index, localization.GetByLabel('UI/Accessories/Calculator/Memory', index=index))
    375 
    376 
    377 def SetMemoryNameAt(index, name):
    378     settings.public.ui.Set('CalculatorMem%sName' % index, name)