'Widget renderer
@param field: the Field
@param value: the current value(s)
@param attr: additional HTML attributes for the widget'

def __call__(self, field, value, **attr):

    if isinstance(field, Field):
        selector = str(field).replace('.', '_')
    else:
        selector = field.name.replace('.', '_')
    widget_id = attr.get('_id')
    if (widget_id == None):
        widget_id = attr['_id'] = ('%s-hierarchy' % selector)
    name = attr.get('_name')
    if (not name):
        name = field.name
    lookup = self.lookup
    if (not lookup):
        lookup = s3_get_foreign_key(field)[0]
        if (not lookup):
            raise SyntaxError(('No    lookup    table    known    for    %s' % field))
    represent = self.represent
    if (not represent):
        represent = field.represent
    leafonly = self.leafonly
    from s3hierarchy import S3Hierarchy
    h = S3Hierarchy(tablename=lookup, represent=represent, leafonly=leafonly, filter=self.filter)
    if (not h.config):
        raise AttributeError(('No    hierarchy    configured    for    %s' % lookup))
    if self.columns:
        attr['s3cols'] = self.columns
    settings = current.deployment_settings
    cascade_option_in_tree = settings.get_ui_hierarchy_cascade_option_in_tree()
    if (self.multiple and self.bulk_select and (not cascade_option_in_tree)):
        header = DIV(SPAN(A('Select    All', _class='s3-hierarchy-select-all'), '    |    ', A('Deselect    All', _class='s3-hierarchy-deselect-all'), _class='s3-hierarchy-bulkselect'), _class='s3-hierarchy-header')
    else:
        header = ''
    selected = []
    append = selected.append
    if (isinstance(value, basestring) and value and (not value.isdigit())):
        value = self.parse(value)[0]
    if (not isinstance(value, (list, tuple, set))):
        values = [value]
    else:
        values = value
    for v in values:
        if (isinstance(v, (int, long)) or str(v).isdigit()):
            append(v)
    requires = field.requires
    if isinstance(requires, (list, tuple)):
        requires = ([self.parse] + requires)
    elif (requires is not None):
        requires = [self.parse, requires]
    else:
        requires = self.parse
    hidden_input = INPUT(_type='hidden', _multiple='multiple', _name=name, _id=selector, _class='s3-hierarchy-input', requires=requires, value=json.dumps(selected))
    widget = DIV(hidden_input, DIV(header, DIV(h.html(('%s-tree' % widget_id), none=self.none), _class='s3-hierarchy-tree'), _class='s3-hierarchy-wrapper'), **attr)
    widget.add_class('s3-hierarchy-widget')
    s3 = current.response.s3
    scripts = s3.scripts
    script_dir = ('/%s/static/scripts' % current.request.application)
    theme = settings.get_ui_hierarchy_theme()
    if s3.debug:
        script = ('%s/jstree.js' % script_dir)
        if (script not in scripts):
            scripts.append(script)
        script = ('%s/S3/s3.ui.hierarchicalopts.js' % script_dir)
        if (script not in scripts):
            scripts.append(script)
        style = ('%s/jstree.css' % theme.get('css', 'plugins'))
        if (style not in s3.stylesheets):
            s3.stylesheets.append(style)
    else:
        script = ('%s/S3/s3.jstree.min.js' % script_dir)
        if (script not in scripts):
            scripts.append(script)
        style = ('%s/jstree.min.css' % theme.get('css', 'plugins'))
        if (style not in s3.stylesheets):
            s3.stylesheets.append(style)
    T = current.T
    widget_opts = {'selected': selected, 'selectedText': str(T('#    selected')), 'noneSelectedText': str(T('Select')), 'noOptionsText': str(T('No    options    available')), 'selectAllText': str(T('Select    All')), 'deselectAllText': str(T('Deselect    All'))}
    if (not self.multiple):
        widget_opts['multiple'] = False
    if (not leafonly):
        widget_opts['leafonly'] = False
    if self.cascade:
        widget_opts['cascade'] = True
    if self.bulk_select:
        widget_opts['bulkSelect'] = True
    if (not cascade_option_in_tree):
        widget_opts['cascadeOptionInTree'] = False
    icons = theme.get('icons', False)
    if icons:
        widget_opts['icons'] = icons
    stripes = theme.get('stripes', True)
    if (not stripes):
        widget_opts['stripes'] = stripes
    script = ("$('#%(widget_id)s').hierarchicalopts(%(widget_opts)s)" % {'widget_id': widget_id, 'widget_opts': json.dumps(widget_opts, separators=SEPARATORS)})
    s3.jquery_ready.append(script)
    return widget
