Example #1
0
    def __init__(self,
                 parent,
                 minimum,
                 maximum,
                 value,
                 step=1,
                 bar_size=None,
                 show_value=False,
                 bar_text_color='white',
                 bar_color=(.3, .3, .3, 1),
                 x=None,
                 y=None,
                 z=None,
                 width=SliderCommon.slider_size,
                 height='100%',
                 bgcolor='gray',
                 **kw):

        self.minimum = util.parse_value(minimum, 0)
        self.type = type(self.minimum)
        self.maximum = util.parse_value(maximum, 0)
        self.range = self.maximum - self.minimum
        self._value = util.parse_value(value, 0)
        self.step = util.parse_value(step, 0)
        self.show_value = show_value
        self.bar_spec = bar_size
        self.bar_color = util.parse_color(bar_color)
        self.bar_text_color = util.parse_color(bar_text_color)
        self.bar = self.dbut = self.ubut = None

        super().__init__(parent, x, y, z, width, height, bgcolor=bgcolor, **kw)
Example #2
0
    def __init__(self,
                 parent,
                 x,
                 y,
                 z,
                 width,
                 height,
                 padding=0,
                 border=None,
                 bgcolor=None,
                 is_visible=True,
                 is_enabled=True,
                 is_transparent=False,
                 children=None,
                 id=None,
                 classes=()):
        self.parent = parent
        self.id = id or self.allocateID()
        self.classes = classes
        self.children = children or list()

        # colors, border and padding
        self.bgcolor = util.parse_color(bgcolor)
        self.border = util.parse_color(border)
        self._padding = util.parse_value(padding)
        if border:
            # force enough room to see the border
            self._padding += 1

        # save off the geometry specifications
        self.x_spec = util.Position(x, self, parent, 'width')
        self.y_spec = util.Position(y, self, parent, 'height')
        self._z = util.parse_value(z) or 0
        self.width_spec = util.Dimension(width, self, parent, 'width')
        self.height_spec = util.Dimension(height, self, parent, 'height')

        # attempt to calculate now what we can
        if self.x_spec.is_fixed:
            self.x = self.x_spec.calculate()
        if self.y_spec.is_fixed:
            self.y = self.y_spec.calculate()
        if self.width_spec.is_fixed:
            self.width = self.width_spec.calculate()
        if self.height_spec.is_fixed:
            self.height = self.height_spec.calculate()

        self.is_visible = is_visible
        self.is_enabled = is_enabled
        self.is_modal = False
        self.is_transparent = is_transparent

        self._event_handlers = dict()

        # add this new element to its parent
        self.parent.addChild(self)

        # indicate we need geometry calculation
        self.resetGeometry()
