314 Commits
beta ... v1.5.0

Author SHA1 Message Date
Robert Jelic
21ff14cf31 Update installer.md 2022-07-28 13:30:35 +02:00
Robert Jelic
8dc84fa241 Update design.md 2022-07-27 17:20:33 +02:00
Robert Jelic
90b450371a Update design.md 2022-07-27 16:56:53 +02:00
Robert Jelic
3e6fae3748 Merge pull request #20 from Erb3/master
Issue Templates
2022-07-27 16:30:33 +02:00
Erlend
c09b778853 Merge branch 'Pyroxenium:master' into master 2022-07-27 16:26:58 +02:00
Erlend
49d4b20ba6 Rename bug report form 2022-07-27 16:25:59 +02:00
Erlend
efcf87e26e Bug report form test 1 2022-07-27 16:24:36 +02:00
Robert Jelic
d30dda60a0 Update basaltPackageManager.lua 2022-07-27 16:18:06 +02:00
Robert Jelic
83a27fbd09 Update Basalt.md 2022-07-27 13:22:04 +02:00
Robert Jelic
763d30a541 fixed bad typing on schedule 2022-07-27 13:21:02 +02:00
Erlend
274aa5babc Add config.yml to issue templates 2022-07-27 12:49:35 +02:00
Erlend
332f19cf8d Rephrase a word on docs issue template 2022-07-27 12:42:45 +02:00
Erlend
a0e17cd425 Add documentation issue templates 2022-07-27 12:41:38 +02:00
Erlend
12e374dcd0 Add feature issue template 2022-07-27 12:40:26 +02:00
Erlend
d0ed3b9e5e Create bug report template 2022-07-27 12:38:01 +02:00
Robert Jelic
5d5df85e8b Update main.lua 2022-07-27 12:37:45 +02:00
Robert Jelic
bb77a42f91 Update basaltPackageManager.lua 2022-07-27 10:06:15 +02:00
Robert Jelic
26b2f5da56 Merge branch 'master' of https://github.com/Pyroxenium/Basalt 2022-07-27 02:48:39 +02:00
Robert Jelic
5bc66a5027 github token
added github token
2022-07-27 02:48:36 +02:00
Robert Jelic
69cd3686ea Update README.md 2022-07-26 00:02:10 +02:00
Robert Jelic
c22ed92d7d Update Home.md 2022-07-26 00:00:22 +02:00
Robert Jelic
168ffcf73c Update main.lua 2022-07-25 23:50:20 +02:00
Robert Jelic
5586eb6fb8 Create basaltPreview2.gif 2022-07-25 22:07:24 +02:00
Robert Jelic
a10cc6eda2 added new preview 2022-07-25 21:39:23 +02:00
Robert Jelic
2638ed84b8 Create discordCC.lua 2022-07-25 21:35:54 +02:00
Robert Jelic
77046d9bce Update installer.md 2022-07-25 21:15:43 +02:00
Robert Jelic
f2e2e773f5 bugfix + changes
- added getMinScroll and getMaxScroll for frames
- fixed a small bug with dynamicvalues
- textfield got a :clear() function
- improved the focus system
- fixed a bug with dynamic values getting into a infinite loop
2022-07-25 21:09:37 +02:00
Robert Jelic
738ad2576e bugfix
- some offset bugfixes
- reworked dynamic values - % got removed for now, now you are able to use parent.w*0.8 instead of 80% - but you are also able to use objectid.x/y/w/h
2022-07-23 21:57:34 +02:00
Robert Jelic
ea36b124be Merge branch 'master' of https://github.com/Pyroxenium/Basalt 2022-07-18 16:46:01 +02:00
Robert Jelic
9d10e95fae docs 2022-07-18 16:45:59 +02:00
Robert Jelic
dbfa91dc28 Update Basalt.md 2022-07-18 14:16:29 +02:00
Robert Jelic
6ab840cb1c Update Basalt.md 2022-07-18 14:11:37 +02:00
Robert Jelic
8157c025ea docs again 2022-07-18 13:58:43 +02:00
Robert Jelic
af34fa1a18 docs 2022-07-17 23:17:28 +02:00
Robert Jelic
dfc53658f1 Merge branch 'master' of https://github.com/Pyroxenium/Basalt 2022-07-17 22:39:13 +02:00
Robert Jelic
01412b4c55 docs 2022-07-17 22:37:32 +02:00
Robert Jelic
3107a7adb8 Update Frame.md 2022-07-17 20:24:09 +02:00
Robert Jelic
3819c14c08 Update README.md 2022-07-17 19:33:13 +02:00
Robert Jelic
8242f7868d Delete geometric.lua 2022-07-17 19:25:17 +02:00
Robert Jelic
f6cdd02270 Delete Lerp.lua 2022-07-17 19:24:58 +02:00
Robert Jelic
4d66e2778f Merge branch 'master' of https://github.com/Pyroxenium/Basalt 2022-07-17 19:20:06 +02:00
Robert Jelic
b940ef7154 added new features
-remade animation
-added xml support
-finished dynamic values
-added new object: graphic
-added themes for frames
-textfield got some basic improvements to create coding editors
2022-07-17 19:20:02 +02:00
Robert Jelic
3e89e73c64 Update Basalt.md 2022-07-12 22:33:53 +02:00
Robert Jelic
fca756888c Update Basalt.md 2022-07-12 22:30:29 +02:00
Robert Jelic
3b33bb7009 small path fix 2022-07-10 19:18:58 +02:00
Robert Jelic
e98c552fa1 Update Basalt.md 2022-07-09 06:35:30 +02:00
Robert Jelic
21b261332d Update Basalt.md 2022-07-08 22:33:37 +02:00
Robert Jelic
f16a32da1a Update Basalt.md 2022-07-08 22:32:22 +02:00
Robert Jelic
842352b473 Update Basalt.md 2022-07-08 22:31:50 +02:00
Robert Jelic
5505e4f3e8 Update main.lua 2022-07-08 21:23:40 +02:00
Robert Jelic
22274b402e Merge branch 'master' of https://github.com/Pyroxenium/Basalt 2022-07-08 21:06:25 +02:00
Robert Jelic
c6d7929741 small bugfix 2022-07-08 21:06:12 +02:00
Robert Jelic
5bd827618d bugfix
fixed bug where bpm was always creating a single file version
2022-07-08 19:53:15 +02:00
Robert Jelic
b78bf92cca Merge branch 'master' of https://github.com/Pyroxenium/Basalt 2022-07-08 19:46:33 +02:00
Robert Jelic
cbdf439791 fixed monitors, added setIndex4scrollbars, added dynamic values 2022-07-08 19:46:28 +02:00
Robert Jelic
022bef3b03 Update README.md 2022-07-08 19:43:53 +02:00
Robert Jelic
5f9060dae3 Update basaltPreview.lua 2022-07-06 20:52:16 +02:00
Robert Jelic
b9fd59d961 Update progressBarEnergyExample.lua 2022-07-06 20:51:58 +02:00
Robert Jelic
716c946b96 Update installer.md 2022-07-06 20:50:55 +02:00
Robert Jelic
02b4eb9f75 Update otherEvents.md 2022-07-06 20:36:36 +02:00
Robert Jelic
8945220ac3 Update keyEvents.md 2022-07-06 20:35:51 +02:00
Robert Jelic
7c49917087 Update mouseEvents.md 2022-07-06 20:35:22 +02:00
Robert Jelic
6b2f1ea946 Update Basalt.md 2022-07-06 20:30:16 +02:00
Robert Jelic
4bbdb3ba31 Update basaltPreview.lua 2022-07-06 20:27:22 +02:00
Robert Jelic
79bea8c094 Update progressBarEnergyExample.lua 2022-07-06 20:26:53 +02:00
Robert Jelic
8665eed03e changed how project will be installed from now on 2022-07-06 20:10:40 +02:00
Robert Jelic
9f5b917f87 Delete basaltInstaller.lua 2022-07-06 20:09:14 +02:00
Robert Jelic
975080bc63 Update Quick-Start.md 2022-07-06 20:08:47 +02:00
Robert Jelic
0f77621548 Update Animation.lua 2022-07-06 19:11:41 +02:00
Robert Jelic
36b2f08ad6 finished package manager 2022-07-05 23:02:38 +02:00
Robert Jelic
c16a8afb01 Update basaltPackager.lua 2022-07-05 22:26:50 +02:00
Robert Jelic
436d85dc52 Delete projectFiles.txt 2022-07-04 20:59:33 +02:00
Robert Jelic
8ad1a690ee Update projectFiles.txt 2022-07-03 23:30:24 +02:00
Robert Jelic
f67dda574d Merge branch 'master' of https://github.com/Pyroxenium/Basalt 2022-07-03 21:48:54 +02:00
Robert Jelic
5efda94244 added basaltpackagemanager(not finished), packager and installer 2022-07-03 21:48:37 +02:00
Robert Jelic
e90d907c1e Delete BasaltPackager.lua 2022-07-03 21:47:45 +02:00
Robert Jelic
28462f0f46 Update init.lua 2022-07-03 21:21:22 +02:00
Robert Jelic
1ad5d85a40 Update init.lua 2022-07-03 21:20:57 +02:00
Robert Jelic
02ed64555f Update README.md 2022-07-03 21:19:58 +02:00
Robert Jelic
c00d466b10 changed the projects filesystem to use require() instead of loadfile()
currently preparing for a better package manager/installer
2022-07-03 21:19:01 +02:00
Robert Jelic
1f18db9965 Update Thread.md 2022-07-02 22:49:26 +02:00
Robert Jelic
ae9a6ac605 Update Textfield.md 2022-07-02 22:39:12 +02:00
Robert Jelic
5a4e1f3b61 Update Program.md 2022-07-02 22:07:02 +02:00
Robert Jelic
95a4164755 Update Program.md 2022-07-02 21:32:20 +02:00
Robert Jelic
7e0a61a3e9 Update Basalt.md 2022-06-27 23:18:29 +02:00
Robert Jelic
7082258a9e Update Label.md 2022-06-26 19:49:04 +02:00
Robert Jelic
974cad1466 Update Input.md 2022-06-26 19:17:58 +02:00
Robert Jelic
add4feab3a Update Image.md 2022-06-26 18:59:02 +02:00
Robert Jelic
06c6e86308 Update Menubar.md 2022-06-26 18:23:30 +02:00
Robert Jelic
a34b7270ec Update Dropdown.md 2022-06-26 18:23:04 +02:00
Robert Jelic
3d71041aa2 Update Checkbox.md 2022-06-26 17:52:08 +02:00
Robert Jelic
d324912eb0 Update Button.md 2022-06-26 17:43:21 +02:00
Robert Jelic
6c123f4cc5 Update mouseEvents.md 2022-06-26 09:25:53 +02:00
Robert Jelic
797a48ea95 Update Basalt.md 2022-06-25 15:57:14 +02:00
Robert Jelic
ccdebe30ef Update _navbar.md 2022-06-25 15:46:11 +02:00
Robert Jelic
91b16fbd80 Update _navbar.md 2022-06-25 15:33:26 +02:00
Robert Jelic
71e8870c7c Update Frame.md 2022-06-25 15:32:10 +02:00
Robert Jelic
1198a5b4e0 Update Object.md 2022-06-25 15:25:08 +02:00
Robert Jelic
c280f8b9d6 Create progressBarEnergyExample.lua 2022-06-24 22:11:27 +02:00
Robert Jelic
8326d02a33 very small bugfix 2022-06-24 21:59:01 +02:00
Robert Jelic
3799cf9013 Update _sidebar.md 2022-06-24 21:23:15 +02:00
Robert Jelic
ccfc2eecd0 Create Progressbar.md 2022-06-24 21:22:42 +02:00
Robert Jelic
a763990b0c Update Label.md 2022-06-24 20:49:14 +02:00
Robert Jelic
2edff41380 Update Menubar.md 2022-06-24 20:43:50 +02:00
Robert Jelic
1c668ef34b Update Menubar.md 2022-06-24 20:43:11 +02:00
Robert Jelic
226471821f Update otherEvents.md 2022-06-24 20:05:47 +02:00
Robert Jelic
2919803846 Update otherEvents.md 2022-06-24 20:05:13 +02:00
Robert Jelic
1b1b4ae22c Rename KeyEvents.md to keyEvents.md 2022-06-24 19:59:18 +02:00
Robert Jelic
813bf7d2cf Update Object.md 2022-06-24 19:55:41 +02:00
Robert Jelic
39b3d1f732 Update Object.md 2022-06-24 19:54:34 +02:00
Robert Jelic
5253d03c60 Update otherEvents.md 2022-06-24 19:43:30 +02:00
Robert Jelic
02a11d656d Update Object.md 2022-06-24 19:40:02 +02:00
Robert Jelic
72e633ec21 Update basaltPreview.lua 2022-06-24 19:36:22 +02:00
Robert Jelic
df4ad896b2 Some changes
-reworked monitor support
-fixed small draw bugs
-changed focus behaviour
-added some events
-fixed offset bug
-added border
-added shadow
-reworkd anchor system
-added possibility to remove background by setting the value to false
2022-06-24 19:33:37 +02:00
Robert Jelic
94cb23fd58 Rename Key to KeyEvents.md 2022-06-20 23:13:33 +02:00
Robert Jelic
939be0764e Create Key 2022-06-20 23:13:07 +02:00
Robert Jelic
9858bce3f6 Update mouseEvents.md 2022-06-20 23:06:44 +02:00
Robert Jelic
3e937033b9 Update mouseEvents.md 2022-06-20 23:05:33 +02:00
Robert Jelic
989fefe330 Update README.md 2022-06-20 23:00:02 +02:00
Robert Jelic
6b3a7cd73f small monitor/offsetbugfix update
-reworked monitor support (you are able to write on monitors through computer)
-fixed offset bugs
-couple of smaller bugfixes
2022-06-20 21:07:09 +02:00
Samuel Pizette
a899b1d247 updated Object.md to new format 2022-06-09 12:37:33 -04:00
Samuel Pizette
b6ee09636b updated param and return headers 2022-06-09 11:43:59 -04:00
Samuel Pizette
4b8f3c2d5c fixed spacing issue 2022-06-09 11:39:34 -04:00
Samuel Pizette
5a6811930b re-re-added design.md 2022-06-09 11:32:54 -04:00
Samuel Pizette
7759b720b6 added syntax highlighting 2022-06-09 11:19:13 -04:00
Samuel Pizette
64e7d777c1 bad syntax fix #2 2022-06-09 11:09:04 -04:00
Samuel Pizette
332be95285 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	docs/home/gettingStarted.md
#	docs/home/installer.md
#	docs/tips/logic.md
2022-06-09 11:08:46 -04:00
Samuel Pizette
cb98307e44 bad syntax fix 2022-06-09 11:08:26 -04:00
Robert Jelic
eb2dd86ac8 Update installer.md 2022-06-08 19:33:40 +02:00
Robert Jelic
5b9a3bb565 Update index.html 2022-06-08 19:30:58 +02:00
Robert Jelic
b6e2aefb68 fixed crash -> if you dont use :setSize() on sub frames 2022-06-06 21:23:50 +02:00
Robert Jelic
4f3ffc328d added switch 2022-06-06 20:49:30 +02:00
Robert Jelic
c5b9a5f568 Merge branch 'master' of https://github.com/Pyroxenium/Basalt 2022-06-06 17:07:10 +02:00
Robert Jelic
b0b104ee82 couple of bugfixes
-fixed screen flickering
-fixed menubar (now works as intended)
-reworked sliders (behaviour more like scrollbars)
-visual fix to dropdowns
2022-06-06 17:06:56 +02:00
Robert Jelic
e833d4bcf1 Update events.md 2022-06-05 14:44:13 +02:00
Robert Jelic
7b2556bd8c Update mouseEvents.md 2022-06-05 14:42:18 +02:00
Robert Jelic
f2972417a7 Update _sidebar.md 2022-06-05 14:41:36 +02:00
Robert Jelic
2a577fff9f Rename events to events.md 2022-06-05 14:39:09 +02:00
Robert Jelic
cfcdbce8d5 Create events 2022-06-05 14:38:55 +02:00
Robert Jelic
980b016b2c Merge pull request #19 from Erb3/erb3-patch3
[WIKI] rephrasing, link updates, sidebar update
2022-06-04 19:57:52 +02:00
Erlend
1c7f465cd8 Using tweaked.cc instead of deprecated computercraft.info link 2022-06-04 19:29:41 +02:00
Erlend
038bab11ba Remove sidebar listing for something that dosent exist 2022-06-04 19:20:15 +02:00
Erlend
3cfc2fca9c Remove unused file 2022-06-04 19:19:41 +02:00
Erlend
2e11c99ef2 Update Home.md with new links, ++
I updated Home.md with new links to the new repo. I also rephrased some things.
2022-06-04 19:17:32 +02:00
Robert Jelic
98b84a9509 Update installer.md 2022-06-03 21:51:05 +02:00
Robert Jelic
50b0bf6b95 update installer image 2022-06-03 21:49:31 +02:00
Robert Jelic
42450d42d3 Update installer.md 2022-06-03 21:47:51 +02:00
Robert Jelic
e29e5cc77d Merge pull request #18 from Erb3/erb3-patch2
Add favicon to wiki
2022-06-03 20:39:17 +02:00
Erlend
a50ed1f486 Add favicon links in index.html 2022-06-03 20:19:45 +02:00
Erlend
6d66757ae4 Add favicon files 2022-06-03 20:18:51 +02:00
Robert Jelic
e5839c3704 Update mouseEvents.md 2022-06-03 19:20:41 +02:00
Robert Jelic
275356fb9d Update mouseEvents.md 2022-06-02 23:26:43 +02:00
Robert Jelic
200dc6ecd7 Update mouseEvents.md 2022-06-02 23:26:12 +02:00
Samkist
8feec5f9f1 fixed-weird-format-indent 2022-06-02 17:24:37 -04:00
Robert Jelic
8bbe7a67df add mouseEvents docs file 2022-06-02 22:55:02 +02:00
Samkist
ee97cff930 re-added design.md 2022-05-31 17:00:19 -04:00
Robert Jelic
11cdd74d39 changed slider issue, fixed monitor bug, added basalt.isKeyDown(keys)
Slider: added setIndex() and changed setValue behaviour
Monitor: Changed monitor draw priority so input's cursor still shows (have to figure out why its even hiding)
added new function where you can check if a user is holding a key currently down
2022-05-31 20:55:14 +02:00
Robert Jelic
5aa57c0930 Update installer.md 2022-05-31 19:55:49 +02:00
Robert Jelic
ecdb35d313 Update _sidebar.md 2022-05-31 16:50:20 +02:00
Robert Jelic
fe74e7df9f Update _sidebar.md 2022-05-31 16:48:26 +02:00
Samuel Pizette
42f1870475 description update 2022-05-30 23:47:13 -04:00
Samuel Pizette
5381a0bf3e Merge remote-tracking branch 'origin/master' 2022-05-30 23:44:54 -04:00
Samuel Pizette
3af8854743 hopeful formatting update 2022-05-30 23:44:33 -04:00
Robert Jelic
4f5693a15b Update Frame.md 2022-05-30 23:17:31 +02:00
Robert Jelic
1675b71c40 -monitor support & getAll() for list-objects
added multiple monitor support
added getAll() for lists, dropdowns, radios and menubars
2022-05-30 22:45:37 +02:00
Robert Jelic
628e02d600 changed wiki link 2022-05-30 22:26:14 +02:00
Samuel Pizette
f5ee3c7880 updated theme of Basalt.md 2022-05-30 16:23:45 -04:00
Robert Jelic
68dba9f253 Update index.html 2022-05-30 19:29:26 +02:00
Robert Jelic
4cfeb1ff02 Update index.html 2022-05-30 19:28:14 +02:00
Robert Jelic
13c5235c3e Update index.html 2022-05-30 19:21:16 +02:00
Robert Jelic
7e52b3cfc5 Update index.html 2022-05-30 19:18:57 +02:00
Robert Jelic
9cdf9b0482 Update index.html 2022-05-30 19:12:37 +02:00
Robert Jelic
cd95f85f28 Update index.html 2022-05-30 19:11:59 +02:00
Robert Jelic
964e987e28 Update Animation.md 2022-05-30 19:10:20 +02:00
Samkist
76af0d3d38 reformatted Animation.md 2022-05-30 12:30:41 -04:00
Samkist
0231ee70b8 cleaned up more css 2022-05-30 12:16:04 -04:00
Samkist
622db56d5b cleaned up css 2022-05-30 12:14:18 -04:00
Samkist
ea88553174 fixed more object links 2022-05-30 11:53:41 -04:00
Samkist
a3e7bf7bde fixed object link 2022-05-30 11:48:36 -04:00
Samkist
e42631d790 fixed headers 2022-05-30 11:44:47 -04:00
Samkist
be28c31687 removed nav tip 2022-05-30 11:40:44 -04:00
Samuel Pizette
864becf7c8 Create CNAME 2022-05-30 11:30:31 -04:00
Samkist
67ecd286d5 added loading text to docs 2022-05-30 03:12:01 -04:00
Samuel Pizette
1e059e80df Update README.md 2022-05-30 03:04:23 -04:00
Samuel Pizette
dad7567a8d Merge pull request #17 from Pyroxenium/add-license-1
Create LICENSE
2022-05-30 03:01:21 -04:00
Samuel Pizette
d0b96d18e6 Create LICENSE 2022-05-30 03:01:14 -04:00
Samkist
d719266e36 update sidebar description 2022-05-30 02:37:08 -04:00
Samkist
90ea73ce4e update documentation meta 2022-05-30 02:36:33 -04:00
Samkist
5ad0e2c2b8 navbar-fix 2022-05-30 02:34:31 -04:00
Samkist
c8c799eb37 updated docs 2022-05-30 02:31:00 -04:00
Samkist
eeb048e898 updated docs 2022-05-30 02:29:00 -04:00
Samuel Pizette
8246977ae3 Merge pull request #16 from Pyroxenium/docsify-feature
started docsify with custom theme
2022-05-30 02:24:11 -04:00
Samkist
e5bc39a6f7 updated docs 2022-05-30 02:23:40 -04:00
Samuel Pizette
2a8817df96 Merge branch 'master' into docsify-feature 2022-05-30 02:14:56 -04:00
Samuel Pizette
65cbe359ba Merge pull request #15 from Erb3/erb3-patch1
Migrate wiki to docsify
2022-05-30 02:11:53 -04:00
Samkist
d638920e3e created wiki 2022-05-30 02:06:50 -04:00
Erlend
d53f172b94 Fix more URLS 2022-05-30 07:58:13 +02:00
Erlend
aade882eb8 Fix Urls 2022-05-30 07:55:03 +02:00
Erlend
91933afdc2 Add all objects 2022-05-30 07:49:44 +02:00
Erlend
a9e8251e59 Fix buttons.md 2022-05-30 07:33:35 +02:00
Erlend
9654441135 finish tips 2022-05-30 07:31:00 +02:00
Erlend
196117c35a Merge branch 'Pyroxenium:master' into erb3-patch1 2022-05-30 07:24:42 +02:00
Samkist
3c821a48d4 updated preview link 2022-05-29 21:53:22 -04:00
Erlend
9b4045153f Merge branch 'Pyroxenium:master' into erb3-patch1 2022-05-29 17:19:13 +02:00
Robert Jelic
b6c969a0cb fixed autosize on bigfonts 2022-05-29 16:50:30 +02:00
Robert Jelic
8f4bf74f27 Merge branch 'master' of https://github.com/Pyroxenium/Basalt 2022-05-29 16:22:48 +02:00
Robert Jelic
7871d7205c added bigfonts api for labels
Added bigfonts to labels
just use :setFontSize(number) (1,2, 3 or 4)
2022-05-29 16:22:28 +02:00
Erlend
6b51ba94f8 add logic 2022-05-29 13:55:25 +02:00
Erlend
465d77f1b5 typo, left not right 2022-05-29 13:43:04 +02:00
Erlend
f7e55c5a57 forgot to remove old theme 2022-05-29 13:41:46 +02:00
Erlend
39020d99d3 dark theme 2022-05-29 13:40:07 +02:00
Erlend
22f649be39 Added headings, and disabled jekyll which makes sidebar work... 2022-05-29 13:31:22 +02:00
Erlend
d1e0220d54 Home Category 2022-05-29 13:28:06 +02:00
Erlend
455127114e Name it correctly 2022-05-29 13:12:52 +02:00
Erlend
8997f27f4a tset1 2022-05-29 13:08:06 +02:00
Robert Jelic
31d03b5f21 Update basaltPreview.lua 2022-05-27 22:14:19 +02:00
Robert Jelic
b01a1e3a71 Update basaltPreview.lua
added progressbar,
fixed scrollbar
2022-05-27 22:14:00 +02:00
Robert Jelic
1f97eeacd1 fixed red cursor bug 2022-05-27 21:57:32 +02:00
Robert Jelic
c17fd8ad5e added textalign to labels 2022-05-27 21:46:42 +02:00
Robert Jelic
892d3496bd added align to labels 2022-05-27 21:42:31 +02:00
Robert Jelic
0348e9317d changed source project 2022-05-27 20:30:00 +02:00
Robert Jelic
6df029c0bc Update readme.md 2022-05-27 20:27:07 +02:00
Robert Jelic
4afb3f9e94 Update readme.md 2022-05-27 20:25:58 +02:00
Robert Jelic
216064ae35 Create readme.md 2022-05-27 20:07:57 +02:00
Robert Jelic
9f987a2f16 Update README.md 2022-05-20 19:29:11 +02:00
Robert Jelic
07dc903734 Update README.md 2022-05-20 19:28:58 +02:00
Robert Jelic
86be8fb420 Update README.md 2022-05-20 19:26:42 +02:00
Robert Jelic
0bd1b98836 Merge branch 'master' of https://github.com/NoryiE/Basalt 2022-05-20 19:24:40 +02:00
Robert Jelic
a0c55bdd6e added a example for objects 2022-05-20 19:24:36 +02:00
Robert Jelic
473e881c70 Update basaltPreview.lua 2022-05-20 17:19:15 +02:00
Robert Jelic
be229460b8 Update basaltPreview.lua 2022-05-20 17:18:24 +02:00
Samuel Pizette
f4f5ba88cb Update README.md 2022-05-20 00:31:36 -04:00
Samuel Pizette
1baaaf26c8 Update README.md 2022-05-19 16:57:41 -04:00
Samuel Pizette
3a61490cdb Update README.md 2022-05-19 16:57:14 -04:00
Robert Jelic
4f20ede76a some smaller changes 2022-05-19 22:50:34 +02:00
Robert Jelic
ed1f32bbf9 removed minifier 2022-05-19 20:30:56 +02:00
Robert Jelic
f5eb16eb94 Merge pull request #6 from NoryiE/samkist-deprecate-isMoveable-and-setMoveable
deprecated isMoveable and setMoveable
2022-05-19 20:01:17 +02:00
Robert Jelic
9c7b4847c3 Merge pull request #5 from NoryiE/samkist-fix-threaderror-string
made some thread errors look nice
2022-05-19 20:00:30 +02:00
Samkist
8e3a8691fb deprecated isMoveable and setMoveable 2022-05-19 13:18:21 -04:00
Samkist
2c9be41720 made some thread errors look nice 2022-05-19 13:12:01 -04:00
Robert Jelic
fc45d284d2 changed source folder 2022-05-19 18:07:02 +02:00
Robert Jelic
48fc275afd Delete basaltInstaller.lua 2022-05-19 17:24:32 +02:00
Robert Jelic
7c3a0159b2 changed source, renamed basalt-minified back to basalt 2022-05-19 17:22:55 +02:00
Samkist
038f015771 switched to minified in preview 2022-05-19 00:15:07 -04:00
Samkist
b61ccfcced fixed issue downloading file 2022-05-18 22:54:47 -04:00
Samkist
4a8ba5ea2c Revert "updated foreground and background color variables to fgColor and bgColor"
This reverts commit 240434422c.
2022-05-18 22:37:20 -04:00
Samkist
240434422c updated foreground and background color variables to fgColor and bgColor 2022-05-18 22:16:39 -04:00
Samkist
27246b6b10 minified 2022-05-18 21:50:21 -04:00
Samkist
62a8078169 more typos oops 2022-05-18 21:49:44 -04:00
Samkist
c6202969a8 updated minified version 2022-05-18 21:47:59 -04:00
Samkist
69bdab164a fix a myriad of my own typos 2022-05-18 21:47:29 -04:00
Samkist
2646fd6c5d made variable names easier to read
renamed basalt-minfied.lua to basalt-minified.lua
2022-05-18 21:15:47 -04:00
Samkist
8ca771606e added basalt-minified.lua 2022-05-18 19:59:33 -04:00
Samkist
f72baa6fb3 reformatted code, removed minified file 2022-05-18 19:58:49 -04:00
Samuel Pizette
ca7cab51dc Update README.md 2022-05-18 15:16:13 -04:00
Robert Jelic
dfe38f3074 Merge pull request #3 from NoryiE/samkist-readme-patch-1
Update README.md
2022-05-18 21:14:40 +02:00
Samuel Pizette
b59370f598 Update README.md
Updated some grammar to help English speakers better understand the readme
2022-05-18 15:10:59 -04:00
Robert Jelic
5b2289f378 added progressbar 2022-05-18 20:18:57 +02:00
Robert Jelic
aab510df6c changed keys, bug fixes 2022-05-11 06:32:59 +02:00
Robert Jelic
3b1fc2bb30 Merge branch 'master' of https://github.com/NoryiE/Basalt 2022-05-11 06:31:11 +02:00
Robert Jelic
6a0224b911 changed keys, small bugfix 2022-05-11 06:31:08 +02:00
Robert Jelic
a1c0833f71 Update README.md 2022-05-10 22:11:32 +02:00
Robert Jelic
04cf5e1477 Update README.md 2022-05-10 22:11:08 +02:00
Robert Jelic
445b37cf52 created minified file 2022-05-08 20:19:33 +02:00
Robert Jelic
d0fdbd0796 Update README.md 2022-05-08 08:52:20 +02:00
Robert Jelic
a0534588f6 added 2 objects, added onBackgroundKey Event
added image object
added pane object

added new event: onBackgroundKey: listens to incomming key events without beeing the focused object
2022-05-08 08:50:51 +02:00
Robert Jelic
d74e885d4c very small bugfix @anchor/abs. position 2022-05-07 06:43:33 +02:00
Robert Jelic
5021c00f6e Update basalt.lua 2022-05-04 20:28:40 +02:00
Robert Jelic
52ed5d0546 Update README.md 2022-05-04 20:00:46 +02:00
Robert Jelic
cf4acbd24a Update README.md 2022-05-03 22:24:58 +02:00
Robert Jelic
3cc14a2023 Create basaltPreview.lua 2022-05-03 22:23:43 +02:00
Robert Jelic
0464280d64 Update basalt.lua 2022-05-03 20:36:51 +02:00
Robert Jelic
a6c28bc293 Update README.md 2022-05-02 20:39:28 +02:00
Robert Jelic
d57b74102e Update README.md 2022-05-02 20:39:12 +02:00
Robert Jelic
2b47231cb5 Update README.md 2022-05-01 22:47:48 +02:00
Robert Jelic
ec689f6838 Update README.md 2022-05-01 22:00:22 +02:00
Robert Jelic
6c8cfd6e48 Update README.md 2022-04-26 23:05:43 +02:00
Robert Jelic
a9041fab28 Update README.md 2022-04-26 23:05:26 +02:00
Robert Jelic
db34eaa2c4 Update README.md 2022-04-24 16:14:36 +02:00
Robert Jelic
fef083c732 Update basalt.lua
just bugfixes
2022-04-22 22:16:31 +02:00
Robert Jelic
4ec36170f6 Update basalt.lua 2022-04-19 20:01:54 +02:00
Robert Jelic
5f445074e6 updated program 2022-04-18 20:59:08 +02:00
Robert Jelic
291fe678bd Update README.md 2022-04-18 19:14:29 +02:00
Robert Jelic
97d1d22048 Merge branch 'master' of https://github.com/NoryiE/Basalt 2022-04-18 19:13:00 +02:00
Robert Jelic
171aa64813 recreated everything (4better drawsys) 2022-04-18 19:12:56 +02:00
Robert Jelic
91fd1a2595 Update README.md 2022-04-14 22:42:23 +02:00
Robert Jelic
a394a8ca5f Update README.md 2022-04-14 22:42:09 +02:00
Robert Jelic
9837d0fdf3 Update README.md 2022-04-04 23:25:03 +02:00
Robert Jelic
d64030a112 Update README.md 2022-04-03 21:06:35 +02:00
Robert Jelic
22405d176f Create basalt.lua 2022-04-03 21:05:55 +02:00
Robert Jelic
37f815dfca Update NyoUI.lua 2022-04-03 15:27:47 +02:00
Robert Jelic
8629ce7b30 Update README.md 2022-04-03 15:22:25 +02:00
Robert Jelic
dc2c616724 Update README.md 2022-04-03 15:22:02 +02:00
Robert Jelic
a0cf8e84d6 Update README.md 2022-04-02 23:24:54 +02:00
Robert Jelic
a30455b2a5 Merge branch 'master' of https://github.com/NoryiE/NyoUI 2022-04-02 18:03:22 +02:00
Robert Jelic
6e99e1b8a7 Update NyoUI.lua 2022-04-02 18:03:15 +02:00
Robert Jelic
d0712f1d11 Update README.md 2022-04-02 15:29:55 +02:00
Robert Jelic
146fa814e5 Update NyoUI.lua 2022-04-02 15:28:43 +02:00
Robert Jelic
7fa5bce620 Update README.md 2022-04-02 14:49:17 +02:00
Robert Jelic
84659cea1e Update README.md 2022-04-02 14:46:50 +02:00
Robert Jelic
34e87d29d2 Update README.md 2022-04-02 14:46:10 +02:00
Robert Jelic
1519d38aaf Update README.md 2022-04-02 14:43:45 +02:00
Robert Jelic
5cdb6bf5bd Update README.md 2022-04-02 14:43:24 +02:00
Robert Jelic
220b5edd8c Merge branch 'master' of https://github.com/NoryiE/NyoUI 2022-03-31 20:00:26 +02:00
Robert Jelic
04dc33c0ca Update NyoUI.lua
added new scrollbar object
added scrollbar to list
made some cool changes
some function renames
2022-03-31 20:00:23 +02:00
Robert Jelic
c2c88b72e0 Update README.md 2022-03-28 23:44:34 +02:00
Robert Jelic
bc4deb1779 Update README.md 2022-03-28 23:43:19 +02:00
Robert Jelic
d99e73f3f3 Update README.md 2022-03-28 23:41:04 +02:00
Robert Jelic
5028f5b6c3 Update README.md 2022-03-28 23:40:13 +02:00
Robert Jelic
be810fa0dc Update README.md 2022-03-28 23:38:56 +02:00
Robert Jelic
f9cdb40c7e Update README.md 2022-03-28 23:38:22 +02:00
Robert Jelic
138e56fa35 Update README.md 2022-03-28 23:38:00 +02:00
Robert Jelic
701567a130 Update README.md 2022-03-28 23:37:43 +02:00
Robert Jelic
814330eda0 Update README.md 2022-03-27 23:01:43 +02:00
131 changed files with 28797 additions and 1642 deletions

37
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,37 @@
---
name: Bug report
about: Bug reports for Basalt
title: 'bug: [TITLE]'
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.
**Checklist**
[ ] I am running the latest version.
Tick the box if you are running the latest version!

View File

@@ -0,0 +1,45 @@
name: Bug Report w/ BETA form
description: Report a bug for Basalt (Using BETA form)!
title: "bug: [TITLE]"
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you see!
value: "A bug happened!"
validations:
required: true
- type: dropdown
id: ccversion
attributes:
label: Computercraft client
description: What ComputerCraft client are you using?
options:
- Ingame (Default)
- CraftOSPC
- CCemux
- CopyCat
- other
validations:
required: true
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output, for example the error. This will be automatically formatted into code, so no need for backticks.
render: shell
- type: checkboxes
id: latest
attributes:
label: Latest Basalt Version
description: We only provide support for the latest version of Basalt!
options:
- label: I use the latest stable version
required: true

4
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,4 @@
contact_links:
- name: Community Support
url: https://discord.gg/yNNnmBVBpE
about: Please ask and answer questions here.

20
.github/ISSUE_TEMPLATE/docs.md vendored Normal file
View File

@@ -0,0 +1,20 @@
---
name: Documentation
about: Anything that you think is wrong about the documentation.
title: 'docs: [TITLE]'
labels: documentation
assignees: ''
---
** Where? **
Please describe what you want changed. Screenshot / Quotes
** Possible solution **
Please describe a possible solution.
** Others **
Anything else you want to say?
** Checklist **
[ ] I am looking at the latest version of the docs.

20
.github/ISSUE_TEMPLATE/feature.md vendored Normal file
View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for Basalt
title: 'feature: [TITLE]'
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

880
Basalt/Frame.lua Normal file
View File

@@ -0,0 +1,880 @@
local Object = require("Object")
local _OBJECTS = require("loadObjects")
local BasaltDraw = require("basaltDraw")
local utils = require("utils")
local layout = require("layout")
local uuid = utils.uuid
local rpairs = utils.rpairs
local xmlValue = utils.getValueFromXML
local sub,min,max = string.sub,math.min,math.max
return function(name, parent, pTerm, basalt)
-- Frame
local base = Object(name)
local objectType = "Frame"
local objects = {}
local objZIndex = {}
local object = {}
local variables = {}
local theme = {}
local dynamicValues = {}
local dynValueId = 0
local termObject = pTerm or term.current()
local monSide = ""
local isMonitor = false
local monitorAttached = false
local dragXOffset = 0
local dragYOffset = 0
local isScrollable = false
local minScroll = 0
local maxScroll = 10
local mirrorActive = false
local mirrorAttached = false
local mirrorSide = ""
local importantScroll = false
local focusedOBjectCache
local focusedObject
base:setZIndex(10)
local basaltDraw = BasaltDraw(termObject)
local cursorBlink = false
local xCursor = 1
local yCursor = 1
local cursorColor = colors.white
local xOffset, yOffset = 0, 0
local lastXMLReferences = {}
local function xmlDefaultValues(data, obj)
if(obj~=nil)then
obj:setValuesByXMLData(data)
end
end
local function addXMLObjectType(tab, f, self)
if(tab~=nil)then
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local obj = f(self, v["@id"] or uuid())
table.insert(lastXMLReferences, obj)
xmlDefaultValues(v, obj)
end
end
end
if (parent ~= nil) then
base.parent = parent
base.width, base.height = parent:getSize()
base.bgColor = parent:getTheme("FrameBG")
base.fgColor = parent:getTheme("FrameText")
else
base.width, base.height = termObject.getSize()
base.bgColor = basalt.getTheme("BasaltBG")
base.fgColor = basalt.getTheme("BasaltText")
end
local function getObject(name)
for _, value in pairs(objects) do
for _, b in pairs(value) do
if (b:getName() == name) then
return b
end
end
end
end
local function getDeepObject(name)
local o = getObject(name)
if(o~=nil)then return o end
for _, value in pairs(objects) do
for _, b in pairs(value) do
if (b:getType() == "Frame") then
local oF = b:getDeepObject(name)
if(oF~=nil)then return oF end
end
end
end
end
local function addObject(obj)
local zIndex = obj:getZIndex()
if (getObject(obj.name) ~= nil) then
return nil
end
if (objects[zIndex] == nil) then
for x = 1, #objZIndex + 1 do
if (objZIndex[x] ~= nil) then
if (zIndex == objZIndex[x]) then
break
end
if (zIndex > objZIndex[x]) then
table.insert(objZIndex, x, zIndex)
break
end
else
table.insert(objZIndex, zIndex)
end
end
if (#objZIndex <= 0) then
table.insert(objZIndex, zIndex)
end
objects[zIndex] = {}
end
obj.parent = object
if(obj.init~=nil)then
obj:init()
end
table.insert(objects[zIndex], obj)
return obj
end
local function removeObject(obj)
for a, b in pairs(objects) do
for key, value in pairs(b) do
if (value == obj) then
table.remove(objects[a], key)
return true;
end
end
end
return false
end
local function stringToNumber(str)
local ok, err = pcall(load("return " .. str))
if not(ok)then error(str.." is not a valid dynamic code") end
return load("return " .. str)()
end
local function newDynamicValue(_, obj, str)
for k,v in pairs(dynamicValues)do
if(v[2]==str)and(v[4]==obj)then
return v
end
end
dynValueId = dynValueId + 1
dynamicValues[dynValueId] = {0, str, {}, obj, dynValueId}
return dynamicValues[dynValueId]
end
local function dynValueGetObjects(obj, str)
local names = {}
local t = {}
for v in str:gmatch("%a+%.x") do
local name = v:gsub("%.x", "")
if(name~="self")and(name~="parent")then
table.insert(names, name) end
end
for v in str:gmatch("%w+%.y") do
local name = v:gsub("%.y", "")
if(name~="self")and(name~="parent")then table.insert(names, name) end
end
for v in str:gmatch("%a+%.w") do
local name = v:gsub("%.w", "")
if(name~="self")and(name~="parent")then
table.insert(names, name)
end
end
for v in str:gmatch("%a+%.h") do
local name = v:gsub("%.h", "")
if(name~="self")and(name~="parent")then
table.insert(names, name) end
end
for k,v in pairs(names)do
t[v] = getObject(v)
if(t[v]==nil)then
error("Dynamic Values - unable to find object "..v)
end
end
t["self"] = obj
t["parent"] = obj:getParent()
return t
end
local function dynValueObjectToNumber(str, objList)
local newStr = str
for v in str:gmatch("%w+%.x") do
newStr = newStr:gsub(v, objList[v:gsub("%.x", "")]:getX())
end
for v in str:gmatch("%w+%.y") do
newStr = newStr:gsub(v, objList[v:gsub("%.y", "")]:getY())
end
for v in str:gmatch("%w+%.w") do
newStr = newStr:gsub(v, objList[v:gsub("%.w", "")]:getWidth())
end
for v in str:gmatch("%w+%.h") do
newStr = newStr:gsub(v, objList[v:gsub("%.h", "")]:getHeight())
end
return newStr
end
local function recalculateDynamicValues()
if(#dynamicValues>0)then
for n=1,dynValueId do
if(dynamicValues[n]~=nil)then
local numberStr
if(#dynamicValues[n][3]<=0)then dynamicValues[n][3] = dynValueGetObjects(dynamicValues[n][4], dynamicValues[n][2]) end
numberStr = dynValueObjectToNumber(dynamicValues[n][2], dynamicValues[n][3])
dynamicValues[n][1] = stringToNumber(numberStr)
end
end
end
end
local function getDynamicValue(id)
return dynamicValues[id][1]
end
object = {
barActive = false,
barBackground = colors.gray,
barTextcolor = colors.black,
barText = "New Frame",
barTextAlign = "left",
isMoveable = false,
newDynamicValue = newDynamicValue,
recalculateDynamicValues = recalculateDynamicValues,
getDynamicValue = getDynamicValue,
getType = function(self)
return objectType
end;
setFocusedObject = function(self, obj)
focusedOBjectCache = obj
return self
end;
getVariable = function(self, name)
return basalt.getVariable(name)
end,
setSize = function(self, w, h, rel)
base.setSize(self, w, h, rel)
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.eventHandler ~= nil) then
value:sendEvent("basalt_resize", value, self)
end
end
end
end
return self
end;
setTheme = function(self, _theme)
theme = _theme
return self
end,
getTheme = function(self, name)
return theme[name] or (self.parent~=nil and self.parent:getTheme(name) or basalt.getTheme(name))
end,
setPosition = function(self, x, y, rel)
base.setPosition(self, x, y, rel)
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.eventHandler ~= nil) then
value:sendEvent("basalt_reposition", value, self)
end
end
end
end
return self
end;
getBasaltInstance = function(self)
return basalt
end,
setOffset = function(self, xO, yO)
xOffset = xO ~= nil and math.floor(xO < 0 and math.abs(xO) or -xO) or xOffset
yOffset = yO ~= nil and math.floor(yO < 0 and math.abs(yO) or -yO) or yOffset
return self
end;
getOffsetInternal = function(self)
return xOffset, yOffset
end;
getOffset = function(self) -- internal
return xOffset < 0 and math.abs(xOffset) or -xOffset, yOffset < 0 and math.abs(yOffset) or -yOffset
end;
removeFocusedObject = function(self)
focusedOBjectCache = nil
return self
end;
getFocusedObject = function(self)
return focusedObject
end;
setCursor = function(self, _blink, _xCursor, _yCursor, color)
if(self.parent~=nil)then
local obx, oby = self:getAnchorPosition()
self.parent:setCursor(_blink or false, (_xCursor or 0)+obx-1, (_yCursor or 0)+oby-1, color or cursorColor)
else
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition(self:getX(), self:getY(), true))
cursorBlink = _blink or false
if (_xCursor ~= nil) then
xCursor = obx + _xCursor - 1
end
if (_yCursor ~= nil) then
yCursor = oby + _yCursor - 1
end
cursorColor = color or cursorColor
self:setVisualChanged()
end
return self
end;
setMoveable = function(self, moveable)
self.isMoveable = moveable or not self.isMoveable
self:setVisualChanged()
return self;
end;
setScrollable = function(self, scrollable)
isScrollable = scrollable and true or false
return self
end,
setImportantScroll = function(self, imp)
importantScroll = imp and true or false
return self
end,
setMaxScroll = function(self, max)
maxScroll = max or maxScroll
return self
end,
setMinScroll = function(self, min)
minScroll = min or minScroll
return self
end,
getMaxScroll = function(self)
return maxScroll
end,
getMinScroll = function(self)
return minScroll
end,
show = function(self)
base.show(self)
if(self.parent==nil)then
basalt.setActiveFrame(self)
if(isMonitor)then
basalt.setMonitorFrame(monSide, self)
else
basalt.setMainFrame(self)
end
end
return self;
end;
hide = function (self)
base.hide(self)
if(self.parent==nil)then
if(activeFrame == self)then activeFrame = nil end
if(isMonitor)then
if(basalt.getMonitorFrame(monSide) == self)then
basalt.setActiveFrame(nil)
end
else
if(basalt.getMainFrame() == self)then
basalt.setMainFrame(nil)
end
end
end
return self
end;
addLayout = function(self, file)
if(file~=nil)then
if(fs.exists(file))then
local f = fs.open(file, "r")
local data = layout:ParseXmlText(f.readAll())
f.close()
lastXMLReferences = {}
self:setValuesByXMLData(data)
end
end
return self
end,
getLastLayout = function(self)
return lastXMLReferences
end,
addLayoutFromString = function(self, str)
if(str~=nil)then
local data = layout:ParseXmlText(str)
self:setValuesByXMLData(data)
end
return self
end,
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("moveable", data)~=nil)then if(xmlValue("moveable", data))then self:setMoveable(true) end end
if(xmlValue("scrollable", data)~=nil)then if(xmlValue("scrollable", data))then self:setScrollable(true) end end
if(xmlValue("monitor", data)~=nil)then self:setMonitor(xmlValue("monitor", data)):show() end
if(xmlValue("mirror", data)~=nil)then self:setMirror(xmlValue("mirror", data)) end
if(xmlValue("bar", data)~=nil)then if(xmlValue("bar", data))then self:showBar(true) else self:showBar(false) end end
if(xmlValue("barText", data)~=nil)then self.barText = xmlValue("barText", data) end
if(xmlValue("barBG", data)~=nil)then self.barBackground = colors[xmlValue("barBG", data)] end
if(xmlValue("barFG", data)~=nil)then self.barTextcolor = colors[xmlValue("barFG", data)] end
if(xmlValue("barAlign", data)~=nil)then self.barTextAlign = xmlValue("barAlign", data) end
if(xmlValue("layout", data)~=nil)then self:addLayout(xmlValue("layout", data)) end
if(xmlValue("xOffset", data)~=nil)then self:setOffset(xmlValue("xOffset", data), yOffset) end
if(xmlValue("yOffset", data)~=nil)then self:setOffset(yOffset, xmlValue("yOffset", data)) end
if(xmlValue("maxScroll", data)~=nil)then self:setMaxScroll(xmlValue("maxScroll", data)) end
if(xmlValue("minScroll", data)~=nil)then self:setMaxScroll(xmlValue("minScroll", data)) end
if(xmlValue("importantScroll", data)~=nil)then self:setImportantScroll(xmlValue("importantScroll", data)) end
local objectList = data:children()
for k,v in pairs(objectList)do
if(v.___name~="animation")then
local name = v.___name:gsub("^%l", string.upper)
if(_OBJECTS[name]~=nil)then
addXMLObjectType(v, self["add"..name], self)
end
end
end
addXMLObjectType(data["frame"], self.addFrame, self)
addXMLObjectType(data["animation"], self.addAnimation, self)
return self
end,
showBar = function(self, showIt)
self.barActive = showIt or not self.barActive
self:setVisualChanged()
return self
end;
setBar = function(self, text, bgCol, fgCol)
self.barText = text or ""
self.barBackground = bgCol or self.barBackground
self.barTextcolor = fgCol or self.barTextcolor
self:setVisualChanged()
return self
end;
setBarTextAlign = function(self, align)
self.barTextAlign = align or "left"
self:setVisualChanged()
return self
end;
setMirror = function(self, side)
mirrorSide = side
if(mirror~=nil)then
basaltDraw.setMirror(mirror)
end
mirrorActive = true
return self
end,
removeMirror = function(self)
mirror = nil
mirrorActive = false
basaltDraw.setMirror(nil)
return self
end,
setMonitor = function(self, side)
if(side~=nil)and(side~=false)then
if(peripheral.getType(side)=="monitor")then
termObject = peripheral.wrap(side)
monitorAttached = true
end
if(self.parent~=nil)then
self.parent:removeObject(self)
end
isMonitor = true
else
termObject = parentTerminal
isMonitor = false
if(basalt.getMonitorFrame(monSide)==self)then
basalt.setMonitorFrame(monSide, nil)
end
end
basaltDraw = BasaltDraw(termObject)
monSide = side or nil
return self;
end;
getVisualChanged = function(self)
local changed = base.getVisualChanged(self)
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.getVisualChanged ~= nil and value:getVisualChanged()) then
changed = true
end
end
end
end
return changed
end;
loseFocusHandler = function(self)
base.loseFocusHandler(self)
if(focusedOBjectCache~=nil)then
focusedOBjectCache:loseFocusHandler()
focusedOBjectCache = nil
end
end;
getFocusHandler = function(self)
base.getFocusHandler(self)
if (self.parent ~= nil) then
self.parent:removeObject(self)
self.parent:addObject(self)
end
end;
keyHandler = function(self, event, key)
if (focusedObject ~= nil) then
if(focusedObject~=self)then
if (focusedObject.keyHandler ~= nil) then
if (focusedObject:keyHandler(event, key)) then
return true
end
end
else
base.keyHandler(self, event, key)
end
end
return false
end;
backgroundKeyHandler = function(self, event, key)
base.backgroundKeyHandler(self, event, key)
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.backgroundKeyHandler ~= nil) then
value:backgroundKeyHandler(event, key)
end
end
end
end
end;
eventHandler = function(self, event, p1, p2, p3, p4)
base.eventHandler(self, event, p1, p2, p3, p4)
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.eventHandler ~= nil) then
value:eventHandler(event, p1, p2, p3, p4)
end
end
end
end
if(isMonitor)then
if(event == "peripheral")and(p1==monSide)then
if(peripheral.getType(monSide)=="monitor")then
monitorAttached = true
termObject = peripheral.wrap(monSide)
basaltDraw = BasaltDraw(termObject)
end
end
if(event == "peripheral_detach")and(p1==monSide)then
monitorAttached = false
end
end
if(mirrorActive)then
if(peripheral.getType(mirrorSide)=="monitor")then
mirrorAttached = true
basaltDraw.setMirror(peripheral.wrap(mirrorSide))
end
if(event == "peripheral_detach")and(p1==mirrorSide)then
monitorAttached = false
end
if(event=="monitor_touch")then
self:mouseHandler(event, p1, p2, p3, p4)
end
end
if (event == "terminate") then
termObject.setCursorPos(1, 1)
termObject.clear()
basalt.stop()
end
end;
mouseHandler = function(self, event, button, x, y)
if (self.drag) then
local xO, yO = self.parent:getOffsetInternal()
xO = xO < 0 and math.abs(xO) or -xO
yO = yO < 0 and math.abs(yO) or -yO
if (event == "mouse_drag") then
local parentX = 1
local parentY = 1
if (self.parent ~= nil) then
parentX, parentY = self.parent:getAbsolutePosition(self.parent:getAnchorPosition())
end
self:setPosition(x + dragXOffset - (parentX - 1) + xO, y + dragYOffset - (parentY - 1) + yO)
end
if (event == "mouse_up") then
self.drag = false
end
return true
end
local fx, fy = self:getAbsolutePosition(self:getAnchorPosition())
local yOff = false
if(fy-1 == y)and(self:getBorder("top"))then
y = y+1
yOff = true
end
if (base.mouseHandler(self, event, button, x, y)) then
fx = fx + xOffset;fy = fy + yOffset;
if(isScrollable)and(importantScroll)then
if(event=="mouse_scroll")then
if(button>0)or(button<0)then
yOffset = max(min(yOffset-button, -minScroll),-maxScroll)
end
end
end
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in rpairs(objects[index]) do
if (value.mouseHandler ~= nil) then
if (value:mouseHandler(event, button, x, y)) then
return true
end
end
end
end
end
self:removeFocusedObject()
if (self.isMoveable) then
if (x >= fx) and (x <= fx + self:getWidth() - 1) and (y == fy) and (event == "mouse_click") then
self.drag = true
dragXOffset = fx - x
dragYOffset = yOff and 1 or 0
end
end
if(isScrollable)and(not importantScroll)then
if(event=="mouse_scroll")then
if(button>0)or(button<0)then
yOffset = max(min(yOffset-button, -minScroll),-maxScroll)
end
end
end
return true
end
return false
end;
setText = function(self, x, y, text)
local obx, oby = self:getAnchorPosition()
if (y >= 1) and (y <= self:getHeight()) then
if (self.parent ~= nil) then
self.parent:setText(max(x + (obx - 1), obx), oby + y - 1, sub(text, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1)))
else
basaltDraw.setText(max(x + (obx - 1), obx), oby + y - 1, sub(text, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1)))
end
end
end;
setBG = function(self, x, y, bgCol)
local obx, oby = self:getAnchorPosition()
if (y >= 1) and (y <= self:getHeight()) then
if (self.parent ~= nil) then
self.parent:setBG(max(x + (obx - 1), obx), oby + y - 1, sub(bgCol, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1)))
else
basaltDraw.setBG(max(x + (obx - 1), obx), oby + y - 1, sub(bgCol, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1)))
end
end
end;
setFG = function(self, x, y, fgCol)
local obx, oby = self:getAnchorPosition()
if (y >= 1) and (y <= self:getHeight()) then
if (self.parent ~= nil) then
self.parent:setFG(max(x + (obx - 1), obx), oby + y - 1, sub(fgCol, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1)))
else
basaltDraw.setFG(max(x + (obx - 1), obx), oby + y - 1, sub(fgCol, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1)))
end
end
end;
writeText = function(self, x, y, text, bgCol, fgCol)
local obx, oby = self:getAnchorPosition()
if (y >= 1) and (y <= self:getHeight()) then
if (self.parent ~= nil) then
self.parent:writeText(max(x + (obx - 1), obx), oby + y - 1, sub(text, max(1 - x + 1, 1), self:getWidth() - x + 1), bgCol, fgCol)
else
basaltDraw.writeText(max(x + (obx - 1), obx), oby + y - 1, sub(text, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1)), bgCol, fgCol)
end
end
end;
drawBackgroundBox = function(self, x, y, width, height, bgCol)
local obx, oby = self:getAnchorPosition()
height = (y < 1 and (height + y > self:getHeight() and self:getHeight() or height + y - 1) or (height + y > self:getHeight() and self:getHeight() - y + 1 or height))
width = (x < 1 and (width + x > self:getWidth() and self:getWidth() or width + x - 1) or (width + x > self:getWidth() and self:getWidth() - x + 1 or width))
if (self.parent ~= nil) then
self.parent:drawBackgroundBox(max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, bgCol)
else
basaltDraw.drawBackgroundBox(max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, bgCol)
end
end;
drawTextBox = function(self, x, y, width, height, symbol)
local obx, oby = self:getAnchorPosition()
height = (y < 1 and (height + y > self:getHeight() and self:getHeight() or height + y - 1) or (height + y > self:getHeight() and self:getHeight() - y + 1 or height))
width = (x < 1 and (width + x > self:getWidth() and self:getWidth() or width + x - 1) or (width + x > self:getWidth() and self:getWidth() - x + 1 or width))
if (self.parent ~= nil) then
self.parent:drawTextBox(max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, sub(symbol,1,1))
else
basaltDraw.drawTextBox(max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, sub(symbol,1,1))
end
end;
drawForegroundBox = function(self, x, y, width, height, fgCol)
local obx, oby = self:getAnchorPosition()
height = (y < 1 and (height + y > self:getHeight() and self:getHeight() or height + y - 1) or (height + y > self:getHeight() and self:getHeight() - y + 1 or height))
width = (x < 1 and (width + x > self:getWidth() and self:getWidth() or width + x - 1) or (width + x > self:getWidth() and self:getWidth() - x + 1 or width))
if (self.parent ~= nil) then
self.parent:drawForegroundBox(max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, fgCol)
else
basaltDraw.drawForegroundBox(max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, fgCol)
end
end;
draw = function(self)
if(isMonitor)and not(monitorAttached)then return false end;
if (self:getVisualChanged()) then
if (base.draw(self)) then
if(focusedObject~=focusedOBjectCache)then
if(focusedOBjectCache~=nil)then
focusedOBjectCache:getFocusHandler()
end
if(focusedObject~=nil)then
focusedObject:loseFocusHandler()
end
focusedObject = focusedOBjectCache
end
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local anchx, anchy = self:getAnchorPosition()
local w,h = self:getSize()
if (self.parent ~= nil) then
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(anchx, anchy, w, h, self.bgColor)
self.parent:drawTextBox(anchx, anchy, w, h, " ")
end
if(self.bgColor~=false)then self.parent:drawForegroundBox(anchx, anchy, w, h, self.fgColor) end
else
if(self.bgColor~=false)then
basaltDraw.drawBackgroundBox(anchx, anchy, w, h, self.bgColor)
basaltDraw.drawTextBox(anchx, anchy, w, h, " ")
end
if(self.fgColor~=false)then basaltDraw.drawForegroundBox(anchx, anchy, w, h, self.fgColor) end
end
termObject.setCursorBlink(false)
if (self.barActive) then
if (self.parent ~= nil) then
self.parent:writeText(anchx, anchy, utils.getTextHorizontalAlign(self.barText, w, self.barTextAlign), self.barBackground, self.barTextcolor)
else
basaltDraw.writeText(anchx, anchy, utils.getTextHorizontalAlign(self.barText, w, self.barTextAlign), self.barBackground, self.barTextcolor)
end
if(self:getBorder("left"))then
if (self.parent ~= nil) then
self.parent:drawBackgroundBox(anchx-1, anchy, 1, 1, self.barBackground)
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(anchx-1, anchy+1, 1, h-1, self.bgColor)
end
end
end
if(self:getBorder("top"))then
if (self.parent ~= nil) then
self.parent:drawBackgroundBox(anchx-1, anchy-1, w+1, 1, self.barBackground)
end
end
end
for _, index in rpairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.draw ~= nil) then
value:draw()
end
end
end
end
if (cursorBlink) then
termObject.setTextColor(cursorColor)
termObject.setCursorPos(xCursor, yCursor)
if (self.parent ~= nil) then
termObject.setCursorBlink(self:isFocused())
else
termObject.setCursorBlink(cursorBlink)
end
end
self:setVisualChanged(false)
end
end
end;
drawUpdate = function(self)
if(isMonitor)and not(monitorAttached)then return false end;
basaltDraw.update()
end;
addObject = function(self, obj)
return addObject(obj)
end;
removeObject = function(self, obj)
return removeObject(obj)
end;
getObject = function(self, obj)
return getObject(obj)
end;
getDeepObject = function(self, name)
return getDeepObject(name)
end,
addFrame = function(self, name)
local obj = basalt.newFrame(name or uuid(), self, nil, basalt)
return addObject(obj)
end;
}
for k,v in pairs(_OBJECTS)do
object["add"..k] = function(self, name)
return addObject(v(name or uuid(), self))
end
end
setmetatable(object, base)
return object
end

741
Basalt/Object.lua Normal file
View File

@@ -0,0 +1,741 @@
local basaltEvent = require("basaltEvent")
local utils = require("utils")
local split = utils.splitString
local numberFromString = utils.numberFromString
local xmlValue = utils.getValueFromXML
return function(name)
-- Base object
local objectType = "Object" -- not changeable
local object = {}
local zIndex = 1
local value
local anchor = "topLeft"
local ignOffset = false
local isVisible = true
local shadow = false
local borderLeft = false
local borderTop = false
local borderRight = false
local borderBottom = false
local shadowColor = colors.black
local borderColor = colors.black
local isEnabled = true
local isDragging = false
local dragStartX, dragStartY, dragXOffset, dragYOffset = 0, 0, 0, 0
local visualsChanged = true
local eventSystem = basaltEvent()
object = {
x = 1,
y = 1,
width = 1,
height = 1,
bgColor = colors.black,
fgColor = colors.white,
name = name or "Object",
parent = nil,
show = function(self)
isVisible = true
visualsChanged = true
return self
end;
hide = function(self)
isVisible = false
visualsChanged = true
return self
end;
enable = function(self)
isEnabled = true
return self
end;
disable = function(self)
isEnabled = false
return self
end;
generateXMLEventFunction = function(self, func, val)
local createF = function(str)
if(str:sub(1,1)=="#")then
local o = self:getBaseFrame():getDeepObject(str:sub(2,str:len()))
if(o~=nil)and(o.internalObjetCall~=nil)then
func(self,function()o:internalObjetCall()end)
end
else
func(self,self:getBaseFrame():getVariable(str))
end
end
if(type(val)=="string")then
createF(val)
elseif(type(val)=="table")then
for k,v in pairs(val)do
createF(v)
end
end
return self
end,
setValuesByXMLData = function(self, data)
local baseFrame = self:getBaseFrame()
if(xmlValue("x", data)~=nil)then self:setPosition(xmlValue("x", data), self.y) end
if(xmlValue("y", data)~=nil)then self:setPosition(self.x, xmlValue("y", data)) end
if(xmlValue("width", data)~=nil)then self:setSize(xmlValue("width", data), self.height) end
if(xmlValue("height", data)~=nil)then self:setSize(self.width, xmlValue("height", data)) end
if(xmlValue("bg", data)~=nil)then self:setBackground(colors[xmlValue("bg", data)]) end
if(xmlValue("fg", data)~=nil)then self:setForeground(colors[xmlValue("fg", data)]) end
if(xmlValue("value", data)~=nil)then self:setValue(colors[xmlValue("value", data)]) end
if(xmlValue("visible", data)~=nil)then if(xmlValue("visible", data))then self:show() else self:hide() end end
if(xmlValue("enabled", data)~=nil)then if(xmlValue("enabled", data))then self:enable() else self:disable() end end
if(xmlValue("zIndex", data)~=nil)then self:setZIndex(xmlValue("zIndex", data)) end
if(xmlValue("anchor", data)~=nil)then self:setAnchor(xmlValue("anchor", data)) end
if(xmlValue("shadow", data)~=nil)then if(xmlValue("shadow", data))then self:showShadow(true) end end
if(xmlValue("shadowColor", data)~=nil)then self:setShadow(colors[xmlValue("shadowColor", data)]) end
if(xmlValue("border", data)~=nil)then if(xmlValue("border", data))then borderLeft,borderTop,borderRight,borderBottom = true,true,true,true end end
if(xmlValue("borderLeft", data)~=nil)then if(xmlValue("borderLeft", data))then borderLeft = true else borderLeft = false end end
if(xmlValue("borderTop", data)~=nil)then if(xmlValue("borderTop", data))then borderTop = true else borderTop = false end end
if(xmlValue("borderRight", data)~=nil)then if(xmlValue("borderRight", data))then borderRight = true else borderRight = false end end
if(xmlValue("borderBottom", data)~=nil)then if(xmlValue("borderBottom", data))then borderBottom = true else borderBottom = false end end
if(xmlValue("borderColor", data)~=nil)then self:setBorder(colors[xmlValue("borderColor", data)]) end
if(xmlValue("ignoreOffset", data)~=nil)then if(xmlValue("ignoreOffset", data))then self:ignoreOffset(true) end end
if(xmlValue("onClick", data)~=nil)then self:generateXMLEventFunction(self.onClick, xmlValue("onClick", data)) end
if(xmlValue("onClickUp", data)~=nil)then self:generateXMLEventFunction(self.onClickUp, xmlValue("onClickUp", data)) end
if(xmlValue("onScroll", data)~=nil)then self:generateXMLEventFunction(self.onScroll, xmlValue("onScroll", data)) end
if(xmlValue("onDrag", data)~=nil)then self:generateXMLEventFunction(self.onDrag, xmlValue("onDrag", data)) end
if(xmlValue("onKey", data)~=nil)then self:generateXMLEventFunction(self.onKey, xmlValue("onKey", data)) end
if(xmlValue("onKeyUp", data)~=nil)then self:generateXMLEventFunction(self.onKeyUp, xmlValue("onKeyUp", data)) end
if(xmlValue("onChange", data)~=nil)then self:generateXMLEventFunction(self.onChange, xmlValue("onChange", data)) end
if(xmlValue("onResize", data)~=nil)then self:generateXMLEventFunction(self.onResize, xmlValue("onResize", data)) end
if(xmlValue("onReposition", data)~=nil)then self:generateXMLEventFunction(self.onReposition, xmlValue("onReposition", data)) end
if(xmlValue("onEvent", data)~=nil)then self:generateXMLEventFunction(self.onEvent, xmlValue("onEvent", data)) end
if(xmlValue("onGetFocus", data)~=nil)then self:generateXMLEventFunction(self.onGetFocus, xmlValue("onGetFocus", data)) end
if(xmlValue("onLoseFocus", data)~=nil)then self:generateXMLEventFunction(self.onLoseFocus, xmlValue("onLoseFocus", data)) end
if(xmlValue("onBackgroundKey", data)~=nil)then self:generateXMLEventFunction(self.onBackgroundKey, xmlValue("onBackgroundKey", data)) end
if(xmlValue("onBackgroundKeyUp", data)~=nil)then self:generateXMLEventFunction(self.onBackgroundKeyUp, xmlValue("onBackgroundKeyUp", data)) end
return self
end,
isVisible = function(self)
return isVisible
end;
setFocus = function(self)
if (self.parent ~= nil) then
self.parent:setFocusedObject(self)
end
return self
end;
setZIndex = function(self, index)
zIndex = index
if (self.parent ~= nil) then
self.parent:removeObject(self)
self.parent:addObject(self)
end
return self
end;
getZIndex = function(self)
return zIndex;
end;
getType = function(self)
return objectType
end;
getName = function(self)
return self.name
end;
remove = function(self)
if (self.parent ~= nil) then
self.parent:removeObject(self)
end
return self
end;
setParent = function(self, frame)
if (frame.getType ~= nil and frame:getType() == "Frame") then
self:remove()
frame:addObject(self)
if (self.draw) then
self:show()
end
end
return self
end;
setValue = function(self, _value)
if (value ~= _value) then
value = _value
visualsChanged = true
self:valueChangedHandler()
end
return self
end;
getValue = function(self)
return value
end;
getVisualChanged = function(self)
return visualsChanged
end;
setVisualChanged = function(self, change)
visualsChanged = change or true
if(change == nil)then visualsChanged = true end
return self
end;
getEventSystem = function(self)
return eventSystem
end;
getParent = function(self)
return self.parent
end;
getObjectReferencesForDynVal = function(self, str)
end,
setPosition = function(self, xPos, yPos, rel)
if(type(xPos)=="number")then
self.x = rel and self:getX()+xPos or xPos
end
if(type(yPos)=="number")then
self.y = rel and self:getY()+yPos or yPos
end
if(self.parent~=nil)then
if(type(xPos)=="string")then
self.x = self.parent:newDynamicValue(self, xPos)
end
if(type(yPos)=="string")then
self.y = self.parent:newDynamicValue(self, yPos)
end
self.parent:recalculateDynamicValues()
end
eventSystem:sendEvent("basalt_reposition", self)
visualsChanged = true
return self
end;
getX = function(self)
return type(self.x) == "number" and self.x or math.floor(self.x[1]+0.5)
end;
getY = function(self)
return type(self.y) == "number" and self.y or math.floor(self.y[1]+0.5)
end;
getPosition = function(self)
return self:getX(), self:getY()
end;
getVisibility = function(self)
return isVisible
end;
setVisibility = function(self, _isVisible)
isVisible = _isVisible or not isVisible
visualsChanged = true
return self
end;
setSize = function(self, width, height, rel)
if(type(width)=="number")then
self.width = rel and self.width+width or width
end
if(type(height)=="number")then
self.height = rel and self.height+height or height
end
if(self.parent~=nil)then
if(type(width)=="string")then
self.width = self.parent:newDynamicValue(self, width)
end
if(type(height)=="string")then
self.height = self.parent:newDynamicValue(self, height)
end
self.parent:recalculateDynamicValues()
end
eventSystem:sendEvent("basalt_resize", self)
visualsChanged = true
return self
end;
getHeight = function(self)
return type(self.height) == "number" and self.height or math.floor(self.height[1]+0.5)
end;
getWidth = function(self)
return type(self.width) == "number" and self.width or math.floor(self.width[1]+0.5)
end;
getSize = function(self)
return self:getWidth(), self:getHeight()
end;
calculateDynamicValues = function(self)
if(type(self.width)=="table")then self.width:calculate() end
if(type(self.height)=="table")then self.height:calculate() end
if(type(self.x)=="table")then self.x:calculate() end
if(type(self.y)=="table")then self.y:calculate() end
return self
end,
setBackground = function(self, color)
self.bgColor = color or false
visualsChanged = true
return self
end;
getBackground = function(self)
return self.bgColor
end;
setForeground = function(self, color)
self.fgColor = color or false
visualsChanged = true
return self
end;
getForeground = function(self)
return self.fgColor
end;
showShadow = function(self, show)
shadow = show or (not shadow)
return self
end;
setShadow = function(self, color)
shadowColor = color
return self
end;
isShadowActive = function(self)
return shadow;
end;
showBorder = function(self, ...)
for _,v in pairs(table.pack(...))do
if(v=="left")then
borderLeft = true
end
if(v=="top")then
borderTop = true
end
if(v=="right")then
borderRight = true
end
if(v=="bottom")then
borderBottom = true
end
end
return self
end;
setBorder = function(self, color)
borderColor = color
return self
end;
getBorder = function(self, side)
if(side=="left")then
return borderLeft;
end
if(side=="top")then
return borderTop;
end
if(side=="right")then
return borderRight;
end
if(side=="bottom")then
return borderBottom;
end
end;
draw = function(self)
if (isVisible) then
if(self.parent~=nil)then
local x, y = self:getAnchorPosition()
local w,h = self:getSize()
if(shadow)then
self.parent:drawBackgroundBox(x+1, y+h, w, 1, shadowColor)
self.parent:drawBackgroundBox(x+w, y+1, 1, h, shadowColor)
self.parent:drawForegroundBox(x+1, y+h, w, 1, shadowColor)
self.parent:drawForegroundBox(x+w, y+1, 1, h, shadowColor)
end
if(borderLeft)then
self.parent:drawTextBox(x-1, y, 1, h, "\149")
self.parent:drawForegroundBox(x-1, y, 1, h, borderColor)
if(self.bgColor~=false)then self.parent:drawBackgroundBox(x-1, y, 1, h, self.bgColor) end
end
if(borderLeft)and(borderTop)then
self.parent:drawTextBox(x-1, y-1, 1, 1, "\151")
self.parent:drawForegroundBox(x-1, y-1, 1, 1, borderColor)
if(self.bgColor~=false)then self.parent:drawBackgroundBox(x-1, y-1, 1, 1, self.bgColor) end
end
if(borderTop)then
self.parent:drawTextBox(x, y-1, w, 1, "\131")
self.parent:drawForegroundBox(x, y-1, w, 1, borderColor)
if(self.bgColor~=false)then self.parent:drawBackgroundBox(x, y-1, w, 1, self.bgColor) end
end
if(borderTop)and(borderRight)then
self.parent:drawTextBox(x+w, y-1, 1, 1, "\149")
self.parent:drawForegroundBox(x+w, y-1, 1, 1, borderColor)
end
if(borderRight)then
self.parent:drawTextBox(x+w, y, 1, h, "\149")
self.parent:drawForegroundBox(x+w, y, 1, h, borderColor)
end
if(borderRight)and(borderBottom)then
self.parent:drawTextBox(x+w, y+h, 1, 1, "\129")
self.parent:drawForegroundBox(x+w, y+h, 1, 1, borderColor)
end
if(borderBottom)then
self.parent:drawTextBox(x, y+h, w, 1, "\131")
self.parent:drawForegroundBox(x, y+h, w, 1, borderColor)
end
if(borderBottom)and(borderLeft)then
self.parent:drawTextBox(x-1, y+h, 1, 1, "\131")
self.parent:drawForegroundBox(x-1, y+h, 1, 1, borderColor)
end
end
return true
end
return false
end;
getAbsolutePosition = function(self, x, y)
-- relative position to absolute position
if (x == nil) or (y == nil) then
x, y = self:getAnchorPosition()
end
if (self.parent ~= nil) then
local fx, fy = self.parent:getAbsolutePosition()
x = fx + x - 1
y = fy + y - 1
end
return x, y
end;
getAnchorPosition = function(self, x, y, ignOff)
if (x == nil) then
x = self:getX()
end
if (y == nil) then
y = self:getY()
end
if(self.parent~=nil)then
local pw,ph = self.parent:getSize()
if (anchor == "top") then
x = math.floor(pw/2) + x - 1
elseif(anchor == "topRight") then
x = pw + x - 1
elseif(anchor == "right") then
x = pw + x - 1
y = math.floor(ph/2) + y - 1
elseif(anchor == "bottomRight") then
x = pw + x - 1
y = ph + y - 1
elseif(anchor == "bottom") then
x = math.floor(pw/2) + x - 1
y = ph + y - 1
elseif(anchor == "bottomLeft") then
y = ph + y - 1
elseif(anchor == "left") then
y = math.floor(ph/2) + y - 1
elseif(anchor == "center") then
x = math.floor(pw/2) + x - 1
y = math.floor(ph/2) + y - 1
end
local xO, yO = self.parent:getOffsetInternal()
if not(ignOffset or ignOff) then
return x+xO, y+yO
end
end
return x, y
end;
ignoreOffset = function(self, ignore)
ignOffset = ignore
if(ignore==nil)then ignOffset = true end
return self
end;
getBaseFrame = function(self)
if(self.parent~=nil)then
return self.parent:getBaseFrame()
end
return self
end;
setAnchor = function(self, newAnchor)
anchor = newAnchor
visualsChanged = true
return self
end;
getAnchor = function(self)
return anchor
end;
onChange = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("value_changed", v)
end
end
return self
end;
onClick = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_click", v)
self:registerEvent("monitor_touch", v)
end
end
return self
end;
onClickUp = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_up", v)
end
end
return self
end;
onScroll = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_scroll", v)
end
end
return self
end;
onDrag = function(self, ...)
if(isEnabled)then
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_drag", v)
end
end
end
return self
end;
onEvent = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("custom_event_handler", v)
end
end
return self
end;
onKey = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("key", v)
self:registerEvent("char", v)
end
end
return self
end;
onResize = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("basalt_resize", v)
end
end
return self
end;
onReposition = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("basalt_reposition", v)
end
end
return self
end;
onKeyUp = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("key_up", v)
end
end
return self
end;
onBackgroundKey = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("background_key", v)
self:registerEvent("background_char", v)
end
end
return self
end;
onBackgroundKeyUp = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("background_key_up", v)
end
end
return self
end;
isFocused = function(self)
if (self.parent ~= nil) then
return self.parent:getFocusedObject() == self
end
return false
end;
onGetFocus = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("get_focus", v)
end
end
return self
end;
onLoseFocus = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("lose_focus", v)
end
end
return self
end;
registerEvent = function(self, event, func)
return eventSystem:registerEvent(event, func)
end;
removeEvent = function(self, event, index)
return eventSystem:removeEvent(event, index)
end;
sendEvent = function(self, event, ...)
return eventSystem:sendEvent(event, self, ...)
end;
mouseHandler = function(self, event, button, x, y)
if(isEnabled)and(isVisible)then
local objX, objY = self:getAbsolutePosition(self:getAnchorPosition())
local w, h = self:getSize()
local yOff = false
if(objY-1 == y)and(self:getBorder("top"))then
y = y+1
yOff = true
end
if(event=="mouse_up")then
isDragging = false
end
if(isDragging)and(event=="mouse_drag")then
local xO, yO, parentX, parentY = 0, 0, 1, 1
if (self.parent ~= nil) then
xO, yO = self.parent:getOffsetInternal()
xO = xO < 0 and math.abs(xO) or -xO
yO = yO < 0 and math.abs(yO) or -yO
parentX, parentY = self.parent:getAbsolutePosition(self.parent:getAnchorPosition())
end
local dX, dY = x + dragXOffset - (parentX - 1) + xO, y + dragYOffset - (parentY - 1) + yO
local val = eventSystem:sendEvent(event, self, event, button, dX, dY, dragStartX, dragStartY, x, y)
end
if (objX <= x) and (objX + w > x) and (objY <= y) and (objY + h > y) then
if(event=="mouse_click")then
isDragging = true
dragStartX, dragStartY = x, y
dragXOffset, dragYOffset = objX - x, objY - y
end
if(event~="mouse_drag")then
if(event~="mouse_up")then
if (self.parent ~= nil) then
self.parent:setFocusedObject(self)
end
end
local val = eventSystem:sendEvent(event, self, event, button, x, y)
if(val~=nil)then return val end
end
return true
end
end
return false
end;
keyHandler = function(self, event, key)
if(isEnabled)then
if (self:isFocused()) then
local val = eventSystem:sendEvent(event, self, event, key)
if(val~=nil)then return val end
return true
end
end
return false
end;
backgroundKeyHandler = function(self, event, key)
if(isEnabled)then
local val = eventSystem:sendEvent("background_"..event, self, event, key)
if(val~=nil)then return val end
end
return true
end;
valueChangedHandler = function(self)
eventSystem:sendEvent("value_changed", self)
end;
eventHandler = function(self, event, p1, p2, p3, p4)
eventSystem:sendEvent("custom_event_handler", self, event, p1, p2, p3, p4)
end;
getFocusHandler = function(self)
local val = eventSystem:sendEvent("get_focus", self)
if(val~=nil)then return val end
return true
end;
loseFocusHandler = function(self)
local val = eventSystem:sendEvent("lose_focus", self)
if(val~=nil)then return val end
return true
end;
}
object.__index = object
return object
end

10
Basalt/init.lua Normal file
View File

@@ -0,0 +1,10 @@
local curDir = fs.getDir(table.pack(...)[2]) or ""
local defaultPath = package.path
local format = "%s;/%s/?.lua;/%s/?/init.lua"
package.path = string.format(format, package.path, curDir,curDir)..string.format(format, package.path, curDir.."/libraries",curDir.."/libraries")..string.format(format, package.path, curDir.."/objects",curDir.."/objects")
local Basalt = require("main")
package.path = defaultPath
return Basalt

View File

@@ -0,0 +1,199 @@
local tHex = require("tHex")
local sub,rep = string.sub,string.rep
return function(drawTerm)
local terminal = drawTerm or term.current()
local mirrorTerm
local width, height = terminal.getSize()
local cacheT = {}
local cacheBG = {}
local cacheFG = {}
local _cacheT = {}
local _cacheBG = {}
local _cacheFG = {}
local emptySpaceLine
local emptyColorLines = {}
local function createEmptyLines()
emptySpaceLine = rep(" ", width)
for n = 0, 15 do
local nColor = 2 ^ n
local sHex = tHex[nColor]
emptyColorLines[nColor] = rep(sHex, width)
end
end
----
createEmptyLines()
local function recreateWindowArray()
local emptyText = emptySpaceLine
local emptyFG = emptyColorLines[colors.white]
local emptyBG = emptyColorLines[colors.black]
for currentY = 1, height do
cacheT[currentY] = sub(cacheT[currentY] == nil and emptyText or cacheT[currentY] .. emptyText:sub(1, width - cacheT[currentY]:len()), 1, width)
cacheFG[currentY] = sub(cacheFG[currentY] == nil and emptyFG or cacheFG[currentY] .. emptyFG:sub(1, width - cacheFG[currentY]:len()), 1, width)
cacheBG[currentY] = sub(cacheBG[currentY] == nil and emptyBG or cacheBG[currentY] .. emptyBG:sub(1, width - cacheBG[currentY]:len()), 1, width)
end
end
recreateWindowArray()
local function setText(x, y, text)
if (y >= 1) and (y <= height) then
if (x + text:len() > 0) and (x <= width) then
local oldCache = cacheT[y]
local newCache
local nEnd = x + #text - 1
if (x < 1) then
local startN = 1 - x + 1
local endN = width - x + 1
text = sub(text, startN, endN)
elseif (nEnd > width) then
local endN = width - x + 1
text = sub(text, 1, endN)
end
if (x > 1) then
local endN = x - 1
newCache = sub(oldCache, 1, endN) .. text
else
newCache = text
end
if nEnd < width then
newCache = newCache .. sub(oldCache, nEnd + 1, width)
end
cacheT[y] = newCache
end
end
end
local function setBG(x, y, colorStr)
if (y >= 1) and (y <= height) then
if (x + colorStr:len() > 0) and (x <= width) then
local oldCache = cacheBG[y]
local newCache
local nEnd = x + #colorStr - 1
if (x < 1) then
colorStr = sub(colorStr, 1 - x + 1, width - x + 1)
elseif (nEnd > width) then
colorStr = sub(colorStr, 1, width - x + 1)
end
if (x > 1) then
newCache = sub(oldCache, 1, x - 1) .. colorStr
else
newCache = colorStr
end
if nEnd < width then
newCache = newCache .. sub(oldCache, nEnd + 1, width)
end
cacheBG[y] = newCache
end
end
end
local function setFG(x, y, colorStr)
if (y >= 1) and (y <= height) then
if (x + colorStr:len() > 0) and (x <= width) then
local oldCache = cacheFG[y]
local newCache
local nEnd = x + #colorStr - 1
if (x < 1) then
local startN = 1 - x + 1
local endN = width - x + 1
colorStr = sub(colorStr, startN, endN)
elseif (nEnd > width) then
local endN = width - x + 1
colorStr = sub(colorStr, 1, endN)
end
if (x > 1) then
local endN = x - 1
newCache = sub(oldCache, 1, endN) .. colorStr
else
newCache = colorStr
end
if nEnd < width then
newCache = newCache .. sub(oldCache, nEnd + 1, width)
end
cacheFG[y] = newCache
end
end
end
local drawHelper = {
setMirror = function(mirror)
mirrorTerm = mirror
end,
setBG = function(x, y, colorStr)
setBG(x, y, colorStr)
end;
setText = function(x, y, text)
setText(x, y, text)
end;
setFG = function(x, y, colorStr)
setFG(x, y, colorStr)
end;
drawBackgroundBox = function(x, y, width, height, bgCol)
for n = 1, height do
setBG(x, y + (n - 1), rep(tHex[bgCol], width))
end
end;
drawForegroundBox = function(x, y, width, height, fgCol)
for n = 1, height do
setFG(x, y + (n - 1) ,rep(tHex[fgCol], width))
end
end;
drawTextBox = function(x, y, width, height, symbol)
for n = 1, height do
setText(x, y + (n - 1), rep(symbol, width))
end
end;
writeText = function(x, y, text, bgCol, fgCol)
bgCol = bgCol or terminal.getBackgroundColor()
fgCol = fgCol or terminal.getTextColor()
setText(x, y, text)
setBG(x, y, rep(tHex[bgCol], text:len()))
setFG(x, y, rep(tHex[fgCol], text:len()))
end;
update = function()
local xC, yC = terminal.getCursorPos()
local isBlinking = false
if (terminal.getCursorBlink ~= nil) then
isBlinking = terminal.getCursorBlink()
end
terminal.setCursorBlink(false)
if(mirrorTerm~=nil)then terminal.setCursorBlink(false) end
for n = 1, height do
terminal.setCursorPos(1, n)
terminal.blit(cacheT[n], cacheFG[n], cacheBG[n])
if(mirrorTerm~=nil)then
mirrorTerm.setCursorPos(1, n)
mirrorTerm.blit(cacheT[n], cacheFG[n], cacheBG[n])
end
end
terminal.setBackgroundColor(colors.black)
terminal.setCursorBlink(isBlinking)
terminal.setCursorPos(xC, yC)
if(mirrorTerm~=nil)then
mirrorTerm.setBackgroundColor(colors.black)
mirrorTerm.setCursorBlink(isBlinking)
mirrorTerm.setCursorPos(xC, yC)
end
end;
setTerm = function(newTerm)
terminal = newTerm;
end;
}
return drawHelper
end

View File

@@ -0,0 +1,35 @@
return function()
local events = {}
local index = {}
local event = {
registerEvent = function(self, _event, func)
if (events[_event] == nil) then
events[_event] = {}
index[_event] = 1
end
events[_event][index[_event]] = func
index[_event] = index[_event] + 1
return index[_event] - 1
end;
removeEvent = function(self, _event, index)
events[_event][index[_event]] = nil
end;
sendEvent = function(self, _event, ...)
local returnValue
if (events[_event] ~= nil) then
for _, value in pairs(events[_event]) do
local val = value(...)
if(val==false)then
returnValue = val
end
end
end
return returnValue
end;
}
event.__index = event
return event
end

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,197 @@
local function line(x1,y1,x2,y2)
local points = {}
if x1 == x2 and y1 == y2 then return {x=x1,y=x2} end
local minX = math.min(x1, x2)
local maxX, minY, maxY
if minX == x1 then minY,maxX,maxY = y1,x2,y2
else minY,maxX,maxY = y2,x1,y1 end
local xDiff,yDiff = maxX - minX,maxY - minY
if xDiff > math.abs(yDiff) then
local y = minY
local dy = yDiff / xDiff
for x = minX, maxX do
table.insert(points,{x=x,y=math.floor(y + 0.5)})
y = y + dy
end
else
local x,dx = minX,xDiff / yDiff
if maxY >= minY then
for y = minY, maxY do
table.insert(points,{x=math.floor(x + 0.5),y=y})
x = x + dx
end
else
for y = minY, maxY, -1 do
table.insert(points,{x=math.floor(x + 0.5),y=y})
x = x - dx
end
end
end
return points
end
local function filledCircle(xC, yC, r)
local points = {}
for x=-r, r+1 do
local dy = math.floor(math.sqrt(r*r - x*x))
for y=-dy, dy+1 do
table.insert(points, {x=xC+x, y=yC+y})
end
end
return points
end
local function ellipse(xC, yC, r1, r2, filled)
local rx,ry = math.ceil(math.floor(r1-0.5)/2),math.ceil(math.floor(r2-0.5)/2)
local x,y=0,ry
local d1 = ((ry * ry) - (rx * rx * ry) + (0.25 * rx * rx))
local dx = 2*ry^2*x
local dy = 2*rx^2*y
local points = {}
while dx < dy do
table.insert(points,{x=x+xC,y=y+yC})
table.insert(points,{x=-x+xC,y=y+yC})
table.insert(points,{x=x+xC,y=-y+yC})
table.insert(points,{x=-x+xC,y=-y+yC})
if filled then
for y=-y+yC+1,y+yC-1 do
table.insert(points,{x=x+xC,y=y})
table.insert(points,{x=-x+xC,y=y})
end
end
if d1 < 0 then
x = x + 1
dx = dx + 2*ry^2
d1 = d1 + dx + ry^2
else
x,y = x+1,y-1
dx = dx + 2*ry^2
dy = dy - 2*rx^2
d1 = d1 + dx - dy + ry^2
end
end
local d2 = (((ry * ry) * ((x + 0.5) * (x + 0.5))) + ((rx * rx) * ((y - 1) * (y - 1))) - (rx * rx * ry * ry))
while y >= 0 do
table.insert(points,{x=x+xC,y=y+yC})
table.insert(points,{x=-x+xC,y=y+yC})
table.insert(points,{x=x+xC,y=-y+yC})
table.insert(points,{x=-x+xC,y=-y+yC})
if filled then
for y=-y+yC,y+yC do
table.insert(points,{x=x+xC,y=y})
table.insert(points,{x=-x+xC,y=y})
end
end
if d2 > 0 then
y = y - 1
dy = dy - 2*rx^2
d2 = d2 + rx^2 - dy
else
y = y - 1
x = x + 1
dy = dy - 2*rx^2
dx = dx + 2*ry^2
d2 = d2 + dx - dy + rx^2
end
end
return points
end
local function circle(xC, yC, r, filled)
return ellipse(xC, yC, r, r, filled)
end
return {
circle = function(x, y, radius, filled)
return circle(x, y, radius, filled)
end,
rectangle = function(x1, y1, x2, y2, filled)
local points = {}
if(filled)then
for y=y1,y2 do
for x=x1,x2 do
table.insert(points, {x=x,y=y})
end
end
else
for y=y1,y2 do
for x=x1,x2 do
if(x==x1)or(x==x2)or(y==y1)or(y==y2)then
table.insert(points, {x=x,y=y})
end
end
end
end
return points
end,
triangle = function(x1, y1, x2, y2, x3, y3, filled)
local function drawFlatTopTriangle(points,x1,y1,x2,y2,x3,y3)
local m1 = (x3 - x1) / (y3 - y1)
local m2 = (x3 - x2) / (y3 - y2)
local yStart = math.ceil(y1 - 0.5)
local yEnd = math.ceil(y3 - 0.5)-1
for y = yStart, yEnd do
local px1 = m1 * (y + 0.5 - y1) + x1
local px2 = m2 * (y + 0.5 - y2) + x2
local xStart = math.ceil(px1 - 0.5)
local xEnd = math.ceil(px2 - 0.5)
for x=xStart,xEnd do
table.insert(points,{x=x,y=y})
end
end
end
local function drawFlatBottomTriangle(points,x1,y1,x2,y2,x3,y3)
local m1 = (x2 - x1) / (y2 - y1)
local m2 = (x3 - x1) / (y3 - y1)
local yStart = math.ceil(y1-0.5)
local yEnd = math.ceil(y3-0.5)-1
for y = yStart, yEnd do
local px1 = m1 * (y + 0.5 - y1) + x1
local px2 = m2 * (y + 0.5 - y1) + x1
local xStart = math.ceil(px1 - 0.5)
local xEnd = math.ceil(px2 - 0.5)
for x=xStart,xEnd do
table.insert(points,{x=x,y=y})
end
end
end
local points = {}
if(filled)then
if y2 < y1 then x1,y1,x2,y2 = x2,y2,x1,y1 end
if y3 < y2 then x2,y2,x3,y3 = x3,y3,x2,y2 end
if y2 < y2 then x1,y1,x2,y2 = x2,y2,x1,y1 end
if y1 == y2 then
if x2 < x1 then x1,y1,x2,y2 = x2,y2,x1,y1 end
drawFlatTopTriangle(points,x1,y1,x2,y2,x3,y3)
elseif y2 == y3 then
if x3 < x2 then x3,y3,x2,y2 = x2,y2,x3,y3 end
drawFlatBottomTriangle(points,x1,y1,x2,y2,x3,y3)
else
local alphaSplit = (y2-y1)/(y3-y1)
local x = x1 + ((x3 - x1) * alphaSplit)
local y = y1 + ((y3 - y1) * alphaSplit)
if x2 < x then
drawFlatBottomTriangle(points,x1,y1,x2,y2,x, y)
drawFlatTopTriangle(points,x2,y2,x,y,x3,y3)
else
drawFlatBottomTriangle(points,x1,y1,x,y,x1,y1)
drawFlatTopTriangle(points,x,y,x2,y2,x3,y3)
end
end
else
points = line(x1,y1,x2,y2)
for k,v in pairs(line(x2,y2,x3,y3))do table.insert(points, v) end
for k,v in pairs(line(x3,y3,x1,y1))do table.insert(points, v) end
end
return points
end,
line = line,
ellipse = function(xCenter, yCenter, radius1, radius2, filled)
return ellipse(xCenter, yCenter, radius1, radius2, filled)
end
}

147
Basalt/libraries/layout.lua Normal file
View File

@@ -0,0 +1,147 @@
local function newNode(name)
local node = {}
node.___value = nil
node.___name = name
node.___children = {}
node.___props = {}
function node:value() return self.___value end
function node:setValue(val) self.___value = val end
function node:name() return self.___name end
function node:setName(name) self.___name = name end
function node:children() return self.___children end
function node:numChildren() return #self.___children end
function node:addChild(child)
if self[child:name()] ~= nil then
if type(self[child:name()].name) == "function" then
local tempTable = {}
table.insert(tempTable, self[child:name()])
self[child:name()] = tempTable
end
table.insert(self[child:name()], child)
else
self[child:name()] = child
end
table.insert(self.___children, child)
end
function node:properties() return self.___props end
function node:numProperties() return #self.___props end
function node:addProperty(name, value)
local lName = "@" .. name
if self[lName] ~= nil then
if type(self[lName]) == "string" then
local tempTable = {}
table.insert(tempTable, self[lName])
self[lName] = tempTable
end
table.insert(self[lName], value)
else
self[lName] = value
end
table.insert(self.___props, { name = name, value = self[name] })
end
return node
end
local XmlParser = {};
function XmlParser:ToXmlString(value)
value = string.gsub(value, "&", "&amp;"); -- '&' -> "&amp;"
value = string.gsub(value, "<", "&lt;"); -- '<' -> "&lt;"
value = string.gsub(value, ">", "&gt;"); -- '>' -> "&gt;"
value = string.gsub(value, "\"", "&quot;"); -- '"' -> "&quot;"
value = string.gsub(value, "([^%w%&%;%p%\t% ])",
function(c)
return string.format("&#x%X;", string.byte(c))
end);
return value;
end
function XmlParser:FromXmlString(value)
value = string.gsub(value, "&#x([%x]+)%;",
function(h)
return string.char(tonumber(h, 16))
end);
value = string.gsub(value, "&#([0-9]+)%;",
function(h)
return string.char(tonumber(h, 10))
end);
value = string.gsub(value, "&quot;", "\"");
value = string.gsub(value, "&apos;", "'");
value = string.gsub(value, "&gt;", ">");
value = string.gsub(value, "&lt;", "<");
value = string.gsub(value, "&amp;", "&");
return value;
end
function XmlParser:ParseArgs(node, s)
string.gsub(s, "(%w+)=([\"'])(.-)%2", function(w, _, a)
node:addProperty(w, self:FromXmlString(a))
end)
end
function XmlParser:ParseXmlText(xmlText)
local stack = {}
local top = newNode()
table.insert(stack, top)
local ni, c, label, xarg, empty
local i, j = 1, 1
while true do
ni, j, c, label, xarg, empty = string.find(xmlText, "<(%/?)([%w_:]+)(.-)(%/?)>", i)
if not ni then break end
local text = string.sub(xmlText, i, ni - 1);
if not string.find(text, "^%s*$") then
local lVal = (top:value() or "") .. self:FromXmlString(text)
stack[#stack]:setValue(lVal)
end
if empty == "/" then -- empty element tag
local lNode = newNode(label)
self:ParseArgs(lNode, xarg)
top:addChild(lNode)
elseif c == "" then -- start tag
local lNode = newNode(label)
self:ParseArgs(lNode, xarg)
table.insert(stack, lNode)
top = lNode
else -- end tag
local toclose = table.remove(stack) -- remove top
top = stack[#stack]
if #stack < 1 then
error("XmlParser: nothing to close with " .. label)
end
if toclose:name() ~= label then
error("XmlParser: trying to close " .. toclose.name .. " with " .. label)
end
top:addChild(toclose)
end
i = j + 1
end
local text = string.sub(xmlText, i);
if #stack > 1 then
error("XmlParser: unclosed " .. stack[#stack]:name())
end
return top
end
function XmlParser:loadFile(xmlFilename, base)
if not base then
base = system.ResourceDirectory
end
local path = system.pathForFile(xmlFilename, base)
local hFile, err = io.open(path, "r");
if hFile and not err then
local xmlText = hFile:read("*a"); -- read file content
io.close(hFile);
return self:ParseXmlText(xmlText), nil;
else
print(err)
return nil
end
end
return XmlParser

View File

@@ -0,0 +1,52 @@
local processes = {}
local process = {}
local processId = 0
function process:new(path, window, ...)
local args = table.pack(...)
local newP = setmetatable({ path = path }, { __index = self })
newP.window = window
newP.processId = processId
newP.coroutine = coroutine.create(function()
os.run({ }, path, table.unpack(args))
end)
processes[processId] = newP
processId = processId + 1
return newP
end
function process:resume(event, ...)
term.redirect(self.window)
local ok, result = coroutine.resume(self.coroutine, event, ...)
self.window = term.current()
if ok then
self.filter = result
else
basalt.debug(result)
end
end
function process:isDead()
if (self.coroutine ~= nil) then
if (coroutine.status(self.coroutine) == "dead") then
table.remove(processes, self.processId)
return true
end
else
return true
end
return false
end
function process:getStatus()
if (self.coroutine ~= nil) then
return coroutine.status(self.coroutine)
end
return nil
end
function process:start()
coroutine.resume(self.coroutine)
end
return process

18
Basalt/libraries/tHex.lua Normal file
View File

@@ -0,0 +1,18 @@
return { -- copy paste is a very important feature
[colors.white] = "0",
[colors.orange] = "1",
[colors.magenta] = "2",
[colors.lightBlue] = "3",
[colors.yellow] = "4",
[colors.lime] = "5",
[colors.pink] = "6",
[colors.gray] = "7",
[colors.lightGray] = "8",
[colors.cyan] = "9",
[colors.purple] = "a",
[colors.blue] = "b",
[colors.brown] = "c",
[colors.green] = "d",
[colors.red] = "e",
[colors.black] = "f",
}

110
Basalt/libraries/utils.lua Normal file
View File

@@ -0,0 +1,110 @@
local splitString = function(str, sep)
if sep == nil then
sep = "%s"
end
local t={}
for v in string.gmatch(str, "([^"..sep.."]+)") do
table.insert(t, v)
end
return t
end
return {
getTextHorizontalAlign = function(text, width, textAlign, replaceChar)
text = string.sub(text, 1, width)
local offset = width - string.len(text)
if (textAlign == "right") then
text = string.rep(replaceChar or " ", offset) .. text
elseif (textAlign == "center") then
text = string.rep(replaceChar or " ", math.floor(offset / 2)) .. text .. string.rep(replaceChar or " ", math.floor(offset / 2))
text = text .. (string.len(text) < width and (replaceChar or " ") or "")
else
text = text .. string.rep(replaceChar or " ", offset)
end
return text
end,
getTextVerticalAlign = function(h, textAlign)
local offset = 0
if (textAlign == "center") then
offset = math.ceil(h / 2)
if (offset < 1) then
offset = 1
end
end
if (textAlign == "bottom") then
offset = h
end
if(offset<1)then offset=1 end
return offset
end,
rpairs = function(t)
return function(t, i)
i = i - 1
if i ~= 0 then
return i, t[i]
end
end, t, #t + 1
end,
splitString = splitString,
createText = function(str, width)
local uniqueLines = splitString(str, "\n")
local lines = {}
for k,v in pairs(uniqueLines)do
local line = ""
local words = splitString(v, " ")
for a,b in pairs(words)do
if(#line+#b <= width)then
line = line=="" and b or line.." "..b
if(a==#words)then table.insert(lines, line) end
else
table.insert(lines, line)
line = b:sub(1,width)
if(a==#words)then table.insert(lines, line) end
end
end
end
return lines
end,
getValueFromXML = function(name, tab)
local var
if(type(tab)~="table")then return end
if(tab[name]~=nil)then
if(type(tab[name])=="table")then
if(tab[name].value~=nil)then
var = tab[name]:value()
end
end
end
if(var==nil)then var = tab["@"..name] end
if(var=="true")then
var = true
elseif(var=="false")then
var = false
elseif(tonumber(var)~=nil)then
var = tonumber(var)
end
return var
end,
numberFromString = function(str)
return load("return " .. str)()
end,
uuid = function()
local random = math.random
local function uuid()
local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
return string.gsub(template, '[xy]', function (c)
local v = (c == 'x') and random(0, 0xf) or random(8, 0xb)
return string.format('%x', v)
end)
end
return uuid()
end,
}

21
Basalt/loadObjects.lua Normal file
View File

@@ -0,0 +1,21 @@
local _OBJECTS = {}
if(packaged)then
for k,v in pairs(getProject("objects"))do
_OBJECTS[k] = v()
end
return _OBJECTS
end
local args = table.pack(...)
local dir = fs.getDir(args[2] or "Basalt")
if(dir==nil)then
error("Unable to find directory "..args[2].." please report this bug to our discord.")
end
for _,v in pairs(fs.list(fs.combine(dir, "objects")))do
if(v~="example.lua")then
local name = v:gsub(".lua", "")
_OBJECTS[name] = require(name)
end
end
return _OBJECTS

342
Basalt/main.lua Normal file
View File

@@ -0,0 +1,342 @@
local basaltEvent = require("basaltEvent")()
local Frame = require("Frame")
local theme = require("theme")
local utils = require("utils")
local uuid = utils.uuid
local createText = utils.createText
local baseTerm = term.current()
local version = 5
local debugger = true
local projectDirectory = fs.getDir(table.pack(...)[2] or "")
local activeKey, frames, monFrames, variables, schedules = {}, {}, {}, {}, {}
local mainFrame, activeFrame, focusedObject, updaterActive
if not term.isColor or not term.isColor() then
error('Basalt requires an advanced (golden) computer to run.', 0)
end
local function stop()
updaterActive = false
end
local setVariable = function(name, var)
variables[name] = var
end
local getVariable = function(name)
return variables[name]
end
local setTheme = function(_theme)
theme = _theme
end
local getTheme = function(name)
return theme[name]
end
local bInstance = {
getMainFrame = function()
return mainFrame
end,
setVariable = setVariable,
getVariable = getVariable,
getTheme = getTheme,
setMainFrame = function(mFrame)
mainFrame = mFrame
end,
getActiveFrame = function()
return activeFrame
end,
setActiveFrame = function(aFrame)
activeFrame = aFrame
end,
getFocusedObject = function()
return focusedObject
end,
setFocusedObject = function(focused)
focusedObject = focused
end,
getMonitorFrame = function(name)
return monFrames[name]
end,
setMonitorFrame = function(name, frame)
monFrames[name] = frame
end,
getBaseTerm = function()
return baseTerm
end,
stop = stop,
newFrame = Frame,
getDirectory = function()
return projectDirectory
end
}
local basaltError = function(errMsg)
baseTerm.clear()
baseTerm.setBackgroundColor(colors.black)
baseTerm.setTextColor(colors.red)
local w,h = baseTerm.getSize()
local splitString = function(str, sep)
if sep == nil then
sep = "%s"
end
local t={}
for v in string.gmatch(str, "([^"..sep.."]+)") do
table.insert(t, v)
end
return t
end
local words = splitString(errMsg, " ")
local line = "Basalt error: "
local yPos = 1
for n=1,#words do
baseTerm.setCursorPos(1,yPos)
if(#line+#words[n]<w)then
line = line.." "..words[n]
else
baseTerm.write(line)
line = words[n]
yPos = yPos + 1
end
if(n==#words)then
baseTerm.write(line)
end
end
baseTerm.setCursorPos(1,yPos+1)
end
local function handleSchedules(event, p1, p2, p3, p4)
if(#schedules>0)then
local finished = {}
for n=1,#schedules do
if(schedules[n]~=nil)then
if (coroutine.status(schedules[n]) == "suspended")then
local ok, result = coroutine.resume(schedules[n], event, p1, p2, p3, p4)
if not(ok)then
basaltError(result)
end
else
table.insert(finished, n)
end
end
end
for n=1,#finished do
table.remove(schedules, finished[n]-(n-1))
end
end
end
local function drawFrames()
if(updaterActive)then
if(mainFrame~=nil)then
mainFrame:draw()
mainFrame:drawUpdate()
end
for _,v in pairs(monFrames)do
v:draw()
v:drawUpdate()
end
end
end
local function basaltUpdateEvent(event, p1, p2, p3, p4)
if(basaltEvent:sendEvent("basaltEventCycle", event, p1, p2, p3, p4)==false)then return end
if(mainFrame~=nil)then
if (event == "mouse_click") then
mainFrame:mouseHandler(event, p1, p2, p3, p4)
activeFrame = mainFrame
elseif (event == "mouse_drag") then
mainFrame:mouseHandler(event, p1, p2, p3, p4)
activeFrame = mainFrame
elseif (event == "mouse_up") then
mainFrame:mouseHandler(event, p1, p2, p3, p4)
activeFrame = mainFrame
elseif (event == "mouse_scroll") then
mainFrame:mouseHandler(event, p1, p2, p3, p4)
activeFrame = mainFrame
elseif (event == "monitor_touch") then
if(monFrames[p1]~=nil)then
monFrames[p1]:mouseHandler(event, p1, p2, p3, p4)
activeFrame = monFrames[p1]
end
end
end
if(event == "key") or (event == "char") then
if(activeFrame~=nil)then
activeFrame:keyHandler(event, p1)
activeFrame:backgroundKeyHandler(event, p1)
end
end
if(event == "key")then
activeKey[p1] = true
end
if(event == "key_up")then
activeKey[p1] = false
end
for _, v in pairs(frames) do
v:eventHandler(event, p1, p2, p3, p4)
end
handleSchedules(event, p1, p2, p3, p4)
drawFrames()
end
local basalt = {}
basalt = {
setTheme = setTheme,
getTheme = getTheme,
getVersion = function()
return version
end,
setVariable = setVariable,
getVariable = getVariable,
setBaseTerm = function(_baseTerm)
baseTerm = _baseTerm
end,
autoUpdate = function(isActive)
local pCall = pcall
updaterActive = isActive
if(isActive==nil)then updaterActive = true end
drawFrames()
while updaterActive do
local event, p1, p2, p3, p4 = os.pullEventRaw()
local ok, err = pCall(basaltUpdateEvent, event, p1, p2, p3, p4)
if not(ok)then
basaltError(err)
return
end
end
end,
update = function(event, p1, p2, p3, p4)
if (event ~= nil) then
basaltUpdateEvent(event, p1, p2, p3, p4)
end
end,
stop = stop,
isKeyDown = function(key)
if(activeKey[key]==nil)then return false end
return activeKey[key];
end,
getFrame = function(name)
for _, value in pairs(frames) do
if (value.name == name) then
return value
end
end
end,
getActiveFrame = function()
return activeFrame
end,
setActiveFrame = function(frame)
if (frame:getType() == "Frame") then
activeFrame = frame
return true
end
return false
end,
onEvent = function(...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
basaltEvent:registerEvent("basaltEventCycle", v)
end
end
end,
schedule = function(f)
assert(f~="function", "Schedule needs a function in order to work!")
return function(...)
local co = coroutine.create(f)
local ok, result = coroutine.resume(co, ...)
if(ok)then
table.insert(schedules, co)
else
basaltError(result)
end
end
end,
createFrame = function(name)
name = name or uuid()
for _, v in pairs(frames) do
if (v.name == name) then
return nil
end
end
local newFrame = Frame(name,nil,nil,bInstance)
table.insert(frames, newFrame)
if(mainFrame==nil)and(newFrame:getName()~="basaltDebuggingFrame")then
newFrame:show()
end
return newFrame
end,
removeFrame = function(name)
frames[name] = nil
end,
setProjectDir = function(dir)
projectDirectory = dir
end,
debug = function(...)
local args = { ... }
if (mainFrame.name ~= "basaltDebuggingFrame") then
if (mainFrame ~= basalt.debugFrame) then
basalt.debugLabel:setParent(mainFrame)
end
end
local str = ""
for key, value in pairs(args) do
str = str .. tostring(value) .. (#args ~= key and ", " or "")
end
basalt.debugLabel:setText("[Debug] " .. str)
for k,v in pairs(createText(str, basalt.debugList:getWidth()))do
basalt.debugList:addItem(v)
end
if (basalt.debugList:getItemCount() > 50) then
basalt.debugList:removeItem(1)
end
basalt.debugList:setValue(basalt.debugList:getItem(basalt.debugList:getItemCount()))
if(basalt.debugList.getItemCount() > basalt.debugList:getHeight())then
basalt.debugList:setOffset(basalt.debugList:getItemCount() - basalt.debugList:getHeight())
end
basalt.debugLabel:show()
end,
}
basalt.debugFrame = basalt.createFrame("basaltDebuggingFrame"):showBar():setBackground(colors.lightGray):setBar("Debug", colors.black, colors.gray)
basalt.debugFrame:addButton("back"):setAnchor("topRight"):setSize(1, 1):setText("\22"):onClick(function() if(basalt.oldFrame~=nil)then basalt.oldFrame:show() end end):setBackground(colors.red):show()
basalt.debugList = basalt.debugFrame:addList("debugList"):setSize(basalt.debugFrame.width - 2, basalt.debugFrame.height - 3):setPosition(2, 3):setScrollable(true):show()
basalt.debugLabel = basalt.debugFrame:addLabel("debugLabel"):onClick(function() basalt.oldFrame = mainFrame basalt.debugFrame:show() end):setBackground(colors.black):setForeground(colors.white):setAnchor("bottomLeft"):ignoreOffset():setZIndex(20):show()
return basalt

View File

@@ -0,0 +1,432 @@
local xmlValue = require("utils").getValueFromXML
local basaltEvent = require("basaltEvent")
local floor = math.floor
local lerp = function(s, e, pct)
return s + (e - s) * pct
end
local linear = function (t)
return t
end
local flip = function (x)
return 1 - x
end
local easeIn = function (t)
return t * t * t
end
local easeOut = function(t)
return flip(easeIn(flip(t)))
end
local easeInOut = function(t)
return lerp(easeIn(t), easeOut(t), t)
end
local lerp = {
linear = linear,
lerp = lerp,
flip=flip,
easeIn=easeIn,
easeOut=easeOut,
easeInOut=easeInOut,
}
return function(name)
local object = {}
local objectType = "Animation"
local timerObj
local animations = {}
local animationTime = 0
local animationActive = false
local index = 1
local infinitePlay = false
local eventSystem = basaltEvent()
local nextWaitTimer = 0
local lastFunc
local loop=false
local autoDestroy = false
local mode = "easeOut"
local _OBJ
local function call(tab)
for k,v in pairs(tab)do
v(object, animations[index].t, index)
end
end
local function onPlay(self)
if(index==1)then self:animationStartHandler() end
if (animations[index] ~= nil) then
call(animations[index].f)
animationTime = animations[index].t
end
index = index + 1
if(animations[index]==nil)then
if(infinitePlay)then
index = 1
animationTime = 0
else
self:animationDoneHandler()
return
end
end
if (animations[index].t > 0) then
timerObj = os.startTimer(animations[index].t - animationTime)
else
onPlay(self)
end
end
local function addAnimationPart(time, f)
for n=1,#animations do
if(animations[n].t==time)then
table.insert(animations[n].f, f)
return
end
end
for n=1,#animations do
if(animations[n].t>time)then
if(animations[n-1]~=nil)then
if(animations[n-1].t<time)then
table.insert(animations, n-1, {t=time, f={f}})
return
end
else
table.insert(animations, n, {t=time, f={f}})
return
end
end
end
if(#animations<=0)then
table.insert(animations, 1, {t=time, f={f}})
return
elseif(animations[#animations].t<time)then
table.insert(animations, {t=time, f={f}})
end
end
local function predefinedLerp(v1,v2,d,t,get,set)
local x,y
addAnimationPart(t+0.05, function()
x,y = get(_OBJ)
end)
for n=0.05,d,0.05 do
addAnimationPart(t+n, function()
local _x = math.floor(lerp.lerp(x, v1, lerp[mode](n / d))+0.5)
local _y = math.floor(lerp.lerp(y, v2, lerp[mode](n / d))+0.5)
set(_OBJ, _x,_y)
end)
end
end;
object = {
name = name,
getType = function(self)
return objectType
end;
getBaseFrame = function(self)
if(self.parent~=nil)then
return self.parent:getBaseFrame()
end
return self
end;
setMode = function(self, newMode)
mode = newMode
return self
end,
generateXMLEventFunction = function(self, func, val)
local createF = function(str)
if(str:sub(1,1)=="#")then
local o = self:getBaseFrame():getDeepObject(str:sub(2,str:len()))
if(o~=nil)and(o.internalObjetCall~=nil)then
func(self,function()o:internalObjetCall()end)
end
else
func(self,self:getBaseFrame():getVariable(str))
end
end
if(type(val)=="string")then
createF(val)
elseif(type(val)=="table")then
for k,v in pairs(val)do
createF(v)
end
end
return self
end,
setValuesByXMLData = function(self, data)
loop = xmlValue("loop", data)==true and true or false
if(xmlValue("object", data)~=nil)then
local o = self:getBaseFrame():getDeepObject(xmlValue("object", data))
if(o==nil)then
o = self:getBaseFrame():getVariable(xmlValue("object", data))
end
if(o~=nil)then
self:setObject(o)
end
end
if(data["move"]~=nil)then
local x = xmlValue("x", data["move"])
local y = xmlValue("y", data["move"])
local duration = xmlValue("duration", data["move"])
local time = xmlValue("time", data["move"])
self:move(x, y, duration, time)
end
if(data["size"]~=nil)then
local w = xmlValue("width", data["size"])
local h = xmlValue("height", data["size"])
local duration = xmlValue("duration", data["size"])
local time = xmlValue("time", data["size"])
self:size(w, h, duration, time)
end
if(data["offset"]~=nil)then
local x = xmlValue("x", data["offset"])
local y = xmlValue("y", data["offset"])
local duration = xmlValue("duration", data["offset"])
local time = xmlValue("time", data["offset"])
self:offset(x, y, duration, time)
end
if(data["textColor"]~=nil)then
local duration = xmlValue("duration", data["textColor"])
local timer = xmlValue("time", data["textColor"])
local t = {}
local tab = data["textColor"]["color"]
if(tab~=nil)then
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
table.insert(t, colors[v:value()])
end
end
if(duration~=nil)and(#t>0)then
self:changeTextColor(duration, timer or 0, table.unpack(t))
end
end
if(data["background"]~=nil)then
local duration = xmlValue("duration", data["background"])
local timer = xmlValue("time", data["background"])
local t = {}
local tab = data["background"]["color"]
if(tab~=nil)then
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
table.insert(t, colors[v:value()])
end
end
if(duration~=nil)and(#t>0)then
self:changeBackground(duration, timer or 0, table.unpack(t))
end
end
if(data["text"]~=nil)then
local duration = xmlValue("duration", data["text"])
local timer = xmlValue("time", data["text"])
local t = {}
local tab = data["text"]["text"]
if(tab~=nil)then
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
table.insert(t, v:value())
end
end
if(duration~=nil)and(#t>0)then
self:changeText(duration, timer or 0, table.unpack(t))
end
end
if(xmlValue("onDone", data)~=nil)then self:generateXMLEventFunction(self.onDone, xmlValue("onDone", data)) end
if(xmlValue("onStart", data)~=nil)then self:generateXMLEventFunction(self.onDone, xmlValue("onStart", data)) end
if(xmlValue("autoDestroy", data)~=nil)then
if(xmlValue("autoDestroy", data))then
autoDestroy = true
end
end
mode = xmlValue("mode", data) or mode
if(xmlValue("play", data)~=nil)then if(xmlValue("play", data))then self:play(loop) end end
return self
end,
getZIndex = function(self)
return 1
end;
getName = function(self)
return self.name
end;
setObject = function(self, obj)
_OBJ = obj
return self
end;
move = function(self, x, y, duration, timer, obj)
_OBJ = obj or _OBJ
predefinedLerp(x,y,duration,timer or 0,_OBJ.getPosition,_OBJ.setPosition)
return self
end,
offset = function(self, x, y, duration, timer, obj)
_OBJ = obj or _OBJ
predefinedLerp(x,y,duration,timer or 0,_OBJ.getOffset,_OBJ.setOffset)
return self
end,
size = function(self, w, h, duration, timer, obj)
_OBJ = obj or _OBJ
predefinedLerp(w,h,duration,timer or 0,_OBJ.getSize,_OBJ.setSize)
return self
end,
changeText = function(self, duration, timer, ...)
local text = {...}
timer = timer or 0
_OBJ = obj or _OBJ
for n=1,#text do
addAnimationPart(timer+n*(duration/#text), function()
_OBJ.setText(_OBJ, text[n])
end)
end
return self
end,
changeBackground = function(self, duration, timer, ...)
local colors = {...}
timer = timer or 0
_OBJ = obj or _OBJ
for n=1,#colors do
addAnimationPart(timer+n*(duration/#colors), function()
_OBJ.setBackground(_OBJ, colors[n])
end)
end
return self
end,
changeTextColor = function(self, duration, timer, ...)
local colors = {...}
timer = timer or 0
_OBJ = obj or _OBJ
for n=1,#colors do
addAnimationPart(timer+n*(duration/#colors), function()
_OBJ.setForeground(_OBJ, colors[n])
end)
end
return self
end,
add = function(self, func, wait)
lastFunc = func
addAnimationPart((wait or nextWaitTimer) + (animations[#animations]~=nil and animations[#animations].t or 0), func)
return self
end;
wait = function(self, wait)
nextWaitTimer = wait
return self
end;
rep = function(self, reps)
if(lastFunc~=nil)then
for n = 1, reps or 1 do
addAnimationPart((wait or nextWaitTimer) + (animations[#animations]~=nil and animations[#animations].t or 0), lastFunc)
end
end
return self
end;
onDone = function(self, f)
eventSystem:registerEvent("animation_done", f)
return self
end,
onStart = function(self, f)
eventSystem:registerEvent("animation_start", f)
return self
end,
setAutoDestroy = function(self, destroy)
autoDestroy = destroy~=nil and destroy or true
return self
end,
animationDoneHandler = function(self)
eventSystem:sendEvent("animation_done", self)
if(autoDestroy)then
self.parent:removeObject(self)
self = nil
end
end;
animationStartHandler = function(self)
eventSystem:sendEvent("animation_start", self)
end;
clear = function(self)
animations = {}
lastFunc = nil
nextWaitTimer = 0
index = 1
animationTime = 0
infinitePlay = false
return self
end;
play = function(self, infinite)
self:cancel()
animationActive = true
infinitePlay = infinite and true or false
index = 1
animationTime = 0
if (animations[index] ~= nil) then
if (animations[index].t > 0) then
timerObj = os.startTimer(animations[index].t)
else
onPlay()
end
else
self:animationDoneHandler()
end
return self
end;
cancel = function(self)
if(timerObj~=nil)then
os.cancelTimer(timerObj)
infinitePlay = false
end
animationActive = false
return self
end;
internalObjetCall = function(self)
self:play(loop)
end,
eventHandler = function(self, event, tObj)
if(animationActive)then
if (event == "timer") and (tObj == timerObj) then
if (animations[index] ~= nil) then
onPlay(self)
else
self:animationDoneHandler()
end
end
end
end;
}
object.__index = object
return object
end

70
Basalt/objects/Button.lua Normal file
View File

@@ -0,0 +1,70 @@
local Object = require("Object")
local utils = require("utils")
local xmlValue = utils.getValueFromXML
return function(name)
-- Button
local base = Object(name)
local objectType = "Button"
local textHorizontalAlign = "center"
local textVerticalAlign = "center"
base:setZIndex(5)
base:setValue("Button")
base.width = 12
base.height = 3
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("ButtonBG")
self.fgColor = self.parent:getTheme("ButtonText")
end,
getType = function(self)
return objectType
end;
setHorizontalAlign = function(self, pos)
textHorizontalAlign = pos
end;
setVerticalAlign = function(self, pos)
textVerticalAlign = pos
end;
setText = function(self, text)
base:setValue(text)
return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("text", data)~=nil)then self:setText(xmlValue("text", data)) end
if(xmlValue("horizontalAlign", data)~=nil)then textHorizontalAlign = xmlValue("horizontalAlign", data) end
if(xmlValue("verticalAlign", data)~=nil)then textVerticalAlign = xmlValue("verticalAlign", data) end
return self
end,
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
local verticalAlign = utils.getTextVerticalAlign(h, textVerticalAlign)
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor)
self.parent:drawTextBox(obx, oby, w, h, " ")
end
if(self.fgColor~=false)then self.parent:drawForegroundBox(obx, oby, w, h, self.fgColor) end
for n = 1, h do
if (n == verticalAlign) then
self.parent:setText(obx, oby + (n - 1), utils.getTextHorizontalAlign(self:getValue(), w, textHorizontalAlign))
end
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

View File

@@ -0,0 +1,71 @@
local Object = require("Object")
local utils = require("utils")
local xmlValue = utils.getValueFromXML
return function(name)
-- Checkbox
local base = Object(name)
local objectType = "Checkbox"
base:setZIndex(5)
base:setValue(false)
base.width = 1
base.height = 1
local object = {
symbol = "\42",
init = function(self)
self.bgColor = self.parent:getTheme("CheckboxBG")
self.fgColor = self.parent:getTheme("CheckboxText")
end,
getType = function(self)
return objectType
end;
mouseHandler = function(self, event, button, x, y)
if (base.mouseHandler(self, event, button, x, y)) then
if ((event == "mouse_click") and (button == 1)) or (event == "monitor_touch") then
if (self:getValue() ~= true) and (self:getValue() ~= false) then
self:setValue(false)
else
self:setValue(not self:getValue())
end
end
return true
end
return false
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("checked", data)~=nil)then if(xmlValue("checked", data))then self:setValue(true) else self:setValue(false) end end
return self
end,
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
local verticalAlign = utils.getTextVerticalAlign(h, "center")
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end
for n = 1, h do
if (n == verticalAlign) then
if (self:getValue() == true) then
self.parent:writeText(obx, oby + (n - 1), utils.getTextHorizontalAlign(self.symbol, w, "center"), self.bgColor, self.fgColor)
else
self.parent:writeText(obx, oby + (n - 1), utils.getTextHorizontalAlign(" ", w, "center"), self.bgColor, self.fgColor)
end
end
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

195
Basalt/objects/Dropdown.lua Normal file
View File

@@ -0,0 +1,195 @@
local Object = require("Object")
local utils = require("utils")
local xmlValue = require("utils").getValueFromXML
return function(name)
local base = Object(name)
local objectType = "Dropdown"
base.width = 12
base.height = 1
base:setZIndex(6)
local list = {}
local itemSelectedBG
local itemSelectedFG
local selectionColorActive = true
local align = "left"
local yOffset = 0
local dropdownW = 16
local dropdownH = 6
local closedSymbol = "\16"
local openedSymbol = "\31"
local isOpened = false
local object = {
getType = function(self)
return objectType
end;
init = function(self)
self.bgColor = self.parent:getTheme("DropdownBG")
self.fgColor = self.parent:getTheme("DropdownText")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
end,
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("selectionBG", data)~=nil)then itemSelectedBG = colors[xmlValue("selectionBG", data)] end
if(xmlValue("selectionFG", data)~=nil)then itemSelectedFG = colors[xmlValue("selectionFG", data)] end
if(xmlValue("dropdownWidth", data)~=nil)then dropdownW = xmlValue("dropdownWidth", data) end
if(xmlValue("dropdownHeight", data)~=nil)then dropdownH = xmlValue("dropdownHeight", data) end
if(xmlValue("offset", data)~=nil)then yOffset = xmlValue("offset", data) end
if(data["item"]~=nil)then
local tab = data["item"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
self:addItem(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
end
end
end,
setOffset = function(self, yOff)
yOffset = yOff
return self
end;
getOffset = function(self)
return yOffset
end;
addItem = function(self, text, bgCol, fgCol, ...)
table.insert(list, { text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } })
return self
end;
getAll = function(self)
return list
end;
removeItem = function(self, index)
table.remove(list, index)
return self
end;
getItem = function(self, index)
return list[index]
end;
getItemIndex = function(self)
local selected = self:getValue()
for key, value in pairs(list) do
if (value == selected) then
return key
end
end
end;
clear = function(self)
list = {}
self:setValue({})
return self
end;
getItemCount = function(self)
return #list
end;
editItem = function(self, index, text, bgCol, fgCol, ...)
table.remove(list, index)
table.insert(list, index, { text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } })
return self
end;
selectItem = function(self, index)
self:setValue(list[index] or {})
return self
end;
setSelectedItem = function(self, bgCol, fgCol, active)
itemSelectedBG = bgCol or self.bgColor
itemSelectedFG = fgCol or self.fgColor
selectionColorActive = active
return self
end;
setDropdownSize = function(self, width, height)
dropdownW, dropdownH = width, height
return self
end;
mouseHandler = function(self, event, button, x, y)
if (isOpened) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
if ((event == "mouse_click") and (button == 1)) or (event == "monitor_touch") then
if (#list > 0) then
for n = 1, dropdownH do
if (list[n + yOffset] ~= nil) then
if (obx <= x) and (obx + dropdownW > x) and (oby + n == y) then
self:setValue(list[n + yOffset])
return true
end
end
end
end
end
if (event == "mouse_scroll") then
yOffset = yOffset + button
if (yOffset < 0) then
yOffset = 0
end
if (button == 1) then
if (#list > dropdownH) then
if (yOffset > #list - dropdownH) then
yOffset = #list - dropdownH
end
else
yOffset = math.min(#list - 1, 0)
end
end
return true
end
self:setVisualChanged()
end
if (base.mouseHandler(self, event, button, x, y)) then
isOpened = true
else
isOpened = false
end
end;
draw = function(self)
if (base.draw(self)) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if (self.parent ~= nil) then
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end
local val = self:getValue()
local text = utils.getTextHorizontalAlign((val~=nil and val.text or ""), w, align):sub(1, w - 1) .. (isOpened and openedSymbol or closedSymbol)
self.parent:writeText(obx, oby, text, self.bgColor, self.fgColor)
if (isOpened) then
for n = 1, dropdownH do
if (list[n + yOffset] ~= nil) then
if (list[n + yOffset] == val) then
if (selectionColorActive) then
self.parent:writeText(obx, oby + n, utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align), itemSelectedBG, itemSelectedFG)
else
self.parent:writeText(obx, oby + n, utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol)
end
else
self.parent:writeText(obx, oby + n, utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol)
end
end
end
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

471
Basalt/objects/Graphic.lua Normal file
View File

@@ -0,0 +1,471 @@
local Object = require("Object")
local geometric = require("geometricPoints")
local tHex = require("tHex")
local xmlValue = require("utils").getValueFromXML
local sub,len,max,min = string.sub,string.len,math.max,math.min
return function(name)
-- Graphic
local base = Object(name)
local objectType = "Graphic"
base:setZIndex(2)
local graphicObjects = {}
local graphic = {}
local shrinkedGraphic = {}
local isGraphicShrinked = false
local xOffset, yOffset = 0, 0
local dragable = false
local xMouse,yMouse
local w, h = 40, 15
local canvasSizeChanged = false
local tColourLookup = {}
for n=1,16 do
tColourLookup[ string.byte( "0123456789abcdef",n,n ) ] = 2^(n-1)
end
local function stringToTable(str)
local t = {}
for i = 1, #str do
t[i] = str:sub(i, i)
end
return t
end
local function setBG(x, y, width, height, colorStr)
if (y >= 1) and (y <= height) then
if (x + len(colorStr) > 0) and (x <= width) then
local oldCache = graphic[y]
local newCache
local nEnd = x + #colorStr - 1
if (x < 1) then
colorStr = sub(colorStr, 1 - x + 1, width - x + 1)
elseif (nEnd > width) then
colorStr = sub(colorStr, 1, width - x + 1)
end
if (x > 1) then
newCache = sub(oldCache, 1, x - 1) .. colorStr
else
newCache = colorStr
end
if nEnd < width then
newCache = newCache .. sub(oldCache, nEnd + 1, width)
end
graphic[y] = newCache
end
end
end
local function redrawCanvasSize()
local w,h = w,h
if(isGraphicShrinked)then w = w*2 h = h*3 end
for y=1,h do
if(graphic[y]~=nil)then
if(w>graphic[y]:len())then
graphic[y] = graphic[y]..(tHex[base.bgColor]):rep(w-graphic[y]:len())
else
graphic[y] = graphic[y]:sub(1,w)
end
else
graphic[y] = (tHex[base.bgColor]):rep(w)
end
end
end
redrawCanvasSize()
local function shrink()
local function parseLine( tImageArg, sLine )
local tLine = {}
for x=1,sLine:len() do
tLine[x] = tColourLookup[ string.byte(sLine,x,x) ] or 0
end
table.insert( tImageArg, tLine )
end
function parseImage( sRawData )
if type( sRawData ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sRawData ) .. ")" )
end
local tImage = {}
for sLine in ( sRawData .. "\n" ):gmatch( "(.-)\n" ) do
parseLine( tImage, sLine )
end
return tImage
end
local rawImg = ""
for y=1,#graphic do
if(y==#graphic)then
rawImg = rawImg..graphic[y]
else
rawImg = rawImg..graphic[y].."\n"
end
end
local img = parseImage(rawImg)
-- shrinkSystem is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/
local relations = { [0] = { 8, 4, 3, 6, 5 }, { 4, 14, 8, 7 }, { 6, 10, 8, 7 }, { 9, 11, 8, 0 }, { 1, 14, 8, 0 }, { 13, 12, 8, 0 }, { 2, 10, 8, 0 }, { 15, 8, 10, 11, 12, 14 },
{ 0, 7, 1, 9, 2, 13 }, { 3, 11, 8, 7 }, { 2, 6, 7, 15 }, { 9, 3, 7, 15 }, { 13, 5, 7, 15 }, { 5, 12, 8, 7 }, { 1, 4, 7, 15 }, { 7, 10, 11, 12, 14 } }
local colourNum, exponents, colourChar = {}, {}, {}
for i = 0, 15 do
exponents[2 ^ i] = i
end
do
local hex = "0123456789abcdef"
for i = 1, 16 do
colourNum[hex:sub(i, i)] = i - 1
colourNum[i - 1] = hex:sub(i, i)
colourChar[hex:sub(i, i)] = 2 ^ (i - 1)
colourChar[2 ^ (i - 1)] = hex:sub(i, i)
local thisRel = relations[i - 1]
for i = 1, #thisRel do
thisRel[i] = 2 ^ thisRel[i]
end
end
end
local function getBestColourMatch(usage)
local lastCol = relations[exponents[usage[#usage][1]]]
for j = 1, #lastCol do
local thisRelation = lastCol[j]
for i = 1, #usage - 1 do
if usage[i][1] == thisRelation then
return i
end
end
end
return 1
end
local function colsToChar(pattern, totals)
if not totals then
local newPattern = {}
totals = {}
for i = 1, 6 do
local thisVal = pattern[i]
local thisTot = totals[thisVal]
totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal
end
pattern = newPattern
end
local usage = {}
for key, value in pairs(totals) do
usage[#usage + 1] = { key, value }
end
if #usage > 1 then
-- Reduce the chunk to two colours:
while #usage > 2 do
table.sort(usage, function(a, b)
return a[2] > b[2]
end)
local matchToInd, usageLen = getBestColourMatch(usage), #usage
local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1]
for i = 1, 6 do
if pattern[i] == matchFrom then
pattern[i] = matchTo
usage[matchToInd][2] = usage[matchToInd][2] + 1
end
end
usage[usageLen] = nil
end
-- Convert to character. Adapted from oli414's function:
-- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/
local data = 128
for i = 1, #pattern - 1 do
if pattern[i] ~= pattern[6] then
data = data + 2 ^ (i - 1)
end
end
return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]]
else
-- Solid colour character:
return "\128", colourChar[pattern[1]], colourChar[pattern[1]]
end
end
local results, width, height, bgCol = { {}, {}, {} }, 0, #img + #img % 3, base.bgColor or colors.black
for i = 1, #img do
if #img[i] > width then
width = #img[i]
end
end
for y = 0, height - 1, 3 do
local cRow, tRow, bRow, counter = {}, {}, {}, 1
for x = 0, width - 1, 2 do
-- Grab a 2x3 chunk:
local pattern, totals = {}, {}
for yy = 1, 3 do
for xx = 1, 2 do
pattern[#pattern + 1] = (img[y + yy] and img[y + yy][x + xx]) and (img[y + yy][x + xx] == 0 and bgCol or img[y + yy][x + xx]) or bgCol
totals[pattern[#pattern]] = totals[pattern[#pattern]] and (totals[pattern[#pattern]] + 1) or 1
end
end
cRow[counter], tRow[counter], bRow[counter] = colsToChar(pattern, totals)
counter = counter + 1
end
results[1][#results[1] + 1], results[2][#results[2] + 1], results[3][#results[3] + 1] = table.concat(cRow), table.concat(tRow), table.concat(bRow)
end
results.width, results.height = #results[1][1], #results[1]
shrinkedGraphic = results
end
local function redraw()
local w,h = w,h
if(isGraphicShrinked)then w = w*2 h = h*3 end
for k,v in pairs(graphicObjects)do
for a,b in pairs(v[1])do
setBG(b.x, b.y, w, h, v[2])
end
end
if(isGraphicShrinked)then
shrink()
end
end
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("GraphicBG")
end,
getType = function(self)
return objectType
end;
setSize = function(self, width, height, rel)
base.setSize(self, width, height, rel)
if not(canvasSizeChanged)then
w = width
h = height
redrawCanvasSize()
end
redraw()
return self
end,
setOffset = function(self, x, y)
xOffset = x or xOffset
yOffset = y or yOffset
return self
end,
setCanvasSize = function(self, width, height)
w,h = width,height
canvasSizeChanged = true
redrawCanvasSize()
return self
end,
clearCanvas = function(self)
graphicObjects = {}
graphic = {}
redrawCanvasSize()
end,
getOffset = function(self)
return xOffset,yOffset
end,
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("text", data)~=nil)then self:setText(xmlValue("text", data)) end
if(xmlValue("xOffset", data)~=nil)then self:setOffset(xmlValue("xOffset", data), yOffset) end
if(xmlValue("yOffset", data)~=nil)then self:setOffset(xOffset, xmlValue("yOffset", data)) end
if(xmlValue("wCanvas", data)~=nil)then w = xmlValue("wCanvas", data) end
if(xmlValue("hCanvas", data)~=nil)then h = xmlValue("hCanvas", data) end
if(xmlValue("shrink", data)~=nil)then if(xmlValue("shrink", data))then self:shrink() end end
if(xmlValue("dragable", data)~=nil)then if(xmlValue("dragable", data))then dragable = true end end
if(data["ellipse"]~=nil)then
local tab = data["ellipse"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local col = colors[xmlValue("color", v)]
local rad1 = xmlValue("radius", v)
local rad2 = xmlValue("radius2", v)
local x = xmlValue("x", v)
local y = xmlValue("y", v)
local filled = xmlValue("filled", v)
self:addEllipse(col, rad1, rad2, x, y, filled)
end
end
if(data["circle"]~=nil)then
local tab = data["circle"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local col = colors[xmlValue("color", v)]
local rad = tonumber(xmlValue("radius", v))
local x = tonumber(xmlValue("x", v))
local y = tonumber(xmlValue("y", v))
local filled = xmlValue("filled", v)
self:addCircle(col, rad, x, y, filled)
end
end
if(data["line"]~=nil)then
local tab = data["line"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local col = colors[xmlValue("color", v)]
local x = tonumber(xmlValue("x", v))
local x2 = tonumber(xmlValue("x2", v))
local y = tonumber(xmlValue("y", v))
local y2 = tonumber(xmlValue("y2", v))
self:addLine(col, x, y, x2, y2)
end
end
if(data["rectangle"]~=nil)then
local tab = data["rectangle"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local col = colors[xmlValue("color", v)]
local x = tonumber(xmlValue("x", v))
local x2 = tonumber(xmlValue("x2", v))
local y = tonumber(xmlValue("y", v))
local y2 = tonumber(xmlValue("y2", v))
local filled = xmlValue("filled", v)=="true" and true or false
self:addRectangle(col, x, y, x2, y2, filled)
end
end
if(data["triangle"]~=nil)then
local tab = data["triangle"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local col = colors[xmlValue("color", v)]
local x = tonumber(xmlValue("x", v))
local x2 = tonumber(xmlValue("x2", v))
local x3 = tonumber(xmlValue("x2", v))
local y = tonumber(xmlValue("y", v))
local y2 = tonumber(xmlValue("y2", v))
local y3 = tonumber(xmlValue("y3", v))
local filled = xmlValue("filled", v)
self:addTriangle(col, x, y, x2, y2, x3, y3, filled)
end
end
return self
end,
addCircle = function(self, color, rad, x, y, filled)
local col = tHex[color]
table.insert(graphicObjects, {geometric.circle(x or 1, y or 1, rad, filled), tHex[color]})
redraw()
return self
end;
addEllipse = function(self, color, rad, rad2, x, y, filled)
table.insert(graphicObjects, {geometric.ellipse(x or 1, y or 1, rad, rad2, filled), tHex[color]})
redraw()
return self
end;
addLine = function(self, color, x1, y1, x2, y2)
table.insert(graphicObjects, {geometric.line(x1 or 1, y1 or 1, x2 or 1, y2 or 1), tHex[color]})
redraw()
return self
end;
addTriangle = function(self, color, x1, y1, x2, y2, x3, y3, filled)
table.insert(graphicObjects, {geometric.triangle(x1 or 1, y1 or 1, x2 or 1, y2 or 1, x3 or 1, y3 or 1, filled), tHex[color]})
redraw()
return self
end;
addRectangle = function(self, color, x1, y1, x2, y2, filled)
table.insert(graphicObjects, {geometric.rectangle(x1 or 1, y1 or 1, x2 or 1, y2 or 1, filled), tHex[color]})
redraw()
return self
end;
shrink = function(self)
isGraphicShrinked = true
redrawCanvasSize()
shrink()
return self
end,
setDragable = function(self, drag)
dragable = drag == true and true or false
return self
end,
mouseHandler = function(self, event, button, x, y)
if(base.mouseHandler(self, event, button, x, y))then
if(dragable)then
if(event=="mouse_click")then
xMouse,yMouse = x,y
end
if(event=="mouse_drag")then
if(xMouse~=nil)and(yMouse~=nil)then
xOffset = max(min(xOffset+xMouse-x, w-self:getWidth()),0)
xMouse = x
yOffset = max(min(yOffset+yMouse-y, h-self:getHeight()),0)
yMouse = y
end
end
end
return true
end
return false
end,
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor)
end
if (isGraphicShrinked) then
-- this is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/
local t, tC, bC = shrinkedGraphic[1], shrinkedGraphic[2], shrinkedGraphic[3]
for i = 1, shrinkedGraphic.height do
local x, y = obx+xOffset, oby + i - 1 + yOffset
if(y>oby-1)and(y<=oby+h-1)and(x<=w+obx)then
local tI = t[i]
local xpos,substart,subend = max(x, obx), max(1 - x + 1, 1), min(w - (x-obx), w)
if type(tI) == "string" then
self.parent:setText(xpos, y, sub(tI, substart, subend))
self.parent:setFG(xpos, y, sub(tC[i], substart, subend))
self.parent:setBG(xpos, y, sub(bC[i], substart, subend))
elseif type(tI) == "table" then
self.parent:setText(xpos, y, sub(tI[2], substart, subend))
self.parent:setFG(xpos, y, sub(tC[i], substart, subend))
self.parent:setBG(xpos, y, sub(bC[i], substart, subend))
end
end
end
else
for i = 1, #graphic do
local x, y = obx+xOffset, oby + i - 1 + yOffset
if(y>oby-1)and(y<=oby+h-1)and(x<=w+obx)then
local xpos,substart,subend = max(x, obx), max(1 - x + 1, 1), min(w - (x-obx), w)
self.parent:setBG(xpos, y, sub(graphic[i],substart,subend))
end
end
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

201
Basalt/objects/Image.lua Normal file
View File

@@ -0,0 +1,201 @@
local Object = require("Object")
local xmlValue = require("utils").getValueFromXML
return function(name)
-- Image
local base = Object(name)
local objectType = "Image"
base:setZIndex(2)
local image
local shrinkedImage
local imageGotShrinked = false
local function shrink()
-- shrinkSystem is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/
local relations = { [0] = { 8, 4, 3, 6, 5 }, { 4, 14, 8, 7 }, { 6, 10, 8, 7 }, { 9, 11, 8, 0 }, { 1, 14, 8, 0 }, { 13, 12, 8, 0 }, { 2, 10, 8, 0 }, { 15, 8, 10, 11, 12, 14 },
{ 0, 7, 1, 9, 2, 13 }, { 3, 11, 8, 7 }, { 2, 6, 7, 15 }, { 9, 3, 7, 15 }, { 13, 5, 7, 15 }, { 5, 12, 8, 7 }, { 1, 4, 7, 15 }, { 7, 10, 11, 12, 14 } }
local colourNum, exponents, colourChar = {}, {}, {}
for i = 0, 15 do
exponents[2 ^ i] = i
end
do
local hex = "0123456789abcdef"
for i = 1, 16 do
colourNum[hex:sub(i, i)] = i - 1
colourNum[i - 1] = hex:sub(i, i)
colourChar[hex:sub(i, i)] = 2 ^ (i - 1)
colourChar[2 ^ (i - 1)] = hex:sub(i, i)
local thisRel = relations[i - 1]
for i = 1, #thisRel do
thisRel[i] = 2 ^ thisRel[i]
end
end
end
local function getBestColourMatch(usage)
local lastCol = relations[exponents[usage[#usage][1]]]
for j = 1, #lastCol do
local thisRelation = lastCol[j]
for i = 1, #usage - 1 do
if usage[i][1] == thisRelation then
return i
end
end
end
return 1
end
local function colsToChar(pattern, totals)
if not totals then
local newPattern = {}
totals = {}
for i = 1, 6 do
local thisVal = pattern[i]
local thisTot = totals[thisVal]
totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal
end
pattern = newPattern
end
local usage = {}
for key, value in pairs(totals) do
usage[#usage + 1] = { key, value }
end
if #usage > 1 then
-- Reduce the chunk to two colours:
while #usage > 2 do
table.sort(usage, function(a, b)
return a[2] > b[2]
end)
local matchToInd, usageLen = getBestColourMatch(usage), #usage
local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1]
for i = 1, 6 do
if pattern[i] == matchFrom then
pattern[i] = matchTo
usage[matchToInd][2] = usage[matchToInd][2] + 1
end
end
usage[usageLen] = nil
end
-- Convert to character. Adapted from oli414's function:
-- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/
local data = 128
for i = 1, #pattern - 1 do
if pattern[i] ~= pattern[6] then
data = data + 2 ^ (i - 1)
end
end
return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]]
else
-- Solid colour character:
return "\128", colourChar[pattern[1]], colourChar[pattern[1]]
end
end
local results, width, height, bgCol = { {}, {}, {} }, 0, #image + #image % 3, base.bgColor or colors.black
for i = 1, #image do
if #image[i] > width then
width = #image[i]
end
end
for y = 0, height - 1, 3 do
local cRow, tRow, bRow, counter = {}, {}, {}, 1
for x = 0, width - 1, 2 do
-- Grab a 2x3 chunk:
local pattern, totals = {}, {}
for yy = 1, 3 do
for xx = 1, 2 do
pattern[#pattern + 1] = (image[y + yy] and image[y + yy][x + xx]) and (image[y + yy][x + xx] == 0 and bgCol or image[y + yy][x + xx]) or bgCol
totals[pattern[#pattern]] = totals[pattern[#pattern]] and (totals[pattern[#pattern]] + 1) or 1
end
end
cRow[counter], tRow[counter], bRow[counter] = colsToChar(pattern, totals)
counter = counter + 1
end
results[1][#results[1] + 1], results[2][#results[2] + 1], results[3][#results[3] + 1] = table.concat(cRow), table.concat(tRow), table.concat(bRow)
end
results.width, results.height = #results[1][1], #results[1]
shrinkedImage = results
end
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("ImageBG")
end,
getType = function(self)
return objectType
end;
loadImage = function(self, path)
image = paintutils.loadImage(path)
imageGotShrinked = false
return self
end;
shrink = function(self)
shrink()
imageGotShrinked = true
return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("shrink", data)~=nil)then if(xmlValue("shrink", data))then self:shrink() end end
if(xmlValue("path", data)~=nil)then self:loadImage(xmlValue("path", data)) end
return self
end,
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
if (image ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if (imageGotShrinked) then
-- this is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/
local t, tC, bC = shrinkedImage[1], shrinkedImage[2], shrinkedImage[3]
for i = 1, shrinkedImage.height do
local tI = t[i]
if type(tI) == "string" then
self.parent:setText(obx, oby + i - 1, tI)
self.parent:setFG(obx, oby + i - 1, tC[i])
self.parent:setBG(obx, oby + i - 1, bC[i])
elseif type(tI) == "table" then
self.parent:setText(obx, oby + i - 1, tI[2])
self.parent:setFG(obx, oby + i - 1, tC[i])
self.parent:setBG(obx, oby + i - 1, bC[i])
end
end
else
for yPos = 1, math.min(#image, h) do
local line = image[yPos]
for xPos = 1, math.min(#line, w) do
if line[xPos] > 0 then
self.parent:drawBackgroundBox(obx + xPos - 1, oby + yPos - 1, 1, 1, line[xPos])
end
end
end
end
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

260
Basalt/objects/Input.lua Normal file
View File

@@ -0,0 +1,260 @@
local Object = require("Object")
local utils = require("utils")
local xmlValue = utils.getValueFromXML
return function(name)
-- Input
local base = Object(name)
local objectType = "Input"
local inputType = "text"
local inputLimit = 0
base:setZIndex(5)
base:setValue("")
base.width = 10
base.height = 1
local textX = 1
local wIndex = 1
local defaultText = ""
local defaultBGCol
local defaultFGCol
local showingText = defaultText
local internalValueChange = false
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("InputBG")
self.fgColor = self.parent:getTheme("InputFG")
end,
getType = function(self)
return objectType
end;
setInputType = function(self, iType)
if (iType == "password") or (iType == "number") or (iType == "text") then
inputType = iType
end
return self
end;
setDefaultText = function(self, text, fCol, bCol)
defaultText = text
defaultBGCol = bCol or defaultBGCol
defaultFGCol = fCol or defaultFGCol
if (self:isFocused()) then
showingText = ""
else
showingText = defaultText
end
return self
end;
getInputType = function(self)
return inputType
end;
setValue = function(self, val)
base.setValue(self, tostring(val))
if not (internalValueChange) then
textX = tostring(val):len() + 1
end
return self
end;
getValue = function(self)
local val = base.getValue(self)
return inputType == "number" and tonumber(val) or val
end;
setInputLimit = function(self, limit)
inputLimit = tonumber(limit) or inputLimit
return self
end;
getInputLimit = function(self)
return inputLimit
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
local dBG,dFG
if(xmlValue("defaultBG", data)~=nil)then dBG = xmlValue("defaultBG", data) end
if(xmlValue("defaultFG", data)~=nil)then dFG = xmlValue("defaultFG", data) end
if(xmlValue("default", data)~=nil)then self:setDefaultText(xmlValue("default", data), dFG~=nil and colors[dFG], dBG~=nil and colors[dBG]) end
if(xmlValue("limit", data)~=nil)then self:setInputLimit(xmlValue("limit", data)) end
if(xmlValue("type", data)~=nil)then self:setInputType(xmlValue("type", data)) end
return self
end,
getFocusHandler = function(self)
base.getFocusHandler(self)
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
showingText = ""
if (self.parent ~= nil) then
self.parent:setCursor(true, obx + textX - wIndex, oby+math.floor(self.height/2), self.fgColor)
end
end
end;
loseFocusHandler = function(self)
base.loseFocusHandler(self)
if (self.parent ~= nil) then
self.parent:setCursor(false)
showingText = defaultText
end
end;
keyHandler = function(self, event, key)
if (base.keyHandler(self, event, key)) then
local w,h = self:getSize()
internalValueChange = true
if (event == "key") then
if (key == keys.backspace) then
-- on backspace
local text = tostring(base.getValue())
if (textX > 1) then
self:setValue(text:sub(1, textX - 2) .. text:sub(textX, text:len()))
if (textX > 1) then
textX = textX - 1
end
if (wIndex > 1) then
if (textX < wIndex) then
wIndex = wIndex - 1
end
end
end
end
if (key == keys.enter) then
-- on enter
if (self.parent ~= nil) then
--self.parent:removeFocusedObject(self)
end
end
if (key == keys.right) then
-- right arrow
local tLength = tostring(base.getValue()):len()
textX = textX + 1
if (textX > tLength) then
textX = tLength + 1
end
if (textX < 1) then
textX = 1
end
if (textX < wIndex) or (textX >= w + wIndex) then
wIndex = textX - w + 1
end
if (wIndex < 1) then
wIndex = 1
end
end
if (key == keys.left) then
-- left arrow
textX = textX - 1
if (textX >= 1) then
if (textX < wIndex) or (textX >= w + wIndex) then
wIndex = textX
end
end
if (textX < 1) then
textX = 1
end
if (wIndex < 1) then
wIndex = 1
end
end
end
if (event == "char") then
local text = base.getValue()
if (text:len() < inputLimit or inputLimit <= 0) then
if (inputType == "number") then
local cache = text
if (key == ".") or (tonumber(key) ~= nil) then
self:setValue(text:sub(1, textX - 1) .. key .. text:sub(textX, text:len()))
textX = textX + 1
end
if (tonumber(base.getValue()) == nil) then
self:setValue(cache)
end
else
self:setValue(text:sub(1, textX - 1) .. key .. text:sub(textX, text:len()))
textX = textX + 1
end
if (textX >= w + wIndex) then
wIndex = wIndex + 1
end
end
end
local obx, oby = self:getAnchorPosition()
local val = tostring(base.getValue())
local cursorX = (textX <= val:len() and textX - 1 or val:len()) - (wIndex - 1)
if (cursorX > self.x + w - 1) then
cursorX = self.x + w - 1
end
if (self.parent ~= nil) then
self.parent:setCursor(true, obx + cursorX, oby+math.floor(h/2), self.fgColor)
end
internalValueChange = false
end
end;
mouseHandler = function(self, event, button, x, y)
if (base.mouseHandler(self, event, button, x, y)) then
if (event == "mouse_click") and (button == 1) then
end
return true
end
return false
end;
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
local verticalAlign = utils.getTextVerticalAlign(h, "center")
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end
for n = 1, h do
if (n == verticalAlign) then
local val = tostring(base.getValue())
local bCol = self.bgColor
local fCol = self.fgColor
local text
if (val:len() <= 0) then
text = showingText
bCol = defaultBGCol or bCol
fCol = defaultFGCol or fCol
end
text = showingText
if (val ~= "") then
text = val
end
text = text:sub(wIndex, w + wIndex - 1)
local space = w - text:len()
if (space < 0) then
space = 0
end
if (inputType == "password") and (val ~= "") then
text = string.rep("*", text:len())
end
text = text .. string.rep(" ", space)
self.parent:writeText(obx, oby + (n - 1), text, bCol, fCol)
end
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

138
Basalt/objects/Label.lua Normal file
View File

@@ -0,0 +1,138 @@
local Object = require("Object")
local utils = require("utils")
local xmlValue = utils.getValueFromXML
local createText = utils.createText
local tHex = require("tHex")
local bigFont = require("bigfont")
return function(name)
-- Label
local base = Object(name)
local objectType = "Label"
base:setZIndex(3)
local autoSize = true
base:setValue("Label")
base.width = 5
local textHorizontalAlign = "left"
local textVerticalAlign = "top"
local fontsize = 0
local fgColChanged,bgColChanged = false,false
local object = {
getType = function(self)
return objectType
end;
setText = function(self, text)
text = tostring(text)
base:setValue(text)
if (autoSize) then
self.width = text:len()
end
if not(fgColChanged)then self.fgColor = self.parent:getForeground() or colors.white end
if not(bgColChanged)then self.bgColor = self.parent:getBackground() or colors.black end
return self
end;
setBackground = function(self, col)
base.setBackground(self, col)
bgColChanged = true
return self
end,
setForeground = function(self, col)
base.setForeground(self, col)
fgColChanged = true
return self
end,
setTextAlign = function(self, hor, vert)
textHorizontalAlign = hor or textHorizontalAlign
textVerticalAlign = vert or textVerticalAlign
self:setVisualChanged()
return self
end;
setFontSize = function(self, size)
if(size>0)and(size<=4)then
fontsize = size-1 or 0
end
return self
end;
getFontSize = function(self)
return fontsize+1
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("text", data)~=nil)then self:setText(xmlValue("text", data)) end
if(xmlValue("verticalAlign", data)~=nil)then textVerticalAlign = xmlValue("verticalAlign", data) end
if(xmlValue("horizontalAlign", data)~=nil)then textHorizontalAlign = xmlValue("horizontalAlign", data) end
if(xmlValue("font", data)~=nil)then self:setFontSize(xmlValue("font", data)) end
return self
end,
setSize = function(self, width, height)
base.setSize(self, width, height)
autoSize = false
self:setVisualChanged()
return self
end;
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
local verticalAlign = utils.getTextVerticalAlign(h, textVerticalAlign)
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor)
self.parent:drawTextBox(obx, oby, w, h, " ") end
if(self.fgColor~=false)then self.parent:drawForegroundBox(obx, oby, w, h, self.fgColor) end
if(fontsize==0)then
if not(autoSize)then
local text = createText(self:getValue(), self:getWidth())
for k,v in pairs(text)do
self.parent:setText(obx, oby+k-1, v)
end
else
for n = 1, h do
if (n == verticalAlign) then
self.parent:setText(obx, oby + (n - 1), utils.getTextHorizontalAlign(self:getValue(), w, textHorizontalAlign))
end
end
end
else
local tData = bigFont(fontsize, self:getValue(), self.fgColor, self.bgColor or colors.black)
if(autoSize)then
self:setSize(#tData[1][1], #tData[1]-1)
end
for n = 1, h do
if (n == verticalAlign) then
local oX, oY = self.parent:getSize()
local cX, cY = #tData[1][1], #tData[1]
obx = obx or math.floor((oX - cX) / 2) + 1
oby = oby or math.floor((oY - cY) / 2) + 1
for i = 1, cY do
self.parent:setFG(obx, oby + i + n - 2, utils.getTextHorizontalAlign(tData[2][i], w, textHorizontalAlign))
self.parent:setBG(obx, oby + i + n - 2, utils.getTextHorizontalAlign(tData[3][i], w, textHorizontalAlign, tHex[self.bgColor or colors.black]))
self.parent:setText(obx, oby + i + n - 2, utils.getTextHorizontalAlign(tData[1][i], w, textHorizontalAlign))
end
end
end
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

187
Basalt/objects/List.lua Normal file
View File

@@ -0,0 +1,187 @@
local Object = require("Object")
local utils = require("utils")
local xmlValue = utils.getValueFromXML
return function(name)
local base = Object(name)
local objectType = "List"
base.width = 16
base.height = 6
base:setZIndex(5)
local list = {}
local itemSelectedBG
local itemSelectedFG
local selectionColorActive = true
local align = "left"
local yOffset = 0
local scrollable = true
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("ListBG")
self.fgColor = self.parent:getTheme("ListText")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
end,
getType = function(self)
return objectType
end;
addItem = function(self, text, bgCol, fgCol, ...)
table.insert(list, { text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } })
if (#list == 1) then
self:setValue(list[1])
end
return self
end;
setOffset = function(self, yOff)
yOffset = yOff
return self
end;
getOffset = function(self)
return yOffset
end;
removeItem = function(self, index)
table.remove(list, index)
return self
end;
getItem = function(self, index)
return list[index]
end;
getAll = function(self)
return list
end;
getItemIndex = function(self)
local selected = self:getValue()
for key, value in pairs(list) do
if (value == selected) then
return key
end
end
end;
clear = function(self)
list = {}
self:setValue({})
return self
end;
getItemCount = function(self)
return #list
end;
editItem = function(self, index, text, bgCol, fgCol, ...)
table.remove(list, index)
table.insert(list, index, { text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } })
return self
end;
selectItem = function(self, index)
self:setValue(list[index] or {})
return self
end;
setSelectedItem = function(self, bgCol, fgCol, active)
itemSelectedBG = bgCol or self.bgColor
itemSelectedFG = fgCol or self.fgColor
selectionColorActive = active
return self
end;
setScrollable = function(self, scroll)
scrollable = scroll
return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("selectionBG", data)~=nil)then itemSelectedBG = colors[xmlValue("selectionBG", data)] end
if(xmlValue("selectionFG", data)~=nil)then itemSelectedFG = colors[xmlValue("selectionFG", data)] end
if(xmlValue("scrollable", data)~=nil)then if(xmlValue("scrollable", data))then self:setScrollable(true) else self:setScrollable(false) end end
if(xmlValue("offset", data)~=nil)then yOffset = xmlValue("offset", data) end
if(data["item"]~=nil)then
local tab = data["item"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
self:addItem(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
end
end
return self
end,
mouseHandler = function(self, event, button, x, y)
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local w,h = self:getSize()
if (obx <= x) and (obx + w > x) and (oby <= y) and (oby + h > y) and (self:isVisible()) then
if (((event == "mouse_click") or (event == "mouse_drag"))and(button==1))or(event=="monitor_touch") then
if (#list > 0) then
for n = 1, h do
if (list[n + yOffset] ~= nil) then
if (obx <= x) and (obx + w > x) and (oby + n - 1 == y) then
self:setValue(list[n + yOffset])
self:getEventSystem():sendEvent("mouse_click", self, "mouse_click", 0, x, y, list[n + yOffset])
end
end
end
end
end
if (event == "mouse_scroll") and (scrollable) then
yOffset = yOffset + button
if (yOffset < 0) then
yOffset = 0
end
if (button >= 1) then
if (#list > h) then
if (yOffset > #list - h) then
yOffset = #list - h
end
if (yOffset >= #list) then
yOffset = #list - 1
end
else
yOffset = yOffset - 1
end
end
end
self:setVisualChanged()
return true
end
end;
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor)
end
for n = 1, h do
if (list[n + yOffset] ~= nil) then
if (list[n + yOffset] == self:getValue()) then
if (selectionColorActive) then
self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, w, align), itemSelectedBG, itemSelectedFG)
else
self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, w, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol)
end
else
self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, w, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol)
end
end
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

230
Basalt/objects/Menubar.lua Normal file
View File

@@ -0,0 +1,230 @@
local Object = require("Object")
local utils = require("utils")
local xmlValue = utils.getValueFromXML
local tHex = require("tHex")
return function(name)
local base = Object(name)
local objectType = "Menubar"
local object = {}
base.width = 30
base.height = 1
base:setZIndex(5)
local list = {}
local itemSelectedBG
local itemSelectedFG
local selectionColorActive = true
local align = "left"
local itemOffset = 0
local space = 1
local scrollable = false
local function maxScroll()
local mScroll = 0
local xPos = 0
local w = object:getWidth()
for n = 1, #list do
if (xPos + list[n].text:len() + space * 2 > w) then
if(xPos < w)then
mScroll = mScroll + (list[n].text:len() + space * 2-(w - xPos))
else
mScroll = mScroll + list[n].text:len() + space * 2
end
end
xPos = xPos + list[n].text:len() + space * 2
end
return mScroll
end
object = {
init = function(self)
self.bgColor = self.parent:getTheme("MenubarBG")
self.fgColor = self.parent:getTheme("MenubarText")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
end,
getType = function(self)
return objectType
end;
addItem = function(self, text, bgCol, fgCol, ...)
table.insert(list, { text = tostring(text), bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } })
if (#list == 1) then
self:setValue(list[1])
end
return self
end;
getAll = function(self)
return list
end;
getItemIndex = function(self)
local selected = self:getValue()
for key, value in pairs(list) do
if (value == selected) then
return key
end
end
end;
clear = function(self)
list = {}
self:setValue({})
return self
end;
setSpace = function(self, _space)
space = _space or space
return self
end;
setOffset = function(self, offset)
itemOffset = offset or 0
if (itemOffset < 0) then
itemOffset = 0
end
local mScroll = maxScroll()
if (itemOffset > mScroll) then
itemOffset = mScroll
end
return self
end;
getOffset = function(self)
return itemOffset
end;
setScrollable = function(self, scroll)
scrollable = scroll
if(scroll==nil)then scrollable = true end
return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("selectionBG", data)~=nil)then itemSelectedBG = colors[xmlValue("selectionBG", data)] end
if(xmlValue("selectionFG", data)~=nil)then itemSelectedFG = colors[xmlValue("selectionFG", data)] end
if(xmlValue("scrollable", data)~=nil)then if(xmlValue("scrollable", data))then self:setScrollable(true) else self:setScrollable(false) end end
if(xmlValue("offset", data)~=nil)then self:setOffset(xmlValue("offset", data)) end
if(xmlValue("space", data)~=nil)then space = xmlValue("space", data) end
if(data["item"]~=nil)then
local tab = data["item"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
self:addItem(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
end
end
return self
end,
removeItem = function(self, index)
table.remove(list, index)
return self
end;
getItem = function(self, index)
return list[index]
end;
getItemCount = function(self)
return #list
end;
editItem = function(self, index, text, bgCol, fgCol, ...)
table.remove(list, index)
table.insert(list, index, { text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } })
return self
end;
selectItem = function(self, index)
self:setValue(list[index] or {})
return self
end;
setSelectedItem = function(self, bgCol, fgCol, active)
itemSelectedBG = bgCol or self.bgColor
itemSelectedFG = fgCol or self.fgColor
selectionColorActive = active
return self
end;
mouseHandler = function(self, event, button, x, y)
if(base.mouseHandler(self, event, button, x, y))then
local objX, objY = self:getAbsolutePosition(self:getAnchorPosition())
local w,h = self:getSize()
if (objX <= x) and (objX + w > x) and (objY <= y) and (objY + h > y) and (self:isVisible()) then
if (self.parent ~= nil) then
self.parent:setFocusedObject(self)
end
if (event == "mouse_click") or (event == "monitor_touch") then
local xPos = 0
for n = 1, #list do
if (list[n] ~= nil) then
if (objX + xPos <= x + itemOffset) and (objX + xPos + list[n].text:len() + (space*2) > x + itemOffset) and (objY == y) then
self:setValue(list[n])
self:getEventSystem():sendEvent(event, self, event, 0, x, y, list[n])
end
xPos = xPos + list[n].text:len() + space * 2
end
end
end
if (event == "mouse_scroll") and (scrollable) then
itemOffset = itemOffset + button
if (itemOffset < 0) then
itemOffset = 0
end
local mScroll = maxScroll()
if (itemOffset > mScroll) then
itemOffset = mScroll
end
end
self:setVisualChanged(true)
return true
end
end
return false
end;
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor)
end
local text = ""
local textBGCol = ""
local textFGCol = ""
for _, v in pairs(list) do
local newItem = (" "):rep(space) .. v.text .. (" "):rep(space)
text = text .. newItem
if(v == self:getValue())then
textBGCol = textBGCol .. tHex[itemSelectedBG or v.bgCol or self.bgColor]:rep(newItem:len())
textFGCol = textFGCol .. tHex[itemSelectedFG or v.FgCol or self.fgColor]:rep(newItem:len())
else
textBGCol = textBGCol .. tHex[v.bgCol or self.bgColor]:rep(newItem:len())
textFGCol = textFGCol .. tHex[v.FgCol or self.fgColor]:rep(newItem:len())
end
end
self.parent:setText(obx, oby, text:sub(itemOffset+1, w+itemOffset))
self.parent:setBG(obx, oby, textBGCol:sub(itemOffset+1, w+itemOffset))
self.parent:setFG(obx, oby, textFGCol:sub(itemOffset+1, w+itemOffset))
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

32
Basalt/objects/Pane.lua Normal file
View File

@@ -0,0 +1,32 @@
local Object = require("Object")
return function(name)
-- Pane
local base = Object(name)
local objectType = "Pane"
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("PaneBG")
self.fgColor = self.parent:getTheme("PaneBG")
end,
getType = function(self)
return objectType
end;
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor)
self.parent:drawForegroundBox(obx, oby, w, h, self.fgColor)
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

665
Basalt/objects/Program.lua Normal file
View File

@@ -0,0 +1,665 @@
local Object = require("Object")
local tHex = require("tHex")
local process = require("process")
local xmlValue = require("utils").getValueFromXML
local sub = string.sub
return function(name, parent)
local base = Object(name)
local objectType = "Program"
base:setZIndex(5)
local object
local cachedPath
local function createBasaltWindow(x, y, width, height)
local xCursor, yCursor = 1, 1
local bgColor, fgColor = colors.black, colors.white
local cursorBlink = false
local visible = false
local cacheT = {}
local cacheBG = {}
local cacheFG = {}
local tPalette = {}
local emptySpaceLine
local emptyColorLines = {}
for i = 0, 15 do
local c = 2 ^ i
tPalette[c] = { parent:getBasaltInstance().getBaseTerm().getPaletteColour(c) }
end
local function createEmptyLines()
emptySpaceLine = (" "):rep(width)
for n = 0, 15 do
local nColor = 2 ^ n
local sHex = tHex[nColor]
emptyColorLines[nColor] = sHex:rep(width)
end
end
local function recreateWindowArray()
createEmptyLines()
local emptyText = emptySpaceLine
local emptyFG = emptyColorLines[colors.white]
local emptyBG = emptyColorLines[colors.black]
for n = 1, height do
cacheT[n] = sub(cacheT[n] == nil and emptyText or cacheT[n] .. emptyText:sub(1, width - cacheT[n]:len()), 1, width)
cacheFG[n] = sub(cacheFG[n] == nil and emptyFG or cacheFG[n] .. emptyFG:sub(1, width - cacheFG[n]:len()), 1, width)
cacheBG[n] = sub(cacheBG[n] == nil and emptyBG or cacheBG[n] .. emptyBG:sub(1, width - cacheBG[n]:len()), 1, width)
end
end
recreateWindowArray()
local function updateCursor()
if xCursor >= 1 and yCursor >= 1 and xCursor <= width and yCursor <= height then
--parentTerminal.setCursorPos(xCursor + x - 1, yCursor + y - 1)
else
--parentTerminal.setCursorPos(0, 0)
end
--parentTerminal.setTextColor(fgColor)
end
local function internalBlit(sText, sTextColor, sBackgroundColor)
-- copy pasti strikes again (cc: window.lua)
local nStart = xCursor
local nEnd = nStart + #sText - 1
if yCursor >= 1 and yCursor <= height then
if nStart <= width and nEnd >= 1 then
-- Modify line
if nStart == 1 and nEnd == width then
cacheT[yCursor] = sText
cacheFG[yCursor] = sTextColor
cacheBG[yCursor] = sBackgroundColor
else
local sClippedText, sClippedTextColor, sClippedBackgroundColor
if nStart < 1 then
local nClipStart = 1 - nStart + 1
local nClipEnd = width - nStart + 1
sClippedText = sub(sText, nClipStart, nClipEnd)
sClippedTextColor = sub(sTextColor, nClipStart, nClipEnd)
sClippedBackgroundColor = sub(sBackgroundColor, nClipStart, nClipEnd)
elseif nEnd > width then
local nClipEnd = width - nStart + 1
sClippedText = sub(sText, 1, nClipEnd)
sClippedTextColor = sub(sTextColor, 1, nClipEnd)
sClippedBackgroundColor = sub(sBackgroundColor, 1, nClipEnd)
else
sClippedText = sText
sClippedTextColor = sTextColor
sClippedBackgroundColor = sBackgroundColor
end
local sOldText = cacheT[yCursor]
local sOldTextColor = cacheFG[yCursor]
local sOldBackgroundColor = cacheBG[yCursor]
local sNewText, sNewTextColor, sNewBackgroundColor
if nStart > 1 then
local nOldEnd = nStart - 1
sNewText = sub(sOldText, 1, nOldEnd) .. sClippedText
sNewTextColor = sub(sOldTextColor, 1, nOldEnd) .. sClippedTextColor
sNewBackgroundColor = sub(sOldBackgroundColor, 1, nOldEnd) .. sClippedBackgroundColor
else
sNewText = sClippedText
sNewTextColor = sClippedTextColor
sNewBackgroundColor = sClippedBackgroundColor
end
if nEnd < width then
local nOldStart = nEnd + 1
sNewText = sNewText .. sub(sOldText, nOldStart, width)
sNewTextColor = sNewTextColor .. sub(sOldTextColor, nOldStart, width)
sNewBackgroundColor = sNewBackgroundColor .. sub(sOldBackgroundColor, nOldStart, width)
end
cacheT[yCursor] = sNewText
cacheFG[yCursor] = sNewTextColor
cacheBG[yCursor] = sNewBackgroundColor
end
end
xCursor = nEnd + 1
if (visible) then
updateCursor()
end
end
end
local function setText(_x, _y, text)
if (text ~= nil) then
local gText = cacheT[_y]
if (gText ~= nil) then
cacheT[_y] = sub(gText:sub(1, _x - 1) .. text .. gText:sub(_x + (text:len()), width), 1, width)
end
end
end
local function setBG(_x, _y, colorStr)
if (colorStr ~= nil) then
local gBG = cacheBG[_y]
if (gBG ~= nil) then
cacheBG[_y] = sub(gBG:sub(1, _x - 1) .. colorStr .. gBG:sub(_x + (colorStr:len()), width), 1, width)
end
end
end
local function setFG(_x, _y, colorStr)
if (colorStr ~= nil) then
local gFG = cacheFG[_y]
if (gFG ~= nil) then
cacheFG[_y] = sub(gFG:sub(1, _x - 1) .. colorStr .. gFG:sub(_x + (colorStr:len()), width), 1, width)
end
end
end
local setTextColor = function(color)
if type(color) ~= "number" then
error("bad argument #1 (expected number, got " .. type(color) .. ")", 2)
elseif tHex[color] == nil then
error("Invalid color (got " .. color .. ")", 2)
end
fgColor = color
end
local setBackgroundColor = function(color)
if type(color) ~= "number" then
error("bad argument #1 (expected number, got " .. type(color) .. ")", 2)
elseif tHex[color] == nil then
error("Invalid color (got " .. color .. ")", 2)
end
bgColor = color
end
local setPaletteColor = function(colour, r, g, b)
-- have to work on
if type(colour) ~= "number" then
error("bad argument #1 (expected number, got " .. type(colour) .. ")", 2)
end
if tHex[colour] == nil then
error("Invalid color (got " .. colour .. ")", 2)
end
local tCol
if type(r) == "number" and g == nil and b == nil then
tCol = { colours.rgb8(r) }
tPalette[colour] = tCol
else
if type(r) ~= "number" then
error("bad argument #2 (expected number, got " .. type(r) .. ")", 2)
end
if type(g) ~= "number" then
error("bad argument #3 (expected number, got " .. type(g) .. ")", 2)
end
if type(b) ~= "number" then
error("bad argument #4 (expected number, got " .. type(b) .. ")", 2)
end
tCol = tPalette[colour]
tCol[1] = r
tCol[2] = g
tCol[3] = b
end
end
local getPaletteColor = function(colour)
if type(colour) ~= "number" then
error("bad argument #1 (expected number, got " .. type(colour) .. ")", 2)
end
if tHex[colour] == nil then
error("Invalid color (got " .. colour .. ")", 2)
end
local tCol = tPalette[colour]
return tCol[1], tCol[2], tCol[3]
end
local basaltwindow = {
setCursorPos = function(_x, _y)
if type(_x) ~= "number" then
error("bad argument #1 (expected number, got " .. type(_x) .. ")", 2)
end
if type(_y) ~= "number" then
error("bad argument #2 (expected number, got " .. type(_y) .. ")", 2)
end
xCursor = math.floor(_x)
yCursor = math.floor(_y)
if (visible) then
updateCursor()
end
end;
getCursorPos = function()
return xCursor, yCursor
end;
setCursorBlink = function(blink)
if type(blink) ~= "boolean" then
error("bad argument #1 (expected boolean, got " .. type(blink) .. ")", 2)
end
cursorBlink = blink
end;
getCursorBlink = function()
return cursorBlink
end;
getPaletteColor = getPaletteColor,
getPaletteColour = getPaletteColor,
setBackgroundColor = setBackgroundColor,
setBackgroundColour = setBackgroundColor,
setTextColor = setTextColor,
setTextColour = setTextColor,
setPaletteColor = setPaletteColor,
setPaletteColour = setPaletteColor,
getBackgroundColor = function()
return bgColor
end;
getBackgroundColour = function()
return bgColor
end;
getSize = function()
return width, height
end;
getTextColor = function()
return fgColor
end;
getTextColour = function()
return fgColor
end;
basalt_resize = function(_width, _height)
width, height = _width, _height
recreateWindowArray()
end;
basalt_reposition = function(_x, _y)
x, y = _x, _y
end;
basalt_setVisible = function(vis)
visible = vis
end;
drawBackgroundBox = function(_x, _y, _width, _height, bgCol)
for n = 1, _height do
setBG(_x, _y + (n - 1), tHex[bgCol]:rep(_width))
end
end;
drawForegroundBox = function(_x, _y, _width, _height, fgCol)
for n = 1, _height do
setFG(_x, _y + (n - 1), tHex[fgCol]:rep(_width))
end
end;
drawTextBox = function(_x, _y, _width, _height, symbol)
for n = 1, _height do
setText(_x, _y + (n - 1), symbol:rep(_width))
end
end;
writeText = function(_x, _y, text, bgCol, fgCol)
bgCol = bgCol or bgColor
fgCol = fgCol or fgColor
setText(x, _y, text)
setBG(_x, _y, tHex[bgCol]:rep(text:len()))
setFG(_x, _y, tHex[fgCol]:rep(text:len()))
end;
basalt_update = function()
if (parent ~= nil) then
for n = 1, height do
parent:setText(x, y + (n - 1), cacheT[n])
parent:setBG(x, y + (n - 1), cacheBG[n])
parent:setFG(x, y + (n - 1), cacheFG[n])
end
end
end;
scroll = function(offset)
if type(offset) ~= "number" then
error("bad argument #1 (expected number, got " .. type(offset) .. ")", 2)
end
if offset ~= 0 then
local sEmptyText = emptySpaceLine
local sEmptyTextColor = emptyColorLines[fgColor]
local sEmptyBackgroundColor = emptyColorLines[bgColor]
for newY = 1, height do
local y = newY + offset
if y >= 1 and y <= height then
cacheT[newY] = cacheT[y]
cacheBG[newY] = cacheBG[y]
cacheFG[newY] = cacheFG[y]
else
cacheT[newY] = sEmptyText
cacheFG[newY] = sEmptyTextColor
cacheBG[newY] = sEmptyBackgroundColor
end
end
end
if (visible) then
updateCursor()
end
end;
isColor = function()
return parent:getBasaltInstance().getBaseTerm().isColor()
end;
isColour = function()
return parent:getBasaltInstance().getBaseTerm().isColor()
end;
write = function(text)
text = tostring(text)
if (visible) then
internalBlit(text, tHex[fgColor]:rep(text:len()), tHex[bgColor]:rep(text:len()))
end
end;
clearLine = function()
if (visible) then
setText(1, yCursor, (" "):rep(width))
setBG(1, yCursor, tHex[bgColor]:rep(width))
setFG(1, yCursor, tHex[fgColor]:rep(width))
end
if (visible) then
updateCursor()
end
end;
clear = function()
for n = 1, height do
setText(1, n, (" "):rep(width))
setBG(1, n, tHex[bgColor]:rep(width))
setFG(1, n, tHex[fgColor]:rep(width))
end
if (visible) then
updateCursor()
end
end;
blit = function(text, fgcol, bgcol)
if type(text) ~= "string" then
error("bad argument #1 (expected string, got " .. type(text) .. ")", 2)
end
if type(fgcol) ~= "string" then
error("bad argument #2 (expected string, got " .. type(fgcol) .. ")", 2)
end
if type(bgcol) ~= "string" then
error("bad argument #3 (expected string, got " .. type(bgcol) .. ")", 2)
end
if #fgcol ~= #text or #bgcol ~= #text then
error("Arguments must be the same length", 2)
end
if (visible) then
internalBlit(text, fgcol, bgcol)
end
end
}
return basaltwindow
end
base.width = 30
base.height = 12
local pWindow = createBasaltWindow(1, 1, base.width, base.height)
local curProcess
local paused = false
local queuedEvent = {}
object = {
init = function(self)
self.bgColor = self.parent:getTheme("ProgramBG")
end,
getType = function(self)
return objectType
end;
show = function(self)
base.show(self)
pWindow.setBackgroundColor(self.bgColor)
pWindow.setTextColor(self.fgColor)
pWindow.basalt_setVisible(true)
return self
end;
hide = function(self)
base.hide(self)
pWindow.basalt_setVisible(false)
return self
end;
setPosition = function(self, x, y, rel)
base.setPosition(self, x, y, rel)
pWindow.basalt_reposition(self:getAnchorPosition())
return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("path", data)~=nil)then cachedPath = xmlValue("path", data) end
if(xmlValue("execute", data)~=nil)then if(xmlValue("execute", data))then if(cachedPath~=nil)then self:execute(cachedPath) end end end
end,
getBasaltWindow = function()
return pWindow
end;
getBasaltProcess = function()
return curProcess
end;
setSize = function(self, width, height, rel)
base.setSize(self, width, height, rel)
pWindow.basalt_resize(self:getSize())
return self
end;
getStatus = function(self)
if (curProcess ~= nil) then
return curProcess:getStatus()
end
return "inactive"
end;
execute = function(self, path, ...)
cachedPath = path or cachedPath
curProcess = process:new(cachedPath, pWindow, ...)
pWindow.setBackgroundColor(colors.black)
pWindow.setTextColor(colors.white)
pWindow.clear()
pWindow.setCursorPos(1, 1)
pWindow.setBackgroundColor(self.bgColor)
pWindow.setTextColor(self.fgColor)
pWindow.basalt_setVisible(true)
curProcess:resume()
paused = false
return self
end;
stop = function(self)
if (curProcess ~= nil) then
if not (curProcess:isDead()) then
curProcess:resume("terminate")
if (curProcess:isDead()) then
if (self.parent ~= nil) then
self.parent:setCursor(false)
end
end
end
end
return self
end;
pause = function(self, p)
paused = p or (not paused)
if (curProcess ~= nil) then
if not (curProcess:isDead()) then
if not (paused) then
self:injectEvents(queuedEvent)
queuedEvent = {}
end
end
end
return self
end;
isPaused = function(self)
return paused
end;
injectEvent = function(self, event, p1, p2, p3, p4, ign)
if (curProcess ~= nil) then
if not (curProcess:isDead()) then
if (paused == false) or (ign) then
curProcess:resume(event, p1, p2, p3, p4)
else
table.insert(queuedEvent, { event = event, args = { p1, p2, p3, p4 } })
end
end
end
return self
end;
getQueuedEvents = function(self)
return queuedEvent
end;
updateQueuedEvents = function(self, events)
queuedEvent = events or queuedEvent
return self
end;
injectEvents = function(self, events)
if (curProcess ~= nil) then
if not (curProcess:isDead()) then
for _, value in pairs(events) do
curProcess:resume(value.event, table.unpack(value.args))
end
end
end
return self
end;
mouseHandler = function(self, event, button, x, y)
if (base.mouseHandler(self, event, button, x, y)) then
if (curProcess == nil) then
return false
end
if not (curProcess:isDead()) then
if not (paused) then
local absX, absY = self:getAbsolutePosition(self:getAnchorPosition(nil, nil, true))
curProcess:resume(event, button, x-absX+1, y-absY+1)
end
end
return true
end
end;
keyHandler = function(self, event, key)
base.keyHandler(self, event, key)
if (self:isFocused()) then
if (curProcess == nil) then
return false
end
if not (curProcess:isDead()) then
if not (paused) then
if (self.draw) then
curProcess:resume(event, key)
end
end
end
end
end;
getFocusHandler = function(self)
base.getFocusHandler(self)
if (curProcess ~= nil) then
if not (curProcess:isDead()) then
if not (paused) then
if (self.parent ~= nil) then
local xCur, yCur = pWindow.getCursorPos()
local obx, oby = self:getAnchorPosition()
if (self.parent ~= nil) then
local w,h = self:getSize()
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then
self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
end
end
end
end
end
end
end;
loseFocusHandler = function(self)
base.loseFocusHandler(self)
if (curProcess ~= nil) then
if not (curProcess:isDead()) then
if (self.parent ~= nil) then
self.parent:setCursor(false)
end
end
end
end;
eventHandler = function(self, event, p1, p2, p3, p4)
if (curProcess == nil) then
return
end
if not (curProcess:isDead()) then
if not (paused) then
if (event ~= "mouse_click") and (event ~= "monitor_touch") and (event ~= "mouse_up") and (event ~= "mouse_scroll") and (event ~= "mouse_drag") and (event ~= "key_up") and (event ~= "key") and (event ~= "char") and (event ~= "terminate") then
curProcess:resume(event, p1, p2, p3, p4)
end
if (self:isFocused()) then
local obx, oby = self:getAnchorPosition()
local xCur, yCur = pWindow.getCursorPos()
if (self.parent ~= nil) then
local w,h = self:getSize()
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then
self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
end
end
if (event == "terminate") and (self:isFocused()) then
self:stop()
end
end
else
if (event ~= "mouse_click") and (event ~= "monitor_touch") and (event ~= "mouse_up") and (event ~= "mouse_scroll") and (event ~= "mouse_drag") and (event ~= "key_up") and (event ~= "key") and (event ~= "char") and (event ~= "terminate") then
table.insert(queuedEvent, { event = event, args = { p1, p2, p3, p4 } })
end
end
end
end;
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
pWindow.basalt_reposition(obx, oby)
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor)
end
pWindow.basalt_update()
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

View File

@@ -0,0 +1,117 @@
local Object = require("Object")
local xmlValue = require("utils").getValueFromXML
return function(name)
-- Checkbox
local base = Object(name)
local objectType = "Progressbar"
local progress = 0
base:setZIndex(5)
base:setValue(false)
base.width = 25
base.height = 1
local activeBarColor
local activeBarSymbol = ""
local activeBarSymbolCol = colors.white
local bgBarSymbol = ""
local direction = 0
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("ProgressbarBG")
self.fgColor = self.parent:getTheme("ProgressbarText")
activeBarColor = self.parent:getTheme("ProgressbarActiveBG")
end,
getType = function(self)
return objectType
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("direction", data)~=nil)then direction = xmlValue("direction", data) end
if(xmlValue("progressColor", data)~=nil)then activeBarColor = colors[xmlValue("progressColor", data)] end
if(xmlValue("progressSymbol", data)~=nil)then activeBarSymbol = xmlValue("progressSymbol", data) end
if(xmlValue("backgroundSymbol", data)~=nil)then bgBarSymbol = xmlValue("backgroundSymbol", data) end
if(xmlValue("progressSymbolColor", data)~=nil)then activeBarSymbolCol = colors[xmlValue("progressSymbolColor", data)] end
if(xmlValue("onDone", data)~=nil)then self:generateXMLEventFunction(self.onProgressDone, xmlValue("onDone", data)) end
return self
end,
setDirection = function(self, dir)
direction = dir
return self
end;
setProgressBar = function(self, color, symbol, symbolcolor)
activeBarColor = color or activeBarColor
activeBarSymbol = symbol or activeBarSymbol
activeBarSymbolCol = symbolcolor or activeBarSymbolCol
return self
end;
setBackgroundSymbol = function(self, symbol)
bgBarSymbol = symbol:sub(1, 1)
return self
end;
setProgress = function(self, value)
if (value >= 0) and (value <= 100) and (progress ~= value) then
progress = value
self:setValue(progress)
if (progress == 100) then
self:progressDoneHandler()
end
end
return self
end;
getProgress = function(self)
return progress
end;
onProgressDone = function(self, f)
self:registerEvent("progress_done", f)
return self
end;
progressDoneHandler = function(self)
self:sendEvent("progress_done", self)
end;
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end
if(bgBarSymbol~="")then self.parent:drawTextBox(obx, oby, w, h, bgBarSymbol) end
if(self.fgColor~=false)then self.parent:drawForegroundBox(obx, oby, w, h, self.fgColor) end
if (direction == 1) then
self.parent:drawBackgroundBox(obx, oby, w, h / 100 * progress, activeBarColor)
self.parent:drawForegroundBox(obx, oby, w, h / 100 * progress, activeBarSymbolCol)
self.parent:drawTextBox(obx, oby, w, h / 100 * progress, activeBarSymbol)
elseif (direction == 2) then
self.parent:drawBackgroundBox(obx, oby + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarColor)
self.parent:drawForegroundBox(obx, oby + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbolCol)
self.parent:drawTextBox(obx, oby + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbol)
elseif (direction == 3) then
self.parent:drawBackgroundBox(obx + math.ceil(w - w / 100 * progress), oby, w / 100 * progress, h, activeBarColor)
self.parent:drawForegroundBox(obx + math.ceil(w - w / 100 * progress), oby, w / 100 * progress, h, activeBarSymbolCol)
self.parent:drawTextBox(obx + math.ceil(w - w / 100 * progress), oby, w / 100 * progress, h, activeBarSymbol)
else
self.parent:drawBackgroundBox(obx, oby, w / 100 * progress, h, activeBarColor)
self.parent:drawForegroundBox(obx, oby, w / 100 * progress, h, activeBarSymbolCol)
self.parent:drawTextBox(obx, oby, w / 100 * progress, h, activeBarSymbol)
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

163
Basalt/objects/Radio.lua Normal file
View File

@@ -0,0 +1,163 @@
local Object = require("Object")
local utils = require("utils")
local xmlValue = utils.getValueFromXML
return function(name)
local base = Object(name)
local objectType = "Radio"
base.width = 8
base:setZIndex(5)
local list = {}
local itemSelectedBG
local itemSelectedFG
local boxSelectedBG
local boxSelectedFG
local boxNotSelectedBG
local boxNotSelectedFG
local selectionColorActive = true
local symbol = "\7"
local align = "left"
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("MenubarBG")
self.fgColor = self.parent:getTheme("MenubarFG")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
boxSelectedBG = self.parent:getTheme("MenubarBG")
boxSelectedFG = self.parent:getTheme("MenubarText")
end,
getType = function(self)
return objectType
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("selectionBG", data)~=nil)then itemSelectedBG = colors[xmlValue("selectionBG", data)] end
if(xmlValue("selectionFG", data)~=nil)then itemSelectedFG = colors[xmlValue("selectionFG", data)] end
if(xmlValue("boxBG", data)~=nil)then boxSelectedBG = colors[xmlValue("boxBG", data)] end
if(xmlValue("inactiveBoxBG", data)~=nil)then boxNotSelectedBG = colors[xmlValue("inactiveBoxBG", data)] end
if(xmlValue("inactiveBoxFG", data)~=nil)then boxNotSelectedFG = colors[xmlValue("inactiveBoxFG", data)] end
if(xmlValue("boxFG", data)~=nil)then boxSelectedFG = colors[xmlValue("boxFG", data)] end
if(xmlValue("symbol", data)~=nil)then symbol = xmlValue("symbol", data) end
if(data["item"]~=nil)then
local tab = data["item"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
self:addItem(xmlValue("text", v), xmlValue("x", v), xmlValue("y", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
end
end
return self
end,
addItem = function(self, text, x, y, bgCol, fgCol, ...)
table.insert(list, { x = x or 1, y = y or 1, text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } })
if (#list == 1) then
self:setValue(list[1])
end
return self
end;
getAll = function(self)
return list
end;
removeItem = function(self, index)
table.remove(list, index)
return self
end;
getItem = function(self, index)
return list[index]
end;
getItemIndex = function(self)
local selected = self:getValue()
for key, value in pairs(list) do
if (value == selected) then
return key
end
end
end;
clear = function(self)
list = {}
self:setValue({})
return self
end;
getItemCount = function(self)
return #list
end;
editItem = function(self, index, text, x, y, bgCol, fgCol, ...)
table.remove(list, index)
table.insert(list, index, { x = x or 1, y = y or 1, text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } })
return self
end;
selectItem = function(self, index)
self:setValue(list[index] or {})
return self
end;
setActiveSymbol = function(self, sym)
symbol = sym:sub(1,1)
return self
end,
setSelectedItem = function(self, bgCol, fgCol, boxBG, boxFG, active)
itemSelectedBG = bgCol or itemSelectedBG
itemSelectedFG = fgCol or itemSelectedFG
boxSelectedBG = boxBG or boxSelectedBG
boxSelectedFG = boxFG or boxSelectedFG
selectionColorActive = active~=nil and active or true
return self
end;
mouseHandler = function(self, event, button, x, y)
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
if ((event == "mouse_click")and(button==1))or(event=="monitor_touch") then
if (#list > 0) then
for _, value in pairs(list) do
if (obx + value.x - 1 <= x) and (obx + value.x - 1 + value.text:len() + 2 >= x) and (oby + value.y - 1 == y) then
self:setValue(value)
if (self.parent ~= nil) then
self.parent:setFocusedObject(self)
end
self:getEventSystem():sendEvent(event, self, event, button, x, y)
self:setVisualChanged()
return true
end
end
end
end
return false
end;
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
for _, value in pairs(list) do
if (value == self:getValue()) then
if (align == "left") then
self.parent:writeText(value.x + obx - 1, value.y + oby - 1, symbol, boxSelectedBG, boxSelectedFG)
self.parent:writeText(value.x + 2 + obx - 1, value.y + oby - 1, value.text, itemSelectedBG, itemSelectedFG)
end
else
self.parent:drawBackgroundBox(value.x + obx - 1, value.y + oby - 1, 1, 1, boxNotSelectedBG or self.bgColor)
self.parent:writeText(value.x + 2 + obx - 1, value.y + oby - 1, value.text, value.bgCol, value.fgCol)
end
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

View File

@@ -0,0 +1,164 @@
local Object = require("Object")
local xmlValue = require("utils").getValueFromXML
return function(name)
local base = Object(name)
local objectType = "Scrollbar"
base.width = 1
base.height = 8
base:setValue(1)
base:setZIndex(2)
local barType = "vertical"
local symbol = " "
local symbolColor
local bgSymbol = "\127"
local maxValue = base.height
local index = 1
local symbolSize = 1
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("ScrollbarBG")
self.fgColor = self.parent:getTheme("ScrollbarText")
symbolColor = self.parent:getTheme("ScrollbarSymbolColor")
end,
getType = function(self)
return objectType
end;
setSymbol = function(self, _symbol)
symbol = _symbol:sub(1, 1)
self:setVisualChanged()
return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("maxValue", data)~=nil)then maxValue = xmlValue("maxValue", data) end
if(xmlValue("backgroundSymbol", data)~=nil)then bgSymbol = xmlValue("backgroundSymbol", data):sub(1,1) end
if(xmlValue("symbol", data)~=nil)then symbol = xmlValue("symbol", data):sub(1,1) end
if(xmlValue("barType", data)~=nil)then barType = xmlValue("barType", data):lower() end
if(xmlValue("symbolSize", data)~=nil)then self:setSymbolSize(xmlValue("symbolSize", data)) end
if(xmlValue("symbolColor", data)~=nil)then symbolColor = colors[xmlValue("symbolColor", data)] end
if(xmlValue("index", data)~=nil)then self:setIndex(xmlValue("index", data)) end
end,
setIndex = function(self, _index)
index = _index
if (index < 1) then
index = 1
end
local w,h = self:getSize()
index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1))
self:setValue(maxValue / (barType == "vertical" and h or w) * index)
return self
end,
getIndex = function(self)
return index
end,
setSymbolSize = function(self, size)
symbolSize = tonumber(size) or 1
local w,h = self:getSize()
if (barType == "vertical") then
self:setValue(index - 1 * (maxValue / (h - (symbolSize - 1))) - (maxValue / (h - (symbolSize - 1))))
elseif (barType == "horizontal") then
self:setValue(index - 1 * (maxValue / (w - (symbolSize - 1))) - (maxValue / (w - (symbolSize - 1))))
end
self:setVisualChanged()
return self
end;
setMaxValue = function(self, val)
maxValue = val
return self
end;
setBackgroundSymbol = function(self, _bgSymbol)
bgSymbol = string.sub(_bgSymbol, 1, 1)
self:setVisualChanged()
return self
end;
setSymbolColor = function(self, col)
symbolColor = col
self:setVisualChanged()
return self
end;
setBarType = function(self, _typ)
barType = _typ:lower()
return self
end;
mouseHandler = function(self, event, button, x, y)
if (base.mouseHandler(self, event, button, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local w,h = self:getSize()
if (((event == "mouse_click") or (event == "mouse_drag")) and (button == 1))or(event=="monitor_touch") then
if (barType == "horizontal") then
for _index = 0, w do
if (obx + _index == x) and (oby <= y) and (oby + h > y) then
index = math.min(_index + 1, w - (symbolSize - 1))
self:setValue(maxValue / w * (index))
self:setVisualChanged()
end
end
end
if (barType == "vertical") then
for _index = 0, h do
if (oby + _index == y) and (obx <= x) and (obx + w > x) then
index = math.min(_index + 1, h - (symbolSize - 1))
self:setValue(maxValue / h * (index))
self:setVisualChanged()
end
end
end
end
if (event == "mouse_scroll") then
index = index + button
if (index < 1) then
index = 1
end
index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1))
self:setValue(maxValue / (barType == "vertical" and h or w) * index)
end
return true
end
end;
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if (barType == "horizontal") then
self.parent:writeText(obx, oby, bgSymbol:rep(index - 1), self.bgColor, self.fgColor)
self.parent:writeText(obx + index - 1, oby, symbol:rep(symbolSize), symbolColor, symbolColor)
self.parent:writeText(obx + index + symbolSize - 1, oby, bgSymbol:rep(w - (index + symbolSize - 1)), self.bgColor, self.fgColor)
end
if (barType == "vertical") then
for n = 0, h - 1 do
if (index == n + 1) then
for curIndexOffset = 0, math.min(symbolSize - 1, h) do
self.parent:writeText(obx, oby + n + curIndexOffset, symbol, symbolColor, symbolColor)
end
else
if (n + 1 < index) or (n + 1 > index - 1 + symbolSize) then
self.parent:writeText(obx, oby + n, bgSymbol, self.bgColor, self.fgColor)
end
end
end
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

163
Basalt/objects/Slider.lua Normal file
View File

@@ -0,0 +1,163 @@
local Object = require("Object")
local xmlValue = require("utils").getValueFromXML
return function(name)
local base = Object(name)
local objectType = "Slider"
base.width = 8
base.height = 1
base:setValue(1)
local barType = "horizontal"
local symbol = " "
local symbolColor
local bgSymbol = "\140"
local maxValue = base.width
local index = 1
local symbolSize = 1
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("SliderBG")
self.fgColor = self.parent:getTheme("SliderText")
symbolColor = self.parent:getTheme("SliderSymbolColor")
end,
getType = function(self)
return objectType
end;
setSymbol = function(self, _symbol)
symbol = _symbol:sub(1, 1)
self:setVisualChanged()
return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("maxValue", data)~=nil)then maxValue = xmlValue("maxValue", data) end
if(xmlValue("backgroundSymbol", data)~=nil)then bgSymbol = xmlValue("backgroundSymbol", data):sub(1,1) end
if(xmlValue("barType", data)~=nil)then barType = xmlValue("barType", data):lower() end
if(xmlValue("symbol", data)~=nil)then symbol = xmlValue("symbol", data):sub(1,1) end
if(xmlValue("symbolSize", data)~=nil)then self:setSymbolSize(xmlValue("symbolSize", data)) end
if(xmlValue("symbolColor", data)~=nil)then symbolColor = colors[xmlValue("symbolColor", data)] end
if(xmlValue("index", data)~=nil)then self:setIndex(xmlValue("index", data)) end
end,
setIndex = function(self, _index)
index = _index
if (index < 1) then
index = 1
end
local w,h = self:getSize()
index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1))
self:setValue(maxValue / (barType == "vertical" and h or w) * index)
return self
end,
getIndex = function(self)
return index
end,
setSymbolSize = function(self, size)
symbolSize = tonumber(size) or 1
if (barType == "vertical") then
self:setValue(index - 1 * (maxValue / (h - (symbolSize - 1))) - (maxValue / (h - (symbolSize - 1))))
elseif (barType == "horizontal") then
self:setValue(index - 1 * (maxValue / (w - (symbolSize - 1))) - (maxValue / (w - (symbolSize - 1))))
end
self:setVisualChanged()
return self
end;
setMaxValue = function(self, val)
maxValue = val
return self
end;
setBackgroundSymbol = function(self, _bgSymbol)
bgSymbol = string.sub(_bgSymbol, 1, 1)
self:setVisualChanged()
return self
end;
setSymbolColor = function(self, col)
symbolColor = col
self:setVisualChanged()
return self
end;
setBarType = function(self, _typ)
barType = _typ:lower()
return self
end;
mouseHandler = function(self, event, button, x, y)
if (base.mouseHandler(self, event, button, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local w,h = self:getSize()
if (((event == "mouse_click") or (event == "mouse_drag")) and (button == 1))or(event=="monitor_touch") then
if (barType == "horizontal") then
for _index = 0, w do
if (obx + _index == x) and (oby <= y) and (oby + h > y) then
index = math.min(_index + 1, w - (symbolSize - 1))
self:setValue(maxValue / w * (index))
self:setVisualChanged()
end
end
end
if (barType == "vertical") then
for _index = 0, h do
if (oby + _index == y) and (obx <= x) and (obx + w > x) then
index = math.min(_index + 1, h - (symbolSize - 1))
self:setValue(maxValue / h * (index))
self:setVisualChanged()
end
end
end
end
if (event == "mouse_scroll") then
index = index + button
if (index < 1) then
index = 1
end
index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1))
self:setValue(maxValue / (barType == "vertical" and h or w) * index)
end
return true
end
end;
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if (barType == "horizontal") then
self.parent:writeText(obx, oby, bgSymbol:rep(index - 1), self.bgColor, self.fgColor)
self.parent:writeText(obx + index - 1, oby, symbol:rep(symbolSize), symbolColor, symbolColor)
self.parent:writeText(obx + index + symbolSize - 1, oby, bgSymbol:rep(w - (index + symbolSize - 1)), self.bgColor, self.fgColor)
end
if (barType == "vertical") then
for n = 0, h - 1 do
if (index == n + 1) then
for curIndexOffset = 0, math.min(symbolSize - 1, h) do
self.parent:writeText(obx, oby + n + curIndexOffset, symbol, symbolColor, symbolColor)
end
else
if (n + 1 < index) or (n + 1 > index - 1 + symbolSize) then
self.parent:writeText(obx, oby + n, bgSymbol, self.bgColor, self.fgColor)
end
end
end
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

87
Basalt/objects/Switch.lua Normal file
View File

@@ -0,0 +1,87 @@
local Object = require("Object")
local xmlValue = require("utils").getValueFromXML
return function(name)
local base = Object(name)
local objectType = "Switch"
base.width = 2
base.height = 1
base.bgColor = colors.lightGray
base.fgColor = colors.gray
base:setValue(false)
base:setZIndex(5)
local bgSymbol = colors.black
local inactiveBG = colors.red
local activeBG = colors.green
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("SwitchBG")
self.fgColor = self.parent:getTheme("SwitchText")
bgSymbol = self.parent:getTheme("SwitchBGSymbol")
inactiveBG = self.parent:getTheme("SwitchInactive")
activeBG = self.parent:getTheme("SwitchActive")
end,
getType = function(self)
return objectType
end;
setSymbolColor = function(self, symbolColor)
bgSymbol = symbolColor
self:setVisualChanged()
return self
end;
setActiveBackground = function(self, bgcol)
activeBG = bgcol
self:setVisualChanged()
return self
end;
setInactiveBackground = function(self, bgcol)
inactiveBG = bgcol
self:setVisualChanged()
return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("inactiveBG", data)~=nil)then inactiveBG = colors[xmlValue("inactiveBG", data)] end
if(xmlValue("activeBG", data)~=nil)then activeBG = colors[xmlValue("activeBG", data)] end
if(xmlValue("symbolColor", data)~=nil)then bgSymbol = colors[xmlValue("symbolColor", data)] end
end,
mouseHandler = function(self, event, button, x, y)
if (base.mouseHandler(self, event, button, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
if ((event == "mouse_click") and (button == 1))or(event=="monitor_touch") then
self:setValue(not self:getValue())
end
return true
end
end;
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor)
if(self:getValue())then
self.parent:drawBackgroundBox(obx, oby, 1, h, activeBG)
self.parent:drawBackgroundBox(obx+1, oby, 1, h, bgSymbol)
else
self.parent:drawBackgroundBox(obx, oby, 1, h, bgSymbol)
self.parent:drawBackgroundBox(obx+1, oby, 1, h, inactiveBG)
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

View File

@@ -0,0 +1,547 @@
local Object = require("Object")
local tHex = require("tHex")
local xmlValue = require("utils").getValueFromXML
return function(name)
local base = Object(name)
local objectType = "Textfield"
local hIndex, wIndex, textX, textY = 1, 1, 1, 1
local lines = { "" }
local bgLines = { "" }
local fgLines = { "" }
local keyWords = { }
local rules = { }
base.width = 30
base.height = 12
base:setZIndex(5)
local function stringGetPositions(str, word)
local pos = {}
if(str:len()>0)then
for w in string.gmatch(str, word)do
local s, e = string.find(str, w)
if(s~=nil)and(e~=nil)then
table.insert(pos,s)
table.insert(pos,e)
local startL = string.sub(str, 1, (s-1))
local endL = string.sub(str, e+1, str:len())
str = startL..(":"):rep(w:len())..endL
end
end
end
return pos
end
local function updateColors(self, l)
l = l or textY
local fgLine = tHex[self.fgColor]:rep(fgLines[l]:len())
local bgLine = tHex[self.bgColor]:rep(bgLines[l]:len())
for k,v in pairs(rules)do
local pos = stringGetPositions(lines[l], v[1])
if(#pos>0)then
for x=1,#pos/2 do
local xP = x*2 - 1
if(v[2]~=nil)then
fgLine = fgLine:sub(1, pos[xP]-1)..tHex[v[2]]:rep(pos[xP+1]-(pos[xP]-1))..fgLine:sub(pos[xP+1]+1, fgLine:len())
end
if(v[3]~=nil)then
bgLine = bgLine:sub(1, pos[xP]-1)..tHex[v[3]]:rep(pos[xP+1]-(pos[xP]-1))..bgLine:sub(pos[xP+1]+1, bgLine:len())
end
end
end
end
for k,v in pairs(keyWords)do
for _,b in pairs(v)do
local pos = stringGetPositions(lines[l], b)
if(#pos>0)then
for x=1,#pos/2 do
local xP = x*2 - 1
fgLine = fgLine:sub(1, pos[xP]-1)..tHex[k]:rep(pos[xP+1]-(pos[xP]-1))..fgLine:sub(pos[xP+1]+1, fgLine:len())
end
end
end
end
fgLines[l] = fgLine
bgLines[l] = bgLine
end
local function updateAllColors(self)
for n=1,#lines do
updateColors(self, n)
end
end
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("TextfieldBG")
self.fgColor = self.parent:getTheme("TextfieldText")
end,
getType = function(self)
return objectType
end;
setBackground = function(self, bg)
base.setBackground(self, bg)
updateAllColors(self)
return self
end,
setForeground = function(self, fg)
base.setForeground(self, fg)
updateAllColors(self)
return self
end,
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(data["lines"]~=nil)then
local l = data["lines"]["line"]
if(l.properties~=nil)then l = {l} end
for k,v in pairs(l)do
self:addLine(v:value())
end
end
if(data["keywords"]~=nil)then
for k,v in pairs(data["keywords"])do
if(colors[k]~=nil)then
local entry = v
if(entry.properties~=nil)then entry = {entry} end
local tab = {}
for a,b in pairs(entry)do
local keywordList = b["keyword"]
if(b["keyword"].properties~=nil)then keywordList = {b["keyword"]} end
for c,d in pairs(keywordList)do
table.insert(tab, d:value())
end
end
self:addKeywords(colors[k], tab)
end
end
end
if(data["rules"]~=nil)then
if(data["rules"]["rule"]~=nil)then
local tab = data["rules"]["rule"]
if(data["rules"]["rule"].properties~=nil)then tab = {data["rules"]["rule"]} end
for k,v in pairs(tab)do
if(xmlValue("pattern", v)~=nil)then
self:addRule(xmlValue("pattern", v), colors[xmlValue("fg", v)], colors[xmlValue("bg", v)])
end
end
end
end
end,
getLines = function(self)
return lines
end;
getLine = function(self, index)
return lines[index]
end;
editLine = function(self, index, text)
lines[index] = text or lines[index]
return self
end;
clear = function(self)
lines = {""}
bgLines = {""}
fgLines = {""}
hIndex, wIndex, textX, textY = 1, 1, 1, 1
return self
end,
addLine = function(self, text, index)
if(text~=nil)then
if(#lines==1)and(lines[1]=="")then
lines[1] = text
bgLines[1] = tHex[self.bgColor]:rep(text:len())
fgLines[1] = tHex[self.fgColor]:rep(text:len())
return self
end
if (index ~= nil) then
table.insert(lines, index, text)
table.insert(bgLines, index, tHex[self.bgColor]:rep(text:len()))
table.insert(fgLines, tHex[self.fgColor]:rep(text:len()))
else
table.insert(lines, text)
table.insert(bgLines, tHex[self.bgColor]:rep(text:len()))
table.insert(fgLines, tHex[self.fgColor]:rep(text:len()))
end
end
return self
end;
addKeywords = function(self, color, tab)
if(keyWords[color]==nil)then
keyWords[color] = {}
end
for k,v in pairs(tab)do
table.insert(keyWords[color], v)
end
return self
end;
addRule = function(self, rule, fg, bg)
table.insert(rules, {rule, fg, bg})
return self
end;
editRule = function(self, rule, fg, bg)
for k,v in pairs(rules)do
if(v[1]==rule)then
rules[k][2] = fg
rules[k][3] = bg
end
end
return self
end;
removeRule = function(self, rule)
for k,v in pairs(rules)do
if(v[1]==rule)then
table.remove(rules, k)
end
end
return self
end;
setKeywords = function(self, color, tab)
keyWords[color] = tab
return self
end;
removeLine = function(self, index)
table.remove(lines, index or #lines)
if (#lines <= 0) then
table.insert(lines, "")
end
return self
end;
getTextCursor = function(self)
return textX, textY
end;
getFocusHandler = function(self)
base.getFocusHandler(self)
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
if (self.parent ~= nil) then
self.parent:setCursor(true, obx + textX - wIndex, oby + textY - hIndex, self.fgColor)
end
end
end;
loseFocusHandler = function(self)
base.loseFocusHandler(self)
if (self.parent ~= nil) then
self.parent:setCursor(false)
end
end;
keyHandler = function(self, event, key)
if (base.keyHandler(self, event, key)) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if (event == "key") then
if (key == keys.backspace) then
-- on backspace
if (lines[textY] == "") then
if (textY > 1) then
table.remove(lines, textY)
table.remove(fgLines, textY)
table.remove(bgLines, textY)
textX = lines[textY - 1]:len() + 1
wIndex = textX - w + 1
if (wIndex < 1) then
wIndex = 1
end
textY = textY - 1
end
elseif (textX <= 1) then
if (textY > 1) then
textX = lines[textY - 1]:len() + 1
wIndex = textX - w + 1
if (wIndex < 1) then
wIndex = 1
end
lines[textY - 1] = lines[textY - 1] .. lines[textY]
fgLines[textY - 1] = fgLines[textY - 1] .. fgLines[textY]
bgLines[textY - 1] = bgLines[textY - 1] .. bgLines[textY]
table.remove(lines, textY)
table.remove(fgLines, textY)
table.remove(bgLines, textY)
textY = textY - 1
end
else
lines[textY] = lines[textY]:sub(1, textX - 2) .. lines[textY]:sub(textX, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 2) .. fgLines[textY]:sub(textX, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 2) .. bgLines[textY]:sub(textX, bgLines[textY]:len())
if (textX > 1) then
textX = textX - 1
end
if (wIndex > 1) then
if (textX < wIndex) then
wIndex = wIndex - 1
end
end
end
if (textY < hIndex) then
hIndex = hIndex - 1
end
updateColors(self)
self:setValue("")
end
if (key == keys.delete) then
-- on delete
if (textX > lines[textY]:len()) then
if (lines[textY + 1] ~= nil) then
lines[textY] = lines[textY] .. lines[textY + 1]
table.remove(lines, textY + 1)
table.remove(bgLines, textY + 1)
table.remove(fgLines, textY + 1)
end
else
lines[textY] = lines[textY]:sub(1, textX - 1) .. lines[textY]:sub(textX + 1, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. fgLines[textY]:sub(textX + 1, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. bgLines[textY]:sub(textX + 1, bgLines[textY]:len())
end
updateColors(self)
end
if (key == keys.enter) then
-- on enter
table.insert(lines, textY + 1, lines[textY]:sub(textX, lines[textY]:len()))
table.insert(fgLines, textY + 1, fgLines[textY]:sub(textX, fgLines[textY]:len()))
table.insert(bgLines, textY + 1, bgLines[textY]:sub(textX, bgLines[textY]:len()))
lines[textY] = lines[textY]:sub(1, textX - 1)
fgLines[textY] = fgLines[textY]:sub(1, textX - 1)
bgLines[textY] = bgLines[textY]:sub(1, textX - 1)
textY = textY + 1
textX = 1
wIndex = 1
if (textY - hIndex >= h) then
hIndex = hIndex + 1
end
self:setValue("")
end
if (key == keys.up) then
-- arrow up
if (textY > 1) then
textY = textY - 1
if (textX > lines[textY]:len() + 1) then
textX = lines[textY]:len() + 1
end
if (wIndex > 1) then
if (textX < wIndex) then
wIndex = textX - w + 1
if (wIndex < 1) then
wIndex = 1
end
end
end
if (hIndex > 1) then
if (textY < hIndex) then
hIndex = hIndex - 1
end
end
end
end
if (key == keys.down) then
-- arrow down
if (textY < #lines) then
textY = textY + 1
if (textX > lines[textY]:len() + 1) then
textX = lines[textY]:len() + 1
end
if (textY >= hIndex + h) then
hIndex = hIndex + 1
end
end
end
if (key == keys.right) then
-- arrow right
textX = textX + 1
if (textY < #lines) then
if (textX > lines[textY]:len() + 1) then
textX = 1
textY = textY + 1
end
elseif (textX > lines[textY]:len()) then
textX = lines[textY]:len() + 1
end
if (textX < 1) then
textX = 1
end
if (textX < wIndex) or (textX >= w + wIndex) then
wIndex = textX - w + 1
end
if (wIndex < 1) then
wIndex = 1
end
end
if (key == keys.left) then
-- arrow left
textX = textX - 1
if (textX >= 1) then
if (textX < wIndex) or (textX >= w + wIndex) then
wIndex = textX
end
end
if (textY > 1) then
if (textX < 1) then
textY = textY - 1
textX = lines[textY]:len() + 1
wIndex = textX - w + 1
end
end
if (textX < 1) then
textX = 1
end
if (wIndex < 1) then
wIndex = 1
end
end
end
if (event == "char") then
lines[textY] = lines[textY]:sub(1, textX - 1) .. key .. lines[textY]:sub(textX, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. tHex[self.fgColor] .. fgLines[textY]:sub(textX, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. tHex[self.bgColor] .. bgLines[textY]:sub(textX, bgLines[textY]:len())
textX = textX + 1
if (textX >= w + wIndex) then
wIndex = wIndex + 1
end
updateColors(self)
self:setValue("")
end
local cursorX = (textX <= lines[textY]:len() and textX - 1 or lines[textY]:len()) - (wIndex - 1)
if (cursorX > self.x + w - 1) then
cursorX = self.x + w - 1
end
local cursorY = (textY - hIndex < h and textY - hIndex or textY - hIndex - 1)
if (cursorX < 1) then
cursorX = 0
end
self.parent:setCursor(true, obx + cursorX, oby + cursorY, self.fgColor)
return true
end
end;
mouseHandler = function(self, event, button, x, y)
if (base.mouseHandler(self, event, button, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local anchx, anchy = self:getAnchorPosition()
local w,h = self:getSize()
if (event == "mouse_click")or(event=="monitor_touch") then
if (lines[y - oby + hIndex] ~= nil) then
textX = x - obx + wIndex
textY = y - oby + hIndex
if (textX > lines[textY]:len()) then
textX = lines[textY]:len() + 1
end
if (textX < wIndex) then
wIndex = textX - 1
if (wIndex < 1) then
wIndex = 1
end
end
if (self.parent ~= nil) then
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
end
end
end
if (event == "mouse_drag") then
if (lines[y - oby + hIndex] ~= nil) then
textX = x - obx + wIndex
textY = y - oby + hIndex
if (textX > lines[textY]:len()) then
textX = lines[textY]:len() + 1
end
if (textX < wIndex) then
wIndex = textX - 1
if (wIndex < 1) then
wIndex = 1
end
end
if (self.parent ~= nil) then
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
end
end
end
if (event == "mouse_scroll") then
hIndex = hIndex + button
if (hIndex > #lines - (h - 1)) then
hIndex = #lines - (h - 1)
end
if (hIndex < 1) then
hIndex = 1
end
if (self.parent ~= nil) then
if (obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (oby + textY - hIndex >= oby and oby + textY - hIndex < oby + h) then
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
else
self.parent:setCursor(false)
end
end
end
self:setVisualChanged()
return true
end
end;
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor)
end
if(self.fgColor~=false)then
self.parent:drawForegroundBox(obx, oby, w, h, self.fgColor)
end
for n = 1, h do
local text = ""
local bg = ""
local fg = ""
if (lines[n + hIndex - 1] ~= nil) then
text = lines[n + hIndex - 1]
fg = fgLines[n + hIndex - 1]
bg = bgLines[n + hIndex - 1]
end
text = text:sub(wIndex, w + wIndex - 1)
bg = bg:sub(wIndex, w + wIndex - 1)
fg = fg:sub(wIndex, w + wIndex - 1)
local space = w - text:len()
if (space < 0) then
space = 0
end
text = text .. string.rep(" ", space)
bg = bg .. string.rep(tHex[self.bgColor], space)
fg = fg .. string.rep(tHex[self.fgColor], space)
self.parent:setText(obx, oby + n - 1, text)
self.parent:setBG(obx, oby + n - 1, bg)
self.parent:setFG(obx, oby + n - 1, fg)
end
end
self:setVisualChanged(false)
end
end;
}
return setmetatable(object, base)
end

97
Basalt/objects/Thread.lua Normal file
View File

@@ -0,0 +1,97 @@
local xmlValue = require("utils").getValueFromXML
return function(name)
local object
local objectType = "Thread"
local func
local cRoutine
local isActive = false
local generateXMLEventFunction = function(self, str)
if(str:sub(1,1)=="#")then
local o = self:getBaseFrame():getDeepObject(str:sub(2,str:len()))
if(o~=nil)and(o.internalObjetCall~=nil)then
return (function()o:internalObjetCall()end)
end
else
return self:getBaseFrame():getVariable(str)
end
return self
end
object = {
name = name,
getType = function(self)
return objectType
end;
getZIndex = function(self)
return 1
end;
getName = function(self)
return self.name
end;
getBaseFrame = function(self)
if(self.parent~=nil)then
return self.parent:getBaseFrame()
end
return self
end;
setValuesByXMLData = function(self, data)
local f
if(xmlValue("thread", data)~=nil)then f = generateXMLEventFunction(self, xmlValue("thread", data)) end
if(xmlValue("start", data)~=nil)then if(xmlValue("start", data))and(f~=nil)then self:start(f) end end
return self
end,
start = function(self, f)
if (f == nil) then
error("Function provided to thread is nil")
end
func = f
cRoutine = coroutine.create(func)
isActive = true
local ok, result = coroutine.resume(cRoutine)
if not (ok) then
if (result ~= "Terminated") then
error("Thread Error Occurred - " .. result)
end
end
return self
end;
getStatus = function(self, f)
if (cRoutine ~= nil) then
return coroutine.status(cRoutine)
end
return nil
end;
stop = function(self, f)
isActive = false
return self
end;
eventHandler = function(self, event, p1, p2, p3)
if (isActive) then
if (coroutine.status(cRoutine) ~= "dead") then
local ok, result = coroutine.resume(cRoutine, event, p1, p2, p3)
if not (ok) then
if (result ~= "Terminated") then
error("Thread Error Occurred - " .. result)
end
end
else
isActive = false
end
end
end;
}
object.__index = object
return object
end

114
Basalt/objects/Timer.lua Normal file
View File

@@ -0,0 +1,114 @@
local basaltEvent = require("basaltEvent")
local xmlValue = require("utils").getValueFromXML
return function(name)
local objectType = "Timer"
local timer = 0
local savedRepeats = 0
local repeats = 0
local timerObj
local eventSystem = basaltEvent()
local timerIsActive = false
local generateXMLEventFunction = function(self, func, val)
local createF = function(str)
if(str:sub(1,1)=="#")then
local o = self:getBaseFrame():getDeepObject(str:sub(2,str:len()))
if(o~=nil)and(o.internalObjetCall~=nil)then
func(self,function()o:internalObjetCall()end)
end
else
func(self,self:getBaseFrame():getVariable(str))
end
end
if(type(val)=="string")then
createF(val)
elseif(type(val)=="table")then
for k,v in pairs(val)do
createF(v)
end
end
return self
end
local object = {
name = name,
getType = function(self)
return objectType
end;
setValuesByXMLData = function(self, data)
if(xmlValue("time", data)~=nil)then timer = xmlValue("time", data) end
if(xmlValue("repeat", data)~=nil)then savedRepeats = xmlValue("repeat", data) end
if(xmlValue("start", data)~=nil)then if(xmlValue("start", data))then self:start() end end
if(xmlValue("onCall", data)~=nil)then generateXMLEventFunction(self, self.onCall, xmlValue("onCall", data)) end
return self
end,
getBaseFrame = function(self)
if(self.parent~=nil)then
return self.parent:getBaseFrame()
end
return self
end;
getZIndex = function(self)
return 1
end;
getName = function(self)
return self.name
end;
setTime = function(self, _timer, _repeats)
timer = _timer or 0
savedRepeats = _repeats or 1
return self
end;
start = function(self)
if(timerIsActive)then
os.cancelTimer(timerObj)
end
repeats = savedRepeats
timerObj = os.startTimer(timer)
timerIsActive = true
return self
end;
isActive = function(self)
return timerIsActive
end;
cancel = function(self)
if (timerObj ~= nil) then
os.cancelTimer(timerObj)
end
timerIsActive = false
return self
end;
onCall = function(self, func)
eventSystem:registerEvent("timed_event", func)
return self
end;
eventHandler = function(self, event, tObj)
if event == "timer" and tObj == timerObj and timerIsActive then
eventSystem:sendEvent("timed_event", self)
if (repeats >= 1) then
repeats = repeats - 1
if (repeats >= 1) then
timerObj = os.startTimer(timer)
end
elseif (repeats == -1) then
timerObj = os.startTimer(timer)
end
end
end;
}
object.__index = object
return object
end

43
Basalt/theme.lua Normal file
View File

@@ -0,0 +1,43 @@
return { -- The default main theme for basalt!
BasaltBG = colors.lightGray,
BasaltText = colors.black,
FrameBG = colors.gray,
FrameText = colors.black,
ButtonBG = colors.gray,
ButtonText = colors.black,
CheckboxBG = colors.gray,
CheckboxText = colors.black,
InputBG = colors.gray,
InputText = colors.black,
TextfieldBG = colors.gray,
TextfieldText = colors.black,
ListBG = colors.gray,
ListText = colors.black,
MenubarBG = colors.gray,
MenubarText = colors.black,
DropdownBG = colors.gray,
DropdownText = colors.black,
RadioBG = colors.gray,
RadioText = colors.black,
SelectionBG = colors.black,
SelectionText = colors.lightGray,
GraphicBG = colors.black,
ImageBG = colors.black,
PaneBG = colors.black,
ProgramBG = colors.black,
ProgressbarBG = colors.gray,
ProgressbarText = colors.black,
ProgressbarActiveBG = colors.black,
ScrollbarBG = colors.lightGray,
ScrollbarText = colors.gray,
ScrollbarSymbolColor = colors.black,
SliderBG = colors.lightGray,
SliderText = colors.gray,
SliderSymbolColor = colors.black,
SwitchBG = colors.lightGray,
SwitchText = colors.gray,
SwitchBGSymbol = colors.black,
SwitchInactive = colors.red,
SwitchActive = colors.green,
}

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Robert Jelic
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1639
NyoUI.lua

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,39 @@
# NyoGUI
A GUI Framework for Computercraft
# Basalt - A UI Framework for CC:Tweaked
Basalt is still under developement and you may find bugs!
## Information
Check out the [wiki](https://basalt.madefor.cc/) for information<br>
If you have questions, feel free to join the discord server: [https://discord.gg/yM7kndJdJJ](https://discord.gg/yM7kndJdJJ)
## Changelogs
From now on we will add changes:
#### Version 4:
- You can now mirror a frame to a monitor by using :setMirror(side)
- with dynamic values you are able to use percentage values and even functions which get called everytime we need the size of that object
- XML got added to make design and logic seperate (you don't have to) - you are now able to use xml to create your UI design.
- Animations are now more advanced and provide many features to do cool stuff. They are also very easy to use now!
- Also some smaller bugfixes
- new bugs to explore
#### Version 3:
- fixed monitor support
- added :setIndex() for scrollbars
- added dynamic value system (not fully done)
#### Version 2:
Note: You won't get any changes for now, so don't redownload the project! (:
- reworked the filesystem, now we use require instead of loadfile
- from now on the single file will be complied on the end users computer
- prepared everything for an advanced installer
#### Version 1:
- created Basalt
- added many objects (buttons, checkbox, labels, programs, switch, radio, lists, dropdowns, input, textfields, images, menubar, animations, threads, timers, progressbar, scrollbar, slider, pane)
- added bigfont
- added blittle
- added coroutine management
- added advanced event system
WIP

1282
basaltPackageManager.lua Normal file

File diff suppressed because one or more lines are too long

504
basaltPackager.lua Normal file
View File

@@ -0,0 +1,504 @@
-- This file is able to minify and create a single file out of a project folder
-- only works for basalt
-- The minify part is fully made by stravant and can be found here: https://github.com/stravant/LuaMinify/blob/master/RobloxPlugin/Minify.lua
-- Thanks to him for his awesome work!
--
-- Minify.lua
--
-- A compilation of all of the neccesary code to Minify a source file, all into one single
-- script for usage on Roblox. Needed to deal with Roblox' lack of `require`.
--
--The minify part is also minified, if you're looking for the packaging part, check out the bottom!
function lookupify(cd)for dd,__a in pairs(cd)do cd[__a]=true end;return cd end
function CountTable(cd)local dd=0;for __a in pairs(cd)do dd=dd+1 end;return dd end
function PrintTable(cd,dd)if cd.Print then return cd.Print()end;dd=dd or 0
local __a=(CountTable(cd)>1)local a_a=string.rep(' ',dd+1)
local b_a="{".. (__a and'\n'or'')
for c_a,d_a in pairs(cd)do
if type(d_a)~='function'then
b_a=b_a.. (__a and a_a or'')
if type(c_a)=='number'then elseif type(c_a)=='string'and
c_a:match("^[A-Za-z_][A-Za-z0-9_]*$")then b_a=b_a..c_a.." = "elseif
type(c_a)=='string'then b_a=b_a.."[\""..c_a.."\"] = "else b_a=b_a.."["..
tostring(c_a).."] = "end
if type(d_a)=='string'then b_a=b_a.."\""..d_a.."\""elseif type(d_a)==
'number'then b_a=b_a..d_a elseif type(d_a)=='table'then b_a=b_a..
PrintTable(d_a,dd+ (__a and 1 or 0))else
b_a=b_a..tostring(d_a)end;if next(cd,c_a)then b_a=b_a..","end;if __a then b_a=b_a..'\n'end end end;b_a=b_a..
(__a and string.rep(' ',dd)or'').."}"return b_a end;local bb=lookupify{' ','\n','\t','\r'}
local cb={['\r']='\\r',['\n']='\\n',['\t']='\\t',['"']='\\"',["'"]="\\'"}
local db=lookupify{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}
local _c=lookupify{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}
local ac=lookupify{'0','1','2','3','4','5','6','7','8','9'}
local bc=lookupify{'0','1','2','3','4','5','6','7','8','9','A','a','B','b','C','c','D','d','E','e','F','f'}
local cc=lookupify{'+','-','*','/','^','%',',','{','}','[',']','(',')',';','#'}
local dc=lookupify{'and','break','do','else','elseif','end','false','for','function','goto','if','in','local','nil','not','or','repeat','return','then','true','until','while'}
function LexLua(cd)local dd={}
local __a,a_a=pcall(function()local _aa=1;local aaa=1;local baa=1
local function caa()local cba=cd:sub(_aa,_aa)if cba=='\n'then baa=1
aaa=aaa+1 else baa=baa+1 end;_aa=_aa+1;return cba end
local function daa(cba)cba=cba or 0;return cd:sub(_aa+cba,_aa+cba)end;local function _ba(cba)local dba=daa()
for i=1,#cba do if dba==cba:sub(i,i)then return caa()end end end;local function aba(cba)
return error(">> :"..aaa..":"..
baa..": "..cba,0)end
local function bba()local cba=_aa
if daa()=='['then local dba=0;while
daa(dba+1)=='='do dba=dba+1 end
if daa(dba+1)=='['then for _=0,dba+1 do caa()end
local _ca=_aa
while true do if daa()==''then
aba("Expected `]"..string.rep('=',dba).."]` near <eof>.",3)end;local cca=true;if daa()==']'then for i=1,dba do if daa(i)~='='then
cca=false end end
if daa(dba+1)~=']'then cca=false end else cca=false end;if cca then break else
caa()end end;local aca=cd:sub(_ca,_aa-1)for i=0,dba+1 do caa()end
local bca=cd:sub(cba,_aa-1)return aca,bca else return nil end else return nil end end
while true do local cba=''
while true do local dca=daa()
if bb[dca]then cba=cba..caa()elseif
dca=='-'and daa(1)=='-'then caa()caa()cba=cba..'--'local _da,ada=bba()
if ada then cba=cba..ada else while daa()~='\n'and
daa()~=''do cba=cba..caa()end end else break end end;local dba=aaa;local _ca=baa
local aca=":"..aaa..":"..baa..":> "local bca=daa()local cca=nil
if bca==''then cca={Type='Eof'}elseif
_c[bca]or db[bca]or bca=='_'then local dca=_aa;repeat caa()bca=daa()until not
(_c[bca]or db[bca]or ac[bca]or bca=='_')
local _da=cd:sub(dca,_aa-1)
if dc[_da]then cca={Type='Keyword',Data=_da}else cca={Type='Ident',Data=_da}end elseif ac[bca]or(daa()=='.'and ac[daa(1)])then local dca=_aa
if bca=='0'and
daa(1)=='x'then caa()caa()while bc[daa()]do caa()end;if _ba('Pp')then
_ba('+-')while ac[daa()]do caa()end end else
while ac[daa()]do caa()end;if _ba('.')then while ac[daa()]do caa()end end;if _ba('Ee')then
_ba('+-')while ac[daa()]do caa()end end end;cca={Type='Number',Data=cd:sub(dca,_aa-1)}elseif bca=='\''or bca==
'\"'then local dca=_aa;local _da=caa()local ada=_aa;while true do local dda=caa()
if dda=='\\'then caa()elseif
dda==_da then break elseif dda==''then aba("Unfinished string near <eof>")end end;local bda=cd:sub(ada,
_aa-2)local cda=cd:sub(dca,_aa-1)
cca={Type='String',Data=cda,Constant=bda}elseif bca=='['then local dca,_da=bba()
if _da then cca={Type='String',Data=_da,Constant=dca}else
caa()cca={Type='Symbol',Data='['}end elseif _ba('>=<')then if _ba('=')then cca={Type='Symbol',Data=bca..'='}else
cca={Type='Symbol',Data=bca}end elseif _ba('~')then
if _ba('=')then
cca={Type='Symbol',Data='~='}else aba("Unexpected symbol `~` in source.",2)end elseif _ba('.')then
if _ba('.')then if _ba('.')then cca={Type='Symbol',Data='...'}else
cca={Type='Symbol',Data='..'}end else cca={Type='Symbol',Data='.'}end elseif _ba(':')then if _ba(':')then cca={Type='Symbol',Data='::'}else
cca={Type='Symbol',Data=':'}end elseif cc[bca]then caa()
cca={Type='Symbol',Data=bca}else local dca,_da=bba()if dca then cca={Type='String',Data=_da,Constant=dca}else
aba("Unexpected Symbol `"..
bca.."` in source.",2)end end;cca.LeadingWhite=cba;cca.Line=dba;cca.Char=_ca
cca.Print=function()
return"<".. (cca.Type..string.rep(' ',7 -#
cca.Type))..
" ".. (cca.Data or'').." >"end;dd[#dd+1]=cca;if cca.Type=='Eof'then break end end end)if not __a then return false,a_a end;local b_a={}local c_a={}local d_a=1
function b_a:Peek(_aa)_aa=_aa or 0;return dd[math.min(
#dd,d_a+_aa)]end
function b_a:Get()local _aa=dd[d_a]d_a=math.min(d_a+1,#dd)return _aa end;function b_a:Is(_aa)return b_a:Peek().Type==_aa end;function b_a:Save()c_a[
#c_a+1]=d_a end
function b_a:Commit()c_a[#c_a]=nil end;function b_a:Restore()d_a=c_a[#c_a]c_a[#c_a]=nil end
function b_a:ConsumeSymbol(_aa)
local aaa=self:Peek()
if aaa.Type=='Symbol'then if _aa then
if aaa.Data==_aa then self:Get()return true else return nil end else self:Get()return aaa end else return
nil end end
function b_a:ConsumeKeyword(_aa)local aaa=self:Peek()if
aaa.Type=='Keyword'and aaa.Data==_aa then self:Get()return true else return nil end end;function b_a:IsKeyword(_aa)local aaa=b_a:Peek()return
aaa.Type=='Keyword'and aaa.Data==_aa end
function b_a:IsSymbol(_aa)
local aaa=b_a:Peek()return aaa.Type=='Symbol'and aaa.Data==_aa end
function b_a:IsEof()return b_a:Peek().Type=='Eof'end;return true,b_a end
function ParseLua(cd)local dd,__a=LexLua(cd)if not dd then return false,__a end
local function a_a(ada)local bda=">> :"..
__a:Peek().Line..":"..__a:Peek().Char..": "..ada.."\n"local cda=0
for dda in
cd:gmatch("[^\n]*\n?")do if dda:sub(-1,-1)=='\n'then dda=dda:sub(1,-2)end;cda=
cda+1
if cda==__a:Peek().Line then bda=bda..">> `"..
dda:gsub('\t',' ').."`\n"for i=1,__a:Peek().Char
do local __b=dda:sub(i,i)
if __b=='\t'then bda=bda..' 'else bda=bda..' 'end end
bda=bda.." ^---"break end end;return bda end;local b_a=0;local c_a={}local d_a={'_','a','b','c','d'}
local function _aa(ada)local bda={}bda.Parent=ada
bda.LocalList={}bda.LocalMap={}
function bda:RenameVars()
for cda,dda in pairs(bda.LocalList)do local __b;b_a=0
repeat b_a=b_a+1;local a_b=b_a
__b=''while a_b>0 do local b_b=a_b%#d_a;a_b=(a_b-b_b)/#d_a
__b=__b..d_a[b_b+1]end until
not c_a[__b]and
not ada:GetLocal(__b)and not bda.LocalMap[__b]dda.Name=__b;bda.LocalMap[__b]=dda end end
function bda:GetLocal(cda)local dda=bda.LocalMap[cda]if dda then return dda end;if bda.Parent then
local __b=bda.Parent:GetLocal(cda)if __b then return __b end end;return nil end
function bda:CreateLocal(cda)local dda={}dda.Scope=bda;dda.Name=cda;dda.CanRename=true;bda.LocalList[#
bda.LocalList+1]=dda
bda.LocalMap[cda]=dda;return dda end;bda.Print=function()return"<Scope>"end;return bda end;local aaa;local baa
local function caa(ada)local bda=_aa(ada)if not __a:ConsumeSymbol('(')then return false,
a_a("`(` expected.")end;local cda={}local dda=false
while not
__a:ConsumeSymbol(')')do
if __a:Is('Ident')then
local c_b=bda:CreateLocal(__a:Get().Data)cda[#cda+1]=c_b;if not __a:ConsumeSymbol(',')then
if
__a:ConsumeSymbol(')')then break else return false,a_a("`)` expected.")end end elseif
__a:ConsumeSymbol('...')then dda=true
if not __a:ConsumeSymbol(')')then return false,
a_a("`...` must be the last argument of a function.")end;break else return false,a_a("Argument name or `...` expected")end end;local __b,a_b=baa(bda)if not __b then return false,a_b end;if not
__a:ConsumeKeyword('end')then
return false,a_a("`end` expected after function body")end;local b_b={}
b_b.AstType='Function'b_b.Scope=bda;b_b.Arguments=cda;b_b.Body=a_b;b_b.VarArg=dda;return true,b_b end
local function daa(ada)
if __a:ConsumeSymbol('(')then local bda,cda=aaa(ada)
if not bda then return false,cda end
if not __a:ConsumeSymbol(')')then return false,a_a("`)` Expected.")end;cda.ParenCount=(cda.ParenCount or 0)+1;return true,cda elseif
__a:Is('Ident')then local bda=__a:Get()local cda=ada:GetLocal(bda.Data)if not cda then
c_a[bda.Data]=true end;local dda={}dda.AstType='VarExpr'dda.Name=bda.Data
dda.Local=cda;return true,dda else return false,a_a("primary expression expected")end end
local function _ba(ada,bda)local cda,dda=daa(ada)if not cda then return false,dda end
while true do
if __a:IsSymbol('.')or
__a:IsSymbol(':')then local __b=__a:Get().Data;if not __a:Is('Ident')then return false,
a_a("<Ident> expected.")end;local a_b=__a:Get()
local b_b={}b_b.AstType='MemberExpr'b_b.Base=dda;b_b.Indexer=__b;b_b.Ident=a_b;dda=b_b elseif not
bda and __a:ConsumeSymbol('[')then local __b,a_b=aaa(ada)if not __b then
return false,a_b end;if not __a:ConsumeSymbol(']')then
return false,a_a("`]` expected.")end;local b_b={}b_b.AstType='IndexExpr'
b_b.Base=dda;b_b.Index=a_b;dda=b_b elseif not bda and __a:ConsumeSymbol('(')then local __b={}
while not
__a:ConsumeSymbol(')')do local b_b,c_b=aaa(ada)if not b_b then return false,c_b end
__b[#__b+1]=c_b
if not __a:ConsumeSymbol(',')then if __a:ConsumeSymbol(')')then break else return false,
a_a("`)` Expected.")end end end;local a_b={}a_b.AstType='CallExpr'a_b.Base=dda;a_b.Arguments=__b;dda=a_b elseif not bda and
__a:Is('String')then local __b={}__b.AstType='StringCallExpr'__b.Base=dda
__b.Arguments={__a:Get()}dda=__b elseif not bda and __a:IsSymbol('{')then local __b,a_b=aaa(ada)if not __b then
return false,a_b end;local b_b={}b_b.AstType='TableCallExpr'b_b.Base=dda
b_b.Arguments={a_b}dda=b_b else break end end;return true,dda end
local function aba(ada)
if __a:Is('Number')then local bda={}bda.AstType='NumberExpr'bda.Value=__a:Get()return
true,bda elseif __a:Is('String')then local bda={}bda.AstType='StringExpr'
bda.Value=__a:Get()return true,bda elseif __a:ConsumeKeyword('nil')then local bda={}bda.AstType='NilExpr'
return true,bda elseif __a:IsKeyword('false')or __a:IsKeyword('true')then local bda={}
bda.AstType='BooleanExpr'bda.Value=(__a:Get().Data=='true')return true,bda elseif
__a:ConsumeSymbol('...')then local bda={}bda.AstType='DotsExpr'return true,bda elseif __a:ConsumeSymbol('{')then local bda={}
bda.AstType='ConstructorExpr'bda.EntryList={}
while true do
if __a:IsSymbol('[')then __a:Get()local cda,dda=aaa(ada)
if not cda then return
false,a_a("Key Expression Expected")end
if not __a:ConsumeSymbol(']')then return false,a_a("`]` Expected")end
if not __a:ConsumeSymbol('=')then return false,a_a("`=` Expected")end;local __b,a_b=aaa(ada)if not __b then
return false,a_a("Value Expression Expected")end
bda.EntryList[#bda.EntryList+1]={Type='Key',Key=dda,Value=a_b}elseif __a:Is('Ident')then local cda=__a:Peek(1)
if
cda.Type=='Symbol'and cda.Data=='='then local dda=__a:Get()if not __a:ConsumeSymbol('=')then
return false,a_a("`=` Expected")end;local __b,a_b=aaa(ada)if not __b then return false,
a_a("Value Expression Expected")end
bda.EntryList[
#bda.EntryList+1]={Type='KeyString',Key=dda.Data,Value=a_b}else local dda,__b=aaa(ada)
if not dda then return false,a_a("Value Exected")end
bda.EntryList[#bda.EntryList+1]={Type='Value',Value=__b}end elseif __a:ConsumeSymbol('}')then break else local cda,dda=aaa(ada)
bda.EntryList[#bda.EntryList+1]={Type='Value',Value=dda}if not cda then return false,a_a("Value Expected")end end
if __a:ConsumeSymbol(';')or __a:ConsumeSymbol(',')then elseif
__a:ConsumeSymbol('}')then break else return false,a_a("`}` or table entry Expected")end end;return true,bda elseif __a:ConsumeKeyword('function')then local bda,cda=caa(ada)if not bda then
return false,cda end;cda.IsLocal=true;return true,cda else return _ba(ada)end end;local bba=lookupify{'-','not','#'}local cba=8
local dba={['+']={6,6},['-']={6,6},['%']={7,7},['/']={7,7},['*']={7,7},['^']={10,9},['..']={5,4},['==']={3,3},['<']={3,3},['<=']={3,3},['~=']={3,3},['>']={3,3},['>=']={3,3},['and']={2,2},['or']={1,1}}
local function _ca(ada,bda)local cda,dda
if bba[__a:Peek().Data]then local __b=__a:Get().Data
cda,dda=_ca(ada,cba)if not cda then return false,dda end;local a_b={}a_b.AstType='UnopExpr'
a_b.Rhs=dda;a_b.Op=__b;dda=a_b else cda,dda=aba(ada)if not cda then return false,dda end end
while true do local __b=dba[__a:Peek().Data]
if __b and __b[1]>bda then
local a_b=__a:Get().Data;local b_b,c_b=_ca(ada,__b[2])if not b_b then return false,c_b end;local d_b={}
d_b.AstType='BinopExpr'd_b.Lhs=dda;d_b.Op=a_b;d_b.Rhs=c_b;dda=d_b else break end end;return true,dda end;aaa=function(ada)return _ca(ada,0)end
local function aca(ada)local bda=nil
if
__a:ConsumeKeyword('if')then local cda={}cda.AstType='IfStatement'cda.Clauses={}
repeat local dda,__b=aaa(ada)if not dda then
return false,__b end;if not __a:ConsumeKeyword('then')then return false,
a_a("`then` expected.")end
local a_b,b_b=baa(ada)if not a_b then return false,b_b end
cda.Clauses[#cda.Clauses+1]={Condition=__b,Body=b_b}until not __a:ConsumeKeyword('elseif')
if __a:ConsumeKeyword('else')then local dda,__b=baa(ada)
if not dda then return false,__b end;cda.Clauses[#cda.Clauses+1]={Body=__b}end;if not __a:ConsumeKeyword('end')then
return false,a_a("`end` expected.")end;bda=cda elseif __a:ConsumeKeyword('while')then
local cda={}cda.AstType='WhileStatement'local dda,__b=aaa(ada)
if not dda then return false,__b end;if not __a:ConsumeKeyword('do')then
return false,a_a("`do` expected.")end;local a_b,b_b=baa(ada)
if not a_b then return false,b_b end;if not __a:ConsumeKeyword('end')then
return false,a_a("`end` expected.")end;cda.Condition=__b;cda.Body=b_b;bda=cda elseif
__a:ConsumeKeyword('do')then local cda,dda=baa(ada)if not cda then return false,dda end
if not
__a:ConsumeKeyword('end')then return false,a_a("`end` expected.")end;local __b={}__b.AstType='DoStatement'__b.Body=dda;bda=__b elseif
__a:ConsumeKeyword('for')then
if not __a:Is('Ident')then return false,a_a("<ident> expected.")end;local cda=__a:Get()
if __a:ConsumeSymbol('=')then local dda=_aa(ada)
local __b=dda:CreateLocal(cda.Data)local a_b,b_b=aaa(ada)if not a_b then return false,b_b end
if not
__a:ConsumeSymbol(',')then return false,a_a("`,` Expected")end;local c_b,d_b=aaa(ada)if not c_b then return false,d_b end;local _ab,aab
if
__a:ConsumeSymbol(',')then _ab,aab=aaa(ada)if not _ab then return false,aab end end;if not __a:ConsumeKeyword('do')then
return false,a_a("`do` expected")end;local bab,cab=baa(dda)
if not bab then return false,cab end;if not __a:ConsumeKeyword('end')then
return false,a_a("`end` expected")end;local dab={}
dab.AstType='NumericForStatement'dab.Scope=dda;dab.Variable=__b;dab.Start=b_b;dab.End=d_b;dab.Step=aab
dab.Body=cab;bda=dab else local dda=_aa(ada)
local __b={dda:CreateLocal(cda.Data)}
while __a:ConsumeSymbol(',')do if not __a:Is('Ident')then return false,
a_a("for variable expected.")end
__b[#__b+1]=dda:CreateLocal(__a:Get().Data)end;if not __a:ConsumeKeyword('in')then
return false,a_a("`in` expected.")end;local a_b={}local b_b,c_b=aaa(ada)if not b_b then
return false,c_b end;a_b[#a_b+1]=c_b
while __a:ConsumeSymbol(',')do
local bab,cab=aaa(ada)if not bab then return false,cab end;a_b[#a_b+1]=cab end;if not __a:ConsumeKeyword('do')then
return false,a_a("`do` expected.")end;local d_b,_ab=baa(dda)
if not d_b then return false,_ab end;if not __a:ConsumeKeyword('end')then
return false,a_a("`end` expected.")end;local aab={}
aab.AstType='GenericForStatement'aab.Scope=dda;aab.VariableList=__b;aab.Generators=a_b;aab.Body=_ab;bda=aab end elseif __a:ConsumeKeyword('repeat')then local cda,dda=baa(ada)
if not cda then return false,dda end;if not __a:ConsumeKeyword('until')then
return false,a_a("`until` expected.")end;local __b,a_b=aaa(ada)
if not __b then return false,a_b end;local b_b={}b_b.AstType='RepeatStatement'b_b.Condition=a_b;b_b.Body=dda;bda=b_b elseif
__a:ConsumeKeyword('function')then if not __a:Is('Ident')then
return false,a_a("Function name expected")end;local cda,dda=_ba(ada,true)if not cda then
return false,dda end;local __b,a_b=caa(ada)if not __b then return false,a_b end
a_b.IsLocal=false;a_b.Name=dda;bda=a_b elseif __a:ConsumeKeyword('local')then
if __a:Is('Ident')then
local cda={__a:Get().Data}while __a:ConsumeSymbol(',')do if not __a:Is('Ident')then return false,
a_a("local var name expected")end
cda[#cda+1]=__a:Get().Data end;local dda={}if
__a:ConsumeSymbol('=')then
repeat local a_b,b_b=aaa(ada)if not a_b then return false,b_b end
dda[#dda+1]=b_b until not __a:ConsumeSymbol(',')end;for a_b,b_b in
pairs(cda)do cda[a_b]=ada:CreateLocal(b_b)end
local __b={}__b.AstType='LocalStatement'__b.LocalList=cda;__b.InitList=dda;bda=__b elseif
__a:ConsumeKeyword('function')then if not __a:Is('Ident')then
return false,a_a("Function name expected")end;local cda=__a:Get().Data
local dda=ada:CreateLocal(cda)local __b,a_b=caa(ada)if not __b then return false,a_b end;a_b.Name=dda
a_b.IsLocal=true;bda=a_b else
return false,a_a("local var or function def expected")end elseif __a:ConsumeSymbol('::')then if not __a:Is('Ident')then return false,
a_a('Label name expected')end
local cda=__a:Get().Data
if not __a:ConsumeSymbol('::')then return false,a_a("`::` expected")end;local dda={}dda.AstType='LabelStatement'dda.Label=cda;bda=dda elseif
__a:ConsumeKeyword('return')then local cda={}
if not __a:IsKeyword('end')then local __b,a_b=aaa(ada)
if __b then cda[1]=a_b;while
__a:ConsumeSymbol(',')do local b_b,c_b=aaa(ada)if not b_b then return false,c_b end
cda[#cda+1]=c_b end end end;local dda={}dda.AstType='ReturnStatement'dda.Arguments=cda;bda=dda elseif
__a:ConsumeKeyword('break')then local cda={}cda.AstType='BreakStatement'bda=cda elseif __a:IsKeyword('goto')then
if not
__a:Is('Ident')then return false,a_a("Label expected")end;local cda=__a:Get().Data;local dda={}dda.AstType='GotoStatement'
dda.Label=cda;bda=dda else local cda,dda=_ba(ada)if not cda then return false,dda end
if
__a:IsSymbol(',')or __a:IsSymbol('=')then
if(dda.ParenCount or 0)>0 then return false,
a_a("Can not assign to parenthesized expression, is not an lvalue")end;local __b={dda}
while __a:ConsumeSymbol(',')do local _ab,aab=_ba(ada)
if not _ab then return false,aab end;__b[#__b+1]=aab end
if not __a:ConsumeSymbol('=')then return false,a_a("`=` Expected.")end;local a_b={}local b_b,c_b=aaa(ada)if not b_b then return false,c_b end;a_b[1]=c_b;while
__a:ConsumeSymbol(',')do local _ab,aab=aaa(ada)if not _ab then return false,aab end
a_b[#a_b+1]=aab end;local d_b={}
d_b.AstType='AssignmentStatement'd_b.Lhs=__b;d_b.Rhs=a_b;bda=d_b elseif
dda.AstType=='CallExpr'or
dda.AstType=='TableCallExpr'or dda.AstType=='StringCallExpr'then local __b={}__b.AstType='CallStatement'__b.Expression=dda;bda=__b else return false,
a_a("Assignment Statement Expected")end end;bda.HasSemicolon=__a:ConsumeSymbol(';')return true,bda end
local bca=lookupify{'end','else','elseif','until'}
baa=function(ada)local bda={}bda.Scope=_aa(ada)bda.AstType='Statlist'local cda={}
while not
bca[__a:Peek().Data]and not __a:IsEof()do
local dda,__b=aca(bda.Scope)if not dda then return false,__b end;cda[#cda+1]=__b end;bda.Body=cda;return true,bda end;local function cca()local ada=_aa()return baa(ada)end;local dca,_da=cca()
return dca,_da end
local _d=lookupify{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}
local ad=lookupify{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}
local bd=lookupify{'0','1','2','3','4','5','6','7','8','9'}
function Format_Mini(cd)local dd,__a;local a_a=0
local function b_a(d_a,_aa,aaa)
if a_a>150 then a_a=0;return d_a.."\n".._aa end;aaa=aaa or' 'local baa,caa=d_a:sub(-1,-1),_aa:sub(1,1)
if
ad[baa]or _d[baa]or baa=='_'then
if not
(ad[caa]or _d[caa]or caa=='_'or bd[caa])then return d_a.._aa elseif caa=='('then
return d_a..aaa.._aa else return d_a..aaa.._aa end elseif bd[baa]then
if caa=='('then return d_a.._aa else return d_a..aaa.._aa end elseif baa==''then return d_a.._aa else
if caa=='('then return d_a..aaa.._aa else return d_a.._aa end end end
__a=function(d_a)local _aa=string.rep('(',d_a.ParenCount or 0)
if
d_a.AstType=='VarExpr'then if d_a.Local then _aa=_aa..d_a.Local.Name else
_aa=_aa..d_a.Name end elseif d_a.AstType=='NumberExpr'then _aa=_aa..
d_a.Value.Data elseif d_a.AstType=='StringExpr'then
_aa=_aa..d_a.Value.Data elseif d_a.AstType=='BooleanExpr'then _aa=_aa..tostring(d_a.Value)elseif
d_a.AstType=='NilExpr'then _aa=b_a(_aa,"nil")elseif d_a.AstType=='BinopExpr'then
_aa=b_a(_aa,__a(d_a.Lhs))_aa=b_a(_aa,d_a.Op)_aa=b_a(_aa,__a(d_a.Rhs))elseif d_a.AstType==
'UnopExpr'then _aa=b_a(_aa,d_a.Op)
_aa=b_a(_aa,__a(d_a.Rhs))elseif d_a.AstType=='DotsExpr'then _aa=_aa.."..."elseif d_a.AstType=='CallExpr'then _aa=_aa..
__a(d_a.Base)_aa=_aa.."("for i=1,#d_a.Arguments do _aa=_aa..
__a(d_a.Arguments[i])
if i~=#d_a.Arguments then _aa=_aa..","end end;_aa=_aa..")"elseif d_a.AstType==
'TableCallExpr'then _aa=_aa..__a(d_a.Base)_aa=_aa..
__a(d_a.Arguments[1])elseif d_a.AstType=='StringCallExpr'then
_aa=_aa..__a(d_a.Base)_aa=_aa..d_a.Arguments[1].Data elseif
d_a.AstType=='IndexExpr'then
_aa=_aa..__a(d_a.Base).."["..__a(d_a.Index).."]"elseif d_a.AstType=='MemberExpr'then _aa=_aa..__a(d_a.Base)..
d_a.Indexer..d_a.Ident.Data elseif
d_a.AstType=='Function'then d_a.Scope:RenameVars()
_aa=_aa.."function("
if#d_a.Arguments>0 then for i=1,#d_a.Arguments do
_aa=_aa..d_a.Arguments[i].Name
if i~=#d_a.Arguments then _aa=_aa..","elseif d_a.VarArg then _aa=_aa..",..."end end elseif
d_a.VarArg then _aa=_aa.."..."end;_aa=_aa..")"_aa=b_a(_aa,dd(d_a.Body))
_aa=b_a(_aa,"end")elseif d_a.AstType=='ConstructorExpr'then _aa=_aa.."{"
for i=1,#d_a.EntryList do
local aaa=d_a.EntryList[i]
if aaa.Type=='Key'then _aa=_aa.."["..
__a(aaa.Key).."]="..__a(aaa.Value)elseif aaa.Type==
'Value'then _aa=_aa..__a(aaa.Value)elseif aaa.Type=='KeyString'then
_aa=_aa..
aaa.Key.."="..__a(aaa.Value)end;if i~=#d_a.EntryList then _aa=_aa..","end end;_aa=_aa.."}"end
_aa=_aa..string.rep(')',d_a.ParenCount or 0)a_a=a_a+#_aa;return _aa end
local c_a=function(d_a)local _aa=''
if d_a.AstType=='AssignmentStatement'then
for i=1,#d_a.Lhs do
_aa=_aa..__a(d_a.Lhs[i])if i~=#d_a.Lhs then _aa=_aa..","end end;if#d_a.Rhs>0 then _aa=_aa.."="
for i=1,#d_a.Rhs do
_aa=_aa..__a(d_a.Rhs[i])if i~=#d_a.Rhs then _aa=_aa..","end end end elseif
d_a.AstType=='CallStatement'then _aa=__a(d_a.Expression)elseif d_a.AstType=='LocalStatement'then
_aa=_aa.."local "
for i=1,#d_a.LocalList do _aa=_aa..d_a.LocalList[i].Name;if i~=#
d_a.LocalList then _aa=_aa..","end end
if#d_a.InitList>0 then _aa=_aa.."="for i=1,#d_a.InitList do _aa=_aa..
__a(d_a.InitList[i])
if i~=#d_a.InitList then _aa=_aa..","end end end elseif d_a.AstType=='IfStatement'then
_aa=b_a("if",__a(d_a.Clauses[1].Condition))_aa=b_a(_aa,"then")
_aa=b_a(_aa,dd(d_a.Clauses[1].Body))
for i=2,#d_a.Clauses do local aaa=d_a.Clauses[i]
if aaa.Condition then
_aa=b_a(_aa,"elseif")_aa=b_a(_aa,__a(aaa.Condition))
_aa=b_a(_aa,"then")else _aa=b_a(_aa,"else")end;_aa=b_a(_aa,dd(aaa.Body))end;_aa=b_a(_aa,"end")elseif d_a.AstType=='WhileStatement'then
_aa=b_a("while",__a(d_a.Condition))_aa=b_a(_aa,"do")_aa=b_a(_aa,dd(d_a.Body))
_aa=b_a(_aa,"end")elseif d_a.AstType=='DoStatement'then _aa=b_a(_aa,"do")
_aa=b_a(_aa,dd(d_a.Body))_aa=b_a(_aa,"end")elseif d_a.AstType=='ReturnStatement'then _aa="return"
for i=1,#d_a.Arguments
do _aa=b_a(_aa,__a(d_a.Arguments[i]))if i~=
#d_a.Arguments then _aa=_aa..","end end elseif d_a.AstType=='BreakStatement'then _aa="break"elseif d_a.AstType=='RepeatStatement'then
_aa="repeat"_aa=b_a(_aa,dd(d_a.Body))_aa=b_a(_aa,"until")
_aa=b_a(_aa,__a(d_a.Condition))elseif d_a.AstType=='Function'then d_a.Scope:RenameVars()if d_a.IsLocal then
_aa="local"end;_aa=b_a(_aa,"function ")if d_a.IsLocal then
_aa=_aa..d_a.Name.Name else _aa=_aa..__a(d_a.Name)end;_aa=
_aa.."("
if#d_a.Arguments>0 then
for i=1,#d_a.Arguments do _aa=_aa..
d_a.Arguments[i].Name;if i~=#d_a.Arguments then _aa=_aa..","elseif d_a.VarArg then
_aa=_aa..",..."end end elseif d_a.VarArg then _aa=_aa.."..."end;_aa=_aa..")"_aa=b_a(_aa,dd(d_a.Body))
_aa=b_a(_aa,"end")elseif d_a.AstType=='GenericForStatement'then d_a.Scope:RenameVars()
_aa="for "
for i=1,#d_a.VariableList do
_aa=_aa..d_a.VariableList[i].Name;if i~=#d_a.VariableList then _aa=_aa..","end end;_aa=_aa.." in"
for i=1,#d_a.Generators do
_aa=b_a(_aa,__a(d_a.Generators[i]))if i~=#d_a.Generators then _aa=b_a(_aa,',')end end;_aa=b_a(_aa,"do")_aa=b_a(_aa,dd(d_a.Body))
_aa=b_a(_aa,"end")elseif d_a.AstType=='NumericForStatement'then _aa="for "_aa=_aa..
d_a.Variable.Name.."="_aa=_aa..
__a(d_a.Start)..","..__a(d_a.End)if d_a.Step then
_aa=_aa..","..__a(d_a.Step)end;_aa=b_a(_aa,"do")
_aa=b_a(_aa,dd(d_a.Body))_aa=b_a(_aa,"end")end;a_a=a_a+#_aa;return _aa end
dd=function(d_a)local _aa=''d_a.Scope:RenameVars()for aaa,baa in pairs(d_a.Body)do
_aa=b_a(_aa,c_a(baa),';')end;return _aa end;cd.Scope:RenameVars()return dd(cd)end
local minify = function(cd)local dd,__a=ParseLua(cd)if not dd then return false,__a end
return true,Format_Mini(__a)end
-- Packaging part:
local args = table.pack(...)
local projectPath = args[1] or "Basalt"
local minifyProject = args[2]=="true" and true or false
local outputFileName = args[3] or "basalt.lua"
assert(fs.isDir(projectPath), "Unable to find directory: "..projectPath)
local projectFiles = {
"objects",
"libraries",
"Frame.lua",
"loadObjects.lua",
"Object.lua",
"theme.lua",
}
local subDirs = {
"objects", "libraries"
}
local mainFile = "main.lua"
local outputFile = io.open(outputFileName, "w")
if(outputFile==nil)then
error("Can't open file "..outputFileName)
end
outputFile:write([[
local project = {}
local packaged = true
local baseRequire = require
local require = function(path)
for _,v in pairs(project)do
for name,b in pairs(v)do
if(name==path)then
return b()
end
end
end
return baseRequire(path);
end
local getProject = function(subDir)
if(subDir~=nil)then
return project[subDir]
end
return project
end
]])
for k,v in pairs(subDirs)do
outputFile:write("project['"..v.."'] = {}")
end
outputFile:write("project['default'] = {}")
local function writeNewPackage(subdir, name, path)
if not(fs.isDir(path))then
outputFile:write("project['"..subdir.."']['"..name.."'] = ".."function(...)")
local fileData = io.open(path, "r"):read("*all")
if(minifyProject)then
local success, data = minify(fileData)
if(success)then
outputFile:write(data:gsub("]]", "] ]"):gsub("]]", "] ]").."\n")
else
print("Error: Can't minify "..path)
end
else
outputFile:write(fileData:gsub("]]", "] ]"):gsub("]]", "] ]").."\n")
end
outputFile:write("end; \n")
end
end
for _,v in pairs(projectFiles)do
if(fs.isDir(fs.combine(projectPath, v)))then
for _,b in pairs(fs.list(fs.combine(projectPath, v)))do
writeNewPackage(v, b:gsub(".lua", ""), fs.combine(fs.combine(projectPath, v), b))
end
else
writeNewPackage("default", v:gsub(".lua", ""), fs.combine(projectPath, v))
end
end
local main = io.open(fs.combine(projectPath, mainFile), "r"):read("*all")
if(minifyProject)then
local success,data = minify(main)
if(success)then
outputFile:write(data)
else
print("Error: Can't minify "..fs.combine(projectPath, mainFile))
end
else
outputFile:write(main)
end
outputFile:close()

0
docs/.nojekyll Normal file
View File

1
docs/CNAME Normal file
View File

@@ -0,0 +1 @@
basalt.madefor.cc

24
docs/Home.md Normal file
View File

@@ -0,0 +1,24 @@
# Welcome to The Basalt Wiki!
*Note: The Basalt Wiki is a work in progress. Please treat Wiki errors the same as bugs and report them accordingly.*
Here you can find information about how to use Basalt as well as examples of functional Basalt code. The aim of Basalt is to improve user interaction through visual display.
## About Basalt
Basalt is intended to be an easy-to-understand UI Framework designed for CC:Tweaked (Also know as "ComputerCraft: Tweaked") - a popular minecraft mod. For more information about CC:Tweaked, checkout the project's [wiki](https://tweaked.cc/) or [download](https://www.curseforge.com/minecraft/mc-mods/cc-tweaked).
## Quick Demo
<img src="https://raw.githubusercontent.com/Pyroxenium/Basalt/master/docs/_media/basaltPreview2.gif" width="600">
## Questions & Bugs
Obviously NyoriE has implemented some easter eggs, *some people* call them "bugs". If you happen to discover one of these just make a new <a href="https://github.com/Pyroxenium/Basalt/issues">issue</a>.
Additionally, if you have questions about Basalt or how to make use of it, feel free to create a new discussion on <a href="https://github.com/Pyroxenium/Basalt/discussions">Basalt's Discussion Board</a>, or ask in our [discord](https://discord.gg/yNNnmBVBpE).
---
Feel free to join our [discord](https://discord.gg/yNNnmBVBpE)!
<br><br>

1
docs/_Footer.md Normal file
View File

@@ -0,0 +1 @@
Thanks for checking out our wiki, join our discord for more help: [discord.gg/yM7kndJdJJ](discord.gg/yM7kndJdJJ)

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

BIN
docs/_media/installer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
docs/_media/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

4
docs/_navbar.md Normal file
View File

@@ -0,0 +1,4 @@
- Getting Started
- [Home](Home.md)
- [Quick Start](home/Quick-Start.md)
- [Installer](home/installer)

35
docs/_sidebar.md Normal file
View File

@@ -0,0 +1,35 @@
- About
- [Home](Home.md)
- [Quick Start](home/Quick-Start.md)
- [Installer](home/installer)
- Objects
- [Basalt](objects/Basalt)
- [Object](objects/Object)
- [Button](objects/Button)
- [Checkbox](objects/Checkbox)
- [Dropdown](objects/Dropdown)
- [Frame](objects/Frame)
- [Image](objects/Image)
- [Input](objects/Input)
- [Label](objects/Label)
- [List](objects/List)
- [Menubar](objects/Menubar)
- [Pane](objects/Pane)
- [Program](objects/Program)
- [Progressbar](objects/Progressbar)
- [Radio](objects/Radio)
- [Scrollbar](objects/Scrollbar)
- [Slider](objects/Slider)
- [Textfield](objects/Textfield)
- [Animation](objects/Animation.md)
- [Thread](objects/Thread)
- [Timer](objects/Timer)
- Events
- [Mouse Events](events/mouseEvents.md)
- [Keyboard Events](events/keyEvents.md)
- [Other Events](events/otherEvents.md)
- Tips & Tricks
- [Component Logic](tips/logic)
- [Changing Button Color](tips/buttons)
- [Advanced usage of Events](tips/events.md)
- [Example Designs](tips/design.md)

39
docs/events/keyEvents.md Normal file
View File

@@ -0,0 +1,39 @@
Here we will talk about keyboard events and how you can manipulate them. There are 2 possible key events you can add to almost every visual object.
# onKey
`onKey(self, event, key)`<br>
The computercraft event which triggers this method is `key`.
Any visual object can register onKey events.
Here is a example on how to add a onKey event to your frame:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame("myMainFrame"):show()
local subFrame = mainFrame:addFrame("subFrame"):setPosition(3,3):setSize(18,6):setBar("Sub Frame",colors.black):showBar():show()
function openSubFrame()
subFrame:show()
end
mainFrame:onKey(openSubFrame)
```
# onKeyUp
`onKeyUp(self, event, key)`<br>
The computercraft event which triggers this method is `key_up`.
Any visual object can register onKeyUp events.
Here is a example on how to add a onKeyUp event to your frame:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame("myMainFrame"):show()
local subFrame = mainFrame:addFrame("subFrame"):setPosition(3,3):setSize(18,6):setBar("Sub Frame",colors.black):showBar():show()
function openSubFrame()
subFrame:show()
end
mainFrame:onKeyUp(openSubFrame)
```

View File

@@ -0,0 +1,82 @@
Here we will talk about mouse events and how you can use them. You can register custom mouse events to all visual objects
# onClick
`onClick(self, event, button, x, y)`<br>
The computercraft event which triggers this method is `mouse_click` and `monitor_touch`.
Any visual object can register onClick events.
Here is a example on how to add a onClick event to your button:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame("myMainFrame"):show()
local button = mainFrame:addButton("myButton"):setPosition(3,3):setSize(12,3):setText("Click"):show()
function buttonOnClick()
basalt.debug("Button got clicked!")
end
button:onClick(buttonOnClick())
```
# onClickUp
`onClickUp(self, event, button, x, y)`<br>
The computercraft event which triggers this method is `mouse_up`.
Any visual object can register onClickUp events.
Here is a example on how to add a onClickUp event to your button:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame("myMainFrame"):show()
local button = mainFrame:addButton("myButton"):setPosition(3,3):setSize(12,3):setText("Click"):show()
function buttonOnClick(self, button, x, y)
basalt.debug("Button got clicked!")
end
button:onClick(buttonOnClick)
function buttonOnRelease(self, button, x, y)
basalt.debug("Button got released!")
end
button:onClickUp(buttonOnRelease)
```
# onScroll
`onScroll(self, event, direction, x, y)`<br>
The computercraft event which triggers this method is `mouse_scroll`.
Any visual object can register onScroll events.
Here is a example on how to add a onScroll event to your button:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame("myMainFrame"):show()
local button = mainFrame:addButton("myButton"):setPosition(3,3):setSize(12,3):setText("Click"):show()
function buttonOnScroll(self, direction, x, y)
basalt.debug("Someone scrolls on me!")
end
button:onScroll(buttonOnScroll)
```
# onDrag
`onDrag(self, event, button, x, y)`<br>
The computercraft event which triggers this method is `mouse_drag`.
Any visual object can register onDrag events.
Here is a example on how to add a onDrag event to your button:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame("myMainFrame"):show()
local button = mainFrame:addButton("myButton"):setPosition(3,3):setSize(12,3):setText("Click"):show()
function buttonOnDrag(self, button, x, y)
basalt.debug("Someone drags me (i know i wont reposition myself)!")
end
button:onDrag(buttonOnDrag)
```

View File

@@ -0,0 +1,79 @@
There are also other useful events you can listen to:
# onChange
`onChange(self)`<br>
This is a custom event which gets triggered as soon as the function :setValue() is called. This function is also called by basalt, for example if you change the input, textfield or checkbox (or all the different types of lists) objects.
Here is a example on how to add a onChange event to your input, and also another example for your checkbox:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame("myMainFrame"):show()
local aInput = mainFrame:addInput("specialInput"):setPosition(3,3):show()
local aCheckbox = mainFrame:addCheckbox("specialCheckbox"):setPosition(3,5):show()
local function checkInput(input)
if(string.lower(input:getValue())=="hello")then
basalt.debug("Hello back!")
end
end
local function checkCheckbox(checkbox)
if(checkbox:getValue()==true)then -- or if(checkbox:getValue())then
basalt.debug("Checkbox is active, let us do something!")
end
end
aInput:onChange(checkInput)
aCheckbox:onChange(checkCheckbox)
```
# onResize
`onResize(self)`<br>
This is a custom event which gets triggered as soon as the parent frame gets resized.
Here is a example on how to add a onResize event to your button:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame("myMainFrame"):show()
local aButton = mainFrame:addButton("myButton"):setPosition(3,3):show()
local function onButtonResize(button)
local width = mainFrame:getWidth()
button:setSize()
end
aButton:onResize(onButtonResize)
```
# onLoseFocus
`onLoseFocus(self)`<br>
This event gets triggered as soon as the object loses its focus.
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame("myFirstFrame"):show()
local aButton = mainFrame:addButton("exampleButton"):setPosition(3,3):onLoseFocus(
function(self)
basalt.debug("Please come back... :(")
end
):show()
```
# onGetFocus
`onGetFocus(self)`<br>
This event gets triggered as soon as the object is the currently focused object.
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame("myFirstFrame"):show()
local aButton = mainFrame:addButton("exampleButton"):setPosition(3,3):onGetFocus(
function(self)
basalt.debug("Welcome back!")
end
):show()
```

BIN
docs/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
docs/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
docs/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

93
docs/home/Quick-Start.md Normal file
View File

@@ -0,0 +1,93 @@
## HowTo Use
To load the framework into your project, make use of the following code on top of your code.
```lua
local basalt = require("Basalt")
```
It does not matter if you have installed the single file version or the full folder project. <br>
Both versions can be loaded by using `require("Basalt")`, you dont need to add `.lua`.
## Download
### Download the folder version
This version is for people who'd like to work with Basalt, change something in Basalt or checkout the project.<br>
But you are also able to just use it to create your own UI.<br>
To install the full project to your CC:Tweaked Computer, use the following command on your CC:Tweaked shell:
`pastebin run ESs1mg7P`
This will download the project as a folder called "Basalt". You are immediatly after the download is done able to use it in your projects.
### Download the single file version
This is the version you should use if you're done with programming. It is a little bit faster and it is also minified, which makes the project smaller.
To install the single filed project to your CC:Tweaked Computer, use the following command on your CC:Tweaked shell:
`pastebin run ESs1mg7P packed`
This will download the project as a single file called "basalt.lua". You are immediatly after the download is done able to use it in your projects.
### Basalt Package Manager
The Basalt Package Manager is still in alpha!<br><br>
The Basalt Package Manager is a visual installer, you are able to change some settings, also to choose which objects are necessary for your projects and which are not.
To install the BPM (Basalt Package Manager) use the following command on your CC:Tweaked shell:
`pastebin run ESs1mg7P bpm true`
The true keyword in the end is optional and would simply start BPM immediately.
## Example
Here is a fully functioning example of Basalt code
```lua
local basalt = require("Basalt") --> Load the Basalt framework
--> Create the first frame. Please note that Basalt needs at least one active "non-parent" frame to properly supply events
--> When Basalt#createFrame makes use of unique identifiers (commonly referred to as UIDs), meaning that the supplied value must be UNIQUE
--> If the supplied UID is ambiguous, Basalt#createFrame returns a nil value
local mainFrame = basalt.createFrame("mainFrame")
--> Show the frame to the user
mainFrame:show()
local button = mainFrame:addButton("clickableButton") --> Add a button to the mainFrame (With a unique identifier)
--> Set the position of the button, Button#setPosition follows an x, y pattern.
--> The x value is how far right the object should be from its anchor (negative values from an anchor will travel left)
--> The y value is how far down the object should be from its anchor (negative values from an anchor will travel up)
button:setPosition(4, 4)
button:setText("Click me!") --> Set the text of our button
local function buttonClick() --> This function serves as our click logic
basalt.debug("I got clicked!")
end
--> Remember! You cannot supply buttonClick(), that will only supply the result of the function
--> Make sure the button knows which function to call when it's clicked
button:onClick(buttonClick)
button:show() --> Make the button visible, so the user can click it
basalt.autoUpdate() --> Basalt#autoUpdate starts the event listener to detect user input
```
If you're like us and strive for succinct and beautiful code, here is a cleaner implementation of the code above:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame("mainFrame"):show()
local button = mainFrame --> Basalt returns an instance of the object on most methods, to make use of "call-chaining"
:addButton("clickableButton") --> This is an example of call chaining
:setPosition(4,4)
:setText("Click me!")
:onClick(
function()
basalt.debug("I got clicked!")
end)
:show()
basalt.autoUpdate()
```

74
docs/home/installer.md Normal file
View File

@@ -0,0 +1,74 @@
# Installer
This is just a script which helps you to setup your program to automatically install the Basalt UI Framework, if it doesn't exists. Means, you create your program (which requires basalt) and add this on the top of your program. Now, everytime you execute your program it checks if basalt.lua (or your custom filepath) exists or not, if not it installs it, or if you are using the advanced installer, it asks the user if the program is allowed to install basalt for you.
## Basic Installer
Here is a very basic one which just installs basalt.lua if don't exist:
```lua
--Basalt configurated installer
local filePath = "basalt.lua" --here you can change the file path default: basalt
if not(fs.exists(filePath))then
shell.run("pastebin run ESs1mg7P packed true "..filePath:gsub(".lua", "")) -- this is an alternative to the wget command
end
local basalt = require(filePath:gsub(".lua", "")) -- here you can change the variablename in any variablename you want default: basalt
```
## Advanced Installer
This is a visual version, it asks the user if he wants to install basalt.lua (if not found)<br>
![](https://raw.githubusercontent.com/Pyroxenium/Basalt/master/docs/_media/installer.png)
```lua
--Basalt configurated installer
local filePath = "basalt.lua" --here you can change the file path default: basalt
if not(fs.exists(filePath))then
local w,h = term.getSize()
term.clear()
local _installerWindow = window.create(term.current(),w/2-8,h/2-3,18,6)
_installerWindow.setBackgroundColor(colors.gray)
_installerWindow.setTextColor(colors.black)
_installerWindow.write(" Basalt Installer ")
_installerWindow.setBackgroundColor(colors.lightGray)
for line=2,6,1 do
_installerWindow.setCursorPos(1,line)
if(line==3)then
_installerWindow.write(" No Basalt found! ")
elseif(line==4)then
_installerWindow.write(" Install it? ")
elseif(line==6)then
_installerWindow.setTextColor(colors.black)
_installerWindow.setBackgroundColor(colors.gray)
_installerWindow.write("Install")
_installerWindow.setBackgroundColor(colors.lightGray)
_installerWindow.write(string.rep(" ",5))
_installerWindow.setBackgroundColor(colors.red)
_installerWindow.write("Cancel")
else
_installerWindow.write(string.rep(" ",18))
end
end
_installerWindow.setVisible(true)
_installerWindow.redraw()
while(not(fs.exists(filePath))) do
local event, p1,p2,p3,p4 = os.pullEvent()
if(event=="mouse_click")then
if(p3==math.floor(h/2+2))and(p2>=w/2-8)and(p2<=w/2-2)then
shell.run("pastebin run ESs1mg7P packed true "..filePath:gsub(".lua", ""))
_installerWindow.setVisible(false)
term.clear()
break
end
if(p3==math.floor(h/2+2))and(p2<=w/2+9)and(p2>=w/2+4)then
_installerWindow.clear()
_installerWindow.setVisible(false)
term.setCursorPos(1,1)
term.clear()
return
end
end
end
term.setCursorPos(1,1)
term.clear()
end
local basalt = require(filePath:gsub(".lua", "")) -- here you can change the variablename in any variablename you want default: basalt
------------------------------
```

54
docs/index.html Normal file
View File

@@ -0,0 +1,54 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Basalt Documentation</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Basalt is an easy-to-understand UI Framework designed for CC:Tweaked - a popular minecraft mod. ">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<!-- <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple-dark.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.28.0/themes/prism-tomorrow.min.css">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<style>
:root {
--theme-color: #16CC27;
--mono-hue: 120;
--mono-saturation: 1%;
--mono-shade3: hsl(var(--mono-hue), var(--mono-saturation), 5%);
--mono-shade2: hsl(var(--mono-hue), var(--mono-saturation), 6%);
--mono-shade1: hsl(var(--mono-hue), var(--mono-saturation), 7%);
--mono-base: hsl(var(--mono-hue), var(--mono-saturation), 20%);
--mono-tint1: hsl(var(--mono-hue), var(--mono-saturation), 25%);
--mono-tint2: hsl(var(--mono-hue), var(--mono-saturation), 30%);
--mono-tint3: hsl(var(--mono-hue), var(--mono-saturation), 35%);
--base-background-color: hsl(var(--mono-hue), var(--mono-saturation), 10%);
--sidebar-nav-pagelink-background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='11.2' viewBox='0 0 7 11.2'%3E%3Cpath d='M1.5 1.5l4 4.1 -4 4.1' stroke-width='1.5' stroke='%23575d5e' fill='none' stroke-linecap='square' stroke-linejoin='miter' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
--sidebar-nav-pagelink-background-image--active: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11.2' height='7' viewBox='0 0 11.2 7'%3E%3Cpath d='M1.5 1.5l4.1 4 4.1-4' stroke-width='1.5' stroke='%23575d5e' fill='none' stroke-linecap='square' stroke-linejoin='miter' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
--sidebar-nav-pagelink-background-image--collapse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='11.2' viewBox='0 0 7 11.2'%3E%3Cpath d='M1.5 1.5l4 4.1 -4 4.1' stroke-width='1.5' stroke='%23575d5e' fill='none' stroke-linecap='square' stroke-linejoin='miter' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
--sidebar-nav-pagelink-background-image--loaded: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11.2' height='7' viewBox='0 0 11.2 7'%3E%3Cpath d='M1.5 1.5l4.1 4 4.1-4' stroke-width='1.5' stroke='%23575d5e' fill='none' stroke-linecap='square' stroke-linejoin='miter' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
}
</style>
</head>
<body>
<div id="app">Did you know: Basalt is a Pyroxene?></div>
<script>
window.$docsify = {
logo: '/_media/logo.png',
loadNavbar: true,
loadSidebar: true,
autoHeader: true,
subMaxLevel: 2,
homepage: 'Home.md',
name: 'Basalt',
repo: 'https://github.com/Pyroxenium/Basalt',
auto2top: true
}
</script>
<!-- Docsify v4 -->
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/js/docsify-themeable.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1.28.0/components/prism-lua.min.js"></script>
</body>
</html>

303
docs/objects/Animation.md Normal file
View File

@@ -0,0 +1,303 @@
With animations, you can create a beautiful experience for users while interacting with objects.<br>
For now the animation class is very basic, it will be expanded in the future, but we have to say you can already do almost everything you can imagine!
Right now animation is a class which makes use of the timer event.<br>
You can find more information below:
`The animation object is still a WIP and the way you use it right now could change in the future!`
## add
Adds a new function to an animation
#### Parameters:
1. `function` The function containing animation logic
#### Returns:
1. `animation` Animation in use
#### Usage:
* This will set the button position to 3,3, waits 1 second, then sets position to 4,4, waits 2 seconds, and then sets the position to 5,5
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton()
local aAnimation = mainFrame:addAnimation():add(function() testButton:setPosition(3,3) end):wait(1):add(function() testButton:setPosition(1,1,"r") end):wait(2):add(function() testButton:setPosition(1,1,"r") end)
aAnimation:play()
```
## wait
Sets a wait timer for the next function after the previous function got executed, no wait timer calls the next function immediately
#### Parameters:
1. `number` The length of delay between the functions _(in seconds)_
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton()
local aAnimation = mainFrame:addAnimation():add(function() testButton:setPosition(3,3) end):wait(1):add(function() testButton:setPosition(1,1,"r") end):wait(2):add(function() testButton:setPosition(1,1,"r") end)
aAnimation:play()
```
## play
Plays the animation
#### Parameters:
1. `boolean` Whether it will loop forever, will most likely be replaced with a count in the future
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton()
local aAnimation = mainFrame:addAnimation():add(function() testButton:setBackground(colors.black) end):wait(1):add(function() testButton:setBackground(colors.gray) end):wait(1):add(function() testButton:setBackground(colors.lightGray) end)
aAnimation:play() -- changes the background color of that button from black to gray and then to lightGray
```
## cancel
Cancels the animation
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton()
local aAnimation = mainFrame:addAnimation():add(function() testButton:setBackground(colors.black) end):wait(1):add(function() aAnimation:cancel() end):wait(1):add(function() testButton:setBackground(colors.lightGray) end)
aAnimation:play()
```
## setObject
Sets the object which the animation should reposition/resize
#### Parameters:
1. `table` object
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton()
local aAnimation = mainFrame:addAnimation():setObject(testButton)
```
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
```
```xml
<animation object="buttonToAnimate" />
```
## move
Moves the object which got defined by setObject
#### Parameters:
1. `number` x coordinate
2. `number` y coordinate
3. `number` duration in seconds
4. `number` time - time when this part should begin (offset to when the animation starts - default 0)
5. `table` object - optional, you could also define the object here
#### Returns:
1. `animation` Animation in use
#### Usage:
* Takes 2 seconds to move the object from its current position to x15 y3
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):move(15,3,2):play()
```
```xml
<animation object="buttonToAnimate" play="true">
<move><x>15</x><y>6</y><duration>2</duration></move>
</animation>
```
## offset
Changes the offset on the object which got defined by setObject
#### Parameters:
1. `number` x offset
2. `number` y offset
3. `number` duration in seconds
4. `number` time - time when this part should begin (offset to when the animation starts - default 0)
5. `table` object - optional, you could also define the object here
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame("frameToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(subFrame):offset(1,12,1):play()
```
```xml
<animation object="frameToAnimate" play="true">
<offset><x>1</x><y>12</y><duration>1</duration></offset>
</animation>
```
## size
Changes the size on the object which got defined by setObject
#### Parameters:
1. `number` width
2. `number` height
3. `number` duration in seconds
4. `number` time - time when this part should begin (offset to when the animation starts - default 0)
5. `table` object - optional, you could also define the object here
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):size(15,3,1):play()
```
```xml
<animation object="buttonToAnimate" play="true">
<offset><w>15</w><h>3</h><duration>1</duration></offset>
</animation>
```
## changeText
Changes the text while animation is running
#### Parameters:
1. `table` multiple text strings - example: {"i", "am", "groot"}
2. `number` duration in seconds
3. `number` time - time when this part should begin (offset to when the animation starts - default 0)
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeText({"i", "am", "groot"}, 2):play()
```
```xml
<animation object="buttonToAnimate" play="true">
<text>
<text>i</text>
<text>am</text>
<text>groot</text>
<duration>2</duration>
</text>
</animation>
```
## changeTextColor
Changes the text color while the animation is running
#### Parameters:
1. `table` multiple color numbers - example: {colors.red, colors.yellow, colors.green}
2. `number` duration in seconds
3. `number` time - time when this part should begin (offset to when the animation starts - default 0)
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor({colors.red, colors.yellow, colors.green}, 2):play()
```
```xml
<animation object="buttonToAnimate" play="true">
<textColor>
<color>red</color>
<color>yellow</color>
<color>green</color>
<duration>2</duration>
</textColor>
</animation>
```
## changeBackground
Changes the background color while the animation is running
#### Parameters:
1. `table` multiple color numbers - example: {colors.red, colors.yellow, colors.green}
2. `number` duration in seconds
3. `number` time - time when this part should begin (offset to when the animation starts - default 0)
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor({colors.red, colors.yellow, colors.green}, 2):play()
```
```xml
<animation object="buttonToAnimate" play="true">
<background>
<color>red</color>
<color>yellow</color>
<color>green</color>
<duration>2</duration>
</background>
</animation>
```
# Events
## onDone
`onDone(self)`<br>
This is a event which gets fired as soon as the animation has finished.
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor({colors.red, colors.yellow, colors.green}, 2):play()
aAnimation:onDone(function()
basalt.debug("The animation is done")
end)
```
In XML you are also able to queue multiple animations, like this:
```xml
<animation id="anim2" object="buttonToAnimate">
<textColor>
<color>red</color>
<color>yellow</color>
<color>green</color>
<duration>2</duration>
</textColor>
</animation>
<animation onDone="#anim2" object="buttonToAnimate" play="true">
<background>
<color>red</color>
<color>yellow</color>
<color>green</color>
<duration>2</duration>
</background>
</animation>
```

201
docs/objects/Basalt.md Normal file
View File

@@ -0,0 +1,201 @@
Before you can access Basalt, you need to add the following code on top of your file:
`local basalt = require("Basalt")`
Now you are able to access the following methods:
## basalt.createFrame
Create a base-frame (main frame)
#### Parameters:
1. `string` name
#### Returns:
1. `frame` object
#### Usage:
* Create and show a frame with id "myFirstFrame"
```lua
local mainFrame = basalt.createFrame("myFirstFrame")
```
## basalt.removeFrame
Removes a base frame
#### Parameters:
1. `string` name
#### Usage:
* Removes the previously created frame with id "myFirstFrame"
```lua
local mainFrame = basalt.createFrame("myFirstFrame")
basalt.removeFrame("myFirstFrame")
```
## basalt.getFrame
Returns a base frame with the given name
#### Parameters:
1. `string` name
#### Returns:
1. `frame` object
#### Usage:
* Creates, fetches and shows the "myFirstFrame" object
```lua
basalt.createFrame("myFirstFrame"):hide()
basalt.getFrame("myFirstFrame"):show()
```
## basalt.getActiveFrame
Returns the currently active base frame
#### Returns:
1. `frame` The current frame
#### Usage:
* Displays the active frame name in the debug console
```lua
basalt.createFrame()
basalt.debug(basalt.getActiveFrame():getName()) -- returns the uuid
```
## basalt.autoUpdate
Starts the draw and event handler until basalt.stopUpdate() is called
#### Usage:
* Enable the basalt updates, otherwise the screen will not continue to update
```lua
local mainFrame = basalt.createFrame()
basalt.autoUpdate()
```
## basalt.update
Calls the draw and event handler once - this gives more flexibility about which events basalt should process. For example you could filter the terminate event.
#### Parameters:
1. `string` The event to be received
2. `...` Additional event variables to capture
#### Usage:
* Creates and starts a custom update cycle
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setPosition(2,2)
while true do
basalt.update(os.pullEventRaw())
end
```
## basalt.stopUpdate
Stops the automatic draw and event handler which got started by basalt.autoUpdate()
#### Usage:
* When the quit button is clicked, the button stops basalt auto updates
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setPosition(2,2):setText("Stop Basalt!")
aButton:onClick(function()
basalt.stopUpdate()
end)
basalt.autoUpdate()
```
## basalt.isKeyDown
Checks if the user is currently holding a key
#### Parameters:
1. `number` key code (use the keys table for that)
#### Returns:
1. `boolean` true or false
#### Usage:
* Shows a debug message with true or false if the left ctrl key is down, as soon as you click on the button.
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setPosition(2,2):setText("Check Ctrl")
aButton:onClick(function()
basalt.debug(basalt.isKeyDown(keys.leftCtrl))
end)
basalt.autoUpdate()
```
## basalt.debug
creates a label with some information on the main frame on the bottom left, if you click on that label it will open a log view for you. See it as the new print for debugging
You can also edit the default debug Label (change position, change color or whatever you want) by accessing the variable basalt.debugLabel
which returns the debug Label.
Also basalt.debugFrame and basalt.debugList are available.
#### Parameters:
1. `...` (multiple parameters are possible, like print does)
#### Usage:
* Prints "Hello! ^-^" to the debug console
```lua
basalt.debug("Hello! ", "^-^")
```
## basalt.setTheme
Sets the base theme of the project! Make sure to cover all existing objects, otherwise it will result in errors. A good example is [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua)
#### Parameters:
1. `table` theme layout look into [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua) for a example
#### Usage:
* Sets the default theme of basalt.
```lua
basalt.setTheme({
ButtonBG = colors.yellow,
ButtonText = colors.red,
...,
})
```
## basalt.setVariable
This stores a variable which you're able to access via xml. You are also able to add a function, which then gets called by object events created in XML.
#### Parameters:
1. `string` a key name
1. `any` any variable
#### Usage:
* Adds a function to basalt.
```lua
basalt.setVariable("clickMe", function()
basalt.debug("I got clicked")
end)
```
```xml
<button onClick="clickMe" text="Click me" />
```
## basalt.schedule
Schedules a function which gets called in a coroutine. After the coroutine is finished it will get destroyed immediatly. It's something like threads, but with some limits.
#### Parameters:
1. `function` a function which should get executed
#### Returns:
1. `function` it returns the function which you have to execute in order to start the coroutine
#### Usage:
* Creates a schedule which switches the color between red and gray
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setText("Click me")
aButton:onClick(basalt.schedule(function(self)
self:setBackground(colors.red)
os.sleep(0.1)
self:setBackground(colors.gray)
os.sleep(0.1)
self:setBackground(colors.red)
os.sleep(0.1)
self:setBackground(colors.gray)
os.sleep(0.1)
self:setBackground(colors.red)
os.sleep(0.1)
self:setBackground(colors.gray)
end))
```

91
docs/objects/Button.md Normal file
View File

@@ -0,0 +1,91 @@
Buttons are objects, which execute something by clicking on them.<br>
Remember button also inherits from [Object](objects/Object.md)
## setText
Sets the displayed button text
#### Parameters:
1. `string` the text the button should show
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a button with "Click me!" as text.
```lua
local mainFrame = basalt.createFrame()
local button = mainFrame:addButton():setText("Click me!")
```
```xml
<button text="Click me!" />
```
## setHorizontalAlign
Sets the horizontal align of the button text
#### Parameters:
1. `string` the position as string ("left", "center", "right") - default is center.
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the button's horizontal text align to right.
```lua
local mainFrame = basalt.createFrame()
local button = mainFrame:addButton()
:setText("Click me!")
:setHorizontalAlign("right")
```
```xml
<button text="Click me!" horizontalAlign="right" />
```
## setVerticalAlign
Sets the vertical align of the button text
#### Parameters:
1. `string` the position as string ("top", "center", "bottom") - default is center.
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the button's horizontal text align to right and the vertical text align to bottom.
```lua
local mainFrame = basalt.createFrame()
local button = mainFrame:addButton()
:setText("Click me!")
:setHorizontalAlign("right")
:setVerticalAlign("bottom")
```
```xml
<button text="Click me!" horizontalAlign="right" verticalAlign="bottom" />
```
# Example
This is a example on how you would create a fully working button:
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setText("Click")
aButton:onClick(function(self,event,button,x,y)
if(event=="mouse_click")and(button==1)then
basalt.debug("Left mousebutton got clicked!")
end
end)
```
and this would be the xml way to do it:
```lua
local mainFrame = basalt.createFrame():addLayout("example.xml")
basalt.setVariable("buttonClick", function(self,event,button,x,y)
if(event=="mouse_click")and(button==1)then
basalt.debug("Left mousebutton got clicked!")
end
end)
```
```xml
<button onClick="buttonClick" text="Click" />
```

33
docs/objects/Checkbox.md Normal file
View File

@@ -0,0 +1,33 @@
With checkbox objects the user can set a bool to true or false
Remember checkbox also inherits from [Object](objects/Object.md)
A checkbox does not have any custom methods. All required methods are provided by the base [object](objects/Object.md) class.
# Example
This is how you would create a event which gets fired as soon as the value gets changed:
```lua
local mainFrame = basalt.createFrame()
local aCheckbox = mainFrame:addCheckbox()
local function checkboxChange(self)
local checked = self:getValue()
basalt.debug("The value got changed into ", checked)
end
aCheckbox:onChange(checkboxChange)
```
also possible via xml:
```lua
local mainFrame = basalt.createFrame():addLayout("example.xml")
basalt.setVariable("checkboxChange", function(self)
local checked = self:getValue()
basalt.debug("The value got changed into ", checked)
end)
```
```xml
<checkbox onChange="checkboxChange" />
```

307
docs/objects/Dropdown.md Normal file
View File

@@ -0,0 +1,307 @@
Dropdowns are objects where the user can click on a button, this will open a list where the user can choose from.
If you want to access values inside items this is how the table for single items is made (just a example):
```lua
item = {
text="1. Entry",
bgCol=colors.black,
fgCol=colors.white
args = {}
}
```
Remember Dropdown also inherits from [Object](objects/Object.md)
## addItem
Adds a item into the dropdown
#### Parameters:
1. `string` The entry name
2. `number|color` unique default background color - optional
3. `number|color` unique default text color - optional
4. `any` any value - you could access this later in a :onChange() event (you need to use :getValue()) - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 3 entries
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
```
```xml
<dropdown>
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>3. Entry</text><bg>yellow</bg><fg>green</fg></item>
</dropdown>
```
## removeItem
Removes a item from the dropdown
#### Parameters:
1. `number` The index which should get removed
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 3 entries and removes the second one.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
aDropdown:removeItem(2)
```
## editItem
Edits a item from the dropdown
#### Parameters:
1. `number` The index which should be edited
2. `string` The new item name
3. `number` the new item background color - optional
4. `number` The new item text color - optional
5. `any` New additional information - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 3 entries and edits the second one.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
aDropdown:editItem(2, "Still 2. Entry", colors.red)
```
## getItem
Returns a item by index
#### Parameters:
1. `number` The index which should be returned
#### Returns:
1. `table` The item table example: {text="1. Entry", bgCol=colors.black, fgCol=colors.white}
#### Usage:
* Creates a default dropdown with 3 entries and edits the second one.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aDropdown:getItem(2).text)
```
## getItemCount
Returns the current item count
#### Returns:
1. `number` The item list count
#### Usage:
* Creates a default dropdown with 3 entries and prints the current item count.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aDropdown:getItemCount())
```
## getAll
Returns all items as table
#### Returns:
1. `table` All items
#### Usage:
* Creates a default menubar with 3 entries and prints a table.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aDropdown:getAll())
```
## selectItem
selects a item in the dropdown (same as a player would click on a item)
#### Parameters:
1. `number` The index which should get selected
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 3 entries and selects the second entry.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
aDropdown:selectItem(2)
```
## clear
Removes all items.
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 3 entries and removes them immediatley. Which makes no sense.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
aDropdown:clear()
```
## getItemIndex
returns the item index of the currently selected item
#### Returns:
1. `number` The current index
#### Usage:
* Creates a default dropdown with 3 entries selects the second entry and prints the currently selected index.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
aDropdown:selectItem(2)
basalt.debug(aDropdown:getItemIndex())
```
## setSelectedItem
Sets the background and the foreground of the item which is currently selected
#### Parameters:
1. `number|color` The background color which should be used
2. `number|color` The text color which should be used
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 4 entries and sets the selection background color to green.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
aDropdown:addItem("4. Entry")
aDropdown:setSelectedItem(colors.green, colors.red)
```
```xml
<dropdown selectionBG="green" selectionFG="red">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>2. Entry</text><bg>yellow</bg><fg>green</fg></item>
</dropdown>
```
## setOffset
Sets the offset of the dropdown (the same as you would scroll) - default is 0
#### Parameters:
1. `number` The offset value
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 6 entries and sets the offset to 3.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
:addItem("1. Entry")
:addItem("2. Entry")
:addItem("3. Entry")
:addItem("4. Entry")
:addItem("5. Entry")
:addItem("6. Entry")
:setOffset(3)
```
```xml
<dropdown offset="3">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text></item>
<item><text>3. Entry</text></item>
<item><text>4. Entry</text></item>
<item><text>5. Entry</text></item>
<item><text>6. Entry</text></item>
</dropdown>
```
## getOffset
Returns the current index offset
#### Returns:
1. `number` offset value
#### Usage:
* Creates a default dropdown with 6 entries and sets the offset to 3, also prints the current offset.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
:addItem("1. Entry")
:addItem("2. Entry")
:addItem("3. Entry")
:addItem("4. Entry")
:addItem("5. Entry")
:addItem("6. Entry")
:setOffset(3)
basalt.debug(aDropdown:getOffset())
```
## setDropdownSize
Sets the size of the opened dropdown
#### Parameters:
1. `number` The width value
2. `number` The height value
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown, adds 3 entries and sets the dropdown size to 15w, 8h
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown():setDropdownSize(15,8)
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry")
aDropdown:addItem("3. Entry")
```
```xml
<dropdown dropdownWidth="15" dropdownHeight="8">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text></item>
<item><text>3. Entry</text></item>
</dropdown>
```

409
docs/objects/Frame.md Normal file
View File

@@ -0,0 +1,409 @@
<a href="https://i.imgur.com/aikc0K1.png"><img src="https://i.imgur.com/aikc0K1.png" height="500" /></a>
Frames are like containers, but are also normal objects.
In other words, you can add other objects _(even frames)_ to a frame; if the frame itself is visible
all sub-objects _(if they are set as visible)_ are also visible. A better description will follow.
## basalt.createFrame
Creates a new non-parent frame - in most cases it is the first thing you'll need.
#### Parameters:
1. `string` name (should be unique)
#### Returns:
1. `frame | nil` The frame created by createFrame, or `nil` if there is already a frame with the given name.
#### Usage:
* Create a frame with an id "myFirstFrame", stored in a variable named frame
```lua
local myFrame = basalt.createFrame("myFirstFrame")
```
## addFrame
Creates a child frame on the frame, the same as [basalt.createFrame](https://github.com/Pyroxenium/Basalt/wiki/Frame#basaltcreateframe) except the frames are given a parent-child relationship automatically
#### Parameters:
1. `string` name (should be unique)
#### Returns:
1. `frame | nil` The frame created by addFrame, or `nil` if there is already a child frame with the given name.<br>
#### Usage:
* Create a new main frame and adds a child frame to it
```lua
local mainFrame = basalt.createFrame()
local myFrame = mainFrame:addFrame()
```
```xml
<frame></frame>
```
## setBar
Sets the text, background, and foreground of the upper bar of the frame, accordingly.
#### Parameters:
1. `string` The title text to set the bar to
2. `number` The background color
2. `number` The foreground color
#### Returns:
1. `frame` The frame being used
#### Usage:
* Set the title to "My first frame!", with a background of black and a foreground of light gray.
```lua
frame:setBar("My first Frame!", colors.black, colors.lightGray)
```
* Store the frame, use the named frame variable after assigning.
```lua
local mainFrame = basalt.createFrame()
local myFrame = MainFrame:addFrame()
myFrame:setBar("My first Frame!")
```
* This abuses the call-chaining that Basalt uses.
```lua
local mainFrame = basalt.createFrame()
local myFrame = mainFrame:addFrame():setBar("My first Frame!")
```
```xml
<frame barText="My first Frame!" barBG="black" barFG="lightGray"></frame>
```
## setBarTextAlign
Sets the frame's bar-text alignment
#### Parameters:
1. `string` Can be supplied with "left", "center", or "right"
#### Returns:
1. `frame` The frame being used
#### Usage:
* Set the title of myFrame to "My first frame!", and align it to the right.
```lua
myFrame:setBar("My first Frame!"):setBarTextAlign("right")
```
```xml
<frame barAlign="right"></frame>
```
## showBar
Toggles the frame's upper bar
#### Parameters:
1. `boolean | nil` Whether the frame's bar is visible or if supplied `nil`, is automatically visible
#### Returns:
1. `frame` The frame being used
#### Usage:
* Sets myFrame to have a bar titled "Hello World!" and subsequently displays it.
```lua
myFrame:setBar("Hello World!"):showBar()
```
```xml
<frame bar="true"></frame>
```
## setMonitor
Sets this frame as a monitor frame
#### Parameters:
1. `string` The monitor name ("right", "left",... "monitor_1", "monitor_2",...)
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new monitor frame, you can use to show objects on a monitor.
```lua
local mainFrame = basalt.createFrame()
local monitorFrame = basalt.createFrame():setMonitor("right")
monitorFrame:setBar("Monitor 1"):showBar()
```
```xml
<frame monitor="right"></frame>
```
## setMirror
mirrors this frame to another peripheral monitor object.
#### Parameters:
1. `string` The monitor name ("right", "left",... "monitor_1", "monitor_2",...)
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates mirror of your main frame to a monitor on the left side.
```lua
local mainFrame = basalt.createFrame():setMirror("left")
```
```xml
<frame mirror="left"></frame>
```
## getObject
Returns a child object of the frame
#### Parameters:
1. `string` The name of the child object
#### Returns:
1. `object | nil` The object with the supplied name, or `nil` if there is no object present with the given name
#### Usage:
* Adds a button with id "myFirstButton", then retrieves it again through the frame object
```lua
myFrame:addButton("myFirstButton")
local aButton = myFrame:getObject("myFirstButton")
```
## removeObject
Removes a child object from the frame
#### Parameters:
1. `string` The name of the child object
#### Returns:
1. `boolean` Whether the object with the given name was properly removed
#### Usage:
* Adds a button with the id "myFirstButton", then removes it with the aforementioned id
```lua
myFrame:addButton("myFirstButton")
myFrame:removeObject("myFirstButton")
```
## setFocusedObject
Sets the currently focused object
#### Parameters:
1. `object` The child object to focus on
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new button, sets the focused object to the previously mentioned button
```lua
local aButton = myFrame:addButton()
myFrame:setFocusedObject(aButton)
```
## removeFocusedObject
Removes the focus of the supplied object
#### Parameters:
1. `object` The child object to remove focus from
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new button then removes the focus from that button when clicking on it
```lua
local aButton = myFrame:addButton():setFocus():onClick(function()
myFrame:removeFocusedObject(aButton)
end)
```
## getFocusedObject
Gets the currently focused object
#### Returns:
1. `object` The currently focused object
#### Usage:
* Gets the currently focused object from the frame, storing it in a variable
```lua
local focusedObject = myFrame:getFocusedObject()
```
## setMovable
Sets whether the frame can be moved. _In order to move the frame click and drag the upper bar of the frame_
#### Parameters:
1. `boolean` Whether the object is movable
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a frame with id "myFirstFrame" and makes it movable
```lua
local myFrame = basalt.createFrame():setMovable(true)
```
```xml
<frame moveable="true"></frame>
```
## setOffset
Sets the frame's coordinate offset. The frame's child objects will receive the frame's coordinate offset. For example, when using a scrollbar, if you use its value to add an offset to a frame, you will get a scrollable frame.
Objects are also able to ignore the offset by using :ignoreOffset() (For example, you may want to ignore the offset on the scrollbar itself)
The function can also be supplied with negative values
#### Parameters:
1. `number` The x direction offset (+/-)
2. `number` The y direction offset (+/-)
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame with x offset of 5 and a y offset of 3
```lua
local myFrame = basalt.createFrame():setOffset(5, 3)
```
* Creates with x offset of 5 and a y offset of -5 (Meaning if you added a button with y position 5, it would be at y position 0)
```lua
local myFrame = basalt.createFrame():setOffset(5, -5)
```
```xml
<frame xOffset="5" yOffset="-5"></frame>
```
## addLayout
Adds a new XML Layout into your frame.
#### Parameters:
1. `string` Path to your layout
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and adds the mainframe.xml layout
```lua
local myFrame = basalt.createFrame():addLayout("mainframe.xml")
```
```xml
<frame layout="mainframe.xml"></frame>
```
## addLayoutFromString
Adds a new XML Layout as string into your frame.
#### Parameters:
1. `string` xml
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and adds the mainframe.xml layout
```lua
local myFrame = basalt.createFrame():addLayoutFromString("<button x='12' y='5' bg='black' />")
```
## getLastLayout
returns a table of all objects this frame has created via xml (useful if you'd like to access all of them for some reason)
#### Returns:
1. `table` table with objects
## setTheme
Sets the default theme of that frame children objects always try to get the theme of its parent frame, if it does not exist it goes to its parent parent frame, and so on until it reaches the basalt managers theme - which is sotred in theme.lua (Please checkout [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua) for how it could look like.
#### Parameters:
1. `table` theme layout look into [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua) for a example
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and adds a new theme which only changes the default color of buttons.
```lua
local myFrame = basalt.createFrame():setTheme({
ButtonBG = colors.yellow,
ButtonText = colors.red,
})
```
## setScrollable
Makes the frame scrollable with mousewheel.
#### Parameters:
1. `bool` scrollable or not
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and makes it scrollable
```lua
local myFrame = basalt.createFrame():setScrollable()
```
```xml
<frame scrollable="true"></frame>
```
## setMinScroll
Sets the minimum offset it is allowed to scroll (default 0)
#### Parameters:
1. `number` minimum y offset
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and makes it scrollable and sets the minimum amount to -5
```lua
local myFrame = basalt.createFrame():setScrollable():setMinScroll(-5)
```
```xml
<frame minScroll="-5"></frame>
```
## setMaxScroll
Sets the maximum offset it is allowed to scroll (default 10)
#### Parameters:
1. `number` maximum y offset
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and makes it scrollable and sets the maximum amount to 25
```lua
local myFrame = basalt.createFrame():setScrollable():setMaxScroll(25)
```
```xml
<frame maxScroll="25"></frame>
```
## setImportantScroll
By default if you hovering your mouse over children objects, you wont scroll the frame, if you set this to true the frame scrolling becomes more important
#### Parameters:
1. `bool` important or not
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and makes it scrollable and defines it as important
```lua
local myFrame = basalt.createFrame():setScrollable():setImportantScroll(true)
```
```xml
<frame importantScroll="true"></frame>
```
# XML Example
*This is how you would implement frames via xml:
```xml
<frame>
<frame width="50%" bg="red">
<button x="2" y="2" width="17" text="Example Button!"/>
</frame>
<frame x="50%+1" width="50%+1" bg="black">
<textfield bg="green" x="2" width="100%-2" />
</frame>
</frame>
```

41
docs/objects/Image.md Normal file
View File

@@ -0,0 +1,41 @@
The image object is for adding more advanced backgrounds.
It also provides a :shrink() function, where you can shrink the images to smaller ones. This functionallity is fully provided by the blittle library created by Bomb Bloke. I did not ask for permission to add it into the framework. If the creator wants me to remove the blittle part, just text me on discord!
The image object is still not done. in the future i will provide more image formats.
Remember image inherits from [Object](objects/Object.md)
## loadImage
loads a default .nfp file into the object.
#### Parameters:
1. `string` the absolute file path
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default image and loads a test.nfp file
```lua
local mainFrame = basalt.createFrame():show()
local aImage = mainFrame:addImage():loadImage("test.nfp")
```
```xml
<image path="test.nfp" />
```
## shrink
Shrinks the current image into a blittle image.
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default image and loads a test.nfp file
```lua
local mainFrame = basalt.createFrame()
local aImage = mainFrame:addImage():loadImage("test.nfp"):shrink()
```
```xml
<image path="test.nfp" shrink="true" />
```

91
docs/objects/Input.md Normal file
View File

@@ -0,0 +1,91 @@
With input's you are able to create a object where the user can type something in.<br>
Here are all possible functions available for inputs:<br>
Remember Input inherits from [Object](objects/Object.md)
## setInputType
Changes the input type. default: text
#### Parameters:
1. `string` input type ("text", "password", "number")
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default input and sets it to numbers only.
```lua
local mainFrame = basalt.createFrame()
local aInput = mainFrame:addInput():setInputType("number")
```
```xml
<input type="number" />
```
## getInputType
Gets the current input type
#### Returns:
1. `string` input type
#### Usage:
* Creates a default input and sets it to numbers only. Also prints the current input type to log.
```lua
local mainFrame = basalt.createFrame()
local aInput = mainFrame:addInput():setInputType("number")
basalt.debug(aInput:getInputType())
```
## setDefaultText
Sets the default text. This will only be displayed if there is no input set by the user.
#### Parameters:
1. `string` input type ("text", "password", "number")
2. `number|color` default background color - optional
3. `number|color` default text color - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default input and sets the default text to "...".
```lua
local mainFrame = basalt.createFrame()
local aInput = mainFrame:addInput():setDefaultText("...")
```
```xml
<input default="..." />
```
## setInputLimit
Sets a character limit to the input.
#### Parameters:
1. `number` character limit
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default input and sets the character limit to 8.
```lua
local mainFrame = basalt.createFrame()
local aInput = mainFrame:addInput():setInputLimit(8)
```
```xml
<input limit="8" />
```
## getInputLimit
Returns the input limit.
#### Returns:
1. `number` character limit
#### Usage:
* Creates a default input and sets the character limit to 8. Prints the current limit.
```lua
local mainFrame = basalt.createFrame()
local aInput = mainFrame:addInput():setInputLimit(8)
basalt.debug(aInput:getInputLimit())
```

77
docs/objects/Label.md Normal file
View File

@@ -0,0 +1,77 @@
A label is for adding simple text.
By default label's width is auto sizing based on the length of the text. If you change the size with setSize it will automatically stop autosizing the width.
The fontsize feature is calculated by bigfonts, a library made by Wojbie (http://www.computercraft.info/forums2/index.php?/topic/25367-bigfont-api-write-bigger-letters-v10/)
Here are all possible functions available for labels.<br>
Remember Label inherits from [Object](objects/Object.md)
## setText
Sets the text which gets displayed.
#### Parameters:
1. `string` The text which should be displayed
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default label with text "Some random text".
```lua
local mainFrame = basalt.createFrame()
local aLabel = mainFrame:addLabel():setText("Some random text")
```
```xml
<label text="Some random text" />
```
## setFontSize
Sets the font size, calculated by bigfonts. Default size is 1.
#### Parameters:
1. `number` The size (1, 2, 3, 4)
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default label, sets the text to "Basalt!" and its font size to 2.
```lua
local mainFrame = basalt.createFrame()
local aLabel = mainFrame:addLabel():setText("Basalt!"):setFontSize(2)
```
```xml
<label font="2" />
```
## getFontSize
Returns the current font size
#### Returns:
1. `number` font size
#### Usage:
* Creates a default label, sets the text to "Basalt!" and its font size to 2. Also prints the current fontsize.
```lua
local mainFrame = basalt.createFrame()
local aLabel = mainFrame:addLabel():setText("Basalt!"):setFontSize(2)
basalt.debug(aLabel:getFontSize())
```
## setTextAlign
Changes the text align
#### Returns:
1. `string` horizontal ("left", "center", "right")
1. `string` vertical ("top", "center", "bottom")
#### Usage:
* Creates a default label, sets the text to "Basalt!" changes the horizontal align to right
```lua
local mainFrame = basalt.createFrame()
local aLabel = mainFrame:addLabel():setText("Basalt!"):setTextAlign("right")
```
```xml
<label horizontalAlign="right" verticalAlign="center" />
```

279
docs/objects/List.md Normal file
View File

@@ -0,0 +1,279 @@
Lists are objects where you can create endless entries, and the user is able to select one of them
If you want to access values inside items this is how the table for single items is made (just a example):
```lua
item = {
text="1. Entry",
bgCol=colors.black,
fgCol=colors.white
args = {}
}
```
Remember Lists also inherits from [Object](objects/Object.md)
## addItem
Adds a item into the list
#### Parameters:
1. `string` The entry name
2. `number|color` unique default background color - optional
3. `number|color` unique default text color - optional
4. `any` any value - you could access this later in a :onChange() event (you need to use :getValue()) - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 3 entries
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
```
```xml
<list>
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>3. Entry</text><bg>yellow</bg><fg>green</fg></item>
</list>
```
## removeItem
Removes a item from the list
#### Parameters:
1. `number` The index which should get removed
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 3 entries and removes the second one.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
aList:removeItem(2)
```
## editItem
Edits a item from the list
#### Parameters:
1. `number` The index which should be edited
2. `string` The new item name
3. `number` the new item background color - optional
4. `number` The new item text color - optional
5. `any` New additional information - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 3 entries and changes the second one.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
aList:editItem(2, "Still 2. Entry", colors.red)
```
## getItem
Returns a item by index
#### Parameters:
1. `number` The index which should be returned
#### Returns:
1. `table` The item table example: {text="1. Entry", bgCol=colors.black, fgCol=colors.white}
#### Usage:
* Creates a default list with 3 entries and edits the second one.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aList:getItem(2).text)
```
## getItemCount
Returns the current item count
#### Returns:
1. `number` The item list count
#### Usage:
* Creates a default list with 3 entries and prints the current item count.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aList:getItemCount())
```
## getAll
Returns all items as table
#### Returns:
1. `table` All items
#### Usage:
* Creates a default menubar with 3 entries and prints a table.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aList:getAll())
```
## selectItem
selects a item in the list (same as a player would click on a item)
#### Parameters:
1. `number` The index which should get selected
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 3 entries and selects the second entry.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
aList:selectItem(2)
```
## clear
Removes all items.
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 3 entries and removes them immediatley. Which makes no sense.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
aList:clear()
```
## getItemIndex
returns the item index of the currently selected item
#### Returns:
1. `number` The current index
#### Usage:
* Creates a default list with 3 entries selects the second entry and prints the currently selected index.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
aList:selectItem(2)
basalt.debug(aList:getItemIndex())
```
## setSelectedItem
Sets the background and the foreground of the item which is currently selected
#### Parameters:
1. `number|color` The background color which should be used
2. `number|color` The text color which should be used
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 4 entries and sets the selection background color to green.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
aList:addItem("4. Entry")
aList:setSelectedItem(colors.green, colors.red)
```
```xml
<list selectionBG="green" selectionFG="red">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>2. Entry</text><bg>yellow</bg><fg>green</fg></item>
</list>
```
## setOffset
Sets the offset of the list (the same as you would scroll) - default is 0
#### Parameters:
1. `number` The offset value
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 6 entries and sets the offset to 3.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
:addItem("1. Entry")
:addItem("2. Entry")
:addItem("3. Entry")
:addItem("4. Entry")
:addItem("5. Entry")
:addItem("6. Entry")
:setOffset(3)
```
```xml
<list offset="3">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text></item>
<item><text>3. Entry</text></item>
<item><text>4. Entry</text></item>
<item><text>5. Entry</text></item>
<item><text>6. Entry</text></item>
</list>
```
## getOffset
Returns the current index offset
#### Returns:
1. `number` offset value
#### Usage:
* Creates a default list with 6 entries and sets the offset to 3, also prints the current offset.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
:addItem("1. Entry")
:addItem("2. Entry")
:addItem("3. Entry")
:addItem("4. Entry")
:addItem("5. Entry")
:addItem("6. Entry")
:setOffset(3)
basalt.debug(aList:getOffset())
```

337
docs/objects/Menubar.md Normal file
View File

@@ -0,0 +1,337 @@
Menubars are like lists but instead of being vertical, they are horizontal. Imagine you are creating a Operating System and you would like to add a taskbar, menubars would be exactly what you need, because they are also scrollable, which means they have endless entry possibility.
If you want to access values inside items this is how the table for single items is made (just a example):
```lua
item = {
text="1. Entry",
bgCol=colors.black,
fgCol=colors.white
args = {}
}
```
Remember menubar inherits from [Object](objects/Object.md)
## addItem
Adds a item into the menubar
#### Parameters:
1. `string` The entry name
2. `number|color` unique default background color - optional
3. `number|color` unique default text color - optional
4. `any` any value - you could access this later in a :onChange() event (you need to use :getValue()) - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
```
```xml
<menubar>
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>3. Entry</text><bg>yellow</bg><fg>green</fg></item>
</menubar>
```
## removeItem
Removes a item from the menubar
#### Parameters:
1. `number` The index which should get removed
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries and removes the second one.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:removeItem(2)
```
## editItem
Edits a item from the menubar
#### Parameters:
1. `number` The index which should be edited
2. `string` The new item name
3. `number` the new item background color - optional
4. `number` The new item text color - optional
5. `any` New additional information - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries and edits the second one.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:editItem(2, "Still 2. Entry", colors.red)
```
## getItem
Returns a item by index
#### Parameters:
1. `number` The index which should be returned
#### Returns:
1. `table` The item table example: {text="1. Entry", bgCol=colors.black, fgCol=colors.white}
#### Usage:
* Creates a default menubar with 3 entries and edits the second one.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aMenubar:getItem(2).text)
```
## getItemCount
Returns the current item count
#### Returns:
1. `number` The item list count
#### Usage:
* Creates a default menubar with 3 entries and prints the current item count.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aMenubar:getItemCount())
```
## getAll
Returns all items as table
#### Returns:
1. `table` All items
#### Usage:
* Creates a default menubar with 3 entries and prints a table.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aMenubar:getAll())
```
## setSpace
Sets the space between entries
#### Parameters:
1. `number` The space between each entry
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries and changes the space to 3.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:setSpace(3)
```
```xml
<menubar space="3">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>3. Entry</text><bg>yellow</bg><fg>green</fg></item>
</menubar>
```
## setScrollable
Makes the menubar scrollable. The menubar will be scrollable as soon as the menubar is to small for all the entries.
#### Parameters:
1. `boolean` if this menubar should be scrollable or not
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries and makes it scrollable.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:setScrollable(true)
```
```xml
<menubar scrollable="true">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>3. Entry</text><bg>yellow</bg><fg>green</fg></item>
</menubar>
```
## selectItem
selects a item in the list (same as a player would click on a item)
#### Parameters:
1. `number` The index which should get selected
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries and selects the second entry.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:selectItem(2)
```
## clear
Removes all items.
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries and removes them immediatley. Which makes no sense.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:clear()
```
## getItemIndex
returns the item index of the currently selected item
#### Returns:
1. `number` The current index
#### Usage:
* Creates a default menubar with 3 entries selects the second entry and prints the currently selected index.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:selectItem(2)
basalt.debug(aMenubar:getItemIndex())
```
## setSelectedItem
Sets the background and the foreground of the item which is currently selected
#### Parameters:
1. `number|color` The background color which should be used
2. `number|color` The text color which should be used
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 4 entries and sets the selection background color to green.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry")
aMenubar:addItem("3. Entry")
aMenubar:addItem("4. Entry")
aMenubar:setSelectedItem(colors.green, colors.yellow)
```
```xml
<menubar selectionBG="green" selectionFG="yellow">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text></item>
<item><text>3. Entry</text></item>
<item><text>4. Entry</text></item>
</menubar>
```
## setOffset
Sets the offset of the menubar (the same as you would scroll) - default is 0
#### Parameters:
1. `number` The offset value
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 6 entries and sets the offset to 3.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry")
aMenubar:addItem("3. Entry")
aMenubar:addItem("4. Entry")
aMenubar:addItem("5. Entry")
aMenubar:addItem("6. Entry")
aMenubar:setOffset(3)
```
```xml
<menubar offset="3">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text></item>
<item><text>3. Entry</text></item>
<item><text>4. Entry</text></item>
<item><text>5. Entry</text></item>
<item><text>6. Entry</text></item>
</menubar>
```
## getOffset
returns the current offset
#### Returns:
1. `number` Current offset
#### Usage:
* Creates a default menubar with 6 entries and sets the offset to 3, prints the current offset.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry")
aMenubar:addItem("3. Entry")
aMenubar:addItem("4. Entry")
aMenubar:addItem("5. Entry")
aMenubar:addItem("6. Entry")
aMenubar:getOffset(3)
basalt.debug(aMenubar:getOffset())
```

395
docs/objects/Object.md Normal file
View File

@@ -0,0 +1,395 @@
This is the base class for all visual objects. Which means, if you create a button, label, frame or something else (no timers, threads or animations) the following methods apply:
## show
Shows the object (only if the parent frame is already visible)
#### Returns:
1. `object` The object in use
#### Usage:
* Shows a frame
```lua
local mainFrame = basalt.createFrame()
local button = mainFrame:addButton()
button:show()
```
```xml
<button visible="true" />
```
## hide
Hides the object
#### Returns:
1. `object` The object in use
#### Usage:
* Hides a frame
```lua
local mainFrame = basalt.createFrame()
local button = mainFrame:addButton():setText("Close"):onClick(function() mainFrame:hide() end)
```
```xml
<button visible="false" />
```
## setPosition
Changes the position relative to its parent frame
#### Parameters:
1. `number` x coordinate
2. `number` y coordinate
3. `boolean` Whether it will add/remove to the current coordinates instead of setting them
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the Buttons position to an x coordinate of 2 with a y coordinate of 3
```lua
local mainFrame = basalt.createFrame()
mainFrame:addButton():setPosition(2,3)
```
```xml
<button x="2" y="3" />
```
## setBackground
Changes the object background color, if you set the value to false the background wont be visible. For example you could see trough a frame.
#### Parameters:
1. `number|color` Background color
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a frame, and sets its background color to `colors.gray`
```lua
local mainFrame = basalt.createFrame():setBackground(colors.gray)
```
```xml
<button bg="gray" />
```
## setForeground
Changes the object text color
#### Parameters:
1. `number|color` Foreground color
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a frame, and sets its foreground color to `colors.green`
```lua
local mainFrame = basalt.createFrame():setForeground(colors.green)
```
```xml
<button fg="green" />
```
## setSize
Changes the object size
#### Parameters:
1. `number` width
2. `number` height
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the frame to have a width of 15 and a height of 12
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame():setSize(15,12)
```
```xml
<frame width="15" height="12" />
```
## setFocus
Sets the object to be the focused object.
If you click on an object, it's normally automatically the focused object. For example, if you call :show() on a frame, and you want this particular frame to be in
the foreground, you should also use :setFocus()
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the button to the focused object
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setFocus()
```
## setZIndex
Sets the z-index. Higher value means higher draw/event priority. You can also add multiple objects to the same z-index, if so the last added object will have the highest priority.
#### Parameters:
1. `number` z-index
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the buttons z-index to `1` and the labels z-index to `2`
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setZIndex(1):setPosition(2,2)
local aLabel = mainFrame:addButton():setZIndex(2):setPosition(2,2):setText("I am a label!")
```
```xml
<button x="2" y="2" zIndex="1" />
<label x="2" y="2" text="I am a label!" zIndex="2" />
```
## setParent
Sets the parent frame of the object
#### Parameters:
1. `frame` The to-be parent frame
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the parent frame of the random frame, adding it to the main frame when the button is clicked"
```lua
local mainFrame = basalt.createFrame()
local aRandomFrame = basalt.createFrame()
local aButton = mainFrame:addButton():onClick(
function()
aRandomFrame:setParent(mainFrame)
end
)
```
## isFocused
Returns if the object is currently the focused object of the parent frame
#### Returns:
1. `boolean` Whether the object is focused
#### Usage:
* Prints whether the button is focused to the debug console
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton()
basalt.debug(aButton:isFocused()) -- shows true or false as a debug message
```
## getAnchorPosition
Converts the x and y coordinates into the anchor coordinates of the object
#### Parameters:
1. `number|nil` x
2. `number|nil` y, if nothing it uses the object's x, y
#### Returns:
1. `number` x
2. `number` y
#### Usage:
* Prints the anchor position to the debug console
```lua
local mainFrame = basalt.createFrame():setSize(15,15)
local aButton = mainFrame:addButton()
:setAnchor("bottomRight")
:setSize(8,1)
:setPosition(1,1)
basalt.debug(aButton:getAnchorPosition()) -- returns 7,14 (framesize - own size) instead of 1,1
```
## setAnchor
Sets the anchor of the object
#### Parameters:
1. `string` Anchor sides `("topLeft" "top", "topRight", "right", "bottomRight", "bottom", "bottomLeft", "left", "center")`
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the button to have an anchor of `bottomRight`
```lua
local mainFrame = basalt.createFrame():show()
local aButton = mainFrame:addButton()
:setAnchor("bottomRight")
:setSize(8,1)
:setPosition(-8,1)
```
```xml
<button anchor="bottomRight" />
```
## getAbsolutePosition
Converts the relative coordinates into absolute coordinates
#### Parameters:
1. `number|nil` x
2. `number|nil` y
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a frame and a button and prints the button's absolute position to the debug console
```lua
local mainFrame = basalt.createFrame():setPosition(3,3)
local aButton = mainFrame:addButton():setSize(8,1):setPosition(4,2)
basalt.debug(aButton:getAbsolutePosition()) -- returns 7,5 (frame coords + own coords) instead of 4,2
```
## setValue
Sets the value of that object (input, label, checkbox, textfield, scrollbar,...)
#### Parameters:
1. `any` Value to set the object to
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a checkbox and ticks it
```lua
local mainFrame = basalt.createFrame()
local aCheckbox = mainFrame:addCheckbox():setValue(true)
```
```xml
<checkbox value="true" />
```
## getValue
Returns the currently saved value
#### Returns:
1. `any` Object's value
#### Usage:
* Prints the value of the checkbox to the debug console
```lua
local mainFrame = basalt.createFrame()
local aCheckbox = mainFrame:addCheckbox():setValue(true)
basalt.debug(aCheckbox:getValue()) -- returns true
```
## getHeight/getWidth
Returns the respective height/width of the object
#### Returns:
1. `number` height/width
#### Usage:
* Prints the height of the object to the debug console
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setSize(5,8)
basalt.debug(aButton:getHeight()) -- returns 8
```
## isVisible
Returns if the object is currently visible
#### Returns:
1. `boolean`
#### Usage:
* Prints boolean visibility of object to debug console
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setSize(5,8)
basalt.debug(aButton:isVisible()) -- returns true
```
## getName
Returns the given name of the object
#### Returns:
1. `string` name
#### Usage:
* Prints name of object to debug window
```lua
local mainFrame = basalt.createFrame()
basalt.debug(mainFrame:getName()) -- returns myFirstFrame
```
## setShadow
Sets the shadow color - default: colors.black
#### Parameters:
1. `number|color` Shadow color
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the shadow to green and shows it:
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame()
:setMoveable()
:setSize(18,6)
:setShadow(colors.green)
:showShadow(true)
```
```xml
<frame width="18" height="6" shadow="true" shadowColor="green" moveable="true" />
```
## showShadow
Shows or hides the shadow
#### Parameters:
1. `boolean` Whether it should show or hide the shadow
#### Returns:
1. `object` The object in use
#### Usage:
* Shows the shadow:
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame()
:setMoveable()
:setSize(18,6)
:showShadow(true)
```
```xml
<frame width="18" height="6" shadow="true" moveable="true" />
```
## setBorder
Sets the border color - default: colors.black
#### Parameters:
1. `number|color` Border color
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the border to green and shows it:
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame()
:setMoveable()
:setSize(18,6)
:setBorder(colors.green)
:showBorder("left", "top", "right", "bottom")
```
```xml
<frame width="18" height="6" border="true" borderColor="green" moveable="true" />
```
## showBorder
Shows or hides the border
#### Parameters:
1. `strings` Whether it should show or hide the border on the specific sides ("left", "top", "right", "bottom")
#### Returns:
1. `object` The object in use
#### Usage:
* Shows the border:
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame()
:setMoveable()
:setSize(18,6)
:showBorder("left", "top", "bottom")
```
```xml
<frame width="18" height="6" border="true" borderColor="green" borderRight="false" moveable="true" />
```

19
docs/objects/Pane.md Normal file
View File

@@ -0,0 +1,19 @@
Panes are very simple sizeable background objects.
The following list is only available to panes: <br>
Remember Pane also inherits from [Object](objects/Object.md)
Pane doesn't have any custom functionallity. If you want to change the color/position or size, just check out the [object](https://github.com/NoryiE/basalt/wiki/Object) wikipage.
## Example:
```lua
local mainFrame = basalt.createFrame()
local aPane = mainFrame:addPane()
aPane:setSize(30, 10)
aPane:setBackground(colors.yellow)
aPane:show()
```
```xml
<pane width="30" height="10" bg="yellow" />
```

167
docs/objects/Program.md Normal file
View File

@@ -0,0 +1,167 @@
Program objects are here for opening other executable programs in your main program. You can execute worms, shell or any custom program you've made.
<br>
Remember Program inherits from [Object](objects/Object.md)
## getStatus
returns the current process status
#### Returns:
1. `string` current status ("running", "normal, "suspended", or "dead")
#### Usage:
* Prints current status
```lua
local mainFrame = basalt.createFrame()
local aProgram = mainFrame:addProgram()
basalt.debug(aProgram:getStatus())
```
## execute
Executes the given path or program
#### Parameters:
1. `string|function` the path to your file as string, or function which should be called
#### Returns:
1. `object` The object in use
#### Usage:
* Executes worm
```lua
local mainFrame = basalt.createFrame()
local aProgram = mainFrame:addProgram()
aProgram:execute("rom/programs/fun/worm.lua") -- executes worm
```
```xml
<program path="rom/programs/fun/worm.lua" execute="true" />
```
## stop
Stops a currently running program
#### Returns:
1. `object` The object in use
#### Usage:
* Stops worm by clicking a button
```lua
local mainFrame = basalt.createFrame()
local aProgram = mainFrame:addProgram()
aProgram:execute("rom/programs/fun/worm.lua") -- executes worm
mainFrame:addButton():setText("Pause"):onClick(function() aProgram:stop() end):show()
```
## pause
pauses the current program (prevents the program from receiving events)
#### Parameters:
1. `boolean` true, false or nothing
#### Returns:
1. `object` The object in use
#### Usage:
* Pauses worm by clicking a button
```lua
local mainFrame = basalt.createFrame():show()
local aProgram = mainFrame:addProgram():execute("rom/programs/shell.lua"):show()
mainFrame:addButton():setText("Pause"):onClick(function() aProgram:pause(true) end):show()
```
## isPaused
returns if the program is paused
#### Returns:
1. `boolean` pause status
#### Usage:
* Prints the pause status of the program
```lua
local mainFrame = basalt.createFrame():show()
local aProgram = mainFrame:addProgram():execute("rom/programs/shell.lua"):show()
basalt.debug(aProgram:isPaused())
```
## injectEvent
injects a event into the program manually. For example you could inject w a s and d for worm, by clicking buttons.
#### Parameters:
1. `string` event
2. `any` parameter
3. `any` parameter
4. `any` parameter
5. `any` parameter
6. `boolean` if this is true, the injected event will be executed even if the program is paused
#### Returns:
1. `object` The object in use
#### Usage:
* injects a event by clicking a button
```lua
local mainFrame = basalt.createFrame():show()
local aProgram = mainFrame:addProgram():execute("rom/programs/shell.lua"):show()
mainFrame:addButton():setText("inject"):onClick(function() aProgram:injectEvent("char", "w") end):show()
```
## injectEvents
Injects multiple events
#### Parameters:
1. `table` a table, items should be {event="event", args={para1, para2, para3, para4}}
#### Returns:
1. `object` The object in use
#### Usage:
* injects a multiple char events by clicking a button
```lua
local mainFrame = basalt.createFrame():show()
local aProgram = mainFrame:addProgram():execute("rom/programs/shell.lua"):show()
local events = {
{event="char", args={"h"}},
{event="char", args={"e"}},
{event="char", args={"y"}}
}
mainFrame:addButton():setText("inject"):onClick(function() aProgram:injectEvents(events) end):show()
```
## getQueuedEvents
If the program is paused, incomming events will be inserted into a queued events table. As soon as the program is unpaused, the queued events table will be empty
#### Returns:
1. `table` a table - {event="event", args={"a", "b",...}}
#### Usage:
* prints the queued events table
```lua
local mainFrame = basalt.createFrame():show()
local aProgram = mainFrame:addProgram():execute("rom/programs/shell.lua"):show()
mainFrame:addButton():setText("inject"):onClick(function() basalt.debug(aProgram:getQueuedEvents()) end):show()
```
## updateQueuedEvents
Here you can manipulate the queued events table
#### Parameters:
1. `table` a table, items should be {event="event", args={para1, para2, para3, para4}}
#### Returns:
1. `object` The object in use
```lua
local mainFrame = basalt.createFrame():show()
local aProgram = mainFrame:addProgram():execute("rom/programs/shell.lua"):show()
mainFrame:addButton():setText("inject"):onClick(function()
local events = aProgram:getQueuedEvents()
table.insert(events,1,{event="char", args={"w"}}
aProgram:updateQueuedEvents(events)
end):show()
```

134
docs/objects/Progressbar.md Normal file
View File

@@ -0,0 +1,134 @@
Progressbars are objects to visually display the current state of your progression. They always go from 0 to 100 (%) - no matter how big they are. which means if you
want to add some energy progress you have to do simple maths: currentValue / maxValue * 100
Here are all possible functions available for progessbars. Remember progressbar inherits from [Object](objects/Object.md)
## setDirection
Sets the direction in which the bar should be expanding.
#### Parameters:
1. `number` x direction (0 = left to right, 1 = top to bottom, 2 = right to left and 3 = bottom to top)
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a progressbar and sets the direction from bottom to top
```lua
local mainFrame = basalt.createFrame()
local aProgressbar = mainFrame:addProgressbar()
aProgressbar:setDirection(3)
```
```xml
<frame direction="3"></frame>
```
## setProgress
This is the function you need to call if you want the progression to change.
#### Parameters:
1. `number` a number from 0 to 100
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a progressbar and sets the current progress to 50
```lua
local mainFrame = basalt.createFrame()
local aProgressbar = mainFrame:addProgressbar()
aProgressbar:setProgress(50)
```
## getProgress
Returns the current progress status
#### Returns:
1. `number` progress (0-100)
#### Usage:
* Creates a progressbar, sets the current progress to 50 and prints the current progress
```lua
local mainFrame = basalt.createFrame()
local aProgressbar = mainFrame:addProgressbar()
aProgressbar:setProgress(50)
basalt.debug(aProgressbar:getProgress())
```
## setProgressBar
This function will change the visual display of your progress bar
#### Parameters:
1. `number|color` the expanding progress bar color
2. `char` optional - the bar symbol - default is " " (space)
3. `number|color` optional - the bar symbol color
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a progressbar and sets the progressbar color to green
```lua
local mainFrame = basalt.createFrame()
local aProgressbar = mainFrame:addProgressbar()
aProgressbar:setProgressBar(colors.green, colors.yellow, colors.red)
```
```xml
<progressbar progressColor="green" progressSymbol="yellow" progressSymbolColor="red" />
```
## setBackgroundSymbol
Will change the default background symbol (default is " " - space)
#### Parameters:
1. `char` the background symbol
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a progressbar and sets the progressbar background symbol to X
```lua
local mainFrame = basalt.createFrame()
local aProgressbar = mainFrame:addProgressbar()
aProgressbar:setBackgroundSymbol("X")
```
```xml
<progressbar backgroundSymbol="X" />
```
# Events
## onProgressDone
`onProgressDone(self)`<br>
A custom event which gets triggered as soon as the progress reaches 100.
Here is a example on how to add a onProgressDone event to your progressbar:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame()
local aProgressbar = mainFrame:addProgressbar()
function progressDone()
basalt.debug("The Progressbar reached 100%!")
end
aProgressbar:onProgressDone(progressDone)
```
Here is also a example how this is done with xml:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame()
basalt.setVariable("progressDone", function()
basalt.debug("The Progressbar reached 100%!")
end)
```
```xml
<progressbar onDone="progressDone" />
```

229
docs/objects/Radio.md Normal file
View File

@@ -0,0 +1,229 @@
Radios are objects which you can freely place, and the user is then able to select a single item.
If you want to access values inside items this is how the table for single items is made (just a example):
```lua
item = {
text="1. Entry",
bgCol=colors.black,
fgCol=colors.white
args = {}
}
```
Remember Radios also inherits from [Object](objects/Object.md)
## addItem
Adds a item to the radio
#### Parameters:
1. `string` The entry name
2. `number` x position
3. `number` y position
2. `number|color` unique default background color - optional
3. `number|color` unique default text color - optional
4. `any` any value - you could access this later in a :onChange() event (you need to use :getValue()) - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default radio with 3 entries
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
```
```xml
<radio>
<item><text>1. Entry</text><x>5</x><y>2</y></item>
<item><text>2. Entry</text><x>5</x><y>4</y><bg>yellow</bg></item>
<item><text>3. Entry</text><x>5</x><y>6</y><bg>yellow</bg><fg>green</fg></item>
</radio>
```
## removeItem
Removes a item from the radio
#### Parameters:
1. `number` The index which should get removed
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default radio with 3 entries and removes the second one.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
aRadio:removeItem(2)
```
## editItem
Edits a item from the radio
#### Parameters:
1. `number` The index which should be edited
2. `string` The new item name
3. `number` the new x position
4. `number` the new y position
3. `number|color` the new item background color - optional
4. `number|color` The new item text color - optional
5. `any` New additional information - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default radio with 3 entries and changes the second one.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
aRadio:editItem(2, "Still 2. Entry", 5, 4, colors.red)
```
## getItem
Returns a item by index
#### Parameters:
1. `number` The index which should be returned
#### Returns:
1. `table` The item table example: {text="1. Entry", bgCol=colors.black, fgCol=colors.white}
#### Usage:
* Creates a default radio with 3 entries and edits the second one.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
basalt.debug(aRadio:getItem(2).text)
```
## getItemCount
Returns the current item count
#### Returns:
1. `number` The item radio count
#### Usage:
* Creates a default radio with 3 entries and prints the current item count.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
basalt.debug(aRadio:getItemCount())
```
## getAll
Returns all items as table
#### Returns:
1. `table` All items
#### Usage:
* Creates a default menubar with 3 entries and prints a table.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
basalt.debug(aRadio:getAll())
```
## selectItem
selects a item in the radio (same as a player would click on a item)
#### Parameters:
1. `number` The index which should get selected
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default radio with 3 entries and selects the second entry.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
aRadio:selectItem(2)
```
## clear
Removes all items.
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default radio with 3 entries and removes them immediatley. Which makes no sense.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
aRadio:clear()
```
## getItemIndex
returns the item index of the currently selected item
#### Returns:
1. `number` The current index
#### Usage:
* Creates a default radio with 3 entries selects the second entry and prints the currently selected index.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
aRadio:selectItem(2)
basalt.debug(aRadio:getItemIndex())
```
## setSelectedItem
Sets the background and the foreground of the item which is currently selected
#### Parameters:
1. `number|color` The background color which should be used
2. `number|color` The text color which should be used
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default radio with 4 entries and sets the selection background color to green.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
aRadio:addItem("4. Entry",5,8)
aRadio:setSelectedItem(colors.green, colors.red)
```
```xml
<radio selectionBG="green" selectionFG="red">
<item><text>1. Entry</text><x>5</x><y>2</y></item>
<item><text>2. Entry</text><x>5</x><y>4</y><bg>yellow</bg></item>
<item><text>3. Entry</text><x>5</x><y>6</y><bg>yellow</bg><fg>green</fg></item>
</radio>
```

108
docs/objects/Scrollbar.md Normal file
View File

@@ -0,0 +1,108 @@
Scrollbars are objects, the user can scroll vertically or horizontally, this will change a value, which you can access by :getValue().<br>
Remember scrollbar also inherits from [Object](objects/Object.md)
## setSymbol
Changes the scrollbar symbol, default is " "
#### Parameters:
1. `string` symbol
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new scrollbar and changes the symbol to X
```lua
local mainFrame = basalt.createFrame()
local scrollbar = mainFrame:addScrollbar():setSymbol("X")
```
```xml
<scrollbar symbol="X" />
```
## setBackgroundSymbol
Changes the symbol in the background, default is "\127"
#### Parameters:
1. `string` symbol
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new scrollbar and changes the background symbol to X
```lua
local mainFrame = basalt.createFrame()
local scrollbar = mainFrame:addScrollbar():setBackgroundSymbol("X")
```
```xml
<scrollbar backgroundSymbol="X" />
```
## setBarType
Changes the scrollbar to be vertical or horizontal, default is vertical
#### Parameters:
1. `string` vertical or horizontal
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new scrollbar and changes the bar type to horizontal
```lua
local mainFrame = basalt.createFrame()
local scrollbar = mainFrame:addScrollbar():setBarType("horizontal")
```
```xml
<scrollbar barType="horizontal" />
```
## setMaxValue
the default max value is always the width (if horizontal) or height (if vertical), if you change the max value the bar will always calculate the value based on its width or height - example: you set the max value to 100, the height is 10 and it is a vertical bar, this means if the bar is on top, the value is 10, if the bar goes one below, it is 20 and so on.
#### Parameters:
1. `number` maximum
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new scrollbar and changes the max value to 20
```lua
local mainFrame = basalt.createFrame()
local scrollbar = mainFrame:addScrollbar():setMaxValue(20)
```
```xml
<scrollbar maxValue="20" />
```
## setIndex
Changes the current index to your choice, for example you could create a button which scrolls up to 1 by using :setIndex(1)
#### Parameters:
1. `number` the index
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new scrollbar and changes the index to 1 as soon as the button got clicked
```lua
local mainFrame = basalt.createFrame()
local scrollbar = mainFrame:addScrollbar():setMaxValue(20)
local button = mainFrame:addButton(function()
scrollbar:setIndex(1)
end)
```
```xml
<scrollbar index="2" />
```
## getIndex
Returns the current index
#### Returns:
1. `number` index

108
docs/objects/Slider.md Normal file
View File

@@ -0,0 +1,108 @@
Sliders are objects, the user can scroll vertically or horizontally, this will change a value, which you can access by :getValue().<br>
Remember slider also inherits from [Object](objects/Object.md)
## setSymbol
Changes the slider symbol, default is " "
#### Parameters:
1. `string` symbol
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new slider and changes the symbol to X
```lua
local mainFrame = basalt.createFrame()
local slider = mainFrame:addSlider():setSymbol("X")
```
```xml
<slider symbol="X" />
```
## setBackgroundSymbol
Changes the symbol in the background, default is "\140"
#### Parameters:
1. `string` symbol
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new slider and changes the background symbol to X
```lua
local mainFrame = basalt.createFrame()
local slider = mainFrame:addSlider():setBackgroundSymbol("X")
```
```xml
<slider backgroundSymbol="X" />
```
## setBarType
Changes the slider to be vertical or horizontal, default is horizontal
#### Parameters:
1. `string` vertical or horizontal
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new slider and changes the bar type to horizontal
```lua
local mainFrame = basalt.createFrame()
local slider = mainFrame:addSlider():setBarType("vertical")
```
```xml
<slider barType="vertical" />
```
## setMaxValue
the default max value is always the width (if horizontal) or height (if vertical), if you change the max value the bar will always calculate the value based on its width or height - example: you set the max value to 100, the height is 10 and it is a vertical bar, this means if the bar is on top, the value is 10, if the bar goes one below, it is 20 and so on.
#### Parameters:
1. `number` maximum
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new slider and changes the max value to 20
```lua
local mainFrame = basalt.createFrame()
local slider = mainFrame:addSlider():setMaxValue(20)
```
```xml
<slider maxValue="20" />
```
## setIndex
Changes the current index to your choice, for example you could create a button which scrolls up to 1 by using :setIndex(1)
#### Parameters:
1. `number` the index
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new slider and changes the index to 1 as soon as the button got clicked
```lua
local mainFrame = basalt.createFrame()
local slider = mainFrame:addSlider():setMaxValue(20)
local button = mainFrame:addButton(function()
slider:setIndex(1)
end)
```
```xml
<slider index="2" />
```
## getIndex
Returns the current index
#### Returns:
1. `number` index

161
docs/objects/Textfield.md Normal file
View File

@@ -0,0 +1,161 @@
Textfields are objects, where the user can write something on multiple lines. it act's like the default edit script (without coloring)<br>
Remember textfield inherits from [Object](objects/Object.md)
## getLines
Returns all lines
#### Returns:
1. `table` lines
#### Usage:
* Prints all lines
```lua
local mainFrame = basalt.createFrame("myFirstFrame"):show()
local aTextfield = mainFrame:addTextfield("myFirstTextfield"):show()
basalt.debug(aTextfield:getLines())
```
## getLine
Returns the line on index position
#### Parameteres:
1. `number` index
#### Returns:
1. `string` line
#### Usage:
* Prints one line
```lua
local mainFrame = basalt.createFrame("myFirstFrame"):show()
local aTextfield = mainFrame:addTextfield("myFirstTextfield"):show()
basalt.debug(aTextfield:getLine(1))
```
## editLine
Edits the line on index position
#### Parameteres:
1. `number` index
2. `string` text
#### Returns:
1. `object` The object in use
#### Usage:
* Edits the line
```lua
local mainFrame = basalt.createFrame("myFirstFrame"):show()
local aTextfield = mainFrame:addTextfield("myFirstTextfield"):show()
basalt.debug(aTextfield:editLine(1, "Hello!"))
```
## addLine
Adds a line on index position
#### Parameteres:
1. `string` text
2. `number` index
#### Returns:
1. `object` The object in use
#### Usage:
* Adds a line
```lua
local mainFrame = basalt.createFrame("myFirstFrame"):show()
local aTextfield = mainFrame:addTextfield("myFirstTextfield"):show()
basalt.debug(aTextfield:addLine("Hello!", 1))
```
```xml
<textfield>
<lines>
<line>Hello!</line>
</lines>
</textfield>
```
## removeLine
Removes the line on index position
#### Parameteres:
1. `number` index
2. `string` text
#### Returns:
1. `object` The object in use
#### Usage:
* Removes a line
```lua
local mainFrame = basalt.createFrame("myFirstFrame"):show()
local aTextfield = mainFrame:addTextfield("myFirstTextfield"):show()
basalt.debug(aTextfield:removeLine())
```
## getTextCursor
Gets text cursor position
#### Returns:
1. `number` x position
2. `number` y position
## addKeywords
Adds keywords for special coloring
#### Parameteres:
1. `number|color` color of your choice
2. `table` a list of keywords which should be colored example: {"if", "else", "then", "while", "do"}
#### Returns:
1. `object` The object in use
#### Usage:
* Changes the color of some words to purple
```lua
local mainFrame = basalt.createFrame()
local aTextfield = mainFrame:addTextfield():addKeywords(colors.purple, {"if", "else", "then", "while", "do", "hello"})
```
```xml
<textfield>
<keywords>
<purple>
<keyword>if</keyword>
<keyword>else</keyword>
<keyword>then</keyword>
<keyword>while</keyword>
<keyword>do</keyword>
<keyword>hello</keyword>
</purple>
</keywords>
</textfield>
```
## addRule
Adds a new rule for special coloring
#### Parameteres:
1. `string` a pattern - check out this page: (https://riptutorial.com/lua/example/20315/lua-pattern-matching)
2. `number|color` text color
3. `number|color` background color - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Changes the color of all numbers
```lua
local mainFrame = basalt.createFrame()
local aTextfield = mainFrame:addTextfield():addRule("%d", colors.lightBlue)
```
```xml
<textfield>
<rules>
<rule>
<pattern>%d</pattern>
<fg>lightBlue</fg>
</rule>
</rules>
</textfield>
```

65
docs/objects/Thread.md Normal file
View File

@@ -0,0 +1,65 @@
Threads are being executed simultaneously.
<br>
## start
starts a new thread and executes the function
#### Parameters:
1. `function` the function which should be executed
#### Returns:
1. `object` The object in use
#### Usage:
* Starts a new thread
```lua
local mainFrame = basalt.createFrame()
local aThread = mainFrame:addThread()
local function randomThreadFunction()
while true do
basalt.debug("Thread is active")
os.sleep(1) -- a sleep/coroutine.yield() or pullEvent is required otherwise we will never come back to the main program (error)
end
end
aThread:start(randomThreadfunction)
```
you are also able to start threads via xml:
```lua
basalt.setVariable("myThread", function() while true do os.sleep(1) end end)
```
```xml
<thread thread="myThread" start="true"/>
```
## stop
stops the thread
#### Returns:
1. `object` The object in use
#### Usage:
* Stops the current running thread by clicking on a button
```lua
local mainFrame = basalt.createFrame()
local aThread = mainFrame:addThread()
local function randomThreadFunction()
while true do
basalt.debug("Thread is active")
os.sleep(1) -- a sleep/coroutine.yield() or pullEvent is required otherwise we will never come back to the main program (error)
end
end
aThread:start(randomThreadfunction)
local aButton = mainFrame:addButton():setText("Stop Thread"):onClick(function() aThread:stop() end)
```
## getStatus
gets the current thread status
#### Returns:
1. `string` current status - ("running", "normal", "suspended", "dead")
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local aThread = mainFrame:addThread()
basalt.debug(aThread:getStatus())
```

84
docs/objects/Timer.md Normal file
View File

@@ -0,0 +1,84 @@
Timers can call your functions delay and repeat it as often as you wish
<br>
## setTime
sets the time the timer should wait after calling your function
#### Parameters:
1. `number` the time to delay
2. `number` how often it should be repeated -1 is infinite
#### Returns:
1. `object` The object
```lua
local mainFrame = basalt.createFrame()
local aTimer = mainFrame:addTimer()
aTimer:setTime(2)
```
```xml
<timer time="2" repeat="1"/>
```
## start
Starts the timer
#### Returns:
1. `object` The object
```lua
local mainFrame = basalt.createFrame()
local aTimer = mainFrame:addTimer()
aTimer:setTime(2):start()
```
```xml
<timer time="2" start="true"/>
```
## cancel
Cancels the timer
#### Returns:
1. `object` The object
```lua
local mainFrame = basalt.createFrame()
local aTimer = mainFrame:addTimer()
aTimer:setTime(2):start()
aTimer:cancel()
```
# Events
## onCall
`onCall(self)`<br>
A custom event which gets triggered as soon as the current timer has finished
Here is a example on how to add a onCall event to your timer:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame()
local aTimer = mainFrame:addTimer()
function call()
basalt.debug("The timer has finished!")
end
aTimer:onCall(call)
```
Here is also a example how this is done with xml:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame()
basalt.setVariable("call", function()
basalt.debug("The timer has finished!")
end)
```
```xml
<progressbar onDone="call" />
```

41
docs/tips/buttons.md Normal file
View File

@@ -0,0 +1,41 @@
Here I want to explain to you how you would create a button with the default color gray, and as long as the user is clicking on the button it will change its color to black (the default frame-background is lightGray).
To make this possible the button needs 1 onClick event, 1 onClickUp event and 1 onLoseFocus event.
Very interesting sidetip: events can hold multiple functions!<br>
**Example snippet:**
```lua
local function buttonColoring()
-- here you can add some coloring for your button
end
local function buttonLogic()
-- here you can add some logic for your button
end
local button = mainFrame:addButton("ExampleButton"):show()
button:onClick(buttonColoring):onClick(buttonLogic) -- yes this would work, if not its a bug!
```
This means you can create a function wich handles only the coloring side of your button, and if your button also needs some logic you just create your own unique function for that and add it to your button.
With this knowledge we create now a function where we pass a button-object as parameter and this will setup the coloring of our button:
**Example snippet:**
```lua
local basalt = dofile("basalt.lua")
local mainFrame = basalt.createFrame("mainFrame"):show()
local button = mainFrame:addButton("firstButton"):setPosition(3,3):setSize(12,3):setText("Click me"):setBackground(colors.gray):setForeground(colors.black):show()
local button2 = mainFrame:addButton("secondButton"):setPosition(25,3):setSize(16,3):setText("Another Btn"):setBackground(colors.gray):setForeground(colors.black):show()
local function setupButtonColoring(btn)
btn:onClick(function() btn:setBackground(colors.black) btn:setForeground(colors.lightGray) end)
btn:onClickUp(function() btn:setBackground(colors.gray) btn:setForeground(colors.black) end)
btn:onLoseFocus(function() btn:setBackground(colors.gray) btn:setForeground(colors.black) end)
end
setupButtonColoring(button)
setupButtonColoring(button2)
basalt.autoUpdate()
```
Now you've got a function which sets your buttons up.

82
docs/tips/design.md Normal file
View File

@@ -0,0 +1,82 @@
Hello! This page contains some tips on how to create cool designs with Basalt
To understand this page, it is recommended to familiarize yourself with [Animations](../objects/Animation.md) as animations are important for creating complex designs
Let us begin with simple things:
## Recolor objects
Let's create a Button:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame():setBackground(colors.black):show()
local aButton = mainFrame:addButton():setSize(10, 3):setText("Beautiful"):setBackground(colors.gray):show()
```
Here lets make use of the event system:<br>
```lua
local function changeButtonColor(self,event,typ,x,y)
if(event=="mouse_click")then
self:setBackground(colors.lightGray)
end
if(event=="mouse_up")then
self:setBackground(colors.gray)
end
end
local function buttonLogic()
-- here you can do some logic when button gets the mouse_up event
end
aButton:onClick(changeButtonColor) -- button color change on click
aButton:onClickUp(changeButtonColor) -- button color change on click up
aButton:onClickUp(buttonLogic) -- button logic on click up
aButton:onLoseFocus(function(self) self:setBackground(colors.gray) end) -- if user is clicking on the button and dragging out of button size this event will change the bg color back to gray
```
## Fade In/Out Objects
instead of recoloring we are also able to slowly reposition the button, something like fade in:<br>
```lua
local buttonAnimation = mainFrame:addAnimation()
local function fadeButtonIn(btn)
if(btn.x < 5)then
btn:setPosition(1,0,"r")
else
buttonAnimation:cancel() -- here you cancel the loop
end
end
buttonAnimation:wait(0.1):add(function() fadeButtonIn(aButton) end):play(true) -- with play(true) you will create a infinite loop
```
This is also possible with entire frames and its children objects. So keep that in mind if you want to create something like a bigger panel to the right or a menu bar
## How To use XML
Here is a example on how to create a cool looking frame by using xml:
```xml
<frame width="parent.w/2" bg="gray" scrollable="true" importantScroll="true">
<button x="2" y="2" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 1!"/>
<button x="2" y="6" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 2!"/>
<button x="2" y="10" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 3!"/>
<button x="2" y="14" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 4!"/>
<button x="2" y="18" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 5!"/>
<button x="2" y="22" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 6!"/>
<button x="2" y="26" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 7!"/>
</frame>
<frame x="parent.w/2+1" width="parent.w/2+1" bg="black">
<textfield bg="gray" x="2" y="2" width="parent.w-2">
<lines>
<line>This is line 1.</line>
<line>And this is line 2.</line>
</lines>
</textfield>
<label anchor="bottomLeft" x="2" y="0" text="I love labels!" fg="lightGray"/>
</frame>
```
in your lua code you just have to add this layout to your frame:
```lua
local basalt = require("Basalt")
basalt.createFrame():addLayout("example.xml")
basalt.autoUpdate()
```

34
docs/tips/events.md Normal file
View File

@@ -0,0 +1,34 @@
## Short way of adding functions to events
Not everyone knows that a function (or in other words a method) does not need to have a name. Instead of a function name you are also able to add the function itself as a argument.
Both do the exact same thing:
```lua
local function clickButton()
basalt.debug("I got clicked!")
end
button:onClick(clickButton)
```
```lua
button:onClick(function()
basalt.debug("I got clicked!")
end)
```
## Using isKeyDown for shortcuts
there is also a function with which you can check if the user is holding a key down, it is called `basalt.isKeyDown()`. It's especially useful for click events.
Let us say you want a button to execute something, but if you are holding ctrl down, something in the execution should get changed. This is how you would
achieve that:
```lua
button:onClick(function()
if(basalt.isKeyDown(keys.leftCtrl)then
basalt.debug("Ctrl is down!")
else
basalt.debug("Ctrl is up!")
end
end)
```
Make sure to always use the available `keys` table: https://computercraft.info/wiki/Keys_(API)

56
docs/tips/logic.md Normal file
View File

@@ -0,0 +1,56 @@
You question yourself how you can execute your own logic while basalt is also active? There are multiple ways of doing that:
## Method 1:
Using parallel.waitForAll
```lua
local basalt = dofile("basalt.lua")
local mainFrame = basalt.createFrame("mainFrame"):show()-- lets create a frame and a button without functionality
mainFrame:addButton("aButton"):onClick(function() end):show()
local function yourCustomHandler()
while true do
-- add your logic here
os.sleep(1) -- you need something which calls coroutine.yield(), yes os.sleep does that os.pullEvent() aswell
end
end
parallel.waitForAll(basalt.autoUpdate, yourCustomHandler) -- here it will handle your function (yourCustomHandler) and basalts handlers at the time
```
You can read [here (tweaked.cc)](https://tweaked.cc/module/parallel.html) what exactly parallel.waitForAll() does
## Method 2:
Using threads
```lua
local basalt = dofile("basalt.lua")
local mainFrame = basalt.createFrame("mainFrame"):show()-- lets create a frame, a button without functionality and a thread
mainFrame:addButton("aButton"):onClick(function() end):show()
local thread = mainFrame:addThread("customHandlerExecutingThread")
local function yourCustomHandler()
while true do
-- add your logic here
os.sleep(1) -- you need something which calls coroutine.yield(), yes os.sleep does that os.pullEvent() aswell
end
end
thread:start(yourCustomHandler) -- this will create a coroutine and starts the coroutine, os.sleep does the rest, so you just have to call start once.
```
## Method 3:
Using timers
```lua
local basalt = dofile("basalt.lua")
local mainFrame = basalt.createFrame("mainFrame"):show()-- lets create a frame, a button without functionality and a timer
mainFrame:addButton("aButton"):onClick(function() end):show()
local timer = mainFrame:addTimer("customHandlerExecutingTimer")
local function yourCustomHandler()
-- add your logic here
end
timer:onCall(yourCustomHandler):setTime(1, -1):start() -- this will call your function every second until you :cancel() the timer
```

View File

@@ -0,0 +1,79 @@
--Basalt configurated installer
local filePath = "basalt.lua" --here you can change the file path default: basalt.lua
if not(fs.exists(filePath))then
shell.run("pastebin run ESs1mg7P packed true "..filePath) -- this is an alternative to the wget command
end
local basalt = require(filePath:gsub(".lua", "")) -- here you can change the variablename in any variablename you want default: basalt
local w, h = term.getSize()
local main = basalt.createFrame("mainFrame"):show()
local objFrame = main:addFrame("objectFrame"):setPosition(1,2):setBackground(colors.lightGray):setSize(w, h-1):show()
local programFrame = main:addFrame("programFrame"):setPosition(1,2):setBackground(colors.lightGray):setSize(w, h-1)
local editorFrame = main:addFrame("editorFrame"):setPosition(1,2):setBackground(colors.lightGray):setSize(w, h-1)
local menuBar = main:addMenubar("mainMenuBar"):addItem("Object"):addItem("Program"):addItem("Editor"):setBackground(colors.gray):setSize(w, 1):setSpace(5):setScrollable():show()
menuBar:onChange(function(self)
objFrame:hide()
programFrame:hide()
editorFrame:hide()
if(self:getValue().text=="Object")then
objFrame:show()
elseif(self:getValue().text=="Program")then
programFrame:show()
elseif(self:getValue().text=="Editor")then
editorFrame:show()
end
end)
local function visualButton(btn)
btn:onClick(function(self) btn:setBackground(colors.black) btn:setForeground(colors.lightGray) end)
btn:onClickUp(function(self) btn:setBackground(colors.gray) btn:setForeground(colors.black) end)
btn:onLoseFocus(function(self) btn:setBackground(colors.gray) btn:setForeground(colors.black) end)
end
--Object Frame:
visualButton(objFrame:addButton("exampleButton"):setText("Button"):setSize(12,3):setPosition(2,2):onClick(function() end):show())
local sliderValue = objFrame:addLabel("sliderValueLabel"):setPosition(11,6):setText("1"):show()
objFrame:addSlider("exampleSlider"):setPosition(2,6):onChange(function(self) sliderValue:setText(self:getValue()) end):show()
objFrame:addInput("exampleText"):setPosition(2,8):setSize(16,1):setBackground(colors.black):setForeground(colors.lightGray):setDefaultText("Text Example", colors.gray):show()
objFrame:addInput("exampleNumber"):setPosition(2,10):setSize(16,1):setBackground(colors.black):setForeground(colors.lightGray):setDefaultText("Number Example", colors.gray):setInputType("number"):show()
objFrame:addInput("examplePassword"):setPosition(2,12):setSize(16,1):setBackground(colors.black):setForeground(colors.lightGray):setDefaultText("Password Example", colors.gray):setInputType("password"):show()
objFrame:addList("exampleList"):setPosition(20,2):addItem("1. Entry"):addItem("2. Entry"):addItem("3. Entry"):addItem("4. Entry"):addItem("5. Entry"):addItem("6. Entry"):addItem("7. Entry"):addItem("8. Entry"):show()
objFrame:addDropdown("exampleDropdown"):setPosition(37,2):addItem("1. Entry"):addItem("2. Entry"):addItem("3. Entry"):addItem("4. Entry"):addItem("5. Entry"):addItem("6. Entry"):addItem("7. Entry"):addItem("8. Entry"):show()
objFrame:addCheckbox("exampleCheckbox1"):setPosition(20,10):show()
objFrame:addLabel("checkbox1Label"):setPosition(22,10):setText("Checkbox 1"):show()
objFrame:addCheckbox("exampleCheckbox2"):setPosition(20,12):show()
objFrame:addLabel("checkbox2Label"):setPosition(22,12):setText("Checkbox 2"):show()
objFrame:addRadio("exampleRadio"):setPosition(35,10):addItem("", 1, 1):addItem("", 1, 3):addItem("", 1, 5):setSelectedItem(colors.gray, colors.black):show()
objFrame:addLabel("radio1Label"):setPosition(37,10):setText("Radio 1"):show()
objFrame:addLabel("radio2Label"):setPosition(37,12):setText("Radio 2"):show()
objFrame:addLabel("radio3Label"):setPosition(37,14):setText("Radio 3"):show()
objFrame:addScrollbar("exampleScrollbar"):setPosition(objFrame:getWidth(),1):setMaxValue(objFrame:getHeight()):setSize(1,objFrame:getHeight()):setSymbolSize(3):ignoreOffset():onChange(function(self) objFrame:setOffset(0, (self:getValue()-1)) end):setAnchor("topRight"):show():setZIndex(15)
local prog = objFrame:addProgressbar("exampleProgressbar"):setAnchor("bottomLeft"):setSize(30, 3):setBackground(colors.gray):setPosition(2,3):onProgressDone(function()
basalt.debug("Progress done!")
end):show()
local timer = objFrame:addTimer("exampleTimer"):setTime(1, -1):onCall(function()
prog:setProgress(prog:getProgress()+2)
end):start()
--Program Frame:
local programCount = 1
visualButton(programFrame:addButton("exampleButton"):setText("Add Shell"):setSize(13,3):setPosition(2,2):onClick(function()
local newProgramWindow = programFrame:addFrame("programFrame"..programCount):setMoveable(true):setBar("Console", colors.black, colors.lightGray):showBar():setPosition(3,3):setSize(26,12):show()
local program = newProgramWindow:addProgram("exampleProgram"..programCount):setSize(26,11):setPosition(1,2):setBackground(colors.black):show()
program:execute("rom/programs/shell.lua")
programCount = programCount + 1
end):show())
-- Editor Frame:
editorFrame:addTextfield("exampleTextfield"):setPosition(2,2):setBackground(colors.black):setSize(w-2,h-3):setForeground(colors.white):show()
basalt.autoUpdate()

162
examples/basaltPreview2.lua Normal file
View File

@@ -0,0 +1,162 @@
local basalt = require("Basalt")
basalt.setVariable("buttonColor", basalt.shedule(function(self)
self:setBackground(colors.black)
self:setForeground(colors.lightGray)
os.sleep(0.1)
self:setBackground(colors.gray)
self:setForeground(colors.black)
end))
local main
basalt.setVariable("ex1", function()
main:addAnimation():setObject(main):setAutoDestroy():offset(0,0,1):play()
end)
basalt.setVariable("ex1Top", function()
local example1 = main:getDeepObject("example1")
example1:addAnimation():setObject(example1):setAutoDestroy():offset(0,0,1):play()
end)
basalt.setVariable("ex2", function()
main:addAnimation():setObject(main):setAutoDestroy():offset(main:getWidth(),0,1):play()
end)
basalt.setVariable("p1", function()
local example2 = main:getDeepObject("example2")
example2:addAnimation():setObject(example2):setAutoDestroy():offset(0,0,1):play()
end)
basalt.setVariable("p2", function()
local example2 = main:getDeepObject("example2")
example2:addAnimation():setObject(example2):setAutoDestroy():offset(0,example2:getHeight(),1):play()
end)
basalt.setVariable("p3", function()
local example2 = main:getDeepObject("example2")
example2:addAnimation():setObject(example2):setAutoDestroy():offset(0,example2:getHeight()*2,1):play()
end)
basalt.setVariable("ex3", function()
main:addAnimation():setObject(main):setAutoDestroy():offset(main:getWidth()*2,0,1):play()
end)
basalt.setVariable("e1", function()
local example3 = main:getDeepObject("example3")
example3:addAnimation():setObject(example3):setAutoDestroy():offset(0,0,1):play()
end)
basalt.setVariable("e2", function()
local example3 = main:getDeepObject("example3")
example3:addAnimation():setObject(example3):setAutoDestroy():offset(0,example3:getHeight(),1):play()
end)
basalt.setVariable("e3", function()
local example3 = main:getDeepObject("example3")
example3:addAnimation():setObject(example3):setAutoDestroy():offset(0,example3:getHeight()*2,1):play()
end)
basalt.setVariable("ex4", function()
main:addAnimation():setObject(main):setAutoDestroy():offset(main:getWidth()*3,0,1):play()
end)
basalt.setVariable("progressChange", function(self)
main:getDeepObject("progressLabel"):setText(self:getValue().."%")
end)
basalt.setVariable("pauseP2", function()
main:getDeepObject("program2"):pause()
end)
basalt.setVariable("pauseP3", function()
main:getDeepObject("program3"):pause()
end)
basalt.setVariable("startAnimation", function()
main:getDeepObject("animation1"):play()
end)
basalt.setVariable("disableStartButton", function()
main:getDeepObject("animationButton"):disable()
end)
basalt.setVariable("enableStartButton", function()
main:getDeepObject("animationButton"):enable()
end)
basalt.setVariable("onTextfieldFocus", function()
main:getDeepObject("coolTextfield"):setForeground(colors.lightGray)
main:getDeepObject("textfieldAnimLoseFocus"):cancel()
main:getDeepObject("textfieldAnimFocus"):play()
end)
basalt.setVariable("onTextfieldLoseFocus", function()
main:getDeepObject("coolTextfield"):setForeground(colors.gray)
main:getDeepObject("textfieldAnimFocus"):cancel()
main:getDeepObject("textfieldAnimLoseFocus"):play()
end)
basalt.setVariable("makeButtonVisible", function()
main:getDeepObject("showAnimBtn1"):show()
main:getDeepObject("showAnimBtn2"):show()
main:getDeepObject("showAnimBtn3"):show()
end)
basalt.setVariable("dragPosition", function(ob, ev, bt, x, y, dragStartX, dragStartY, mouseX, mouseY)
ob:setPosition(x, y)
end)
local function inject(prog, key)
local events = prog:getQueuedEvents()
table.insert(events, 1, {event="key", args = {key}})
prog:injectEvents(events)
prog:updateQueuedEvents({})
end
basalt.setVariable("p3Up", function()
local program = main:getDeepObject("program3")
inject(program, keys.w)
end)
basalt.setVariable("p3Down", function()
local program = main:getDeepObject("program3")
inject(program, keys.s)
end)
basalt.setVariable("p3Left", function()
local program = main:getDeepObject("program3")
inject(program, keys.a)
end)
basalt.setVariable("p3Right", function()
local program = main:getDeepObject("program3")
inject(program, keys.d)
end)
basalt.setVariable("noDrag", function(self)
return false
end)
basalt.setVariable("openSidebar", function(self)
main:addAnimation():setObject(main:getDeepObject("sidebar")):setAutoDestroy():move(-12,1,1):play()
end)
basalt.setVariable("closeSidebar", function(self)
main:addAnimation():setObject(main:getDeepObject("sidebar")):setAutoDestroy():move(2,1,1):play()
end)
basalt.setVariable("progressTheProgressbar", function()
os.sleep(1)
local progressbar = main:getDeepObject("progressBar")
local progress = 0
while true do
progressbar:setProgress(progress)
progress = progress+0.25
os.sleep(1)
end
end)
main = basalt.createFrame():addLayout("basaltPreview2.xml")
basalt.autoUpdate()

209
examples/basaltPreview2.xml Normal file
View File

@@ -0,0 +1,209 @@
<frame onScroll="ex1OnScroll" id="example1" width="parent.w" height="parent.w" bg="lightGray" maxScroll="32" scrollable="true">
<label text="Objects" font="2" x="16" y="2" />
<button onClick="buttonColor" onClick="ex2" anchor="topRight" height="1" width="8" x="-7" y="2" text="Next" />
<button onDrag="dragPosition" x="2" y="6" width="parent.w/2-2" height="5" />
<button onDrag="dragPosition" x="parent.w/2+1" y="6" width="parent.w/2-2" height="5" />
<frame y="13" x="2" width="parent.w/2-2" height="16" bg="black" scrollable="true" importantScroll="true">
<button onClick="buttonColor" width="parent.w-2" x="2" y="2" text="Example Button 1" />
<button onClick="buttonColor" width="parent.w-2" x="2" y="6" text="Example Button 2" />
<button onClick="buttonColor" width="parent.w-2" x="2" y="10" text="Example Button 3" />
<button onClick="buttonColor" width="parent.w-2" x="2" y="14" text="Example Button 4" />
<button onClick="buttonColor" width="parent.w-2" x="2" y="18" text="Example Button 5" />
<button onClick="buttonColor" width="parent.w-2" x="2" y="22" text="Example Button 6" />
</frame>
<frame y="13" x="parent.w/2+1" width="parent.w/2-2" height="16" bg="black" scrollable="true" importantScroll="true">
<label x="2" y="2" text="Radios and Checkboxes:" fg="lightGray" />
<radio x="2" y="4" bg="gray" fg="lightGray" boxBG="black" boxFG="lightGray" selectionBG="black" inactiveBoxBG="black">
<item><text>Radio 1</text><x>2</x><y>1</y><bg>black</bg></item>
<item><text>Radio 2</text><x>2</x><y>3</y><bg>black</bg></item>
<item><text>Radio 3</text><x>2</x><y>5</y><bg>black</bg></item>
<item><text>Radio 4</text><x>2</x><y>7</y><bg>black</bg></item>
<item><text>Radio 5</text><x>2</x><y>9</y><bg>black</bg></item>
</radio>
<checkbox x="3" y="15" /><label x="5" y="15" text="Checkbox 1" fg="lightGray" />
<checkbox x="3" y="17" /><label x="5" y="17" text="Checkbox 2" fg="lightGray" />
<checkbox x="3" y="19" /><label x="5" y="19" text="Checkbox 3" fg="lightGray" />
<checkbox x="3" y="21" /><label x="5" y="21" text="Checkbox 4" fg="lightGray" />
</frame>
<progressbar onChange="progressChange" width="parent.w-2" height="3" x="2" y="30" id="progressBar" />
<label x="parent.w/2-7" y="31" zIndex="6" bg="false" text="Progressbar Example" fg="lightGray" />
<label id="progressLabel" x="3" y="31" zIndex="6" bg="false" text="0%" fg="lightGray" />
<thread thread="progressTheProgressbar" start="true" />
<frame zIndex="16" y="34" x="4" width="32" height="12" moveable="true" bar="true" barText="Moveable Frame" barBG="black" barFG="lightGray" shadow="true">
<label x="2" y="3" text="Input:" fg="lightGray" />
<input default="Default Text" defaultFG="gray" width="parent.w-2" x="2" y="5" bg="black" fg="lightGray" />
<input default="Only numbers" defaultFG="gray" width="parent.w-2" x="2" y="7" type="number" bg="black" fg="lightGray" />
<input default="Password" defaultFG="gray" width="parent.w-2" x="2" y="9" type="password" bg="black" fg="lightGray" />
</frame>
<frame zIndex="16" y="36" x="6" width="32" height="12" moveable="true" bar="true" barText="Moveable Frame 2" barBG="black" barFG="lightGray" border="true" borderTop="false">
<label x="2" y="3" text="Dropdowns, Lists and Menubars" fg="lightGray" />
<dropdown x="2" y="5" bg="black" fg="lightGray">
<item><text>Entry 1</text></item>
<item><text>Entry 2</text></item>
<item><text>Entry 3</text></item>
<item><text>Entry 4</text></item>
<item><text>Entry 5</text></item>
<item><text>Entry 6</text></item>
<item><text>Entry 7</text></item>
<item><text>Entry 8</text></item>
</dropdown>
<list x="parent.w/2" y="5" width="parent.w/2-1" bg="black" fg="gray" selectionFG="lightGray">
<item><text>Entry 1</text></item>
<item><text>Entry 2</text></item>
<item><text>Entry 3</text></item>
<item><text>Entry 4</text></item>
<item><text>Entry 5</text></item>
<item><text>Entry 6</text></item>
<item><text>Entry 7</text></item>
<item><text>Entry 8</text></item>
</list>
<menubar x="2" y="1" anchor="bottomLeft" width="parent.w-2" bg="black" fg="gray" selectionFG="lightGray" scrollable="true">
<item><text>Entry 1</text></item>
<item><text>Entry 2</text></item>
<item><text>Entry 3</text></item>
<item><text>Entry 4</text></item>
<item><text>Entry 5</text></item>
<item><text>Entry 6</text></item>
<item><text>Entry 7</text></item>
<item><text>Entry 8</text></item>
</menubar>
</frame>
<button onClick="buttonColor" onClick="ex1Top" x="parent.w-12" y="48" text="Top" />
</frame>
<frame id="example3" x="parent.w*2+1" width="parent.w" height="parent.h" bg="lightGray" >
<label text="Editor" font="2" x="16" y="2" />
<textfield x="2" y="6" width="parent.w-2" height="parent.h-7"/>
<frame ignoreOffset="true" id="sidebar" anchor="topRight" x="3" width="14" height="parent.h" bg="black" >
<button onClick="buttonColor" onClick="closeSidebar" anchor="bottomLeft" width="5" height="1" x="1" y="1" fg="black" bg="gray" text="Close" />
<button onClick="buttonColor" onClick="e1" onClick="closeSidebar" width="parent.w-2" x="2" y="2" text="Example 1" />
<button onClick="buttonColor" onClick="e2" onClick="closeSidebar" width="parent.w-2" x="2" y="6" text="Example 2" />
<button onClick="buttonColor" onClick="e3" onClick="closeSidebar" width="parent.w-2" x="2" y="10" text="Example 3" />
</frame>
<textfield x="2" y="parent.h+2" width="parent.w-2" height="parent.h-3">
<keywords>
<purple>
<keyword>if</keyword>
<keyword>then</keyword>
<keyword>else</keyword>
<keyword>elseif</keyword>
<keyword>repeat</keyword>
<keyword>do</keyword>
<keyword>while</keyword>
<keyword>end</keyword>
<keyword>function</keyword>
<keyword>for</keyword>
</purple>
<blue>
<keyword>local</keyword>
<keyword>true</keyword>
<keyword>false</keyword>
<keyword>nil</keyword>
</blue>
<yellow>
<keyword>print</keyword>
<keyword>pairs</keyword>
<keyword>ipairs</keyword>
</yellow>
</keywords>
<rules>
<rule>
<pattern>%d</pattern>
<fg>lightBlue</fg>
</rule>
<rule>
<pattern>%"%a+%"</pattern>
<fg>red</fg>
</rule>
<rule>
<pattern>[-]+[%w*%s*%p*]*</pattern>
<fg>green</fg>
</rule>
</rules>
</textfield>
<textfield id="coolTextfield" onGetFocus="onTextfieldFocus" onLoseFocus="onTextfieldLoseFocus" x="2" y="parent.h*2+2" width="20" height="3" bg="black" fg="gray">
<lines>
<line>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna </line>
<line>aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata </line>
<line>sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor </line>
<line>invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet</line>
<line>clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</line>
</lines>
</textfield>
<button id="anotherRandomButton" onClick="buttonColor" x="coolTextfield.x" y="coolTextfield.y + coolTextfield.h + 1" text="Button" />
<button onClick="buttonColor" x="coolTextfield.x + coolTextfield.w + 2" y="coolTextfield.y" text="Button" />
<animation id="textfieldAnimFocus" object="coolTextfield"><size width="40" height="12" duration="1"/></animation>
<animation id="textfieldAnimLoseFocus" object="coolTextfield"><size width="20" height="3" duration="1"/></animation>
<button ignoreOffset="true" onClick="buttonColor" onClick="openSidebar" anchor="bottomRight" width="5" height="1" x="-3" y="1" text="Open" />
<button onClick="buttonColor" onClick="ex2" x="2" y="2" width="8" height="1" text="Back" />
<button onClick="buttonColor" onClick="ex4" anchor="topRight" x="-7" y="2" width="8" height="1" text="Next" />
</frame>
<frame zIndex="17" id="example4" x="parent.w*3+1" width="parent.w" height="parent.h" bg="lightGray" >
<label text="Animations" font="2" x="16" y="2" />
<button onClick="buttonColor" onClick="ex3" x="2" y="2" width="8" height="1" text="Back" />
<frame id="showAnimFrame1" x="15" y="30" width="2" height="2" bg="black" >
<label id="animFrameLabel" text="Hello" x="-5" y="-1" fg="lightGray" />
<button anchor="bottomLeft" id="animFrameBtn1" text="Cool" x="-5" y="15" fg="lightGray" bg="gray" />
<button anchor="bottomRight" id="animFrameBtn2" text="Button" x="50" y="15" fg="lightGray" bg="gray" />
</frame>
<animation id="animation19" onDone="enableStartButton" object="animationButton"><move x="22" y="10" duration="0.5"/> <size width="12" height="3" duration="1"/></animation>
<animation id="animation18" onDone="#animation19" object="showAnimFrame1"><move x="50" y="20" duration="0.5"/><size width="2" height="2" duration="0.5"/></animation>
<animation id="animation17" onDone="#animation18" object="showAnimFrame1"><move x="5" y="6" duration="1"/><size width="30" height="8" duration="1"/></animation>
<animation id="animation16" onDone="#animation17" object="showAnimFrame1"><move x="2" y="6" duration="1"/><size width="48" height="13" duration="1"/></animation>
<animation id="animation15" onDone="#animation16" object="showAnimFrame1"><size width="36" height="10" duration="1"/></animation>
<animation id="animation14" onDone="#animation15" object="animFrameBtn2"><move x="-12" y="-2" duration="0.7"/></animation>
<animation id="animation13" onDone="#animation14" object="animFrameBtn1"><move x="3" y="-2" duration="0.7"/></animation>
<animation id="animation12" onDone="#animation13" object="animFrameLabel"><move x="3" y="3" duration="1"/><text duration="2"><text>Hello, i</text><text>Hello, i am</text><text>Hello, i am just</text><text>Hello, i am just a</text><text>Hello, i am just a label</text></text></animation>
<animation id="animation11" onDone="#animation12" object="showAnimFrame1"><move x="5" y="6" duration="1"/><size width="42" height="12" duration="1"/></animation>
<button id="showAnimBtn1" x="25" y="-6" width="16" text="Button 1" visible="false" />
<button id="showAnimBtn2" x="0" y="-6" width="16" text="Button 2" visible="false" />
<button id="showAnimBtn3" x="50" y="-6" width="16" text="Button 3" visible="false" />
<animation id="animation10" onDone="#animation11" object="showAnimBtn1"><move x="60" y="6" duration="1"/><size width="2" height="2" duration="1"/></animation>
<animation id="animation9" onDone="#animation10" object="showAnimBtn1"><move x="5" y="6" duration="0.5"/><size width="42" height="9" duration="1"/></animation>
<animation id="btn2PosAnim2" object="showAnimBtn2"><move x="-15" y="22" duration="0.5"/></animation>
<animation id="btn3PosAnim2" object="showAnimBtn3"><move x="55" y="22" duration="0.5"/></animation>
<animation mode="linear" id="animation8" onDone="#animation9" onDone="#btn2PosAnim2" onDone="#btn3PosAnim2" object="showAnimBtn3"><textColor duration="1"><color>yellow</color><color>green</color><color>red</color><color>blue</color><color>purple</color><color>orange</color><color>brown</color><color>black</color></textColor>
<background duration="3"><color>red</color><color>blue</color><color>green</color><color>purple</color><color>orange</color><color>black</color><color>lightBlue</color><color>gray</color></background></animation>
<animation mode="linear" id="animation7" object="showAnimBtn2"><textColor duration="3"><color>yellow</color><color>green</color><color>red</color><color>blue</color><color>purple</color><color>orange</color><color>brown</color><color>black</color></textColor></animation>
<animation mode="linear" id="animation6" object="showAnimBtn1"><background duration="3"><color>red</color><color>blue</color><color>green</color><color>purple</color><color>orange</color><color>black</color><color>brown</color><color>gray</color></background></animation>
<animation id="btn3PosAnim" onDone="#animation6" object="showAnimBtn3"><move x="9" y="14" duration="0.8"/><size width="35" height="3" duration="1.2"/></animation>
<animation id="btn2PosAnim" onDone="#animation7" object="showAnimBtn2"><move x="9" y="10" duration="0.6"/><size width="35" height="3" duration="1.2"/></animation>
<animation id="btn1PosAnim" onDone="#animation8" object="showAnimBtn1"><move x="9" y="6" duration="0.4"/><size width="35" height="3" duration="1.2"/></animation>
<animation mode="linear" id="animation4" onDone="#btn1PosAnim" onDone="#btn2PosAnim" onDone="#btn3PosAnim" onDone="makeButtonVisible" object="animationButton"><move x="-15" y="4" duration="0.5"/><size width="1" height="1" duration="0.5"/></animation>
<animation mode="linear" id="animation3" onDone="#animation4" object="animationButton"><move x="12" y="14" duration="0.7"/></animation>
<animation mode="linear" id="animation2" onDone="#animation3" object="animationButton"><move x="32" y="16" duration="1"/></animation>
<animation mode="linear" id="animation1" onStart="disableStartButton" onDone="#animation2" object="animationButton"><move x="34" y="9" duration="1.2"/></animation>
<button id="animationButton" onClick="startAnimation" onClick="buttonColor" x="22" y="10" text="Start" />
</frame>
<frame id="example2" x="parent.w+1" width="parent.w" height="parent.h" bg="lightGray" >
<label text="Program" font="2" x="16" y="2" />
<program x="2" y="6" width="parent.w-12" height="parent.h-6" path="rom/programs/shell.lua" execute="true" />
<button onClick="buttonColor" onClick="p2" anchor="bottomRight" width="8" x="-7" y="-2" text="Down" />
<frame moveable="true" bar="true" barText="Program" x="2" y="parent.h+2" width="28" height="12" bg="black" >
<program id="program2" x="1" y="2" width="parent.w" height="parent.h-1" path="rom/programs/fun/worm.lua" execute="true" />
</frame>
<frame moveable="true" bar="true" barText="Program" x="6" y="parent.h+4" width="28" height="12" bg="black" >
<program id="program2" x="1" y="2" width="parent.w" height="parent.h-1" path="rom/programs/shell.lua" execute="true" />
</frame>
<button onClick="buttonColor" onClick="p1" width="8" x="parent.w-8" y="parent.h+2" text="Up" />
<button onClick="buttonColor" onClick="p3" width="8" x="parent.w-8" y="parent.h*2-3" text="Down" />
<button onClick="buttonColor" onClick="p2" width="8" x="parent.w-8" y="parent.h*2+2" text="Up" />
<program id="program3" onClick="test" x="2" y="parent.h*2+2" width="parent.w-12" height="parent.h-2" path="rom/programs/fun/worm.lua" execute="true" />
<button onClick="buttonColor" onClick="pauseP3" width="8" x="parent.w-8" y="parent.w*2+7" text="Pause" />
<button onClick="buttonColor" onClick="p3Up" width="1" height="1" x="parent.w-5" y="parent.h*2+11" text="^" />
<button onClick="buttonColor" onClick="p3Down" width="1" height="1" x="parent.w-5" y="parent.h*2+13" text="v" />
<button onClick="buttonColor" onClick="p3Left" width="1" height="1" x="parent.w-7" y="parent.h*2+12" text="<" />
<button onClick="buttonColor" onClick="p3Right" width="1" height="1" x="parent.w-3" y="parent.h*2+12" text="&#62;" />
<button onClick="buttonColor" onClick="ex1" x="2" y="2" width="8" height="1" text="Back" />
<button onClick="buttonColor" onClick="ex3" anchor="topRight" x="-7" y="2" width="8" height="1" text="Next" />
</frame>

290
examples/discordCC.lua Normal file
View File

@@ -0,0 +1,290 @@
local bot_id = "" -- put the bot id between the ""!
local servers = { -- setup the server/channels here, look at the example.
[""] = {
"",
},
--[[ Example:
["SERVER_ID"] = {
"CHANNEL_ID",
"CHANNEL_ID",
"CHANNEL_ID",
},
["SERVER_ID"] = {
"CHANNEL_ID",
"CHANNEL_ID",
"CHANNEL_ID",
},
]]
}
if(bot_id=="")then
error("Please setup the bot id and servers/channels first!")
end
local filePath = "basalt"
if not(fs.exists(filePath))then
shell.run("pastebin run ESs1mg7P packed true "..filePath)
end
local basalt = require(filePath) -- UI Library
local main = basalt.createFrame():setBackground(colors.lightGray)
local loginFrame = main:addFrame():setBackground(colors.lightGray)
local messageFrameList = main:addFrame():setPosition("parent.w+1", 1):setBackground(colors.black):setScrollable(true):setImportantScroll(true)
local refreshRate = 2
local messageFrames = {}
local availableGuilds = {}
local channel_id = ""
for k,v in pairs(servers)do
if(v[1]~=nil)then
channel_id = v[1]
end
break
end
local function getAllGuilds(bot)
local content = http.get("https://discord.com/api/users/@me/guilds", {["Content-Type"] = "application/json", ["Authorization"] = "Bot "..bot})
if(content~=nil)then
return textutils.unserializeJSON(content.readAll())
end
end
local function getAllChannels(bot, guild)
local content = http.get("https://discord.com/api/guilds/"..guild.."/channels", {["Content-Type"] = "application/json", ["Authorization"] = "Bot "..bot})
if(content~=nil)then
local t = {}
for k,v in pairs(textutils.unserializeJSON(content.readAll()))do
table.insert(t, v.position, v)
end
return t
end
end
local splitString = function(str, sep)
if sep == nil then
sep = "%s"
end
local t={}
for v in string.gmatch(str, "([^"..sep.."]+)") do
table.insert(t, v)
end
if(#t==0)then table.insert(t,str) end
return t
end
local function createText(str, width)
local uniqueLines = splitString(str, "\n")
local lines = {}
for k,v in pairs(uniqueLines)do
local line = ""
local words = splitString(v, " ")
for a,b in pairs(words)do
if(#line+#b <= width)then
line = line=="" and b or line.." "..b
if(a==#words)then table.insert(lines, line) end
else
table.insert(lines, line)
line = b:sub(1,width)
if(a==#words)then table.insert(lines, line) end
end
end
end
return lines
end
local maxOffset = 0
local autoOffset = true
local function newMessage(position, msg, username, sendTime)
local lines = createText(msg, messageFrameList:getWidth()-5)
if(messageFrames[position]==nil)then
if(messageFrames[position-1]~=nil)then
messageFrames[position] = messageFrameList:addFrame("message"..tostring(position)):setPosition(2, "message"..(position-1)..".y + message"..(position-1)..".h")
else
messageFrames[position] = messageFrameList:addFrame("message"..tostring(position)):setPosition(2, 1)
end
messageFrames[position]:addLabel("title")
messageFrames[position]:addLabel("body")
end
maxOffset = maxOffset + #lines+3
if(autoOffset)then
messageFrameList:setOffset(0, maxOffset - messageFrameList:getHeight()+1)
end
messageFrames[position]:setSize("parent.w-1", #lines+3):setBackground(colors.black)
messageFrames[position]:getObject("title"):setSize("parent.w-2", 1):setPosition(2,1):setText(username):setForeground(colors.lightGray):setBackground(colors.gray)
messageFrames[position]:getObject("body"):setSize("parent.w-2", #lines+1):setPosition(2,3):setText(msg):setForeground(colors.lightGray)
end
local function updateDiscordMessages(channel, bot)
if(channel~=nil)and(bot~=nil)then
currentMessages = {}
local content = http.get("https://discord.com/api/channels/"..channel.."/messages?limit=25", {["Content-Type"] = "application/json", ["Authorization"] = "Bot "..bot})
if(content~=nil)then
local t = textutils.unserializeJSON(content.readAll())
local tR = {}
for i=#t, 1, -1 do
tR[#tR+1] = t[i]
end
for k,v in pairs(tR)do
newMessage(k, v.content, v.author.username, v.time)
end
end
end
end
local animations = {}
local function offsetAnimation(obj, x, y, t)
if(animations[obj:getName()]~=nil)then animations[obj:getName()]:cancel() end
animations[obj:getName()] = main:addAnimation():setAutoDestroy(true):setObject(obj):offset(x, y, t or 1):play()
end
local function positionAnimation(obj, x, y, t)
if(animations[obj:getName()]~=nil)then animations[obj:getName()]:cancel() end
animations[obj:getName()] = main:addAnimation():setAutoDestroy(true):setObject(obj):move(x, y, t or 1):play()
end
local sideBar = messageFrameList:addFrame():setPosition(-18, 1):setSize(20, "parent.h"):setZIndex(17):ignoreOffset():setScrollable(true):setImportantScroll(true)
sideBar:addButton():setText("Back"):setForeground(colors.lightGray):setBackground(colors.black):setPosition(3,2):setSize("parent.w - 4", 3):onClick(function()
offsetAnimation(main, 0, 0)
positionAnimation(sideBar, -18, 1)
end)
sideBar:addLabel():setText("Channels:"):setForeground(colors.black):setPosition(2,6)
sideBar:onClick(function(self, event)
if(event=="mouse_click")then
positionAnimation(self, 1, 1)
messageFrameList:setImportantScroll(false)
end
end)
sideBar:onLoseFocus(function()
positionAnimation(sideBar, -18, 1)
messageFrameList:setImportantScroll(true)
end)
local newTextFrame = messageFrameList:addFrame():setSize("parent.w - 4", 10):setPosition(3, 1):setZIndex(16):ignoreOffset():setBackground(colors.gray):setAnchor("bottomLeft")
local msgInfo = newTextFrame:addLabel():setText("Click here to write a message")
local messageField = newTextFrame:addTextfield():setSize("parent.w-2", "parent.h-4"):setPosition(2,3):setBackground(colors.lightGray)
newTextFrame:onClick(function(self, event)
if(event=="mouse_click")then
positionAnimation(self, 3, -8, 0.5)
messageFrameList:setImportantScroll(false)
msgInfo:setText("New Message:")
end
end)
messageFrameList:onScroll(function()
local xO, yO = messageFrameList:getOffset()
messageFrameList:getMaxScroll()
if(yO==messageFrameList:getMaxScroll())then
autoOffset = true
else
autoOffset = false
end
end)
local function messageBoxLoseFocus()
positionAnimation(newTextFrame, 3, 1, 0.5)
messageFrameList:setImportantScroll(true)
msgInfo:setText("Click here to write a message")
messageField:clear()
end
newTextFrame:addButton():setText("Cancel"):setAnchor("bottomLeft"):setBackground(colors.black):setForeground(colors.lightGray):setSize(12,1):setPosition(2,1):onClick(function()
messageBoxLoseFocus()
end)
newTextFrame:onLoseFocus(messageBoxLoseFocus)
loginFrame:addLabel():setAnchor("center"):setPosition(-2, -1):setText("Username:")
local nameInput = loginFrame:addInput():setAnchor("center"):setPosition(3,0):setBackground(colors.black):setForeground(colors.lightGray):setSize(16,1):setDefaultText("Username...", colors.gray)
local serverList = loginFrame:addList():setPosition(3, 6):setSize(16, 10)
local channelRadio = sideBar:addRadio():setForeground(colors.black):setBackground(colors.gray):setSelectedItem(colors.gray, colors.lightGray):setActiveSymbol(" ")
local channelObjects = {}
local updateChannels = basalt.shedule(function()
if(bot_id~=nil)then
for k,v in pairs(channelObjects)do
sideBar:removeObject(v)
end
channelObjects = {}
if(serverList:getValue().args~=nil)then
local y = 8
local maxScroll = 2
for k,v in pairs(servers[serverList:getValue().args[1]])do
local content = http.get("https://discord.com/api/channels/"..v, {["Content-Type"] = "application/json", ["Authorization"] = "Bot "..bot_id})
local channel = textutils.unserializeJSON(content.readAll())
if(channel~=nil)then
channelRadio:addItem("#"..channel.name,1, y, nil,nil,v)
y = y + 1
maxScroll = maxScroll + 1
end
end
end
end
end)
serverList:onChange(updateChannels)
basalt.shedule(function()
if(bot_id~=nil)then
for k,v in pairs(servers)do
local content = http.get("https://discord.com/api/guilds/"..k, {["Content-Type"] = "application/json", ["Authorization"] = "Bot "..bot_id})
local guild = textutils.unserializeJSON(content.readAll())
if(guild~=nil)then
serverList:addItem(guild.name,nil,nil,k)
end
end
end
end)()
updateChannels()
channelRadio:onChange(function(self)
local val = self:getValue()
if(val~=nil)and(val.args[1]~=nil)then
channel_id = val.args[1]
end
end)
loginFrame:addButton():setAnchor("bottomRight"):setPosition(-10, -2):setSize(11,3):setText("Login"):onClick(function()
offsetAnimation(main, main:getWidth(), 0)
end)
loginFrame:addLabel():setPosition(3, 5):setText("Servers:")
local function sendDiscordMessage(msg, channel, bot)
if(channel~=nil)and(bot~=nil)then
if(nameInput:getValue()~="")then
msg = string.gsub(msg, "\n", "\\n")
http.post("https://discord.com/api/channels/"..channel.."/messages", '{ "content": "['..nameInput:getValue()..']: '..msg..'" }', {["Content-Type"] = "application/json", ["Authorization"] = "Bot "..bot})
end
end
end
newTextFrame:addButton():setText("Send"):setAnchor("bottomRight"):setBackground(colors.black):setForeground(colors.lightGray):setSize(12,1):setPosition(-11,1)
:onClick(function()
local msg = table.concat(messageField:getLines(), "\n")
if(#msg>0)then
sendDiscordMessage(msg, channel_id, bot_id)
end
messageBoxLoseFocus()
end)
local function refreshMessages()
while true do
maxOffset = 0
updateDiscordMessages(channel_id, bot_id)
maxOffset = maxOffset - messageFrameList:getHeight()+1
messageFrameList:setMaxScroll(maxOffset)
sleep(refreshRate)
end
end
local thread = main:addThread():start(refreshMessages)
basalt.autoUpdate()

View File

@@ -0,0 +1,52 @@
-- This is a example on how to use progressbars for energy. I used the Mekanism Ultimate Energy Cube.
local filePath = "basalt.lua" --here you can change the file path default: basalt.lua
if not(fs.exists(filePath))then
shell.run("pastebin run ESs1mg7P packed true "..filePath) -- this is an alternative to the wget command
end
local basalt = require(filePath:gsub(".lua", "")) -- here you can change the variablename in any variablename you want default: basalt
local energyCube = peripheral.find("ultimateEnergyCube")
local main = basalt.createFrame("main"):show()
local progressText = main:addLabel("currentEnergyValue")
:setText(0)
:setForeground(colors.gray)
:setBackground(false)
:setPosition(10, 3)
:setZIndex(6)
:show()
local energyProgress = main:addProgressbar("mainEnergyCube")
:setSize(20,3)
:setPosition(2,2)
:setBackground(colors.black)
:setProgressBar(colors.green)
:show()
energyProgress:onChange(function()
local energy = tostring(energyCube.getEnergy())
progressText:setText(energy)
progressText:setPosition(energyProgress:getWidth()/2+1 - math.floor(energy:len()/2), 3)
end)
local function checkCurrentEnergy()
while true do
energyCube = peripheral.find("ultimateEnergyCube")
if(energyCube~=nil)then
local energyCalculation = energyCube.getEnergy() / energyCube.getMaxEnergy() * 100
energyProgress:setProgress(energyCalculation)
else
energyProgress:setProgress(0)
os.sleep(3)
end
os.sleep(1)
end
end
main:addThread("energyThread"):start(checkCurrentEnergy)
basalt.autoUpdate()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
local basaltFileName = "basalt-source.lua"
local absolutePath = "source"
local basalt = dofile(fs.combine(absolutePath, "packager.lua")) -- path to packager
local b = fs.open(fs.combine(absolutePath, basaltFileName), "w")
b.write(basalt)
b.close()

View File

@@ -0,0 +1,4 @@
local absolutePath = "source"
local basalt = dofile(fs.combine(absolutePath, "packager.lua"))
return (load(basalt, "t")())

View File

@@ -0,0 +1,68 @@
local basaltFileName = "basalt.lua"
local absoluteFilePath = "source/project"
local requiredFiles = {
"mainTop.lua",
"mainBottom.lua",
"Frame.lua",
"Object.lua",
"defaultTheme.lua",
"lib/drawHelper.lua",
"lib/eventSystem.lua",
"lib/process.lua",
"lib/utils.lua",
}
local basalt = ""
for k,v in pairs(requiredFiles)do
assert(fs.exists(fs.combine(absoluteFilePath, v)), "File "..v.." doesn't exists!")
end
local lib = fs.list(fs.combine(absoluteFilePath, "lib"))
local objects = fs.list(fs.combine(absoluteFilePath, "objects"))
local file = fs.open(fs.combine(absoluteFilePath, "mainTop.lua"), "r")
basalt = basalt..file.readAll().."\n"
file.close()
local file = fs.open(fs.combine(absoluteFilePath, "defaultTheme.lua"), "r")
basalt = basalt..file.readAll().."\n"
file.close()
for _,v in pairs(lib)do
local path = fs.combine(fs.combine(absoluteFilePath, "lib"), v)
if not(fs.isDir(path))then
local file = fs.open(path, "r")
basalt = basalt..file.readAll().."\n"
file.close()
end
end
local file = fs.open(fs.combine(absoluteFilePath, "Object.lua"), "r")
basalt = basalt..file.readAll().."\n"
file.close()
for _,v in pairs(objects)do
if(v~="example.lua")then
local path = fs.combine(fs.combine(absoluteFilePath, "objects"), v)
if not(fs.isDir(path))then
local file = fs.open(path, "r")
basalt = basalt..file.readAll().."\n"
file.close()
end
end
end
local file = fs.open(fs.combine(absoluteFilePath, "Frame.lua"), "r")
basalt = basalt..file.readAll().."\n"
file.close()
local file = fs.open(fs.combine(absoluteFilePath, "mainBottom.lua"), "r")
basalt = basalt..file.readAll().."\n"
file.close()
--local b = fs.open(fs.combine(absoluteFilePath, "basalt.lua"), "w")
--b.write(basalt)
--b.close()
return basalt

View File

@@ -0,0 +1,657 @@
local function Frame(name, parent)
-- Frame
local base = Object(name)
local objectType = "Frame"
local objects = {}
local objZIndex = {}
local object = {}
local termObject = parentTerminal
local monSide = ""
local isMonitor = false
local monitorAttached = false
local dragXOffset = 0
local dragYOffset = 0
base:setZIndex(10)
local drawHelper = basaltDrawHelper(termObject)
local cursorBlink = false
local xCursor = 1
local yCursor = 1
local cursorColor = colors.white
local xOffset, yOffset = 0, 0
if (parent ~= nil) then
base.parent = parent
base.width, base.height = parent:getSize()
base.bgColor = theme.FrameBG
base.fgColor = theme.FrameFG
else
base.width, base.height = termObject.getSize()
base.bgColor = theme.basaltBG
base.fgColor = theme.basaltFG
end
local function getObject(name)
for _, value in pairs(objects) do
for _, b in pairs(value) do
if (b.name == name) then
return value
end
end
end
end
local function addObject(obj)
local zIndex = obj:getZIndex()
if (getObject(obj.name) ~= nil) then
return nil
end
if (objects[zIndex] == nil) then
for x = 1, #objZIndex + 1 do
if (objZIndex[x] ~= nil) then
if (zIndex == objZIndex[x]) then
break
end
if (zIndex > objZIndex[x]) then
table.insert(objZIndex, x, zIndex)
break
end
else
table.insert(objZIndex, zIndex)
end
end
if (#objZIndex <= 0) then
table.insert(objZIndex, zIndex)
end
objects[zIndex] = {}
end
obj.parent = object
table.insert(objects[zIndex], obj)
return obj
end
local function removeObject(obj)
for a, b in pairs(objects) do
for key, value in pairs(b) do
if (value == obj) then
table.remove(objects[a], key)
return true;
end
end
end
return false
end
object = {
barActive = false,
barBackground = colors.gray,
barTextcolor = colors.black,
barText = "New Frame",
barTextAlign = "left",
isMoveable = false,
getType = function(self)
return objectType
end;
setFocusedObject = function(self, obj)
if (focusedObject ~= nil) then
focusedObject:loseFocusHandler()
focusedObject = nil
end
if(obj~=nil)then
focusedObject = obj
obj:getFocusHandler()
end
return self
end;
setSize = function(self, w, h)
base.setSize(self, w, h)
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.eventHandler ~= nil) then
value:sendEvent("basalt_resize", value, self)
end
end
end
end
return self
end;
setOffset = function(self, xO, yO)
xOffset = xO ~= nil and math.floor(xO < 0 and math.abs(xO) or -xO) or xOffset
yOffset = yO ~= nil and math.floor(yO < 0 and math.abs(yO) or -yO) or yOffset
return self
end;
getFrameOffset = function(self) -- internal
return xOffset, yOffset
end;
removeFocusedObject = function(self)
if (focusedObject ~= nil) then
focusedObject:loseFocusHandler()
end
focusedObject = nil
return self
end;
getFocusedObject = function(self)
return focusedObject
end;
setCursor = function(self, _blink, _xCursor, _yCursor, color)
if(self.parent~=nil)then
local obx, oby = self:getAnchorPosition()
self.parent:setCursor(_blink or false, (_xCursor or 0)+obx-1, (_yCursor or 0)+oby-1, color or cursorColor)
else
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
cursorBlink = _blink or false
if (_xCursor ~= nil) then
xCursor = obx + _xCursor - 1
end
if (_yCursor ~= nil) then
yCursor = oby + _yCursor - 1
end
cursorColor = color or cursorColor
self:setVisualChanged()
end
return self
end;
setMoveable = function(self, moveable)
self.isMoveable = moveable or not self.isMoveable
self:setVisualChanged()
return self;
end;
show = function(self)
base.show(self)
if(self.parent==nil)then
activeFrame = self;
if(isMonitor)then
monFrames[monSide] = self;
else
mainFrame = self;
end
end
return self;
end;
hide = function (self)
base.hide(self)
if(self.parent==nil)then
if(activeFrame == self)then activeFrame = nil end
if(isMonitor)then
if(monFrames[monSide] == self)then
monFrames[monSide] = nil;
end
else
if(mainFrame == self)then
mainFrame = nil;
end
end
end
return self
end;
showBar = function(self, showIt)
self.barActive = showIt or not self.barActive
self:setVisualChanged()
return self
end;
setBar = function(self, text, bgCol, fgCol)
self.barText = text or ""
self.barBackground = bgCol or self.barBackground
self.barTextcolor = fgCol or self.barTextcolor
self:setVisualChanged()
return self
end;
setBarTextAlign = function(self, align)
self.barTextAlign = align or "left"
self:setVisualChanged()
return self
end;
setMonitor = function(self, side)
if(side~=nil)and(side~=false)then
if(peripheral.getType(side)=="monitor")then
termObject = peripheral.wrap(side)
monitorAttached = true
end
isMonitor = true
else
termObject = parentTerminal
isMonitor = false
if(monFrames[monSide]==self)then
monFrames[monSide] = nil
end
end
drawHelper = basaltDrawHelper(termObject)
monSide = side or nil
return self;
end;
getVisualChanged = function(self)
local changed = base.getVisualChanged(self)
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.getVisualChanged ~= nil and value:getVisualChanged()) then
changed = true
end
end
end
end
return changed
end;
loseFocusHandler = function(self)
base.loseFocusHandler(self)
end;
getFocusHandler = function(self)
base.getFocusHandler(self)
if (self.parent ~= nil) then
self.parent:removeObject(self)
self.parent:addObject(self)
end
end;
keyHandler = function(self, event, key)
if (focusedObject ~= nil) then
if(focusedObject~=self)then
if (focusedObject.keyHandler ~= nil) then
if (focusedObject:keyHandler(event, key)) then
return true
end
end
else
base.keyHandler(self, event, key)
end
end
return false
end;
backgroundKeyHandler = function(self, event, key)
base.backgroundKeyHandler(self, event, key)
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.backgroundKeyHandler ~= nil) then
value:backgroundKeyHandler(event, key)
end
end
end
end
end;
eventHandler = function(self, event, p1, p2, p3, p4)
base.eventHandler(self, event, p1, p2, p3, p4)
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.eventHandler ~= nil) then
value:eventHandler(event, p1, p2, p3, p4)
end
end
end
end
if(isMonitor)then
if(event == "peripheral")and(p1==monSide)then
if(peripheral.getType(monSide)=="monitor")then
monitorAttached = true
termObject = peripheral.wrap(monSide)
drawHelper = basaltDrawHelper(termObject)
end
end
if(event == "peripheral_detach")and(p1==monSide)then
monitorAttached = false
end
end
if (event == "terminate") then
termObject.clear()
termObject.setCursorPos(1, 1)
basalt.stop()
end
end;
mouseHandler = function(self, event, button, x, y)
local xO, yO = self:getOffset()
xO = xO < 0 and math.abs(xO) or -xO
yO = yO < 0 and math.abs(yO) or -yO
if (self.drag) then
if (event == "mouse_drag") then
local parentX = 1;
local parentY = 1
if (self.parent ~= nil) then
parentX, parentY = self.parent:getAbsolutePosition(self.parent:getAnchorPosition())
end
self:setPosition(x + dragXOffset - (parentX - 1) + xO, y + dragYOffset - (parentY - 1) + yO)
end
if (event == "mouse_up") then
self.drag = false
end
return true
end
local objX, objY = self:getAbsolutePosition(self:getAnchorPosition())
local yOff = false
if(objY-1 == y)and(self:getBorder("top"))then
y = y+1
yOff = true
end
if (base.mouseHandler(self, event, button, x, y)) then
local fx, fy = self:getAbsolutePosition(self:getAnchorPosition())
fx = fx + xOffset;fy = fy + yOffset;
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in rpairs(objects[index]) do
if (value.mouseHandler ~= nil) then
if (value:mouseHandler(event, button, x, y)) then
return true
end
end
end
end
end
if (self.isMoveable) then
local fx, fy = self:getAbsolutePosition(self:getAnchorPosition())
if (x >= fx) and (x <= fx + self.width - 1) and (y == fy) and (event == "mouse_click") then
self.drag = true
dragXOffset = fx - x
dragYOffset = yOff and 1 or 0
end
end
if (focusedObject ~= nil) then
focusedObject:loseFocusHandler()
focusedObject = nil
end
return true
end
return false
end;
setText = function(self, x, y, text)
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
if (y >= 1) and (y <= self.height) then
if (self.parent ~= nil) then
local parentX, parentY = self.parent:getAnchorPosition()
self.parent:setText(math.max(x + (obx - 1), obx) - (parentX - 1), oby + y - 1 - (parentY - 1), sub(text, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1)))
else
drawHelper.setText(math.max(x + (obx - 1), obx), oby + y - 1, sub(text, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1))) -- math.max(self.width - x + 1,1) now, before: self.width - x + 1
end
end
end;
setBG = function(self, x, y, bgCol)
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
if (y >= 1) and (y <= self.height) then
if (self.parent ~= nil) then
local parentX, parentY = self.parent:getAnchorPosition()
self.parent:setBG(math.max(x + (obx - 1), obx) - (parentX - 1), oby + y - 1 - (parentY - 1), sub(bgCol, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1)))
else
drawHelper.setBG(math.max(x + (obx - 1), obx), oby + y - 1, sub(bgCol, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1)))
end
end
end;
setFG = function(self, x, y, fgCol)
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
if (y >= 1) and (y <= self.height) then
if (self.parent ~= nil) then
local parentX, parentY = self.parent:getAnchorPosition()
self.parent:setFG(math.max(x + (obx - 1), obx) - (parentX - 1), oby + y - 1 - (parentY - 1), sub(fgCol, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1)))
else
drawHelper.setFG(math.max(x + (obx - 1), obx), oby + y - 1, sub(fgCol, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1)))
end
end
end;
writeText = function(self, x, y, text, bgCol, fgCol)
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
if (y >= 1) and (y <= self.height) then
if (self.parent ~= nil) then
local parentX, parentY = self.parent:getAnchorPosition()
self.parent:writeText(math.max(x + (obx - 1), obx) - (parentX - 1), oby + y - 1 - (parentY - 1), sub(text, math.max(1 - x + 1, 1), self.width - x + 1), bgCol, fgCol)
else
drawHelper.writeText(math.max(x + (obx - 1), obx), oby + y - 1, sub(text, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1)), bgCol, fgCol)
end
end
end;
drawBackgroundBox = function(self, x, y, width, height, bgCol)
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
height = (y < 1 and (height + y > self.height and self.height or height + y - 1) or (height + y > self.height and self.height - y + 1 or height))
width = (x < 1 and (width + x > self.width and self.width or width + x - 1) or (width + x > self.width and self.width - x + 1 or width))
if (self.parent ~= nil) then
local parentX, parentY = self.parent:getAnchorPosition()
self.parent:drawBackgroundBox(math.max(x + (obx - 1), obx) - (parentX - 1), math.max(y + (oby - 1), oby) - (parentY - 1), width, height, bgCol)
else
drawHelper.drawBackgroundBox(math.max(x + (obx - 1), obx), math.max(y + (oby - 1), oby), width, height, bgCol)
end
end;
drawTextBox = function(self, x, y, width, height, symbol)
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
height = (y < 1 and (height + y > self.height and self.height or height + y - 1) or (height + y > self.height and self.height - y + 1 or height))
width = (x < 1 and (width + x > self.width and self.width or width + x - 1) or (width + x > self.width and self.width - x + 1 or width))
if (self.parent ~= nil) then
local parentX, parentY = self.parent:getAnchorPosition()
self.parent:drawTextBox(math.max(x + (obx - 1), obx) - (parentX - 1), math.max(y + (oby - 1), oby) - (parentY - 1), width, height, symbol:sub(1, 1))
else
drawHelper.drawTextBox(math.max(x + (obx - 1), obx), math.max(y + (oby - 1), oby), width, height, symbol:sub(1, 1))
end
end;
drawForegroundBox = function(self, x, y, width, height, fgCol)
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
height = (y < 1 and (height + y > self.height and self.height or height + y - 1) or (height + y > self.height and self.height - y + 1 or height))
width = (x < 1 and (width + x > self.width and self.width or width + x - 1) or (width + x > self.width and self.width - x + 1 or width))
if (self.parent ~= nil) then
local parentX, parentY = self.parent:getAnchorPosition()
self.parent:drawForegroundBox(math.max(x + (obx - 1), obx) - (parentX - 1), math.max(y + (oby - 1), oby) - (parentY - 1), width, height, fgCol)
else
drawHelper.drawForegroundBox(math.max(x + (obx - 1), obx), math.max(y + (oby - 1), oby), width, height, fgCol)
end
end;
draw = function(self)
if(isMonitor)and not(monitorAttached)then return false end;
if (self:getVisualChanged()) then
if (base.draw(self)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local anchx, anchy = self:getAnchorPosition()
if (self.parent ~= nil) then
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(anchx, anchy, self.width, self.height, self.bgColor)
self.parent:drawTextBox(anchx, anchy, self.width, self.height, " ")
end
if(self.bgColor~=false)then self.parent:drawForegroundBox(anchx, anchy, self.width, self.height, self.fgColor) end
else
if(self.bgColor~=false)then
drawHelper.drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor)
drawHelper.drawTextBox(obx, oby, self.width, self.height, " ")
end
if(self.fgColor~=false)then drawHelper.drawForegroundBox(obx, oby, self.width, self.height, self.fgColor) end
end
termObject.setCursorBlink(false)
if (self.barActive) then
if (self.parent ~= nil) then
self.parent:writeText(anchx, anchy, getTextHorizontalAlign(self.barText, self.width, self.barTextAlign), self.barBackground, self.barTextcolor)
else
drawHelper.writeText(obx, oby, getTextHorizontalAlign(self.barText, self.width, self.barTextAlign), self.barBackground, self.barTextcolor)
end
if(self:getBorder("left"))then
if (self.parent ~= nil) then
self.parent:drawBackgroundBox(anchx-1, anchy, 1, 1, self.barBackground)
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(anchx-1, anchy+1, 1, self.height-1, self.bgColor)
end
end
end
if(self:getBorder("top"))then
if (self.parent ~= nil) then
self.parent:drawBackgroundBox(anchx-1, anchy-1, self.width+1, 1, self.barBackground)
end
end
end
for _, index in rpairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.draw ~= nil) then
value:draw()
end
end
end
end
if (cursorBlink) then
termObject.setTextColor(cursorColor)
termObject.setCursorPos(xCursor, yCursor)
if (self.parent ~= nil) then
termObject.setCursorBlink(self:isFocused())
else
termObject.setCursorBlink(cursorBlink)
end
end
self:setVisualChanged(false)
end
end
end;
drawUpdate = function(self)
if(isMonitor)and not(monitorAttached)then return false end;
drawHelper.update()
end;
addObject = function(self, obj)
return addObject(obj)
end;
removeObject = function(self, obj)
return removeObject(obj)
end;
getObject = function(self, obj)
return getObject(obj)
end;
addButton = function(self, name)
local obj = Button(name)
obj.name = name
return addObject(obj)
end;
addLabel = function(self, name)
local obj = Label(name)
obj.bgColor = self.bgColor
obj.fgColor = self.fgColor
return addObject(obj)
end;
addCheckbox = function(self, name)
local obj = Checkbox(name)
return addObject(obj)
end;
addInput = function(self, name)
local obj = Input(name)
return addObject(obj)
end;
addProgram = function(self, name)
local obj = Program(name)
return addObject(obj)
end;
addTextfield = function(self, name)
local obj = Textfield(name)
return addObject(obj)
end;
addList = function(self, name)
local obj = List(name)
obj.name = nam
return addObject(obj)
end;
addDropdown = function(self, name)
local obj = Dropdown(name)
return addObject(obj)
end;
addRadio = function(self, name)
local obj = Radio(name)
return addObject(obj)
end;
addTimer = function(self, name)
local obj = Timer(name)
return addObject(obj)
end;
addAnimation = function(self, name)
local obj = Animation(name)
return addObject(obj)
end;
addSlider = function(self, name)
local obj = Slider(name)
return addObject(obj)
end;
addScrollbar = function(self, name)
local obj = Scrollbar(name)
return addObject(obj)
end;
addMenubar = function(self, name)
local obj = Menubar(name)
return addObject(obj)
end;
addThread = function(self, name)
local obj = Thread(name)
return addObject(obj)
end;
addPane = function(self, name)
local obj = Pane(name)
return addObject(obj)
end;
addImage = function(self, name)
local obj = Image(name)
return addObject(obj)
end;
addProgressbar = function(self, name)
local obj = Progressbar(name)
return addObject(obj)
end;
addSwitch = function(self, name)
local obj = Switch(name)
return addObject(obj)
end;
addFrame = function(self, name)
local obj = Frame(name, self)
return addObject(obj)
end;
}
setmetatable(object, base)
return object
end

View File

@@ -0,0 +1,573 @@
local function Object(name)
-- Base object
local objectType = "Object" -- not changeable
local value
local zIndex = 1
local anchor = "topLeft"
local ignOffset = false
local isVisible = false
local shadow = false
local borderLeft = false
local borderTop = false
local borderRight = false
local borderBottom = false
local shadowColor = colors.black
local borderColor = colors.black
local visualsChanged = true
local eventSystem = BasaltEvents()
local object = {
x = 1,
y = 1,
width = 1,
height = 1,
bgColor = colors.black,
fgColor = colors.white,
name = name or "Object",
parent = nil,
show = function(self)
isVisible = true
visualsChanged = true
return self
end;
hide = function(self)
isVisible = false
visualsChanged = true
return self
end;
isVisible = function(self)
return isVisible
end;
setFocus = function(self)
if (self.parent ~= nil) then
self.parent:setFocusedObject(self)
end
return self
end;
setZIndex = function(self, index)
zIndex = index
if (self.parent ~= nil) then
self.parent:removeObject(self)
self.parent:addObject(self)
end
return self
end;
getZIndex = function(self)
return zIndex;
end;
getType = function(self)
return objectType
end;
getName = function(self)
return self.name
end;
remove = function(self)
if (self.parent ~= nil) then
self.parent:removeObject(self)
end
return self
end;
setParent = function(self, frame)
if (frame.getType ~= nil and frame:getType() == "Frame") then
self:remove()
frame:addObject(self)
if (self.draw) then
self:show()
end
end
return self
end;
setValue = function(self, _value)
if (value ~= _value) then
value = _value
visualsChanged = true
self:valueChangedHandler()
end
return self
end;
getValue = function(self)
return value
end;
getVisualChanged = function(self)
return visualsChanged
end;
setVisualChanged = function(self, change)
visualsChanged = change or true
if(change == nil)then visualsChanged = true end
return self
end;
getEventSystem = function(self)
return eventSystem
end;
getParent = function(self)
return self.parent
end;
setPosition = function(self, xPos, yPos, rel)
if (rel) then
self.x, self.y = math.floor(self.x + xPos), math.floor(self.y + yPos)
else
self.x, self.y = math.floor(xPos), math.floor(yPos)
end
visualsChanged = true
return self
end;
getPosition = function(self)
return self.x, self.y
end;
getVisibility = function(self)
return isVisible
end;
setVisibility = function(self, _isVisible)
isVisible = _isVisible or not isVisible
visualsChanged = true
return self
end;
setSize = function(self, width, height)
self.width, self.height = width, height
eventSystem:sendEvent("basalt_resize", self)
visualsChanged = true
return self
end;
getHeight = function(self)
return self.height
end;
getWidth = function(self)
return self.width
end;
getSize = function(self)
return self.width, self.height
end;
setBackground = function(self, color)
self.bgColor = color
visualsChanged = true
return self
end;
getBackground = function(self)
return self.bgColor
end;
setForeground = function(self, color)
self.fgColor = color
visualsChanged = true
return self
end;
getForeground = function(self)
return self.fgColor
end;
showShadow = function(self, show)
shadow = show or (not shadow)
return self
end;
setShadow = function(self, color)
shadowColor = color
return self
end;
isShadowActive = function(self)
return shadow;
end;
showBorder = function(self, ...)
for _,v in pairs(table.pack(...))do
if(v=="left")then
borderLeft = true
end
if(v=="top")then
borderTop = true
end
if(v=="right")then
borderRight = true
end
if(v=="bottom")then
borderBottom = true
end
end
return self
end;
setBorder = function(self, color)
shadowColor = color
return self
end;
getBorder = function(self, side)
if(side=="left")then
return borderLeft;
end
if(side=="top")then
return borderTop;
end
if(side=="right")then
return borderRight;
end
if(side=="bottom")then
return borderBottom;
end
end;
draw = function(self)
if (isVisible) then
if(self.parent~=nil)then
local x, y = self:getAnchorPosition()
if(shadow)then
self.parent:drawBackgroundBox(x+1, y+self.height, self.width, 1, shadowColor)
self.parent:drawBackgroundBox(x+self.width, y+1, 1, self.height, shadowColor)
self.parent:drawForegroundBox(x+1, y+self.height, self.width, 1, shadowColor)
self.parent:drawForegroundBox(x+self.width, y+1, 1, self.height, shadowColor)
end
if(borderLeft)then
self.parent:drawTextBox(x-1, y, 1, self.height, "\149")
self.parent:drawForegroundBox(x-1, y, 1, self.height, borderColor)
if(self.bgColor~=false)then self.parent:drawBackgroundBox(x-1, y, 1, self.height, self.bgColor) end
end
if(borderLeft)and(borderTop)then
self.parent:drawTextBox(x-1, y-1, 1, 1, "\151")
self.parent:drawForegroundBox(x-1, y-1, 1, 1, borderColor)
if(self.bgColor~=false)then self.parent:drawBackgroundBox(x-1, y-1, 1, 1, self.bgColor) end
end
if(borderTop)then
self.parent:drawTextBox(x, y-1, self.width, 1, "\131")
self.parent:drawForegroundBox(x, y-1, self.width, 1, borderColor)
if(self.bgColor~=false)then self.parent:drawBackgroundBox(x, y-1, self.width, 1, self.bgColor) end
end
if(borderTop)and(borderRight)then
self.parent:drawTextBox(x+self.width, y-1, 1, 1, "\149")
self.parent:drawForegroundBox(x+self.width, y-1, 1, 1, borderColor)
end
if(borderRight)then
self.parent:drawTextBox(x+self.width, y, 1, self.height, "\149")
self.parent:drawForegroundBox(x+self.width, y, 1, self.height, borderColor)
end
if(borderRight)and(borderBottom)then
self.parent:drawTextBox(x+self.width, y+self.height, 1, 1, "\129")
self.parent:drawForegroundBox(x+self.width, y+self.height, 1, 1, borderColor)
end
if(borderBottom)then
self.parent:drawTextBox(x, y+self.height, self.width, 1, "\131")
self.parent:drawForegroundBox(x, y+self.height, self.width, 1, borderColor)
end
if(borderBottom)and(borderLeft)then
self.parent:drawTextBox(x-1, y+self.height, 1, 1, "\131")
self.parent:drawForegroundBox(x-1, y+self.height, 1, 1, borderColor)
end
end
return true
end
return false
end;
getAbsolutePosition = function(self, x, y)
-- relative position to absolute position
if (x == nil) or (y == nil) then
x, y = self:getAnchorPosition()
end
if (self.parent ~= nil) then
local fx, fy = self.parent:getAbsolutePosition(self.parent:getAnchorPosition())
x = fx + x - 1
y = fy + y - 1
end
return x, y
end;
getAnchorPosition = function(self, x, y, ignOff)
if (x == nil) then
x = self.x
end
if (y == nil) then
y = self.y
end
if (anchor == "top") then
x = math.floor(self.parent.width/2) + x - 1
elseif(anchor == "topRight") then
x = self.parent.width + x - 1
elseif(anchor == "right") then
x = self.parent.width + x - 1
y = math.floor(self.parent.height/2) + y - 1
elseif(anchor == "bottomRight") then
x = self.parent.width + x - 1
y = self.parent.height + y - 1
elseif(anchor == "bottom") then
x = math.floor(self.parent.width/2) + x - 1
y = self.parent.height + y - 1
elseif(anchor == "bottomLeft") then
y = self.parent.height + y - 1
elseif(anchor == "left") then
y = math.floor(self.parent.height/2) + y - 1
elseif(anchor == "center") then
x = math.floor(self.parent.width/2) + x - 1
y = math.floor(self.parent.height/2) + y - 1
end
local xO, yO = self:getOffset()
if not(ignOffset or ignOff) then
return x+xO, y+yO
end
return x, y
end;
getOffset = function(self)
if (self.parent ~= nil) then
return self.parent:getFrameOffset()
end
return 0, 0
end;
ignoreOffset = function(self, ignore)
ignOffset = ignore
if(ignore==nil)then ignOffset = true end
return self
end;
getBaseFrame = function(self)
if(self.parent~=nil)then
return self.parent:getBaseFrame()
end
return self
end;
setAnchor = function(self, newAnchor)
anchor = newAnchor
visualsChanged = true
return self
end;
getAnchor = function(self)
return anchor
end;
onChange = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("value_changed", v)
end
end
return self
end;
onClick = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_click", v)
self:registerEvent("monitor_touch", v)
end
end
return self
end;
onClickUp = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_up", v)
end
end
return self
end;
onScroll = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_scroll", v)
end
end
return self
end;
onDrag = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_drag", v)
end
end
return self
end;
onEvent = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("custom_event_handler", v)
end
end
return self
end;
onKey = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("key", v)
self:registerEvent("char", v)
end
end
return self
end;
onResize = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("basalt_resize", v)
end
end
return self
end;
onKeyUp = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("key_up", v)
end
end
return self
end;
onBackgroundKey = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("background_key", v)
self:registerEvent("background_char", v)
end
end
return self
end;
onBackgroundKeyUp = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("background_key_up", v)
end
end
return self
end;
isFocused = function(self)
if (self.parent ~= nil) then
return self.parent:getFocusedObject() == self
end
return false
end;
onGetFocus = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("get_focus", v)
end
end
return self
end;
onLoseFocus = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("lose_focus", v)
end
end
return self
end;
registerEvent = function(self, event, func)
return eventSystem:registerEvent(event, func)
end;
removeEvent = function(self, event, index)
return eventSystem:removeEvent(event, index)
end;
sendEvent = function(self, event, ...)
return eventSystem:sendEvent(event, self, ...)
end;
mouseHandler = function(self, event, button, x, y)
local objX, objY = self:getAbsolutePosition(self:getAnchorPosition())
local yOff = false
if(objY-1 == y)and(self:getBorder("top"))then
y = y+1
yOff = true
end
if (objX <= x) and (objX + self.width > x) and (objY <= y) and (objY + self.height > y) and (isVisible) then
if (self.parent ~= nil) then
self.parent:setFocusedObject(self)
end
local val = eventSystem:sendEvent(event, self, event, button, x, y)
if(val~=nil)then return val end
return true
end
return false
end;
keyHandler = function(self, event, key)
if (self:isFocused()) then
local val = eventSystem:sendEvent(event, self, event, key)
if(val~=nil)then return val end
return true
end
return false
end;
backgroundKeyHandler = function(self, event, key)
local val = eventSystem:sendEvent("background_"..event, self, event, key)
if(val~=nil)then return val end
return true
end;
valueChangedHandler = function(self)
eventSystem:sendEvent("value_changed", self)
end;
eventHandler = function(self, event, p1, p2, p3, p4)
eventSystem:sendEvent("custom_event_handler", self, event, p1, p2, p3, p4)
end;
getFocusHandler = function(self)
local val = eventSystem:sendEvent("get_focus", self)
if(val~=nil)then return val end
return true
end;
loseFocusHandler = function(self)
local val = eventSystem:sendEvent("lose_focus", self)
if(val~=nil)then return val end
return true
end;
}
object.__index = object
return object
end

View File

@@ -0,0 +1,23 @@
-- current version 1
local theme = {
basaltBG = colors.lightGray,
basaltFG = colors.black,
FrameBG = colors.gray,
FrameFG = colors.black,
ButtonBG = colors.gray,
ButtonFG = colors.black,
CheckboxBG = colors.gray,
CheckboxFG = colors.black,
InputBG = colors.gray,
InputFG = colors.black,
textfieldBG = colors.gray,
textfieldFG = colors.black,
listBG = colors.gray,
listFG = colors.black,
dropdownBG = colors.gray,
dropdownFG = colors.black,
radioBG = colors.gray,
radioFG = colors.black,
selectionBG = colors.black,
selectionFG = colors.lightGray,
}

Some files were not shown because too many files have changed in this diff Show More