# This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ###Sketch Config #type = PluginCompound #class_name = 'MultilineText' #menu_text = 'Multiline Text' #standard_messages = 1 #custom_dialog = 'MultilineTextDlg' ###End (''"Multiline Text") import Tkinter from Tkconstants import * from Tkinter import StringVar, Entry, Label, Button, Frame, Text, END, \ BOTH, LEFT, TOP, X, W, GROOVE, Frame, Label, StringVar, Radiobutton import os from string import split, rstrip from types import StringType from math import ceil import Sketch.const from Sketch import Scale, TrafoPlugin, SimpleText, Translation, Identity, \ GetFont, StandardColors, SolidPattern, UndoAfter, _ from Sketch.UI.sketchdlg import SketchPanel from Lib.multilinetext.TextEditor import TextEditor, FONTS, Style, \ raw2styling, styling2raw from Lib.multilinetext.chunker import Chunker class MultilineText(TrafoPlugin): class_name = 'MultilineText' has_edit_mode = 0 is_Text = 0 is_SimpleText = 0 is_curve = 0 is_clip = 0 has_font = 0 has_fill = 0 has_line = 0 is_Group = 1 Ungroup = TrafoPlugin.GetObjects def __init__(self, text = '', styling = [], trafo = None, loading = 0, duplicate = None): self.objects = [] TrafoPlugin.__init__(self, trafo = trafo, duplicate = duplicate) if duplicate is not None: self.text = duplicate.text self.styling = duplicate.styling[:] else: self.text = text if loading: # XXX a bit ugly raw = styling styling = raw2styling(raw) self.styling = styling if not loading: self.recompute() def recompute(self): chunker = Chunker(rstrip(self.text), self.styling, '\t') objects = [] options = {} x = 0 y = 0 maxy = 0 line = [] while not chunker.eof(): text, styles = chunker.get() family = styles['family'].options color = styles['color'].options fill = SolidPattern(getattr(StandardColors, color)) # XXX should be done in advance size = styles['size'].options bold = styles['bold'].options italic = styles['italic'].options if bold and italic: attr = ['Bold Italic', 'Bold Oblique', 'Demi Oblique', 'Demi Italic', 'Medium Italic', 'Demi Bold Italic'] elif bold: attr = ['Bold', 'Demi', 'Medium', 'Demi Bold'] elif italic: attr = ['Italic', 'Oblique', 'Book Oblique', 'Light Italic', 'Regular Oblique', 'Regular Italic'] else: attr = ['Roman', 'Book', 'Light', 'Regular'] supersub = styles['supersub'].options if len(text)>0: height = 1.2*size # XXX is that ok ? if maxy 0: y = y-maxy else: y = y-size maxy = 0 x = 0 for obj in line: obj.Transform(self.trafo(Translation(0, y))) line = [] elif reason == '\t': x = x+width+size # # XXX this is very provisional x = ceil(x/50.)*50. else: x = x+width # XXX this is a problem: what happens, if the MultilineText onbject # is empty ?? #~ if len(objects)>0: self.set_objects(objects) def SetParameters(self, params): return TrafoPlugin.SetParameters(self, params) def Transform(self, trafo): return self.set_transformation(trafo(self.trafo)) def Text(self): return self.text def Styling(self): return self.styling def SaveToFile(self, file): raw = styling2raw(self.styling) TrafoPlugin.SaveToFile(self, file, self.text, raw, self.trafo.coeff()) def AsBezier(self): return self.objects[0].AsBezier() def Paths(self): return self.objects[0].Paths() class MultilineTextDlg(SketchPanel): title = _("Multiline Text") class_name = "MultilineTextPanel" receivers = SketchPanel.receivers[:] def __init__(self, master, main_window, doc): SketchPanel.__init__(self, master, main_window, doc, name = 'multilinetxtdlg') receivers.append((Sketch.const.SELECTION, 'Update')) def Update(self): """ This method is used as a callback and is automatically called when the selection changes """ # get selection selections = self.document.SelectedObjects() if len(selections) == 1: selected = selections[0] if selected.is_Plugin and selected.class_name == 'MultilineText': self.set_text(selected.text) self.set_styling(selected.styling) return self.set_text('') self.set_styling([]) def init_from_doc(self): """ Called whenever the document changes and from __init__ """ self.Update() def build_dlg(self): top = self.top self.text = '' text_field = TextEditor(top, background = 'white', width = 40, height = 20) text_field.pack(fill = BOTH, expand = 1) text_field.button_apply.configure(command=self.apply) text_field.warn = self.report_error self.text_field = text_field def report_error(self, title, message): app = self.main_window.application app.MessageBox(title = title, message = message, icon = 'warning') def get_text(self): tk = self.master.tk return tk.utf8_to_latin1(self.text_field.get('1.0', 'end')[:-1]) def get_styling(self): return self.text_field.styling_get('1.0', 'end') def set_text(self, text): self.text_field.delete('1.0', 'end') self.text_field.insert('end', text) def set_styling(self, styling): if len(styling) == 0: self.text_field.style_removeall() else: self.text_field.styling_apply('1.0', styling) def apply(self): text = self.get_text() styling = self.get_styling() doc = self.document selections = doc.SelectedObjects() if len(selections) == 1: selected = selections[0] if selected.is_Plugin and selected.class_name =='MultilineText': doc.BeginTransaction(_("Set MultilineText Parameters")) try: try: params = {} params["text"] = text params["styling"] = styling doc.AddUndo(selected.SetParameters(params)) except: doc.AbortTransaction() finally: doc.EndTransaction() return object = MultilineText(text, styling) self.main_window.PlaceObject(object)