Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@member.fsf.org>2009-08-21 16:56:12 (GMT)
committer Aleksey Lim <alsroot@member.fsf.org>2009-08-25 15:47:56 (GMT)
commit8d6a09f140ee167c312668215546d085705f9127 (patch)
treef002c2ee3dc60521d81574673611c2e83e16b508 /src
parentd108520f37360c5edc0ac20a1511cae352aa786c (diff)
Rewrite smooth table
Diffstat (limited to 'src')
-rw-r--r--src/jarabe/journal/browse/localsource.py41
-rw-r--r--src/jarabe/journal/browse/smoothtable.py290
-rw-r--r--src/jarabe/journal/browse/source.py85
-rw-r--r--src/jarabe/journal/browse/tableview.py7
-rw-r--r--src/jarabe/journal/objectview.py (renamed from src/jarabe/journal/objectsview.py)0
5 files changed, 294 insertions, 129 deletions
diff --git a/src/jarabe/journal/browse/localsource.py b/src/jarabe/journal/browse/localsource.py
deleted file mode 100644
index e19941e..0000000
--- a/src/jarabe/journal/browse/localsource.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (C) 2009, Aleksey Lim
-#
-# 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
-
-import gtk
-
-from jarabe.journal.browse.source import Source
-
-class LocalSource(Source):
- def __init__(self, resultset):
- Source.__init__(self)
- self._resultset = resultset
-
- def get_count(self):
- return self._resultset.length
-
- def get_row(self, offset):
- if offset >= self.get_count():
- return False
- self._resultset.seek(offset)
- return self._resultset.read()
-
- def get_order(self):
- """ Get current order, returns (field_name, gtk.SortType) """
- pass
-
- def set_order(self, field_name, sort_type):
- """ Set current order """
- pass
diff --git a/src/jarabe/journal/browse/smoothtable.py b/src/jarabe/journal/browse/smoothtable.py
new file mode 100644
index 0000000..8962a11
--- /dev/null
+++ b/src/jarabe/journal/browse/smoothtable.py
@@ -0,0 +1,290 @@
+# Copyright (C) 2009, Aleksey Lim
+#
+# 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
+
+import gtk
+import gobject
+import math
+import bisect
+import logging
+
+class SmoothTable(gtk.Container):
+ __gsignals__ = {
+ 'set-scroll-adjustments': (gobject.SIGNAL_RUN_FIRST, None,
+ [gtk.Adjustment, gtk.Adjustment]),
+ 'fill-in': (gobject.SIGNAL_RUN_FIRST, None,
+ [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]),
+ }
+
+ def __init__(self, rows, columns, new_widget):
+ assert(rows and columns)
+
+ self._rows = []
+ self._adj = None
+ self._adj_value_changed_id = None
+ self._bin_window = None
+ self._bin_rows = 0
+ self._cell_height = 0
+ self._reordered = None
+ self._last_allocation = None
+
+ gtk.Container.__init__(self)
+
+ cell_no = 0
+ for y in range(rows + 2):
+ row = []
+ for x in range(columns):
+ cell = new_widget()
+ cell.set_parent(self)
+ cell.size_allocate(gtk.gdk.Rectangle(-1, -1))
+ cell_no += 1
+ row.append(cell)
+ self._rows.append(row)
+
+ def get_columns(self):
+ return len(self._rows[0])
+
+ columns = property(get_columns)
+
+ def get_rows(self):
+ return len(self._rows) - 2
+
+ rows = property(get_rows)
+
+ def get_head(self):
+ if self._adj is None:
+ return 0
+ return int(self._adj.value) - int(self._adj.value) % self._cell_height
+
+ head = property(get_head)
+
+ def set_count(self, count):
+ self._bin_rows = max(0, math.ceil(float(count) / len(self._rows[0])))
+
+ if self._adj is not None:
+ self._setup_adjustment(force=True)
+ if self.flags() & gtk.REALIZED:
+ self._bin_window.resize(self.allocation.width,
+ int(self._adj.upper))
+
+ def do_realize(self):
+ self.set_flags(gtk.REALIZED)
+
+ self.window = gtk.gdk.Window(
+ self.get_parent_window(),
+ window_type=gtk.gdk.WINDOW_CHILD,
+ x=self.allocation.x,
+ y=self.allocation.y,
+ width=self.allocation.width,
+ height=self.allocation.height,
+ wclass=gtk.gdk.INPUT_OUTPUT,
+ colormap=self.get_colormap(),
+ event_mask=gtk.gdk.VISIBILITY_NOTIFY_MASK)
+ self.window.set_user_data(self)
+
+ self._bin_window = gtk.gdk.Window(
+ self.window,
+ window_type=gtk.gdk.WINDOW_CHILD,
+ x=0,
+ y=int(-self._adj.value),
+ width=self.allocation.width,
+ height=int(self._adj.upper),
+ colormap=self.get_colormap(),
+ wclass=gtk.gdk.INPUT_OUTPUT,
+ event_mask=(self.get_events() | gtk.gdk.EXPOSURE_MASK |
+ gtk.gdk.SCROLL_MASK))
+ self._bin_window.set_user_data(self)
+
+ self.set_style(self.style.attach(self.window))
+ self.style.set_background(self.window, gtk.STATE_NORMAL)
+ self.style.set_background(self._bin_window, gtk.STATE_NORMAL)
+
+ for row in self._rows:
+ for cell in row:
+ cell.set_parent_window(self._bin_window)
+
+ self.queue_resize()
+
+ def do_size_allocate(self, allocation):
+ if self._reordered is not None:
+ if allocation == self._reordered:
+ self._reordered = None
+ return
+ self._reordered = None
+
+ self.allocation = allocation
+ self._cell_height = allocation.height / self.rows
+
+ self._setup_adjustment(force=True)
+
+ if self.flags() & gtk.REALIZED:
+ self.window.move_resize(*allocation)
+ self._bin_window.resize(allocation.width, int(self._adj.upper))
+
+ def do_unrealize(self):
+ self._bin_window.set_user_data(None)
+ self._bin_window.destroy()
+ self._bin_window = None
+ gtk.Container.do_unrealize(self)
+
+ def do_style_set(self, style):
+ gtk.Widget.do_style_set(self, style)
+ if self.flags() & gtk.REALIZED:
+ self.style.set_background(self._bin_window, gtk.STATE_NORMAL)
+
+ def do_expose_event(self, event):
+ if event.window != self._bin_window:
+ return False
+ gtk.Container.do_expose_event(self, event)
+ return False
+
+ def do_map(self):
+ self.set_flags(gtk.MAPPED)
+
+ for row in self._rows:
+ for cell in row:
+ cell.map()
+
+ self._bin_window.show()
+ self.window.show()
+
+ def do_size_request(self, req):
+ req.width = 0
+ req.height = 0
+
+ for row in self._rows:
+ for cell in row:
+ cell.size_request()
+
+ def do_forall(self, include_internals, callback, data):
+ for row in self._rows:
+ for cell in row:
+ callback(cell, data)
+
+ def do_add(self, widget):
+ pass
+
+ def do_remove(self, widget):
+ pass
+
+ def do_set_scroll_adjustments(self, hadjustment, vadjustment):
+ if vadjustment is None or vadjustment == self._adj:
+ return
+
+ if self._adj is not None:
+ self._adj.disconnect(self._adj_value_changed_id)
+
+ self._adj = vadjustment
+ self._setup_adjustment()
+
+ self._adj_value_changed_id = vadjustment.connect('value-changed',
+ self.__adjustment_value_changed_cb)
+
+ def _setup_adjustment(self, force=False):
+ self._adj.lower = 0
+ self._adj.upper = self._bin_rows * self._cell_height
+ self._adj.page_size = self.allocation.height
+ self._adj.changed()
+
+ max_value = max(0, self._adj.upper - self._adj.page_size)
+ if self._adj.value > max_value:
+ self._adj.value = max_value
+ self._adj.value_changed()
+ elif force:
+ self._adj.value_changed()
+
+ def _allocate_row(self, row, cell_y):
+ cell_x = 0
+ cell_no = cell_y / self._cell_height * self.columns
+
+ for cell in row:
+ self.emit('fill-in', cell, cell_no)
+
+ callocation = gtk.gdk.Rectangle(cell_x, cell_y)
+ callocation.width = self.allocation.width / self.columns
+ callocation.height = self._cell_height
+ cell.size_allocate(callocation)
+
+ cell_x += callocation.width
+ cell_no += 1
+
+ def __adjustment_value_changed_cb(self, sender=None):
+ if not self.flags() & gtk.REALIZED:
+ return
+
+ spare_rows = []
+ visible_rows = []
+ page_end = self._adj.value + self._adj.page_size
+
+ if self._last_allocation != self.allocation:
+ self._last_allocation = self.allocation
+ spare_rows = [] + self._rows
+ else:
+ class IndexedRow:
+ def __init__(self, row):
+ self.row = row
+
+ def __lt__(self, other):
+ return self.row[0].allocation.y < other.row[0].allocation.y
+
+ for row in self._rows:
+ if row[0].allocation.y < 0 or \
+ row[0].allocation.y > page_end or \
+ (row[0].allocation.y + self._cell_height) < \
+ self._adj.value:
+ spare_rows.append(row)
+ else:
+ bisect.insort_right(visible_rows, IndexedRow(row))
+
+ if not visible_rows or \
+ len(visible_rows) < self.rows + (self.head != visible_rows[0]):
+ self._reordered = self.allocation
+
+ def insert_spare_row(cell_y, end_y):
+ while cell_y < end_y:
+ if not spare_rows:
+ logging.error('spare_rows should not be empty')
+ return
+ row = spare_rows.pop()
+ self._allocate_row(row, cell_y)
+ cell_y = cell_y + self._cell_height
+
+ cell_y = self.head
+ for i in visible_rows:
+ insert_spare_row(cell_y, i.row[0].allocation.y)
+ cell_y = i.row[0].allocation.y + i.row[0].allocation.height
+ insert_spare_row(cell_y, page_end)
+
+ self._bin_window.move(0, int(-self._adj.value))
+ self.window.process_updates(True)
+
+SmoothTable.set_set_scroll_adjustments_signal('set-scroll-adjustments')
+
+if __name__ == '__main__':
+ window = gtk.Window()
+
+ scrolled = gtk.ScrolledWindow()
+ scrolled.set_policy(gtk.POLICY_ALWAYS, gtk.POLICY_ALWAYS)
+ window.add(scrolled)
+
+ def cb(sender, button, offset):
+ button.props.label = str(offset)
+ table = SmoothTable(3, 3, gtk.Button)
+ table.connect('fill-in', cb)
+ table.set_count(100)
+ scrolled.add(table)
+
+ window.show_all()
+ gtk.main()
diff --git a/src/jarabe/journal/browse/source.py b/src/jarabe/journal/browse/source.py
deleted file mode 100644
index 64fa2ab..0000000
--- a/src/jarabe/journal/browse/source.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright (C) 2009, Aleksey Lim
-#
-# 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
-
-import gtk
-from gobject import property, GObject, SIGNAL_RUN_FIRST, TYPE_PYOBJECT
-
-FIELD_UID = 0
-FIELD_TITLE = 1
-FIELD_MTIME = 2
-FIELD_TIMESTAMP = 3
-FIELD_KEEP = 4
-FIELD_BUDDIES = 5
-FIELD_ICON_COLOR = 6
-FIELD_MIME_TYPE = 7
-FIELD_PROGRESS = 8
-FIELD_ACTIVITY = 9
-FIELD_MOUNT_POINT = 10
-FIELD_ACTIVITY_ID = 11
-FIELD_BUNDLE_ID = 12
-
-FIELD_FAVORITE = 30
-FIELD_ICON = 31
-FIELD_MODIFY_TIME = 32
-FIELD_THUMB = 33
-
-FIELDS_LIST = {'uid': (FIELD_UID, str),
- 'title': (FIELD_TITLE, str),
- 'mtime': (FIELD_MTIME, str),
- 'timestamp': (FIELD_TIMESTAMP, int),
- 'keep': (FIELD_KEEP, int),
- 'buddies': (FIELD_BUDDIES, str),
- 'icon-color': (FIELD_ICON_COLOR, str),
- 'mime_type': (FIELD_MIME_TYPE, str),
- 'progress': (FIELD_MIME_TYPE, str),
- 'activity': (FIELD_ACTIVITY, str),
- 'mountpoint': (FIELD_ACTIVITY, str),
- 'activity_id': (FIELD_ACTIVITY_ID, str),
- 'bundle_id': (FIELD_BUNDLE_ID, str),
-
- 'favorite': (FIELD_FAVORITE, bool),
- 'icon': (FIELD_ICON, str),
- 'modify_time': (FIELD_MODIFY_TIME, str),
- 'thumb': (FIELD_THUMB, gtk.gdk.Pixbuf)}
-
-class Source(GObject):
- __gsignals__ = {
- 'objects-updated': (SIGNAL_RUN_FIRST, None, []),
- 'row-delayed-fetch': (SIGNAL_RUN_FIRST, None, 2*[TYPE_PYOBJECT])
- }
-
- def get_count(self):
- """ Returns number of objects """
- pass
-
- def get_row(self, offset):
- """ Get object
-
- Returns:
- objects in dict {field_name: value, ...}
- False can't fint object
- None wait for reply signal
-
- """
- pass
-
- def get_order(self):
- """ Get current order, returns (field_name, gtk.SortType) """
- pass
-
- def set_order(self, field_name, sort_type):
- """ Set current order """
- pass
diff --git a/src/jarabe/journal/browse/tableview.py b/src/jarabe/journal/browse/tableview.py
index 43a871b..4aa6697 100644
--- a/src/jarabe/journal/browse/tableview.py
+++ b/src/jarabe/journal/browse/tableview.py
@@ -329,7 +329,7 @@ class TableView(gtk.Bin):
def _get_frame(self):
adj = self._full_adjustment
return (int(adj.value / self._cell_height) * self._cols,
- (int(adj.value / self._cell_height) + self._rows) * \
+ (int(adj.value / self._cell_height) + self._rows + 1) * \
self._cols - 1)
def __adjustment_value_changed(self, adjustment, force=False):
@@ -361,8 +361,9 @@ class TableView(gtk.Bin):
cell.row = None
if cell_num < count:
- cell.row = self._model.get_row((cell_num,),
- self._get_frame())
+ row = self._model.get_row((cell_num,), self._get_frame())
+ if row != False:
+ cell.row = row
self._fillin_cell(canvas, cell)
cell_num += 1
diff --git a/src/jarabe/journal/objectsview.py b/src/jarabe/journal/objectview.py
index fca232b..fca232b 100644
--- a/src/jarabe/journal/objectsview.py
+++ b/src/jarabe/journal/objectview.py