From 2243c08958dcfccff3bb29b9effac0f100e70eee Mon Sep 17 00:00:00 2001
From: cetus1 <51400133+cetus1@users.noreply.github.com>
Date: Sun, 9 Jun 2019 15:06:45 +0300
Subject: [PATCH 1/6] Update gui.py
Added functions to disable and hide widgets
---
 remi/gui.py | 112 ++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 87 insertions(+), 25 deletions(-)
diff --git a/remi/gui.py b/remi/gui.py
index 40a78ac6..4438dea3 100644
--- a/remi/gui.py
+++ b/remi/gui.py
@@ -66,7 +66,7 @@ def jsonize(d):
 
 def load_resource(filename):
     """ Convenient function. Given a local path and filename (not in standard remi resource format),
-        loads the content and returns a base64 encoded data. 
+        loads the content and returns a base64 encoded data.
         This method allows to bypass the remi resource file management, accessing directly local disk files.
 
         Args:
@@ -85,7 +85,7 @@ def load_resource(filename):
     else:
         data = str(data, 'utf-8')
     return "data:%(mime)s;base64,%(data)s"%{'mime':mimetype, 'data':data}
-    
+
 
 def to_uri(uri_data):
     """ Convenient function to encase the resource filename or data in url('') keyword
@@ -102,13 +102,13 @@ def to_uri(uri_data):
 class EventSource(object):
     def __init__(self, *args, **kwargs):
         self.setup_event_methods()
-    
+
     def setup_event_methods(self):
         for (method_name, method) in inspect.getmembers(self, predicate=inspect.ismethod):
             _event_info = None
             if hasattr(method, "_event_info"):
                 _event_info = method._event_info
-            
+
             if hasattr(method, '__is_event'):
                 e = ClassEventConnector(self, method_name, method)
                 setattr(self, method_name, e)
@@ -130,7 +130,7 @@ def __init__(self, event_source_instance, event_name, event_method_bound):
         self.callback = None
         self.userdata = None
         self.connect = self.do #for compatibility reasons
-        
+
     def do(self, callback, *userdata):
         """ The callback and userdata gets stored, and if there is some javascript to add
             the js code is appended as attribute for the event source
@@ -529,7 +529,6 @@ class Widget(Tag, EventSource):
 
     @decorate_constructor_parameter_types([])
     def __init__(self, children = None, style = None, *args, **kwargs):
-
         """
         Args:
             children (Widget, or iterable of Widgets): The child to be appended. In case of a dictionary,
@@ -555,6 +554,10 @@ def __init__(self, children = None, style = None, *args, **kwargs):
         self.set_layout_orientation(kwargs.get('layout_orientation', Widget.LAYOUT_VERTICAL))
         self.set_size(kwargs.get('width'), kwargs.get('height'))
         self.set_style(style)
+        self._saved_display_style = None
+        self._saved_pointer_events_style = None
+        self._visible = True
+        self._enable = True
 
         if children:
             self.append(children)
@@ -572,14 +575,60 @@ def set_style(self, style):
                     k, v = s.split(':', 1)
                     self.style[k.strip()] = v.strip()
 
+    def set_hidden(self, hided):
+        """
+        Args:
+            hided (bool): hide - if True, show - if False
+        """
+#        for child in self.children.values():
+#            if type(child) not in (type(''), type(u'')):
+#                child.set_hidden(hided)
+        if hided:
+            self._saved_display_style = self.style.get('display', None)
+            try:
+                self.style['display'] = 'none'
+            except KeyError:
+                pass
+        else:
+            if self.style['display'] == 'none':
+                if self._saved_display_style is None:
+                    del self.style['display']
+                else:
+                    self.style['display'] = self._saved_display_style
+        self._visible = not hided
+
     def set_enabled(self, enabled):
-        if enabled:
+        """
+        Args:
+            enabled (bool): enable - if True, disable - if False
+        """
+        for child in self.children.values():
+            if type(child) not in (type(''), type(u'')):
+                child.set_enabled(enabled)
+        if not enabled:
+            self.attributes['disabled'] = 'true'
+            self._saved_pointer_events_style = self.style.get('pointer-events', None)
             try:
-                del self.attributes['disabled']
+                self.style['pointer-events'] = 'none'
             except KeyError:
                 pass
         else:
