From 476248687008977a2af2e102edbd258b5ec2b98c Mon Sep 17 00:00:00 2001 From: "Eugeniy E. Mikhailov" Date: Fri, 17 Dec 2021 11:12:48 -0500 Subject: draft of web gui --- qolab/gui/__init__.py | 1 + qolab/gui/web.py | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 qolab/gui/__init__.py create mode 100644 qolab/gui/web.py diff --git a/qolab/gui/__init__.py b/qolab/gui/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/qolab/gui/__init__.py @@ -0,0 +1 @@ + diff --git a/qolab/gui/web.py b/qolab/gui/web.py new file mode 100644 index 0000000..0b15ff8 --- /dev/null +++ b/qolab/gui/web.py @@ -0,0 +1,142 @@ +import justpy as jp +import matplotlib.pyplot as plt + +button_classes = 'bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full' +label_div_classes = 'py-2 px-4' +checkbox_classed = label_div_classes +labelnames_classes = 'font-bold' +panel_div_classes = 'space-x-4 border' +controls_div_classes = 'flex space-x-4 border' +input_classes = "m-2 bg-gray-200 border-2 border-gray-200 rounded w-20 text-gray-700 focus:outline-none focus:bg-white focus:border-purple-500" + + +class QOLPushButton(jp.Button): + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.set_classes('bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full') + +class QOLPushButtonNoUndo(QOLPushButton): + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.set_classes('bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded-full') + +class QOLParamHeader(jp.Div): + def __init__(self, label='NameNotSet', **kwargs): + super().__init__(**kwargs) + root = self + root.label=label + root.set_classes(label_div_classes) + root.data[label]=None + jp.Span(text=f'{label}: ', classes=labelnames_classes, a=root) + + def getValue(self): + return self.data[self.label] + + def setValue(self, val): + self.data[self.label]=val + +class QOLParamReadOnly(QOLParamHeader): + """ Read Only from the web point of view """ + def __init__(self, label='NameNotSet', **kwargs): + super().__init__(label=label, **kwargs) + root = self + jp.Span(model=[root, label], a=root) + +class QOLParamReadWrite(QOLParamHeader): + def __init__(self, label='NameNotSet', **kwargs): + super().__init__(label=label, **kwargs) + root = self + self.input=jp.Input(classes=input_classes, model=[root, label], a=root, spellcheck="false") + +class QOLCheckbox(jp.Label): + def __init__(self, label='NameNotSet', **kwargs): + super().__init__(**kwargs) + root = self + root.data['checked'] = False + root.label=label + root.set_classes(checkbox_classed) + checkbox = jp.Input(type='checkbox', model=[root, 'checked'], classes='form-checkbox', a=root) + caption = jp.Span(text=label, a=root) + + def getValue(self): + return self.data['checked'] + + def setValue(self, val): + self.data['checked'] = val + +class QOLTimeLog(jp.Div): + def __init__(self, **kwargs): + super().__init__(**kwargs) + root = self + root.log = None; # log must have 'plot' and 'clear_data' methods + root.set_classes(panel_div_classes) + dcontrols = jp.Div(a=root) + dcontrols.set_classes(controls_div_classes) + bclear = QOLPushButtonNoUndo(a=dcontrols, text='Clear log', click=self._clear_data) + breplot = QOLPushButton(a=dcontrols, text='Replot', click=self._replot) + self.chart = jp.Matplotlib(a=root) + # f = plt.figure() + # plt.close(f) + self.plot() + + def _clear_data(self, msg): + self.clear_data() + + def plot(self): + log.clear_data() + + def _replot(self, msg): + self.plot() + + def plot(self): + log = self.log + f = plt.figure() + if log is None: + plt.title('Log data is unavailable') + else: + log.plot() + self.chart.set_figure(f) + plt.close(f) + jp.run_task(self.update()) + + +class QOLSaveControls(jp.Div): + def __init__(self, **kwargs): + super().__init__(**kwargs) + root = self + root.set_classes(controls_div_classes) + + root.save=QOLPushButton(a=root, text='Save', name='Save', click=self._save) + root.next_file=QOLPushButton(a=root, text='Next file', name='NextFile', click=self._next_file) + self.autosave=QOLCheckbox(label='autosave', a=root ) + self.file_name=QOLParamReadOnly(label='FileName', a=root) + + def _save(self, msg): + """ This is place holder: user should assign 'save' with a callback """ + print('Warning: `save` callback is not set') + pass + + def _next_file(self, msg): + """ This is place holder: user should assign 'next_file' with a callback """ + print('Warning: `next_file` callback is not set') + pass + + + +def gui_test(): + return wp + +if __name__ == '__main__': + wp = jp.WebPage(delete_flag=False) + rw = QOLParamReadWrite(label='ReadWriteParam', a=wp) + rw.setValue(12345) + + log = QOLTimeLog(a=wp) + + def test(self, msg): + print(rw.getValue()) + QOLPushButtonNoUndo(text='Danger', a=wp, onclick=test) + sc = QOLSaveControls(a=wp) + + jp.justpy(gui_test) + -- cgit v1.2.3