~ubuntu-branches/ubuntu/hardy/gnue-common/hardy

« back to all changes in this revision

Viewing changes to src/formatting/BaseMask.py

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Mitchell
  • Date: 2005-03-09 11:06:31 UTC
  • Revision ID: james.westby@ubuntu.com-20050309110631-8gvvn39q7tjz1kj6
Tags: upstream-0.5.14
ImportĀ upstreamĀ versionĀ 0.5.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# This file is part of GNU Enterprise.
 
3
#
 
4
# GNU Enterprise is free software; you can redistribute it
 
5
# and/or modify it under the terms of the GNU General Public
 
6
# License as published by the Free Software Foundation; either
 
7
# version 2, or (at your option) any later version.
 
8
#
 
9
# GNU Enterprise is distributed in the hope that it will be
 
10
# useful, but WITHOUT ANY WARRANTY; without even the implied
 
11
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 
12
# PURPOSE. See the GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public
 
15
# License along with program; see the file COPYING. If not,
 
16
# write to the Free Software Foundation, Inc., 59 Temple Place
 
17
# - Suite 330, Boston, MA 02111-1307, USA.
 
18
#
 
19
# Copyright 2001-2005 Free Software Foundation
 
20
#
 
21
# FILE:
 
22
# BaseMask.py
 
23
#
 
24
# DESCRIPTION:
 
25
#
 
26
# NOTES:
 
27
#
 
28
 
 
29
from gnue.common.apps import GDebug
 
30
from FormatExceptions import *
 
31
 
 
32
# TODO: i18n
 
33
#   import locale
 
34
#   locale.nl_langinfo(  option)
 
35
#
 
36
#   Return some locale-specific information as a string. This function is
 
37
#   not available on all systems, and the set of possible options might
 
38
#   also vary across platforms. The possible argument values are numbers,
 
39
#   for which symbolic constants are available in the locale module.
 
40
#
 
41
#   DAY_1 ... DAY_7
 
42
#   Return name of the n-th day of the week.
 
43
#
 
44
#   ABDAY_1 ... ABDAY_7
 
45
#   Return abbreviated name of the n-th day of the week.
 
46
#
 
47
#   MON_1 ... MON_12
 
48
#   Return name of the n-th month.
 
49
#
 
50
#   ABMON_1 ... ABMON_12
 
51
#   Return abbreviated name of the n-th month.
 
52
 
 
53
 
 
54
# This is a class for a mask literal element
 
55
class Literal:
 
56
  def __init__(self, literal):
 
57
    self.literal = literal
 
58
 
 
59
  def getFormattedValue(self, value):
 
60
    return self.literal
 
61
 
 
62
  def isValidEntry(self, value):
 
63
    return value == self.literal
 
64
 
 
65
  def isCompleteEntry(self, value):
 
66
    return 0
 
67
 
 
68
class BaseMask:
 
69
  value = ""
 
70
  maskMappings = {}
 
71
  inputHandlers = []
 
72
  outputHandlers = []
 
73
  output2Handlers = []
 
74
  predefinedLiterals = ""
 
75
  basetype = "base"
 
76
  defaultmask = ""
 
77
  literalClass = Literal
 
78
 
 
79
  def __init__(self, outputMask, inputMask=None, outputMask2=None):
 
80
 
 
81
    self.outputHandlers  = self.parseMask(outputMask)
 
82
    print "Creating mask handler: %s;%s" % (outputMask,inputMask)
 
83
    print self.outputHandlers
 
84
    
 
85
    if inputMask != None:
 
86
      self.inputHandlers = self.parseMask(inputMask)
 
87
    if outputMask2 != None:
 
88
      self.output2Handlers = self.parseMask(outputMask2)
 
89
 
 
90
    # Calculate our array lengths once to speed up
 
91
    # our code. This should always be equivalent to:
 
92
    #   len(self.inputHandlers)
 
93
    #   len(self.inputMaskPos)
 
94
    #   len(self.inputMaskLen)
 
95
    #   len(self.inputDisplayLen)
 
96
    self.inputCount = len(self.inputHandlers)
 
97
 
 
98
    self.reset()
 