-            self.attributes['disabled'] = 'True'
+            try:
+                del self.attributes['disabled']
+            except KeyError:
+                pass
+            if self.style['pointer-events'] == 'none':
+                if self._saved_pointer_events_style is None:
+                    del self.style['pointer-events']
+                else:
+                    self.style['pointer-events'] = self._saved_pointer_events_style
+        self._enable = enabled
+
+    def is_visible(self):
+        return self._visible
+
+    def is_enabled(self):
+        return self._enable
 
     def set_size(self, width, height):
         """Set the widget size.
@@ -884,7 +933,7 @@ def onkeyup(self, key, keycode, ctrl, shift, alt):
         """Called when user types and releases a key. 
         The widget should be able to receive the focus in order to emit the event.
         Assign a 'tabindex' attribute to make it focusable.
-        
+
         Args:
             key (str): the character value
             keycode (str): the numeric char code
@@ -903,7 +952,7 @@ def onkeydown(self, key, keycode, ctrl, shift, alt):
         """Called when user types and releases a key.
         The widget should be able to receive the focus in order to emit the event.
         Assign a 'tabindex' attribute to make it focusable.
-        
+
         Args:
             key (str): the character value
             keycode (str): the numeric char code
@@ -913,7 +962,7 @@ def onkeydown(self, key, keycode, ctrl, shift, alt):
     @decorate_explicit_alias_for_listener_registration
     def set_on_focus_listener(self, callback, *userdata):
         self.onfocus.connect(callback, *userdata)
-        
+
     @decorate_explicit_alias_for_listener_registration
     def set_on_blur_listener(self, callback, *userdata):
         self.onblur.connect(callback, *userdata)
@@ -961,7 +1010,7 @@ def set_on_touchstart_listener(self, callback, *userdata):
     @decorate_explicit_alias_for_listener_registration
     def set_on_touchend_listener(self, callback, *userdata):
         self.ontouchend.connect(callback, *userdata)
-        
+
     @decorate_explicit_alias_for_listener_registration
     def set_on_touchenter_listener(self, callback, *userdata):
         self.ontouchenter.connect(callback, *userdata)
@@ -1010,7 +1059,7 @@ def __init__(self, title, *args, **kwargs):
                 """
                 
                 """)
-        
+
         self._classes = []
         self.set_title(title)
 
@@ -1026,7 +1075,7 @@ def set_icon_file(self, filename, rel="icon"):
 
     def set_icon_data(self, base64_data, mimetype="image/png", rel="icon"):
         """ Allows to define an icon for the App
-        
+
             Args:
                 base64_data (str): base64 encoded image data  (ie. "data:image/x-icon;base64,AAABAAEAEBA....")
                 mimetype (str): mimetype of the image ("image/png" or "image/x-icon"...)
@@ -1322,7 +1371,7 @@ def __init__(self, *args, **kwargs):
         loading_widget.set_identifier("loading")
 
         self.append(loading_widget)
-    
+
     @decorate_set_on_listener("(self, emitter)")
     @decorate_event_js("""sendCallback('%(emitter_identifier)s','%(event_name)s');
             event.stopPropagation();event.preventDefault();
@@ -1396,6 +1445,7 @@ def define_grid(self, matrix):
         Args:
             matrix (list): list of iterables of strings (lists or something else). 
                 Items in the matrix have to correspond to a key for the children.
+                The key must start with a letter.
         """
         self.style['grid-template-areas'] = ''.join("'%s'"%(' '.join(x)) for x in matrix) 
 
@@ -1433,7 +1483,7 @@ def append(self, value, key=''):
         value.style['position'] = 'static'
 
         return key
-    
+
     def remove_child(self, child):
         if 'grid-area' in child.style.keys():
             del child.style['grid-area']
@@ -1454,7 +1504,7 @@ def set_row_sizes(self, values):
             values (iterable of int or str): values are treated as percentage.
         """
         self.style['grid-template-rows'] = ' '.join(map(lambda value: (str(value) if str(value).endswith('%') else str(value) + '%') , values))
-    
+
     def set_column_gap(self, value):
         """Sets the gap value between columns
 
@@ -1524,11 +1574,11 @@ def set_from_asciiart(self, asciipattern):
                 i=rows[ri].find("|",i+1)
 
         columns[row_max_width] = row_max_width
-        
+
         row_sizes = []
         for r in row_defs.keys():
             row_sizes.append(float(rows.count(rows[r]))/float(len(rows))*100.0)
-        
+
         column_sizes = []
         prev_size = 0.0
         for c in columns.values():
@@ -1580,7 +1630,7 @@ def append(self, value, key=''):
             for child in value:
                 keys.append( self.append(child) )
             return keys
-        
+
         key = str(key)
         if not isinstance(value, Widget):
             raise ValueError('value should be a Widget (otherwise use add_child(key,other)')
@@ -1847,7 +1897,7 @@ def onchange(self, new_value):
             sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params);""")
     def onkeyup(self, new_value, keycode):
         """Called when user types and releases a key into the TextInput
