Forum Archive

Overriding tint_color on an inherited ui.View?

iAmMortos

I was in the process of making a custom button ui.View with event hooks for button press as well as button release. I wanted to make a button that would trigger repeated actions when held down. That's all well and good and the eventing works fine, but I also tried to emulate, to the best of my ability, all the features that ui.Button has, like allowing text and or an icon that makes use of tint_color etc. This required overriding the draw method and inserting the set_needs_display() calls in the appropriate places.

Apparently, however, setting tint_color on a ui.View does not trigger the set_needs_display() to redraw the view. I assumed that tint_color was just a property on ui.View that, under the covers, did all the fancy things to make the view update itself by default, and that I would be able to override it in a reasonable manner to call super().tint_color.fset() or something like that followed by a set_needs_display() to redraw my view. After looking into it a little further, ui.View.tint_color is just a plain old attribute. So in order for me to properly handle the redrawing of the View I had to make new property getters and setters named tint that sets tint_color and calls set_needs_display().

I really dislike this solution because now the API for my custom button is nonstandard and it makes me feel... dirty... lol

Am I misunderstanding how tint_color works/should work?

JonB

One approach would be to simply use a ui.Button, under the hood, and just use the UI.View for touch.

actually the best approach maybe to use @mikael's objc gestures which lets you define more detailed gestures on any UI item, by hooking into the underlying native objects and iOS gestures.

There was also some discussion a while back on using some sort of mocking framework, which I forget the name of, to "extend" built in types, which involved some sort of metaclass magic. maybe @dgelessus or @mikael will remember...

iAmMortos

Marvelous suggestions. Thank you!

I would love to know how they do this black magic tint_color buffoonery underneath. I'm always more and more impressed with what is possible within the bounds of this app. It's incredible.

Thanks again.

JonB

Under the hood, it is all done in c... objc UIViews have a method you can define called tintColorDidChange that you would use to redraw whatever needs redrawing.

if you were implementing your own version using draw, in python, you would indeed use @properties, and getters and setters.

Another similar example of "composting": here is a vertical slider which is a ui.View containing a slider. Most of the key attributes are just sent to and read from the embedded slider. There may a more general approach using getattribute etc to route attributes, or force redraw, etc
https://github.com/jsbain/uicomponents/blob/master/VerticalSlider.py

mikael

@iAmMortos, all of @JonB’s suggestions make sense.

The extend option would allow you to use the code you already have for your View, and would be used like this:

#coding: utf-8
from ui import *
from composite import Composite
import console

class YourTouchView(View):
  ''' Class that handles touch events instead
  of the underlying button. '''
  touch_sink = True

  def touch_ended(self, touch):
    console.hud_alert('Custom touch')

if __name__ == '__main__':
  v = View()
  v.background_color = 'white'
  v.present('sheet')

  btn = Button(title='Click me', background_color='white', tint_color='black')

  my_button = Composite(btn, YourTouchView)

  v.add_subview(my_button)
  my_button.center = v.center
  my_button.tint_color = 'red'

You can also create a reusable ”Chainable” class with the same effect, see the documentation for details. Please note that the whole composite thing is very much beta.

mikael

@JonB, ”composting”, lol.

dgelessus

There was also some discussion a while back on using some sort of mocking framework, which I forget the name of, to "extend" built in types

That sounds like @Webmaster4o's ui2 perhaps? Specifically the subclassing module.

JonB

Ah, ProxyTypes is what I was thinking of.
https://forum.omz-software.com/topic/2513/getting-the-parent-of-a-dynamically-method-as-a-function/15