def __init__(self, hotspot=None, benchmark=None, a_vector=None, opening_item=0): if hotspot: self.hotspot = vector.Point( hotspot.x, hotspot.y) # intersection point of vector and morph if benchmark: self.benchmark = vector.Point( benchmark.x, benchmark.y) # starting point of layout self.vector = a_vector # axis self.opening_item = opening_item # index of item within menu sequence
def mouse_exit(self, event): ''' Mouse exited item. This is a filtered event from super GuiControl. Assert no button down (not a drag.) Dynamic orthogonality. A handle menu MIGHT follow the mouse in orthogonal directions, if the handle menu is a TrackingHandleMenu AND we didn't hit a stop (the limit of an edge of the controlee morph.) Exit from item is EITHER in "menu exit" direction OR in "menu change item" direction. ''' # Calculate vector in DCS of mouse exit. center = self.bounds.center_of() exit_vector = vector.Point(event.x, event.y) - center # normalize to manager's (the menu's) axis norm_vect = vector.normalize_vector_to_vector( exit_vector, self.group_manager.layout_spec.vector) if norm_vect.y > 10 or norm_vect.y < -10: # FIXME not hardcoded # exited the side, which means close menu self.close_manager() else: # Exited "change item" side of menu item. # Tell manager to decide next action (another item, or close menu.) self.group_manager.do_change_item(event, exit_vector)
def benchmark_from_hotspot(axis, hotspot): ''' Calculate benchmark from hotspot. Since opening on middle item, benchmark at first item is half length away. ''' to_benchmark = axis.copy() to_benchmark *= -10 # scale by half length of menu - half width of item # Here menu is 3 items of 20 overlapping by 10 = 40 / 2 -10 benchmark = vector.Point(hotspot.x, hotspot.y) + to_benchmark return benchmark # benchmark is a point
def pixels_off_menu_axis(self, event): ''' Is mouse motion orthogonal (sideways) to menu axis? Returns count of pixels off axis. !!! Note that the sign indicates left(countercw) or right (clockwise) of the menu axis, not a direction along the coordinate system. ''' # Specific for horiz menus: return not event.y == self.get_center().y # vector from menu origin to mouse event menu_vector = self.group_manager.layout_spec.vector menu_benchmark = self.group_manager.layout_spec.benchmark mouse_vector = vector.Point(event.x, event.y) - menu_benchmark # normalize to menu vector normal_vector = vector.normalize_vector_to_vector( mouse_vector, menu_vector) # print "mouse", mouse_vector, "menu", menu_vector, "normal", normal_vector return normal_vector.y
def layout(self, event=None): ''' Layout (position) all items in group, according to layout_spec. For all Handle Menus: In a line. (Tracking: orthogonal to glyph, Stationed: vertical) Ordered towards anti-direction of axis vector. Overlapping items. A handle group lays out all items even though only one is shown. When exit an item, other items are already laid out. Using transforms, a menu only needs to be layed out once. A change to layoutspec can require updates to the transform or the layout. ''' point = vector.Point(0, 0) for item in self: item.center_at(point) # Next item along a line (the x-axis). # FIXME more generally, get the size of an item # point.y += item.get_dimensions().height point.x += config.ITEM_SIZE / 2 # HEIGHT?
def find_new_hotspot(controlee, spec, pixels_off_axis): '''Returns new hotspot (intersection of menu axis and glyph) or None.''' # Hit pattern is a line of pixels orthogonal to x-axis at distance 2 hit_pattern = (vector.Point(2, -2), vector.Point(2, -1), vector.Point(2, 0), vector.Point(2, 1), vector.Point(2, 2)) # Make transform of hit pattern to bring it into relation with menu matrix = make_slide_transform(spec, pixels_off_axis) for point in hit_pattern: transformed_point = vector.Point( *matrix.transform_point(point.x, point.y)) # transformed_point now in DCS #print "Old hotspot", spec.hotspot, "Transformed", transformed_point if controlee.in_path(transformed_point): return transformed_point return None