Windspar

PyGame EntryBox

Apr 6th, 2019
491
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.79 KB | None | 0 0
  1. import pygame
  2.  
  3. class Recall:
  4.     def __init__(self):
  5.         self.pos = 0
  6.         self.buffer = []
  7.  
  8.     def down(self):
  9.         if self.pos > 0:
  10.             self.pos -= 1
  11.             text = self.buffer[self.pos]
  12.             return text
  13.         else:
  14.             self.pos = -1
  15.  
  16.     def up(self):
  17.         if self.pos < len(self.buffer) - 1:
  18.             self.pos += 1
  19.             return self.buffer[self.pos]
  20.  
  21.     def store(self, text):
  22.         self.pos = -1
  23.         if text not in self.buffer:
  24.             if len(self.buffer) > 4:
  25.                 self.buffer = [text] + self.buffer[:4]
  26.             else:
  27.                 self.buffer.insert(0, text)
  28.         elif self.buffer[0] != text:
  29.             self.buffer.remove(text)
  30.             self.buffer.insert(0, text)
  31.  
  32. class EntryBox:
  33.     def __init__(self, font, rect, callback,
  34.         textcolor = pygame.Color("white"),
  35.         boxcolor = pygame.Color("gray44"),
  36.         hovercolor = pygame.Color("aliceblue"),
  37.         selectedcolor = pygame.Color("dodgerblue")):
  38.  
  39.         self.font = font
  40.         self.rect = rect
  41.         self.callback = callback
  42.         self.boxcolor = boxcolor
  43.         self.textcolor = textcolor
  44.         self.hovercolor = hovercolor
  45.         self.selectedcolor = selectedcolor
  46.  
  47.         self.buffer = []
  48.         self.image = None
  49.         w, h = self.font.size("|")
  50.         self.image_rect = pygame.Rect(rect.x, rect.y + (rect.h - h) / 2, w, h)
  51.         self.hover = False
  52.         self.offset = [0, 0]
  53.         self.selected = False
  54.         self.recall = Recall()
  55.         self.carrot_pos = 0
  56.         self.carrot_left = self.rect.x
  57.         self.carrot_show = True
  58.         self.carrot_image = font.render("|", 1, textcolor)
  59.  
  60.         self.key_event = {
  61.             pygame.K_BACKSPACE: self.keydown_backspace,
  62.             pygame.K_DELETE: self.keydown_delete,
  63.             pygame.K_DOWN: self.keydown_down,
  64.             pygame.K_END: self.keydown_end,
  65.             pygame.K_HOME: self.keydown_home,
  66.             pygame.K_LEFT: self.keydown_left,
  67.             pygame.K_RETURN: self.keydown_return,
  68.             pygame.K_RIGHT: self.keydown_right,
  69.             pygame.K_UP: self.keydown_up
  70.         }
  71.  
  72.     def draw(self, surface):
  73.         if self.selected:
  74.             color = self.selectedcolor
  75.         elif self.hover:
  76.             color = self.hovercolor
  77.         else:
  78.             color = self.boxcolor
  79.  
  80.         surface.fill(color, self.rect)
  81.  
  82.         if self.image:
  83.             surface.blit(self.image, self.image_rect)
  84.  
  85.         if self.selected:
  86.             surface.blit(self.carrot_image, (self.carrot_left, self.image_rect.y))
  87.  
  88.     def keydown_backspace(self):
  89.         if self.carrot_pos > 1:
  90.             front = self.buffer[:self.carrot_pos - 1]
  91.             back = self.buffer[self.carrot_pos:]
  92.             self.buffer = front + back
  93.             self.carrot_pos -= 1
  94.         else:
  95.             self.keydown_delete()
  96.  
  97.     def keydown_delete(self):
  98.         self.buffer = []
  99.         self.image = None
  100.         self.carrot_pos = 0
  101.         self.carrot_left = self.rect.x
  102.         self.offset = [0, 0]
  103.  
  104.     def keydown_down(self):
  105.         self.buffer = self.recall.down()
  106.         if self.buffer:
  107.             self.carrot_pos = len(self.buffer)
  108.         else:
  109.             self.keydown_delete()
  110.  
  111.     def keydown_end(self):
  112.         self.carrot_pos = len(self.buffer)
  113.  
  114.     def keydown_home(self):
  115.         self.carrot_pos = 0
  116.  
  117.     def keydown_left(self):
  118.         if self.carrot_pos > 0:
  119.             self.carrot_pos -= 1
  120.  
  121.     def keydown_return(self):
  122.         self.recall.store(self.buffer)
  123.         text = ''.join(self.buffer)
  124.         self.keydown_delete()
  125.         self.callback(text)
  126.  
  127.     def keydown_right(self):
  128.         if self.carrot_pos < len(self.buffer):
  129.             self.carrot_pos += 1
  130.  
  131.     def keydown_up(self):
  132.         recall_buffer = self.recall.up()
  133.         if recall_buffer:
  134.             self.buffer = recall_buffer
  135.             self.carrot_pos = len(self.buffer)
  136.  
  137.     def on_keydown(self, event):
  138.         if self.selected:
  139.             self.carrot_show = True
  140.             ctrl = event.mod & pygame.KMOD_CTRL
  141.  
  142.             if ctrl == 0 and 31 < event.key < 127:
  143.                 self.buffer.insert(self.carrot_pos, event.unicode)
  144.                 self.carrot_pos += 1
  145.                 self.update_text()
  146.             elif ctrl == 0:
  147.                 if self.key_event.get(event.key, False):
  148.                     self.key_event[event.key]()
  149.                     self.update_text()
  150.  
  151.     def on_mousemotion(self, event):
  152.         self.hover = self.rect.collidepoint(event.pos)
  153.  
  154.     def update_text(self):
  155.         if len(self.buffer) > 0:
  156.             text = ''.join(self.buffer)
  157.             width = self.rect.width - 4
  158.  
  159.             if self.carrot_pos > self.offset[1]:
  160.                 self.offset[1] = self.carrot_pos
  161.             elif self.carrot_pos < self.offset[0]:
  162.                 self.offset[0] = self.carrot_pos
  163.  
  164.             while self.font.size(text[self.offset[0]:self.offset[1]])[0] < width and self.offset[0] > 0:
  165.                 self.offset[0] -= 1
  166.  
  167.             while self.font.size(text[self.offset[0]:self.offset[1]])[0] > width and self.offset[0] < self.carrot_pos:
  168.                 self.offset[0] += 1
  169.  
  170.             while self.font.size(text[self.offset[0]:self.offset[1]])[0] < width and self.offset[1] < len(self.buffer):
  171.                 self.offset[1] += 1
  172.  
  173.             while self.font.size(text[self.offset[0]:self.offset[1]])[0] > width:
  174.                 self.offset[1] -= 1
  175.  
  176.             t = text[self.offset[0]:self.offset[1]]
  177.             self.image = self.font.render(t, 1, self.textcolor)
  178.             self.image_rect.size = self.image.get_rect().size
  179.             self.image_rect.centery = self.rect.centery
  180.             t = text[self.offset[0]:self.carrot_pos]
  181.             self.carrot_left = self.font.size(t)[0] + self.rect.x - 1
  182.  
  183.         else:
  184.             self.keydown_delete()
  185.  
  186. # Simple Scene Interface
  187. class Scene:
  188.     def draw(self, surface, game): pass
  189.     def event(self, event, game): pass
  190.  
  191. class Game:
  192.     def __init__(self, caption, width, height):
  193.         # Basic pygame setup
  194.         pygame.display.set_caption(caption)
  195.         self.rect = pygame.Rect(0, 0, width, height)
  196.         self.surface = pygame.display.set_mode(self.rect.size)
  197.         self.clock = pygame.time.Clock()
  198.         self.running = False
  199.         self.fps = 30
  200.         self.delta = 0
  201.  
  202.         # Scene Interface
  203.         self.scene = Scene()
  204.         Game.info = self
  205.  
  206.     def mainloop(self):
  207.         self.running = True
  208.         while self.running:
  209.             for event in pygame.event.get():
  210.                 self.scene.event(event, self)
  211.  
  212.             self.scene.draw(self.surface, self)
  213.             pygame.display.flip()
  214.             self.delta = self.clock.tick(self.fps)
  215.  
  216. class Example(Scene):
  217.     def __init__(self):
  218.         font = pygame.font.Font(None, 24)
  219.         self.entry = EntryBox(font, pygame.Rect(20, 20, 200, 40), self.entry_return)
  220.  
  221.         self.background = pygame.Color('Black')
  222.  
  223.     def entry_return(self, text):
  224.         print(text)
  225.  
  226.     def draw(self, surface, game):
  227.         surface.fill(self.background)
  228.         self.entry.draw(surface)
  229.  
  230.     def event(self, event, game):
  231.         if event.type == pygame.QUIT:
  232.             game.running = False
  233.         elif event.type == pygame.KEYDOWN:
  234.             self.entry.on_keydown(event)
  235.         elif event.type == pygame.MOUSEMOTION:
  236.             self.entry.on_mousemotion(event)
  237.         elif event.type == pygame.MOUSEBUTTONDOWN:
  238.             if event.button == 1 and self.entry.hover:
  239.                 self.entry.selected = True
  240.             else:
  241.                 self.entry.selected = False
  242.  
  243. def main():
  244.     pygame.init()
  245.     game = Game("Entry Box Example", 800, 600)
  246.     game.scene = Example()
  247.     game.mainloop()
  248.     pygame.quit()
  249.  
  250. main()
Add Comment
Please, Sign In to add comment