示例#1
0
class MessageBox(object):
    def __init__(self, pos=[0,0], font=None,
                 area=[50,50], align=["left","top"],
                 visible=True,
                 image=None, image_mode=None,
                 messages=[], max_lines=None,
                 wrap=False,
                 text_padding=[0,0]):

        self.kind="MessageBox"

        self.pos=pos
        self.font=font
        if not self.font:self.font=Font()

        self.text_padding=text_padding

        self.area=area
        self.align=align

        self.visible=visible

        self.image=image
        self.image_mode=image_mode
        if self.image:
            if isinstance(self.image, pygame.Surface):
                pass
            else:
                self.image=self.image.resize(self.area,
                                             self.image_mode)
                self.area=[self.image.get_width(),
                           self.image.get_height()]

        self.messages=[]
        self.max_lines=max_lines

        self.max_width=0

        self.wrap=wrap

        for i in messages:
            self.add_message(i)

        self.vscroll=0
        self.hscroll=0

    def add_message(self, mess):
        if self.wrap:
            for x in gui_util.wrap_text(self.font, mess, self.wrap)[0]:
                self.messages.append(x)
        else:
            self.messages.append(mess)

        if self.max_lines:
            while len(self.messages)>self.max_lines:
                del self.messages[0]

        self.max_width=0
        for i in self.messages:
            w=self.font.size(i)[0]
            if w>self.max_width:
                self.max_width=w

    def update(self, event):
        pass

    def scroll(self, v=0, h=0):
        self.vscroll+=v
        if self.vscroll<0:
            self.vscroll=0
        if (len(self.messages)+1)*(self.font.fsize-(self.font.fsize/3))>self.area[1]:
            max=(self.font.fsize-(self.font.fsize/3))*(len(self.messages)+1)
            max-=self.area[1]
            if self.vscroll>max:
                self.vscroll=max
        else:
            self.vscroll=0

        self.hscroll+=h
        if self.hscroll<0:
            self.hscroll=0

        if self.max_width > self.area[0]:
            if self.hscroll>self.max_width-self.area[1]:
                self.hscroll=self.max_width-self.area[1]
        else:
            self.hscroll=0

    def render(self, surface):
        if self.visible:
            ret_clip=surface.get_clip()
            new_clip=pygame.Rect((self.pos[0]+self.text_padding[0],
                                  self.pos[1]+self.text_padding[1]),
                                 (self.area[0]-self.text_padding[0]*2,
                                  self.area[1]-self.text_padding[1]*2))
            new_clip.clip(ret_clip)

            if self.image:
                if isinstance(self.image, pygame.Surface):
                    surface.blit(self.image, self.pos)
                else:
                    self.image.render(surface, self.pos)

            surface.set_clip(new_clip)

            lines=[self.font.render(i) for i in self.messages]

            fs=self.font.fsize-(self.font.fsize/3)

            for l in xrange(len(lines)):
                line=lines[l]
                r=line.get_rect()

                y=self.pos[1]+self.text_padding[1]+\
                       (fs*l)+\
                       self.vscroll-(fs*(len(self.messages)+1)-self.area[1])

                x=self.pos[0]+self.text_padding[0]-self.hscroll

                if self.align[0]=="left":
                    r.left=x
                elif self.align[0]=="center":
                    r.centerx=x+self.area[0]/2-self.text_padding[0]
                else:
                    r.right=x+self.area[0]-self.text_padding[0]*2

                if self.align[1]=="top":
                    r.top=y
                elif self.align[1]=="center":
                    r.centery=y
                else:
                    r.bottom=y

                surface.blit(line, r.topleft)
            surface.set_clip(ret_clip)