99
 
 
100
 
 
101
  def reset(self):
 
102
 
 
103
    # Holds the starting positions of each element section...
 
104
    self.inputMaskPos = [0] * self.inputCount
 
105
 
 
106
    # Holds the length of each element section...
 
107
    self.inputMaskLen = [0] * self.inputCount
 
108
 
 
109
    # Holds the length of each formatted element section...
 
110
    self.inputDisplayLen = [0] * self.inputCount
 
111
    # .. including padding
 
112
    self.inputFormattedLen = [0] * self.inputCount
 
113
 
 
114
 
 
115
    self.index = 0
 
116
    self.cursor = 0
 
117
    self.display = ""
 
118
    self.input = ""
 
119
 
 
120
 
 
121
  # Take a mask string and break it into its elements and map it to handlers
 
122
  def parseMask(self, mask, edit=0):
 
123
    GDebug.printMesg(7,'parseMask("%s")' % mask)
 
124
    maskHandler = []
 
125
 
 
126
    # Load a predefined mask, if that's what user specified
 
127
    # TODO: Should predefined masks be pulled from other than gnue.conf?
 
128
    if len(mask) > 1 and mask[0] == '&':
 
129
      for i in range(edit+1):
 
130
        edstr = ('edit','')[i]
 
131
        if mask[1:] == self.basetype:
 
132
          try:
 
133
            mask = gConfig('%s%smask' % (self.basetype, edstr), self.defaultmask)
 
134
          except KeyError: 
 
135
            pass
 
136
        else:
 
137
          try:
 
138
            mask = gConfig('%smask_%s' % (self.basetype, edstr, mask[1:]))
 
139
          except KeyError:
 
140
            pass
 
141
      if not len(mask):
 
142
        tmsg =  u_('The requested format mask "%(mask)s" is not defined for '
 
143
                   '%(type)s fields') \
 
144
                % {'mask': mask [1:],
 
145
                   'type': self.basetype}
 
146
        raise PredefinedMaskNotFound, tmsg
 
147
 
 
148
    # Process each character in mask at a time
 
149
    isLiteral = 0
 
150
    for ch in mask:
 
151
      if ch == '\\':
 
152
        isLiteral = 1
 
153
      elif isLiteral or ch in self.predefinedLiterals:
 
154
        isLiteral = 0
 
155
        maskHandler.append(self.literalClass(ch))
 
156
      elif self.maskMappings.has_key(ch):
 
157
        maskHandler.append(self.maskMappings[ch])
 
158
      else:
 
159
        tmsg = u_('Unexpected character "%(char)s" in %(type)s mask.') \
 
160
               % {'char': ch,
 
161
                  'type': self.basetype}
 
162
        raise InvalidCharInMask, tmsg
 
163
 
 
164
    return maskHandler
 
165
 
 
166
  # If secondary is true, then use secondary mask (outputMask2)
 
167
  def getFormattedOutput(self, secondary=0):
 
168
    pass
 
169
 
 
170
  def getFormattedInput(self):
 
171
    pass
 
172
 
 
173
 
 
174
  def setText(self, text):
 
175
    self.input = text
 
176
    self.display = text
 
177
    self.reset()
 
178
 
 
179
  def isValid(self):
 
180
    return 1
 
181
 
 
182
  # Returns (value, formatted text, cursor)
 
183
  def addText(self, value, text, pos, replaces=0, padding="_"):
 
184
    shift = 0
 
185
    cursor = self.cursor
 
186
    for size in self.inputDisplayLen:
 
187
      shift -= size
 
188
 
 
189
    print "Starting cursor: %s; shift: %s" % (cursor, shift)
 
190
 
 
191
 
 
192
    value = self.processEdit(value, text, pos, replaces)
 
193
    formatted = self.getFormattedInput(value,padding=padding)
 
194
 
 
195
    for size in self.inputDisplayLen:
 
196
      shift += size
 
197
 
 
198
    self.cursor = cursor + shift
 
199
    self.moveCursorRelative(0)
 
200
 
 
201
    print "Ending cursor: %s; shift: %s" % (self.cursor, shift)
 