-        
+
         Note: This event can't be registered together with Widget.onchange.
 
         Args:
@@ -2127,7 +2177,7 @@ class ListView(Widget):
     """
 
     @decorate_constructor_parameter_types([bool])
-    def __init__(self, selectable = True, *args, **kwargs):
+    def __init__(self, selectable=True, *args, **kwargs):
         """
         Args:
             kwargs: See Widget.__init__()
@@ -2848,6 +2898,19 @@ def onchange(self, widget, value):
     def set_on_change_listener(self, callback, *userdata):
         self.onchange.connect(callback, *userdata)
 
+    def set_enabled(self, enabled):
+        self._checkbox.set_enabled(enabled)
+        self._label.set_enabled(enabled)
+        super(CheckBoxLabel, self).set_enabled(enabled)
+
+
+class RadioHBox(Input):
+    """todo"""
+
+
+class RadioVBox(Input):
+    """todo"""
+
 
 class CheckBox(Input):
     """check box widget useful as numeric input field implements the onchange event."""
@@ -3284,7 +3347,6 @@ def __init__(self, text, *args, **kwargs):
         self.set_text(text)
 
     def append(self, value, key=''):
-        
         return self.sub_container.append(value, key=key)
 
 
@@ -3588,7 +3650,7 @@ def set_size(self, w, h):
 
 
 class SvgImage(SvgRectangle):
-    """svg image - a raster image element for svg graphics, 
+    """svg image - a raster image element for svg graphics,
         this have to be appended into Svg elements."""
 
     @decorate_constructor_parameter_types([str, int, int, int, int])
From 4c9f7d492c8721007c43a860b308d00848585b88 Mon Sep 17 00:00:00 2001
From: cetus1 <51400133+cetus1@users.noreply.github.com>
Date: Sun, 9 Jun 2019 15:09:20 +0300
Subject: [PATCH 2/6] Update widgets_overview_app.py
Added functions to deactivate and hide widgets
---
 examples/widgets_overview_app.py | 76 +++++++++++++++++++++++++++-----
 1 file changed, 64 insertions(+), 12 deletions(-)
diff --git a/examples/widgets_overview_app.py b/examples/widgets_overview_app.py
index a5df611a..3e810ce5 100644
--- a/examples/widgets_overview_app.py
+++ b/examples/widgets_overview_app.py
@@ -1,3 +1,4 @@
+#!/usr/bin/python
 """
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -29,9 +30,11 @@ def main(self):
         # the margin 0px auto centers the main container
         verticalContainer = gui.Widget(width=540, margin='0px auto', style={'display': 'block', 'overflow': 'hidden'})
 
-        horizontalContainer = gui.Widget(width='100%', layout_orientation=gui.Widget.LAYOUT_HORIZONTAL, margin='0px', style={'display': 'block', 'overflow': 'auto'})
-        
-        subContainerLeft = gui.Widget(width=320, style={'display': 'block', 'overflow': 'auto', 'text-align': 'center'})
+        horizontalContainer = gui.Widget(width='100%', layout_orientation=gui.Widget.LAYOUT_HORIZONTAL, margin='0px',
+                style={'display': 'block', 'overflow': 'auto'})
+
+        self.subContainerLeft = subContainerLeft = gui.Widget(width=320,
+                style={'display': 'block', 'overflow': 'auto', 'text-align': 'center'})
         self.img = gui.Image('/res:logo.png', height=100, margin='10px')
         self.img.onclick.do(self.on_img_clicked)
 
@@ -44,7 +47,7 @@ def main(self):
         self.table.on_table_row_click.do(self.on_table_row_click)
 
         # the arguments are	width - height - layoutOrientationOrizontal
