aboutsummaryrefslogtreecommitdiff
path: root/qolab/gui/web.py
blob: ac4d16462b16618ec37b26c966c21fc3e5ec2763 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import justpy as jp
import asyncio
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'
controls_group_classes = 'flex space-x-4'
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.InputChangeOnly(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.traces = 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)
        save_controls = QOLSaveControls(a=dcontrols)
        self.chart = jp.Matplotlib(a=root)
        self.plot()
    
    async def _clear_data(self, msg):
        self.clear_data()
        await self.update()

    def clear_data(self):
        traces = self.traces
        if traces is not None:
            traces.clear_data()
            self.plot()

    async def _replot(self, msg):
        self.plot()
        await self.update()

    async def update_loop(self, update_interval=4):
        update_interval=5
        while True:
            self.plot()
            await self.update()
            await asyncio.sleep(update_interval)

    def plot(self):
        traces = self.traces
        f = plt.figure()
        if traces is None:
            plt.title('Log data is unavailable')
        else:
            traces.plot()
        self.chart.set_figure(f)
        plt.close(f)


class QOLSaveControls(jp.Div):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        root = self
        root.set_classes(controls_group_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)