Full Code of mahart-studio/kivystudio for AI

master c97c38f6bf62 cached
87 files
268.2 KB
75.8k tokens
418 symbols
1 requests
Download .txt
Showing preview only (291K chars total). Download the full file or copy to clipboard to get everything.
Repository: mahart-studio/kivystudio
Branch: master
Commit: c97c38f6bf62
Files: 87
Total size: 268.2 KB

Directory structure:
gitextract_7y9q4d6t/

├── .gitignore
├── LICENSE
├── README.md
├── kivystudio/
│   ├── __init__.py
│   ├── assembler.py
│   ├── behaviors/
│   │   ├── __init__.py
│   │   ├── highlightbehavior.py
│   │   ├── hoverbehavior.py
│   │   └── hoverinfobehavior.py
│   ├── components/
│   │   ├── __init__.py
│   │   ├── codeplace/
│   │   │   ├── __init__.py
│   │   │   ├── code.kv
│   │   │   ├── codeplace.py
│   │   │   └── tabs/
│   │   │       ├── __init__.py
│   │   │       ├── codetab.py
│   │   │       ├── errortab.py
│   │   │       ├── welcome.kv
│   │   │       └── welcometab.py
│   │   ├── emulator_area/
│   │   │   ├── __init__.py
│   │   │   ├── emulator.kv
│   │   │   └── screen_drop.py
│   │   ├── screens/
│   │   │   ├── __init__.py
│   │   │   ├── screen.kv
│   │   │   └── screen_test.py
│   │   ├── sibebar/
│   │   │   ├── __init__.py
│   │   │   ├── fileexplorer/
│   │   │   │   ├── __init__.py
│   │   │   │   └── filewidgets.py
│   │   │   ├── generalsearch.py
│   │   │   ├── gitmanager.py
│   │   │   └── sidebar.kv
│   │   ├── terminal/
│   │   │   ├── __init__.py
│   │   │   ├── command_terminal.py
│   │   │   └── logger_space.py
│   │   └── topmenu/
│   │       ├── __init__.py
│   │       ├── dropmenu.kv
│   │       └── dropmenu.py
│   ├── libs/
│   │   ├── __init__.py
│   │   └── resizablebehavior/
│   │       ├── LICENSE
│   │       ├── README.md
│   │       ├── __init__.py
│   │       ├── modal_cursor.py
│   │       └── resize.py
│   ├── main.kv
│   ├── main.py
│   ├── parser/
│   │   └── __init__.py
│   ├── resources/
│   │   └── font-awesome.fontd
│   ├── settings.py
│   ├── tools/
│   │   ├── __init__.py
│   │   ├── iconfonts/
│   │   │   ├── LICENSE
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── iconfonts.py
│   │   │   └── test/
│   │   │       ├── font-awesome.css
│   │   │       ├── font-awesome.fontd
│   │   │       └── main.py
│   │   ├── infolabel.py
│   │   ├── logger.py
│   │   └── quicktools.py
│   └── widgets/
│       ├── __init__.py
│       ├── codeinput/
│       │   ├── __init__.py
│       │   ├── code_extra_behavior.py
│       │   ├── code_find.py
│       │   ├── codeinput.kv
│       │   ├── codeinput.py
│       │   ├── styles/
│       │   │   ├── __init__.py
│       │   │   └── native_tweak.py
│       │   └── tools.py
│       ├── dropdown.py
│       ├── filemanager/
│       │   ├── LICENSE
│       │   ├── README.md
│       │   ├── __init__.py
│       │   ├── filechooserthumbview/
│       │   │   ├── LICENSE
│       │   │   └── __init__.py
│       │   └── filemanager.kv
│       ├── iconlabel.py
│       ├── rightclick_drop.py
│       ├── searchinput.py
│       ├── splitter.py
│       └── tabbedpanel.py
├── project/
│   ├── prjtTest1.htm
│   └── prjtTest1.js
├── repoTest1.js
├── repoTest2.htm
├── setup.py
├── tests/
│   ├── test_codeplace.py
│   └── test_emulator.py
└── to-do.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
*.pyc
*.zip
*.gif
pyc.py
__pycache__/
.vscode/
build/
dist/
*egg-info

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2019 @mahartstudio

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
#### KivyStudio
<!-- ![KivyStudio](https://raw.githubusercontent.com/MichaelStott/KivMob/master/demo/assets/kivmob-title.png) -->

[![Build Status](https://travis-ci.com/MichaelStott/KivMob.svg?branch=master)](https://travis-ci.com/MichaelStott/KivMob)
[![Python](https://img.shields.io/badge/python-2-green.svg)](https://www.python.org/downloads/release/python-270/)
[![Python](https://img.shields.io/badge/python-3-green.svg)](https://www.python.org/downloads/release/python-270/)
[![Downloads](https://pepy.tech/badge/kivmob)](https://pepy.tech/project/kivmob)
[![Maintainability](https://api.codeclimate.com/v1/badges/add8cd9bd9600d898b79/maintainability)](https://codeclimate.com/github/MichaelStott/KivMob/maintainability)

A kivy software development environment targeted towards fast testing and interactive development.
* #### Features
  - Emulation can be done in real time
  - Supports multiple screen views for mobile devices
  - Supports orientation changes for mobile devices
  - Supports outer window emulation for desktop intended emulation and for full test on mobile devices

* **Status**: under development...
* **Release**: 0


### Installation

Package file for various platform will be available on first release


### Demo Screenshot
<p align="center">
  <img src="https://raw.githubusercontent.com/mahart-studio/kivystudio/master/showcase/Screenshot(1).png">
</p>

### Quickstart

* Create a new folder
* Open **kivystudio**.
* On the top menu bar go to **File** option
* Click **Open Folder**,

<p align="center">
  <img src="https://raw.githubusercontent.com/mahart-studio/kivystudio/master/showcase/Screenshot(2).png">
</p>

* Choose your folder

<p align="center">
  <img src="https://raw.githubusercontent.com/mahart-studio/kivystudio/master/showcase/Screenshot(3).png">
</p>

* Press <kbd>Ctrl</kbd> + <kbd>N</kbd> : a new file will open-up


Copy the following code into the editor provided.
```python
from kivy.app import App
from kivy.uix.button import Button

class MyApp(App):
	def build(self):
		return Button(text='Welcome to KivyStudio!!')

if __name__ == '__main__':
	MyApp().run()
```

* To save the code, press <kbd>Ctrl</kbd> + <kbd>S</kbd>.
* Right click on **File** tab
* Choose **Set for Emulation**, or press <kbd>Ctrl</kbd> + <kbd>E</kbd> to select the file for emulation
* Then, press <kbd>Ctrl</kbd> + <kbd>R</kbd> to see the output, *OR* you can also set auto-emulation from **File** tab
* To switch screens, use the <kbd>Ctrl</kbd> + <kbd>Tab</kbd> combination
* To open and close terminal panel, press <kbd>Ctrl</kbd> + <kbd>`</kbd>

<p align="center">
  <img src="https://raw.githubusercontent.com/mahart-studio/kivystudio/master/showcase/Screenshot(4).png">
</p>

### Contributions
To contribute to this project
* Fork the repository
* Clone it
``` git clone https://github.com/mahart-studio/kivystudio.git``` 
* Start by solving an issue or fixing a known bug
* Create a **Pull Request**
* PR would be merged after review.


================================================
FILE: kivystudio/__init__.py
================================================
from kivy.config import Config
Config.set('graphics', 'width', '1000')
Config.set('graphics', 'height', '730')
Config.set('kivy', 'exit_on_escape', '0')
Config.set('input', 'mouse', 'mouse,disable_multitouch')

__version__ = '0.2.0.dev'


def get_kivystudio_app():
     from .main import studio_app
     return studio_app



================================================
FILE: kivystudio/assembler.py
================================================

from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.clock import mainthread

from kivystudio.widgets.filemanager import filemanager
from kivystudio.parser import emulate_file

from kivystudio.components.topmenu import TopMenu
from kivystudio.components.codeplace import code_place, code_container
from kivystudio.components.sibebar import SideBar
from kivystudio.components.terminal import TerminalSpace
from kivystudio.components.emulator_area import get_emulator_area
from kivystudio.settings import settings_obj

class Assembly(BoxLayout):
    '''
    Widget to assemble and structure 
    all widgets
    '''

def add_new_tab(paths):
    for path in paths:
        code_place.add_code_tab(filename=path)

@mainthread
def open_project(paths):
    if paths:
        side_bar.ids.explorer_btn='down'
        side_bar.fileexplorer.load_directory(paths[0])

def main_key_handler(win, *args):
    '''' main keyboard and shortcut lisener '''
    # print(args)
    if args[0] == 114 and  'ctrl' in args[3]:     # emulate file Ctrl+R
        emulate_file(emulator_area.emulation_file)

    elif args[0] == 107 and 'ctrl' in args[3]:    # Open folder Ctrl+K
        filemanager.choose_dir(path='.',on_selection=open_project)

    elif args[0] == 111 and 'ctrl' in args[3]:    # Open file Ctrl+O
        filemanager.open_file(path='.',on_selection=add_new_tab)

    elif args[0] == 110 and 'ctrl' in args[3]:    # New file Ctrl+N
        code_place.add_code_tab(tab_type='new_file')

    elif args[0] == 96 and 'ctrl' in args[3]:    # Toggle terminal  Ctrl+`
        from kivystudio.components.codeplace import terminal
        terminal.toggle_state()

    elif args[0] == 45 and 'ctrl' in args[3]:    # Zoom out Ctrl -
        if settings_obj.dpi_scale > 0.8:
            settings_obj.dpi_scale -= 0.1

    elif args[0] == 61 and 'ctrl' in args[3]:    # Zoom in Ctrl +
        if settings_obj.dpi_scale < 1.4:
            settings_obj.dpi_scale += 0.1

Window.bind(on_key_down=main_key_handler)


emulator_area = get_emulator_area()
side_bar = SideBar()
Assembler = Assembly()

box = Assembler.ids.box
box.add_widget(side_bar)
box.add_widget(code_container)
box.add_widget(emulator_area)


================================================
FILE: kivystudio/behaviors/__init__.py
================================================
from .highlightbehavior import HighlightBehavior
from .hoverbehavior import HoverBehavior
from .hoverinfobehavior import HoverInfoBehavior

================================================
FILE: kivystudio/behaviors/highlightbehavior.py
================================================

from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.properties import (BooleanProperty, ObjectProperty, 
                ListProperty, OptionProperty, NumericProperty)
from kivy.base import runTouchApp
from kivy.graphics import InstructionGroup, Color, Rectangle, RoundedRectangle, Callback
from kivy.uix.behaviors import FocusBehavior
from kivy.clock import Clock
from kivy.event import EventDispatcher

from kivy.core.window import Window, Keyboard

__all__ = ('HighlightBehavior', )

class HighlightBehavior(object):

    current_highlighted_child = ObjectProperty(None, allownone=True)
    ''' current highlighted child
        on ObjectProperty and defualts to None '''

    highlighted_color = ListProperty([.2,.5,1,.5])
    ''' color that show highlighted widget
        a ListProperty defualts to [.2,.5,1.5] make sure it transparent
        because it's drawn over the widget '''

    auto_scroll_to = BooleanProperty(False)
    ''' automatically scroll to the widget when widget is out of focus 
    note* parent most be a scrollview to enable the property'''

    highlighted_shape = OptionProperty('rectangle', options=['rounded_rectangle','rectangle'])


    highlight_orientation = OptionProperty('vertical', options=['vertical',
                                'horizontal', 'grid'])
    ''' Orientation in which the highlighting will take place if
    grid grid len must be set'''

    instruction_canvas = ObjectProperty(InstructionGroup())
    ''' internal instruction group used to draw the canvas on the
        currently highlighted child '''

    grid_len = NumericProperty(0)


    def __init__(self, **kwargs):
        super(HighlightBehavior, self).__init__(**kwargs)


    def set_first_child(self, dt):
        if len(self.children) >= 1:
            self.set_highlighted(self.children[0])


    def on_highlighted_color(self, *args):
        self.redraw_canvas()

    def redraw_canvas(self, *args):
        if self.current_highlighted_child:
            self.instruction_canvas.clear()
            self.instruction_canvas.add(Color(*self.highlighted_color))

            if self.highlighted_shape =='rectangle':
                self.instruction_canvas.add(Rectangle(pos=self.current_highlighted_child.pos, size=self.current_highlighted_child.size))
            elif self.highlighted_shape =='rounded_rectangle':
                self.instruction_canvas.add(RoundedRectangle(pos=self.current_highlighted_child.pos, size=self.current_highlighted_child.size))
            else:
                raise Exception('Invalid highlighted shape {}'.format(self.highlighted_shape))

    def on_focus(self, arg, focus):
        if focus:
            Window.bind(on_key_down=self.handle_key)
            if self.current_highlighted_child is None:
                Clock.schedule_once(self.set_first_child)
        else:
            Window.unbind(on_key_down=self.handle_key)


    def on_children(self, *args):
        if len(self.children) == 1:
            self.set_highlighted(self.children[0])


    def set_highlighted(self, child):
        if not (child == self.current_highlighted_child):
            if self.current_highlighted_child: # remove the canvas from the previosly highlighted child
                self.current_highlighted_child.canvas.after.remove(self.instruction_canvas)

            child.canvas.after.add(self.instruction_canvas)
            self.current_highlighted_child = child
            with child.canvas:
                Callback(self.redraw_canvas)

    def handle_key(self, keyboard, key, codepoint, text, modifier, *args):

        key_str = Keyboard.keycode_to_string(Window._system_keyboard, key)
        modifier.sort()
        if modifier:
            value = '_'.join(modifier) + '_' + key_str
        else:
            value = key_str
        
        callable_method = 'do_' + value

        try:
            func = getattr(self, callable_method)
        except AttributeError:
            pass
        else:
            func()

    def _moving(self):
        if self.auto_scroll_to:
            self.parent.scroll_to(self.current_highlighted_child)


    def do_up(self):
        if self.highlight_orientation == 'vertical':
            children = self.children[:]
            index = children.index(self.current_highlighted_child)
            if not(index >= len(children)-1):
                self.set_highlighted(children[(index)+1])
                self._moving()
        
        elif self.highlight_orientation == 'horizontal':
            pass
        
        elif self.highlight_orientation == 'grid':
            children = self.children[:]
            index = children.index(self.current_highlighted_child)
            if not(index+self.grid_len >= len(children)):
                self.set_highlighted(children[(index)+self.grid_len])
                self._moving()

        else:
            raise Exception('invalid highlight_orientation %s'%self.highlight_orientation)

    def do_down(self):
        if self.highlight_orientation == 'vertical':
            children = self.children[:]
            index = children.index(self.current_highlighted_child)
            if not(index < 1):
                self.set_highlighted(children[(index)-1])
                self._moving()

        elif self.highlight_orientation == 'horizontal':
            pass
        
        elif self.highlight_orientation == 'grid':
            children = self.children[:]
            index = children.index(self.current_highlighted_child)
            if not(index+self.grid_len < 1):
                self.set_highlighted(children[(index)-self.grid_len])
                self._moving()
        else:
            raise Exception('invalid highlight_orientation %s'%self.highlight_orientation)

    def do_right(self):
        if self.highlight_orientation == 'vertical':
            pass

        elif self.highlight_orientation == 'horizontal' or self.highlight_orientation == 'grid':

            self._moving()
            children = self.children[:]
            index = children.index(self.current_highlighted_child)
            if not(index < 1):
                self.set_highlighted(children[(index)-1])
                self._moving()
        else:
            raise Exception('invalid highlight_orientation %s'%self.highlight_orientation)

    def do_left(self):

        if self.highlight_orientation == 'vertical':
            pass

        elif self.highlight_orientation == 'horizontal' or self.highlight_orientation == 'grid':

            children = self.children[:]
            index = children.index(self.current_highlighted_child)
            if not(index >= len(children)-1):
                self.set_highlighted(children[(index)+1])
                self._moving()

        else:
            raise Exception('invalid highlight_orientation %s'%self.highlight_orientation)

    def do_enter(self):
        pass

    def do_ctrl_up(self):
        pass
    def do_shift_up(self):
        pass
    def do_shift_down(self):
        pass
    def do_shift_left(self):
        pass
    def do_shift_up(self):
        pass

'''
        if value :
            self.map.get(value)[0]()
            return True
'''
class What(HighlightBehavior, FocusBehavior, GridLayout):
    pass

if __name__ == "__main__":
    what = What(cols=3, grid_len=3, highlight_orientation='grid')

    for btn in range(12):
        what.add_widget(Button(text=str(btn)))

    runTouchApp(what)


================================================
FILE: kivystudio/behaviors/hoverbehavior.py
================================================

''' A quick implementation of mouse hovering 
    just fires one event called 'on_hover'
    when the mouse hover on a widget the inhenrites from this
    behavior
    Ex:
    class HoverButton(HoverBehavior, Button):

        def on_hover(self, *args):
            if self.hover:
                self.text = 'Yeah!!'
            else:
                self.text =''
'''

from kivy.core.window import Window
from kivy.properties import ObjectProperty

class HoverBehavior(object):

    hover = ObjectProperty(False)
    ''' indicate is mouse if over the widget
    defaults to False'''


    def on_parent(self, *args):

        if self.parent:
            Window.bind(mouse_pos=self.on_mouse_move)
        else:
            Window.unbind(mouse_pos=self.on_mouse_move)


    def on_mouse_move(self, win, pos):

        if self.collide_point(*self.to_widget(*pos)):
            self.hover = True
        else:
            self.hover = False


if __name__ == "__main__":
    from kivy.base import runTouchApp as app
    from kivy.uix.button import Button
    from kivy.uix.boxlayout import BoxLayout

    class HoverButton(HoverBehavior, Button):

        def on_hover(self, *args):
            if self.is_hover:
                self.text = 'Yeah!!'
            else:
                self.text =''
    box=BoxLayout()
    box.add_widget(HoverButton())
    box.add_widget(Button(text='Hello'))
    app(box)

================================================
FILE: kivystudio/behaviors/hoverinfobehavior.py
================================================
'''
Mixin behavior widget that inherits from kivystudio.behavior.HoverBehavior
used on a widget, to show extra infomation on what the widgets does
by hovering on it

Simple usages:

class MyButton(HoverInfoBehavior, Button):

    def __init__(self, **kwargs):
        super(MyButton, self).__init__(**kwargs)
        self.info_text = 'Click me'

        # or if the info text might change you, could bind it to an atrr
        self.mytext = 'somthing'
        self.info_text_attr = 'mytext'



'''
from kivy.clock import Clock
from kivy.properties import StringProperty
from kivystudio.tools import infolabel

from .hoverbehavior import HoverBehavior

class HoverInfoBehavior(HoverBehavior):

    info_text = StringProperty('')
    
    info_text_attr = StringProperty('')

    def on_parent(self, *a):
        if self.parent is None:
            infolabel.remove_info_on_mouse()
        return super(HoverInfoBehavior, self).on_parent(*a)

    def on_hover(self, *a):
        if self.hover:
            Clock.schedule_once(self.show_label_info,1)
        else:
            Clock.unschedule(self.show_label_info)
            infolabel.remove_info_on_mouse()

    def show_label_info(self,dt):
        info_text = self.info_text
        if self.info_text_attr:
            info_text = getattr(self, self.info_text_attr)

        # if info_text:
        infolabel.show_info_on_mouse(info_text)


================================================
FILE: kivystudio/components/__init__.py
================================================


================================================
FILE: kivystudio/components/codeplace/__init__.py
================================================

from .codeplace import CodePlace

from kivystudio.widgets.splitter import StudioSplitter
from kivystudio.components.terminal import TerminalSpace

class CodeContainer(StudioSplitter):
    pass
code_container = CodeContainer()
container = code_container.ids.container


code_place = CodePlace()
code_place.add_code_tab(tab_type='welcome')  # add welcoming tab

terminal = TerminalSpace()

container.add_widget(code_place)
container.add_widget(terminal)


================================================
FILE: kivystudio/components/codeplace/code.kv
================================================

<CodeContainer>:
    sizable_from: 'right'
    max_size: root.parent.width-self.parent.children[2].width if self.parent and len(self.parent.children)>2 else 0
    min_size: '700dp'
    FloatLayout:
        id: container


<CodePlace>:
    orientation: 'vertical'
    tab_manager: tab_manager
    pos_hint: {'center_y': .5, 'center_x': .5}
    CodeTabsContainer:
        size_hint_y: None
        height: '36dp'
        canvas.before:
            Color:
                rgba: (0.12, 0.12, 0.12, 1)
            Rectangle:
                size: self.size
                pos: self.pos

        # canvas to show shadow division
        canvas.after:
            Color:
                rgba: (0, 0, 0, .4)
            Line:
                points: [self.x,self.y, self.right,self.y]
            Color:
                rgba: (0, 0, 0, .3)
            Line:
                points: [self.x,self.y-1, self.x-1,self.y-1]
            Color:
                rgba: (0, 0, 0, .2)
            Line:
                points: [self.x,self.y-2, self.x,self.y-2]
            Color:
                rgba: (0, 0, 0, .1)
            Line:
                points: [self.x,self.y-3, self.x,self.y-3]
                width: 2

        GridLayout:
            rows: 1
            id: tab_manager
            size_hint_x: None
            width: self.minimum_width



<TabToggleButton>:
    size_hint_x: None
    width: self.minimum_width
    padding: '6dp'
    spacing: '3dp'
    canvas_color: (0.12, 0.12, 0.12, 1)
    allow_no_selection: False
    group: '__tabed_btn__'
    on_state:
        if self.state == 'down': self.canvas_color= (.2,.2,.2,1)
        else: self.canvas_color= (0.12, 0.12, 0.12, 1)
    canvas.before:
        Color:
            rgba: self.canvas_color
        Rectangle:
            size: self.size
            pos: self.pos
    IconLabel:
        size_hint_x: None
        width: '10dp'
        text: '%s'%(icon('fa-file-code-o'))
        color: .2,.5,1,.8
    Label:
        font_size: '13.5dp'
        text: root.text
        text_size: None, None
        padding: '3dp', 0
        shorten: True
        shorten_from: 'right'
        size_hint_x: None
        width: max(self.texture_size[0]+10, 110)
    TabPannelIndicator:
        id: indicator
        on_release: root.close_tab()

<TabPannelIndicator>:
    size_hint_x: None
    width: '12dp'


<CodeTabDropDown>:
    MenuButton:
        on_release: root.close_tab()
        MenuLabel:
            text: 'Close'
        MenuLabel:
            text: 'Ctrl+W'
            type: 'shortcut'
    ToggleMenuButton:
        text: 'Set file for emulation'
        on_state:
            if self.state=='down': root.set_for_emulation()
            else: root.set_for_emulation(remove=True)
    MenuButton:
        MenuLabel:
            text: 'Copy path'
        MenuLabel:
            text: 'Alt-Ctrl+C'
            type: 'shortcut'
    MenuButton:
        MenuLabel:
            text: 'Copy relative path'
        MenuLabel:
            text: 'Alt-Ctrl+Shift+C'
            type: 'shortcut'
        MenuLabel:
            text: 'Split Up'
    MenuButton:
        MenuLabel:
            text: 'Split Down'
    MenuButton:
        MenuLabel:
            text: 'Split Left'
    MenuButton:
        MenuLabel:
            text: 'Split Right'


<FileErrorTab>:
    text: "This file is not displayed because it is either binary or uses an unsupported text encoding."
    canvas.before:
        Color:
            rgba: (0.12, 0.12, 0.12, 1)
        Rectangle:
            size: self.size
            pos: self.pos


================================================
FILE: kivystudio/components/codeplace/codeplace.py
================================================

from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition, ScreenManagerException
from kivy.uix.scrollview import ScrollView
from kivy.uix.behaviors import ToggleButtonBehavior, FocusBehavior
from kivy.uix.boxlayout import BoxLayout

from kivy import properties as prop
from kivy.clock import Clock
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.extras.highlight import KivyLexer


from kivystudio.widgets.codeinput import FullCodeInput
from kivystudio.widgets.filemanager import filemanager
from kivystudio.components.emulator_area import get_emulator_area
from kivystudio.tools import quicktools, load_kv
from kivystudio.tools.logger import Logger

from .tabs.welcometab import WelcomeTab
from .tabs.codetab import TabToggleButton
from .tabs.errortab import FileErrorTab

from pygments import lexers
import os

# file_formats = ['.py', '.kv', '.spec', '.txt']

def get_tab_from_group(filename):
    all_tabs = ToggleButtonBehavior.get_widgets('__tabed_btn__')
    if not all_tabs: return
    for tab in all_tabs:
        if tab.filename == filename:
            return tab


def get_lexer_for_file(filename):
    ext = os.path.splitext(filename)[1]
    try:
        lexer = lexers.get_lexer_for_filename(filename)
    except lexers.ClassNotFound:
        if ext == '.kv':
            lexer = KivyLexer()
        else:
            lexer = lexers.TextLexer()
    # print('found {} for {}'.format(lexer, filename))
    return lexer


class CodeScreenManager(ScreenManager):

    def __init__(self, **kwargs):
        super(CodeScreenManager, self).__init__(**kwargs)
        self.transition = NoTransition()

    def add_widget(self, widget, name, tab_type='code'):
        if tab_type=='code':
            Clock.schedule_once(lambda dt: self.open_file(widget),1)     # open the file

        try:
            widget.code_input.lexer = get_lexer_for_file(widget.filename)
        except:
            pass

        screen = CodeScreen(name=name)
        screen.add_widget(widget,tab_type=tab_type)
        super(CodeScreenManager, self).add_widget(screen)

    def open_file(self, code_input):
        if os.path.exists(code_input.filename):
            with open(code_input.filename, 'r') as f:
                code_input.code_input.focus = False
                code_input.code_input.text = f.read()

    def save_current_tab(self):
        self.get_screen(self.current).save_file()

    def save_all_tabs(self):
        for name in self.screen_names:
            self.get_screen(name).save_file()

    def get_children_with_filename(self, filename):
        try:
            child = list(filter(lambda child: child.name==filename, self.screens))[0]
            return child
        except IndexError:
            raise Exception('code manager as no child with such filename {}'.format(filename))


class CodeScreen(Screen):
    
    code_field = prop.ObjectProperty(None)

    def on_pre_enter(self):
        if self.code_field:
            self.code_field.code_input.focus = True
            Window.bind(on_key_down=self.keyboard_down)

        tab = get_tab_from_group(self.name)
        if tab:
            Clock.schedule_once(lambda dt: setattr(tab, 'state', 'down'))


    def on_pre_leave(self):
        if self.code_field:
            Window.unbind(on_key_down=self.keyboard_down)

    def on_enter(self):
        if self.code_field:
            self.code_field.code_input.focus = True

    def save_file(self, new_file=False, auto_save=False):
        if self.code_field.tab_type=='code':
            if not self.code_field.saved or new_file:
                with open(self.name, 'w') as fn:
                    fn.write(self.code_field.code_input.text)
    
            self.code_field.saved = True
        if new_file:
            self.code_field.code_input.lexer = get_lexer_for_file(self.name)
                
        if self.code_field.tab_type=='new_file' and not auto_save:
            filemanager.save_file(path='/root', on_selection=self.save_new_file)


    def save_new_file(self, paths):
        if paths:
            path=paths[0]
            self.code_field.tab.filename=path
            self.code_field.tab.text = os.path.split(path)[1]
            self.code_field.tab_type='code'
            self.name=path
            self.save_file(new_file=True)

    def add_widget(self, widget, tab_type='code'):
        super(CodeScreen, self).add_widget(widget)
        if tab_type=='code' or tab_type=='new_file':
            self.code_field = widget
            self.code_field.tab_type=tab_type
            self.code_field.bind(saved=self.saving_file)

    def saving_file(self, ins, saved):
        tab = get_tab_from_group(self.name)
        tab.saved = saved       

    def keyboard_down(self, window, *args):
        # print(args)
        if args[0] == 115 and 'ctrl' in args[3]:  # save file Ctrl+S
            self.save_file()
            return False

        if args[0] == 101 and 'ctrl' in args[3]:  # select file for emulation file Ctrl+E
            if os.path.exists(self.name):
                get_emulator_area().emulation_file=self.name
                Logger.info("Emulator: File '{}' selected".format(self.name))
            else:
                Logger.info("Emulator: invalid file selected".format(self.name))


class CodePlace(BoxLayout):
    
    code_manager = prop.ObjectProperty(None)

    tab_manager = prop.ObjectProperty(None)

    new_empty_tab = prop.NumericProperty(0)
    '''count of empty tabs that has been opened
    '''

    def __init__(self, **kwargs):
        super(CodePlace, self).__init__(**kwargs)
        self.code_manager = CodeScreenManager()
        self.add_widget(self.code_manager)

        Window.bind(on_key_down=self.keyboard_down)
        Window.bind(on_dropfile=self.file_droped)

    def file_droped(self, window, filename, *args):
        if self.collide_point(*window.mouse_pos):
            print('File droped on code input {} '.format(filename))
            if filename:
                self.add_code_tab(filename=filename.decode('utf-8'))

    def add_widget(self, widget, tab_type=''):
        if len(self.children) > 1:
            if tab_type =='code' or tab_type =='new_file' or tab_type=='unsupported':
                tab = TabToggleButton(text=os.path.split(widget.filename)[1],
                                    filename=widget.filename)
                widget.tab = tab
                widget.tab_type = tab_type
                self.code_manager.add_widget(widget, widget.filename, tab_type=tab_type)

            elif tab_type=='welcome':
                self.code_manager.add_widget(widget, 'kivystudiowelcome', tab_type=tab_type)
                tab = TabToggleButton(text='Welcome',filename='kivystudiowelcome')

            tab.bind(state=self.change_screen)
            self.tab_manager.add_widget(tab)
            Clock.schedule_once(lambda dt: setattr(tab, 'state', 'down'))

        else:
            super(CodePlace, self).add_widget(widget)

    def change_screen(self, tab, state):
        if state == 'down':
            self.code_manager.current = tab.filename
            checked_list = list(filter(lambda child: child != tab, ToggleButtonBehavior.get_widgets(tab.group)))
            for child in checked_list:
                if child != tab:
                    child.state='normal'

    def keyboard_down(self, window, *args):

        if args[0] == 9 and args[3] == ['ctrl']:   # switching screen with ctrl tab
            self.code_manager.current = self.code_manager.next()
            return True

        if args[0] == 119 and args[3] == ['ctrl']:   # close tab
            try:
                name = self.code_manager.get_screen(self.code_manager.current).name
                tab = get_tab_from_group(name)
                self.remove_code_tab(tab)
            except ScreenManagerException:
                pass

    def remove_code_tab(self, tab):
        self.tab_manager.remove_widget(tab)
        codeinput=self.code_manager.get_children_with_filename(tab.filename)
        self.code_manager.remove_widget(codeinput)

        if tab.filename.startswith('Untitled-') and not os.path.exists(tab.filename):
            self.new_empty_tab -= 1

    def add_code_tab(self, filename='', tab_type='code'):
        if filename and os.path.exists(filename):
            if not quicktools.is_binary(filename):
                widget=FullCodeInput(filename=filename)
            else:
                widget=FileErrorTab(filename=filename)
                tab_type='unsupported'
            try:
                self.code_manager.get_screen(filename)
                self.code_manager.current=filename
            except ScreenManagerException:   # then it is not added
                self.add_widget(widget, tab_type=tab_type)

        elif tab_type=='new_file':   # a new tab
            self.new_empty_tab += 1
            while True:
                try:
                    self.code_manager.get_screen(filename)
                    self.code_manager.current=filename
                except ScreenManagerException:   # then it is not added
                    filename = 'Untitled-{}'.format(self.new_empty_tab)
                    self.add_widget(FullCodeInput(filename=filename), tab_type=tab_type)
                    return
                self.new_empty_tab += 1

        elif tab_type == 'welcome':
            try:
                self.code_manager.get_screen('kivystudiowelcome')
                self.code_manager.current=filename
            except ScreenManagerException:   # then it is not added
                self.add_widget(WelcomeTab(), tab_type=tab_type)



class CodeTabsContainer(ScrollView):
    '''horizontal scrollview where the small tab 
        buttons lay'''

    def on_touch_down(self, touch):
        FocusBehavior.ignored_touch.append(touch)
        return super(CodeTabsContainer, self).on_touch_down(touch)

load_kv(__file__, 'code.kv')


================================================
FILE: kivystudio/components/codeplace/tabs/__init__.py
================================================


================================================
FILE: kivystudio/components/codeplace/tabs/codetab.py
================================================
from kivy.uix.behaviors import ToggleButtonBehavior,ButtonBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.image import Image
from kivy.core.window import Window
from kivy.clock import Clock, mainthread
from kivy.properties import (StringProperty,
                            ObjectProperty,
                            BooleanProperty)
from kivystudio.behaviors import HoverInfoBehavior
from kivystudio.behaviors import HighlightBehavior
from kivystudio.widgets.iconlabel import IconLabelButton
from kivystudio.widgets.rightclick_drop import RightClickDrop
from kivystudio.tools import set_auto_mouse_position
from kivystudio.tools.iconfonts import icon
from kivystudio.components.emulator_area import get_emulator_area

rightclick_dropdown = [None]

class TabToggleButton(HoverInfoBehavior, ToggleButtonBehavior, BoxLayout):

    filename = StringProperty('')

    saved = BooleanProperty(True)

    text = StringProperty('')

    def __init__(self, **kwargs):
        super(TabToggleButton, self).__init__(**kwargs)
        # set the info attr because filename could change
        self.info_text_attr = 'filename'

        if rightclick_dropdown[0] is None:
            self.rightclick_dropdown = CodeTabDropDown()
            rightclick_dropdown[0] = self.rightclick_dropdown
        else:
            self.rightclick_dropdown=rightclick_dropdown[0]

    def on_saved(self, *args):
        if self.saved:
            self.ids.indicator.text =''
        elif not self.saved:
            self.ids.indicator.text = '%s' % (icon('fa-circle'))
            self.ids.indicator.font_size = '12dp'

    def on_state(self, *args):
        if self.state=='down' and not self.saved:
            self.ids.indicator.text = '%s' % (icon('fa-circle'))
            self.ids.indicator.font_size = '12dp'
        elif self.state=='down' and self.saved:
            self.ids.indicator.text = '%s' % (icon('fa-close'))
            self.ids.indicator.font_size = '16dp'
        elif self.state=='normal':
            self.ids.indicator.source =''
 

    def on_touch_down(self,touch):
        if self.collide_point(*touch.pos):
            if touch.button == 'right':
                self.rightclick_dropdown.open(self)
                FocusBehavior.ignored_touch.append(touch)
                return True

        if touch.button == 'left':
            return super(TabToggleButton, self).on_touch_down(touch)

    def close_tab(self):
        from kivystudio.assembler import code_place
        code_place.remove_code_tab(self)


    def __str__(self):
        return self.filename


class CodeTabDropDown(RightClickDrop):

    def __init__(self, **kwargs):
        super(CodeTabDropDown, self).__init__(**kwargs)
        self.tab = None

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):  # touch should not unfocus input
            FocusBehavior.ignored_touch.append(touch)
        return super(CodeTabDropDown,self).on_touch_down(touch)

    def open(self, tab):
        self.tab=tab
        super(CodeTabDropDown, self).open()

    def set_for_emulation(self, remove=False):
        if not remove:
            get_emulator_area().emulation_file=self.tab.filename
        else:
            get_emulator_area().emulation_file=''

    def close_tab(self):
        self.dismiss()
        self.tab.close_tab()


class TabPannelIndicator(IconLabelButton):
        
    def on_hover(self, *a):
        if self.hover:
            self.text = '%s' % (icon('fa-close'))
            self.font_size = '16dp'
        if not self.hover and not self.parent.saved:
            self.text = '%s' % (icon('fa-circle'))
            self.font_size = '12dp'
        if not self.hover and self.parent.saved and self.parent.state=='normal':
            self.text = ''
        if not self.hover and self.parent.saved and self.parent.state=='down':
            self.text = '%s' % (icon('fa-close'))
            self.font_size = '16dp'

        return super(TabPannelIndicator, self).on_hover(*a)


================================================
FILE: kivystudio/components/codeplace/tabs/errortab.py
================================================
from kivy.uix.label import Label
from kivy.properties import StringProperty

class FileErrorTab(Label):
    filename = StringProperty('')


================================================
FILE: kivystudio/components/codeplace/tabs/welcome.kv
================================================
#: import icon kivystudio.tools.iconfonts.icon
#: import quicktools kivystudio.tools.quicktools
            # IconLabel:
            #     text: '%s'%(icon('fa-bug'))
            # IconLabel:
            #     text: '%s'%(icon('fa-code-fork'))

<WelcomeTab>:
    BoxLayout:
        orientation: 'vertical'
        BoxLayout:
            size_hint_y: None
            height:'80dp'
            orientation: 'vertical'
            Label:
                haling:'center'
                text: 'Kivy Studio' 
                bold: True
                font_size: '40dp'
        BoxLayout:
            size_hint_y: None
            height:'150dp'
            GridLayout:
                cols: 4
                IconLabel:
                    text: '%s'%(icon('fa-android'))
                    color: .2,1,.2
                    font_size: '64dp'
                IconLabel:
                    text: '%s'%(icon('fa-apple'))
                    color: .9,.9,.95
                    font_size: '64dp'
                IconLabel:
                    text: '%s'%(icon('fa-linux'))
                    font_size: '64dp'
                IconLabel:
                    text: '%s'%(icon('fa-windows'))
                    font_size: '64dp'
        BoxLayout:
            padding: '30dp'
            GridLayout:
                cols: 1
                Label:
                    size_hint_y: None
                    height: '32dp'
                    text: 'Start'
                    bold: True
                    font_size: '18dp'
                BoxLayout:
                    orientation: 'vertical'
                    size_hint_y: None
                    height: self.minimum_height
                    Label:
                        on_ref_press: quicktools.open_new_file()
                        text: '[u][color=2255FF][ref="d"]Open new file[/ref][/color][/u] - [ctrl N]'
                        markup: True
                        size_hint_y: None
                        height: '32dp'
                    Label:
                        on_ref_press: quicktools.open_file()
                        text: '[u][color=2255FF][ref="d"]Open file[/ref][/color][/u] - [ctrl O]'
                        markup: True
                        size_hint_y: None
                        height: '32dp'
                    Label:
                        on_ref_press: quicktools.open_folder()
                        text: '[u][color=2255FF][ref="d"]Open folder[/ref][/color][/u] - [ctrl K]'
                        markup: True
                        size_hint_y: None
                        height: '32dp'
            GridLayout:
                cols: 1
                Label:
                    size_hint_y: None
                    height: '32dp'
                    text: 'Recent'
                    bold: True
                    font_size: '18dp'
                BoxLayout:
                    orientation: 'vertical'


================================================
FILE: kivystudio/components/codeplace/tabs/welcometab.py
================================================
from kivystudio.widgets.iconlabel import IconLabel
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder

from os.path import join, dirname
Builder.load_file(join(dirname(__file__), 'welcome.kv'))

class WelcomeTab(BoxLayout):
    pass


================================================
FILE: kivystudio/components/emulator_area/__init__.py
================================================
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.uix.screenmanager import ScreenManager, Screen

from kivy.lang import Builder
from kivy.properties import ObjectProperty, StringProperty
from kivy.clock import Clock

from kivystudio.behaviors import HoverBehavior
from kivystudio.components import screens
from kivystudio.widgets.iconlabel import IconLabelButton

from .screen_drop import ScreenDrop

import os
__all__ = ('get_emulator',)
filepath = os.path.dirname(__file__)
Builder.load_file(os.path.join(filepath,'emulator.kv'))

class EmulatorArea(BoxLayout):

    screen_display = ObjectProperty(None)

    emulation_file = StringProperty('')

    def __init__(self, **kwargs):
        super(EmulatorArea, self).__init__(**kwargs)
        self.screen_manager = EmulatorScreens()
        self.add_widget(self.screen_manager)
        self.screen_display = ScreenDisplay()
        self.screen_manager.add_widget(self.screen_display)
    
    def add_widget(self, widget):
        super(EmulatorArea, self).add_widget(widget)

    def toggle_orientation(self):
        if self.screen_display.screen.orientation =='portrait': 
            self.screen_display.screen.orientation ='landscape'
        else:
            self.screen_display.screen.orientation ='portrait'

    def open_screen_drop(self,widget):
        ScreenDrop().open(widget, self.screen_display)


class ScreenTopMenu(BoxLayout):
    
    screen = ObjectProperty(None)



class EmulatorScreens(ScreenManager):
    
    def add_widget(self, widget):
        screen = Screen()
        screen.add_widget(widget)
        super(EmulatorScreens, self).add_widget(screen)



class ScreenDisplay(HoverBehavior, FloatLayout):
    
    screen = ObjectProperty(None)

    topmenu = ObjectProperty(None)

    screen_name = StringProperty('')

    def __init__(self, **kwargs):
        super(ScreenDisplay, self).__init__(**kwargs)
        self.scaler = ScreenTopMenu()
        self.screen_name = 'AndroidPhoneScreen'

    def on_hover(self, *args):
        pass

    def on_screen_name(self, *a):
        self.former_screen = self.screen
        self.screen = getattr(screens, self.screen_name)()

    def on_screen(self, obj, screen):
        if self.former_screen:
            root = self.former_screen.root_widget
            if root:
                self.former_screen.clear_widgets()
                screen.add_widget(root)

        # now add new screen 
        self.clear_widgets()
        self.add_widget(screen)
        self.bind(center=self.screen.setter('center'))
        self.scaler.screen = screen


instance=[]
def get_emulator_area():
    if instance:
        return instance[0]
    else:
        emulator_area = EmulatorArea(size_hint_x=.45)
        instance.append(emulator_area)
        return emulator_area


================================================
FILE: kivystudio/components/emulator_area/emulator.kv
================================================
#: import split os.path.split

<EmulatorArea>:
    orientation: 'vertical'
    GridLayout:
        canvas.before:
            Color:
                rgba: (0.12, 0.12, 0.12, 1)
            Rectangle:
                size: self.size
                pos: self.pos
        rows: 1
        id: tab_manager
        size_hint_y: None
        height: '36dp'

        Label:
            size_hint_x: None
            width: min(self.texture_size[0]+dp(7), dp(108))
            text: split(root.emulation_file)[1]
            shorten: True
            shorten_from: 'right'
        IconLabelButton:
            info_text: 'Zooom Out'
            color: .8,.8,.8,1
            size_hint_x: None
            width: '36dp'
            text: icon('fa-search-minus')
            on_release:
                if not root.screen_display.screen.scale < 0.10: root.screen_display.screen.scale -= 0.05
        IconLabelButton:
            info_text: 'Zooom In'
            color: .8,.8,.8,1
            text: icon('fa-search-plus')
            size_hint_x: None
            width: '36dp'
            icon_source: 'images/scale2.png'
            on_release:
                if not root.screen_display.screen.scale > 1.0: root.screen_display.screen.scale += 0.05
        IconToggleLabel:
            info_text: 'Change Orientation'
            color: .8,.8,.8,1
            text: icon('fa-mobile', 24)
            size_hint_x: None
            width: '36dp'
            angle:0
            on_state:
                root.toggle_orientation();
                if self.state=='down': self.angle=90
                else: self.angle=0
            canvas:
                Clear
                PushMatrix
                Rotate:
                    angle: self.angle
                    origin: self.center_x , self.center_y
                Rectangle:
                    size: self.texture_size
                    pos: self.center_x - 12, self.center_y - 12
                    texture: self.texture
                PopMatrix

        IconLabelButton:
            info_text: 'Change Screen'
            on_release: root.open_screen_drop(self)
            size_hint_x: None
            width: '36dp'
            text: icon('fa-ellipsis-h')

<ScreenDisplay>:
    name: 'Emulator'
    canvas.before:
        Color:
            rgba: .5,.5,.5,1
        Rectangle:
            size: self.size
            pos: self.pos

<ScreenDrop>:
    auto_width: False
    width: '260dp'
    MenuButton:
        on_release: root.screen_display.screen_name=self.children[0].text
        MenuLabel:
            text: 'IphoneScreen'
    MenuButton:
        on_release: root.screen_display.screen_name=self.children[0].text
        MenuLabel:
            text: 'IpadScreen'
    MenuButton:
        on_release: root.screen_display.screen_name=self.children[0].text
        MenuLabel:
            text: 'AndriodTabScreen'
    MenuButton:
        on_release: root.screen_display.screen_name=self.children[0].text
        MenuLabel:
            text: 'AndroidPhoneScreen'


================================================
FILE: kivystudio/components/emulator_area/screen_drop.py
================================================
from kivystudio.widgets.dropdown import DropDownBase

class ScreenDrop(DropDownBase):

    def open(self, widget, screen_display):
        self.screen_display = screen_display
        super(ScreenDrop, self).open(widget)

================================================
FILE: kivystudio/components/screens/__init__.py
================================================
import os

from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty, NumericProperty, StringProperty, ListProperty
from kivy.uix.scatter import Scatter
from kivy.lang import Builder 
from kivy.metrics import dp

# module resources
from kivy.resources import resource_add_path
resource_add_path(os.path.dirname(os.path.realpath(__file__)))

__all__ = ('IphoneScreen', 'IpadScreen', 'AndroidPhoneScreen', 'AndriodTabScreen', )

class ScreenScatter(Scatter):
    ''' base widget for screens'''

    root_widget = ObjectProperty(None, allow_none=True)

    angle = NumericProperty(0)

    orientation = StringProperty('portrait')
	
    container = ObjectProperty(None)

    border_size =ListProperty([0,0])

    border_pos =ListProperty([0,0])

    source = StringProperty('')

    def __init__(self, **k):
        super(ScreenScatter, self).__init__(**k)
        self.bind(pos=self.set_border)
        self.bind(size=self.set_border)

    def add_widget(self, widget):
        if len(self.children) > 0:
            self.root_widget = widget
            if widget.parent:
                widget.parent.remove_widget(widget)
            self.container.add_widget(widget)
        else:
            super(ScreenScatter, self).add_widget(widget)

    def clear_widgets(self):
        self.container.clear_widgets()

    def on_orientation(self, *a):
        if self.orientation == 'portrait':
            self.angle = 0
            self.container.size = (self.height,self.width)
        elif self.orientation == 'landscape':
            self.angle = -90
            self.container.size = (self.height,self.width)

        self.set_border(from_orientation=True)

    def set_border(self, *a, **k):
        if self.orientation == 'portrait':
            self.border_pos = self.get_pos 
            self.border_size = self.get_size
        elif self.orientation == 'landscape':
            self.border_pos = self.get_pos

        try:
            from_orientation = k.pop('from_orientation')
        except KeyError:
            from_orientation = False

        if from_orientation:
            self.center = self.parent.center

    def on_parent(self,*a):
        if self.parent:
            self.set_border()
            self.center = self.parent.center

    @property
    def get_pos(self):
        pass

    @property
    def get_size(self):
        pass


class IphoneScreen(ScreenScatter):
    @property
    def get_pos(self):
        pos = (-25, -dp(133))
        if self.orientation == 'landscape':
            return (-self.container.height+pos[0], pos[1])
        return pos

    @property
    def get_size(self):

        return (self.width + dp(50), self.height + dp(270))

class IpadScreen(ScreenScatter):
    @property
    def get_pos(self):
        pos = (-dp(95), -dp(77))
        if self.orientation == 'landscape':
            return (-self.container.height+pos[0], pos[1])
        return pos

    @property
    def get_size(self):
        return (self.width + dp(190), self.height + dp(154))

class AndriodTabScreen(ScreenScatter):
    @property
    def get_pos(self):
        if self.orientation == 'landscape':
            return (-self.container.height-35, -dp(51))
        return (-dp(35), -dp(51))

    @property
    def get_size(self):
        return (self.width + dp(70), self.height + dp(102))

class AndroidPhoneScreen(ScreenScatter):
    @property
    def get_pos(self):
        if self.orientation == 'landscape':
            return (-self.container.height-16.5, -dp(85.5))
        return (-dp(16.5), -dp(85.5))

    @property
    def get_size(self):
        return (self.container.width + dp(32), self.container.height + dp(152))


class ScreenContainer(FloatLayout):

    # overide
    def add_widget(self,widget):
        if len(self.children) > 1:
            screen = self.ids.inner_container.get_screen('container')
            screen.add_widget(widget)
            # self.ids.inner_container.add_widget(screen)
        else:
            super(ScreenContainer,self).add_widget(widget)

    # overide
    def clear_widgets(self):
        screen = self.ids.inner_container.get_screen('container')
        screen.clear_widgets()

Builder.load_file('screen.kv')



if __name__ == "__main__":
    from kivy.base import runTouchApp as app
    app(build)


================================================
FILE: kivystudio/components/screens/screen.kv
================================================
#: import Window kivy.core.window.Window

# 398 804
<AndroidPhoneScreen>:
    size: container.size
    container: container
    scale: 0.75
    ScreenContainer:
        id: container
        size: '320dp', '610dp'
        source: 'images/android_lolipop1.png'

# 380 743
<IphoneScreen>:
    size: container.size
    container: container
    scale: 0.75
    ScreenContainer:
        id: container
        size: ('300dp', '500dp')
        source: 'images/iphone.png'

#1271 992
<IpadScreen>:
    size: container.size
    container: container
    scale: 0.75
    ScreenContainer:
        id: container
        size: ('800dp', '512dp')
        source: 'images/ipad.png'

# 953 612
<AndriodTabScreen>:
    size: container.size
    container: container
    ScreenContainer:
        id: container
        size: ('500dp', '280dp')
        source: 'images/android_tab.png'
        my_parent: self.parent

<ScreenScatter>:
    do_rotation: False
    do_scale: False
    do_translation: False
    # scale_min: 1
    size_hint: None, None
    auto_bring_to_front: False

<ScreenContainer>:
    source: ''
    FloatLayout:
        source: root.source
        size_hint: None, None
        pos_hint: {'center_y': .5, 'center_x': .5}
        canvas.before:
            PushMatrix:
            Rotate:
                angle: root.parent.angle if self.parent else 0
                origin: (0,0,1)
            BorderImage:
                source: root.source
                size: root.parent.border_size if self.parent else (0,0)
                pos: root.parent.border_pos if self.parent else (0,0)
            PopMatrix:
    ScreenManager:
        id: inner_container
        Screen:
            name: 'container'


================================================
FILE: kivystudio/components/screens/screen_test.py
================================================
from kivy.lang import Builder
from kivy.base import runTouchApp as app
from __init__ import *

app(
Builder.load_string('''

BoxLayout:
    Carousel:
        canvas.before:
            Color:
                rgba: 1,1,1,1
            Rectangle:
                size: self.size
                pos: self.pos
        FloatLayout:
            IphoneScreen:
                on_scale: self.center=root.center
                center: root.center
                id: screen
                Button:
                    text: 'Hello'
                    font_size: '17dp'

            BoxLayout:
                pos_hint: {'y': .01, 'center_x': .5}
                size_hint: None,None
                size: '120dp', '60dp'
                Button:
                    text: '-'
                    bold: True
                    on_release:
                        if not(screen.scale < -100.0) : screen.scale -= 0.05
                Button:
                    text: '+'
                    bold: True
                    on_release:
                        if not(screen.scale > 4.0): screen.scale += 0.05

# Carousel:
#     AndroidPhoneScreen:
#         Button:
#             text: 'Hello'
#     IphoneScreen:
#         Button:
#             text: 'Hello'
#     IpadScreen:
#         Button:
#             text: 'Hello'
#     AndriodTabScreen:
#         Button:
#             text: 'Hello'

''')
)


================================================
FILE: kivystudio/components/sibebar/__init__.py
================================================
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.uix.screenmanager import ScreenManager

from kivy.lang import Builder

from kivystudio.behaviors import HoverInfoBehavior

from .fileexplorer import FileExplorer
from .gitmanager import GitManager
from .generalsearch import GeneralSearch
from kivy import properties as prop

import os
filepath = os.path.dirname(__file__)
Builder.load_file(os.path.join(filepath,'sidebar.kv'))


__all__ = ('SideBar',)

class SideBar(BoxLayout):

    def __init__(self, **k):
        super(SideBar, self).__init__(**k)
        self.fileexplorer = FileExplorer()
        self.gitmanager = GitManager()
        self.generalsearch = GeneralSearch()

    def toggle_bar(self, tab):
        if tab.state=='down':
            if len(self.children) > 1:
                self.remove_widget(self.children[0])
                self.width = '46dp'

            tab_bar = getattr(self, tab.tab_type)
            self.width += tab_bar.width
            self.add_widget(tab_bar)
        else:
            self.width = '46dp'
            if len(self.children) > 1:
                    self.remove_widget(self.children[0])
    

class SideButter(HoverInfoBehavior, ToggleButtonBehavior, Label):
    '''
    buttons on the sidebar
    '''
    def on_hover(self, *a):
        if self.hover:
            self.color = (1,1,1,1)
        elif not self.hover and self.state == 'normal':
            self.color = (.5,.5,.5,1)

        return super(SideButter, self).on_hover(*a)

class SideToggleBar(ScreenManager):
    '''ScreenManager of the sidebar
    '''



================================================
FILE: kivystudio/components/sibebar/fileexplorer/__init__.py
================================================
from kivy.uix.treeview import TreeViewLabel, TreeView
from kivy.uix.screenmanager import Screen
from kivy.uix.button import Button
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from .filewidgets import TreeViewFile
import os
from os.path import join, split, dirname

class FileView(TreeView):
    def on_touch_down(self, touch):
        node = self.get_node_at_pos(touch.pos)
        if not node:
            return
        if node.disabled:
            return
        # toggle node or selection ?
        self.toggle_node(node)
        self.select_node(node)
        # node.dispatch('on_touch_down', touch)
        return True



class FileExplorer(Screen):
    tree_view = ObjectProperty(None)

    def __init__(self, **k):
        super(FileExplorer, self).__init__(**k)
        # self.load_directory('widgets')  #test

    def load_directory(self, directory):
        '''
        load a directory all it files and subdirectory
        on the the tree view '''
        tree_view = self.tree_view
        for node in tree_view.iterate_all_nodes(node=None):
            tree_view.remove_node(node)
        dir_nodes = {}
        for dirpath, dirnames, filenames in os.walk(directory):
            try:
                top= dir_nodes[dirname(dirpath)]
            except KeyError:
                top=None

            parent = tree_view.add_node(TreeViewLabel(text=split(dirpath)[1]), top)
            dir_nodes[dirpath] = parent

            for file in filenames:
                tree_view.add_node(TreeViewFile(text=file,path=join(dirpath,file)),
                        parent)


Builder.load_string('''
<TreeViewLabel>:
    width: self.texture_size[0]
    shorten_from: 'right'
    shorten: True
    height: dp(24)
    text_size: self.width, None

<FileExplorer>:
    tree_view: tree_view
    canvas.before:
        Color:
            rgba: .1,.1,.1,1
        Rectangle:
            size: self.size
    size_hint_x: None
    width: '160dp'
    GridLayout:
        cols: 1
        Label:
            text: 'Explorer!'
            font_size: '16dp'
            size_hint_y: None
            height: '32dp'
        ScrollView:
            id: tree_scroll
            bar_width: 10
            scroll_type: ['bars', 'content']
            FileView:
                id: tree_view
                indent_level: '12dp'
                indent_start: '16dp'
                size_hint: 1, None
                height: max(tree_scroll.height, self.minimum_height)

''')


================================================
FILE: kivystudio/components/sibebar/fileexplorer/filewidgets.py
================================================
from kivy.uix.treeview import TreeViewNode, TreeViewLabel
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import ListProperty, StringProperty, BooleanProperty

from kivystudio.tools.iconfonts import icon
from kivystudio.tools import quicktools
from kivystudio.behaviors import HoverBehavior

import os

# class TreeViewFile(HoverBehavior, TreeViewNode, BoxLayout):
class TreeViewFile(TreeViewLabel):
    hover_color = ListProperty([.15,.15,.15,0])
    ' default color when the mouse hovers over the widget'

    path = StringProperty('')
    ' path to the file or directory '

    display_name = StringProperty('')
    ' name displayed for the file or directory '

    display_icon = StringProperty('')
    ''' icon displayed on the right side of the file
    or directory '''

    def on_hover(self, *a):
        if self.hover:
            self.hover_color = (.14,.14,.14,.8)
        else:
            self.hover_color = (.15,.15,.15,0)

    def on_is_selected(self, *args):
        if self.is_selected:
            quicktools.open_file(self.path)

    def on_path(self, *a):
        if os.path.isdir(self.path):
            self.display_icon = icon('fa-caret-right',16)
        elif os.path.isfile(self.path):
            self.display_icon = icon('fa-file-code-o', 16)

        self.display_name = os.path.split(self.path)[1]



Builder.load_string('''
#: import icon kivystudio.tools.iconfonts.icon
<TreeViewFile>:
    size_hint_y: None
    height: '24dp'
    canvas.before:
        Color:
            rgba: self.hover_color
        Rectangle:
            size: self.size
            pos: self.pos

<TreeViewFile1>:
    size_hint_y: None
    height: '24dp'
    canvas.before:
        Clear
        Color:
            rgba: self.hover_color
        Rectangle:
            size: self.size
            pos: self.pos
    canvas.after:
        Clear
    IconLabel:
        size_hint_x: None
        width: '24dp'
        text: root.display_icon
        color: .2,.5,1,1
    Label:
        text: root.display_name
''')


================================================
FILE: kivystudio/components/sibebar/generalsearch.py
================================================
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder

Builder.load_string('''
<GeneralSearch>:
    size_hint_x: None
    width: '160dp'
    canvas.before:
        Color:
            rgba: .1,.1,.1,1
        Rectangle:
            size: self.size
    Label:
        text: 'Search....'
''')

class GeneralSearch(Screen):
    pass



================================================
FILE: kivystudio/components/sibebar/gitmanager.py
================================================
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder

Builder.load_string('''
<GitManager>:
    size_hint_x: None
    width: '160dp'
    canvas.before:
        Color:
            rgba: .1,.1,.1,1
        Rectangle:
            size: self.size
    Label:
        text: 'Git'
''')


class GitManager(Screen):
    pass


================================================
FILE: kivystudio/components/sibebar/sidebar.kv
================================================
#: import icon kivystudio.tools.iconfonts.icon

<SideBar>:
    size_hint_x:  None
    width: '46dp'
    FloatLayout:
        size_hint_x:  None
        width: '46dp'
        canvas.before:
            Color:
                rgba: .12,.12,.12,1
            Rectangle:
                size: self.size
                pos: self.pos

        GridLayout:
            cols: 1
            size_hint_y: None
            height: self.minimum_height
            pos_hint: {'center_x': .5, 'center_y': .5}
            SideButter:
                info_text: 'Search (Ctrl+Shift+F)'
                text: '%s'%(icon('fa-search'))
                tab_type: 'generalsearch'
                on_state: root.toggle_bar(self)
            SideButter:
                id: explorer_btn
                info_text: 'Explorer (Ctrl+Shift+E)'
                text: '%s'%(icon('fa-folder-open'))
                tab_type: 'fileexplorer'
                on_state: root.toggle_bar(self)
            SideButter:
                info_text: 'Settings (Ctrl+Shift+S)'
                text: '%s'%(icon('fa-cogs'))
                tab_type: 'gitmanager'
                on_state: root.toggle_bar(self)
            SideButter:
                info_text: 'Source Control (Ctrl+Shift+G)'
                text: '%s'%(icon('fa-github'))
                tab_type: 'gitmanager'
                on_state: root.toggle_bar(self)


<SideButter>:
    size_hint: 1, None
    height: '46dp'
    font_size: '32dp'
    markup: True
    color: .5,.5,.5,1
    on_state:
        if self.state=='down': self.color=(1,1,1,1)
        else: self.color=(.5,.5,.5,1)
    group: 'side_butters'


================================================
FILE: kivystudio/components/terminal/__init__.py
================================================
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.uix.label import Label
from kivy.uix.screenmanager import Screen
from kivy import properties as prop
from kivy.clock import Clock

from kivy.lang import Builder
from kivystudio.libs.resizablebehavior import ResizableBehavior

from .logger_space import ErrorLogger

class TerminalSpace(ResizableBehavior, BoxLayout):

    manager = prop.ObjectProperty(None)
    ''' Instance of screen manager used '''

    tab_container = prop.ObjectProperty(None)
    ''' instance of a gridlayout where tha tab lays'''

    state = prop.OptionProperty('open', options=['open', 'close'])

    def __init__(self, **k):
        super(TerminalSpace, self).__init__(**k)
        self.logger = ErrorLogger()
        self.add_widget(self.logger, title='Logs')

    def add_widget(self, widget, title=''):
        if len(self.children) > 1:
            tab = TerminalTab()
            tab.text=title
            tab.name=title
            tab.bind(state=self.tab_state)
            self.tab_container.add_widget(tab)
            Clock.schedule_once(lambda dt: setattr(tab, 'state', 'down'))
            screen = Screen(name=title)
            screen.add_widget(widget)
            self.manager.add_widget(screen)
        else:
            super(TerminalSpace, self).add_widget(widget)

    def tab_state(self, tab, state):
        panel = self.manager.get_screen(tab.name).children[0]
        if state=='down':
            self.manager.current = tab.name
            for item in panel.top_pannel_items:
                self.top_pannel.add_widget(item, 2)
        else:
            for item in panel.top_pannel_items:
                if item in self.top_pannel.children:
                    self.top_pannel.remove_widget(item)

 
    def on_state(self, *args):
        if self.state=='open':
            self.height = self.norm_height
        else:
            self.height='48dp'

    def toggle_state(self):
        if self.state=='open':
            self.state='close'
        else:
            self.state='open'

class TerminalTab(ToggleButtonBehavior, Label):

    def on_state(self, *a):
        if self.state=='down':
            self.text = "[u]" + self.text + "[/u]"
            self.color = (.9,.9,.9,1)
        else:
            self.text = self.text.replace('[u]','').replace('[/u]','')
            self.color = (.5,.5,.5,1)


Builder.load_string('''
<TerminalSpace>:
    resizable_up: True
    tab_container: tab_container
    top_pannel: top_pannel
    manager: manager
    orientation: 'vertical'
    pos_hint: {'y': 0, 'center_x': .5}
    size_hint_y: None
    max_norm_height: dp(380)
    norm_height: dp(200)
    height: self.norm_height
    on_height:
        if self.height > self.max_norm_height: height_tog.state='down'
    canvas.before:
        Color:
            rgba: .12,.12,.12,1
        Rectangle:
            size: self.size
            pos: self.pos
        Color:
            rgba: 1,1,1,1
        Line:
            points: [self.x,self.top,self.right,self.top]
            width: dp(1.4)
    BoxLayout:
        size_hint_y: None
        height: '48dp'
        GridLayout:
            id: tab_container
            rows: 1
        BoxLayout:
            id: top_pannel
            size_hint_x: None
            width: self.minimum_width
            IconToggleLabel:
                id: height_tog
                icon_normal: 'fa-angle-up'
                icon_down: 'fa-angle-down'
                icon: self.icon_normal
                icon_size: 30
                size_hint_x: None
                width: '32dp'
                on_state:
                    root.state='open'
                    if self.state=='down': root.height=root.max_norm_height
                    else: root.height=root.norm_height
            IconLabelButton:
                icon: 'fa-close'
                size_hint_x: None
                width: '32dp'
                on_release: root.state='close'
    ScreenManager:
        id: manager

<TerminalTab>:
    allow_no_selection: True
    group: '__terminal_tab__'
    size_hint_x: None
    width: '94dp'
    markup: True

<TopPanelButton@IconLabelButton>:
    icon: 'fa-close'
    size_hint_x: None
    width: '32dp'

''')

================================================
FILE: kivystudio/components/terminal/command_terminal.py
================================================


================================================
FILE: kivystudio/components/terminal/logger_space.py
================================================
from kivy.uix.boxlayout import BoxLayout
from kivy import properties as prop
from kivy.lang import Builder
from kivy.factory import Factory

MAX_LOG_LINES = 260


class ErrorLogger(BoxLayout):
    
    text = prop.StringProperty()
    ''' property where the logs are stored '''

    top_pannel_items = prop.ListProperty()

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        clearbtn = Factory.TopPanelButton(icon='fa-trash-o')
        clearbtn.bind(on_release=self.clear_logs)
        self.top_pannel_items.append(clearbtn)


    def log(self, msg):
        lines = self.text.splitlines()
        if len(lines) > MAX_LOG_LINES:    # clean previous logs
            self.text = '\n'.join(lines[int(MAX_LOG_LINES/2):])
        self.text += msg+'\n'
        self.ids.scroll.scroll_y = 0

    def clear_logs(self, *args):
        self.text = ''


class InternalErrorLogger(BoxLayout):
    
    text = prop.StringProperty('Hello '*39)

Builder.load_string('''
<ErrorLogger>:
    ScrollView:
        id: scroll
		bar_width: '10dp'
        scroll_type: ['bars', 'content']
        Label:
            text: root.text
            text_size: self.width, None
            size_hint_y: None
            height: self.texture_size[1]
            valign: 'top'
            halign: 'left'
            color: .8,.8,.8,1
            markup: True
            font_size: '14sp'


''')

================================================
FILE: kivystudio/components/topmenu/__init__.py
================================================

from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.behaviors import ToggleButtonBehavior, ButtonBehavior

from kivy.clock import Clock
from kivy.lang import Builder
from kivy.properties import ListProperty, BooleanProperty, ObjectProperty

from kivystudio.behaviors import HoverBehavior
from . import dropmenu

__all__ = ('TopMenu',)


class TopMenu(GridLayout):
    
    drop_on_hover = BooleanProperty(False)
    menu = ObjectProperty()

    def __init__(self, **kwargs):
        super(TopMenu, self).__init__(**kwargs)

    # def drop(self, btn, hover):
    #     if hover and not self.dropdown.parent:
    #         self.dropdown.drop_list=btn.drop_list
    #         self.dropdown.open(btn)
    #     else:
    #         Clock.schedule_once(self.decide_drop)
    
    # def decide_drop(self, dt):
    #     if not self.dropdown.hover:
    #         self.dropdown.dismiss()

        
    def open_menu(self, widget):
        if self.menu:   
            x = self.menu.dismiss()
        menu_name = self.remove_underscore(widget.text) + 'TopMenu'
        setattr(self, 'menu_name', getattr(dropmenu, menu_name)())
        self.menu = getattr(self, 'menu_name')
        self.menu.open(self.children[widget.index])
    
    def remove_underscore(self, text):
        return  text.replace('[u]','').replace('[/u]','')

    def add_underscore(self,text):
        return "[u]" + text + "[/u]"


class TopMenuItem(HoverBehavior, ButtonBehavior, Label):

    def on_hover(self, *args):
        widget, hover = args
        if hover:
            widget.text = self.parent.add_underscore(widget.text)
            widget.color = (.1,.5,.1,1)
        else:
            widget.text = self.parent.remove_underscore(widget.text)
            widget.color = (0,0,0,1)
    

Builder.load_string('''

<TopMenu>:
    size_hint_y: None
    height: '24dp'
    rows: 1
    canvas.before:
        Color:
            rgba: .85,.85,.85,1
        Rectangle:
            size: self.size
            pos: self.pos
    TopMenuItem:
        text: 'File'
        index:4
        on_release: root.open_menu(self)

    TopMenuItem:
        text: 'Edit'
        index:3
        on_release: root.open_menu(self)

    TopMenuItem:
        text: 'View'
        index:2
        on_release: root.open_menu(self)
    
    TopMenuItem:
        text: 'Selection'
        index:1
        on_release: root.open_menu(self)
    
    TopMenuItem:
        text: 'Help'
        index:0
        on_release: root.open_menu(self)

<TopMenuItem>:
    size_hint_x: None
    width: '60dp'
    markup: True
    color: (0,0,0,1)



''')


================================================
FILE: kivystudio/components/topmenu/dropmenu.kv
================================================
#: import icon kivystudio.tools.iconfonts.icon

<FileTopMenu>:
    auto_width: False
    width: '300dp'
    MenuButton:
        on_release: root.new_file()
        MenuLabel:
            text: 'New File'
        MenuLabel:
            halign:'right'
            text: 'Ctrl+N'
            type: 'shortcut'
    MenuButton:
        on_release: root.open_file()
        MenuLabel:
            text: 'Open File'
        MenuLabel:
            halign:'right'
            text: 'Ctrl+O'
            type: 'shortcut'
    MenuButton:
        on_release: root.open_folder()
        MenuLabel:
            text: 'Open Folder'
        MenuLabel:
            halign:'right'
            text: '[Ctrl+K Ctrl+O]'
            type: 'shortcut'
    MenuButton:
        on_release: root.save()
        MenuLabel:
            text: 'Save'
        MenuLabel:
            halign:'right'
            text: 'Ctrl+S'
            type: 'shortcut'
    ToggleMenuButton:
        text: 'Auto Save'
        state: 'down' if settings.auto_save else 'normal'
        on_state:
            if self.state=='down': settings.auto_save=1
            else: settings.auto_save=0
    ToggleMenuButton:
        text: 'Auto emulation'
        state: 'down' if settings.auto_emulate else 'normal'
        on_state:
            if self.state=='down': settings.auto_emulate=1
            else: settings.auto_emulate=0
    MenuButton:
        on_release: root.save_as()
        MenuLabel:
            text: 'Save as'
        MenuLabel:
            halign:'right'
            text: 'Ctrl+Shift+S'
            type: 'shortcut'
    MenuButton:
        on_release: root.save_all()
        MenuLabel:
            text: 'Save All'
    MenuButton:
        on_release: root.exit_window()
        MenuLabel:
            text: 'Exit'
        MenuLabel:
            halign:'right'
            text: 'Ctrl+Q'
            type: 'shortcut'

<EditTopMenu>:
    auto_width: False
    width: '300dp'
    MenuButton:
        on_release: 
        MenuLabel:
            text: 'Edit File'
        MenuLabel:
            halign:'right'
            text: ''
            type: 'shortcut'

<ViewTopMenu>:
    auto_width: False
    width: '300dp'
    MenuButton:
        on_release: 
        MenuLabel:
            text: 'View File'
        MenuLabel:
            halign:'right'
            text: ''
            type: 'shortcut'

<SelectionTopMenu>:
    auto_width: False
    width: '300dp'
    MenuButton:
        on_release: 
        MenuLabel:
            text: 'Selection File'
        MenuLabel:
            halign:'right'
            text: ''
            type: 'shortcut'

<HelpTopMenu>:
    auto_width: False
    width: '300dp'
    MenuButton:
        on_release: print('help was clicked!')
        MenuLabel:
            text: 'Help'

<MenuLabel@Label>:
    text_size: self.size
    halign: 'left'
    valign: 'middle'
    padding: '20dp', 0
    type: 'text'
    color: ((0/255,0/255,0/255,.9) if self.type=='text' else (160/255,160/255,160/255,.9)) if self.parent else (236/255,243.255,1,.5)

<MenuButton>:
    size_hint_y: None
    height: '30dp'
    canvas_color: 1,1,1,1
    text_colors: ((.1,.1,.1,1), (.5,.5,.5,1))   
    on_hover:
        if self.hover: self.canvas_color = .2,.5,1,1; self.text_colors=((1,1,1,1),(1,1,1,1))
        else: self.canvas_color = 1,1,1,1; self.text_colors=((0,0,0,1), (.5,.5,.5,1))
    canvas.before:
        Color:
            rgba: self.canvas_color
        Rectangle:
            size: self.size
            pos: self.pos

<ToggleMenuButton>:
    size_hint_y: None
    height: '30dp'
    canvas_color: 1,1,1,1
    text_colors: (.1,.1,.1,1)
    text: ''
    on_hover: 
        if self.hover: self.canvas_color = .2,.5,1,1;self.state;
        else: self.canvas_color = (1,1,1,1)
    on_state: tick.state=self.state
    canvas.before:
        Color:
            rgba: self.canvas_color
        Rectangle:
            size: self.size
            pos: self.pos

    MenuLabel:
        text: root.text
    IconToggleLabel:
        size_hint_x: None
        width: '48dp'
        id: tick
        color: .2,.2,.2,1
        on_state:
            if self.state=='normal': self.text='';print(self.state)
            else: self.text = icon('fa-check', 16)
        on_parent: self.state='down'

================================================
FILE: kivystudio/components/topmenu/dropmenu.py
================================================
from kivy.uix.behaviors import ButtonBehavior, ToggleButtonBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder

from kivystudio.behaviors import HoverBehavior
from kivystudio.widgets.dropdown import DropDownBase
from kivystudio import tools

tools.load_kv(__file__,'dropmenu.kv')


class MenuButton(HoverBehavior, ButtonBehavior, BoxLayout):
    def on_hover(self, widget, hover):
        if hover: 
            self.canvas_color = .2,.5,1,1
            if len(self.children) > 1:
                    self.children[0].color = (1,1,1,1)
        else: 
            self.canvas_color = (1,1,1,1)
            if len(self.children) > 1: 
                    self.children[0].color = (.5,.5,.5,1); 
        
        

class ToggleMenuButton(HoverBehavior, ToggleButtonBehavior, BoxLayout):
    pass

class FileTopMenu(DropDownBase):
    
    def __init__(self, **k):
        super(FileTopMenu, self).__init__(**k)

    def new_file(self):
        tools.quicktools.open_new_file()

    def open_file(self):
        tools.quicktools.open_file()

    def open_folder(self):
        tools.quicktools.open_file()
    
    def open_recent(self):
        tools.quicktools.open_recent()

    def save(self):
        tools.quicktools.save()

    def save_all(self):
        tools.quicktools.save_all()

    def save_as(self):
        tools.quicktools.save_as()

    def exit_window(self):
        tools.quicktools.exit_window()
        
    
class EditTopMenu(DropDownBase):
    def __init__(self, **k):
        super(EditTopMenu, self).__init__(**k)

class ViewTopMenu(DropDownBase):
    def __init__(self, **k):
        super(ViewTopMenu, self).__init__(**k)

class SelectionTopMenu(DropDownBase):
    def __init__(self, **k):
        super(SelectionTopMenu, self).__init__(**k)

class HelpTopMenu(DropDownBase):
    def __init__(self, **k):
        super(HelpTopMenu, self).__init__(**k)
        


================================================
FILE: kivystudio/libs/__init__.py
================================================


================================================
FILE: kivystudio/libs/resizablebehavior/LICENSE
================================================
MIT License

Copyright (c) 2016 Kivy Garden

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: kivystudio/libs/resizablebehavior/README.md
================================================
# Resizable Behavior

A behavior for kivy widgets that allows them to be resized by touching/clickin on a corner and dragging.    
     
     
[Youtube demostration video](https://www.youtube.com/watch?v=8VqLV4McmK0)     
      
      
Below is also a **screenshot of the included resizable widget application**.     
     
     
![ScreenShot](https://raw.github.com/kivy-garden/garden.resizable_behavior/master/doc/screenshot.png)

## Usage    

Import and inherit like any other kivy behavior
```python
from kivy.garden.resizablebehavior import ResizableBehavior
from kivy.uix.button import Button

class ResizableButton(ResizableBehavior, Button):
    pass
```

Enable / disable resizing of a specific side in kwargs or after
```python
res_button = ResizableButton(
    resizable_left = False,
    resizable_right = True,
    resizable_up = False,
    resizable_down = True)

res_button.resizable_left = False
res_button.resizable_right = True
res_button.resizable_up = False
res_button.resizable_down = True
```

Lock / unlock resizing
```python
res_button.resize_lock = True
```
    
Adjust the size of resizable border in kwargs or after
```python
res_button = ResizableButton(resizable_border=8999)

res_button.resizable_border = 100
```

Offset the resizable_border (by default it is inside the widget) in kwargs or after     
```python
res_button = ResizableButton(resizable_border_offset=100)

#A value of resizable_border * 0.5 will center it on the edge of the ResizableButton
res_button.resizable_border_offset = res_button.resizable_border * 0.5
```

Set min and max sizes in kwargs or after     
```python
res_button = ResizableButton(
    min_resizable_width = 100,
    min_resizable_height = 101,
    max_resizable_width = 102,
    max_resizable_height = 103)
    
res_button.min_resizable_width = 100
res_button.min_resizable_height = 101
res_button.max_resizable_width = 102
res_button.max_resizable_height = 103
```

Enable / disable the cursor
```python
res_button.set_cursor_mode(0) # Disabled
res_button.set_cursor_mode(1) # Enabled
# SDL2 system cursors might be added to kivy core in future
```

Change the size of the cursor
```python
res_button.set_cursor_size(width_int, height_int)
```

Change cursor icons
```python
res_button.set_cursor_icons(
    'img/1.png',     # The horizontal icon
    'img/2.png',     # The 45 degree clockwise icon
    'img/3.png',     # The 90 degree clockwise icon
    'img/4.png')     # The 135 degree clockwise icon
```


================================================
FILE: kivystudio/libs/resizablebehavior/__init__.py
================================================
from .resize import ResizableBehavior


================================================
FILE: kivystudio/libs/resizablebehavior/modal_cursor.py
================================================
from kivy.properties import BooleanProperty, StringProperty, ListProperty
from kivy.graphics import InstructionGroup
from kivy.uix.modalview import ModalView
from kivy.graphics import Rectangle
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.metrics import dp, cm
from time import time
import os
path = os.path.split(os.path.realpath(__file__))[0]


class CursorModalView(ModalView):
    '''
    The CursorModalView is the parent of ResizeCursor
    '''

    last_opened = 0.0

    def __init__(self, **kwargs):
        super(CursorModalView, self).__init__(**kwargs)
        self.auto_dismiss = False
        self.size_hint = (None, None)
        self.background_color = (0, 0, 0, 0)
        self.pos = (-9999, -9999)
        self.cursor = ResizeCursor()
        self.add_widget(self.cursor)
        self.open()

    def open(self, *largs):
        self._window = self._search_window()
        if not self._window:
            Logger.warning('ModalView: cannot open view, no window found.')
            return
        if self.parent:
            self.parent.remove_widget(self)
        self._window.add_widget(self)

    def put_on_top(self, *args):
        self.dismiss()
        self.open()

    def on_hidden(self, val):
        # View has to be reopened to get it on top of other widgets
        timenow = time()
        if not val and timenow > self.last_opened + 1:
            self.dismiss()
            self.open()
            self.last_opened = timenow

    def on_touch_down(self, *args):
        pass

    def on_touch_up(self, *args):
        pass

    def on_touch_move(self, *args):
        pass


class ResizeCursor(Widget):
    '''
    The ResizeCursor is the mouse cursor
    '''

    hidden = BooleanProperty(True)
    '''State of cursors visibility
    It is switched to True when mouse is inside the widgets resize border
    and False when it isn't.

    :attr:`hidden` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to True.
    '''

    resize_icon_paths = ListProperty([
    '{}/resize_horizontal.png'.format(path),
    '{}/resize2.png'.format(path),
    '{}/resize_vertical.png'.format(path),
    '{}/resize1.png'.format(path),
    ])
    '''Cursor icon paths,

    :attr:`resize_icon_paths` is a :class:`~kivy.properties.ListProperty` and
    defaults to [
    'resize_horizontal.png',
    'resize2.png',
    'resize_vertical.png',
    'resize1.png',
    ]
    '''

    grabbed_by = None
    '''Object reference.
    Is used to prevent attribute changes from multiple widgets at same time.

    :attr:`grabbed_by` defaults to None.
    '''

    sides = ()
    source = StringProperty('')

    def __init__(self, **kwargs):
        super(ResizeCursor, self).__init__(**kwargs)
        self.size_hint = (None, None)
        self.pos_hint = (None, None)
        self.source = ''
        self.rect = Rectangle(pos=(-9998,-9998), size=(1, 1))
        self.size = (dp(22), dp(22))
        self.pos = [-9998, -9998]

        # Makes an instruction group with a rectangle and
        # loads an image inside it
        # Binds its properties to mouse positional changes and events triggered
        instr = InstructionGroup()
        instr.add(self.rect)
        self.canvas.after.add(instr)
        self.bind(pos=lambda obj, val: setattr(self.rect, 'pos', val))
        self.bind(source=lambda obj, val: setattr(self.rect, 'source', val))
        self.bind(hidden=lambda obj, val: self.on_mouse_move(Window.mouse_pos))
        Window.bind(mouse_pos=lambda obj, val: self.on_mouse_move(val))

    def on_size(self, obj, val):
        self.rect.size = val

    def on_hidden(self, obj, val):
        if not self.disabled:
            self.parent.on_hidden(val)
            if val:
                Window.show_cursor = True
            else:
                Window.show_cursor = False

    def on_mouse_move(self, val):
        if self.hidden or self.disabled or not self.source:
            if self.pos[0] != -9999:
                self.pos[0] = -9999
        else:
            self.pos[0] = val[0] - self.width / 2.0
            self.pos[1] = val[1] - self.height / 2.0

    def change_side(self, left, right, up, down):
        # Changes images when ResizableBehavior.hovering_resizable
        # state changes
        if self.disabled:
            return
        if not self.hidden and self.sides != (left, right, up, down):
            if left and up or right and down:
                self.source = self.resize_icon_paths[1]
            elif left and down or right and up:
                self.source = self.resize_icon_paths[3]
            elif left or right:
                self.source = self.resize_icon_paths[0]
            elif up or down:
                self.source = self.resize_icon_paths[2]
            else:
                if not any((left, right, up, down)):
                    self.pos[0] = -9999
            self.sides = (left, right, up, down)

    def grab(self, wid):
        self.grabbed_by = wid

    def ungrab(self, wid):
        if self.grabbed_by == wid:
            self.grabbed_by = None

    def on_disabled(self, obj, val):
        if not val:
            Window.show_cursor = True


================================================
FILE: kivystudio/libs/resizablebehavior/resize.py
================================================
'''
Resizable Behavior
===============

The :class:`~kivy.uix.behaviors.resize.ResizableBehavior`
`mixin <https://en.wikipedia.org/wiki/Mixin>`_ class provides Resize behavior.
When combined with a widget, dragging at the resize enabled widget edge
defined by the
:attr:`~kivy.uix.behaviors.resize.ResizableBehavior.resizable_border`
will resize the widget.

For an overview of behaviors, please refer to the :mod:`~kivy.uix.behaviors`
documentation.

Example
-------

The following example adds resize behavior to a sidebar to make it resizable

    from kivy.app import App
    from kivy.uix.floatlayout import FloatLayout
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.behaviors import ResizableBehavior
    from kivy.uix.label import Label
    from kivy.metrics import cm
    from kivy.uix.button import Button
    from kivy.graphics import *


    class ResizableSideBar(ResizableBehavior, BoxLayout):
        def __init__(self, **kwargs):
            super(ResizableSideBar, self).__init__(**kwargs)
            self.bg = Rectangle(pos=self.pos, size=self.size)
            self.resizable_right = True
            for x in range(1, 10):
                lbl = Label(size_hint=(1, None), height=(cm(1)))
                lbl.text = 'Text '+str(x)
                self.add_widget(lbl)
            self.bind(size=lambda obj, val: setattr(self.bg, 'size', val))

            instr = InstructionGroup()
            instr.add(Color(0.6, 0.6, 0.7, 1))
            instr.add(self.bg)
            self.canvas.before.add(instr)

    class Sample(FloatLayout):
        def __init__(self, **kwargs):
            super(Sample, self).__init__(**kwargs)
            sb = ResizableSideBar(orientation='vertical', size_hint=(None, 1))
            sb.width = cm(4)
            self.add_widget(sb)


    class SampleApp(App):
        def build(self):
            return Sample()


    SampleApp().run()

See :class:`~kivy.uix.behaviors.ResizableBehavior` for details.
'''

from kivy.clock import Clock
from kivy.properties import BooleanProperty, NumericProperty
from kivy.metrics import dp, cm
from .modal_cursor import CursorModalView
from kivy.core.window import Window
from kivy.logger import Logger
from kivy.app import App


__all__ = ('ResizableBehavior', )
_modalview = CursorModalView()


class ResizableBehavior(object):
    '''
    The ResizableBehavior `mixin <https://en.wikipedia.org/wiki/Mixin>`_
    class provides Resize behavior.
    When combined with a widget, dragging at the resize enabled widget edge
    defined by the
    :attr:`~kivy.uix.behaviors.resize.ResizableBehavior.resizable_border`
    will resize the widget. Please see the :mod:`drag behaviors module
    <kivy.uix.behaviors.resize>` documentation for more information.
    '''

    hovering_resizable = BooleanProperty(False)
    '''State of mouse hover.
    It is switched to True when mouse is inside the widgets resize border
    and False when it isn't.

    :attr:`hovering_resizable` is a :class:`~kivy.properties.BooleanProperty`
    and defaults to False.
    '''

    resizable_border = NumericProperty(dp(20))
    '''Widgets resizable border size on each side.
    Minimum resizing size is limited to resizable_border * 3 on all sides

    :attr:`resizable_border` is a :class:`~kivy.properties.NumericProperty` and
    defaults to 20 dp.
    '''

    resizable_border_offset = NumericProperty(0)
    '''Positive values move the resizable_border outside of the widget
    and negative values put it closer to the center of the widget.
    A value of resizable_border * 0.5 will center it on the widgets border,
    which is the most expected behavior, but can sometimes interfere with
    nearby widgets.

    :attr:`resizable_border_offset` is a
    :class:`~kivy.properties.NumericProperty` and defaults to 0.
    '''

    min_resizable_width = NumericProperty(0)
    '''Minimum width

    :attr:`min_resizable_width` is a :class:`~kivy.properties.NumericProperty`
    and defaults to 0 (disabled).
    '''

    min_resizable_height = NumericProperty(0)
    '''Minimum height

    :attr:`min_resizable_height` is a :class:`~kivy.properties.NumericProperty`
    and defaults to 0 (disabled).
    '''

    max_resizable_width = NumericProperty(0)
    '''Maximum width

    :attr:`max_resizable_width` is a :class:`~kivy.properties.NumericProperty`
    and defaults to 0 (disabled).
    '''

    max_resizable_height = NumericProperty(0)
    '''Maximum height

    :attr:`max_resizable_height` is a :class:`~kivy.properties.NumericProperty`
    and defaults to 0 (disabled).
    '''

    resizable_left = BooleanProperty(False)
    '''Enable / disable resizing on left side

    :attr:`resizable_left` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to False.
    '''

    resizable_right = BooleanProperty(False)
    '''Enable / disable resizing on right side

    :attr:`resizable_right` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to False.
    '''

    resizable_up = BooleanProperty(False)
    '''Enable / disable resizing on upper side

    :attr:`resizable_up` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to False.
    '''

    resizable_down = BooleanProperty(False)
    '''Enable / disable resizing on lower side

    :attr:`resizable_down` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to False.
    '''

    resizing_left = BooleanProperty(False)
    '''A State which is enabled/disabled depending on the position relative to
    the left resize border
    It is switched to True when mouse is inside the left resize border and
    False when it isn't.
    It adjusts the mouse cursor and manages resizing when touch is moved.

    :attr:`resizing_left` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to False.
    '''

    resizing_right = BooleanProperty(False)
    '''A State which is enabled/disabled depending on the position relative to
    the right resize border
    It is switched to True when mouse is inside the right resize border and
    False when it isn't.
    It adjusts the mouse cursor and manages resizing when touch is moved.

    :attr:`resizing_right` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to False.
    '''

    resizing_up = BooleanProperty(False)
    '''A State which is enabled/disabled depending on the position relative
    to the upper resize border
    It is switched to True when mouse is inside the upper resize border and
    False when it isn't.
    It adjusts the mouse cursor and manages resizing when touch is moved.

    :attr:`resizing_up` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to False.
    '''

    resizing_down = BooleanProperty(False)
    '''A State which is enabled/disabled depending on the position relative
    to the lower resize border
    It is switched to True when mouse is inside the lower resize border and
    False when it isn't.
    It adjusts the mouse cursor and manages resizing when touch is moved.

    :attr:`resizing_down` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to False.
    '''

    resizing = BooleanProperty(False)
    '''State of widget resizing.
    It is switched to True when a resize border is touched and back to
    False when it is released.
    It manages resizing when touch is moved.

    :attr:`resizing` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to False.
    '''

    can_move_resize = BooleanProperty(True)
    '''Move widget when resizing down or left.
    To keep position on screen in a floatlayout,
    actual postition has to be adjusted.
    Resizing and changing position variables is problematic
    inside movement restricting widgets,
    (StackLayout, BoxLayout, others) this property manages that.

    :attr:`can_move_resize` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to True.
    '''

    resize_lock = BooleanProperty(False)
    '''Enable / disable resizing

    :attr:`resize_lock` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to False.
    '''

    cursor = _modalview.cursor

    def __init__(self, **kwargs):
        super(ResizableBehavior, self).__init__(**kwargs)
        Window.bind(mouse_pos=self.on_mouse_move)
        Clock.schedule_once(_modalview.put_on_top, 0)
        self.oldpos, self.oldsize = [], []

    def on_enter_resizable(self):
        self.cursor.hidden = False

    def on_leave_resizable(self):
        self.cursor.hidden = True

    def on_mouse_move(self, _, pos):
        if self.resize_lock:
            return

        if self.cursor and self.cursor.grabbed_by is None:
            oldhover = self.hovering_resizable
            pos = self.to_widget(pos[0]+self.pos[0], pos[1]+self.pos[1])  #added by Snu
            self.hovering_resizable = self.check_resizable_side(pos[0], pos[1])
            if oldhover != self.hovering_resizable:
                if self.hovering_resizable:
                    self.on_enter_resizable()
                else:
                    self.on_leave_resizable()

    def check_resizable_side(self, x, y):
        # Add small performance increase when distance is too high
        # for possible hovering

        if abs(self.x - x) > self.width + self.resizable_border_offset:
            return False
        elif abs(self.y - y) > self.height + self.resizable_border_offset:
            return False

        startx = self.x - self.resizable_border_offset
        endx = self.right + self.resizable_border_offset
        starty = self.y - self.resizable_border_offset
        endy = self.top + self.resizable_border_offset
        if self.resizable_left:
            self.resizing_left = False
            if startx <= x <= startx + self.resizable_border:
                if starty <= y <= endy:
                    self.resizing_left = True
        if self.resizable_right and not self.resizing_left:
            self.resizing_right = False
            if endx - self.resizable_border <= x <= endx:
                if starty <= y <= endy:
                    self.resizing_right = True
        if self.resizable_up:
            self.resizing_up = False
            if endy - self.resizable_border <= y <= endy:
                if startx <= x <= endx:
                    self.resizing_up = True
        if self.resizable_down and not self.resizing_up:
            self.resizing_down = False
            if starty <= y <= starty + self.resizable_border:
                if startx <= x <= endx:
                    self.resizing_down = True

        if any((self.resizing_left, self.resizing_right,
                self.resizing_up, self.resizing_down)):
            if self.cursor:
                self.cursor.change_side(
                    self.resizing_left, self.resizing_right,
                    self.resizing_up, self.resizing_down)
            return True
        else:
            return False

    def on_touch_down(self, touch):
        if not self.hovering_resizable:
            return super(ResizableBehavior, self).on_touch_down(touch)

        if self.resize_lock:
            return super(ResizableBehavior, self).on_touch_down(touch)

        if not any([
            self.resizing_right, self.resizing_left,
            self.resizing_down, self.resizing_up
        ]):
            return super(ResizableBehavior, self).on_touch_down(touch)

        self.oldpos = list(self.pos)
        self.oldsize = list(self.size)
        self.resizing = True
        self.cursor.grab(self)
        return True

    def on_touch_move(self, touch):
        if not self.resizing:
            return super(ResizableBehavior, self).on_touch_move(touch)
        self.resize_widget(touch)

    def resize_widget(self, touch):
        rb3 = self.resizable_border * 3

        if self.resizing_right:
            if touch.pos[0] > self.pos[0] + rb3:
                self.width = touch.pos[0] - self.pos[0]

        elif self.resizing_left:
            if touch.pos[0] < self.oldpos[0] + self.oldsize[0] - rb3:
                if self.can_move_resize:
                    self.pos[0] = touch.pos[0]
                    self.width = self.oldpos[0] - touch.pos[0] + \
                        self.oldsize[0]
                else:
                    self.width = abs(touch.pos[0] - self.pos[0])
                    if self.width < rb3:
                        self.width = rb3

        if self.resizing_down:
            if touch.pos[1] < self.oldpos[1] + self.oldsize[1] - rb3:
                if self.can_move_resize:
                    self.pos[1] = touch.pos[1]
                    self.height = self.oldpos[1] - touch.pos[1] + \
                        self.oldsize[1]
                else:
                    self.height = abs(touch.pos[1] - self.pos[1])
                    if self.height < rb3:
                        self.height = rb3

        elif self.resizing_up:
            if touch.pos[1] > self.pos[1] + rb3:
                self.height = touch.pos[1] - self.pos[1]

        self.check_min_max_size(touch)
        return True

    def check_min_max_size(self, touch):
        # Resizes widgets back to min / max when smaller / bigger
        # Resets position only when it's necessary
        if self.min_resizable_width:
            if self.width < self.min_resizable_width:
                if self.pos[0] != self.oldpos[0]:
                    self.width = self.min_resizable_width
                    self.pos[0] = self.oldpos[0] + self.oldsize[0] - self.width
                else:
                    self.width = self.min_resizable_width

        if self.max_resizable_width:
            if self.width > self.max_resizable_width:
                if self.pos[0] != self.oldpos[0]:
                    self.width = self.max_resizable_width
                    self.pos[0] = self.oldpos[0] + self.oldsize[0] - self.width
                else:
                    self.width = self.max_resizable_width

        if self.min_resizable_height:
            if self.height < self.min_resizable_height:
                if self.pos[1] != self.oldpos[1]:
                    self.height = self.min_resizable_height
                    self.pos[1] = (
                        self.oldpos[1] + self.oldsize[1] - self.height)
                else:
                    self.height = self.min_resizable_height

        if self.max_resizable_height:
            if self.height > self.max_resizable_height:
                if self.pos[1] != self.oldpos[1]:
                    self.height = self.max_resizable_height
                    self.pos[1] = (
                        self.oldpos[1] + self.oldsize[1] - self.height)
                else:
                    self.height = self.max_resizable_height

    def on_touch_up(self, touch):
        if not self.resizing:
            return super(ResizableBehavior, self).on_touch_up(touch)
        self.resizing = False
        self.resizing_right = False
        self.resizing_left = False
        self.resizing_down = False
        self.resizing_up = False
        self.cursor.ungrab(self)
        self.on_mouse_move(None, touch.pos)
        return True

    def on_resize_lock(self, obj, locked):
        'Resets behavior to default values when resizing is locked'
        if locked:
            self.resizing = False
            self.resizing_right = False
            self.resizing_left = False
            self.resizing_down = False
            self.resizing_up = False
            Window.show_cursor = True
            self.cursor.ungrab(self)
            self.cursor.hidden = True

    def set_cursor_size(self, size):
        '''Default cursor size is (dp(22), dp(22)).
        Use this method to change it
        '''
        self.cursor.size = size

    def set_cursor_icons(self, hor, deg45, deg90, deg135):
        '''Change cursor icon paths.
        Function takes 4 arguments, first is horizontal,
        next 3 are turned 45, 90, 135 degrees clockwise.
        '''
        self.cursor.resize_icon_paths[0] = hor
        self.cursor.resize_icon_paths[1] = deg45
        self.cursor.resize_icon_paths[2] = deg90
        self.cursor.resize_icon_paths[3] = deg135

    def set_cursor_mode(self, value):
        '''Method takes expects one integer
        0 - Disables the resize cursor
        1 - Default mode, os cursor is hidden and replaced with resize cursor
        when mouse position enters widgets resizable_border
        '''
        if value == 0 and not self.cursor.disabled:
            self.cursor.disabled = True
        elif value == 1 and self.cursor.disabled:
            self.cursor.disabled = False


================================================
FILE: kivystudio/main.kv
================================================
#: import icon kivystudio.tools.iconfonts.icon
#: import settings kivystudio.settings.settings_obj

<Assembly>:
    orientation: 'vertical'
    TopMenu:
    BoxLayout:
        id: box


================================================
FILE: kivystudio/main.py
================================================
'''
KivyStudio main.py
entry point for the Application
'''

import sys, os
sys.path = [os.pardir] + sys.path

# from kivy.config import Config
# Config.set('modules', 'monitor', '')

from kivy.app import App
from os.path import dirname, join
from kivy.lang import Builder
from kivystudio import tools

filepath = dirname(__file__)
tools.load_kv(__file__,'main.kv')

# registering custom icons
tools.iconfonts.register('awesome_font',
    join(filepath,'resources/font-awesome.ttf'),
    join(filepath, 'resources/font-awesome.fontd'))

from kivystudio.assembler import Assembler


class KivyStudio(App):

    def build(self):
        return Assembler
    
    def run(self):
        super(KivyStudio, self).run()


studio_app = KivyStudio()

def main():
    studio_app.run()

if __name__ == "__main__":
    main()


================================================
FILE: kivystudio/parser/__init__.py
================================================
import os, sys
import traceback
from threading import Thread
from functools import partial
try:
    from importlib import reload
except:      # for py 2 compatibility
    pass

from kivy.lang import Builder
from kivy.clock import mainthread
from kivy.uix.widget import Widget
from kivy.resources import resource_add_path, resource_remove_path

from kivystudio.components.emulator_area import get_emulator_area
from kivystudio.tools.logger import Logger

def emulate_file(filename, threaded=False):
    if not filename:
        Logger.error("KivyStudio: No file selected press Ctrl-E to select file for emulation")
        return

    Logger.info("Emulator: Starting Emulation on file '{}'".format(filename))
    root=None
    if not os.path.exists(filename):
        Logger.error("KivyStudio: file {} not found".format(filename))
        return

    with open(filename) as fn:
        file_content =  fn.read()

    if app_not_run_properly(file_content):
        Logger.error("Emulator: App not run properly 'try running under if __name__ == '__main__':")
        return

    dirname=os.path.dirname(filename)
    sys.path.append(dirname)
    os.chdir(dirname)
    resource_add_path(dirname)

    get_emulator_area().screen_display.screen.clear_widgets()
    if threaded:
        Thread(target=partial(start_emulation, filename,
                            file_content, threaded=threaded)).start()
    else:
        start_emulation(filename, file_content, threaded=threaded)

def start_emulation(filename, file_content, threaded=False):
    root = None
    has_error = False
    if os.path.splitext(filename)[1] =='.kv':    # load the kivy file directly
        try:    # cacthing error with kivy files
            Builder.unload_file(filename)
            root = Builder.load_file(filename)
        except:
            has_error = True
            trace = traceback.format_exc()
            Logger.error("Emulator: {}".format(trace))

    elif os.path.splitext(filename)[1] =='.py':
        load_defualt_kv(filename, file_content)
        try:    # cahching error with python files
            root = load_py_file(filename, file_content)
        except:
            has_error = True
            trace = traceback.format_exc()
            Logger.error("Emulator: {}".format(trace))
    else:
        Logger.warning("KivyStudio: can't emulate file type {}".format(filename))

    if not root and not has_error:
        Logger.error('Emulator: No root widget found.')
    elif not isinstance(root,Widget) and not has_error:
        Logger.error("KivyStudio: root instance found = '{}' and is not a widget".format(root))
    elif root:
        if threaded:
            emulation_done(root, filename)
        else:
            get_emulator_area().screen_display.screen.add_widget(root)

    dirname=os.path.dirname(filename)
    sys.path.pop()
    resource_remove_path(dirname)

@mainthread
def emulation_done(root, filename):
    ' add root on the main thread '
    if root:
        get_emulator_area().screen_display.screen.add_widget(root)


def load_defualt_kv(filename, file_content):
    ''' load the default kivy file
        associated the the python file,
        usaully lowercase of the app class
    '''
    app_cls_name = get_app_cls_name(file_content)
    if app_cls_name is None:
        return

    kv_name = app_cls_name.lower()
    if app_cls_name.endswith('App'):
        kv_name = app_cls_name[:len(app_cls_name)-3].lower()

    if app_cls_name:
        file_dir = os.path.dirname(filename)
        kv_filename = os.path.join(file_dir, kv_name+'.kv')

        if os.path.exists(kv_filename):
            try:    # cacthing error with kivy files
                Builder.unload_file(kv_filename)
                root = Builder.load_file(kv_filename)
            except:
                trace = traceback.format_exc()
                Logger.error("KivyStudio: You kivy file has a problem")
                Logger.error("KivyStudio: {}".format(trace))


def get_app_cls_name(file_content):

    lines = file_content.splitlines()
    app_cls = get_import_as('from kivy.app import App', lines)
    if not app_cls:
    	app_cls = get_import_as('from kivymd.app import MDApp', lines)

    def check_app_cls(line):
        line = line.strip()
        return line.startswith('class') and line.endswith('(%s):'%app_cls)

    found = list(filter(check_app_cls, lines))
    if found:
        line = found[0]
        cls_name = line.split('(')[0].split(' ')[1]
        return cls_name


def get_root_from_runTouch(filename):
    with open(filename) as fn:
        text =  fn.read()

    lines = text.splitlines()
    run_touch = get_import_as('from kivy.base import runTouchApp', lines)

    def check_run_touch(line):
        line = line.strip()
        return line.startswith('%s(' % run_touch)

    found = list(filter(check_run_touch, lines))

    if found:
        line = found[0]
        root_name = line.strip().split('(')[1].split(')')[0]

        root_file = import_from_dir(filename)
        root = getattr(reload(root_file), root_name)
        return root


def load_py_file(filename, file_content):

    app_cls_name = get_app_cls_name(file_content)
    if app_cls_name:

        root_file = import_from_dir(filename)
        app_cls = getattr(reload(root_file), app_cls_name)
        root = app_cls().build()
        return root
    
    run_root = get_root_from_runTouch(filename)
    if run_root:
        return run_root


def import_from_dir(filename):
    ''' force python to import this file
    from the project_ dir'''

    dirname, file = os.path.split(filename)
    sys.path = [dirname] + sys.path

    import_word = os.path.splitext(file)[0]
    imported = __import__(import_word)
    return imported


def get_import_as(start, lines):
    ''' get the variable used by user when importing as.
        Ex: from kivy import platform
            it will return plaform
        Ex: from kivy import platform as plt
            it will return plt
    '''
    line = list(filter(lambda line: line.strip().startswith(start), lines))
    if line:
        words = line[0].split(' ')
        import_word = words[len(words)-1]
        return import_word

def app_not_run_properly(file_content):
    
    lines = file_content.splitlines()
    run_touch = get_import_as('from kivy.base import runTouchApp', lines)

    def check_run_touch(line):
        return line.startswith('%s(' % run_touch)
    found1 = list(filter(check_run_touch, lines))

    def check_run_app(line):
        app_name = get_app_cls_name(file_content)
        return line.endswith('run()') and line.startswith(app_name)
    found2 = list(filter(check_run_app, lines))

    return found1 or found2


================================================
FILE: kivystudio/resources/font-awesome.fontd
================================================
{"fa-camera": 61488, "fa-building-o": 61687, "fa-align-left": 61494, "fa-hand-o-up": 61606, "fa-external-link-square": 61772, "fa-cubes": 61875, "fa-get-pocket": 62053, "fa-share-alt-square": 61921, "fa-comment-o": 61669, "fa-thumbs-o-down": 61576, "fa-heart": 61444, "fa-file-photo-o": 61893, "fa-list": 61498, "fa-calendar-o": 61747, "fa-euro": 61779, "fa-life-buoy": 61901, "fa-stethoscope": 61681, "fa-bookmark": 61486, "fa-barcode": 61482, "fa-th-large": 61449, "fa-square": 61640, "fa-bank": 61852, "fa-times-circle-o": 61532, "fa-tachometer": 61668, "fa-bell-o": 61602, "fa-leaf": 61548, "fa-skype": 61822, "fa-certificate": 61603, "fa-car": 61881, "fa-ship": 61978, "fa-navicon": 61641, "fa-arrows-alt": 61618, "fa-server": 62003, "fa-cab": 61882, "fa-clone": 62029, "fa-wifi": 61931, "fa-meanpath": 61964, "fa-send-o": 61913, "fa-subscript": 61740, "fa-shirtsinbulk": 61972, "fa-sticky-note": 62025, "fa-road": 61464, "fa-times-circle": 61527, "fa-cart-arrow-down": 61976, "fa-safari": 62055, "fa-file-code-o": 61897, "fa-tty": 61924, "fa-list-ul": 61642, "fa-shopping-basket": 62097, "fa-arrow-circle-o-down": 61466, "fa-file-movie-o": 61896, "fa-slideshare": 61927, "fa-toggle-left": 61841, "fa-circle-o-notch": 61902, "fa-check-circle": 61528, "fa-mars-stroke-h": 61995, "fa-chevron-circle-up": 61753, "fa-circle": 61713, "fa-y-combinator-square": 61908, "fa-gbp": 61780, "fa-umbrella": 61673, "fa-sort-numeric-asc": 61794, "fa-pencil-square": 61771, "fa-soccer-ball-o": 61923, "fa-bicycle": 61958, "fa-user-times": 62005, "fa-trash-o": 61460, "fa-recycle": 61880, "fa-bell-slash-o": 61943, "fa-share-square-o": 61509, "fa-yc-square": 61908, "fa-users": 61632, "fa-yen": 61783, "fa-unlink": 61735, "fa-ban": 61534, "fa-sort-amount-asc": 61792, "fa-film": 61448, "fa-caret-down": 61655, "fa-file-text": 61788, "fa-list-alt": 61474, "fa-th-list": 61451, "fa-life-ring": 61901, "fa-filter": 61616, "fa-bluetooth-b": 62100, "fa-caret-up": 61656, "fa-sign-out": 61579, "fa-pencil": 61504, "fa-ticket": 61765, "fa-area-chart": 61950, "fa-skyatlas": 61974, "fa-opencart": 62013, "fa-hand-o-left": 61605, "fa-dedent": 61499, "fa-html5": 61755, "fa-at": 61946, "fa-dropbox": 61803, "fa-file-zip-o": 61894, "fa-long-arrow-up": 61814, "fa-stack-overflow": 61804, "fa-product-hunt": 62088, "fa-chevron-circle-left": 61751, "fa-check-square": 61770, "fa-cloud-download": 61677, "fa-caret-square-o-down": 61776, "fa-microphone-slash": 61745, "fa-folder": 61563, "fa-keyboard-o": 61724, "fa-bar-chart-o": 61568, "fa-transgender-alt": 61989, "fa-reddit-alien": 62081, "fa-openid": 61851, "fa-sort-asc": 61662, "fa-pause-circle": 62091, "fa-archive": 61831, "fa-eraser": 61741, "fa-cart-plus": 61975, "fa-inbox": 61468, "fa-truck": 61649, "fa-file-word-o": 61890, "fa-pied-piper-alt": 61864, "fa-object-ungroup": 62024, "fa-phone-square": 61592, "fa-eye": 61550, "fa-sun-o": 61829, "fa-folder-o": 61716, "fa-rebel": 61904, "fa-bars": 61641, "fa-cc-paypal": 61940, "fa-simplybuilt": 61973, "fa-won": 61785, "fa-hand-lizard-o": 62040, "fa-balance-scale": 62030, "fa-frown-o": 61721, "fa-repeat": 61470, "fa-arrow-circle-o-up": 61467, "fa-taxi": 61882, "fa-map-o": 62072, "fa-question": 61736, "fa-meh-o": 61722, "fa-terminal": 61728, "fa-caret-left": 61657, "fa-stop": 61517, "fa-tv": 62060, "fa-spoon": 61873, "fa-th": 61450, "fa-files-o": 61637, "fa-pause": 61516, "fa-mail-reply": 61714, "fa-cutlery": 61685, "fa-linux": 61820, "fa-battery-empty": 62020, "fa-hourglass-start": 62033, "fa-pause-circle-o": 62092, "fa-arrow-circle-left": 61608, "fa-shopping-cart": 61562, "fa-map-pin": 62070, "fa-youtube-play": 61802, "fa-drupal": 61865, "fa-bed": 62006, "fa-battery-quarter": 62019, "fa-weixin": 61911, "fa-exchange": 61676, "fa-gg-circle": 62049, "fa-angle-double-up": 61698, "fa-forward": 61518, "fa-hand-pointer-o": 62042, "fa-cog": 61459, "fa-reddit-square": 61858, "fa-arrow-circle-down": 61611, "fa-battery-three-quarters": 62017, "fa-venus-double": 61990, "fa-tumblr-square": 61812, "fa-angellist": 61961, "fa-toggle-off": 61956, "fa-info": 61737, "fa-eyedropper": 61947, "fa-behance": 61876, "fa-map-signs": 62071, "fa-file-audio-o": 61895, "fa-gavel": 61667, "fa-glass": 61440, "fa-hand-o-right": 61604, "fa-cube": 61874, "fa-pinterest-square": 61651, "fa-cc-stripe": 61941, "fa-battery-full": 62016, "fa-lightbulb-o": 61675, "fa-caret-square-o-up": 61777, "fa-video-camera": 61501, "fa-jsfiddle": 61900, "fa-long-arrow-left": 61815, "fa-caret-right": 61658, "fa-volume-down": 61479, "fa-tags": 61484, "fa-arrow-up": 61538, "fa-folder-open-o": 61717, "fa-shield": 61746, "fa-dashcube": 61968, "fa-rotate-right": 61470, "fa-angle-double-down": 61699, "fa-facebook": 61594, "fa-hand-scissors-o": 62039, "fa-scribd": 62090, "fa-sort": 61660, "fa-twitter-square": 61569, "fa-power-off": 61457, "fa-gratipay": 61828, "fa-mars": 61986, "fa-header": 61916, "fa-user": 61447, "fa-exclamation-circle": 61546, "fa-level-down": 61769, "fa-vine": 61898, "fa-tint": 61507, "fa-wordpress": 61850, "fa-expeditedssl": 62014, "fa-slack": 61848, "fa-cut": 61636, "fa-key": 61572, "fa-tripadvisor": 62050, "fa-opera": 62058, "fa-object-group": 62023, "fa-heartbeat": 61982, "fa-laptop": 61705, "fa-bomb": 61922, "fa-angle-double-left": 61696, "fa-quote-left": 61709, "fa-paw": 61872, "fa-reddit": 61857, "fa-cc-visa": 61936, "fa-circle-o": 61708, "fa-odnoklassniki-square": 62052, "fa-cc-jcb": 62027, "fa-mail-reply-all": 61730, "fa-lastfm": 61954, "fa-group": 61632, "fa-microphone": 61744, "fa-camera-retro": 61571, "fa-maxcdn": 61750, "fa-buysellads": 61965, "fa-play-circle-o": 61469, "fa-ge": 61905, "fa-i-cursor": 62022, "fa-percent": 62101, "fa-photo": 61502, "fa-toggle-on": 61957, "fa-fax": 61868, "fa-code-fork": 61734, "fa-y-combinator": 62011, "fa-map": 62073, "fa-try": 61845, "fa-diamond": 61977, "fa-neuter": 61996, "fa-quote-right": 61710, "fa-mobile": 61707, "fa-bell-slash": 61942, "fa-trademark": 62044, "fa-file-video-o": 61896, "fa-mixcloud": 62089, "fa-plus-circle": 61525, "fa-folder-open": 61564, "fa-css3": 61756, "fa-fast-forward": 61520, "fa-toggle-down": 61776, "fa-credit-card": 61597, "fa-caret-square-o-left": 61841, "fa-hourglass-3": 62035, "fa-hourglass-2": 62034, "fa-hourglass-1": 62033, "fa-angle-down": 61703, "fa-edge": 62082, "fa-trello": 61825, "fa-train": 62008, "fa-sheqel": 61963, "fa-file-powerpoint-o": 61892, "fa-arrow-left": 61536, "fa-television": 62060, "fa-life-saver": 61901, "fa-copy": 61637, "fa-sticky-note-o": 62026, "fa-mars-double": 61991, "fa-star-half-o": 61731, "fa-black-tie": 62078, "fa-chevron-up": 61559, "fa-chevron-down": 61560, "fa-fonticons": 62080, "fa-check-circle-o": 61533, "fa-plug": 61926, "fa-deviantart": 61885, "fa-dashboard": 61668, "fa-hourglass-o": 62032, "fa-plus": 61543, "fa-cc-discover": 61938, "fa-hashtag": 62098, "fa-gamepad": 61723, "fa-rub": 61784, "fa-history": 61914, "fa-sign-in": 61584, "fa-sort-amount-desc": 61793, "fa-rss-square": 61763, "fa-transgender": 61988, "fa-graduation-cap": 61853, "fa-whatsapp": 62002, "fa-mercury": 61987, "fa-amazon": 62064, "fa-medkit": 61690, "fa-bug": 61832, "fa-twitch": 61928, "fa-file-archive-o": 61894, "fa-forumbee": 61969, "fa-cny": 61783, "fa-arrows": 61511, "fa-map-marker": 61505, "fa-wheelchair": 61843, "fa-plus-square": 61694, "fa-male": 61827, "fa-institution": 61852, "fa-envelope-o": 61443, "fa-xing-square": 61801, "fa-step-forward": 61521, "fa-stumbleupon-circle": 61859, "fa-pencil-square-o": 61508, "fa-weibo": 61834, "fa-gear": 61459, "fa-rocket": 61749, "fa-bluetooth": 62099, "fa-search-plus": 61454, "fa-stop-circle": 62093, "fa-bell": 61683, "fa-undo": 61666, "fa-fast-backward": 61513, "fa-sliders": 61918, "fa-hotel": 62006, "fa-steam": 61878, "fa-hand-paper-o": 62038, "fa-circle-thin": 61915, "fa-share-square": 61773, "fa-asterisk": 61545, "fa-arrow-down": 61539, "fa-random": 61556, "fa-share-alt": 61920, "fa-beer": 61692, "fa-exclamation-triangle": 61553, "fa-commenting": 62074, "fa-volume-up": 61480, "fa-flag-checkered": 61726, "fa-ellipsis-h": 61761, "fa-hand-spock-o": 62041, "fa-crop": 61733, "fa-paragraph": 61917, "fa-battery-3": 62017, "fa-ellipsis-v": 61762, "fa-gift": 61547, "fa-strikethrough": 61644, "fa-motorcycle": 61980, "fa-life-bouy": 61901, "fa-reply-all": 61730, "fa-paper-plane-o": 61913, "fa-star-half": 61577, "fa-download": 61465, "fa-usb": 62087, "fa-chevron-circle-down": 61754, "fa-calculator": 61932, "fa-gg": 62048, "fa-contao": 62061, "fa-hand-o-down": 61607, "fa-leanpub": 61970, "fa-star-o": 61446, "fa-pie-chart": 61952, "fa-venus": 61985, "fa-inr": 61782, "fa-rupee": 61782, "fa-eur": 61779, "fa-tumblr": 61811, "fa-indent": 61500, "fa-mars-stroke-v": 61994, "fa-git": 61907, "fa-envelope": 61664, "fa-bitbucket-square": 61810, "fa-legal": 61667, "fa-gittip": 61828, "fa-chevron-left": 61523, "fa-cogs": 61573, "fa-arrow-circle-o-left": 61840, "fa-briefcase": 61617, "fa-user-md": 61680, "fa-angle-left": 61700, "fa-yc": 62011, "fa-long-arrow-right": 61816, "fa-coffee": 61684, "fa-copyright": 61945, "fa-toggle-up": 61777, "fa-support": 61901, "fa-youtube-square": 61798, "fa-cc-mastercard": 61937, "fa-unsorted": 61660, "fa-compress": 61542, "fa-android": 61819, "fa-font": 61489, "fa-arrow-right": 61537, "fa-minus": 61544, "fa-bitbucket": 61809, "fa-facebook-f": 61594, "fa-subway": 62009, "fa-headphones": 61477, "fa-paperclip": 61638, "fa-industry": 62069, "fa-rmb": 61783, "fa-minus-square": 61766, "fa-moon-o": 61830, "fa-file-excel-o": 61891, "fa-line-chart": 61953, "fa-fighter-jet": 61691, "fa-sort-alpha-desc": 61790, "fa-spotify": 61884, "fa-star-half-empty": 61731, "fa-share": 61540, "fa-comment": 61557, "fa-mars-stroke": 61993, "fa-stack-exchange": 61837, "fa-pied-piper": 61863, "fa-building": 61869, "fa-thumbs-up": 61796, "fa-chevron-circle-right": 61752, "fa-adjust": 61506, "fa-sellsy": 61971, "fa-paypal": 61933, "fa-signal": 61458, "fa-sort-up": 61662, "fa-shekel": 61963, "fa-codiepie": 62084, "fa-calendar-plus-o": 62065, "fa-digg": 61862, "fa-save": 61639, "fa-shopping-bag": 62096, "fa-eye-slash": 61552, "fa-backward": 61514, "fa-hand-stop-o": 62038, "fa-mail-forward": 61540, "fa-link": 61633, "fa-table": 61646, "fa-tag": 61483, "fa-turkish-lira": 61845, "fa-envelope-square": 61849, "fa-optin-monster": 62012, "fa-money": 61654, "fa-instagram": 61805, "fa-volume-off": 61478, "fa-unlock-alt": 61758, "fa-minus-circle": 61526, "fa-hacker-news": 61908, "fa-hand-grab-o": 62037, "fa-adn": 61808, "fa-list-ol": 61643, "fa-magnet": 61558, "fa-calendar-minus-o": 62066, "fa-linkedin": 61665, "fa-paper-plane": 61912, "fa-mouse-pointer": 62021, "fa-reply": 61714, "fa-smile-o": 61720, "fa-hourglass-half": 62034, "fa-behance-square": 61877, "fa-twitter": 61593, "fa-expand": 61541, "fa-flask": 61635, "fa-flash": 61671, "fa-trophy": 61585, "fa-long-arrow-down": 61813, "fa-odnoklassniki": 62051, "fa-angle-double-right": 61697, "fa-home": 61461, "fa-bolt": 61671, "fa-italic": 61491, "fa-comments": 61574, "fa-commenting-o": 62075, "fa-toggle-right": 61778, "fa-file": 61787, "fa-bold": 61490, "fa-internet-explorer": 62059, "fa-cc-amex": 61939, "fa-sort-down": 61661, "fa-anchor": 61757, "fa-medium": 62010, "fa-calendar": 61555, "fa-superscript": 61739, "fa-wechat": 61911, "fa-file-text-o": 61686, "fa-cloud": 61634, "fa-user-plus": 62004, "fa-times": 61453, "fa-street-view": 61981, "fa-trash": 61944, "fa-paste": 61674, "fa-ambulance": 61689, "fa-suitcase": 61682, "fa-binoculars": 61925, "fa-user-secret": 61979, "fa-sort-alpha-asc": 61789, "fa-picture-o": 61502, "fa-cc": 61962, "fa-calendar-times-o": 62067, "fa-phone": 61589, "fa-github-square": 61586, "fa-hand-peace-o": 62043, "fa-windows": 61818, "fa-500px": 62062, "fa-calendar-check-o": 62068, "fa-clock-o": 61463, "fa-connectdevelop": 61966, "fa-text-height": 61492, "fa-houzz": 62076, "fa-align-right": 61496, "fa-angle-right": 61701, "fa-hand-rock-o": 62037, "fa-heart-o": 61578, "fa-steam-square": 61879, "fa-underline": 61645, "fa-file-image-o": 61893, "fa-bus": 61959, "fa-play-circle": 61764, "fa-plus-square-o": 61846, "fa-rss": 61598, "fa-battery-0": 62020, "fa-battery-1": 62019, "fa-battery-2": 62018, "fa-google-plus-square": 61652, "fa-battery-4": 62016, "fa-caret-square-o-right": 61778, "fa-child": 61870, "fa-space-shuttle": 61847, "fa-pinterest-p": 62001, "fa-outdent": 61499, "fa-lock": 61475, "fa-dot-circle-o": 61842, "fa-git-square": 61906, "fa-clipboard": 61674, "fa-mortar-board": 61853, "fa-university": 61852, "fa-github": 61595, "fa-jpy": 61783, "fa-vk": 61833, "fa-print": 61487, "fa-code": 61729, "fa-book": 61485, "fa-pinterest": 61650, "fa-youtube": 61799, "fa-fire": 61549, "fa-hourglass-end": 62035, "fa-tasks": 61614, "fa-xing": 61800, "fa-ioxhost": 61960, "fa-play": 61515, "fa-flag-o": 61725, "fa-battery-half": 62018, "fa-search": 61442, "fa-genderless": 61997, "fa-renren": 61835, "fa-database": 61888, "fa-plane": 61554, "fa-sort-numeric-desc": 61795, "fa-intersex": 61988, "fa-tree": 61883, "fa-scissors": 61636, "fa-question-circle": 61529, "fa-close": 61453, "fa-crosshairs": 61531, "fa-apple": 61817, "fa-wrench": 61613, "fa-sitemap": 61672, "fa-language": 61867, "fa-automobile": 61881, "fa-hourglass": 62036, "fa-bar-chart": 61568, "fa-file-o": 61462, "fa-krw": 61785, "fa-soundcloud": 61886, "fa-floppy-o": 61639, "fa-upload": 61587, "fa-arrow-circle-o-right": 61838, "fa-info-circle": 61530, "fa-cloud-upload": 61678, "fa-facebook-official": 62000, "fa-search-minus": 61456, "fa-music": 61441, "fa-stumbleupon": 61860, "fa-star-half-full": 61731, "fa-file-picture-o": 61893, "fa-image": 61502, "fa-mobile-phone": 61707, "fa-dollar": 61781, "fa-google-wallet": 61934, "fa-feed": 61598, "fa-vimeo": 62077, "fa-futbol-o": 61923, "fa-hdd-o": 61600, "fa-remove": 61453, "fa-bullseye": 61760, "fa-location-arrow": 61732, "fa-female": 61826, "fa-joomla": 61866, "fa-thumb-tack": 61581, "fa-align-justify": 61497, "fa-external-link": 61582, "fa-arrow-circle-right": 61609, "fa-level-up": 61768, "fa-gears": 61573, "fa-foursquare": 61824, "fa-venus-mars": 61992, "fa-yelp": 61929, "fa-exclamation": 61738, "fa-star": 61445, "fa-google-plus": 61653, "fa-ra": 61904, "fa-h-square": 61693, "fa-lastfm-square": 61955, "fa-registered": 62045, "fa-edit": 61508, "fa-unlock": 61596, "fa-sort-desc": 61661, "fa-tencent-weibo": 61909, "fa-thumbs-down": 61797, "fa-eject": 61522, "fa-linkedin-square": 61580, "fa-pagelines": 61836, "fa-chain": 61633, "fa-yahoo": 61854, "fa-send": 61912, "fa-check": 61452, "fa-compass": 61774, "fa-viacoin": 62007, "fa-angle-up": 61702, "fa-wikipedia-w": 62054, "fa-qrcode": 61481, "fa-paint-brush": 61948, "fa-bookmark-o": 61591, "fa-usd": 61781, "fa-chevron-right": 61524, "fa-ruble": 61784, "fa-delicious": 61861, "fa-btc": 61786, "fa-lemon-o": 61588, "fa-arrow-circle-up": 61610, "fa-comments-o": 61670, "fa-chrome": 62056, "fa-check-square-o": 61510, "fa-ils": 61963, "fa-birthday-cake": 61949, "fa-tablet": 61706, "fa-codepen": 61899, "fa-stop-circle-o": 62094, "fa-chain-broken": 61735, "fa-puzzle-piece": 61742, "fa-creative-commons": 62046, "fa-spinner": 61712, "fa-newspaper-o": 61930, "fa-globe": 61612, "fa-firefox": 62057, "fa-vimeo-square": 61844, "fa-magic": 61648, "fa-align-center": 61495, "fa-warning": 61553, "fa-desktop": 61704, "fa-cc-diners-club": 62028, "fa-thumbs-o-up": 61575, "fa-dribbble": 61821, "fa-square-o": 61590, "fa-columns": 61659, "fa-flickr": 61806, "fa-retweet": 61561, "fa-flag": 61476, "fa-google": 61856, "fa-file-sound-o": 61895, "fa-bitcoin": 61786, "fa-text-width": 61493, "fa-arrows-v": 61565, "fa-hospital-o": 61688, "fa-step-backward": 61512, "fa-bullhorn": 61601, "fa-fire-extinguisher": 61748, "fa-arrows-h": 61566, "fa-refresh": 61473, "fa-fort-awesome": 62086, "fa-github-alt": 61715, "fa-reorder": 61641, "fa-modx": 62085, "fa-facebook-square": 61570, "fa-empire": 61905, "fa-credit-card-alt": 62083, "fa-qq": 61910, "fa-rouble": 61784, "fa-minus-square-o": 61767, "fa-rotate-left": 61666, "fa-file-pdf-o": 61889}

================================================
FILE: kivystudio/settings.py
================================================
import os
from kivy.event import EventDispatcher
from kivy.config import ConfigParser
from kivy.properties import ConfigParserProperty
from kivystudio.tools import get_user_data_dir
from kivy.core.window  import Window

Window.maximize()

config = ConfigParser('kivystudio')
config.adddefaultsection('application')
config.adddefaultsection('graphics')
config_file = os.path.join(get_user_data_dir('kivystudio'), 'config.ini')
config.read(config_file)

class SettingDispatcher(EventDispatcher):

    auto_save = ConfigParserProperty(0, 'application', 'auto_save', 'kivystudio',val_type=int)

    auto_emulate = ConfigParserProperty(1, 'application', 'auto_emulate', 'kivystudio',val_type=int)

    dpi_scale = ConfigParserProperty(1, 'graphics', 'dpi_scale', 'kivystudio',val_type=float)

settings_obj = SettingDispatcher()


================================================
FILE: kivystudio/tools/__init__.py
================================================

import os
from os.path import dirname, join, exists, expanduser
from kivy import platform
from kivy.lang import Builder
from kivy.core.window import Window

def set_auto_mouse_position(widget):
    ''' functions trys to position widget
    automaticaly on the mouse pos'''

    if Window.mouse_pos[0]+widget.width > Window.width:
        widget.x = Window.mouse_pos[0]

    else:
        widget.x = Window.mouse_pos[0]
    
    if (Window.mouse_pos[1]+widget.height > Window.height):
        widget.top = Window.mouse_pos[1]-16
    else:
        widget.top = Window.mouse_pos[1]-16

def load_kv(filepath, file):
	''' load a kivy file from the current
		directory of the file calling this func
		where filepath is __file__ and file is a kv file''' 
	filepath = dirname(filepath)
	Builder.load_file(join(filepath, file))


def get_user_data_dir(name):
    # Determine and return the user_data_dir.
    data_dir = ""
    if platform == 'ios':
        raise NotImplemented()
    elif platform == 'android':
        raise NotImplemented()
    elif platform == 'win':
        data_dir = os.path.join(os.environ['APPDATA'], name)
    elif platform == 'macosx':
        data_dir = '~/Library/Application Support/{}'.format(name)
        data_dir = expanduser(data_dir)
    else:  # _platform == 'linux' or anything else...:
        data_dir = os.environ.get('XDG_CONFIG_HOME', '~/.config')
        data_dir = expanduser(join(data_dir, name))
    if not exists(data_dir):
        os.mkdir(data_dir)
    return data_dir


================================================
FILE: kivystudio/tools/iconfonts/LICENSE
================================================
Copyright (c) 2010-2015 Kivy Team and other contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: kivystudio/tools/iconfonts/README.md
================================================
![Screenshot](https://github.com/jeysonmc/garden.iconfonts/blob/master/screenshot.png "Scrennshot")


Kivy-iconfonts
==============

Simple helper functions to make easier to use icon fonts in Labels and derived widgets

Usage
=====

Once you have a .fontd file (see below) for your ttf iconfont generated you can use it like this:

In your main.py register your font:
```python
    iconfonts.register('default_font', 'iconfont_sample.ttf', 'iconfont_sample.fontd')
```

In your kv file or string:
```yaml
    #: import icon kivy.garden.iconfonts.icon
    Button:
        markup: True # Always turn markup on
        text: "%s"%(icon('icon-comment'))
```
See __init__.py for another example.

Generating a fontd file
=====================

A .fontd file is just a python dictionary filled with icon_code: unicode_value entries. This information is extracted from a css file (all iconfonts packages I've seen have one).

**Example with Font-Awesome**

1. Download Font-Awesome (http://fortawesome.github.io/Font-Awesome/)
2. Copy both the TTF and CSS files (fonts/fontawesome-webfont.ttf and css/font-awesome.css) to your project
3. Create and execute a python script to generate your fontd file:
```python
iconfonts.create_fontdict_file('font-awesome.css', 'font-awesome.fontd')
```
4. If everything went well your font dictionary file exists. You can delete the css file (font-awesome.css)


More IconFonts
==============
- http://fortawesome.github.io/Font-Awesome/
- http://fontello.com/
- https://icomoon.io

LICENSE
=======

MIT (except sample font that I got from http://fontello.com)


Credits
=======

Author: Jeyson Molina <jeyson.mco@gmail.com>


================================================
FILE: kivystudio/tools/iconfonts/__init__.py
================================================
"""
Kivy-iconfonts
==============

Simple helper functions to make easier to use icon fonts in Labels and derived
widgets.
"""
from .iconfonts import *


if __name__ == '__main__':
    from kivy.lang import Builder
    from kivy.base import runTouchApp
    from kivy.animation import Animation
    from os.path import join, dirname

    kv = """
#: import icon iconfonts.icon
BoxLayout:
    Button:
        markup: True
        text: "%s"%(icon('icon-comment', 32))
    Button:
        markup: True
        text: "%s"%(icon('icon-emo-happy', 64))

    Button:
        markup: True
        text: "%s Text"%(icon('icon-plus-circled', 24))

    Button:
        markup: True
        text: "%s"%(icon('icon-doc-text-inv', 64, 'ff3333'))

    Label:
        id: _anim
        markup: True
        text: "%s"%(icon('icon-spin6', 32))
        font_color: 1, 0, 0, 1
        p: 0
        canvas:
            Clear
            PushMatrix
            Rotate:
                angle: -self.p
                origin: self.center_x , self.center_y
            Rectangle:
                size: (32, 32)
                pos: self.center_x - 16, self.center_y - 16
                texture: self.texture
            PopMatrix
    """

    register('default_font', 'iconfont_sample.ttf',
             join(dirname(__file__), 'iconfont_sample.fontd'))

    root = Builder.load_string(kv)
    an = Animation(p=360, duration=2) + Animation(p=0, duration=0)
    an.repeat = True
    an.start(root.ids['_anim'])
    runTouchApp(root)


================================================
FILE: kivystudio/tools/iconfonts/iconfonts.py
================================================
import re
import json
from collections import OrderedDict
from kivy.compat import PY2

_register = OrderedDict()

if not PY2:
    unichr = chr


def register(name, ttf_fname, fontd_fname):
    """Register an Iconfont
    :param name: font name identifier.
    :param ttf_fname: ttf filename (path)
    :param fontd_fname: fontdic filename. (See create_fontdic)
    """
    with open(fontd_fname, 'r') as f:
        fontd = json.loads(f.read())
        _register[name] = ttf_fname, fontd_fname, fontd


def icon(code, size=None, color=None, font_name=None):
    """ Gets an icon from iconfont.
    :param code: Icon codename (ex: 'icon-name')
    :param size: Icon size
    :param color: Icon color
    :param font_name: Registered font name. If None first one is used.
    :returns: icon text (with markups)
    """
    font = list(_register.keys())[0] if font_name is None else font_name
    font_data = _register[font]
    s = "[font=%s]%s[/font]" % (font_data[0], unichr(font_data[2][code]))
    if size is not None:
        s = "[size=%s]%s[/size]" % (size, s)
    if color is not None:
        s = "[color=%s]%s[/color]" % (color, s)

    return s


def create_fontdict_file(css_fname, output_fname):
    """Creates a font dictionary file. Basically creates a dictionary filled
    with icon_code: unicode_value entries
    obtained from a CSS file.
    :param css_fname: CSS filename where font's rules are declared.
    :param output_fname: Fontd file destination
    """
    with open(css_fname, 'r') as f:
        data = f.read()
        res = _parse(data)
        with open(output_fname, 'w') as o:
            o.write(json.dumps(res))
        return res


def _parse(data):
    # find start index where icons rules start
    pat_start = re.compile('}.+content:', re.DOTALL)
    rules_start = [x for x in re.finditer(pat_start, data)][0].start()
    data = data[rules_start:]  # crop data
    data = data.replace("\\", '0x')  # replace unicodes
    data = data.replace("'", '"')  # replace quotes
    # iterate rule indices and extract value
    pat_keys = re.compile('[a-zA-Z0-9_-]+:before')
    res = dict()
    for i in re.finditer(pat_keys, data):
        start = i.start()
        end = data.find('}', start)
        key = i.group().replace(':before', '')
        try:
            value = int(data[start:end].split('"')[1], 0)
        except (IndexError, ValueError):
            continue
        res[key] = value
    return res



================================================
FILE: kivystudio/tools/iconfonts/test/font-awesome.css
================================================
/*!
 *  Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome
 *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
 */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.5.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.5.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.5.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.5.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}


================================================
FILE: kivystudio/tools/iconfonts/test/font-awesome.fontd
================================================
{"fa-camera": 61488, "fa-building-o": 61687, "fa-align-left": 61494, "fa-hand-o-up": 61606, "fa-external-link-square": 61772, "fa-cubes": 61875, "fa-get-pocket": 62053, "fa-share-alt-square": 61921, "fa-comment-o": 61669, "fa-thumbs-o-down": 61576, "fa-heart": 61444, "fa-file-photo-o": 61893, "fa-list": 61498, "fa-calendar-o": 61747, "fa-euro": 61779, "fa-life-buoy": 61901, "fa-stethoscope": 61681, "fa-bookmark": 61486, "fa-barcode": 61482, "fa-th-large": 61449, "fa-square": 61640, "fa-bank": 61852, "fa-times-circle-o": 61532, "fa-tachometer": 61668, "fa-bell-o": 61602, "fa-leaf": 61548, "fa-skype": 61822, "fa-certificate": 61603, "fa-car": 61881, "fa-ship": 61978, "fa-navicon": 61641, "fa-arrows-alt": 61618, "fa-server": 62003, "fa-cab": 61882, "fa-clone": 62029, "fa-wifi": 61931, "fa-meanpath": 61964, "fa-send-o": 61913, "fa-subscript": 61740, "fa-shirtsinbulk": 61972, "fa-sticky-note": 62025, "fa-road": 61464, "fa-times-circle": 61527, "fa-cart-arrow-down": 61976, "fa-safari": 62055, "fa-file-code-o": 61897, "fa-tty": 61924, "fa-list-ul": 61642, "fa-shopping-basket": 62097, "fa-arrow-circle-o-down": 61466, "fa-file-movie-o": 61896, "fa-slideshare": 61927, "fa-toggle-left": 61841, "fa-circle-o-notch": 61902, "fa-check-circle": 61528, "fa-mars-stroke-h": 61995, "fa-chevron-circle-up": 61753, "fa-circle": 61713, "fa-y-combinator-square": 61908, "fa-gbp": 61780, "fa-umbrella": 61673, "fa-sort-numeric-asc": 61794, "fa-pencil-square": 61771, "fa-soccer-ball-o": 61923, "fa-bicycle": 61958, "fa-user-times": 62005, "fa-trash-o": 61460, "fa-recycle": 61880, "fa-bell-slash-o": 61943, "fa-share-square-o": 61509, "fa-yc-square": 61908, "fa-users": 61632, "fa-yen": 61783, "fa-unlink": 61735, "fa-ban": 61534, "fa-sort-amount-asc": 61792, "fa-film": 61448, "fa-caret-down": 61655, "fa-file-text": 61788, "fa-list-alt": 61474, "fa-th-list": 61451, "fa-life-ring": 61901, "fa-filter": 61616, "fa-bluetooth-b": 62100, "fa-caret-up": 61656, "fa-sign-out": 61579, "fa-pencil": 61504, "fa-ticket": 61765, "fa-area-chart": 61950, "fa-skyatlas": 61974, "fa-opencart": 62013, "fa-hand-o-left": 61605, "fa-dedent": 61499, "fa-html5": 61755, "fa-at": 61946, "fa-dropbox": 61803, "fa-file-zip-o": 61894, "fa-long-arrow-up": 61814, "fa-stack-overflow": 61804, "fa-product-hunt": 62088, "fa-chevron-circle-left": 61751, "fa-check-square": 61770, "fa-cloud-download": 61677, "fa-caret-square-o-down": 61776, "fa-microphone-slash": 61745, "fa-folder": 61563, "fa-keyboard-o": 61724, "fa-bar-chart-o": 61568, "fa-transgender-alt": 61989, "fa-reddit-alien": 62081, "fa-openid": 61851, "fa-sort-asc": 61662, "fa-pause-circle": 62091, "fa-archive": 61831, "fa-eraser": 61741, "fa-cart-plus": 61975, "fa-inbox": 61468, "fa-truck": 61649, "fa-file-word-o": 61890, "fa-pied-piper-alt": 61864, "fa-object-ungroup": 62024, "fa-phone-square": 61592, "fa-eye": 61550, "fa-sun-o": 61829, "fa-folder-o": 61716, "fa-rebel": 61904, "fa-bars": 61641, "fa-cc-paypal": 61940, "fa-simplybuilt": 61973, "fa-won": 61785, "fa-hand-lizard-o": 62040, "fa-balance-scale": 62030, "fa-frown-o": 61721, "fa-repeat": 61470, "fa-arrow-circle-o-up": 61467, "fa-taxi": 61882, "fa-map-o": 62072, "fa-question": 61736, "fa-meh-o": 61722, "fa-terminal": 61728, "fa-caret-left": 61657, "fa-stop": 61517, "fa-tv": 62060, "fa-spoon": 61873, "fa-th": 61450, "fa-files-o": 61637, "fa-pause": 61516, "fa-mail-reply": 61714, "fa-cutlery": 61685, "fa-linux": 61820, "fa-battery-empty": 62020, "fa-hourglass-start": 62033, "fa-pause-circle-o": 62092, "fa-arrow-circle-left": 61608, "fa-shopping-cart": 61562, "fa-map-pin": 62070, "fa-youtube-play": 61802, "fa-drupal": 61865, "fa-bed": 62006, "fa-battery-quarter": 62019, "fa-weixin": 61911, "fa-exchange": 61676, "fa-gg-circle": 62049, "fa-angle-double-up": 61698, "fa-forward": 61518, "fa-hand-pointer-o": 62042, "fa-cog": 61459, "fa-reddit-square": 61858, "fa-arrow-circle-down": 61611, "fa-battery-three-quarters": 62017, "fa-venus-double": 61990, "fa-tumblr-square": 61812, "fa-angellist": 61961, "fa-toggle-off": 61956, "fa-info": 61737, "fa-eyedropper": 61947, "fa-behance": 61876, "fa-map-signs": 62071, "fa-file-audio-o": 61895, "fa-gavel": 61667, "fa-glass": 61440, "fa-hand-o-right": 61604, "fa-cube": 61874, "fa-pinterest-square": 61651, "fa-cc-stripe": 61941, "fa-battery-full": 62016, "fa-lightbulb-o": 61675, "fa-caret-square-o-up": 61777, "fa-video-camera": 61501, "fa-jsfiddle": 61900, "fa-long-arrow-left": 61815, "fa-caret-right": 61658, "fa-volume-down": 61479, "fa-tags": 61484, "fa-arrow-up": 61538, "fa-folder-open-o": 61717, "fa-shield": 61746, "fa-dashcube": 61968, "fa-rotate-right": 61470, "fa-angle-double-down": 61699, "fa-facebook": 61594, "fa-hand-scissors-o": 62039, "fa-scribd": 62090, "fa-sort": 61660, "fa-twitter-square": 61569, "fa-power-off": 61457, "fa-gratipay": 61828, "fa-mars": 61986, "fa-header": 61916, "fa-user": 61447, "fa-exclamation-circle": 61546, "fa-level-down": 61769, "fa-vine": 61898, "fa-tint": 61507, "fa-wordpress": 61850, "fa-expeditedssl": 62014, "fa-slack": 61848, "fa-cut": 61636, "fa-key": 61572, "fa-tripadvisor": 62050, "fa-opera": 62058, "fa-object-group": 62023, "fa-heartbeat": 61982, "fa-laptop": 61705, "fa-bomb": 61922, "fa-angle-double-left": 61696, "fa-quote-left": 61709, "fa-paw": 61872, "fa-reddit": 61857, "fa-cc-visa": 61936, "fa-circle-o": 61708, "fa-odnoklassniki-square": 62052, "fa-cc-jcb": 62027, "fa-mail-reply-all": 61730, "fa-lastfm": 61954, "fa-group": 61632, "fa-microphone": 61744, "fa-camera-retro": 61571, "fa-maxcdn": 61750, "fa-buysellads": 61965, "fa-play-circle-o": 61469, "fa-ge": 61905, "fa-i-cursor": 62022, "fa-percent": 62101, "fa-photo": 61502, "fa-toggle-on": 61957, "fa-fax": 61868, "fa-code-fork": 61734, "fa-y-combinator": 62011, "fa-map": 62073, "fa-try": 61845, "fa-diamond": 61977, "fa-neuter": 61996, "fa-quote-right": 61710, "fa-mobile": 61707, "fa-bell-slash": 61942, "fa-trademark": 62044, "fa-file-video-o": 61896, "fa-mixcloud": 62089, "fa-plus-circle": 61525, "fa-folder-open": 61564, "fa-css3": 61756, "fa-fast-forward": 61520, "fa-toggle-down": 61776, "fa-credit-card": 61597, "fa-caret-square-o-left": 61841, "fa-hourglass-3": 62035, "fa-hourglass-2": 62034, "fa-hourglass-1": 62033, "fa-angle-down": 61703, "fa-edge": 62082, "fa-trello": 61825, "fa-train": 62008, "fa-sheqel": 61963, "fa-file-powerpoint-o": 61892, "fa-arrow-left": 61536, "fa-television": 62060, "fa-life-saver": 61901, "fa-copy": 61637, "fa-sticky-note-o": 62026, "fa-mars-double": 61991, "fa-star-half-o": 61731, "fa-black-tie": 62078, "fa-chevron-up": 61559, "fa-chevron-down": 61560, "fa-fonticons": 62080, "fa-check-circle-o": 61533, "fa-plug": 61926, "fa-deviantart": 61885, "fa-dashboard": 61668, "fa-hourglass-o": 62032, "fa-plus": 61543, "fa-cc-discover": 61938, "fa-hashtag": 62098, "fa-gamepad": 61723, "fa-rub": 61784, "fa-history": 61914, "fa-sign-in": 61584, "fa-sort-amount-desc": 61793, "fa-rss-square": 61763, "fa-transgender": 61988, "fa-graduation-cap": 61853, "fa-whatsapp": 62002, "fa-mercury": 61987, "fa-amazon": 62064, "fa-medkit": 61690, "fa-bug": 61832, "fa-twitch": 61928, "fa-file-archive-o": 61894, "fa-forumbee": 61969, "fa-cny": 61783, "fa-arrows": 61511, "fa-map-marker": 61505, "fa-wheelchair": 61843, "fa-plus-square": 61694, "fa-male": 61827, "fa-institution": 61852, "fa-envelope-o": 61443, "fa-xing-square": 61801, "fa-step-forward": 61521, "fa-stumbleupon-circle": 61859, "fa-pencil-square-o": 61508, "fa-weibo": 61834, "fa-gear": 61459, "fa-rocket": 61749, "fa-bluetooth": 62099, "fa-search-plus": 61454, "fa-stop-circle": 62093, "fa-bell": 61683, "fa-undo": 61666, "fa-fast-backward": 61513, "fa-sliders": 61918, "fa-hotel": 62006, "fa-steam": 61878, "fa-hand-paper-o": 62038, "fa-circle-thin": 61915, "fa-share-square": 61773, "fa-asterisk": 61545, "fa-arrow-down": 61539, "fa-random": 61556, "fa-share-alt": 61920, "fa-beer": 61692, "fa-exclamation-triangle": 61553, "fa-commenting": 62074, "fa-volume-up": 61480, "fa-flag-checkered": 61726, "fa-ellipsis-h": 61761, "fa-hand-spock-o": 62041, "fa-crop": 61733, "fa-paragraph": 61917, "fa-battery-3": 62017, "fa-ellipsis-v": 61762, "fa-gift": 61547, "fa-strikethrough": 61644, "fa-motorcycle": 61980, "fa-life-bouy": 61901, "fa-reply-all": 61730, "fa-paper-plane-o": 61913, "fa-star-half": 61577, "fa-download": 61465, "fa-usb": 62087, "fa-chevron-circle-down": 61754, "fa-calculator": 61932, "fa-gg": 62048, "fa-contao": 62061, "fa-hand-o-down": 61607, "fa-leanpub": 61970, "fa-star-o": 61446, "fa-pie-chart": 61952, "fa-venus": 61985, "fa-inr": 61782, "fa-rupee": 61782, "fa-eur": 61779, "fa-tumblr": 61811, "fa-indent": 61500, "fa-mars-stroke-v": 61994, "fa-git": 61907, "fa-envelope": 61664, "fa-bitbucket-square": 61810, "fa-legal": 61667, "fa-gittip": 61828, "fa-chevron-left": 61523, "fa-cogs": 61573, "fa-arrow-circle-o-left": 61840, "fa-briefcase": 61617, "fa-user-md": 61680, "fa-angle-left": 61700, "fa-yc": 62011, "fa-long-arrow-right": 61816, "fa-coffee": 61684, "fa-copyright": 61945, "fa-toggle-up": 61777, "fa-support": 61901, "fa-youtube-square": 61798, "fa-cc-mastercard": 61937, "fa-unsorted": 61660, "fa-compress": 61542, "fa-android": 61819, "fa-font": 61489, "fa-arrow-right": 61537, "fa-minus": 61544, "fa-bitbucket": 61809, "fa-facebook-f": 61594, "fa-subway": 62009, "fa-headphones": 61477, "fa-paperclip": 61638, "fa-industry": 62069, "fa-rmb": 61783, "fa-minus-square": 61766, "fa-moon-o": 61830, "fa-file-excel-o": 61891, "fa-line-chart": 61953, "fa-fighter-jet": 61691, "fa-sort-alpha-desc": 61790, "fa-spotify": 61884, "fa-star-half-empty": 61731, "fa-share": 61540, "fa-comment": 61557, "fa-mars-stroke": 61993, "fa-stack-exchange": 61837, "fa-pied-piper": 61863, "fa-building": 61869, "fa-thumbs-up": 61796, "fa-chevron-circle-right": 61752, "fa-adjust": 61506, "fa-sellsy": 61971, "fa-paypal": 61933, "fa-signal": 61458, "fa-sort-up": 61662, "fa-shekel": 61963, "fa-codiepie": 62084, "fa-calendar-plus-o": 62065, "fa-digg": 61862, "fa-save": 61639, "fa-shopping-bag": 62096, "fa-eye-slash": 61552, "fa-backward": 61514, "fa-hand-stop-o": 62038, "fa-mail-forward": 61540, "fa-link": 61633, "fa-table": 61646, "fa-tag": 61483, "fa-turkish-lira": 61845, "fa-envelope-square": 61849, "fa-optin-monster": 62012, "fa-money": 61654, "fa-instagram": 61805, "fa-volume-off": 61478, "fa-unlock-alt": 61758, "fa-minus-circle": 61526, "fa-hacker-news": 61908, "fa-hand-grab-o": 62037, "fa-adn": 61808, "fa-list-ol": 61643, "fa-magnet": 61558, "fa-calendar-minus-o": 62066, "fa-linkedin": 61665, "fa-paper-plane": 61912, "fa-mouse-pointer": 62021, "fa-reply": 61714, "fa-smile-o": 61720, "fa-hourglass-half": 62034, "fa-behance-square": 61877, "fa-twitter": 61593, "fa-expand": 61541, "fa-flask": 61635, "fa-flash": 61671, "fa-trophy": 61585, "fa-long-arrow-down": 61813, "fa-odnoklassniki": 62051, "fa-angle-double-right": 61697, "fa-home": 61461, "fa-bolt": 61671, "fa-italic": 61491, "fa-comments": 61574, "fa-commenting-o": 62075, "fa-toggle-right": 61778, "fa-file": 61787, "fa-bold": 61490, "fa-internet-explorer": 62059, "fa-cc-amex": 61939, "fa-sort-down": 61661, "fa-anchor": 61757, "fa-medium": 62010, "fa-calendar": 61555, "fa-superscript": 61739, "fa-wechat": 61911, "fa-file-text-o": 61686, "fa-cloud": 61634, "fa-user-plus": 62004, "fa-times": 61453, "fa-street-view": 61981, "fa-trash": 61944, "fa-paste": 61674, "fa-ambulance": 61689, "fa-suitcase": 61682, "fa-binoculars": 61925, "fa-user-secret": 61979, "fa-sort-alpha-asc": 61789, "fa-picture-o": 61502, "fa-cc": 61962, "fa-calendar-times-o": 62067, "fa-phone": 61589, "fa-github-square": 61586, "fa-hand-peace-o": 62043, "fa-windows": 61818, "fa-500px": 62062, "fa-calendar-check-o": 62068, "fa-clock-o": 61463, "fa-connectdevelop": 61966, "fa-text-height": 61492, "fa-houzz": 62076, "fa-align-right": 61496, "fa-angle-right": 61701, "fa-hand-rock-o": 62037, "fa-heart-o": 61578, "fa-steam-square": 61879, "fa-underline": 61645, "fa-file-image-o": 61893, "fa-bus": 61959, "fa-play-circle": 61764, "fa-plus-square-o": 61846, "fa-rss": 61598, "fa-battery-0": 62020, "fa-battery-1": 62019, "fa-battery-2": 62018, "fa-google-plus-square": 61652, "fa-battery-4": 62016, "fa-caret-square-o-right": 61778, "fa-child": 61870, "fa-space-shuttle": 61847, "fa-pinterest-p": 62001, "fa-outdent": 61499, "fa-lock": 61475, "fa-dot-circle-o": 61842, "fa-git-square": 61906, "fa-clipboard": 61674, "fa-mortar-board": 61853, "fa-university": 61852, "fa-github": 61595, "fa-jpy": 61783, "fa-vk": 61833, "fa-print": 61487, "fa-code": 61729, "fa-book": 61485, "fa-pinterest": 61650, "fa-youtube": 61799, "fa-fire": 61549, "fa-hourglass-end": 62035, "fa-tasks": 61614, "fa-xing": 61800, "fa-ioxhost": 61960, "fa-play": 61515, "fa-flag-o": 61725, "fa-battery-half": 62018, "fa-search": 61442, "fa-genderless": 61997, "fa-renren": 61835, "fa-database": 61888, "fa-plane": 61554, "fa-sort-numeric-desc": 61795, "fa-intersex": 61988, "fa-tree": 61883, "fa-scissors": 61636, "fa-question-circle": 61529, "fa-close": 61453, "fa-crosshairs": 61531, "fa-apple": 61817, "fa-wrench": 61613, "fa-sitemap": 61672, "fa-language": 61867, "fa-automobile": 61881, "fa-hourglass": 62036, "fa-bar-chart": 61568, "fa-file-o": 61462, "fa-krw": 61785, "fa-soundcloud": 61886, "fa-floppy-o": 61639, "fa-upload": 61587, "fa-arrow-circle-o-right": 61838, "fa-info-circle": 61530, "fa-cloud-upload": 61678, "fa-facebook-official": 62000, "fa-search-minus": 61456, "fa-music": 61441, "fa-stumbleupon": 61860, "fa-star-half-full": 61731, "fa-file-picture-o": 61893, "fa-image": 61502, "fa-mobile-phone": 61707, "fa-dollar": 61781, "fa-google-wallet": 61934, "fa-feed": 61598, "fa-vimeo": 62077, "fa-futbol-o": 61923, "fa-hdd-o": 61600, "fa-remove": 61453, "fa-bullseye": 61760, "fa-location-arrow": 61732, "fa-female": 61826, "fa-joomla": 61866, "fa-thumb-tack": 61581, "fa-align-justify": 61497, "fa-external-link": 61582, "fa-arrow-circle-right": 61609, "fa-level-up": 61768, "fa-gears": 61573, "fa-foursquare": 61824, "fa-venus-mars": 61992, "fa-yelp": 61929, "fa-exclamation": 61738, "fa-star": 61445, "fa-google-plus": 61653, "fa-ra": 61904, "fa-h-square": 61693, "fa-lastfm-square": 61955, "fa-registered": 62045, "fa-edit": 61508, "fa-unlock": 61596, "fa-sort-desc": 61661, "fa-tencent-weibo": 61909, "fa-thumbs-down": 61797, "fa-eject": 61522, "fa-linkedin-square": 61580, "fa-pagelines": 61836, "fa-chain": 61633, "fa-yahoo": 61854, "fa-send": 61912, "fa-check": 61452, "fa-compass": 61774, "fa-viacoin": 62007, "fa-angle-up": 61702, "fa-wikipedia-w": 62054, "fa-qrcode": 61481, "fa-paint-brush": 61948, "fa-bookmark-o": 61591, "fa-usd": 61781, "fa-chevron-right": 61524, "fa-ruble": 61784, "fa-delicious": 61861, "fa-btc": 61786, "fa-lemon-o": 61588, "fa-arrow-circle-up": 61610, "fa-comments-o": 61670, "fa-chrome": 62056, "fa-check-square-o": 61510, "fa-ils": 61963, "fa-birthday-cake": 61949, "fa-tablet": 61706, "fa-codepen": 61899, "fa-stop-circle-o": 62094, "fa-chain-broken": 61735, "fa-puzzle-piece": 61742, "fa-creative-commons": 62046, "fa-spinner": 61712, "fa-newspaper-o": 61930, "fa-globe": 61612, "fa-firefox": 62057, "fa-vimeo-square": 61844, "fa-magic": 61648, "fa-align-center": 61495, "fa-warning": 61553, "fa-desktop": 61704, "fa-cc-diners-club": 62028, "fa-thumbs-o-up": 61575, "fa-dribbble": 61821, "fa-square-o": 61590, "fa-columns": 61659, "fa-flickr": 61806, "fa-retweet": 61561, "fa-flag": 61476, "fa-google": 61856, "fa-file-sound-o": 61895, "fa-bitcoin": 61786, "fa-text-width": 61493, "fa-arrows-v": 61565, "fa-hospital-o": 61688, "fa-step-backward": 61512, "fa-bullhorn": 61601, "fa-fire-extinguisher": 61748, "fa-arrows-h": 61566, "fa-refresh": 61473, "fa-fort-awesome": 62086, "fa-github-alt": 61715, "fa-reorder": 61641, "fa-modx": 62085, "fa-facebook-square": 61570, "fa-empire": 61905, "fa-credit-card-alt": 62083, "fa-qq": 61910, "fa-rouble": 61784, "fa-minus-square-o": 61767, "fa-rotate-left": 61666, "fa-file-pdf-o": 61889}

================================================
FILE: kivystudio/tools/iconfonts/test/main.py
================================================
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.base import runTouchApp
from kivy.lang import Builder

import os, json ,sys
from os.path import join, dirname
p =(dirname(dirname(join(os.getcwd(), __file__))))
print(p)
sys.path.append(p)
from iconfonts import register, icon

font_file = join(dirname(__file__), 'font-awesome.fontd')
register('awesome_font', 'font-awesome.ttf',
     font_file)


with open(font_file, 'r') as f:
    fontd = json.loads(f.read())

class Boxer(BoxLayout):

	def search(self, text):
		add_icons(text)

root = Builder.load_string('''
Boxer:
	orientation: 'vertical'
	TextInput:
		size_hint_y: None
		height: '48dp'
		on_text: root.search(self.text)
	ScrollView:
		bar_width: '24dp'
		GridLayout:
			id: grid
			height: self.minimum_height
			size_hint_y: None
			cols: 1
''')

def add_icons(search=''):
	root.ids.grid.clear_widgets()
	keys = list(fontd.keys())
	keys.sort()
	for icon_name in keys:
		if search and icon_name.find(search)==-1:
			continue
		lb = Label(markup=True, size_hint_y=None)
		lb.text= '[color=3280ff]%s[/color] '%(icon(icon_name, 32)) + icon_name
		root.ids.grid.add_widget(lb)

add_icons()
runTouchApp(root)


================================================
FILE: kivystudio/tools/infolabel.py
================================================
from kivy.uix.label import Label
from kivy.lang import Builder
from kivy.core.window import Window

from .__init__ import set_auto_mouse_position

def show_info_on_mouse(message=''):
    ''' func that displays an info 
        on mouse cursor'''
    if message:
        if info_label in Window.children:
            Window.remove_widget(info_label)

        info_label.text = ''
        info_label.text = message
        set_auto_mouse_position(info_label)
        Window.add_widget(info_label)


def remove_info_on_mouse():
    if info_label in Window.children:
        Window.remove_widget(info_label)


class InfoLabel(Label):
    pass


Builder.load_string('''
<InfoLabel>:
    size_hint: None,None
    text_size: None, self.height
    valign: 'middle'
    halign:'left'
    width:  self.texture_size[0]+10
    height: '30dp'
    color: 1,1,1,1
    padding: '4dp', '4dp'
    canvas.before:
        Color:
            rgba: 0,0,0,.9
        RoundedRectangle:
            size: self.size
            pos: self.pos
''')
info_label = InfoLabel()


================================================
FILE: kivystudio/tools/logger.py
================================================
from kivy.logger import Logger as KivyLogger
from kivy.utils import get_hex_from_color, escape_markup

COLORS  = {
    'info': (.3,1,.4,1),
    'warning': (1,1,0,1),
    'error': (1,.5,.2,1),
    }

class LoggerBase:

    def _format_log(self, log_type, msg):
        msg = msg.split(':',1) + ['']
        log_color = get_hex_from_color(COLORS[log_type])
        log_title = "[color=%s]&bl;[b]%-14s[/b]&br;[/color]  " \
            % (log_color, log_type.upper())
        if msg[1]:
            log_msg = "[%-18s] %s" % (msg[0], msg[1])
        else:
            log_msg = "%s" % msg[0]
        
        return log_title+log_msg

    def info(self, msg, log_out=False):
        log = self._format_log('info', msg)
        self._log_out(msg, log, 'info', log_out=log_out)
        
    def warning(self, msg, log_out=False):
        log = self._format_log('warning', msg)
        self._log_out(msg, log, 'warning', log_out=log_out)

    def error(self, msg, log_out=False):
        log = self._format_log('error', msg)
        self._log_out(msg, log, 'error', log_out=log_out)

    def _log_out(self, msg, log, log_type, log_out=False):
        from kivystudio.components.codeplace import terminal
        terminal.logger.log(log)
        if log_out:
            getattr(KivyLogger, log_type)(msg)

    def clear_logs(self):
        from kivystudio.components.codeplace import terminal
        terminal.logger.clear_logs()

Logger = LoggerBase()

from kivy.clock import mainthread
@mainthread
def test_log(*args):
    Logger.info('Welcome to KivyStudio')
test_log()


================================================
FILE: kivystudio/tools/quicktools.py
================================================
from kivy.logger import Logger
import sys
from kivystudio.widgets.filemanager import filemanager


def open_new_file():
    ''' open a new file on
        the CodeInput '''
    from kivystudio.assembler import code_place
    code_place.add_code_tab(tab_type='new_file')

def open_file(filename=''):
    ''' open a file (existing file) on
        the CodeInput, if filename, it open a 
        new tab for the file, else it opens a filechooser'''
    from kivystudio.assembler import add_new_tab
    if filename:
        add_new_tab([filename,])
    else:
        filemanager.open_file(path='/root',on_selection=add_new_tab)

def open_folder(folder=''):
    ''' open a folder, if folder, it open a 
        new project, else it opens a filechooser'''
    from kivystudio.assembler import open_project
    if folder:
        open_project([folder,])
    else:
        filemanager.choose_dir(path='.',on_selection=open_project)

def open_recent():
    pass

def save():
    ''' save the current opened
        file '''
    from kivystudio.assembler import code_place
    code_place.code_manager.save_current_tab()

def save_all():
    ''' save all file currently opened '''
    from kivystudio.assembler import code_place
    code_place.code_manager.save_all_tabs()

def save_as():
    pass

def exit_window():
    exit()

import string
def is_binary(filename):
    ''' checks if a file is a binary file or not 
        used to validate file before opening them in
        the studio '''
    s = open(filename, 'rb').read(512)
    def func(num):
        return bytes(chr(num).encode('utf-8'))

    text_char = b''.join( list(map(func, range(32,127))) ) #+ list('\n\r\t\b') )
    if sys.version_info[0] == 3:
        _null_trans = b''.maketrans(b"",b"")
    else:
        _null_trans = string.maketrans('', '')

    if not s: # empty files are considered text files
        return False
    
    if b'\0' in s:
        # file with null bytes are likely binary
        return True

    t = s.translate(_null_trans, delete=text_char)

    # t = s.translate(str.maketrans('', '', text_char))
    # if more than 30% are non-text charaters 
    # then it is considered binary
    if float(len(t))/float(len(s)) > 0.30:
        return True
    return False


================================================
FILE: kivystudio/widgets/__init__.py
================================================


================================================
FILE: kivystudio/widgets/codeinput/__init__.py
================================================
from kivy.core.window import Window
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.scrollview import ScrollView
from kivy.clock import Clock
from kivy.metrics import dp
from kivy.lang import Builder
from kivy.properties import BooleanProperty, StringProperty, ListProperty, ObjectProperty
from kivy.utils import get_color_from_hex

from kivystudio.behaviors import HoverBehavior
from kivystudio.widgets.rightclick_drop import RightClickDrop

from .styles import NativeTweakStyle
from .codeinput import CodeInput
from .code_find import CodeInputFind
from .code_extra_behavior import CodeExtraBehavior

import os
from pygments import styles

class CodeInputDropDown(RightClickDrop):
    ''' DropDown widget show when mouse 
        is right clicked on CodeInput
        '''

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):  # so doesn't unfocus input
            FocusBehavior.ignored_touch.append(touch)
        return super(CodeInputDropDown,self).on_touch_down(touch)
    
    def open(self, code_input):
        self.codeinput = codeinput
        super(CodeInputDropDown,self).open()

    def copy(self):
        self.codeinput.copy()

    def paste(self):
        self.codeinput.paste()

    def cut(self):
        self.codeinput.cut()


class InnerCodeInput(HoverBehavior, CodeExtraBehavior, CodeInput):

    path = StringProperty('')
    '''Path of the current file
        `path` is a :class:`~kivy.properties.StringProperty`
    and defaults to ''
    '''

    rightclick_dropdown = None
    ''' drop down menu that appears when the right click button is clicked
        `rightclick_dropdown` is an instance of .code_find.CodeInputFind
        '''
    code_finder = None
    '''  '''

    def __init__(self, **kwargs):
        super(InnerCodeInput, self).__init__(**kwargs)
        self.style_name = 'native'
        self.background_normal= ''
        self.background_active= ''

    def on_style_name(self, *args):
        self.style = NativeTweakStyle
        self.background_color = get_color_from_hex(self.style.background_color)
        self._trigger_refresh_text()

    def on_text(self, *args):
        if self.focus:
            self.parent.saved = False
            self.check_settings()

    def check_settings(self):
        from kivystudio.settings import settings_obj
        auto_save = settings_obj.auto_save
        auto_emulate = settings_obj.auto_emulate
        if auto_save:
            self.parent.parent.save_file(auto_save=True)
        if auto_emulate:
            from kivystudio.parser import emulate_file
            from kivystudio.components.emulator_area import get_emulator_area
            if get_emulator_area().emulation_file == self.parent.filename:
                emulate_file(self.parent.filename)

    def keyboard_on_textinput(self, window, text):
        'overiding the default textinput keyboard listener '
        if (text == '=' or text == '-') and 'ctrl' in Window.modifiers:
            return True
        super(InnerCodeInput,self).keyboard_on_textinput(window, text)

    def keyboard_on_key_down(self, keyboard, keycode, text, modifiers):
        'overiding the default keyboard listener '
        # print(keycode, modifiers)

        if keycode[1] == 'tab' and 'shift' in modifiers:  # unindentation [Shit-tab]
            self._do_reverse_indentation()

        elif keycode[1] == 'tab' and self.selection_text:  # multiple indentation [Tab]
            self.do_multiline_indent()

        elif keycode[1] == 'backspace' and 'ctrl' in modifiers:   # delete word left  [Ctrl-bsc]
            self.delete_word_left()

        elif keycode[1] == '/' and 'ctrl' in modifiers:     # a comment ctrl /
            self.do_comment()

        elif keycode[1] == 'enter':
            Clock.schedule_once(lambda dt: self.do_auto_indent())
            return super(CodeInput, self).keyboard_on_key_down(keyboard, keycode, text, modifiers)

        elif keycode[1] == 'f' and 'ctrl' in modifiers:     # ctrl f to open a search
            self.open_code_finder()

        elif keycode[0] == 27:     # on escape, do nothing
            return True

        else:
            # then return super for others
            return super(CodeInput, self).keyboard_on_key_down(keyboard, keycode, text, modifiers)
    
    def open_code_finder(self):
        ''' open the search finder 
            on the codeinput '''
        code_finder = InnerCodeInput.code_finder
        if code_finder:
            code_finder.open(self)
        else:
            InnerCodeInput.code_finder = CodeInputFind()
            InnerCodeInput.code_finder.open(self)
    
    def open_rightclick_dropdown(self):
        ''' open the dropdown right click 
            on the codeinput '''
        rightclick_dropdown = InnerCodeInput.rightclick_dropdown
        if rightclick_dropdown:
            rightclick_dropdown.open()
        else:
            InnerCodeInput.rightclick_dropdown = CodeInputDropDown()
            InnerCodeInput.rightclick_dropdown.open(self)

    def on_hover(self, *a):
        ''' changing the mouse cursor 
            on code input'''
        if self.hover:
            Window.set_system_cursor('ibeam')  # set cursor to ibeam
        else:
            Window.set_system_cursor('arrow')  # set cursor to arrow

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            if touch.button == 'right':
                self.open_rightclick_dropdown()
                FocusBehavior.ignored_touch.append(touch)
                return True

        if touch.button == 'left':
            return super(InnerCodeInput,self).on_touch_down(touch)


class NumberingGrid(ScrollView):

    def on_touch_down(self, touch):
        if self.collide_point( *touch.pos):
            FocusBehavior.ignored_touch.append(touch)
            super(NumberingGrid, self).on_touch_down(touch)

class ScrollingBar(ScrollView):

    def on_touch_down(self, touch):
        if self.collide_point( *touch.pos):
            FocusBehavior.ignored_touch.append(touch)
            super(ScrollingBar, self).on_touch_down(touch)


class FullCodeInput(GridLayout):

    _do_cursor_scroll =BooleanProperty(True)

    code_input = ObjectProperty(None)

    tab = ObjectProperty(None)

    tab_type = StringProperty('code')

    filename = StringProperty('')
    ''' name current file in the input 
            :data:`filename` is a :class:`~kivy.properties.StringProperty`
    and defaults to ''
    '''

    saved = BooleanProperty(True)
    '''Indicates if the current file is saved or not
        :data:`saved` is a :class:`~kivy.properties.BooleanProperty`
    and defaults to True
    '''

    def __init__(self, **kwargs):
        super(FullCodeInput, self).__init__(**kwargs)
        Clock.schedule_once(self.first_number)
        self._former_line_lenght = 1
        self.first_time = True


    def first_number(self, dt):
        label = Numbers_(height=dp(self.ids.code_input.line_height), text=str(1))
        Clock.schedule_once(lambda dt: setattr(label, 'state', 'down'))
        label.fbind('on_press', self._number_pressed)
        self.ids.numbering.add_widget(label)
        self._former_line_lenght = 1


    def _number_pressed(self, lb):
        self.ids.code_input.cursor = (self.ids.code_input.cursor[0], int(lb.text)-1)


    def change_scroll_y(self, txt, scroll):
        if self._do_cursor_scroll:

            lines_lenght = len(txt._lines)
            line_pos = txt.cursor_row +1

            norm_y = float(line_pos) / lines_lenght
            scroll.scroll_y  = abs(norm_y-1)
            if line_pos == 1:
                scroll.scroll_y  = 1

        # scroll scroll numbers
        line_num =  txt.cursor_row + 1
        children = self.ids.numbering.children[::-1]
        if children:
            child = children[line_num-1]
            self.ids.number_scroll.scroll_to(child, dp(5))

            Clock.schedule_once(lambda dt: setattr(child, 'state', 'down'))
            def toggle(chd):
                if chd!=child:
                    chd.state='normal'
            map(lambda child: toggle, ToggleButtonBehavior.get_widgets(child.group))


    def do_bar_scroll(self, txt, scroll):
        lines_lenght = len(txt._lines)
        line_pos = int(abs(scroll.scroll_y-1) * lines_lenght)
        cursor_y = abs(line_pos)

        txt.cursor = (txt.cursor_col, cursor_y)

    def number_me(self, txt, scroll):
        lines_lenght = len(txt._lines)
        line_pos = txt.cursor_row +2

        if not(lines_lenght <= 1) or not(self.first_time):

            if lines_lenght >= self._former_line_lenght:

                if line_pos == lines_lenght:
                    self.do_new_line(txt, scroll)
                else:
                    self.do_new_line(txt, scroll)

            els
Download .txt
gitextract_7y9q4d6t/

├── .gitignore
├── LICENSE
├── README.md
├── kivystudio/
│   ├── __init__.py
│   ├── assembler.py
│   ├── behaviors/
│   │   ├── __init__.py
│   │   ├── highlightbehavior.py
│   │   ├── hoverbehavior.py
│   │   └── hoverinfobehavior.py
│   ├── components/
│   │   ├── __init__.py
│   │   ├── codeplace/
│   │   │   ├── __init__.py
│   │   │   ├── code.kv
│   │   │   ├── codeplace.py
│   │   │   └── tabs/
│   │   │       ├── __init__.py
│   │   │       ├── codetab.py
│   │   │       ├── errortab.py
│   │   │       ├── welcome.kv
│   │   │       └── welcometab.py
│   │   ├── emulator_area/
│   │   │   ├── __init__.py
│   │   │   ├── emulator.kv
│   │   │   └── screen_drop.py
│   │   ├── screens/
│   │   │   ├── __init__.py
│   │   │   ├── screen.kv
│   │   │   └── screen_test.py
│   │   ├── sibebar/
│   │   │   ├── __init__.py
│   │   │   ├── fileexplorer/
│   │   │   │   ├── __init__.py
│   │   │   │   └── filewidgets.py
│   │   │   ├── generalsearch.py
│   │   │   ├── gitmanager.py
│   │   │   └── sidebar.kv
│   │   ├── terminal/
│   │   │   ├── __init__.py
│   │   │   ├── command_terminal.py
│   │   │   └── logger_space.py
│   │   └── topmenu/
│   │       ├── __init__.py
│   │       ├── dropmenu.kv
│   │       └── dropmenu.py
│   ├── libs/
│   │   ├── __init__.py
│   │   └── resizablebehavior/
│   │       ├── LICENSE
│   │       ├── README.md
│   │       ├── __init__.py
│   │       ├── modal_cursor.py
│   │       └── resize.py
│   ├── main.kv
│   ├── main.py
│   ├── parser/
│   │   └── __init__.py
│   ├── resources/
│   │   └── font-awesome.fontd
│   ├── settings.py
│   ├── tools/
│   │   ├── __init__.py
│   │   ├── iconfonts/
│   │   │   ├── LICENSE
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── iconfonts.py
│   │   │   └── test/
│   │   │       ├── font-awesome.css
│   │   │       ├── font-awesome.fontd
│   │   │       └── main.py
│   │   ├── infolabel.py
│   │   ├── logger.py
│   │   └── quicktools.py
│   └── widgets/
│       ├── __init__.py
│       ├── codeinput/
│       │   ├── __init__.py
│       │   ├── code_extra_behavior.py
│       │   ├── code_find.py
│       │   ├── codeinput.kv
│       │   ├── codeinput.py
│       │   ├── styles/
│       │   │   ├── __init__.py
│       │   │   └── native_tweak.py
│       │   └── tools.py
│       ├── dropdown.py
│       ├── filemanager/
│       │   ├── LICENSE
│       │   ├── README.md
│       │   ├── __init__.py
│       │   ├── filechooserthumbview/
│       │   │   ├── LICENSE
│       │   │   └── __init__.py
│       │   └── filemanager.kv
│       ├── iconlabel.py
│       ├── rightclick_drop.py
│       ├── searchinput.py
│       ├── splitter.py
│       └── tabbedpanel.py
├── project/
│   ├── prjtTest1.htm
│   └── prjtTest1.js
├── repoTest1.js
├── repoTest2.htm
├── setup.py
├── tests/
│   ├── test_codeplace.py
│   └── test_emulator.py
└── to-do.txt
Download .txt
SYMBOL INDEX (418 symbols across 50 files)

FILE: kivystudio/__init__.py
  function get_kivystudio_app (line 10) | def get_kivystudio_app():

FILE: kivystudio/assembler.py
  class Assembly (line 16) | class Assembly(BoxLayout):
  function add_new_tab (line 22) | def add_new_tab(paths):
  function open_project (line 27) | def open_project(paths):
  function main_key_handler (line 32) | def main_key_handler(win, *args):

FILE: kivystudio/behaviors/highlightbehavior.py
  class HighlightBehavior (line 16) | class HighlightBehavior(object):
    method __init__ (line 46) | def __init__(self, **kwargs):
    method set_first_child (line 50) | def set_first_child(self, dt):
    method on_highlighted_color (line 55) | def on_highlighted_color(self, *args):
    method redraw_canvas (line 58) | def redraw_canvas(self, *args):
    method on_focus (line 70) | def on_focus(self, arg, focus):
    method on_children (line 79) | def on_children(self, *args):
    method set_highlighted (line 84) | def set_highlighted(self, child):
    method handle_key (line 94) | def handle_key(self, keyboard, key, codepoint, text, modifier, *args):
    method _moving (line 112) | def _moving(self):
    method do_up (line 117) | def do_up(self):
    method do_down (line 138) | def do_down(self):
    method do_right (line 158) | def do_right(self):
    method do_left (line 173) | def do_left(self):
    method do_enter (line 189) | def do_enter(self):
    method do_ctrl_up (line 192) | def do_ctrl_up(self):
    method do_shift_up (line 194) | def do_shift_up(self):
    method do_shift_down (line 196) | def do_shift_down(self):
    method do_shift_left (line 198) | def do_shift_left(self):
    method do_shift_up (line 200) | def do_shift_up(self):
  class What (line 208) | class What(HighlightBehavior, FocusBehavior, GridLayout):

FILE: kivystudio/behaviors/hoverbehavior.py
  class HoverBehavior (line 19) | class HoverBehavior(object):
    method on_parent (line 26) | def on_parent(self, *args):
    method on_mouse_move (line 34) | def on_mouse_move(self, win, pos):
  class HoverButton (line 47) | class HoverButton(HoverBehavior, Button):
    method on_hover (line 49) | def on_hover(self, *args):

FILE: kivystudio/behaviors/hoverinfobehavior.py
  class HoverInfoBehavior (line 27) | class HoverInfoBehavior(HoverBehavior):
    method on_parent (line 33) | def on_parent(self, *a):
    method on_hover (line 38) | def on_hover(self, *a):
    method show_label_info (line 45) | def show_label_info(self,dt):

FILE: kivystudio/components/codeplace/__init__.py
  class CodeContainer (line 7) | class CodeContainer(StudioSplitter):

FILE: kivystudio/components/codeplace/codeplace.py
  function get_tab_from_group (line 29) | def get_tab_from_group(filename):
  function get_lexer_for_file (line 37) | def get_lexer_for_file(filename):
  class CodeScreenManager (line 50) | class CodeScreenManager(ScreenManager):
    method __init__ (line 52) | def __init__(self, **kwargs):
    method add_widget (line 56) | def add_widget(self, widget, name, tab_type='code'):
    method open_file (line 69) | def open_file(self, code_input):
    method save_current_tab (line 75) | def save_current_tab(self):
    method save_all_tabs (line 78) | def save_all_tabs(self):
    method get_children_with_filename (line 82) | def get_children_with_filename(self, filename):
  class CodeScreen (line 90) | class CodeScreen(Screen):
    method on_pre_enter (line 94) | def on_pre_enter(self):
    method on_pre_leave (line 104) | def on_pre_leave(self):
    method on_enter (line 108) | def on_enter(self):
    method save_file (line 112) | def save_file(self, new_file=False, auto_save=False):
    method save_new_file (line 126) | def save_new_file(self, paths):
    method add_widget (line 135) | def add_widget(self, widget, tab_type='code'):
    method saving_file (line 142) | def saving_file(self, ins, saved):
    method keyboard_down (line 146) | def keyboard_down(self, window, *args):
  class CodePlace (line 160) | class CodePlace(BoxLayout):
    method __init__ (line 170) | def __init__(self, **kwargs):
    method file_droped (line 178) | def file_droped(self, window, filename, *args):
    method add_widget (line 184) | def add_widget(self, widget, tab_type=''):
    method change_screen (line 204) | def change_screen(self, tab, state):
    method keyboard_down (line 212) | def keyboard_down(self, window, *args):
    method remove_code_tab (line 226) | def remove_code_tab(self, tab):
    method add_code_tab (line 234) | def add_code_tab(self, filename='', tab_type='code'):
  class CodeTabsContainer (line 268) | class CodeTabsContainer(ScrollView):
    method on_touch_down (line 272) | def on_touch_down(self, touch):

FILE: kivystudio/components/codeplace/tabs/codetab.py
  class TabToggleButton (line 20) | class TabToggleButton(HoverInfoBehavior, ToggleButtonBehavior, BoxLayout):
    method __init__ (line 28) | def __init__(self, **kwargs):
    method on_saved (line 39) | def on_saved(self, *args):
    method on_state (line 46) | def on_state(self, *args):
    method on_touch_down (line 57) | def on_touch_down(self,touch):
    method close_tab (line 67) | def close_tab(self):
    method __str__ (line 72) | def __str__(self):
  class CodeTabDropDown (line 76) | class CodeTabDropDown(RightClickDrop):
    method __init__ (line 78) | def __init__(self, **kwargs):
    method on_touch_down (line 82) | def on_touch_down(self, touch):
    method open (line 87) | def open(self, tab):
    method set_for_emulation (line 91) | def set_for_emulation(self, remove=False):
    method close_tab (line 97) | def close_tab(self):
  class TabPannelIndicator (line 102) | class TabPannelIndicator(IconLabelButton):
    method on_hover (line 104) | def on_hover(self, *a):

FILE: kivystudio/components/codeplace/tabs/errortab.py
  class FileErrorTab (line 4) | class FileErrorTab(Label):

FILE: kivystudio/components/codeplace/tabs/welcometab.py
  class WelcomeTab (line 8) | class WelcomeTab(BoxLayout):

FILE: kivystudio/components/emulator_area/__init__.py
  class EmulatorArea (line 22) | class EmulatorArea(BoxLayout):
    method __init__ (line 28) | def __init__(self, **kwargs):
    method add_widget (line 35) | def add_widget(self, widget):
    method toggle_orientation (line 38) | def toggle_orientation(self):
    method open_screen_drop (line 44) | def open_screen_drop(self,widget):
  class ScreenTopMenu (line 48) | class ScreenTopMenu(BoxLayout):
  class EmulatorScreens (line 54) | class EmulatorScreens(ScreenManager):
    method add_widget (line 56) | def add_widget(self, widget):
  class ScreenDisplay (line 63) | class ScreenDisplay(HoverBehavior, FloatLayout):
    method __init__ (line 71) | def __init__(self, **kwargs):
    method on_hover (line 76) | def on_hover(self, *args):
    method on_screen_name (line 79) | def on_screen_name(self, *a):
    method on_screen (line 83) | def on_screen(self, obj, screen):
  function get_emulator_area (line 98) | def get_emulator_area():

FILE: kivystudio/components/emulator_area/screen_drop.py
  class ScreenDrop (line 3) | class ScreenDrop(DropDownBase):
    method open (line 5) | def open(self, widget, screen_display):

FILE: kivystudio/components/screens/__init__.py
  class ScreenScatter (line 16) | class ScreenScatter(Scatter):
    method __init__ (line 33) | def __init__(self, **k):
    method add_widget (line 38) | def add_widget(self, widget):
    method clear_widgets (line 47) | def clear_widgets(self):
    method on_orientation (line 50) | def on_orientation(self, *a):
    method set_border (line 60) | def set_border(self, *a, **k):
    method on_parent (line 75) | def on_parent(self,*a):
    method get_pos (line 81) | def get_pos(self):
    method get_size (line 85) | def get_size(self):
  class IphoneScreen (line 89) | class IphoneScreen(ScreenScatter):
    method get_pos (line 91) | def get_pos(self):
    method get_size (line 98) | def get_size(self):
  class IpadScreen (line 102) | class IpadScreen(ScreenScatter):
    method get_pos (line 104) | def get_pos(self):
    method get_size (line 111) | def get_size(self):
  class AndriodTabScreen (line 114) | class AndriodTabScreen(ScreenScatter):
    method get_pos (line 116) | def get_pos(self):
    method get_size (line 122) | def get_size(self):
  class AndroidPhoneScreen (line 125) | class AndroidPhoneScreen(ScreenScatter):
    method get_pos (line 127) | def get_pos(self):
    method get_size (line 133) | def get_size(self):
  class ScreenContainer (line 137) | class ScreenContainer(FloatLayout):
    method add_widget (line 140) | def add_widget(self,widget):
    method clear_widgets (line 149) | def clear_widgets(self):

FILE: kivystudio/components/sibebar/__init__.py
  class SideBar (line 22) | class SideBar(BoxLayout):
    method __init__ (line 24) | def __init__(self, **k):
    method toggle_bar (line 30) | def toggle_bar(self, tab):
  class SideButter (line 45) | class SideButter(HoverInfoBehavior, ToggleButtonBehavior, Label):
    method on_hover (line 49) | def on_hover(self, *a):
  class SideToggleBar (line 57) | class SideToggleBar(ScreenManager):

FILE: kivystudio/components/sibebar/fileexplorer/__init__.py
  class FileView (line 10) | class FileView(TreeView):
    method on_touch_down (line 11) | def on_touch_down(self, touch):
  class FileExplorer (line 25) | class FileExplorer(Screen):
    method __init__ (line 28) | def __init__(self, **k):
    method load_directory (line 32) | def load_directory(self, directory):

FILE: kivystudio/components/sibebar/fileexplorer/filewidgets.py
  class TreeViewFile (line 13) | class TreeViewFile(TreeViewLabel):
    method on_hover (line 27) | def on_hover(self, *a):
    method on_is_selected (line 33) | def on_is_selected(self, *args):
    method on_path (line 37) | def on_path(self, *a):

FILE: kivystudio/components/sibebar/generalsearch.py
  class GeneralSearch (line 17) | class GeneralSearch(Screen):

FILE: kivystudio/components/sibebar/gitmanager.py
  class GitManager (line 18) | class GitManager(Screen):

FILE: kivystudio/components/terminal/__init__.py
  class TerminalSpace (line 13) | class TerminalSpace(ResizableBehavior, BoxLayout):
    method __init__ (line 23) | def __init__(self, **k):
    method add_widget (line 28) | def add_widget(self, widget, title=''):
    method tab_state (line 42) | def tab_state(self, tab, state):
    method on_state (line 54) | def on_state(self, *args):
    method toggle_state (line 60) | def toggle_state(self):
  class TerminalTab (line 66) | class TerminalTab(ToggleButtonBehavior, Label):
    method on_state (line 68) | def on_state(self, *a):

FILE: kivystudio/components/terminal/logger_space.py
  class ErrorLogger (line 9) | class ErrorLogger(BoxLayout):
    method __init__ (line 16) | def __init__(self, **kwargs):
    method log (line 23) | def log(self, msg):
    method clear_logs (line 30) | def clear_logs(self, *args):
  class InternalErrorLogger (line 34) | class InternalErrorLogger(BoxLayout):

FILE: kivystudio/components/topmenu/__init__.py
  class TopMenu (line 18) | class TopMenu(GridLayout):
    method __init__ (line 23) | def __init__(self, **kwargs):
    method open_menu (line 38) | def open_menu(self, widget):
    method remove_underscore (line 46) | def remove_underscore(self, text):
    method add_underscore (line 49) | def add_underscore(self,text):
  class TopMenuItem (line 53) | class TopMenuItem(HoverBehavior, ButtonBehavior, Label):
    method on_hover (line 55) | def on_hover(self, *args):

FILE: kivystudio/components/topmenu/dropmenu.py
  class MenuButton (line 12) | class MenuButton(HoverBehavior, ButtonBehavior, BoxLayout):
    method on_hover (line 13) | def on_hover(self, widget, hover):
  class ToggleMenuButton (line 25) | class ToggleMenuButton(HoverBehavior, ToggleButtonBehavior, BoxLayout):
  class FileTopMenu (line 28) | class FileTopMenu(DropDownBase):
    method __init__ (line 30) | def __init__(self, **k):
    method new_file (line 33) | def new_file(self):
    method open_file (line 36) | def open_file(self):
    method open_folder (line 39) | def open_folder(self):
    method open_recent (line 42) | def open_recent(self):
    method save (line 45) | def save(self):
    method save_all (line 48) | def save_all(self):
    method save_as (line 51) | def save_as(self):
    method exit_window (line 54) | def exit_window(self):
  class EditTopMenu (line 58) | class EditTopMenu(DropDownBase):
    method __init__ (line 59) | def __init__(self, **k):
  class ViewTopMenu (line 62) | class ViewTopMenu(DropDownBase):
    method __init__ (line 63) | def __init__(self, **k):
  class SelectionTopMenu (line 66) | class SelectionTopMenu(DropDownBase):
    method __init__ (line 67) | def __init__(self, **k):
  class HelpTopMenu (line 70) | class HelpTopMenu(DropDownBase):
    method __init__ (line 71) | def __init__(self, **k):

FILE: kivystudio/libs/resizablebehavior/modal_cursor.py
  class CursorModalView (line 13) | class CursorModalView(ModalView):
    method __init__ (line 20) | def __init__(self, **kwargs):
    method open (line 30) | def open(self, *largs):
    method put_on_top (line 39) | def put_on_top(self, *args):
    method on_hidden (line 43) | def on_hidden(self, val):
    method on_touch_down (line 51) | def on_touch_down(self, *args):
    method on_touch_up (line 54) | def on_touch_up(self, *args):
    method on_touch_move (line 57) | def on_touch_move(self, *args):
  class ResizeCursor (line 61) | class ResizeCursor(Widget):
    method __init__ (line 102) | def __init__(self, **kwargs):
    method on_size (line 122) | def on_size(self, obj, val):
    method on_hidden (line 125) | def on_hidden(self, obj, val):
    method on_mouse_move (line 133) | def on_mouse_move(self, val):
    method change_side (line 141) | def change_side(self, left, right, up, down):
    method grab (line 160) | def grab(self, wid):
    method ungrab (line 163) | def ungrab(self, wid):
    method on_disabled (line 167) | def on_disabled(self, obj, val):

FILE: kivystudio/libs/resizablebehavior/resize.py
  class ResizableBehavior (line 77) | class ResizableBehavior(object):
    method __init__ (line 247) | def __init__(self, **kwargs):
    method on_enter_resizable (line 253) | def on_enter_resizable(self):
    method on_leave_resizable (line 256) | def on_leave_resizable(self):
    method on_mouse_move (line 259) | def on_mouse_move(self, _, pos):
    method check_resizable_side (line 273) | def check_resizable_side(self, x, y):
    method on_touch_down (line 317) | def on_touch_down(self, touch):
    method on_touch_move (line 336) | def on_touch_move(self, touch):
    method resize_widget (line 341) | def resize_widget(self, touch):
    method check_min_max_size (line 377) | def check_min_max_size(self, touch):
    method on_touch_up (line 414) | def on_touch_up(self, touch):
    method on_resize_lock (line 426) | def on_resize_lock(self, obj, locked):
    method set_cursor_size (line 438) | def set_cursor_size(self, size):
    method set_cursor_icons (line 444) | def set_cursor_icons(self, hor, deg45, deg90, deg135):
    method set_cursor_mode (line 454) | def set_cursor_mode(self, value):

FILE: kivystudio/main.py
  class KivyStudio (line 28) | class KivyStudio(App):
    method build (line 30) | def build(self):
    method run (line 33) | def run(self):
  function main (line 39) | def main():

FILE: kivystudio/parser/__init__.py
  function emulate_file (line 18) | def emulate_file(filename, threaded=False):
  function start_emulation (line 48) | def start_emulation(filename, file_content, threaded=False):
  function emulation_done (line 86) | def emulation_done(root, filename):
  function load_defualt_kv (line 92) | def load_defualt_kv(filename, file_content):
  function get_app_cls_name (line 119) | def get_app_cls_name(file_content):
  function get_root_from_runTouch (line 137) | def get_root_from_runTouch(filename):
  function load_py_file (line 159) | def load_py_file(filename, file_content):
  function import_from_dir (line 174) | def import_from_dir(filename):
  function get_import_as (line 186) | def get_import_as(start, lines):
  function app_not_run_properly (line 199) | def app_not_run_properly(file_content):

FILE: kivystudio/settings.py
  class SettingDispatcher (line 16) | class SettingDispatcher(EventDispatcher):

FILE: kivystudio/tools/__init__.py
  function set_auto_mouse_position (line 8) | def set_auto_mouse_position(widget):
  function load_kv (line 23) | def load_kv(filepath, file):
  function get_user_data_dir (line 31) | def get_user_data_dir(name):

FILE: kivystudio/tools/iconfonts/iconfonts.py
  function register (line 12) | def register(name, ttf_fname, fontd_fname):
  function icon (line 23) | def icon(code, size=None, color=None, font_name=None):
  function create_fontdict_file (line 42) | def create_fontdict_file(css_fname, output_fname):
  function _parse (line 57) | def _parse(data):

FILE: kivystudio/tools/iconfonts/test/main.py
  class Boxer (line 21) | class Boxer(BoxLayout):
    method search (line 23) | def search(self, text):
  function add_icons (line 42) | def add_icons(search=''):

FILE: kivystudio/tools/infolabel.py
  function show_info_on_mouse (line 7) | def show_info_on_mouse(message=''):
  function remove_info_on_mouse (line 20) | def remove_info_on_mouse():
  class InfoLabel (line 25) | class InfoLabel(Label):

FILE: kivystudio/tools/logger.py
  class LoggerBase (line 10) | class LoggerBase:
    method _format_log (line 12) | def _format_log(self, log_type, msg):
    method info (line 24) | def info(self, msg, log_out=False):
    method warning (line 28) | def warning(self, msg, log_out=False):
    method error (line 32) | def error(self, msg, log_out=False):
    method _log_out (line 36) | def _log_out(self, msg, log, log_type, log_out=False):
    method clear_logs (line 42) | def clear_logs(self):
  function test_log (line 50) | def test_log(*args):

FILE: kivystudio/tools/quicktools.py
  function open_new_file (line 6) | def open_new_file():
  function open_file (line 12) | def open_file(filename=''):
  function open_folder (line 22) | def open_folder(folder=''):
  function open_recent (line 31) | def open_recent():
  function save (line 34) | def save():
  function save_all (line 40) | def save_all():
  function save_as (line 45) | def save_as():
  function exit_window (line 48) | def exit_window():
  function is_binary (line 52) | def is_binary(filename):

FILE: kivystudio/widgets/codeinput/__init__.py
  class CodeInputDropDown (line 24) | class CodeInputDropDown(RightClickDrop):
    method on_touch_down (line 29) | def on_touch_down(self, touch):
    method open (line 34) | def open(self, code_input):
    method copy (line 38) | def copy(self):
    method paste (line 41) | def paste(self):
    method cut (line 44) | def cut(self):
  class InnerCodeInput (line 48) | class InnerCodeInput(HoverBehavior, CodeExtraBehavior, CodeInput):
    method __init__ (line 63) | def __init__(self, **kwargs):
    method on_style_name (line 69) | def on_style_name(self, *args):
    method on_text (line 74) | def on_text(self, *args):
    method check_settings (line 79) | def check_settings(self):
    method keyboard_on_textinput (line 91) | def keyboard_on_textinput(self, window, text):
    method keyboard_on_key_down (line 97) | def keyboard_on_key_down(self, keyboard, keycode, text, modifiers):
    method open_code_finder (line 127) | def open_code_finder(self):
    method open_rightclick_dropdown (line 137) | def open_rightclick_dropdown(self):
    method on_hover (line 147) | def on_hover(self, *a):
    method on_touch_down (line 155) | def on_touch_down(self, touch):
  class NumberingGrid (line 166) | class NumberingGrid(ScrollView):
    method on_touch_down (line 168) | def on_touch_down(self, touch):
  class ScrollingBar (line 173) | class ScrollingBar(ScrollView):
    method on_touch_down (line 175) | def on_touch_down(self, touch):
  class FullCodeInput (line 181) | class FullCodeInput(GridLayout):
    method __init__ (line 203) | def __init__(self, **kwargs):
    method first_number (line 210) | def first_number(self, dt):
    method _number_pressed (line 218) | def _number_pressed(self, lb):
    method change_scroll_y (line 222) | def change_scroll_y(self, txt, scroll):
    method do_bar_scroll (line 247) | def do_bar_scroll(self, txt, scroll):
    method number_me (line 254) | def number_me(self, txt, scroll):
    method do_new_line (line 273) | def do_new_line(self, txt, scroll):
    method remove_line_numbering (line 282) | def remove_line_numbering(self, txt, scroll):
  class Numbers_ (line 290) | class Numbers_(ToggleButtonBehavior, Label):
    method on_state (line 298) | def on_state(self, *args):

FILE: kivystudio/widgets/codeinput/code_extra_behavior.py
  class CodeExtraBehavior (line 4) | class CodeExtraBehavior(object):
    method do_comment (line 6) | def do_comment(self):
    method do_multiline_comment (line 36) | def do_multiline_comment(self, lines):
    method do_multiline_indent (line 56) | def do_multiline_indent(self):
    method uncomment_multiline (line 72) | def uncomment_multiline(self, lines):
    method do_one_line_comment (line 105) | def do_one_line_comment(self, line):
    method _do_my_refresh (line 133) | def _do_my_refresh(self, new_text):
    method _set_my_undo_redo (line 144) | def _set_my_undo_redo(self, find, offset, substring):
    method do_auto_indent (line 159) | def do_auto_indent(self):
    method get_closest_indentation (line 169) | def get_closest_indentation(self, lines):
    method _do_reverse_indentation (line 187) | def _do_reverse_indentation(self):
    method _multi_unindent (line 220) | def _multi_unindent(self, lines):
    method delete_word_left (line 244) | def delete_word_left(self):
    method _split_smart (line 281) | def _split_smart(self, text):

FILE: kivystudio/widgets/codeinput/code_find.py
  class CodeInputFind (line 8) | class CodeInputFind(BoxLayout):
    method on_touch_down (line 34) | def on_touch_down(self, touch):
    method find_next (line 41) | def find_next(self, search):
    method find_prev (line 95) | def find_prev(self, search):
    method find (line 151) | def find(self,search):
    method open (line 156) | def open(self,code_input):
    method dismiss (line 166) | def dismiss(self):

FILE: kivystudio/widgets/codeinput/codeinput.py
  class CodeInput (line 59) | class CodeInput(CodeNavigationBehavior, TextInput):
    method __init__ (line 92) | def __init__(self, **kwargs):
    method on_style_name (line 117) | def on_style_name(self, *args):
    method on_style (line 122) | def on_style(self, *args):
    method _create_line_label (line 126) | def _create_line_label(self, text, hint=False):
    method _get_line_options (line 154) | def _get_line_options(self):
    method _check_doc_string (line 161) | def _check_doc_string(self):
    method _get_text_width (line 189) | def _get_text_width(self, text, tab_width, _label_cached):
    method _get_bbcode (line 201) | def _get_bbcode(self, ntext):
    method _cursor_offset (line 224) | def _cursor_offset(self):
    method on_lexer (line 238) | def on_lexer(self, instance, value):
    method on_foreground_color (line 241) | def on_foreground_color(self, instance, text_color):
  class CodeInputTest (line 255) | class CodeInputTest(App):
    method build (line 256) | def build(self):

FILE: kivystudio/widgets/codeinput/styles/native_tweak.py
  class NativeTweakStyle (line 17) | class NativeTweakStyle(Style):

FILE: kivystudio/widgets/codeinput/tools.py
  function find_next (line 3) | def find_next(self, search, use_regex=False, case=False):
  function find_prev (line 50) | def find_prev(self, search, use_regex=False, case=False):

FILE: kivystudio/widgets/dropdown.py
  class DropDownBase (line 22) | class DropDownBase(HoverBehavior, DropDown):
    method on_open (line 30) | def on_open(self):
    method on_dismiss (line 33) | def on_dismiss(self):
    method on_touch_up (line 36) | def on_touch_up(self, touch):

FILE: kivystudio/widgets/filemanager/__init__.py
  class SideSelector_ (line 32) | class SideSelector_(HighlightBehavior, FocusBehavior, GridLayout):
  class SideButton_ (line 36) | class SideButton_(Button):
    method on_touch_down (line 38) | def on_touch_down(self, touch):
  class FileManager (line 44) | class FileManager(ModalView):
    method __init__ (line 56) | def __init__(self, **k):
    method get_defualt_user_dir (line 64) | def get_defualt_user_dir(self):
    method set_side_panel_dir (line 79) | def set_side_panel_dir(self, name):
    method on_path (line 84) | def on_path(self, path):
    method _go_dir_with_btn (line 102) | def _go_dir_with_btn(self, btn, *args):
    method on_open (line 113) | def on_open(self):
    method on_dismiss (line 116) | def on_dismiss(self):
    method handle_key (line 122) | def handle_key(self, keyboard, key, codepoint, text, modifier, *args):
    method reverse_dir (line 132) | def reverse_dir(self):
    method on_mode (line 138) | def on_mode(self, *args):
    method folder_selected (line 167) | def folder_selected(self, *args):
    method handle_escape (line 171) | def handle_escape(self):
    method handle_bubble (line 177) | def handle_bubble(self, btn):
    method create_new_folder (line 184) | def create_new_folder(self, textinput):
    method handle_saving (line 202) | def handle_saving(self, textinput):
    method file_selected (line 209) | def file_selected(self, obj, path):
    method on_finished (line 214) | def on_finished(self, path):
    method open_file (line 218) | def open_file(self, path='', on_selection=None):
    method save_file (line 223) | def save_file(self, path='', on_selection=None):
    method choose_dir (line 228) | def choose_dir(self, path='', on_selection=None):

FILE: kivystudio/widgets/filemanager/filechooserthumbview/__init__.py
  class IconWidget_ (line 152) | class IconWidget_(GridLayout):
    method __init__ (line 155) | def __init__(self, **kwargs):
    method on_touch_down (line 159) | def on_touch_down(self, touch):
    method on_double_tap (line 170) | def on_double_tap(self, touch):
  class FileStack_ (line 175) | class FileStack_(HighlightBehavior, FocusBehavior, StackLayout):
    method do_enter (line 178) | def do_enter(self):
  class StudioFileChooserThumbView (line 187) | class StudioFileChooserThumbView(FileChooserController):
    method __init__ (line 227) | def __init__(self, **kwargs):
    method clear_cache (line 234) | def clear_cache(self, *args):
    method _dir_has_too_much_files (line 240) | def _dir_has_too_much_files(self, path):
    method _create_entry_widget (line 249) | def _create_entry_widget(self, ctx):
    method _get_image (line 261) | def _get_image(self, ctx):
    method _generate_image_from_flac (line 330) | def _generate_image_from_flac(self, flacPath):
    method _generate_image_from_mp3 (line 350) | def _generate_image_from_mp3(self, mp3Path):
    method _generate_image_from_art (line 368) | def _generate_image_from_art(self, art, path):
    method _gen_temp_file_name (line 383) | def _gen_temp_file_name(self, extension):
    method _generate_image_from_data (line 386) | def _generate_image_from_data(self, path, extension, data):
    method _generate_image_from_video (line 395) | def _generate_image_from_video(self, videoPath):
    method _gen_label (line 413) | def _gen_label(self, ctx):
    method on_file_select (line 430) | def on_file_select(self, path):
  class ThreadedThumbnailGenerator (line 434) | class ThreadedThumbnailGenerator(object):
    method __init__ (line 439) | def __init__(self):
    method append (line 443) | def append(self, widget, ctx, func):
    method run (line 446) | def run(self):
    method _loop (line 451) | def _loop(self):
  function is_picture (line 460) | def is_picture(mime, name):
  function pix_from_art (line 472) | def pix_from_art(art):
  function get_mime (line 487) | def get_mime(fileName):
  function extract_image_from_video (line 499) | def extract_image_from_video(path, size, play_overlay):
  function get_png_from_video (line 511) | def get_png_from_video(software, video_path, size, play_overlay):
  function stack_images (line 538) | def stack_images(software, bg, fg, out):
  function exec_exists (line 543) | def exec_exists(bin):
  function compute_size (line 554) | def compute_size(maxs, imgw, imgh):
  function setlabel (line 574) | def setlabel(instance, value):

FILE: kivystudio/widgets/iconlabel.py
  class IconLabel (line 8) | class IconLabel(HoverInfoBehavior, Label):
    method __init__ (line 12) | def __init__(self, **k):
  class IconLabelButton (line 17) | class IconLabelButton(ButtonBehavior, IconLabel):
  class IconToggleLabel (line 20) | class IconToggleLabel(ToggleButtonBehavior, IconLabel):
    method on_state (line 25) | def on_state(self, *args):

FILE: kivystudio/widgets/rightclick_drop.py
  class RightClickDrop (line 7) | class RightClickDrop(BoxLayout):
    method __init__ (line 9) | def __init__(self, **kwargs):
    method on_touch_down (line 12) | def on_touch_down(self, touch):
    method on_parent (line 20) | def on_parent(self, *a):
    method _on_keyboard (line 26) | def _on_keyboard(self, instance, keycode, *args):
    method open (line 34) | def open(self):
    method dismiss (line 39) | def dismiss(self):

FILE: kivystudio/widgets/searchinput.py
  class SearchInput (line 4) | class SearchInput(TextInput):

FILE: kivystudio/widgets/splitter.py
  class StudioSplitter (line 22) | class StudioSplitter(Splitter):
  class StudioSplitterStrip (line 25) | class StudioSplitterStrip(HoverBehavior, SplitterStrip):
    method on_hover (line 29) | def on_hover(self, *args):
    method on_press (line 36) | def on_press(self):
    method on_touch_up (line 39) | def on_touch_up(self, touch):

FILE: kivystudio/widgets/tabbedpanel.py
  class StudioPanelItem (line 7) | class StudioPanelItem(TabbedPanelHeader):
    method __init__ (line 18) | def __init__(self, **kwargs):
    method add_widget (line 21) | def add_widget(self, widget):
    method remove_widget (line 24) | def remove_widget(self, widget):

FILE: setup.py
  function get_all_kv_files (line 22) | def get_all_kv_files():

FILE: tests/test_codeplace.py
  class CodePlaceTest (line 10) | class CodePlaceTest(GraphicUnitTest):
    method test_tabState (line 12) | def test_tabState(self):

FILE: tests/test_emulator.py
  class EmulatorTest (line 9) | class EmulatorTest(GraphicUnitTest):
    method setUp (line 11) | def setUp(self):
    method test_emulation (line 18) | def test_emulation(self):
    method test_changeScreen (line 25) | def test_changeScreen(self):
    method test_scaling (line 41) | def test_scaling(self):
Condensed preview — 87 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (292K chars).
[
  {
    "path": ".gitignore",
    "chars": 69,
    "preview": "*.pyc\n*.zip\n*.gif\npyc.py\n__pycache__/\n.vscode/\nbuild/\ndist/\n*egg-info"
  },
  {
    "path": "LICENSE",
    "chars": 1070,
    "preview": "MIT License\n\nCopyright (c) 2019 @mahartstudio\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
  },
  {
    "path": "README.md",
    "chars": 2978,
    "preview": "#### KivyStudio\n<!-- ![KivyStudio](https://raw.githubusercontent.com/MichaelStott/KivMob/master/demo/assets/kivmob-title"
  },
  {
    "path": "kivystudio/__init__.py",
    "chars": 323,
    "preview": "from kivy.config import Config\nConfig.set('graphics', 'width', '1000')\nConfig.set('graphics', 'height', '730')\nConfig.se"
  },
  {
    "path": "kivystudio/assembler.py",
    "chars": 2218,
    "preview": "\nfrom kivy.uix.boxlayout import BoxLayout\nfrom kivy.core.window import Window\nfrom kivy.clock import mainthread\n\nfrom ki"
  },
  {
    "path": "kivystudio/behaviors/__init__.py",
    "chars": 138,
    "preview": "from .highlightbehavior import HighlightBehavior\nfrom .hoverbehavior import HoverBehavior\nfrom .hoverinfobehavior import"
  },
  {
    "path": "kivystudio/behaviors/highlightbehavior.py",
    "chars": 7454,
    "preview": "\nfrom kivy.uix.gridlayout import GridLayout\nfrom kivy.uix.button import Button\nfrom kivy.properties import (BooleanPrope"
  },
  {
    "path": "kivystudio/behaviors/hoverbehavior.py",
    "chars": 1403,
    "preview": "\n''' A quick implementation of mouse hovering \n    just fires one event called 'on_hover'\n    when the mouse hover on a "
  },
  {
    "path": "kivystudio/behaviors/hoverinfobehavior.py",
    "chars": 1392,
    "preview": "'''\nMixin behavior widget that inherits from kivystudio.behavior.HoverBehavior\nused on a widget, to show extra infomatio"
  },
  {
    "path": "kivystudio/components/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kivystudio/components/codeplace/__init__.py",
    "chars": 453,
    "preview": "\nfrom .codeplace import CodePlace\n\nfrom kivystudio.widgets.splitter import StudioSplitter\nfrom kivystudio.components.ter"
  },
  {
    "path": "kivystudio/components/codeplace/code.kv",
    "chars": 3557,
    "preview": "\n<CodeContainer>:\n    sizable_from: 'right'\n    max_size: root.parent.width-self.parent.children[2].width if self.parent"
  },
  {
    "path": "kivystudio/components/codeplace/codeplace.py",
    "chars": 9931,
    "preview": "\nfrom kivy.uix.screenmanager import ScreenManager, Screen, NoTransition, ScreenManagerException\nfrom kivy.uix.scrollview"
  },
  {
    "path": "kivystudio/components/codeplace/tabs/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kivystudio/components/codeplace/tabs/codetab.py",
    "chars": 4049,
    "preview": "from kivy.uix.behaviors import ToggleButtonBehavior,ButtonBehavior\nfrom kivy.uix.boxlayout import BoxLayout\nfrom kivy.ui"
  },
  {
    "path": "kivystudio/components/codeplace/tabs/errortab.py",
    "chars": 138,
    "preview": "from kivy.uix.label import Label\nfrom kivy.properties import StringProperty\n\nclass FileErrorTab(Label):\n    filename = S"
  },
  {
    "path": "kivystudio/components/codeplace/tabs/welcome.kv",
    "chars": 2917,
    "preview": "#: import icon kivystudio.tools.iconfonts.icon\n#: import quicktools kivystudio.tools.quicktools\n            # IconLabel:"
  },
  {
    "path": "kivystudio/components/codeplace/tabs/welcometab.py",
    "chars": 253,
    "preview": "from kivystudio.widgets.iconlabel import IconLabel\nfrom kivy.uix.boxlayout import BoxLayout\nfrom kivy.lang import Builde"
  },
  {
    "path": "kivystudio/components/emulator_area/__init__.py",
    "chars": 2913,
    "preview": "from kivy.uix.floatlayout import FloatLayout\nfrom kivy.uix.boxlayout import BoxLayout\nfrom kivy.uix.label import Label\nf"
  },
  {
    "path": "kivystudio/components/emulator_area/emulator.kv",
    "chars": 3021,
    "preview": "#: import split os.path.split\n\n<EmulatorArea>:\n    orientation: 'vertical'\n    GridLayout:\n        canvas.before:\n      "
  },
  {
    "path": "kivystudio/components/emulator_area/screen_drop.py",
    "chars": 220,
    "preview": "from kivystudio.widgets.dropdown import DropDownBase\n\nclass ScreenDrop(DropDownBase):\n\n    def open(self, widget, screen"
  },
  {
    "path": "kivystudio/components/screens/__init__.py",
    "chars": 4363,
    "preview": "import os\n\nfrom kivy.uix.floatlayout import FloatLayout\nfrom kivy.uix.screenmanager import ScreenManager, Screen\nfrom ki"
  },
  {
    "path": "kivystudio/components/screens/screen.kv",
    "chars": 1700,
    "preview": "#: import Window kivy.core.window.Window\n\n# 398 804\n<AndroidPhoneScreen>:\n    size: container.size\n    container: contai"
  },
  {
    "path": "kivystudio/components/screens/screen_test.py",
    "chars": 1392,
    "preview": "from kivy.lang import Builder\nfrom kivy.base import runTouchApp as app\nfrom __init__ import *\n\napp(\nBuilder.load_string("
  },
  {
    "path": "kivystudio/components/sibebar/__init__.py",
    "chars": 1655,
    "preview": "from kivy.uix.boxlayout import BoxLayout\nfrom kivy.uix.label import Label\nfrom kivy.uix.behaviors import ToggleButtonBeh"
  },
  {
    "path": "kivystudio/components/sibebar/fileexplorer/__init__.py",
    "chars": 2492,
    "preview": "from kivy.uix.treeview import TreeViewLabel, TreeView\nfrom kivy.uix.screenmanager import Screen\nfrom kivy.uix.button imp"
  },
  {
    "path": "kivystudio/components/sibebar/fileexplorer/filewidgets.py",
    "chars": 2060,
    "preview": "from kivy.uix.treeview import TreeViewNode, TreeViewLabel\nfrom kivy.uix.boxlayout import BoxLayout\nfrom kivy.lang import"
  },
  {
    "path": "kivystudio/components/sibebar/generalsearch.py",
    "chars": 348,
    "preview": "from kivy.uix.screenmanager import Screen\nfrom kivy.lang import Builder\n\nBuilder.load_string('''\n<GeneralSearch>:\n    si"
  },
  {
    "path": "kivystudio/components/sibebar/gitmanager.py",
    "chars": 335,
    "preview": "from kivy.uix.screenmanager import Screen\nfrom kivy.lang import Builder\n\nBuilder.load_string('''\n<GitManager>:\n    size_"
  },
  {
    "path": "kivystudio/components/sibebar/sidebar.kv",
    "chars": 1633,
    "preview": "#: import icon kivystudio.tools.iconfonts.icon\n\n<SideBar>:\n    size_hint_x:  None\n    width: '46dp'\n    FloatLayout:\n   "
  },
  {
    "path": "kivystudio/components/terminal/__init__.py",
    "chars": 4265,
    "preview": "from kivy.uix.boxlayout import BoxLayout\nfrom kivy.uix.behaviors import ToggleButtonBehavior\nfrom kivy.uix.label import "
  },
  {
    "path": "kivystudio/components/terminal/command_terminal.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kivystudio/components/terminal/logger_space.py",
    "chars": 1390,
    "preview": "from kivy.uix.boxlayout import BoxLayout\nfrom kivy import properties as prop\nfrom kivy.lang import Builder\nfrom kivy.fac"
  },
  {
    "path": "kivystudio/components/topmenu/__init__.py",
    "chars": 2697,
    "preview": "\nfrom kivy.uix.gridlayout import GridLayout\nfrom kivy.uix.label import Label\nfrom kivy.uix.dropdown import DropDown\nfrom"
  },
  {
    "path": "kivystudio/components/topmenu/dropmenu.kv",
    "chars": 4256,
    "preview": "#: import icon kivystudio.tools.iconfonts.icon\n\n<FileTopMenu>:\n    auto_width: False\n    width: '300dp'\n    MenuButton:\n"
  },
  {
    "path": "kivystudio/components/topmenu/dropmenu.py",
    "chars": 1913,
    "preview": "from kivy.uix.behaviors import ButtonBehavior, ToggleButtonBehavior\nfrom kivy.uix.boxlayout import BoxLayout\nfrom kivy.l"
  },
  {
    "path": "kivystudio/libs/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kivystudio/libs/resizablebehavior/LICENSE",
    "chars": 1068,
    "preview": "MIT License\n\nCopyright (c) 2016 Kivy Garden\n\nPermission is hereby granted, free of charge, to any person obtaining a cop"
  },
  {
    "path": "kivystudio/libs/resizablebehavior/README.md",
    "chars": 2479,
    "preview": "# Resizable Behavior\n\nA behavior for kivy widgets that allows them to be resized by touching/clickin on a corner and dra"
  },
  {
    "path": "kivystudio/libs/resizablebehavior/__init__.py",
    "chars": 38,
    "preview": "from .resize import ResizableBehavior\n"
  },
  {
    "path": "kivystudio/libs/resizablebehavior/modal_cursor.py",
    "chars": 5185,
    "preview": "from kivy.properties import BooleanProperty, StringProperty, ListProperty\nfrom kivy.graphics import InstructionGroup\nfro"
  },
  {
    "path": "kivystudio/libs/resizablebehavior/resize.py",
    "chars": 16593,
    "preview": "'''\nResizable Behavior\n===============\n\nThe :class:`~kivy.uix.behaviors.resize.ResizableBehavior`\n`mixin <https://en.wik"
  },
  {
    "path": "kivystudio/main.kv",
    "chars": 184,
    "preview": "#: import icon kivystudio.tools.iconfonts.icon\n#: import settings kivystudio.settings.settings_obj\n\n<Assembly>:\n    orie"
  },
  {
    "path": "kivystudio/main.py",
    "chars": 814,
    "preview": "'''\nKivyStudio main.py\nentry point for the Application\n'''\n\nimport sys, os\nsys.path = [os.pardir] + sys.path\n\n# from kiv"
  },
  {
    "path": "kivystudio/parser/__init__.py",
    "chars": 6684,
    "preview": "import os, sys\nimport traceback\nfrom threading import Thread\nfrom functools import partial\ntry:\n    from importlib impor"
  },
  {
    "path": "kivystudio/resources/font-awesome.fontd",
    "chars": 15896,
    "preview": "{\"fa-camera\": 61488, \"fa-building-o\": 61687, \"fa-align-left\": 61494, \"fa-hand-o-up\": 61606, \"fa-external-link-square\": 6"
  },
  {
    "path": "kivystudio/settings.py",
    "chars": 823,
    "preview": "import os\nfrom kivy.event import EventDispatcher\nfrom kivy.config import ConfigParser\nfrom kivy.properties import Config"
  },
  {
    "path": "kivystudio/tools/__init__.py",
    "chars": 1511,
    "preview": "\nimport os\nfrom os.path import dirname, join, exists, expanduser\nfrom kivy import platform\nfrom kivy.lang import Builder"
  },
  {
    "path": "kivystudio/tools/iconfonts/LICENSE",
    "chars": 1081,
    "preview": "Copyright (c) 2010-2015 Kivy Team and other contributors\n\nPermission is hereby granted, free of charge, to any person ob"
  },
  {
    "path": "kivystudio/tools/iconfonts/README.md",
    "chars": 1655,
    "preview": "![Screenshot](https://github.com/jeysonmc/garden.iconfonts/blob/master/screenshot.png \"Scrennshot\")\n\n\nKivy-iconfonts\n==="
  },
  {
    "path": "kivystudio/tools/iconfonts/__init__.py",
    "chars": 1509,
    "preview": "\"\"\"\nKivy-iconfonts\n==============\n\nSimple helper functions to make easier to use icon fonts in Labels and derived\nwidget"
  },
  {
    "path": "kivystudio/tools/iconfonts/iconfonts.py",
    "chars": 2445,
    "preview": "import re\nimport json\nfrom collections import OrderedDict\nfrom kivy.compat import PY2\n\n_register = OrderedDict()\n\nif not"
  },
  {
    "path": "kivystudio/tools/iconfonts/test/font-awesome.css",
    "chars": 27466,
    "preview": "/*!\n *  Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome\n *  License - http://fontawesome.io/lice"
  },
  {
    "path": "kivystudio/tools/iconfonts/test/font-awesome.fontd",
    "chars": 15896,
    "preview": "{\"fa-camera\": 61488, \"fa-building-o\": 61687, \"fa-align-left\": 61494, \"fa-hand-o-up\": 61606, \"fa-external-link-square\": 6"
  },
  {
    "path": "kivystudio/tools/iconfonts/test/main.py",
    "chars": 1197,
    "preview": "from kivy.uix.label import Label\nfrom kivy.uix.boxlayout import BoxLayout\nfrom kivy.base import runTouchApp\nfrom kivy.la"
  },
  {
    "path": "kivystudio/tools/infolabel.py",
    "chars": 1046,
    "preview": "from kivy.uix.label import Label\nfrom kivy.lang import Builder\nfrom kivy.core.window import Window\n\nfrom .__init__ impor"
  },
  {
    "path": "kivystudio/tools/logger.py",
    "chars": 1564,
    "preview": "from kivy.logger import Logger as KivyLogger\nfrom kivy.utils import get_hex_from_color, escape_markup\n\nCOLORS  = {\n    '"
  },
  {
    "path": "kivystudio/tools/quicktools.py",
    "chars": 2246,
    "preview": "from kivy.logger import Logger\nimport sys\nfrom kivystudio.widgets.filemanager import filemanager\n\n\ndef open_new_file():\n"
  },
  {
    "path": "kivystudio/widgets/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kivystudio/widgets/codeinput/__init__.py",
    "chars": 10441,
    "preview": "from kivy.core.window import Window\nfrom kivy.uix.gridlayout import GridLayout\nfrom kivy.uix.label import Label\nfrom kiv"
  },
  {
    "path": "kivystudio/widgets/codeinput/code_extra_behavior.py",
    "chars": 9341,
    "preview": "''' Etra Awesome CodeInput Mixin/Behavior\n'''\n\nclass CodeExtraBehavior(object):\n\n    def do_comment(self):\n        ' com"
  },
  {
    "path": "kivystudio/widgets/codeinput/code_find.py",
    "chars": 5278,
    "preview": "from kivy.properties import BooleanProperty, ObjectProperty, StringProperty\nfrom kivy.uix.boxlayout import BoxLayout\nfro"
  },
  {
    "path": "kivystudio/widgets/codeinput/codeinput.kv",
    "chars": 5459,
    "preview": "\n<FullCodeInput>:\n    cols: 3\n    code_input: code_input\n    NumberingGrid:\n        id: number_scroll\n        size_hint_"
  },
  {
    "path": "kivystudio/widgets/codeinput/codeinput.py",
    "chars": 8610,
    "preview": "'''\nCode Input\n==========\n\n.. versionadded:: 1.5.0\n\n.. image:: images/codeinput.jpg\n\n.. note::\n\n    This widget requires"
  },
  {
    "path": "kivystudio/widgets/codeinput/styles/__init__.py",
    "chars": 42,
    "preview": "from .native_tweak import NativeTweakStyle"
  },
  {
    "path": "kivystudio/widgets/codeinput/styles/native_tweak.py",
    "chars": 2045,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\n    pygments.styles.native\n    ~~~~~~~~~~~~~~~~~~~~~~\n\n    pygments version of my \"native\" v"
  },
  {
    "path": "kivystudio/widgets/codeinput/tools.py",
    "chars": 2765,
    "preview": "import re\n\ndef find_next(self, search, use_regex=False, case=False):\n    '''Find the next occurrence of the string accor"
  },
  {
    "path": "kivystudio/widgets/dropdown.py",
    "chars": 1124,
    "preview": "from kivystudio.behaviors import HoverBehavior\nfrom kivy.uix.dropdown import DropDown\nfrom kivy.properties import Object"
  },
  {
    "path": "kivystudio/widgets/filemanager/LICENSE",
    "chars": 1100,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2019 Mahart Studios <mahartstudio.com>\n\nPermission is hereby granted, free of charg"
  },
  {
    "path": "kivystudio/widgets/filemanager/README.md",
    "chars": 2180,
    "preview": "================\nFileManager\n================\n\nA comprehensive file chooser intensively designed for the for desktop pla"
  },
  {
    "path": "kivystudio/widgets/filemanager/__init__.py",
    "chars": 8151,
    "preview": "\nfrom .filechooserthumbview import StudioFileChooserThumbView\n\nfrom kivy.uix.modalview import ModalView\nfrom kivy.uix.be"
  },
  {
    "path": "kivystudio/widgets/filemanager/filechooserthumbview/LICENSE",
    "chars": 1110,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2013-2014 Davide Depau <me AT davideddu DOR org>\n\nPermission is hereby granted, fre"
  },
  {
    "path": "kivystudio/widgets/filemanager/filechooserthumbview/__init__.py",
    "chars": 17296,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\n\"\"\"StudioFileChooserThumbView\n====================\n\nThe StudioFileChooser"
  },
  {
    "path": "kivystudio/widgets/filemanager/filemanager.kv",
    "chars": 7211,
    "preview": "#: import win kivy.core.window.Window\n#: import Clock kivy.clock.Clock\n\n\n<FileManager>:\n    _dir_selector: dir_selector\n"
  },
  {
    "path": "kivystudio/widgets/iconlabel.py",
    "chars": 929,
    "preview": "from kivy.uix.label import Label\nfrom kivy.uix.behaviors import ToggleButtonBehavior, ButtonBehavior\nfrom kivy import pr"
  },
  {
    "path": "kivystudio/widgets/rightclick_drop.py",
    "chars": 1455,
    "preview": "from kivy.uix.boxlayout import BoxLayout\nfrom kivy.core.window import Window\nfrom kivy.lang import Builder\n\nfrom kivystu"
  },
  {
    "path": "kivystudio/widgets/searchinput.py",
    "chars": 606,
    "preview": "from kivy.uix.textinput import TextInput\nfrom kivy.lang import Builder\n\nclass SearchInput(TextInput):\n    pass\n\nBuilder."
  },
  {
    "path": "kivystudio/widgets/splitter.py",
    "chars": 1566,
    "preview": "from kivy.uix.splitter import Splitter, SplitterStrip\nfrom kivy.lang import Builder\nfrom kivy.core.window import Window\n"
  },
  {
    "path": "kivystudio/widgets/tabbedpanel.py",
    "chars": 753,
    "preview": "from kivy.properties import ObjectProperty\nfrom kivy.uix.floatlayout import FloatLayout\nfrom kivy.uix.tabbedpanel import"
  },
  {
    "path": "project/prjtTest1.htm",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "project/prjtTest1.js",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "repoTest1.js",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "repoTest2.htm",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "setup.py",
    "chars": 1965,
    "preview": "'''\nSetup.py\n========\n'''\n\nfrom os.path import dirname, join, abspath\nimport io,os\n\ntry:\n    from setuptools import setu"
  },
  {
    "path": "tests/test_codeplace.py",
    "chars": 884,
    "preview": "\nfrom kivy.tests.common import GraphicUnitTest\nfrom kivy.base import EventLoop\n\nimport sys\nfrom os.path import dirname\ns"
  },
  {
    "path": "tests/test_emulator.py",
    "chars": 1581,
    "preview": "\nfrom kivy.tests.common import GraphicUnitTest\nfrom kivy.base import EventLoop\n\nimport sys\nfrom os.path import dirname\ns"
  },
  {
    "path": "to-do.txt",
    "chars": 390,
    "preview": "\nTo-Do List\n\n* FilExplorer\n* CodeInput Search\n* Auto Suggestion in CodeInput\n* Bottom Menu\n* Custom terminal (Command Li"
  }
]

About this extraction

This page contains the full source code of the mahart-studio/kivystudio GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 87 files (268.2 KB), approximately 75.8k tokens, and a symbol index with 418 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!