X-Git-Url: https://scm.cri.ensmp.fr/git/minwii.git/blobdiff_plain/346a9b8e1fcfe30629f0d1ee4675e9e8f89890cf..4c4732c6ed8cb0aaa70fb2d4c6e5a958868c5349:/src/pgu/gui/textarea.py diff --git a/src/pgu/gui/textarea.py b/src/pgu/gui/textarea.py deleted file mode 100644 index 667076a..0000000 --- a/src/pgu/gui/textarea.py +++ /dev/null @@ -1,287 +0,0 @@ -""" -""" -import pygame -from pygame.locals import * - -from const import * -import widget - -class TextArea(widget.Widget): - """A multi-line text input. - -
TextArea(value="",width = 120, height = 30, size=20)
- -
-
value
initial text -
size
size for the text box, in characters -
- - Example - - w = TextArea(value="Cuzco the Goat",size=20) - - w = TextArea("Marbles") - - w = TextArea("Groucho\nHarpo\nChico\nGummo\nZeppo\n\nMarx", 200, 400, 12) - - - """ - def __init__(self,value="",width = 120, height = 30, size=20,**params): - params.setdefault('cls','input') - params.setdefault('width', width) - params.setdefault('height', height) - - widget.Widget.__init__(self,**params) - self.value = value # The value of the TextArea - self.pos = len(str(value)) # The position of the cursor - self.vscroll = 0 # The number of lines that the TextArea is currently scrolled - self.font = self.style.font # The font used for rendering the text - self.cursor_w = 2 # Cursor width (NOTE: should be in a style) - w,h = self.font.size("e"*size) - if not self.style.height: self.style.height = h - if not self.style.width: self.style.width = w - - def resize(self,width=None,height=None): - if (width != None) and (height != None): - self.rect = pygame.Rect(self.rect.x, self.rect.y, width, height) - return self.rect.w, self.rect.h - - def paint(self,s): - - # TODO: What's up with this 20 magic number? It's the margin of the left and right sides, but I'm not sure how this should be gotten other than by trial and error. - max_line_w = self.rect.w - 20 - - # Update the line allocation for the box's value - self.doLines(max_line_w) - - # Make sure that the vpos and hpos of the cursor is set properly - self.updateCursorPos() - - # Make sure that we're scrolled vertically such that the cursor is visible - if (self.vscroll < 0): - self.vscroll = 0 - if (self.vpos < self.vscroll): - self.vscroll = self.vpos - elif ((self.vpos - self.vscroll + 1) * self.line_h > self.rect.h): - self.vscroll = - (self.rect.h / self.line_h - self.vpos - 1) - - # Blit each of the lines in turn - cnt = 0 - for line in self.lines: - line_pos = (0, (cnt - self.vscroll) * self.line_h) - if (line_pos[1] >= 0) and (line_pos[1] < self.rect.h): - s.blit( self.font.render(line, 1, self.style.color), line_pos ) - cnt += 1 - - # If the textarea is focused, then also show the cursor - if self.container.myfocus is self: - r = self.getCursorRect() - s.fill(self.style.color,r) - - # This function updates self.vpos and self.hpos based on self.pos - def updateCursorPos(self): - self.vpos = 0 # Reset the current line that the cursor is on - self.hpos = 0 - - line_cnt = 0 - char_cnt = 0 - - for line in self.lines: - line_char_start = char_cnt # The number of characters at the start of the line - - # Keep track of the character count for words - char_cnt += len(line) - - # If our cursor count is still less than the cursor position, then we can update our cursor line to assume that it's at least on this line - if (char_cnt > self.pos): - self.vpos = line_cnt - self.hpos = self.pos - line_char_start - - break # Now that we know where our cursor is, we exit the loop - - line_cnt += 1 - - if (char_cnt <= self.pos) and (len(self.lines) > 0): - self.vpos = len(self.lines) - 1 - self.hpos = len(self.lines[ self.vpos ] ) - - # Returns a rectangle that is of the size and position of where the cursor is drawn - def getCursorRect(self): - lw = 0 - if (len(self.lines) > 0): - lw, lh = self.font.size( self.lines[ self.vpos ][ 0:self.hpos ] ) - - r = pygame.Rect(lw, (self.vpos - self.vscroll) * self.line_h, self.cursor_w, self.line_h) - return r - - # This function sets the cursor position according to an x/y value (such as by from a mouse click) - def setCursorByXY(self, (x, y)): - self.vpos = ((int) (y / self.line_h)) + self.vscroll - if (self.vpos >= len(self.lines)): - self.vpos = len(self.lines) - 1 - - currentLine = self.lines[ self.vpos ] - - for cnt in range(0, len(currentLine) ): - self.hpos = cnt - lw, lh = self.font.size( currentLine[ 0:self.hpos + 1 ] ) - if (lw > x): - break - - lw, lh = self.font.size( currentLine ) - if (lw < x): - self.hpos = len(currentLine) - - self.setCursorByHVPos() - - # This function sets the cursor position by the horizontal/vertical cursor position. - def setCursorByHVPos(self): - line_cnt = 0 - char_cnt = 0 - - for line in self.lines: - line_char_start = char_cnt # The number of characters at the start of the line - - # Keep track of the character count for words - char_cnt += len(line) - - # If we're on the proper line - if (line_cnt == self.vpos): - # Make sure that we're not trying to go over the edge of the current line - if ( self.hpos >= len(line) ): - self.hpos = len(line) - 1 - # Set the cursor position - self.pos = line_char_start + self.hpos - break # Now that we've set our cursor position, we exit the loop - - line_cnt += 1 - - # Splits up the text found in the control's value, and assigns it into the lines array - def doLines(self, max_line_w): - self.line_h = 10 - self.lines = [] # Create an empty starter list to start things out. - - inx = 0 - line_start = 0 - while inx >= 0: - # Find the next breakable whitespace - # HACK: Find a better way to do this to include tabs and system characters and whatnot. - prev_word_start = inx # Store the previous whitespace - spc_inx = self.value.find(' ', inx+1) - nl_inx = self.value.find('\n', inx+1) - - if (min(spc_inx, nl_inx) == -1): - inx = max(spc_inx, nl_inx) - else: - inx = min(spc_inx, nl_inx) - - # Measure the current line - lw, self.line_h = self.font.size( self.value[ line_start : inx ] ) - - # If we exceeded the max line width, then create a new line - if (lw > max_line_w): - #Fall back to the previous word start - self.lines.append(self.value[ line_start : prev_word_start + 1 ]) - line_start = prev_word_start + 1 - # TODO: Check for extra-long words here that exceed the length of a line, to wrap mid-word - - # If we reached the end of our text - if (inx < 0): - # Then make sure we added the last of the line - if (line_start < len( self.value ) ): - self.lines.append( self.value[ line_start : len( self.value ) ] ) - # If we reached a hard line break - elif (self.value[inx] == "\n"): - # Then make a line break here as well. - newline = self.value[ line_start : inx + 1 ] - newline = newline.replace("\n", " ") # HACK: We know we have a newline character, which doesn't print nicely, so make it into a space. Comment this out to see what I mean. - self.lines.append( newline ) - - line_start = inx + 1 - else: - # Otherwise, we just continue progressing to the next space - pass - - def _setvalue(self,v): - self.__dict__['value'] = v - self.send(CHANGE) - - def event(self,e): - used = None - if e.type == KEYDOWN: - if e.key == K_BACKSPACE: - if self.pos: - self._setvalue(self.value[:self.pos-1] + self.value[self.pos:]) - self.pos -= 1 - elif e.key == K_DELETE: - if len(self.value) > self.pos: - self._setvalue(self.value[:self.pos] + self.value[self.pos+1:]) - elif e.key == K_HOME: - # Find the previous newline - newPos = self.value.rfind('\n', 0, self.pos) - if (newPos >= 0): - self.pos = newPos - elif e.key == K_END: - # Find the previous newline - newPos = self.value.find('\n', self.pos, len(self.value) ) - if (newPos >= 0): - self.pos = newPos - elif e.key == K_LEFT: - if self.pos > 0: self.pos -= 1 - used = True - elif e.key == K_RIGHT: - if self.pos < len(self.value): self.pos += 1 - used = True - elif e.key == K_UP: - self.vpos -= 1 - self.setCursorByHVPos() - elif e.key == K_DOWN: - self.vpos += 1 - self.setCursorByHVPos() - # The following return/tab keys are standard for PGU widgets, but I took them out here to facilitate multi-line text editing -# elif e.key == K_RETURN: -# self.next() -# elif e.key == K_TAB: -# pass - else: - #c = str(e.unicode) - try: - if (e.key == K_RETURN): - c = "\n" - elif (e.key == K_TAB): - c = " " - else: - c = (e.unicode).encode('latin-1') - if c: - self._setvalue(self.value[:self.pos] + c + self.value[self.pos:]) - self.pos += len(c) - except: #ignore weird characters - pass - self.repaint() - elif e.type == MOUSEBUTTONDOWN: - self.setCursorByXY(e.pos) - self.repaint() - - elif e.type == FOCUS: - self.repaint() - elif e.type == BLUR: - self.repaint() - - self.pcls = "" - if self.container.myfocus is self: self.pcls = "focus" - - return used - - def __setattr__(self,k,v): - if k == 'value': - if v == None: v = '' - v = str(v) - self.pos = len(v) - _v = self.__dict__.get(k,NOATTR) - self.__dict__[k]=v - if k == 'value' and _v != NOATTR and _v != v: - self.send(CHANGE) - self.repaint() - -# The first version of this code was done by Clint Herron, and is a modified version of input.py (by Phil Hassey). -# It is under the same license as the rest of the PGU library. \ No newline at end of file