Example #3
0
    def __init__(self,
                 parent,
                 items=list(),
                 size=None,
                 is_exclusive=False,
                 color='black',
                 bgcolor='white',
                 is_vertical=True,
                 alt_bgcolor='eee',
                 active_bgcolor='ffc',
                 item_pad=0,
                 is_transparent=True,
                 scrollable=True,
                 font_size=None,
                 **kw):
        self.is_vertical = is_vertical
        self.is_exclusive = is_exclusive

        if font_size is None:
            font_size = parent.getStyle().font_size
        else:
            font_size = util.parse_value(font_size, None)

        size = util.parse_value(size, None)

        if is_vertical:
            if size is not None:
                kw['height'] = size * font_size
        else:
            if size is not None:
                kw['width'] = size * font_size

        super().__init__(parent,
                         bgcolor=bgcolor,
                         scrollable=scrollable,
                         scrollable_resize=scrollable,
                         is_transparent=is_transparent,
                         **kw)
        if scrollable:
            f = self.contents
        else:
            f = self
        if is_vertical:
            f.layout = layouts.Vertical(f, padding=item_pad)
        else:
            f.layout = layouts.Horizontal(f, padding=item_pad)

        # specific attributes for Options
        self.color = util.parse_color(color)
        self.base_bgcolor = self.bgcolor
        self.alt_bgcolor = util.parse_color(alt_bgcolor)
        self.active_bgcolor = util.parse_color(active_bgcolor)
        self.font_size = font_size

        for label, id, kw in items:
            self.addOption(label, id, **kw)
    def handleSizing(self):
        try:
            # if the bar size spec is a straight integer, use it
            min_size = int(self.bar_spec) + self.slider_size
        except:
            min_size = self.slider_size * 2
        height = self.height
        if height < min_size:
            height = min_size

        # assume buttons are same height
        bh = ArrowButtonUp.get_arrow().height

        # only have buttons if there's enough room (two buttons plus
        # scrolling room)
        self.have_buttons = height > (bh * 2 + min_size)
        if self.have_buttons and self.dbut is None:
            # do this after the call to super to allow it to set the parent etc.
            self.dbut = ArrowButtonDown(self,
                                        classes=('-repeater-button-min', ),
                                        color='black')
            self.ubut = ArrowButtonUp(self,
                                      y=height - bh,
                                      color='black',
                                      classes=('-repeater-button-max', ))
        elif not self.have_buttons and self.dbut is not None:
            self.dbut.delete()
            self.ubut.delete()
            self.dbut = self.ubut = None

        # add slider bar
        #i_height = self.inner_rect.height
        i_height = height
        self.bar_size = util.parse_value(self.bar_spec, i_height)
        if self.bar_size is None:
            self.bar_size = int(
                max(self.slider_size, i_height / (self.range + 1)))

        s = self.show_value and str(self._value) or ' '
        # note: dimensions are funny because the bar is rotated 90 degrees
        if self.bar is None:
            self.bar = SliderBar(self,
                                 'y',
                                 s,
                                 self.width,
                                 self.bar_size,
                                 bgcolor=self.bar_color,
                                 color=self.bar_text_color)
        else:
            self.bar.text = s
            self.bar.height = self.bar_size

        self.height = height

        # fix up sizing and positioning of elements
        if self.dbut is not None:
            self.dbut.resize()
            self.ubut.resize()
        self.bar.resize()
        self.positionBar()
Example #5
0
File: table.py Project: pyzh/pyglet
    def __init__(self,
                 parent,
                 size=None,
                 is_exclusive=False,
                 color=(0, 0, 0, 1),
                 bgcolor=(1, 1, 1, 1),
                 alt_bgcolor=(.9, .9, .9, 1),
                 active_bgcolor=(1, .8, .8, 1),
                 x=0,
                 y=0,
                 z=0,
                 width='100%',
                 height=None,
                 **kw):
        font_size = parent.getStyle().font_size
        size = util.parse_value(size, None)
        if size is not None:
            height = (size + 1) * font_size

        self.is_exclusive = is_exclusive

        super().__init__(parent, x, y, z, width, height, bgcolor=bgcolor, **kw)

        # rows go in under the heading
        # self.contents = TableContainer(self)
        self.contents = ContainerFrame(self)
        self.contents.layout = layouts.Layout(self.contents)
        self.contents.checkForScrollbars()

        # specific attributes for rows
        self.color = util.parse_color(color)
        self.base_bgcolor = self.bgcolor
        self.alt_bgcolor = util.parse_color(alt_bgcolor)
        self.active_bgcolor = util.parse_color(active_bgcolor)
Example #6
0
 def __init__(self,
              parent,
              text,
              x=None,
              y=None,
              z=None,
              width=None,
              height=None,
              font_size=None,
              valign='top',
              halign='left',
              color='black',
              rotate=0,
              **kw):
     self.valign = valign
     self.halign = halign
     self.font_size = int(font_size or parent.getStyle().font_size)
     self.color = util.parse_color(color)
     self.rotate = util.parse_value(rotate, 0)
     assert self.rotate in (0, 90, 180, 270), \
         'rotate must be one of 0, 90, 180, 270, not %r'%(self.rotate, )
     # set parent now so style is available
     self.parent = parent
     super(LabelCommon, self).__init__(parent, x, y, z, width, height, **kw)
     self.text = text
Example #7
0
    def __init__(self,
                 parent,
                 value=0.0,
                 show_value=True,
                 bar_color='gray',
                 bgcolor=(.3, .3, .3, 1),
                 color='white',
                 width=None,
                 height=16,
                 halign='center',
                 valign='center',
                 **kw):

        self._value = util.parse_value(value, 0)
        self.show_value = show_value
        self.bar_color = util.parse_color(bar_color)

        super().__init__(parent,
                         ' ',
                         width=width,
                         height=height,
                         bgcolor=bgcolor,
                         color=color,
                         halign=halign,
                         valign=valign,
                         **kw)

        if self.show_value:
            self.text = '%d%%' % (value * 100)
