Diff of /src/style.kv [000000] .. [fcbb05]

Switch to side-by-side view

--- a
+++ b/src/style.kv
@@ -0,0 +1,691 @@
+#:kivy 1.10.0
+#:import color src.color
+#:import util src.util
+
+<Widget>:
+    font_name: 'Roboto-Bold'
+    font_size: 16
+
+<Spacer@Widget>:
+    size_hint: 1, 1
+
+<HSpacer@Widget>:
+    size_hint: 1, None
+
+<VSpacer@Widget>:
+    size_hint: None, 1
+    
+<HDivider@Widget>:
+    size_hint: 1, None
+    height: 3
+
+    canvas.before:
+        Color:
+            rgba: 0, 0, 0, .08
+        Rectangle:
+            pos: self.pos
+            size: self.size
+
+<LeftLabel@Label>:
+    font_name: 'Roboto'
+    size_hint: None, None
+    color: .4, .4, .4, 1
+    halign: 'left'
+
+    on_texture_size:
+        self.width = 40 + self.texture.width
+        self.height = self.texture.height
+
+<TextButton@Button>:
+    background_normal: ''
+    background_color: 0, 0, 0, 0
+
+    size_hint: None, None
+    bold: True
+    color: color.B4 if self.state == 'normal' else color.B3
+
+    halign: 'left'
+
+    canvas.before:
+        Color:
+            rgba: (0, 0, 0, .01) if self.state != 'normal' else (0, 0, 0, 0)
+        RoundedRectangle:
+            size: self.size
+            pos: self.pos
+
+    on_texture_size:
+        self.width = 40 + self.texture.width
+        self.height = self.texture.height
+
+
+<Card@BoxLayout>:
+    size_hint: None, None
+    
+    orientation: 'vertical'
+
+    background_color: 0, 0, 0, 0
+    bg_color: 1, 1, 1, 1
+
+    radius: 20
+    canvas.before:
+        Rectangle:
+            size: self.size[0] + 2 * self.radius, self.size[1] + 2 * self.radius
+            pos: self.pos[0] - self.radius, self.pos[1] - 1.5 * self.radius
+            texture: color.createBoxShadow(self.size[0] + self.radius, self.size[1] + self.radius, 0.8 * self.radius, 0.4)
+
+        Color:
+            rgba: self.bg_color
+        Rectangle:
+            size: self.size
+            pos: self.pos
+
+<Chip>:
+    size_hint: None, None
+    height: self.minimum_height
+    width: self.minimum_width
+
+    radius: 5
+
+    selected: True
+    text: ''
+
+    canvas.before:
+        Rectangle:
+            size: self.size[0] + 2 * self.radius, self.size[1] + 2 * self.radius
+            pos: self.pos[0] - self.radius, self.pos[1] - 1.5 * self.radius
+            texture: color.createBoxShadow(self.size[0] + self.radius, self.size[1] + self.radius, self.radius, 0.3)
+        Color:
+            rgb: (.85, .85, .85) if self.selected else (.95, .95, .95)
+        RoundedRectangle:
+            size: self.size
+            pos: self.pos
+            radius: [4]
+
+<ChipInput>:
+    padding: [10, 0, 5, 0]
+    spacing: 0
+
+    hint_text: ''
+    TextInput:
+        id: input
+        background: ''
+        background_color: 0, 0, 0, 0
+
+        multiline: False
+
+        font_name: 'Roboto'
+        size_hint: None, None
+        size: 80, self.minimum_height - 2
+
+        hint_text: self.hint_text
+
+        on_text_validate:
+            root.submit()
+        on_text:
+            self.width = max(80, 20 + self._lines_labels[0].size[0] if self._lines_labels else 0)            
+        canvas.before:
+            Color:
+                rgb: .4, .4, .4
+
+<ChipInputAdder>:
+    padding: [10, 0, 5, 0]
+    spacing: 0
+
+    hint_text: ''
+
+    TextInput:
+        id: input
+        background: ''
+        background_color: 0, 0, 0, 0
+
+        multiline: False
+
+        font_name: 'Roboto'
+        size_hint: None, None
+        size: 80, self.minimum_height - 2
+
+        hint_text: self.hint_text
+
+        on_text_validate:
+            root.submit()
+        on_text:
+            self.width = max(80, 20 + self._lines_labels[0].size[0] if self._lines_labels else 0)            
+        canvas.before:
+            Color:
+                rgb: .4, .4, .4
+
+    Button:
+        size_hint: None, 1
+        width: self.height
+
+        background_normal: ''
+        background_color: 0, 0, 0, 0
+
+        canvas.before:
+            Color:
+                rgba: (.6, .6, .6, 1) if self.state == 'normal' else (.5, .5, .5, 1)
+            Line:
+                points: [self.pos[0] + self.height * .3, self.pos[1] + self.height * .5, self.pos[0] + self.height * .7, self.pos[1] + self.height * .5]
+                width: self.height / 20
+                cap: 'square'
+            Line:
+                points: [self.pos[0] + self.height * .5, self.pos[1] + self.height * .3, self.pos[0] + self.height * .5, self.pos[1] + self.height * .7]
+                width: self.height / 20
+                cap: 'square'
+        on_press:
+            root.submit()
+
+<ChipRemovable>:
+    selected: False
+
+    padding: [10, 5, 5, 5]
+    spacing: 10
+
+    Label:
+        font_name: 'Roboto'
+        size_hint: None, None
+        color: .4, .4, .4, 1
+        halign: 'left'
+
+        text: root.text
+
+        on_texture_size:
+            self.size = self.texture.size
+
+    Button:
+        id: btn_remove
+
+        size_hint: None, 1
+        width: self.height
+
+        background_normal: ''
+        background_color: 0, 0, 0, 0
+
+        canvas.before:
+            Color:
+                rgba: (.6, .6, .6, 1) if self.state == 'normal' else (.5, .5, .5, 1)
+            Line:
+                points: [self.pos[0] + self.height * .3, self.pos[1] + self.height * .3, self.pos[0] + self.height * .7, self.pos[1] + self.height * .7]
+                width: self.height / 20
+            Line:
+                points: [self.pos[0] + self.height * .3, self.pos[1] + self.height * .7, self.pos[0] + self.height * .7, self.pos[1] + self.height * .3]
+                width: self.height / 20
+        
+        on_press:
+            root.remove()
+
+
+<Body@Card>:
+    orientation: 'vertical'
+    size_hint: 1, None
+    pos_hint: { 'center_x': .5, 'center_y': .5 }
+    
+    padding: 20
+    spacing: 20
+
+<HPage@ScrollView>:
+    do_scroll_x: False
+    do_scroll_y: True
+<HPageBox@BoxLayout>:
+    orientation: 'vertical'
+    size_hint: 1, None
+    height: self.minimum_height
+    padding: 20
+<HPageBody@Body>:
+    height: self.minimum_height
+<HTitle@Label>:
+    size_hint: 1, None
+    height: 40
+    color: .4, .4, .4, 1
+    font_name: 'RobotoMono-Regular'
+<HStack@StackLayout>:
+    size_hint: 1, None
+    height: self.minimum_height
+    spacing: 10
+
+
+<PopupFileLoader>:
+    size_hint: None, None
+    size: 500, 500
+
+    title: ''
+    title_color: .4, .4, .4, 1
+
+    background: ''
+    background_color: 0, 0, 0, 0
+    separator_height: 0
+
+    radius: 10
+    file_path: None
+
+    canvas.before:
+        Color:
+            rgba: 1, 1, 1, 1
+        Rectangle:
+            size: self.size[0] + 2 * self.radius, self.size[1] + 2 * self.radius
+            pos: self.pos[0] - self.radius, self.pos[1] - 2 * self.radius
+            texture: color.createBoxShadow(self.size[0] + self.radius, self.size[1] + self.radius, self.radius, 0.4)
+
+    BoxLayout:
+        orientation: 'vertical'
+        FileChooserListView:
+            id: file_chooser
+            color: 0, 0, 0, 1
+ 
+            dirselect: True
+            path: util.samples_dir
+ 
+            on_selection:
+                root.selectFile(args[1])
+            on_submit:
+                root.submitFile()
+        BoxLayout:
+            size_hint: 1, None
+            height: self.minimum_height + 10
+
+            TextButton:
+                text: 'SELECT'
+                on_press:
+                    root.submitFile()
+            TextButton:
+                text: 'CLOSE'
+                on_press:
+                    root.dismiss()
+
+<FileChooserListView>:
+    layout: layout
+    FileChooserListLayout:
+        id: layout
+        controller: root
+
+[FileListEntry@FloatLayout+TreeViewNode]:
+    locked: False
+    entries: []
+    path: ctx.path
+    is_selected: self.path in ctx.controller().selection
+
+    orientation: 'horizontal'
+    size_hint_y: None
+    height: '48dp' if dp(1) > 1 else '24dp'
+    is_leaf: not ctx.isdir or ctx.name.endswith('..' + ctx.sep) or self.locked
+    on_touch_down: self.collide_point(*args[1].pos) and ctx.controller().entry_touched(self, args[1])
+    on_touch_up: self.collide_point(*args[1].pos) and ctx.controller().entry_released(self, args[1])
+    BoxLayout:
+        pos: root.pos
+        size_hint_x: None
+        width: root.width - dp(10)
+
+        Label:
+            color: .4, .4, .4, 1
+            id: filename
+            text_size: self.width, None
+            halign: 'left'
+            shorten: True
+            text: ctx.name
+        Label:
+            color: .4, .4, .4, 1
+            text_size: self.width, None
+            size_hint_x: None
+            halign: 'right'
+            text: '{}'.format(ctx.get_nice_size())
+
+
+<ScreenCard@Card>:
+    width: min(600, self.parent.width - 40)
+
+    padding: 20
+    spacing: 8
+
+<StartScreenLabel@Label>:
+    size_hint: None, None
+    bold: True
+    color: .4, .4, .4, 1
+
+    halign: 'left'
+
+    on_texture_size:
+        self.width = 40 + (self.texture.width if self.text else 0)
+        self.height = self.texture.height
+
+<SpaceStart>:
+    HPage:
+        HPageBox:
+            HPageBody:
+                pos_hint: { 'center_x': .5, 'center_y': .5 }
+
+                size_hint: None, None
+                width: min(900, 0.8 * root.width)
+                height: max(0.9 * root.height, self.minimum_height)
+
+                HTitle:
+                    font_size: 40
+                    text: 'APOS'
+                HTitle:
+                    font_name: 'Roboto'
+                    color: color.B3
+                    font_size: 20
+                    bold: True
+                    text: 'Advanced Pathology OS'
+
+                ScreenCard:
+                    height: 130
+                    StartScreenLabel:
+                        text: 'START'
+                        
+                    HSpacer:
+                        height: 3
+                    TextButton:
+                        text: 'Create slide'
+                        on_press:
+                            app.root.ids.workspace.transition.direction = 'left'
+                            app.root.ids.workspace.current = 'screen_createslide'
+                    TextButton:
+                        text: 'Analyze slide'
+                        on_press:
+                            app.root.ids.workspace.transition.direction = 'left'
+                            app.root.ids.workspace.current = 'screen_analyze'
+                    Spacer:
+
+                ScreenCard:
+                    height: 130
+                    StartScreenLabel:
+                        text: 'TRAIN'
+                    HSpacer:
+                        height: 3
+                    TextButton:
+                        text: 'Create disease filter'
+                        on_press:
+                            app.root.ids.workspace.transition.direction = 'right'
+                            app.root.ids.workspace.current = 'screen_train'
+                    TextButton:
+                        text: 'Categorize training data'
+                        on_press:
+                            app.root.ids.workspace.transition.direction = 'right'
+                            app.root.ids.workspace.current = 'screen_categorize'
+                    Spacer:
+                
+                ScreenCard:
+                    height: 100
+                
+                    StartScreenLabel:
+                        text: 'MISCELLANEOUS'
+                    HSpacer:
+                        height: 3
+                    TextButton: 
+                        text: 'System Info'
+                        on_press:
+                            app.root.ids.workspace.transition.direction = 'up'
+                            app.root.ids.workspace.current = 'screen_credits'
+                    Spacer:
+
+                Spacer:
+
+                LeftLabel:
+                    font_size: 13
+                    font_name: 'RobotoMono-Regular'
+                    text: util.app_creators
+
+
+
+<ReturnToMain@TextButton>:
+    text: 'BACK'
+    dir: 'right'
+
+    on_press:
+        app.root.ids.workspace.transition.direction = self.dir
+        app.root.ids.workspace.current = 'screen_start'
+
+<SpaceCreateSlide>:
+    HPage:
+        HPageBox:
+            HPageBody:
+                TextButton:
+                    text: 'BACK'
+                    on_press:
+                        app.root.ids.workspace.current = 'screen_start'
+                        app.root.ids.workspace.transition.direction = 'right'
+
+                HTitle:
+                    text: 'Create Slide'
+                HDivider:
+
+                ImagePlot:
+                    size: 600, 600
+                    id: plot
+                
+                HDivider:
+
+                HStack:
+                    LeftLabel:
+                        text: 'IP address'
+                    ChipInput:
+                        hint_text: 'Ip Address'
+                        callback: root.set_ip
+                
+                HStack:
+                    TextButton:
+                        id: btn_start
+                        text: 'Start Webcam'
+                        on_press:
+                            root.toggle_webcam()
+                    TextButton:
+                        text: 'Capture Image'
+                        on_press:
+                            root.capture()
+<FilterApply>:
+    size_hint: None, None
+    size: 400, 80
+
+    radius: 8
+    padding: 5
+
+    text: ''
+
+    canvas.before:
+        Color:
+            rgba: 1, 1, 1, 1
+        Rectangle:
+            size: self.size[0] + 2 * self.radius, self.size[1] + 2 * self.radius
+            pos: self.pos[0] - self.radius, self.pos[1] - 1.5 * self.radius
+            texture: color.createBoxShadow(self.size[0] + self.radius, self.size[1] + self.radius, 0.8 * self.radius, 0.3)
+        
+        Color:
+            rgba: 1, 1, 1, 1
+        Rectangle:
+            size: self.size
+            pos: self.pos
+
+    LeftLabel:
+        font_name: 'RobotoMono-Regular'
+
+        color: .4, .4, .4, 1
+        text: root.text
+    
+    HSpacer:
+        height: 10
+    HStack:
+        TextButton:
+            id: btn_train
+            text: 'Analyze'
+            on_press:
+                root.analysis_callback()
+        TextButton:
+            id: btn_reset
+            text: 'Reset'
+            on_press:
+                root.reset()
+ 
+
+
+<SpaceAnalyze>:
+    HPage:
+        HPageBox:
+            HPageBody:
+                TextButton:
+                    text: 'BACK'
+                        
+                    on_press:
+                        app.root.ids.workspace.transition.direction = 'right'
+                        app.root.ids.workspace.current = 'screen_start'
+
+                HTitle:
+                    text: 'Analyze Slide'
+
+                HDivider:
+
+                HStack:
+                    ImageLoader:
+                        size: 450, 450    
+                        id: slide
+                    ImagePlot:
+                        size: 450, 450    
+                        id: sub_sample
+
+                TextButton:
+                    text: 'Select Slide'
+                    on_press:
+                        root.ids.slide.popup_selectImage()
+
+                HDivider:
+
+                LeftLabel:
+                    font_name: 'RobotoMono-Regular'
+                    text: 'REPORT'
+                    bold: True
+                LeftLabel:
+                    font_name: 'RobotoMono-Regular'
+                    id: info
+                    text: ''
+    
+                HDivider:
+
+                TextButton:
+                    text: 'Reload Filters'
+                    on_press:
+                        root.loadFilters()
+                HStack:
+                    id: filter_list
+
+<FilterTrain>:
+    size_hint: None, None
+    size: 600, 400
+
+    radius: 8
+    padding: 5
+
+    text: ''
+
+    canvas.before:
+        Color:
+            rgba: 1, 1, 1, 1
+        Rectangle:
+            size: self.size[0] + 2 * self.radius, self.size[1] + 2 * self.radius
+            pos: self.pos[0] - self.radius, self.pos[1] - 1.5 * self.radius
+            texture: color.createBoxShadow(self.size[0] + self.radius, self.size[1] + self.radius, 0.8 * self.radius, 0.3)
+        
+        Color:
+            rgba: 1, 1, 1, 1
+        Rectangle:
+            size: self.size
+            pos: self.pos
+
+    LeftLabel:
+        font_name: 'RobotoMono-Regular'
+
+        color: .4, .4, .4, 1
+        text: root.text
+
+    HSpacer:
+        height: 10
+    HStack:
+        TextButton:
+            id: btn_train
+            text: 'Train'
+            on_press:
+                root.train()
+                root.ids.btn_save.text = 'Save'
+        TextButton:
+            id: btn_save
+            text: ''
+            on_press:
+                text: 'Saving ...'
+                root.save()
+        
+<SpaceTrain>:
+    HPage:
+        HPageBox:
+            HPageBody:
+                ReturnToMain:
+                    dir: 'left'
+
+                HTitle:
+                    text: 'Create Filter'
+            
+                HDivider:
+            
+                HStack:
+                    ImagePlot:
+                        id: plot
+
+                HStack:
+                    TextButton:
+                        text: 'Load Filters'
+                        on_press:
+                            root.load_filters()
+                
+                HDivider:
+                HStack:
+                    id: filter_editor
+
+<SpaceFixedBody@Body>:
+    size_hint: .9, .8
+    size_hint_max: 1000, 800
+    size_hint_min: 500, 500
+
+
+
+<SpaceCategorize>:
+    slide_img: None
+    
+    HPage:
+        HPageBox:
+            HPageBody: 
+                TextButton:
+                    text: 'BACK'
+                    dir: 'right'
+
+                    on_press:
+                        app.root.ids.workspace.transition.direction = self.dir
+                        app.root.ids.workspace.current = 'screen_start'
+
+                HTitle:
+                    text: 'Categorize'
+
+                StackLayout:
+                    size_hint: 1, None
+                    width: self.minimum_width
+                    height: self.minimum_height
+                    spacing: 10
+
+                    ImageLoader:
+                        size: 350, 350
+                        id: slide
+                    
+                    ImageLoader:
+                        size: 350, 350
+                        id: sub_sample
+
+<SpaceCredits>:
+    SpaceFixedBody:
+        ReturnToMain:
+            dir: 'down'
+        Label:
+            color: .4, .4, .4, 1
+            text: util.app_credits
+            font_name: 'RobotoMono-Regular'
+            size_hint: 1, .5
+
+<MainWindow>:
+    title: 'MicroLab - DeepStain'
+    WorkSpace:
+        id: workspace
\ No newline at end of file