dresscode 0.0.5
Dress up your code with a beautiful graphical user interface !
License: MIT
Requires Python: >=3.5
Keywords: gui,productivity,framework,python,pyrustic,tkinter,desktop-application,lightweight

<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-animated-logo.gif" alt="Cover">
    <br>
    <p align="center">
    </p>
</div>



<!-- Intro Text -->
# Dresscode
<b> Dress up your code with a beautiful graphical user interface ! </b>

This project is part of the [Pyrustic Ecosystem](https://github.com/pyrustic/pyrustic#overview). Look powered by the [cyberpunk](https://github.com/pyrustic/tk-cyberpunk-theme#readme) theme.

Beta version. Only for early-adopters !

<!-- Quick Links -->
[Installation](#installation) | [Reference](https://github.com/pyrustic/dresscode/tree/master/docs/reference#readme)


# Showcase

Welcome ! Let me show you something:

<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-1.png" alt="Figure" width="650">
    <p align="center">
    <b> Figure 1 - Demo </b>
    </p>
</div>

What if I told you that I did this with `1 Hex-digit lines of code` :tm: ?

The menu bar in `Figure 1` is not a gimmick. Clicking on the buttons in the menu bar opens another page. So in fact I showed only 1/3 of the pages !

Let's take a look at the other pages:

<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-2.png" alt="Figure" width="650">
    <p align="center">
    <b> Figure 2 - 1 hex-digit lines of code generated an app with 3 pages ! </b>
    </p>
</div>


Now you are wondering how I did this with just `1 hex-digit lines of code` :tm:.

Well, I first defined the first page:

```python
from dresscode import page

home_page = page.Page(pid="home", name="Home")
home_page.add_entry(title="Username")
home_page.add_entry(title="Password", secretive=True)
home_page.add_button(new_row=True)
```

Then I defined the second page:

```python
from dresscode import page

edit_page = page.Page(pid="edit", name="Edit")
edit_page.add_entry(title="Username")
edit_page.add_button(on_click=lambda page, cid: page.show_toast("Hello"))
```

Then the third page:

```python
from dresscode import page

about_page = page.Page(pid="about", name="About")
about_page.add_button(text="Open Github")
about_page.add_button(text="Download the Wheel")
```


And then I created the app and linked the three pages to it.
```python
from dresscode import app, page
...
my_app = app.App(title="Dresscode Demo", width=450, height=150, home="home")
my_app.add_page(home_page)
my_app.add_page(edit_page)
my_app.add_page(about_page)
my_app.start()
```

The 1 hex-digit lines of code:

```python
from dresscode import app, page
my_app = app.App(title="Dresscode Demo", width=450, height=150, home="home")
home_page = page.Page(pid="home", name="Home")
home_page.add_entry(title="Username")
home_page.add_entry(title="Password", secretive=True)
home_page.add_button(new_row=True)
edit_page = page.Page(pid="edit", name="Edit")
edit_page.add_entry(title="Username")
edit_page.add_button(on_click=lambda page, cid: page.show_toast("Hello"))
about_page = page.Page(pid="about", name="About")
about_page.add_button(text="Open Github")
about_page.add_button(text="Download the Wheel")
my_app.add_page(home_page)
my_app.add_page(edit_page)
my_app.add_page(about_page)
my_app.start()
```



<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-3.gif" alt="Figure" width="650">
    <p align="center">
    <b> Figure 3 - Demo Animation </b>
    </p>
</div>

Voilà !

This is the full source code with comment and well structured:

```python
from dresscode.app import App
from dresscode.page import Page


def get_home_page():
    # defining the home page here
    page = Page(pid="home", name="Home")  # pid = page id !
    page.add_entry(title="Username")
    page.add_entry(title="Password", secretive=True)  # secret secret !
    page.add_button(new_row=True)
    return page


def get_edit_page():
    page = Page(pid="edit", name="Edit")
    page.add_entry(title="Username")
    # Clicking this button will pop up a "Hello"
    page.add_button(on_click=lambda page, cid: page.show_toast("Hello"))
    return page


def get_about_page():
    page = Page(pid="about", name="About")
    page.add_button(text="Open Github")
    page.add_button(text="Download the Wheel")
    return page


# the home argument is the pid of the page to show at start up
app = App(title="Dresscode Demo", width=450, height=150, home="home")

# adding pages to the app !
app.add_page(get_home_page())
app.add_page(get_edit_page())
app.add_page(get_about_page())

# lift up !
app.start()  # the mainloop is hidden here ! ;)

```

Basically, you can just `pip install dresscode`, open a lightweight code editor, copy, paste, run the code and yeah it should work ! Try it !

Wondering what will happen when there are 10 pages ? Yes your menu bar will be full. The solution: buy large screens !

Joking aside, here's the solution:

```python
...
# Asking Dresscode to create a dropdown menu 'Menu'
# then stack inside it the references to the pages ! 
app.add_page(home_page, category="Menu")
app.add_page(edit_page, category="Menu")
app.add_page(about_page, category="Menu")
...

```
<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-4.png" alt="Figure" width="650">
    <p align="center">
    <b> Figure 4 - No need to buy large screens ! </b>
    </p>
</div>


## Installation

```bash

pip install dresscode --upgrade --upgrade-strategy eager

```


## Interaction with Dresscode
_Dress up your code with a beautiful graphical user interface !_ was the intro to this README. There is a clear distinction between the backend and the frontend. The question that arises is therefore how to communicate the frontend and the backend.

With `Dresscode`, you can specify when creating a component which handler to call when a particular event occurs.

With the button component, there are the `on_click` parameter to keep a reference to the event handler. So basically, you just need to have a handler with 2 parameters: `page` and `cid`.

```python
from dresscode.app import App
from dresscode.page import Page


def handler(page, cid):
    """
    page: the page object
    cid: the component id (here, the button cid)
    """
    # say 'Hello' !
    page.show_toast("Hello component {}".format(cid))
    # you can inspect the dict of components (keys are cid)
    components = page.components  # be curious, inspect the dict !
    # you can retrieve the data from a component
    username = page.read_component("username")
    # or you can display a large text
    page.show_text("Helloo\n{}".format(username), title="My large text")
    # or, ask for a confirmation
    ok = page.ask_confirmation()  # blocks the app, returns a boolean
    # you can even decide to scroll the content of the page
    page.scroll(value=1.0)
    # you can add a new page at runtime !!!
    app = page.app
    app.add_page(Page(pid="new_page", name="New"))
    # and guess what, you can open this new page !
    app.open_page("new_page")
    # and if you are in a hurry to open the home page
    app.open_home()


def get_home_page():
    # home page - a pid will be generated automatically if you don't set it
    page = Page(pid="home", name="Home")
    page.add_entry(cid="username", title="Username")
    # if you don't set a cid, it will be generated
    page.add_button(on_click=handler)  # a cid will be generated automatically

    # Note, if you click the button twice, you will get a:
    # dresscode.exception.DresscodeException
    # Duplicate page id isn't allowed (new_page) !
    # Guess why ! This isn't a bug but a feature ! hahaha !
    return page


app = App(title="Dresscode Demo", width=450, height=150, home="home")

app.add_page(get_home_page())

# lift up !
app.start()

```



## Components

Do you think `Dresscode` only offers two components, the input field and the button ?

Normally that would be enough. But I implemented a multitude of components to allow everyone to build applications quickly, from the simplest to the most complex.

### Checkbuttons

<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-5.png" alt="Figure" width="650">
    <p align="center">
    <b> Figure 5 - Checkbuttons </b>
    </p>
</div>

```python
from dresscode.app import App
from dresscode.page import Page


def get_home_page():
    page = Page(pid="home", name="Home")
    items = ("Banana", "Apple", "Avocado")
    page.add_checkbutton(title="Choose your favorite fruits", items=items)
    # you could add a on_choice event handler ;)
    return page


app = App(title="Dresscode Demo", width=450, height=150, home="home")

app.add_page(get_home_page())

# lift up !
app.start()

```

### Dropdown list

<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-6.png" alt="Figure" width="650">
    <p align="center">
    <b> Figure 6 - Drop-down list </b>
    </p>
</div>

```python
from dresscode.app import App
from dresscode.page import Page


def get_home_page():
    page = Page(pid="home", name="Home")
    items = ("Banana", "Apple", "Avocado")
    page.add_dropdown_list(title="Choose your favorite fruit", items=items)
    # you could add a on_choice event handler ;)
    return page


app = App(title="Dresscode Demo", width=450, height=150, home="home")

app.add_page(get_home_page())

# lift up !
app.start()

```

### Editor

<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-7.png" alt="Figure" width="650">
    <p align="center">
    <b> Figure 7 - Editor </b>
    </p>
</div>

```python
from dresscode.app import App
from dresscode.page import Page


def get_home_page():
    page = Page(pid="home", name="Home")
    essay = "non est ad astra mollis e terris via\nSénèque"
    page.add_editor(title="My essay", text=essay, readonly=True)
    # you could change the width and or height...
    return page


app = App(title="Dresscode Demo", width=450, height=150, home="home")

app.add_page(get_home_page())

# lift up !
app.start()

```

### Label

<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-8.png" alt="Figure" width="650">
    <p align="center">
    <b> Figure 8 - Label </b>
    </p>
</div>

```python
from dresscode.app import App
from dresscode.page import Page


def get_home_page():
    page = Page(pid="home", name="Home")
    page.add_label(text="Marvelous")
    page.add_label(text="Dresscode", color="white")
    page.add_label(text="Project", color="cyan")
    text = "Make Desktop Apps Great Again !"
    page.add_label(new_row=True, text=text, color="gray",
                   side="right",
                   font=("Corrier", 10))
    return page


app = App(title="Dresscode Demo", width=450, height=150, home="home")

app.add_page(get_home_page())

# lift up !
app.start()

```

### Radiobuttons

<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-9.png" alt="Figure" width="650">
    <p align="center">
    <b> Figure 9 - Radiobuttons </b>
    </p>
</div>

```python
from dresscode.app import App
from dresscode.page import Page


def get_home_page():
    page = Page(pid="home", name="Home")
    items = ("Blue", "Red")
    page.add_radiobutton(title="Make a choice", items=items)

    return page


app = App(title="Dresscode Demo", width=450, height=150, home="home")

app.add_page(get_home_page())

# lift up !
app.start()

```

### Space

<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-10.png" alt="Figure" width="650">
    <p align="center">
    <b> Figure 10 - SpaceX </b>
    </p>
</div>

```python
from dresscode.app import App
from dresscode.page import Page


def get_home_page():
    page = Page(pid="home", name="Home")
    items = ("Blue", "Red")
    page.add_button()
    page.add_button()
    page.add_space()  # you can alter the width, height and more...
    page.add_button()

    return page


app = App(title="Dresscode Demo", width=450, height=150, home="home")

app.add_page(get_home_page())

# lift up !
app.start()

```

### Spinbox

<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-11.png" alt="Figure" width="650">
    <p align="center">
    <b> Figure 11 - Spinbox </b>
    </p>
</div>

```python
from dresscode.app import App
from dresscode.page import Page


def get_home_page():
    page = Page(pid="home", name="Home")
    items = ("Blue", "Red")
    page.add_spinbox(title="Make a choice", items=items)
    return page


app = App(title="Dresscode Demo", width=450, height=150, home="home")

app.add_page(get_home_page())

# lift up !
app.start()

```


### path entry
The path entry is part of [megawidget](https://github.com/pyrustic/megawidget) !

<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-12.png" alt="Figure" width="650">
    <p align="center">
    <b> Figure 12 - Pathentry </b>
    </p>
</div>

```python
from dresscode.app import App
from dresscode.page import Page


def get_home_page():
    page = Page(pid="home", name="Home")
    page.add_path_entry(title="Directory", browse="dir")
    page.add_path_entry(new_row=True, title="File")
    return page


app = App(title="Dresscode Demo", width=450, height=150, home="home")

app.add_page(get_home_page())

# lift up !
app.start()

```

### Table
The table is part of [megawidget](https://github.com/pyrustic/megawidget) !

<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-13.png" alt="Figure" width="650">
    <p align="center">
    <b> Figure 13 - Table </b>
    </p>
</div>

```python
from dresscode.app import App
from dresscode.page import Page


def get_home_page():
    page = Page(pid="home", name="Home")
    columns = ("Name", "Age", "Gender")
    data = [("Jack", 45, "Male"), ("Jane", 37, "Female"), ("Alex", 100, "?")]
    page.add_table(title="My data", columns=columns, data=data)
    return page


app = App(title="Dresscode Demo", width=650, height=300, home="home")

app.add_page(get_home_page())

# lift up !
app.start()

```

### Image
Admit that you didn't expect this !

<!-- Image -->
<div align="center">
    <img src="https://raw.githubusercontent.com/pyrustic/misc/master/media/dresscode-figure-14.png" alt="Figure" width="650">
    <p align="center">
    <b> Figure 14 - Image </b>
    </p>
</div>


```python
from dresscode.app import App
from dresscode.page import Page


def get_home_page():
    page = Page(pid="home", name="Home")
    page.add_label(text="Welcome !", side=None, anchor="center", color="gray")
    with open("/home/alex/dresscode.png", "rb") as file:
        image = file.read()
    # to center any component, the trick: side=None, anchor="center" !
    page.add_image(new_row=True, image=image, side=None, anchor="center")
    page.add_label(text="https://github.com/pyrustic", side=None, anchor="center",
                   font=("Courrier", 10), new_row=True, color="gray")
    return page


app = App(title="Dresscode Demo", width=650, height=400, home="home")

app.add_page(get_home_page())

# lift up !
app.start()

```

### Cherry on the cake

Since we have this rebellious little side to wanting to customize everything, I implemented the possibility of adding custom components !

```python

# WARNING: THIS SNIPPET IS DEPRECATED
# WAIT FOR A STABLE VERSION

from dresscode.app import App
from dresscode.page import Page


# I will cover this topic another time !


def data_getter(page, cid):
    data = None
    return data


def builder(page, cid):
    parts = {}
    return parts, data_getter


def get_home_page():
    page = Page(pid="home", name="Home")
    page.add_custom(builder=builder)
    return page


app = App(title="Dresscode Demo", width=650, height=400, home="home")

app.add_page(get_home_page())

# lift up !
app.start()

```

There you go, so I won't be asked to add new components ! :)



Work in progress...