├── .github
└── workflows
│ └── python-publish.yml
├── .gitignore
├── LICENSE
├── MANIFEST.in
├── README.md
├── __init__.py
├── assets
├── IMG_3260.PNG
└── README.md
├── docs
└── get_bard_token.md
├── fletsb
├── __init__.py
├── __main__.py
├── edit.py
├── engines
│ ├── __init__.py
│ ├── bardai_engine.py
│ ├── edit_subwidgets_engine.py
│ ├── edit_widget_engine.py
│ ├── suggesting_engine.py
│ └── viewer_engine.py
├── load_storyboard.py
├── pages
│ ├── Settings
│ │ ├── __init__.py
│ │ └── pages.py
│ ├── __init__.py
│ ├── create_new_file.py
│ ├── main_page.py
│ └── settings.py
├── sections
│ ├── __init__.py
│ ├── edit_section.py
│ ├── left_section.py
│ └── preview_section.py
├── tools
│ ├── __init__.py
│ ├── color_picker.py
│ ├── create_storyboard.py
│ ├── get_url_icon.py
│ ├── list_picker.py
│ ├── page_info.py
│ └── storyboard_class.py
├── ui_toolkit
│ ├── __init__.py
│ └── widget_browser_frame.py
└── widgets
│ ├── All.py
│ ├── __init__.py
│ └── widgets
│ ├── __init__.py
│ ├── button.py
│ ├── column.py
│ ├── image.py
│ ├── label.py
│ ├── markdown.py
│ ├── navigator.py
│ ├── open_url.py
│ ├── padding.py
│ ├── paragraph.py
│ ├── row.py
│ ├── textfield.py
│ └── title.py
├── pyproject.toml
├── rules
├── about_me.json
├── all.json
└── signin_rules.json
└── setup.py
/.github/workflows/python-publish.yml:
--------------------------------------------------------------------------------
1 | # This workflow will upload a Python Package using Twine when a release is created
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
3 |
4 | # This workflow uses actions that are not certified by GitHub.
5 | # They are provided by a third-party and are governed by
6 | # separate terms of service, privacy policy, and support
7 | # documentation.
8 |
9 | name: Upload Python Package
10 |
11 | on:
12 | release:
13 | types: [published]
14 |
15 | permissions:
16 | contents: read
17 |
18 | jobs:
19 | deploy:
20 |
21 | runs-on: ubuntu-latest
22 |
23 | steps:
24 | - uses: actions/checkout@v3
25 | - name: Set up Python
26 | uses: actions/setup-python@v3
27 | with:
28 | python-version: '3.x'
29 | - name: Install dependencies
30 | run: |
31 | python -m pip install --upgrade pip
32 | pip install build
33 | - name: Build package
34 | run: python -m build
35 | - name: Publish package
36 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
37 | with:
38 | user: __token__
39 | password: ${{ secrets.PYPI_API_TOKEN }}
40 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .env
106 | .venv
107 | env/
108 | venv/
109 | ENV/
110 | env.bak/
111 | venv.bak/
112 |
113 | # Spyder project settings
114 | .spyderproject
115 | .spyproject
116 |
117 | # Rope project settings
118 | .ropeproject
119 |
120 | # mkdocs documentation
121 | /site
122 |
123 | # mypy
124 | .mypy_cache/
125 | .dmypy.json
126 | dmypy.json
127 |
128 | # Pyre type checker
129 | .pyre/
130 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Yousef Aladwani
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include fletsb/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Flet StoryBoard
2 | Flet StoryBoard is a python library that have an easy to use tools for building graphical interfaces based on python `flet` library. Powerful interfaces with simple usability. Build the UI with ease of `fletsb`, then connect it with your back-end!
3 |
4 | ## Goal 🏁
5 | My goal is to allow programmers to focus on the back-end, and build the front-end using just a simple easy-to-use window without any front-end coding require.
6 |
7 | ## installation ⬇️
8 | - Python > 3.7
9 |
10 | You can try Flet_StoryBoard on web!, just click here: [fletsb on web](https://skbarbon.github.io/wfletsb/)
11 |
12 | For install:
13 | > `pip install Flet_StoryBoard`
14 |
15 | for Upgrade:
16 | > `pip install Flet_StoryBoard --upgrade`
17 |
18 | ## Little Peek
19 |
20 |
21 |
22 | ## What's new on `Flet_StoryBoard` `1.0` 🎉
23 | - ReSupport custom widgets with flet.
24 | - Multiple pages support.
25 | - New Suggestions
26 | - New way to load the StoryBoard on your app.
27 | - The ability to add external `flet` controls inside the StoryBoard.
28 | - New Feature called `Smart suggestions`. It gets your goal then suggest things based on it.
29 | - Support templates. A template is a file contain pre-set props for all StoryBoard's widgets, like fonts and default text color. - soon -
30 | - ReBuild the architecture of the library.
31 | * Please read the docs to know more about library usage. [docs page](https://github.com/SKbarbon/Flet_StoryBoard/wiki)
32 | * if there is any another issues not fixed yet, please create an issue here: [issues page](https://github.com/SKbarbon/Flet_StoryBoard/issues)
33 |
34 |
35 | ## usage & examples 🤝
36 | You can use the editor just from the web!, click here to start:
37 | [fletsb on web](https://skbarbon.github.io/wfletsb)
38 |
39 | There is a very simple docs here about library usage.
40 | [docs page](https://github.com/SKbarbon/Flet_StoryBoard/wiki)
41 |
42 | ### create/edit your own StoryBoard
43 | ```cmd
44 | python3 -m fletsb.edit myUI.fletsb
45 | ```
46 | It will edit the existing one or create a new one if not.
47 |
48 | ### load a StoryBoard
49 | To load your StoryBoard on your app, you can do this example code:
50 |
51 | ```python
52 | from fletsb import LoadStoryBoard, StoryBoard
53 |
54 | def main (storyBoard:StoryBoard):
55 | pass
56 |
57 | LoadStoryBoard(target_function=main, storyboard_file_path="myUI.fletsb")
58 | ```
59 |
60 | To know more about the `StoryBoard` class, follow the [docs page](https://github.com/SKbarbon/Flet_StoryBoard/wiki) .
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/85fbe95030d7def96f59b0ad37ea32f324f2af87/__init__.py
--------------------------------------------------------------------------------
/assets/IMG_3260.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/85fbe95030d7def96f59b0ad37ea32f324f2af87/assets/IMG_3260.PNG
--------------------------------------------------------------------------------
/assets/README.md:
--------------------------------------------------------------------------------
1 | assets dir
2 |
--------------------------------------------------------------------------------
/docs/get_bard_token.md:
--------------------------------------------------------------------------------
1 | # How to get bard API token ?
2 | To get your bard API token, open google bard page: (Google bard)[https://bard.google.com/], then open the inspector.
3 |
4 |
5 |
6 | Then open the "Application" page, then find the `https://bard.google.com` section that under the cookies. Then search for `__Secure-1PSID` then copy its value.
7 |
8 |
9 |
10 | ## Dont share it with any one!
11 |
--------------------------------------------------------------------------------
/fletsb/__init__.py:
--------------------------------------------------------------------------------
1 | from .load_storyboard import LoadStoryBoard
2 | from .tools.storyboard_class import StoryBoard
--------------------------------------------------------------------------------
/fletsb/__main__.py:
--------------------------------------------------------------------------------
1 | print("""
2 | These are all 'Flet_StoryBoard' commands:
3 |
4 | .edit: For create/edit an exist storyboard => python3 -m Flet_StoryBoard.edit
5 |
6 | """)
--------------------------------------------------------------------------------
/fletsb/edit.py:
--------------------------------------------------------------------------------
1 | from .pages.create_new_file import CreateNewFile
2 | from .pages.main_page import mainPage
3 | import sys
4 | import os
5 | import flet
6 |
7 | cmd_args = sys.argv
8 | debug_mode = False
9 | if "--debug" in cmd_args:
10 | debug_mode = True
11 |
12 |
13 | class manage_edit:
14 | def __init__(self) -> None:
15 | self.cmd_args = sys.argv
16 | self.file_name = None
17 | flet.app(target=self.CNF)
18 |
19 | if self.file_name is None and debug_mode:
20 | print("Debug alert: Unexpected exit, no errors.")
21 | sys.exit("Exit.")
22 | return
23 |
24 | if self.file_name is None:
25 | sys.exit("Exit.")
26 | return
27 |
28 | if not str(self.file_name).endswith(".fletsb"):
29 | self.file_name = str(self.file_name) + ".fletsb"
30 |
31 | if debug_mode:
32 | print("Debug alert: About to run the editor.")
33 |
34 | mainPage(self.file_name)
35 |
36 | def CNF(self, page):
37 | CreateNewFile(page, manage_class=self)
38 |
39 |
40 | if len(cmd_args) == 1:
41 | # To create a new file.
42 | if debug_mode:
43 | print("Debug alert: About to show the 'CreateNewFile' window.")
44 | manage_edit()
45 | else:
46 | # To edit an existing File.
47 | full_path = ""
48 | for i in range(1, len(cmd_args)):
49 | if full_path == "":
50 | full_path = full_path + cmd_args[i]
51 | else:
52 | full_path = full_path + " " + cmd_args[i]
53 |
54 | full_path = full_path.replace(" --debug", "")
55 | full_path = full_path.replace("--debug", "")
56 |
57 | if os.path.isfile(full_path):
58 | if debug_mode:
59 | print("Debug alert: About to run the editor.")
60 | mainPage(full_path)
61 | else:
62 | print(f"Warning: File not found '{full_path}', so create a new one.")
63 | if debug_mode:
64 | print("Debug alert: About to show the 'CreateNewFile' window.")
65 | manage_edit()
66 |
--------------------------------------------------------------------------------
/fletsb/engines/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/85fbe95030d7def96f59b0ad37ea32f324f2af87/fletsb/engines/__init__.py
--------------------------------------------------------------------------------
/fletsb/engines/bardai_engine.py:
--------------------------------------------------------------------------------
1 | """
2 | The bardAPI integration.
3 | """
4 | from bardapi import Bard
5 | import os, flet, random, time, json, requests
6 |
7 |
8 | new_widgets_template = """
9 | You are an AI for UI builder in a software called `Flet_StoryBoard`. Users will ask you to make something on their storyboard. The storyboard is a actually a json file that contain a UI stuff. Note that all your responses must be as json syntax. If a user tell you anything that unrelated to your job, return a `ok=false` on json. You can add new widgets. If the user ask you to put a widget that is not defined down bellow, then you choose one of the available widgets bellow that are similar to it.
10 | Please make sure that you are making a good UI/UX practice with the widgets properties. For example if the title is on center alianment then make the paragraph alianment also in center. The page color is , so make sure that you are not using the same color of the page color for the text color so the user can see the text.
11 |
12 | The widgets are available are with their own properties:
13 | - Title: title, title_color, size, width, italic, bold, hide, expand, alignment, text_align.
14 | - Paragraph: text, text_color, size, width, italic, bold, hide, alignment, text_align.
15 | - Button: text, function_name, text_color, bgcolor, alignment, width, height, hide.
16 | - Markdown: content, width, height, alignment.
17 | - Open Url: text, url, text_color, bgcolor, alignment, width, height, border_radius, hide.
18 | - Image: src, width, height, border_radius, alignment.
19 | - TextField: text, label, hint_text, width, height, border_radius, bgcolor, color, alignment.
20 |
21 | Note: do NOT set the `widget_class_name` to a name that does not exists above.
22 |
23 | This is an example of how your json responses must look like:
24 | ```json
25 | {
26 | "all" : [
27 | {
28 | "widget_class_name": "Title",
29 | "properties": {
30 | "title": "myTitle",
31 | "title_color": "white",
32 | "size": 23,
33 | "width": 350,
34 | "italic": false,
35 | "bold": true,
36 | "hide": false,
37 | "expand": false,
38 | "alignment": "center",
39 | "text_align": "left"
40 | }
41 | },
42 | {
43 | "widget_class_name": "Title",
44 | "properties": {
45 | "title": "myTitle2",
46 | "title_color": "white",
47 | "size": 23,
48 | "width": 350,
49 | "italic": false,
50 | "bold": true,
51 | "hide": false,
52 | "expand": false,
53 | "alignment": "center",
54 | "text_align": "left"
55 | }
56 | }
57 | ]
58 | }
59 | ```
60 |
61 | The user message is:
62 | ```user_message
63 |
64 | ```
65 |
66 | Try not to put the user message on any widget except if he did ask for it.
67 | Please make sure that you are making a good UI/UX practice with the widgets properties. For example if the title is on center alianment then make the paragraph alianment also in center. The page color is , so make sure that you are not using the same color of the page color for the text color so the user can see the text.
68 | Use each widget for its correct job. For example if you want a link to open in the browser, use the `Open Url` widget.
69 | Dont set the `widget_class_name` on the json to a name that does not exists above, For example if the user ask for a text, there is no Text widget, so you must search for a similar supported widget like the `title`.
70 | Do not use any widget name except: Title, Button, Markdown, Open Url, Image or TextField.
71 | Put all the widgets as shown on the previous json example.
72 | """
73 |
74 | class BardapiSupport:
75 | def __init__(self) -> None:
76 | self.bard_init()
77 |
78 | def push_ui (self, push_on_top_views_function, main_class):
79 | main_class.main_row.opacity = 0.2
80 | main_class.main_row.update()
81 |
82 | self.main_class = main_class
83 | container = flet.Container(on_click=self.close_the_input)
84 | self.container = container
85 |
86 | if self.get_bard_token() == None:
87 | bard_token = flet.TextField(hint_text="Put your bard Token..",
88 | bgcolor="white", color="black", on_submit=self.save_the_token)
89 | container.content = flet.Column([
90 | flet.Row([flet.Text("Your Bard Token")], alignment="center"),
91 | flet.Row([bard_token], alignment="center"),
92 | flet.Row([flet.Container(flet.Text("How to get the API token? Its totally free!", color="blue"), on_click=self.how_to_get_bard_token_page)], alignment="center")
93 | ], alignment="center")
94 | self.ress = push_on_top_views_function(self.container)
95 | if bard_token.page != None:
96 | bard_token.focus()
97 | else:
98 | ai_message_input = flet.TextField(
99 | border_radius=18,
100 | hint_text="",
101 | bgcolor="white",
102 | on_submit=self.on_message_submit,
103 | color="black"
104 | )
105 |
106 | container.content = flet.Column([
107 | flet.Row([ai_message_input], alignment="center"),
108 | flet.Row([flet.Text("The Bard AI", color="white")], alignment="center")
109 | ], alignment="center")
110 | self.ress = push_on_top_views_function(self.container)
111 |
112 | if ai_message_input.page != None:
113 | ai_message_input.focus()
114 |
115 | texts = ["Image with random cat image..", "A title that contain a cat emoji..", "A simple sign in page.."]
116 | for i in str(random.choice(texts)):
117 | ai_message_input.hint_text = ai_message_input.hint_text + i
118 | ai_message_input.update()
119 | time.sleep(0.02)
120 |
121 | def on_message_submit (self, e):
122 | e.control.disabled = True
123 | e.control.update()
124 |
125 | try: result = self.ask_bard(e.control.value)
126 | except:
127 | print("Error with connecting with bard."); self.close_the_input(self.container); return
128 |
129 | try:
130 | result = self.load_the_respone_to_dict(result)
131 | except Exception as e:
132 | print(f"Error:\n{e}")
133 | self.close_the_input(self.container)
134 | return
135 |
136 | for new_widget in result['all']:
137 | wid = self.main_class.add_new_widget(new_widget["widget_class_name"])
138 | wid.update(new_widget['properties'])
139 | self.main_class.preview_section.update_preview(self.main_class.current_page_name)
140 | self.main_class.edit_a_widget(len(self.main_class.dict_content["pages"][self.main_class.current_page_name]["widgets"]) - 1)
141 | self.main_class.page.update()
142 |
143 | self.close_the_input(self.container)
144 |
145 | def close_the_input (self, e):
146 | self.main_class.main_row.opacity = 1.0
147 | self.main_class.main_row.update()
148 | self.ress()
149 |
150 | def get_bard_token (self):
151 | if not os.path.isfile (".bardapi"):
152 | return None
153 |
154 | bardapi_token = open(".bardapi", encoding="utf-8").read()
155 |
156 | return bardapi_token
157 |
158 | def bard_init(self):
159 | token = self.get_bard_token()
160 | if token is None:
161 | return False
162 |
163 | os.environ['_BARD_API_KEY'] = str(token)
164 |
165 | session = requests.Session()
166 | self.session = session
167 | session.headers = {
168 | "Host": "bard.google.com",
169 | "X-Same-Domain": "1",
170 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36",
171 | "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
172 | "Origin": "https://bard.google.com",
173 | "Referer": "https://bard.google.com/",
174 | }
175 | session.cookies['__Secure-1PSID'] = os.environ.get("_BARD_API_KEY")
176 | self.bard = Bard(session=session, timeout=12)
177 |
178 | def ask_bard (self, message):
179 | self.container.content = flet.Column([flet.Row([
180 | flet.Text("The AI is thinking 😃!", weight="bold", size=26, color="white")
181 | ], alignment="center")], alignment="center")
182 | self.container.update()
183 |
184 | token = self.get_bard_token()
185 | if token == None:
186 | return False
187 |
188 | os.environ['_BARD_API_KEY'] = f"{token}"
189 | message_new = new_widgets_template.replace("", message)
190 | message_new = str(message_new).replace("", str(self.main_class.page.bgcolor))
191 | return str(self.bard.get_answer(message_new)['content'])
192 |
193 | def load_the_respone_to_dict (self, respone:str):
194 | full_string = ""
195 | found_it = False
196 | for i in str(respone).split("\n"):
197 | if found_it:
198 | if str(i).startswith("```"):
199 | break
200 | full_string = full_string + f"\n{i}"
201 |
202 | if str(i).startswith("```json"):
203 | found_it = True
204 |
205 | return json.loads(full_string)
206 |
207 | def how_to_get_bard_token_page (self, e):
208 | p : flet.Page = e.page
209 | p.launch_url("https://github.com/SKbarbon/Flet_StoryBoard/blob/main/docs/get_bard_token.md")
210 | self.close_the_input(e)
211 |
212 | def save_the_token (self, token):
213 | token = token.control.value
214 | open(".bardapi", "w+", encoding="utf-8").write(token)
215 | self.close_the_input(token)
--------------------------------------------------------------------------------
/fletsb/engines/edit_subwidgets_engine.py:
--------------------------------------------------------------------------------
1 | import flet
2 |
3 | from ..widgets.All import all_widgets
4 | from ..tools.color_picker import ColorPicker
5 | from ..tools.list_picker import ListPopup
6 |
7 |
8 | # main_widget_mother_class: is the widgets mother like row or column.
9 | class EditSubWidgetsEngine:
10 | def __init__(self, main_class, main_widget_mother_class, section_view: flet.Column, widget_number) -> None:
11 | self.main_class = main_class
12 | self.main_widget_mother_class = main_widget_mother_class
13 | self.section_view = section_view
14 | self.widget_number = widget_number
15 |
16 | self.all_fields = {}
17 |
18 | self.show_edit_tools()
19 |
20 | def show_edit_tools(self):
21 | # Update the ViewerEngine.
22 | self.main_class.preview_section.update_preview(self.main_class.current_page_name)
23 |
24 | # start
25 | self.section_view.clean()
26 | content = self.main_widget_mother_class.template["widgets"]
27 | class_name = content[self.widget_number]["widget_class_name"]
28 | widget_content = content[self.widget_number]
29 |
30 | # widget not found
31 | if class_name not in all_widgets:
32 | self.section_view.controls.append(
33 | flet.Row(
34 | [
35 | flet.Text(
36 | f"There is no supported\nwidget named '{class_name}'.",
37 | color=flet.colors.WHITE
38 | )
39 | ]
40 | )
41 | )
42 | return
43 |
44 | the_class = all_widgets[class_name]["class"]
45 | the_class = the_class(
46 | self.main_class,
47 | self.main_widget_mother_class.preview_section,
48 | widget_number=self.widget_number
49 | )
50 | default_args = the_class.args
51 |
52 | title = flet.Text(f"Edit {class_name}", size=25, weight=flet.FontWeight.BOLD, color=flet.colors.WHITE)
53 | self.section_view.controls.append(title)
54 |
55 | for t in widget_content["properties"]:
56 | prop_name = t
57 | prop_value = widget_content["properties"][t]
58 | if prop_name not in default_args:
59 | print("Error while load widget properties in edit engine.")
60 | self.section_view.clean()
61 | return
62 | prop_type = default_args[prop_name]["type"]
63 |
64 | # This statement below is for adding the fields for edit a widget.
65 | if isinstance(prop_type(), str):
66 | tf = flet.TextField(width=160, bgcolor=flet.colors.WHITE, color=flet.colors.BLACK, label=prop_name)
67 | tf.value = prop_value
68 | self.section_view.controls.append(flet.Row([tf], alignment=flet.MainAxisAlignment.CENTER))
69 | self.all_fields[prop_name] = tf
70 | if "multi_line" in default_args[prop_name]:
71 | tf.multiline = True
72 |
73 | elif isinstance(prop_type(), int):
74 | slid = flet.Slider(min=0, max=500, divisions=500, label="{value}", width=160)
75 | slid.value = int(prop_value)
76 | self.section_view.controls.append(
77 | flet.Row(
78 | [flet.Text(f"{prop_name}:", color=flet.colors.WHITE, width=150)],
79 | alignment=flet.MainAxisAlignment.CENTER
80 | )
81 | )
82 | self.section_view.controls.append(flet.Row([slid], alignment=flet.MainAxisAlignment.CENTER))
83 | self.all_fields[prop_name] = slid
84 |
85 | elif isinstance(prop_type(), bool):
86 | tog = flet.Switch()
87 | tog.value = prop_value
88 | self.section_view.controls.append(
89 | flet.Row([flet.Text(f"{prop_name}", color=flet.colors.WHITE, size=13), tog],
90 | alignment=flet.MainAxisAlignment.CENTER, spacing=25))
91 | self.all_fields[prop_name] = tog
92 |
93 | elif type(prop_type()) == type(ColorPicker()):
94 | self.section_view.controls.append(flet.Text(""))
95 | colp = ColorPicker(
96 | self.section_view,
97 | selected_color=prop_value,
98 | add_it=False,
99 | title_name=prop_name,
100 | drop_width=120
101 | )
102 | self.section_view.controls.append(flet.Row([colp.v], alignment=flet.MainAxisAlignment.CENTER))
103 | self.all_fields[prop_name] = colp
104 |
105 | elif isinstance(prop_type(), list):
106 | dr = flet.Dropdown(width=160, label=prop_name)
107 | for i in default_args[prop_name]["options"]:
108 | dr.options.append(flet.dropdown.Option(f"{i}"))
109 | dr.value = prop_value
110 | self.section_view.controls.append(flet.Row([dr], alignment=flet.MainAxisAlignment.CENTER))
111 | self.all_fields[prop_name] = dr
112 |
113 | elif type(prop_type()) == type(ListPopup()):
114 | lp = ListPopup(default_args[prop_name]["options"], self.main_class, prop_value, prop_name)
115 | self.section_view.controls.append(flet.Row([lp.self_ui], alignment=flet.MainAxisAlignment.CENTER))
116 | self.all_fields[prop_name] = lp
117 |
118 | # This button below for widgets that support sub-widgets.
119 | if hasattr(the_class, "support_sub_widgets"):
120 | add_sub_widget_button = flet.TextButton("Add sub-widget", on_click=the_class.widgets_to_add_in)
121 | self.section_view.controls.append(
122 | flet.Row([add_sub_widget_button], alignment=flet.MainAxisAlignment.CENTER))
123 |
124 | # This slider below is for rearranging the widget on the page.
125 | rearrange_slider = flet.Slider(
126 | min=0,
127 | max=len(content),
128 | value=self.widget_number,
129 | label="{value}",
130 | width=160,
131 | divisions=len(content)
132 | )
133 | self.section_view.controls.append(
134 | flet.Row([flet.Text(f"reArrange:", color=flet.colors.WHITE, width=150)],
135 | alignment=flet.MainAxisAlignment.CENTER))
136 | self.section_view.controls.append(flet.Row([rearrange_slider], alignment=flet.MainAxisAlignment.CENTER))
137 | self.rearrange_slider = rearrange_slider
138 |
139 | self.section_view.controls.append(flet.Text("\n"))
140 | # Down bellow is for done_button and delete_btn.
141 | done_button = flet.ElevatedButton(
142 | "Done",
143 | bgcolor=flet.colors.WHITE,
144 | color=flet.colors.BLACK,
145 | width=150,
146 | height=40,
147 | on_click=self.done_edit
148 | )
149 | self.section_view.controls.append(flet.Row([done_button], alignment=flet.MainAxisAlignment.CENTER))
150 |
151 | delete_button = flet.TextButton(
152 | content=flet.Text(
153 | "delete",
154 | color=flet.colors.RED,
155 | size=13
156 | ),
157 | on_click=self.delete_widget
158 | )
159 | self.section_view.controls.append(flet.Row([delete_button], alignment=flet.MainAxisAlignment.CENTER))
160 |
161 | def done_edit(self, *args):
162 | new_widget_properties_dict = {}
163 | for P in self.all_fields:
164 | new_widget_properties_dict[P] = self.all_fields[P].value
165 |
166 | if int(self.widget_number) == int(self.rearrange_slider.value):
167 | # If the widget arrange is the same.
168 | self.main_widget_mother_class.template["widgets"][self.widget_number]["properties"].update(
169 | new_widget_properties_dict)
170 | else:
171 | # If the widget arrange is NOT the same.
172 | if int(self.rearrange_slider.value) >= int(len(self.main_widget_mother_class.template["widgets"])):
173 | self.main_widget_mother_class.template["widgets"][self.widget_number]["properties"].update(
174 | new_widget_properties_dict)
175 | copy_of_content = self.main_widget_mother_class.template["widgets"][self.widget_number]
176 | del self.main_widget_mother_class.template["widgets"][self.widget_number]
177 |
178 | self.main_widget_mother_class.template["widgets"].append(copy_of_content)
179 |
180 | self.widget_number = int(len(self.main_widget_mother_class.template["widgets"]) - 1)
181 | else:
182 | self.main_widget_mother_class.template["widgets"][self.widget_number]["properties"].update(
183 | new_widget_properties_dict)
184 | copy_of_content = self.main_widget_mother_class.template["widgets"][self.widget_number]
185 |
186 | self.main_widget_mother_class.template["widgets"][int(self.rearrange_slider.value)] = copy_of_content
187 | del self.main_widget_mother_class.template["widgets"][self.widget_number]
188 |
189 | self.widget_number = int(self.rearrange_slider.value)
190 |
191 | # Update the viewer engine to see the edit changes.
192 | self.main_widget_mother_class.update_preview()
193 | self.main_class.preview_section.update_preview(self.main_class.current_page_name)
194 | self.main_class.page.update()
195 |
196 | # Reopen the editor again
197 | EditSubWidgetsEngine(
198 | main_class=self.main_class,
199 | main_widget_mother_class=self.main_widget_mother_class,
200 | section_view=self.section_view,
201 | widget_number=self.widget_number
202 | )
203 | self.main_class.page.update()
204 |
205 | def delete_widget(self, *args):
206 | del self.main_widget_mother_class.template["widgets"][self.widget_number]
207 | self.section_view.clean()
208 |
209 | # Update the ViewerEngine to see the edit changes.
210 | self.main_class.preview_section.update_preview(self.main_class.current_page_name)
211 | self.main_class.page.update()
212 |
--------------------------------------------------------------------------------
/fletsb/engines/edit_widget_engine.py:
--------------------------------------------------------------------------------
1 | import flet
2 |
3 | from ..widgets.All import all_widgets
4 | from ..tools.color_picker import ColorPicker
5 | from ..tools.list_picker import ListPopup
6 |
7 |
8 | class EditWidgetsEngine:
9 | def __init__(self, main_class, section_view: flet.Column, widget_number) -> None:
10 | self.main_class = main_class
11 | self.section_view = section_view
12 | self.widget_number = widget_number
13 |
14 | self.current_page_name = self.main_class.current_page_name
15 | self.all_fields = {}
16 |
17 | self.show_edit_tools()
18 |
19 | def show_edit_tools(self):
20 | self.section_view.clean()
21 | content = self.main_class.dict_content
22 | class_name = content["pages"][self.current_page_name]["widgets"][self.widget_number]["widget_class_name"]
23 | widget_content = content["pages"][self.current_page_name]["widgets"][self.widget_number]
24 |
25 | if class_name not in all_widgets:
26 | # if widget not found.
27 | self.section_view.controls.append(
28 | flet.Row(
29 | [flet.Text(f"There is no supported\nwidget named '{class_name}'.", color=flet.colors.WHITE)]
30 | )
31 | )
32 | return
33 |
34 | the_class = all_widgets[class_name]["class"]
35 | the_class = the_class(
36 | self.main_class,
37 | self.main_class.preview_section.main_view,
38 | widget_number=self.widget_number
39 | )
40 | default_args = the_class.args
41 |
42 | title = flet.Text(f"Edit {class_name}", size=25, weight=flet.FontWeight.BOLD, color=flet.colors.WHITE)
43 | self.section_view.controls.append(title)
44 |
45 | # ---Remove the not defualt arg-----
46 | props_updated = dict(widget_content["properties"])
47 | for checker in widget_content["properties"]:
48 | if checker not in default_args:
49 | props_updated.pop(checker)
50 | widget_content["properties"] = dict(props_updated)
51 | # ---Remove the not defualt arg-----
52 |
53 | for t in widget_content["properties"]:
54 | prop_name = t
55 | prop_value = widget_content["properties"][t]
56 | if prop_name not in default_args:
57 | print("Error while load widget properties in edit engine.")
58 | self.section_view.clean()
59 | return
60 | prop_type = default_args[prop_name]["type"]
61 |
62 | # These statements below are for adding the fields for edit a widget.
63 | if isinstance(prop_type(), str):
64 | tf = flet.TextField(width=160, bgcolor=flet.colors.WHITE, color=flet.colors.BLACK, label=prop_name)
65 | tf.value = prop_value
66 | self.section_view.controls.append(flet.Row([tf], alignment=flet.MainAxisAlignment.CENTER))
67 | self.all_fields[prop_name] = tf
68 | if "multi_line" in default_args[prop_name]:
69 | tf.multiline = True
70 |
71 | elif type(prop_type()) == type(int()):
72 | slid = flet.Slider(min=0, max=500, divisions=500, label="{value}", width=160)
73 | slid.value = int(prop_value)
74 | self.section_view.controls.append(
75 | flet.Row(
76 | [
77 | flet.Text(
78 | f"{prop_name}:",
79 | color=flet.colors.WHITE,
80 | width=150
81 | )
82 | ], alignment=flet.MainAxisAlignment.CENTER
83 | )
84 | )
85 | self.section_view.controls.append(
86 | flet.Row(
87 | [slid],
88 | alignment=flet.MainAxisAlignment.CENTER
89 | )
90 | )
91 | self.all_fields[prop_name] = slid
92 |
93 | elif type(prop_type()) == type(bool()):
94 | tog = flet.Switch()
95 | tog.value = prop_value
96 | self.section_view.controls.append(
97 | flet.Row([flet.Text(f"{prop_name}", color=flet.colors.WHITE, size=13), tog],
98 | alignment=flet.MainAxisAlignment.CENTER, spacing=25))
99 | self.all_fields[prop_name] = tog
100 |
101 | elif type(prop_type()) == type(ColorPicker()):
102 | self.section_view.controls.append(flet.Text(""))
103 | colp = ColorPicker(self.section_view, selected_color=prop_value, add_it=False, title_name=prop_name,
104 | drop_width=120)
105 | self.section_view.controls.append(flet.Row([colp.v], alignment=flet.MainAxisAlignment.CENTER))
106 | self.all_fields[prop_name] = colp
107 |
108 | elif isinstance(prop_type(), list):
109 | dr = flet.Dropdown(width=160, label=prop_name)
110 | for i in default_args[prop_name]["options"]:
111 | dr.options.append(flet.dropdown.Option(f"{i}"))
112 | dr.value = prop_value
113 | self.section_view.controls.append(flet.Row([dr], alignment=flet.MainAxisAlignment.CENTER))
114 | self.all_fields[prop_name] = dr
115 |
116 | elif type(prop_type()) == type(ListPopup()):
117 | lp = ListPopup(default_args[prop_name]["options"], self.main_class, prop_value, prop_name)
118 | self.section_view.controls.append(flet.Row([lp.self_ui], alignment=flet.MainAxisAlignment.CENTER))
119 | self.all_fields[prop_name] = lp
120 |
121 | # This button below for widgets that support sub-widgets.
122 | if hasattr(the_class, "support_sub_widgets"):
123 | add_sub_widget_button = flet.TextButton("Add sub-widget", on_click=the_class.widgets_to_add_in)
124 | self.section_view.controls.append(
125 | flet.Row(
126 | [add_sub_widget_button],
127 | alignment=flet.MainAxisAlignment.CENTER
128 | )
129 | )
130 |
131 | # This slider bellow is for rearrange the widget on the page.
132 | rearrange_slider = flet.Slider(
133 | min=0,
134 | max=len(content["pages"][self.current_page_name]["widgets"]),
135 | value=self.widget_number,
136 | label="{value}",
137 | width=160,
138 | divisions=len(content["pages"][self.current_page_name]["widgets"])
139 | )
140 | self.section_view.controls.append(
141 | flet.Row(
142 | [flet.Text(f"reArrange:", color=flet.colors.WHITE, width=150)],
143 | alignment=flet.MainAxisAlignment.CENTER
144 | )
145 | )
146 | self.section_view.controls.append(flet.Row([rearrange_slider], alignment=flet.MainAxisAlignment.CENTER))
147 | self.rearrange_slider = rearrange_slider
148 |
149 | self.section_view.controls.append(flet.Text("\n"))
150 | # Down bellow is for done_button and delete_btn.
151 | done_button = flet.ElevatedButton(
152 | "Done",
153 | bgcolor=flet.colors.WHITE,
154 | color=flet.colors.BLACK,
155 | width=150,
156 | height=40,
157 | on_click=self.done_edit
158 | )
159 | self.section_view.controls.append(
160 | flet.Row(
161 | [done_button],
162 | alignment=flet.MainAxisAlignment.CENTER
163 | )
164 | )
165 |
166 | delete_button = flet.TextButton(
167 | content=flet.Text("delete", color=flet.colors.RED, size=13),
168 | on_click=self.delete_widget
169 | )
170 | self.section_view.controls.append(
171 | flet.Row(
172 | [delete_button],
173 | alignment=flet.MainAxisAlignment.CENTER
174 | )
175 | )
176 |
177 | def done_edit(self, *args):
178 | new_widget_properties_dict = {}
179 | for P in self.all_fields:
180 | new_widget_properties_dict[P] = self.all_fields[P].value
181 |
182 | if int(self.widget_number) == int(self.rearrange_slider.value):
183 | # If the widget arrange is the same.
184 | self.main_class.dict_content["pages"][self.current_page_name]["widgets"][self.widget_number][
185 | "properties"].update(new_widget_properties_dict)
186 | else:
187 | # If the widget arrange is NOT the same.
188 | if int(self.rearrange_slider.value) >= int(
189 | len(self.main_class.dict_content["pages"][self.main_class.current_page_name]["widgets"])):
190 | self.main_class.dict_content["pages"][self.current_page_name]["widgets"][self.widget_number][
191 | "properties"].update(new_widget_properties_dict)
192 | copy_of_content = self.main_class.dict_content["pages"][self.current_page_name]["widgets"][
193 | self.widget_number]
194 | del self.main_class.dict_content["pages"][self.current_page_name]["widgets"][self.widget_number]
195 |
196 | self.main_class.dict_content["pages"][self.current_page_name]["widgets"].append(copy_of_content)
197 |
198 | self.widget_number = int(
199 | len(self.main_class.dict_content["pages"][self.current_page_name]["widgets"]) - 1)
200 | else:
201 | self.main_class.dict_content["pages"][self.current_page_name]["widgets"][self.widget_number][
202 | "properties"].update(new_widget_properties_dict)
203 | copy_of_content = self.main_class.dict_content["pages"][self.current_page_name]["widgets"][
204 | self.widget_number]
205 |
206 | self.main_class.dict_content["pages"][self.current_page_name]["widgets"][
207 | int(self.rearrange_slider.value)] = copy_of_content
208 | del self.main_class.dict_content["pages"][self.current_page_name]["widgets"][self.widget_number]
209 |
210 | self.widget_number = int(self.rearrange_slider.value)
211 |
212 | # Update the viewer engine to see the edit changes.
213 | self.main_class.preview_section.update_preview(self.main_class.current_page_name)
214 | self.main_class.page.update()
215 |
216 | # ReOpen the editor again
217 | EditWidgetsEngine(
218 | main_class=self.main_class,
219 | section_view=self.section_view,
220 | widget_number=self.widget_number
221 | )
222 | self.main_class.page.update()
223 |
224 | def delete_widget(self, *args):
225 | del self.main_class.dict_content["pages"][self.current_page_name]["widgets"][self.widget_number]
226 | self.section_view.clean()
227 |
228 | # Update the viewer engine to see the edit changes.
229 | self.main_class.preview_section.update_preview(self.main_class.current_page_name)
230 | self.main_class.page.update()
231 |
--------------------------------------------------------------------------------
/fletsb/engines/suggesting_engine.py:
--------------------------------------------------------------------------------
1 | import json
2 | import flet
3 | import random
4 | import os
5 | import requests
6 |
7 |
8 | class SuggestingEngine:
9 | def __init__(self, main_class):
10 | self.main_class = main_class
11 |
12 | self.main_col = flet.Column(
13 | width=self.main_class.left_section.main_container.width,
14 | height=self.main_class.left_section.main_container.height,
15 | # issue: True is not a valid value for the scroll mode. Use flet.SCROLL_MODE
16 | scroll=True
17 | )
18 |
19 | def push_new_suggestion(self):
20 | settings = self.main_class.dict_content["storyboard_settings"]
21 | applied = settings["storyboard_suggestions"]
22 |
23 | # if `storyboard suggestions` is off.
24 | if not applied:
25 | return
26 |
27 | suggestions_rules_name = self.main_class.dict_content["pages"][self.main_class.current_page_name]["settings"][
28 | "suggestions_rules"]
29 |
30 | if suggestions_rules_name == "none":
31 | return
32 |
33 | # Get the rules file
34 | if not os.path.isdir("rules"):
35 | os.mkdir("rules")
36 |
37 | if not os.path.isfile(f"rules/{suggestions_rules_name}.json"):
38 | all_rules = requests.get("https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/main/rules/all.json").text
39 | all_rules = json.loads(all_rules)
40 |
41 | if suggestions_rules_name not in all_rules["all_rules"]:
42 | return
43 | else:
44 | rf = requests.get(all_rules["all_rules"][suggestions_rules_name]).text
45 | open(f"rules/{suggestions_rules_name}.json", "w+", encoding="utf-8").write(rf)
46 |
47 | rules_file = json.loads(open(f"rules/{suggestions_rules_name}.json", encoding="utf-8").read())
48 |
49 | # step1: Get current widgets.
50 | current_widgets = list(self.main_class.dict_content["pages"][self.main_class.current_page_name]["widgets"])
51 |
52 | # step2: Count classes on widgets.
53 | classes_in_widgets = {}
54 | for c in current_widgets:
55 | if c["widget_class_name"] not in classes_in_widgets:
56 | classes_in_widgets[c["widget_class_name"]] = 1
57 | else:
58 | classes_in_widgets[c["widget_class_name"]] = classes_in_widgets[c["widget_class_name"]] + 1
59 |
60 | # step3: Search for the correct case on the rules file.
61 | for rule in rules_file["rules"]:
62 | if rule["case"] == classes_in_widgets:
63 | self.change_left_section_into_suggestion(rule["sugs"])
64 | break
65 |
66 | def change_left_section_into_suggestion(self, suggestions):
67 | def go_back(e):
68 | if last_on_section == self.main_col:
69 | self.main_class.left_section.show_all_widgets()
70 | else:
71 | self.main_class.left_section.show_new_content(last_on_section)
72 |
73 | main_col = self.main_col
74 | main_col.controls.clear()
75 |
76 | back_btn = flet.TextButton("< Back", on_click=go_back)
77 | main_col.controls.append(back_btn)
78 |
79 | title = flet.Text("Suggestions ✨", weight=flet.FontWeight.BOLD, size=22, color=flet.colors.WHITE)
80 | main_col.controls.append(title)
81 |
82 | main_col.controls.append(
83 | flet.Row(
84 | [flet.Text("", color=flet.colors.WHITE, size=13)],
85 | alignment=flet.MainAxisAlignment.CENTER
86 | )
87 | )
88 |
89 | for sug in suggestions:
90 | sc = self.suggestion_card(sug, go_back)
91 | main_col.controls.append(
92 | flet.Row(
93 | [sc],
94 | alignment=flet.MainAxisAlignment.CENTER
95 | )
96 | )
97 |
98 | last_on_section = self.main_class.left_section.main_container
99 | self.main_class.left_section.show_new_content(self.main_col)
100 |
101 | def suggestion_card(self, suggestion_dict, go_back_function):
102 | def add_widget(e):
103 | go_back_function(e)
104 | w = self.main_class.add_new_widget(suggestion_dict["class"])
105 | w.update(suggestion_dict["props"])
106 | self.main_class.preview_section.update_preview(self.main_class.current_page_name)
107 | self.main_class.edit_a_widget(len(self.main_class.dict_content["pages"][self.main_class.current_page_name]["widgets"]) - 1)
108 | self.main_class.page.update()
109 |
110 | colors = [flet.colors.WHITE, "#F5DEE5", flet.colors.YELLOW]
111 |
112 | card_container = flet.Container(
113 | bgcolor=random.choice(colors),
114 | width=170,
115 | height=225,
116 | border_radius=13
117 | )
118 | column = flet.Column()
119 | card_container.content = column
120 |
121 | class_name = suggestion_dict["class"]
122 | why_to_add = suggestion_dict["about"]
123 |
124 | title = flet.Text(
125 | value=f"\n {class_name}",
126 | size=23,
127 | weight=flet.FontWeight.BOLD,
128 | color=flet.colors.BLACK,
129 | width=card_container.width
130 | )
131 | about = flet.Text(
132 | value=f"{why_to_add}",
133 | size=13,
134 | color=flet.colors.BLACK,
135 | width=card_container.width - 37,
136 | height=90
137 | )
138 | apply_button = flet.Container(
139 | flet.Row(
140 | [flet.Text("Add", color="white")],
141 | alignment=flet.MainAxisAlignment.CENTER
142 | ),
143 | bgcolor=flet.colors.BLACK,
144 | width=card_container.width - 15,
145 | height=40,
146 | border_radius=13,
147 | on_click=add_widget
148 | )
149 |
150 | column.controls.append(title)
151 | column.controls.append(flet.Row([about], alignment=flet.MainAxisAlignment.CENTER))
152 | column.controls.append(
153 | flet.Row(
154 | [apply_button],
155 | alignment=flet.MainAxisAlignment.CENTER
156 | )
157 | )
158 |
159 | # issue: column is not updated: column.update()
160 |
161 | return card_container
162 |
--------------------------------------------------------------------------------
/fletsb/engines/viewer_engine.py:
--------------------------------------------------------------------------------
1 | from flet import Page, Container
2 | import flet
3 |
4 | from ..widgets.All import all_widgets
5 |
6 |
7 | class viewerEngine:
8 | def __init__ (self, main_class, content_dict:dict, page_name, parent_view, widgets_parent_view, development=True):
9 | """
10 | This is the engine of preview.
11 | parent_view -> is the Container in the develop case, and Page in the production case
12 | widgets_parent_view -> is the Column in the develop case, and Page in the production case
13 | """
14 | self.main_class = main_class
15 | self.content = content_dict
16 | self.page_name = page_name
17 | self.parent_view = parent_view
18 | self.widgets_parent_view = widgets_parent_view
19 | self.development = development
20 |
21 | self.last_clicked = None # last widget clicked to edit. this is for make a border color around it to know its selected.
22 |
23 | self.update_page()
24 | self.push_views()
25 |
26 | def push_views (self):
27 | page_name : str = self.page_name
28 | content = self.content["pages"][page_name]
29 | sub_widgets = content["widgets"]
30 |
31 | self.widgets_parent_view.controls.clear()
32 | num = 0
33 | for widget in sub_widgets:
34 | if widget["widget_class_name"] in all_widgets:
35 | widget_class = all_widgets[widget["widget_class_name"]]["class"]
36 | widget_class = widget_class(self.main_class, self.widgets_parent_view, widget_number=num)
37 | if hasattr(widget_class, "support_sub_widgets"):
38 | widget_class.update(widget["properties"], widget["widgets"])
39 | else:
40 | widget_class.update(widget["properties"])
41 | if self.development:
42 | self.create_development_container(widget_class.return_widget(), num)
43 | else:
44 | self.widgets_parent_view.controls.append(widget_class.return_widget())
45 | num = num + 1
46 |
47 |
48 | def update_page (self):
49 | p : flet.Container = self.parent_view
50 | page_settings = self.content["pages"][self.page_name]["settings"]
51 | bgcolor = page_settings["bgcolor"]
52 | p.bgcolor = bgcolor
53 |
54 | if "allow_scroll" in self.main_class.dict_content["storyboard_settings"]:
55 | self.widgets_parent_view.scroll = self.main_class.dict_content["storyboard_settings"]["allow_scroll"]
56 |
57 | def create_development_container (self, cls, widget_number):
58 | def on_click (cls):
59 | if self.last_clicked != None:
60 | self.last_clicked.border = None
61 | self.last_clicked = c
62 | self.last_clicked.border = flet.border.all(2, flet.colors.BLUE_100)
63 | #? This function will call the main_page edit.
64 | self.main_class.edit_a_widget(widget_number)
65 |
66 | c = flet.Container(cls, on_click=on_click, border_radius=8)
67 | self.widgets_parent_view.controls.append(c)
68 | return c
--------------------------------------------------------------------------------
/fletsb/load_storyboard.py:
--------------------------------------------------------------------------------
1 | from .engines.viewer_engine import viewerEngine
2 | from .tools.storyboard_class import StoryBoard
3 | from .widgets.All import all_widgets
4 | import json
5 | import flet
6 |
7 |
8 | class LoadStoryBoard:
9 | def __init__(self, target_function, storyboard_file_path: str, view=flet.FLET_APP):
10 | # set up the important props
11 | self.current_page_name = "main"
12 | self.file_path = storyboard_file_path
13 | self.development_mode = False
14 | self.all_widgets = all_widgets
15 | self.dict_content = json.loads(open(self.file_path, encoding="utf-8").read())
16 | self.target_function = target_function
17 |
18 | # copy of things
19 | self.viewerEngine = viewerEngine
20 | # Run the app.
21 | flet.app(target=self.run, view=view)
22 |
23 | def run(self, page: flet.Page):
24 | self.storyboard_class = StoryBoard(page=page, main_class=self)
25 | page.vertical_alignment = page.vertical_alignment = flet.MainAxisAlignment.CENTER
26 | self.page = page
27 | ve = viewerEngine(self, self.dict_content, self.current_page_name, page, page, self.development_mode)
28 | self.target_function(self.storyboard_class)
29 | page.update()
--------------------------------------------------------------------------------
/fletsb/pages/Settings/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/85fbe95030d7def96f59b0ad37ea32f324f2af87/fletsb/pages/Settings/__init__.py
--------------------------------------------------------------------------------
/fletsb/pages/Settings/pages.py:
--------------------------------------------------------------------------------
1 | import flet
2 |
3 | from ...tools.color_picker import ColorPicker
4 |
5 |
6 | def page_settings_page(settings_class):
7 | def allow_scrolling(e):
8 | settings_class.main_class.dict_content["storyboard_settings"]["allow_scroll"] = e.control.value
9 | page: flet.Page = settings_class.page
10 | page.show_snack_bar(
11 | flet.SnackBar(
12 | flet.Text(f"Done! But this is not saved, you must go click 'Save' on the editor."),
13 | open=True
14 | )
15 | )
16 | settings_class.main_class.preview_section.update_preview()
17 | page.update()
18 |
19 | def on_change_bgcolor(color):
20 | settings_class.main_class.dict_content["pages"][current_page_name]["settings"]["bgcolor"] = color
21 | page: flet.Page = settings_class.page
22 | page.show_snack_bar(
23 | flet.SnackBar(
24 | flet.Text(f"Done! But this is not saved, you must go click 'Save' on the editor."),
25 | open=True
26 | )
27 | )
28 | settings_class.main_class.preview_section.update_preview()
29 | page.update()
30 |
31 | v = settings_class.page_viewing_section
32 | v.clean()
33 |
34 | current_page_name = settings_class.main_class.current_page_name
35 | title = flet.Text(
36 | f"\n Pages - {current_page_name}",
37 | color=flet.colors.WHITE,
38 | weight=flet.FontWeight.BOLD,
39 | size=28
40 | )
41 | v.controls.append(title)
42 |
43 | if "allow_scroll" not in settings_class.main_class.dict_content["storyboard_settings"]:
44 | settings_class.main_class.dict_content["storyboard_settings"]["allow_scroll"] = False
45 |
46 | row_allow_scrolling = flet.Row(
47 | [
48 | flet.Text("Allow scrolling", color="white", width=300),
49 | flet.Switch(
50 | on_change=allow_scrolling,
51 | value=settings_class.main_class.dict_content["storyboard_settings"]["allow_scroll"]
52 | )
53 | ],
54 | alignment=flet.MainAxisAlignment.CENTER
55 | )
56 | v.controls.append(row_allow_scrolling)
57 |
58 | cp = ColorPicker(v, settings_class.main_class.dict_content["pages"][current_page_name]["settings"]["bgcolor"],
59 | on_choose_color=on_change_bgcolor, add_it=False, title_name="bgcolor")
60 | v.controls.append(
61 | flet.Container(
62 | flet.Row(
63 | [cp.v],
64 | alignment=flet.MainAxisAlignment.CENTER
65 | ),
66 | bgcolor=flet.colors.BLACK
67 | )
68 | )
69 |
70 | v.update()
71 |
--------------------------------------------------------------------------------
/fletsb/pages/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/85fbe95030d7def96f59b0ad37ea32f324f2af87/fletsb/pages/__init__.py
--------------------------------------------------------------------------------
/fletsb/pages/create_new_file.py:
--------------------------------------------------------------------------------
1 | import flet
2 | import time
3 | import os
4 | import json
5 | import requests
6 |
7 | from ..tools.create_storyboard import Create_StoryBoard
8 |
9 |
10 | class CreateNewFile:
11 | def __init__(self, page: flet.Page, manage_class):
12 | page.window_resizable = False
13 | page.update()
14 | page.window_center()
15 |
16 | # Set page prop
17 | page.bgcolor = flet.colors.BLACK
18 |
19 | # Setup Content's mother.
20 | self.manage_class = manage_class
21 | self.page = page
22 | self.mother = flet.AnimatedSwitcher(
23 | expand=True,
24 | content=flet.Text(""),
25 | transition=flet.AnimatedSwitcherTransition.FADE,
26 | duration=500,
27 | reverse_duration=250,
28 | switch_in_curve=flet.AnimationCurve.EASE_IN
29 | )
30 | page.add(self.mother)
31 |
32 | time.sleep(0.3)
33 | # Run the first page.
34 | self.page_one()
35 |
36 | def page_one(self):
37 | page = self.page
38 | mother = self.mother
39 | main_column = flet.Column()
40 | mother.content = main_column
41 |
42 | main_column.controls.append(flet.Text("\n\n"))
43 |
44 | title_1 = flet.Text(
45 | "\n Let's imagine 😃,\n What if there is a ...",
46 | color=flet.colors.WHITE,
47 | size=36,
48 | weight=flet.FontWeight.BOLD
49 | )
50 | describe = flet.Text(
51 | " Everything start from the imagine skill.\n With Flet_StoryBoard you will make the impossible ✨.\n",
52 | color=flet.colors.WHITE60,
53 | size=15
54 | )
55 | next_button = flet.Container(
56 | flet.Row(
57 | [flet.Text("Start", color=flet.colors.BLACK)],
58 | alignment=flet.MainAxisAlignment.CENTER
59 | ),
60 | bgcolor=flet.colors.WHITE,
61 | width=100,
62 | height=35,
63 | border_radius=11,
64 | on_click=self.page_two
65 | )
66 |
67 | main_column.controls.append(title_1)
68 | main_column.controls.append(describe)
69 | main_column.controls.append(
70 | flet.Column(
71 | [
72 | flet.Row(
73 | [next_button],
74 | alignment=flet.MainAxisAlignment.END
75 | )
76 | ],
77 | alignment=flet.MainAxisAlignment.END,
78 | expand=True
79 | )
80 | )
81 |
82 | page.update()
83 |
84 | def page_two(self, *args):
85 | def on_type(event):
86 | if event.control.value == "":
87 | next_button.tooltip = "You must pick a name."
88 | next_button.disabled = True
89 | next_button.update()
90 | else:
91 | next_button.tooltip = "Click to generate the file."
92 | next_button.disabled = False
93 | page.title = "Flet StoryBoard - " + str(event.control.value)
94 | if os.path.isfile(f"{page.title}.fletsb"):
95 | page.title = page.title + " | Warning: File name exist"
96 | page.update()
97 | self.file_name = str(event.control.value)
98 |
99 | page = self.page
100 | mother = self.mother
101 | main_column = flet.Column()
102 | mother.content = main_column
103 |
104 | main_column.controls.append(flet.Text("\n\n"))
105 |
106 | Title1 = flet.Text("\n Hey sir 🎩,\n What is the name ?", color=flet.colors.WHITE, size=36, weight="bold")
107 | main_column.controls.append(Title1)
108 |
109 | describe = flet.Text(
110 | " Lets choose a name of our UI.\n This name is the same as StoryBoad file name!.\n",
111 | color=flet.colors.WHITE60, size=15)
112 | main_column.controls.append(describe)
113 |
114 | StoryBoard_Name = flet.TextField(label="UI name", border_color=flet.colors.BLACK, cursor_color=flet.colors.BLACK,
115 | bgcolor=flet.colors.WHITE, border_radius=19, width=350, height=60, on_change=on_type,
116 | color=flet.colors.BLACK, on_submit=self.page_three)
117 | main_column.controls.append(flet.Row([StoryBoard_Name], alignment="center"))
118 |
119 | next_button = flet.Container(flet.Row([flet.Text("Generate", color=flet.colors.BLACK)], alignment="center"),
120 | bgcolor=flet.colors.WHITE, width=100, height=35, border_radius=11, on_click=self.page_three,
121 | disabled=True)
122 | main_column.controls.append(
123 | flet.Column([flet.Row([next_button], alignment="END")], alignment="END", expand=True))
124 |
125 | mother.update()
126 | page.update()
127 |
128 | def page_three(self, *args):
129 | page = self.page
130 | page.title = page.title
131 | mother = self.mother
132 | main_column = flet.Column()
133 | mother.content = main_column
134 |
135 | main_column.controls.append(flet.Text("\n\n"))
136 |
137 | Title1 = flet.Text("\n Now🪄,\n Just choose a template!!", color=flet.colors.WHITE, size=36, weight="bold")
138 | main_column.controls.append(Title1)
139 |
140 | describe = flet.Text(
141 | " Ok, what is a template ?.\n A template is a theme and pre-set page that make it quick to start.\n",
142 | color=flet.colors.WHITE60, size=15)
143 | main_column.controls.append(describe)
144 |
145 | r = flet.Row([
146 | self.make_a_template_button(flet.colors.WHITE24, "Blank new - default", "ADD_ROUNDED"),
147 | self.make_a_template_button(flet.colors.WHITE24, "Import template - soon", "GET_APP_OUTLINED", disable=True)
148 | ], alignment="center", spacing=15)
149 | main_column.controls.append(r)
150 |
151 | mother.update()
152 | page.update()
153 |
154 | def page_four(self, *args):
155 | page = self.page
156 | page.title = page.title
157 | mother = self.mother
158 | main_column = flet.Column()
159 | mother.content = main_column
160 |
161 | main_column.controls.append(flet.Text("\n\n"))
162 |
163 | Title1 = flet.Text("\n Wait😄,\n Building things for you.", color=flet.colors.WHITE, size=36, weight="bold")
164 | main_column.controls.append(Title1)
165 |
166 | mother.update()
167 | page.update()
168 | time.sleep(1)
169 | self.apply_suggestion_page()
170 |
171 | def apply_suggestion_page(self, *a):
172 | def dont_apply(e):
173 | Create_StoryBoard(self.file_name, "default", False)
174 | self.manage_class.file_name = self.file_name
175 | self.page.window_close()
176 |
177 | def apply_it(e):
178 | self.final_page_with_storyboard_suggest()
179 |
180 | page = self.page
181 | page.vertical_alignment = flet.MainAxisAlignment.CENTER
182 | page.title = page.title
183 | mother = self.mother
184 | main_column = flet.Column()
185 | mother.content = main_column
186 | col = main_column
187 |
188 | col.controls.append(flet.Row([flet.Text("", height=15)], alignment="center"))
189 |
190 | image = flet.Image(src="https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/main/assets/IMG_3260.PNG",
191 | width=250, height=250)
192 | col.controls.append(flet.Row([image], alignment="center"))
193 |
194 | title = flet.Text("Apply StoryBoard suggestions", size=20, weight="bold", color=flet.colors.WHITE)
195 | col.controls.append(flet.Row([title], alignment="center"))
196 |
197 | describe = flet.Text("""
198 | These are suggestions based on smart rules that help
199 | you build your interface by suggesting
200 | widgets based on your goal.
201 | """, size=13, color=flet.colors.WHITE)
202 | col.controls.append(flet.Row([describe], alignment="center"))
203 |
204 | apply_button = flet.ElevatedButton("Apply", bgcolor=flet.colors.WHITE, color=flet.colors.BLACK, width=250, on_click=apply_it)
205 | col.controls.append(flet.Row([apply_button], alignment="center"))
206 |
207 | no_btn = flet.TextButton(content=flet.Text("no thanks", color="red"), on_click=dont_apply)
208 | col.controls.append(flet.Row([no_btn], alignment="center"))
209 |
210 | mother.update()
211 | page.update()
212 |
213 | def final_page_with_storyboard_suggest(self):
214 | def apply_and_start(rule_name, rule_install_url):
215 | rules_file_content = requests.get(rule_install_url).text
216 | if not os.path.isdir("rules"):
217 | os.mkdir("rules")
218 | open(f"rules/{rule_name}.json", "w+", encoding="utf-8").write(str(rules_file_content))
219 | Create_StoryBoard(self.file_name, "default", True, rule_name)
220 | self.manage_class.file_name = self.file_name
221 | self.page.window_close()
222 |
223 | # ------
224 | page = self.page
225 | page.title = page.title
226 | mother = self.mother
227 | main_column = flet.Column()
228 | mother.content = main_column
229 | col = main_column
230 | col.scroll = True
231 |
232 | main_column.controls.append(flet.Text("\n\n"))
233 |
234 | Title1 = flet.Text("Choose your case.", color=flet.colors.WHITE, size=36, weight="bold")
235 | main_column.controls.append(flet.Row([Title1], alignment="center"))
236 | mother.update()
237 | describe = flet.Text("""
238 | Choose your 'main' page goal from the
239 | options down bellow. This will install the right suggestions rules
240 | for your main page case.
241 | """, size=13, color=flet.colors.WHITE)
242 | col.controls.append(flet.Row([describe], alignment="center"))
243 | mother.update()
244 |
245 | all_rules = requests.get("https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/main/rules/all.json").text
246 | all_rules = json.loads(all_rules)
247 |
248 | for rule_option in all_rules["all_rules"]:
249 | col.controls.append(
250 | self.make_a_rule_button_option(rule_option, all_rules["all_rules"][rule_option], apply_and_start))
251 |
252 | col.scroll = True
253 | mother.update()
254 |
255 | def make_a_template_button(self, bgcolor, name, icon, disable=False):
256 | def on_hov(event):
257 | if event.data == "true":
258 | event.control.bgcolor = flet.colors.WHITE12
259 | elif event.data == "false":
260 | event.control.bgcolor = flet.colors.WHITE24
261 | event.control.update()
262 | event.control.update()
263 |
264 | cc = flet.Column(alignment="center", disabled=disable)
265 | c = flet.Container(width=220, height=140, bgcolor=bgcolor, border_radius=10, on_click=self.page_four,
266 | on_hover=on_hov)
267 | cc.controls.append(c)
268 |
269 | Icon = flet.Icon(icon, size=20, color=flet.colors.WHITE)
270 | c.content = flet.Row([Icon], alignment="center")
271 |
272 | name_it = flet.Text(name, color=flet.colors.WHITE, size=13, text_align="center")
273 | cc.controls.append(flet.Row([name_it], alignment="center"))
274 |
275 | return cc
276 |
277 | def make_a_rule_button_option(self, name, url, on_click):
278 | def on_choose(e):
279 | on_click(name, url)
280 |
281 | b = flet.ElevatedButton(f"{name}", on_click=on_choose, bgcolor=flet.colors.WHITE, color=flet.colors.BLACK, width=150, height=45)
282 |
283 | return flet.Row([b], alignment="center")
284 |
--------------------------------------------------------------------------------
/fletsb/pages/main_page.py:
--------------------------------------------------------------------------------
1 | #! This is the editing page of a storyboard.
2 | from flet import Page, Row, Text
3 | from ..widgets.All import all_widgets
4 | import flet
5 | import os
6 | import json
7 | import time
8 | import requests
9 |
10 |
11 | #* local imports
12 | from ..sections.left_section import leftSection
13 | from ..sections.preview_section import PreviewSection
14 | from ..sections.edit_section import editSection
15 | from ..engines.edit_widget_engine import EditWidgetsEngine
16 | from ..engines.edit_subwidgets_engine import EditSubWidgetsEngine
17 | from ..engines.suggesting_engine import SuggestingEngine
18 | from ..widgets.All import all_widgets
19 | from ..pages.settings import SettingsPage
20 | from ..engines.bardai_engine import BardapiSupport
21 |
22 |
23 | class mainPage:
24 | def __init__(self, file_path):
25 | if not os.path.isfile(file_path):
26 | raise FileExistsError(f"There is no Flet StoryBoard on path '{file_path}' .")
27 |
28 |
29 | self.current_page_name = "main"
30 | self.file_path = file_path
31 | self.development_mode = True
32 | self.dict_content = json.loads(open(file_path, encoding="utf-8").read())
33 |
34 | #? Copy of classes
35 | self.bard_support_bridge = BardapiSupport()
36 | self.all_widgets = all_widgets
37 | self._editWidgetsEngine = EditWidgetsEngine
38 | self._editSubWidgetsEngine = EditSubWidgetsEngine
39 |
40 | #? Run the app
41 | flet.app(target=self.app)
42 |
43 | def app (self, page:Page):
44 | page.title = f"Flet StoryBoard - {self.file_path}"
45 | page.spacing = 0
46 | page.bgcolor = "black"
47 | page.vertical_alignment = flet.MainAxisAlignment.CENTER
48 | page.window_width = 850
49 | page.window_height = 650
50 | page.window_min_width = 850
51 | page.window_min_height = 640
52 | self.page = page
53 | page.appbar = self.generate_app_bar()
54 | page.window_center()
55 | page.update()
56 |
57 | # main stack
58 | self.main_stack = flet.Stack(expand=True)
59 | page.add(self.main_stack)
60 |
61 | # The main row
62 | self.main_row = Row(scroll=False)
63 | # page.add(self.main_row)
64 | self.main_stack.controls.append(self.main_row)
65 | page.update()
66 |
67 | #? append the sections
68 | self.left_section = leftSection(page, self, self.main_row)
69 | self.preview_section = PreviewSection(page, self, self.main_row)
70 | self.edit_section = editSection(page, self, self.main_row)
71 |
72 | #? Set finals of page.
73 | page.on_resize = self.on_page_resize
74 | page.on_keyboard_event = self.manage_keyboard_commands
75 |
76 |
77 | #? Setup the storyboard suggestions engine.
78 | self.suggesting_engine = SuggestingEngine(self)
79 | time.sleep(0.5)
80 | self.suggesting_engine.push_new_suggestion()
81 |
82 | def on_page_resize (self, *event):
83 | page = self.page
84 | self.left_section.main_container.width = self.page.width / 4 - 30
85 | self.left_section.main_container.height = self.page.height - 70
86 | self.preview_section.main_view.width = page.width-(page.width/4)*2
87 | self.preview_section.main_view.height = page.height-150
88 | self.edit_section.main_column.width = self.page.width / 4 - 10
89 | self.edit_section.main_column.height = page.height - 70
90 |
91 | self.page.update()
92 |
93 | def pages_browser (self):
94 | def create_a_page (e):
95 | self.create_new_page(str(e.control.value))
96 | self.page.appbar = self.generate_app_bar()
97 | self.page.update()
98 | def open_a_page (e):
99 | page_name = str(e.control.content.controls[0].value)
100 | if page_name in self.dict_content["pages"]:
101 | self.current_page_name = page_name
102 | self.preview_section.update_preview(self.current_page_name)
103 | self.last_checked_page_button.bgcolor = flet.colors.GREY_700
104 | self.last_checked_page_button = e.control
105 | e.control.bgcolor = "blue"
106 | time.sleep(0.3)
107 | self.suggesting_engine.push_new_suggestion()
108 | self.page.update()
109 | def ask_for_new_page_name (e):
110 | mr.scroll = False
111 | tf = flet.TextField(label="Page name", on_submit=create_a_page, height=40, color="white")
112 | mr.controls = [tf]
113 | mr.update()
114 | tf.focus()
115 | mr = flet.Row([], width=250, scroll=True)
116 | mr.controls.append(flet.TextButton(content=flet.Text("✨", size=18), on_click=self.edit_page_suggestion_state, width=35))
117 | new_page_button = flet.Container(flet.Row([flet.Text("+ Page", size=12, color="black")], alignment="center"), on_click=ask_for_new_page_name,
118 | bgcolor="white", width=60, height=30, border_radius=12)
119 | mr.controls.append(new_page_button)
120 |
121 | for p in self.dict_content["pages"]:
122 | c = flet.Container(flet.Row([
123 | flet.Text(p, color="white", size=12)
124 | ], alignment="center"), bgcolor=flet.colors.GREY_700, width=60, height=30, border_radius=12, on_click=open_a_page)
125 | mr.controls.append(c)
126 | if str(p) == str(self.current_page_name):
127 | c.bgcolor = "blue"
128 | self.last_checked_page_button = c
129 |
130 | return mr
131 |
132 | def generate_app_bar (self):
133 | a = flet.AppBar(
134 | bgcolor=self.page.bgcolor,
135 | leading=flet.Row([
136 | Text(" "),
137 | flet.Icon(flet.icons.DASHBOARD_ROUNDED, size=18, color="white"),
138 | Text("Flet StoryBoard", color="white", weight="bold", size=15)
139 | ], spacing=15
140 | ),
141 | actions=[
142 | Row([
143 | flet.TextButton(content=flet.Text("Settings", size=12, color="white"),
144 | on_click=self.open_settings_page),
145 | flet.ElevatedButton("Save", bgcolor="white", color="black", width=100, height=35,
146 | on_click=self.save_all, tooltip="click to save | also control + S"),
147 | Text(" ")
148 | ], alignment=15)
149 | ],
150 | title=self.pages_browser(),
151 | center_title=True
152 | )
153 |
154 | return a
155 |
156 |
157 | def manage_keyboard_commands (self, event):
158 | key = event.key # It would be a key like: 'A' or 'Enter'.
159 | shift = event.shift # It would be a bool value of where the shift key is clicked or not.
160 | ctrl = event.ctrl # It would be a bool value of where the control key is clicked or not.
161 | alt = event.alt # It would be a bool value of where the option key is clicked or not.
162 | meta = event.meta # It would be a bool value of where the command key is clicked or not.
163 |
164 | if str(key).lower() == "s" and ctrl:
165 | #? Clicked to save file
166 | self.save_all()
167 | elif str(key).lower() == "s" and meta:
168 | #? Clicked to save file
169 | self.save_all()
170 | elif str(key).lower() == "b" and ctrl:
171 | #? push bard input
172 | self.bard_support_bridge.push_ui(self.push_on_top_views, self)
173 | elif str(key).lower() == "b" and meta:
174 | #? push bard input
175 | self.bard_support_bridge.push_ui(self.push_on_top_views, self)
176 |
177 |
178 | def save_all (self, *args):
179 | new_content = json.dumps(self.dict_content)
180 | file = open(self.file_path, "w+", encoding="utf-8")
181 | file.write(new_content)
182 |
183 | page = self.page
184 | page.snack_bar = flet.SnackBar(
185 | content=flet.Text(f"This Flet StoryBoard '{self.file_path}' is saved!"),
186 | action="Alright!"
187 | )
188 | page.snack_bar.open = True
189 | page.update()
190 |
191 |
192 | def add_new_widget (self, widget_name, page_name=None):
193 | widget_number = len(self.dict_content["pages"][self.current_page_name]["widgets"])-1
194 | widget_class = all_widgets[widget_name]["class"]
195 | widget_class = widget_class(self, self.preview_section.main_view_column, widget_number=widget_number)
196 |
197 | self.dict_content["pages"][self.current_page_name]["widgets"].append(widget_class.template)
198 |
199 | self.preview_section.update_preview(self.current_page_name)
200 | self.page.update()
201 |
202 | self.edit_a_widget(len(self.dict_content["pages"][self.current_page_name]["widgets"])-1)
203 |
204 | time.sleep(0.5)
205 | self.suggesting_engine.push_new_suggestion()
206 |
207 | return widget_class
208 |
209 | def edit_a_widget (self, widget_number_on_content):
210 | self.edit_section.edit_widget_using_engine(widget_number_on_content)
211 | self.page.update()
212 |
213 |
214 | def create_new_page (self, page_name):
215 | page_dict = {
216 | "settings" : {
217 | "bgcolor" : "black",
218 | "suggestions_rules" : "none"
219 | },
220 | "widgets" : [
221 |
222 | ]
223 | }
224 | self.dict_content["pages"][page_name] = page_dict
225 | self.current_page_name = str(page_name)
226 | self.page.appbar = self.generate_app_bar()
227 | self.preview_section.update_preview(self.current_page_name)
228 |
229 |
230 | def edit_page_suggestion_state (self, *a):
231 | def go_back (e):
232 | self.left_section.show_new_content(last_content)
233 | self.page.update()
234 |
235 | def apply_and_start (name_of_sug):
236 | self.dict_content["pages"][self.current_page_name]["settings"]["suggestions_rules"] = str(name_of_sug)
237 | go_back("")
238 | self.suggesting_engine.push_new_suggestion()
239 |
240 | def make_a_rule_button_option (name):
241 | def on_choose (e):
242 | apply_and_start(name)
243 | b = flet.ElevatedButton(f"{name}", on_click=on_choose, bgcolor="white", color="blacK", width=150, height=45)
244 | return flet.Row([b], alignment="center")
245 |
246 | last_content = self.left_section.main_container
247 | c = flet.Column(width=last_content.width, height=last_content.height)
248 |
249 | back_btn = flet.TextButton("< Back", on_click=go_back)
250 | c.controls.append(back_btn)
251 |
252 | title = flet.Text("Chose the suggestion rules for this page.", color="white", size=17, weight="bold")
253 | c.controls.append(title)
254 |
255 | all_rules = requests.get("https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/main/rules/all.json").text
256 | all_rules = json.loads(all_rules)
257 |
258 | for rule_option in all_rules["all_rules"]:
259 | c.controls.append(make_a_rule_button_option(rule_option))
260 |
261 | c.controls.append(flet.Row([flet.Text("more will come soon", color="white", size=13)], alignment="center"))
262 | c.scroll = True
263 | self.left_section.show_new_content(c)
264 |
265 | def open_settings_page (self, *e):
266 | SettingsPage(self.page, self)
267 |
268 |
269 | def push_on_top_views (self, container:flet.Container):
270 | def erase_all ():
271 | self.main_stack.controls.remove(col)
272 | self.main_stack.update()
273 |
274 | container.width = self.page.width
275 | container.height = self.page.height
276 | col = flet.Column([
277 | flet.Row([container], alignment="center")
278 | ], alignment="center")
279 | self.main_stack.controls.append(
280 | col
281 | )
282 | if self.main_stack.page != None:
283 | self.main_stack.update()
284 |
285 | return erase_all
--------------------------------------------------------------------------------
/fletsb/pages/settings.py:
--------------------------------------------------------------------------------
1 | from flet import Page
2 | import flet
3 | import time
4 |
5 | from .Settings.pages import page_settings_page
6 |
7 | class SettingsPage:
8 | def __init__(self, page:Page, main_class) -> None:
9 | self.page : Page = page
10 | self.main_class = main_class
11 | #? Create a copy of things.
12 | self.__last_keyboard_manager = main_class.manage_keyboard_commands
13 | self.__last_controls = list(page.controls)
14 | self.__lat_appbar = page.appbar
15 | self.__last_on_resize_function = main_class.on_page_resize
16 |
17 | #? For keyboard events
18 | self.current_selected_page = None
19 | self.page_opend = True
20 | #? Hide all page controls
21 | self.hide_all()
22 |
23 | #? ReSet all page controls
24 | page.on_keyboard_event = self.keyboard_keys_manager
25 | page.on_resize = self.on_page_resize
26 | page.controls.clear()
27 | page.appbar = None
28 | page.bgcolor = "black"
29 | page.update()
30 |
31 | main_row = flet.Row(alignment="center")
32 | page.add(main_row)
33 |
34 | #? pages browseing section
35 | pages_browser_container = flet.Container(border_radius=12)
36 | self.pages_broswer = flet.Column(width=page.width/3, height=page.height-50, scroll=True)
37 | pages_browser_container.content = self.pages_broswer
38 | main_row.controls.append(pages_browser_container)
39 | page.update()
40 |
41 | #? viewing selected page section
42 | page_viewing_section_container = flet.Container(bgcolor="#1C1C1E", border_radius=12)
43 | self.page_viewing_section = flet.Column(width=page.width-(page.width/3)-50, height=page.height-50, scroll=True)
44 | page_viewing_section_container.content = self.page_viewing_section
45 | main_row.controls.append(page_viewing_section_container)
46 | page.update()
47 |
48 | #? The title and back_btn
49 | title = flet.Text(" Settings", size=28, weight="bold", color="white")
50 | self.pages_broswer.controls.append(flet.Row([
51 | flet.IconButton("CLOSE_ROUNDED", on_click=self.go_back, icon_color="white", width=30), title
52 | ], spacing=0))
53 |
54 | self.pages_broswer.controls.append(flet.Text(""))
55 |
56 | #? show all settings pages
57 | for p in self.get_all_settings_pages():
58 | self.pages_broswer.controls.append(page_navigator_frame_button(p, self.get_all_settings_pages()[p]["icon"], self.get_all_settings_pages()[p]["function"],self))
59 |
60 | page.update()
61 |
62 | def open_new_settings_page(self, control):
63 | """Open a new sub-page on settings page"""
64 | pass
65 |
66 | def route_to_page (self):
67 | """Use flet Route to a page"""
68 |
69 | def hide_all (self):
70 | page : Page = self.page
71 | for i in range(10):
72 | for c in page.controls:
73 | c.opacity = c.opacity - 0.1
74 | page.appbar.opacity = page.appbar.opacity - 0.1
75 | c.update()
76 | for ac in page.appbar.actions:
77 | ac.opacity = ac.opacity - 0.1
78 | ac.update()
79 | page.appbar.leading.opacity = page.appbar.leading.opacity - 0.1
80 | page.appbar.leading.update()
81 | page.appbar.title.opacity = page.appbar.title.opacity - 0.1
82 | page.appbar.title.update()
83 | time.sleep(0.01)
84 |
85 | def go_back (self, *e):
86 | self.page_opend = False
87 | page : Page = self.page
88 | page.on_keyboard_event = self.__last_keyboard_manager
89 | page.controls.clear()
90 | page.bgcolor = "black"
91 | page.appbar = self.__lat_appbar
92 |
93 | for c in self.__last_controls:
94 | c.opacity = 1.0
95 | page.controls.append(c)
96 |
97 | for ac in page.appbar.actions:
98 | ac.opacity = 1.0
99 |
100 | page.appbar.leading.opacity = 1.0
101 | page.appbar.title.opacity = 1.0
102 |
103 | page.on_resize = self.__last_on_resize_function
104 | page.update()
105 |
106 | def on_page_resize (self, e):
107 | page = self.page
108 | self.pages_broswer.width = page.width/3 - 50
109 | self.pages_broswer.height = self.page.height - 50
110 | self.page_viewing_section.width = page.width-(page.width/3-50)-50
111 | self.page_viewing_section.height = page.height-50
112 | self.page.update()
113 |
114 | def get_all_settings_pages (self):
115 | return {
116 | "Pages" : {"icon":"PREVIEW_ROUNDED", "function":page_settings_page, "name":"Pages"},
117 | "Editor" : {"icon":"SETTINGS_ROUNDED", "function":editor_page, "name":"Editor"}
118 | }
119 |
120 | def keyboard_keys_manager (self, e):
121 | if self.page_opend == False: return
122 | pass
123 |
124 |
125 | #? Generate page button
126 | def page_navigator_frame_button (name:str, icon, function, settings_class:SettingsPage, as_a_click=False):
127 | def on_hov (e):
128 | if str(e.data) == "true":
129 | container.bgcolor = flet.colors.WHITE60
130 | else:
131 | container.bgcolor = None
132 | container.update()
133 | if e.control == settings_class.current_selected_page:
134 | e.control.bgcolor = "blue"
135 | e.control.update()
136 |
137 | def on_click (e):
138 | if settings_class.current_selected_page == None:
139 | settings_class.current_selected_page = container
140 | container.bgcolor = "blue"
141 | if container.page == None:
142 | settings_class.page.update()
143 | else:
144 | container.update()
145 | else:
146 | settings_class.current_selected_page.bgcolor = None
147 | if settings_class.current_selected_page.page != None:
148 | settings_class.current_selected_page.update()
149 | settings_class.current_selected_page = container
150 | container.bgcolor = "blue"
151 | if container.page == None:
152 | settings_class.page.update()
153 | else:
154 | container.update()
155 |
156 | function(settings_class)
157 |
158 |
159 |
160 | container = flet.Container(width=200, height=40, border_radius=12, expand=True,
161 | on_hover=on_hov, on_click=on_click)
162 | r = flet.Row([flet.Text(" ")], alignment="center", width=200)
163 | container.content = r
164 |
165 | ICON = flet.Icon(icon, size=20, color="white")
166 | r.controls.append(ICON)
167 |
168 | NAME = flet.Text(name, size=17, color="white", expand=True, text_align="left")
169 | r.controls.append(NAME)
170 |
171 | if as_a_click:
172 | container.bgcolor = "blue"
173 | on_click(container)
174 |
175 | return flet.Row([container], alignment="center")
176 |
177 |
178 | #? Pages
179 |
180 |
181 | def editor_page (settings_class:SettingsPage):
182 | v = settings_class.page_viewing_section
183 | v.clean()
184 | v.controls.append(flet.Text("soon", color="white"))
185 | v.update()
--------------------------------------------------------------------------------
/fletsb/sections/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/85fbe95030d7def96f59b0ad37ea32f324f2af87/fletsb/sections/__init__.py
--------------------------------------------------------------------------------
/fletsb/sections/edit_section.py:
--------------------------------------------------------------------------------
1 | from flet import Column, Page, Row
2 | import flet
3 |
4 | from ..engines.edit_widget_engine import EditWidgetsEngine
5 |
6 |
7 | class editSection:
8 | def __init__(self, page:Page, main_class, main_row:Row) -> None:
9 | self.page : Page = page
10 | self.main_class = main_class
11 | self.main_row : Row = main_row
12 |
13 | self.main_column = Column(width=page.width/4, height=page.height,scroll=True)
14 |
15 | main_row.controls.append(self.main_column)
16 |
17 | def edit_widget_using_engine (self, widget_number):
18 | ee = EditWidgetsEngine(main_class=self.main_class, section_view=self.main_column, widget_number=widget_number)
--------------------------------------------------------------------------------
/fletsb/sections/left_section.py:
--------------------------------------------------------------------------------
1 | # This is the left section part.
2 | from flet import Page, AnimatedSwitcher, Container, Row, Column
3 | import flet
4 | import time
5 |
6 | from ..widgets.All import all_widgets
7 | from ..ui_toolkit.widget_browser_frame import Widget_Browse_Frame
8 |
9 | class leftSection:
10 | def __init__(self, page:Page, main_class, main_row:Row) -> None:
11 | self.page : Page = page
12 | self.main_class = main_class
13 | self.main_row = main_row
14 |
15 | self.self_ui = AnimatedSwitcher(transition=flet.AnimatedSwitcherTransition.FADE, duration=500, reverse_duration=250, switch_in_curve=flet.AnimationCurve.EASE, switch_out_curve=flet.AnimationCurve.EASE_IN_BACK)
16 | self.main_container = Container(bgcolor=page.bgcolor, width=page.width/4-30, height=page.height)
17 | self.self_ui.content = self.main_container
18 | main_row.controls.append(self.self_ui)
19 |
20 | #? Show all widgets.
21 | self.show_all_widgets()
22 |
23 |
24 | def show_new_content (self, container:Container):
25 | self.main_container = container
26 | self.self_ui.content = container
27 |
28 | if self.self_ui.page != None:
29 | self.self_ui.update()
30 | else:
31 | self.page.update()
32 |
33 | if hasattr(self.main_class, "on_page_resize"):
34 | try: self.main_class.on_page_resize()
35 | except: pass
36 |
37 |
38 | def show_all_widgets (self):
39 | page = self.page
40 | #* This is the default section.
41 |
42 | col = Column(scroll=True)
43 | title = flet.Text("Widgets", size=25, weight="bold", color="white")
44 | col.controls.append(title)
45 | for wid in all_widgets:
46 | w = Widget_Browse_Frame(wid, all_widgets[wid], self.main_class.add_new_widget, self.main_class.current_page_name)
47 | col.controls.append(w)
48 |
49 |
50 | self.main_container = Container(bgcolor=page.bgcolor, width=page.width/4, height=page.height)
51 | self.main_container.content = col
52 | self.show_new_content(self.main_container)
53 | self.page.update()
54 |
55 |
56 | def show_the_suggestions (self):
57 | pass
--------------------------------------------------------------------------------
/fletsb/sections/preview_section.py:
--------------------------------------------------------------------------------
1 | import flet
2 | from ..engines.viewer_engine import viewerEngine
3 |
4 |
5 | class PreviewSection:
6 | def __init__(self, page: flet.Page, main_class, main_row: flet.Row):
7 | self.page: flet.Page = page
8 | self.main_class = main_class
9 |
10 | self.main_view = flet.Container(
11 | width=page.width - (page.width / 4) * 2,
12 | height=page.height - 80,
13 | border=flet.border.all(0.4, flet.colors.WHITE60),
14 | border_radius=12
15 | )
16 | main_row.controls.append(self.main_view)
17 |
18 | self.main_view_column = flet.Column(alignment=flet.MainAxisAlignment.CENTER)
19 | self.main_view.content = self.main_view_column
20 |
21 | self.update_preview()
22 | page.update()
23 |
24 | def update_preview(self, page_name="main"):
25 | ve = viewerEngine(
26 | self.main_class,
27 | self.main_class.dict_content,
28 | page_name,
29 | self.main_view,
30 | self.main_view_column
31 | )
32 |
--------------------------------------------------------------------------------
/fletsb/tools/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/85fbe95030d7def96f59b0ad37ea32f324f2af87/fletsb/tools/__init__.py
--------------------------------------------------------------------------------
/fletsb/tools/color_picker.py:
--------------------------------------------------------------------------------
1 | from flet import Container, Row, Column
2 | import flet
3 |
4 |
5 | def none(*args):
6 | pass
7 |
8 |
9 | class ColorPicker:
10 |
11 | def __init__(
12 | self,
13 | main_view=None,
14 | selected_color="white",
15 | on_choose_color=none,
16 | add_it=True,
17 | title_name="select color",
18 | drop_width=200,
19 | color_prev_width=50
20 | ) -> None:
21 |
22 | if main_view is None:
23 | return
24 | self.__all_colors = ["None", "white", "black", "pink", "red", "green", "yellow", "blue", "hex-color"]
25 |
26 | self.drop_width = drop_width
27 | self.on_choose_color = on_choose_color
28 | self.main_view = main_view
29 | self.selected_color = selected_color
30 |
31 | v = Container()
32 | self.v = v
33 |
34 | main_dropdown = flet.Dropdown(width=drop_width, value=selected_color, label=title_name,
35 | on_change=self.on_choose)
36 | for i in self.__all_colors:
37 | main_dropdown.options.append(flet.dropdown.Option(i))
38 | self.mainDropdown = main_dropdown
39 |
40 | color_preview = flet.Container(width=color_prev_width, height=50, bgcolor=self.selected_color, border_radius=8,
41 | border=flet.border.all(0.1, "white"))
42 | self.color_preview = color_preview
43 |
44 | main_row = Row(
45 | controls=[
46 | main_dropdown,
47 | color_preview
48 | ]
49 | )
50 | self.main_row = main_row
51 |
52 | v.content = main_row
53 | if add_it:
54 | main_view.controls.append(v)
55 |
56 | def on_choose(self, me):
57 | def on_change_color(me):
58 | tfc.value = str(tfc.value).replace(" ", "")
59 | tfc.update()
60 | if tfc.value != "#":
61 | new_color_selected = tfc.value
62 | self.selected_color = tfc.value
63 | self.color_preview.bgcolor = tfc.value
64 | self.on_choose_color(tfc.value)
65 | self.v.update()
66 |
67 | def back_to_orig(me):
68 | self.color_preview.on_click = None
69 | self.selected_color = "white"
70 | self.mainDropdown.value = self.selected_color
71 | self.color_preview.bgcolor = self.selected_color
72 | self.main_row.controls[0] = self.mainDropdown
73 | self.v.update()
74 |
75 | new_color_selected = me.control.value
76 | tfc = flet.TextField(
77 | label="hex-color",
78 | value="#0",
79 | width=self.drop_width,
80 | on_change=on_change_color,
81 | on_submit=on_change_color
82 | )
83 |
84 | if str(new_color_selected) == "hex-color":
85 | self.main_row.controls[0] = tfc
86 | self.color_preview.on_click = back_to_orig
87 | elif str(new_color_selected) == "None":
88 | self.color_preview.bgcolor = None
89 | self.selected_color = None
90 | self.on_choose_color(new_color_selected)
91 | else:
92 | self.color_preview.bgcolor = new_color_selected
93 | self.selected_color = new_color_selected
94 | self.on_choose_color(new_color_selected)
95 |
96 | self.v.update()
97 |
98 | def update(self):
99 | self.mainDropdown.value = self.selected_color
100 | self.color_preview.bgcolor = self.selected_color
101 | self.v.update()
102 |
103 | @property
104 | def value(self):
105 | return self.selected_color
106 |
--------------------------------------------------------------------------------
/fletsb/tools/create_storyboard.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 |
4 | def Create_StoryBoard(file_name, template="default", storyboard_suggestions=False,
5 | main_page_suggestions_rules="none", support_bard_ai=False):
6 |
7 | if template == "default":
8 | storyboard_default_template = {
9 | "storyboard_settings": {
10 | "template": "default",
11 | "storyboard_suggestions": storyboard_suggestions,
12 | "allow_scroll": False,
13 | "support_bard" : support_bard_ai
14 | },
15 | "pages": {
16 | "main": {
17 | "settings": {
18 | "bgcolor": "black",
19 | "suggestions_rules": f"{main_page_suggestions_rules}"
20 | },
21 | "widgets": [
22 |
23 | ]
24 | }
25 | }
26 | }
27 |
28 | file = open(f"{file_name}.fletsb", "w+", encoding="utf-8")
29 | file.write(json.dumps(storyboard_default_template))
30 | return True
31 | else:
32 | print("External templates are nor supported yet.")
33 |
--------------------------------------------------------------------------------
/fletsb/tools/get_url_icon.py:
--------------------------------------------------------------------------------
1 | from bs4 import BeautifulSoup
2 | import requests
3 | import urllib3
4 | from requests.packages.urllib3.exceptions import InsecureRequestWarning
5 |
6 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
7 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
8 |
9 |
10 | def get_site_favicon(url):
11 | response = requests.get(url, verify=False)
12 | soup = BeautifulSoup(response.text, 'html.parser')
13 | favicon_link = soup.find('link', rel='icon') or soup.find('link', rel='shortcut icon') or soup.find('link', rel='apple-touch-icon')
14 | try:
15 | favicon_url = favicon_link['href']
16 | if str(favicon_url).startswith("http"):
17 | return f"{favicon_url}"
18 | else:
19 | return f"{url}/{favicon_url}"
20 | except:
21 | return None
22 |
--------------------------------------------------------------------------------
/fletsb/tools/list_picker.py:
--------------------------------------------------------------------------------
1 | import flet
2 |
3 |
4 | class ListPopup:
5 | def __init__(self, the_list=None, main_class=None, default_choice=None, title=None):
6 | if the_list is None:
7 | return
8 |
9 | self.title = title
10 | self.page: flet.Page = main_class.page
11 | self.main_class = main_class
12 | self.self_ui = flet.TextButton(f"{title}: f{default_choice}", on_click=self.show_popup)
13 | self.the_list = the_list
14 | self.__selected = default_choice
15 |
16 | def show_popup(self, *args):
17 | def on_search(e):
18 | for i in self.all_list_choices:
19 | col.controls.remove(i)
20 |
21 | self.all_list_choices = []
22 |
23 | if search_field.value == "":
24 | for icon in self.the_list:
25 | name = str(icon)
26 | if name.startswith("__"):
27 | pass
28 | else:
29 | self.all_list_choices.append(self.generate_new(name, col))
30 | col.update()
31 | return
32 |
33 | self.all_list_choices = []
34 | self.all_list_choices.clear()
35 | s = str(search_field.value).lower()
36 |
37 | for i in self.the_list:
38 | name = str(i)
39 | if str(i).lower().startswith(s):
40 | self.all_list_choices.append(self.generate_new(name, col))
41 | col.update()
42 |
43 | page: flet.Page = self.main_class.page
44 |
45 | cont = flet.Container(bgcolor=flet.colors.BLACK, border_radius=12)
46 | loading_text = flet.Text("Loading..", color=flet.colors.WHITE)
47 | cont.content = flet.Row([loading_text], alignment=flet.MainAxisAlignment.CENTER, height=100)
48 |
49 | page.dialog = flet.AlertDialog()
50 | page.dialog.content = cont
51 | page.dialog.open = True
52 | page.update()
53 |
54 | col = flet.ListView(width=450, height=500)
55 | col.controls.append(flet.Text("Choose one:", color="white", size=28, weight=flet.FontWeight.BOLD))
56 |
57 | search_field = flet.TextField(label="Search", on_change=on_search)
58 | col.controls.append(search_field)
59 |
60 | self.all_list_choices = []
61 | for icon in self.the_list:
62 | name = str(icon)
63 | if name.startswith("__"):
64 | pass
65 | else:
66 | self.all_list_choices.append(self.generate_new(name, col))
67 |
68 | cont.content = col
69 | page.update()
70 |
71 | def generate_new(self, value_name, col):
72 | def on_choose(e):
73 | self.self_ui.text = f"{self.title}: f{value_name}"
74 | self.__selected = value_name
75 | self.page.dialog.open = False
76 | self.page.update()
77 |
78 | r = flet.Row(
79 | [
80 | flet.Icon(value_name, size=22, color=flet.colors.WHITE),
81 | flet.Text(f"{value_name}", color=flet.colors.WHITE)
82 | ]
83 | )
84 | cc = flet.Container(content=r, on_click=on_choose)
85 | col.controls.append(cc)
86 | return cc
87 |
88 | @property
89 | def value(self):
90 | return self.__selected
91 |
--------------------------------------------------------------------------------
/fletsb/tools/page_info.py:
--------------------------------------------------------------------------------
1 |
2 | def get_page_bgcolor (content_dict, page_name):
3 | return content_dict["pages"][page_name]["settings"]["bgcolor"]
4 |
--------------------------------------------------------------------------------
/fletsb/tools/storyboard_class.py:
--------------------------------------------------------------------------------
1 | import flet
2 |
3 |
4 | class StoryBoard:
5 | def __init__(self, page, main_class):
6 | self.__page: flet.Page = page
7 | self.__main_class = main_class
8 | self.functions = {}
9 |
10 | def add_function(self, function_name, function):
11 | """
12 | Define function, so the storyboard's widgets can access to. Like `function name` property of the `Button` widget need to have a Defined function.
13 | """
14 | self.functions[function_name] = function
15 | self.points = {}
16 |
17 | def add_flet_control(self, control, on_centered=True):
18 | """
19 | Add a flet control to the storyboard.
20 | if `on_centered = True` that means that the control will center the storyboard.
21 | """
22 | if on_centered:
23 | r = flet.Row([control], alignment=flet.MainAxisAlignment.CENTER)
24 | self.__page.add(r)
25 | self.__page.update()
26 | else:
27 | self.__page.add(control)
28 |
29 | def get_point(self, point_name: str):
30 | """
31 | The point is a place you choose to store some data in.
32 | You will get `None` as a return if the point have nothing yet.
33 | """
34 | if point_name not in self.points:
35 | return None
36 | else:
37 | return self.points[point_name]
38 |
39 | def navigate_to_page(self, page_name: str):
40 | """
41 | Go to a page name
42 | """
43 | if page_name not in self.__main_class.dict_content["pages"]:
44 | raise KeyError(f"Page '{page_name}' is not found.")
45 |
46 | viewerEngine = self.__main_class.viewerEngine
47 | viewerEngine = viewerEngine(
48 | self.__main_class,
49 | self.__main_class.dict_content,
50 | page_name,
51 | self.__page,
52 | self.__page,
53 | self.__main_class.development_mode
54 | )
55 | self.__page.update()
56 |
57 | def close_window(self):
58 | """Close the window"""
59 | self.__page.window_close()
--------------------------------------------------------------------------------
/fletsb/ui_toolkit/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/85fbe95030d7def96f59b0ad37ea32f324f2af87/fletsb/ui_toolkit/__init__.py
--------------------------------------------------------------------------------
/fletsb/ui_toolkit/widget_browser_frame.py:
--------------------------------------------------------------------------------
1 | import flet
2 |
3 |
4 | def Widget_Browse_Frame(widget_name, widget_info_dict, on_click, page_name):
5 | def action(event):
6 | on_click(widget_name, page_name)
7 |
8 | def on_hover(event):
9 | event.control.bgcolor = "#474747" if event.data == "true" else "#5C5C5C"
10 | event.control.update()
11 |
12 | r = flet.Row(
13 | [
14 | flet.Text(" "),
15 | flet.Icon(widget_info_dict["icon"], size=18, color=flet.colors.WHITE),
16 | flet.Text(widget_name, size=13, color=flet.colors.WHITE)
17 | ],
18 | spacing=12
19 | )
20 |
21 | c = flet.Container(
22 | content=r,
23 | width=170,
24 | height=35,
25 | bgcolor="#5C5C5C",
26 | on_click=action,
27 | expand=True,
28 | on_hover=on_hover,
29 | border_radius=12
30 | )
31 |
32 | return flet.Row([c], alignment=flet.MainAxisAlignment.CENTER)
33 |
--------------------------------------------------------------------------------
/fletsb/widgets/All.py:
--------------------------------------------------------------------------------
1 | from .widgets.title import Title
2 | from .widgets.open_url import Open_Url
3 | from .widgets.button import Button
4 | from .widgets.label import Label
5 | from .widgets.markdown import Markdown
6 | from .widgets.paragraph import Paragraph
7 | from .widgets.row import Row
8 | from .widgets.column import Column
9 | from .widgets.image import Image
10 | from .widgets.padding import Padding
11 | from .widgets.textfield import TextField
12 | from .widgets.navigator import Navigator
13 |
14 | all_widgets = {
15 | "Title": {"icon": "TEXT_FIELDS_ROUNDED", "class": Title},
16 | "TextField": {"icon": "INPUT_ROUNDED", "class": TextField},
17 | "Open Url": {"icon": "INSERT_LINK_SHARP", "class": Open_Url},
18 | "Button": {"icon": "SMART_BUTTON_ROUNDED", "class": Button},
19 | "Label": {"icon": "MEDICAL_INFORMATION_OUTLINED", "class": Label},
20 | "Markdown": {"icon": "TEXT_SNIPPET_ROUNDED", "class": Markdown},
21 | "Paragraph": {"icon": "SHORT_TEXT_ROUNDED", "class": Paragraph},
22 | "Row": {"icon": "VIEW_COLUMN_OUTLINED", "class": Row},
23 | "Column" : {"icon":"TABLE_ROWS_SHARP", "class":Column},
24 | "Image": {"icon": "IMAGE_OUTLINED", "class": Image},
25 | "Padding": {"icon": "SPACE_BAR_ROUNDED", "class": Padding},
26 | "Navigator": {"icon": "NAVIGATE_NEXT", "class": Navigator}
27 | }
28 |
--------------------------------------------------------------------------------
/fletsb/widgets/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/85fbe95030d7def96f59b0ad37ea32f324f2af87/fletsb/widgets/__init__.py
--------------------------------------------------------------------------------
/fletsb/widgets/widgets/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/85fbe95030d7def96f59b0ad37ea32f324f2af87/fletsb/widgets/widgets/__init__.py
--------------------------------------------------------------------------------
/fletsb/widgets/widgets/button.py:
--------------------------------------------------------------------------------
1 | import flet
2 | from ...tools.color_picker import ColorPicker
3 |
4 |
5 | class Button(object):
6 | def __init__(self, main_class, parent, *args, **kwargs) -> None:
7 | self.parent = parent
8 | self.main_class = main_class
9 | self.self_object = flet.ElevatedButton(on_click=self.on_button_click)
10 |
11 | # all args
12 | self.args = {
13 | "text": {"type": str, "default_value": "click me"},
14 | "function name": {"type": str, "default_value": ""},
15 | "text_color": {"type": ColorPicker, "default_value": "black"},
16 | "bgcolor": {"type": ColorPicker, "default_value": "white"},
17 | "alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "center"},
18 | "width": {"type": int, "default_value": 95},
19 | "height": {"type": int, "default_value": 40},
20 | "hide": {"type": bool, "default_value": False}
21 | }
22 |
23 | # Template dict
24 | # This is where the widget data will be stored.
25 | self.template = {
26 | "widget_class_name": "Button",
27 | "properties": {}
28 | }
29 | for p in self.args:
30 | self.template["properties"][p] = self.args[p]["default_value"]
31 |
32 | self.update()
33 |
34 | def update(self, new_props: dict = None):
35 | t = self.self_object
36 | props = self.template["properties"]
37 |
38 | if new_props is not None:
39 | for i in new_props:
40 | self.template["properties"][i] = new_props[i]
41 |
42 | t.text = props["text"]
43 | t.color = props["text_color"]
44 | t.bgcolor = props["bgcolor"]
45 | t.width = props["width"]
46 | t.height = props["height"]
47 | t.visible = props["hide"] == False
48 |
49 | if self.self_object.page is not None:
50 | self.self_object.update()
51 |
52 | def on_button_click(self, event):
53 | if self.main_class.development_mode:
54 | return
55 | else:
56 | props = self.template["properties"]
57 | if props["function name"] == "":
58 | return
59 |
60 | if props["function name"] in self.main_class.storyboard_class.functions:
61 | self.main_class.storyboard_class.functions[props["function name"]]()
62 | else:
63 | fn = props["function name"]
64 | print(f"Pass error: There is not function found called {fn}")
65 |
66 | def return_widget(self):
67 | props = self.template["properties"]
68 | if self.main_class.development_mode:
69 | self.self_object.disabled = True
70 | if props["alignment"] == "left":
71 | return flet.Row([flet.Text(" "), self.self_object])
72 | elif props["alignment"] == "center":
73 | return flet.Row([self.self_object], alignment=flet.MainAxisAlignment.CENTER)
74 | else:
75 | return flet.Row([self.self_object, flet.Text(" ")], alignment=flet.alignment.center_right)
76 |
--------------------------------------------------------------------------------
/fletsb/widgets/widgets/column.py:
--------------------------------------------------------------------------------
1 | import flet
2 | from ...ui_toolkit.widget_browser_frame import Widget_Browse_Frame
3 |
4 |
5 | class Column(object):
6 | def __init__(self, main_class, parent, *args, **kwargs) -> None:
7 | self.parent = parent
8 | self.main_class = main_class
9 | self.self_object = flet.Column()
10 |
11 | self.widget_number = kwargs["widget_number"]
12 |
13 | # Column Special args.
14 | self.dont_border_subs = True
15 | self.last_added = None
16 | self.support_sub_widgets = True
17 |
18 | if main_class.development_mode:
19 | self.development_mode = True
20 | else:
21 | self.development_mode = False
22 |
23 | # all args
24 | self.args = {
25 | "width": {"type": int, "default_value": 23},
26 | "height": {"type": int, "default_value": 150},
27 | "hide": {"type": bool, "default_value": False},
28 | "scroll": {"type": bool, "default_value": False},
29 | "auto_scroll_to_end": {"type": bool, "default_value": True},
30 | "expand": {"type": bool, "default_value": True},
31 | "alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "center"},
32 | "sub_widgets_alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "center"},
33 | }
34 |
35 | # Template dict
36 | # This is where the widget data will be stored.
37 | self.template = {
38 | "widget_class_name": "Column",
39 | "properties": {},
40 | "widgets": []
41 | }
42 | for p in self.args:
43 | self.template["properties"][p] = self.args[p]["default_value"]
44 |
45 | self.update()
46 |
47 | def update(self, new_props: dict = None, new_sub_widgets: dict = None):
48 | c = self.self_object
49 | props = self.template["properties"]
50 |
51 | if new_props is not None:
52 | for i in new_props:
53 | self.template["properties"][i] = new_props[i]
54 |
55 | if new_sub_widgets is not None:
56 | for w in new_sub_widgets:
57 | self.template["widgets"].append(w)
58 |
59 | c.width = props["width"]
60 | c.height = props["height"]
61 | c.visible = props["hide"] == False
62 | c.expand = props["expand"]
63 | c.scroll = props["scroll"]
64 | c.alignment = props["sub_widgets_alignment"]
65 | c.auto_scroll = props["auto_scroll_to_end"]
66 |
67 | if self.self_object.page is not None:
68 | self.self_object.update()
69 |
70 | self.update_preview()
71 |
72 | # Column tools
73 | def widgets_to_add_in(self, *args):
74 | """To show all widgets that are available to add to the Column."""
75 | for i in args:
76 | i.control.visible = False
77 | i.control.update()
78 |
79 | def go_back(*e):
80 | self.main_class.left_section.show_new_content(copy_of_last_container)
81 | if self.last_added is not None:
82 | if self.last_added.page is None:
83 | self.last_added.border = None
84 | self.main_class.page.update()
85 | else:
86 | self.last_added.border = None
87 | self.last_added.update()
88 | self.main_class.on_page_resize()
89 | for i in args:
90 | i.control.visible = True
91 | i.control.update()
92 |
93 | page = self.main_class.page
94 | # This is the default section.
95 |
96 | col = flet.Column(scroll=True)
97 | col.controls.append(flet.TextButton("< Back", on_click=go_back))
98 | title = flet.Text("Widgets in Column", size=25, weight=flet.FontWeight.BOLD, color="white")
99 | col.controls.append(title)
100 | all_widgets = self.main_class.all_widgets
101 | for wid in all_widgets:
102 | w = Widget_Browse_Frame(wid, all_widgets[wid], self.add_new_widget, self.main_class.current_page_name)
103 | col.controls.append(w)
104 |
105 | main_container = flet.Container(
106 | content=col,
107 | bgcolor=page.bgcolor,
108 | width=page.width / 4,
109 | height=page.height
110 | )
111 |
112 | copy_of_last_container = self.main_class.left_section.self_ui.content
113 | self.main_class.left_section.show_new_content(main_container)
114 | self.main_class.on_page_resize()
115 | self.main_class.page.update()
116 |
117 | def add_new_widget(self, widget_name, page_name):
118 | """To add the widget, and open the edit to edit this new sub-widget."""
119 | self.dont_border_subs = False
120 | all_widgets = self.main_class.all_widgets
121 | widget_class = all_widgets[widget_name]["class"]
122 | widget_class = widget_class(
123 | self, self.preview_section,
124 | widget_number=len(self.template["widgets"]) - 1,
125 | is_a_sub=True
126 | )
127 |
128 | self.template["widgets"].append(widget_class.template)
129 | self.main_class.dict_content["pages"][self.main_class.current_page_name]["widgets"][self.widget_number]["widgets"] = self.template["widgets"]
130 |
131 | self.update_preview()
132 | editSubWidgetsEngine = self.main_class._editSubWidgetsEngine
133 | editSubWidgetsEngine = editSubWidgetsEngine(
134 | self.main_class,
135 | self,
136 | self.main_class.edit_section.main_column,
137 | len(self.template["widgets"]) - 1
138 | )
139 | self.main_class.page.update()
140 |
141 | def update_preview(self):
142 | all_widgets = self.main_class.all_widgets
143 | self.preview_section.controls.clear()
144 | sub_widgets = self.template["widgets"]
145 | num = 0
146 |
147 | for widget in sub_widgets:
148 | if widget["widget_class_name"] in all_widgets:
149 | widget_class = all_widgets[widget["widget_class_name"]]["class"]
150 | widget_class = widget_class(self.main_class, self.preview_section)
151 | if hasattr(widget_class, "support_sub_widgets"):
152 | widget_class.update(widget["properties"], widget["widgets"])
153 | else:
154 | widget_class.update(widget["properties"])
155 | if self.development_mode:
156 | self.create_development_container(widget_class.return_widget(), num)
157 | else:
158 | self.preview_section.controls.append(widget_class.return_widget())
159 | num = num + 1
160 |
161 | self.main_class.page.update()
162 |
163 | @property
164 | def preview_section(self):
165 | return self.self_object
166 |
167 | def return_widget(self):
168 | props = self.template["properties"]
169 |
170 | if props["alignment"] == "left":
171 | return flet.Row([flet.Text(" "), self.self_object])
172 | elif props["alignment"] == "center":
173 | return flet.Row([self.self_object], alignment=flet.MainAxisAlignment.CENTER, spacing=0)
174 | else:
175 | return flet.Row([self.self_object, flet.Text(" ")], alignment=flet.MainAxisAlignment.END)
176 |
177 | def create_development_container(self, cls, widget_number):
178 | if self.last_added is None:
179 | c = flet.Container(cls, border_radius=8, border=flet.border.all(2, flet.colors.YELLOW_300))
180 | self.last_added = c
181 | else:
182 | self.last_added.border = None
183 | c = flet.Container(cls, border_radius=8, border=flet.border.all(2, flet.colors.YELLOW_300))
184 | self.last_added = c
185 |
186 | self.preview_section.controls.append(c)
187 | return c
188 |
--------------------------------------------------------------------------------
/fletsb/widgets/widgets/image.py:
--------------------------------------------------------------------------------
1 | import flet
2 |
3 |
4 | class Image(object):
5 | def __init__(self, main_class, parent, *args, **kwargs) -> None:
6 | self.parent = parent
7 | self.main_class = main_class
8 | self.self_object = flet.Image(fit=flet.ImageFit.COVER)
9 |
10 | # all args
11 | self.args = {
12 | "src": {"type": str, "default_value": "https://picsum.photos/id/237/200/300"},
13 | "width": {"type": int, "default_value": 150},
14 | "height": {"type": int, "default_value": 150},
15 | "border_radius": {"type": int, "default_value": 75},
16 | "alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "center"},
17 | }
18 |
19 | # Template dict
20 | # This is where the widget data will be stored.
21 | self.template = {
22 | "widget_class_name": "Image",
23 | "properties": {}
24 | }
25 | for p in self.args:
26 | self.template["properties"][p] = self.args[p]["default_value"]
27 |
28 | self.update()
29 |
30 | def update(self, new_props: dict = None):
31 | img = self.self_object
32 | props = self.template["properties"]
33 |
34 | if new_props is not None:
35 | for i in new_props:
36 | self.template["properties"][i] = new_props[i]
37 |
38 | img.src = props["src"]
39 | img.width = props["width"]
40 | img.height = props["height"]
41 | img.border_radius = props["border_radius"]
42 |
43 | if self.self_object.page is not None:
44 | self.self_object.update()
45 |
46 | def return_widget(self):
47 | props = self.template["properties"]
48 | if props["alignment"] == "left":
49 | return flet.Row([flet.Text(" "), self.self_object])
50 | elif props["alignment"] == "center":
51 | return flet.Row([self.self_object], alignment=flet.MainAxisAlignment.CENTER)
52 | else:
53 | return flet.Row([self.self_object, flet.Text(" ")], alignment=flet.alignment.center_right)
54 |
--------------------------------------------------------------------------------
/fletsb/widgets/widgets/label.py:
--------------------------------------------------------------------------------
1 | import flet
2 | from ...tools.color_picker import ColorPicker
3 | from ...tools.list_picker import ListPopup
4 |
5 |
6 | class Label(object):
7 | def __init__(self, main_class, parent, *args, **kwargs) -> None:
8 | self.parent = parent
9 | self.main_class = main_class
10 | self.self_object = flet.Row()
11 | self.title_object = flet.Text()
12 | self.icon_object = flet.Icon()
13 |
14 | self.self_object.controls.append(self.icon_object)
15 | self.self_object.controls.append(self.title_object)
16 |
17 | # all args
18 | all_icons = []
19 | for icon in flet.icons.__dict__:
20 | name = str(icon)
21 | if name.startswith("__"):
22 | pass
23 | else:
24 | all_icons.append(name)
25 |
26 | self.args = {
27 | "title": {"type": str, "default_value": "Just me and coffee"},
28 | "icon": {"type": ListPopup, "options": all_icons, "default_value": "EMOJI_FOOD_BEVERAGE_ROUNDED"},
29 | "title_color": {"type": ColorPicker, "default_value": "white"},
30 | "icon_color": {"type": ColorPicker, "default_value": "white"},
31 | "title_size": {"type": int, "default_value": 18},
32 | "icon_size": {"type": int, "default_value": 18},
33 | "spacing": {"type": int, "default_value": 15},
34 | "title_bold": {"type": int, "default_value": True},
35 | "alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "center"}
36 | }
37 |
38 | # Template dict
39 | # This is where the widget data will be stored.
40 | self.template = {
41 | "widget_class_name": "Label",
42 | "properties": {}
43 | }
44 | for p in self.args:
45 | self.template["properties"][p] = self.args[p]["default_value"]
46 |
47 | self.update()
48 |
49 | def update(self, new_props: dict = None):
50 | r = self.self_object
51 | t = self.title_object
52 | I = self.icon_object
53 | props = self.template["properties"]
54 |
55 | if new_props is not None:
56 | for i in new_props:
57 | self.template["properties"][i] = new_props[i]
58 |
59 | r.spacing = props["spacing"]
60 |
61 | t.value = props["title"]
62 | t.color = props["title_color"]
63 | t.size = props["title_size"]
64 |
65 | if props["title_bold"]:
66 | t.weight = "bold"
67 | else:
68 | t.weight = "normal"
69 |
70 | I.name = props["icon"]
71 | I.color = props["icon_color"]
72 | I.size = props["icon_size"]
73 |
74 | if self.self_object.page is not None:
75 | self.self_object.update()
76 |
77 | def return_widget(self):
78 | props = self.template["properties"]
79 | if props["alignment"] == "left":
80 | return flet.Row([flet.Text(" "), self.self_object])
81 | elif props["alignment"] == "center":
82 | return flet.Row([self.self_object], alignment=flet.MainAxisAlignment.CENTER)
83 | else:
84 | return flet.Row([self.self_object, flet.Text(" ")], alignment=flet.alignment.center_right)
85 |
--------------------------------------------------------------------------------
/fletsb/widgets/widgets/markdown.py:
--------------------------------------------------------------------------------
1 | import flet
2 |
3 |
4 | class Markdown(object):
5 | def __init__(self, main_class, parent, *args, **kwargs) -> None:
6 | self.parent = parent
7 | self.main_class = main_class
8 | self.self_object = flet.Markdown(
9 | selectable=True,
10 | extension_set=flet.MarkdownExtensionSet.GITHUB_WEB,
11 | code_style=flet.TextStyle(font_family="Roboto Mono", color="blue")
12 | )
13 |
14 | # all args
15 | self.args = {
16 | "content": {"type": str, "default_value": "", "multi_line": True},
17 | "code_theme": {"type": list, "options": ["a11y-dark", "arta", "atom-one-dark", "dark", "default"],
18 | "default_value": "default"},
19 | "width": {"type": int, "default_value": 150},
20 | "height": {"type": int, "default_value": 150},
21 | "alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "left"}
22 | }
23 |
24 | # Template dict
25 | # This is where the widget data will be stored.
26 | self.template = {
27 | "widget_class_name": "Markdown",
28 | "properties": {}
29 | }
30 | for p in self.args:
31 | self.template["properties"][p] = self.args[p]["default_value"]
32 |
33 | self.update()
34 |
35 | def update(self, new_props: dict = None):
36 | m = self.self_object
37 | props = self.template["properties"]
38 |
39 | if new_props is not None:
40 | for i in new_props:
41 | self.template["properties"][i] = new_props[i]
42 |
43 | m.value = props["content"]
44 | m.width = props["width"]
45 | m.height = props["height"]
46 |
47 | if self.self_object.page is not None:
48 | self.self_object.update()
49 |
50 | def return_widget(self):
51 | props = self.template["properties"]
52 | if props["alignment"] == "left":
53 | return flet.Row([flet.Text(" "), self.self_object])
54 | elif props["alignment"] == "center":
55 | return flet.Row([self.self_object], alignment=flet.MainAxisAlignment.CENTER)
56 | else:
57 | return flet.Row([self.self_object, flet.Text(" ")], alignment=flet.alignment.center_right)
58 |
--------------------------------------------------------------------------------
/fletsb/widgets/widgets/navigator.py:
--------------------------------------------------------------------------------
1 | import flet
2 | from ...tools.color_picker import ColorPicker
3 |
4 |
5 | class Navigator(object):
6 | def __init__(self, main_class, parent, *args, **kwargs) -> None:
7 | self.parent = parent
8 | self.main_class = main_class
9 | self.self_object = flet.ElevatedButton(on_click=self.on_button_click)
10 |
11 | # all args
12 | all_pages = []
13 | for i in self.main_class.dict_content["pages"]:
14 | all_pages.append(i)
15 | self.args = {
16 | "text": {"type": str, "default_value": "click me"},
17 | "page name": {"type": list, "options": all_pages, "default_value": "main"},
18 | "width": {"type": int, "default_value": 150},
19 | "height": {"type": int, "default_value": 45},
20 | "alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "center"},
21 | "bgcolor": {"type": ColorPicker, "default_value": "black"},
22 | "text_color": {"type": ColorPicker, "default_value": "blue"}
23 | }
24 |
25 | # Template dict
26 | # This is where the widget data will be stored.
27 | self.template = {
28 | "widget_class_name": "Navigator",
29 | "properties": {}
30 | }
31 | for p in self.args:
32 | self.template["properties"][p] = self.args[p]["default_value"]
33 |
34 | self.update()
35 |
36 | def update(self, new_props: dict = None):
37 | t = self.self_object
38 | props = self.template["properties"]
39 |
40 | if new_props is not None:
41 | for i in new_props:
42 | self.template["properties"][i] = new_props[i]
43 |
44 | t.text = props["text"]
45 | t.color = props["text_color"]
46 | t.bgcolor = props["bgcolor"]
47 | t.width = props["width"]
48 | t.height = props["height"]
49 |
50 | if self.self_object.page is not None:
51 | self.self_object.update()
52 |
53 | def on_button_click(self, event):
54 | if self.main_class.development_mode:
55 | return
56 | else:
57 | props = self.template["properties"]
58 | self.main_class.storyboard_class.navigate_to_page(props["page name"])
59 |
60 | def return_widget(self):
61 | props = self.template["properties"]
62 | if self.main_class.development_mode:
63 | self.self_object.disabled = True
64 | if props["alignment"] == "left":
65 | return flet.Row([flet.Text(" "), self.self_object])
66 | elif props["alignment"] == "center":
67 | return flet.Row([self.self_object], alignment=flet.MainAxisAlignment.CENTER)
68 | else:
69 | return flet.Row([self.self_object, flet.Text(" ")], alignment=flet.alignment.center_right)
70 |
--------------------------------------------------------------------------------
/fletsb/widgets/widgets/open_url.py:
--------------------------------------------------------------------------------
1 | import flet
2 | from ...tools.color_picker import ColorPicker
3 | from ...tools.list_picker import ListPopup
4 |
5 |
6 | class Open_Url(object):
7 | def __init__(self, main_class, parent, *args, **kwargs) -> None:
8 | self.parent = parent
9 | self.main_class = main_class
10 | self.self_object = flet.Container(on_click=self.open_url)
11 | self.url_text = flet.Text()
12 | self.url_icon = flet.Icon(size=12)
13 | self.self_object.content = flet.Row([self.url_icon, self.url_text], alignment=flet.MainAxisAlignment.CENTER)
14 |
15 | # all args
16 | all_icons = []
17 | for icon in flet.icons.__dict__:
18 | name = str(icon)
19 | if name.startswith("__"):
20 | pass
21 | else:
22 | all_icons.append(name)
23 |
24 | self.args = {
25 | "text": {"type": str, "default_value": "example url"},
26 | "url": {"type": str, "default_value": "https://example.com"},
27 | "link icon": {"type": ListPopup, "options": all_icons, "default_value": "INSERT_LINK_OUTLINED"},
28 | "text_color": {"type": ColorPicker, "default_value": "blue"},
29 | "icon_color": {"type": ColorPicker, "default_value": "blue"},
30 | "bgcolor": {"type": ColorPicker, "default_value": "black"},
31 | "alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "center"},
32 | "width": {"type": int, "default_value": 130},
33 | "height": {"type": int, "default_value": 30},
34 | "text_size": {"type": int, "default_value": 15},
35 | "icon_size": {"type": int, "default_value": 15},
36 | "border_radius": {"type": int, "default_value": 10},
37 | "hide": {"type": bool, "default_value": False}
38 | }
39 |
40 | # Template dict
41 | # This is where the widget data will be stored.
42 | self.template = {
43 | "widget_class_name": "Open Url",
44 | "properties": {}
45 | }
46 | for p in self.args:
47 | self.template["properties"][p] = self.args[p]["default_value"]
48 |
49 | self.update()
50 |
51 | def update(self, new_props: dict = None):
52 | c = self.self_object
53 | t = self.url_text
54 | ii = self.url_icon
55 | props = self.template["properties"]
56 |
57 | if new_props is not None:
58 | for i in new_props:
59 | self.template["properties"][i] = new_props[i]
60 |
61 | url = props["url"]
62 | c.tooltip = f"open '{url}'"
63 | c.width = props["width"]
64 | c.bgcolor = props["bgcolor"]
65 | c.border_radius = props["border_radius"]
66 | c.height = props["height"]
67 | c.visible = props["hide"] == False
68 |
69 | t.value = props["text"]
70 | t.color = props["text_color"]
71 | t.text_align = props["text_color"]
72 | t.size = props["text_size"]
73 |
74 | ii.name = props["link icon"]
75 | ii.color = props["icon_color"]
76 | ii.size = props["icon_size"]
77 | if self.self_object.page is not None:
78 | self.self_object.update()
79 |
80 | def open_url(self, event):
81 | if self.main_class.development_mode: return
82 | url = self.template["properties"]["url"]
83 | event.control.page.launch_url(url)
84 |
85 | def return_widget(self):
86 | props = self.template["properties"]
87 | if props["alignment"] == "left":
88 | return flet.Row([flet.Text(" "), self.self_object])
89 | elif props["alignment"] == "center":
90 | return flet.Row([self.self_object], alignment=flet.MainAxisAlignment.CENTER)
91 | else:
92 | # issue: right is not a valid value
93 | return flet.Row([self.self_object, flet.Text(" ")], alignment="right")
94 |
--------------------------------------------------------------------------------
/fletsb/widgets/widgets/padding.py:
--------------------------------------------------------------------------------
1 | import flet
2 |
3 |
4 | class Padding(object):
5 | def __init__(self, main_class, parent, *args, **kwargs) -> None:
6 | self.parent = parent
7 | self.main_class = main_class
8 | self.self_object = flet.Text("")
9 |
10 | # all args
11 | self.args = {
12 | "width": {"type": int, "default_value": 50},
13 | "height": {"type": int, "default_value": 50},
14 | "alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "center"}
15 | }
16 |
17 | # Template dict
18 | # This is where the widget data will be stored.
19 | self.template = {
20 | "widget_class_name": "Padding",
21 | "properties": {}
22 | }
23 | for p in self.args:
24 | self.template["properties"][p] = self.args[p]["default_value"]
25 |
26 | self.update()
27 |
28 | def update(self, new_props: dict = None):
29 | p = self.self_object
30 | props = self.template["properties"]
31 |
32 | if new_props is not None:
33 | for i in new_props:
34 | self.template["properties"][i] = new_props[i]
35 |
36 | p.width = props["width"]
37 | p.height = props["height"]
38 |
39 | if self.self_object.page is not None:
40 | self.self_object.update()
41 |
42 | def return_widget(self):
43 | props = self.template["properties"]
44 | if props["alignment"] == "left":
45 | return flet.Row([flet.Text(" "), self.self_object])
46 | elif props["alignment"] == "center":
47 | return flet.Row([self.self_object], alignment=flet.MainAxisAlignment.CENTER)
48 | else:
49 | return flet.Row([self.self_object, flet.Text(" ")], alignment=flet.alignment.center_right)
50 |
--------------------------------------------------------------------------------
/fletsb/widgets/widgets/paragraph.py:
--------------------------------------------------------------------------------
1 | import flet
2 | from ...tools.color_picker import ColorPicker
3 |
4 |
5 | class Paragraph(object):
6 | def __init__(self, main_class, parent, *args, **kwargs) -> None:
7 | self.parent = parent
8 | self.main_class = main_class
9 | self.self_object = flet.Text("")
10 |
11 | # all args
12 | self.args = {
13 | "text": {"type": str,
14 | "default_value": "dude,\nThere is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain 🙃...",
15 | "multi_line": True},
16 | "text_color": {"type": ColorPicker, "default_value": "white"},
17 | "size": {"type": int, "default_value": 16},
18 | "width": {"type": int, "default_value": 300},
19 | "italic": {"type": bool, "default_value": False},
20 | "bold": {"type": bool, "default_value": False},
21 | "hide": {"type": bool, "default_value": False},
22 | "expand": {"type": bool, "default_value": False},
23 | "alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "center"},
24 | "text_align": {"type": list, "options": ["left", "center", "right"], "default_value": "left"}
25 | }
26 |
27 | # Template dict
28 | # This is where the widget data will be stored.
29 | self.template = {
30 | "widget_class_name": "Paragraph",
31 | "properties": {}
32 | }
33 | for p in self.args:
34 | self.template["properties"][p] = self.args[p]["default_value"]
35 |
36 | self.update()
37 |
38 | def update(self, new_props: dict = None):
39 | t = self.self_object
40 | props = self.template["properties"]
41 |
42 | if new_props is not None:
43 | for i in new_props:
44 | self.template["properties"][i] = new_props[i]
45 |
46 | t.value = props["text"]
47 | t.size = props["size"]
48 | t.color = props["text_color"]
49 | t.width = props["width"]
50 | t.expand = props["expand"]
51 | t.italic = props["italic"]
52 | t.visible = props["hide"] == False
53 |
54 | if str(props["text_align"]).lower() == "left":
55 | t.text_align = flet.TextAlign.LEFT
56 | elif str(props["text_align"]).lower() == "center":
57 | t.text_align = flet.TextAlign.CENTER
58 | elif str(props["text_align"]).lower() == "right":
59 | t.text_align = flet.TextAlign.RIGHT
60 |
61 | if props["bold"]:
62 | t.weight = "bold"
63 | else:
64 | t.weight = "normal"
65 |
66 | if self.self_object.page is not None:
67 | self.self_object.update()
68 |
69 | def return_widget(self):
70 | props = self.template["properties"]
71 | if props["alignment"] == "left":
72 | return flet.Row([flet.Text(" "), self.self_object])
73 | elif props["alignment"] == "center":
74 | return flet.Row([self.self_object], alignment=flet.MainAxisAlignment.CENTER)
75 | else:
76 | return flet.Row([self.self_object, flet.Text(" ")], alignment=flet.alignment.center_right)
77 |
--------------------------------------------------------------------------------
/fletsb/widgets/widgets/row.py:
--------------------------------------------------------------------------------
1 | import flet
2 | from ...ui_toolkit.widget_browser_frame import Widget_Browse_Frame
3 |
4 |
5 | class Row(object):
6 | def __init__(self, main_class, parent, *args, **kwargs) -> None:
7 | self.parent = parent
8 | self.main_class = main_class
9 | self.self_object = flet.Row()
10 |
11 | self.widget_number = kwargs["widget_number"]
12 |
13 | # Row Special args.
14 | self.dont_border_subs = True
15 | self.last_added = None
16 | self.support_sub_widgets = True
17 |
18 | if main_class.development_mode:
19 | self.development_mode = True
20 | else:
21 | self.development_mode = False
22 |
23 | # all args
24 | self.args = {
25 | "width": {"type": int, "default_value": 23},
26 | "height": {"type": int, "default_value": 150},
27 | "hide": {"type": bool, "default_value": False},
28 | "scroll": {"type": bool, "default_value": False},
29 | "auto_scroll_to_end": {"type": bool, "default_value": True},
30 | "expand": {"type": bool, "default_value": True},
31 | "alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "center"},
32 | "sub_widgets_alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "center"},
33 | }
34 |
35 | # Template dict
36 | # This is where the widget data will be stored.
37 | self.template = {
38 | "widget_class_name": "Row",
39 | "properties": {},
40 | "widgets": []
41 | }
42 | for p in self.args:
43 | self.template["properties"][p] = self.args[p]["default_value"]
44 |
45 | self.update()
46 |
47 | def update(self, new_props: dict = None, new_sub_widgets: dict = None):
48 | r = self.self_object
49 | props = self.template["properties"]
50 |
51 | if new_props is not None:
52 | for i in new_props:
53 | self.template["properties"][i] = new_props[i]
54 |
55 | if new_sub_widgets is not None:
56 | for w in new_sub_widgets:
57 | self.template["widgets"].append(w)
58 |
59 | r.width = props["width"]
60 | r.height = props["height"]
61 | r.visible = props["hide"] == False
62 | r.expand = props["expand"]
63 | r.scroll = props["scroll"]
64 | r.alignment = props["sub_widgets_alignment"]
65 | r.auto_scroll = props["auto_scroll_to_end"]
66 |
67 | if self.self_object.page is not None:
68 | self.self_object.update()
69 |
70 | self.update_preview()
71 |
72 | # Row tools
73 | def widgets_to_add_in(self, *args):
74 | """To show all widgets that are available to add to the row."""
75 | for i in args:
76 | i.control.visible = False
77 | i.control.update()
78 |
79 | def go_back(*e):
80 | self.main_class.left_section.show_new_content(copy_of_last_container)
81 | if self.last_added is not None:
82 | if self.last_added.page is None:
83 | self.last_added.border = None
84 | self.main_class.page.update()
85 | else:
86 | self.last_added.border = None
87 | self.last_added.update()
88 | self.main_class.on_page_resize()
89 | for i in args:
90 | i.control.visible = True
91 | i.control.update()
92 |
93 | page = self.main_class.page
94 | # This is the default section.
95 |
96 | # issue: scroll has not attribute True
97 | col = flet.Column(scroll=True)
98 | col.controls.append(flet.TextButton("< Back", on_click=go_back))
99 | title = flet.Text("Widgets in row", size=25, weight=flet.FontWeight.BOLD, color="white")
100 | col.controls.append(title)
101 | all_widgets = self.main_class.all_widgets
102 | for wid in all_widgets:
103 | w = Widget_Browse_Frame(wid, all_widgets[wid], self.add_new_widget, self.main_class.current_page_name)
104 | col.controls.append(w)
105 |
106 | main_container = flet.Container(
107 | content=col,
108 | bgcolor=page.bgcolor,
109 | width=page.width / 4,
110 | height=page.height
111 | )
112 |
113 | copy_of_last_container = self.main_class.left_section.self_ui.content
114 | self.main_class.left_section.show_new_content(main_container)
115 | self.main_class.on_page_resize()
116 | self.main_class.page.update()
117 |
118 | def add_new_widget(self, widget_name, page_name):
119 | """To add the widget, and open the edit to edit this new sub-widget."""
120 | self.dont_border_subs = False
121 | all_widgets = self.main_class.all_widgets
122 | widget_class = all_widgets[widget_name]["class"]
123 | widget_class = widget_class(
124 | self, self.preview_section,
125 | widget_number=len(self.template["widgets"]) - 1,
126 | is_a_sub=True
127 | )
128 |
129 | self.template["widgets"].append(widget_class.template)
130 | self.main_class.dict_content["pages"][self.main_class.current_page_name]["widgets"][self.widget_number]["widgets"] = self.template["widgets"]
131 |
132 | self.update_preview()
133 | editSubWidgetsEngine = self.main_class._editSubWidgetsEngine
134 | editSubWidgetsEngine = editSubWidgetsEngine(
135 | self.main_class,
136 | self,
137 | self.main_class.edit_section.main_column,
138 | len(self.template["widgets"]) - 1
139 | )
140 | self.main_class.page.update()
141 |
142 | def update_preview(self):
143 | all_widgets = self.main_class.all_widgets
144 | self.preview_section.controls.clear()
145 | sub_widgets = self.template["widgets"]
146 | num = 0
147 |
148 | for widget in sub_widgets:
149 | if widget["widget_class_name"] in all_widgets:
150 | widget_class = all_widgets[widget["widget_class_name"]]["class"]
151 | widget_class = widget_class(self.main_class, self.preview_section)
152 | if hasattr(widget_class, "support_sub_widgets"):
153 | widget_class.update(widget["properties"], widget["widgets"])
154 | else:
155 | widget_class.update(widget["properties"])
156 | if self.development_mode:
157 | self.create_development_container(widget_class.return_widget(), num)
158 | else:
159 | self.preview_section.controls.append(widget_class.return_widget())
160 | num = num + 1
161 |
162 | self.main_class.page.update()
163 |
164 | @property
165 | def preview_section(self):
166 | return self.self_object
167 |
168 | def return_widget(self):
169 | props = self.template["properties"]
170 |
171 | if props["alignment"] == "left":
172 | return flet.Row([flet.Text(" "), self.self_object])
173 | elif props["alignment"] == "center":
174 | return flet.Row([self.self_object], alignment=flet.MainAxisAlignment.CENTER, spacing=0)
175 | else:
176 | return flet.Row([self.self_object, flet.Text(" ")], alignment=flet.MainAxisAlignment.END)
177 |
178 | def create_development_container(self, cls, widget_number):
179 | if self.last_added is None:
180 | c = flet.Container(cls, border_radius=8, border=flet.border.all(2, flet.colors.YELLOW_300))
181 | self.last_added = c
182 | else:
183 | self.last_added.border = None
184 | c = flet.Container(cls, border_radius=8, border=flet.border.all(2, flet.colors.YELLOW_300))
185 | self.last_added = c
186 |
187 | self.preview_section.controls.append(c)
188 | return c
189 |
--------------------------------------------------------------------------------
/fletsb/widgets/widgets/textfield.py:
--------------------------------------------------------------------------------
1 | import flet
2 | from ...tools.color_picker import ColorPicker
3 |
4 |
5 | class TextField(object):
6 | def __init__(self, main_class, parent, *args, **kwargs) -> None:
7 | self.parent = parent
8 | self.main_class = main_class
9 | self.self_object = flet.TextField(
10 | on_focus=self.on_start_type,
11 | on_change=self.on_change_text,
12 | on_submit=self.on_end_type,
13 | selection_color=flet.colors.BLACK,
14 | cursor_color=flet.colors.BLACK
15 | )
16 |
17 | # all args
18 | self.args = {
19 | "text": {"type": str, "default_value": ""},
20 | "label": {"type": str, "default_value": "text.."},
21 | "hint_text": {"type": str, "default_value": "text.."},
22 | "can_reveal_password": {"type": bool, "default_value": True},
23 | "password": {"type": bool, "default_value": False},
24 | "width": {"type": int, "default_value": 200},
25 | "height": {"type": int, "default_value": 65},
26 | "border_radius": {"type": int, "default_value": 12},
27 | "bgcolor": {"type": ColorPicker, "default_value": "white"},
28 | "color": {"type": ColorPicker, "default_value": "black"},
29 | "alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "center"},
30 | "on start": {"type": str, "default_value": ""},
31 | "on change": {"type": str, "default_value": ""},
32 | "on end": {"type": str, "default_value": ""},
33 | "point name": {"type": str, "default_value": ""}
34 | }
35 |
36 | # Template dict
37 | # This is where the widget data will be stored.
38 | self.template = {
39 | "widget_class_name": "TextField",
40 | "properties": {}
41 | }
42 | for p in self.args:
43 | self.template["properties"][p] = self.args[p]["default_value"]
44 |
45 | self.update()
46 |
47 | def update(self, new_props: dict = None):
48 | tf = self.self_object
49 | props = self.template["properties"]
50 |
51 | if new_props is not None:
52 | for i in new_props:
53 | self.template["properties"][i] = new_props[i]
54 |
55 | tf.value = props["text"]
56 | tf.label = props["label"]
57 | tf.hint_text = props["hint_text"]
58 | tf.password = props["password"]
59 | tf.can_reveal_password = props["can_reveal_password"]
60 | tf.width = props["width"]
61 | tf.height = props["height"]
62 | tf.bgcolor = props["bgcolor"]
63 | tf.color = props["color"]
64 | tf.border_radius = props["border_radius"]
65 |
66 | if self.self_object.page is not None:
67 | self.self_object.update()
68 |
69 | def on_start_type(self, event):
70 | if self.main_class.development_mode:
71 | return
72 | else:
73 | props = self.template["properties"]
74 | if props["on start"] == "":
75 | return
76 |
77 | if props["on start"] in self.main_class.storyboard_class.functions:
78 | self.main_class.storyboard_class.functions[props["on start"]]()
79 | else:
80 | fn = props["on start"]
81 | print(f"Pass error: There is not function found called {fn}")
82 |
83 | def on_change_text(self, event):
84 | if self.main_class.development_mode:
85 | return
86 | else:
87 | props = self.template["properties"]
88 | if props["point name"] != "":
89 | self.main_class.storyboard_class.points[props["point name"]] = str(self.self_object.value)
90 | if props["on change"] == "":
91 | return
92 |
93 | if props["on change"] in self.main_class.storyboard_class.functions:
94 | self.main_class.storyboard_class.functions[props["on change"]](self.self_object.value)
95 | else:
96 | fn = props["on change"]
97 | print(f"Pass error: There is not function found called {fn}")
98 |
99 | def on_end_type(self, event):
100 | if self.main_class.development_mode:
101 | return
102 | else:
103 | props = self.template["properties"]
104 | if props["point name"] != "":
105 | self.main_class.storyboard_class.points[props["point name"]] = str(self.self_object.value)
106 | if props["on end"] == "": return
107 |
108 | if props["on end"] in self.main_class.storyboard_class.functions:
109 | self.main_class.storyboard_class.functions[props["on end"]](self.self_object.value)
110 | else:
111 | fn = props["on end"]
112 | print(f"Pass error: There is not function found called {fn}")
113 |
114 | def return_widget(self):
115 | if self.main_class.development_mode:
116 | self.self_object.disabled = True
117 | props = self.template["properties"]
118 | if props["alignment"] == "left":
119 | return flet.Row([flet.Text(" "), self.self_object])
120 | elif props["alignment"] == "center":
121 | return flet.Row([self.self_object], alignment=flet.MainAxisAlignment.CENTER)
122 | else:
123 | return flet.Row([self.self_object, flet.Text(" ")], alignment=flet.alignment.center_right)
124 |
--------------------------------------------------------------------------------
/fletsb/widgets/widgets/title.py:
--------------------------------------------------------------------------------
1 | import flet
2 | from ...tools.color_picker import ColorPicker
3 |
4 |
5 | class Title(object):
6 | def __init__(self, main_class, parent, *args, **kwargs) -> None:
7 | self.parent = parent
8 | self.main_class = main_class
9 | self.self_object = flet.Text("")
10 |
11 | # all args
12 | self.args = {
13 | "title": {"type": str, "default_value": "myTitle"},
14 | "title_color": {"type": ColorPicker, "default_value": "white"},
15 | "size": {"type": int, "default_value": 23},
16 | "width": {"type": int, "default_value": 350},
17 | "italic": {"type": bool, "default_value": False},
18 | "bold": {"type": bool, "default_value": True},
19 | "hide": {"type": bool, "default_value": False},
20 | "expand": {"type": bool, "default_value": False},
21 | "alignment": {"type": list, "options": ["left", "center", "right"], "default_value": "center"},
22 | "text_align": {"type": list, "options": ["left", "center", "right"], "default_value": "left"}
23 | }
24 |
25 | # Template dict
26 | # This is where the widget data will be stored.
27 | self.template = {
28 | "widget_class_name": "Title",
29 | "properties": {}
30 | }
31 | for p in self.args:
32 | self.template["properties"][p] = self.args[p]["default_value"]
33 |
34 | self.update()
35 |
36 | def update(self, new_props: dict = None):
37 | t = self.self_object
38 | props = self.template["properties"]
39 |
40 | if new_props is not None:
41 | for i in new_props:
42 | self.template["properties"][i] = new_props[i]
43 |
44 | t.value = props["title"]
45 | t.size = props["size"]
46 | t.color = props["title_color"]
47 | t.width = props["width"]
48 | t.expand = props["expand"]
49 | t.italic = props["italic"]
50 | t.visible = props["hide"] == False
51 | if str(props["text_align"]).lower() == "left":
52 | t.text_align = flet.TextAlign.LEFT
53 | elif str(props["text_align"]).lower() == "center":
54 | t.text_align = flet.TextAlign.CENTER
55 | elif str(props["text_align"]).lower() == "right":
56 | t.text_align = flet.TextAlign.RIGHT
57 |
58 | if props["bold"]:
59 | t.weight = "bold"
60 | else:
61 | t.weight = "normal"
62 |
63 | if self.self_object.page is not None:
64 | self.self_object.update()
65 |
66 | def return_widget(self):
67 | props = self.template["properties"]
68 | if props["alignment"] == "left":
69 | return flet.Row([flet.Text(" "), self.self_object])
70 | elif props["alignment"] == "center":
71 | return flet.Row([self.self_object], alignment=flet.MainAxisAlignment.CENTER)
72 | else:
73 | return flet.Row([self.self_object, flet.Text(" ")], alignment=flet.alignment.center_right)
74 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = [
3 | "setuptools>=54",
4 | "wheel"
5 | ]
6 | build-backend = "setuptools.build_meta"
--------------------------------------------------------------------------------
/rules/about_me.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules" : [
3 | {
4 | "case" : {},
5 | "sugs" : [
6 | {
7 | "class" : "Title",
8 | "about" : "Add a short title to make your page better.",
9 | "props" : {
10 | "title" : "hey 👋!",
11 | "size" : 26
12 | }
13 | }
14 | ]
15 | },
16 | {
17 | "case" : {"Title":1},
18 | "sugs" : [
19 | {
20 | "class" : "Image",
21 | "about" : "Add an image to make the page look better.",
22 | "props" : {
23 | "src" : "https://images.pexels.com/photos/5220075/pexels-photo-5220075.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
24 | "width" : 150,
25 | "height" : 150,
26 | "border_radius" : 35
27 | }
28 | }
29 | ]
30 | },
31 | {
32 | "case" : {"Title":1, "Image":1},
33 | "sugs" : [
34 | {
35 | "class" : "Title",
36 | "about" : "Add a small text under the image to make it knowable by users.",
37 | "props" : {
38 | "title" : "Thats me :)",
39 | "size" : 11,
40 | "width" : 130,
41 | "bold" : false
42 | }
43 | },
44 | {
45 | "class" : "Paragraph",
46 | "about" : "Add a paragraph that talks about you.",
47 | "props" : {
48 | "text" : "hello !,\nmy name is Dave, and I'm just a\nfictional legend. And also I am a content creator!",
49 | "size" : 16,
50 | "bold" : true
51 | }
52 | }
53 | ]
54 | },
55 | {
56 | "case" : {"Title":2, "Image":1},
57 | "sugs" : [
58 | {
59 | "class" : "Paragraph",
60 | "about" : "Add a paragraph that talks about you.",
61 | "props" : {
62 | "text" : "hello !,\nmy name is Dave, and I'm just a\nfictional legend. And also I am a content creator!",
63 | "size" : 16,
64 | "bold" : true
65 | }
66 | }
67 | ]
68 | },
69 | {
70 | "case" : {"Title":2, "Image":1, "Paragraph":1},
71 | "sugs" : [
72 | {
73 | "class" : "Padding",
74 | "about" : "Add padding to make space between widgets.",
75 | "props" : {
76 | "height" : 60
77 | }
78 | },
79 | {
80 | "class" : "Open Url",
81 | "about" : "Add a link to one of your accounts or to email.",
82 | "props" : {
83 | "text" : "TikTok - 20k",
84 | "link icon" : "TIKTOK_ROUNDED",
85 | "text_color" : "black",
86 | "bgcolor" : "white",
87 | "icon_color" : "black",
88 | "width" : 150,
89 | "height" : 40,
90 | "text_size" : 15,
91 | "icon_size" : 15
92 | }
93 | }
94 | ]
95 | },
96 | {
97 | "case" : {"Title":2, "Image":1, "Paragraph":1, "Padding":1},
98 | "sugs" : [
99 | {
100 | "class" : "Open Url",
101 | "about" : "Add a link to one of your accounts or to email.",
102 | "props" : {
103 | "text" : "TikTok - 20k",
104 | "link icon" : "TIKTOK_ROUNDED",
105 | "text_color" : "black",
106 | "bgcolor" : "white",
107 | "icon_color" : "black",
108 | "width" : 150,
109 | "height" : 40,
110 | "text_size" : 15,
111 | "icon_size" : 15
112 | }
113 | }
114 | ]
115 | },
116 | {
117 | "case" : {"Title":1, "Image":1, "Paragraph":1},
118 | "sugs" : [
119 | {
120 | "class" : "Padding",
121 | "about" : "Add padding to make space between widgets.",
122 | "props" : {
123 | "height" : 60
124 | }
125 | },
126 | {
127 | "class" : "Open Url",
128 | "about" : "Add a link to one of your accounts or to email.",
129 | "props" : {
130 | "text" : "TikTok - 20k",
131 | "link icon" : "TIKTOK_ROUNDED",
132 | "text_color" : "black",
133 | "bgcolor" : "white",
134 | "icon_color" : "black",
135 | "width" : 150,
136 | "height" : 40,
137 | "text_size" : 15,
138 | "icon_size" : 15
139 | }
140 | }
141 | ]
142 | },
143 | {
144 | "case" : {"Title":1, "Image":1, "Paragraph":1, "Padding":1},
145 | "sugs" : [
146 | {
147 | "class" : "Open Url",
148 | "about" : "Add a link to one of your accounts or to email.",
149 | "props" : {
150 | "text" : "TikTok - 20k",
151 | "link icon" : "TIKTOK_ROUNDED",
152 | "text_color" : "black",
153 | "bgcolor" : "white",
154 | "icon_color" : "black",
155 | "width" : 150,
156 | "height" : 40,
157 | "text_size" : 15,
158 | "icon_size" : 15
159 | }
160 | }
161 | ]
162 | }
163 |
164 | ]
165 | }
166 |
--------------------------------------------------------------------------------
/rules/all.json:
--------------------------------------------------------------------------------
1 | {
2 | "all_rules" : {
3 | "sign_in page" : "https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/main/rules/signin_rules.json",
4 | "about_me page" : "https://raw.githubusercontent.com/SKbarbon/Flet_StoryBoard/main/rules/about_me.json"
5 | }
6 | }
--------------------------------------------------------------------------------
/rules/signin_rules.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules" : [
3 | {
4 | "case" : {},
5 | "sugs" : [
6 | {
7 | "class" : "Title",
8 | "about" : "Add a 'sign in' title so users know about this page.",
9 | "props" : {
10 | "title" : "sign in",
11 | "size" : 26
12 | }
13 | }
14 | ]
15 | },
16 | {
17 | "case" : {"Title":1},
18 | "sugs" : [
19 | {
20 | "class" : "Paragraph",
21 | "about" : "Add a paragraph describing the current page, in a little more detail.",
22 | "props" : {
23 | "text" : "You look like you did not sign in.\nPlease sign in to start using the app 😃."
24 | }
25 | },
26 | {
27 | "class" : "TextField",
28 | "about" : "Add a username TextField so users can enter their names.",
29 | "props" : {
30 | "label" : "username",
31 | "hint_text" : "username"
32 | }
33 | }
34 | ]
35 | },
36 | {
37 | "case" : {"Title":1, "Paragraph":1},
38 | "sugs" : [
39 | {
40 | "class" : "TextField",
41 | "about" : "Add a username TextField so users can enter their names.",
42 | "props" : {
43 | "label" : "username",
44 | "hint_text" : "username",
45 | "width" : 250,
46 | "height" : 50
47 | }
48 | }
49 | ]
50 | },
51 | {
52 | "case" : {"Title":1, "Paragraph":1, "TextField":1},
53 | "sugs" : [
54 | {
55 | "class" : "TextField",
56 | "about" : "Add a password TextField so users can enter their passwords.",
57 | "props" : {
58 | "label" : "password",
59 | "hint_text" : "password",
60 | "password" : true,
61 | "width" : 250,
62 | "height" : 50
63 | }
64 | }
65 | ]
66 | },
67 | {
68 | "case" : {"Title":1, "Paragraph":1, "TextField":2},
69 | "sugs" : [
70 | {
71 | "class" : "Button",
72 | "about" : "Add a button to submit the sign-in.",
73 | "props" : {
74 | "text" : "Done!",
75 | "text_color" : "white",
76 | "bgcolor" : "blue",
77 | "width" : 100,
78 | "height" : 40
79 | }
80 | }
81 | ]
82 | },
83 | {
84 | "case" : {"Title":1, "TextField":1},
85 | "sugs" : [
86 | {
87 | "class" : "TextField",
88 | "about" : "Add a password TextField so users can enter their passwords.",
89 | "props" : {
90 | "label" : "password",
91 | "hint_text" : "password",
92 | "password" : true,
93 | "width" : 250,
94 | "height" : 50
95 | }
96 | }
97 | ]
98 | },
99 | {
100 | "case" : {"Title":1, "TextField":2},
101 | "sugs" : [
102 | {
103 | "class" : "Button",
104 | "about" : "Add a button to submit the sign-in.",
105 | "props" : {
106 | "text" : "Done!",
107 | "text_color" : "white",
108 | "bgcolor" : "blue",
109 | "width" : 100,
110 | "height" : 40
111 | }
112 | }
113 | ]
114 | },
115 | {
116 | "case" : {"Paragraph":1},
117 | "sugs" : [
118 | {
119 | "class" : "TextField",
120 | "about" : "Add a username TextField so users can enter their names.",
121 | "props" : {
122 | "label" : "username",
123 | "hint_text" : "username",
124 | "width" : 250,
125 | "height" : 50
126 | }
127 | }
128 | ]
129 | },
130 | {
131 | "case" : {"Paragraph":1, "TextField":1},
132 | "sugs" : [
133 | {
134 | "class" : "TextField",
135 | "about" : "Add a password TextField so users can enter their passwords.",
136 | "props" : {
137 | "label" : "password",
138 | "hint_text" : "password",
139 | "password" : true,
140 | "width" : 250,
141 | "height" : 50
142 | }
143 | }
144 | ]
145 | },
146 | {
147 | "case" : {"Paragraph":1, "TextField":2},
148 | "sugs" : [
149 | {
150 | "class" : "Button",
151 | "about" : "Add a button to submit the sign-in.",
152 | "props" : {
153 | "text" : "Done!",
154 | "text_color" : "white",
155 | "bgcolor" : "blue",
156 | "width" : 100,
157 | "height" : 40
158 | }
159 | }
160 | ]
161 | },
162 | {
163 | "case" : {"Title":1, "Paragraph":1, "TextField":2, "Label":1},
164 | "sugs" : [
165 | {
166 | "class" : "Button",
167 | "about" : "Add a button to submit the sign-in.",
168 | "props" : {
169 | "text" : "Done!",
170 | "text_color" : "white",
171 | "bgcolor" : "blue",
172 | "width" : 100,
173 | "height" : 40
174 | }
175 | }
176 | ]
177 | }
178 | ]
179 | }
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 |
3 | with open("README.md", encoding="utf-8") as f:
4 | long_des = str(f.read())
5 |
6 | setup(
7 | name='Flet StoryBoard',
8 | version='1.5',
9 | author='SKbarbon',
10 | description='A UI-Builder that helps programmers build the front-end without codding it.',
11 | long_description=long_des,
12 | long_description_content_type='text/markdown',
13 | url='https://github.com/SKbarbon/Flet-StoryBoard',
14 | install_requires=["flet==0.5.2", "requests", "bardapi"],
15 | packages=find_packages(),
16 | classifiers=[
17 | "Programming Language :: Python :: 3",
18 | "Operating System :: MacOS :: MacOS X",
19 | "Operating System :: Microsoft :: Windows"
20 | ],
21 | )
--------------------------------------------------------------------------------