-        subContainerRight = gui.Widget(style={'width': '220px', 'display': 'block', 'overflow': 'auto', 'text-align': 'center'})
+        self.subContainerRight = subContainerRight = gui.Widget(style={'width': '220px', 'display': 'block', 'overflow': 'auto', 'text-align': 'center'})
         self.count = 0
         self.counter = gui.Label('', width=200, height=30, margin='10px')
 
@@ -102,7 +105,7 @@ def main(self):
         self.video.attributes['height'] = '100%'
         self.video.attributes['controls'] = 'true'
         self.video.style['border'] = 'none'
-                                     
+
         self.tree = gui.TreeView(width='100%', height=300)
         ti1 = gui.TreeItem("Item1")
         ti2 = gui.TreeItem("Item2")
@@ -117,7 +120,7 @@ def main(self):
         self.tree.append([ti1, ti2, ti3])
         ti2.append([subti1, subti2, subti3, subti4])
         subti4.append([subsubti1, subsubti2, subsubti3])
-        
+
         # appending a widget to another, the first argument is a string key
         subContainerRight.append([self.counter, self.lbl, self.bt, self.txt, self.spin, self.progress, self.check, self.btInputDiag, self.btFileDiag])
         # use a defined key as we replace this widget later
@@ -130,10 +133,8 @@ def main(self):
 
         horizontalContainer.append([subContainerLeft, subContainerRight])
 
-        menu = gui.Menu(width='100%', height='30px')
+        self.menu = menu = gui.Menu(width='100%', height='30px')
         m1 = gui.MenuItem('File', width=100, height=30)
-        m2 = gui.MenuItem('View', width=100, height=30)
-        m2.onclick.do(self.menu_view_clicked)
         m11 = gui.MenuItem('Save', width=100, height=30)
         m12 = gui.MenuItem('Open', width=100, height=30)
         m12.onclick.do(self.menu_open_clicked)
@@ -141,12 +142,32 @@ def main(self):
         m111.onclick.do(self.menu_save_clicked)
         m112 = gui.MenuItem('Save as', width=100, height=30)
         m112.onclick.do(self.menu_saveas_clicked)
+        m2 = gui.MenuItem('View', width=100, height=30)
+        m21 = gui.MenuItem('Left panel', width=100, height=30)
+        m211 = gui.MenuItem('Disable', width=100, height=30)
+        m211.onclick.do(self.menu_disable_left_panel_clicked)
+        m212 = gui.MenuItem('Hide', width=100, height=30)
+        m212.onclick.do(self.menu_hide_left_panel_clicked)
+        m22 = gui.MenuItem('Right panel', width=100, height=30)
+        m221 = gui.MenuItem('Disable', width=100, height=30)
+        m221.onclick.do(self.menu_disable_right_panel_clicked)
+        m222 = gui.MenuItem('Hide', width=100, height=30)
+        m222.onclick.do(self.menu_hide_right_panel_clicked)
+        m23 = gui.MenuItem('About', width=100, height=30)
+        m231 = gui.MenuItem('Disable', width=100, height=30)
+        m231.onclick.do(self.menu_disable_about_clicked)
         m3 = gui.MenuItem('Dialog', width=100, height=30)
         m3.onclick.do(self.menu_dialog_clicked)
+        m4 = gui.MenuItem('About', width=100, height=30)
+        m4.onclick.do(self.menu_about_clicked)
 
-        menu.append([m1, m2, m3])
+        menu.append([m1, m2, m3, {'about':m4}])
         m1.append([m11, m12])
         m11.append([m111, m112])
+        m2.append([m21, m22, m23])
+        m21.append([m211, m212])
+        m22.append([m221, m222])
+        m23.append([m231])
 
         menubar = gui.MenuBar(width='100%', height='30px')
         menubar.append(menu)
@@ -305,8 +326,36 @@ def menu_saveas_clicked(self, widget):
     def menu_open_clicked(self, widget):
         self.lbl.set_text('Menu clicked: Open')
 
