Initial work on erigo support in pyefl.
This will be developed in a separate branch and it will be ready for the 1.14 release. The generator implemented here is on-the-fly, it does not generate the python code, but actually generate the real interface from the json file on runtime. The work is really at a good point yet, just need to fix/implement some little more. Test included
This commit is contained in:
parent
d4572bf26a
commit
2d2bbb1977
|
@ -396,6 +396,22 @@ cdef class Object(evasObject):
|
|||
if type(self) is Object:
|
||||
raise TypeError("Must not instantiate Object, but subclasses")
|
||||
|
||||
property part_text:
|
||||
"""Sets the text of a specific part of this object.
|
||||
|
||||
:type: (part_name, text_to_set)
|
||||
|
||||
.. versionadded:: 1.14
|
||||
|
||||
"""
|
||||
def __set__(self, value):
|
||||
part, text = value
|
||||
if isinstance(part, unicode): part = PyUnicode_AsUTF8String(part)
|
||||
if isinstance(text, unicode): text = PyUnicode_AsUTF8String(text)
|
||||
elm_object_part_text_set(self.obj,
|
||||
<const char *>part if part is not None else NULL,
|
||||
<const char *>text if text is not None else NULL)
|
||||
|
||||
def part_text_set(self, part, text):
|
||||
"""Sets the text of a given part of this object.
|
||||
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
# Copyright (C) 2007-2015 various contributors (see AUTHORS)
|
||||
#
|
||||
# This file is part of Python-EFL.
|
||||
#
|
||||
# Python-EFL is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 3 of the License, or (at your option) any later version.
|
||||
#
|
||||
# Python-EFL is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this Python-EFL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
|
||||
TODO
|
||||
====
|
||||
|
||||
* fix 'file' property
|
||||
* mainmenu ??
|
||||
* implement Resources ... but when? always in the file prop?
|
||||
* test more widget items (only menu tested atm)
|
||||
* implement callbacks
|
||||
* documentation for this module
|
||||
|
||||
"""
|
||||
|
||||
import importlib
|
||||
import json
|
||||
|
||||
###################################################################
|
||||
## NOTE/TODO: importlib is only implemented from python 2.7
|
||||
## From py-efl 1.14 we will need to rise py min version
|
||||
###################################################################
|
||||
|
||||
|
||||
KLASSES = {
|
||||
'Elm_Win': ('efl.elementary.window', 'Window'),
|
||||
'Elm_Bg': ('efl.elementary.background', 'Background'),
|
||||
'Elm_Box': ('efl.elementary.box', 'Box'),
|
||||
'Elm_Button': ('efl.elementary.button', 'Button'),
|
||||
'Elm_Image': ('efl.elementary.image', 'Image'),
|
||||
'Elm_Label': ('efl.elementary.label', 'Label'),
|
||||
'Elm_Layout': ('efl.elementary.layout', 'Layout'),
|
||||
'Elm_Menu': ('efl.elementary.menu', 'Menu'),
|
||||
'Elm_Table': ('efl.elementary.table', 'Table'),
|
||||
}
|
||||
|
||||
|
||||
class ErigoGui(object):
|
||||
""" TODO: Class doc """
|
||||
|
||||
def __init__ (self, json_file=None, json_string=None, verbose=False):
|
||||
self._verbose = verbose
|
||||
self._widgets = {} # key: widget_name data: widget_instance
|
||||
|
||||
if json_file is not None:
|
||||
self._print('\n### Generating gui from file: %s' % json_file)
|
||||
data = json.load(open(json_file))
|
||||
elif json_string is not None:
|
||||
self._print('\n### Generating gui from string')
|
||||
data = json.loads(json_string)
|
||||
else:
|
||||
raise RuntimeError('One of "file" or "json_string" is mandatory')
|
||||
|
||||
for w_name in data['Settings']['start_points']:
|
||||
_widget_generate(self, data, w_name)
|
||||
|
||||
def _print(self, msg):
|
||||
if self._verbose:
|
||||
print(msg)
|
||||
|
||||
|
||||
def _widget_generate(self, data, name):
|
||||
self._print('\n### Generating widget: %s' % name)
|
||||
|
||||
# get the widget class object from the correct module
|
||||
w_data = data['Widgets'][name]
|
||||
eo_klass_name = w_data['Desc']['class']
|
||||
module_name, klass_name = KLASSES[eo_klass_name]
|
||||
mod = importlib.import_module(module_name)
|
||||
klass = getattr(mod, klass_name)
|
||||
|
||||
# class constructor
|
||||
if eo_klass_name+'.constructor' in w_data.get('Properties', []):
|
||||
# Custom CONSTRUCTOR
|
||||
params = w_data['Properties'][eo_klass_name+'.constructor']
|
||||
params = _params_list_parse(mod, params)
|
||||
w = klass(*params)
|
||||
else:
|
||||
# Standard CONSTRUCTOR
|
||||
parent_name = w_data['Desc']['parent']
|
||||
parent = self._widgets[parent_name]
|
||||
w = klass(parent)
|
||||
self._widgets[name] = w
|
||||
|
||||
|
||||
# make the widget public if requested
|
||||
if w_data['Desc'].get('public', False) is True:
|
||||
self._print('Installing name: %s' % name)
|
||||
setattr(self, name, w)
|
||||
|
||||
|
||||
# apply widget properties
|
||||
if 'Properties' in w_data:
|
||||
for eo_name, p_vals in w_data['Properties'].items():
|
||||
p_name = eo_name.split('.')[-1]
|
||||
if p_name == 'visibility':
|
||||
if p_vals[0] is True:
|
||||
w.show()
|
||||
elif p_name == 'constructor':
|
||||
pass
|
||||
else:
|
||||
self._print('property %s => %s' % (p_name, p_vals))
|
||||
p_vals = _params_list_parse(mod, p_vals)
|
||||
if p_name == 'file': # ARGHHHHHHHHHHH TODO FIXME
|
||||
p_vals = (p_vals[0])
|
||||
if len(p_vals) == 1:
|
||||
setattr(w, p_name, p_vals[0])
|
||||
else:
|
||||
setattr(w, p_name, p_vals)
|
||||
|
||||
|
||||
# generate widget items
|
||||
if 'Items' in w_data:
|
||||
for item_name, item_data in w_data['Items'].items():
|
||||
_item_generate(self, w, None, item_name, item_data)
|
||||
|
||||
|
||||
# generate (and pack) children widgets
|
||||
if eo_klass_name == 'Elm_Win':
|
||||
for c_name in w_data.get('Contains', []):
|
||||
child = _widget_generate(self, data, c_name)
|
||||
w.resize_object_add(child)
|
||||
|
||||
elif eo_klass_name == 'Elm_Box':
|
||||
for c_name in w_data.get('Contains', []):
|
||||
child = _widget_generate(self, data, c_name)
|
||||
w.pack_end(child)
|
||||
|
||||
elif eo_klass_name == 'Elm_Table':
|
||||
for c_name, (x, y, cspan, rspan) in w_data.get('Contains', {}).items():
|
||||
child = _widget_generate(self, data, c_name)
|
||||
w.pack(child, x, y, rspan, cspan)
|
||||
|
||||
return w
|
||||
|
||||
|
||||
def _item_generate(self, parent_widget, parent_item, item_name, item_data):
|
||||
self._print("Generating ITEM: %s" % item_name)
|
||||
it = parent_widget.item_add(parent_item,
|
||||
item_data['label'], # use kargs instead ?
|
||||
item_data['icon'])
|
||||
# print(item_data)
|
||||
# TODO make the item accessible with his name from the base class ???
|
||||
|
||||
if 'Items' in item_data:
|
||||
for item_name, item_data in item_data['Items'].items():
|
||||
_item_generate(self, parent_widget, it, item_name, item_data)
|
||||
|
||||
|
||||
def _params_list_parse(mod, params):
|
||||
return [ _param_parse(mod, p) for p in params ]
|
||||
|
||||
def _param_parse(mod, p_value):
|
||||
if isinstance(p_value, (unicode, str)):
|
||||
if p_value.startswith('ELM_'):
|
||||
enum_val = getattr(mod, p_value, None)
|
||||
if enum_val is not None:
|
||||
return enum_val
|
||||
return p_value
|
||||
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
{
|
||||
"JSON_Version":"2",
|
||||
"Settings":
|
||||
{
|
||||
"project":"pyefl_erigo_test",
|
||||
"images_prefix":"",
|
||||
"start_points":["elm_win1"]
|
||||
},
|
||||
"Resources":
|
||||
{
|
||||
"Images":
|
||||
{
|
||||
"logo":"/home/yakov/egui/examples/logo.png"
|
||||
}
|
||||
},
|
||||
"Widgets":
|
||||
{
|
||||
"elm_win1":
|
||||
{
|
||||
"Desc":
|
||||
{
|
||||
"parent":null,
|
||||
"class":"Elm_Win"
|
||||
},
|
||||
"Properties":
|
||||
{
|
||||
"Evas.Object.visibility":[true],
|
||||
"Elm_Win.constructor":[null, "ELM_WIN_BASIC"],
|
||||
"Elm_Win.autodel":[true],
|
||||
"Elm_Win.title":["Win1 Title"],
|
||||
"Evas.Object.size":[381, 480]
|
||||
},
|
||||
"Contains":["elm_bg1", "elm_box1"]
|
||||
},
|
||||
"elm_win1_main_menu":
|
||||
{
|
||||
"Desc":
|
||||
{
|
||||
"parent":"elm_win1",
|
||||
"class":"Elm_Menu",
|
||||
"public":true
|
||||
},
|
||||
"Items":
|
||||
{
|
||||
"elm_win1_main_menu_it0":
|
||||
{
|
||||
"type":"regular",
|
||||
"icon":"stop",
|
||||
"label":"Button",
|
||||
"callback":null,
|
||||
"Items":
|
||||
{
|
||||
"elm_win1_main_menu_it2":
|
||||
{
|
||||
"type":"regular",
|
||||
"icon":"fileopen",
|
||||
"label":"Show",
|
||||
"callback":null
|
||||
},
|
||||
"elm_win1_main_menu_it3":
|
||||
{
|
||||
"type":"regular",
|
||||
"icon":"list-add",
|
||||
"label":"Hide",
|
||||
"callback":null
|
||||
}
|
||||
}
|
||||
},
|
||||
"elm_win1_main_menu_it1":
|
||||
{
|
||||
"type":"regular",
|
||||
"icon":"list-add",
|
||||
"label":"Table",
|
||||
"callback":null,
|
||||
"Items":
|
||||
{
|
||||
"elm_win1_main_menu_it4":
|
||||
{
|
||||
"type":"regular",
|
||||
"icon":"search",
|
||||
"label":"Show",
|
||||
"callback":null
|
||||
},
|
||||
"elm_win1_main_menu_it5":
|
||||
{
|
||||
"type":"regular",
|
||||
"icon":"fileopen",
|
||||
"label":"Hide",
|
||||
"callback":null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"elm_bg1":
|
||||
{
|
||||
"Desc":
|
||||
{
|
||||
"parent":"elm_win1",
|
||||
"class":"Elm_Bg"
|
||||
},
|
||||
"Properties":
|
||||
{
|
||||
"Evas.Object.visibility":[true],
|
||||
"Elm_Widget.part_text":[null, "elm_bg1"],
|
||||
"Evas.Object.size_hint_weight":[1, 1]
|
||||
}
|
||||
},
|
||||
"elm_box1":
|
||||
{
|
||||
"Desc":
|
||||
{
|
||||
"parent":"elm_win1",
|
||||
"class":"Elm_Box"
|
||||
},
|
||||
"Properties":
|
||||
{
|
||||
"Evas.Object.visibility":[true],
|
||||
"Elm_Widget.part_text":[null, "elm_box1"],
|
||||
"Evas.Object.size_hint_weight":[1, 1]
|
||||
},
|
||||
"Contains":["elm_label1", "elm_button1", "elm_table1"]
|
||||
},
|
||||
"elm_button1":
|
||||
{
|
||||
"Desc":
|
||||
{
|
||||
"parent":"elm_box1",
|
||||
"class":"Elm_Button"
|
||||
},
|
||||
"Properties":
|
||||
{
|
||||
"Evas.Object.visibility":[true],
|
||||
"Elm_Widget.part_text":[null, "elm_button1"],
|
||||
"Evas.Object.size_hint_weight":[1, 1],
|
||||
"Evas.Object.size_hint_align":[-1, -1]
|
||||
}
|
||||
},
|
||||
"elm_table1":
|
||||
{
|
||||
"Desc":
|
||||
{
|
||||
"parent":"elm_box1",
|
||||
"class":"Elm_Table"
|
||||
},
|
||||
"Properties":
|
||||
{
|
||||
"Evas.Object.visibility":[true],
|
||||
"Elm_Widget.part_text":[null, "elm_table1"],
|
||||
"Evas.Object.size_hint_weight":[1, 1],
|
||||
"Evas.Object.size_hint_align":[-1, -1]
|
||||
},
|
||||
"Contains":
|
||||
{
|
||||
"elm_button2":[0, 0, 1, 1],
|
||||
"elm_button3":[1, 1, 1, 1],
|
||||
"elm_image1":[1, 0, 1, 1]
|
||||
}
|
||||
},
|
||||
"elm_button2":
|
||||
{
|
||||
"Desc":
|
||||
{
|
||||
"parent":"elm_table1",
|
||||
"class":"Elm_Button"
|
||||
},
|
||||
"Properties":
|
||||
{
|
||||
"Evas.Object.visibility":[true],
|
||||
"Elm_Widget.part_text":[null, "elm_button2"],
|
||||
"Evas.Object.size_hint_weight":[1, 1],
|
||||
"Evas.Object.color":[0, 255, 0, 255]
|
||||
},
|
||||
"Callbacks":
|
||||
{
|
||||
"clicked":["Modify", "elm_button1", "Evas.Object.visibility", [false]]
|
||||
}
|
||||
},
|
||||
"elm_button3":
|
||||
{
|
||||
"Desc":
|
||||
{
|
||||
"parent":"elm_table1",
|
||||
"class":"Elm_Button"
|
||||
},
|
||||
"Properties":
|
||||
{
|
||||
"Evas.Object.visibility":[true],
|
||||
"Elm_Widget.part_text":[null, "elm_button3"],
|
||||
"Evas.Object.size_hint_weight":[1, 1],
|
||||
"Evas.Object.color":[255, 255, 0, 255]
|
||||
},
|
||||
"Callbacks":
|
||||
{
|
||||
"clicked":["Modify", "elm_button1", "Evas.Object.visibility", [true]]
|
||||
}
|
||||
},
|
||||
"elm_image1":
|
||||
{
|
||||
"Desc":
|
||||
{
|
||||
"parent":"elm_table1",
|
||||
"class":"Elm_Image"
|
||||
},
|
||||
"Properties":
|
||||
{
|
||||
"Elm_Widget.part_text":[null, "elm_image1"],
|
||||
"Evas.Object.size_hint_weight":[1, 1],
|
||||
"Evas.Object.visibility":[true],
|
||||
"Efl.File.file":["logo", null],
|
||||
"Evas.Object.size":[40, 40],
|
||||
"Evas.Object.size_hint_align":[-1, -1]
|
||||
}
|
||||
},
|
||||
"elm_label1":
|
||||
{
|
||||
"Desc":
|
||||
{
|
||||
"parent":"elm_box1",
|
||||
"class":"Elm_Label",
|
||||
"public":true
|
||||
},
|
||||
"Properties":
|
||||
{
|
||||
"Evas.Object.visibility":[true],
|
||||
"Elm_Widget.part_text":[null, "Label"],
|
||||
"Evas.Object.size_hint_weight":[1, 0]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
from efl import elementary
|
||||
from efl.utils.erigo import ErigoGui
|
||||
|
||||
prj_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "erigo_prj")
|
||||
json_file = os.path.join(prj_path, "test_gui.egui")
|
||||
|
||||
def erigo_clicked(obj):
|
||||
start_time = time.time()
|
||||
|
||||
# Test from file
|
||||
egui = ErigoGui(json_file, verbose=True)
|
||||
|
||||
# Test from json string
|
||||
# json = open(json_file).read()
|
||||
# egui = ErigoGui(json_string=json, verbose=True)
|
||||
|
||||
egui.elm_label1.text = 'GUI Generated in %.5f seconds' % \
|
||||
(time.time() - start_time)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
elementary.init()
|
||||
|
||||
erigo_clicked(None)
|
||||
|
||||
elementary.run()
|
||||
elementary.shutdown()
|
||||
|
Loading…
Reference in New Issue