Ticket #1829: 0001-Added-Label-Thought-Support.patch
File 0001-Added-Label-Thought-Support.patch, 17.4 KB (added by jasg, 14 years ago) |
---|
-
new file icons/label-mode.svg
From b854758c74a87cb87b1ff8ca25ad115f0e0e5572 Mon Sep 17 00:00:00 2001 From: Jorge Saldivar <jsaldivar@paraguayeduca.org>, Martin Abente <mabente@paraguayeduca.org> Date: Mon, 15 Mar 2010 11:23:15 -0300 Subject: [PATCH] Added Label Thought Support --- icons/label-mode.svg | 73 +++++++++++++++++ labyrinthactivity.py | 15 +++- src/ImageThought.py | 2 +- src/LabelThought.py | 215 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/MMapArea.py | 26 +++++-- 5 files changed, 319 insertions(+), 12 deletions(-) create mode 100644 icons/label-mode.svg create mode 100644 src/LabelThought.py diff --git a/icons/label-mode.svg b/icons/label-mode.svg new file mode 100644 index 0000000..361ec68
- + 1 <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 <svg 3 xmlns:dc="http://purl.org/dc/elements/1.1/" 4 xmlns:cc="http://creativecommons.org/ns#" 5 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 6 xmlns:svg="http://www.w3.org/2000/svg" 7 xmlns="http://www.w3.org/2000/svg" 8 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 9 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 10 enable-background="new 0 0 55 54.696" 11 height="54.696px" 12 version="1.1" 13 viewBox="0 0 55 54.696" 14 width="55px" 15 x="0px" 16 xml:space="preserve" 17 y="0px" 18 id="svg2" 19 sodipodi:version="0.32" 20 inkscape:version="0.47pre4 r22446" 21 sodipodi:docname="label-mode.svg" 22 inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata 23 id="metadata22"><rdf:RDF><cc:Work 24 rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type 25 rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs 26 id="defs20"><inkscape:perspective 27 sodipodi:type="inkscape:persp3d" 28 inkscape:vp_x="0 : 27.348 : 1" 29 inkscape:vp_y="0 : 1000 : 0" 30 inkscape:vp_z="55 : 27.348 : 1" 31 inkscape:persp3d-origin="27.5 : 18.232 : 1" 32 id="perspective24" /> 33 34 35 36 37 </defs><sodipodi:namedview 38 inkscape:window-height="735" 39 inkscape:window-width="1264" 40 inkscape:pageshadow="2" 41 inkscape:pageopacity="0.0" 42 guidetolerance="10.0" 43 gridtolerance="10.0" 44 objecttolerance="10.0" 45 borderopacity="1.0" 46 bordercolor="#666666" 47 pagecolor="#ffffff" 48 id="base" 49 showgrid="true" 50 inkscape:zoom="8.4466873" 51 inkscape:cx="27.5" 52 inkscape:cy="27.348" 53 inkscape:window-x="0" 54 inkscape:window-y="4" 55 inkscape:current-layer="svg2" 56 inkscape:window-maximized="0"><inkscape:grid 57 type="xygrid" 58 id="grid2820" /></sodipodi:namedview><g 59 id="g2817" 60 transform="translate(0,2)" 61 style="fill:#ffffff"><rect 62 y="38.695999" 63 x="21" 64 height="5" 65 width="18" 66 id="rect2822" 67 style="fill:#ffffff;fill-opacity:1;stroke:none" /><rect 68 y="4.6959991" 69 x="17" 70 height="39" 71 width="6" 72 id="rect2824" 73 style="fill:#ffffff;fill-opacity:1;stroke:none" /></g></svg> 74 No newline at end of file -
labyrinthactivity.py
diff --git a/labyrinthactivity.py b/labyrinthactivity.py index d212c8c..954fbb4 100644
a b class LabyrinthActivity(activity.Activity): 274 274 activity_toolbar.share.props.visible = False 275 275 toolbox.set_current_toolbar(1) 276 276 277 self.mods = [None] * 4277 self.mods = [None] * 6 278 278 279 279 self.mods[0] = RadioToolButton(named_icon='select-mode') 280 280 self.mods[0].set_tooltip(_('Edit mode')) … … class LabyrinthActivity(activity.Activity): 304 304 self.mods[3].connect('clicked', self.__mode_cb, MMapArea.MODE_IMAGE) 305 305 target_toolbar.insert(self.mods[3], tool_offset + 3) 306 306 307 self.mods[5] = RadioToolButton(named_icon='label-mode') 308 self.mods[5].set_tooltip(_('Label mode')) 309 self.mods[5].set_accelerator(_('<ctrl>a')) 310 self.mods[5].set_group(self.mods[0]) 311 self.mods[5].connect('clicked', self.__mode_cb, MMapArea.MODE_LABEL) 312 target_toolbar.insert(self.mods[5], tool_offset + 4) 313 307 314 separator = gtk.SeparatorToolItem() 308 target_toolbar.insert(separator, tool_offset + 4)315 target_toolbar.insert(separator, tool_offset + 5) 309 316 310 317 tool = ToolButton('link') 311 318 tool.set_tooltip(_('Link/unlink two selected thoughts')) 312 319 tool.set_accelerator(_('<ctrl>l')) 313 320 tool.connect('clicked', self.__link_cb) 314 target_toolbar.insert(tool, tool_offset + 5)321 target_toolbar.insert(tool, tool_offset + 6) 315 322 316 323 tool = ToolButton('edit-delete') 317 324 tool.set_tooltip(_('Erase selected thought(s)')) 318 325 tool.connect('clicked', self.__delete_cb) 319 target_toolbar.insert(tool, tool_offset + 6)326 target_toolbar.insert(tool, tool_offset + 7) 320 327 321 328 self.show_all() 322 329 self._mode = MMapArea.MODE_TEXT -
src/ImageThought.py
diff --git a/src/ImageThought.py b/src/ImageThought.py index 0b3e15e..964aa99 100644
a b class ImageThought (ResizableThought): 100 100 utils.export_thought_outline (context, self.ul, self.lr, self.background_color, self.am_selected, self.am_primary, utils.STYLE_NORMAL, 101 101 (move_x, move_y)) 102 102 if self.pic: 103 103 raw_pixels = self.pic.get_pixels_array() 104 104 if hasattr(context, "set_source_pixbuf"): 105 105 context.set_source_pixbuf (self.pic, self.pic_location[0]+move_x, self.pic_location[1]+move_y) 106 106 elif hasattr(context, "set_source_surface"): -
new file src/LabelThought.py
diff --git a/src/LabelThought.py b/src/LabelThought.py new file mode 100644 index 0000000..af89073
- + 1 #! /usr/bin/env python 2 # LabelThoughts.py 3 # This file is part of Labyrinth 4 # 5 # Copyright (C) 2010 - Jorge Saldivar <jsaldivar@paraguayeduca.org> 6 # Martin Abente <mabente@paraguayeduca.org> 7 # 8 # Labyrinth is free software; you can redistribute it and/or modify 9 # it under the terms of the GNU General Public License as published by 10 # the Free Software Foundation; either version 2 of the License, or 11 # (at your option) any later version. 12 # 13 # Labyrinth is distributed in the hope that it will be useful, 14 # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 # GNU General Public License for more details. 17 # 18 # You should have received a copy of the GNU General Public License 19 # along with Labyrinth; if not, write to the Free Software 20 # Foundation, Inc., 51 Franklin St, Fifth Floor, 21 # Boston, MA 02110-1301 USA 22 # 23 24 import gtk 25 import pango 26 import utils 27 import xml.dom 28 29 from BaseThought import * 30 from TextThought import TextThought 31 32 class LabelThought (TextThought): 33 def __init__ (self, coords, pango_context, thought_number, save, undo, loading, background_color, foreground_color, name="label_thought"): 34 super (LabelThought, self).__init__(coords, pango_context, thought_number, save, undo, loading, background_color, foreground_color, name) 35 self.edge = True 36 37 def can_be_parent(self): 38 return False 39 40 def draw (self, context): 41 self.recalc_edges () 42 if self.edge: 43 ResizableThought.draw(self, context) 44 if self.creating: 45 return 46 (textx, texty) = (self.min_x, self.min_y) 47 if self.am_primary: 48 r, g, b = utils.primary_colors["text"] 49 elif (self.foreground_color): 50 r, g, b = utils.gtk_to_cairo_color(self.foreground_color) 51 else: 52 r, g ,b = utils.gtk_to_cairo_color(utils.default_colors["text"]) 53 context.set_source_rgb (r, g, b) 54 self.layout.set_alignment(pango.ALIGN_CENTER) 55 context.move_to (textx, texty) 56 context.show_layout (self.layout) 57 if self.editing: 58 if self.preedit: 59 (strong, weak) = self.layout.get_cursor_pos (self.index + self.preedit[2]) 60 else: 61 (strong, weak) = self.layout.get_cursor_pos (self.index) 62 (startx, starty, curx,cury) = strong 63 startx /= pango.SCALE 64 starty /= pango.SCALE 65 curx /= pango.SCALE 66 cury /= pango.SCALE 67 context.move_to (textx + startx, texty + starty) 68 context.line_to (textx + startx, texty + starty + cury) 69 context.stroke () 70 context.set_source_rgb (0,0,0) 71 context.stroke () 72 73 def update_save (self): 74 next = self.element.firstChild 75 while next: 76 m = next.nextSibling 77 if next.nodeName == "attribute": 78 self.element.removeChild (next) 79 next.unlink () 80 next = m 81 82 if self.text_element.parentNode is not None: 83 self.text_element.replaceWholeText (self.text) 84 text = self.extended_buffer.get_text () 85 if text: 86 self.extended_buffer.update_save() 87 else: 88 try: 89 self.element.removeChild(self.extended_buffer.element) 90 except xml.dom.NotFoundErr: 91 pass 92 self.element.setAttribute ("cursor", str(self.index)) 93 self.element.setAttribute ("ul-coords", str(self.ul)) 94 self.element.setAttribute ("lr-coords", str(self.lr)) 95 self.element.setAttribute ("identity", str(self.identity)) 96 self.element.setAttribute ("background-color", utils.color_to_string(self.background_color)) 97 self.element.setAttribute ("foreground-color", utils.color_to_string(self.foreground_color)) 98 self.element.setAttribute ("edge", str(self.edge)) 99 if self.am_selected: 100 self.element.setAttribute ("current_root", "true") 101 else: 102 try: 103 self.element.removeAttribute ("current_root") 104 except xml.dom.NotFoundErr: 105 pass 106 if self.am_primary: 107 self.element.setAttribute ("primary_root", "true"); 108 else: 109 try: 110 self.element.removeAttribute ("primary_root") 111 except xml.dom.NotFoundErr: 112 pass 113 doc = self.element.ownerDocument 114 it = self.attributes.get_iterator() 115 while (1): 116 r = it.range() 117 for x in it.get_attrs(): 118 if x.type == pango.ATTR_WEIGHT and x.value == pango.WEIGHT_BOLD: 119 elem = doc.createElement ("attribute") 120 self.element.appendChild (elem) 121 elem.setAttribute("start", str(r[0])) 122 elem.setAttribute("end", str(r[1])) 123 elem.setAttribute("type", "bold") 124 elif x.type == pango.ATTR_STYLE and x.value == pango.STYLE_ITALIC: 125 elem = doc.createElement ("attribute") 126 self.element.appendChild (elem) 127 elem.setAttribute("start", str(r[0])) 128 elem.setAttribute("end", str(r[1])) 129 elem.setAttribute("type", "italics") 130 elif x.type == pango.ATTR_UNDERLINE and x.value == pango.UNDERLINE_SINGLE: 131 elem = doc.createElement ("attribute") 132 self.element.appendChild (elem) 133 elem.setAttribute("start", str(r[0])) 134 elem.setAttribute("end", str(r[1])) 135 elem.setAttribute("type", "underline") 136 elif x.type == pango.ATTR_FONT_DESC: 137 elem = doc.createElement ("attribute") 138 self.element.appendChild (elem) 139 elem.setAttribute("start", str(r[0])) 140 elem.setAttribute("end", str(r[1])) 141 elem.setAttribute("type", "font") 142 elem.setAttribute("value", x.desc.to_string ()) 143 if not it.next(): 144 break 145 146 def load (self, node, tar): 147 self.index = int (node.getAttribute ("cursor")) 148 self.end_index = self.index 149 tmp = node.getAttribute ("ul-coords") 150 self.ul = utils.parse_coords (tmp) 151 tmp = node.getAttribute ("lr-coords") 152 self.lr = utils.parse_coords (tmp) 153 154 self.width = self.lr[0] - self.ul[0] 155 self.height = self.lr[1] - self.ul[1] 156 157 self.identity = int (node.getAttribute ("identity")) 158 try: 159 tmp = node.getAttribute ("background-color") 160 self.background_color = gtk.gdk.color_parse(tmp) 161 tmp = node.getAttribute ("foreground-color") 162 self.foreground_color = gtk.gdk.color_parse(tmp) 163 except ValueError: 164 pass 165 166 self.am_selected = node.hasAttribute ("current_root") 167 self.am_primary = node.hasAttribute ("primary_root") 168 169 if node.getAttribute ("edge") == "True": 170 self.edge = True 171 else: 172 self.edge = False 173 174 for n in node.childNodes: 175 if n.nodeType == n.TEXT_NODE: 176 self.text = n.data 177 elif n.nodeName == "Extended": 178 self.extended_buffer.load(n) 179 elif n.nodeName == "attribute": 180 attrType = n.getAttribute("type") 181 start = int(n.getAttribute("start")) 182 end = int(n.getAttribute("end")) 183 184 if attrType == "bold": 185 attr = pango.AttrWeight(pango.WEIGHT_BOLD, start, end) 186 elif attrType == "italics": 187 attr = pango.AttrStyle(pango.STYLE_ITALIC, start, end) 188 elif attrType == "underline": 189 attr = pango.AttrUnderline(pango.UNDERLINE_SINGLE, start, end) 190 elif attrType == "font": 191 font_name = str(n.getAttribute("value")) 192 pango_font = pango.FontDescription (font_name) 193 attr = pango.AttrFontDesc (pango_font, start, end) 194 self.attributes.change(attr) 195 else: 196 print "Unknown: "+n.nodeName 197 self.rebuild_byte_table () 198 self.recalc_edges() 199 200 def enter(self): 201 if self.editing: 202 return 203 self.orig_text = self.text 204 self.editing = True 205 self.edge = True 206 207 def leave(self): 208 if not self.editing: 209 return 210 ResizableThought.leave(self) 211 self.editing = False 212 self.end_index = self.index 213 self.emit ("update_links") 214 self.edge = False 215 self.recalc_edges () -
src/MMapArea.py
diff --git a/src/MMapArea.py b/src/MMapArea.py index a0a16df..5fdcf87 100644
a b 21 21 # 22 22 23 23 import math 24 25 24 import time 26 25 import gtk 27 26 import pango … … import xml.dom.minidom as dom 35 34 36 35 import Links 37 36 import TextThought 37 import LabelThought 38 38 import ImageThought 39 39 import DrawingThought 40 40 import ResourceThought … … MODE_TEXT = 1 53 53 MODE_IMAGE = 2 54 54 MODE_DRAW = 3 55 55 MODE_RESOURCE = 4 56 MODE_LABEL = 5 56 57 57 58 VIEW_LINES = 0 58 59 VIEW_BEZIER = 1 … … class MMapArea (gtk.DrawingArea): 534 535 else: 535 536 map(lambda x : x.unselect(), self.selected) 536 537 self.selected = [thought] 537 self.current_root = [] 538 if thought.can_be_parent(): 539 self.current_root = [] 538 540 for x in self.selected: 539 541 if x.can_be_parent(): 540 542 self.current_root.append(x) … … class MMapArea (gtk.DrawingArea): 723 725 724 726 if type == MODE_TEXT: 725 727 thought = TextThought.TextThought (coords, self.pango_context, self.nthoughts, self.save, self.undo, loading, self.background_color, self.foreground_color) 728 elif type == MODE_LABEL: 729 thought = LabelThought.LabelThought (coords, self.pango_context, self.nthoughts, self.save, self.undo, loading, self.background_color, self.foreground_color) 726 730 elif type == MODE_IMAGE: 727 731 thought = ImageThought.ImageThought (coords, self.pango_context, self.nthoughts, self.save, self.undo, loading, self.background_color, self.foreground_color) 728 732 elif type == MODE_DRAW: … … class MMapArea (gtk.DrawingArea): 1022 1026 for node in top_element.childNodes: 1023 1027 if node.nodeName == "thought": 1024 1028 self.load_thought (node, MODE_TEXT, tar) 1029 elif node.nodeName == "label_thought": 1030 self.load_thought (node, MODE_LABEL, tar) 1025 1031 elif node.nodeName == "image_thought": 1026 1032 self.load_thought (node, MODE_IMAGE, tar) 1027 1033 elif node.nodeName == "drawing_thought": … … class MMapArea (gtk.DrawingArea): 1167 1173 def link_menu_cb (self): 1168 1174 if len (self.selected) != 2: 1169 1175 return 1176 if not self.selected[0].can_be_parent() or \ 1177 not self.selected[1].can_be_parent(): 1178 return 1170 1179 lnk = None 1171 1180 for l in self.links: 1172 1181 if l.connects (self.selected[0], self.selected[1]): … … class MMapArea (gtk.DrawingArea): 1225 1234 1226 1235 if not thought: 1227 1236 return True 1228 if not self.primary: 1229 self.make_primary (thought) 1230 self.select_thought (thought, None) 1237 if not self.primary and \ 1238 thought.can_be_parent(): 1239 self.make_primary (thought) 1240 self.select_thought (thought, None) 1231 1241 else: 1232 1242 self.emit ("change_buffer", thought.extended_buffer) 1233 1243 self.hookup_im_context (thought) … … class MMapArea (gtk.DrawingArea): 1235 1245 self.undo.block () 1236 1246 if not self.current_root: 1237 1247 self.current_root.append(self.primary) 1238 for x in self.current_root: 1239 self.create_link (x, None, thought) 1248 if thought.can_be_parent(): 1249 for x in self.current_root: 1250 if x.can_be_parent(): 1251 self.create_link (x, None, thought) 1240 1252 for x in self.selected: 1241 1253 x.unselect () 1242 1254 self.selected = [thought]