Example #8
0
    def __init__(self, parent, size=None, is_exclusive=False,
            color=(0, 0, 0, 1), bgcolor=(1, 1, 1, 1),
            alt_bgcolor=(.9, .9, .9, 1), active_bgcolor=(1, .8, .8, 1),
            x=0, y=0, z=0, width='100%', height=None, **kw):
        font_size = parent.getStyle().font_size
        size = util.parse_value(size, None)
        if size is not None:
            height = (size + 1) * font_size

        self.is_exclusive = is_exclusive

        super(Table, self).__init__(parent, x, y, z, width, height,
            bgcolor=bgcolor, **kw)

        # rows go in under the heading
        #self.contents = TableContainer(self)
        self.contents = ContainerFrame(self)
        self.contents.layout = layouts.Layout(self.contents)
        self.contents.checkForScrollbars()

        # specific attributes for rows
        self.color = util.parse_color(color)
        self.base_bgcolor = self.bgcolor
        self.alt_bgcolor = util.parse_color(alt_bgcolor)
        self.active_bgcolor = util.parse_color(active_bgcolor)
Example #9
0
    def handleSizing(self):
        try:
            # if the bar size spec is a straight integer, use it
            min_size = int(self.bar_spec) + self.slider_size
        except:
            min_size = self.slider_size * 2
        width = self.width
        if width < min_size:
            width = min_size

        # assume buttons are same width
        bw = ArrowButtonLeft.get_arrow().width

        # only have buttons if there's enough room (two buttons plus
        # scrolling room)
        self.have_buttons = width > (bw * 2 + min_size)
        if self.have_buttons and self.lbut is None:
            self.lbut = ArrowButtonLeft(self,
                                        classes=('-repeater-button-min', ),
                                        color='black')
            self.rbut = ArrowButtonRight(self,
                                         x=width - bw,
                                         color='black',
                                         classes=('-repeater-button-max', ))
        elif not self.have_buttons and self.lbut is not None:
            self.lbut.delete()
            self.rbut.delete()
            self.lbut = self.rbut = None

        # slider bar size
        # i_width = self.inner_rect.width
        i_width = width
        self.bar_size = util.parse_value(self.bar_spec, i_width)
        if self.bar_size is None:
            self.bar_size = int(
                max(self.slider_size, i_width / (self.range + 1)))

        s = self.show_value and str(self._value) or ' '
        # we force blending here so we don't generate a bazillion textures
        if self.bar is None:
            self.bar = SliderBar(self,
                                 'x',
                                 s,
                                 self.bar_size,
                                 self.height,
                                 bgcolor=self.bar_color,
                                 color=self.bar_text_color)
        else:
            self.bar.text = s
            self.bar.width = self.bar_size

        self.width = width

        # fix up sizing and positioning of elements
        if self.lbut is not None:
            self.lbut.resize()
            self.rbut.resize()
        self.bar.resize()
        self.positionBar()
Example #10
0
    def __init__(self, parent, x, y, z, width, height, padding=0,
                 border=None, bgcolor=None, is_visible=True, is_enabled=True,
                 is_transparent=False, children=None, id=None, classes=()):
        self.parent = parent
        self.id = id or self.allocateID()
        self.classes = classes
        self.children = children or list()

        # colors, border and padding
        self.bgcolor = util.parse_color(bgcolor)
        self.border = util.parse_color(border)
        self._padding = util.parse_value(padding)
        if border:
            # force enough room to see the border
            self._padding += 1

        # save off the geometry specifications
        self.x_spec = util.Position(x, self, parent, 'width')
        self.y_spec = util.Position(y, self, parent, 'height')
        self._z = util.parse_value(z) or 0
        self.width_spec = util.Dimension(width, self, parent, 'width')
        self.height_spec = util.Dimension(height, self, parent, 'height')

        # attempt to calculate now what we can
        if self.x_spec.is_fixed:
            self.x = self.x_spec.calculate()
        if self.y_spec.is_fixed:
            self.y = self.y_spec.calculate()
        if self.width_spec.is_fixed:
            self.width = self.width_spec.calculate()
        if self.height_spec.is_fixed:
            self.height = self.height_spec.calculate()

        self.is_visible = is_visible
        self.is_enabled = is_enabled
        self.is_modal = False
        self.is_transparent = is_transparent

        self._event_handlers = dict()

        # add this new element to its parent
        self.parent.addChild(self)

        # indicate we need geometry calculation
        self.resetGeometry()