-    def menu_view_clicked(self, widget):
-        self.lbl.set_text('Menu clicked: View')
+    def menu_disable_left_panel_clicked(self, widget):
+        self.lbl.set_text('Disable left panel')
+        flag = self.subContainerLeft.is_enabled()
+        self.subContainerLeft.set_enabled(not flag)
+        widget.set_text('Enable' if flag else 'Disable')
+
+    def menu_disable_right_panel_clicked(self, widget):
+        self.lbl.set_text('Disable right panel')
+        flag = self.subContainerRight.is_enabled()
+        self.subContainerRight.set_enabled(not flag)
+        widget.set_text('Enable' if flag else 'Disable')
+
+    def menu_hide_left_panel_clicked(self, widget):
+        self.lbl.set_text('Hide left panel')
+        flag = self.subContainerLeft.is_visible()
+        self.subContainerLeft.set_hidden(flag)
+        widget.set_text('Show' if flag else 'Hide')
+
+    def menu_hide_right_panel_clicked(self, widget):
+        self.lbl.set_text('Hide right panel')
+        flag = self.subContainerRight.is_visible()
+        self.subContainerRight.set_hidden(flag)
+        widget.set_text('Show' if flag else 'Hide')
+
+    def menu_disable_about_clicked(self, widget):
+        menu_about = self.menu.get_child('about')
+        flag = menu_about.is_enabled()
+        menu_about.set_enabled(not flag)
+        widget.set_text('Enable' if flag else 'Disable')
+        self.lbl.set_text('%s About' % ('Disable'if flag else 'Enable' ))
 
     def fileupload_on_success(self, widget, filename):
         self.lbl.set_text('File upload success: ' + filename)
@@ -314,6 +363,9 @@ def fileupload_on_success(self, widget, filename):
     def fileupload_on_failed(self, widget, filename):
         self.lbl.set_text('File upload failed: ' + filename)
 
+    def menu_about_clicked(self, widget):
+        self.lbl.set_text('Menu clicked: About')
+
     def on_close(self):
         """ Overloading App.on_close event to stop the Timer.
         """
From 405c20cc98127f8c76dcb64690344fe11a6df14f Mon Sep 17 00:00:00 2001
From: cetus1 <51400133+cetus1@users.noreply.github.com>
Date: Wed, 12 Jun 2019 13:55:37 +0300
Subject: [PATCH 3/6] Update gui.py
---
 remi/gui.py | 128 +++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 116 insertions(+), 12 deletions(-)
diff --git a/remi/gui.py b/remi/gui.py
index 4438dea3..7dec2118 100644
--- a/remi/gui.py
+++ b/remi/gui.py
@@ -2445,7 +2445,6 @@ def get_key(self):
     def onchange(self, value):
         """Called when a new DropDownItem gets selected.
         """
-        log.debug('combo box. selected %s' % value)
         self.select_by_value(value)
         return (value, )
 
@@ -2898,21 +2897,126 @@ def onchange(self, widget, value):
     def set_on_change_listener(self, callback, *userdata):
         self.onchange.connect(callback, *userdata)
 
-    def set_enabled(self, enabled):
-        self._checkbox.set_enabled(enabled)
-        self._label.set_enabled(enabled)
-        super(CheckBoxLabel, self).set_enabled(enabled)
 
+class CheckBox(Input):
+    """check box widget useful as numeric input field implements the onchange event."""
+
+    @decorate_constructor_parameter_types([bool, str])
+    def __init__(self, checked=False, user_data='', **kwargs):
+        """
+        Args:
+            checked (bool):
+            user_data (str):
+            kwargs: See Widget.__init__()
+        """
+        super(CheckBox, self).__init__('checkbox', user_data, **kwargs)
+        self.set_value(checked)
+        self.attributes[Widget.EVENT_ONCHANGE] = \
+            "var params={};params['value']=document.getElementById('%(emitter_identifier)s').checked;" \
+            "sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params);"% \
+            {'emitter_identifier':str(self.identifier), 'event_name':Widget.EVENT_ONCHANGE}
+
+    @decorate_set_on_listener("(self, emitter, value)")
+    @decorate_event
+    def onchange(self, value):
+        value = value in ('True', 'true')
+        self.set_value(value)
+        return (value, )
 
-class RadioHBox(Input):
-    """todo"""
+    def set_value(self, checked, update_ui=1):
+        if checked:
+            self.attributes['checked'] = 'checked'
+        else:
+            if 'checked' in self.attributes:
+                del self.attributes['checked']
 
+    def get_value(self):
+        """
+        Returns:
+            bool:
+        """
+        return 'checked' in self.attributes
 
