Home | Trees | Indices | Help |
|
---|
|
1 # Copyright (C) 2012 Vaadin Ltd. 2 # Copyright (C) 2012 Richard Lincoln 3 # 4 # Licensed under the Apache License, Version 2.0 (the "License"); 5 # you may not use this file except in compliance with the License. 6 # You may obtain a copy of the License at 7 # 8 # http://www.apache.org/licenses/LICENSE-2.0 9 # 10 # Unless required by applicable law or agreed to in writing, software 11 # distributed under the License is distributed on an "AS IS" BASIS, 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 16 """Provides an easy way of creating and managing sets of fields.""" 17 18 from warnings import warn 19 20 from muntjac.data.item import IEditor, IItem 21 from muntjac.data.buffered import IBuffered, SourceException 22 from muntjac.data.validatable import IValidatable 23 from muntjac.data.validator import InvalidValueException 24 from muntjac.data.property import IValueChangeListener 25 from muntjac.event.action_manager import ActionManager 26 27 from muntjac.ui.abstract_field import AbstractField 28 from muntjac.ui.default_field_factory import DefaultFieldFactory 29 from muntjac.ui.abstract_component import AbstractComponent 30 from muntjac.ui.field import IField 31 from muntjac.ui.custom_layout import CustomLayout 32 from muntjac.ui.component_container import IComponentContainer 33 from muntjac.ui.grid_layout import GridLayout 34 from muntjac.ui.field_factory import IFieldFactory 35 from muntjac.ui.form_layout import FormLayout 36 from muntjac.ui.horizontal_layout import HorizontalLayout 37 from muntjac.ui.select import Select 38 from muntjac.event.action import INotifier 39 40 from muntjac.terminal.composite_error_message import CompositeErrorMessage 41 4244 """Form component provides easy way of creating and managing sets fields. 45 46 C{Form} is a container for fields implementing L{IField} 47 interface. It provides support for any layouts and provides buffering 48 interface for easy connection of commit and discard buttons. All the form 49 fields can be customized by adding validators, setting captions and icons, 50 setting immediateness, etc. Also direct mechanism for replacing existing 51 fields with selections is given. 52 53 C{Form} provides customizable editor for classes implementing 54 L{IItem} interface. Also the form itself implements 55 this interface for easier connectivity to other items. To use the form as 56 editor for an item, just connect the item to form with 57 L{Form.setItemDataSource}. If only a part of the item needs to 58 be edited, L{Form.setItemDataSource} can be used 59 instead. After the item has been connected to the form, the automatically 60 created fields can be customized and new fields can be added. If you need 61 to connect a class that does not implement L{IItem} 62 interface, most properties of any class following bean pattern, can be 63 accessed trough C{muntjac.data.util.BeanItem}. 64 65 @author: Vaadin Ltd. 66 @author: Richard Lincoln 67 @version: 1.1.2 68 """ 69 70 CLIENT_WIDGET = None #ClientWidget(VForm) 711084 1085 109373 """Constructs a new form with given L{Layout} and 74 L{FormFieldFactory}. 75 76 By default the form uses L{FormLayout}. 77 78 @param formLayout: 79 the layout of the form. 80 @param fieldFactory: 81 the IFieldFactory of the form. 82 """ 83 self._propertyValue = None 84 85 #: Layout of the form. 86 self._layout = None 87 88 #: IItem connected to this form as datasource. 89 self._itemDatasource = None 90 91 #: Ordered list of property ids in this editor. 92 self._propertyIds = list() 93 94 #: Current buffered source exception. 95 self._currentBufferedSourceException = None 96 97 #: Is the form in write trough mode. 98 self._writeThrough = True 99 100 #: Is the form in read trough mode. 101 self._readThrough = True 102 103 #: Mapping from propertyName to corresponding field. 104 self._fields = dict() 105 106 #: Form may act as an IItem, its own properties are stored here. 107 self._ownProperties = dict() 108 109 #: IField factory for this form. 110 self._fieldFactory = None 111 112 #: Visible item properties. 113 self._visibleItemProperties = None 114 115 #: Form needs to repaint itself if child fields value changes due 116 # possible change in form validity. 117 # 118 # TODO introduce ValidityChangeEvent (#6239) and start using it instead. 119 # See e.g. DateField#notifyFormOfValidityChange(). 120 self._fieldValueChangeListener = FieldValueChangeListener(self) 121 122 self._formFooter = None 123 124 #: If this is true, commit implicitly calls setValidationVisible(true). 125 self._validationVisibleOnCommit = True 126 127 # special handling for gridlayout; remember initial cursor pos 128 self._gridlayoutCursorX = -1 129 self._gridlayoutCursorY = -1 130 131 #: Keeps track of the Actions added to this component, and manages the 132 # painting and handling as well. Note that the extended AbstractField 133 # is a L{ShortcutNotifier} and has a actionManager that delegates 134 # actions to the containing window. This one does not delegate. 135 self._ownActionManager = ActionManager(self) 136 137 if fieldFactory is None: 138 fieldFactory = DefaultFieldFactory.get() 139 140 super(Form, self).__init__() 141 142 self.setLayout(formLayout) 143 self.setFormFieldFactory(fieldFactory) 144 self.setValidationVisible(False) 145 self.setWidth(100, self.UNITS_PERCENTAGE)146 147149 super(Form, self).paintContent(target) 150 151 self._layout.paint(target) 152 if self._formFooter is not None: 153 self._formFooter.paint(target) 154 155 if self._ownActionManager is not None: 156 self._ownActionManager.paintActions(None, target)157 158160 super(Form, self).changeVariables(source, variables) 161 162 # Actions 163 if self._ownActionManager is not None: 164 self._ownActionManager.handleActions(variables, self)165 166168 """The error message of a Form is the error of the first field with 169 a non-empty error. 170 171 Empty error messages of the contained fields are skipped, because an 172 empty error indicator would be confusing to the user, especially if 173 there are errors that have something to display. This is also the 174 reason why the calculation of the error message is separate from 175 validation, because validation fails also on empty errors. 176 """ 177 # Reimplement the checking of validation error by using 178 # getErrorMessage() recursively instead of validate(). 179 validationError = None 180 if self.isValidationVisible(): 181 for i in self._propertyIds: 182 f = self._fields.get(i) 183 if isinstance(f, AbstractComponent): 184 field = f 185 186 validationError = field.getErrorMessage() 187 if validationError is not None: 188 # Show caption as error for fields with empty errors 189 if '' == str(validationError): 190 e = InvalidValueException(field.getCaption()) 191 validationError = e 192 break 193 elif isinstance(f, IField) and not f.isValid(): 194 # Something is wrong with the field, but no proper 195 # error is given. Generate one. 196 e = InvalidValueException(field.getCaption()) 197 validationError = e 198 break 199 200 # Return if there are no errors at all 201 if (self.getComponentError() is None and validationError is None 202 and self._currentBufferedSourceException is None): 203 return None 204 205 # Throw combination of the error types 206 return CompositeErrorMessage([self.getComponentError(), 207 validationError, self._currentBufferedSourceException])208 209211 """Controls the making validation visible implicitly on commit. 212 213 Having commit() call setValidationVisible(True) implicitly is the 214 default behaviour. You can disable the implicit setting by setting 215 this property as false. 216 217 It is useful, because you usually want to start with the form free 218 of errors and only display them after the user clicks Ok. You can 219 disable the implicit setting by setting this property as false. 220 221 @param makeVisible: 222 If true (default), validation is made visible when 223 commit() is called. If false, the visibility is left 224 as it is. 225 """ 226 self._validationVisibleOnCommit = makeVisible227 228230 """Is validation made automatically visible on commit? 231 232 See setValidationVisibleOnCommit(). 233 234 @return: true if validation is made automatically visible on commit. 235 """ 236 return self._validationVisibleOnCommit237 238240 # Commit changes to the data source. 241 242 problems = None 243 244 # Only commit on valid state if so requested 245 if not self.isInvalidCommitted() and not self.isValid(): 246 # The values are not ok and we are told not to commit invalid 247 # values 248 if self._validationVisibleOnCommit: 249 self.setValidationVisible(True) 250 251 # Find the first invalid value and throw the exception 252 self.validate() 253 254 # Try to commit all 255 for i in self._propertyIds: 256 try: 257 f = self._fields.get(i) 258 # Commit only non-readonly fields. 259 if not f.isReadOnly(): 260 f.commit() 261 except SourceException, e: 262 if problems is None: 263 problems = list() 264 problems.append(e) 265 266 # No problems occurred 267 if problems is None: 268 if self._currentBufferedSourceException is not None: 269 self._currentBufferedSourceException = None 270 self.requestRepaint() 271 return 272 273 # Commit problems 274 causes = [None] * len(problems) 275 index = 0 276 for i in problems: 277 causes[index] = i 278 index += 1 # post increment 279 280 e = SourceException(self, causes) 281 self._currentBufferedSourceException = e 282 self.requestRepaint() 283 raise e284 285287 # Discards local changes and refresh values from the data source 288 problems = None 289 290 # Try to discard all changes 291 for i in self._propertyIds: 292 try: 293 self._fields.get(i).discard() 294 except SourceException, e: 295 if problems is None: 296 problems = list() 297 problems.append(e) 298 299 # No problems occurred 300 if problems is None: 301 if self._currentBufferedSourceException is not None: 302 self._currentBufferedSourceException = None 303 self.requestRepaint() 304 return 305 306 # Discards problems occurred 307 causes = [None] * len(problems) 308 index = 0 309 for i in problems: 310 causes[index] = i 311 index += 1 # post increment 312 313 e = SourceException(self, causes) 314 self._currentBufferedSourceException = e 315 self.requestRepaint() 316 raise e317 318320 # Is the object modified but not committed? 321 322 for i in self._propertyIds: 323 f = self._fields.get(i) 324 if f is not None and f.isModified(): 325 return True 326 327 return False328 329 333 334 338 339341 # Sets the editor's read-through mode to the specified status. 342 if readThrough != self._readThrough: 343 self._readThrough = readThrough 344 for i in self._propertyIds: 345 self._fields.get(i).setReadThrough(readThrough)346 347349 # Sets the editor's read-through mode to the specified status. 350 if writeThrough != self._writeThrough: 351 self._writeThrough = writeThrough 352 for i in self._propertyIds: 353 self._fields.get(i).setWriteThrough(writeThrough)354 355357 """Adds a new property to form and create corresponding field. 358 359 @see: L{IItem.addItemProperty} 360 """ 361 # Checks inputs 362 if (idd is None) or (prop is None): 363 raise ValueError, 'Id and property must be non-null' 364 365 # Checks that the property id is not reserved 366 if self._propertyIds.contains(idd): 367 return False 368 369 self._propertyIds.add(idd) 370 self._ownProperties[idd] = prop 371 372 # Gets suitable field 373 field = self._fieldFactory.createField(self, idd, self) 374 if field is None: 375 return False 376 377 # Configures the field 378 field.setPropertyDataSource(prop) 379 380 # Register and attach the created field 381 self.addField(idd, field) 382 383 return True384 385387 """Registers the field with the form and adds the field to the 388 form layout. 389 390 The property id must not be already used in the form. 391 392 This field is added to the layout using the L{attachField} method. 393 394 @param propertyId: 395 the Property id the the field. 396 @param field: 397 the field which should be added to the form. 398 """ 399 self.registerField(propertyId, field) 400 self.attachField(propertyId, field) 401 self.requestRepaint()402 403405 """Register the field with the form. All registered fields are 406 validated when the form is validated and also committed when the 407 form is committed. 408 409 The property id must not be already used in the form. 410 411 @param propertyId: 412 the Property id of the field. 413 @param field: 414 the IField that should be registered 415 """ 416 if propertyId is None or field is None: 417 return 418 419 self._fields[propertyId] = field 420 field.addListener(self._fieldValueChangeListener, 421 IValueChangeListener) 422 if propertyId not in self._propertyIds: 423 # adding a field directly 424 self._propertyIds.append(propertyId) 425 426 # Update the read and write through status and immediate to match the 427 # form. 428 # Should this also include invalidCommitted (#3993)? 429 field.setReadThrough(self._readThrough) 430 field.setWriteThrough(self._writeThrough) 431 if self.isImmediate() and isinstance(field, AbstractComponent): 432 field.setImmediate(True)433 434436 """Adds the field to the form layout. 437 438 The field is added to the form layout in the default position (the 439 position used by L{Layout.addComponent}. If the 440 underlying layout is a L{CustomLayout} the field is added to 441 the CustomLayout location given by the string representation of the 442 property id using L{CustomLayout.addComponent}. 443 444 Override this method to control how the fields are added to the 445 layout. 446 """ 447 if propertyId is None or field is None: 448 return 449 450 if isinstance(self._layout, CustomLayout): 451 self._layout.addComponent(field, str(propertyId)) 452 else: 453 self._layout.addComponent(field)454 455457 """The property identified by the property id. 458 459 The property data source of the field specified with property id is 460 returned. If there is a (with specified property id) having no data 461 source, the field is returned instead of the data source. 462 463 @see: L{IItem.getItemProperty} 464 """ 465 field = self._fields.get(idd) 466 if field is None: 467 # field does not exist or it is not (yet) created for 468 # this property 469 return self._ownProperties.get(idd) 470 471 prop = field.getPropertyDataSource() 472 473 if prop is not None: 474 return prop 475 else: 476 return field477 478480 """Gets the field identified by the propertyid. 481 482 @param propertyId: 483 the id of the property. 484 """ 485 return self._fields.get(propertyId)486 487 490 491493 """Removes the property and corresponding field from the form. 494 495 @see: L{IItem.removeItemProperty} 496 """ 497 if idd in self._ownProperties: 498 del self._ownProperties[idd] 499 500 field = self._fields.get(idd) 501 502 if field is not None: 503 self._propertyIds.remove(idd) 504 del self._fields[idd] 505 self.detachField(field) 506 field.removeListener(self._fieldValueChangeListener, 507 IValueChangeListener) 508 return True 509 510 return False511 512514 """Called when a form field is detached from a Form. Typically when 515 a new IItem is assigned to Form via L{setItemDataSource}. 516 517 Override this method to control how the fields are removed from the 518 layout. 519 520 @param field: 521 the field to be detached from the forms layout. 522 """ 523 p = field.getParent() 524 if isinstance(p, IComponentContainer): 525 p.removeComponent(field)526 527529 """Removes all properties and fields from the form. 530 531 @return: the Success of the operation. Removal of all fields succeeded 532 if (and only if) the return value is C{True}. 533 """ 534 properties = list(self._propertyIds) 535 success = True 536 537 for i in range(len(properties)): 538 if not self.removeItemProperty(properties[i]): 539 success = False 540 541 return success542 543 546 547549 """Set the item datasource for the form, but limit the form contents to 550 specified properties of the item. 551 552 Setting item datasource clears any fields, the form might contain and 553 adds the specified the properties as fields to the form, in the 554 specified order. 555 556 @see: L{Viewer.setItemDataSource} 557 """ 558 if propertyIds is None: 559 if newDataSource is not None: 560 self.setItemDataSource(newDataSource, 561 newDataSource.getItemPropertyIds()) 562 else: 563 self.setItemDataSource(newDataSource, []) 564 else: 565 if isinstance(self._layout, GridLayout): 566 gl = self._layout 567 if self._gridlayoutCursorX == -1: 568 # first setItemDataSource, remember initial cursor 569 self._gridlayoutCursorX = gl.getCursorX() 570 self._gridlayoutCursorY = gl.getCursorY() 571 else: 572 # restore initial cursor 573 gl.setCursorX(self._gridlayoutCursorX) 574 gl.setCursorY(self._gridlayoutCursorY) 575 576 # Removes all fields first from the form 577 self.removeAllProperties() 578 579 # Sets the datasource 580 self._itemDatasource = newDataSource 581 582 # If the new datasource is null, just set null datasource 583 if self._itemDatasource is None: 584 self.requestRepaint() 585 return 586 587 # Adds all the properties to this form 588 for idd in propertyIds: 589 prop = self._itemDatasource.getItemProperty(idd) 590 if idd is not None and prop is not None: 591 f = self._fieldFactory.createField(self._itemDatasource, 592 idd, self) 593 if f is not None: 594 f.setPropertyDataSource(prop) 595 self.addField(idd, f)596 597599 """Gets the layout of the form. 600 601 By default form uses C{OrderedLayout} with C{form}-style. 602 603 @return: the Layout of the form. 604 """ 605 return self._layout606 607609 """Sets the layout of the form. 610 611 By default form uses C{OrderedLayout} with C{form}-style. 612 613 @param newLayout: 614 the Layout of the form. 615 """ 616 # Use orderedlayout by default 617 if newLayout is None: 618 newLayout = FormLayout() 619 620 # reset cursor memory 621 self._gridlayoutCursorX = -1 622 self._gridlayoutCursorY = -1 623 624 # Move fields from previous layout 625 if self._layout is not None: 626 properties = list(self._propertyIds) 627 for i in range(len(properties)): 628 f = self.getField(properties[i]) 629 self.detachField(f) 630 if isinstance(newLayout, CustomLayout): 631 newLayout.addComponent(f, str(properties[i])) 632 else: 633 newLayout.addComponent(f) 634 635 self._layout.setParent(None) 636 637 # Replace the previous layout 638 newLayout.setParent(self) 639 self._layout = newLayout640 641643 """Sets the form field to be selectable from static list of changes. 644 645 The list values and descriptions are given as array. The value-array 646 must contain the current value of the field and the lengths of the 647 arrays must match. Null values are not supported. 648 649 @param propertyId: 650 the id of the property. 651 @param values: 652 @param descriptions: 653 @return: the select property generated 654 """ 655 # Checks the parameters 656 if propertyId is None or values is None or descriptions is None: 657 raise ValueError, 'All parameters must be non-null' 658 659 if len(values) != len(descriptions): 660 raise ValueError, \ 661 'Value and description list are of different size' 662 663 # Gets the old field 664 oldField = self._fields.get(propertyId) 665 if oldField is None: 666 raise ValueError, ('IField with given propertyid \'' 667 + str(propertyId) + '\' can not be found.') 668 669 if oldField.getPropertyDataSource() is None: 670 value = oldField.getValue() 671 else: 672 value = oldField.getPropertyDataSource().getValue() 673 674 # Checks that the value exists and check if the select should 675 # be forced in multiselect mode 676 found = False 677 isMultiselect = False 678 i = 0 679 while i < len(values) and not found: 680 if (values[i] == value 681 or (value is not None and value == values[i])): 682 found = True 683 i += 1 684 685 if value is not None and not found: 686 if isinstance(value, (list, set)): 687 for val in value: 688 found = False 689 i = 0 690 while i < len(values) and not found: 691 if (values[i] == val or 692 (val is not None and val == values[i])): 693 found = True 694 i += 1 695 if not found: 696 raise ValueError, ('Currently selected value \'' 697 + val + '\' of property \'' 698 + str(propertyId) + '\' was not found') 699 700 isMultiselect = True 701 else: 702 raise ValueError, ('Current value \'' 703 + value + '\' of property \'' 704 + str(propertyId) + '\' was not found') 705 706 # Creates the new field matching to old field parameters 707 newField = Select() 708 if isMultiselect: 709 newField.setMultiSelect(True) 710 711 newField.setCaption(oldField.getCaption()) 712 newField.setReadOnly(oldField.isReadOnly()) 713 newField.setReadThrough(oldField.isReadThrough()) 714 newField.setWriteThrough(oldField.isWriteThrough()) 715 716 # Creates the options list 717 newField.addContainerProperty('desc', str, '') 718 newField.setItemCaptionPropertyId('desc') 719 for idd in values: 720 if idd is None: 721 idd = newField.addItem() 722 item = newField.getItem(idd) 723 newField.setNullSelectionItemId(idd) 724 else: 725 item = newField.addItem(idd) 726 727 if item is not None: 728 item.getItemProperty('desc').setValue( str(descriptions[i]) ) 729 730 # Sets the property data source 731 prop = oldField.getPropertyDataSource() 732 oldField.setPropertyDataSource(None) 733 newField.setPropertyDataSource(prop) 734 735 # Replaces the old field with new one 736 self._layout.replaceComponent(oldField, newField) 737 self._fields[propertyId] = newField 738 newField.addListener(self._fieldValueChangeListener, 739 prop.IValueChangeListener) 740 oldField.removeListener(self._fieldValueChangeListener, 741 prop.IValueChangeListener) 742 743 return newField744 745747 """Notifies the component that it is connected to an application 748 749 @see: L{IComponent.attach} 750 """ 751 super(Form, self).attach() 752 self._layout.attach() 753 if self._formFooter is not None: 754 self._formFooter.attach()755 756758 """Notifies the component that it is detached from the application. 759 760 @see: L{IComponent.detach} 761 """ 762 super(Form, self).detach() 763 self._layout.detach() 764 if self._formFooter is not None: 765 self._formFooter.detach()766 767769 """Tests the current value of the object against all registered 770 validators 771 772 @see: L{IValidatable.isValid} 773 """ 774 valid = True 775 776 for i in self._propertyIds: 777 valid &= self._fields[i].isValid() 778 779 return valid and super(Form, self).isValid()780 781783 """Checks the validity of the validatable. 784 785 @see: L{IValidatable.validate} 786 """ 787 super(Form, self).validate() 788 for i in self._propertyIds: 789 self._fields[i].validate()790 791793 """Checks the validabtable object accept invalid values. 794 795 @see: L{IValidatable.isInvalidAllowed} 796 """ 797 return True798 799801 """Should the validabtable object accept invalid values. 802 803 @see: L{IValidatable.setInvalidAllowed} 804 """ 805 raise NotImplementedError806 807809 """Sets the component's to read-only mode to the specified state. 810 811 @see: L{IComponent.setReadOnly} 812 """ 813 super(Form, self).setReadOnly(readOnly) 814 for i in self._propertyIds: 815 self._fields[i].setReadOnly(readOnly)816 817819 """Sets the field factory of Form. 820 821 C{IFieldFactory} is used to create fields for form properties. By 822 default the form uses BaseFieldFactory to create IField instances. 823 824 @param fieldFactory: 825 the New factory used to create the fields. 826 @see: L{IField} 827 @see: L{FormFieldFactory} 828 @deprecated: use L{setFormFieldFactory} instead 829 """ 830 warn('use setFormFieldFactory() instead', DeprecationWarning) 831 self._fieldFactory = fieldFactory832 833835 """Sets the field factory used by this Form to genarate Fields for 836 properties. 837 838 L{FormFieldFactory} is used to create fields for form properties. 839 L{DefaultFieldFactory} is used by default. 840 841 @param fieldFactory: 842 the new factory used to create the fields. 843 @see: L{IField} 844 @see: L{FormFieldFactory} 845 """ 846 self._fieldFactory = fieldFactory847 848850 """Get the field factory of the form. 851 852 @return: the FormFieldFactory Factory used to create the fields. 853 """ 854 return self._fieldFactory855 856858 """Get the field factory of the form. 859 860 @return: the IFieldFactory Factory used to create the fields. 861 @deprecated: Use L{getFormFieldFactory} instead. Set the 862 FormFieldFactory using L{setFormFieldFactory}. 863 """ 864 warn('Use getFormFieldFactory() instead', DeprecationWarning) 865 866 if isinstance(self._fieldFactory, IFieldFactory): 867 return self._fieldFactory 868 869 return None870 871873 """Gets the field type. 874 875 @see: L{AbstractField.getType} 876 """ 877 if self.getPropertyDataSource() is not None: 878 return self.getPropertyDataSource().getType() 879 return object880 881883 """Sets the internal value. 884 885 This is relevant when the Form is used as IField. 886 887 @see: L{AbstractField.setInternalValue} 888 """ 889 # Stores the old value 890 oldValue = self._propertyValue 891 892 # Sets the current Value 893 super(Form, self).setInternalValue(newValue) 894 self._propertyValue = newValue 895 896 # Ignores form updating if data object has not changed. 897 if oldValue != newValue: 898 self.setFormDataSource(newValue, self.getVisibleItemProperties())899 900902 """Gets the first focusable field in form. If there are enabled, 903 non-read-only fields, the first one of them is returned. Otherwise, 904 the field for the first property (or null if none) is returned. 905 906 @return: the IField. 907 """ 908 if self.getItemPropertyIds() is not None: 909 for idd in self.getItemPropertyIds(): 910 if idd is not None: 911 field = self.getField(idd) 912 if field.isEnabled() and not field.isReadOnly(): 913 return field 914 915 # fallback: first field if none of the fields is enabled 916 # and writable 917 idd = iter( self.getItemPropertyIds() ).next() 918 if idd is not None: 919 return self.getField(idd) 920 921 return None922 923925 """Updates the internal form datasource. 926 927 Method setFormDataSource. 928 """ 929 # If data is an item use it. 930 item = None 931 if isinstance(data, IItem): 932 item = data 933 elif data is not None: 934 raise NotImplementedError 935 #item = BeanItem(data) 936 937 # Sets the datasource to form 938 if item is not None and properties is not None: 939 # Shows only given properties 940 self.setItemDataSource(item, properties) 941 else: 942 # Shows all properties 943 self.setItemDataSource(item)944 945947 """Returns the visibleProperties. 948 949 @return: the collection of visible IItem properites. 950 """ 951 return self._visibleItemProperties952 953955 """Sets the visibleProperties. 956 957 @param visibleProperties: 958 the visibleProperties to set. 959 """ 960 self._visibleItemProperties = visibleProperties 961 value = self.getValue() 962 if value is None: 963 value = self._itemDatasource 964 self.setFormDataSource(value, self.getVisibleItemProperties())965 966968 """Focuses the first field in the form. 969 970 @see: L{IFocusable.focus} 971 """ 972 f = self.getFirstFocusableField() 973 if f is not None: 974 f.focus()975 976978 """Sets the Tabulator index of this Focusable component. 979 980 @see: L{IFocusable.setTabIndex} 981 """ 982 super(Form, self).setTabIndex(tabIndex) 983 for i in self.getItemPropertyIds(): 984 i.setTabIndex(tabIndex)985 986988 """Setting the form to be immediate also sets all the fields 989 of the form to the same state. 990 """ 991 super(Form, self).setImmediate(immediate) 992 for f in self._fields.values(): 993 if isinstance(f, AbstractComponent): 994 f.setImmediate(immediate)995 996998 """Form is empty if all of its fields are empty.""" 999 for f in self._fields.values(): 1000 if isinstance(f, AbstractField): 1001 if not f.isEmpty(): 1002 return False 1003 return True1004 10051007 """Adding validators directly to form is not supported. 1008 1009 Add the validators to form fields instead. 1010 """ 1011 raise NotImplementedError1012 1013 1025 1026 1036 10371039 super(Form, self).setEnabled(enabled) 1040 if self.getParent() is not None and not self.getParent().isEnabled(): 1041 # some ancestor still disabled, don't update children 1042 return 1043 else: 1044 self.getLayout().requestRepaintAll()1045 10461048 """Gets the L{ActionManager} responsible for handling 1049 L{Action}s added to this Form. 1050 1051 Note that Form has another ActionManager inherited from 1052 L{AbstractField}. The ownActionManager handles Actions 1053 attached to this Form specifically, while the ActionManager 1054 in AbstractField delegates to the containing Window (i.e global 1055 Actions). 1056 """ 1057 if self._ownActionManager is None: 1058 self._ownActionManager = ActionManager(self) 1059 return self._ownActionManager1060 1061 1064 10651067 if self._ownActionManager is not None: 1068 self._ownActionManager.removeActionHandler(actionHandler)1069 10701072 """Removes all action handlers""" 1073 if self._ownActionManager is not None: 1074 self._ownActionManager.removeAllActionHandlers()1075 1076 1079 1080
Home | Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Sat Jul 6 13:41:14 2013 | http://epydoc.sourceforge.net |