aboutsummaryrefslogtreecommitdiff
path: root/qolab
diff options
context:
space:
mode:
authorEugeniy E. Mikhailov <evgmik@gmail.com>2021-12-17 11:12:48 -0500
committerEugeniy E. Mikhailov <evgmik@gmail.com>2021-12-17 11:12:48 -0500
commit476248687008977a2af2e102edbd258b5ec2b98c (patch)
tree742a6df6b896708a94763e4c3110db8191c2ed35 /qolab
parentfb3da43e4eb939350624e4013a5d0a97be92ac64 (diff)
downloadpyExpControl-476248687008977a2af2e102edbd258b5ec2b98c.tar.gz
pyExpControl-476248687008977a2af2e102edbd258b5ec2b98c.zip
draft of web gui
Diffstat (limited to 'qolab')
-rw-r--r--qolab/gui/__init__.py1
-rw-r--r--qolab/gui/web.py142
2 files changed, 143 insertions, 0 deletions
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)
+