Exemplo n.º 1
0
    def paint_text(self, parent_offset, surface):
        mid = len(self.line.current)/2
        midvalues = self.line.current[mid:mid+2]
        if len(midvalues) < 2:
            # not enough control points to figure out where to put text
            return
        midsrc, middst = midvalues
        angle = ((middst - midsrc).angle() % (2*math.pi))

        if 1*(2*math.pi)/4 < angle < 3*(2*math.pi)/4:
            angle += math.pi
            angle %= 2*math.pi

        t = self.rendered_text
        text_centering_vector = Point((-t.get_width()/2, -t.get_height()))
        text_centering_length = text_centering_vector.norm()
        text_centering_angle = text_centering_vector.angle()

        rt, coors = rotate_surface(t, angle)

        # coors[0] is where the original topleft is in the
        # rotated surface:
        topleft = coors[0]

        desired_topleft = midsrc + from_polar(text_centering_angle+angle,
                                              text_centering_length)
                
        pos = tuple(desired_topleft - topleft + parent_offset)
        surface.blit(rt, map(int, pos))
Exemplo n.º 2
0
def SurroundLayout(width, height, source_widget, subwidgets_of, scale=1, subwidgets_center_offset=None):
    if subwidgets_center_offset is None:
        subwidgets_center_offset = Point(0,source_widget.size.norm()*scale)
        span = pi
    else:
        span = pi
    source_widget.scale = scale
    subwidgets = reversed(sorted((widget.order.sublevel, widget) for widget in list(subwidgets_of(source_widget))))
    subwidgets = list(subwidgets)
    num = len(subwidgets)
    if num <= 1:
        return
    center_angle = subwidgets_center_offset.angle() - (span/2)
    radius = subwidgets_center_offset.norm()
    angle_step = span/(num-1)
    center = source_widget.pos
    for i,(sublevel, subwidget) in enumerate(subwidgets):
        angle = center_angle + angle_step*i
        subwidget.pos = center + Point.from_polar(angle, radius)
        new_offset = Point.from_polar(angle, radius/3.0)
        SurroundLayout(width, height, subwidget, subwidgets_of, scale=scale*0.8, subwidgets_center_offset=new_offset)
Exemplo n.º 3
0
    def __init__(self, size, pos = None, order=None, hover_color=(120,120,250), unhover_color=(20,20,150)):
        if pos is None:
            pos = Point(0,0)
        if order is None:
            order = Order()
        self.target_pos = pos.shallow_copy()
        self._size = size
        self.order = order
        self._pos = pos.shallow_copy()
        self.target_scale = 1
        self._scale = 1

        self.visible = True
        self.size_margin = 10
        self.speed = Point(0.1,0.1)
        self.scale_speed = 0.1
        self.autogrow_to_fit_text = True
        self.rendered_text_lines = None
        self.text_lines = []
        self._target_size = self._size.shallow_copy()
        
        self.font_size = 12
        self._prev_font_scale = 12
        self._prev_text_lines = self.text_lines[:]

        # node for topology
        self.node = Graph.Node(self)
        # node for layout hints
        self.puller_node = Graph.Node(self)
        self.pusher_node = Graph.Node(self)
        
        self.update_font()

        self.hover_color = hover_color
        self.unhover_color = unhover_color
        self.border_color = hover_color
        self.hover_out()

        self.accel = Point(0,0)
        self.vel = Point(0,0)
Exemplo n.º 4
0
    def update_pos(self):
        
        #self._pos += (self.target_pos - self._pos)*self.speed
        global_scale = 0.5
        
        self.accel = Point(0,0) #(self.target_pos - self._pos)*self.speed
        for puller in self.puller_node.iter_all_connections():
            w = puller.value
            this_scale = global_scale
            if w in [n.value for n in self.node.connections['out']]:
                # Decrease forces!
                this_scale = global_scale*2.0
                
            vec = (w.pos - self.pos)
            r = vec.norm()
            if r==0:
                continue
            vec = vec*r*(1/(self.scale*12.0*this_scale))
            if vec.norm() > 15: # don't let them get too close!
                self.accel += vec
            else:
                self.accel -= vec
        for pusher in self.pusher_node.iter_all_connections():
            w = pusher.value
            vec = (w.pos - self.pos)
            r = vec.norm()
            if r==0:
                continue
            vec = vec*(1/r)*(self.scale*1500*global_scale)
            if vec.norm() > 15: # don't let them get too close!
                self.accel -= vec
            else:
                self.accel += vec

            
        self.vel += self.accel
        self.vel *= 0.02 # "friction"
        if (self.vel.norm() > self.MAX_VEL):
            self.vel = Point.from_polar(self.vel.angle(), self.MAX_VEL)

        
        self.pos += self.vel
        self._pos = self.pos
