Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Ui control subclassing [really good idea 😬]
-
@JonB , I am looking. But I am also looking for a way you solved the load pyui issue also. Bindings etc... Not get getting very far... But I think the answer is there. I looked at your code. But only brief. I was excited to make it like you did in the new.
But my first thought was also to try and Marshall between the values. I understand the concept, but executing is a different matter for me at my level. But when I fail enough times I will go back to your code 😬 -
@JonB , the code below has some problems. I am not sure yet, but that's not an issue I think. Just a matter of working out. But just wanted to see what you think about the approach.
The main part is your code from your AdvancedTextView. I tried my own ideas and failed 😱😁
Never mind. But as you mentioned above the detail of the internals should be removed. Please keep in mind I have little exp with OOP. But I have tried to abstract it the best I knew how.
It would be nice if you or someone else could tell me I am on the right track, or if I am butchering it.
I tried to use new with the _uiButtonExt class so that the uiButtonExt didn't have to call the super explicitly. I think it could work, but I didn't get it working.''' dict of dicts key == x.__class.__name__ value = dict of the defaults for the object ''' _std_defaults = \ { 'Button' : { 'tint_color': 'black', 'width' : 80, 'height' : 32, 'background_color' : 'yellow', 'x' : 100, 'y' : 200, }, } class ControlExt(ui.View): def __init__(self , ui_object, *args, **kwargs): print 'in here, ControlExt init' print kwargs self.obj = ui_object() self.std_object_creation(self.obj) self.set_obj_args(self.obj, *args, **kwargs) def __setattr__(self, name,value): if name not in ['frame','width','height','x','y','flex','hidden','transform']: if hasattr(self,'obj'): if name in dir(self.obj): object.__setattr__(self.obj,name,value) object.__setattr__(self,name,value) def __getattribute__(self,name): try: return object.__getattribute__(self,name) except AttributeError: if hasattr(self,'obj') and name in dir(self.obj): return object.__getattribute__(self.obj,name) else: raise # dont use the obj init to set the args, kwargs def set_obj_args(obj, *args, **kwargs): print 'set_obj_args args etc', kwargs for k,v in kwargs.iteritems(): if hasattr(obj, k): if k == 'image': setattr(obj, k , self.get_named_ui_image(v)) else: setattr(obj, k, v) def get_named_ui_image(self, image_name): return ui.Image.named(image_name) def std_object_creation(self, obj): #set the attrs of the object as created without passing attrs class_str = obj.__class__.__name__ obj_defaults = _std_defaults.get(class_str, False) if not obj_defaults: return print 'in here, std_object_creation', obj_defaults for k,v in obj_defaults.iteritems(): if hasattr(obj, k): if k == 'image': setattr(obj, k , self.get_named_ui_image(v)) else: print 'std_object_creation', k, v setattr(obj, k, v) # we need to create one per ui. class type class _uiButtonExt(ControlExt): ''' Can do ui.Button specfic stuff here ''' def __init__(self, *args, **kwargs): ControlExt.__init__(self, ui.Button, *args, **kwargs) # we only want to deal with this class class uiButtonExt(_uiButtonExt): def __init__(self, *args, **kwargs): _uiButtonExt.__init__(self, *args, **kwargs) if __name__ == '__main__': f = (0,0, 500, 500) v = ui.View(frame = f ) v.present('sheet') btn = uiButtonExt(width = 300, heigth = 32, title = 'tom jones', tint_color = 'orange', bg_color = 'black') v.add_subview(btn)
-
The idea is that the ControlExt handles all the attribute marshalling as you did before. Also,bro handle the so called default constructor the defaults the ui object is normally created with without params. Also to handle the kwargs for the object , rather than pass them to the object , iterate through them and set them, as they are all not handled when passed as params. Hopefully this Class will be able to handle all the ui elements generically.
Then the _uiButtonExt which inherits from ControlExt is suppose to try and shield another layer of implementation from the user/developer. Will need to create a _uiTextViewExt, _uiTableView etc...
The reason for the middleware class is so that we can get specific about the specific object if required without exposing the implementation details to the developer.Lastly the child class (not sure correct terminology) , uiButtonExt(_uiButtonExt). But for all intent and purposes this should behave as a uiButton class. As I mentioned above it would be nice not to have to call the super init, I think I can be worked out with new.
Anyway, just wanted to give my rationale. I thought it was important to put the middleware class in. The ControlExt class could get very messy if we have to keep dealing with exceptions. My feeling was to try to keep that as generic as possible
-
@omz, although it seems obvious but maybe not. But Python code lib patches/additions don't need to wait for a Pythonista release. If you are really finished, you can put them in a repo for us to test and use. Just tell us in the site-packages we should place it,
I think as long as the interface is finalised or very close to what will be released.
Just another idea -
I believe you will need to set flex='wh' in your obj, so that the encapsulated object follows your new class in terms of size(that is why I explicitly prevented frame parameters from getting passed to the encapsulated obj). Also, probably things like border, border_width, corner_radius and maybe a few others should not go to the encapsulated obj.
For buttons and other action-y things, presumably the point is to take some other action. So you might want special handling of action and delegate attributes (don't pass them on to obj). For instance, you would as part of the standard creation set up an _action, set obj.action=self._action, and in self._action you'd check self.action is present and callable, in which case you'd call it, perhaps before or after doing something custom. Delegate's need similar treatment, except you also maybe need to implement all standard delegate actions, so you can intercept and modify the way the delegates work.
-
@JonB , thanks. Yes I am working on that now. Gets confusing with get and set attributes being overriden . I have seen the warnings when reading about doing this before 😱
I understand the object, Call now. Calling the base class to avoid endless recursion. But unless I am mistaken I also have to add the ui_object to the view in ControlEx, I hadn't been doing that. But it makes sense I need to. I have done it now. Works more like I expect it to. I can see a title for expample 👍
But I will just keep working on it. LOL, no wonder I never finish anything 🤐Will also look at the delegates if I every get this part working
-
Is your intention that a developer would subclass ButtonExt? or _ButtonExt?
-
@JonB , _uiButtonEx. Well that's the idea. Not sure it's the correct idea. but from my comments , I can see why it's confusing. I have been getting confused myself. I am rewinding a lot now, because it's too complicated. Not the structure of the classes, just the attr stuff in ControlExt. I got a little carried away and I am lost with all the side effects. So will go back to your basic code, and start again in that class 😱😜
Only way to learn. -
@JonB , have made some headway... Not much to brag about though... I can still see the potential 😱😁
I put it in a gist , nowhere close to being finished. But the idea is there -
comments in the gist.
-
@JonB , thanks. Great comments. I have been working on it. It will take a few days before I upload again. But also have to learn about splitting the files up now. I have done it, but the imports not working as I thought they would. I got it working , but I can see it's not right. I did the init file and did the all list. But it's ok, I am missing something yet again in my understanding. I also made some comments at the gist. But I have uiLabel, uiButton, ui.TextField working ok at the moment. UiTextField using self as a delegate. Easy to have an external delegate.
But again thanks for your help. I am sure this is not a challenge for you. But I have to learn so many things along the way. But loving it 😳😱😛 -
@JonB , thanks. Great comments. I have been working on it. It will take a few days before I upload again. But also have to learn about splitting the files up now. I have done it, but the imports not working as I thought they would. I got it working , but I can see it's not right. I did the init file and did the all list. But it's ok, I am missing something yet again in my understanding. I also made some comments at the gist. But I have uiLabel, uiButton, ui.TextField working ok at the moment. UiTextField using self as a delegate. Easy to have an external delegate.
But again thanks for your help. I am sure this is not a challenge for you. But I have to learn so many things along the way. But loving it 😳😱😛 -
@JonB , thanks. Great comments. I have been working on it. It will take a few days before I upload again. But also have to learn about splitting the files up now. I have done it, but the imports not working as I thought they would. I got it working , but I can see it's not right. I did the init file and did the all list. But it's ok, I am missing something yet again in my understanding. I also made some comments at the gist. But I have uiLabel, uiButton, ui.TextField working ok at the moment. UiTextField using self as a delegate. Easy to have an external delegate.
But again thanks for your help. I am sure this is not a challenge for you. But I have to learn so many things along the way. But loving it 😳😱😛 -
@JonB , thanks. Great comments. I have been working on it. It will take a few days before I upload again. But also have to learn about splitting the files up now. I have done it, but the imports not working as I thought they would. I got it working , but I can see it's not right. I did the init file and did the all list. But it's ok, I am missing something yet again in my understanding. I also made some comments at the gist. But I have uiLabel, uiButton, ui.TextField working ok at the moment. UiTextField using self as a delegate. Easy to have an external delegate.
But again thanks for your help. I am sure this is not a challenge for you. But I have to learn so many things along the way. But loving it 😳😱😛 -
@JonB , I have put this in its own repo now. Look it's ugly. I am still working through it. I am slow though. It's quite evident there a lot a of things I don't understand. But hopefully as I keep working on it , it will start to take a better shape. Even the naming is crap 😀 Anyway, it's viewable and runnable.
The repo
-
@JonB , please be a little patient with me.i have had many visitors the last few days. I have been working on it when I get the chance. The current repo Not even worth looking at. Many things change. But in the finer details of implementing this, is getting very tricky. For me at least. The side effects are so hard work out.but, I will update the repo in a few days.
Basically saying I am still working on it. I think the next version will be ok. But I am still struggling with the structure of a package! -
@JonB , after a long afternoon of trying understand the side effects I was creating, I have decided to go a different way. It gets worse when trying to add functionality to the class, which is the main intent. I am not giving up. I just dont think its a viable solution. I know you did it in a limited context.
I have thought of another way with just some wrapper functions. I am pretty sure i will be able to achieve almost all I wanted to do with a fraction of the code and side effects. Let's see 😱😳👍