202
 
 
203
    return (value, formatted, self.cursor)
 
204
 
 
205
 
 
206
 
 
207
  # Returns (value, formatted text, cursor)
 
208
  def deleteText(self, text, pos, characters):
 
209
    pass
 
210
 
 
211
 
 
212
 
 
213
  #
 
214
  # Given a display cursor, calculate the index into the string
 
215
  #
 
216
  def cursorToIndex(self, cursor):
 
217
    # TODO
 
218
    pos = 0
 
219
    index = 0
 
220
    i = 0
 
221
    while ( i < self.inputCount - 1      ) and \
 
222
          ( cursor < pos + self.inputDisplayLen[i] ) :
 
223
      pos += self.inputDisplayLen[i]
 
224
      i += 1
 
225
 
 
226
 
 
227
    diff = cursor - pos - self.inputDisplayLen[i]
 
228
    if diff > self.inputMaskLen[i]:
 
229
      diff = self.inputMaskLen[i]
 
230
 
 
231
    return max(self.inputMaskPos[i] + diff,0)
 
232
 
 
233
 
 
234
  #
 
235
  # Given an index into the string, calculate the display cursor,
 
236
  #
 
237
  def indexToCursor(self, index):
 
238
 
 
239
    i = 0
 
240
    while ( i < self.inputCount - 1 ) and \
 
241
          ( index < self.inputMaskPos[i] ) :
 
242
      i += 1
 
243
 
 
244
    pos = self.inputMaskPos[i]
 
245
 
 
246
    diff = index - pos - self.inputMaskLen[i]
 
247
 
 
248
    # TODO
 
249
    return max(pos + diff,0)
 
250
 
 
251
 
 
252
  #
 
253
  # Move cursor using relative units
 
254
  #
 
255
  # If relative > 0, move cursor to the right <relative> units
 
256
  # If relative < 0, move cursor to the left |<relative>| units
 
257
  # This takes into account Literals, etc.
 
258
  #
 
259
  def moveCursorRelative(self, relative):
 
260
 
 
261
    print "*** moveCursorRelative(%s)" % relative
 
262
 
 
263
    # Direction = -1 (left) or 1 (right).
 
264
    direction = relative == 0 or int(relative/abs(relative))
 
265
 
 
266
    print "relative=%s" % relative
 
267
    print "direction=%s" % direction
 
268
 
 
269
    self.cursor = self.cursor + relative
 
270
 
 
271
    print "cursor #1: %s" % self.cursor
 
272
 
 
273
    if self.cursor <= 0:
 
274
      self.cursor = 0
 
275
      self.direction = 1
 
276
    elif self.cursor > len(self.display):
 
277
      self.cursor = len(self.display)
 
278
      self.direction = -1
 
279
 
 
280
    print "cursor #2: %s" % self.cursor
 
281
 
 
282
    pos = 0
 
283
    section = 0
 
284
    while section < self.inputCount and \
 
285
          ((pos + self.inputDisplayLen[section]) < self.cursor):
 
286
 
 
287
      pos += self.inputDisplayLen[section]
 
288
      print "%s; %s" %(section, pos)
 
289
      section += 1
 
290
 
 
291
 
 
292
    print "pos=%s" % pos
 
293
    print "section=%s" % pos
 
294
 
 
295
    if pos + self.inputFormattedLen[section] == self.cursor:
 
296
      print "cursor #2b: %s" % self.cursor
 
297
      section += direction
 
298
 
 
299
    print "section=%s" % section
 
300
 
 
301
    if section == self.inputCount:
 
302
#      self.cursor = pos + self.inputDisplayLen[-1]
 
303
      print "cursor #3: %s" % self.cursor
 
304
      section -= 1
 
305
 
 
306
 
 
307
 
 
308
    print "section=%s" % section
 
309
    if isinstance(self.inputHandlers[section], Literal):
 
310
      self.moveCursorRelative(direction)
 
311
      print "cursor #4: %s" % self.cursor
 
312
 
 
313
    self.index = self.cursorToIndex(self.cursor)
 
314
 
 
315
    print "New cursor position: %s" % self.cursor
 