Example #11
0
    def __init__(self,
                 parent,
                 text='',
                 font_size=None,
                 size=None,
                 x=0,
                 y=0,
                 z=0,
                 width=None,
                 height=None,
                 border='black',
                 padding=2,
                 bgcolor='white',
                 color='black',
                 focus_border=(.3, .3, .7, 1),
                 **kw):
        style = parent.getStyle()
        if font_size is None:
            font_size = style.font_size
        else:
            font_size = util.parse_value(font_size, None)
        self.font_size = font_size
        if size is not None:
            size = util.parse_value(size, None)
            width = size * style.getGlyphString('M', size=font_size).width
            width += padding * 2
        super().__init__(parent,
                         x,
                         y,
                         z,
                         width,
                         height,
                         padding=padding,
                         border=border,
                         bgcolor=bgcolor,
                         **kw)

        self.ti = TextInputLine(self,
                                text,
                                font_size=font_size,
                                bgcolor=bgcolor,
                                color=color)

        self.base_border = self.border
        self.focus_border = util.parse_color(focus_border)
Example #12
0
    def __init__(self, parent, items=list(), size=None, is_exclusive=False,
                 color='black', bgcolor='white', is_vertical=True,
                 alt_bgcolor='eee', active_bgcolor='ffc', item_pad=0,
                 is_transparent=True, scrollable=True, font_size=None, **kw):
        self.is_vertical = is_vertical
        self.is_exclusive = is_exclusive

        if font_size is None:
            font_size = parent.getStyle().font_size
        else:
            font_size = util.parse_value(font_size, None)

        size = util.parse_value(size, None)

        if is_vertical:
            if size is not None:
                kw['height'] = size * font_size
        else:
            if size is not None:
                kw['width'] = size * font_size

        super().__init__(parent, bgcolor=bgcolor,
                         scrollable=scrollable,
                         scrollable_resize=scrollable,
                         is_transparent=is_transparent, **kw)
        if scrollable:
            f = self.contents
        else:
            f = self
        if is_vertical:
            f.layout = layouts.Vertical(f, padding=item_pad)
        else:
            f.layout = layouts.Horizontal(f, padding=item_pad)

        # specific attributes for Options
        self.color = util.parse_color(color)
        self.base_bgcolor = self.bgcolor
        self.alt_bgcolor = util.parse_color(alt_bgcolor)
        self.active_bgcolor = util.parse_color(active_bgcolor)
        self.font_size = font_size

        for label, id, kw in items:
            self.addOption(label, id, **kw)
Example #13
0
    def handleSizing(self):
        try:
            # if the bar size spec is a straight integer, use it
            min_size = int(self.bar_spec) + self.slider_size
        except:
            min_size = self.slider_size * 2
        height = self.height
        if height < min_size:
            height = min_size

        # assume buttons are same height
        bh = ArrowButtonUp.get_arrow().height

        # only have buttons if there's enough room (two buttons plus
        # scrolling room)
        self.have_buttons = height > (bh * 2 + min_size)
        if self.have_buttons and self.dbut is None:
            # do this after the call to super to allow it to set the parent
            # etc.
            self.dbut = ArrowButtonDown(self, classes=('-repeater-button-min',),
                                        color='black')
            self.ubut = ArrowButtonUp(self, y=height - bh, color='black',
                                      classes=('-repeater-button-max',))
        elif not self.have_buttons and self.dbut is not None:
            self.dbut.delete()
            self.ubut.delete()
            self.dbut = self.ubut = None

        # add slider bar
        # i_height = self.inner_rect.height
        i_height = height
        self.bar_size = util.parse_value(self.bar_spec, i_height)
        if self.bar_size is None:
            self.bar_size = int(max(self.slider_size, i_height /
                                    (self.range + 1)))

        s = self.show_value and str(self._value) or ' '
        # note: dimensions are funny because the bar is rotated 90 degrees
        if self.bar is None:
            self.bar = SliderBar(self, 'y', s, self.width, self.bar_size,
                                 bgcolor=self.bar_color,
                                 color=self.bar_text_color)
        else:
            self.bar.text = s
            self.bar.height = self.bar_size

        self.height = height

        # fix up sizing and positioning of elements
        if self.dbut is not None:
            self.dbut.resize()
            self.ubut.resize()
        self.bar.resize()
        self.positionBar()
