Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/jarabe/journal/entry.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/jarabe/journal/entry.py')
-rw-r--r--src/jarabe/journal/entry.py184
1 files changed, 184 insertions, 0 deletions
diff --git a/src/jarabe/journal/entry.py b/src/jarabe/journal/entry.py
new file mode 100644
index 0000000..7347fe1
--- /dev/null
+++ b/src/jarabe/journal/entry.py
@@ -0,0 +1,184 @@
+# Copyright (C) 2010, 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 logging
+
+import gtk
+import gobject
+import pango
+
+
+class Entry(gtk.TextView):
+ """One paragraph string entry with additional features
+
+ * multi line mode for wrapping long lines
+ * having wrapping and ellipses simultaneously in inactive mode
+ * accent in inactive mode
+
+ NOTE: Use text property instead of buffer, buffer's value will be
+ changed in inactive mode
+
+ """
+
+ def __init__(self, **kwargs):
+ self._max_line_count = 1
+ self._text = None
+
+ gobject.GObject.__init__(self, **kwargs)
+
+ self._tag = self.props.buffer.create_tag()
+ self._tag.props.weight = pango.WEIGHT_BOLD
+
+ gtk.TextView.set_accepts_tab(self, False)
+ self.set_max_line_count(self._max_line_count)
+
+ self.connect('key-press-event', self.__key_press_event_cb)
+ self.connect('focus-in-event', self.__focus_in_event_cb)
+ self.connect('focus-out-event', self.__focus_out_event_cb)
+ self.connect('button-release-event', self.__button_release_event_cb)
+
+ def set_accepts_tab(self, value):
+ # accepts_tab cannot be set by users
+ assert(False)
+
+ def get_accepts_tab(self):
+ return gtk.TextView.get_accepts_tab()
+
+ accepts_tab = gobject.property(
+ getter=get_accepts_tab, setter=set_accepts_tab)
+
+ def set_wrap_mode(self, value):
+ # accepts_tab cannot be set by users
+ assert(False)
+
+ def get_wrap_mode(self):
+ return gtk.TextView.get_wrap_mode()
+
+ wrap_mode = gobject.property(
+ getter=get_wrap_mode, setter=set_wrap_mode)
+
+ def get_max_line_count(self):
+ return self._max_line_count
+
+ def set_max_line_count(self, max_line_count):
+ max_line_count = max(1, max_line_count)
+ self._max_line_count = max_line_count
+
+ if max_line_count == 1:
+ gtk.TextView.set_wrap_mode(self, gtk.WRAP_NONE)
+ else:
+ gtk.TextView.set_wrap_mode(self, gtk.WRAP_WORD)
+
+ context = self.get_pango_context()
+ metrics = context.get_metrics(self.style.font_desc)
+ line_height = pango.PIXELS(metrics.get_ascent() + \
+ metrics.get_descent())
+ self.set_size_request(-1, line_height * max_line_count)
+
+ max_line_count = gobject.property(
+ getter=get_max_line_count, setter=set_max_line_count)
+
+ def get_text(self):
+ return self._text
+
+ def set_text(self, value):
+ self._text = value
+ self.props.buffer.props.text = value
+ if not self.props.has_focus:
+ self._accept()
+
+ text = gobject.property(getter=get_text, setter=set_text)
+
+ def do_size_allocate(self, allocation):
+ gtk.TextView.do_size_allocate(self, allocation)
+ if not self.props.has_focus:
+ self._accept()
+
+ def _accept(self):
+ if self._text is None:
+ return
+
+ gtk.TextView.set_wrap_mode(self, gtk.WRAP_WORD)
+
+ buf = self.props.buffer
+ buf.props.text = self._text
+
+ def accent():
+ start = buf.get_start_iter()
+ end = buf.get_end_iter()
+ buf.apply_tag(self._tag, start, end)
+
+ def last_offset():
+ iter = buf.get_start_iter()
+ for __ in xrange(self._max_line_count):
+ if not self.forward_display_line(iter):
+ return None
+ return iter.get_offset()
+
+ accent()
+ offset = last_offset()
+
+ if offset is not None:
+ offset = len(buf.props.text[:offset].rstrip()) - 1
+ buf.props.text = buf.props.text[:offset] + '...'
+
+ final_offset = last_offset()
+ if final_offset is not None and final_offset < offset + 3:
+ # ellipses added new line
+ buf.props.text = buf.props.text[:offset - 3] + '...'
+
+ accent()
+
+ def __button_release_event_cb(self, widget, event):
+ buf = self.props.buffer
+ if not buf.get_has_selection():
+ buf.select_range(buf.get_end_iter(), buf.get_start_iter())
+ return False
+
+ def __focus_in_event_cb(self, widget, event):
+ self.props.buffer.props.text = self._text
+
+ if self._max_line_count == 1:
+ gtk.TextView.set_wrap_mode(self, gtk.WRAP_NONE)
+ else:
+ gtk.TextView.set_wrap_mode(self, gtk.WRAP_WORD)
+
+ return False
+
+ def __focus_out_event_cb(self, widget, event):
+ self._text = self.props.buffer.props.text
+ self._accept()
+ return False
+
+ def __key_press_event_cb(self, widget, event):
+ ignore_mask = [gtk.keysyms.Return]
+ if self._max_line_count == 1:
+ ignore_mask.extend([gtk.keysyms.Up, gtk.keysyms.Down])
+
+ if event.keyval in ignore_mask:
+ key_event = event
+ if event.keyval in [gtk.keysyms.Up]:
+ # change Shift mask for backwards keys
+ if key_event.state & gtk.gdk.SHIFT_MASK:
+ key_event.state &= ~gtk.gdk.SHIFT_MASK
+ else:
+ key_event.state |= gtk.gdk.SHIFT_MASK
+ key_event.keyval = gtk.keysyms.Tab
+ key_event.hardware_keycode = 0
+ gtk.main_do_event(key_event)
+ return True
+
+ return False