http://code.google.com/p/labyrinth/source/detail?r=353
Modified:
/trunk/ChangeLog
/trunk/Windows/defs.py
/trunk/Windows/winsetup.py
/trunk/src/BaseThought.py
/trunk/src/Browser.py
/trunk/src/DrawingThought.py
/trunk/src/ImageThought.py
/trunk/src/Links.py
/trunk/src/MMapArea.py
/trunk/src/MainWindow.py
/trunk/src/MapList.py
/trunk/src/PeriodicSaveThread.py
/trunk/src/ResourceThought.py
/trunk/src/TextBufferMarkup.py
/trunk/src/TextThought.py
/trunk/src/TrayIcon.py
/trunk/src/UndoManager.py
/trunk/src/__init__.py
/trunk/src/labyrinth.py
/trunk/src/prefs.py
/trunk/src/utils.py
=======================================
--- /trunk/ChangeLog Sat Apr 23 07:14:18 2011
+++ /trunk/ChangeLog Sat Apr 23 07:28:34 2011
@@ -1,4 +1,9 @@
-2009-03-08 Matthias Vogelgesang <matthias.v...@gmail.com>
+2011-04-23 Matthias Vogelgesang <matthias.v...@gmail.com>
+
+ * src/*.py
+ Respect PEP-8.
+
+2011-04-23 Matthias Vogelgesang <matthias.v...@gmail.com>
* src/MainWindow.py
* src/utils.py
=======================================
--- /trunk/Windows/winsetup.py Fri Apr 6 03:12:35 2007
+++ /trunk/Windows/winsetup.py Sat Apr 23 07:28:34 2011
@@ -22,7 +22,7 @@
# GNU General Public License, version 2 or later
-# for build this on a win32 environment and becames with a standalone
distribution
+# for build this on a win32 environment and becames with a standalone
distribution
# a base python 2.4 for 2in32 instalation must be present
# along with gtk+ development libraries
# pywin32com extensions, reportlab module, pygtk for win32 and
pysqlite-1.1.7.win32-py2.4 (current win32 distro install is using this
pysqlite 3 version)
@@ -50,31 +50,31 @@
import glob
import py2exe
-opts = {
- "py2exe": {
+opts = {
+ "py2exe": {
"includes": "cairo,pangocairo,pango,atk,gobject,xml.dom,xml.dom.minidom,threading,shutil,pygtk,gtk,sys,gtk.glade",
"optimize": 2,
- "dist_dir": "dist\\data_files",
- }
-}
+ "dist_dir": "dist\\data_files",
+ }
+}
setup(
name = "Labyrinth",
description = "Labyrinth",
version = "0.3",
- windows = [
- {
- "script": "src\\labyrinth.py",
- "icon_resources": [(1, "Windows\labyrinth.ico")]
+ windows = [
+ {
+ "script": "src\\labyrinth.py",
+ "icon_resources": [(1, "Windows\labyrinth.ico")]
}],
- options = opts,
- data_files=[
- ("images",
- glob.glob("data\\*.png")),
- ("data",
- glob.glob("data\\*.glade")),
- ("data",
- glob.glob("data\\*.xml")),
- ("",
- glob.glob("src\\*.py"))],
-)
+ options = opts,
+ data_files=[
+ ("images",
+ glob.glob("data\\*.png")),
+ ("data",
+ glob.glob("data\\*.glade")),
+ ("data",
+ glob.glob("data\\*.xml")),
+ ("",
+ glob.glob("src\\*.py"))],
+)
=======================================
--- /trunk/src/BaseThought.py Mon Apr 7 09:58:38 2008
+++ /trunk/src/BaseThought.py Sat Apr 23 07:28:34 2011
@@ -31,308 +31,308 @@
MODE_DRAW = 2
class BaseThought (gobject.GObject):
- ''' The basic class to derive other thoughts from. \
- Instructions for creating derivative thought types are \
- given as comments'''
- # These are general signals. They are available to all thoughts to
- # emit. If you emit other signals, the chances are they'll be ignored
- # by the MMapArea. It's you're responsiblity to catch and handle them.
- # All these signals are handled correctly by the MMapArea.
- __gsignals__ = dict (select_thought = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT,)),
- begin_editing = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ()),
- popup_requested = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT, gobject.TYPE_INT)),
- claim_unending_link = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ()),
- update_view = (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- create_link = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT,)),
- title_changed = (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING,)),
- finish_editing = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ()),
- delete_thought = (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- text_selection_changed = (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_STRING)),
- change_mouse_cursor = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_INT,)),
- update_links = (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- grab_focus = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_BOOLEAN,)),
- update_attrs = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN,
gobject.TYPE_BOOLEAN, pango.FontDescription)))
-
- # The first thing that should be called is this constructor
- # It sets some basic properties of all thoughts and should be called
- # before you start doing you're own thing with thoughts
- # save: the save document passed into the derived constructor
- # elem_type: a string representing the thought type (e.g. "image_thought")
- def __init__ (self, save, elem_type, undo, background_color,
foreground_color):
- # Note: Once the thought has been successfully initialised (i.e. at the
end
- # of the constructor) you MUST set all_okay to True
- # Otherwise, bad things will happen.
- self.all_okay = False
- super (BaseThought, self).__init__()
- self.ul = self.lr = None
- self.am_primary = False
- self.am_selected = False
- self.sensitive = 5
- self.editing = False
- self.identity = -1
- self.index = 0
- self.end_index = 0
- self.text = ""
- self.want_move = False
- self.undo = undo
- self.background_color = background_color
- self.foreground_color = foreground_color
- self.model_iter = None
- extended_elem = save.createElement ("Extended")
- self.extended_buffer = TextBufferMarkup.ExtendedBuffer (self.undo,
extended_elem, save)
- self.extended_buffer.set_text("")
- self.extended_buffer.connect ("set_focus", self.focus_buffer)
- self.extended_buffer.connect ("set_attrs", self.set_extended_attrs)
- self.element = save.createElement (elem_type)
- self.element.appendChild (extended_elem)
-
- # These are self-explanitory. You probably don't want to
- # overwrite these methods, unless you have a very good reason
- def get_save_element (self):
- return self.element
-
- def make_primary (self):
- self.am_primary = True
-
- def select (self):
- self.am_selected = True
-
- def unselect (self):
- self.am_selected = False
-
- def get_max_area (self):
- if not self.ul or not self.lr:
- return 999,999,-999,-999
- return self.ul[0], self.ul[1], self.lr[0], self.lr[1]
-
- def okay (self):
- return self.all_okay
-
- def move_by (self, x, y):
- self.ul = (self.ul[0]+x, self.ul[1]+y)
- self.recalc_edges ()
- self.emit ("update_links")
- self.emit ("update_view")
-
- def focus_buffer (self, buf):
- self.emit ("select_thought", None)
- self.emit ("grab_focus", True)
-
- def set_extended_attrs(self, buf, bold, underline, italics, pango_font):
- self.emit("update_attrs", bold, underline, italics, pango_font)
-
- def can_be_parent (self):
- return True
-
- # This, you may want to change. Though, doing so will only affect
- # thoughts that are "parents"
- def find_connection (self, other):
- if self.editing or other.editing:
- return None, None
- if not self.ul or not self.lr or not other.ul \
- or not other.lr:
- return None, None
-
- if utils.use_bezier_curves:
- if other.ul[0] > self.lr[0]:
- xfrom = self.lr[0]
- xto = other.ul[0]
- else:
- xfrom = self.ul[0]
- xto = other.lr[0]
- else:
- xfrom = self.ul[0]-((self.ul[0]-self.lr[0]) / 2.)
- xto = other.ul[0]-((other.ul[0]-other.lr[0]) / 2.)
-
- yfrom = self.ul[1]-((self.ul[1]-self.lr[1]) / 2.)
- yto = other.ul[1]-((other.ul[1]-other.lr[1]) / 2.)
- return (xfrom, yfrom), (xto, yto)
-
- # All the rest of these should be handled within you're thought
- # type, supposing you actually want to handle them.
- # You almost certianly do want to ;)
- def process_button_down (self, event, mode, transformed):
- return False
-
- def process_button_release (self, event, unending_link, mode,
transformed):
- return False
-
- def process_key_press (self, event, mode):
- return False
-
- def handle_motion (self, event, mode, transformed):
- pass
-
- def includes (self, coords, mode):
- pass
-
- def begin_editing (self):
- return False
-
- def finish_editing (self):
- pass
-
- def draw (self, context):
- pass
-
- def load (self, node):
- pass
-
- def update_save (self):
- pass
-
- def copy_text (self, clip):
- pass
-
- def cut_text (self, clip):
- pass
-
- def paste_text (self, clip):
- pass
-
- def export (self, context, move_x, move_y):
- pass
-
- def commit_text (self, im_context, string, mode):
- pass
-
- def want_motion (self):
- return False
-
- def recalc_edges (self):
- pass
-
- def delete_surroundings(self, imcontext, offset, n_chars, mode):
- pass
-
- def preedit_changed (self, imcontext, mode):
- pass
-
- def preedit_end (self, imcontext, mode):
- pass
-
- def preedit_start (self, imcontext, mode):
- pass
-
- def retrieve_surroundings (self, imcontext, mode):
- pass
-
- def set_bold (self, active):
- pass
-
- def get_popup_menu_items(self):
- pass
+ ''' The basic class to derive other thoughts from. \
+ Instructions for creating derivative thought types are \
+ given as comments'''
+ # These are general signals. They are available to all thoughts to
+ # emit. If you emit other signals, the chances are they'll be ignored
+ # by the MMapArea. It's you're responsiblity to catch and handle them.
+ # All these signals are handled correctly by the MMapArea.
+ __gsignals__ = dict (select_thought = (gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_PYOBJECT,)),
+ begin_editing =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
()),
+ popup_requested =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_PYOBJECT,
gobject.TYPE_INT)),
+ claim_unending_link =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
()),
+ update_view =
(gobject.SIGNAL_RUN_LAST,
+
gobject.TYPE_NONE,
+
()),
+ create_link =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_PYOBJECT,)),
+ title_changed =
(gobject.SIGNAL_RUN_LAST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_STRING,)),
+ finish_editing =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
()),
+ delete_thought =
(gobject.SIGNAL_RUN_LAST,
+
gobject.TYPE_NONE,
+
()),
+ text_selection_changed =
(gobject.SIGNAL_RUN_LAST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_INT,
gobject.TYPE_INT, gobject.TYPE_STRING)),
+ change_mouse_cursor =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_INT,)),
+
update_links = (gobject.SIGNAL_RUN_LAST,
+
gobject.TYPE_NONE,
+
()),
+
grab_focus = (gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_BOOLEAN,)),
+
update_attrs = (gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_BOOLEAN,
gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN,
pango.FontDescription)))
+
+ # The first thing that should be called is this constructor
+ # It sets some basic properties of all thoughts and should be called
+ # before you start doing you're own thing with thoughts
+ # save: the save document passed into the derived constructor
+ # elem_type: a string representing the thought type
(e.g. "image_thought")
+ def __init__ (self, save, elem_type, undo, background_color,
foreground_color):
+ # Note: Once the thought has been successfully initialised (i.e.
at the end
+ # of the constructor) you MUST set all_okay to True
+ # Otherwise, bad things will happen.
+ self.all_okay = False
+ super (BaseThought, self).__init__()
+ self.ul = self.lr = None
+ self.am_primary = False
+ self.am_selected = False
+ self.sensitive = 5
+ self.editing = False
+ self.identity = -1
+ self.index = 0
+ self.end_index = 0
+ self.text = ""
+ self.want_move = False
+ self.undo = undo
+ self.background_color = background_color
+ self.foreground_color = foreground_color
+ self.model_iter = None
+ extended_elem = save.createElement ("Extended")
+ self.extended_buffer = TextBufferMarkup.ExtendedBuffer (self.undo,
extended_elem, save)
+ self.extended_buffer.set_text("")
+ self.extended_buffer.connect ("set_focus", self.focus_buffer)
+ self.extended_buffer.connect ("set_attrs", self.set_extended_attrs)
+ self.element = save.createElement (elem_type)
+ self.element.appendChild (extended_elem)
+
+ # These are self-explanitory. You probably don't want to
+ # overwrite these methods, unless you have a very good reason
+ def get_save_element (self):
+ return self.element
+
+ def make_primary (self):
+ self.am_primary = True
+
+ def select (self):
+ self.am_selected = True
+
+ def unselect (self):
+ self.am_selected = False
+
+ def get_max_area (self):
+ if not self.ul or not self.lr:
+ return 999,999,-999,-999
+ return self.ul[0], self.ul[1], self.lr[0], self.lr[1]
+
+ def okay (self):
+ return self.all_okay
+
+ def move_by (self, x, y):
+ self.ul = (self.ul[0]+x, self.ul[1]+y)
+ self.recalc_edges ()
+ self.emit ("update_links")
+ self.emit ("update_view")
+
+ def focus_buffer (self, buf):
+ self.emit ("select_thought", None)
+ self.emit ("grab_focus", True)
+
+ def set_extended_attrs(self, buf, bold, underline, italics,
pango_font):
+ self.emit("update_attrs", bold, underline, italics, pango_font)
+
+ def can_be_parent (self):
+ return True
+
+ # This, you may want to change. Though, doing so will only affect
+ # thoughts that are "parents"
+ def find_connection (self, other):
+ if self.editing or other.editing:
+ return None, None
+ if not self.ul or not self.lr or not other.ul \
+ or not other.lr:
+ return None, None
+
+ if utils.use_bezier_curves:
+ if other.ul[0] > self.lr[0]:
+ xfrom = self.lr[0]
+ xto = other.ul[0]
+ else:
+ xfrom = self.ul[0]
+ xto = other.lr[0]
+ else:
+ xfrom = self.ul[0]-((self.ul[0]-self.lr[0]) / 2.)
+ xto = other.ul[0]-((other.ul[0]-other.lr[0]) / 2.)
+
+ yfrom = self.ul[1]-((self.ul[1]-self.lr[1]) / 2.)
+ yto = other.ul[1]-((other.ul[1]-other.lr[1]) / 2.)
+ return (xfrom, yfrom), (xto, yto)
+
+ # All the rest of these should be handled within you're thought
+ # type, supposing you actually want to handle them.
+ # You almost certianly do want to ;)
+ def process_button_down (self, event, mode, transformed):
+ return False
+
+ def process_button_release (self, event, unending_link, mode,
transformed):
+ return False
+
+ def process_key_press (self, event, mode):
+ return False
+
+ def handle_motion (self, event, mode, transformed):
+ pass
+
+ def includes (self, coords, mode):
+ pass
+
+ def begin_editing (self):
+ return False
+
+ def finish_editing (self):
+ pass
+
+ def draw (self, context):
+ pass
+
+ def load (self, node):
+ pass
+
+ def update_save (self):
+ pass
+
+ def copy_text (self, clip):
+ pass
+
+ def cut_text (self, clip):
+ pass
+
+ def paste_text (self, clip):
+ pass
+
+ def export (self, context, move_x, move_y):
+ pass
+
+ def commit_text (self, im_context, string, mode):
+ pass
+
+ def want_motion (self):
+ return False
+
+ def recalc_edges (self):
+ pass
+
+ def delete_surroundings(self, imcontext, offset, n_chars, mode):
+ pass
+
+ def preedit_changed (self, imcontext, mode):
+ pass
+
+ def preedit_end (self, imcontext, mode):
+ pass
+
+ def preedit_start (self, imcontext, mode):
+ pass
+
+ def retrieve_surroundings (self, imcontext, mode):
+ pass
+
+ def set_bold (self, active):
+ pass
+
+ def get_popup_menu_items(self):
+ pass
class ResizableThought (BaseThought):
- ''' A resizable thought base class. This allows the sides and corners \
- of the thought to be dragged around. It only provides the very basic
\
- functionality. Other stuff must be done within the derived classes'''
-
- # Possible types of resizing - where the user selected to resize
- RESIZE_NONE = 0
- RESIZE_LEFT = 1
- RESIZE_RIGHT = 2
- RESIZE_TOP = 3
- RESIZE_BOTTOM = 4
- RESIZE_UL = 5
- RESIZE_UR = 6
- RESIZE_LL = 7
- RESIZE_LR = 8
-
- def __init__ (self, save, elem_type, undo, background_color,
foreground_color):
- super (ResizableThought, self).__init__(save, elem_type, undo,
background_color, foreground_color)
- self.resizing = False
- self.button_down = False
-
- def includes (self, coords, mode):
- if not self.ul or not self.lr or not coords:
- return False
-
- inside = (coords[0] < self.lr[0] + self.sensitive) and \
- (coords[0] > self.ul[0] - self.sensitive) and \
- (coords[1] < self.lr[1] + self.sensitive) and \
- (coords[1] > self.ul[1] - self.sensitive)
-
- self.resizing = self.RESIZE_NONE
- self.motion_coords = coords
-
- if inside and (mode != MODE_EDITING or self.button_down):
- self.emit ("change_mouse_cursor", gtk.gdk.LEFT_PTR)
- return inside
-
- if inside:
- # 2 cases: 1. The click was within the main area
- # 2. The click was near the border
- # In the first case, we handle as normal
- # In the second case, we want to intercept all the fun thats
- # going to happen so we can resize the thought
- if abs (coords[0] - self.ul[0]) < self.sensitive:
- # its near the top edge somewhere
- if abs (coords[1] - self.ul[1]) < self.sensitive:
- # Its in the ul corner
- self.resizing = self.RESIZE_UL
- self.emit ("change_mouse_cursor", gtk.gdk.TOP_LEFT_CORNER)
- elif abs (coords[1] - self.lr[1]) < self.sensitive:
- # Its in the ll corner
- self.resizing = self.RESIZE_LL
- self.emit ("change_mouse_cursor", gtk.gdk.BOTTOM_LEFT_CORNER)
- elif coords[1] < self.lr[1] and coords[1] > self.ul[1]:
- #anywhere else along the left edge
- self.resizing = self.RESIZE_LEFT
- self.emit ("change_mouse_cursor", gtk.gdk.LEFT_SIDE)
- elif abs (coords[0] - self.lr[0]) < self.sensitive:
- if abs (coords[1] - self.ul[1]) < self.sensitive:
- # Its in the UR corner
- self.resizing = self.RESIZE_UR
- self.emit ("change_mouse_cursor", gtk.gdk.TOP_RIGHT_CORNER)
- elif abs (coords[1] - self.lr[1]) < self.sensitive:
- # Its in the lr corner
- self.resizing = self.RESIZE_LR
- self.emit ("change_mouse_cursor", gtk.gdk.BOTTOM_RIGHT_CORNER)
- elif coords[1] < self.lr[1] and coords[1] > self.ul[1]:
- #anywhere else along the right edge
- self.resizing = self.RESIZE_RIGHT
- self.emit ("change_mouse_cursor", gtk.gdk.RIGHT_SIDE)
- elif abs (coords[1] - self.ul[1]) < self.sensitive and \
- (coords[0] < self.lr[0] and coords[0] > self.ul[0]):
- # Along the top edge somewhere
- self.resizing = self.RESIZE_TOP
- self.emit ("change_mouse_cursor", gtk.gdk.TOP_SIDE)
- elif abs (coords[1] - self.lr[1]) < self.sensitive and \
- (coords[0] < self.lr[0] and coords[0] > self.ul[0]):
- # Along the bottom edge somewhere
- self.resizing = self.RESIZE_BOTTOM
- self.emit ("change_mouse_cursor", gtk.gdk.BOTTOM_SIDE)
- else:
- self.emit ("change_mouse_cursor", gtk.gdk.LEFT_PTR)
- self.want_move = (self.resizing != self.RESIZE_NONE)
- return inside
+ ''' A resizable thought base class. This allows the sides and corners
\
+ of the thought to be dragged around. It only provides the very
basic \
+ functionality. Other stuff must be done within the derived
classes'''
+
+ # Possible types of resizing - where the user selected to resize
+ RESIZE_NONE = 0
+ RESIZE_LEFT = 1
+ RESIZE_RIGHT = 2
+ RESIZE_TOP = 3
+ RESIZE_BOTTOM = 4
+ RESIZE_UL = 5
+ RESIZE_UR = 6
+ RESIZE_LL = 7
+ RESIZE_LR = 8
+
+ def __init__ (self, save, elem_type, undo, background_color,
foreground_color):
+ super (ResizableThought, self).__init__(save, elem_type, undo,
background_color, foreground_color)
+ self.resizing = False
+ self.button_down = False
+
+ def includes (self, coords, mode):
+ if not self.ul or not self.lr or not coords:
+ return False
+
+ inside = (coords[0] < self.lr[0] + self.sensitive) and \
+ (coords[0] > self.ul[0] - self.sensitive) and \
+ (coords[1] < self.lr[1] + self.sensitive) and \
+ (coords[1] > self.ul[1] - self.sensitive)
+
+ self.resizing = self.RESIZE_NONE
+ self.motion_coords = coords
+
+ if inside and (mode != MODE_EDITING or self.button_down):
+ self.emit ("change_mouse_cursor", gtk.gdk.LEFT_PTR)
+ return inside
+
+ if inside:
+ # 2 cases: 1. The click was within the main area
+ # 2. The click was near the border
+ # In the first case, we handle as normal
+ # In the second case, we want to intercept all the fun thats
+ # going to happen so we can resize the thought
+ if abs (coords[0] - self.ul[0]) < self.sensitive:
+ # its near the top edge somewhere
+ if abs (coords[1] - self.ul[1]) < self.sensitive:
+ # Its in the ul corner
+ self.resizing = self.RESIZE_UL
+ self.emit ("change_mouse_cursor",
gtk.gdk.TOP_LEFT_CORNER)
+ elif abs (coords[1] - self.lr[1]) < self.sensitive:
+ # Its in the ll corner
+ self.resizing = self.RESIZE_LL
+ self.emit ("change_mouse_cursor",
gtk.gdk.BOTTOM_LEFT_CORNER)
+ elif coords[1] < self.lr[1] and coords[1] > self.ul[1]:
+ #anywhere else along the left edge
+ self.resizing = self.RESIZE_LEFT
+ self.emit ("change_mouse_cursor", gtk.gdk.LEFT_SIDE)
+ elif abs (coords[0] - self.lr[0]) < self.sensitive:
+ if abs (coords[1] - self.ul[1]) < self.sensitive:
+ # Its in the UR corner
+ self.resizing = self.RESIZE_UR
+ self.emit ("change_mouse_cursor",
gtk.gdk.TOP_RIGHT_CORNER)
+ elif abs (coords[1] - self.lr[1]) < self.sensitive:
+ # Its in the lr corner
+ self.resizing = self.RESIZE_LR
+ self.emit ("change_mouse_cursor",
gtk.gdk.BOTTOM_RIGHT_CORNER)
+ elif coords[1] < self.lr[1] and coords[1] > self.ul[1]:
+ #anywhere else along the right edge
+ self.resizing = self.RESIZE_RIGHT
+ self.emit ("change_mouse_cursor", gtk.gdk.RIGHT_SIDE)
+ elif abs (coords[1] - self.ul[1]) < self.sensitive and \
+ (coords[0] < self.lr[0] and coords[0] > self.ul[0]):
+ # Along the top edge somewhere
+ self.resizing = self.RESIZE_TOP
+ self.emit ("change_mouse_cursor", gtk.gdk.TOP_SIDE)
+ elif abs (coords[1] - self.lr[1]) < self.sensitive and \
+ (coords[0] < self.lr[0] and coords[0] > self.ul[0]):
+ # Along the bottom edge somewhere
+ self.resizing = self.RESIZE_BOTTOM
+ self.emit ("change_mouse_cursor", gtk.gdk.BOTTOM_SIDE)
+ else:
+ self.emit ("change_mouse_cursor", gtk.gdk.LEFT_PTR)
+ self.want_move = (self.resizing != self.RESIZE_NONE)
+ return inside
=======================================
--- /trunk/src/Browser.py Sun May 11 15:19:37 2008
+++ /trunk/src/Browser.py Sat Apr 23 07:28:34 2011
@@ -2,7 +2,7 @@
# This file is part of Labyrinth
#
# Copyright (C) 2006 - Don Scorgie <D...@Scorgie.org>
-# - Andreas Sliwka <andreas...@gmail.com>
+# - Andreas Sliwka <andreas...@gmail.com>
#
# Labyrinth is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@
from os.path import *
import os
if os.name != 'nt':
- import gconf
+ import gconf
import gtk.glade
import MainWindow
from MapList import MapList
@@ -39,303 +39,302 @@
import gettext
_ = gettext.gettext
-AUTHORS = ['Don Scorgie <D...@Scorgie.org>',
- 'Martin Schaaf <mas...@ma-scha.de>',
- 'Matthias Vogelgesang <matthias.v...@gmail.com>',
- 'Andreas Sliwka <andreas...@gmail.com>']
+AUTHORS = ['Don Scorgie <D...@Scorgie.org>',
+ 'Martin Schaaf <mas...@ma-scha.de>',
+ 'Matthias Vogelgesang <matthias.v...@gmail.com>',
+ 'Andreas Sliwka <andreas...@gmail.com>']
class Browser (gtk.Window):
- COL_ID = 0
- COL_TITLE = 1
- COL_MODTIME = 2
-
- def __init__(self, start_hidden, tray_icon):
- super(Browser, self).__init__()
- self.glade=gtk.glade.XML(utils.get_data_file_name('labyrinth.glade'))
- self.view = self.glade.get_widget ('MainView')
- self.populate_view ()
- self.view.connect ('row-activated', self.open_row_cb)
- self.view.connect ('cursor-changed', self.cursor_change_cb)
-
- self.view_dependants = []
-
- self.open_button = self.glade.get_widget('OpenButton')
- self.delete_button = self.glade.get_widget('DeleteButton')
- self.open_menu = self.glade.get_widget('open1')
- self.delete_menu = self.glade.get_widget('delete1')
-
- self.view_dependants.append (self.open_button)
- self.view_dependants.append (self.delete_button)
- self.view_dependants.append (self.open_menu)
- self.view_dependants.append (self.delete_menu)
-
- self.open_button.connect ('clicked', self.open_clicked)
- self.glade.get_widget('NewButton').connect ('clicked', self.new_clicked)
- self.delete_button.connect ('clicked', self.delete_clicked)
-
- self.open_menu.connect ('activate', self.open_clicked)
- self.glade.get_widget('new1').connect ('activate', self.new_clicked)
- self.delete_menu.connect ('activate', self.delete_clicked)
- self.glade.get_widget('import1').connect ('activate',
self.import_clicked)
- self.glade.get_widget('quit1').connect ('activate', self.quit_clicked)
- self.glade.get_widget('about1').connect ('activate', self.about_clicked)
- self.glade.get_widget('showhelp').connect ('activate',
self.show_help_clicked)
-
- map(lambda x : x.set_sensitive(False), self.view_dependants)
-
- props = { gnome.PARAM_APP_DATADIR : '/usr/share' }
- prog = gnome.program_init('labyrinth', '0.5', properties=props)
-
- self.main_window = self.glade.get_widget ('MapBrowser')
-
- # set remembered size
- if os.name != 'nt':
- self.config_client = gconf.client_get_default()
- self.config_client.add_dir ("/apps/labyrinth",
gconf.CLIENT_PRELOAD_NONE)
-
- width = self.config_client.get_int ('/apps/labyrinth/width')
- height = self.config_client.get_int ('/apps/labyrinth/height')
- utils.use_bezier_curves = self.config_client.get_bool
('/apps/labyrinth/curves')
- if width == 0 or height == 0:
- width = 400
- height = 300
- else:
- width = 400
- height = 300
-
- view_sortable = self.view.get_model ()
- view_sortable.connect ('sort-column-changed',
self.sort_column_changed_cb)
- if os.name != 'nt':
- sort_order =
self.config_client.get_int('/apps/labyrinth/map_sort_order')
- column_id =
self.config_client.get_int('/apps/labyrinth/map_sort_order_column')
- view_sortable.set_sort_column_id (column_id, sort_order)
-
- self.main_window.resize (width, height)
-
- if os.name != 'nt':
- try:
- self.main_window.set_icon_name ('labyrinth')
- except:
-
self.main_window.set_icon_from_file(utils.get_data_file_name('labyrinth.svg'))
- else:
- self.main_window.set_icon_from_file('images\\labyrinth-24.png')
- if tray_icon:
- self.main_window.connect ('delete_event', self.toggle_main_window, None)
- traymenu = gtk.Menu()
- quit_item = gtk.MenuItem("Quit")
- quit_item.connect("activate",self.quit_clicked)
- traymenu.add(quit_item)
- traymenu.show_all()
- self.traymenu = traymenu
- self.trayicon = TrayIcon.TrayIcon(
- icon_name="labyrinth",
- menu=traymenu,
- activate=self.toggle_main_window)
- else:
- self.main_window.connect('delete_event', self.quit_clicked, None)
- if start_hidden:
- self.main_window.hide ()
- else:
- self.main_window.show_all ()
-
- def toggle_main_window(self,*args):
- if self.main_window.get_property("visible"):
- self.main_window.hide()
- else:
- self.main_window.show()
- return True
-
- def map_title_cb (self, mobj, new_title, mobj1):
- map = MapList.get_by_window(mobj)
- if not map:
- raise AttributeError ("What a mess, can't find the map")
- map.title = new_title
-
- def get_selected_map(self):
- sel = self.view.get_selection ()
- (model, it) = sel.get_selected ()
- if it:
- (num,) = MapList.tree_view_model.get (it, self.COL_ID)
- return MapList.get_by_index(num)
- return None
-
- def cursor_change_cb (self, treeview):
- selected_map = self.get_selected_map ()
- sensitive = not not self.get_selected_map ()
- map(lambda x : x.set_sensitive(sensitive), self.view_dependants)
-
- def open_map_filename (self, fname):
- win = MainWindow.LabyrinthWindow (fname)
- win.show ()
-
- def open_map (self, map, imported=False):
- win = MainWindow.LabyrinthWindow (map.filename, imported)
- win.connect ("title-changed", self.map_title_cb)
- win.connect ("window_closed", self.remove_map_cb)
- win.connect ("file_saved", self.file_save_cb)
- win.show ()
- map.window = win
- return (MapList.index(map), win)
-
- def open_selected_map(self):
- map = self.get_selected_map()
- if map is None:
- raise "you clicked the 'open' button bud had no map selected"
- if map.window:
- print "Window for map '%s' is already open" % map.title
- # may be the window should be raised?
- else:
- self.open_map (map)
-
- def show_help_clicked(self, arg):
- try:
- gnome.help_display('labyrinth')
- except gobject.GError, e:
- print _('Unable to display help: %s') % str(e)
-
- def about_clicked (self, arg):
- about_dialog = gtk.AboutDialog ()
- about_dialog.set_name ("Labyrinth")
- about_dialog.set_version (utils.get_version())
- if os.name != 'nt':
- try:
- about_dialog.set_logo_icon_name("labyrinth")
- except:
- pass
- else:
- about_dialog.set_logo
(gtk.gdk.pixbuf_new_from_file("images\\labyrinth-24.png"))
- about_dialog.set_license (
- "Labyrinth is free software; you can redistribute it and/or modify "
- "it under the terms of the GNU General Public Licence as published by "
- "the Free Software Foundation; either version 2 of the Licence, or "
- "(at your option) any later version."
- "\n\n"
- "Labyrinth 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 Licence for more details."
- "\n\n"
- "You should have received a copy of the GNU General Public Licence "
- "along with Labyrinth; if not, write to the Free Software Foundation,
Inc., "
- "59 Temple Place, Suite 330, Boston, MA 02111-1307 USA")
- about_dialog.set_wrap_license (True)
- about_dialog.set_copyright ("2006-2008 Don Scorgie et. al")
- about_dialog.set_authors (AUTHORS)
- about_dialog.set_website ("http://code.google.com/p/labyrinth")
- about_dialog.set_translator_credits (_("Translation by Don Scorgie"))
- about_dialog.run ()
- about_dialog.hide ()
- del (about_dialog)
- return
-
- def open_clicked (self, button):
- self.open_selected_map()
-
- def open_row_cb (self, view, path, col):
- self.open_selected_map ()
-
- def new_clicked (self, button):
- map = MapList.create_empty_map()
- self.open_map(map)
-
- def delete_clicked (self, button):
- map = self.get_selected_map ()
- if not map:
- raise "You clicked on delete but had no map selected"
- error_message = ""
- if map.window:
- error_message = _("The map cannot be deleted right now. Is it open?")
- elif not map.filename:
- error_message = _("The map has no associated filename.")
- if error_message:
- dialog = gtk.MessageDialog (self, gtk.DIALOG_MODAL,
gtk.MESSAGE_WARNING, gtk.BUTTONS_OK,
- _("Cannot delete this map"))
- dialog.format_secondary_text (error_message)
- dialog.run ()
- dialog.hide ()
- del (dialog)
- return
- dialog = gtk.MessageDialog (self, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING,
gtk.BUTTONS_YES_NO,
- _("Do you really want to delete this Map?"))
- resp = dialog.run ()
- dialog.hide ()
- del (dialog)
- if resp != gtk.RESPONSE_YES:
- return
- MapList.delete (map)
- self.view.emit ('cursor-changed')
-
- def remove_map_cb (self, mobj, a):
- map = MapList.get_by_window(mobj)
- if map:
- MapList.delete(map)
- self.view.emit ('cursor-changed')
- return
- raise "Cant remove map of window %s" % mobj
-
- def file_save_cb (self, mobj, new_fname, mobj1):
- map = MapList.get_by_window(mobj)
- if map:
- map.window = None
- map.filename = new_fname
- return
-
- def import_clicked(self, button, other=None, *data):
- chooser = gtk.FileChooserDialog(title=_("Open File"),
action=gtk.FILE_CHOOSER_ACTION_OPEN, \
- buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN,
gtk.RESPONSE_OK))
-
- filtr = gtk.FileFilter ()
- filtr.set_name(_('MAPZ Compressed Map (*.mapz)'))
- filtr.add_pattern('*.mapz')
- chooser.add_filter(filtr)
-
- response = chooser.run()
- if response == gtk.RESPONSE_OK:
- filename = chooser.get_filename()
- tf = tarfile.open(filename)
- mapname = utils.get_save_dir() + tf.getnames()[0]
- tf.extractall(utils.get_save_dir())
- tf.close()
- map = MapList.new_from_file(mapname)
- map.filename = mapname
-
- chooser.destroy()
-
- def quit_clicked (self, button, other=None, *data):
- for map in MapList.get_open_windows():
- map.window.close_window_cb (None)
-
- width, height = self.main_window.get_size()
-
- if os.name != 'nt':
- self.config_client.set_int('/apps/labyrinth/width', width)
- self.config_client.set_int('/apps/labyrinth/height', height)
-
- gtk.main_quit ()
-
- def populate_view (self):
- cellrenderer = gtk.CellRendererText()
- cellrenderer.set_property("ellipsize", pango.ELLIPSIZE_END)
- column = gtk.TreeViewColumn(_("Map Name"), cellrenderer,
- text=self.COL_TITLE)
- column.set_resizable(True)
- column.set_expand (True)
- column.set_sort_column_id (1)
- self.view.append_column(column)
-
- col1 = gtk.TreeViewColumn (_("Last Modified"), gtk.CellRendererText(),
- text=self.COL_MODTIME)
- col1.set_resizable(True)
- col1.set_sort_column_id (2)
- self.view.append_column(col1)
-
- self.view.set_model (MapList.get_TreeViewModel())
- self.view.set_search_column(self.COL_TITLE)
- self.view.set_enable_search (True)
-
- def sort_column_changed_cb (self, data):
- column_id, sort_order = data.get_sort_column_id ()
- if os.name != 'nt':
- self.config_client.set_int('/apps/labyrinth/map_sort_order', sort_order)
- self.config_client.set_int('/apps/labyrinth/map_sort_order_column',
column_id)
-
+ COL_ID = 0
+ COL_TITLE = 1
+ COL_MODTIME = 2
+
+ def __init__(self, start_hidden, tray_icon):
+ super(Browser, self).__init__()
+
self.glade=gtk.glade.XML(utils.get_data_file_name('labyrinth.glade'))
+ self.view = self.glade.get_widget ('MainView')
+ self.populate_view ()
+ self.view.connect ('row-activated', self.open_row_cb)
+ self.view.connect ('cursor-changed', self.cursor_change_cb)
+
+ self.view_dependants = []
+
+ self.open_button = self.glade.get_widget('OpenButton')
+ self.delete_button = self.glade.get_widget('DeleteButton')
+ self.open_menu = self.glade.get_widget('open1')
+ self.delete_menu = self.glade.get_widget('delete1')
+
+ self.view_dependants.append (self.open_button)
+ self.view_dependants.append (self.delete_button)
+ self.view_dependants.append (self.open_menu)
+ self.view_dependants.append (self.delete_menu)
+
+ self.open_button.connect ('clicked', self.open_clicked)
+ self.glade.get_widget('NewButton').connect ('clicked',
self.new_clicked)
+ self.delete_button.connect ('clicked', self.delete_clicked)
+
+ self.open_menu.connect ('activate', self.open_clicked)
+ self.glade.get_widget('new1').connect ('activate',
self.new_clicked)
+ self.delete_menu.connect ('activate', self.delete_clicked)
+ self.glade.get_widget('import1').connect ('activate',
self.import_clicked)
+ self.glade.get_widget('quit1').connect ('activate',
self.quit_clicked)
+ self.glade.get_widget('about1').connect ('activate',
self.about_clicked)
+ self.glade.get_widget('showhelp').connect ('activate',
self.show_help_clicked)
+
+ map(lambda x : x.set_sensitive(False), self.view_dependants)
+
+ props = { gnome.PARAM_APP_DATADIR : '/usr/share' }
+ prog = gnome.program_init('labyrinth', '0.5', properties=props)
+
+ self.main_window = self.glade.get_widget ('MapBrowser')
+
+ # set remembered size
+ if os.name != 'nt':
+ self.config_client = gconf.client_get_default()
+ self.config_client.add_dir ("/apps/labyrinth",
gconf.CLIENT_PRELOAD_NONE)
+
+ width = self.config_client.get_int ('/apps/labyrinth/width')
+ height = self.config_client.get_int ('/apps/labyrinth/height')
+ utils.use_bezier_curves = self.config_client.get_bool
('/apps/labyrinth/curves')
+ if width == 0 or height == 0:
+ width = 400
+ height = 300
+ else:
+ width = 400
+ height = 300
+
+ view_sortable = self.view.get_model ()
+ view_sortable.connect ('sort-column-changed',
self.sort_column_changed_cb)
+ if os.name != 'nt':
+ sort_order =
self.config_client.get_int('/apps/labyrinth/map_sort_order')
+ column_id =
self.config_client.get_int('/apps/labyrinth/map_sort_order_column')
+ view_sortable.set_sort_column_id (column_id, sort_order)
+
+ self.main_window.resize (width, height)
+
+ if os.name != 'nt':
+ try:
+ self.main_window.set_icon_name ('labyrinth')
+ except:
+
self.main_window.set_icon_from_file(utils.get_data_file_name('labyrinth.svg'))
+ else:
+ self.main_window.set_icon_from_file('images\\labyrinth-24.png')
+ if tray_icon:
+ self.main_window.connect ('delete_event',
self.toggle_main_window, None)
+ traymenu = gtk.Menu()
+ quit_item = gtk.MenuItem("Quit")
+ quit_item.connect("activate",self.quit_clicked)
+ traymenu.add(quit_item)
+ traymenu.show_all()
+ self.traymenu = traymenu
+ self.trayicon = TrayIcon.TrayIcon(
+ icon_name="labyrinth",
+ menu=traymenu,
+
activate=self.toggle_main_window)
+ else:
+ self.main_window.connect('delete_event', self.quit_clicked,
None)
+ if start_hidden:
+ self.main_window.hide ()
+ else:
+ self.main_window.show_all ()
+
+ def toggle_main_window(self,*args):
+ if self.main_window.get_property("visible"):
+ self.main_window.hide()
+ else:
+ self.main_window.show()
+ return True
+
+ def map_title_cb (self, mobj, new_title, mobj1):
+ map = MapList.get_by_window(mobj)
+ if not map:
+ raise AttributeError ("What a mess, can't find the map")
+ map.title = new_title
+
+ def get_selected_map(self):
+ sel = self.view.get_selection ()
+ (model, it) = sel.get_selected ()
+ if it:
+ (num,) = MapList.tree_view_model.get (it, self.COL_ID)
+ return MapList.get_by_index(num)
+ return None
+
+ def cursor_change_cb (self, treeview):
+ selected_map = self.get_selected_map ()
+ sensitive = not not self.get_selected_map ()
+ map(lambda x : x.set_sensitive(sensitive), self.view_dependants)
+
+ def open_map_filename (self, fname):
+ win = MainWindow.LabyrinthWindow (fname)
+ win.show ()
+
+ def open_map (self, map, imported=False):
+ win = MainWindow.LabyrinthWindow (map.filename, imported)
+ win.connect ("title-changed", self.map_title_cb)
+ win.connect ("window_closed", self.remove_map_cb)
+ win.connect ("file_saved", self.file_save_cb)
+ win.show ()
+ map.window = win
+ return (MapList.index(map), win)
+
+ def open_selected_map(self):
+ map = self.get_selected_map()
+ if map is None:
+ raise "you clicked the 'open' button bud had no map selected"
+ if map.window:
+ print "Window for map '%s' is already open" % map.title
+ # may be the window should be raised?
+ else:
+ self.open_map (map)
+
+ def show_help_clicked(self, arg):
+ try:
+ gnome.help_display('labyrinth')
+ except gobject.GError, e:
+ print _('Unable to display help: %s') % str(e)
+
+ def about_clicked (self, arg):
+ about_dialog = gtk.AboutDialog ()
+ about_dialog.set_name ("Labyrinth")
+ about_dialog.set_version (utils.get_version())
+ if os.name != 'nt':
+ try:
+ about_dialog.set_logo_icon_name("labyrinth")
+ except:
+ pass
+ else:
+ about_dialog.set_logo
(gtk.gdk.pixbuf_new_from_file("images\\labyrinth-24.png"))
+ about_dialog.set_license (
+"Labyrinth is free software; you can redistribute it and/or modify "
+"it under the terms of the GNU General Public Licence as published by "
+"the Free Software Foundation; either version 2 of the Licence, or "
+"(at your option) any later version."
+"\n\n"
+"Labyrinth 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 Licence for more details."
+"\n\n"
+"You should have received a copy of the GNU General Public Licence "
+"along with Labyrinth; if not, write to the Free Software Foundation,
Inc., "
+"59 Temple Place, Suite 330, Boston, MA 02111-1307 USA")
+ about_dialog.set_wrap_license (True)
+ about_dialog.set_copyright ("2006-2008 Don Scorgie et. al")
+ about_dialog.set_authors (AUTHORS)
+ about_dialog.set_website ("http://code.google.com/p/labyrinth")
+ about_dialog.set_translator_credits (_("Translation by Don
Scorgie"))
+ about_dialog.run ()
+ about_dialog.hide ()
+ del (about_dialog)
+ return
+
+ def open_clicked (self, button):
+ self.open_selected_map()
+
+ def open_row_cb (self, view, path, col):
+ self.open_selected_map ()
+
+ def new_clicked (self, button):
+ map = MapList.create_empty_map()
+ self.open_map(map)
+
+ def delete_clicked (self, button):
+ map = self.get_selected_map ()
+ if not map:
+ raise "You clicked on delete but had no map selected"
+ error_message = ""
+ if map.window:
+ error_message = _("The map cannot be deleted right now. Is it
open?")
+ elif not map.filename:
+ error_message = _("The map has no associated filename.")
+ if error_message:
+ dialog = gtk.MessageDialog (self, gtk.DIALOG_MODAL,
gtk.MESSAGE_WARNING, gtk.BUTTONS_OK,
+ _("Cannot
delete this map"))
+ dialog.format_secondary_text (error_message)
+ dialog.run ()
+ dialog.hide ()
+ del (dialog)
+ return
+ dialog = gtk.MessageDialog (self, gtk.DIALOG_MODAL,
gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO,
+ _("Do you
really want to delete this Map?"))
+ resp = dialog.run ()
+ dialog.hide ()
+ del (dialog)
+ if resp != gtk.RESPONSE_YES:
+ return
+ MapList.delete (map)
+ self.view.emit ('cursor-changed')
+
+ def remove_map_cb (self, mobj, a):
+ map = MapList.get_by_window(mobj)
+ if map:
+ MapList.delete(map)
+ self.view.emit ('cursor-changed')
+ return
+ raise "Cant remove map of window %s" % mobj
+
+ def file_save_cb (self, mobj, new_fname, mobj1):
+ map = MapList.get_by_window(mobj)
+ if map:
+ map.window = None
+ map.filename = new_fname
+ return
+
+ def import_clicked(self, button, other=None, *data):
+ chooser = gtk.FileChooserDialog(title=_("Open File"),
action=gtk.FILE_CHOOSER_ACTION_OPEN, \
+
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN,
gtk.RESPONSE_OK))
+
+ filtr = gtk.FileFilter ()
+ filtr.set_name(_('MAPZ Compressed Map (*.mapz)'))
+ filtr.add_pattern('*.mapz')
+ chooser.add_filter(filtr)
+
+ response = chooser.run()
+ if response == gtk.RESPONSE_OK:
+ filename = chooser.get_filename()
+ tf = tarfile.open(filename)
+ mapname = utils.get_save_dir() + tf.getnames()[0]
+ tf.extractall(utils.get_save_dir())
+ tf.close()
+ map = MapList.new_from_file(mapname)
+ map.filename = mapname
+
+ chooser.destroy()
+
+ def quit_clicked (self, button, other=None, *data):
+ for map in MapList.get_open_windows():
+ map.window.close_window_cb (None)
+
+ width, height = self.main_window.get_size()
+
+ if os.name != 'nt':
+ self.config_client.set_int('/apps/labyrinth/width', width)
+ self.config_client.set_int('/apps/labyrinth/height', height)
+
+ gtk.main_quit ()
+
+ def populate_view (self):
+ cellrenderer = gtk.CellRendererText()
+ cellrenderer.set_property("ellipsize", pango.ELLIPSIZE_END)
+ column = gtk.TreeViewColumn(_("Map Name"), cellrenderer,
+
text=self.COL_TITLE)
+ column.set_resizable(True)
+ column.set_expand (True)
+ column.set_sort_column_id (1)
+ self.view.append_column(column)
+
+ col1 = gtk.TreeViewColumn (_("Last Modified"),
gtk.CellRendererText(),
+
text=self.COL_MODTIME)
+ col1.set_resizable(True)
+ col1.set_sort_column_id (2)
+ self.view.append_column(col1)
+
+ self.view.set_model (MapList.get_TreeViewModel())
+ self.view.set_search_column(self.COL_TITLE)
+ self.view.set_enable_search (True)
+
+ def sort_column_changed_cb (self, data):
+ column_id, sort_order = data.get_sort_column_id ()
+ if os.name != 'nt':
+ self.config_client.set_int('/apps/labyrinth/map_sort_order',
sort_order)
+
self.config_client.set_int('/apps/labyrinth/map_sort_order_column',
column_id)
=======================================
--- /trunk/src/DrawingThought.py Fri Apr 11 09:31:48 2008
+++ /trunk/src/DrawingThought.py Sat Apr 23 07:28:34 2011
@@ -44,576 +44,576 @@
UNDO_ERASE = 2
class DrawingThought (BaseThought.ResizableThought):
- class DrawingPoint (object):
- def __init__ (self, coords, style=STYLE_CONTINUE, color =
gtk.gdk.Color(0,0,0), width = 2):
- self.x, self.y = coords
- self.style = style
- if color == None:
- color = gtk.gdk.Color(0,0,0)
- self.color = color
- self.width = 1
- def move_by (self, x, y):
- self.x += x
- self.y += y
-
- def __init__ (self, coords, pango_context, thought_number, save, undo,
loading, background_color, foreground_color):
- global ndraw
- super (DrawingThought, self).__init__(save, "drawing_thought", undo,
background_color, foreground_color)
- ndraw+=1
- self.identity = thought_number
- self.want_move = False
- self.points = []
- self.text = _("Drawing #%d" % ndraw)
- self.drawing = 0
- if not loading:
- margin = utils.margin_required (utils.STYLE_NORMAL)
- self.ul = (coords[0]-margin[0], coords[1]-margin[1])
- self.lr = (coords[0]+100+margin[2], coords[1]+100+margin[3])
- self.min_x = coords[0]+90
- self.max_x = coords[0]+15
- self.min_y = coords[1]+90
- self.max_y = coords[1]+15
- self.width = 100
- self.height = 100
-
- self.all_okay = True
-
- def draw (self, context):
- if len (self.extended_buffer.get_text()) == 0:
- utils.draw_thought_outline (context, self.ul, self.lr,
self.background_color, self.am_selected, self.am_primary,
utils.STYLE_NORMAL)
- else:
- utils.draw_thought_outline (context, self.ul, self.lr,
self.background_color, self.am_selected, self.am_primary,
utils.STYLE_EXTENDED_CONTENT)
- cwidth = context.get_line_width ()
- context.set_line_width (2)
- if len (self.points) > 0:
- for p in self.points:
- if p.style == STYLE_BEGIN:
- context.move_to (p.x, p.y)
- r,g,b = utils.gtk_to_cairo_color(self.foreground_color)
- context.set_source_rgb (r, g, b)
- elif p.style == STYLE_END:
- context.line_to (p.x, p.y)
- context.stroke()
- else:
- context.line_to (p.x, p.y)
-
- context.set_line_width (cwidth)
- context.stroke ()
- return
-
- def want_motion (self):
- return self.want_move
-
- def recalc_edges (self):
- self.lr = (self.ul[0]+self.width, self.ul[1]+self.height)
-
- def undo_resize (self, action, mode):
- self.undo.block ()
- choose = 1
- if mode == UndoManager.UNDO:
- choose = 0
- self.ul = action.args[choose][0]
- self.width = action.args[choose][1]
- self.height = action.args[choose][2]
- self.recalc_edges ()
- self.emit ("update_links")
- self.emit ("update_view")
- self.undo.unblock ()
-
- def undo_drawing (self, action, mode):
- self.undo.block ()
- if mode == UndoManager.UNDO:
- choose = 1
- for p in action.args[0]:
- self.points.remove (p)
- else:
- choose = 2
- for p in action.args[0]:
- self.points.append (p)
-
- self.ul = action.args[choose][0]
- self.width = action.args[choose][1]
- self.height = action.args[choose][2]
- self.recalc_edges ()
- self.emit ("update_links")
- self.emit ("update_view")
- self.undo.unblock ()
-
- def process_button_down (self, event, mode, transformed):
- modifiers = gtk.accelerator_get_default_mod_mask ()
- self.button_down = True
- if event.button == 1:
- if event.type == gtk.gdk.BUTTON_PRESS:
- self.emit ("select_thought", event.state & modifiers)
- self.emit ("update_view")
- if mode == MODE_EDITING and self.resizing != self.RESIZE_NONE:
- self.want_move = True
- self.drawing = 0
- self.orig_size = (self.ul, self.width, self.height)
- return True
- elif mode == MODE_DRAW:
- self.want_move = True
- self.drawing = 2
- if not event.state & gtk.gdk.SHIFT_MASK:
- self.drawing = 1
- self.orig_size = (self.ul, self.width, self.height)
- self.ins_points = []
- self.del_points = []
- return True
- elif event.button == 3:
- self.emit ("popup_requested", event, 1)
- self.emit ("update_view")
-
- def process_button_release (self, event, unending_link, mode,
transformed):
- self.button_down = False
- if unending_link:
- unending_link.set_child (self)
- self.emit ("claim_unending_link")
- if len(self.points) > 0:
- self.points[-1].style=STYLE_END
- self.emit ("update_view")
- if self.want_move and self.drawing == 0:
- self.undo.add_undo (UndoManager.UndoAction (self, UNDO_RESIZE,
self.undo_resize, \
- self.orig_size, (self.ul, self.width, self.height)))
- elif self.want_move and self.drawing == 1:
- self.undo.add_undo (UndoManager.UndoAction (self, UNDO_DRAW,
self.undo_drawing, \
- self.ins_points, self.orig_size, \
- (self.ul, self.width, self.height)))
- elif self.want_move and self.drawing == 2:
- self.undo.add_undo (UndoManager.UndoAction (self, UNDO_ERASE,
self.undo_erase, \
- self.ins_points))
- self.drawing = 0
- self.want_move = False
-
- def undo_erase (self, action, mode):
- self.undo.block ()
- action.args[0].reverse ()
- if mode == UndoManager.UNDO:
- for x in action.args[0]:
- if x[0] == 0:
- self.points.remove (x[2])
- else:
- self.points.insert (x[1],x[2])
- else:
- for x in action.args[0]:
- if x[0] == 0:
- self.points.insert (x[1], x[2])
- else:
- self.points.remove (x[2])
- self.undo.unblock ()
- self.emit ("update_view")
-
- def handle_motion (self, event, mode, transformed):
- if (self.resizing == self.RESIZE_NONE or not self.want_move or not
event.state & gtk.gdk.BUTTON1_MASK) \
- and mode != MODE_DRAW:
- if not event.state & gtk.gdk.BUTTON1_MASK or mode != MODE_EDITING:
- return False
- else:
- self.emit ("create_link", \
- (self.ul[0]-((self.ul[0]-self.lr[0]) / 2.),
self.ul[1]-((self.ul[1]-self.lr[1]) / 2.)))
- diffx = transformed[0] - self.motion_coords[0]
- diffy = transformed[1] - self.motion_coords[1]
- change = (len(self.points) == 0)
- tmp = self.motion_coords
- self.motion_coords = transformed
- if self.resizing != self.RESIZE_NONE:
- if self.resizing == self.RESIZE_LEFT:
- if self.ul[0] + diffx > self.min_x:
- self.motion_coords = tmp
- return True
- self.ul = (self.ul[0]+diffx, self.ul[1])
- if change:
- self.max_x += diffx
- elif self.resizing == self.RESIZE_RIGHT:
- if self.lr[0] + diffx < self.max_x:
- self.motion_coords = tmp
- return True
- self.lr = (self.lr[0]+diffx, self.lr[1])
- if change:
- self.min_x += diffx
- elif self.resizing == self.RESIZE_TOP:
- if self.ul[1] + diffy > self.min_y:
- self.motion_coords = tmp
- return True
- self.ul = (self.ul[0], self.ul[1]+diffy)
- if change:
- self.max_y += diffy
- elif self.resizing == self.RESIZE_BOTTOM:
- if self.lr[1] + diffy < self.max_y:
- self.motion_coords = tmp
- return True
- self.lr = (self.lr[0], self.lr[1]+diffy)
- if change:
- self.min_y += diffy
- elif self.resizing == self.RESIZE_UL:
- if self.ul[1] + diffy > self.min_y or self.ul[0] + diffx > self.min_x:
- self.motion_coords = tmp
- return True
- self.ul = (self.ul[0]+diffx, self.ul[1]+diffy)
- if change:
- self.max_x += diffx
- self.max_y += diffy
- elif self.resizing == self.RESIZE_UR:
- if self.ul[1] + diffy > self.min_y or self.lr[0] + diffx < self.max_x:
- self.motion_coords = tmp
- return True
- self.ul = (self.ul[0], self.ul[1]+diffy)
- self.lr = (self.lr[0]+diffx, self.lr[1])
- if change:
- self.min_x += diffx
- self.max_y += diffy
- elif self.resizing == self.RESIZE_LL:
- if self.lr[1] + diffy < self.max_y or self.ul[0] + diffx > self.min_x:
- self.motion_coords = tmp
- return True
- self.ul = (self.ul[0]+diffx, self.ul[1])
- self.lr = (self.lr[0], self.lr[1]+diffy)
- if change:
- self.max_x += diffx
- self.min_y += diffy
- elif self.resizing == self.RESIZE_LR:
- if self.lr[1] + diffy < self.max_y:
- self.motion_coords = tmp
- return True
- if self.lr[0] + diffx < self.max_x:
- self.motion_coords = tmp
- return True
- self.lr = (self.lr[0]+diffx, self.lr[1]+diffy)
- if change:
- self.min_x += diffx
- self.min_y += diffy
- self.width = self.lr[0] - self.ul[0]
- self.height = self.lr[1] - self.ul[1]
- self.emit ("update_links")
- self.emit ("update_view")
- return True
-
- elif self.drawing == 1:
- if transformed[0] < self.ul[0]+5:
- self.ul = (transformed[0]-5, self.ul[1])
- elif transformed[0] > self.lr[0]-5:
- self.lr = (transformed[0]+5, self.lr[1])
- if transformed[1] < self.ul[1]+5:
- self.ul = (self.ul[0], transformed[1]-5)
- elif transformed[1] > self.lr[1]-5:
- self.lr = (self.lr[0], transformed[1]+5)
-
- if transformed[0] < self.min_x:
- self.min_x = transformed[0]-10
- elif transformed[0] > self.max_x:
- self.max_x = transformed[0]+5
- if transformed[1] < self.min_y:
- self.min_y = transformed[1]-10
- elif transformed[1] > self.max_y:
- self.max_y = transformed[1]+5
- self.width = self.lr[0] - self.ul[0]
- self.height = self.lr[1] - self.ul[1]
- if len(self.points) == 0 or self.points[-1].style == STYLE_END:
- p = self.DrawingPoint (transformed, STYLE_BEGIN, self.foreground_color)
- else:
- p = self.DrawingPoint (transformed, STYLE_CONTINUE)
- self.points.append (p)
- self.ins_points.append (p)
- elif self.drawing == 2 and len (self.points) > 0:
- out = self.points[0]
- loc = []
- handle = []
- ins_point = -1
-
- for x in self.points:
- ins_point += 1
- dist = (x.x - transformed[0])**2 + (x.y - transformed[1])**2
-
- if dist < 16:
- if x == self.points[0]:
- out = None
- loc.append ((ins_point, x, dist))
- else:
- if len(loc) != 0:
- handle.append ((loc, out, x))
- loc = []
- elif x.style != STYLE_BEGIN:
- x1 = x.x - out.x
- y1 = x.y - out.y
- d_rsqr = x1**2 + y1 **2
- d = ((out.x-transformed[0])*(x.y-transformed[1]) -
(x.x-transformed[0])*(out.y-transformed[1]))
- det = (d_rsqr*16) - d**2
- if det > 0:
- xt = -99999
- yt = -99999
- xalt = -99999
- yalt = -99999
- if y1 < 0:
- sgn = -1
- else:
- sgn = 1
- xt = (((d*y1) + sgn*x1 * math.sqrt (det)) / d_rsqr) +transformed[0]
- xalt = (((d*y1) - sgn*x1 * math.sqrt (det)) / d_rsqr)
+transformed[0]
- yt = (((-d*x1) + abs(y1)*math.sqrt(det)) / d_rsqr) + transformed[1]
- yalt = (((-d*x1) - abs(y1)*math.sqrt(det)) / d_rsqr) +transformed[1]
- x1_inside = (xt > x.x and xt < out.x) or (xt > out.x and xt < x.x)
- x2_inside = (xalt > x.x and xalt < out.x) or (xalt > out.x and xalt
< x.x)
- y1_inside = (yt > x.y and yt < out.y) or (yt > out.y and yt < x.y)
- y2_inside = (yalt > x.y and yalt < out.y) or (yalt > out.y and yalt
< x.y)
+ class DrawingPoint (object):
+ def __init__ (self, coords, style=STYLE_CONTINUE, color =
gtk.gdk.Color(0,0,0), width = 2):
+ self.x, self.y = coords
+ self.style = style
+ if color == None:
+ color = gtk.gdk.Color(0,0,0)
+ self.color = color
+ self.width = 1
+ def move_by (self, x, y):
+ self.x += x
+ self.y += y
+
+ def __init__ (self, coords, pango_context, thought_number, save, undo,
loading, background_color, foreground_color):
+ global ndraw
+ super (DrawingThought, self).__init__(save, "drawing_thought",
undo, background_color, foreground_color)
+ ndraw+=1
+ self.identity = thought_number
+ self.want_move = False
+ self.points = []
+ self.text = _("Drawing #%d" % ndraw)
+ self.drawing = 0
+ if not loading:
+ margin = utils.margin_required (utils.STYLE_NORMAL)
+ self.ul = (coords[0]-margin[0], coords[1]-margin[1])
+ self.lr = (coords[0]+100+margin[2], coords[1]+100+margin[3])
+ self.min_x = coords[0]+90
+ self.max_x = coords[0]+15
+ self.min_y = coords[1]+90
+ self.max_y = coords[1]+15
+ self.width = 100
+ self.height = 100
+
+ self.all_okay = True
+
+ def draw (self, context):
+ if len (self.extended_buffer.get_text()) == 0:
+ utils.draw_thought_outline (context, self.ul, self.lr,
self.background_color, self.am_selected, self.am_primary,
utils.STYLE_NORMAL)
+ else:
+ utils.draw_thought_outline (context, self.ul, self.lr,
self.background_color, self.am_selected, self.am_primary,
utils.STYLE_EXTENDED_CONTENT)
+ cwidth = context.get_line_width ()
+ context.set_line_width (2)
+ if len (self.points) > 0:
+ for p in self.points:
+ if p.style == STYLE_BEGIN:
+ context.move_to (p.x, p.y)
+ r,g,b = utils.gtk_to_cairo_color(self.foreground_color)
+ context.set_source_rgb (r, g, b)
+ elif p.style == STYLE_END:
+ context.line_to (p.x, p.y)
+ context.stroke()
+ else:
+ context.line_to (p.x, p.y)
+
+ context.set_line_width (cwidth)
+ context.stroke ()
+ return
+
+ def want_motion (self):
+ return self.want_move
+
+ def recalc_edges (self):
+ self.lr = (self.ul[0]+self.width, self.ul[1]+self.height)
+
+ def undo_resize (self, action, mode):
+ self.undo.block ()
+ choose = 1
+ if mode == UndoManager.UNDO:
+ choose = 0
+ self.ul = action.args[choose][0]
+ self.width = action.args[choose][1]
+ self.height = action.args[choose][2]
+ self.recalc_edges ()
+ self.emit ("update_links")
+ self.emit ("update_view")
+ self.undo.unblock ()
+
+ def undo_drawing (self, action, mode):
+ self.undo.block ()
+ if mode == UndoManager.UNDO:
+ choose = 1
+ for p in action.args[0]:
+ self.points.remove (p)
+ else:
+ choose = 2
+ for p in action.args[0]:
+ self.points.append (p)
+
+ self.ul = action.args[choose][0]
+ self.width = action.args[choose][1]
+ self.height = action.args[choose][2]
+ self.recalc_edges ()
+ self.emit ("update_links")
+ self.emit ("update_view")
+ self.undo.unblock ()
+
+ def process_button_down (self, event, mode, transformed):
+ modifiers = gtk.accelerator_get_default_mod_mask ()
+ self.button_down = True
+ if event.button == 1:
+ if event.type == gtk.gdk.BUTTON_PRESS:
+ self.emit ("select_thought", event.state & modifiers)
+ self.emit ("update_view")
+ if mode == MODE_EDITING and self.resizing != self.RESIZE_NONE:
+ self.want_move = True
+ self.drawing = 0
+ self.orig_size = (self.ul, self.width, self.height)
+ return True
+ elif mode == MODE_DRAW:
+ self.want_move = True
+ self.drawing = 2
+ if not event.state & gtk.gdk.SHIFT_MASK:
+ self.drawing = 1
+ self.orig_size = (self.ul, self.width, self.height)
+ self.ins_points = []
+ self.del_points = []
+ return True
+ elif event.button == 3:
+ self.emit ("popup_requested", event, 1)
+ self.emit ("update_view")
+
+ def process_button_release (self, event, unending_link, mode,
transformed):
+ self.button_down = False
+ if unending_link:
+ unending_link.set_child (self)
+ self.emit ("claim_unending_link")
+ if len(self.points) > 0:
+ self.points[-1].style=STYLE_END
+ self.emit ("update_view")
+ if self.want_move and self.drawing == 0:
+ self.undo.add_undo (UndoManager.UndoAction (self, UNDO_RESIZE,
self.undo_resize, \
+
self.orig_size,
(self.ul, self.width, self.height)))
+ elif self.want_move and self.drawing == 1:
+ self.undo.add_undo (UndoManager.UndoAction (self, UNDO_DRAW,
self.undo_drawing, \
+
self.ins_points,
self.orig_size, \
+
(self.ul,
self.width, self.height)))
+ elif self.want_move and self.drawing == 2:
+ self.undo.add_undo (UndoManager.UndoAction (self, UNDO_ERASE,
self.undo_erase, \
+
self.ins_points))
+ self.drawing = 0
+ self.want_move = False
+
+ def undo_erase (self, action, mode):
+ self.undo.block ()
+ action.args[0].reverse ()
+ if mode == UndoManager.UNDO:
+ for x in action.args[0]:
+ if x[0] == 0:
+ self.points.remove (x[2])
+ else:
+ self.points.insert (x[1],x[2])
+ else:
+ for x in action.args[0]:
+ if x[0] == 0:
+ self.points.insert (x[1], x[2])
+ else:
+ self.points.remove (x[2])
+ self.undo.unblock ()
+ self.emit ("update_view")
+
+ def handle_motion (self, event, mode, transformed):
+ if (self.resizing == self.RESIZE_NONE or not self.want_move or not
event.state & gtk.gdk.BUTTON1_MASK) \
+ and mode != MODE_DRAW:
+ if not event.state & gtk.gdk.BUTTON1_MASK or mode !=
MODE_EDITING:
+ return False
+ else:
+ self.emit ("create_link", \
+ (self.ul[0]-((self.ul[0]-self.lr[0]) / 2.),
self.ul[1]-((self.ul[1]-self.lr[1]) / 2.)))
+ diffx = transformed[0] - self.motion_coords[0]
+ diffy = transformed[1] - self.motion_coords[1]
+ change = (len(self.points) == 0)
+ tmp = self.motion_coords
+ self.motion_coords = transformed
+ if self.resizing != self.RESIZE_NONE:
+ if self.resizing == self.RESIZE_LEFT:
+ if self.ul[0] + diffx > self.min_x:
+ self.motion_coords = tmp
+ return True
+ self.ul = (self.ul[0]+diffx, self.ul[1])
+ if change:
+ self.max_x += diffx
+ elif self.resizing == self.RESIZE_RIGHT:
+ if self.lr[0] + diffx < self.max_x:
+ self.motion_coords = tmp
+ return True
+ self.lr = (self.lr[0]+diffx, self.lr[1])
+ if change:
+ self.min_x += diffx
+ elif self.resizing == self.RESIZE_TOP:
+ if self.ul[1] + diffy > self.min_y:
+ self.motion_coords = tmp
+ return True
+ self.ul = (self.ul[0], self.ul[1]+diffy)
+ if change:
+ self.max_y += diffy
+ elif self.resizing == self.RESIZE_BOTTOM:
+ if self.lr[1] + diffy < self.max_y:
+ self.motion_coords = tmp
+ return True
+ self.lr = (self.lr[0], self.lr[1]+diffy)
+ if change:
+ self.min_y += diffy
+ elif self.resizing == self.RESIZE_UL:
+ if self.ul[1] + diffy > self.min_y or self.ul[0] + diffx >
self.min_x:
+ self.motion_coords = tmp
+ return True
+ self.ul = (self.ul[0]+diffx, self.ul[1]+diffy)
+ if change:
+ self.max_x += diffx
+ self.max_y += diffy
+ elif self.resizing == self.RESIZE_UR:
+ if self.ul[1] + diffy > self.min_y or self.lr[0] + diffx <
self.max_x:
+ self.motion_coords = tmp
+ return True
+ self.ul = (self.ul[0], self.ul[1]+diffy)
+ self.lr = (self.lr[0]+diffx, self.lr[1])
+ if change:
+ self.min_x += diffx
+ self.max_y += diffy
+ elif self.resizing == self.RESIZE_LL:
+ if self.lr[1] + diffy < self.max_y or self.ul[0] + diffx >
self.min_x:
+ self.motion_coords = tmp
+ return True
+ self.ul = (self.ul[0]+diffx, self.ul[1])
+ self.lr = (self.lr[0], self.lr[1]+diffy)
+ if change:
+ self.max_x += diffx
+ self.min_y += diffy
+ elif self.resizing == self.RESIZE_LR:
+ if self.lr[1] + diffy < self.max_y:
+ self.motion_coords = tmp
+ return True
+ if self.lr[0] + diffx < self.max_x:
+ self.motion_coords = tmp
+ return True
+ self.lr = (self.lr[0]+diffx, self.lr[1]+diffy)
+ if change:
+ self.min_x += diffx
+ self.min_y += diffy
+ self.width = self.lr[0] - self.ul[0]
+ self.height = self.lr[1] - self.ul[1]
+ self.emit ("update_links")
+ self.emit ("update_view")
+ return True
+
+ elif self.drawing == 1:
+ if transformed[0] < self.ul[0]+5:
+ self.ul = (transformed[0]-5, self.ul[1])
+ elif transformed[0] > self.lr[0]-5:
+ self.lr = (transformed[0]+5, self.lr[1])
+ if transformed[1] < self.ul[1]+5:
+ self.ul = (self.ul[0], transformed[1]-5)
+ elif transformed[1] > self.lr[1]-5:
+ self.lr = (self.lr[0], transformed[1]+5)
+
+ if transformed[0] < self.min_x:
+ self.min_x = transformed[0]-10
+ elif transformed[0] > self.max_x:
+ self.max_x = transformed[0]+5
+ if transformed[1] < self.min_y:
+ self.min_y = transformed[1]-10
+ elif transformed[1] > self.max_y:
+ self.max_y = transformed[1]+5
+ self.width = self.lr[0] - self.ul[0]
+ self.height = self.lr[1] - self.ul[1]
+ if len(self.points) == 0 or self.points[-1].style == STYLE_END:
+ p = self.DrawingPoint (transformed, STYLE_BEGIN,
self.foreground_color)
+ else:
+ p = self.DrawingPoint (transformed, STYLE_CONTINUE)
+ self.points.append (p)
+ self.ins_points.append (p)
+ elif self.drawing == 2 and len (self.points) > 0:
+ out = self.points[0]
+ loc = []
+ handle = []
+ ins_point = -1
+
+ for x in self.points:
+ ins_point += 1
+ dist = (x.x - transformed[0])**2 + (x.y -
transformed[1])**2
+
+ if dist < 16:
+ if x == self.points[0]:
+ out = None
+ loc.append ((ins_point, x, dist))
+ else:
+ if len(loc) != 0:
+ handle.append ((loc, out, x))
+ loc = []
+ elif x.style != STYLE_BEGIN:
+ x1 = x.x - out.x
+ y1 = x.y - out.y
+ d_rsqr = x1**2 + y1 **2
+ d = ((out.x-transformed[0])*(x.y-transformed[1]) -
(x.x-transformed[0])*(out.y-transformed[1]))
+ det = (d_rsqr*16) - d**2
+ if det > 0:
+ xt = -99999
+ yt = -99999
+ xalt = -99999
+ yalt = -99999
+ if y1 < 0:
+ sgn = -1
+ else:
+ sgn = 1
+ xt = (((d*y1) + sgn*x1 * math.sqrt (det)) /
d_rsqr) +transformed[0]
+ xalt = (((d*y1) - sgn*x1 * math.sqrt (det)) /
d_rsqr) +transformed[0]
+ yt = (((-d*x1) + abs(y1)*math.sqrt(det)) /
d_rsqr) + transformed[1]
+ yalt = (((-d*x1) - abs(y1)*math.sqrt(det)) /
d_rsqr) +transformed[1]
+ x1_inside = (xt > x.x and xt < out.x) or (xt >
out.x and xt < x.x)
+ x2_inside = (xalt > x.x and xalt < out.x) or
(xalt > out.x and xalt < x.x)
+ y1_inside = (yt > x.y and yt < out.y) or (yt >
out.y and yt < x.y)
+ y2_inside = (yalt > x.y and yalt < out.y) or
(yalt > out.y and yalt < x.y)
- if (x1_inside and x2_inside and y1_inside and y2_inside):
- if abs (xalt - x.x) < abs (xt - x.x):
- handle.append ((None, out, x, ins_point, xt, xalt, yt, yalt))
- else:
- handle.append ((None, out, x, ins_point, xalt, xt, yalt, yt))
- elif x.x == out.x and y1_inside and y2_inside:
- if abs (yalt - x.y) < abs (yt - x.y):
- handle.append ((None, out, x, ins_point, xt, xalt, yt, yalt))
- else:
- handle.append ((None, out, x, ins_point, xalt, xt, yalt, yt))
- elif x.y == out.y and x1_inside and x2_inside:
- if abs (xalt - x.x) < abs (xt - x.x):
- handle.append ((None, out, x, ins_point, xt, xalt, yt, yalt))
- else:
- handle.append ((None, out, x, ins_point, xalt, xt, yalt, yt))
-
- out = x
- if loc:
- handle.append ((loc, out, None))
- appends = []
- dels = []
- for l in handle:
- inside = l[0]
- prev = l[1]
- next = l[2]
- if not inside:
- ins = l[3]
- x1 = l[4]
- x2 = l[5]
- y1 = l[6]
- y2 = l[7]
- p1 = self.DrawingPoint ((x1,y1), STYLE_END)
- p2 = self.DrawingPoint ((x2,y2), STYLE_BEGIN)
- appends.append ((p1, ins))
- appends.append ((p2, ins))
- else:
- first = inside[0][1]
- last = inside[-1][1]
- done_ins = 0
- if last.style != STYLE_END:
- end_dist = math.sqrt (inside[-1][2]) - 4
- alpha = math.atan2 ((last.y-next.y), (last.x-next.x))
- new_x = end_dist * math.cos(alpha) + last.x
- new_y = end_dist * math.sin(alpha) + last.y
- p = self.DrawingPoint ((new_x, new_y), STYLE_BEGIN)
- appends.append ((p, inside[-1][0]))
- done_ins = 1
- if first.style != STYLE_BEGIN:
- start_dist = math.sqrt (inside[0][2]) - 4
- alpha = math.atan2 ((first.y-prev.y),(first.x-prev.x))
- new_x = start_dist * math.cos (alpha) + first.x
- new_y = start_dist * math.sin (alpha) + first.y
- p = self.DrawingPoint ((new_x, new_y), STYLE_END)
- appends.append ((p, inside[0][0]-done_ins))
- for i in inside:
- dels.append (i[1])
- inserts = 0
- for x in appends:
- self.points.insert (x[1]+inserts, x[0])
- self.ins_points.append ((0, x[1]+inserts, x[0]))
- inserts+=1
- for x in dels:
- self.ins_points.append ((1, self.points.index (x), x))
- self.points.remove (x)
-
- self.emit ("update_links")
- self.emit ("update_view")
- return True
-
- def move_by (self, x, y):
- self.ul = (self.ul[0]+x, self.ul[1]+y)
- self.min_x += x
- self.min_y += y
- self.max_x += x
- self.max_y += y
- map(lambda p : p.move_by(x,y), self.points)
- self.recalc_edges ()
- self.emit ("update_links")
-
- def update_save (self):
- next = self.element.firstChild
- while next:
- m = next.nextSibling
- if next.nodeName == "point":
- self.element.removeChild (next)
- next.unlink ()
- next = m
- text = self.extended_buffer.get_text ()
- if text:
- self.extended_buffer.update_save()
- else:
- try:
- self.element.removeChild(self.extended_buffer.element)
- except xml.dom.NotFoundErr:
- pass
- self.element.setAttribute ("ul-coords", str(self.ul))
- self.element.setAttribute ("lr-coords", str(self.lr))
- self.element.setAttribute ("identity", str(self.identity))
- self.element.setAttribute ("background-color",
self.background_color.to_string())
- self.element.setAttribute ("foreground-color",
self.foreground_color.to_string())
- self.element.setAttribute ("min_x", str(self.min_x))
- self.element.setAttribute ("min_y", str(self.min_y))
- self.element.setAttribute ("max_x", str(self.max_x))
- self.element.setAttribute ("max_y", str(self.max_y))
-
- if self.am_selected:
- self.element.setAttribute ("current_root", "true")
- else:
- try:
- self.element.removeAttribute ("current_root")
- except xml.dom.NotFoundErr:
- pass
- if self.am_primary:
- self.element.setAttribute ("primary_root", "true");
- else:
- try:
- self.element.removeAttribute ("primary_root")
- except xml.dom.NotFoundErr:
- pass
- doc = self.element.ownerDocument
- for p in self.points:
- elem = doc.createElement ("point")
- self.element.appendChild (elem)
- elem.setAttribute ("coords", str((p.x,p.y)))
- elem.setAttribute ("type", str(p.style))
- elem.setAttribute ("color", p.color.to_string())
- return
-
- def load (self, node):
- tmp = node.getAttribute ("ul-coords")
- self.ul = utils.parse_coords (tmp)
- tmp = node.getAttribute ("lr-coords")
- self.lr = utils.parse_coords (tmp)
- self.identity = int (node.getAttribute ("identity"))
- try:
- tmp = node.getAttribute ("background-color")
- self.background_color = gtk.gdk.color_parse(tmp)
- tmp = node.getAttribute ("foreground-color")
- self.foreground_color = gtk.gdk.color_parse(tmp)
- except ValueError:
- pass
- self.min_x = float(node.getAttribute ("min_x"))
- self.min_y = float(node.getAttribute ("min_y"))
- self.max_x = float(node.getAttribute ("max_x"))
- self.max_y = float(node.getAttribute ("max_y"))
-
- self.width = self.lr[0] - self.ul[0]
- self.height = self.lr[1] - self.ul[1]
-
- self.am_selected = node.hasAttribute ("current_root")
- self.am_primary = node.hasAttribute ("primary_root")
-
- for n in node.childNodes:
- if n.nodeName == "Extended":
- self.extended_buffer.load(n)
- elif n.nodeName == "point":
- style = int (n.getAttribute ("type"))
- tmp = n.getAttribute ("coords")
- c = utils.parse_coords (tmp)
- col = None
- try:
- tmp = n.getAttribute ("color")
- col = gtk.gdk.color_parse (tmp)
- except ValueError:
- pass
- self.points.append (self.DrawingPoint (c, style, col))
- else:
- print "Unknown node type: "+str(n.nodeName)
-
- def export (self, context, move_x, move_y):
- utils.export_thought_outline (context, self.ul, self.lr,
self.background_color, self.am_selected, self.am_primary,
utils.STYLE_NORMAL,
- (move_x, move_y))
- cwidth = context.get_line_width ()
- context.set_line_width (1)
- if len (self.points) > 0:
- for p in self.points:
- if p.style == STYLE_BEGIN:
- context.move_to (p.x+move_x, p.y+move_y)
- else:
- context.line_to (p.x+move_x,p.y+move_y)
-
- context.set_line_width (cwidth)
- r,g,b = utils.gtk_to_cairo_color(self.foreground_color)
- context.set_source_rgb (r, g, b)
- context.stroke ()
- return
-
- def includes (self, coords, mode):
- if not self.ul or not self.lr or not coords:
- return False
-
- if self.want_move and mode == MODE_DRAW:
- self.emit ("change_mouse_cursor", gtk.gdk.PENCIL)
- return True
-
- inside = (coords[0] < self.lr[0] + self.sensitive) and \
- (coords[0] > self.ul[0] - self.sensitive) and \
- (coords[1] < self.lr[1] + self.sensitive) and \
- (coords[1] > self.ul[1] - self.sensitive)
-
- self.resizing = self.RESIZE_NONE
- self.motion_coords = coords
-
- if inside and (mode != MODE_EDITING or self.button_down):
- if mode == MODE_DRAW:
- self.emit ("change_mouse_cursor", gtk.gdk.PENCIL)
- else:
- self.emit ("change_mouse_cursor", gtk.gdk.LEFT_PTR)
- return inside
-
- if inside:
- # 2 cases: 1. The click was within the main area
- # 2. The click was near the border
- # In the first case, we handle as normal
- # In the second case, we want to intercept all the fun thats
- # going to happen so we can resize the thought
- if abs (coords[0] - self.ul[0]) < self.sensitive:
- # its near the top edge somewhere
- if abs (coords[1] - self.ul[1]) < self.sensitive:
- # Its in the ul corner
- self.resizing = self.RESIZE_UL
- self.emit ("change_mouse_cursor", gtk.gdk.TOP_LEFT_CORNER)
- elif abs (coords[1] - self.lr[1]) < self.sensitive:
- # Its in the ll corner
- self.resizing = self.RESIZE_LL
- self.emit ("change_mouse_cursor", gtk.gdk.BOTTOM_LEFT_CORNER)
- elif coords[1] < self.lr[1] and coords[1] > self.ul[1]:
- #anywhere else along the left edge
- self.resizing = self.RESIZE_LEFT
- self.emit ("change_mouse_cursor", gtk.gdk.LEFT_SIDE)
- elif abs (coords[0] - self.lr[0]) < self.sensitive:
- if abs (coords[1] - self.ul[1]) < self.sensitive:
- # Its in the UR corner
- self.resizing = self.RESIZE_UR
- self.emit ("change_mouse_cursor", gtk.gdk.TOP_RIGHT_CORNER)
- elif abs (coords[1] - self.lr[1]) < self.sensitive:
- # Its in the lr corner
- self.resizing = self.RESIZE_LR
- self.emit ("change_mouse_cursor", gtk.gdk.BOTTOM_RIGHT_CORNER)
- elif coords[1] < self.lr[1] and coords[1] > self.ul[1]:
- #anywhere else along the right edge
- self.resizing = self.RESIZE_RIGHT
- self.emit ("change_mouse_cursor", gtk.gdk.RIGHT_SIDE)
- elif abs (coords[1] - self.ul[1]) < self.sensitive and \
- (coords[0] < self.lr[0] and coords[0] > self.ul[0]):
- # Along the top edge somewhere
- self.resizing = self.RESIZE_TOP
- self.emit ("change_mouse_cursor", gtk.gdk.TOP_SIDE)
- elif abs (coords[1] - self.lr[1]) < self.sensitive and \
- (coords[0] < self.lr[0] and coords[0] > self.ul[0]):
- # Along the bottom edge somewhere
- self.resizing = self.RESIZE_BOTTOM
- self.emit ("change_mouse_cursor", gtk.gdk.BOTTOM_SIDE)
- else:
- self.emit ("change_mouse_cursor", gtk.gdk.LEFT_PTR)
- self.want_move = (self.resizing != self.RESIZE_NONE)
- return inside
-
- def get_popup_menu_items(self):
- return []
+ if (x1_inside and x2_inside and y1_inside and
y2_inside):
+ if abs (xalt - x.x) < abs (xt - x.x):
+ handle.append ((None, out, x,
ins_point, xt, xalt, yt, yalt))
+ else:
+ handle.append ((None, out, x,
ins_point, xalt, xt, yalt, yt))
+ elif x.x == out.x and y1_inside and y2_inside:
+ if abs (yalt - x.y) < abs (yt - x.y):
+ handle.append ((None, out, x,
ins_point, xt, xalt, yt, yalt))
+ else:
+ handle.append ((None, out, x,
ins_point, xalt, xt, yalt, yt))
+ elif x.y == out.y and x1_inside and x2_inside:
+ if abs (xalt - x.x) < abs (xt - x.x):
+ handle.append ((None, out, x,
ins_point, xt, xalt, yt, yalt))
+ else:
+ handle.append ((None, out, x,
ins_point, xalt, xt, yalt, yt))
+
+ out = x
+ if loc:
+ handle.append ((loc, out, None))
+ appends = []
+ dels = []
+ for l in handle:
+ inside = l[0]
+ prev = l[1]
+ next = l[2]
+ if not inside:
+ ins = l[3]
+ x1 = l[4]
+ x2 = l[5]
+ y1 = l[6]
+ y2 = l[7]
+ p1 = self.DrawingPoint ((x1,y1), STYLE_END)
+ p2 = self.DrawingPoint ((x2,y2), STYLE_BEGIN)
+ appends.append ((p1, ins))
+ appends.append ((p2, ins))
+ else:
+ first = inside[0][1]
+ last = inside[-1][1]
+ done_ins = 0
+ if last.style != STYLE_END:
+ end_dist = math.sqrt (inside[-1][2]) - 4
+ alpha = math.atan2 ((last.y-next.y),
(last.x-next.x))
+ new_x = end_dist * math.cos(alpha) + last.x
+ new_y = end_dist * math.sin(alpha) + last.y
+ p = self.DrawingPoint ((new_x, new_y), STYLE_BEGIN)
+ appends.append ((p, inside[-1][0]))
+ done_ins = 1
+ if first.style != STYLE_BEGIN:
+ start_dist = math.sqrt (inside[0][2]) - 4
+ alpha = math.atan2
((first.y-prev.y),(first.x-prev.x))
+ new_x = start_dist * math.cos (alpha) + first.x
+ new_y = start_dist * math.sin (alpha) + first.y
+ p = self.DrawingPoint ((new_x, new_y), STYLE_END)
+ appends.append ((p, inside[0][0]-done_ins))
+ for i in inside:
+ dels.append (i[1])
+ inserts = 0
+ for x in appends:
+ self.points.insert (x[1]+inserts, x[0])
+ self.ins_points.append ((0, x[1]+inserts, x[0]))
+ inserts+=1
+ for x in dels:
+ self.ins_points.append ((1, self.points.index (x), x))
+ self.points.remove (x)
+
+ self.emit ("update_links")
+ self.emit ("update_view")
+ return True
+
+ def move_by (self, x, y):
+ self.ul = (self.ul[0]+x, self.ul[1]+y)
+ self.min_x += x
+ self.min_y += y
+ self.max_x += x
+ self.max_y += y
+ map(lambda p : p.move_by(x,y), self.points)
+ self.recalc_edges ()
+ self.emit ("update_links")
+
+ def update_save (self):
+ next = self.element.firstChild
+ while next:
+ m = next.nextSibling
+ if next.nodeName == "point":
+ self.element.removeChild (next)
+ next.unlink ()
+ next = m
+ text = self.extended_buffer.get_text ()
+ if text:
+ self.extended_buffer.update_save()
+ else:
+ try:
+ self.element.removeChild(self.extended_buffer.element)
+ except xml.dom.NotFoundErr:
+ pass
+ self.element.setAttribute ("ul-coords", str(self.ul))
+ self.element.setAttribute ("lr-coords", str(self.lr))
+ self.element.setAttribute ("identity", str(self.identity))
+ self.element.setAttribute ("background-color",
self.background_color.to_string())
+ self.element.setAttribute ("foreground-color",
self.foreground_color.to_string())
+ self.element.setAttribute ("min_x", str(self.min_x))
+ self.element.setAttribute ("min_y", str(self.min_y))
+ self.element.setAttribute ("max_x", str(self.max_x))
+ self.element.setAttribute ("max_y", str(self.max_y))
+
+ if self.am_selected:
+ self.element.setAttribute ("current_root", "true")
+ else:
+ try:
+ self.element.removeAttribute ("current_root")
+ except xml.dom.NotFoundErr:
***The diff for this file has been truncated for email.***
=======================================
--- /trunk/src/ImageThought.py Tue Apr 8 10:27:31 2008
+++ /trunk/src/ImageThought.py Sat Apr 23 07:28:34 2011
@@ -37,301 +37,299 @@
UNDO_RESIZE = 0
class ImageThought (BaseThought.ResizableThought):
- def __init__ (self, coords, pango_context, thought_number, save, undo,
loading, background_color):
- super (ImageThought, self).__init__(save, "image_thought", undo,
background_color, None)
-
- self.identity = thought_number
- margin = utils.margin_required (utils.STYLE_NORMAL)
- self.want_move = False
- if coords:
- self.ul = (coords[0]-margin[0], coords[1] - margin[1])
- self.pic_location = coords
- else:
- self.ul = None
- self.button_press = False
-
- if not loading:
- self.all_okay = self.open_image ()
- else:
- self.all_okay = True
-
- def open_image (self, filename = None):
- # Present a dialog for the user to choose an image here
- if not filename:
- fil = gtk.FileFilter ()
- fil.set_name("Images")
- fil.add_pixbuf_formats ()
- dialog = gtk.FileChooserDialog (_("Choose image to insert"), None,
gtk.FILE_CHOOSER_ACTION_OPEN, \
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
- dialog.add_filter (fil)
- res = dialog.run ()
- dialog.hide ()
- if res != gtk.RESPONSE_OK:
- return False
- else:
- fname = dialog.get_filename()
- else:
- fname = filename
-
- try:
- self.orig_pic = gtk.gdk.pixbuf_new_from_file (fname)
- except:
- try:
- # lets see if file was imported and is already extracted
- fname = utils.get_save_dir() + 'images/' +
utils.strip_path_from_file_name(filename)
- self.orig_pic = gtk.gdk.pixbuf_new_from_file (fname)
- except:
- return False
-
- self.filename = fname
-
- if not filename:
- self.width = self.orig_pic.get_width ()
- self.height = self.orig_pic.get_height ()
- margin = utils.margin_required (utils.STYLE_NORMAL)
-
- self.lr = (self.pic_location[0]+self.width+margin[2],
self.pic_location[1]+self.height+margin[3])
- self.pic = self.orig_pic
- self.text = fname[fname.rfind('/')+1:fname.rfind('.')]
- return True
-
- def draw (self, context):
- if len (self.extended_buffer.get_text()) == 0:
- utils.draw_thought_outline (context, self.ul, self.lr,
self.background_color, self.am_selected, self.am_primary,
utils.STYLE_NORMAL)
- else:
- utils.draw_thought_outline (context, self.ul, self.lr,
self.background_color, self.am_selected, self.am_primary,
utils.STYLE_EXTENDED_CONTENT)
-
- if self.pic:
- context.set_source_pixbuf (self.pic, self.pic_location[0],
self.pic_location[1])
- context.rectangle (self.pic_location[0], self.pic_location[1],
self.width, self.height)
- context.fill ()
- context.set_source_rgb (0,0,0)
-
- def export (self, context, move_x, move_y):
- utils.export_thought_outline (context, self.ul, self.lr,
self.background_color, self.am_selected, self.am_primary,
utils.STYLE_NORMAL,
- (move_x, move_y))
- if self.pic:
- if hasattr(context, "set_source_pixbuf"):
- context.set_source_pixbuf (self.pic, self.pic_location[0]+move_x,
self.pic_location[1]+move_y)
- elif hasattr(context, "set_source_surface"):
- pixel_array = utils.pixbuf_to_cairo (self.pic.get_pixels_array())
- image_surface = cairo.ImageSurface.create_for_data(pixel_array,
cairo.FORMAT_ARGB32, self.width, self.height, -1)
- context.set_source_surface (image_surface,
self.pic_location[0]+move_x, self.pic_location[1]+move_y)
- context.rectangle (self.pic_location[0]+move_x,
self.pic_location[1]+move_y, self.width, self.height)
- context.fill ()
- context.set_source_rgb (0,0,0)
-
- def want_motion (self):
- return self.want_move
-
- def recalc_edges (self):
- margin = utils.margin_required (utils.STYLE_NORMAL)
- self.pic_location = (self.ul[0]+margin[0], self.ul[1]+margin[1])
- self.lr = (self.pic_location[0]+self.width+margin[2],
self.pic_location[1]+self.height+margin[3])
-
- def undo_resize (self, action, mode):
- self.undo.block ()
- if mode == UndoManager.UNDO:
- choose = 0
- else:
- choose = 1
- self.ul = action.args[choose][0]
- self.width = action.args[choose][1]
- self.height = action.args[choose][2]
- self.pic = self.orig_pic.scale_simple (int(self.width),
int(self.height), gtk.gdk.INTERP_HYPER)
- self.recalc_edges ()
- self.emit ("update_links")
- self.emit ("update_view")
- self.undo.unblock ()
-
- def process_button_down (self, event, mode, transformed):
- modifiers = gtk.accelerator_get_default_mod_mask ()
- self.button_down = True
- if event.button == 1:
- if event.type == gtk.gdk.BUTTON_PRESS:
- self.emit ("select_thought", event.state & modifiers)
- self.emit ("update_view")
- if mode == MODE_EDITING and self.resizing != self.RESIZE_NONE:
- self.orig_size = (self.ul, self.width, self.height)
- self.want_move = True
- return True
- elif event.button == 3:
- self.emit ("popup_requested", event, 1)
- self.emit ("update_view")
-
- def process_button_release (self, event, unending_link, mode,
transformed):
- self.button_down = False
- if unending_link:
- unending_link.set_child (self)
- self.emit ("claim_unending_link")
- if self.orig_pic:
- self.pic = self.orig_pic.scale_simple (int(self.width),
int(self.height), gtk.gdk.INTERP_HYPER)
- self.emit ("update_view")
- if self.want_move:
- self.undo.add_undo (UndoManager.UndoAction (self, UNDO_RESIZE,
self.undo_resize, \
- self.orig_size, (self.ul, self.width, self.height)))
- self.want_move = False
-
- def handle_motion (self, event, mode, transformed):
- if self.resizing == self.RESIZE_NONE or not self.want_move or not
event.state & gtk.gdk.BUTTON1_MASK:
- if not event.state & gtk.gdk.BUTTON1_MASK:
- return False
- elif mode == MODE_EDITING:
- self.emit ("create_link", \
- (self.ul[0]-((self.ul[0]-self.lr[0]) / 2.),
self.ul[1]-((self.ul[1]-self.lr[1]) / 2.)))
- return True
- diffx = transformed[0] - self.motion_coords[0]
- diffy = transformed[1] - self.motion_coords[1]
- tmp = self.motion_coords
- self.motion_coords = transformed
- if self.resizing == self.RESIZE_LEFT:
- if self.width - diffx < 10:
- self.motion_coords = tmp
- return True
- self.ul = (self.ul[0]+diffx, self.ul[1])
- self.pic_location = (self.pic_location[0]+diffx, self.pic_location[1])
- self.width -= diffx
- elif self.resizing == self.RESIZE_RIGHT:
- if self.width + diffx < 10:
- self.motion_coords = tmp
- return True
- self.lr = (self.lr[0]+diffx, self.lr[1])
- self.width += diffx
- elif self.resizing == self.RESIZE_TOP:
- if self.height - diffy < 10:
- self.motion_coords = tmp
- return True
- self.ul = (self.ul[0], self.ul[1]+diffy)
- self.pic_location = (self.pic_location[0], self.pic_location[1]+diffy)
- self.height -= diffy
- elif self.resizing == self.RESIZE_BOTTOM:
- if self.height + diffy < 10:
- self.motion_coords = tmp
- return True
- self.lr = (self.lr[0], self.lr[1]+diffy)
- self.height += diffy
- elif self.resizing == self.RESIZE_UL:
- if self.height - diffy < 10 or self.width - diffx < 10:
- self.motion_coords = tmp
- return True
- self.ul = (self.ul[0]+diffx, self.ul[1]+diffy)
- self.pic_location = (self.pic_location[0]+diffx,
self.pic_location[1]+diffy)
- self.width -= diffx
- self.height -= diffy
- elif self.resizing == self.RESIZE_UR:
- if self.height - diffy < 10 or self.width + diffx < 10:
- self.motion_coords = tmp
- return True
- self.ul = (self.ul[0], self.ul[1]+diffy)
- self.lr = (self.lr[0]+diffx, self.lr[1])
- self.pic_location = (self.pic_location[0], self.pic_location[1]+diffy)
- self.width += diffx
- self.height -= diffy
- elif self.resizing == self.RESIZE_LL:
- if self.height + diffy < 10 or self.width - diffx < 10:
- self.motion_coords = tmp
- return True
- self.ul = (self.ul[0]+diffx, self.ul[1])
- self.lr = (self.lr[0], self.lr[1]+diffy)
- self.pic_location = (self.pic_location[0]+diffx, self.pic_location[1])
- self.width -= diffx
- self.height += diffy
- elif self.resizing == self.RESIZE_LR:
- if self.height + diffy < 10:
- self.motion_coords = tmp
- return True
- if self.width + diffx < 10:
- self.motion_coords = tmp
- return True
- self.lr = (self.lr[0]+diffx, self.lr[1]+diffy)
- self.width += diffx
- self.height += diffy
- if self.orig_pic:
- self.pic = self.orig_pic.scale_simple (int(self.width),
int(self.height), gtk.gdk.INTERP_NEAREST)
- self.emit ("update_links")
- self.emit ("update_view")
- return True
-
- def update_save (self):
- text = self.extended_buffer.get_text ()
- if text:
- self.extended_buffer.update_save()
- else:
- try:
- self.element.removeChild(self.extended_buffer.element)
- except xml.dom.NotFoundErr:
- pass
- self.element.setAttribute ("ul-coords", str(self.ul))
- self.element.setAttribute ("lr-coords", str(self.lr))
- self.element.setAttribute ("identity", str(self.identity))
- self.element.setAttribute ("background-color",
self.background_color.to_string())
- self.element.setAttribute ("file", str(self.filename))
- self.element.setAttribute ("image_width", str(self.width))
- self.element.setAttribute ("image_height", str(self.height))
- if self.am_selected:
- self.element.setAttribute ("current_root", "true")
- else:
- try:
- self.element.removeAttribute ("current_root")
- except xml.dom.NotFoundErr:
- pass
- if self.am_primary:
- self.element.setAttribute ("primary_root", "true")
- else:
- try:
- self.element.removeAttribute ("primary_root")
- except xml.dom.NotFoundErr:
- pass
- return
-
- def load (self, node):
- tmp = node.getAttribute ("ul-coords")
- self.ul = utils.parse_coords (tmp)
- tmp = node.getAttribute ("lr-coords")
- self.lr = utils.parse_coords (tmp)
- self.filename = node.getAttribute ("file")
- self.identity = int (node.getAttribute ("identity"))
- try:
- tmp = node.getAttribute ("background-color")
- self.background_color = gtk.gdk.color_parse(tmp)
- except ValueError:
- pass
- self.width = float(node.getAttribute ("image_width"))
- self.height = float(node.getAttribute ("image_height"))
- self.am_selected = node.hasAttribute ("current_root")
- self.am_primary = node.hasAttribute ("primary_root")
-
- for n in node.childNodes:
- if n.nodeName == "Extended":
- self.extended_buffer.load(n)
- else:
- print "Unknown: "+n.nodeName
- margin = utils.margin_required (utils.STYLE_NORMAL)
- self.pic_location = (self.ul[0]+margin[0], self.ul[1]+margin[1])
- self.okay = self.open_image (self.filename)
- self.lr = (self.pic_location[0]+self.width+margin[2],
self.pic_location[1]+self.height+margin[3])
- if not self.okay:
- dialog = gtk.MessageDialog (None, gtk.DIALOG_MODAL |
gtk.DIALOG_DESTROY_WITH_PARENT,
- gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE,
- _("Error loading file"))
- dialog.format_secondary_text (_("%s could not be found. Associated
thought will be empty."%self.filename))
- dialog.run ()
- dialog.hide ()
- self.pic = None
- self.orig_pic = None
- else:
- self.pic = self.orig_pic.scale_simple (int(self.width),
int(self.height), gtk.gdk.INTERP_HYPER)
- return
-
- def change_image_cb(self, widget):
- self.open_image()
-
- def get_popup_menu_items(self):
- image = gtk.Image()
- image.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_MENU)
- item = gtk.ImageMenuItem(_('Change Image'))
- item.set_image(image)
- item.connect('activate', self.change_image_cb)
- return [item]
-
-
+ def __init__ (self, coords, pango_context, thought_number, save, undo,
loading, background_color):
+ super (ImageThought, self).__init__(save, "image_thought", undo,
background_color, None)
+
+ self.identity = thought_number
+ margin = utils.margin_required (utils.STYLE_NORMAL)
+ self.want_move = False
+ if coords:
+ self.ul = (coords[0]-margin[0], coords[1] - margin[1])
+ self.pic_location = coords
+ else:
+ self.ul = None
+ self.button_press = False
+
+ if not loading:
+ self.all_okay = self.open_image ()
+ else:
+ self.all_okay = True
+
+ def open_image (self, filename = None):
+ # Present a dialog for the user to choose an image here
+ if not filename:
+ fil = gtk.FileFilter ()
+ fil.set_name("Images")
+ fil.add_pixbuf_formats ()
+ dialog = gtk.FileChooserDialog (_("Choose image to insert"),
None, gtk.FILE_CHOOSER_ACTION_OPEN, \
+ (gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
+ dialog.add_filter (fil)
+ res = dialog.run ()
+ dialog.hide ()
+ if res != gtk.RESPONSE_OK:
+ return False
+ else:
+ fname = dialog.get_filename()
+ else:
+ fname = filename
+
+ try:
+ self.orig_pic = gtk.gdk.pixbuf_new_from_file (fname)
+ except:
+ try:
+ # lets see if file was imported and is already extracted
+ fname = utils.get_save_dir() + 'images/' +
utils.strip_path_from_file_name(filename)
+ self.orig_pic = gtk.gdk.pixbuf_new_from_file (fname)
+ except:
+ return False
+
+ self.filename = fname
+
+ if not filename:
+ self.width = self.orig_pic.get_width ()
+ self.height = self.orig_pic.get_height ()
+ margin = utils.margin_required (utils.STYLE_NORMAL)
+
+ self.lr = (self.pic_location[0]+self.width+margin[2],
self.pic_location[1]+self.height+margin[3])
+ self.pic = self.orig_pic
+ self.text = fname[fname.rfind('/')+1:fname.rfind('.')]
+ return True
+
+ def draw (self, context):
+ if len (self.extended_buffer.get_text()) == 0:
+ utils.draw_thought_outline (context, self.ul, self.lr,
self.background_color, self.am_selected, self.am_primary,
utils.STYLE_NORMAL)
+ else:
+ utils.draw_thought_outline (context, self.ul, self.lr,
self.background_color, self.am_selected, self.am_primary,
utils.STYLE_EXTENDED_CONTENT)
+
+ if self.pic:
+ context.set_source_pixbuf (self.pic, self.pic_location[0],
self.pic_location[1])
+ context.rectangle (self.pic_location[0], self.pic_location[1],
self.width, self.height)
+ context.fill ()
+ context.set_source_rgb (0,0,0)
+
+ def export (self, context, move_x, move_y):
+ utils.export_thought_outline (context, self.ul, self.lr,
self.background_color, self.am_selected, self.am_primary,
utils.STYLE_NORMAL,
+ (move_x,
move_y))
+ if self.pic:
+ if hasattr(context, "set_source_pixbuf"):
+ context.set_source_pixbuf (self.pic,
self.pic_location[0]+move_x, self.pic_location[1]+move_y)
+ elif hasattr(context, "set_source_surface"):
+ pixel_array = utils.pixbuf_to_cairo
(self.pic.get_pixels_array())
+ image_surface =
cairo.ImageSurface.create_for_data(pixel_array, cairo.FORMAT_ARGB32,
self.width, self.height, -1)
+ context.set_source_surface (image_surface,
self.pic_location[0]+move_x, self.pic_location[1]+move_y)
+ context.rectangle (self.pic_location[0]+move_x,
self.pic_location[1]+move_y, self.width, self.height)
+ context.fill ()
+ context.set_source_rgb (0,0,0)
+
+ def want_motion (self):
+ return self.want_move
+
+ def recalc_edges (self):
+ margin = utils.margin_required (utils.STYLE_NORMAL)
+ self.pic_location = (self.ul[0]+margin[0], self.ul[1]+margin[1])
+ self.lr = (self.pic_location[0]+self.width+margin[2],
self.pic_location[1]+self.height+margin[3])
+
+ def undo_resize (self, action, mode):
+ self.undo.block ()
+ if mode == UndoManager.UNDO:
+ choose = 0
+ else:
+ choose = 1
+ self.ul = action.args[choose][0]
+ self.width = action.args[choose][1]
+ self.height = action.args[choose][2]
+ self.pic = self.orig_pic.scale_simple (int(self.width),
int(self.height), gtk.gdk.INTERP_HYPER)
+ self.recalc_edges ()
+ self.emit ("update_links")
+ self.emit ("update_view")
+ self.undo.unblock ()
+
+ def process_button_down (self, event, mode, transformed):
+ modifiers = gtk.accelerator_get_default_mod_mask ()
+ self.button_down = True
+ if event.button == 1:
+ if event.type == gtk.gdk.BUTTON_PRESS:
+ self.emit ("select_thought", event.state & modifiers)
+ self.emit ("update_view")
+ if mode == MODE_EDITING and self.resizing != self.RESIZE_NONE:
+ self.orig_size = (self.ul, self.width, self.height)
+ self.want_move = True
+ return True
+ elif event.button == 3:
+ self.emit ("popup_requested", event, 1)
+ self.emit ("update_view")
+
+ def process_button_release (self, event, unending_link, mode,
transformed):
+ self.button_down = False
+ if unending_link:
+ unending_link.set_child (self)
+ self.emit ("claim_unending_link")
+ if self.orig_pic:
+ self.pic = self.orig_pic.scale_simple (int(self.width),
int(self.height), gtk.gdk.INTERP_HYPER)
+ self.emit ("update_view")
+ if self.want_move:
+ self.undo.add_undo (UndoManager.UndoAction (self, UNDO_RESIZE,
self.undo_resize, \
+
self.orig_size,
(self.ul, self.width, self.height)))
+ self.want_move = False
+
+ def handle_motion (self, event, mode, transformed):
+ if self.resizing == self.RESIZE_NONE or not self.want_move or not
event.state & gtk.gdk.BUTTON1_MASK:
+ if not event.state & gtk.gdk.BUTTON1_MASK:
+ return False
+ elif mode == MODE_EDITING:
+ self.emit ("create_link", \
+ (self.ul[0]-((self.ul[0]-self.lr[0]) / 2.),
self.ul[1]-((self.ul[1]-self.lr[1]) / 2.)))
+ return True
+ diffx = transformed[0] - self.motion_coords[0]
+ diffy = transformed[1] - self.motion_coords[1]
+ tmp = self.motion_coords
+ self.motion_coords = transformed
+ if self.resizing == self.RESIZE_LEFT:
+ if self.width - diffx < 10:
+ self.motion_coords = tmp
+ return True
+ self.ul = (self.ul[0]+diffx, self.ul[1])
+ self.pic_location = (self.pic_location[0]+diffx,
self.pic_location[1])
+ self.width -= diffx
+ elif self.resizing == self.RESIZE_RIGHT:
+ if self.width + diffx < 10:
+ self.motion_coords = tmp
+ return True
+ self.lr = (self.lr[0]+diffx, self.lr[1])
+ self.width += diffx
+ elif self.resizing == self.RESIZE_TOP:
+ if self.height - diffy < 10:
+ self.motion_coords = tmp
+ return True
+ self.ul = (self.ul[0], self.ul[1]+diffy)
+ self.pic_location = (self.pic_location[0],
self.pic_location[1]+diffy)
+ self.height -= diffy
+ elif self.resizing == self.RESIZE_BOTTOM:
+ if self.height + diffy < 10:
+ self.motion_coords = tmp
+ return True
+ self.lr = (self.lr[0], self.lr[1]+diffy)
+ self.height += diffy
+ elif self.resizing == self.RESIZE_UL:
+ if self.height - diffy < 10 or self.width - diffx < 10:
+ self.motion_coords = tmp
+ return True
+ self.ul = (self.ul[0]+diffx, self.ul[1]+diffy)
+ self.pic_location = (self.pic_location[0]+diffx,
self.pic_location[1]+diffy)
+ self.width -= diffx
+ self.height -= diffy
+ elif self.resizing == self.RESIZE_UR:
+ if self.height - diffy < 10 or self.width + diffx < 10:
+ self.motion_coords = tmp
+ return True
+ self.ul = (self.ul[0], self.ul[1]+diffy)
+ self.lr = (self.lr[0]+diffx, self.lr[1])
+ self.pic_location = (self.pic_location[0],
self.pic_location[1]+diffy)
+ self.width += diffx
+ self.height -= diffy
+ elif self.resizing == self.RESIZE_LL:
+ if self.height + diffy < 10 or self.width - diffx < 10:
+ self.motion_coords = tmp
+ return True
+ self.ul = (self.ul[0]+diffx, self.ul[1])
+ self.lr = (self.lr[0], self.lr[1]+diffy)
+ self.pic_location = (self.pic_location[0]+diffx,
self.pic_location[1])
+ self.width -= diffx
+ self.height += diffy
+ elif self.resizing == self.RESIZE_LR:
+ if self.height + diffy < 10:
+ self.motion_coords = tmp
+ return True
+ if self.width + diffx < 10:
+ self.motion_coords = tmp
+ return True
+ self.lr = (self.lr[0]+diffx, self.lr[1]+diffy)
+ self.width += diffx
+ self.height += diffy
+ if self.orig_pic:
+ self.pic = self.orig_pic.scale_simple (int(self.width),
int(self.height), gtk.gdk.INTERP_NEAREST)
+ self.emit ("update_links")
+ self.emit ("update_view")
+ return True
+
+ def update_save (self):
+ text = self.extended_buffer.get_text ()
+ if text:
+ self.extended_buffer.update_save()
+ else:
+ try:
+ self.element.removeChild(self.extended_buffer.element)
+ except xml.dom.NotFoundErr:
+ pass
+ self.element.setAttribute ("ul-coords", str(self.ul))
+ self.element.setAttribute ("lr-coords", str(self.lr))
+ self.element.setAttribute ("identity", str(self.identity))
+ self.element.setAttribute ("background-color",
self.background_color.to_string())
+ self.element.setAttribute ("file", str(self.filename))
+ self.element.setAttribute ("image_width", str(self.width))
+ self.element.setAttribute ("image_height", str(self.height))
+ if self.am_selected:
+ self.element.setAttribute ("current_root", "true")
+ else:
+ try:
+ self.element.removeAttribute ("current_root")
+ except xml.dom.NotFoundErr:
+ pass
+ if self.am_primary:
+ self.element.setAttribute ("primary_root", "true")
+ else:
+ try:
+ self.element.removeAttribute ("primary_root")
+ except xml.dom.NotFoundErr:
+ pass
+ return
+
+ def load (self, node):
+ tmp = node.getAttribute ("ul-coords")
+ self.ul = utils.parse_coords (tmp)
+ tmp = node.getAttribute ("lr-coords")
+ self.lr = utils.parse_coords (tmp)
+ self.filename = node.getAttribute ("file")
+ self.identity = int (node.getAttribute ("identity"))
+ try:
+ tmp = node.getAttribute ("background-color")
+ self.background_color = gtk.gdk.color_parse(tmp)
+ except ValueError:
+ pass
+ self.width = float(node.getAttribute ("image_width"))
+ self.height = float(node.getAttribute ("image_height"))
+ self.am_selected = node.hasAttribute ("current_root")
+ self.am_primary = node.hasAttribute ("primary_root")
+
+ for n in node.childNodes:
+ if n.nodeName == "Extended":
+ self.extended_buffer.load(n)
+ else:
+ print "Unknown: "+n.nodeName
+ margin = utils.margin_required (utils.STYLE_NORMAL)
+ self.pic_location = (self.ul[0]+margin[0], self.ul[1]+margin[1])
+ self.okay = self.open_image (self.filename)
+ self.lr = (self.pic_location[0]+self.width+margin[2],
self.pic_location[1]+self.height+margin[3])
+ if not self.okay:
+ dialog = gtk.MessageDialog (None, gtk.DIALOG_MODAL |
gtk.DIALOG_DESTROY_WITH_PARENT,
+
gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE,
+
_("Error loading file"))
+ dialog.format_secondary_text (_("%s could not be found.
Associated thought will be empty."%self.filename))
+ dialog.run ()
+ dialog.hide ()
+ self.pic = None
+ self.orig_pic = None
+ else:
+ self.pic = self.orig_pic.scale_simple (int(self.width),
int(self.height), gtk.gdk.INTERP_HYPER)
+ return
+
+ def change_image_cb(self, widget):
+ self.open_image()
+
+ def get_popup_menu_items(self):
+ image = gtk.Image()
+ image.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_MENU)
+ item = gtk.ImageMenuItem(_('Change Image'))
+ item.set_image(image)
+ item.connect('activate', self.change_image_cb)
+ return [item]
=======================================
--- /trunk/src/Links.py Tue May 13 09:21:52 2008
+++ /trunk/src/Links.py Sat Apr 23 07:28:34 2011
@@ -10,7 +10,7 @@
#
# Labyrinth 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
+# 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
@@ -29,251 +29,250 @@
_ = gettext.gettext
def norm(x, y):
- mod = math.sqrt(abs((x[0]**2 - y[0]**2) + (x[1]**2 - y[1]**2)))
- return [abs(x[0]-y[0]) / (mod), abs(x[1] - y[1]) / (mod)]
+ mod = math.sqrt(abs((x[0]**2 - y[0]**2) + (x[1]**2 - y[1]**2)))
+ return [abs(x[0]-y[0]) / (mod), abs(x[1] - y[1]) / (mod)]
class Link (gobject.GObject):
- __gsignals__ = dict (select_link = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT,)),
- update_view = (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- popup_requested = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT, gobject.TYPE_INT)))
- def __init__ (self, save, parent = None, child = None, start_coords =
None, end_coords = None, strength = 2):
- super (Link, self).__init__()
- self.parent = parent
- self.child = child
- self.end = end_coords
- self.start = start_coords
- self.strength = strength
- self.element = save.createElement ("link")
- self.selected = False
- self.color = utils.gtk_to_cairo_color(gtk.gdk.color_parse("black"))
-
- if not self.start and parent and parent.lr:
- self.start = (parent.ul[0]-((parent.ul[0]-parent.lr[0]) / 2.), \
- parent.ul[1]-((parent.ul[1]-parent.lr[1]) / 2.))
-
- if parent and child:
- self.find_ends ()
-
- def get_save_element (self):
- return self.element
-
- def includes (self, coords, mode):
- # TODO: Change this to make link selection work. Also needs
- # some fairly large changes in MMapArea
- if not self.start or not self.end or not coords:
- return False
-
- mag = (math.sqrt(((self.end[0] - self.start[0]) ** 2) + \
- ((self.end[1] - self.start[1]) ** 2)))
-
- U = (((coords[0] - self.start[0]) * (self.end[0] - self.start[0])) + \
- ((coords[1] - self.start[1]) * (self.end[1] - self.start[1]))) / \
- (mag**2)
-
- inter = [self.start[0] + U*(self.end[0] - self.start[0]),
- self.start[1] + U*(self.end[1] - self.start[1])]
- dist = math.sqrt(((coords[0] - inter[0]) ** 2) + \
- ((coords[1] - inter[1]) ** 2))
- if dist < (3+self.strength) and dist > -(3+self.strength):
- if self.start[0] < self.end[0] and coords[0] > self.start[0] and
coords[0] < self.end[0]:
- return True
- elif coords[0] < self.start[0] and coords[0] > self.end[0]:
- return True
-
- return False
-
- def connects (self, thought, thought2):
- return (self.parent == thought and self.child == thought2) or \
- (self.child == thought and self.parent == thought2)
-
- def set_end (self, coords):
- self.end = coords
-
- def set_strength (self, strength):
- self.strength = strength
-
- def change_strength (self, thought, thought2):
- if not self.connects (thought, thought2):
- return False
- if self.parent == thought:
- self.strength += 1
- else:
- self.strength -= 1
- return self.strength != 0
-
- def set_child (self, child):
- self.child = child
- self.find_ends ()
-
- def uses (self, thought):
- return self.parent == thought or self.child == thought
-
- def find_ends (self):
- (self.start, self.end) = self.parent.find_connection (self.child)
-
- def draw (self, context):
- if not self.start or not self.end:
- return
- cwidth = context.get_line_width ()
- context.set_line_width (self.strength)
- context.move_to (self.start[0], self.start[1])
-
- if utils.use_bezier_curves:
- dx = self.end[0] - self.start[0]
- x2 = self.start[0] + dx / 2.0
- x3 = self.end[0] - dx / 2.0
- context.curve_to(x2, self.start[1], x3, self.end[1], self.end[0],
self.end[1])
- else:
- context.line_to (self.end[0], self.end[1])
-
- if self.selected:
- color = utils.selected_colors["bg"]
- context.set_source_rgb (color[0], color[1], color[2])
- else:
- context.set_source_rgb (self.color[0], self.color[1], self.color[2])
- context.stroke ()
- context.set_line_width (cwidth)
- context.set_source_rgb (0.0, 0.0, 0.0)
-
- def export (self, context, move_x, move_y):
- rem = False
- if not self.start or not self.end:
- # Probably shouldn't do this, but its safe now
- self.start = (self.parent.ul[0]-((self.parent.ul[0]-self.parent.lr[0])
/ 2.), \
- self.parent.ul[1]-((self.parent.ul[1]-self.parent.lr[1]) / 2.))
- self.end = (self.child.ul[0]-((self.child.ul[0]-self.child.lr[0]) /
2.), \
- self.child.ul[1]-((self.child.ul[1]-self.child.lr[1]) / 2.))
- rem = True
- cwidth = context.get_line_width ()
- context.set_line_width (self.strength)
- context.move_to (self.start[0]+move_x, self.start[1]+move_y)
- context.line_to (self.end[0]+move_x, self.end[1]+move_y)
- context.stroke ()
- context.set_line_width (cwidth)
- if rem:
- self.start = self.end = None
-
- def set_parent_child (self, parent, child):
- self.parent = parent
- self.child = child
- if self.parent and self.child:
- self.find_ends ()
-
- def update_save (self):
- self.element.setAttribute ("start", str(self.start))
- self.element.setAttribute ("end", str(self.end))
- self.element.setAttribute ("strength", str(self.strength))
- self.element.setAttribute ("color", str(self.color))
- if self.child:
- self.element.setAttribute ("child", str(self.child.identity))
- else:
- self.element.setAttribute ("child", "None")
- if self.parent:
- self.element.setAttribute ("parent", str(self.parent.identity))
- else:
- self.element.setAttribute ("parent", "None")
-
- def load (self, node):
- self.parent_number = self.child_number = -1
- tmp = node.getAttribute ("end")
- if not tmp:
- print "No tmp found"
- return
- self.end = utils.parse_coords (tmp)
- tmp = node.getAttribute ("start")
- if not tmp:
- print "No start found"
- return
- self.start = utils.parse_coords (tmp)
- self.strength = int(node.getAttribute ("strength"))
- try:
- colors = node.getAttribute ("color").split()
- self.color = (float(colors[0].strip('(,)')),
float(colors[1].strip('(,)')), float(colors[2].strip('(,)')))
- except:
- pass
- if node.hasAttribute ("parent"):
- tmp = node.getAttribute ("parent")
- if tmp == "None":
- self.parent_number = -1
- else:
- self.parent_number = int (tmp)
- if node.hasAttribute ("child"):
- tmp = node.getAttribute ("child")
- if tmp == "None":
- self.child_number = -1
- else:
- self.child_number = int (tmp)
-
- def process_button_down (self, event, mode, transformed):
- modifiers = gtk.accelerator_get_default_mod_mask ()
- self.button_down = True
- if event.button == 1:
- if event.type == gtk.gdk.BUTTON_PRESS:
- self.emit ("select_link", event.state & modifiers)
- self.emit ("update_view")
- elif event.button == 3:
- self.emit ("popup_requested", event, 2)
- self.emit ("update_view")
- return False
-
- def process_button_release (self, event, unending_link, mode,
transformed):
- return False
-
- def process_key_press (self, event, mode):
- if mode != BaseThought.MODE_EDITING:
- return False
- if event.keyval == gtk.keysyms.plus or \
- event.keyval == gtk.keysyms.KP_Add:
- self.strength += 1
- elif (event.keyval == gtk.keysyms.minus or \
- event.keyval == gtk.keysyms.KP_Subtract) and \
- self.strength > 1:
- self.strength -= 1
- elif event.keyval == gtk.keysyms.Escape:
- self.unselect()
- self.emit("update_view")
- return True
-
- def handle_motion (self, event, mode, transformed):
- pass
-
- def want_motion (self):
- return False
-
- def select(self):
- self.selected = True
-
- def unselect(self):
- self.selected = False
-
- def move_by (self, x,y):
- pass
-
- def can_be_parent (self):
- return False
-
- def set_color_cb(self, widget):
- dialog = gtk.ColorSelectionDialog(_('Choose Color'))
- dialog.connect('response', self.color_selection_ok_cb)
- self.color_sel = dialog.colorsel
- dialog.run()
-
- def color_selection_ok_cb(self, dialog, response_id):
- if response_id == gtk.RESPONSE_OK:
- self.color =
utils.gtk_to_cairo_color(self.color_sel.get_current_color())
- dialog.destroy()
-
- def get_popup_menu_items(self):
- image = gtk.Image()
- image.set_from_stock(gtk.STOCK_COLOR_PICKER, gtk.ICON_SIZE_MENU)
- item = gtk.ImageMenuItem(_('Set Color'))
- item.set_image(image)
- item.connect('activate', self.set_color_cb)
- return [item]
-
+ __gsignals__ = dict (select_link = (gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_PYOBJECT,)),
+ update_view =
(gobject.SIGNAL_RUN_LAST,
+
gobject.TYPE_NONE,
+
()),
+ popup_requested =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_PYOBJECT,
gobject.TYPE_INT)))
+ def __init__ (self, save, parent = None, child = None, start_coords =
None, end_coords = None, strength = 2):
+ super (Link, self).__init__()
+ self.parent = parent
+ self.child = child
+ self.end = end_coords
+ self.start = start_coords
+ self.strength = strength
+ self.element = save.createElement ("link")
+ self.selected = False
+ self.color = utils.gtk_to_cairo_color(gtk.gdk.color_parse("black"))
+
+ if not self.start and parent and parent.lr:
+ self.start = (parent.ul[0]-((parent.ul[0]-parent.lr[0]) / 2.),
\
+
parent.ul[1]-((parent.ul[1]-parent.lr[1]) / 2.))
+
+ if parent and child:
+ self.find_ends ()
+
+ def get_save_element (self):
+ return self.element
+
+ def includes (self, coords, mode):
+ # TODO: Change this to make link selection work. Also needs
+ # some fairly large changes in MMapArea
+ if not self.start or not self.end or not coords:
+ return False
+
+ mag = (math.sqrt(((self.end[0] - self.start[0]) ** 2) + \
+ ((self.end[1] - self.start[1]) ** 2)))
+
+ U = (((coords[0] - self.start[0]) * (self.end[0] - self.start[0]))
+ \
+ ((coords[1] - self.start[1]) * (self.end[1] - self.start[1]))) / \
+ (mag**2)
+
+ inter = [self.start[0] + U*(self.end[0] - self.start[0]),
+ self.start[1] + U*(self.end[1] - self.start[1])]
+ dist = math.sqrt(((coords[0] - inter[0]) ** 2) + \
+ ((coords[1] - inter[1]) ** 2))
+ if dist < (3+self.strength) and dist > -(3+self.strength):
+ if self.start[0] < self.end[0] and coords[0] > self.start[0]
and coords[0] < self.end[0]:
+ return True
+ elif coords[0] < self.start[0] and coords[0] > self.end[0]:
+ return True
+
+ return False
+
+ def connects (self, thought, thought2):
+ return (self.parent == thought and self.child == thought2) or \
+ (self.child == thought and self.parent == thought2)
+
+ def set_end (self, coords):
+ self.end = coords
+
+ def set_strength (self, strength):
+ self.strength = strength
+
+ def change_strength (self, thought, thought2):
+ if not self.connects (thought, thought2):
+ return False
+ if self.parent == thought:
+ self.strength += 1
+ else:
+ self.strength -= 1
+ return self.strength != 0
+
+ def set_child (self, child):
+ self.child = child
+ self.find_ends ()
+
+ def uses (self, thought):
+ return self.parent == thought or self.child == thought
+
+ def find_ends (self):
+ (self.start, self.end) = self.parent.find_connection (self.child)
+
+ def draw (self, context):
+ if not self.start or not self.end:
+ return
+ cwidth = context.get_line_width ()
+ context.set_line_width (self.strength)
+ context.move_to (self.start[0], self.start[1])
+
+ if utils.use_bezier_curves:
+ dx = self.end[0] - self.start[0]
+ x2 = self.start[0] + dx / 2.0
+ x3 = self.end[0] - dx / 2.0
+ context.curve_to(x2, self.start[1], x3, self.end[1],
self.end[0], self.end[1])
+ else:
+ context.line_to (self.end[0], self.end[1])
+
+ if self.selected:
+ color = utils.selected_colors["bg"]
+ context.set_source_rgb (color[0], color[1], color[2])
+ else:
+ context.set_source_rgb (self.color[0], self.color[1],
self.color[2])
+ context.stroke ()
+ context.set_line_width (cwidth)
+ context.set_source_rgb (0.0, 0.0, 0.0)
+
+ def export (self, context, move_x, move_y):
+ rem = False
+ if not self.start or not self.end:
+ # Probably shouldn't do this, but its safe now
+ self.start =
(self.parent.ul[0]-((self.parent.ul[0]-self.parent.lr[0]) / 2.), \
+
self.parent.ul[1]-((self.parent.ul[1]-self.parent.lr[1]) / 2.))
+ self.end =
(self.child.ul[0]-((self.child.ul[0]-self.child.lr[0]) / 2.), \
+
self.child.ul[1]-((self.child.ul[1]-self.child.lr[1]) / 2.))
+ rem = True
+ cwidth = context.get_line_width ()
+ context.set_line_width (self.strength)
+ context.move_to (self.start[0]+move_x, self.start[1]+move_y)
+ context.line_to (self.end[0]+move_x, self.end[1]+move_y)
+ context.stroke ()
+ context.set_line_width (cwidth)
+ if rem:
+ self.start = self.end = None
+
+ def set_parent_child (self, parent, child):
+ self.parent = parent
+ self.child = child
+ if self.parent and self.child:
+ self.find_ends ()
+
+ def update_save (self):
+ self.element.setAttribute ("start", str(self.start))
+ self.element.setAttribute ("end", str(self.end))
+ self.element.setAttribute ("strength", str(self.strength))
+ self.element.setAttribute ("color", str(self.color))
+ if self.child:
+ self.element.setAttribute ("child", str(self.child.identity))
+ else:
+ self.element.setAttribute ("child", "None")
+ if self.parent:
+ self.element.setAttribute ("parent", str(self.parent.identity))
+ else:
+ self.element.setAttribute ("parent", "None")
+
+ def load (self, node):
+ self.parent_number = self.child_number = -1
+ tmp = node.getAttribute ("end")
+ if not tmp:
+ print "No tmp found"
+ return
+ self.end = utils.parse_coords (tmp)
+ tmp = node.getAttribute ("start")
+ if not tmp:
+ print "No start found"
+ return
+ self.start = utils.parse_coords (tmp)
+ self.strength = int(node.getAttribute ("strength"))
+ try:
+ colors = node.getAttribute ("color").split()
+ self.color = (float(colors[0].strip('(,)')),
float(colors[1].strip('(,)')), float(colors[2].strip('(,)')))
+ except:
+ pass
+ if node.hasAttribute ("parent"):
+ tmp = node.getAttribute ("parent")
+ if tmp == "None":
+ self.parent_number = -1
+ else:
+ self.parent_number = int (tmp)
+ if node.hasAttribute ("child"):
+ tmp = node.getAttribute ("child")
+ if tmp == "None":
+ self.child_number = -1
+ else:
+ self.child_number = int (tmp)
+
+ def process_button_down (self, event, mode, transformed):
+ modifiers = gtk.accelerator_get_default_mod_mask ()
+ self.button_down = True
+ if event.button == 1:
+ if event.type == gtk.gdk.BUTTON_PRESS:
+ self.emit ("select_link", event.state & modifiers)
+ self.emit ("update_view")
+ elif event.button == 3:
+ self.emit ("popup_requested", event, 2)
+ self.emit ("update_view")
+ return False
+
+ def process_button_release (self, event, unending_link, mode,
transformed):
+ return False
+
+ def process_key_press (self, event, mode):
+ if mode != BaseThought.MODE_EDITING:
+ return False
+ if event.keyval == gtk.keysyms.plus or \
+ event.keyval == gtk.keysyms.KP_Add:
+ self.strength += 1
+ elif (event.keyval == gtk.keysyms.minus or \
+ event.keyval == gtk.keysyms.KP_Subtract) and \
+ self.strength > 1:
+ self.strength -= 1
+ elif event.keyval == gtk.keysyms.Escape:
+ self.unselect()
+ self.emit("update_view")
+ return True
+
+ def handle_motion (self, event, mode, transformed):
+ pass
+
+ def want_motion (self):
+ return False
+
+ def select(self):
+ self.selected = True
+
+ def unselect(self):
+ self.selected = False
+
+ def move_by (self, x,y):
+ pass
+
+ def can_be_parent (self):
+ return False
+
+ def set_color_cb(self, widget):
+ dialog = gtk.ColorSelectionDialog(_('Choose Color'))
+ dialog.connect('response', self.color_selection_ok_cb)
+ self.color_sel = dialog.colorsel
+ dialog.run()
+
+ def color_selection_ok_cb(self, dialog, response_id):
+ if response_id == gtk.RESPONSE_OK:
+ self.color =
utils.gtk_to_cairo_color(self.color_sel.get_current_color())
+ dialog.destroy()
+
+ def get_popup_menu_items(self):
+ image = gtk.Image()
+ image.set_from_stock(gtk.STOCK_COLOR_PICKER, gtk.ICON_SIZE_MENU)
+ item = gtk.ImageMenuItem(_('Set Color'))
+ item.set_image(image)
+ item.connect('activate', self.set_color_cb)
+ return [item]
=======================================
--- /trunk/src/MMapArea.py Sat Feb 28 12:19:26 2009
+++ /trunk/src/MMapArea.py Sat Apr 23 07:28:34 2011
@@ -11,7 +11,7 @@
#
# Labyrinth 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
+# 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
@@ -82,1318 +82,1317 @@
# OR: Change this class to MMapAreaNew and MMapAreaOld to MMapArea
class MMapArea (gtk.DrawingArea):
- '''A MindMapArea Widget. A blank canvas with a collection of child
thoughts.\
- It is responsible for processing signals and such from the whole area
and \
- passing these on to the correct child. It also informs things when to
draw'''
-
- __gsignals__ = dict (title_changed = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING, )),
- doc_save = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)),
- doc_delete = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ()),
- change_mode = (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_INT, )),
- change_buffer = (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_OBJECT, )),
- text_selection_changed = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_STRING)),
- thought_selection_changed = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)),
- set_focus = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN)),
- set_attrs = (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN,
gobject.TYPE_BOOLEAN, pango.FontDescription)))
-
- def __init__(self, undo):
- super (MMapArea, self).__init__()
-
- self.thoughts = []
- self.links = []
- self.selected = []
- self.num_selected = 0
- self.primary = None
- self.editing = None
- self.pango_context = self.create_pango_context()
- self.undo = undo
- self.scale_fac = 1.0
- self.translate = False
- self.translation = [0.0,0.0]
- self.timeout = -1
- self.current_cursor = None
- self.do_filter = True
- self.is_bbox_selecting = False
-
- self.unending_link = None
- self.nthoughts = 0
-
- impl = dom.getDOMImplementation()
- self.save =
impl.createDocument("http://www.donscorgie.blueyonder.co.uk/labns", "MMap",
None)
- self.element = self.save.documentElement
- self.im_context = gtk.IMMulticontext ()
-
- self.mode = MODE_EDITING
- self.old_mode = MODE_EDITING
-
- self.connect ("expose_event", self.expose)
- self.connect ("button_release_event", self.button_release)
- self.connect ("button_press_event", self.button_down)
- self.connect ("motion_notify_event", self.motion)
- self.connect ("key_press_event", self.key_press)
- self.connect ("key_release_event", self.key_release)
- self.connect ("scroll_event", self.scroll)
- self.commit_handler = None
- self.title_change_handler = None
- self.moving = False
- self.move_origin = None
- self.move_origin_new = None
- self.motion = None
- self.move_action = None
- self.current_root = []
- self.rotation = 0
-
- self.set_events (gtk.gdk.KEY_PRESS_MASK |
- gtk.gdk.KEY_RELEASE_MASK |
- gtk.gdk.BUTTON_PRESS_MASK |
- gtk.gdk.BUTTON_RELEASE_MASK |
- gtk.gdk.POINTER_MOTION_MASK |
- gtk.gdk.SCROLL_MASK
- )
-
- self.set_flags (gtk.CAN_FOCUS)
-
- # set theme colors
- w = gtk.Window()
- w.realize()
- style = w.get_style()
- self.pango_context.set_font_description(style.font_desc)
- self.font_name = style.font_desc.to_string()
- utils.default_font = self.font_name
-
- utils.default_colors["text"] =
utils.gtk_to_cairo_color(style.text[gtk.STATE_NORMAL])
- utils.default_colors["base"] =
utils.gtk_to_cairo_color(style.base[gtk.STATE_NORMAL])
- self.background_color = style.base[gtk.STATE_NORMAL]
- self.foreground_color = style.text[gtk.STATE_NORMAL]
- utils.default_colors["bg"] =
utils.gtk_to_cairo_color(style.bg[gtk.STATE_NORMAL])
- utils.default_colors["fg"] =
utils.gtk_to_cairo_color(style.fg[gtk.STATE_NORMAL])
-
- utils.selected_colors["text"] =
utils.gtk_to_cairo_color(style.text[gtk.STATE_SELECTED])
- utils.selected_colors["bg"] =
utils.gtk_to_cairo_color(style.bg[gtk.STATE_SELECTED])
- utils.selected_colors["fg"] =
utils.gtk_to_cairo_color(style.fg[gtk.STATE_SELECTED])
- utils.selected_colors["fill"] =
utils.gtk_to_cairo_color(style.base[gtk.STATE_SELECTED])
-
- def transform_coords(self, loc_x, loc_y):
- if hasattr(self, "transform"):
- return self.transform.transform_point(loc_x, loc_y)
-
- def untransform_coords(self, loc_x, loc_y):
- if hasattr(self, "untransform"):
- return self.untransform.transform_point(loc_x, loc_y)
-
- def button_down (self, widget, event):
- coords = self.transform_coords (event.get_coords()[0],
event.get_coords()[1])
-
- ret = False
- obj = self.find_object_at (coords)
- if event.button == 2:
- self.set_cursor (gtk.gdk.FLEUR)
- self.original_translation = self.translation
- self.origin_x = event.x
- self.origin_y = event.y
- return
- if obj and obj.want_motion ():
- self.motion = obj
- ret = obj.process_button_down (event, self.mode, coords)
- if event.button == 1 and self.mode == MODE_EDITING:
- self.moving = not (event.state & gtk.gdk.CONTROL_MASK)
- self.move_origin = (coords[0], coords[1])
- self.move_origin_new = self.move_origin
- return ret
- if obj:
- if event.button == 1 and self.mode == MODE_EDITING:
- self.moving = not (event.state & gtk.gdk.CONTROL_MASK)
- self.move_origin = (coords[0], coords[1])
- self.move_origin_new = self.move_origin
- ret = obj.process_button_down (event, self.mode, coords)
- elif event.button == 1 and self.mode == MODE_EDITING and not
self.editing:
- self.bbox_origin = coords
- self.is_bbox_selecting = True
- elif event.button == 3:
- ret = self.create_popup_menu (None, event, MENU_EMPTY_SPACE)
-
- if self.editing:
- self.finish_editing()
- return ret
-
- def undo_move (self, action, mode):
- self.undo.block ()
- move_thoughts = action.args[1]
- old_coords = action.args[0]
- new_coords = action.args[2]
- move_x = old_coords[0] - new_coords[0]
- move_y = old_coords[1] - new_coords[1]
- if mode == UndoManager.REDO:
- move_x = -move_x
- move_y = -move_y
- self.unselect_all ()
- for t in move_thoughts:
- self.select_thought (t, -1)
- t.move_by (move_x, move_y)
- self.undo.unblock ()
- self.invalidate ((old_coords[0], old_coords[1], new_coords[0],
new_coords[1]))
-
- def button_release (self, widget, event):
- coords = self.transform_coords (event.get_coords()[0],
event.get_coords()[1])
-
- if self.mode == MODE_EDITING:
- self.set_cursor(gtk.gdk.LEFT_PTR)
- else:
- self.set_cursor(gtk.gdk.CROSSHAIR)
-
- ret = False
- if self.is_bbox_selecting:
- self.is_bbox_selecting = False
- self.invalidate ()
- try:
- if abs(self.bbox_origin[0] - coords[0]) > 2.0:
- return True
- except AttributeError: # no bbox_current
- pass
-
- if self.translate:
- self.translate = False
- return True
- if self.moving and self.move_action:
- self.move_action.add_arg (coords)
- self.undo.add_undo (self.move_action)
- self.move_action = None
-
- self.motion = None
- self.moving = False
- self.move_origin = None
-
- obj = self.find_object_at (coords)
- if event.button == 2:
- self.undo.add_undo (UndoManager.UndoAction (self,
UndoManager.TRANSFORM_CANVAS, \
- self.undo_transform_cb,
- self.scale_fac, self.scale_fac,
- self.original_translation,
- self.translation))
-
- if obj:
- ret = obj.process_button_release (event, self.unending_link, self.mode,
coords)
- if len(self.selected) != 1:
- self.invalidate() # does not invalidate correctly with
obj.get_max_area()
- return ret
- elif self.unending_link or event.button == 1:
- sel = self.selected
- thought = self.create_new_thought (coords)
- if not thought:
- return True
- if not self.primary:
- self.make_primary (thought)
- self.select_thought (thought, None)
- else:
- self.emit ("change_buffer", thought.extended_buffer)
- self.hookup_im_context (thought)
- # Creating links adds an undo action. Block it here
- self.undo.block ()
- for x in self.current_root:
- self.create_link (x, None, thought)
- for x in self.selected:
- x.unselect ()
- self.selected = [thought]
- thought.select ()
- if self.unending_link:
- self.unending_link.set_child (thought)
- self.links.append (self.unending_link)
- element = self.unending_link.get_save_element ()
- self.element.appendChild (element)
- self.unending_link = None
- self.undo.unblock ()
- thought.foreground_color = self.foreground_color
- thought.background_color = self.background_color
- act = UndoManager.UndoAction (self, UNDO_CREATE, self.undo_create_cb,
thought, sel, \
- self.mode, self.old_mode, event.get_coords())
- for l in self.links:
- if l.uses (thought):
- act.add_arg (l)
- if self.undo.peak ().undo_type == UNDO_DELETE_SINGLE:
- last_action = self.undo.pop ()
- action = UndoManager.UndoAction (self, UNDO_COMBINE_DELETE_NEW,
self.undo_joint_cb, \
- last_action, act)
- self.undo.add_undo (action)
- else:
- self.undo.add_undo (act)
- self.begin_editing (thought)
-
- self.invalidate ()
- return ret
-
- def undo_transform_cb (self, action, mode):
- if mode == UndoManager.UNDO:
- self.scale_fac = action.args[0]
- self.translation = action.args[2]
- else:
- self.scale_fac = action.args[1]
- self.translation = action.args[3]
- self.invalidate ()
-
- def scroll (self, widget, event):
- scale = self.scale_fac
- if event.direction == gtk.gdk.SCROLL_UP:
- self.scale_fac*=1.2
-
- # The following code is used to zoom where the cursor is currently
- # located. It feels quite awkward but is requested by issue 100.
- coords = self.transform_coords(event.x, event.y)
- geom = self.window.get_geometry()
- middle = self.transform_coords(geom[2]/2.0, geom[3]/2.0)
-
- self.translation[0] -= coords[0] - middle[0]
- self.translation[1] -= coords[1] - middle[1]
- elif event.direction == gtk.gdk.SCROLL_DOWN:
- self.scale_fac/=1.2
- self.undo.add_undo (UndoManager.UndoAction (self,
UndoManager.TRANSFORM_CANVAS, \
- self.undo_transform_cb,
- scale, self.scale_fac, self.translation,
- self.translation))
- self.invalidate()
-
- def undo_joint_cb (self, action, mode):
- delete = action.args[0]
- create = action.args[1]
-
- if mode == UndoManager.UNDO:
- self.undo_create_cb (create, mode)
- self.undo_deletion (delete, mode)
- else:
- self.undo_deletion (delete, mode)
- self.undo_create_cb (create, mode)
- self.invalidate ()
-
- def key_press (self, widget, event):
- if not self.do_filter or not self.im_context.filter_keypress (event):
- if self.editing:
- if not self.editing.process_key_press (event, self.mode):
- return self.global_key_handler (event)
- return True
- if len(self.selected) != 1 or not self.selected[0].process_key_press
(event, self.mode):
- return self.global_key_handler (event)
- return True
-
- def key_release (self, widget, event):
- self.im_context.filter_keypress (event)
- return True
-
- def motion (self, widget, event):
- coords = self.transform_coords (event.get_coords()[0],
event.get_coords()[1])
-
- if self.motion:
- if self.motion.handle_motion (event, self.mode, coords):
- return True
- obj = self.find_object_at (coords)
- if self.unending_link and not self.is_bbox_selecting:
- self.unending_link.set_end (coords)
- self.invalidate ()
- return True
- elif event.state & gtk.gdk.BUTTON1_MASK and self.is_bbox_selecting:
- self.bbox_current = coords
- self.invalidate()
-
- ul = [ self.bbox_origin[0], self.bbox_origin[1] ]
- lr = [ coords[0], coords[1] ]
- if self.bbox_origin[0] > coords[0]:
- if self.bbox_origin[1] < coords[1]:
- ul[0] = coords[0]
- ul[1] = self.bbox_origin[1]
- lr[0] = self.bbox_origin[0]
- lr[1] = coords[1]
- else:
- ul = coords
- lr = self.bbox_origin
- elif self.bbox_origin[1] > coords[1]:
- ul[0] = self.bbox_origin[0]
- ul[1] = coords[1]
- lr[0] = coords[0]
- lr[1] = self.bbox_origin[1]
-
- # FIXME: O(n) runtime is bad
- for t in self.thoughts:
- if t.lr[0] > ul[0] and t.ul[1] < lr[1] and t.ul[0] < lr[0] and t.lr[1]
> ul[1] :
- if t not in self.selected:
- self.select_thought(t, gtk.gdk.SHIFT_MASK)
- else:
- if t in self.selected:
- t.unselect()
- self.selected.remove(t)
-
- return True
- elif self.moving and not self.editing and not self.unending_link:
- self.set_cursor(gtk.gdk.FLEUR)
- if not self.move_action:
- self.move_action = UndoManager.UndoAction (self, UNDO_MOVE,
self.undo_move, self.move_origin,
- self.selected)
- for t in self.selected:
- t.move_by (coords[0] - self.move_origin_new[0], coords[1] -
self.move_origin_new[1])
- self.move_origin_new = (coords[0], coords[1])
- self.invalidate ()
- return True
- elif self.editing and event.state & gtk.gdk.BUTTON1_MASK and not obj and
not self.is_bbox_selecting:
- # We were too quick with the movement. We really actually want to
- # create the unending link
- self.create_link (self.editing)
- self.finish_editing ()
- elif event.state & gtk.gdk.BUTTON2_MASK:
- self.translate = True
- self.translation[0] -= (self.origin_x - event.x) / self.scale_fac
- self.translation[1] -= (self.origin_y - event.y) / self.scale_fac
- self.origin_x = event.x
- self.origin_y = event.y
- self.invalidate()
- return True
-
- if obj:
- obj.handle_motion (event, self.mode, coords)
- elif self.mode == MODE_IMAGE or self.mode == MODE_DRAW:
- self.set_cursor(gtk.gdk.CROSSHAIR)
- else:
- self.set_cursor(gtk.gdk.LEFT_PTR)
-
- def find_object_at (self, coords):
- for x in reversed(self.thoughts):
- if x.includes (coords, self.mode):
- return x
- for x in self.links:
- if x.includes (coords, self.mode):
- return x
- return None
-
- def realize_cb (self, widget):
- self.disconnect (self.realize_handle)
- if self.mode == MODE_IMAGE or self.mode == MODE_DRAW:
- self.set_cursor (gtk.gdk.CROSSHAIR)
- else:
- self.set_cursor (gtk.gdk.LEFT_PTR)
- return False
-
- def set_cursor(self, kind):
- new_cursor = CursorFactory().get_cursor(kind)
- if self.current_cursor != new_cursor:
- self.current_cursor = new_cursor
- self.window.set_cursor(self.current_cursor)
-
- def set_mode (self, mode):
- if mode == self.mode:
- return
- self.old_mode = self.mode
- self.mode = mode
- self.finish_editing ()
- self.hookup_im_context ()
-
- if self.window:
- if mode == MODE_IMAGE or mode == MODE_DRAW:
- self.set_cursor (gtk.gdk.CROSSHAIR)
- else:
- self.set_cursor (gtk.gdk.LEFT_PTR)
- else:
- self.realize_handle = self.connect ("realize", self.realize_cb)
- self.mode = mode
- if self.window:
- self.invalidate ()
-
- def title_changed_cb (self, widget, new_title):
- self.emit ("title_changed", new_title)
-
- def make_primary (self, thought):
- if self.primary:
- print "Warning: Already have a primary root"
- if self.title_change_handler:
- self.primary.disconnect (self.title_change_handler)
- self.title_change_handler = thought.connect ("title_changed",
self.title_changed_cb)
- self.emit ("title_changed", thought.text)
- self.primary = thought
- thought.make_primary ()
-
- def hookup_im_context (self, thought = None):
- if self.commit_handler:
- self.im_context.disconnect (self.commit_handler)
- self.im_context.disconnect (self.delete_handler)
- self.im_context.disconnect (self.preedit_changed_handler)
- self.im_context.disconnect (self.preedit_end_handler)
- self.im_context.disconnect (self.preedit_start_handler)
- self.im_context.disconnect (self.retrieve_handler)
- self.commit_handler = None
- if thought:
- try:
- self.commit_handler = self.im_context.connect ("commit",
thought.commit_text, self.mode, self.font_name)
- self.delete_handler = self.im_context.connect ("delete-surrounding",
thought.delete_surroundings, self.mode)
- self.preedit_changed_handler = self.im_context.connect
("preedit-changed", thought.preedit_changed, self.mode)
- self.preedit_end_handler = self.im_context.connect ("preedit-end",
thought.preedit_end, self.mode)
- self.preedit_start_handler = self.im_context.connect ("preedit-start",
thought.preedit_start, self.mode)
- self.retrieve_handler = self.im_context.connect
("retrieve-surrounding", thought.retrieve_surroundings, \
- self.mode)
- self.do_filter = True
- except AttributeError:
- self.do_filter = False
- else:
- self.do_filter = False
-
- def unselect_all (self):
- self.hookup_im_context ()
- for t in self.selected:
- t.unselect ()
- self.selected = []
-
- def select_link (self, link, modifiers):
- if modifiers and modifiers & gtk.gdk.SHIFT_MASK and len (self.selected)
> 1 and self.selected.count (link) > 0:
- self.selected.remove (link)
- link.unselect ()
- return
-
- self.hookup_im_context()
- if self.editing:
- self.finish_editing ()
- if modifiers and (modifiers & gtk.gdk.SHIFT_MASK or modifiers == -1):
- if self.selected.count (link) == 0:
- self.selected.append (link)
- else:
- map (lambda t : t.unselect(), self.selected)
- self.selected = [link]
- link.select()
- self.emit("change_buffer", None)
-
- def select_thought (self, thought, modifiers):
- self.hookup_im_context ()
- if self.editing:
- self.finish_editing ()
-
- if thought in self.selected and self.moving:
- return
-
- if thought not in self.thoughts:
- self.thoughts.append(thought)
-
- if modifiers and (modifiers & gtk.gdk.SHIFT_MASK or modifiers == -1):
- if self.selected.count (thought) == 0:
- self.selected.append (thought)
- else:
- map(lambda x : x.unselect(), self.selected)
- self.selected = [thought]
- self.current_root = []
- for x in self.selected:
- if x.can_be_parent():
- self.current_root.append(x)
- thought.select ()
- if len(self.selected) == 1:
- self.emit ("thought_selection_changed", thought.background_color,
thought.foreground_color)
- self.background_color = thought.background_color
- self.foreground_color = thought.foreground_color
- try:
- self.emit ("change_buffer", thought.extended_buffer)
- except AttributeError:
- self.emit ("change_buffer", None)
- self.hookup_im_context (thought)
- else:
- self.emit ("change_buffer", None)
-
- def begin_editing (self, thought):
- if self.editing and thought != self.editing:
- self.finish_editing ()
- if thought.begin_editing ():
- self.editing = thought
-
- def undo_link_action (self, action, mode):
- self.undo.block ()
- if self.editing:
- self.finish_editing ()
- link = action.args[0]
- if action.undo_type == UNDO_CREATE_LINK:
- if mode == UndoManager.REDO:
- self.element.appendChild (link.element)
- self.links.append (link)
- else:
- self.delete_link (link)
- elif action.undo_type == UNDO_DELETE_LINK:
- if mode == UndoManager.UNDO:
- self.element.appendChild (link.element)
- self.links.append (link)
- else:
- self.delete_link (link)
- elif action.undo_type == UNDO_STRENGTHEN_LINK:
- if mode == UndoManager.UNDO:
- link.set_strength (action.args[1])
- else:
- link.set_strength (action.args[2])
-
- self.undo.unblock ()
- self.invalidate ()
-
- def connect_link (self, link):
- link.connect ("select_link", self.select_link)
- link.connect ("update_view", self.update_view)
- link.connect ("popup_requested", self.create_popup_menu)
-
- def create_link (self, thought, thought_coords = None, child = None,
child_coords = None, strength = 2):
- if child:
- self.add_thought_to_model(child)
- for x in self.links:
- if x.connects (thought, child):
- if x.change_strength (thought, child):
- self.delete_link (x)
- return
- link = Links.Link (self.save, parent = thought, child = child, strength
= strength)
- self.connect_link (link)
- element = link.get_save_element ()
- self.element.appendChild (element)
- self.links.append (link)
- return link
- else:
- if self.unending_link:
- del self.unending_link
- self.unending_link = Links.Link (self.save, parent = thought,
start_coords = thought_coords,
- end_coords = child_coords, strength = strength)
-
- def set_mouse_cursor_cb (self, thought, cursor_type):
- if not self.moving:
- self.set_cursor (cursor_type)
-
- def update_all_links(self):
- map(lambda l : l.find_ends(), self.links)
-
- def update_links_cb (self, thought):
- for x in self.links:
- if x.uses (thought):
- x.find_ends ()
-
- def claim_unending_link (self, thought):
- if not self.unending_link:
- return
- if self.unending_link.parent == thought:
- del self.unending_link
- self.unending_link = None
- return
- for x in self.links:
- if x.connects (self.unending_link.parent, thought):
- old_strength = x.strength
- x.change_strength (self.unending_link.parent, thought)
- new_strength = x.strength
- self.undo.add_undo (UndoManager.UndoAction (self,
UNDO_STRENGTHEN_LINK, self.undo_link_action, x, \
- old_strength, new_strength))
- del self.unending_link
- self.unending_link = None
- return
-
- self.undo.add_undo (UndoManager.UndoAction (self, UNDO_CREATE_LINK,
self.undo_link_action, self.unending_link))
- self.unending_link.set_child (thought)
- self.links.append (self.unending_link)
- element = self.unending_link.get_save_element ()
- self.element.appendChild (element)
- self.unending_link = None
-
- def create_popup_menu (self, thought, event, menu_type):
- menu = gtk.Menu()
- undo_item = gtk.ImageMenuItem(gtk.STOCK_UNDO)
- undo_item.connect('activate', self.undo.undo_action)
- undo_item.set_sensitive(self.undo.exists_undo_action())
- redo_item = gtk.ImageMenuItem(gtk.STOCK_REDO)
- redo_item.connect('activate', self.undo.redo_action)
- redo_item.set_sensitive(self.undo.exists_redo_action())
- sep_item = gtk.SeparatorMenuItem()
- menu.append(undo_item)
- menu.append(redo_item)
- menu.append(sep_item)
- undo_item.show()
- redo_item.show()
- sep_item.show()
-
- if thought:
- for item in thought.get_popup_menu_items():
- menu.append(item)
- item.show()
-
- menu.popup(None, None, None, event.button, event.get_time())
-
- def finish_editing (self, thought = None):
- if not self.editing or (thought and thought != self.editing):
- return
-
- self.editing.finish_editing ()
- thought = self.editing
- self.editing = None
-
- if not thought:
- return
- if thought.model_iter:
- self.tree_model.set_value (thought.model_iter, 0, thought.text)
- else:
- self.add_thought_to_model (thought)
-
- def update_view (self, thought):
- if not self.editing:
- self.invalidate ()
- else:
- x,y,w,h = thought.get_max_area()
- w += 10
- h += 10
- self.invalidate ((x,y,w,h))
-
- def invalidate (self, transformed_area = None):
- '''Helper function to invalidate the entire screen, forcing a redraw'''
- rect = None
- if not transformed_area:
- alloc = self.get_allocation ()
- rect = gtk.gdk.Rectangle (0, 0, alloc.width, alloc.height)
- else:
- ul = self.untransform_coords(transformed_area[0], transformed_area[1])
- lr = self.untransform_coords(transformed_area[2], transformed_area[3])
- rect = gtk.gdk.Rectangle (int(ul[0]), int(ul[1]), int(lr[0]-ul[0]),
int(lr[1]-ul[1]))
- if self.window:
- self.window.invalidate_rect (rect, True)
-
- def expose (self, widget, event):
- '''Expose event. Calls the draw function'''
- context = self.window.cairo_create ()
- self.draw (event, context)
- return False
-
- def draw (self, event, context):
- '''Draw the map and all the associated thoughts'''
- area = event.area
- context.rectangle (area.x, area.y, area.width, area.height)
- context.clip ()
- context.set_source_rgb (1.0,1.0,1.0)
- context.move_to (area.x, area.y)
- context.paint ()
- context.set_source_rgb (0.0,0.0,0.0)
-
- alloc = self.get_allocation ()
- context.translate(alloc.width/2., alloc.height/2.)
- context.scale(self.scale_fac, self.scale_fac)
- context.translate(-alloc.width/2., -alloc.height/2.)
- context.translate(self.translation[0], self.translation[1])
-
- for l in self.links:
- l.draw (context)
-
- if self.unending_link:
- self.unending_link.draw (context)
-
- self.untransform = context.get_matrix()
- self.transform = context.get_matrix()
- self.transform.invert()
-
- ax, ay = self.transform_coords(area.x, area.y)
- width = area.width / self.scale_fac
- height = area.height / self.scale_fac
- for t in self.thoughts:
- try:
- if max(t.ul[0],ax)<=min(t.lr[0],ax+width) and
max(t.ul[1],ay)<=min(t.lr[1],ay+height):
- t.draw (context)
- except:
- t.draw(context)
-
- if self.is_bbox_selecting:
- xs = self.bbox_origin[0]
- ys = self.bbox_origin[1]
- xe = self.bbox_current[0] - xs
- ye = self.bbox_current[1] - ys
-
- xs,ys = context.user_to_device(xs, ys)
- xe,ye = context.user_to_device_distance(xe, ye)
- xs = int(xs) + 0.5
- ys = int(ys) + 0.5
- xe = int(xe)
- ye = int(ye)
- xs,ys = context.device_to_user(xs, ys)
- xe,ye = context.device_to_user_distance(xe, ye)
-
- color = utils.selected_colors["border"]
- context.set_line_width(1.0)
- context.set_source_rgb(color[0], color[1], color[2])
- context.rectangle(xs, ys, xe, ye)
- context.stroke()
-
- color = utils.selected_colors["fill"]
- context.set_source_rgba(color[0], color[1], color[2], 0.3)
- context.rectangle(xs, ys, xe, ye)
- context.fill()
- context.set_line_width(2.0)
- context.set_source_rgba(0.0, 0.0, 0.0, 1.0)
-
- def undo_create_cb (self, action, mode):
- self.undo.block ()
- if mode == UndoManager.UNDO:
- if action.args[0] == self.editing:
- self.editing = None
- self.unselect_all ()
- for t in action.args[1]:
- self.select_thought (t, -1)
- self.delete_thought (action.args[0])
- self.emit ("change_mode", action.args[3])
- else:
- self.emit ("change_mode", action.args[2])
- thought = action.args[0]
- self.thoughts.append (thought)
- for t in action.args[1]:
- self.unselect_all ()
- self.select_thought (t, -1)
- self.hookup_im_context (thought)
- self.emit ("change_buffer", thought.extended_buffer)
- self.element.appendChild (thought.element)
- for l in action.args[5:]:
- self.links.append (l)
- self.element.appendChild (l.element)
-
- self.begin_editing (thought)
- self.emit ("set_focus", None, False)
- self.undo.unblock ()
- self.invalidate ()
-
- def create_new_thought (self, coords, thought_type = None, loading =
False):
- if self.editing:
- self.editing.finish_editing ()
- if thought_type!= None:
- type = thought_type
- else:
- type = self.mode
-
- if type == TYPE_TEXT:
- thought = TextThought.TextThought (coords, self.pango_context,
self.nthoughts, self.save, self.undo, loading, self.background_color,
self.foreground_color)
- elif type == TYPE_IMAGE:
- thought = ImageThought.ImageThought (coords, self.pango_context,
self.nthoughts, self.save, self.undo, loading, self.background_color)
- elif type == TYPE_DRAWING:
- thought = DrawingThought.DrawingThought (coords, self.pango_context,
self.nthoughts, self.save, self.undo, \
- loading,self.background_color, self.foreground_color)
- elif type == TYPE_RESOURCE:
- thought = ResourceThought.ResourceThought (coords, self.pango_context,
self.nthoughts, self.save, self.undo, loading, self.background_color,
self.foreground_color)
- if not thought.okay ():
- return None
-
- if type == TYPE_IMAGE:
- self.emit ("change_mode", self.old_mode)
- self.nthoughts += 1
- element = thought.element
- self.element.appendChild (thought.element)
- thought.connect ("select_thought", self.select_thought)
- thought.connect ("begin_editing", self.begin_editing)
- thought.connect ("popup_requested", self.create_popup_menu)
- thought.connect ("create_link", self.create_link)
- thought.connect ("claim_unending_link", self.claim_unending_link)
- thought.connect ("update_view", self.update_view)
- thought.connect ("finish_editing", self.finish_editing)
- thought.connect ("delete_thought", self.delete_thought)
- thought.connect ("text_selection_changed", self.text_selection_cb)
- thought.connect ("change_mouse_cursor", self.set_mouse_cursor_cb)
- thought.connect ("update_links", self.update_links_cb)
- thought.connect ("grab_focus", self.regain_focus_cb)
- thought.connect ("update-attrs", self.update_attr_cb)
- self.thoughts.append (thought)
- return thought
-
- def regain_focus_cb (self, thought, ext):
- self.emit ("set_focus", None, ext)
-
- def update_attr_cb (self, widget, bold, italics, underline, pango_font):
- self.emit ("set_attrs", bold, italics, underline, pango_font)
-
- def delete_thought (self, thought):
- action = UndoManager.UndoAction (self, UNDO_DELETE_SINGLE,
self.undo_deletion, [thought])
- if thought.model_iter:
- self.tree_model.remove(thought.model_iter)
- if thought.element in self.element.childNodes:
- self.element.removeChild (thought.element)
- self.thoughts.remove (thought)
- try:
- self.selected.remove (thought)
- except:
- pass
- if self.editing == thought:
- self.hookup_im_context ()
- self.editing = None
- if self.primary == thought:
- thought.disconnect (self.title_change_handler)
- self.title_change_handler = None
- self.primary = None
- if self.thoughts:
- self.make_primary (self.thoughts[0])
- rem_links = []
- for l in self.links:
- if l.uses (thought):
- action.add_arg (l)
- rem_links.append (l)
- for l in rem_links:
- self.delete_link (l)
- self.undo.add_undo (action)
- return True
-
- def undo_deletion (self, action, mode):
- self.undo.block ()
- if mode == UndoManager.UNDO:
- self.unselect_all ()
- for l in action.args[1:]:
- self.links.append (l)
- self.element.appendChild (l.element)
- for t in action.args[0]:
- self.thoughts.append (t)
- self.select_thought (t, -1)
- self.element.appendChild (t.element)
- self.add_thought_to_model (t)
- if action.undo_type == UNDO_DELETE_SINGLE:
- self.begin_editing (action.args[0][0])
- self.emit ("change_buffer", action.args[0][0].extended_buffer)
- if not self.primary:
- self.make_primary (action.args[0][0])
- else:
- self.emit ("change_buffer", None)
- else:
- for t in action.args[0]:
- self.delete_thought (t)
- for l in action.args[1:]:
- self.delete_link (l)
- self.emit ("set_focus", None, False)
- self.undo.unblock ()
- self.invalidate ()
-
- def delete_selected_elements (self):
- if len(self.selected) == 0:
- return
- action = UndoManager.UndoAction (self, UNDO_DELETE, self.undo_deletion,
copy.copy(self.selected))
- # delete_thought as a callback adds it's own undo action. Block that
here
- self.undo.block ()
- tmp = self.selected
- t = tmp.pop()
- while t:
- if t in self.thoughts:
- for l in self.links:
- if l.uses (t):
- action.add_arg (l)
- self.delete_thought (t)
- if t in self.links:
- self.delete_link (t)
- if len (tmp) == 0:
- t = None
- else:
- t = tmp.pop()
- self.undo.unblock ()
- self.undo.add_undo (action)
- self.invalidate ()
-
- def delete_link (self, link):
- if link.element in self.element.childNodes:
- self.element.removeChild (link.element)
- #link.element.unlink ()
- self.links.remove (link)
-
- def popup_menu_key (self, event):
- print "Popup Menu Key"
-
- def find_related_thought (self, radians):
- # Find thought within angle
- best = None
- bestangle = 1000.
- bestdist = 10000.
- def do_find (one, two, currentangle, curdist, sensitivity):
- init_x = (one.ul[0] + one.lr[0]) / 2.
- init_y = (one.ul[1] + one.lr[1]) / 2.
- other_x = (two.ul[0] + two.lr[0]) / 2.
- other_y = (two.ul[1] + two.lr[1]) / 2.
- angle = math.atan2 ((other_y - init_y), (other_x - init_x))
- while angle > math.pi:
- angle -= math.pi
- while angle < -math.pi:
- angle += math.pi
- # We have to special-case left due to stupidity of tan's
- # We shift it by pi radians
- if radians == RAD_LEFT:
- relangle = abs((angle+math.pi) - (radians+math.pi))
- if relangle > math.pi*2.:
- relangle -= math.pi*2.
- else:
- relangle = abs(angle - radians)
- newdist = math.sqrt ((init_x - other_x)**2 + (init_y - other_y)**2)
- magicnum = newdist + (50. * relangle)
+ '''A MindMapArea Widget. A blank canvas with a collection of child
thoughts.\
+ It is responsible for processing signals and such from the whole
area and \
+ passing these on to the correct child. It also informs things when
to draw'''
+
+ __gsignals__ = dict (title_changed =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_STRING,
)),
+
doc_save = (gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_PYOBJECT,
gobject.TYPE_PYOBJECT)),
+ doc_delete =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
()),
+ change_mode =
(gobject.SIGNAL_RUN_LAST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_INT,
)),
+ change_buffer =
(gobject.SIGNAL_RUN_LAST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_OBJECT,
)),
+ text_selection_changed =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_INT,
gobject.TYPE_INT, gobject.TYPE_STRING)),
+ thought_selection_changed =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_PYOBJECT,
gobject.TYPE_PYOBJECT)),
+
set_focus = (gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_PYOBJECT,
gobject.TYPE_BOOLEAN)),
+
set_attrs = (gobject.SIGNAL_RUN_LAST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_BOOLEAN,
gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN,
pango.FontDescription)))
+
+ def __init__(self, undo):
+ super (MMapArea, self).__init__()
+
+ self.thoughts = []
+ self.links = []
+ self.selected = []
+ self.num_selected = 0
+ self.primary = None
+ self.editing = None
+ self.pango_context = self.create_pango_context()
+ self.undo = undo
+ self.scale_fac = 1.0
+ self.translate = False
+ self.translation = [0.0,0.0]
***The diff for this file has been truncated for email.***
=======================================
--- /trunk/src/MainWindow.py Sat Apr 23 07:14:18 2011
+++ /trunk/src/MainWindow.py Sat Apr 23 07:28:34 2011
@@ -10,7 +10,7 @@
#
# Labyrinth 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
+# 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
@@ -36,775 +36,774 @@
import ImageThought
import BaseThought
if os.name != 'nt':
- import gconf
+ import gconf
# UNDO varieties for us
UNDO_MODE = 0
UNDO_SHOW_EXTENDED = 1
class LabyrinthWindow (gobject.GObject):
- __gsignals__ = dict (title_changed = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING, gobject.TYPE_OBJECT)),
- doc_save = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING, gobject.TYPE_OBJECT)),
- file_saved = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING, gobject.TYPE_OBJECT)),
- window_closed = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- (gobject.TYPE_OBJECT, )))
-
- def __init__ (self, filename, imported=False):
- super(LabyrinthWindow, self).__init__()
-
- # FIXME: This can go when we move entirely to gtk 2.10
- # pygtk 2.8 doesn't have the correct function :(
- self.set_val = gtk.gtk_version[1] > 8
-
- # First, construct the MainArea and connect it all up
- self.undo = UndoManager.UndoManager (self)
- self.undo.block ()
- self.MainArea = MMapArea.MMapArea (self.undo)
- self.MainArea.connect ("title_changed", self.title_changed_cb)
- self.MainArea.connect ("doc_save", self.doc_save_cb)
- self.MainArea.connect ("doc_delete", self.doc_del_cb)
- self.MainArea.connect ("change_mode", self.mode_request_cb)
- self.MainArea.connect ("button-press-event", self.main_area_focus_cb)
- self.MainArea.connect ("change_buffer", self.switch_buffer_cb)
- self.MainArea.connect ("thought_selection_changed",
self.thought_selected_cb)
- self.MainArea.connect ("set_focus", self.main_area_focus_cb)
- self.MainArea.connect ("set_attrs", self.attrs_cb)
- if os.name != 'nt':
- self.MainArea.connect ("text_selection_changed",
self.selection_changed_cb)
- self.config_client = gconf.client_get_default()
-
- glade = gtk.glade.XML(utils.get_data_file_name('labyrinth.glade'))
- self.main_window = glade.get_widget ('MapWindow')
- self.main_window.set_focus_child (self.MainArea)
- if os.name != 'nt':
- try:
- self.main_window.set_icon_name ('labyrinth')
- except:
-
self.main_window.set_icon_from_file(utils.get_data_file_name('labyrinth.svg'))
- else:
- self.main_window.set_icon_from_file('images\\labyrinth-24.png')
-
- # insert menu, toolbar and map
- self.create_menu()
- glade.get_widget ('main_area_insertion').pack_start(self.MainArea)
- vbox = glade.get_widget ('map_window_vbox')
- menubar = self.ui.get_widget('/MenuBar')
- menubar.show_all()
- vbox.pack_start(menubar)
- vbox.reorder_child(menubar, 0)
- vbox.set_child_packing(menubar, 0, 0, 0, gtk.PACK_START)
-
- toolbar = self.ui.get_widget('/ToolBar')
- toolbar.show_all()
- vbox.pack_start(toolbar)
- vbox.reorder_child(toolbar, 1)
- vbox.set_child_packing(toolbar, 0, 0, 0, gtk.PACK_START)
-
- # TODO: Bold, Italics etc.
- self.bold_widget = glade.get_widget('tool_bold')
- self.bold_widget.connect('toggled', self.bold_toggled)
- self.bold_block = False
- self.bold_state = False
- self.italic_widget = glade.get_widget('tool_italic')
- self.italic_widget.connect('toggled', self.italic_toggled)
- self.italic_block = False
- self.italic_state = False
- self.underline_widget = glade.get_widget('tool_underline')
- self.underline_widget.connect('toggled', self.underline_toggled)
- self.underline_block = False
- self.underline_state = False
-
- self.font_widget = glade.get_widget('font_button')
- self.font_widget.connect ("font-set", self.font_change_cb)
- self.background_widget = glade.get_widget('background_color_button')
- self.background_widget.connect ("color-set", self.background_change_cb)
- self.foreground_widget = glade.get_widget('foreground_color_button')
- self.foreground_widget.connect ("color-set", self.foreground_change_cb)
-
- self.cut = self.ui.get_widget ('/MenuBar/EditMenu/Cut')
- self.copy = self.ui.get_widget ('/MenuBar/EditMenu/Copy')
- self.paste = self.ui.get_widget ('/MenuBar/EditMenu/Paste')
- self.link = self.ui.get_widget ('/MenuBar/EditMenu/LinkThoughts')
- self.delete = self.ui.get_widget ('/MenuBar/EditMenu/DeleteNodes')
-
- self.ui.get_widget('/MenuBar/EditMenu').connect ('activate',
self.edit_activated_cb)
- self.cut.set_sensitive (False)
- self.copy.set_sensitive (False)
-
- # get toolbars and activate corresponding menu entries
- self.main_toolbar = self.ui.get_widget ('/ToolBar')
- self.format_toolbar = glade.get_widget ('format_toolbar')
-
self.ui.get_widget('/MenuBar/ViewMenu/ShowToolbars/ShowMainToolbar').set_active(True)
-
self.ui.get_widget('/MenuBar/ViewMenu/ShowToolbars/ShowFormatToolbar').set_active(True)
-
self.ui.get_widget('/MenuBar/ViewMenu/UseBezier').set_active(utils.use_bezier_curves)
-
- # Add in the extended info view
- self.extended_window = glade.get_widget('extended_window')
- self.extended = glade.get_widget('extended')
- self.invisible_buffer = gtk.TextBuffer ()
-
- # Connect all our signals
- self.main_window.connect ("configure_event", self.configure_cb)
- self.main_window.connect ("window-state-event", self.window_state_cb)
- self.main_window.connect ("destroy", self.close_window_cb)
-
- # Deal with loading the map
- if not filename:
- self.MainArea.set_size_request (400, 400)
- # TODO: This shouldn't be set to a hard-coded number. Fix.
- self.pane_pos = 500
- self.title_cp = _("Untitled Map")
- self.mode = MMapArea.MODE_EDITING
- self.extended_visible = False
- else:
- self.parse_file (filename)
-
- # Setup treeview for a11y
- self.create_tree_view(glade)
- self.MainArea.initialize_model(self.tree_model)
-
- up_box = glade.get_widget('up_box')
- up_box.connect("button-press-event", self.translate, "Up")
- up_box.connect("button-release-event", self.finish_translate)
- down_box = glade.get_widget('down_box')
- down_box.connect("button-press-event", self.translate, "Down")
- down_box.connect("button-release-event", self.finish_translate)
- right_box = glade.get_widget('right_box')
- right_box.connect("button-press-event", self.translate, "Right")
- right_box.connect("button-release-event", self.finish_translate)
- left_box = glade.get_widget('left_box')
- left_box.connect("button-press-event", self.translate, "Left")
- left_box.connect("button-release-event", self.finish_translate)
-
- self.align_button = glade.get_widget('tool_align')
- self.align_handler_id = self.align_button.connect('clicked',
self.align_cb, "vl")
- glade.get_widget('align_vertical_left').connect('activate',
self.align_cb, "vl")
- glade.get_widget('align_vertical_right').connect('activate',
self.align_cb, "vr")
- glade.get_widget('align_vertical_center').connect('activate',
self.align_cb, "vc")
- glade.get_widget('align_horizontal_top').connect('activate',
self.align_cb, "ht")
- glade.get_widget('align_horizontal_bottom').connect('activate',
self.align_cb, "hb")
- glade.get_widget('align_horizontal_center').connect('activate',
self.align_cb, "hc")
-
- panes = glade.get_widget('vpaned1')
- panes.connect ("button-release-event", self.pos_changed)
- panes.set_position (self.pane_pos)
-
- # Other stuff
- self.width, self.height = self.main_window.get_size ()
-
- # if we import, we dump the old filename to create a new hashed one
- self.save_file = None
- if not imported:
- self.save_file = filename
-
- self.maximised = False
- self.view_type = 0
- if self.set_val:
- self.act.set_current_value (self.mode)
-
- self.undo.unblock ()
- self.start_timer ()
-
- def show(self):
- self.main_window.show_all()
- self.ext_act.set_active(self.extended_visible)
- if not self.extended_visible:
- self.extended_window.hide()
- if os.name != 'nt':
- if not self.config_client.get_bool('/apps/labyrinth/show_tree_view'):
- self.tree_view.hide()
- else:
- self.tree_view.expand_all()
- self.ui.get_widget('/MenuBar/ViewMenu/ViewOutline').set_active(True)
-
- def create_menu (self):
- actions = [
- ('FileMenu', None, _('File')),
- ('Export', None, _('Export as Image'), None,
- _("Export your map as an image"), self.export_cb),
- ('ExportMap', gtk.STOCK_SAVE_AS, _('Export Map...'), '<control>S',
- _("Export your map as XML"), self.export_map_cb),
- ('Close', gtk.STOCK_CLOSE, None, '<control>W',
- _('Close the current window'), self.close_window_cb),
- ('EditMenu', None, _('_Edit')),
- ('ViewMenu', None, _('_View')),
- ('ShowToolbars', None, _('_Toolbar')),
- ('Undo', gtk.STOCK_UNDO, None, '<control>Z', None),
- ('Redo', gtk.STOCK_REDO, None, '<control><shift>Z', None),
- ('Cut', gtk.STOCK_CUT, None, '<control>X',
- None, self.cut_text_cb),
- ('Copy', gtk.STOCK_COPY, None, '<control>C',
- None, self.copy_text_cb),
- ('Paste', gtk.STOCK_PASTE, None, '<control>V',
- None, self.paste_text_cb),
- ('LinkThoughts', None, _("Link Thoughts"), '<control>L',
- _("Link the selected thoughts"), self.link_thoughts_cb),
- ('ModeMenu', None, _('_Mode')),
- ('DeleteNodes', gtk.STOCK_DELETE, _('_Delete'), 'Delete',
- _('Delete the selected element(s)'), self.delete_cb),
- ('ZoomIn', gtk.STOCK_ZOOM_IN, None, '<control>plus',
- None, self.zoomin_cb),
- ('ZoomOut', gtk.STOCK_ZOOM_OUT, None, '<control>minus',
- None, self.zoomout_cb)]
- self.radio_actions = [
- ('Edit', gtk.STOCK_EDIT, _('_Edit Mode'), '<control>E',
- _('Turn on edit mode'), MMapArea.MODE_EDITING),
- ('AddImage', gtk.STOCK_ADD, _('_Add Image'), None,
- _('Add an image to selected thought'), MMapArea.MODE_IMAGE),
- ('Drawing', gtk.STOCK_COLOR_PICKER, _('_Drawing Mode'), None,
- _('Make a pretty drawing'), MMapArea.MODE_DRAW),
- ('AddResource', gtk.STOCK_NETWORK, _('Add Resource'), None,
- _('Add a resource'), MMapArea.MODE_RESOURCE)]
- self.view_radio_actions = [
- ('UseBezier', None, _('Use _Curves'), None,
- _('Use curves as links'), MMapArea.VIEW_BEZIER),
- ('UseLines', None, _('Use _Lines'), None,
- _('Use straight lines as links'), MMapArea.VIEW_LINES)]
- self.toggle_actions = [
- ('ViewExtend', None, _('_Extended Information'), None,
- _('Show extended information for thoughts'), self.view_extend_cb),
- ('ViewOutline', None, _('_Outline'), None,
- _('Show outline of thought hierarchy'), self.view_outline_cb),
- ('ShowMainToolbar', None, _('_Main'), None,
- _('Show main toolbar'), self.show_main_toolbar_cb),
- ('ShowFormatToolbar', None, _('_Format'), None,
- _('Show format toolbar'), self.show_format_toolbar_cb)]
-
- ag = gtk.ActionGroup ('WindowActions')
- ag.add_actions (actions)
- ag.add_radio_actions (self.radio_actions)
- ag.add_radio_actions (self.view_radio_actions)
- ag.add_toggle_actions (self.toggle_actions)
- self.act = ag.get_action ('Edit')
- self.ext_act = ag.get_action ('ViewExtend')
- self.act.connect ("changed", self.mode_change_cb)
- self.undo.set_widgets (ag.get_action ('Undo'), ag.get_action ('Redo'))
-
- self.view_action = ag.get_action('UseBezier')
- self.view_action.connect ("changed", self.view_change_cb)
-
- self.ui = gtk.UIManager ()
- self.ui.insert_action_group (ag, 0)
- self.ui.add_ui_from_file (utils.get_data_file_name('labyrinth-ui.xml'))
- self.main_window.add_accel_group (self.ui.get_accel_group ())
-
- def create_tree_view(self, glade):
- self.tree_model = gtk.TreeStore(gobject.TYPE_STRING)
- self.tree_view = glade.get_widget('outline_treeview')
- self.tree_view.set_model(self.tree_model)
- cell_renderer = gtk.CellRendererText()
- tree_column = gtk.TreeViewColumn(_('Thoughts'), cell_renderer)
- self.tree_view.append_column(tree_column)
- tree_column.add_attribute(cell_renderer, "text", 0)
-
- def align_cb(self, widget, direction):
- if direction == "vl" or direction == "ht":
- self.MainArea.align_top_left(direction == "vl")
- elif direction == "vr" or direction == "hb":
- self.MainArea.align_bottom_right(direction == "vr")
- else:
- self.MainArea.align_centered(direction == "vc")
-
- if widget != self.align_button:
- self.align_button.disconnect(self.align_handler_id)
- self.align_handler_id = self.align_button.connect('clicked',
self.align_cb, direction)
- self.align_button.set_icon_name(widget.get_image().get_icon_name()[0])
-
- def link_thoughts_cb (self, arg):
- self.MainArea.link_menu_cb ()
-
- def undo_show_extended (self, action, mode):
- self.undo.block ()
- self.ext_act.set_active (not self.ext_act.get_active ())
- self.undo.unblock ()
-
- def view_extend_cb (self, arg):
- self.undo.add_undo (UndoManager.UndoAction (self, UNDO_SHOW_EXTENDED,
self.undo_show_extended))
- self.extended_visible = arg.get_active ()
- if self.extended_visible:
- self.extended_window.show ()
- self.view_type = 1
- else:
- self.extended_window.hide ()
- self.view_type = 0
-
- def view_outline_cb (self, arg):
- if arg.get_active ():
- self.tree_view.show()
- else:
- self.tree_view.hide()
- if os.name != 'nt':
- self.config_client.set_bool('/apps/labyrinth/show_tree_view',
arg.get_active())
-
- def show_main_toolbar_cb(self, arg):
- if arg.get_active():
- self.main_toolbar.show()
- else:
- self.main_toolbar.hide()
-
- def show_format_toolbar_cb(self, arg):
- if arg.get_active():
- self.format_toolbar.show()
- else:
- self.format_toolbar.hide()
-
- def view_change_cb(self, base, activated):
- utils.use_bezier_curves = activated.get_current_value() ==
MMapArea.VIEW_BEZIER
- if os.name != 'nt':
- self.config_client.set_bool('/apps/labyrinth/curves',
utils.use_bezier_curves)
- self.MainArea.update_all_links()
- self.MainArea.invalidate()
-
- def attrs_cb (self, widget, bold, italics, underline, pango_font):
- # Yes, there is a block method for signals
- # but I don't currently know how to
- # implement it for action-based signals
- # without messyness
- if bold != self.bold_state:
- self.bold_block = True
- self.bold_widget.set_active(bold)
- if italics != self.italic_state:
- self.italic_block = True
- self.italic_widget.set_active(italics)
- if underline != self.underline_state:
- self.underline_block = True
- self.underline_widget.set_active(underline)
- if pango_font:
- font_name = pango_font.to_string()
- self.font_widget.set_font_name (font_name)
- self.MainArea.set_font(font_name)
- else:
- self.font_widget.set_font_name (utils.default_font)
-
- def translate (self, box, arg1, direction):
- self.orig_translate = [self.MainArea.translation[0],
self.MainArea.translation[1]]
- if direction == "Up":
- translation_x = 0
- translation_y = 5
- elif direction == "Down":
- translation_x = 0
- translation_y = -5
- elif direction == "Right":
- translation_x = -5
- translation_y = 0
- elif direction == "Left":
- translation_x = 5
- translation_y = 0
- else:
- print "Error"
- return
- gobject.timeout_add (20, self.translate_timeout, translation_x,
translation_y)
- self.tr_to = True
-
- def translate_timeout (self, addition_x, addition_y):
- if not self.tr_to:
- return False
- self.MainArea.translation[0] += addition_x / self.MainArea.scale_fac
- self.MainArea.translation[1] += addition_y / self.MainArea.scale_fac
- self.MainArea.invalidate()
- return self.tr_to
-
- def finish_translate (self, box, arg1):
- self.undo.add_undo (UndoManager.UndoAction (self.MainArea,
UndoManager.TRANSFORM_CANVAS, \
- self.MainArea.undo_transform_cb,
- self.MainArea.scale_fac,
- self.MainArea.scale_fac,
- self.orig_translate,
- self.MainArea.translation))
- self.tr_to = False
-
- def pos_changed (self, panes, arg2):
- self.pane_pos = panes.get_position ()
-
- def bold_toggled (self, action):
- self.bold_state = (not self.bold_state)
- if self.bold_block:
- self.bold_block = False
- return
- if self.extended.is_focus ():
- self.extended.get_buffer().set_bold(action.get_active())
- else:
- self.MainArea.set_bold (action.get_active())
-
- def italic_toggled (self, action):
- self.italic_state = (not self.italic_state)
- if self.italic_block:
- self.italic_block = False
- return
- if self.extended.is_focus ():
- self.extended.get_buffer().set_italics(action.get_active())
- else:
- self.MainArea.set_italics (action.get_active())
-
- def underline_toggled (self, action):
- self.underline_state = (not self.underline_state)
- if self.underline_block:
- self.underline_block = False
- return
- if self.extended.is_focus ():
- self.extended.get_buffer().set_underline(action.get_active())
- else:
- self.MainArea.set_underline (action.get_active())
-
- def foreground_change_cb (self, button):
- if not self.extended.is_focus ():
- self.MainArea.set_foreground_color (button.get_color())
-
- def background_change_cb (self, button):
- if not self.extended.is_focus ():
- self.MainArea.set_background_color (button.get_color())
-
- def font_change_cb (self, button):
- if not self.extended.is_focus ():
- self.MainArea.set_font (button.get_font_name ())
-
- def zoomin_cb(self, arg):
- self.MainArea.scale_fac*=1.2
- self.MainArea.invalidate()
-
- def zoomout_cb(self, arg):
- self.MainArea.scale_fac/=1.2
- self.MainArea.invalidate()
-
- def new_window_cb (self, arg):
- global_new_window ()
- return
-
- def switch_buffer_cb (self, arg, new_buffer):
- if new_buffer:
- self.extended.set_editable (True)
- self.extended.set_buffer (new_buffer)
- else:
- self.extended.set_buffer (self.invisible_buffer)
- self.extended.set_editable (False)
-
- def thought_selected_cb (self, arg, background_color, foreground_color):
- if background_color:
- self.background_widget.set_color(background_color)
- if foreground_color:
- self.foreground_widget.set_color(foreground_color)
-
- def main_area_focus_cb (self, arg, event, extended = False):
- if not extended:
- self.MainArea.grab_focus ()
- else:
- self.extended.grab_focus ()
-
- def revert_mode (self, action, mode):
- self.undo.block ()
- if mode == UndoManager.UNDO:
- self.mode_request_cb (None, action.args[0])
- else:
- self.mode_request_cb (None, action.args[1])
- self.undo.unblock ()
-
- def mode_change_cb (self, base, activated):
- self.MainArea.set_mode (activated.get_current_value ())
- self.mode = activated.get_current_value ()
-
- def mode_request_cb (self, widget, mode):
- if self.set_val:
- self.act.set_current_value (mode)
-
- def title_changed_cb (self, widget, new_title):
- self.title_cp = self.title_cp = _('Untitled Map')
- if new_title != '':
- split = new_title.splitlines ()
- self.title_cp = reduce(lambda x,y : x + ' ' + y, split)
-
- if len(self.title_cp) > 27:
- x = self.title_cp[:27] + "..."
- self.emit ("title-changed", x, self)
- else:
- self.emit ("title-changed", self.title_cp, self)
- self.main_window.set_title (self.title_cp)
-
- def delete_cb (self, event):
- self.MainArea.delete_selected_elements ()
-
- def close_window_cb (self, event):
- self.SaveTimer.cancel = True
- self.main_window.hide ()
- self.MainArea.save_thyself ()
- del (self)
-
- def doc_del_cb (self, widget):
- self.emit ('window_closed', None)
-
- def serialize_to_xml(self, doc, top_element):
- top_element.setAttribute ("title", self.title_cp)
- top_element.setAttribute ("mode", str(self.mode))
- top_element.setAttribute ("size", str((self.width,self.height)))
- top_element.setAttribute ("position", str((self.xpos,self.ypos)))
- top_element.setAttribute ("maximised", str(self.maximised))
- top_element.setAttribute ("view_type", str(self.view_type))
- top_element.setAttribute ("pane_position", str(self.pane_pos))
- top_element.setAttribute ("scale_factor", str(self.MainArea.scale_fac))
- top_element.setAttribute ("translation", str(self.MainArea.translation))
- string = doc.toxml ()
- return string.encode ("utf-8" )
-
- def save_map(self, filename, string):
- f = file (filename, 'w')
- f.write (string)
- f.close ()
-
- def doc_save_cb (self, widget, doc, top_element):
- save_string = self.serialize_to_xml(doc, top_element)
- if not self.save_file:
- hsh = hashlib.sha256 (save_string)
- save_loc = utils.get_save_dir ()
- self.save_file = save_loc+hsh.hexdigest()+".map"
- counter = 1
- while os.path.exists(self.save_file):
-
- print "Warning: Duplicate File. Saving to alternative"
- self.save_file = save_loc + "Dup"+str(counter)+hsh.hexdigest()+".map"
- counter += 1
-
- self.save_map(self.save_file, save_string)
- self.emit ('file_saved', self.save_file, self)
-
- def export_map_cb(self, event):
- chooser = gtk.FileChooserDialog(title=_("Save File As"),
action=gtk.FILE_CHOOSER_ACTION_SAVE, \
- buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN,
gtk.RESPONSE_OK))
- chooser.set_current_name ("%s.mapz" % self.main_window.title)
- response = chooser.run()
- if response == gtk.RESPONSE_OK:
- filename = chooser.get_filename ()
- self.MainArea.save_thyself ()
- tf = tarfile.open (filename, "w")
- tf.add (self.save_file, utils.strip_path_from_file_name(self.save_file))
- for t in self.MainArea.thoughts:
- if isinstance(t, ImageThought.ImageThought):
- tf.add (t.filename, 'images/' +
utils.strip_path_from_file_name(t.filename))
-
- tf.close()
-
- chooser.destroy()
-
- def parse_file (self, filename):
- f = file (filename, 'r')
- doc = dom.parse (f)
- top_element = doc.documentElement
- self.title_cp = top_element.getAttribute ("title")
- self.mode = int (top_element.getAttribute ("mode"))
- if top_element.hasAttribute ("maximised"):
- maxi = top_element.getAttribute ("maximised")
- else:
- maxi = False
- if maxi == "True":
- self.main_window.maximize ()
- if top_element.hasAttribute ("pane_position"):
- self.pane_pos = int (top_element.getAttribute ("pane_position"))
- else:
- self.pane_pos = 500
- if top_element.hasAttribute ("view_type"):
- vt = int (top_element.getAttribute ("view_type"))
- else:
- vt = 0
- self.extended_visible = vt == 1
-
- tmp = top_element.getAttribute ("size")
- (width, height) = utils.parse_coords (tmp)
- tmp = top_element.getAttribute ("position")
- (x, y) = utils.parse_coords (tmp)
- self.main_window.resize (int (width), int (height))
-
- # Don't know why, but metacity seems to move the window 24 pixels
- # further down than requested. Compensate by removing 24
- # pixels from the stored size
- y -= 24
- self.main_window.move (int (x), int (y))
-
- self.MainArea.set_mode (self.mode)
- self.MainArea.load_thyself (top_element, doc)
- if top_element.hasAttribute("scale_factor"):
- self.MainArea.scale_fac = float (top_element.getAttribute
("scale_factor"))
- if top_element.hasAttribute("translation"):
- tmp = top_element.getAttribute("translation")
- (x,y) = utils.parse_coords(tmp)
- self.MainArea.translation = [x,y]
-
- def configure_cb (self, window, event):
- self.xpos = event.x
- self.ypos = event.y
- self.width = event.width
- self.height = event.height
- return False
-
- def window_state_cb (self, window, event):
- if event.changed_mask & gtk.gdk.WINDOW_STATE_MAXIMIZED:
- self.maximised = not self.maximised
-
- def toggle_range (self, arg, native_width, native_height, max_width,
max_height):
- if arg.get_active ():
- self.spin_width.set_value (max_width)
- self.spin_height.set_value (max_height)
- # TODO: Fix this (and below) to cope with non-native resolutions
properly
- #self.spin_width.set_sensitive (True)
- #self.spin_height.set_sensitive (True)
- else:
- #self.spin_width.set_sensitive (False)
- #self.spin_height.set_sensitive (False)
- self.spin_width.set_value (native_width)
- self.spin_height.set_value (native_height)
-
- def export_cb (self, event):
- maxx, maxy = self.MainArea.get_max_area ()
-
- x, y, width, height, bitdepth = self.MainArea.window.get_geometry ()
- glade = gtk.glade.XML (utils.get_data_file_name('labyrinth.glade'))
- dialog = glade.get_widget ('ExportImageDialog')
- box = glade.get_widget ('dialog_insertion')
- fc = gtk.FileChooserWidget(gtk.FILE_CHOOSER_ACTION_SAVE)
- box.pack_end (fc)
-
- filter_mapping = [ (_('All Files'), ['*']),
- (_('PNG Image (*.png)'), ['*.png']),
- (_('JPEG Image (*.jpg, *.jpeg)'), ['*.jpeg', '*.jpg']),
- (_('SVG Vector Image (*.svg)'), ['*.svg']),
- (_('PDF Portable Document (*.pdf)'), ['*.pdf']) ]
-
- for (filter_name, filter_patterns) in filter_mapping:
- fil = gtk.FileFilter ()
- fil.set_name(filter_name)
- for pattern in filter_patterns:
- fil.add_pattern(pattern)
- fc.add_filter(fil)
-
- fc.set_current_name ("%s.png" % self.main_window.title)
- rad = glade.get_widget ('rb_complete_map')
- rad2 = glade.get_widget ('rb_visible_area')
- self.spin_width = glade.get_widget ('width_spin')
- self.spin_height = glade.get_widget ('height_spin')
- self.spin_width.set_value (maxx)
- self.spin_height.set_value (maxy)
- self.spin_width.set_sensitive (False)
- self.spin_height.set_sensitive (False)
-
- rad.connect ('toggled', self.toggle_range, width, height,maxx,maxy)
-
- fc.show ()
- while 1:
- # Cheesy loop. Break out as needed.
- response = dialog.run()
- if response == gtk.RESPONSE_OK:
- ext_mime_mapping = { 'png':'png', 'jpg':'jpeg', 'jpeg':'jpeg', \
- 'svg':'svg', 'pdf':'pdf' }
- filename = fc.get_filename()
- ext = filename[filename.rfind('.')+1:]
-
- try:
- mime = ext_mime_mapping[ext]
- break
- except KeyError:
- msg = gtk.MessageDialog(self, gtk.DIALOG_DESTROY_WITH_PARENT,
gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, \
- _("Unknown file format"))
- msg.format_secondary_text (_("The file type '%s' is unsupported.
Please use the suffix '.png',"\
- " '.jpg' or '.svg'." % ext))
- msg.run ()
- msg.destroy ()
- else:
- dialog.destroy ()
- return
-
- true_width = int (self.spin_width.get_value ())
- true_height = int (self.spin_height.get_value ())
- native = not rad.get_active ()
- dialog.destroy ()
-
- if mime in ['png', 'jpg']:
- self.save_as_pixmap(filename, mime, true_width, true_height, bitdepth,
native)
- else:
- surface = None
- if mime == 'svg':
- surface = cairo.SVGSurface(filename, true_width, true_height)
- elif mime == 'pdf':
- surface = cairo.PDFSurface(filename, true_width, true_height)
- self.save_surface(surface, true_width, true_height, native)
-
- def save_as_pixmap(self, filename, mime, width, height, bitdepth, native):
- pixmap = gtk.gdk.Pixmap (None, width, height, bitdepth)
- self.MainArea.export (pixmap.cairo_create (), width, height, native)
-
- pb =
gtk.gdk.Pixbuf.get_from_drawable(gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,
True, 8, width, height), \
- pixmap, \
- gtk.gdk.colormap_get_system(), \
- 0, 0, 0, 0, width, height)
- pb.save(filename, mime)
-
- def save_surface(self, surface, width, height, native):
- cairo_context = cairo.Context(surface)
- context = pangocairo.CairoContext(cairo_context)
- self.MainArea.export(context, width, height, native)
- surface.finish()
-
- def selection_changed_cb (self, area, start, end, text):
- clip = gtk.Clipboard (selection="PRIMARY")
- if text:
- clip.set_text (text)
- else:
- clip.clear ()
-
- def edit_activated_cb (self, menu):
- # FIXME: Keybindings should also be deactivated.
- self.cut.set_sensitive (False)
- self.copy.set_sensitive (False)
- self.paste.set_sensitive (False)
- self.link.set_sensitive (False)
- if self.extended.is_focus ():
- self.paste.set_sensitive (True)
- stend = self.extended.get_buffer().get_selection_bounds()
- if len (stend) > 1:
- start, end = stend
- else:
- start = end = stend
- else:
- start, end = self.MainArea.get_selection_bounds ()
- try:
- if self.mode == MMapArea.MODE_EDITING and len(self.MainArea.selected)
and \
- self.MainArea.selected[0].editing:
- self.paste.set_sensitive (True)
- except AttributeError:
- pass
- if len (self.MainArea.selected) == 2:
- self.link.set_sensitive (True)
-
- if start and start != end:
- self.cut.set_sensitive (True)
- self.copy.set_sensitive (True)
-
- def cut_text_cb (self, event):
- clip = gtk.Clipboard ()
- if self.extended.is_focus ():
- self.extended.get_buffer().cut_clipboard (clip)
- else:
- self.MainArea.cut_clipboard (clip)
-
- def copy_text_cb (self, event):
- clip = gtk.Clipboard ()
- if self.extended.is_focus ():
- self.extended.get_buffer().copy_clipboard (clip)
- else:
- self.MainArea.copy_clipboard (clip)
-
- def paste_text_cb (self, event):
- clip = gtk.Clipboard ()
- if self.extended.is_focus ():
- self.extended.get_buffer().paste_clipboard (clip, None, True)
- else:
- self.MainArea.paste_clipboard (clip)
-
- def start_timer (self):
- self.SaveTimer = PeriodicSaveThread.PeriodicSaveThread(self.MainArea)
- self.SaveTimer.setDaemon( True)
- self.SaveTimer.start()
-
+ __gsignals__ = dict (title_changed =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_STRING,
gobject.TYPE_OBJECT)),
+
doc_save = (gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_STRING,
gobject.TYPE_OBJECT)),
+ file_saved =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_STRING,
gobject.TYPE_OBJECT)),
+ window_closed =
(gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_OBJECT,
)))
+
+ def __init__ (self, filename, imported=False):
+ super(LabyrinthWindow, self).__init__()
+
+ # FIXME: This can go when we move entirely to gtk 2.10
+ # pygtk 2.8 doesn't have the correct function :(
+ self.set_val = gtk.gtk_version[1] > 8
+
+ # First, construct the MainArea and connect it all up
+ self.undo = UndoManager.UndoManager (self)
+ self.undo.block ()
+ self.MainArea = MMapArea.MMapArea (self.undo)
+ self.MainArea.connect ("title_changed", self.title_changed_cb)
+ self.MainArea.connect ("doc_save", self.doc_save_cb)
+ self.MainArea.connect ("doc_delete", self.doc_del_cb)
+ self.MainArea.connect ("change_mode", self.mode_request_cb)
+ self.MainArea.connect ("button-press-event",
self.main_area_focus_cb)
+ self.MainArea.connect ("change_buffer", self.switch_buffer_cb)
+ self.MainArea.connect ("thought_selection_changed",
self.thought_selected_cb)
+ self.MainArea.connect ("set_focus", self.main_area_focus_cb)
+ self.MainArea.connect ("set_attrs", self.attrs_cb)
+ if os.name != 'nt':
+ self.MainArea.connect ("text_selection_changed",
self.selection_changed_cb)
+ self.config_client = gconf.client_get_default()
+
+ glade = gtk.glade.XML(utils.get_data_file_name('labyrinth.glade'))
+ self.main_window = glade.get_widget ('MapWindow')
+ self.main_window.set_focus_child (self.MainArea)
+ if os.name != 'nt':
+ try:
+ self.main_window.set_icon_name ('labyrinth')
+ except:
+
self.main_window.set_icon_from_file(utils.get_data_file_name('labyrinth.svg'))
+ else:
+ self.main_window.set_icon_from_file('images\\labyrinth-24.png')
+
+ # insert menu, toolbar and map
+ self.create_menu()
+ glade.get_widget ('main_area_insertion').pack_start(self.MainArea)
+ vbox = glade.get_widget ('map_window_vbox')
+ menubar = self.ui.get_widget('/MenuBar')
+ menubar.show_all()
+ vbox.pack_start(menubar)
+ vbox.reorder_child(menubar, 0)
+ vbox.set_child_packing(menubar, 0, 0, 0, gtk.PACK_START)
+
+ toolbar = self.ui.get_widget('/ToolBar')
+ toolbar.show_all()
+ vbox.pack_start(toolbar)
+ vbox.reorder_child(toolbar, 1)
+ vbox.set_child_packing(toolbar, 0, 0, 0, gtk.PACK_START)
+
+ # TODO: Bold, Italics etc.
+ self.bold_widget = glade.get_widget('tool_bold')
+ self.bold_widget.connect('toggled', self.bold_toggled)
+ self.bold_block = False
+ self.bold_state = False
+ self.italic_widget = glade.get_widget('tool_italic')
+ self.italic_widget.connect('toggled', self.italic_toggled)
+ self.italic_block = False
+ self.italic_state = False
+ self.underline_widget = glade.get_widget('tool_underline')
+ self.underline_widget.connect('toggled', self.underline_toggled)
+ self.underline_block = False
+ self.underline_state = False
+
+ self.font_widget = glade.get_widget('font_button')
+ self.font_widget.connect ("font-set", self.font_change_cb)
+ self.background_widget =
glade.get_widget('background_color_button')
+ self.background_widget.connect ("color-set",
self.background_change_cb)
+ self.foreground_widget =
glade.get_widget('foreground_color_button')
+ self.foreground_widget.connect ("color-set",
self.foreground_change_cb)
+
+ self.cut = self.ui.get_widget ('/MenuBar/EditMenu/Cut')
+ self.copy = self.ui.get_widget ('/MenuBar/EditMenu/Copy')
+ self.paste = self.ui.get_widget ('/MenuBar/EditMenu/Paste')
+ self.link = self.ui.get_widget ('/MenuBar/EditMenu/LinkThoughts')
+ self.delete = self.ui.get_widget ('/MenuBar/EditMenu/DeleteNodes')
+
+ self.ui.get_widget('/MenuBar/EditMenu').connect ('activate',
self.edit_activated_cb)
+ self.cut.set_sensitive (False)
+ self.copy.set_sensitive (False)
+
+ # get toolbars and activate corresponding menu entries
+ self.main_toolbar = self.ui.get_widget ('/ToolBar')
+ self.format_toolbar = glade.get_widget ('format_toolbar')
+
self.ui.get_widget('/MenuBar/ViewMenu/ShowToolbars/ShowMainToolbar').set_active(True)
+
self.ui.get_widget('/MenuBar/ViewMenu/ShowToolbars/ShowFormatToolbar').set_active(True)
+
self.ui.get_widget('/MenuBar/ViewMenu/UseBezier').set_active(utils.use_bezier_curves)
+
+ # Add in the extended info view
+ self.extended_window = glade.get_widget('extended_window')
+ self.extended = glade.get_widget('extended')
+ self.invisible_buffer = gtk.TextBuffer ()
+
+ # Connect all our signals
+ self.main_window.connect ("configure_event", self.configure_cb)
+ self.main_window.connect ("window-state-event",
self.window_state_cb)
+ self.main_window.connect ("destroy", self.close_window_cb)
+
+ # Deal with loading the map
+ if not filename:
+ self.MainArea.set_size_request (400, 400)
+ # TODO: This shouldn't be set to a hard-coded number. Fix.
+ self.pane_pos = 500
+ self.title_cp = _("Untitled Map")
+ self.mode = MMapArea.MODE_EDITING
+ self.extended_visible = False
+ else:
+ self.parse_file (filename)
+
+ # Setup treeview for a11y
+ self.create_tree_view(glade)
+ self.MainArea.initialize_model(self.tree_model)
+
+ up_box = glade.get_widget('up_box')
+ up_box.connect("button-press-event", self.translate, "Up")
+ up_box.connect("button-release-event", self.finish_translate)
+ down_box = glade.get_widget('down_box')
+ down_box.connect("button-press-event", self.translate, "Down")
+ down_box.connect("button-release-event", self.finish_translate)
+ right_box = glade.get_widget('right_box')
+ right_box.connect("button-press-event", self.translate, "Right")
+ right_box.connect("button-release-event", self.finish_translate)
+ left_box = glade.get_widget('left_box')
+ left_box.connect("button-press-event", self.translate, "Left")
+ left_box.connect("button-release-event", self.finish_translate)
+
+ self.align_button = glade.get_widget('tool_align')
+ self.align_handler_id = self.align_button.connect('clicked',
self.align_cb, "vl")
+ glade.get_widget('align_vertical_left').connect('activate',
self.align_cb, "vl")
+ glade.get_widget('align_vertical_right').connect('activate',
self.align_cb, "vr")
+ glade.get_widget('align_vertical_center').connect('activate',
self.align_cb, "vc")
+ glade.get_widget('align_horizontal_top').connect('activate',
self.align_cb, "ht")
+ glade.get_widget('align_horizontal_bottom').connect('activate',
self.align_cb, "hb")
+ glade.get_widget('align_horizontal_center').connect('activate',
self.align_cb, "hc")
+
+ panes = glade.get_widget('vpaned1')
+ panes.connect ("button-release-event", self.pos_changed)
+ panes.set_position (self.pane_pos)
+
+ # Other stuff
+ self.width, self.height = self.main_window.get_size ()
+
+ # if we import, we dump the old filename to create a new hashed one
+ self.save_file = None
+ if not imported:
+ self.save_file = filename
+
+ self.maximised = False
+ self.view_type = 0
+ if self.set_val:
+ self.act.set_current_value (self.mode)
+
+ self.undo.unblock ()
+ self.start_timer ()
+
+ def show(self):
+ self.main_window.show_all()
+ self.ext_act.set_active(self.extended_visible)
+ if not self.extended_visible:
+ self.extended_window.hide()
+ if os.name != 'nt':
+ if not
self.config_client.get_bool('/apps/labyrinth/show_tree_view'):
+ self.tree_view.hide()
+ else:
+ self.tree_view.expand_all()
+
self.ui.get_widget('/MenuBar/ViewMenu/ViewOutline').set_active(True)
+
+ def create_menu (self):
+ actions = [
+ ('FileMenu', None, _('File')),
+ ('Export', None, _('Export as Image'), None,
+ _("Export your map as an image"), self.export_cb),
+ ('ExportMap', gtk.STOCK_SAVE_AS, _('Export
Map...'), '<control>S',
+ _("Export your map as XML"), self.export_map_cb),
+ ('Close', gtk.STOCK_CLOSE, None, '<control>W',
+ _('Close the current window'), self.close_window_cb),
+ ('EditMenu', None, _('_Edit')),
+ ('ViewMenu', None, _('_View')),
+ ('ShowToolbars', None, _('_Toolbar')),
+ ('Undo', gtk.STOCK_UNDO, None, '<control>Z', None),
+ ('Redo', gtk.STOCK_REDO, None, '<control><shift>Z', None),
+ ('Cut', gtk.STOCK_CUT, None, '<control>X',
+ None, self.cut_text_cb),
+ ('Copy', gtk.STOCK_COPY, None, '<control>C',
+ None, self.copy_text_cb),
+ ('Paste', gtk.STOCK_PASTE, None, '<control>V',
+ None, self.paste_text_cb),
+ ('LinkThoughts', None, _("Link Thoughts"), '<control>L',
+ _("Link the selected thoughts"), self.link_thoughts_cb),
+ ('ModeMenu', None, _('_Mode')),
+ ('DeleteNodes', gtk.STOCK_DELETE, _('_Delete'), 'Delete',
+ _('Delete the selected element(s)'), self.delete_cb),
+ ('ZoomIn', gtk.STOCK_ZOOM_IN, None, '<control>plus',
+ None, self.zoomin_cb),
+ ('ZoomOut', gtk.STOCK_ZOOM_OUT, None, '<control>minus',
+ None, self.zoomout_cb)]
+ self.radio_actions = [
+ ('Edit', gtk.STOCK_EDIT, _('_Edit Mode'), '<control>E',
+ _('Turn on edit mode'), MMapArea.MODE_EDITING),
***The diff for this file has been truncated for email.***
=======================================
--- /trunk/src/MapList.py Thu Apr 3 05:35:02 2008
+++ /trunk/src/MapList.py Sat Apr 23 07:28:34 2011
@@ -10,7 +10,7 @@
#
# Labyrinth 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
+# 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
@@ -28,188 +28,188 @@
import datetime
class MapList(object):
- COL_ID = 0
- COL_TITLE = 1
- COL_FNAME = 2
- COL_OPEN = 3
- """Holds the list of maps. has a couple of convinience functions. Sings
irish folk
-
- this is (regarding to MCV) a model class. """
- class MapCore(object):
- __slots__ = "__dict__ filename title nodes window index".split(" ")
- def __init__(self, index):
- self.__dict__["filename"] = None
- self.__dict__["title"] = None
- self.__dict__["modtime"] = None
- self.__dict__["nodes"] = []
- self.__dict__["window"] = None
- self.__dict__["index"] = index
-
- def _read_from_file(self, filename):
- doc = dom.parse (filename)
- top_element = doc.documentElement
- self.filename = filename
- self.title = top_element.getAttribute ("title")
- self.window = None
-
- def __getattr__(self, key):
- dict = self.__dict__
- if key in dict:
- return dict[key]
- else:
- raise ValueError("Class MapCore does not have an attribute named %s" %
key)
-
- def __setattr__(self, key, value):
- dict = self.__dict__
- if key in dict:
- old_value=dict[key]
- dict[key]=value
- else:
- raise ValueError("Class MapCore does not have an attribute named %s" %
key)
- if "dont_listen" in dict: return
- listener = "_%s_changed" % key
- class_dict = self.__class__.__dict__
- if listener in class_dict and callable(class_dict[listener]):
- class_dict[listener](self, value, old_value)
-
- # these listeners get called after the attribute has been changed already
-
- def _filename_changed(self, value, old_value):
- if not old_value is None:
- del MapList._maps_by_filename[old_value]
- if not value is None:
- MapList._maps_by_filename[value] = self.index
-
- def _title_changed(self, value, old_value):
- MapList._at_col_set_value(self.index, MapList.COL_TITLE, value)
-
- def __str__(self):
- return "<MapCore title='%s' window='%s'>" % (self.title, self.window
and "yes" or "no")
-
- def __repr__(self):
- return self.__str__()
-
- _maps = []
- _maps_by_filename = {}
- tree_view_model = gtk.ListStore(int, str, str, str, 'gboolean')
-
- def __init__(self):
- raise Exception("This class is a singleton full of classmethods, dont
instantiate it.")
-
- @classmethod
- def load_all_from_dir(cls,dir):
- for f in os.listdir(dir):
- if not os.path.isdir(dir+f):
- cls.new_from_file(dir+f)
-
- @classmethod
- def new_from_file(cls, filename):
- index = len(cls._maps)
- map = cls.MapCore(index = index)
- cls._maps.append(map)
- map.modtime =
datetime.datetime.fromtimestamp(os.stat(filename)[8]).strftime("%x %X")
- cls.tree_view_model.append([map.index, map.title, map.modtime,
map.filename, False])
- map._read_from_file(filename)
- return map
-
- @classmethod
- def create_empty_map(cls):
- index = cls.next_col_id ()
- map = cls.MapCore(index = index)
- map.modtime = datetime.datetime.now().strftime("%x %X")
- cls._maps.append(map)
- cls.tree_view_model.append([map.index, map.title, map.modtime,
map.filename, False])
- return map
-
- @classmethod
- def __str__(cls):
- return "<MapList>\n\t%s\n</MapList>" % "\n\t".join([ map.__str__() for
map in cls._maps])
-
- @classmethod
- def delete(cls, map):
- index = cls._maps.index(map)
- del cls._maps[ index ]
- if map.filename:
- del cls._maps_by_filename[map.filename]
- os.unlink(map.filename)
- iter = cls.get_iter_by_col_id(map.index)
- if iter:
- cls.tree_view_model.remove(iter)
-
- @classmethod
- def index(cls, map):
- cls._maps.index(map)
-
- # these functions return None or a single MapCore
- @classmethod
- def get_by_index(cls, index):
- for map in cls._maps:
- if map.index == index:
- return map
- return None
-
- @classmethod
- def __getitem__(cls, index):
- return cls._maps[index]
-
- @classmethod
- def get_by_filename(cls, name):
- return cls._maps[cls._maps_by_filename[name]]
-
- @classmethod
- def get_by_window(cls, window):
- for map in cls._maps:
- if map.window == window:
- return map
- return None
-
- #These functions return a (possibly empty) list of MapCores
- @classmethod
- def get_open_windows(cls):
- return [map for map in cls._maps if map.window is not None]
-
- # other functions
- @classmethod
- def count(cls):
- return len(cls._maps)
-
- # these functions wrap the gtk.ListStore that is used as View
- @classmethod
- def get_TreeViewModel(cls):
- return cls.tree_view_model
-
- @classmethod
- def _at_col_set_value(cls, col_id, col, value):
- iter = cls.get_iter_by_col_id (col_id)
- if iter:
- cls.tree_view_model.set_value(iter, col, value)
-
- @classmethod
- def get_iter_by_col_id(cls, col_id):
- found = False
- iter = cls.tree_view_model.get_iter_first ()
- while iter:
- (num,) = cls.tree_view_model.get (iter, MapList.COL_ID)
- if col_id == num:
- found = True
- break
- iter = cls.tree_view_model.iter_next (iter)
-
- if not found:
- iter = None
-
- return iter
-
- @classmethod
- def next_col_id(cls):
- next_col_id = -1
- iter = cls.tree_view_model.get_iter_first ()
- while iter:
- (num,) = cls.tree_view_model.get (iter, MapList.COL_ID)
- if next_col_id < num:
- next_col_id = num
- iter = cls.tree_view_model.iter_next (iter)
-
- return next_col_id + 1
+ COL_ID = 0
+ COL_TITLE = 1
+ COL_FNAME = 2
+ COL_OPEN = 3
+ """Holds the list of maps. has a couple of convinience functions.
Sings irish folk
+
+ this is (regarding to MCV) a model class. """
+ class MapCore(object):
+ __slots__ = "__dict__ filename title nodes window index".split(" ")
+ def __init__(self, index):
+ self.__dict__["filename"] = None
+ self.__dict__["title"] = None
+ self.__dict__["modtime"] = None
+ self.__dict__["nodes"] = []
+ self.__dict__["window"] = None
+ self.__dict__["index"] = index
+
+ def _read_from_file(self, filename):
+ doc = dom.parse (filename)
+ top_element = doc.documentElement
+ self.filename = filename
+ self.title = top_element.getAttribute ("title")
+ self.window = None
+
+ def __getattr__(self, key):
+ dict = self.__dict__
+ if key in dict:
+ return dict[key]
+ else:
+ raise ValueError("Class MapCore does not have an attribute
named %s" % key)
+
+ def __setattr__(self, key, value):
+ dict = self.__dict__
+ if key in dict:
+ old_value=dict[key]
+ dict[key]=value
+ else:
+ raise ValueError("Class MapCore does not have an attribute
named %s" % key)
+ if "dont_listen" in dict: return
+ listener = "_%s_changed" % key
+ class_dict = self.__class__.__dict__
+ if listener in class_dict and callable(class_dict[listener]):
+ class_dict[listener](self, value, old_value)
+
+ # these listeners get called after the attribute has been changed
already
+
+ def _filename_changed(self, value, old_value):
+ if not old_value is None:
+ del MapList._maps_by_filename[old_value]
+ if not value is None:
+ MapList._maps_by_filename[value] = self.index
+
+ def _title_changed(self, value, old_value):
+ MapList._at_col_set_value(self.index, MapList.COL_TITLE, value)
+
+ def __str__(self):
+ return "<MapCore title='%s' window='%s'>" % (self.title,
self.window and "yes" or "no")
+
+ def __repr__(self):
+ return self.__str__()
+
+ _maps = []
+ _maps_by_filename = {}
+ tree_view_model = gtk.ListStore(int, str, str, str, 'gboolean')
+
+ def __init__(self):
+ raise Exception("This class is a singleton full of classmethods,
dont instantiate it.")
+
+ @classmethod
+ def load_all_from_dir(cls,dir):
+ for f in os.listdir(dir):
+ if not os.path.isdir(dir+f):
+ cls.new_from_file(dir+f)
+
+ @classmethod
+ def new_from_file(cls, filename):
+ index = len(cls._maps)
+ map = cls.MapCore(index = index)
+ cls._maps.append(map)
+ map.modtime =
datetime.datetime.fromtimestamp(os.stat(filename)[8]).strftime("%x %X")
+ cls.tree_view_model.append([map.index, map.title, map.modtime,
map.filename, False])
+ map._read_from_file(filename)
+ return map
+
+ @classmethod
+ def create_empty_map(cls):
+ index = cls.next_col_id ()
+ map = cls.MapCore(index = index)
+ map.modtime = datetime.datetime.now().strftime("%x %X")
+ cls._maps.append(map)
+ cls.tree_view_model.append([map.index, map.title, map.modtime,
map.filename, False])
+ return map
+
+ @classmethod
+ def __str__(cls):
+ return "<MapList>\n\t%s\n</MapList>" % "\n\t".join([ map.__str__()
for map in cls._maps])
+
+ @classmethod
+ def delete(cls, map):
+ index = cls._maps.index(map)
+ del cls._maps[ index ]
+ if map.filename:
+ del cls._maps_by_filename[map.filename]
+ os.unlink(map.filename)
+ iter = cls.get_iter_by_col_id(map.index)
+ if iter:
+ cls.tree_view_model.remove(iter)
+
+ @classmethod
+ def index(cls, map):
+ cls._maps.index(map)
+
+ # these functions return None or a single MapCore
+ @classmethod
+ def get_by_index(cls, index):
+ for map in cls._maps:
+ if map.index == index:
+ return map
+ return None
+
+ @classmethod
+ def __getitem__(cls, index):
+ return cls._maps[index]
+
+ @classmethod
+ def get_by_filename(cls, name):
+ return cls._maps[cls._maps_by_filename[name]]
+
+ @classmethod
+ def get_by_window(cls, window):
+ for map in cls._maps:
+ if map.window == window:
+ return map
+ return None
+
+ #These functions return a (possibly empty) list of MapCores
+ @classmethod
+ def get_open_windows(cls):
+ return [map for map in cls._maps if map.window is not None]
+
+ # other functions
+ @classmethod
+ def count(cls):
+ return len(cls._maps)
+
+ # these functions wrap the gtk.ListStore that is used as View
+ @classmethod
+ def get_TreeViewModel(cls):
+ return cls.tree_view_model
+
+ @classmethod
+ def _at_col_set_value(cls, col_id, col, value):
+ iter = cls.get_iter_by_col_id (col_id)
+ if iter:
+ cls.tree_view_model.set_value(iter, col, value)
+
+ @classmethod
+ def get_iter_by_col_id(cls, col_id):
+ found = False
+ iter = cls.tree_view_model.get_iter_first ()
+ while iter:
+ (num,) = cls.tree_view_model.get (iter, MapList.COL_ID)
+ if col_id == num:
+ found = True
+ break
+ iter = cls.tree_view_model.iter_next (iter)
+
+ if not found:
+ iter = None
+
+ return iter
+
+ @classmethod
+ def next_col_id(cls):
+ next_col_id = -1
+ iter = cls.tree_view_model.get_iter_first ()
+ while iter:
+ (num,) = cls.tree_view_model.get (iter, MapList.COL_ID)
+ if next_col_id < num:
+ next_col_id = num
+ iter = cls.tree_view_model.iter_next (iter)
+
+ return next_col_id + 1
MapList.load_all_from_dir(utils.get_save_dir ())
=======================================
--- /trunk/src/PeriodicSaveThread.py Sun Mar 23 06:55:40 2008
+++ /trunk/src/PeriodicSaveThread.py Sat Apr 23 07:28:34 2011
@@ -24,14 +24,13 @@
class PeriodicSaveThread(threading.Thread):
- def __init__(self, main_area):
- threading.Thread.__init__(self)
- self.main_area = main_area
- self.cancel = False
-
- def run (self):
- time.sleep (60)
- while not self.cancel:
- self.main_area.save_thyself ()
- time.sleep (60)
-
+ def __init__(self, main_area):
+ threading.Thread.__init__(self)
+ self.main_area = main_area
+ self.cancel = False
+
+ def run (self):
+ time.sleep (60)
+ while not self.cancel:
+ self.main_area.save_thyself ()
+ time.sleep (60)
=======================================
--- /trunk/src/ResourceThought.py Thu May 15 06:34:04 2008
+++ /trunk/src/ResourceThought.py Sat Apr 23 07:28:34 2011
@@ -31,112 +31,112 @@
_ = gettext.gettext
class ResourceThought (TextThought.TextThought):
- def __init__ (self, coords, pango_context, thought_number, save, undo,
loading, background_color, foreground_color):
- super (ResourceThought, self).__init__(coords, pango_context,
thought_number, save, undo, loading, background_color,
foreground_color, "res_thought")
-
- self.uri = ""
-
- # TODO: we should handle such things with a singleton
- self.glade = gtk.glade.XML(utils.get_data_file_name('labyrinth.glade'))
- self.dialog = self.glade.get_widget('ResourceChooserDialog')
- self.dialog.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OK, gtk.RESPONSE_OK)
-
- if not loading:
- self.process_uri_dialog()
-
- self.all_okay = True
-
- def process_uri_dialog(self, initial=True):
- res = self.dialog.run()
- self.dialog.hide()
-
- if res == gtk.RESPONSE_OK:
- # FIXME: validate input
- self.uri = self.glade.get_widget('urlEntry').get_text()
- if initial:
- self.add_text(self.uri)
- self.rebuild_byte_table()
-
- def process_button_down (self, event, mode, transformed):
- modifiers = gtk.accelerator_get_default_mod_mask ()
- if event.type == gtk.gdk.BUTTON_PRESS and not self.editing:
- self.emit ("select_thought", event.state & modifiers)
- if event.button == 1 and mode == BaseThought.MODE_EDITING and event.type
== gtk.gdk._2BUTTON_PRESS:
- if self.uri.find("http://") == -1:
- webbrowser.open("http://" + self.uri)
- else:
- webbrowser.open(self.uri)
- elif event.button == 3:
- self.emit ("popup_requested", event, 1)
-
- def update_save (self):
- super(ResourceThought, self).update_save()
- self.element.setAttribute ("uri", self.uri)
-
- def load (self, node):
- super(ResourceThought, self).load(node)
- self.uri = node.getAttribute ("uri")
- self.glade.get_widget('urlEntry').set_text(self.uri)
-
- def draw (self, context):
- if not self.layout:
- self.recalc_edges ()
- if not self.editing:
- if not self.ul or not self.lr:
- print "Warning: Trying to draw unfinished box "+str(self.identity)+".
Aborting."
- return
- utils.draw_thought_extended (context, self.ul, self.lr, \
- self.am_selected, self.am_primary, self.background_color, False, True)
- else:
- ux, uy = self.ul
- if prefs.get_direction() == gtk.TEXT_DIR_LTR:
- context.move_to (ux, uy+5)
- context.line_to (ux, uy)
- context.line_to (ux+5, uy)
- else:
- lx = self.lr[0]
- context.move_to (lx, uy+5)
- context.line_to (lx, uy)
- context.line_to (lx-5, uy)
- context.stroke ()
-
- (textx, texty) = (self.text_location[0], self.text_location[1])
- r, g, b = utils.gtk_to_cairo_color(self.foreground_color)
- context.set_source_rgb (r, g, b)
- context.move_to (textx, texty)
- context.show_layout (self.layout)
- if self.editing:
- if self.preedit:
- (strong, weak) = self.layout.get_cursor_pos (self.index +
self.preedit[2])
- else:
- (strong, weak) = self.layout.get_cursor_pos (self.index)
- (startx, starty, curx,cury) = strong
- startx /= pango.SCALE
- starty /= pango.SCALE
- curx /= pango.SCALE
- cury /= pango.SCALE
- context.move_to (textx + startx, texty + starty)
- context.line_to (textx + startx, texty + starty + cury)
- context.stroke ()
- context.set_source_rgb (0,0,0)
- context.stroke ()
-
- def get_popup_menu_items(self):
- image = gtk.Image()
- image.set_from_stock(gtk.STOCK_EDIT, gtk.ICON_SIZE_MENU)
- edit_item = gtk.ImageMenuItem(_('Edit Text'))
- edit_item.set_image(image)
- edit_item.connect('activate', self.edit_cb)
- image = gtk.Image()
- image.set_from_stock(gtk.STOCK_NETWORK, gtk.ICON_SIZE_MENU)
- uri_item = gtk.ImageMenuItem(_('Edit URI'))
- uri_item.set_image(image)
- uri_item.connect('activate', self.edit_uri_cb)
- return [edit_item, uri_item]
-
- def edit_cb(self, widget):
- self.emit ("begin_editing")
-
- def edit_uri_cb(self, widget):
- self.process_uri_dialog(False)
+ def __init__ (self, coords, pango_context, thought_number, save, undo,
loading, background_color, foreground_color):
+ super (ResourceThought, self).__init__(coords, pango_context,
thought_number, save, undo, loading, background_color,
foreground_color, "res_thought")
+
+ self.uri = ""
+
+ # TODO: we should handle such things with a singleton
+ self.glade =
gtk.glade.XML(utils.get_data_file_name('labyrinth.glade'))
+ self.dialog = self.glade.get_widget('ResourceChooserDialog')
+ self.dialog.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
+ gtk.STOCK_OK, gtk.RESPONSE_OK)
+
+ if not loading:
+ self.process_uri_dialog()
+
+ self.all_okay = True
+
+ def process_uri_dialog(self, initial=True):
+ res = self.dialog.run()
+ self.dialog.hide()
+
+ if res == gtk.RESPONSE_OK:
+ # FIXME: validate input
+ self.uri = self.glade.get_widget('urlEntry').get_text()
+ if initial:
+ self.add_text(self.uri)
+ self.rebuild_byte_table()
+
+ def process_button_down (self, event, mode, transformed):
+ modifiers = gtk.accelerator_get_default_mod_mask ()
+ if event.type == gtk.gdk.BUTTON_PRESS and not self.editing:
+ self.emit ("select_thought", event.state & modifiers)
+ if event.button == 1 and mode == BaseThought.MODE_EDITING and
event.type == gtk.gdk._2BUTTON_PRESS:
+ if self.uri.find("http://") == -1:
+ webbrowser.open("http://" + self.uri)
+ else:
+ webbrowser.open(self.uri)
+ elif event.button == 3:
+ self.emit ("popup_requested", event, 1)
+
+ def update_save (self):
+ super(ResourceThought, self).update_save()
+ self.element.setAttribute ("uri", self.uri)
+
+ def load (self, node):
+ super(ResourceThought, self).load(node)
+ self.uri = node.getAttribute ("uri")
+ self.glade.get_widget('urlEntry').set_text(self.uri)
+
+ def draw (self, context):
+ if not self.layout:
+ self.recalc_edges ()
+ if not self.editing:
+ if not self.ul or not self.lr:
+ print "Warning: Trying to draw unfinished
box "+str(self.identity)+". Aborting."
+ return
+ utils.draw_thought_extended (context, self.ul, self.lr, \
+ self.am_selected, self.am_primary,
self.background_color, False, True)
+ else:
+ ux, uy = self.ul
+ if prefs.get_direction() == gtk.TEXT_DIR_LTR:
+ context.move_to (ux, uy+5)
+ context.line_to (ux, uy)
+ context.line_to (ux+5, uy)
+ else:
+ lx = self.lr[0]
+ context.move_to (lx, uy+5)
+ context.line_to (lx, uy)
+ context.line_to (lx-5, uy)
+ context.stroke ()
+
+ (textx, texty) = (self.text_location[0], self.text_location[1])
+ r, g, b = utils.gtk_to_cairo_color(self.foreground_color)
+ context.set_source_rgb (r, g, b)
+ context.move_to (textx, texty)
+ context.show_layout (self.layout)
+ if self.editing:
+ if self.preedit:
+ (strong, weak) = self.layout.get_cursor_pos (self.index +
self.preedit[2])
+ else:
+ (strong, weak) = self.layout.get_cursor_pos (self.index)
+ (startx, starty, curx,cury) = strong
+ startx /= pango.SCALE
+ starty /= pango.SCALE
+ curx /= pango.SCALE
+ cury /= pango.SCALE
+ context.move_to (textx + startx, texty + starty)
+ context.line_to (textx + startx, texty + starty + cury)
+ context.stroke ()
+ context.set_source_rgb (0,0,0)
+ context.stroke ()
+
+ def get_popup_menu_items(self):
+ image = gtk.Image()
+ image.set_from_stock(gtk.STOCK_EDIT, gtk.ICON_SIZE_MENU)
+ edit_item = gtk.ImageMenuItem(_('Edit Text'))
+ edit_item.set_image(image)
+ edit_item.connect('activate', self.edit_cb)
+ image = gtk.Image()
+ image.set_from_stock(gtk.STOCK_NETWORK, gtk.ICON_SIZE_MENU)
+ uri_item = gtk.ImageMenuItem(_('Edit URI'))
+ uri_item.set_image(image)
+ uri_item.connect('activate', self.edit_uri_cb)
+ return [edit_item, uri_item]
+
+ def edit_cb(self, widget):
+ self.emit ("begin_editing")
+
+ def edit_uri_cb(self, widget):
+ self.process_uri_dialog(False)
=======================================
--- /trunk/src/TextBufferMarkup.py Fri Apr 11 09:31:48 2008
+++ /trunk/src/TextBufferMarkup.py Sat Apr 23 07:28:34 2011
@@ -15,7 +15,7 @@
#
# You should have received a copy of the GNU General Public License
# along with labyrinth; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301 USA
#
@@ -27,282 +27,280 @@
ADD_ATTR = 42
REMOVE_ATTR = 43
-class ExtendedBuffer(gtk.TextBuffer):
- __gsignals__ = dict (set_focus = (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ()),
- set_attrs = (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN,
gobject.TYPE_BOOLEAN, pango.FontDescription)))
-
- def __init__(self, undo_manager, save, save_doc):
- super (gtk.TextBuffer, self).__init__()
- self.undo = undo_manager
- self.connect('insert-text', self.insert_text_cb)
- self.connect_after('insert-text', self.apply_attrs_cb)
- self.connect('delete-range', self.delete_range_cb)
- self.text_elem = save_doc.createTextNode ("Extended")
- self.save = save_doc
- self.element = save
- self.element.appendChild(self.text_elem)
- self.bold_tag = self.create_tag("bold", weight=pango.WEIGHT_BOLD)
- self.italics_tag = self.create_tag("italics", style=pango.STYLE_ITALIC)
- self.underline_tag = self.create_tag("underline",
underline=pango.UNDERLINE_SINGLE)
- self.current_tags = []
- self.requested_tags = []
- self.connect_after('mark-set',self.mark_set_cb)
- self.bold_block = False
- self.italic_block = False
-
- def undo_action (self, action, mode):
- self.undo.block ()
- self.emit ("set_focus")
- if action.undo_type == UndoManager.DELETE_LETTER or action.undo_type ==
UndoManager.DELETE_WORD:
- real_mode = not mode
- else:
- real_mode = mode
- if real_mode == UndoManager.UNDO:
- self.delete (self.get_iter_at_offset(action.args[0]),
- self.get_iter_at_offset (action.args[0]+action.args[2]))
- else:
- self.insert (self.get_iter_at_offset(action.args[0]), action.args[1])
- self.undo.unblock ()
- bold = italics = underline = False
- for x in self.current_tags:
- if x == "bold":
- bold = True
- elif x == "italic":
- italics = True
- elif x == "underline":
- underline = True
- self.emit("set_attrs_bla", bold, italics, underline, None)
-
- def delete_range_cb (self, buffer, iter, it1):
- text = self.get_text (iter, it1)
- self.undo.add_undo (UndoManager.UndoAction (self,
UndoManager.DELETE_LETTER, self.undo_action,
- iter.get_offset(), text, len (text), -1, None, None))
- return False
-
- def insert_text_cb (self, buffer, iter, text, length):
- self.undo.add_undo (UndoManager.UndoAction (self,
UndoManager.INSERT_LETTER, self.undo_action,
- iter.get_offset(), text, length, None, None))
-
- return False
-
- def apply_attrs_cb (self, buffer, iter, text, length):
- prev_iter = iter.copy()
- if not prev_iter.backward_chars(length):
- print "Errored"
- for x in self.current_tags:
- self.apply_tag_by_name(x, prev_iter, iter)
- return False
-
- def mark_set_cb(self, buffer, iter, mark, *params):
- italics = underline = bold = False
- if iter.has_tag(self.bold_tag):
- bold = True
- elif self.current_tags.count("bold") > 0:
- self.current_tags.remove("bold")
- if iter.has_tag(self.italics_tag):
- italics = True
- elif self.current_tags.count("italics") > 0:
- self.current_tags.remove("italics")
- if iter.has_tag(self.underline_tag):
- underline = True
- elif self.current_tags.count("underline") > 0:
- self.current_tags.remove("underline")
- for x in self.requested_tags:
- if x == "bold":
- bold = True
- if x == "italics":
- italics = True
- if x == "underline":
- underline = True
- if self.current_tags.count(x) == 0:
- self.current_tags.append(x)
-
- self.emit("set_attrs", bold, italics, underline, None)
- return False
-
- def update_save (self):
- next = self.element.firstChild
- while next:
- m = next.nextSibling
- if next.nodeName == "attribute":
- self.element.removeChild (next)
- next.unlink ()
- next = m
-
- self.text_elem.replaceWholeText (self.get_text())
- mark = self.get_insert()
- it = self.get_iter_at_mark(mark)
- self.element.setAttribute("mark", str(it.get_offset()))
- iter = self.get_start_iter()
- cur = 0
- tags = {}
- doc = self.element.ownerDocument
- tag_table = self.get_tag_table()
- while(1):
- if iter.begins_tag(tag_table.lookup("bold")):
- tags["bold"] = cur
- if iter.ends_tag(tag_table.lookup("bold")):
- elem = doc.createElement ("attribute")
- self.element.appendChild (elem)
- start = tags.pop("bold")
- elem.setAttribute("start", str(start))
- elem.setAttribute("end", str(cur))
- elem.setAttribute("type", "bold")
- if iter.begins_tag(tag_table.lookup("italics")):
- tags["italics"] = cur
- if iter.ends_tag(tag_table.lookup("italics")):
- elem = doc.createElement ("attribute")
- self.element.appendChild (elem)
- start = tags.pop("italics")
- elem.setAttribute("start", str(start))
- elem.setAttribute("end", str(cur))
- elem.setAttribute("type", "italics")
- if iter.begins_tag(tag_table.lookup("underline")):
- tags["underline"] = cur
- if iter.ends_tag(tag_table.lookup("underline")):
- elem = doc.createElement ("attribute")
- self.element.appendChild (elem)
- start = tags.pop("underline")
- elem.setAttribute("start", str(start))
- elem.setAttribute("end", str(cur))
- elem.setAttribute("type", "underline")
- cur+=1
- if not iter.forward_char():
- break
- for x in tags:
- elem = doc.createElement ("attribute")
- self.element.appendChild (elem)
- elem.setAttribute("start", str(tags[x]))
- elem.setAttribute("end", str(-1))
- elem.setAttribute("type", x)
-
- def load(self, node):
- mark = None
- if node.hasAttribute("mark"):
- mark = int(node.getAttribute("mark"))
- for n in node.childNodes:
- if n.nodeType == n.TEXT_NODE:
- if n.data != "LABYRINTH_AUTOGEN_TEXT_REMOVE":
- self.set_text(n.data)
- elif n.nodeName == "attribute":
- attrType = n.getAttribute("type")
- start = int(n.getAttribute("start"))
- end = int(n.getAttribute("end"))
- start_it = self.get_iter_at_offset(start)
- if end >= 0:
- end_it = self.get_iter_at_offset(end)
- else:
- end_it = self.get_end_iter()
-
- self.apply_tag_by_name(attrType, start_it, end_it)
- else:
- print "Error: Unknown type: %s. Ignoring." % n.nodeName
- if mark:
- ins_iter = self.get_iter_at_offset(mark)
- self.move_mark_by_name("insert", ins_iter)
- self.move_mark_by_name("selection_bound", ins_iter)
-
- def get_text (self, start=None, end=None, include_hidden_chars=True):
- if not start: start=self.get_start_iter()
- if not end: end=self.get_end_iter()
- return gtk.TextBuffer.get_text(self,start,end)
-
- def undo_attr (self, action, mode):
- if mode == UndoManager.UNDO:
- if action.undo_type == ADD_ATTR and len(action.args[1]) > 0:
- self.remove_tag_by_name(action.args[0], action.args[1][0],
- action.args[1][1])
- elif action.undo_type == ADD_ATTR and len(action.args[1]) == 0:
- self.current_tags.remove(action.args[0])
- self.requested_tags.remove(action.args[0])
- elif action.undo_type == REMOVE_ATTR and len(action.args[1]) > 0:
- self.apply_tag_by_name(action.args[0], action.args[1][0],
- action.args[1][1])
- else:
- self.current_tags.append(action.args[0])
- self.requested_tags.append(action.args[0])
- else:
- if action.undo_type == ADD_ATTR and len(action.args[1]) > 0:
- self.apply_tag_by_name(action.args[0], action.args[1][0],
- action.args[1][1])
- elif action.undo_type == ADD_ATTR and len(action.args[1]) == 0:
- self.current_tags.append(action.args[0])
- self.requested_tags.append(action.args[0])
- elif action.undo_type == REMOVE_ATTR and len(action.args[1]) > 0:
- self.remove_tag_by_name(action.args[0], action.args[1][0],
- action.args[1][1])
- else:
- self.current_tags.remove(action.args[0])
- self.requested_tags.remove(action.args[0])
- bold = italics = underline = False
- for x in self.current_tags:
- if x == "bold":
- bold = True
- elif x == "italics":
- italics = True
- elif x == "underline":
- underline = True
- self.emit("set_attrs", bold, italics, underline)
-
- def set_bold (self, bold):
- selection = self.get_selection_bounds()
- if bold:
- if len(selection) > 0:
- self.apply_tag_by_name("bold", selection[0], selection[1])
- else:
- self.current_tags.append("bold")
- self.requested_tags.append("bold")
- self.undo.add_undo(UndoManager.UndoAction(self, ADD_ATTR,
self.undo_attr,
- "bold", selection))
- else:
- if len(selection) > 0:
- self.remove_tag_by_name("bold", selection[0], selection[1])
- else:
- self.current_tags.remove("bold")
- self.requested_tags.remove("bold")
- self.undo.add_undo(UndoManager.UndoAction(self, REMOVE_ATTR,
self.undo_attr,
- "bold", selection))
-
- def set_italics (self, italics):
- selection = self.get_selection_bounds()
- if italics:
- if len(selection) > 0:
- self.apply_tag_by_name("italics", selection[0], selection[1])
- else:
- self.current_tags.append("italics")
- self.requested_tags.append("italics")
- self.undo.add_undo(UndoManager.UndoAction(self, ADD_ATTR,
self.undo_attr,
- "italics", selection))
- else:
- if len(selection) > 0:
- self.remove_tag_by_name("italics", selection[0], selection[1])
- else:
- self.current_tags.remove("italics")
- self.requested_tags.remove("italics")
- self.undo.add_undo(UndoManager.UndoAction(self, REMOVE_ATTR,
self.undo_attr,
- "italics", selection))
-
- def set_underline (self, underline):
- selection = self.get_selection_bounds()
- if underline:
- if len(selection) > 0:
- self.apply_tag_by_name("underline", selection[0], selection[1])
- else:
- self.current_tags.append("underline")
- self.requested_tags.append("underline")
- self.undo.add_undo(UndoManager.UndoAction(self, ADD_ATTR,
self.undo_attr,
- "underline", selection))
- else:
- if len(selection) > 0:
- self.remove_tag_by_name("underline", selection[0], selection[1])
- else:
- self.current_tags.remove("underline")
- self.requested_tags.remove("underline")
- self.undo.add_undo(UndoManager.UndoAction(self, REMOVE_ATTR,
self.undo_attr,
- "underline", selection))
-
-
+class ExtendedBuffer(gtk.TextBuffer):
+ __gsignals__ = dict (set_focus = (gobject.SIGNAL_RUN_FIRST,
+
gobject.TYPE_NONE,
+
()),
+ set_attrs =
(gobject.SIGNAL_RUN_LAST,
+
gobject.TYPE_NONE,
+
(gobject.TYPE_BOOLEAN,
gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN,
pango.FontDescription)))
+
+ def __init__(self, undo_manager, save, save_doc):
+ super (gtk.TextBuffer, self).__init__()
+ self.undo = undo_manager
+ self.connect('insert-text', self.insert_text_cb)
+ self.connect_after('insert-text', self.apply_attrs_cb)
+ self.connect('delete-range', self.delete_range_cb)
+ self.text_elem = save_doc.createTextNode ("Extended")
+ self.save = save_doc
+ self.element = save
+ self.element.appendChild(self.text_elem)
+ self.bold_tag = self.create_tag("bold", weight=pango.WEIGHT_BOLD)
+ self.italics_tag = self.create_tag("italics",
style=pango.STYLE_ITALIC)
+ self.underline_tag = self.create_tag("underline",
underline=pango.UNDERLINE_SINGLE)
+ self.current_tags = []
+ self.requested_tags = []
+ self.connect_after('mark-set',self.mark_set_cb)
+ self.bold_block = False
+ self.italic_block = False
+
+ def undo_action (self, action, mode):
+ self.undo.block ()
+ self.emit ("set_focus")
+ if action.undo_type == UndoManager.DELETE_LETTER or
action.undo_type == UndoManager.DELETE_WORD:
+ real_mode = not mode
+ else:
+ real_mode = mode
+ if real_mode == UndoManager.UNDO:
+ self.delete (self.get_iter_at_offset(action.args[0]),
+ self.get_iter_at_offset
(action.args[0]+action.args[2]))
+ else:
+ self.insert (self.get_iter_at_offset(action.args[0]),
action.args[1])
+ self.undo.unblock ()
+ bold = italics = underline = False
+ for x in self.current_tags:
+ if x == "bold":
+ bold = True
+ elif x == "italic":
+ italics = True
+ elif x == "underline":
+ underline = True
+ self.emit("set_attrs_bla", bold, italics, underline, None)
+
+ def delete_range_cb (self, buffer, iter, it1):
+ text = self.get_text (iter, it1)
+ self.undo.add_undo (UndoManager.UndoAction (self,
UndoManager.DELETE_LETTER, self.undo_action,
+
iter.get_offset(),
text, len (text), -1, None, None))
+ return False
+
+ def insert_text_cb (self, buffer, iter, text, length):
+ self.undo.add_undo (UndoManager.UndoAction (self,
UndoManager.INSERT_LETTER, self.undo_action,
+
iter.get_offset(),
text, length, None, None))
+
+ return False
+
+ def apply_attrs_cb (self, buffer, iter, text, length):
+ prev_iter = iter.copy()
+ if not prev_iter.backward_chars(length):
+ print "Errored"
+ for x in self.current_tags:
+ self.apply_tag_by_name(x, prev_iter, iter)
+ return False
+
+ def mark_set_cb(self, buffer, iter, mark, *params):
+ italics = underline = bold = False
+ if iter.has_tag(self.bold_tag):
+ bold = True
+ elif self.current_tags.count("bold") > 0:
+ self.current_tags.remove("bold")
+ if iter.has_tag(self.italics_tag):
+ italics = True
+ elif self.current_tags.count("italics") > 0:
+ self.current_tags.remove("italics")
+ if iter.has_tag(self.underline_tag):
+ underline = True
+ elif self.current_tags.count("underline") > 0:
+ self.current_tags.remove("underline")
+ for x in self.requested_tags:
+ if x == "bold":
+ bold = True
+ if x == "italics":
+ italics = True
+ if x == "underline":
+ underline = True
+ if self.current_tags.count(x) == 0:
+ self.current_tags.append(x)
+
+ self.emit("set_attrs", bold, italics, underline, None)
+ return False
+
+ def update_save (self):
+ next = self.element.firstChild
+ while next:
+ m = next.nextSibling
+ if next.nodeName == "attribute":
+ self.element.removeChild (next)
+ next.unlink ()
+ next = m
+
+ self.text_elem.replaceWholeText (self.get_text())
+ mark = self.get_insert()
+ it = self.get_iter_at_mark(mark)
+ self.element.setAttribute("mark", str(it.get_offset()))
+ iter = self.get_start_iter()
+ cur = 0
+ tags = {}
+ doc = self.element.ownerDocument
+ tag_table = self.get_tag_table()
+ while(1):
+ if iter.begins_tag(tag_table.lookup("bold")):
+ tags["bold"] = cur
+ if iter.ends_tag(tag_table.lookup("bold")):
+ elem = doc.createElement ("attribute")
+ self.element.appendChild (elem)
+ start = tags.pop("bold")
+ elem.setAttribute("start", str(start))
+ elem.setAttribute("end", str(cur))
+ elem.setAttribute("type", "bold")
+ if iter.begins_tag(tag_table.lookup("italics")):
+ tags["italics"] = cur
+ if iter.ends_tag(tag_table.lookup("italics")):
+ elem = doc.createElement ("attribute")
+ self.element.appendChild (elem)
+ start = tags.pop("italics")
+ elem.setAttribute("start", str(start))
+ elem.setAttribute("end", str(cur))
+ elem.setAttribute("type", "italics")
+ if iter.begins_tag(tag_table.lookup("underline")):
+ tags["underline"] = cur
+ if iter.ends_tag(tag_table.lookup("underline")):
+ elem = doc.createElement ("attribute")
+ self.element.appendChild (elem)
+ start = tags.pop("underline")
+ elem.setAttribute("start", str(start))
+ elem.setAttribute("end", str(cur))
+ elem.setAttribute("type", "underline")
+ cur+=1
+ if not iter.forward_char():
+ break
+ for x in tags:
+ elem = doc.createElement ("attribute")
+ self.element.appendChild (elem)
+ elem.setAttribute("start", str(tags[x]))
+ elem.setAttribute("end", str(-1))
+ elem.setAttribute("type", x)
+
+ def load(self, node):
+ mark = None
+ if node.hasAttribute("mark"):
+ mark = int(node.getAttribute("mark"))
+ for n in node.childNodes:
+ if n.nodeType == n.TEXT_NODE:
+ if n.data != "LABYRINTH_AUTOGEN_TEXT_REMOVE":
+ self.set_text(n.data)
+ elif n.nodeName == "attribute":
+ attrType = n.getAttribute("type")
+ start = int(n.getAttribute("start"))
+ end = int(n.getAttribute("end"))
+ start_it = self.get_iter_at_offset(start)
+ if end >= 0:
+ end_it = self.get_iter_at_offset(end)
+ else:
+ end_it = self.get_end_iter()
+
+ self.apply_tag_by_name(attrType, start_it, end_it)
+ else:
+ print "Error: Unknown type: %s. Ignoring." % n.nodeName
+ if mark:
+ ins_iter = self.get_iter_at_offset(mark)
+ self.move_mark_by_name("insert", ins_iter)
+ self.move_mark_by_name("selection_bound", ins_iter)
+
+ def get_text (self, start=None, end=None, include_hidden_chars=True):
+ if not start: start=self.get_start_iter()
+ if not end: end=self.get_end_iter()
+ return gtk.TextBuffer.get_text(self,start,end)
+
+ def undo_attr (self, action, mode):
+ if mode == UndoManager.UNDO:
+ if action.undo_type == ADD_ATTR and len(action.args[1]) > 0:
+ self.remove_tag_by_name(action.args[0], action.args[1][0],
+
action.args[1][1])
+ elif action.undo_type == ADD_ATTR and len(action.args[1]) == 0:
+ self.current_tags.remove(action.args[0])
+ self.requested_tags.remove(action.args[0])
+ elif action.undo_type == REMOVE_ATTR and len(action.args[1]) >
0:
+ self.apply_tag_by_name(action.args[0], action.args[1][0],
+
action.args[1][1])
+ else:
+ self.current_tags.append(action.args[0])
+ self.requested_tags.append(action.args[0])
+ else:
+ if action.undo_type == ADD_ATTR and len(action.args[1]) > 0:
+ self.apply_tag_by_name(action.args[0], action.args[1][0],
+
action.args[1][1])
+ elif action.undo_type == ADD_ATTR and len(action.args[1]) == 0:
+ self.current_tags.append(action.args[0])
+ self.requested_tags.append(action.args[0])
+ elif action.undo_type == REMOVE_ATTR and len(action.args[1]) >
0:
+ self.remove_tag_by_name(action.args[0], action.args[1][0],
+
action.args[1][1])
+ else:
+ self.current_tags.remove(action.args[0])
+ self.requested_tags.remove(action.args[0])
+ bold = italics = underline = False
+ for x in self.current_tags:
+ if x == "bold":
+ bold = True
+ elif x == "italics":
+ italics = True
+ elif x == "underline":
+ underline = True
+ self.emit("set_attrs", bold, italics, underline)
+
+ def set_bold (self, bold):
+ selection = self.get_selection_bounds()
+ if bold:
+ if len(selection) > 0:
+ self.apply_tag_by_name("bold", selection[0], selection[1])
+ else:
+ self.current_tags.append("bold")
+ self.requested_tags.append("bold")
+ self.undo.add_undo(UndoManager.UndoAction(self, ADD_ATTR,
self.undo_attr,
+ "bold",
selection))
+ else:
+ if len(selection) > 0:
+ self.remove_tag_by_name("bold", selection[0], selection[1])
+ else:
+ self.current_tags.remove("bold")
+ self.requested_tags.remove("bold")
+ self.undo.add_undo(UndoManager.UndoAction(self, REMOVE_ATTR,
self.undo_attr,
+ "bold",
selection))
+
+ def set_italics (self, italics):
+ selection = self.get_selection_bounds()
+ if italics:
+ if len(selection) > 0:
+ self.apply_tag_by_name("italics", selection[0],
selection[1])
+ else:
+ self.current_tags.append("italics")
+ self.requested_tags.append("italics")
+ self.undo.add_undo(UndoManager.UndoAction(self, ADD_ATTR,
self.undo_attr,
+ "italics",
selection))
+ else:
+ if len(selection) > 0:
+ self.remove_tag_by_name("italics", selection[0],
selection[1])
+ else:
+ self.current_tags.remove("italics")
+ self.requested_tags.remove("italics")
+ self.undo.add_undo(UndoManager.UndoAction(self, REMOVE_ATTR,
self.undo_attr,
+ "italics",
selection))
+
+ def set_underline (self, underline):
+ selection = self.get_selection_bounds()
+ if underline:
+ if len(selection) > 0:
+ self.apply_tag_by_name("underline", selection[0],
selection[1])
+ else:
+ self.current_tags.append("underline")
+ self.requested_tags.append("underline")
+ self.undo.add_undo(UndoManager.UndoAction(self, ADD_ATTR,
self.undo_attr,
+ "underline",
selection))
+ else:
+ if len(selection) > 0:
+ self.remove_tag_by_name("underline", selection[0],
selection[1])
+ else:
+ self.current_tags.remove("underline")
+ self.requested_tags.remove("underline")
+ self.undo.add_undo(UndoManager.UndoAction(self, REMOVE_ATTR,
self.undo_attr,
+ "underline",
selection))
=======================================
--- /trunk/src/TextThought.py Wed Jul 16 10:16:35 2008
+++ /trunk/src/TextThought.py Sat Apr 23 07:28:34 2011
@@ -11,7 +11,7 @@
#
# Labyrinth 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
+# 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
@@ -36,1197 +36,1197 @@
UNDO_REMOVE_ATTR_SELECTION=67
class TextThought (BaseThought.BaseThought):
- def __init__ (self, coords, pango_context, thought_number, save, undo,
loading, background_color, foreground_color, name="thought"):
- super (TextThought, self).__init__(save, name, undo, background_color,
foreground_color)
-
- self.index = 0
- self.end_index = 0
- self.bytes = ""
- self.bindex = 0
- self.text_location = coords
- self.text_element = save.createTextNode ("GOOBAH")
- self.element.appendChild (self.text_element)
- self.layout = None
- self.identity = thought_number
- self.pango_context = pango_context
- self.moving = False
- self.preedit = None
- self.attrlist = None
- self.attributes = pango.AttrList()
- self.current_attrs = []
-
- if prefs.get_direction () == gtk.TEXT_DIR_LTR:
- self.pango_context.set_base_dir (pango.DIRECTION_LTR)
- else:
- self.pango_context.set_base_dir (pango.DIRECTION_RTL)
-
- self.b_f_i = self.bindex_from_index
- margin = utils.margin_required (utils.STYLE_NORMAL)
- if coords:
- self.ul = (coords[0]-margin[0], coords[1] - margin[1])
- else:
- self.ul = None
- self.all_okay = True
-
- def index_from_bindex (self, bindex):
- if bindex == 0:
- return 0
- index = 0
- for x in range(bindex):
- index += int(self.bytes[x])
- return index
-
- def bindex_from_index (self, index):
- if index == 0:
- return 0
- bind = 0
- nbytes = 0
- for x in self.bytes:
- nbytes += int (x)
- bind+=1
- if nbytes == index:
- break
- if nbytes < index:
- bind = len(self.bytes)
- return bind
-
- def attrs_changed (self):
- bold = False
- italics = False
- underline = False
- pango_font = None
- del self.attrlist
- self.attrlist = pango.AttrList ()
- # TODO: splice instead of own method
- it = self.attributes.get_iterator()
-
- while 1:
- at = it.get_attrs()
- for x in at:
- self.attrlist.insert(x)
- if it.next() == False:
- break
- if self.preedit:
- ins_text = self.preedit[0]
- ins_style = self.preedit[1]
- if self.index == len(self.text):
- show_text = self.text+ins_text
- elif self.index == 0:
- show_text = ins_text + self.text
- else:
- split1 = self.text[:self.index]
- split2 = self.text[self.index:]
- show_text = split1 + ins_text + split2
- self.attrlist.splice(ins_style, self.index, len(ins_text))
- else:
- show_text = self.text
-
- it = self.attributes.get_iterator()
- while(1):
- found = False
- r = it.range()
- if self.index == self.end_index:
- if r[0] <= self.index and r[1] > self.index:
- found = True
- elif self.index < self.end_index:
- if r[0] > self.end_index:
- break
- if self.index == self.end_index and \
- r[0] < self.index and \
- r[1] > self.index:
- found = True
- elif self.index != self.end_index and r[0] <= self.index and \
- r[1] >= self.end_index:
- # We got a winner!
- found = True
- else:
- if r[0] > self.index:
- break
- if self.index == self.end_index and \
- r[0] < self.index and \
- r[1] > self.index:
- found = True
- elif self.index != self.end_index and r[0] <= self.end_index and \
- r[1] >= self.index:
- # We got another winner!
- found = True
-
- if found:
- # FIXME: the it.get() seems to crash python
- # through pango.
- attr = it.get_attrs()
- for x in attr:
- if x.type == pango.ATTR_WEIGHT and \
- x.value == pango.WEIGHT_BOLD:
- bold = True
- elif x.type == pango.ATTR_STYLE and \
- x.value == pango.STYLE_ITALIC:
- italics = True
- elif x.type == pango.ATTR_UNDERLINE and \
- x.value == pango.UNDERLINE_SINGLE:
- underline = True
- elif x.type == pango.ATTR_FONT_DESC:
- pango_font = x.desc
- if it.next() == False:
- break
- to_add = []
- if bold:
- to_add.append(pango.AttrWeight(pango.WEIGHT_BOLD, self.index,
self.index))
- if italics:
- to_add.append(pango.AttrStyle(pango.STYLE_ITALIC, self.index,
self.index))
- if underline:
- to_add.append(pango.AttrUnderline(pango.UNDERLINE_SINGLE, self.index,
self.index))
- if pango_font:
- to_add.append(pango.AttrFontDesc(pango_font, self.index, self.index))
- for x in self.current_attrs:
- if x.type == pango.ATTR_WEIGHT and x.value == pango.WEIGHT_BOLD:
- bold = True
- to_add.append(x)
- if x.type == pango.ATTR_STYLE and x.value == pango.STYLE_ITALIC:
- italics = True
- to_add.append(x)
- if x.type == pango.ATTR_UNDERLINE and x.value == pango.UNDERLINE_SINGLE:
- underline = True
- to_add.append(x)
- if x.type == pango.ATTR_FONT_DESC:
- pango_font = x.desc
- to_add.append(x)
- del self.current_attrs
- self.current_attrs = to_add
- self.emit("update-attrs", bold, italics, underline, pango_font)
- return show_text
-
- def recalc_edges (self):
- if (not hasattr(self, "layout")):
- return
- del self.layout
- show_text = self.attrs_changed ()
-
- r,g,b = utils.selected_colors["fill"]
- r *= 65536
- g *= 65536
- b *= 65536
- if self.index > self.end_index:
- bgsel = pango.AttrBackground (int(r), int(g), int(b), self.end_index,
self.index)
- else:
- bgsel = pango.AttrBackground (int(r), int(g), int(b), self.index,
self.end_index)
- self.attrlist.insert (bgsel)
-
- self.layout = pango.Layout (self.pango_context)
- self.layout.set_text (show_text)
- self.layout.set_attributes(self.attrlist)
-
- (x,y) = self.layout.get_pixel_size ()
- margin = utils.margin_required (utils.STYLE_NORMAL)
- if prefs.get_direction () == gtk.TEXT_DIR_LTR:
- self.text_location = (self.ul[0] + margin[0], self.ul[1] + margin[1])
- self.lr = (x + self.text_location[0]+margin[2], y +
self.text_location[1] + margin[3])
- else:
- self.layout.set_alignment (pango.ALIGN_RIGHT)
- tmp1 = self.ul[1]
- if not self.lr:
- self.lr = (self.ul[0], self.ul[1] + y + margin[1] + margin[3])
- self.text_location = (self.lr[0] - margin[2] - x, self.ul[1] +
margin[1])
- self.ul = (self.lr[0] - margin[0] - margin[2] - x, tmp1)
-
- def commit_text (self, context, string, mode, font_name):
- if not self.editing:
- self.emit ("begin_editing")
- self.set_font(font_name)
- self.add_text (string)
- self.recalc_edges ()
- self.emit ("title_changed", self.text)
- self.emit ("update_view")
-
- def add_text (self, string):
- if self.index > self.end_index:
- left = self.text[:self.end_index]
- right = self.text[self.index:]
- bleft = self.bytes[:self.b_f_i (self.end_index)]
- bright = self.bytes[self.b_f_i (self.index):]
- change = self.end_index - self.index + len(string)
- old = self.index
- self.index = self.end_index
- self.end_index = old
- elif self.index < self.end_index:
- left = self.text[:self.index]
- right = self.text[self.end_index:]
- bleft = self.bytes[:self.b_f_i (self.index)]
- bright = self.bytes[self.b_f_i (self.end_index):]
- change = self.index - self.end_index + len(string)
- else:
- left = self.text[:self.index]
- right = self.text[self.index:]
- bleft = self.bytes[:self.b_f_i(self.index)]
- bright = self.bytes[self.b_f_i(self.index):]
- change = len(string)
-
- it = self.attributes.get_iterator()
- changes= []
- for x in self.current_attrs:
- x.start_index = self.index
- x.end_index = self.index + len(string)
- changes.append(x)
- old_attrs = []
- while (1):
- (start,end) = it.range()
- l = it.get_attrs()
- if start <= self.index:
- if end > self.end_index:
- # Inside range
- for x in l:
- old_attrs.append(x.copy())
- x.end_index += change
- changes.append(x)
- else:
- for x in l:
- old_attrs.append(x.copy())
- changes.append(x)
- else:
- if end > self.end_index:
- for x in l:
- old_attrs.append(x.copy())
- x.end_index += change
- x.start_index += change
- changes.append(x)
- else:
- for x in l:
- old_attrs.append(x.copy())
- changes.append(x)
- if it.next() == False:
- break
-
- del self.attributes
- self.attributes = pango.AttrList()
- for x in changes:
- self.attributes.change(x)
-
- self.text = left + string + right
- self.undo.add_undo (UndoManager.UndoAction (self,
UndoManager.INSERT_LETTER, self.undo_text_action,
- self.bindex, string, len(string), old_attrs, changes))
- self.index += len (string)
- self.bytes = bleft + str(len(string)) + bright
- self.bindex = self.b_f_i (self.index)
- self.end_index = self.index
-
- def draw (self, context):
- if not self.layout:
- self.recalc_edges ()
- if not self.editing:
- # We should draw the entire bounding box around ourselves
- # We should also have our coordinates figured out. If not, scream!
- if not self.ul or not self.lr:
- print "Warning: Trying to draw unfinished box "+str(self.identity)+".
Aborting."
- return
- style = utils.STYLE_EXTENDED_CONTENT
- if len (self.extended_buffer.get_text()) == 0:
- style = utils.STYLE_NORMAL
- utils.draw_thought_outline (context, self.ul, self.lr,
self.background_color, self.am_selected, self.am_primary, style)
- else:
- ux, uy = self.ul
- if prefs.get_direction() == gtk.TEXT_DIR_LTR:
- context.move_to (ux, uy+5)
- context.line_to (ux, uy)
- context.line_to (ux+5, uy)
- else:
- lx = self.lr[0]
- context.move_to (lx, uy+5)
- context.line_to (lx, uy)
- context.line_to (lx-5, uy)
- context.stroke ()
-
- (textx, texty) = (self.text_location[0], self.text_location[1])
- if (self.foreground_color):
- r, g, b = utils.gtk_to_cairo_color(self.foreground_color)
- else:
- r, g ,b = utils.gtk_to_cairo_color(utils.default_colors["text"])
- context.set_source_rgb (r, g, b)
- context.move_to (textx, texty)
- context.show_layout (self.layout)
- if self.editing:
- if self.preedit:
- (strong, weak) = self.layout.get_cursor_pos (self.index +
self.preedit[2])
- else:
- (strong, weak) = self.layout.get_cursor_pos (self.index)
- (startx, starty, curx,cury) = strong
- startx /= pango.SCALE
- starty /= pango.SCALE
- curx /= pango.SCALE
- cury /= pango.SCALE
- context.move_to (textx + startx, texty + starty)
- context.line_to (textx + startx, texty + starty + cury)
- context.stroke ()
- context.set_source_rgb (0,0,0)
- context.stroke ()
-
- def begin_editing (self):
- self.editing = True
- self.emit ("update_links")
- return True
-
- def finish_editing (self):
- if not self.editing:
- return
- self.editing = False
- self.end_index = self.index
- self.emit ("update_links")
- self.recalc_edges ()
- if len (self.text) == 0:
- self.emit ("delete_thought")
-
- def includes (self, coords, mode):
- if not self.ul or not self.lr or not coords:
- return False
-
- inside = (coords[0] < self.lr[0] + self.sensitive) and \
- (coords[0] > self.ul[0] - self.sensitive) and \
- (coords[1] < self.lr[1] + self.sensitive) and \
- (coords[1] > self.ul[1] - self.sensitive)
- if inside and self.editing:
- self.emit ("change_mouse_cursor", gtk.gdk.XTERM)
- elif inside:
- self.emit ("change_mouse_cursor", gtk.gdk.LEFT_PTR)
- return inside
-
- def process_key_press (self, event, mode):
- modifiers = gtk.accelerator_get_default_mod_mask ()
- shift = event.state & modifiers == gtk.gdk.SHIFT_MASK
- handled = True
- clear_attrs = True
- if not self.editing:
- return False
-
- if (event.state & modifiers) & gtk.gdk.CONTROL_MASK:
- if event.keyval == gtk.keysyms.a:
- self.index = self.bindex = 0
- self.end_index = len (self.text)
- elif event.keyval == gtk.keysyms.Escape:
- self.emit ("finish_editing")
- elif event.keyval == gtk.keysyms.Left:
- if prefs.get_direction() == gtk.TEXT_DIR_LTR:
- self.move_index_back (shift)
- else:
- self.move_index_forward (shift)
- elif event.keyval == gtk.keysyms.Right:
- if prefs.get_direction() == gtk.TEXT_DIR_RTL:
- self.move_index_back (shift)
- else:
- self.move_index_forward (shift)
- elif event.keyval == gtk.keysyms.Up:
- self.move_index_up (shift)
- elif event.keyval == gtk.keysyms.Down:
- self.move_index_down (shift)
- elif event.keyval == gtk.keysyms.Home:
- if prefs.get_direction() == gtk.TEXT_DIR_LTR:
- self.move_index_horizontal (shift, True) # move home
- else:
- self.move_index_horizontal (shift) # move end
- self.move_index_horizontal (shift, True) # move home
- elif event.keyval == gtk.keysyms.End:
- self.move_index_horizontal (shift) # move
- elif event.keyval == gtk.keysyms.BackSpace and self.editing:
- self.backspace_char ()
- elif event.keyval == gtk.keysyms.Delete and self.editing:
- self.delete_char ()
- elif len (event.string) != 0:
- self.add_text (event.string)
- clear_attrs = False
- else:
- handled = False
- if clear_attrs:
- del self.current_attrs
- self.current_attrs = []
- self.recalc_edges ()
- self.selection_changed ()
- self.emit ("title_changed", self.text)
- self.bindex = self.bindex_from_index (self.index)
- self.emit ("update_view")
- return handled
-
- def undo_text_action (self, action, mode):
- self.undo.block ()
- if action.undo_type == UndoManager.DELETE_LETTER or action.undo_type ==
UndoManager.DELETE_WORD:
- real_mode = not mode
- attrslist = [action.args[5], action.args[4]]
- else:
- real_mode = mode
- attrslist = [action.args[3], action.args[4]]
- self.bindex = action.args[0]
- self.index = self.index_from_bindex (self.bindex)
- self.end_index = self.index
- if real_mode == UndoManager.UNDO:
- attrs = attrslist[0]
- self.end_index = self.index + action.args[2]
- self.delete_char ()
- else:
- attrs = attrslist[1]
- self.add_text (action.text)
- self.rebuild_byte_table ()
- self.bindex = self.b_f_i (self.index)
-
- del self.attributes
- self.attributes = pango.AttrList()
- map(lambda a : self.attributes.change(a), attrs)
- self.recalc_edges ()
- self.emit ("begin_editing")
- self.emit ("title_changed", self.text)
- self.emit ("update_view")
- self.emit ("grab_focus", False)
- self.undo.unblock ()
-
- def delete_char (self):
- if self.index == self.end_index == len (self.text):
- return
- if self.index > self.end_index:
- self.index, self.end_index = self.end_index, self.index
- if self.index != self.end_index:
- left = self.text[:self.index]
- right = self.text[self.end_index:]
- local_text = self.text[self.index:self.end_index]
- bleft = self.bytes[:self.b_f_i (self.index)]
- bright = self.bytes[self.b_f_i (self.end_index):]
- local_bytes = self.bytes[self.b_f_i (self.index):self.b_f_i
(self.end_index)]
- change = -len(local_text)
- else:
- left = self.text[:self.index]
- right = self.text[self.index+int(self.bytes[self.bindex]):]
- local_text =
self.text[self.index:self.index+int(self.bytes[self.bindex])]
- bleft = self.bytes[:self.b_f_i(self.index)]
- bright = self.bytes[self.b_f_i(self.index)+1:]
- local_bytes = self.bytes[self.b_f_i(self.index)]
- change = -len(local_text)
-
- changes= []
- old_attrs = []
- accounted = -change
-
- it = self.attributes.get_iterator()
- while (1):
- (start,end) = it.range()
- l = it.get_attrs()
- if end <= self.index:
- for x in l:
- changes.append(x)
- elif start < self.index and end <= self.end_index:
- # partial ending
- for x in l:
- old_attrs.append(x.copy())
- accounted -= (x.end_index - self.index)
- x.end_index -= (x.end_index - self.index)
- changes.append(x)
- elif start <= self.index and end >= self.end_index:
- # Swallow whole
- accounted -= (end - start)
- for x in l:
- old_attrs.append(x.copy())
- x.end_index += change
- changes.append(x)
- elif start < self.end_index and end > self.end_index:
- # partial beginning
- for x in l:
- old_attrs.append(x.copy())
- accounted -= (x.start_index - self.index)
- x.start_index = self.index
- x.end_index = x.start_index + (end - start) - accounted
- changes.append(x)
- else:
- # Past
- for x in l:
- old_attrs.append(x.copy())
- x.start_index += change
- x.end_index += change
- changes.append(x)
- if it.next() == False:
- break
-
- del self.attributes
- self.attributes = pango.AttrList()
- map(lambda a : self.attributes.change(a), changes)
-
- self.undo.add_undo (UndoManager.UndoAction (self,
UndoManager.DELETE_LETTER, self.undo_text_action,
- self.b_f_i (self.index), local_text, len(local_text), local_bytes,
old_attrs,
- changes))
- self.text = left+right
- self.bytes = bleft+bright
- self.end_index = self.index
-
- def backspace_char (self):
- if self.index == self.end_index == 0:
- return
- if self.index > self.end_index:
- self.index, self.end_index = self.end_index, self.index
- if self.index != self.end_index:
- left = self.text[:self.index]
- right = self.text[self.end_index:]
- bleft = self.bytes[:self.b_f_i (self.index)]
- bright = self.bytes[self.b_f_i (self.end_index):]
- local_text = self.text[self.index:self.end_index]
- local_bytes = self.bytes[self.b_f_i (self.index):self.b_f_i
(self.end_index)]
- change = -len(local_text)
- else:
- left = self.text[:self.index-int(self.bytes[self.bindex-1])]
- right = self.text[self.index:]
- bleft = self.bytes[:self.b_f_i(self.index)-1]
- bright = self.bytes[self.b_f_i(self.index):]
- local_text =
self.text[self.index-int(self.bytes[self.bindex-1]):self.index]
- local_bytes = self.bytes[self.b_f_i(self.index)-1]
- self.index-=int(self.bytes[self.bindex-1])
- change = -len(local_text)
-
- old_attrs = []
- changes= []
- accounted = -change
-
- it = self.attributes.get_iterator()
- while (1):
- (start,end) = it.range()
- l = it.get_attrs()
- if end <= self.index:
- for x in l:
- old_attrs.append(x.copy())
- changes.append(x)
- elif start < self.index and end <= self.end_index:
- # partial ending
- for x in l:
- old_attrs.append(x.copy())
- accounted -= (x.end_index - self.index)
- x.end_index -= (x.end_index - self.index)
- changes.append(x)
- elif start <= self.index and end >= self.end_index:
- # Swallow whole
- accounted -= (end - start)
- for x in l:
- old_attrs.append(x.copy())
- x.end_index += change
- changes.append(x)
- elif start < self.end_index and end > self.end_index:
- # partial beginning
- for x in l:
- old_attrs.append(x.copy())
- accounted -= (x.start_index - self.index)
- x.start_index = self.index
- x.end_index = x.start_index + (end - start) - accounted
- changes.append(x)
- else:
- # Past
- for x in l:
- old_attrs.append(x.copy())
- x.start_index += change
- x.end_index += change
- changes.append(x)
- if it.next() == False:
- break
-
-
- del self.attributes
- self.attributes = pango.AttrList()
- map(lambda a : self.attributes.change(a), changes)
-
- self.text = left+right
- self.bytes = bleft+bright
- self.end_index = self.index
- self.undo.add_undo (UndoManager.UndoAction (self,
UndoManager.DELETE_LETTER, self.undo_text_action,
- self.b_f_i (self.index), local_text, len(local_text), local_bytes,
old_attrs,
- changes))
- if self.index < 0:
- self.index = 0
-
- def move_index_back (self, mod):
- if self.index <= 0:
- self.end_index = self.index
- return
- self.index -= int(self.bytes[self.bindex-1])
- if not mod:
- self.end_index = self.index
-
- def move_index_forward (self, mod):
- if self.index >= len(self.text):
- self.end_index = self.index
- return
- self.index += int(self.bytes[self.bindex])
- if not mod:
- self.end_index = self.index
-
- def move_index_up (self, mod):
- tmp = self.text.decode ()
- lines = tmp.splitlines ()
- if len (lines) == 1:
- self.end_index = self.index
- return
- loc = 0
- line = 0
- for i in lines:
- loc += len (i)+1
- if loc > self.index:
- loc -= len (i)+1
- line -= 1
- break
- line+=1
- if line == -1:
- self.end_index = self.index
- return
- elif line >= len (lines):
- self.bindex -= len (lines[-1])+1
- self.index = self.index_from_bindex (self.bindex)
- if not mod:
- self.end_index = self.index
- return
- dist = self.bindex - loc -1
- self.bindex = loc
- if dist < len (lines[line]):
- self.bindex -= (len (lines[line]) - dist)
- else:
- self.bindex -= 1
- if self.bindex < 0:
- self.bindex = 0
- self.index = self.index_from_bindex (self.bindex)
- if not mod:
- self.end_index = self.index
-
- def move_index_down (self, mod):
- tmp = self.text.decode ()
- lines = tmp.splitlines ()
- if len (lines) == 1:
- self.end_index = self.index
- return
- loc = 0
- line = 0
- for i in lines:
- loc += len (i)+1
- if loc > self.bindex:
- break
- line += 1
- if line >= len (lines)-1:
- self.end_index = self.index
- return
- dist = self.bindex - (loc - len (lines[line]))+1
- self.bindex = loc
- if dist > len (lines[line+1]):
- self.bindex += len (lines[line+1])
- else:
- self.bindex += dist
- self.index = self.index_from_bindex (self.bindex)
- if not mod:
- self.end_index = self.index
-
- def move_index_horizontal(self, mod, home=False):
- lines = self.text.splitlines ()
- loc = 0
- line = 0
- for i in lines:
- loc += len (i) + 1
- if loc > self.index:
- self.index = loc - 1
- if home:
- self.index -= len(i)
- if not mod:
- self.end_index = self.index
- return
- line += 1
-
- def process_button_down (self, event, mode, transformed):
- modifiers = gtk.accelerator_get_default_mod_mask ()
-
- if event.button == 1:
- if event.type == gtk.gdk.BUTTON_PRESS and not self.editing:
- self.emit ("select_thought", event.state & modifiers)
- elif event.type == gtk.gdk.BUTTON_PRESS and self.editing:
- x = int ((transformed[0] - self.ul[0])*pango.SCALE)
- y = int ((transformed[1] - self.ul[1])*pango.SCALE)
- loc = self.layout.xy_to_index (x, y)
- self.index = loc[0]
- if loc[0] >= len(self.text) -1 or self.text[loc[0]+1] == '\n':
- self.index += loc[1]
- self.bindex = self.bindex_from_index (self.index)
- if not (event.state & modifiers) & gtk.gdk.SHIFT_MASK:
- self.end_index = self.index
- elif mode == BaseThought.MODE_EDITING and event.type ==
gtk.gdk._2BUTTON_PRESS:
- if self.editing:
- self.move_index_horizontal(False) # go to the end
- self.index = 0 # and mark all
- else:
- self.emit ("begin_editing")
- elif event.button == 2 and self.editing:
- x = int ((transformed[0] - self.ul[0])*pango.SCALE)
- y = int ((transformed[1] - self.ul[1])*pango.SCALE)
- loc = self.layout.xy_to_index (x, y)
- self.index = loc[0]
- if loc[0] >= len(self.text) -1 or self.text[loc[0]+1] == '\n':
- self.index += loc[1]
- self.bindex = self.bindex_from_index (self.index)
- self.end_index = self.index
- if os.name != 'nt':
- clip = gtk.Clipboard (selection="PRIMARY")
- self.paste_text (clip)
- elif event.button == 3:
- self.emit ("popup_requested", event, 1)
-
- del self.current_attrs
- self.current_attrs = []
- self.recalc_edges()
- self.emit ("update_view")
-
- def process_button_release (self, event, unending_link, mode,
transformed):
- if unending_link:
- unending_link.set_child (self)
- self.emit ("claim_unending_link")
-
- def selection_changed (self):
- (start, end) = (min(self.index, self.end_index), max(self.index,
self.end_index))
- self.emit ("text_selection_changed", start, end, self.text[start:end])
-
- def handle_motion (self, event, mode, transformed):
- if event.state & gtk.gdk.BUTTON1_MASK and self.editing:
- if transformed[0] < self.lr[0] and transformed[0] > self.ul[0] and \
- transformed[1] < self.lr[1] and transformed[1] > self.ul[1]:
- x = int ((transformed[0] - self.ul[0])*pango.SCALE)
- y = int ((transformed[1] - self.ul[1])*pango.SCALE)
- loc = self.layout.xy_to_index (x, y)
- self.index = loc[0]
- if loc[0] >= len(self.text) -1 or self.text[loc[0]+1] == '\n':
- self.index += loc[1]
- self.bindex = self.bindex_from_index (self.index)
- self.selection_changed ()
- elif mode == BaseThought.MODE_EDITING:
- self.emit ("finish_editing")
- self.emit ("create_link", \
- (self.ul[0]-((self.ul[0]-self.lr[0]) / 2.),
self.ul[1]-((self.ul[1]-self.lr[1]) / 2.)))
- return True
- elif event.state & gtk.gdk.BUTTON1_MASK and not self.editing and \
- mode == BaseThought.MODE_EDITING and not event.state &
gtk.gdk.CONTROL_MASK:
- self.emit ("create_link", \
- (self.ul[0]-((self.ul[0]-self.lr[0]) / 2.),
self.ul[1]-((self.ul[1]-self.lr[1]) / 2.)))
- self.recalc_edges()
- self.emit ("update_view")
-
- def export (self, context, move_x, move_y):
- utils.export_thought_outline (context, self.ul, self.lr,
self.background_color, self.am_selected, self.am_primary,
utils.STYLE_NORMAL,
- (move_x, move_y))
-
- r,g,b = utils.gtk_to_cairo_color (self.foreground_color)
- context.set_source_rgb (r, g, b)
- context.move_to (self.text_location[0]+move_x,
self.text_location[1]+move_y)
- context.show_layout (self.layout)
- context.set_source_rgb (0,0,0)
- context.stroke ()
-
- def update_save (self):
- next = self.element.firstChild
- while next:
- m = next.nextSibling
- if next.nodeName == "attribute":
- self.element.removeChild (next)
- next.unlink ()
- next = m
-
- if self.text_element.parentNode is not None:
- self.text_element.replaceWholeText (self.text)
- text = self.extended_buffer.get_text ()
- if text:
- self.extended_buffer.update_save()
- else:
- try:
- self.element.removeChild(self.extended_buffer.element)
- except xml.dom.NotFoundErr:
- pass
- self.element.setAttribute ("cursor", str(self.index))
- self.element.setAttribute ("selection_end", str(self.end_index))
- self.element.setAttribute ("ul-coords", str(self.ul))
- self.element.setAttribute ("lr-coords", str(self.lr))
- self.element.setAttribute ("identity", str(self.identity))
- self.element.setAttribute ("background-color",
self.background_color.to_string())
- self.element.setAttribute ("foreground-color",
self.foreground_color.to_string())
- if self.editing:
- self.element.setAttribute ("edit", "true")
- else:
- try:
- self.element.removeAttribute ("edit")
- except xml.dom.NotFoundErr:
- pass
- if self.am_selected:
- self.element.setAttribute ("current_root", "true")
- else:
- try:
- self.element.removeAttribute ("current_root")
- except xml.dom.NotFoundErr:
- pass
- if self.am_primary:
- self.element.setAttribute ("primary_root", "true");
- else:
- try:
- self.element.removeAttribute ("primary_root")
- except xml.dom.NotFoundErr:
- pass
- doc = self.element.ownerDocument
- it = self.attributes.get_iterator()
- while (1):
- r = it.range()
- for x in it.get_attrs():
- if x.type == pango.ATTR_WEIGHT and x.value == pango.WEIGHT_BOLD:
- elem = doc.createElement ("attribute")
- self.element.appendChild (elem)
- elem.setAttribute("start", str(r[0]))
- elem.setAttribute("end", str(r[1]))
- elem.setAttribute("type", "bold")
- elif x.type == pango.ATTR_STYLE and x.value == pango.STYLE_ITALIC:
- elem = doc.createElement ("attribute")
- self.element.appendChild (elem)
- elem.setAttribute("start", str(r[0]))
- elem.setAttribute("end", str(r[1]))
- elem.setAttribute("type", "italics")
- elif x.type == pango.ATTR_UNDERLINE and x.value ==
pango.UNDERLINE_SINGLE:
- elem = doc.createElement ("attribute")
- self.element.appendChild (elem)
- elem.setAttribute("start", str(r[0]))
- elem.setAttribute("end", str(r[1]))
- elem.setAttribute("type", "underline")
- elif x.type == pango.ATTR_FONT_DESC:
- elem = doc.createElement ("attribute")
- self.element.appendChild (elem)
- elem.setAttribute("start", str(r[0]))
- elem.setAttribute("end", str(r[1]))
- elem.setAttribute("type", "font")
- elem.setAttribute("value", x.desc.to_string ())
- if not it.next():
- break
-
- def rebuild_byte_table (self):
- # Build the Byte table
- del self.bytes
- self.bytes = ''
- tmp = self.text.encode ("utf-8")
- current = 0
- for z in range(len(self.text)):
- if str(self.text[z]) == str(tmp[current]):
- self.bytes += '1'
- else:
- blen = 2
- while 1:
- try:
- if str(tmp[current:current+blen].encode()) == str(self.text[z]):
- self.bytes += str(blen)
- current+=(blen-1)
- break
- blen += 1
- except:
- blen += 1
- current+=1
- self.bindex = self.b_f_i (self.index)
- self.text = tmp
-
- def load (self, node):
- self.index = int (node.getAttribute ("cursor"))
- if node.hasAttribute ("selection_end"):
- self.end_index = int (node.getAttribute ("selection_end"))
- else:
- self.end_index = self.index
- tmp = node.getAttribute ("ul-coords")
- self.ul = utils.parse_coords (tmp)
- tmp = node.getAttribute ("lr-coords")
- self.lr = utils.parse_coords (tmp)
- self.identity = int (node.getAttribute ("identity"))
- try:
- tmp = node.getAttribute ("background-color")
- self.background_color = gtk.gdk.color_parse(tmp)
- tmp = node.getAttribute ("foreground-color")
- self.foreground_color = gtk.gdk.color_parse(tmp)
- except ValueError:
- pass
-
- if node.hasAttribute ("edit"):
- self.editing = True
- else:
- self.editing = False
- self.end_index = self.index
-
- self.am_selected = node.hasAttribute ("current_root")
- self.am_primary = node.hasAttribute ("primary_root")
-
- for n in node.childNodes:
- if n.nodeType == n.TEXT_NODE:
- self.text = n.data
- elif n.nodeName == "Extended":
- self.extended_buffer.load(n)
- elif n.nodeName == "attribute":
- attrType = n.getAttribute("type")
- start = int(n.getAttribute("start"))
- end = int(n.getAttribute("end"))
-
- if attrType == "bold":
- attr = pango.AttrWeight(pango.WEIGHT_BOLD, start, end)
- elif attrType == "italics":
- attr = pango.AttrStyle(pango.STYLE_ITALIC, start, end)
- elif attrType == "underline":
- attr = pango.AttrUnderline(pango.UNDERLINE_SINGLE, start, end)
- elif attrType == "font":
- font_name = str(n.getAttribute("value"))
- pango_font = pango.FontDescription (font_name)
- attr = pango.AttrFontDesc (pango_font, start, end)
- self.attributes.change(attr)
- else:
- print "Unknown: "+n.nodeName
- self.rebuild_byte_table ()
- self.recalc_edges ()
-
- def copy_text (self, clip):
- if self.end_index > self.index:
- clip.set_text (self.text[self.index:self.end_index])
- else:
- clip.set_text (self.text[self.end_index:self.index])
-
- def cut_text (self, clip):
- if self.end_index > self.index:
- clip.set_text (self.text[self.index:self.end_index])
- else:
- clip.set_text (self.text[self.end_index:self.index])
- self.delete_char ()
- self.recalc_edges ()
- self.emit ("title_changed", self.text)
- self.bindex = self.bindex_from_index (self.index)
- self.emit ("update_view")
-
- def paste_text (self, clip):
- text = clip.wait_for_text()
- if not text:
- return
- self.add_text (text)
- self.rebuild_byte_table ()
- self.recalc_edges ()
- self.emit ("title_changed", self.text)
- self.bindex = self.bindex_from_index (self.index)
- self.emit ("update_view")
-
- def delete_surroundings(self, imcontext, offset, n_chars, mode):
- # TODO: Add in Attr stuff
- orig = len(self.text)
- left = self.text[:offset]
- right = self.text[offset+n_chars:]
- local_text = self.text[offset:offset+n_chars]
- self.text = left+right
- self.rebuild_byte_table ()
- new = len(self.text)
- if self.index > len(self.text):
- self.index = len(self.text)
-
- change = old - new
- changes = []
- old_attrs = []
- accounted = -change
- index = offset
- end_index = offset - (new-orig)
-
- it = self.attributes.get_iterator()
- while (1):
- (start,end) = it.range()
- l = it.get_attrs()
- if end <= start:
- for x in l:
- changes.append(x)
***The diff for this file has been truncated for email.***
=======================================
--- /trunk/src/TrayIcon.py Mon Oct 23 14:09:49 2006
+++ /trunk/src/TrayIcon.py Sat Apr 23 07:28:34 2011
@@ -15,7 +15,7 @@
#
# You should have received a copy of the GNU General Public License
# along with Labyrinth; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301 USA
#
@@ -32,43 +32,43 @@
from utils import *
class TrayIcon(object):
- """This is possibly the thinnest wrapper class I've written. Ever.
-
- Its a tray icon that you can parameterize during initialisation with the
name or file of an icon, with a menu and a simple callback
-
- It will create such an Icon, will display the image, call back the
callback when left clicked and pop up the menu
- when right clicked.
- """
- def __init__(self, icon_name="TestTrayIcon", icon_file=None, menu=None,
activate=None):
- # thats so incredibly simple!
- if icon_file:
- self.status_icon=gtk.status_icon_new_from_file(icon_file)
- else:
- self.status_icon=gtk.status_icon_new_from_icon_name(icon_name)
-
- # connect the menu and the callback if given
- if menu:
- self.connect_popup_menu(menu)
-
- if activate:
- self.connect_activate(activate)
-
- def connect_activate(self, method):
- def activate_callback(status_icon, *data):
- method()
- self.status_icon.connect("activate", activate_callback)
-
- def connect_popup_menu(self, menu):
- def popup_menu_callback(status_icon, button, activate_time, *data):
- menu.popup(None, None, gtk.status_icon_position_menu, button,
activate_time, status_icon)
- self.status_icon.connect("popup-menu", popup_menu_callback)
+ """This is possibly the thinnest wrapper class I've written. Ever.
+
+ Its a tray icon that you can parameterize during initialisation with
the name or file of an icon, with a menu and a simple callback
+
+ It will create such an Icon, will display the image, call back the
callback when left clicked and pop up the menu
+ when right clicked.
+ """
+ def __init__(self, icon_name="TestTrayIcon", icon_file=None,
menu=None, activate=None):
+ # thats so incredibly simple!
+ if icon_file:
+ self.status_icon=gtk.status_icon_new_from_file(icon_file)
+ else:
+ self.status_icon=gtk.status_icon_new_from_icon_name(icon_name)
+
+ # connect the menu and the callback if given
+ if menu:
+ self.connect_popup_menu(menu)
+
+ if activate:
+ self.connect_activate(activate)
+
+ def connect_activate(self, method):
+ def activate_callback(status_icon, *data):
+ method()
+ self.status_icon.connect("activate", activate_callback)
+
+ def connect_popup_menu(self, menu):
+ def popup_menu_callback(status_icon, button, activate_time, *data):
+ menu.popup(None, None, gtk.status_icon_position_menu, button,
activate_time, status_icon)
+ self.status_icon.connect("popup-menu", popup_menu_callback)
if __name__ == "__main__":
- menu = gtk.Menu()
- quit_item = gtk.MenuItem("Quit")
- quit_item.connect("activate", gtk.main_quit)
- menu.add(quit_item)
- menu.show_all()
- yell_at_them = lambda : sys.stdout.write("you hit %s...\n" % trayicon)
- trayicon = TrayIcon(icon_name="labyrinth", menu=menu,
activate=yell_at_them)
- gtk.main()
+ menu = gtk.Menu()
+ quit_item = gtk.MenuItem("Quit")
+ quit_item.connect("activate", gtk.main_quit)
+ menu.add(quit_item)
+ menu.show_all()
+ yell_at_them = lambda : sys.stdout.write("you hit %s...\n" % trayicon)
+ trayicon = TrayIcon(icon_name="labyrinth", menu=menu,
activate=yell_at_them)
+ gtk.main()
=======================================
--- /trunk/src/UndoManager.py Fri Apr 11 09:31:48 2008
+++ /trunk/src/UndoManager.py Sat Apr 23 07:28:34 2011
@@ -36,216 +36,216 @@
TRANSFORM_CANVAS = 104
class UndoAction:
- def __init__(self, owner, undo_type, callback, *args):
- self.owner = owner
- self.undo_type = undo_type
- self.callback = callback
- self.text = ""
- if undo_type == INSERT_LETTER or undo_type == INSERT_WORD or undo_type
== DELETE_LETTER or \
- undo_type == DELETE_WORD:
- for z in args:
- if isinstance(z, basestring):
- self.text = z
- break
- self.args = args
- def add_arg (self, *args):
- for t in args:
- self.args += (t,)
+ def __init__(self, owner, undo_type, callback, *args):
+ self.owner = owner
+ self.undo_type = undo_type
+ self.callback = callback
+ self.text = ""
+ if undo_type == INSERT_LETTER or undo_type == INSERT_WORD or
undo_type == DELETE_LETTER or \
+ undo_type == DELETE_WORD:
+ for z in args:
+ if isinstance(z, basestring):
+ self.text = z
+ break
+ self.args = args
+ def add_arg (self, *args):
+ for t in args:
+ self.args += (t,)
class UndoManager:
- ''' A basic manager for undoing and redoing actions.\
- Doesn't do anything itself, instead it marshals \
- all the minion classes to do its bidding. Any class \
- can add items to its lists and they're corresponding \
- methods will be called if and when needed. The \
- manager doesn't care what you give it, so long as
- it has a method to call and an owner'''
-
- def __init__(self, top_owner, undo_widget = None, redo_widget = None):
- self.undo = undo_widget
- self.redo = redo_widget
-
- self.blocked = False
-
- self.undo_list = []
- self.redo_list = []
-
- if self.undo:
- self.undo.connect('activate', self.undo_action)
- if self.redo:
- self.redo.connect('activate', self.redo_action)
- self.owner = top_owner
- self.update_sensitive ()
-
- def block (self):
- ''' Used as generally, when an undo is performed a \
- signal will be emitted that causes an undo action \
- to be added. Use this to block tht from happening \
- To add actions again, call unblock'''
- self.blocked = True
-
- def unblock (self):
- self.blocked = False
-
- def set_widgets (self, undo, redo):
- self.undo = undo
- self.redo = redo
- self.undo.connect('activate', self.undo_action)
- self.redo.connect('activate', self.redo_action)
- self.update_sensitive ()
-
- def update_sensitive (self):
- if not self.undo or not self.redo:
- return
- self.undo.set_sensitive(len(self.undo_list) > 0)
- self.redo.set_sensitive(len(self.redo_list) > 0)
-
- def undo_action (self, arg):
- result = self.undo_list.pop()
- self.redo_list.append (result)
- self.update_sensitive ()
- result.callback (result, mode=UNDO)
-
- def redo_action (self, arg):
- result = self.redo_list.pop()
- self.undo_list.append (result)
- self.update_sensitive ()
- result.callback (result, mode=REDO)
-
- def combine_insertions (self, action):
- final_text = action.text
- start_iter = action.args[0]
- length = action.args[2]
- owner = action.owner
- cb = action.callback
- old_attrs = action.args[3]
- new_attrs = action.args[4]
- if len (self.undo_list) > 0:
- back = self.undo_list.pop ()
- else:
- self.undo_list.append (action)
- return
- add_back = True
- while back and back.owner == owner \
- and (back.undo_type == INSERT_LETTER or back.undo_type ==
INSERT_WORD):
- if back.text.rfind(' ') != -1:
- break
- old_attrs = back.args[3]
- if back.args[0] <= start_iter:
- start_iter = back.args[0]
- final_text = back.text+final_text
- else:
- final_text += back.text
- length += back.args[2]
- if len (self.undo_list) == 0:
- add_back = False
- break
- back = self.undo_list.pop ()
- if add_back:
- self.undo_list.append (back)
- combi = UndoAction (owner, INSERT_WORD, cb, start_iter, final_text,
length, old_attrs, new_attrs)
- self.undo_list.append (combi)
-
- def combine_deletions (self, action):
- bytes = True
- byte_collection = action.args[3]
- final_text = action.text
- start_iter = action.args[0]
- length = action.args[2]
- owner = action.owner
- cb = action.callback
- old_attrs = action.args[4]
- new_attrs = action.args[5]
- if len (self.undo_list) > 0:
- back = self.undo_list.pop ()
- else:
- self.undo_list.append (action)
- return
- add_back = True
- while back and back.owner == owner \
- and (back.undo_type == DELETE_LETTER or back.undo_type ==
DELETE_WORD):
- if back.text.rfind(' ') != -1:
- break
- old_attrs = back.args[4]
- if back.args[0] <= start_iter:
- start_iter = back.args[0]
- final_text = back.text+final_text
- if bytes:
- byte_collection = back.args[3] + byte_collection
- else:
- final_text += back.text
- if bytes:
- byte_collection += back.args[3]
- length += back.args[2]
- if len (self.undo_list) == 0:
- add_back = False
- break
- back = self.undo_list.pop ()
- if add_back:
- self.undo_list.append (back)
- if bytes:
- combi = UndoAction (owner, DELETE_WORD, cb, start_iter, final_text,
length, byte_collection, old_attrs, new_attrs)
- else:
- combi = UndoAction (owner, DELETE_WORD, cb, start_iter, final_text,
length, -1, old_attrs, new_attrs)
- self.undo_list.append (combi)
-
- def combine_transforms (self, action):
- if len (self.undo_list) > 0:
- back = self.undo_list.pop ()
- else:
- self.undo_list.append (action)
- return
- add_back = True
- final_zoom = action.args[1]
- final_trans = action.args[3]
- orig_zoom = action.args[0]
- orig_trans = action.args[2]
- owner = action.owner
- cb = action.callback
- while back and back.owner == owner and \
- back.undo_type == TRANSFORM_CANVAS:
- orig_zoom = back.args[0]
- orig_trans = back.args[2]
- if len (self.undo_list) == 0:
- add_back = False
- break
- back = self.undo_list.pop ()
- if add_back:
- self.undo_list.append (back)
- self.undo_list.append (UndoAction (owner, TRANSFORM_CANVAS, cb,
orig_zoom,
- final_zoom, orig_trans, final_trans))
-
- def peak (self):
- if len (self.undo_list) > 0:
- return self.undo_list[-1]
- else:
- return UndoAction (None, None, None)
-
- def pop (self):
- if len (self.undo_list) > 0:
- return self.undo_list.pop ()
- else:
- return None
-
- def exists_undo_action (self):
- return len(self.undo_list) > 0
-
- def exists_redo_action (self):
- return len(self.redo_list) > 0
-
- def add_undo (self, action):
- if self.blocked:
- return
- if not isinstance(action, UndoAction):
- print "Error: Not a valid undo action. Ignoring."
- return
- del self.redo_list[:]
- if action.undo_type == INSERT_LETTER:
- self.combine_insertions (action)
- elif action.undo_type == DELETE_LETTER:
- self.combine_deletions (action)
- elif action.undo_type == TRANSFORM_CANVAS:
- self.combine_transforms (action)
- else:
- self.undo_list.append (action)
- self.update_sensitive ()
+ ''' A basic manager for undoing and redoing actions.\
+ Doesn't do anything itself, instead it marshals \
+ all the minion classes to do its bidding. Any class \
+ can add items to its lists and they're corresponding \
+ methods will be called if and when needed. The \
+ manager doesn't care what you give it, so long as
+ it has a method to call and an owner'''
+
+ def __init__(self, top_owner, undo_widget = None, redo_widget = None):
+ self.undo = undo_widget
+ self.redo = redo_widget
+
+ self.blocked = False
+
+ self.undo_list = []
+ self.redo_list = []
+
+ if self.undo:
+ self.undo.connect('activate', self.undo_action)
+ if self.redo:
+ self.redo.connect('activate', self.redo_action)
+ self.owner = top_owner
+ self.update_sensitive ()
+
+ def block (self):
+ ''' Used as generally, when an undo is performed a \
+ signal will be emitted that causes an undo action \
+ to be added. Use this to block tht from happening \
+ To add actions again, call unblock'''
+ self.blocked = True
+
+ def unblock (self):
+ self.blocked = False
+
+ def set_widgets (self, undo, redo):
+ self.undo = undo
+ self.redo = redo
+ self.undo.connect('activate', self.undo_action)
+ self.redo.connect('activate', self.redo_action)
+ self.update_sensitive ()
+
+ def update_sensitive (self):
+ if not self.undo or not self.redo:
+ return
+ self.undo.set_sensitive(len(self.undo_list) > 0)
+ self.redo.set_sensitive(len(self.redo_list) > 0)
+
+ def undo_action (self, arg):
+ result = self.undo_list.pop()
+ self.redo_list.append (result)
+ self.update_sensitive ()
+ result.callback (result, mode=UNDO)
+
+ def redo_action (self, arg):
+ result = self.redo_list.pop()
+ self.undo_list.append (result)
+ self.update_sensitive ()
+ result.callback (result, mode=REDO)
+
+ def combine_insertions (self, action):
+ final_text = action.text
+ start_iter = action.args[0]
+ length = action.args[2]
+ owner = action.owner
+ cb = action.callback
+ old_attrs = action.args[3]
+ new_attrs = action.args[4]
+ if len (self.undo_list) > 0:
+ back = self.undo_list.pop ()
+ else:
+ self.undo_list.append (action)
+ return
+ add_back = True
+ while back and back.owner == owner \
+ and (back.undo_type == INSERT_LETTER or back.undo_type ==
INSERT_WORD):
+ if back.text.rfind(' ') != -1:
+ break
+ old_attrs = back.args[3]
+ if back.args[0] <= start_iter:
+ start_iter = back.args[0]
+ final_text = back.text+final_text
+ else:
+ final_text += back.text
+ length += back.args[2]
+ if len (self.undo_list) == 0:
+ add_back = False
+ break
+ back = self.undo_list.pop ()
+ if add_back:
+ self.undo_list.append (back)
+ combi = UndoAction (owner, INSERT_WORD, cb, start_iter,
final_text, length, old_attrs, new_attrs)
+ self.undo_list.append (combi)
+
+ def combine_deletions (self, action):
+ bytes = True
+ byte_collection = action.args[3]
+ final_text = action.text
+ start_iter = action.args[0]
+ length = action.args[2]
+ owner = action.owner
+ cb = action.callback
+ old_attrs = action.args[4]
+ new_attrs = action.args[5]
+ if len (self.undo_list) > 0:
+ back = self.undo_list.pop ()
+ else:
+ self.undo_list.append (action)
+ return
+ add_back = True
+ while back and back.owner == owner \
+ and (back.undo_type == DELETE_LETTER or back.undo_type
== DELETE_WORD):
+ if back.text.rfind(' ') != -1:
+ break
+ old_attrs = back.args[4]
+ if back.args[0] <= start_iter:
+ start_iter = back.args[0]
+ final_text = back.text+final_text
+ if bytes:
+ byte_collection = back.args[3] + byte_collection
+ else:
+ final_text += back.text
+ if bytes:
+ byte_collection += back.args[3]
+ length += back.args[2]
+ if len (self.undo_list) == 0:
+ add_back = False
+ break
+ back = self.undo_list.pop ()
+ if add_back:
+ self.undo_list.append (back)
+ if bytes:
+ combi = UndoAction (owner, DELETE_WORD, cb, start_iter,
final_text, length, byte_collection, old_attrs, new_attrs)
+ else:
+ combi = UndoAction (owner, DELETE_WORD, cb, start_iter,
final_text, length, -1, old_attrs, new_attrs)
+ self.undo_list.append (combi)
+
+ def combine_transforms (self, action):
+ if len (self.undo_list) > 0:
+ back = self.undo_list.pop ()
+ else:
+ self.undo_list.append (action)
+ return
+ add_back = True
+ final_zoom = action.args[1]
+ final_trans = action.args[3]
+ orig_zoom = action.args[0]
+ orig_trans = action.args[2]
+ owner = action.owner
+ cb = action.callback
+ while back and back.owner == owner and \
+ back.undo_type == TRANSFORM_CANVAS:
+ orig_zoom = back.args[0]
+ orig_trans = back.args[2]
+ if len (self.undo_list) == 0:
+ add_back = False
+ break
+ back = self.undo_list.pop ()
+ if add_back:
+ self.undo_list.append (back)
+ self.undo_list.append (UndoAction (owner, TRANSFORM_CANVAS, cb,
orig_zoom,
+
final_zoom, orig_trans, final_trans))
+
+ def peak (self):
+ if len (self.undo_list) > 0:
+ return self.undo_list[-1]
+ else:
+ return UndoAction (None, None, None)
+
+ def pop (self):
+ if len (self.undo_list) > 0:
+ return self.undo_list.pop ()
+ else:
+ return None
+
+ def exists_undo_action (self):
+ return len(self.undo_list) > 0
+
+ def exists_redo_action (self):
+ return len(self.redo_list) > 0
+
+ def add_undo (self, action):
+ if self.blocked:
+ return
+ if not isinstance(action, UndoAction):
+ print "Error: Not a valid undo action. Ignoring."
+ return
+ del self.redo_list[:]
+ if action.undo_type == INSERT_LETTER:
+ self.combine_insertions (action)
+ elif action.undo_type == DELETE_LETTER:
+ self.combine_deletions (action)
+ elif action.undo_type == TRANSFORM_CANVAS:
+ self.combine_transforms (action)
+ else:
+ self.undo_list.append (action)
+ self.update_sensitive ()
=======================================
--- /trunk/src/__init__.py Tue Aug 29 10:24:42 2006
+++ /trunk/src/__init__.py Sat Apr 23 07:28:34 2011
@@ -6,12 +6,12 @@
UNINSTALLED_LAB = False
def _check (path):
return exists(path) and isdir(path) and isfile(path+"/AUTHORS")
-
+
name = join (dirname (__file__), '..')
if _check (name):
UNINSTALLED_LAB = True
-
+
if UNINSTALLED_LAB:
SHARED_DATA_DIR = abspath(join(dirname(__file__), '..', 'data'))
else:
- SHARED_DATA_DIR = join(DATA_DIR, "labyrinth")
+ SHARED_DATA_DIR = join(DATA_DIR, "labyrinth")
=======================================
--- /trunk/src/labyrinth.py Fri Feb 27 09:46:34 2009
+++ /trunk/src/labyrinth.py Sat Apr 23 07:28:34 2011
@@ -12,7 +12,7 @@
#
# Labyrith 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
+# 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
@@ -28,15 +28,15 @@
import os.path as osp
if os.name != 'nt':
- pygtk.require('2.0')
- def _check (path):
- return osp.exists(path) and osp.isdir(path) and
osp.isfile(path+"/AUTHORS")
-
- name = osp.join(osp.dirname(__file__), '..')
- if _check(name):
- sys.path.insert(0, osp.abspath(name))
- else:
- sys.path.insert(0, osp.abspath("@PYTHONDIR@"))
+ pygtk.require('2.0')
+ def _check (path):
+ return osp.exists(path) and osp.isdir(path) and
osp.isfile(path+"/AUTHORS")
+
+ name = osp.join(osp.dirname(__file__), '..')
+ if _check(name):
+ sys.path.insert(0, osp.abspath(name))
+ else:
+ sys.path.insert(0, osp.abspath("@PYTHONDIR@"))
import gtk
@@ -45,58 +45,58 @@
import Browser
import prefs
try:
- import defs
- localedir = abspath(join(defs.DATA_DIR, "locale"))
+ import defs
+ localedir = abspath(join(defs.DATA_DIR, "locale"))
except:
- localedir = ""
+ localedir = ""
gettext.bindtextdomain('labyrinth', localedir)
if hasattr(gettext, 'bind_textdomain_codeset'):
- gettext.bind_textdomain_codeset('labyrinth','UTF-8')
+ gettext.bind_textdomain_codeset('labyrinth','UTF-8')
gettext.textdomain('labyrinth')
if hasattr(locale, 'bindtextdomain'):
- if not os.name == 'nt':
- locale.bindtextdomain('labyrinth', localedir)
- if hasattr(locale, 'bind_textdomain_codeset'):
- locale.bind_textdomain_codeset('labyrinth','UTF-8')
- locale.textdomain('labyrinth')
+ if not os.name == 'nt':
+ locale.bindtextdomain('labyrinth', localedir)
+ if hasattr(locale, 'bind_textdomain_codeset'):
+ locale.bind_textdomain_codeset('labyrinth','UTF-8')
+ locale.textdomain('labyrinth')
gtk.glade.bindtextdomain('labyrinth')
gtk.glade.textdomain('labyrinth')
def main():
- parser = optparse.OptionParser()
- parser.add_option("--use-tray-icon", dest="tray_icon",
- action="store_true", default=False)
- parser.add_option("--no-tray-icon", dest="tray_icon",
action="store_false")
- parser.add_option("--hide-main-window", action="store_true",
default=False)
- parser.add_option("-m", "--map", action="store", type="string",
dest="filename",
- help="Open a map from a given filename (from internal database)")
- parser.add_option("-o", "--open", action="store", type="string",
- dest="filepath", help="Open a map from a given filename (including
path)")
-
- (options, args) = parser.parse_args()
- if not options.tray_icon:
- options.hide_main_window=False
-
- MapBrowser = Browser.Browser (
- start_hidden = options.hide_main_window,
- tray_icon = options.tray_icon
- )
-
- if options.filename != None:
- MapBrowser.open_map_filename (utils.get_save_dir() + options.filename)
- elif options.filepath != None:
- MapBrowser.open_map_filename (options.filepath)
-
- try:
- gtk.main()
- except:
- print "Exception caught while running. Dying a death."
- sys.exit(1)
+ parser = optparse.OptionParser()
+ parser.add_option("--use-tray-icon", dest="tray_icon",
+ action="store_true", default=False)
+ parser.add_option("--no-tray-icon", dest="tray_icon",
action="store_false")
+ parser.add_option("--hide-main-window", action="store_true",
default=False)
+ parser.add_option("-m", "--map", action="store", type="string",
dest="filename",
+ help="Open a map from a given filename (from internal
database)")
+ parser.add_option("-o", "--open", action="store", type="string",
+ dest="filepath", help="Open a map from a given filename
(including path)")
+
+ (options, args) = parser.parse_args()
+ if not options.tray_icon:
+ options.hide_main_window=False
+
+ MapBrowser = Browser.Browser (
+ start_hidden = options.hide_main_window,
+ tray_icon = options.tray_icon
+)
+
+ if options.filename != None:
+ MapBrowser.open_map_filename (utils.get_save_dir() +
options.filename)
+ elif options.filepath != None:
+ MapBrowser.open_map_filename (options.filepath)
+
+ try:
+ gtk.main()
+ except:
+ print "Exception caught while running. Dying a death."
+ sys.exit(1)
if __name__ == '__main__':
- main()
+ main()
=======================================
--- /trunk/src/prefs.py Sun Mar 11 14:08:07 2007
+++ /trunk/src/prefs.py Sat Apr 23 07:28:34 2011
@@ -15,7 +15,7 @@
#
# You should have received a copy of the GNU General Public License
# along with Labyrinth; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301 USA
#
@@ -26,13 +26,13 @@
_dirn = None
def init ():
- global _dirn
- _dirn = gtk.widget_get_default_direction ()
-
+ global _dirn
+ _dirn = gtk.widget_get_default_direction ()
+
def get_direction ():
- global _dirn
- return _dirn
-
-
+ global _dirn
+ return _dirn
+
+
init ()
=======================================
--- /trunk/src/utils.py Sat Apr 23 07:14:18 2011
+++ /trunk/src/utils.py Sat Apr 23 07:28:34 2011
@@ -31,100 +31,100 @@
__BE_VERBOSE=os.environ.get('DEBUG_LABYRINTH',0)
if __BE_VERBOSE:
- def print_debug(*data):
- sys.stderr.write("\n".join(data) + "\n")
+ def print_debug(*data):
+ sys.stderr.write("\n".join(data) + "\n")
else:
- def print_debug(*data):
- pass
+ def print_debug(*data):
+ pass
# FIXME: this is a no-go, but fast and efficient
# global variables
use_bezier_curves = False
default_colors = {
- "text" : (0.0, 0.0, 0.0),
- "fg" : (0.0, 0.0, 0.0),
- "bg" : (0.0, 0.0, 0.0),
- "base" : (0.0, 0.0, 0.0)
- }
+ "text" : (0.0, 0.0, 0.0),
+ "fg" : (0.0, 0.0, 0.0),
+ "bg" : (0.0, 0.0, 0.0),
+ "base" : (0.0, 0.0, 0.0)
+ }
selected_colors = {
- "text" : (0.0, 0.0, 0.0),
- "fg" : (0.0, 0.0, 0.0),
- "bg" : (0.0, 0.0, 0.0),
- "border" : (0.0, 0.0, 0.0), # bounding box
- "fill" : (0.0, 0.0, 0.0) # bounding box
- }
+ "text" : (0.0, 0.0, 0.0),
+ "fg" : (0.0, 0.0, 0.0),
+ "bg" : (0.0, 0.0, 0.0),
+ "border" : (0.0, 0.0, 0.0), # bounding box
+ "fill" : (0.0, 0.0, 0.0) # bounding box
+ }
default_font = None
def get_save_dir ():
- ''' Returns the path to the directory to save the maps to '''
- try:
- base = os.environ ['HOME']
- except:
- base = os.environ ['USERPROFILE']
- if os.name != 'nt':
- dirname = os.path.join (base, ".gnome2", "labyrinth"+os.sep)
- else:
- dirname = os.path.join (base, ".labyrinth"+os.sep)
- if not os.access (dirname, os.W_OK):
- os.makedirs (dirname)
- return dirname
+ ''' Returns the path to the directory to save the maps to '''
+ try:
+ base = os.environ ['HOME']
+ except:
+ base = os.environ ['USERPROFILE']
+ if os.name != 'nt':
+ dirname = os.path.join (base, ".gnome2", "labyrinth"+os.sep)
+ else:
+ dirname = os.path.join (base, ".labyrinth"+os.sep)
+ if not os.access (dirname, os.W_OK):
+ os.makedirs (dirname)
+ return dirname
def parse_coords (string):
- if string == "None":
- return None
- local = string[1:string.find(',')]
- local_2 = string[string.find (',')+1:string.find(')')]
- coord = (float(local), float(local_2))
- return coord
+ if string == "None":
+ return None
+ local = string[1:string.find(',')]
+ local_2 = string[string.find (',')+1:string.find(')')]
+ coord = (float(local), float(local_2))
+ return coord
__data_dir = None
_version = None
def get_version ():
- global _version
- if not _version:
- try:
- import defs
- _version = defs.VERSION
- except:
- _version = "Uninstalled"
- return _version
+ global _version
+ if not _version:
+ try:
+ import defs
+ _version = defs.VERSION
+ except:
+ _version = "Uninstalled"
+ return _version
def get_data_dir():
- '''returns the data dir. Tries to find it the first time its called'''
- global __data_dir
- if os.name != 'nt':
-
- if __data_dir is None:
- #decide wether we run under development or if the program has been
installed
- path = join(dirname(__file__), '..')
- if exists(path) and isdir(path) and isfile(path+"/AUTHORS"):
- __data_dir = os.sep.join([dirname(__file__), '..' , 'data'])
- else:
- try:
- import defs
- __data_dir=defs.pkgdatadir
- except:
- __data_dir = "./data"
- else:
- if __data_dir is None:
- __data_dir = join (".","data")
- return __data_dir
+ '''returns the data dir. Tries to find it the first time its called'''
+ global __data_dir
+ if os.name != 'nt':
+
+ if __data_dir is None:
+ #decide wether we run under development or if the program has
been installed
+ path = join(dirname(__file__), '..')
+ if exists(path) and isdir(path) and isfile(path+"/AUTHORS"):
+ __data_dir =
os.sep.join([dirname(__file__), '..' , 'data'])
+ else:
+ try:
+ import defs
+ __data_dir=defs.pkgdatadir
+ except:
+ __data_dir = "./data"
+ else:
+ if __data_dir is None:
+ __data_dir = join (".","data")
+ return __data_dir
def get_data_file_name (file_name):
- ''' takes a string and either returns it with the data directory
prepended.'''
- return get_data_dir() + os.sep + file_name
+ ''' takes a string and either returns it with the data directory
prepended.'''
+ return get_data_dir() + os.sep + file_name
def get_data_file (file_name):
- ''' takes a string and either returns a data file of that name or raises
an exception if it cant find it '''
- return open(get_data_file_name(file_name))
+ ''' takes a string and either returns a data file of that name or
raises an exception if it cant find it '''
+ return open(get_data_file_name(file_name))
def strip_path_from_file_name(f):
- ''' Removes the path including all leading and trailing slashes from a
filename. '''
- return f.split('/')[-1]
+ ''' Removes the path including all leading and trailing slashes from a
filename. '''
+ return f.split('/')[-1]
# Drawing functions
@@ -135,73 +135,72 @@
STYLE_EXTENDED_CONTENT = 1
def draw_thought_outline (context, ul, lr, background_color, am_root =
False, am_primary = False, style=STYLE_NORMAL):
- draw_thought_extended(context, ul, lr, am_root, am_primary,
background_color, style == STYLE_EXTENDED_CONTENT)
+ draw_thought_extended(context, ul, lr, am_root, am_primary,
background_color, style == STYLE_EXTENDED_CONTENT)
# This is used to find the required margin from the (real) ul / lr coords
to the edge of the
# box area. Makes selection of thoughts less erratic
def margin_required (style = STYLE_NORMAL):
- if style == STYLE_NORMAL:
- return margin_thought_classic ()
- else:
- print "Error: Unknown thought margine style: "+str(style)
+ if style == STYLE_NORMAL:
+ return margin_thought_classic ()
+ else:
+ print "Error: Unknown thought margine style: "+str(style)
# Classic thought style drawing code
def margin_thought_classic ():
- return (5, 5, 5, 5)
+ return (5, 5, 5, 5)
def gtk_to_cairo_color(color):
- return (color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0)
+ return (color.red / 65535.0, color.green / 65535.0, color.blue /
65535.0)
def draw_thought_extended (context, ul, lr, am_root, am_primary,
background_color, fatborder=False, dashborder=False):
- context.move_to (ul[0], ul[1]+5)
- context.line_to (ul[0], lr[1]-5)
- context.curve_to (ul[0], lr[1], ul[0], lr[1], ul[0]+5, lr[1])
- context.line_to (lr[0]-5, lr[1])
- context.curve_to (lr[0], lr[1], lr[0], lr[1], lr[0], lr[1]-5)
- context.line_to (lr[0], ul[1]+5)
- context.curve_to (lr[0], ul[1], lr[0], ul[1], lr[0]-5, ul[1])
- context.line_to (ul[0]+5, ul[1])
- context.curve_to (ul[0], ul[1], ul[0], ul[1], ul[0], ul[1]+5)
- if am_root:
- bg = selected_colors["bg"]
- context.set_source_rgb (bg[0], bg[1], bg[2])
- elif am_primary:
- context.set_source_rgb (0.937, 0.831, 0.000)
- else:
- r,g,b = gtk_to_cairo_color(background_color)
- context.set_source_rgb (r, g, b)
- context.fill_preserve ()
- context.set_source_rgb (0,0,0)
- if dashborder:
- context.set_dash([4.0], 0.0)
- if fatborder:
- orig_line_width = context.get_line_width ()
- context.set_line_width (5.0)
- context.stroke ()
- context.set_line_width (orig_line_width)
- else:
- context.stroke ()
-
- if dashborder:
- context.set_dash([], 0.0)
-
+ context.move_to (ul[0], ul[1]+5)
+ context.line_to (ul[0], lr[1]-5)
+ context.curve_to (ul[0], lr[1], ul[0], lr[1], ul[0]+5, lr[1])
+ context.line_to (lr[0]-5, lr[1])
+ context.curve_to (lr[0], lr[1], lr[0], lr[1], lr[0], lr[1]-5)
+ context.line_to (lr[0], ul[1]+5)
+ context.curve_to (lr[0], ul[1], lr[0], ul[1], lr[0]-5, ul[1])
+ context.line_to (ul[0]+5, ul[1])
+ context.curve_to (ul[0], ul[1], ul[0], ul[1], ul[0], ul[1]+5)
+ if am_root:
+ bg = selected_colors["bg"]
+ context.set_source_rgb (bg[0], bg[1], bg[2])
+ elif am_primary:
+ context.set_source_rgb (0.937, 0.831, 0.000)
+ else:
+ r,g,b = gtk_to_cairo_color(background_color)
+ context.set_source_rgb (r, g, b)
+ context.fill_preserve ()
+ context.set_source_rgb (0,0,0)
+ if dashborder:
+ context.set_dash([4.0], 0.0)
+ if fatborder:
+ orig_line_width = context.get_line_width ()
+ context.set_line_width (5.0)
+ context.stroke ()
+ context.set_line_width (orig_line_width)
+ else:
+ context.stroke ()
+
+ if dashborder:
+ context.set_dash([], 0.0)
+
# Export outline stuff
def export_thought_outline (context, ul, lr, background_color, am_root =
False, am_primary = False, style=STYLE_NORMAL, move=(0,0)):
- real_ul = (ul[0]+move[0], ul[1]+move[1])
- real_lr = (lr[0]+move[0], lr[1]+move[1])
- draw_thought_extended (context, real_ul, real_lr, False, am_primary,
background_color, style == STYLE_EXTENDED_CONTENT)
+ real_ul = (ul[0]+move[0], ul[1]+move[1])
+ real_lr = (lr[0]+move[0], lr[1]+move[1])
+ draw_thought_extended (context, real_ul, real_lr, False, am_primary,
background_color, style == STYLE_EXTENDED_CONTENT)
def pixbuf_to_cairo (pixel_array):
- result = []
- for y in pixel_array:
- row = []
- for x in y:
- color = [int(x[2][0]), int(x[1][0]), int(x[0][0])]
- if len(x) == 3:
- color.append(255)
- elif len(x) == 4:
- color.append(int(x[3][0]))
- row.append(color)
- result.append(row)
- return array(result, 'b')
-
+ result = []
+ for y in pixel_array:
+ row = []
+ for x in y:
+ color = [int(x[2][0]), int(x[1][0]), int(x[0][0])]
+ if len(x) == 3:
+ color.append(255)
+ elif len(x) == 4:
+ color.append(int(x[3][0]))
+ row.append(color)
+ result.append(row)
+ return array(result, 'b')