Example #14
0
    def __init__(self, parent, minimum, maximum, value, step=1,
                 bar_size=None, show_value=False, bar_text_color='white',
                 bar_color=(.3, .3, .3, 1), x=None, y=None, z=None,
                 width=SliderCommon.slider_size, height='100%',
                 bgcolor='gray', **kw):

        self.minimum = util.parse_value(minimum, 0)
        self.type = type(self.minimum)
        self.maximum = util.parse_value(maximum, 0)
        self.range = self.maximum - self.minimum
        self._value = util.parse_value(value, 0)
        self.step = util.parse_value(step, 0)
        self.show_value = show_value
        self.bar_spec = bar_size
        self.bar_color = util.parse_color(bar_color)
        self.bar_text_color = util.parse_color(bar_text_color)
        self.bar = self.dbut = self.ubut = None

        super().__init__(parent, x, y, z, width, height,
                         bgcolor=bgcolor, **kw)
    def __init__(self,
                 parent,
                 minimum,
                 maximum,
                 value,
                 step=1,
                 bar_size=None,
                 show_value=False,
                 bar_text_color='white',
                 bar_color=(.3, .3, .3, 1),
                 x=None,
                 y=None,
                 z=None,
                 width='100%',
                 height=SliderCommon.slider_size,
                 bgcolor='gray',
                 **kw):

        self.minimum = util.parse_value(minimum, 0)
        self.type = type(self.minimum)
        self.maximum = util.parse_value(maximum, 0)
        self.range = self.maximum - self.minimum
        self._value = util.parse_value(value, 0)
        self.step = util.parse_value(step, 0)
        self.show_value = show_value
        self.bar_spec = bar_size
        self.bar_color = util.parse_color(bar_color)
        self.bar_text_color = util.parse_color(bar_text_color)
        self.bar = self.lbut = self.rbut = None

        # for step repeat when clicking in the bar
        self.delay_timer = None

        super(HorizontalSlider, self).__init__(parent,
                                               x,
                                               y,
                                               z,
                                               width,
                                               height,
                                               bgcolor=bgcolor,
                                               **kw)
Example #16
0
 def __init__(self,
              parent,
              halign=LEFT,
              valign=TOP,
              padding=0,
              wrap=None,
              **kw):
     self.halign = halign
     self.valign = valign
     self.padding = util.parse_value(padding)
     self.wrap = wrap and util.Dimension(wrap, parent, parent, 'height')
     super().__init__(parent, **kw)
Example #17
0
    def handleSizing(self):
        try:
            # if the bar size spec is a straight integer, use it
            min_size = int(self.bar_spec) + self.slider_size
        except:
            min_size = self.slider_size * 2
        width = self.width
        if width < min_size:
            width = min_size

        # assume buttons are same width
        bw = ArrowButtonLeft.get_arrow().width

        # only have buttons if there's enough room (two buttons plus
        # scrolling room)
        self.have_buttons = width > (bw * 2 + min_size)
        if self.have_buttons and self.lbut is None:
            self.lbut = ArrowButtonLeft(self, classes=('-repeater-button-min',),
                                        color='black')
            self.rbut = ArrowButtonRight(self, x=width - bw, color='black',
                                         classes=('-repeater-button-max',))
        elif not self.have_buttons and self.lbut is not None:
            self.lbut.delete()
            self.rbut.delete()
            self.lbut = self.rbut = None

        # slider bar size
        # i_width = self.inner_rect.width
        i_width = width
        self.bar_size = util.parse_value(self.bar_spec, i_width)
        if self.bar_size is None:
            self.bar_size = int(
                max(self.slider_size, i_width / (self.range + 1)))

        s = self.show_value and str(self._value) or ' '
        # we force blending here so we don't generate a bazillion textures
        if self.bar is None:
            self.bar = SliderBar(self, 'x', s, self.bar_size, self.height,
                                 bgcolor=self.bar_color,
                                 color=self.bar_text_color)
        else:
            self.bar.text = s
            self.bar.width = self.bar_size

        self.width = width

        # fix up sizing and positioning of elements
        if self.lbut is not None:
            self.lbut.resize()
            self.rbut.resize()
        self.bar.resize()
        self.positionBar()