Exemplo n.º 5
0
class Widget(object):
    MAX_VEL = 20
    
    def __init__(self, size, pos = None, order=None, hover_color=(120,120,250), unhover_color=(20,20,150)):
        if pos is None:
            pos = Point(0,0)
        if order is None:
            order = Order()
        self.target_pos = pos.shallow_copy()
        self._size = size
        self.order = order
        self._pos = pos.shallow_copy()
        self.target_scale = 1
        self._scale = 1

        self.visible = True
        self.size_margin = 10
        self.speed = Point(0.1,0.1)
        self.scale_speed = 0.1
        self.autogrow_to_fit_text = True
        self.rendered_text_lines = None
        self.text_lines = []
        self._target_size = self._size.shallow_copy()
        
        self.font_size = 12
        self._prev_font_scale = 12
        self._prev_text_lines = self.text_lines[:]

        # node for topology
        self.node = Graph.Node(self)
        # node for layout hints
        self.puller_node = Graph.Node(self)
        self.pusher_node = Graph.Node(self)
        
        self.update_font()

        self.hover_color = hover_color
        self.unhover_color = unhover_color
        self.border_color = hover_color
        self.hover_out()

        self.accel = Point(0,0)
        self.vel = Point(0,0)
        
    def in_bounds(self, pos):
        s = self._scaled_size()
        if ((pos.x > self._pos.x)
            and (pos.y > self._pos.y)
            and (pos.x < self._pos.x + s.x)
            and (pos.y < self._pos.y + s.y)):
            return True
        return False

    def set_pos(self, pos):
        self.target_pos = pos.shallow_copy()
    def get_pos(self):
        return self.target_pos
    pos = property(get_pos, set_pos)

    def set_scale(self, scale):
        self.target_scale = scale
        self.update_target_text_scale()
    def get_scale(self):
        return self.target_scale
    scale = property(get_scale, set_scale)

    def set_size(self, size):
        self._size = size/self.target_scale
    def get_size(self):
        if not self.text_lines:
            return self._size*self.target_scale
        return self._target_size
    size = property(get_size, set_size)
    
    def update_pos(self):
        
        #self._pos += (self.target_pos - self._pos)*self.speed
        global_scale = 0.5
        
        self.accel = Point(0,0) #(self.target_pos - self._pos)*self.speed
        for puller in self.puller_node.iter_all_connections():
            w = puller.value
            this_scale = global_scale
            if w in [n.value for n in self.node.connections['out']]:
                # Decrease forces!
                this_scale = global_scale*2.0
                
            vec = (w.pos - self.pos)
            r = vec.norm()
            if r==0:
                continue
            vec = vec*r*(1/(self.scale*12.0*this_scale))
            if vec.norm() > 15: # don't let them get too close!
                self.accel += vec
            else:
                self.accel -= vec
        for pusher in self.pusher_node.iter_all_connections():
            w = pusher.value
            vec = (w.pos - self.pos)
            r = vec.norm()
            if r==0:
                continue
            vec = vec*(1/r)*(self.scale*1500*global_scale)
            if vec.norm() > 15: # don't let them get too close!
                self.accel -= vec
            else:
                self.accel += vec

            
        self.vel += self.accel
        self.vel *= 0.02 # "friction"
        if (self.vel.norm() > self.MAX_VEL):
            self.vel = Point.from_polar(self.vel.angle(), self.MAX_VEL)

        
        self.pos += self.vel
        self._pos = self.pos

    def update_scale(self):
        self._scale += (self.target_scale - self._scale)*self.scale_speed
        self.update_font()
        #print self._scale

    def update_font(self):
        if not self.text_lines:
            return
        font_scale = int(self.font_size*self._scale*2)
        if (self.text_lines == self._prev_text_lines) and (font_scale == self._prev_font_scale):
            return
        self._prev_text_lines = self.text_lines
        self._prev_font_scale = font_scale
        
        self.font = self.get_font(font_scale)
        self.rendered_text_lines = []
        mw, mh = 0, 0
        linesize = self.font.get_linesize()
        
        for i, line in enumerate(self.text_lines):
            rendered_line = self.font.render(line, True, (250,250,250,150))
            self.rendered_text_lines.append((rendered_line, linesize*i))
            w,h = self.font.size(line)
            mw = max(mw, w)
            mh += linesize
        if self.autogrow_to_fit_text:
            self._size = Point(mw, mh)
            
        
    def _scaled_size(self):
        if not self.text_lines:
            return self._size*self._scale
        return self._size
    
    def paint(self, surface):
        if not self.visible:
            return
        #self.set_text(str(self.order.sublevel))
        self.update_scale()
        self.update_pos()
        s = self._scaled_size()

        self.draw_connections(surface)

        pygame.draw.rect(surface, self.color, (self._pos.x, self._pos.y, s.x, s.y), 0)
        pygame.draw.rect(surface, self.border_color, (self._pos.x, self._pos.y, s.x, s.y), 2)
        #pygame.draw.ellipse(surface, self.color, (self._pos.x, self._pos.y, s.x, s.y), 3)
        if self.rendered_text_lines:
            for rendered_text_line, y in self.rendered_text_lines:
                surface.blit(rendered_text_line, (self._pos.x, self._pos.y+y))

    def draw_connections(self, surface):
        s = self._scaled_size()
        my_pos = self._pos + Point(s.x/2, s.y/2)

        # Draw "pull" connections
        for widget_node in self.puller_node.iter_all_connections():
            widget = widget_node.value
            if not widget.visible:
                continue
            other_pos = widget._pos + Point(widget._scaled_size().x/2, widget._scaled_size().y/2)
            pygame.draw.aalines(surface, (200,20,50,100), False, (my_pos.as_tuple(), other_pos.as_tuple()), True)

        # draw topological connections
        for widget_node in self.node.connections['out']:
            widget = widget_node.value
            other_pos = widget._pos + Point(widget._scaled_size().x/2, widget._scaled_size().y/2)
            pygame.draw.aalines(surface, (200,220,250,100), False, (my_pos.as_tuple(), other_pos.as_tuple()), True)