示例#2
0
class InputBox(object):
    def __init__(self, pos=[0,0], font=None,
                 prompt="", width=250,
                 start_text="", visible=True,
                 image_normal=None, image_hover=None,
                 image_click=None, image_mode=None,
                 cache_on_KEY=None, ignore_active=False,

                 align=["left","top"],
                 text_padding=[0,0],
                 ignore_events=[]):

        self.kind="InputBox"

        #TODO: allow area, istead of width, and allow multiple lines of input

        self.pos=pos

        self.image_mode=image_mode

        self.align=align
        self.text_padding=text_padding

        self.ignore_active=ignore_active

        self.width=width

        self.ignore_events=ignore_events

        self.font=font
        if not self.font:
            self.font=Font()

        self.rect=pygame.Rect(self.pos, [width, self.font.fsize])

        self.prompt=prompt
        self.message=start_text
        self.cached_messages=[]

        self.text_pos=len(self.message)

        self.cache_on_KEY=cache_on_KEY

        self.blink_speed=0.5
        self.blink_last=time.time()

        self.image_normal=image_normal
        self.image_hover=image_hover
        self.image_click=image_click

        if self.image_normal:
            if isinstance(self.image_normal, pygame.Surface):
                pass
            else:
                self.image_normal=self.image_normal.resize(self.rect.size,
                                                           self.image_mode)

                self.rect=self.image_normal.get_rect()
                self.rect.topleft=self.pos
                self.width=self.rect.width-self.text_padding[0]*2

        if self.image_hover:
            if isinstance(self.image_hover, pygame.Surface):
                pass
            else:
                self.image_hover=self.image_hover.resize(self.rect.size,
                                                         self.image_mode)

        if self.image_click:
            if isinstance(self.image_click, pygame.Surface):
                pass
            else:
                self.image_click=self.image_click.resize(self.rect.size,
                                                         self.image_mode)

        self.hovering=False
        self.mouse_button_down=False
        self.am_clicked=False
        self.active=False

        self.visible=visible

    def update(self, event):
        mouse_pos=pygame.mouse.get_pos()
        if self.visible:
            if event.type==MOUSEBUTTONDOWN:
                if event.button==1:
                    if self.rect.collidepoint(mouse_pos):
                        self.mouse_button_down=True
                    else:
                        self.mouse_button_down=False
            elif event.type==MOUSEBUTTONUP:
                self.mouse_button_down=False
                if event.button==1:
                    if self.rect.collidepoint(mouse_pos):
                        self.was_clicked=True
                        self.active=True
                        self.am_clicked=True
                    else:
                        self.was_clicked=False
                        self.active=False
                        self.am_clicked=False

            elif event.type==KEYDOWN:
                if self.active or self.ignore_active:
                    a=gui_util.convert_event_to_key(event)
                    if not a:
                        return

                    if a in self.ignore_events:
                        return

                    if self.cache_on_KEY:
                        if a==self.cache_on_KEY:
                            self.cached_messages.append(self.message)
                            self.message=""
                            self.text_pos=0
                            return
                        if event.type==KEYDOWN:
                            if event.key==self.cache_on_KEY:
                                self.cached_messages.append(self.message)
                                self.message=""
                                self.text_pos=0
                                return
                    if a=="BACK":
                        if self.text_pos:
                            self.message=self.message[:len(self.message)-1]
                            self.text_pos-=1
                    elif a=="DEL":
                        if len(self.message) > self.text_pos:
                            self.message=self.message[:self.text_pos]+\
                                          self.message[self.text_pos+1:]
                    elif a=="HOME":
                        self.text_pos=0

                    elif a=="END":
                        self.text_pos=len(self.message)
                    elif a=="LEFT":
                        if self.text_pos>0:
                            self.text_pos-=1
                    elif a=="RIGHT":
                        if self.text_pos<len(self.message):
                            self.text_pos+=1
                    elif a=="RETURN":
                        b=self.message[:self.text_pos]+"\n"+self.message[self.text_pos+1:]
                        if self.font.size(self.prompt+b)[0]<self.width:
                            self.message=b
                            self.text_pos+=1
                    elif a=="TAB":
                        b=self.message[:self.text_pos]+"    "+self.message[self.text_pos+1:]
                        if self.font.size(self.prompt+b)[0]<self.width:
                            self.message=b
                            self.text_pos+=4
                    else:
                        b=self.message[:self.text_pos]+a+self.message[self.text_pos+1:]

                        if self.font.size(self.prompt+b)[0]<self.width:
                            self.message=b
                            self.text_pos+=1

            if self.rect.collidepoint(mouse_pos):
                self.hovering=True
                if self.mouse_button_down:
                    self.am_clicked=True
                else:
                    self.am_clicked=False
            else:
                self.hovering=False

    def empty_cache(self):
        a=self.cached_messages[::]
        self.cached_messages=[]
        return a

    def render(self, surface):
        if self.visible:
            if self.am_clicked:
                image=self.image_click
            elif self.hovering:
                image=self.image_hover
            else:
                image=self.image_normal

            if image:
                if isinstance(image, pygame.Surface):
                    surface.blit(image, self.rect.topleft)
                else:
                    image.render(surface, self.rect.topleft)

            text=self.font.render(self.prompt+self.message)
            r=text.get_rect()
            if self.align[0]=="left":
                r.left=self.rect.left
            elif self.align[0]=="center":
                r.centerx=self.rect.centerx
            else:
                r.right=self.rect.right

            if self.align[1]=="top":
                r.top=self.rect.top
            elif self.align[1]=="center":
                r.centery=self.rect.centery
            else:
                r.bottom=self.rect.bottom

            r.left+=self.text_padding[0]
            r.top+=self.text_padding[1]

            surface.blit(text, r.topleft)

            if time.time()>=self.blink_last+self.blink_speed:
                r.left=r.right
                r.left-=self.font.size(self.message[self.text_pos::])[0]
                r.left-=self.font.fsize/15
                if self.active or self.ignore_active:
                    surface.blit(self.font.render("|"), r)
            if time.time()>=self.blink_last+self.blink_speed*2:
                self.blink_last=time.time()