Skip to content

Commit 46d0a85

Browse files
committed
Merge.
2 parents 42ebcc2 + 2b860cd commit 46d0a85

File tree

9 files changed

+691
-483
lines changed

9 files changed

+691
-483
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ Subfolders are accepted, and so:
4848
my_widget.attributes['background-image'] = "url('/my_resources:subfolder/other_subfolder/image.png')"
4949
```
5050

51+
The event TextInput.onenter is no more supported.
52+
53+
The events TextInput.onkeydown and TextInput.onkeyup are now different, and require a different listener format. There is an additional parameter keycode.
54+
55+
The TextInput.onchange event now occurs also in case of Enter key pressed, if TextInput is single_line.
56+
5157

5258
Getting Started
5359
===

editor/editor.py

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -593,14 +593,7 @@ def main(self):
593593
594594
return false;""" % {'evt':self.EVENT_ONDROPPPED}
595595
self.project.attributes['editor_varname'] = 'App'
596-
self.project.attributes[self.project.EVENT_ONKEYDOWN] = """
597-
var params={};
598-
params['keypressed']=event.keyCode;
599-
sendCallbackParam('%(id)s','%(evt)s',params);
600-
if(event.keyCode==46){
601-
return false;
602-
}
603-
""" % {'id':str(id(self)), 'evt':self.project.EVENT_ONKEYDOWN}
596+
self.project.onkeydown.connect(self.onkeydown)
604597

605598
self.projectConfiguration = editor_widgets.ProjectConfigurationDialog('Project Configuration', 'Write here the configuration for your project.')
606599

@@ -801,10 +794,10 @@ def toolbar_delete_clicked(self, widget):
801794
self.selectedWidget = parent
802795
print("tag deleted")
803796

804-
def onkeydown(self, keypressed):
805-
if str(keypressed)=='46': #46 the delete keycode
797+
def onkeydown(self, emitter, key, keycode, ctrl, shift, alt):
798+
if str(keycode)=='46': #46 the delete keycode
806799
self.toolbar_delete_clicked(None)
807-
print("Key pressed: " + str(keypressed))
800+
print("Key pressed: " + str(keycode))
808801

809802

810803
def on_dropped(self, left, top):
@@ -816,16 +809,5 @@ def on_dropped(self, left, top):
816809
self.style['top']=top
817810

818811

819-
def main():
820-
#p = Project()
821-
#root = p.load('./example_project.py')
822-
#p.append(root, "root")
823-
#p.save(None)
824-
825-
# starts the webserver
826-
# optional parameters
827-
# start(MyApp,address='127.0.0.1', port=8081, multiple_instance=False,enable_file_cache=True, update_interval=0.1, start_browser=True)
828-
start(Editor, debug=False, address='0.0.0.0', port=8082, update_interval=0.01)
829-
830812
if __name__ == "__main__":
831-
main()
813+
start(Editor, debug=False, address='0.0.0.0', port=8082, update_interval=0.01, multiple_instance=True)

editor/editor_widgets.py

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -295,16 +295,17 @@ def show(self, *args):
295295

296296
def add_fileinput_field(self, defaultname='untitled'):
297297
self.txtFilename = gui.TextInput()
298-
self.txtFilename.onenter.connect(self.on_enter_key_pressed)
298+
self.txtFilename.onkeydown.connect(self.on_enter_key_pressed)
299299
self.txtFilename.set_text(defaultname)
300300

301301
self.add_field_with_label("filename","Filename",self.txtFilename)
302302

303303
def get_fileinput_value(self):
304304
return self.get_field('filename').get_value()
305305

306-
def on_enter_key_pressed(self, widget, value):
307-
self.confirm_value(None)
306+
def on_enter_key_pressed(self, widget, value, keycode):
307+
if keycode=="13":
308+
self.confirm_value(None)
308309

309310
@gui.decorate_event
310311
def confirm_value(self, widget):
@@ -651,7 +652,7 @@ def __init__(self, appInstance, **kwargs):
651652
self.style['display'] = 'block'
652653
self.style['overflow'] = 'hidden'
653654

654-
self.txtInput = StringEditor(width='80%', height='100%')
655+
self.txtInput = gui.TextInput(width='80%', height='100%')
655656
self.txtInput.style['float'] = 'left'
656657
self.txtInput.onchange.connect(self.on_txt_changed)
657658
self.append(self.txtInput)
@@ -685,32 +686,6 @@ def set_value(self, value):
685686
self.txtInput.set_value(value)
686687

687688

688-
class StringEditor(gui.TextInput, gui.EventSource):
689-
""" This class sends the input directly to the listener, but don't applies the changes
690-
to the widget itself in order to avoid to get updated losting the focus.
691-
The value will be committed to the widget itself when blurs.
692-
"""
693-
def __init__(self, *args, **kwargs):
694-
super(StringEditor, self).__init__(True, *args, **kwargs)
695-
gui.EventSource.__init__(self)
696-
self.attributes[self.EVENT_ONBLUR] = \
697-
"""var elem=document.getElementById('%(id)s');elem.value = elem.value.split('\\n').join('');
698-
var params={};params['new_value']=elem.value;
699-
sendCallbackParam('%(id)s','%(evt)s',params);""" % {'id': self.identifier, 'evt': self.EVENT_ONCHANGE}
700-
701-
self.attributes[self.EVENT_ONKEYUP] = \
702-
"""var elem=document.getElementById('%(id)s');elem.value = elem.value.split('\\n').join('');
703-
var params={};params['new_value']=elem.value;
704-
sendCallbackParam('%(id)s','%(evt)s',params);""" % {'id': self.identifier, 'evt': self.EVENT_ONKEYUP}
705-
706-
self.attributes[self.EVENT_ONKEYDOWN] = \
707-
"""if((event.charCode||event.keyCode)==13){event.keyCode = 0;event.charCode = 0; return false;}""" % {'id': self.identifier}
708-
709-
@gui.decorate_event
710-
def onkeyup(self, new_value):
711-
return (new_value,)
712-
713-
714689
#widget that allows to edit a specific html and css attributes
715690
# it has a descriptive label, an edit widget (TextInput, SpinBox..) based on the 'type' and a title
716691
class EditorAttributeInput(gui.Widget, gui.EventSource):
@@ -757,7 +732,7 @@ def __init__(self, attributeName, attributeDict, appInstance=None):
757732
self.inputWidget = CssSizeInput(appInstance)
758733

759734
else: #default editor is string
760-
self.inputWidget = StringEditor()
735+
self.inputWidget = gui.TextInput()
761736

762737
self.inputWidget.onchange.connect(self.on_attribute_changed)
763738
self.inputWidget.set_size('50%','22px')

examples/examples_from_contributors/SCOREBOARD_WITH_SETTING_PAGE/SCOREBOARD_WITH_SETTING_PAGE.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def idle(self):
2828
def ChangeColor(self, Text, Side, Num, BtUp, BtDn):
2929
self.In = 1
3030
with self.update_lock:
31-
Text.set_text(Num)
31+
Text.set_text(str(Num))
3232
Side.style['background-color'] = 'red'
3333
BtUp.attributes['class']='up80red'
3434
BtDn.attributes['class']='dn80red'
@@ -89,22 +89,22 @@ def main(self):
8989
self.wid3 = gui.Widget(width=230, height=350, margin='5px', style={'background':'green'})
9090
# Left side interface
9191
self.lblLeftName = gui.Label(self.Name1, width='95%', height='60px', style={'margin':'20px 2px 0px', 'font-size':'40px', 'line-height':'60px', 'text-align':'center', 'overflow':'hidden'})
92-
self.lblLeftNum = gui.Label(self.LeftNum, width='100%', height='130px', style={'margin':'0px 0px 10px', 'font-size':'140px', 'line-height':'130px', 'text-align':'center'})
92+
self.lblLeftNum = gui.Label(str(self.LeftNum), width='100%', height='130px', style={'margin':'0px 0px 10px', 'font-size':'140px', 'line-height':'130px', 'text-align':'center'})
9393
self.btLeftPlus = gui.Button('', width='80px', height='80px', style={'margin':'0px 10px 20px', 'font-size':'50px', 'line-height':'50px', 'text-align':'center'})
9494
self.btLeftPlus.attributes['class']='up80'
9595
self.btLeftMinus = gui.Button('', width='80px', height='80px', style={'margin':'0px 10px 20px', 'font-size':'50px', 'line-height':'50px', 'text-align':'center'})
9696
self.btLeftMinus.attributes['class']='dn80'
9797
lblLeftMatch = gui.Label('MATCHES WON:', width=150, height='30px', style={'margin':'0px 5px', 'font-size':'20px', 'line-height':'30px', 'text-align':'left', 'display':'inline'})
98-
self.lblLeftMatches = gui.Label(self.LeftMatchNum, width=30, height='30px', style={'margin':'0px 5px', 'font-size':'20px', 'line-height':'30px', 'text-align':'left', 'display':'inline'})
98+
self.lblLeftMatches = gui.Label(str(self.LeftMatchNum), width=30, height='30px', style={'margin':'0px 5px', 'font-size':'20px', 'line-height':'30px', 'text-align':'left', 'display':'inline'})
9999
# Right side interface
100100
self.lblRightName = gui.Label(self.Name2, width='95%', height='60px', style={'margin':'20px 2px 0px', 'font-size':'40px', 'line-height':'60px', 'text-align':'center', 'overflow':'hidden'})
101-
self.lblRightNum = gui.Label(self.LeftNum, width='100%', height='130px', style={'margin':'0px 0px 10px', 'font-size':'140px', 'line-height':'130px', 'text-align':'center'})
101+
self.lblRightNum = gui.Label(str(self.LeftNum), width='100%', height='130px', style={'margin':'0px 0px 10px', 'font-size':'140px', 'line-height':'130px', 'text-align':'center'})
102102
self.btRightPlus = gui.Button('', width='80px', height='80px', style={'margin':'0px 10px 20px', 'font-size':'50px', 'line-height':'50px', 'text-align':'center'})
103103
self.btRightPlus.attributes['class']='up80'
104104
self.btRightMinus = gui.Button('', width='80px', height='80px', style={'margin':'0px 10px 20px', 'font-size':'50px', 'line-height':'50px', 'text-align':'center'})
105105
self.btRightMinus.attributes['class']='dn80'
106106
lblRightMatch = gui.Label('MATCHES WON:', width=150, height='30px', style={'margin':'0px 5px', 'font-size':'20px', 'line-height':'30px', 'text-align':'left', 'display':'inline'})
107-
self.lblRightMatches = gui.Label(self.RightMatchNum, width=30, height='30px', style={'margin':'0px 5px', 'font-size':'20px', 'line-height':'30px', 'text-align':'left', 'display':'inline'})
107+
self.lblRightMatches = gui.Label(str(self.RightMatchNum), width=30, height='30px', style={'margin':'0px 5px', 'font-size':'20px', 'line-height':'30px', 'text-align':'left', 'display':'inline'})
108108
# Appends all the widgets to create the interface
109109
self.wid2.append([self.lblLeftName, self.lblLeftNum, self.btLeftPlus, self.btLeftMinus, lblLeftMatch, self.lblLeftMatches])
110110
self.wid3.append([self.lblRightName, self.lblRightNum, self.btRightPlus, self.btRightMinus, lblRightMatch, self.lblRightMatches])
@@ -113,7 +113,7 @@ def main(self):
113113
# Extra labels and button to manage:
114114
# The number of games to win, to win a match
115115
lblMatch = gui.Label('GAMES FOR MATCH:', width='50%', height='50px', style={'margin':'15px 2px 0px 10px', 'font-size':'25px', 'line-height':'35px', 'text-align':'center'})
116-
self.lblMatches = gui.Label(self.MatchNum, width='8%', height='50px', style={'margin':'15px 2px 0px', 'font-size':'25px', 'line-height':'35px', 'text-align':'center'})
116+
self.lblMatches = gui.Label(str(self.MatchNum), width='8%', height='50px', style={'margin':'15px 2px 0px', 'font-size':'25px', 'line-height':'35px', 'text-align':'center'})
117117
btMatchPlus = gui.Button('', width='50px', height='50px', style={'margin':'5px 2px 0px 20px', 'font-size':'30px', 'line-height':'30px', 'text-align':'center'})
118118
btMatchPlus.attributes['class']='up50'
119119
btMatchMinus = gui.Button('', width='50px', height='50px', style={'margin':'5px 2px', 'font-size':'30px', 'line-height':'30px', 'text-align':'center'})
@@ -185,11 +185,11 @@ def on_button_setting(self, emitter):
185185
def check_score(self):
186186
# Here the software update automatically any number you can see in the app
187187
if (self.LeftNum < self.MatchNum) and (self.RightNum < self.MatchNum):
188-
self.lblLeftNum.set_text(self.LeftNum)
189-
self.lblRightNum.set_text(self.RightNum)
190-
self.lblLeftMatches.set_text(self.LeftMatchNum)
191-
self.lblRightMatches.set_text(self.RightMatchNum)
192-
self.lblMatches.set_text(self.MatchNum)
188+
self.lblLeftNum.set_text(str(self.LeftNum))
189+
self.lblRightNum.set_text(str(self.RightNum))
190+
self.lblLeftMatches.set_text(str(self.LeftMatchNum))
191+
self.lblRightMatches.set_text(str(self.RightMatchNum))
192+
self.lblMatches.set_text(str(self.MatchNum))
193193
# Here the software check if a background needs to be green or orange.
194194
if (self.LeftNum < self.MatchNum - 1):
195195
self.wid2.style['background-color'] = 'green'

examples/examples_from_contributors/bootstrap.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@
1818

1919
class MyApp(App):
2020
def __init__(self, *args):
21+
res_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'res')
22+
#static_file_path can be an array of strings allowing to define
23+
# multiple resource path in where the resources will be placed
24+
super(MyApp, self).__init__(*args, static_file_path=res_path)
25+
26+
def idle(self):
27+
#idle loop, you can place here custom code
28+
# avoid to use infinite iterations, it would stop gui update
29+
pass
30+
31+
def main(self):
2132
#custom additional html head tags
2233
my_html_head = """<title>Bootstrap Test</title>"""
2334

@@ -38,18 +49,11 @@ def __init__(self, *args):
3849
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
3950
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
4051
"""
52+
#appending elements to page header
53+
self.page.children['head'].add_child('myhtml', my_html_head)
54+
self.page.children['head'].add_child('mycss', my_css_head)
55+
self.page.children['head'].add_child('myjs', my_js_head)
4156

42-
res_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'res')
43-
#static_file_path can be an array of strings allowing to define
44-
# multiple resource path in where the resources will be placed
45-
super(MyApp, self).__init__(*args, static_file_path=res_path, html_head=my_html_head, css_head=my_css_head, js_head=my_js_head)
46-
47-
def idle(self):
48-
#idle loop, you can place here custom code
49-
# avoid to use infinite iterations, it would stop gui update
50-
pass
51-
52-
def main(self):
5357
#creating a container VBox type, vertical (you can use also HBox or Widget)
5458
main_container = gui.VBox(width='500px', height='500px', style={'margin':'0px auto','padding':'10px'})
5559

@@ -105,6 +109,6 @@ def main(self):
105109

106110
if __name__ == "__main__":
107111
# starts the webserver
108-
start(MyApp, address='127.0.0.1', port=8085, start_browser=True, username=None, password=None)
112+
start(MyApp, debug=True, address='127.0.0.1', port=8085, start_browser=True, username=None, password=None)
109113

110114

examples/page_internals_app.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"""
2+
Licensed under the Apache License, Version 2.0 (the "License");
3+
you may not use this file except in compliance with the License.
4+
You may obtain a copy of the License at
5+
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.
13+
"""
14+
15+
import remi.gui as gui
16+
from remi import start, App
17+
import os
18+
19+
class MyApp(App):
20+
def __init__(self, *args):
21+
res_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'res')
22+
#static_file_path can be an array of strings allowing to define
23+
# multiple resource path in where the resources will be placed
24+
super(MyApp, self).__init__(*args, static_file_path=res_path)
25+
26+
def main(self):
27+
#creating a container VBox type, vertical (you can use also HBox or Widget)
28+
main_container = gui.VBox(width=300, height=200, style={'margin':'0px auto'})
29+
self.page.children['head'].add_child('test', '<meta patate>')
30+
self.page.children['body'].style['background-color'] = 'lightyellow'
31+
self.page.children['body'].onkeydown.connect(self.onkeydown)
32+
# returning the root widget
33+
return main_container
34+
35+
def onkeydown(self, emitter, key, keycode, ctrl, shift, alt):
36+
print("keydown: %s"%key)
37+
38+
def onload(self, emitter):
39+
print(">>>>>>>>> ON PAGE LOADED")
40+
41+
def onerror(self, emitter, message, source, line, col):
42+
print(">>>>>>>>> ON ERROR: %s\n%s\n%s\n%s"%(message, source, line, col))
43+
self.execute_javascript('document.onkeydo')
44+
45+
46+
if __name__ == "__main__":
47+
# starts the webserver
48+
start(MyApp, debug=True, address='0.0.0.0', port=8081)

examples/template_advanced_app.py

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@
1818

1919
class MyApp(App):
2020
def __init__(self, *args):
21+
res_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'res')
22+
#static_file_path can be an array of strings allowing to define
23+
# multiple resource path in where the resources will be placed
24+
super(MyApp, self).__init__(*args, static_file_path=res_path)
25+
26+
def idle(self):
27+
""" Idle loop, you can place here custom code,
28+
avoid to use infinite iterations, it would stop gui update.
29+
This is a Thread safe method where you can update the
30+
gui with information from external Threads.
31+
"""
32+
pass
33+
34+
def main(self):
2135
#custom additional html head tags
2236
my_html_head = """
2337
"""
@@ -31,21 +45,15 @@ def __init__(self, *args):
3145
my_js_head = """
3246
<script></script>
3347
"""
48+
#appending elements to page header
49+
self.page.children['head'].add_child('myhtml', my_html_head)
50+
self.page.children['head'].add_child('mycss', my_css_head)
51+
self.page.children['head'].add_child('myjs', my_js_head)
52+
#eventually set up body attributes/style
53+
#self.page.children['body'].style['background-color'] = 'lightyellow'
54+
#eventually set up body event listeners
55+
#self.page.children['body'].onkeydown.connect(self.onkeydown)
3456

35-
res_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'res')
36-
#static_file_path can be an array of strings allowing to define
37-
# multiple resource path in where the resources will be placed
38-
super(MyApp, self).__init__(*args, static_file_path=res_path, html_head=my_html_head, css_head=my_css_head, js_head=my_js_head)
39-
40-
def idle(self):
41-
""" Idle loop, you can place here custom code,
42-
avoid to use infinite iterations, it would stop gui update.
43-
This is a Thread safe method where you can update the
44-
gui with information from external Threads.
45-
"""
46-
pass
47-
48-
def main(self):
4957
#creating a container VBox type, vertical (you can use also HBox or Widget)
5058
main_container = gui.VBox(width=300, height=200, style={'margin':'0px auto'})
5159

@@ -54,11 +62,34 @@ def main(self):
5462

5563
def on_close(self):
5664
""" Overloading App.on_close event allows to perform some
57-
activities before app termination.
58-
"""
65+
activities before app termination. """
5966
super(MyApp, self).on_close()
6067

68+
def onload(self, emitter):
69+
""" WebPage Event that occurs on webpage loaded """
70+
super(MyApp, self).onload(emitter)
71+
72+
def onerror(self, emitter, message, source, lineno, colno):
73+
""" WebPage Event that occurs on webpage errors """
74+
super(MyApp, self).onerror(emitter, message, source, lineno, colno)
75+
76+
def ononline(self, emitter):
77+
""" WebPage Event that occurs on webpage goes online after a disconnection """
78+
super(MyApp, self).ononline(emitter)
79+
80+
def onpagehide(self, emitter):
81+
""" WebPage Event that occurs on webpage when the user navigates away """
82+
super(MyApp, self).onpagehide(emitter)
83+
84+
def onpageshow(self, emitter):
85+
""" WebPage Event that occurs on webpage gets shown """
86+
super(MyApp, self).onpageshow(emitter)
87+
88+
def onresize(self, emitter, width, height):
89+
""" WebPage Event that occurs on webpage gets resized """
90+
super(MyApp, self).onresize(emitter, width, height)
91+
6192

6293
if __name__ == "__main__":
6394
# starts the webserver
64-
start(MyApp, address='0.0.0.0', port=0, start_browser=True, username=None, password=None)
95+
start(MyApp, debug=True, address='0.0.0.0', port=0, start_browser=True, username=None, password=None)

0 commit comments

Comments
 (0)