"""This module is responsible for creating widgets from a pyglade.xmhtml.TagTree. As opposed to the C code generation approach, this will build the widget tree at runtime. There is nothing wrong with the code generation approach, but this one is what I have decided to do. I may write a code generator at some later point (the tag tree and style generators are sufficiently general). """ import sys import string from gtk import * # the style sheet generator import style error = "pyglade.build.error" # This is a dictionary of widget creation routines. # It should have string keys representing widget classes, and a tuple as # the value. The first function is for creation of this widget type. # It should take one argument (the TagTree node), and returns a widget # with those attributes. Note that it doesn't have to set the widget # names or connect signal handlers (in fact it shouldn't do this). # # The second function is for adding a child to this container widget. If # this widget class is not a container, the second item in the tuple should # be None. If it is a container, the function should take as arguments the # container, the child, and finally the 'child' TagTree node corresponding to # the child widget (or None if there is no child TagTree node). _widgets = {} class WidgetTree: def __init__(self, tree): if tree.has_key('gtk-interface'): tree = tree['gtk-interface'] if tree.tag != 'gtk-interface': raise error, "first argument not the base of tag tree" self.__signals = {} # signals self.__widgets = {} # widgets by name self.__paths = {} # widgets by path self.tooltips = None # parse rc strings if tree.has_key('style'): rc_parse_string(style.as_string(tree)) # create widgets if tree.has_key('widget'): children = tree.widget if type(children) != type(()): children = (children,) for child in children: self.__new_widget(child) if self.tooltips: self.tooltips.enable(); def get_widget(self, name): if string.find(name, '.') == -1: # no dot return self.__widgets[name] else: return self.__paths[name] def connect(self, signame, handler, *data): self.__signals[signame] = (self.__signals[signame][0], data, handler) def disconnect(self, signame): self.__signals[signame] = (self.__signals[signame][0], (),None) def __signal_handler(self, wid, *args): signame = args[-1] args = args[:-1] objname, data, handler = self.__signals[signame] if not handler: return obj = self.__widgets[objname] return apply(handler, (obj,) + args + data) def __new_widget(self, node, parent=''): path = parent + '.' + node.name wclass = node['class'] if wclass == 'Placeholder': sys.stderr.write( "warning: placeholders still in description\n") return create, add = _widgets[wclass] widget = create(node) if node.has_key('name'): widget.set_name(node.name) self.__widgets[node.name] = widget self.__paths[path[:-1]] = widget self.__set_common_params(widget, node) if node.has_key('signal'): self.__setup_sighandlers(widget, node) if node.has_key('widget'): if not add: raise error, "don't know how to add " + \ "widgets to this container" children = node.widget if type(children) != type(()): children = (children,) for child in children: self.__new_widget(child, parent=path) cwidget = self.get_widget(child.name) add(widget, cwidget, child) # these can only be set after packing has_default = child.get_bool('has_default', FALSE) if has_default: cwidget.grab_default() has_focus = child.get_bool('has_focus', FALSE) if has_focus: cwidget.grab_focus() if node.get_bool('visible', TRUE): widget.show() def __set_common_params(self, widget, node): width = node.get_int('width', -1) height = node.get_int('height', -1) if width != -1 or height != -1: widget.set_usize(width, height) sensitive = node.get_bool('sensitive', TRUE) if not sensitive: widget.set_sensitive(FALSE) tooltip = node.get('tooltip', None) if tooltip: if not self.tooltips: self.tooltips = GtkTooltips() self.tooltips.set_tip(widget, tooltip, '') can_default = node.get_bool('can_default', FALSE) if can_default: widget.set_flags(CAN_DEFAULT) can_focus = node.get_bool('can_focus', FALSE) if can_focus: widget.set_flags(CAN_FOCUS) events = node.get_int('events', 0) if events: widget.set_events(events) extension = node.get('extension_events', None) if extension: widget.set_extension_events(extension) border_width = node.get_int('border_width', 0) if border_width: widget.set_border_width(border_width) def __setup_sighandlers(self, widget, node): signals = node.signal if type(signals) != type(()): signals = (signals,) for sig in signals: signame = sig.name self.__signals[sig.handler] = ( sig.get('object', node.name), (), None) if sig.get_bool('after', FALSE): widget.connect_after(signame, self.__signal_handler, sig.handler) else: widget.connect(signame, self.__signal_handler, sig.handler) # These functions handle adding elements to the various container types def container_add(cont, child, info): cont.add(child) def box_add(box, child, info): info = info.child expand = info.get_bool('expand', TRUE) fill = info.get_bool('fill', TRUE) padding = info.get_int('padding', 0) if info.get('pack', 'GTK_PACK_START') == 'GTK_PACK_START': box.pack_start(child, expand=expand, fill=fill,padding=padding) else: box.pack_end(child, expand=expand, fill=fill,padding=padding) def table_add(table, child, info): info = info.child la = info.get_int('left_attach', 0) ra = info.get_int('right_attach', 1) ta = info.get_int('top_attach', 0) ba = info.get_int('bottom_attach', 1) xpad = info.get_int('xpad', 0) ypad = info.get_int('ypad', 0) xoptions=0 yoptions=0 if info.get_bool('xexpand', TRUE): xoptions = xoptions | EXPAND if info.get_bool('xshrink', FALSE): xoptions = xoptions | SHRINK if info.get_bool('xfill', TRUE): xoptions = xoptions | FILL if info.get_bool('yexpand', TRUE): yoptions = yoptions | EXPAND if info.get_bool('yshrink', FALSE): yoptions = yoptions | SHRINK if info.get_bool('yfill', TRUE): yoptions = yoptions | FILL table.attach(child, la,ra, ta,ba, xoptions=xoptions, yoptions=yoptions, xpadding=xpad, ypadding=ypad) def fixed_add(fix, child, info): x = info.get_int('x', 0) y = info.get_int('y', 0) fix.put(child, x, y) def clist_add(clist, child, info): col = info.parent.get('col_no', 0) info.parent['col_no'] = col + 1 clist.set_column_widget(col, child) def paned_add(paned, child, info): pane = info.parent.get('pane2', FALSE) info.parent['pane2'] = TRUE if not pane: paned.add1(child) else: paned.add2(child) def notebook_add(book, child, info): pages = info.parent.pages if not info.has_key('child_name') or info.child_name != 'Notebook:tab': pages.append(child) else: # child is a label book.append_page(pages[0], child) del pages[0] def dialog_add(dlg, child, info): # the widgets are already added pass def menuitem_add(mi, menu, info): mi.set_submenu(menu) def menushell_add(menu, mi, info): menu.append(mi) def misc_set(misc, info): xalign = info.get_float('xalign', 0.5) yalign = info.get_float('yalign', 0.5) misc.set_alignment(xalign, yalign) xpad = info.get_int('xpad', 0) ypad = info.get_int('ypad', 0) misc.set_padding(xpad, ypad) def label_new(node): str = node.get('label', '') label = GtkLabel(str) misc_set(label, node) just = node.get('justify', JUSTIFY_CENTER) label.set_justify(just) return label def entry_new(node): ent = GtkEntry(maxlen=node.get_int('text_max_length', -1)) if not node.get_bool('editable', TRUE): ent.set_editable(FALSE) if not node.get_bool('text_visible', TRUE): ent.set_visibility(FALSE) text = node.get('text', '') if text: ent.set_text(text) return ent def text_new(node): text = GtkText() text.set_editable(node.get_bool('editable', FALSE)) t = node.get('text', '') if t: text.insert_text(t) return text def button_new(node): label = node.get('label', '') return GtkButton(label) def togglebutton_new(node): label = node.get('label', '') tog = GtkToggleButton(label) if node.get_bool('active', FALSE): tog.set_state(TRUE) return tog def checkbutton_new(node): label = node.get('label', '') cb = GtkCheckButton(label) if node.get_bool('active', FALSE): cb.set_state(TRUE) if not node.get_bool('draw_indicator', TRUE): cb.set_mode(FALSE) return cb def radiobutton_new(node): label = node.get('label', '') # do something about radio button groups ... rb = GtkRadioButton(label) if node.get_bool('active', FALSE): rb.set_state(TRUE) if not node.get_bool('draw_indicator', TRUE): rb.set_mode(FALSE) return rb def optionmenu_new(node): omenu = GtkOptionMenu() menu = GtkMenu() for item in string.split(node.get('items', ''), '\n'): mi = GtkMenuItem(item) menu.append(mi) mi.show() omenu.set_menu(menu) return omenu def combo_new(node): combo = GtkCombo() if node.get_bool('case_sensitive', FALSE): combo.set_case_sensitive(TRUE) if not node.get_bool('use_arrows', TRUE): combo.set_use_arrows(FALSE) if node.get_bool('use_arrows_always', FALSE): combo.set_use_arrows_always(TRUE) return combo def list_new(node): list = GtkList() mode = node.get('selection_mode', SELECTION_SINGLE) list.set_selection_mode(mode) return list def clist_new(node): numcols = node.get_int('columns', 1) clist = GtkCList(numcols) widths = node.get('column_widths', None) if widths: widths = map(string.atoi, string.split(widths, ',')) for i in range(numcols): clist.set_column_width(i, widths[i]) if node.get_bool('show_titles', TRUE): clist.column_titles_show() mode = node.get('selection_mode', SELECTION_SINGLE) clist.set_selection_mode(mode) #shadow = node.get('shadow_type', SHADOW_IN) #clist.set_border(shadow) #hpol = node.get('hscrollbar_policy', POLICY_ALWAYS) #vpol = node.get('vscrollbar_policy', POLICY_ALWAYS) #clist.set_policy(hpol, vpol) return clist def tree_new(node): tree = GtkTree() mode = node.get('selection_mode', SELECTION_SINGLE) tree.set_selection_mode(mode) mode = node.get('view_mode', TREE_VIEW_LINE) tree.set_view_mode(mode) if not node.get_bool('view_line', TRUE): tree.set_view_lines(FALSE) return tree def spinbutton_new(node): climb_rate = node.get_int('climb_rate', 1) digits = node.get_int('digits', 0) hvalue = node.get_float('hvalue', 1) hlower = node.get_float('hlower', 0) hupper = node.get_float('hupper', 100) hstep = node.get_float('hstep', 1) hpage = node.get_float('hpage', 10) hpage_size = node.get_float('hpage_size', 10) adj = GtkAdjustment(hvalue, hlower, hupper, hstep, hpage, hpage_size) spin = GtkSpinButton(adj=adj, climb_rate=climb_rate, digits = digits) spin.set_numeric(node.get_bool('numeric', FALSE)) pol = node.get('update_policy', UPDATE_IF_VALID) spin.set_update_policy(pol) spin.set_snap_to_ticks(node.get_bool('snap', FALSE)) spin.set_wrap(node.get_bool('wrap', FALSE)) return spin def hscale_new(node): hvalue = node.get_float('hvalue', 1) hlower = node.get_float('hlower', 0) hupper = node.get_float('hupper', 100) hstep = node.get_float('hstep', 1) hpage = node.get_float('hpage', 10) hpage_size = node.get_float('hpage_size', 10) adj = GtkAdjustment(hvalue, hlower, hupper, hstep, hpage, hpage_size) scale = GtkHScale(adj) scale.set_draw_value(node.get_bool('draw_value', TRUE)) scale.set_value_pos(node.get('value_pos', POS_TOP)) scale.set_digits(node.get_int('digits', 1)) scale.set_update_policy(node.get('policy', UPDATE_CONTINUOUS)) return scale def vscale_new(node): hvalue = node.get_float('hvalue', 1) hlower = node.get_float('hlower', 0) hupper = node.get_float('hupper', 100) hstep = node.get_float('hstep', 1) hpage = node.get_float('hpage', 10) hpage_size = node.get_float('hpage_size', 10) adj = GtkAdjustment(hvalue, hlower, hupper, hstep, hpage, hpage_size) scale = GtkVScale(adj) scale.set_draw_value(node.get_bool('draw_value', TRUE)) scale.set_value_pos(node.get('value_pos', POS_TOP)) scale.set_digits(node.get_int('digits', 1)) scale.set_update_policy(node.get('policy', UPDATE_CONTINUOUS)) return scale def hruler_new(node): widget = GtkHRuler() widget.set_metric(node.get('metric', PIXELS)) lower = node.get_int('lower', 0) upper = node.get_int('upper', 10) pos = node.get_int('position', 0) max = node.get_int('max_size', 10) widget.set_range(lower, upper, pos, max) return widget def vruler_new(node): widget = GtkVRuler() widget.set_metric(node.get('metric', PIXELS)) lower = node.get_int('lower', 0) upper = node.get_int('upper', 10) pos = node.get_int('position', 0) max = node.get_int('max_size', 10) widget.set_range(lower, upper, pos, max) return widget def hscrollbar_new(node): hvalue = node.get_float('hvalue', 1) hlower = node.get_float('hlower', 0) hupper = node.get_float('hupper', 100) hstep = node.get_float('hstep', 1) hpage = node.get_float('hpage', 10) hpage_size = node.get_float('hpage_size', 10) adj = GtkAdjustment(hvalue, hlower, hupper, hstep, hpage, hpage_size) scroll = GtkHScrollbar(adj) scroll.set_update_policy(node.get('policy', UPDATE_CONTINUOUS)) return scroll def vscrollbar_new(node): hvalue = node.get_float('hvalue', 1) hlower = node.get_float('hlower', 0) hupper = node.get_float('hupper', 100) hstep = node.get_float('hstep', 1) hpage = node.get_float('hpage', 10) hpage_size = node.get_float('hpage_size', 10) adj = GtkAdjustment(hvalue, hlower, hupper, hstep, hpage, hpage_size) scroll = GtkVScrollbar(adj) scroll.set_update_policy(node.get('policy', UPDATE_CONTINUOUS)) return scroll def statusbar_new(node): return GtkStatusbar() def toolbar_new(node): orient = node.get('orientation', ORIENTATION_HORIZONTAL) style = node.get('type', TOOLBAR_ICONS) tool = GtkToolbar(orient, style) tool.set_space_size(node.get_int('space_size', 5)) tool.set_tooltips(node.get_bool('tooltips', TRUE)) return tool def progressbar_new(node): return GtkProgressBar() def arrow_new(node): dir = node.get('arrow_type', ARROW_RIGHT) shadow = node.get('shadow_type', SHADOW_OUT) arr = GtkArrow(dir, shadow) misc_set(arr, node) return arr # image not supported def pixmap_new(node): # the first parameter needs to be the toplevel widget pix,bit = create_pixmap_from_xpm(None, None, node.get('filename', '')) pixmap = GtkPixmap(pix, bit) misc_set(pixmap) return pixmap def drawingarea_new(node): return GtkDrawingArea() def hseparator_new(node): return GtkHSeparator() def vseparator_new(node): return GtkVSeparator() def menubar_new(node): return GtkMenuBar() def menu_new(node): return GtkMenu() def menuitem_new(node): if node.has_key('label'): ret = GtkMenuItem(node.label) else: ret = GtkMenuItem() if node.get_bool('right_justify', FALSE): ret.right_justify() return ret def checkmenuitem_new(node): ret = GtkCheckMenuItem(node.label) if node.get_bool('right_justify', FALSE): ret.right_justify() if node.get_bool('active', FALSE): ret.set_state(TRUE) if node.get_bool('always_show_toggle', FALSE): ret.set_show_toggle(TRUE) return ret def radiomenuitem_new(node): ret = GtkRadioMenuItem(node.label) if node.get_bool('right_justify', FALSE): ret.right_justify() if node.get_bool('active', FALSE): ret.set_state(TRUE) if node.get_bool('always_show_toggle', FALSE): ret.set_show_toggle(TRUE) return ret def hbox_new(node): if node.has_key('child_name') and node.child_name[:7] == 'Dialog:': return node.__wid homogeneous = node.get_bool('homogeneous', FALSE) spacing = node.get_int('spacing', 0) return GtkHBox(homogeneous=homogeneous, spacing=spacing) def vbox_new(node): if node.has_key('child_name') and node.child_name[:7] == 'Dialog:': return node.__wid homogeneous = node.get_bool('homogeneous', FALSE) spacing = node.get_int('spacing', 0) return GtkVBox(homogeneous=homogeneous, spacing=spacing) def table_new(node): rows = node.get_int('rows', 1) cols = node.get_int('columns', 1) homog = node.get_bool('homogeneous', FALSE) table = GtkTable(rows, cols, homog) table.set_row_spacings(node.get_int('row_spacing', 0)) table.set_col_spacings(node.get_int('col_spacing', 0)) return table def fixed_new(node): return GtkFixed() def hbuttonbox_new(node): bbox = GtkHButtonBox() layout = node.get('layout_style', BUTTONBOX_DEFAULT_STYLE) bbox.set_layout(layout) spacing = node.get_int('child_min_width', None) if spacing: bbox.set_spacing(spacing) width, height = bbox.get_child_size_default() width = node.get_int('child_min_width', width) height = node.get_int('child_min_height', height) bbox.set_child_size(width, height) ipx, ipy = bbox.get_child_ipadding_default() ipx = node.get_int('child_ipad_x', ipx) ipy = node.get_int('child_ipad_y', ipy) bbox.set_child_ipadding(ipx, ipy) return bbox def vbuttonbox_new(node): bbox = GtkVButtonBox() layout = node.get('layout_style', BUTTONBOX_DEFAULT_STYLE) bbox.set_layout(layout) spacing = node.get_int('child_min_width', None) if spacing: bbox.set_spacing(spacing) width, height = bbox.get_child_size_default() width = node.get_int('child_min_width', width) height = node.get_int('child_min_height', height) bbox.set_child_size(width, height) ipx, ipy = bbox.get_child_ipadding_default() ipx = node.get_int('child_ipad_x', ipx) ipy = node.get_int('child_ipad_y', ipy) bbox.set_child_ipadding(ipx, ipy) return bbox def frame_new(node): label = node.get('label', '') frame = GtkFrame(label) xalign = node.get_int('label_xalign', 0) frame.set_label_align(xalign, 0.5) shadow = node.get('shadow_type', SHADOW_ETCHED_IN) frame.set_shadow_type(shadow) return frame def aspectframe_new(node): xalign = node.get_int('xalign', 0) yalign = node.get_int('yalign', 0) ratio = node.get_float('ratio', 1) obey = node.get_bool('obey_child', TRUE) frame = GtkAspectFrame(xalign, yalign, ratio, obey_child) label = node.get('label', '') if label: frame.set_label(label) xalign = node.get_int('label_xalign', 0) frame.set_label_align(xalign, 0.5) shadow = node.get('shadow_type', SHADOW_ETCHED_IN) frame.set_shadow_type(shadow) return frame def hpaned_new(node): paned = GtkHPaned() handle_size = node.get_int('handle_size', 0) if handle_size: paned.set_handle_size(handle_size) gutter_size = node.get_int('gutter_size', 0) if gutter_size: paned.set_gutter_size(gutter_size) return paned def vpaned_new(node): paned = GtkVPaned() handle_size = node.get_int('handle_size', 0) if handle_size: paned.set_handle_size(handle_size) gutter_size = node.get_int('gutter_size', 0) if gutter_size: paned.set_gutter_size(gutter_size) return paned def handlebox_new(node): return GtkHandleBox() def notebook_new(node): book = GtkNotebook() book.set_show_tabs(node.get_bool('show_tabs', TRUE)) book.set_show_border(node.get_bool('show_border', TRUE)) book.set_tab_pos(node.get('tab_pos', POS_TOP)) book.set_scrollable(node.get_bool('scrollable', FALSE)) book.set_tab_border(node.get_int('tab_border', 3)) book.popup_enable(node.get_bool('popup_enable', FALSE)) node['pages'] = [] return book def alignment_new(node): xalign = node.get_float('xalign', 0.5) yalign = node.get_float('yalign', 0.5) xscale = node.get_float('xscale', 0) yscale = node.get_float('yscale', 0) return GtkAlignment(xalign, yalign, xscale, yscale) def eventbox_new(node): return GtkEventBox() def scrolledwindow_new(node): win = GtkScrolledWindow() hpol = node.get('hscrollbar_policy', POLICY_ALWAYS) vpol = node.get('vscrollbar_policy', POLICY_ALWAYS) win.set_policy(hpol, vpol) # do something about update policies here ... return win def viewport_new(node): port = GtkViewport() shadow = node.get('shadow_type', SHADOW_IN) port.set_shadow_type(shadow) return port def curve_new(node): curve = GtkCurve() curve.set_curve_type(node.get('curve_type', CURVE_TYPE_SPLINE)) minx = node.get_float('min_x', 0) maxx = node.get_float('max_x', 1) miny = node.get_float('min_y', 0) maxy = node.get_float('max_y', 1) curve.set_range(minx, maxx, miny, maxy) return curve def gammacurve_new(node): gamma = GtkGammaCurve() # do something about the curve parameters ... return gamma def colorselection_new(node): cs = GtkColorSelection() cs.set_update_policy(node.get('policy', UPDATE_CONTINUOUS)) return cs def preview_new(node): type = node.get('type', PREVIEW_COLOR) prev = GtkPreview(type) prev.set_expand(node.get_bool('expand', TRUE)) return prev def window_new(node): wintype = node.get('type', 'toplevel') widget = GtkWindow(wintype) widget.set_title(node.get('title', node.name)) x = node.get_int('x', -1) y = node.get_int('y', -1) if x != -1 or y != -1: widget.set_uposition(x, y) pos = node.get('position', None) if pos: widget.set_position(pos) ashrink = node.get_bool('allow_shrink', TRUE) agrow = node.get_bool('allow_grow', TRUE) autoshrink = node.get_bool('auto_shrink', FALSE) if not ashrink or not agrow or autoshrink: widget.set_policy(ashrink, agrow, autoshrink) return widget def dialog_new(node): widget = GtkDialog() widget.set_title(node.get('title', node.name)) x = node.get_int('x', -1) y = node.get_int('y', -1) if x != -1 or y != -1: widget.set_uposition(x, y) pos = node.get('position', None) if pos: widget.set_position(pos) ashrink = node.get_bool('allow_shrink', TRUE) agrow = node.get_bool('allow_grow', TRUE) autoshrink = node.get_bool('auto_shrink', FALSE) if not ashrink or not agrow or autoshrink: widget.set_policy(ashrink, agrow, autoshrink) # do some weird stuff because the vbox/action area is already created node.widget['__wid'] = widget.vbox children = node.widget.widget if type(children) != type(()): children = (children,) for i in range(len(children)): if children[i].has_key('child_name') and \ children[i].child_name == 'Dialog:action_area': node['widget'] = (node.widget, children[i]) children[i].parent = node children[i]['__wid'] = widget.action_area node.widget[0]['widget'] = children[0:i]+children[i+1:] break return widget def colorselectiondialog_new(node): return GtkColorSelectionDialog() _widgets = { # widgets ... 'GtkLabel': (label_new, None), 'GtkEntry': (entry_new, None), 'GtkText': (text_new, None), 'GtkButton': (button_new, None), 'GtkToggleButton': (togglebutton_new, None), 'GtkCheckButton': (checkbutton_new, None), 'GtkRadioButton': (radiobutton_new, None), 'GtkOptionMenu': (optionmenu_new, None), 'GtkCombo': (combo_new, None), 'GtkList': (list_new, None), 'GtkCList': (clist_new, clist_add), 'GtkTree': (tree_new, None), 'GtkSpinButton': (spinbutton_new, None), 'GtkHScale': (hscale_new, None), 'GtkVScale': (vscale_new, None), 'GtkHRuler': (hruler_new, None), 'GtkVRuler': (vruler_new, None), 'GtkHScrollbar': (hscrollbar_new, None), 'GtkVScrollbar': (vscrollbar_new, None), 'GtkStatusbar': (statusbar_new, None), 'GtkToolbar': (toolbar_new, None), 'GtkProgressBar': (progressbar_new, None), 'GtkArrow': (arrow_new, None), 'GtkPixmap': (pixmap_new, None), 'GtkDrawingArea': (drawingarea_new, None), 'GtkHSeparator': (hseparator_new, None), 'GtkVSeparator': (vseparator_new, None), # Menu stuff ... 'GtkMenuBar': (menubar_new, menushell_add), 'GtkMenu': (menu_new, menushell_add), 'GtkMenuItem': (menuitem_new, menuitem_add), 'GtkCheckMenuItem':(checkmenuitem_new,menuitem_add), 'GtkRadioMenuItem':(radiomenuitem_new,menuitem_add), # Containers ... 'GtkHBox': (hbox_new, box_add), 'GtkVBox': (vbox_new, box_add), 'GtkTable': (table_new, table_add), 'GtkFixed': (fixed_new, fixed_add), 'GtkHButtonBox': (hbuttonbox_new, container_add), 'GtkVButtonBox': (vbuttonbox_new, container_add), 'GtkFrame': (frame_new, container_add), 'GtkAspectFrame': (aspectframe_new, container_add), 'GtkHPaned': (hpaned_new, paned_add), 'GtkVPaned': (vpaned_new, paned_add), 'GtkHandleBox': (handlebox_new, container_add), 'GtkNotebook': (notebook_new, notebook_add), 'GtkAlignment': (alignment_new, container_add), 'GtkEventBox': (eventbox_new, container_add), 'GtkScrolledWindow': (scrolledwindow_new, container_add), 'GtkViewport': (viewport_new, container_add), # Miscellaneous ... 'GtkCurve': (curve_new, None), 'GtkGammaCurve': (gammacurve_new, None), 'GtkColorSelection': (colorselection_new, None), 'GtkPreview': (preview_new, None), # Windows ... 'GtkWindow': (window_new, container_add), 'GtkDialog': (dialog_new, dialog_add), 'GtkColorSelectionDialog': (colorselectiondialog_new, None), }