def draw(self): r = ui.Rect(*self.bounds).inset(*self.circle_inset) oval = ui.Path.oval(r.x, r.y, r.width, r.height) c = ui.parse_color(self.circle_color) nc = (c[0], c[1], c[2], self.circle_alpha) # color with alpha pattern = '9' * len(self.text) text_rect = ui.Rect(0, 0, r.width * .8, r.height * .6) text_rect.center(r.center()) fs = self.get_max_fontsize(text_rect, pattern, self.font_name, self.inset_rect) with ui.GState(): ui.set_color(nc) oval.fill() ui.draw_string(self.text, rect=text_rect, font=(self.font_name, fs), color=self.text_color, alignment=ui.ALIGN_CENTER, line_break_mode=ui.LB_TRUNCATE_TAIL) j = ui.Path.rect(*text_rect) ui.set_color((0, 0, 0, .5)) j.fill()
def draw(self): # the shape drawing area r = ui.Rect(*self.frame) ui.set_color('teal') r.width -= self.tv.width r.x = self.tv.bounds.max_x r.y = self.tv.bounds.y s = ui.Path.rect(*r) s.fill() ui.set_color('blue') s.stroke() # square the rectangle to draw the shape into r1 = ui.Rect(r.x, r.y, r.width, r.width).inset(5, 5) r1.center(r.center()) ui.set_color('white') # draw the shape based on the list selection txt_type = self.get_selected_row_data() if txt_type is 'Rect': s1 = ui.Path.rect(*r1) elif txt_type is 'Oval': s1 = ui.Path.oval(*r1) elif txt_type is 'Rounded_Rect': s1 = ui.Path.rounded_rect(r1[0], r1[1], r1[2], r1[3], 3) #s1 = ui.Path.rounded_rect(*r1, 3) elif txt_type is 'Polygon': s1 = ui.Path.rect(*r1) print('ok, thats for you to implement...') s1.fill()
def draw(self): r = ui.Rect(*self.bounds) r, rects = rects_on_circle_path(r, 10, margin=20, num_objs=36) s = ui.Path.oval(*r) ui.set_color('lime') s.stroke() ui.set_color('orange') for r in rects: s = ui.Path.oval(*r) s.fill() r = ui.Rect(*self.bounds) r, rects = rects_on_circle_path(r, 15, margin=40, num_objs=12) s = ui.Path.oval(*r) ui.set_color('yellow') s.stroke() ui.set_color('purple') for r in rects: s = ui.Path.oval(*r) s.fill() r = ui.Rect(*self.bounds) r, rects = rects_on_circle_path(r, 25, margin=80, num_objs=6) s = ui.Path.oval(*r) ui.set_color('orange') s.stroke() ui.set_color('lime') for r in rects: s = ui.Path.rect(*r) s.fill()
def do_position(obj, pos_code='', pad = 0): ''' do_position: a very simple positioning function for ui elements. as simple as it is can be useful. especially for testing. args: 1. obj - a ui object Instance such as a ui.Button 2. pos_code - 1 to x letters or combinations in the set ('c', 't', 'l','b', 'r'). eg 'c' will postion the obj in the middle of the parent view. 'tc' or 'ct' will position the obj at the top center if the screen. 3. pad - is to give a type of margin from the edges. for t and l pad is added, for b and r pad is subtracted. c is not effected by pad returns: a tuple (boolean, ui.Rect) if False, exited early, eg, not yet added to a view. ui.Rect will be set as (0, 0, 0, 0) if True, the ui.Rect is set to the frame of the object. regardless if it moved or not. if both cases ui.Rect will be a valid ui.Rect ''' # if the control is not added to a view, i.e no superview, we cant # do much other than return if not obj.superview: return (False, ui.Rect()) # we only reference superview.bounds. hopefully this is correct! r = ui.Rect(*obj.superview.bounds) # in the func we only deal with lowercase pos_code. we normalise # the case so upper or lower or a mixture can be used as input pos_code = pos_code.lower() # c for center is a special case. does not know if you want vertical # or horizontal center. we delete c from input if it exists and # make sure its the first operation. then we dont get side effects if 'c' in pos_code: pos_code = 'c' + pos_code.replace('c', '') for i in range(len(pos_code)): code = pos_code[i] if code is 'c': obj.center = r.center() elif code is 'l': obj.x = r.min_x + pad elif code is 'r': obj.x = r.max_x - (obj.width+pad) elif code is 't': obj.y = r.min_y + pad elif code is 'b': obj.y = r.max_y - (obj.height + pad) elif code is 'r': obj.y = r.max_y - (obj.height + pad) return (True, ui.Rect(*obj.frame))
def do_position(obj, pos_code='', pad=0): if not obj.superview: return (False, ui.Rect()) # we only reference superview.bounds. hopefully this is correct! r = ui.Rect(*obj.superview.bounds) #obj.center = r.center() if 'c' in pos_code: pos_code = 'c' + pos_code.replace('c', '') pos_code = (pos_code or '').lower() for i in range(len(pos_code)): code = pos_code[i] if code is 'c': obj.center = r.center() elif code is 'l': obj.x = r.min_x + pad elif code is 'r': obj.x = r.max_x - (obj.width + pad) elif code is 't': obj.y = r.min_y + pad elif code is 'b': obj.y = r.max_y - (obj.height + pad) elif code is 'm': obj.y = (r.height / 2) - (obj.height / 2) return (True, ui.Rect(*obj.frame))
def draw(self): r = ui.Rect(*self.bounds).inset(1, 1) s = ui.Path.oval(*r) s.line_width = 2 ui.set_color('silver') s.fill() ui.set_color('black') s.stroke() ui.set_color('white') r = ui.Rect(*self.bounds).inset(3, 3) s = ui.Path.oval(*r) s.line_width = 1 s.stroke() if self.selected: ui.set_color('red') ui.set_shadow('black', 0, 0, 15) r = ui.Rect(*self.bounds).inset(18, 18) s = ui.Path.oval(*r) s.fill() else: ui.set_color('darkgray') ui.set_shadow('black', 0, 0, 15) r = ui.Rect(*self.bounds).inset(18, 18) s = ui.Path.oval(*r) s.fill()
def touch_began(self, touch): self.superview.superview.selected() self.start = tuple(touch.location) self.o_frame = ui.Rect(*self.frame) self.o_p_frame = ui.Rect(*self.superview.frame) self.mode = (touch.location[0] < 25) + (self.frame[2] - 25 < touch.location[0]) * 2
def get_max_fontsize(r, text, font_name, inset_rect = ui.Rect()): r1 = ui.Rect(*r).inset(*inset_rect) for i in xrange(5, 1000): w, h = ui.measure_string(text, max_width=0, font=(font_name, i), alignment=ui.ALIGN_LEFT, line_break_mode=ui.LB_TRUNCATE_TAIL) if w > r1.width or h > r1.height: return (i - 1, ui.Rect(r1.x, r1.y, w, h))
def __init__(self, *args, **kwargs): self.text = '0' self.inset_rect = ui.Rect() self.circle_color = 'teal' self.circle_alpha = 1 self.circle_inset = ui.Rect() self.font_name = 'Arial Rounded MT Bold' self.text_color = 'white' self.process_kwargs(**kwargs)
def rects_on_circle_path(rect_path, obj_width, margin=2, num_objs=12): ''' rects_on_circle_path PARAMS: 1. rect_path = the bounding rect of the circle **Note the rect is inseted half of the shape_width param + the margin param. the resulting rects are centered on the bounding circle. 2. obj_width = the width of the shape/rect you are placing on the path. 3. margin = 2 , additionally insets the rect_path by this value 4. num_objects = 12. the number of objects to distribute around rect_path. set to 12 as default, a clock face. odd and even numbers are ok. RETURNS: tuple(Rect, list) 1. Rect = the adjusted rect_path after transformations in the func. 2. a list[] containing a ui.Rect's. the length of the list is equal to the num_objs param. NOTES: For some reason i can't do the math if my life depended on it. I copied the math from the AnalogClock.py pythonista example. ALSO should have a param to shift the basline of the rects, off the center line of the rect_path. the reason why i return a list of rects in the tuple is for flexibility. in the example, just drawing. but could just as easily be positioning ui.Button/ui.Label object or whatever. oh, btw i know its a bit of a mess. hard when you are not sure of the math to get it as concise as it should be. ''' rects = [] r = ui.Rect(*rect_path).inset((obj_width / 2) + margin, (obj_width / 2) + margin) radius = r.width / 2 for i in range(0, num_objs): a = 2 * pi * (i + 1) / num_objs pos = (sin(a) * (radius * 1), cos(a) * (radius * 1)) r1 = ui.Rect(pos[0], pos[1], obj_width, obj_width) r1.x += ((r.width / 2) - (obj_width / 2) + r.x) r1.y += ((r.height / 2) - (obj_width / 2) + r.y) rects.append(r1) return (r, rects)
def layout(self): # master view r = ui.Rect(*self.bounds) r.width = r.width * self.master_percent self.master.frame = r r = ui.Rect(*self.bounds) r.width -= self.master.width r.x = self.master.width self.detail.bounds = r.inset(10, 10, 44, 0)
def grid_wh_(bounds, w, h): # a grid based on widths and heights # return a list of lists of ui.Rects r = ui.Rect(*bounds) rl = [] for i in range(int(r.height / h)): lst = [] for j in range(int(r.width / w)): lst.append(ui.Rect(j*w, h*i, w, h)) rl.append(lst) return rl
def split_view_h(parent, view, v_list, h_gap=0): ''' split a view horizontally. ''' r = ui.Rect(*view.frame) # reduce our width to allow for the h_gap param r.width -= h_gap * (len(v_list) - 1) def translate_width(pw, w): # i know can be done better... but thinking will expand this if w == 0 or w > 1: return w elif w == -1: return ph elif w < 1.0: return pw * w # translate the numbers in v_list to absolute numbers v_list = [translate_width(r.width, x) if x else x for x in v_list] # var is the space left over in the view after the absolute heights # have been subtracted divided by the number if items that are # equal to 0 zero_count = v_list.count(0) # aviod divide by zero error var = (r.width - sum(v_list)) / zero_count if zero_count else\ (r.width - sum(v_list)) # replaces 0 in v_list with var. v_list = [var if x == 0 else x for x in v_list] x = r.x y = r.y num_views = len(parent.subviews) for i, w in enumerate(v_list): frame = ui.Rect(x, y, w, r.height) if i is 0: # this is the frame we split. we just resize it view.frame = frame else: frame.x += (h_gap * i) v = ui.View(name='h' + str(i + num_views), frame=frame) v.flex = 'whlrtb' v.border_width = view.border_width v.corner_radius = view.corner_radius parent.add_subview(v) x += w
def __init__(self, x, y, width, height): self.rect = ui.Rect(x, y, width, height) self.border_rect = ui.Rect(x + self.border_margin, y + self.border_margin, width - 2 * self.border_margin, height - 2 * self.border_margin) self.border_rect.update_color((200, 200, 200)) self.inner_rect = ui.Rect(x + 2 * self.border_margin, y + 2 * self.border_margin, width - 4 * self.border_margin, height - 4 * self.border_margin) self.tabs = []
def grid_rc_(bounds, rows=1, columns=1): # a grid based on rows and columns # return a list of lists of ui.Rects r = ui.Rect(*bounds) w = r.width / columns h = r.height / rows rl = [] for i in range(rows): lst = [] for j in range(columns): lst.append(ui.Rect(j*w, h*i, w, h)) rl.append(lst) return rl
def layout(self): idx = 0 r = ui.Rect(*self.bounds) w = r.width / self._cols h = r.height / self._rows for i in range(self._rows): for j in range(self._cols): btn = self.day_btn_list[idx] f = ui.Rect(j * w, (i * h), w, h) btn.frame = f btn.day_lb.frame = btn.bounds.inset(10, 10) btn.day_lb.corner_radius = btn.width / 2 idx += 1
def layout(self): bw = self.width / 7 bh = self.height * 2 / 3 frame = ui.Rect(2 * bw, 0, 0.5 * bw, bh - 5) self.colons[0].frame = frame.inset(1, 1) frame = ui.Rect(4.5 * bw, 0, 0.5 * bw, bh - 5) self.colons[1].frame = frame.inset(1, 1) frame = ui.Rect(0, bh, self.width, self.height - bh) self.button.frame = frame.inset(4, 4) for i, b in enumerate(self.clock_numbers): frame = ui.Rect((i + 0.5 * int(i / 2)) * bw, 0, bw, bh) b.frame = frame.inset(3, 3) self.display_view.frame = (0, 0, self.width, bh)
def draw(self): r = ui.Rect(10, 10, 200, 200) s = ui.Path.oval(*r) ui.set_color('deeppink') s.fill() draw_arc(r.inset(10, 10))
def calculate_a_rect(i): a = -2 * math.pi * (i + 1) / num_objs + math.radians(-150) pos = math.sin(a) * radius, math.cos(a) * radius r1 = ui.Rect(*pos, obj_width, obj_width) r1.x += r.width / 2 - obj_width / 2 + r.x r1.y += r.height / 2 - obj_width / 2 + r.y return r1
def get_fixed_grid(self): w = self.width / self.cols h = self.height / self.rows # this list comp, is nice, for me anyway. return [ui.Rect(x*w, y*h, w, h) for x in range(self.cols) for y in range(self.rows)]
def layout(self): #resize ourself r = ui.Rect(*self.parent.bounds) r.width = r.width * self.width_percent self.frame = r # resize the table r1 = ui.Rect(*self.bounds) self.table.frame = r1.inset(44, 5) self.search.border_width = 2 # rezize search self.search.y = 0 self.search.x = 0 self.search.width = self.width
def draw(self): ''' draw a treatment for a selected date ''' if not self.sel_obj: return btn = self.sel_obj # only execute the code below, if the selected date is the # same year and monthb if self.selected_date: if btn.date.year != self.selected_date.year or\ btn.date.month != self.selected_date.month: return r = ui.Rect(*btn.day_lb.bounds).inset(0, 0) if r.width < r.height: r.height = r.width else: r.width = r.height r.center(btn.center) s = ui.Path.oval(*r) ui.set_color(self.date_selection_color) s.fill()
def __init__(self, r=ui.Rect(), *args, **kwargs): r = ui.Rect(*r) # considered to be defaults self.rect = r self.text = 'SAMPLE' self.font_name = 'Arial Rounded MT Bold' self.font_size = 0 self.text_color = 'white' self.margin = (0, 0) self.origin = (0, 0) self.use_shadow = True self.shadow_params = ('white', 0, 0, 0) self.rotate = 0 self.do_kwargs(**kwargs)
def emoji_to_image(emoji_char, w=32, h=32, font_name='Arial Rounded MT Bold', font_size=28, file_path=None): r = ui.Rect(0, 0, w, h) with ui.ImageContext(r.width, r.height) as ctx: # just draw the string ui.draw_string(emoji_char, rect=r, font=(font_name, font_size), color='black', alignment=ui.ALIGN_CENTER, line_break_mode=ui.LB_TRUNCATE_TAIL) img = ctx.get_image() # write a file if file_path if file_path: with open(file_path, 'wb') as file: file.write(img.to_png()) return img
def draw_label(self): owner = self.owner ui.set_color('purple') s = str('{:.0%}'.format(owner.value)) lb_rect = ui.Rect(*owner.cv) lb_rect.center(owner.center) ui.draw_string(s, lb_rect , font=('Arial Rounded MT Bold', 22), color='black', alignment=ui.ALIGN_CENTER, line_break_mode=ui.LB_TRUNCATE_TAIL)
def draw(self): # do a draw, just to see how it works r = ui.Rect(*self.bounds).inset(20, 20) s = ui.Path.rect(*r) s.line_width = 10 ui.set_color('blue') s.stroke()
def make_button(style=_btn_style, ext_attrs=_extra_attrs, *args, **kwargs): btn = ui.Button() # process the normal atttrs for k, v in kwargs.iteritems(): if hasattr(btn, k): setattr(btn, k, v) # process a style dict for k, v in style.iteritems(): if hasattr(btn, k): setattr(btn, k, v) # process addtional attrs... for k, v in ext_attrs.iteritems(): setattr(btn, k, v) # if kwargs has a parent key, then we add the subview to the parent if kwargs.has_key('parent'): kwargs['parent'].add_subview(btn) btn.size_to_fit() # size to fit is too tight btn.frame = ui.Rect(*btn.bounds).inset(0, -5) return btn
def layout(self): r = ui.Rect(*self.bounds) self.named_slider.center = self.center self.named_slider.y = self.height - self.named_slider.height - 40 return slider_min_max = self.get_subview_by_name('smm') slider_min_max.center = self.center slider_min_max.y = self.height - slider_min_max.height - 40
def subview_bounds(view): subviews_accumulated = list( accumulate([v.frame for v in view.subviews], ui.Rect.union)) if len(subviews_accumulated): bounds = subviews_accumulated[-1] else: bounds = ui.Rect(0, 0, 0, 0) return bounds.inset(-At.gap, -At.gap)
def layout(self): bw = self.width / COLS bh = floor(self.height / ROWS) if self.height <= 130 else floor(110 / ROWS) for i, btn in enumerate(self.buttons): btn.frame = ui.Rect(i % COLS * bw, i // COLS * bh, bw, bh).inset(2, 2) btn.alpha = 1 if btn.frame.max_y < self.height else 0