-class RadioVBox(Input):
-    """todo"""
 
+class RadioHGroup(Widget):
 
-class CheckBox(Input):
+    @decorate_constructor_parameter_types([[str], int, [str]])
+    def __init__(self, labels, checked=0, user_data=[], **kwargs):
+        """
+        Args:
+            label [(str)]:
+            checked (int) or (str):
+            user_data [(str)]:
+            kwargs: See Widget.__init__()
+        """
+        super(RadioHGroup, self).__init__(**kwargs)
+        self.set_layout_orientation(Widget.LAYOUT_HORIZONTAL)
+        user_data = user_data or [ '%i' % i for i in xrange(len(labels)) ]
+        self._radiogroup = [ RadioBoxLabel(label, False, data) for label, data in zip(labels, user_data) ]
+        if type(checked) in (type(''), type(u'')):
+            checked = int(user_data.index(checked))
+        self._radiogroup[checked].set_value(True)
+        self._idx = checked
+        self.append(self._radiogroup)
+        for radiobox in self._radiogroup:
+            radiobox.onchange.connect(self.onchange)
+
+    @decorate_set_on_listener("(self, emitter, value)")
+    @decorate_event
+    def onchange(self, widget, value):
+        prev_idx = self._idx
+        self._radiogroup[prev_idx].set_value(False)
+        self._idx = self._radiogroup.index(widget)
+        return (value, self._idx, prev_idx)
+
+    @decorate_explicit_alias_for_listener_registration
+    def set_on_change_listener(self, callback, *userdata):
+        self.onchange.connect(callback, *userdata)
+
+
+#class RadioVGroup(RadioHGroup):
+#    def __init__(self, labels, checked=0, user_data=[], **kwargs):
+#        """
+#        Args:
+#            label [(str)]:
+#            checked (int) or (str):
+#            user_data [(str)]:
+#            kwargs: See Widget.__init__()
+#        """
+#        super(RadioVGroup, self).__init__(labels, checked, user_data, **kwargs)
+#        self.set_layout_orientation(Widget.LAYOUT_VERTICAL)
+
+
+class RadioBoxLabel(Widget):
+
+    @decorate_constructor_parameter_types([str, bool, str])
+    def __init__(self, label='', checked=False, user_data='', **kwargs):
+        """
+        Args:
+            label (str):
+            checked (bool):
+            user_data (str):
+            kwargs: See Widget.__init__()
+        """
+        super(RadioBoxLabel, self).__init__(**kwargs)
+        self.set_layout_orientation(Widget.LAYOUT_HORIZONTAL)
+        self._radiobox = RadioBox(checked, user_data)
+        self._label = Label(label)
+        self.append(self._radiobox, key='radiobox')
+        self.append(self._label, key='label')
+
+        self.set_value = self._radiobox.set_value
+        self.get_value = self._radiobox.get_value
+
+        self._radiobox.onchange.connect(self.onchange)
+
+    @decorate_set_on_listener("(self, emitter, value)")
+    @decorate_event
+    def onchange(self, widget, value):
+        return (value, )
+
+
+class RadioBox(Input):
     """check box widget useful as numeric input field implements the onchange event."""
 
     @decorate_constructor_parameter_types([bool, str])
