dateSinglelineEdit.py (16834B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\control\dateSinglelineEdit.py 2 import calendar 3 import eveLocalization 4 from carbonui import fontconst 5 from carbonui.control.singlelineedits.singleLineEditInteger import SingleLineEditInteger 6 from carbonui.control.singlelineedits.singleLineEditText import SingleLineEditText 7 from carbonui.primitives.container import Container 8 from carbonui.primitives.containerAutoSize import ContainerAutoSize 9 from eve.client.script.ui.control.eveLabel import EveLabelSmall, Label 10 from carbonui.uicore import uicore 11 import carbonui.const as uiconst 12 import blue 13 from eve.client.script.ui.shared.fitting.fittingUtil import EatSignalChangingErrors 14 from localization import GetByLabel 15 from signals.signalUtil import ChangeSignalConnect 16 17 def _GetYearMonthDayFromTimestamp(timestamp): 18 timestamp += eveLocalization.GetTimeDelta() * const.SEC 19 year, month, _, day, _, _, _, _ = blue.os.GetTimeParts(timestamp) 20 return (year, month, day) 21 22 23 def _GetTimestampFromYearMonthDay(endOfDay, yearValue, monthValue, dayValue): 24 try: 25 if endOfDay: 26 timestamp = blue.os.GetTimeFromParts(yearValue, monthValue, dayValue, 23, 59, 59, 0) 27 else: 28 timestamp = blue.os.GetTimeFromParts(yearValue, monthValue, dayValue, 0, 0, 0, 0) 29 except Exception: 30 timestamp = 0 31 32 timestamp -= eveLocalization.GetTimeDelta() * const.SEC 33 return timestamp 34 35 36 def _GetHourMinuteFromTimestamp(timestamp): 37 timestamp += eveLocalization.GetTimeDelta() * const.SEC 38 _, _, _, _, hour, minute, _, _ = blue.os.GetTimeParts(timestamp) 39 return (hour, minute) 40 41 42 def _GetTimestampFromHourMinute(hourValue, minuteValue): 43 timestamp = hourValue * const.HOUR + minuteValue * const.MIN 44 timestamp -= eveLocalization.GetTimeDelta() * const.SEC 45 return timestamp 46 47 48 class DateSinglelineEdit(SingleLineEditInteger): 49 __guid__ = 'DateSinglelineEdit' 50 default_width = 100 51 default_left = 0 52 default_top = 0 53 default_textLeftMargin = 2 54 default_textRightMargin = 2 55 56 def ApplyAttributes(self, attributes): 57 maxLength = attributes.get('maxLength', 0) 58 self.numberFormatter = '{0:0>%s}' % maxLength 59 super(DateSinglelineEdit, self).ApplyAttributes(attributes) 60 self._textClipper.padLeft = 0 61 self._textClipper.padRight = 0 62 63 def ConstructBackground(self): 64 pass 65 66 def SetText(self, text, *args, **kwargs): 67 if uicore.registry.GetFocus() is not self: 68 text = self.GetAdjustedText(text) or text 69 return super(DateSinglelineEdit, self).SetText(text) 70 71 def FormatNumeric(self, otext, useGrouping = True, decimalPlaces = 0, leadingZeroes = 0): 72 leadingZeroes = 2 73 return super(DateSinglelineEdit, self).FormatNumeric(otext, useGrouping=False, decimalPlaces=decimalPlaces, leadingZeroes=leadingZeroes) 74 75 def ShowNumericControls(self): 76 pass 77 78 def BlinkButtons(self, val): 79 pass 80 81 def RefreshTextClipper(self): 82 pass 83 84 def OnKillFocus(self, *args): 85 super(DateSinglelineEdit, self).OnKillFocus(*args) 86 self.AdjustValue() 87 88 def AdjustValue(self): 89 text = self.GetAdjustedText(self.GetText()) 90 if text is None: 91 return 92 self.SetText(text) 93 94 def GetAdjustedText(self, textToAdjust): 95 if not textToAdjust and textToAdjust != 0: 96 return 97 text = self.numberFormatter.format(textToAdjust) 98 return text 99 100 def OnKeyDown(self, vkey, flag): 101 index = self.caretIndex[0] 102 if vkey == uiconst.VK_LEFT: 103 if index - 1 < 0: 104 uicore.registry.FindFocus(-1) 105 return 106 elif vkey == uiconst.VK_RIGHT: 107 if index + 1 > len(self.text): 108 uicore.registry.FindFocus(1) 109 return 110 super(DateSinglelineEdit, self).OnKeyDown(vkey, flag) 111 112 113 class DatePickerControl(ContainerAutoSize): 114 default_height = 18 115 default_align = uiconst.TOPLEFT 116 117 def ApplyAttributes(self, attributes): 118 Container.ApplyAttributes(self, attributes) 119 fontSize = attributes.fontSize or fontconst.DEFAULT_FONTSIZE 120 self.rangeStartTime = attributes.ranges[0] 121 self.rangeStopTime = attributes.ranges[1] 122 self.isEndField = attributes.get('isEndField', False) 123 self.onEditFieldChangedFunc = attributes.get('OnEditFieldChanged', None) 124 value = attributes.setValue 125 background = SingleLineEditText(bgParent=self, padTop=0, padBottom=-1) 126 minYear, maxYear = self.GetAvailableYears() 127 self.yearEdit = DateSinglelineEdit(name='yearEdit', parent=self, align=uiconst.TOLEFT, minValue=minYear, maxValue=maxYear, setvalue=value[0], OnFocusLost=self.ApplyChanges, OnReturn=self.ApplyChanges, fontsize=fontSize) 128 textMargins = DateSinglelineEdit.default_textLeftMargin + DateSinglelineEdit.default_textRightMargin - 1 129 textWidth, textHeight = Label.MeasureTextSize('0000', fontsize=fontSize) 130 self.yearEdit.width = textWidth + textMargins 131 self.yearEdit.ChangeNumericValue = lambda x: self.ChangeNumericValue(self.yearEdit, x) 132 self.yearEdit.background.display = False 133 dot1 = ContainerAutoSize(name='dot1', parent=self, align=uiconst.TOLEFT) 134 Label(parent=dot1, text='.', align=uiconst.CENTERLEFT, top=0, fontsize=fontSize) 135 self.monthEdit = DateSinglelineEdit(name='monthEdit', parent=self, align=uiconst.TOLEFT, minValue=1, maxValue=12, setvalue=value[1], OnFocusLost=self.ApplyChanges, OnReturn=self.ApplyChanges, fontsize=fontSize) 136 textWidth, textHeight = Label.MeasureTextSize('00', fontsize=fontSize) 137 self.monthEdit.width = textWidth + textMargins 138 self.monthEdit.ChangeNumericValue = lambda x: self.ChangeNumericValue(self.monthEdit, x) 139 dot2 = ContainerAutoSize(name='dot2', parent=self, align=uiconst.TOLEFT) 140 Label(parent=dot2, text='.', align=uiconst.CENTERLEFT, top=0, fontsize=fontSize) 141 self.dayEdit = DateSinglelineEdit(name='dayEdit', parent=self, align=uiconst.TOLEFT, minValue=1, maxValue=31, setvalue=value[2], OnFocusLost=self.ApplyChanges, OnReturn=self.ApplyChanges, fontsize=fontSize) 142 self.dayEdit.width = textWidth + textMargins 143 self.dayEdit.ChangeNumericValue = lambda x: self.ChangeNumericValue(self.dayEdit, x) 144 145 def ChangeNumericValue(self, editField, val): 146 if editField != self.dayEdit: 147 DateSinglelineEdit.ChangeNumericValue(editField, val) 148 self.ApplyChanges() 149 return 150 if uicore.uilib.Key(uiconst.VK_CONTROL): 151 val *= 10 152 if val > 0: 153 val = max(1, long(val)) 154 else: 155 val = min(-1, long(val)) 156 current = editField.GetValue() 157 new = current + val 158 if editField.minValue <= new <= editField.maxValue: 159 DateSinglelineEdit.ChangeNumericValue(editField, val) 160 self.ApplyChanges() 161 return 162 currentTimestamp = self.GetTimestamp() 163 newTimestamp = currentTimestamp + val * const.DAY 164 self.SetPickerValueFromTimestamp(newTimestamp) 165 self.ApplyChanges() 166 167 def GetAvailableYears(self): 168 startYear, _, _ = _GetYearMonthDayFromTimestamp(self.rangeStartTime) 169 endYear, _, _ = _GetYearMonthDayFromTimestamp(self.rangeStopTime) 170 if endYear < startYear: 171 return [startYear, startYear] 172 return [startYear, endYear] 173 174 def SetPickerValueFromTimestamp(self, timestamp): 175 year, month, day = _GetYearMonthDayFromTimestamp(timestamp) 176 self.SetPickerValue(year, month, day) 177 178 def SetPickerValue(self, year, month, day): 179 self.yearEdit.SetText(year) 180 self.monthEdit.SetText(month) 181 self.dayEdit.SetText(day) 182 183 def ApplyChanges(self, *args): 184 self.CorrectFieldBoundaries() 185 if self.AreInvalidFieldsInTransition(): 186 return 187 if not self.AreTimestampsInRange(): 188 self.CorrectFields() 189 if self.onEditFieldChangedFunc: 190 self.onEditFieldChangedFunc(self, None, None) 191 self.CheckAreFieldsValidAndCorrectThem() 192 193 def CorrectFieldBoundaries(self): 194 yearValue = self.yearEdit.GetValue() or self.yearEdit.minValue 195 monthValue = self.monthEdit.GetValue() or self.monthEdit.minValue 196 firstday, numdays = calendar.monthrange(yearValue, monthValue) 197 if self.dayEdit.maxValue != numdays: 198 self.dayEdit.SetMaxValue(numdays) 199 self.dayEdit.ClampMinMaxValue() 200 201 def AreInvalidFieldsInTransition(self): 202 timeStamp = self.GetTimestamp() 203 if timeStamp is None: 204 return True 205 return False 206 207 def AreTimestampsInRange(self): 208 timeStamp = self.GetTimestamp() 209 rangeStartTime = self.GetMinStartTime() 210 if rangeStartTime > timeStamp: 211 return False 212 rangeStopTime = self.GetMaxEndTime() 213 if rangeStopTime < timeStamp: 214 return False 215 return True 216 217 def GetMaxEndTime(self): 218 rangeStopTime = self.rangeStopTime - const.DAY if not self.isEndField else self.rangeStopTime 219 return rangeStopTime 220 221 def GetMinStartTime(self): 222 rangeStartTime = self.rangeStartTime + const.DAY if self.isEndField else self.rangeStartTime 223 return rangeStartTime 224 225 def CorrectFields(self): 226 timeStamp = self.GetTimestamp() 227 rangeStartTime = self.GetMinStartTime() 228 if rangeStartTime > timeStamp: 229 year, month, day = _GetYearMonthDayFromTimestamp(rangeStartTime) 230 self.SetPickerValue(year, month, day) 231 return 232 rangeStopTime = self.GetMaxEndTime() 233 if rangeStopTime < timeStamp: 234 year, month, day = _GetYearMonthDayFromTimestamp(rangeStopTime) 235 self.SetPickerValue(year, month, day) 236 return 237 238 def CheckAreFieldsValidAndCorrectThem(self): 239 if not self.AreTimestampsInRange(): 240 self.CorrectFields() 241 242 def GetTimestamp(self): 243 yearValue = self.yearEdit.GetValue() or self.yearEdit.minValue 244 monthValue = self.monthEdit.GetValue() or self.monthEdit.minValue 245 dayValue = self.dayEdit.GetValue() or self.dayEdit.minValue 246 timestamp = _GetTimestampFromYearMonthDay(self.isEndField, yearValue, monthValue, dayValue) 247 return timestamp 248 249 250 class HourMinPickerControl(Container): 251 default_height = 18 252 default_align = uiconst.TOPLEFT 253 254 def ApplyAttributes(self, attributes): 255 Container.ApplyAttributes(self, attributes) 256 fontSize = attributes.fontSize or fontconst.DEFAULT_FONTSIZE 257 self.onEditFieldChangedFunc = attributes.get('OnEditFieldChanged', None) 258 self.onEditFieldRolledOverFunc = attributes.get('onEditFieldRolledOverFunc', None) 259 value = attributes.setValue 260 background = SingleLineEditText(bgParent=self, padTop=0, padBottom=-1) 261 textMargins = DateSinglelineEdit.default_textLeftMargin + DateSinglelineEdit.default_textRightMargin - 1 262 self.hourEdit = DateSinglelineEdit(name='hourEdit', parent=self, align=uiconst.TOLEFT, width=36, ints=[0, 23], maxLength=2, setvalue=value[0], OnFocusLost=self.ApplyChanges, OnReturn=self.ApplyChanges, fontsize=fontSize) 263 textWidth, textHeight = Label.MeasureTextSize('00', fontsize=fontSize) 264 self.hourEdit.width = textWidth + textMargins 265 self.hourEdit.ChangeNumericValue = lambda x: self.ChangeNumericValue(self.hourEdit, x) 266 self.hourEdit.background.display = False 267 dot1 = ContainerAutoSize(name='dot2', parent=self, align=uiconst.TOLEFT) 268 Label(parent=dot1, text=':', align=uiconst.CENTERLEFT, top=-2, fontsize=fontSize) 269 self.minEdit = DateSinglelineEdit(name='minEdit', parent=self, align=uiconst.TOLEFT, width=20, maxLength=2, ints=[0, 59], setvalue=value[1], OnFocusLost=self.ApplyChanges, OnReturn=self.ApplyChanges, fontsize=fontSize) 270 self.minEdit.width = textWidth + textMargins 271 self.minEdit.ChangeNumericValue = lambda x: self.ChangeNumericValue(self.minEdit, x) 272 self.width = self.hourEdit.width + self.minEdit.width + 3 273 274 def ApplyChanges(self, *args): 275 if self.onEditFieldChangedFunc: 276 self.onEditFieldChangedFunc() 277 278 def GetTimestamp(self): 279 hourValue = self.hourEdit.GetValue() or self.hourEdit.minValue 280 minuteValue = self.minEdit.GetValue() or self.minEdit.minValue 281 timestamp = _GetTimestampFromHourMinute(hourValue, minuteValue) 282 return timestamp 283 284 def ChangeNumericValue(self, editField, val): 285 if uicore.uilib.Key(uiconst.VK_CONTROL): 286 val *= 10 287 if val > 0: 288 val = max(1, long(val)) 289 else: 290 val = min(-1, long(val)) 291 if editField == self.minEdit: 292 val *= 30 293 current = editField.GetValue() 294 new = current + val 295 if not self.onEditFieldRolledOverFunc or editField.minValue <= new <= editField.maxValue: 296 DateSinglelineEdit.ChangeNumericValue(editField, val) 297 self.ApplyChanges() 298 return 299 currentTimestamp = self.GetTimestamp() 300 if editField == self.hourEdit: 301 newTimestamp = currentTimestamp + val * const.HOUR 302 else: 303 newTimestamp = currentTimestamp + val * const.MIN 304 self.onEditFieldRolledOverFunc(newTimestamp) 305 306 def SetPickerValue(self, hour, minute): 307 self.hourEdit.SetText(hour) 308 self.minEdit.SetText(minute) 309 310 def SetPickerValueFromTimestamp(self, timestamp): 311 hour, minute = _GetHourMinuteFromTimestamp(timestamp) 312 self.SetPickerValue(hour, minute) 313 314 315 class DateRangePicker(Container): 316 317 def ApplyAttributes(self, attributes): 318 Container.ApplyAttributes(self, attributes) 319 self.sliderController = attributes.sliderController 320 labelPaths = attributes.labelPaths 321 fromTime = attributes.fromTime 322 toTime = attributes.toTime 323 ranges = self.sliderController.GetDataRange() 324 fyear, fmonth, _, fday, _, _, _, _ = blue.os.GetTimeParts(fromTime) 325 tyear, tmonth, _, tday, _, _, _, _ = blue.os.GetTimeParts(toTime) 326 beforeText = GetByLabel(labelPaths[0]) 327 rangeLabel = EveLabelSmall(parent=self, text=beforeText, align=uiconst.TOPLEFT, top=5, left=0) 328 left = rangeLabel.left + rangeLabel.textwidth + 10 329 self.fromPicker = DatePickerControl(name='fromPicker', parent=self, OnEditFieldChanged=self.OnEditFieldChanged, setValue=[fyear, fmonth, fday], top=2, left=left, ranges=ranges) 330 self.fromPicker.SetSizeAutomatically() 331 left = self.fromPicker.left + self.fromPicker.width + 4 332 betweenText = GetByLabel(labelPaths[1]) 333 toLabel = EveLabelSmall(parent=self, text=betweenText, align=uiconst.TOPLEFT, top=5, left=left) 334 left = toLabel.left + toLabel.textwidth + 4 335 self.toPicker = DatePickerControl(name='toPicker', parent=self, left=left, OnEditFieldChanged=self.OnEditFieldChanged, setValue=[tyear, tmonth, tday], top=2, ranges=ranges, isEndField=True) 336 left = self.toPicker.left + self.toPicker.width + 4 337 text = GetByLabel('UI/Common/InvalidRange') 338 self.validLabel = EveLabelSmall(parent=self, text=text.upper(), align=uiconst.TOPLEFT, top=5, left=left) 339 self.validLabel.SetRGBA(1, 0, 0, 0.75) 340 self.validLabel.display = False 341 self.ChangeSignalConnection() 342 343 def ChangeSignalConnection(self, connect = True): 344 signalAndCallback = [(self.sliderController.on_change, self.SetVisibleRange)] 345 ChangeSignalConnect(signalAndCallback, connect) 346 347 def OnEditFieldChanged(self, picker, editField, text): 348 fromTimestamp = self.fromPicker.GetTimestamp() 349 toTimeStamp = self.toPicker.GetTimestamp() 350 if fromTimestamp and toTimeStamp: 351 self.sliderController.SetVisibleRange((fromTimestamp, toTimeStamp)) 352 353 def SetVisibleRange(self): 354 fromValues, fromTime, toValues, toTime = self.GetVisibleRangeTimeParts() 355 self.fromPicker.SetPickerValue(*fromValues) 356 self.toPicker.SetPickerValue(*toValues) 357 if fromTime >= toTime: 358 self.validLabel.display = True 359 else: 360 self.validLabel.display = False 361 362 def GetVisibleRangeTimeParts(self): 363 fromTime, toTime = self.sliderController.GetVisibleRange() 364 fyear, fmonth, _, fday, _, _, _, _ = blue.os.GetTimeParts(fromTime) 365 tyear, tmonth, _, tday, _, _, _, _ = blue.os.GetTimeParts(toTime) 366 return ([fyear, fmonth, fday], 367 fromTime, 368 [tyear, tmonth, tday], 369 toTime) 370 371 def Close(self): 372 with EatSignalChangingErrors(errorMsg='DateRangePicker'): 373 self.ChangeSignalConnection(connect=False) 374 Container.Close(self)