aboutsummaryrefslogtreecommitdiffstats
path: root/lvc/widgets/gtk/tableviewcells.py
diff options
context:
space:
mode:
Diffstat (limited to 'lvc/widgets/gtk/tableviewcells.py')
-rw-r--r--lvc/widgets/gtk/tableviewcells.py249
1 files changed, 249 insertions, 0 deletions
diff --git a/lvc/widgets/gtk/tableviewcells.py b/lvc/widgets/gtk/tableviewcells.py
new file mode 100644
index 0000000..6511970
--- /dev/null
+++ b/lvc/widgets/gtk/tableviewcells.py
@@ -0,0 +1,249 @@
+# @Base: Miro - an RSS based video player application
+# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+# Participatory Culture Foundation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# In addition, as a special exception, the copyright holders give
+# permission to link the code of portions of this program with the OpenSSL
+# library.
+#
+# You must obey the GNU General Public License in all respects for all of
+# the code used other than OpenSSL. If you modify file(s) with this
+# exception, you may extend this exception to your version of the file(s),
+# but you are not obligated to do so. If you do not wish to do so, delete
+# this exception statement from your version. If you delete this exception
+# statement from all source files in the program, then also delete it here.
+
+"""tableviewcells.py - Cell renderers for TableView."""
+
+import gobject
+import gtk
+import pango
+
+from lvc import signals
+from lvc.widgets import widgetconst
+import drawing
+import wrappermap
+from .base import make_gdk_color
+
+class CellRenderer(object):
+ """Simple Cell Renderer
+ https://develop.participatoryculture.org/index.php/WidgetAPITableView"""
+ def __init__(self):
+ self._renderer = gtk.CellRendererText()
+ self.want_hover = False
+
+ def setup_attributes(self, column, attr_map):
+ column.add_attribute(self._renderer, 'text', attr_map['value'])
+
+ def set_align(self, align):
+ if align == 'left':
+ self._renderer.props.xalign = 0.0
+ elif align == 'center':
+ self._renderer.props.xalign = 0.5
+ elif align == 'right':
+ self._renderer.props.xalign = 1.0
+ else:
+ raise ValueError("unknown alignment: %s" % align)
+
+ def set_color(self, color):
+ self._renderer.props.foreground_gdk = make_gdk_color(color)
+
+ def set_bold(self, bold):
+ font_desc = self._renderer.props.font_desc
+ if bold:
+ font_desc.set_weight(pango.WEIGHT_BOLD)
+ else:
+ font_desc.set_weight(pango.WEIGHT_NORMAL)
+ self._renderer.props.font_desc = font_desc
+
+ def set_text_size(self, size):
+ if size == widgetconst.SIZE_NORMAL:
+ self._renderer.props.scale = 1.0
+ elif size == widgetconst.SIZE_SMALL:
+ # FIXME: on 3.5 we just ignored the call. Always setting scale to
+ # 1.0 basically replicates that behavior, but should we actually
+ # try to implement the semantics of SIZE_SMALL?
+ self._renderer.props.scale = 1.0
+ else:
+ raise ValueError("unknown size: %s" % size)
+
+ def set_font_scale(self, scale_factor):
+ self._renderer.props.scale = scale_factor
+
+class ImageCellRenderer(object):
+ """Cell Renderer for images
+ https://develop.participatoryculture.org/index.php/WidgetAPITableView"""
+ def __init__(self):
+ self._renderer = gtk.CellRendererPixbuf()
+ self.want_hover = False
+
+ def setup_attributes(self, column, attr_map):
+ column.add_attribute(self._renderer, 'pixbuf', attr_map['image'])
+
+class GTKCheckboxCellRenderer(gtk.CellRendererToggle):
+ def do_activate(self, event, treeview, path, background_area, cell_area,
+ flags):
+ iter = treeview.get_model().get_iter(path)
+ self.set_active(not self.get_active())
+ wrappermap.wrapper(self).emit('clicked', iter)
+
+gobject.type_register(GTKCheckboxCellRenderer)
+
+class CheckboxCellRenderer(signals.SignalEmitter):
+ """Cell Renderer for booleans
+ https://develop.participatoryculture.org/index.php/WidgetAPITableView"""
+ def __init__(self):
+ signals.SignalEmitter.__init__(self)
+ self.create_signal("clicked")
+ self._renderer = GTKCheckboxCellRenderer()
+ wrappermap.add(self._renderer, self)
+ self.want_hover = False
+
+ def set_control_size(self, size):
+ pass
+
+ def setup_attributes(self, column, attr_map):
+ column.add_attribute(self._renderer, 'active', attr_map['value'])
+
+class GTKCustomCellRenderer(gtk.GenericCellRenderer):
+ """Handles the GTK hide of CustomCellRenderer
+ https://develop.participatoryculture.org/index.php/WidgetAPITableView"""
+
+ def on_get_size(self, widget, cell_area=None):
+ wrapper = wrappermap.wrapper(self)
+ widget_wrapper = wrappermap.wrapper(widget)
+ style = drawing.DrawingStyle(widget_wrapper, use_base_color=True)
+ # NOTE: CustomCellRenderer.cell_data_func() sets up its attributes
+ # from the model itself, so we don't have to worry about setting them
+ # here.
+ width, height = wrapper.get_size(style, widget_wrapper.layout_manager)
+ x_offset = self.props.xpad
+ y_offset = self.props.ypad
+ width += self.props.xpad * 2
+ height += self.props.ypad * 2
+ if cell_area:
+ x_offset += cell_area.x
+ y_offset += cell_area.x
+ extra_width = max(0, cell_area.width - width)
+ extra_height = max(0, cell_area.height - height)
+ x_offset += int(round(self.props.xalign * extra_width))
+ y_offset += int(round(self.props.yalign * extra_height))
+ return x_offset, y_offset, width, height
+
+ def on_render(self, window, widget, background_area, cell_area, expose_area,
+ flags):
+ widget_wrapper = wrappermap.wrapper(widget)
+ cell_wrapper = wrappermap.wrapper(self)
+
+ selected = (flags & gtk.CELL_RENDERER_SELECTED)
+ if selected:
+ if widget.flags() & gtk.HAS_FOCUS:
+ state = gtk.STATE_SELECTED
+ else:
+ state = gtk.STATE_ACTIVE
+ else:
+ state = gtk.STATE_NORMAL
+ if cell_wrapper.IGNORE_PADDING:
+ area = background_area
+ else:
+ xpad = self.props.xpad
+ ypad = self.props.ypad
+ area = gtk.gdk.Rectangle(cell_area.x + xpad, cell_area.y + ypad,
+ cell_area.width - xpad * 2, cell_area.height - ypad * 2)
+ context = drawing.DrawingContext(window, area, expose_area)
+ if (selected and not widget_wrapper.draws_selection and
+ widget_wrapper.use_custom_style):
+ # Draw the base color as our background. This erases the gradient
+ # that GTK draws for selected items.
+ window.draw_rectangle(widget.style.base_gc[state], True,
+ background_area.x, background_area.y,
+ background_area.width, background_area.height)
+ context.style = drawing.DrawingStyle(widget_wrapper,
+ use_base_color=True, state=state)
+ widget_wrapper.layout_manager.update_cairo_context(context.context)
+ hotspot_tracker = widget_wrapper.hotspot_tracker
+ if (hotspot_tracker and hotspot_tracker.hit and
+ hotspot_tracker.column == self.column and
+ hotspot_tracker.path == self.path):
+ hotspot = hotspot_tracker.name
+ else:
+ hotspot = None
+ if (self.path, self.column) == widget_wrapper.hover_info:
+ hover = widget_wrapper.hover_pos
+ hover = (hover[0] - xpad, hover[1] - ypad)
+ else:
+ hover = None
+ # NOTE: CustomCellRenderer.cell_data_func() sets up its attributes
+ # from the model itself, so we don't have to worry about setting them
+ # here.
+ widget_wrapper.layout_manager.reset()
+ cell_wrapper.render(context, widget_wrapper.layout_manager, selected,
+ hotspot, hover)
+
+ def on_activate(self, event, widget, path, background_area, cell_area,
+ flags):
+ pass
+
+ def on_start_editing(self, event, widget, path, background_area,
+ cell_area, flags):
+ pass
+gobject.type_register(GTKCustomCellRenderer)
+
+class CustomCellRenderer(object):
+ """Customizable Cell Renderer
+ https://develop.participatoryculture.org/index.php/WidgetAPITableView"""
+
+ IGNORE_PADDING = False
+
+ def __init__(self):
+ self._renderer = GTKCustomCellRenderer()
+ self.want_hover = False
+ wrappermap.add(self._renderer, self)
+
+ def setup_attributes(self, column, attr_map):
+ column.set_cell_data_func(self._renderer, self.cell_data_func,
+ attr_map)
+
+ def cell_data_func(self, column, cell, model, iter, attr_map):
+ cell.column = column
+ cell.path = model.get_path(iter)
+ row = model[iter]
+ # Set attributes on self instead cell This works because cell is just
+ # going to turn around and call our methods to do the rendering.
+ for name, index in attr_map.items():
+ setattr(self, name, row[index])
+
+ def hotspot_test(self, style, layout, x, y, width, height):
+ return None
+
+class InfoListRenderer(CustomCellRenderer):
+ """Custom Renderer for InfoListModels
+ https://develop.participatoryculture.org/index.php/WidgetAPITableView"""
+
+ def cell_data_func(self, column, cell, model, iter, attr_map):
+ self.info, self.attrs, self.group_info = \
+ wrappermap.wrapper(model).row_for_iter(iter)
+ cell.column = column
+ cell.path = model.get_path(iter)
+
+class InfoListRendererText(CellRenderer):
+ """Renderer for InfoListModels that only display text
+ https://develop.participatoryculture.org/index.php/WidgetAPITableView"""
+
+ def setup_attributes(self, column, attr_map):
+ infolist.gtk.setup_text_cell_data_func(column, self._renderer,
+ self.get_value)