@@ -2923,7 +3027,7 @@ def __init__(self, checked=False, user_data='', **kwargs):
             user_data (str):
             kwargs: See Widget.__init__()
         """
-        super(CheckBox, self).__init__('checkbox', user_data, **kwargs)
+        super(RadioBox, self).__init__('radio', user_data, **kwargs)
         self.set_value(checked)
         self.attributes[Widget.EVENT_ONCHANGE] = \
             "var params={};params['value']=document.getElementById('%(emitter_identifier)s').checked;" \
@@ -2935,7 +3039,7 @@ def __init__(self, checked=False, user_data='', **kwargs):
     def onchange(self, value):
         value = value in ('True', 'true')
         self.set_value(value)
-        return (value, )
+        return (self.attributes['value'], )
 
     def set_value(self, checked, update_ui=1):
         if checked:
From 74e0be1e24615ad74d58fa95b9fbd72ca7c5281f Mon Sep 17 00:00:00 2001
From: cetus1 <51400133+cetus1@users.noreply.github.com>
Date: Wed, 12 Jun 2019 14:01:06 +0300
Subject: [PATCH 4/6] Update widgets_overview_app.py
---
 examples/widgets_overview_app.py | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/examples/widgets_overview_app.py b/examples/widgets_overview_app.py
index 3e810ce5..f27d9afc 100644
--- a/examples/widgets_overview_app.py
+++ b/examples/widgets_overview_app.py
@@ -99,6 +99,9 @@ def main(self):
         self.date = gui.Date('2015-04-13', width=200, height=20, margin='10px')
         self.date.onchange.do(self.date_changed)
 
+        self.radioGroup = gui.RadioHGroup(['radio1', 'radio2'], 0, width=200, height=20, margin='10px')
+        self.radioGroup.onchange.do(self.on_radio_change)
+
         self.video = gui.Widget( _type='iframe', width=290, height=200, margin='10px')
         self.video.attributes['src'] = "https://drive.google.com/file/d/0B0J9Lq_MRyn4UFRsblR3UTBZRHc/preview"
         self.video.attributes['width'] = '100%'
@@ -122,7 +125,8 @@ def main(self):
         subti4.append([subsubti1, subsubti2, subsubti3])
 
         # appending a widget to another, the first argument is a string key
-        subContainerRight.append([self.counter, self.lbl, self.bt, self.txt, self.spin, self.progress, self.check, self.btInputDiag, self.btFileDiag])
+        subContainerRight.append([self.counter, self.lbl, self.bt, self.txt, self.spin, self.progress, self.check,
+                self.radioGroup, self.btInputDiag, self.btFileDiag])
         # use a defined key as we replace this widget later
         fdownloader = gui.FileDownloader('download test', '../remi/res/logo.png', width=200, height=30, margin='10px')
         subContainerRight.append(fdownloader, key='file_downloader')
@@ -268,6 +272,9 @@ def on_spin_change(self, widget, newValue):
     def on_check_change(self, widget, newValue):
         self.lbl.set_text('CheckBox changed, new value: ' + str(newValue))
 
+    def on_radio_change(self, widget, value, idx, oldIdx):
+        self.lbl.set_text('Radio changed, on: radio%s' % value)
+
     def open_input_dialog(self, widget):
         self.inputDialog = gui.InputDialog('Input Dialog', 'Your name?',
                                            initial_value='type here', 
From 95af7ede3d35e3663749393ec23ff680473426d9 Mon Sep 17 00:00:00 2001
From: cetus1 <51400133+cetus1@users.noreply.github.com>
Date: Wed, 12 Jun 2019 17:09:40 +0300
Subject: [PATCH 5/6] Update gui.py
---
 remi/gui.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/remi/gui.py b/remi/gui.py
index 7dec2118..15afb32c 100644
--- a/remi/gui.py
+++ b/remi/gui.py
@@ -2973,7 +2973,7 @@ def onchange(self, widget, value):
     def set_on_change_listener(self, callback, *userdata):
         self.onchange.connect(callback, *userdata)
 
-
+# TODO
 #class RadioVGroup(RadioHGroup):
 #    def __init__(self, labels, checked=0, user_data=[], **kwargs):
 #        """
@@ -3936,4 +3936,3 @@ def set_fill(self, color='black'):
             color (str): stroke color
         """
         self.attributes['fill'] = color
-        
From ec07a891f448870b46c6fc547fff50e0fe714705 Mon Sep 17 00:00:00 2001
From: cetus1 <51400133+cetus1@users.noreply.github.com>
Date: Wed, 12 Jun 2019 17:12:11 +0300
Subject: [PATCH 6/6] Update widgets_overview_app.py
---
 examples/widgets_overview_app.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/examples/widgets_overview_app.py b/examples/widgets_overview_app.py
index f27d9afc..c8d1cc62 100644
--- a/examples/widgets_overview_app.py
+++ b/examples/widgets_overview_app.py
@@ -273,7 +273,7 @@ def on_check_change(self, widget, newValue):
         self.lbl.set_text('CheckBox changed, new value: ' + str(newValue))
 
     def on_radio_change(self, widget, value, idx, oldIdx):
-        self.lbl.set_text('Radio changed, on: radio%s' % value)
+        self.lbl.set_text('Radio changed, on: radio%i' % (idx+1))
 
     def open_input_dialog(self, widget):
         self.inputDialog = gui.InputDialog('Input Dialog', 'Your name?',