formFields.py (29800B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\control\forms\formFields.py 2 import datetime 3 import time 4 from datetime import date 5 import eveicon 6 import eveui 7 import uthread2 8 from dateutil import relativedelta 9 from eveui import ItemTypeField 10 from eveui.autocomplete import ItemCategorySuggestion, ItemGroupSuggestion, ItemTypeSuggestion, LocationSuggestion, ShipTypeSuggestion 11 from eveui.autocomplete.npc.suggestion import FactionSuggestion, NpcCorporationSuggestion 12 from eveui.autocomplete.player.suggestion import OwnerIdentitySuggestion 13 from carbonui import Align, ButtonFrameType, ButtonVariant, Density, TextColor, uiconst 14 from carbonui.text.styles import TextBody, TextDetail 15 from carbonui.control.button import Button 16 from carbonui.control.buttonIcon import ButtonIcon 17 from carbonui.control.checkbox import Checkbox 18 from carbonui.control.combo import Combo 19 from carbonui.control.forms import formComponent 20 from carbonui.control.forms.form import Form 21 from carbonui.control.forms.formsUtil import FormatAsIncompleteInput 22 from carbonui.control.singlelineedits.singleLineEditFloat import SingleLineEditFloat 23 from carbonui.control.singlelineedits.singleLineEditInteger import SingleLineEditInteger 24 from carbonui.control.singlelineedits.singleLineEditText import SingleLineEditText 25 from carbonui.primitives.container import Container 26 from carbonui.primitives.containerAutoSize import ContainerAutoSize 27 from carbonui.primitives.flowcontainer import FlowContainer 28 from carbonui.primitives.line import Line 29 from carbonui.primitives.sprite import Sprite 30 from eve.client.script.ui.control.datepicker import DatePicker 31 from eve.client.script.ui.control.eveEditPlainText import EditPlainText 32 from eve.client.script.ui.control.infoIcon import InfoIcon 33 from localization import GetByLabel 34 from localization.formatters.timeIntervalFormatters import FormatSpecificDurationWritten 35 36 class BaseField(ContainerAutoSize): 37 default_align = Align.TOTOP 38 default_alignMode = Align.TOTOP 39 default_padTop = 8 40 default_padBottom = 16 41 42 def ApplyAttributes(self, attributes): 43 super(BaseField, self).ApplyAttributes(attributes) 44 self.label = None 45 self.icon = None 46 self.info = None 47 self.component = attributes.component 48 self.ConstructLayout() 49 self.component.init_value(self.get_value()) 50 self.component.on_label_changed.connect(self.OnLabelChanged) 51 self.component.on_icon_changed.connect(self.OnIconChanged) 52 self.component.on_hint_changed.connect(self.OnHintChanged) 53 self.component.on_validated.connect(self.OnValidated) 54 self.component.on_value_set.connect(self.set_value) 55 self.component.on_value_cleared.connect(self.clear_value) 56 self.component.on_visibility_changed.connect(self.OnVisibilityChanged) 57 self.display = self.component.is_visible 58 if self.component.indent_level: 59 self.padLeft = self.component.indent_level * 24 60 61 def OnLabelChanged(self, component): 62 if self.label: 63 self.label.text = self._get_label_text() 64 65 def OnIconChanged(self, component): 66 if self.icon: 67 self.icon.texturePath = component.icon 68 69 def OnHintChanged(self, component): 70 self.component.hint = component.hint 71 self.ConstructHint(self.header_container) 72 73 def OnVisibilityChanged(self, component): 74 self.display = component.is_visible 75 76 def OnValidated(self, component, is_valid): 77 if not self.label: 78 return 79 text = self._get_label_text() 80 if not is_valid: 81 text = FormatAsIncompleteInput(text) 82 self.label.text = text 83 84 def ConstructLayout(self): 85 self.ConstructHeader() 86 self.ConstructBody() 87 88 def Reconstruct(self): 89 self.Flush() 90 self.ConstructLayout() 91 92 def ConstructHeader(self): 93 self.header_container = ContainerAutoSize(name='header_container', parent=self, align=self.align, alignMode=self.alignMode, padBottom=4) 94 self.ConstructIcon(self.header_container) 95 self.ConstructHint(self.header_container) 96 self.ConstructLabel(self.header_container) 97 98 def ConstructIcon(self, parent): 99 icon = self.component.icon 100 if not icon: 101 return 102 icon_container = Container(name='icon_container', parent=parent, state=uiconst.UI_DISABLED, align=Align.TOLEFT, width=16) 103 self.icon = Sprite(parent=icon_container, texturePath=icon, align=Align.CENTER, height=16, width=16, color=TextColor.SECONDARY) 104 105 def ConstructLabel(self, parent): 106 self.label = TextDetail(parent=parent, align=self.align, text=self._get_label_text(), color=TextColor.SECONDARY, padLeft=4) 107 108 def ConstructHint(self, parent = None): 109 if self.component.hint: 110 self.info = InfoIcon(parent=parent or self, align=Align.TOPRIGHT, hint=self.component.hint) 111 elif self.info: 112 self.info.Close() 113 self.info = None 114 115 def ConstructBody(self): 116 pass 117 118 def get_value(self): 119 raise NotImplementedError 120 121 def _OnValueChanged(self, *args): 122 self.component.on_field_value_changed(self.get_value()) 123 124 def set_value(self, value): 125 raise NotImplementedError 126 127 def clear_value(self): 128 raise NotImplementedError 129 130 def _get_label_text(self): 131 return self.component.label 132 133 134 class FormField(BaseField): 135 default_padTop = 0 136 default_padBottom = 0 137 138 def ConstructLayout(self): 139 self.ConstructHint() 140 ConstructFields(self, self.component) 141 self.component.on_components_changed.connect(self.OnComponentsChanged) 142 143 def OnComponentsChanged(self, *args): 144 self.Reconstruct() 145 146 def get_value(self): 147 return self.component.get_value() 148 149 def set_value(self, value): 150 pass 151 152 def clear_value(self): 153 pass 154 155 156 class EditField(BaseField): 157 158 def ConstructBody(self): 159 max_chars = self.component.get_max_characters() 160 self.textEdit = SingleLineEditText(name=self.component.get_id(), parent=self, setvalue=self.component.get_value(), hintText=self.component.placeholder, align=Align.TOTOP, OnChange=self._OnValueChanged, showLetterCounter=bool(max_chars), maxLength=max_chars) 161 162 def get_value(self): 163 return self.textEdit.GetText().strip() 164 165 def set_value(self, value): 166 self.textEdit.SetText(value) 167 168 169 class EditFieldMultiLine(BaseField): 170 171 def ConstructBody(self): 172 max_chars = self.component.get_max_characters() 173 self.textEdit = EditPlainText(name=self.component.get_id(), parent=self, setvalue=self.component.get_value(), hintText=self.component.placeholder, height=32 + self.component.num_lines * 16, align=Align.TOTOP, countWithTags=bool(max_chars), counterMax=max_chars, showattributepanel=self.component.show_formatting_panel) 174 self.textEdit.OnChange = self._OnValueChanged 175 176 def get_value(self): 177 return self.textEdit.GetValue().strip() 178 179 def set_value(self, value): 180 self.textEdit.SetText(value) 181 182 183 class Label(BaseField): 184 185 def ConstructLayout(self): 186 self.ConstructLabel(self) 187 188 def get_value(self): 189 return None 190 191 def set_value(self, value): 192 pass 193 194 195 class IntegerEditField(BaseField): 196 197 def ApplyAttributes(self, attributes): 198 super(IntegerEditField, self).ApplyAttributes(attributes) 199 self.component.min_value_changed_signal.connect(self.set_min_value) 200 self.component.max_value_changed_signal.connect(self.set_max_value) 201 202 def Close(self): 203 super(IntegerEditField, self).Close() 204 self.component.min_value_changed_signal.disconnect(self.set_min_value) 205 self.component.max_value_changed_signal.disconnect(self.set_max_value) 206 207 def ConstructBody(self): 208 self.edit = SingleLineEditInteger(name=self.component.get_id(), parent=self, setvalue=self.component.get_value(), minValue=self.component.min_value, maxValue=self.component.max_value, align=self.align, hintText=self.component.placeholder, OnChange=self._OnValueChanged) 209 210 def get_value(self): 211 if not self.edit.text: 212 return None 213 return self.edit.GetValue() 214 215 def set_value(self, value): 216 self.edit.SetValue(value) 217 218 def clear_value(self): 219 self.edit.Clear() 220 221 def get_min_value(self): 222 return self.edit.minValue 223 224 def get_max_value(self): 225 return self.edit.maxValue 226 227 def set_min_value(self, value): 228 self.edit.SetMinValue(value) 229 if self.get_value() < value: 230 self.set_value(value) 231 232 def set_max_value(self, value): 233 self.edit.SetMaxValue(value) 234 if self.get_value() > value: 235 self.set_value(value) 236 237 238 class HorizontalIntegerField(IntegerEditField): 239 default_align = Align.TOPLEFT 240 default_alignMode = None 241 default_padTop = 0 242 default_padBottom = 0 243 244 def ConstructLabel(self, parent): 245 self.label = TextDetail(parent=parent, align=self.align, text=self._get_label_text(), color=TextColor.SECONDARY) 246 247 def ConstructBody(self): 248 header_width = self.header_container.GetAutoSize()[0] 249 self.edit = SingleLineEditInteger(name=self.component.get_id(), parent=self, setvalue=self.component.get_value(), minValue=self.component.min_value, maxValue=self.component.max_value, align=self.align, hintText=self.component.placeholder, OnChange=self._OnValueChanged, padLeft=header_width + 16, width=180) 250 self.SetSizeAutomatically() 251 252 253 class FormFieldWithHorizontalBody(FormField): 254 default_padTop = 8 255 default_padBottom = 16 256 257 def ConstructLayout(self): 258 BaseField.ConstructLayout(self) 259 260 def ConstructBody(self): 261 body_container = ContainerAutoSize(name='body_container', parent=self, align=Align.TOTOP) 262 fields = [] 263 padLeft = 0 264 for component in self.component.get_components(): 265 component_container = ContainerAutoSize(name='component_container', parent=body_container, align=Align.TOPLEFT, padLeft=padLeft) 266 field = ConstructField(component_container, component) 267 fields.append(field) 268 component_container.SetSizeAutomatically() 269 padLeft += component_container.width + 24 270 271 self.component.on_components_changed.connect(self.OnComponentsChanged) 272 body_container.SetSizeAutomatically() 273 self.SetSizeAutomatically() 274 total_height = body_container.height 275 for field in fields: 276 field.label.padTop = max(0, (total_height - field.label.height) / 2) 277 278 279 class FloatEditField(BaseField): 280 281 def ConstructBody(self): 282 self.edit = SingleLineEditFloat(name=self.component.get_id(), parent=self, setvalue=self.component.get_value(), minValue=self.component.min_value, maxValue=self.component.max_value, align=Align.TOTOP, OnChange=self._OnValueChanged, decimalPlaces=2) 283 284 def get_value(self): 285 return self.edit.GetValue() 286 287 def set_value(self, value): 288 self.edit.SetValue(value) 289 290 291 class CheckboxField(BaseField): 292 293 def ConstructLayout(self): 294 self.ConstructHint() 295 self.checkbox = Checkbox(name=self.component.get_id(), parent=self, checked=self.component.get_value(), text=self.component.get_label(), callback=self._OnValueChanged) 296 297 def get_value(self): 298 return self.checkbox.GetValue() 299 300 def set_value(self, value): 301 self.checkbox.checked = value 302 303 def ConstructHint(self, parent = None): 304 if self.component.hint: 305 InfoIcon(parent=self, align=Align.CENTERRIGHT, hint=self.component.hint) 306 307 308 class CheckBoxFieldButton(BaseField): 309 310 def ConstructLayout(self): 311 self.ConstructHint() 312 self.button = ButtonIcon(parent=self, align=Align.CENTERRIGHT, width=20, height=20, iconSize=16, padLeft=-20, padRight=16, color=TextColor.SECONDARY, texturePath=eveicon.open_window, func=self.component.open_window_func, hint=self.component.open_window_hint) 313 self.checkbox = Checkbox(name=self.component.get_id(), parent=self, checked=self.component.get_value(), text=self.component.get_label(), callback=self._OnValueChanged) 314 315 def get_value(self): 316 return self.checkbox.GetValue() 317 318 def set_value(self, value): 319 self.checkbox.checked = value 320 321 def ConstructHint(self, parent = None): 322 if self.component.hint: 323 InfoIcon(parent=self, align=Align.CENTERRIGHT, hint=self.component.hint) 324 325 326 class ComboField(BaseField): 327 328 def ConstructBody(self): 329 self.combo = Combo(name=self.component.get_id(), parent=self, align=Align.TOTOP, callback=self._OnValueChanged, options=self.component.options, select=self.component.get_value(), nothingSelectedText=self.component.placeholder) 330 331 def get_value(self): 332 return self.combo.GetValue() 333 334 def set_value(self, value): 335 self.combo.SelectItemByValue(value) 336 if value is None: 337 self.combo.SetNothingSelected() 338 339 340 class EveTypeField(BaseField): 341 342 def ConstructBody(self): 343 type_id = self.component.get_value() 344 completed_suggestion = ItemTypeSuggestion(type_id=type_id) if type_id else None 345 self.edit = ItemTypeField(parent=self, align=Align.TOTOP, placeholder=self.component.placeholder, show_suggestions_on_focus=True, completed_suggestion=completed_suggestion, type_filter=self.component.type_filter) 346 self.edit.bind(completed_suggestion=self._OnValueChanged) 347 348 def get_value(self): 349 selected = self.edit.completed_suggestion 350 if selected: 351 return selected.type_id 352 353 def set_value(self, value): 354 pass 355 356 357 class MixedHierarchyItemFormField(BaseField): 358 359 def ConstructBody(self): 360 completed_suggestion = self._get_completed_suggestion() 361 self.edit = eveui.ItemField(parent=self, align=Align.TOTOP, placeholder=self.component.placeholder, show_suggestions_on_focus=True, type_filter=self.component.type_filter, group_filter=self.component.group_filter, category_filter=self.component.category_filter, completed_suggestion=completed_suggestion, include_type=self.component.include_type, include_group=self.component.include_group, include_category=self.component.include_category) 362 self.edit.bind(completed_suggestion=self._OnValueChanged) 363 364 def _get_completed_suggestion(self): 365 value = self.component.get_value() 366 if not value: 367 return 368 try: 369 item_type, item = value[0] 370 except TypeError: 371 return 372 373 if item_type == 'item_type': 374 return ItemTypeSuggestion(type_id=item) 375 if item_type == 'item_group': 376 return ItemGroupSuggestion(group_id=item) 377 if item_type == 'item_category': 378 return ItemCategorySuggestion(category_id=item) 379 380 def get_value(self): 381 suggestion = self.edit.completed_suggestion 382 if isinstance(suggestion, ItemTypeSuggestion): 383 return ('item_type', suggestion.type_id) 384 if isinstance(suggestion, ItemGroupSuggestion): 385 return ('item_group', suggestion.group_id) 386 if isinstance(suggestion, ItemCategorySuggestion): 387 return ('item_category', suggestion.category_id) 388 389 def set_value(self, value): 390 pass 391 392 393 class SolarSystemField(BaseField): 394 395 def ConstructBody(self): 396 location_id = self.component.get_value() 397 completed_suggestion = LocationSuggestion(location_id=location_id) if location_id else None 398 self.edit = eveui.SolarSystemField(parent=self, align=Align.TOTOP, placeholder=self.component.placeholder, show_suggestions_on_focus=True, completed_suggestion=completed_suggestion, location_id=location_id) 399 self.edit.bind(completed_suggestion=self._OnValueChanged) 400 401 def get_value(self): 402 selected = self.edit.completed_suggestion 403 if selected: 404 return selected.location_id 405 406 def set_value(self, value): 407 pass 408 409 410 class NPCFactionField(BaseField): 411 412 def ConstructBody(self): 413 faction_id = self.component.get_value() 414 completed_suggestion = FactionSuggestion(faction_id=faction_id) if faction_id else None 415 self.edit = eveui.FactionField(parent=self, align=Align.TOTOP, placeholder=self.component.placeholder, show_suggestions_on_focus=True, completed_suggestion=completed_suggestion) 416 self.edit.bind(completed_suggestion=self._OnValueChanged) 417 418 def get_value(self): 419 selected = self.edit.completed_suggestion 420 if selected: 421 return selected.faction_id 422 423 def set_value(self, value): 424 pass 425 426 427 class PlayerCorporationField(BaseField): 428 429 def ConstructBody(self): 430 corp_id = self.component.get_value() 431 completed_suggestion = OwnerIdentitySuggestion(owner_id=corp_id) if corp_id else None 432 self.edit = eveui.PlayerCorporationField(parent=self, align=Align.TOTOP, placeholder=self.component.placeholder, show_suggestions_on_focus=True, completed_suggestion=completed_suggestion) 433 self.edit.bind(completed_suggestion=self._OnValueChanged) 434 435 def get_value(self): 436 selected = self.edit.completed_suggestion 437 if selected: 438 return selected.corp_id 439 440 def set_value(self, value): 441 pass 442 443 444 class NPCCorporationField(BaseField): 445 446 def ConstructBody(self): 447 corporation_id = self.component.get_value() 448 completed_suggestion = NpcCorporationSuggestion(corporation_id=corporation_id) if corporation_id else None 449 self.edit = eveui.NpcCorporationField(parent=self, align=Align.TOTOP, placeholder=self.component.placeholder, show_suggestions_on_focus=True, completed_suggestion=completed_suggestion, filter=self.component.filter) 450 self.edit.bind(completed_suggestion=self._OnValueChanged) 451 452 def get_value(self): 453 selected = self.edit.completed_suggestion 454 if selected: 455 return selected.corporation_id 456 457 def set_value(self, value): 458 pass 459 460 461 class OrganizationField(BaseField): 462 463 def ConstructBody(self): 464 owner_id = self.component.get_value() 465 completed_suggestion = OwnerIdentitySuggestion(owner_id=owner_id) if owner_id else None 466 self.edit = eveui.OrganizationField(parent=self, align=Align.TOTOP, placeholder=self.component.placeholder, show_suggestions_on_focus=True, completed_suggestion=completed_suggestion) 467 self.edit.bind(completed_suggestion=self._OnValueChanged) 468 469 def get_value(self): 470 selected = self.edit.completed_suggestion 471 if selected: 472 return selected.owner_id 473 474 def set_value(self, value): 475 pass 476 477 478 class PlayerOrPlayerOrganizationField(BaseField): 479 480 def ConstructBody(self): 481 owner_id = self.component.get_value() 482 completed_suggestion = OwnerIdentitySuggestion(owner_id=owner_id) if owner_id else None 483 self.edit = eveui.PlayerOrPlayerOrganizationField(parent=self, align=Align.TOTOP, placeholder=self.component.placeholder, show_suggestions_on_focus=True, completed_suggestion=completed_suggestion, include_character=self.component.include_character, include_corporation=self.component.include_corporation, include_alliance=self.component.include_alliance, include_faction=self.component.include_faction) 484 self.edit.bind(completed_suggestion=self._OnValueChanged) 485 486 def get_value(self): 487 selected = self.edit.completed_suggestion 488 if selected: 489 return selected.owner_id 490 491 def set_value(self, value): 492 pass 493 494 495 class ShipAndTreeGroupField(BaseField): 496 497 def ConstructBody(self): 498 type_id = self.component.get_value() 499 completed_suggestion = ShipTypeSuggestion(type_id=type_id) if type_id else None 500 self.edit = eveui.ShipField(parent=self, align=Align.TOTOP, placeholder=self.component.placeholder, show_suggestions_on_focus=True, completed_suggestion=completed_suggestion) 501 self.edit.bind(completed_suggestion=self._OnValueChanged) 502 503 def get_value(self): 504 selected = self.edit.completed_suggestion 505 if selected: 506 return selected.owner_id 507 508 def set_value(self, value): 509 pass 510 511 512 class DateTimeField(BaseField): 513 default_clipChildren = True 514 default_padTop = -8 515 516 def _get_default_value(self): 517 if self.component.duration_datetime: 518 duration_in_seconds = self.component.duration_datetime.total_seconds() 519 time_to_advance = relativedelta.relativedelta(seconds=duration_in_seconds) 520 else: 521 time_to_advance = relativedelta.relativedelta(weeks=1) 522 now = datetime.datetime.utcnow() 523 target_time = now + time_to_advance 524 target_time_tuple = target_time.timetuple() 525 return target_time_tuple 526 527 def ConstructBody(self): 528 if self.component.time_options is not None: 529 self._buttons = [] 530 self._button_data = {} 531 _flow = FlowContainer(parent=self, align=Align.TOTOP, height=24, contentSpacing=(8, 8)) 532 self._construct_buttons_from_options(_flow) 533 date_container = ContainerAutoSize(name='date_container', parent=self, align=Align.TOTOP, alignMode=Align.TOTOP, top=32) 534 set_picker_value = self._get_default_value() 535 self.date_picker = DatePicker(name='datepicker', parent=date_container, align=Align.TOTOP, width=256, height=18) 536 now = time.gmtime() 537 self.date_picker.Startup(now=now, withTime=True, timeparts=self.component.timeparts, startYear=now[0], yearRange=self.component.year_range, set_value=set_picker_value) 538 self.date_picker.OnDateChange = self._OnValueChanged 539 self.duration_label = TextBody(name='duration_label', parent=self, align=Align.TOTOP, top=8) 540 self._update_duration_label() 541 uthread2.start_tasklet(self._time_remaining_routine) 542 543 def _time_remaining_routine(self): 544 while not self.destroyed: 545 self._update_duration_label() 546 uthread2.sleep(1) 547 548 def _pre_set_from_timedelta(self): 549 self.date_picker.SetValueFromNow(seconds=self.component.duration_datetime.total_seconds()) 550 self.component.on_field_value_changed(self.get_value()) 551 552 def _construct_buttons_from_options(self, parent): 553 options = self.component.time_options 554 for idx, option in enumerate(options): 555 period, label, duration = self._parse_option(option) 556 is_first = idx == 0 557 is_last = idx == len(options) - 1 558 self._add_button(parent, period, label, duration, is_first=is_first, is_last=is_last) 559 560 def _parse_option(self, option): 561 digits = '' 562 period = '' 563 for char in option: 564 if char.isdigit(): 565 digits = digits + char 566 else: 567 char = char.lower() 568 if char not in ('h', 'd', 'w', 'm') or len(digits) == 0: 569 raise ValueError('Invalid time option %s', option) 570 period = char 571 break 572 573 if len(digits) == 0 or len(period) == 0: 574 raise ValueError('Invalid time option %s', option) 575 duration = int(digits) 576 label = '' 577 if period == 'h': 578 label = FormatSpecificDurationWritten(duration, type='hour') 579 elif period == 'd': 580 label = FormatSpecificDurationWritten(duration, type='day') 581 elif period == 'w': 582 label = FormatSpecificDurationWritten(duration, type='week') 583 elif period == 'm': 584 label = FormatSpecificDurationWritten(duration, type='month') 585 return (period, label, duration) 586 587 def _add_button(self, parent, period, label, duration, is_first, is_last): 588 if is_first: 589 frame_type = ButtonFrameType.CUT_BOTTOM_LEFT 590 elif is_last: 591 frame_type = ButtonFrameType.CUT_BOTTOM_RIGHT 592 else: 593 frame_type = ButtonFrameType.RECTANGLE 594 button = Button(parent=parent, label=label, func=self._button_clicked, variant=ButtonVariant.GHOST, density=Density.COMPACT, frame_type=frame_type) 595 self._buttons.append(button) 596 self._button_data[button] = (period, duration) 597 598 def _deselect_buttons(self): 599 for button in self._buttons: 600 if button.variant == ButtonVariant.PRIMARY: 601 button.variant = ButtonVariant.GHOST 602 603 def _button_clicked(self, component): 604 if component is None: 605 return 606 for button in self._buttons: 607 if component == button: 608 button.variant = ButtonVariant.PRIMARY 609 elif button.variant == ButtonVariant.PRIMARY: 610 button.variant = ButtonVariant.GHOST 611 612 period, duration = self._button_data[component] 613 if period == 'h': 614 self.date_picker.SetValueFromNow(hours=duration) 615 elif period == 'd': 616 self.date_picker.SetValueFromNow(days=duration) 617 elif period == 'w': 618 self.date_picker.SetValueFromNow(weeks=duration) 619 elif period == 'm': 620 self.date_picker.SetValueFromNow(months=duration) 621 self._update_duration_label() 622 self.component.on_field_value_changed(self.get_value()) 623 624 def _is_valid_duration(self): 625 if self.date_picker.HasDatePassed(): 626 return False 627 delta = self.date_picker.GetDurationFromNow() 628 if delta.months is 0 and delta.days is 0 and delta.hours is 0 and delta.minutes < 15: 629 return False 630 if delta.years is 0: 631 return True 632 if delta.years is 1 and delta.days is 0: 633 date_now = date.today() 634 date_in_picker = self.date_picker.GetValueAsDateTime() 635 if date_now.day is date_in_picker.day and date_now.month is date_in_picker.month: 636 return True 637 return False 638 639 def _update_duration_label(self): 640 written_form = self.date_picker.GetDurationFromNowString(show_from='day') 641 if written_form: 642 label = u'{} {}'.format(GetByLabel('UI/Corporations/Goals/ChosenDuration'), written_form) 643 else: 644 label = GetByLabel('UI/Corporations/Goals/DurationInPast') 645 self.duration_label.text = label 646 if self._is_valid_duration() and self.duration_label.color is not TextColor.NORMAL: 647 self.duration_label.color = TextColor.NORMAL 648 elif self.duration_label.color is not TextColor.DANGER: 649 self.duration_label.color = TextColor.DANGER 650 651 def _OnValueChanged(self, *args): 652 super(DateTimeField, self)._OnValueChanged(*args) 653 self._deselect_buttons() 654 self._update_duration_label() 655 656 def get_value(self): 657 return self.date_picker.GetValue() 658 659 def set_value(self, value): 660 self.date_picker.SetValue(value) 661 662 663 class Divider(BaseField): 664 665 def ConstructLayout(self): 666 Line(parent=self, align=Align.TOTOP, weight=1, opacity=0.2) 667 668 def get_value(self): 669 return None 670 671 def set_value(self, value): 672 pass 673 674 675 class AccessListField(BaseField): 676 default_padTop = -8 677 678 def ConstructBody(self): 679 self.combo = Combo(name=self.component.get_id(), parent=self, align=Align.TOTOP, callback=self._OnValueChanged, options=self.component.options, select=self.component.get_value(), nothingSelectedText=self.component.placeholder) 680 681 def ConstructHeader(self): 682 pass 683 684 def ConstructIcon(self, parent): 685 pass 686 687 def ConstructLabel(self, parent): 688 pass 689 690 def ConstructHint(self, parent = None): 691 pass 692 693 def get_value(self): 694 return self.combo.GetValue() 695 696 def set_value(self, value): 697 if not value: 698 self.combo.SetNothingSelected() 699 else: 700 self.combo.SelectItemByValue(value) 701 702 703 def ConstructFields(parent, form): 704 for component in form.get_components(): 705 ConstructField(parent, component) 706 707 708 def ConstructField(parent, component, **kwargs): 709 field_cls = GetFieldClass(component) 710 return field_cls(name='{}_{}'.format(field_cls.__name__, component.__class__.__name__), parent=parent, component=component, **kwargs) 711 712 713 def GetFieldClass(component): 714 if component.field_cls: 715 return component.field_cls 716 if isinstance(component, Form): 717 return FormField 718 if isinstance(component, formComponent.Boolean): 719 return CheckboxField 720 if isinstance(component, formComponent.Text): 721 return EditField 722 if isinstance(component, formComponent.TextMultiLine): 723 return EditFieldMultiLine 724 if isinstance(component, formComponent.Integer): 725 return IntegerEditField 726 if isinstance(component, formComponent.Float): 727 return FloatEditField 728 if isinstance(component, formComponent.Enum): 729 return ComboField 730 if isinstance(component, formComponent.EveType): 731 return EveTypeField 732 if isinstance(component, formComponent.SolarSystem): 733 return SolarSystemField 734 if isinstance(component, formComponent.NPCFaction): 735 return NPCFactionField 736 if isinstance(component, formComponent.PlayerCorporation): 737 return PlayerCorporationField 738 if isinstance(component, formComponent.NPCCorporation): 739 return NPCCorporationField 740 if isinstance(component, formComponent.PlayerOrPlayerOrganization): 741 return PlayerOrPlayerOrganizationField 742 if isinstance(component, formComponent.Label): 743 return Label 744 if isinstance(component, formComponent.Divider): 745 return Divider 746 if isinstance(component, formComponent.DateTime): 747 return DateTimeField 748 if isinstance(component, formComponent.MixedHierarchy): 749 return MixedHierarchyItemFormField 750 if isinstance(component, formComponent.AccessList): 751 return AccessListField 752 if isinstance(component, formComponent.BooleanButton): 753 return CheckBoxFieldButton 754 raise ValueError('Unknown component', repr(component))