##         for widget_node in self.pusher_node.iter_all_connections():
##             widget = widget_node.value
##             other_pos = widget._pos + Point(widget._scaled_size().x/2, widget._scaled_size().y/2)
##             pygame.draw.aalines(surface, (20,220,50,100), False, (my_pos.as_tuple(), other_pos.as_tuple()), True)

    @staticmethod
    @Func.cached
    def get_font(font_size):
        return pygame.font.SysFont('serif',font_size)

    def update_target_text_scale(self):
        if not self.text_lines:
            return
        mw,mh = 0,0
        for line in self.text_lines:
            w,h = self.get_font(int(self.font_size*self.target_scale*2)).size(line)
            mw = max(mw, w)
            mh += h
        self._target_size = Point(mw,mh)
        
    def set_text(self, text_lines):
        self.text_lines = text_lines[:]
        if not self.text_lines:
            self.rendered_text_lines = []
            return
        
        self.update_target_text_scale()
        self.update_font()

    def set_text_line(self, num, line):
        if num >= len(self.text_lines):
            self.text_lines.extend(['']*(num-len(self.text_lines)+1))
        self.text_lines[num] = line
        self.set_text(self.text_lines)

    def hover_in(self):
        self.color = self.hover_color

    def hover_out(self):
        self.color = self.unhover_color
Exemplo n.º 6
0
def TableLayout(width, height, widgets, scale=1, autoscale=True, offset = None):
    if offset is None:
        offset = Point(0,0)

    # if scale is None - scale to fit the whole size
    margin = 10
    if not autoscale:
        margin *= scale
        
    x_margin = y_margin = margin
        
    pos = Point(x_margin, y_margin)
    next_row = 0


    # order the widgets according to level, and find the maximum widget size
    
    ordered = []
    max_size = Point(0,0)
    for widget in widgets:
        if autoscale:
            widget.scale = 1
        else:
            widget.scale = scale
        
        level = widget.order.level
        sublevel = widget.order.sublevel
            
        ordered.append((level, sublevel, widget))
        max_size.x = max(max_size.x, widget.size.x)
        max_size.y = max(max_size.y, widget.size.y)

    ordered.sort()

    # setup the widgets in a table

    prev_level = 0
    pos = Point(x_margin,y_margin)
    table_size = Point(0,0)
    for level, sublevel, widget in ordered:
        if ((pos.x + max_size.x >= width)
            or (level > prev_level)):
            prev_level = level
            pos.y += max_size.y + y_margin
            pos.x = x_margin
                
        widget.pos = pos.shallow_copy()
        pos.x += max_size.x + x_margin

        table_size.x = max(table_size.x, widget.pos.x + widget.size.x)
        table_size.y = max(table_size.y, widget.pos.y + widget.size.y)


    if autoscale:
        # STUPID IMPLEMENTATION
        # todo change it
        # go back and relayout with the calculated scale
        new_scale = min(float(width-10) / table_size.x, float(height-10) / table_size.y)
        TableLayout(width, height, widgets, new_scale * scale, autoscale=False)
        return
    
    # center the table
    size = Point(width, height)
    center_pos = size*0.5 - table_size*0.5 - Point(x_margin, y_margin)
    # now center the table
    for widget in widgets:
        widget.pos += center_pos + offset