1# ------------------------------------------------------------------------------ 2# 3# Copyright (c) 2005, Enthought, Inc. 4# All rights reserved. 5# 6# This software is provided without warranty under the terms of the BSD 7# license included in LICENSE.txt and may be redistributed only 8# under the conditions described in the aforementioned license. The license 9# is also available online at http://www.enthought.com/licenses/BSD.txt 10# 11# Thanks for using Enthought open source! 12# 13# Author: David C. Morrill 14# Date: 10/18/2004 15# 16# ------------------------------------------------------------------------------ 17 18""" Defines the abstract ViewElement class that all trait view template items 19 (i.e., View, Group, Item, Include) derive from. 20""" 21 22import re 23 24from traits.api import AbstractViewElement, Bool, HasPrivateTraits, Instance 25 26from .ui_traits import ( 27 AnObject, 28 DockStyle, 29 EditorStyle, 30 ExportType, 31 HelpId, 32 Image, 33) 34 35 36label_pat = re.compile(r"^(.*)\[(.*)\](.*)$", re.MULTILINE | re.DOTALL) 37label_pat2 = re.compile(r"^(.*){(.*)}(.*)$", re.MULTILINE | re.DOTALL) 38 39# ------------------------------------------------------------------------- 40# 'ViewElement' class (abstract): 41# ------------------------------------------------------------------------- 42 43 44class ViewElement(HasPrivateTraits): 45 """ An element of a view. 46 """ 47 48 def replace_include(self, view_elements): 49 """ Searches the current object's **content** attribute for objects that 50 have an **id** attribute, and replaces each one with an Include object 51 with the same **id** value, and puts the replaced object into the 52 specified ViewElements object. 53 54 Parameters 55 ---------- 56 view_elements : ViewElements object 57 Object containing Group, Item, and Include objects 58 """ 59 pass # Normally overridden in a subclass 60 61 def is_includable(self): 62 """ Returns whether the object is replacable by an Include object. 63 """ 64 return False # Normally overridden in a subclass 65 66 67class DefaultViewElement(ViewElement): 68 """ A view element that can be used as a default value for traits whose 69 value is a view element. 70 """ 71 72 # ------------------------------------------------------------------------- 73 # Trait definitions: 74 # ------------------------------------------------------------------------- 75 76 #: The default context object to edit: 77 object = AnObject 78 79 #: The default editor style to use: 80 style = EditorStyle 81 82 #: The default dock style to use: 83 dock = DockStyle 84 85 #: The default notebook tab image to use: 86 image = Image 87 88 #: The category of elements dragged out of the view: 89 export = ExportType 90 91 #: Should labels be added to items in a group? 92 show_labels = Bool(True) 93 94 95# ------------------------------------------------------------------------- 96# Trait definitions: 97# ------------------------------------------------------------------------- 98 99# The container trait used by ViewSubElements: 100Container = Instance(ViewElement, factory=DefaultViewElement) 101 102# ------------------------------------------------------------------------- 103# 'ViewSubElement' class (abstract): 104# ------------------------------------------------------------------------- 105 106 107class ViewSubElement(ViewElement): 108 """ Abstract class representing elements that can be contained in a view. 109 """ 110 111 # ------------------------------------------------------------------------- 112 # Trait definitions: 113 # ------------------------------------------------------------------------- 114 115 #: The object this ViewSubElement is contained in; must be a ViewElement. 116 container = Container 117 118 #: External help context identifier: 119 help_id = HelpId 120 121 def _split(self, name, value, char, finder, assign, result): 122 """ Splits a string at a specified character. 123 """ 124 col = finder(value, char) 125 if col < 0: 126 return value 127 128 items = (value[:col].strip(), value[col + 1:].strip()) 129 if items[assign] != "": 130 setattr(self, name, items[assign]) 131 132 return items[result] 133 134 def _option(self, string, option, name, value): 135 """ Sets a object trait if a specified option string is found. 136 """ 137 col = string.find(option) 138 if col >= 0: 139 string = string[:col] + string[col + len(option):] 140 setattr(self, name, value) 141 142 return string 143 144 def _parse_style(self, value): 145 """ Parses any of the one-character forms of the **style** trait. 146 """ 147 value = self._option(value, "$", "style", "simple") 148 value = self._option(value, "@", "style", "custom") 149 value = self._option(value, "*", "style", "text") 150 value = self._option(value, "~", "style", "readonly") 151 value = self._split("style", value, ";", str.rfind, 1, 0) 152 153 return value 154 155 def _parse_label(self, value): 156 """ Parses a '[label]' value from the string definition. 157 """ 158 match = label_pat.match(value) 159 if match is not None: 160 self._parsed_label() 161 else: 162 match = label_pat2.match(value) 163 164 empty = False 165 if match is not None: 166 self.label = match.group(2).strip() 167 empty = self.label == "" 168 value = match.group(1) + match.group(3) 169 170 return (value, empty) 171 172 def _parsed_label(self): 173 """ Handles a label being found in the string definition. 174 """ 175 pass 176 177 def _repr_value(self, value, prefix="", suffix="", ignore=""): 178 """ Returns a "pretty print" version of a specified Item trait value. 179 """ 180 if value == ignore: 181 return "" 182 183 return "%s%s%s" % (prefix, value, suffix) 184 185 def _repr_options(self, *names): 186 """ Returns a 'pretty print' version of a list of traits. 187 """ 188 result = [] 189 for name in names: 190 value = getattr(self, name) 191 if value != self.trait(name).default_value_for(self, name): 192 result.append((name, repr(value))) 193 194 if len(result) > 0: 195 n = max([len(name) for name, value in result]) 196 return ",\n".join( 197 ["%s = %s" % (name.ljust(n), value) for name, value in result] 198 ) 199 200 return None 201 202 def _indent(self, string, indent=" "): 203 """ Indents each line in a specified string by 4 spaces. 204 """ 205 return "\n".join([indent + s for s in string.split("\n")]) 206 207 208# Register ViewElement as implementing AbstractViewElement 209# TODO: eventually have ViewElement inherit directly 210AbstractViewElement.register(ViewElement) 211