Example #18
0
    def __init__(self, parent, minimum, maximum, value, step=1,
            bar_size=None, show_value=False, bar_text_color='white',
            bar_color=(.3, .3, .3, 1), x=None, y=None, z=None, width='100%',
            height=SliderCommon.slider_size, bgcolor='gray', **kw):

        self.minimum = util.parse_value(minimum, 0)
        self.type = type(self.minimum)
        self.maximum = util.parse_value(maximum, 0)
        self.range = self.maximum - self.minimum
        self._value = util.parse_value(value, 0)
        self.step = util.parse_value(step, 0)
        self.show_value = show_value
        self.bar_spec = bar_size
        self.bar_color = util.parse_color(bar_color)
        self.bar_text_color = util.parse_color(bar_text_color)
        self.bar = self.lbut = self.rbut = None

        # for step repeat when clicking in the bar
        self.delay_timer = None

        super(HorizontalSlider, self).__init__(parent, x, y, z, width, height,
            bgcolor=bgcolor, **kw)
Example #19
0
    def __init__(self, parent, text='', font_size=None, size=None,
            x=0, y=0, z=0, width=None, height=None, border='black',
            padding=2, bgcolor='white', color='black',
            focus_border=(.3, .3, .7, 1), **kw):
        style = parent.getStyle()
        if font_size is None:
            font_size = style.font_size
        else:
            font_size = util.parse_value(font_size, None)
        self.font_size = font_size
        if size is not None:
            size = util.parse_value(size, None)
            width = size * style.getGlyphString('M', size=font_size).width
            width += padding*2
        super(TextInput, self).__init__(parent, x, y, z, width, height,
            padding=padding, border=border, bgcolor=bgcolor, **kw)

        self.ti = TextInputLine(self, text, font_size=font_size,
            bgcolor=bgcolor, color=color)

        self.base_border = self.border
        self.focus_border = util.parse_color(focus_border)
Example #20
0
    def __init__(self, parent, value=0.0, show_value=True,
            bar_color='gray', bgcolor=(.3, .3, .3, 1), color='white',
            width=None, height=16, halign='center', valign='center', **kw):

        self._value = util.parse_value(value, 0)
        self.show_value = show_value
        self.bar_color = util.parse_color(bar_color)

        super(Progress, self).__init__(parent, ' ', width=width,
            height=height, bgcolor=bgcolor, color=color, halign=halign,
            valign=valign, **kw)

        if self.show_value:
            self.text = '%d%%'%(value * 100)
Example #21
0
 def __init__(self, parent, text, x=None, y=None, z=None, width=None,
         height=None, font_size=None, valign='top', halign='left',
         color='black', rotate=0, **kw):
     self.valign = valign
     self.halign = halign
     self.font_size = int(font_size or parent.getStyle().font_size)
     self.color = util.parse_color(color)
     self.rotate = util.parse_value(rotate, 0)
     assert self.rotate in (0, 90, 180, 270), \
         'rotate must be one of 0, 90, 180, 270, not %r'%(self.rotate, )
     # set parent now so style is available
     self.parent = parent
     super(LabelCommon, self).__init__(parent, x, y, z, width, height, **kw)
     self.text = text
Example #22
0
 def __init__(self, parent, colpad=0, rowpad=0, colaligns=None, **kw):
     self.colaligns = colaligns
     self.colpad = util.parse_value(colpad, 0)
     self.rowpad = util.parse_value(rowpad, 0)
     super().__init__(parent, **kw)
Example #23
0
 def __init__(self, parent, halign=LEFT, valign=TOP, padding=0, wrap=None, **kw):
     self.halign = halign
     self.valign = valign
     self.padding = util.parse_value(padding)
     self.wrap = wrap and util.Dimension(wrap, parent, parent, "height")
     super().__init__(parent, **kw)
Example #24
0
 def __init__(self, parent, colpad=0, rowpad=0, colaligns=None, **kw):
     self.colaligns = colaligns
     self.colpad = util.parse_value(colpad, 0)
     self.rowpad = util.parse_value(rowpad, 0)
     super().__init__(parent, **kw)