316
 
 
317
    return self.cursor
 
318
 
 
319
 
 
320
  #
 
321
  # Move cursor to the beginning of the field
 
322
  #
 
323
  def moveCursorToBegin(self):
 
324
 
 
325
    # Reset cursor to beginning
 
326
    self.cursor = 0
 
327
    self.index = 0
 
328
 
 
329
    # This will handle if the first character is a literal
 
330
    # (e.g., for phone numbers (999) 999-9999, this will move
 
331
    # to the first '9', not the '('
 
332
    return self.moveCursorRelative(0)
 
333
 
 
334
 
 
335
  #
 
336
  # Move cursor to the beginning of the field
 
337
  #
 
338
  def moveCursorToEnd(self):
 
339
 
 
340
    # Reset cursor to beginning
 
341
    self.cursor = self.indexToCursor(self.lastInputPos)
 
342
 
 
343
    return self.moveCursorRelative(0)
 
344
 
 
345
 
 
346
 
 
347
  #
 
348
  # Edit the value
 
349
  #
 
350
  def processEdit (self, value, str, pos=0, replaces=0):
 
351
    print "-"*50
 
352
    GDebug.printMesg(7,'processEdit(%s,%s,%s,%s)' % (value,str,pos,replaces))
 
353
    nv = value
 
354
 
 
355
    if pos == len(nv):
 
356
      nv += str
 
357
    else:
 
358
      nv = "%s%s%s" % (nv[:pos],str,nv[pos+replaces:])
 
359
 
 
360
    GDebug.printMesg(7,"inputMaskPos=%s" % self.inputMaskPos)
 
361
 
 
362
    print "pos=%s"%pos
 
363
 
 
364
    section = 0
 
365
    while section < self.inputCount and \
 
366
          self.inputMaskPos[section] < pos and \
 
367
          self.inputMaskPos[section] > 0:
 
368
      section += 1
 
369
    i = pos
 
370
 
 
371
    # Debug...
 
372
    section = 0
 
373
    i = 0
 
374
 
 
375
    while i < len(nv):
 
376
      if not self.inputHandlers[section]\
 
377
           .isValidEntry(nv[self.inputMaskPos[section]:i+1]):
 
378
        if i == self.inputMaskPos[section] and \
 
379
           not isinstance(self.inputHandlers[section],Literal):
 
380
          self.inputMaskLen[section] = i - self.inputMaskPos[section]
 
381
          return nv
 
382
        else:
 
383
          self.inputMaskLen[section] = i - self.inputMaskPos[section]
 
384
          if section == self.inputCount - 1:
 
385
            if i != len(nv)-1:
 
386
              return nv
 
387
            else:
 
388
              break
 
389
          else:
 
390
            section += 1
 
391
            self.inputMaskPos[section] = i
 
392
            self.inputMaskLen[section] = 0
 
393
      else:
 
394
        i += 1
 
395
 
 
396
    self.inputMaskLen[section] = i - self.inputMaskPos[section]
 
397
 
 
398
    for i in range(section+1, self.inputCount):
 
399
      self.inputMaskLen[i] = 0
 
400
 
 
401
    self.index = pos + len(value)
 
402
    self.cursor = self.indexToCursor(self.index)
 
403
    print "after processEdit, index=%s;cursor=%s" % (self.index, self.cursor)
 
404
 
 
405
    GDebug.printMesg(7,"<< %s" % nv)
 
406
    return nv
 
407
 
 
408
 
 
409
 
 
410
# This is a base class for mask elements
 
411
class MaskSection:
 
412
 
 
413
  def __init__(self):
 
414
    self.minLength = 0
 
415
    self.maxLength = 0
 
416
 
 
417
    self.intersperse = 0
 
418
    self.intersperseString = ","
 
419
    self.intersperseRepeat = 1
 
420
 
 
421
 
 
422
  def getFormattedValue(self):
 
423
    return self.value
 
424
 
 
425
  def isValidEntry(self, value):
 
426
    return 0
 
427
 
 
428
  def isCompleteEntry(self, value):
 
429
    return len(value) == self.maxLength
 
430
 
 
431
 
 
432