FieldRegistry.py 5.31 KB
Newer Older
1 2
import os
import OFS
3
from App.ImageFile import ImageFile
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
from FieldHelpTopic import FieldHelpTopic

class FieldRegistry:
    """A registry of fields, maintaining a dictionary with
    the meta_type of the field classes as key and the field class as
    values. Updates the Form as necessary as well.
    """
    def __init__(self):
        """Initializer of FieldRegistry.
        """
        self._fields = {}

    def get_field_class(self, fieldname):
        """Get a certain field class by its name (meta_type)
        fieldname -- the name of the field to get from the registry
        """
        return self._fields[fieldname]

    def get_field_classes(self):
        """Return all fields.
        """
        return self._fields
    
    def registerField(self, field_class, icon=None):
        """Register field with Formulator.
        field_class -- the class of the field to be registered
        icon        -- optional filename of the icon
        """
        # put it in registry dictionary
        self._fields[field_class.meta_type] = field_class
        # set up dummy fields in field's form
        initializeFieldForm(field_class)
        # set up the icon if a filename is supplied
        if icon:
            setupIcon(field_class, icon, 'Formulator')

    def registerFieldHelp(self, *args, **kw):
        """XXX: this is a quick fix to avoid bloating the ZODB.
           Proper fix should only add FieldHelp when it's missing.
        """
        pass

    def initializeFields(self):
        """Initialize all field classes in field forms to use actual field
        objects so we can finally eat our own dogfood.
        """
        # for each field, realize fields in form
        # this is finally possible as all field classes are now
        # fully defined.
        for field_class in self._fields.values():
            field_class.form._realize_fields()
            field_class.override_form._realize_fields()
            field_class.tales_form._realize_fields()
            
# initialize registry as a singleton
FieldRegistry = FieldRegistry()
        
def initializeFieldForm(field_class):
    """Initialize the properties (fields and values) on a particular
    field class. Also add the tales and override methods.
    """
    from Form import BasicForm
    from DummyField import fields
    
    form = BasicForm()
    override_form = BasicForm()
    tales_form = BasicForm()
    for field in getPropertyFields(field_class.widget):
        form.add_field(field, "widget")
        tales_field = fields.TALESField(field.id,
                                        title=field.get_value('title'),
                                        description="",
                                        default="",
                                        display_width=40,
                                        required=0)
        tales_form.add_field(tales_field, "widget")
        
        method_field = fields.MethodField(field.id,
                                          title=field.get_value("title"),
                                          description="",
                                          default="",
                                          required=0)
        override_form.add_field(method_field, "widget")
        
    for field in getPropertyFields(field_class.validator): 
        form.add_field(field, "validator")
        tales_field = fields.TALESField(field.id,
                                        title=field.get_value('title'),
                                        description="",
                                        default="",
                                        display_with=40,
                                        required=0)
        tales_form.add_field(tales_field, "validator")
        
        method_field = fields.MethodField(field.id,
                                          title=field.get_value("title"),
                                          description="",
                                          default="",
                                          required=0)
        override_form.add_field(method_field, "validator")
        
    field_class.form = form         
    field_class.override_form = override_form
    field_class.tales_form = tales_form
    
def getPropertyFields(obj):
    """Get property fields from a particular widget/validator.
    """
    fields = []
    for property_name in obj.property_names:
        fields.append(getattr(obj, property_name))
    return fields

def setupIcon(klass, icon, repository):
    """Load icon into Zope image object and put it in Zope's
    repository for use by the ZMI, for a particular class.
    klass -- the class of the field we're adding
    icon  -- the icon
    """
    # set up misc_ respository if not existing yet
    if not hasattr(OFS.misc_.misc_, repository):
        setattr(OFS.misc_.misc_, 
                repository, 
                OFS.misc_.Misc_(repository, {}))
        
    # get name of icon in the misc_ directory
    icon_name = os.path.split(icon)[1]
        
    # set up image object from icon file
    icon_image = ImageFile(icon, globals())
    icon_image.__roles__ = None

    # put icon image object in misc_/Formulator/
    getattr(OFS.misc_.misc_, repository)[icon_name] = icon_image

    # set icon attribute in field_class to point to this image obj
    setattr(klass, 'icon', 'misc_/%s/%s' %
            (repository, icon_name))