├── CNAME
├── LICENSE
├── README.md
└── docs
├── CNAME
├── TEST.md
├── _config.yml
├── _data
└── meta
│ └── categories.json
├── _features
└── index.md
├── _includes
├── breadcrumbs.html
├── lazyload.html
└── toc.html
├── _intro
└── index.md
├── _layouts
└── default.html
├── _samples
├── customcontrols
│ ├── ccCOMCreatable.png
│ ├── ccClassIdAttribute.png
│ ├── ccClassIdInsert.png
│ ├── ccCustomControlAttribute.png
│ ├── ccGridButtonImage.png
│ ├── ccICustomControl.png
│ ├── ccSampleProject.png
│ ├── defining.md
│ ├── formdesigner.md
│ ├── index.md
│ ├── painting.md
│ └── propertysheetandserialization.md
├── index.md
├── packages
│ ├── createpackage.md
│ ├── importpackagefromfile.md
│ ├── importpackagefromtwinserv.md
│ ├── index.md
│ └── updatepackage.md
└── webview2
│ ├── index.md
│ ├── reentrancy.md
│ └── userdatafolder.md
├── assets
├── lazysizes.min.js
└── treeview.css
├── images
└── twinBASICIconTransparent.png
├── index.md
├── samples.md
└── sitemap.xml
/CNAME:
--------------------------------------------------------------------------------
1 | docs.twinbasic.com
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 twinbasic
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # twinBASIC User Documentation
2 | General user documentation for twinBASIC
3 |
4 | - work in progress
5 |
6 | This repository is the home for general user documentation for everything to do with twinBASIC. The Wiki is the starting point:
7 | https://github.com/twinbasic/documentation/wiki
8 |
9 | If you want to get involved in improving the documentation, please fork the wiki, using the URL https://github.com/twinbasic/documentation.wiki.git, and submit pull requests for your suggested changes.
10 |
11 | All help is very much appreciated :)
12 |
13 |
14 |
15 |
16 | Wayne Phillips
17 |
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | docs.twinbasic.com
--------------------------------------------------------------------------------
/docs/TEST.md:
--------------------------------------------------------------------------------
1 | Another test 😅
2 |
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | url: twinbasic.github.io
2 | title: twinBASIC Documentation
3 | baseurl: /
4 | remote_theme: pages-themes/slate@v0.2.0
5 | markdown: redcarpet
6 | redcarpet:
7 | extensions: ["no_intra_emphasis", "tables", "autolink", "strikethrough", "with_toc_data", "disable_indented_code_blocks"]
8 | defaults:
9 | - scope:
10 | path: ""
11 | values:
12 | layout: default
13 | plugins:
14 | - jekyll-remote-theme
15 | collections:
16 | intro:
17 | output: true
18 | features:
19 | output: true
20 | samples:
21 | output: true
--------------------------------------------------------------------------------
/docs/_data/meta/categories.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "category": "customcontrols",
4 | "title": "Custom Controls",
5 | "description": "Using custom controls in twinBASIC"
6 | },
7 | {
8 | "category": "packages",
9 | "title": "Packages",
10 | "description": "Using packages in twinBASIC and TWINPACK server."
11 | },
12 | {
13 | "category": "webview2",
14 | "title": "WebView2",
15 | "description": "Using WebView2 as a control in twinBASIC"
16 | }
17 | ]
--------------------------------------------------------------------------------
/docs/_features/index.md:
--------------------------------------------------------------------------------
1 | This is tB features main page.
--------------------------------------------------------------------------------
/docs/_includes/breadcrumbs.html:
--------------------------------------------------------------------------------
1 |
51 |
52 |
53 |
61 |
62 |
--------------------------------------------------------------------------------
/docs/_samples/customcontrols/ccCOMCreatable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twinbasic/documentation/a9edde28713c6bbed2ff2032f8eaf1b522e60e0a/docs/_samples/customcontrols/ccCOMCreatable.png
--------------------------------------------------------------------------------
/docs/_samples/customcontrols/ccClassIdAttribute.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twinbasic/documentation/a9edde28713c6bbed2ff2032f8eaf1b522e60e0a/docs/_samples/customcontrols/ccClassIdAttribute.png
--------------------------------------------------------------------------------
/docs/_samples/customcontrols/ccClassIdInsert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twinbasic/documentation/a9edde28713c6bbed2ff2032f8eaf1b522e60e0a/docs/_samples/customcontrols/ccClassIdInsert.png
--------------------------------------------------------------------------------
/docs/_samples/customcontrols/ccCustomControlAttribute.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twinbasic/documentation/a9edde28713c6bbed2ff2032f8eaf1b522e60e0a/docs/_samples/customcontrols/ccCustomControlAttribute.png
--------------------------------------------------------------------------------
/docs/_samples/customcontrols/ccGridButtonImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twinbasic/documentation/a9edde28713c6bbed2ff2032f8eaf1b522e60e0a/docs/_samples/customcontrols/ccGridButtonImage.png
--------------------------------------------------------------------------------
/docs/_samples/customcontrols/ccICustomControl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twinbasic/documentation/a9edde28713c6bbed2ff2032f8eaf1b522e60e0a/docs/_samples/customcontrols/ccICustomControl.png
--------------------------------------------------------------------------------
/docs/_samples/customcontrols/ccSampleProject.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twinbasic/documentation/a9edde28713c6bbed2ff2032f8eaf1b522e60e0a/docs/_samples/customcontrols/ccSampleProject.png
--------------------------------------------------------------------------------
/docs/_samples/customcontrols/defining.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Defining a custom control
3 | category: customcontrols
4 | order: 2
5 | ---
6 |
7 | # Defining a CustomControl
8 |
9 | A CustomControl is simply an ordinary twinBASIC class, with a few extra attributes and requirements.
10 |
11 | {% include toc.html content=page.content skip_toc=page.skip_toc%}
12 |
13 | _**TIP: It is highly advisable to look at and experiment with the sample project provided with twinBASIC before trying to implement your own CustomControl.**_
14 |
15 | {% include lazyload.html image_src="ccSampleProject.png" image_title="CustomControl Sample Project" %}
16 |
17 | ***
18 |
19 | ## CustomControl() attribute
20 |
21 | {% include lazyload.html image_src="ccCustomControlAttribute.png" image_title="CustomControl attribute" %}
22 |
23 | This is a required attribute for all CustomControls. You must provide the relative path to an image file within your project that can be used to identify your control in the form designer toolbox. We recommend that you put the image file in the Miscellaneous folder in your project.
24 |
25 | {% include lazyload.html image_src="ccGridButtonImage.png" image_title="CustomControl GridImage Folder" %}
26 |
27 | ***
28 |
29 | ## ClassId() attribute
30 |
31 | {% include lazyload.html image_src="ccClassIdAttribute.png" image_title="CustomControl ClassId Attribute" %}
32 |
33 | This is a required attribute for all CustomControls. You must provide a unique CLSID (GUID) in order for the form engine to work with your control.
34 |
35 | _**TIP: if you enter ` [ ClassId () ] ` twinBASIC helps you out - just press the 'insert a randomly generated GUID' text:**_
36 |
37 | {% include lazyload.html image_src="ccClassIdInsert.png" image_title="CustomControl ClassId auto-generate" %}
38 |
39 | ***
40 |
41 | ## COMCreatable() attribute
42 |
43 | {% include lazyload.html image_src="ccCOMCreatable.png" image_title="CustomControl COMCreatable attribute" %}
44 |
45 | This is an optional attribute, but it is usually advisable to set this attribute to False, as you don't need to instantiate CustomControls from external COM environments.
46 |
47 | ***
48 |
49 | ## Must implement ICustomControl
50 |
51 | {% include lazyload.html image_src="ccICustomControl.png" image_title="CustomControl ICustomControl interface" %}
52 |
53 | All CustomControls *must* implement CustomControls.ICustomControl. This interface currently has 3 methods that you must implement:
54 |
55 | ```
56 | Sub Initialize(ByVal Context As CustomControlContext)
57 | ```
58 |
59 | This method is called when your control is attached to a form. You must store the provided Context object in a class field as it offers a `Repaint()` method for informing the form engine that something in your control has changed and needs to be repainted.
60 |
61 | ```
62 | Sub Destroy()
63 | ```
64 |
65 | This method is called when your control is detached from a form. This allows an opportunity to break circular references so that your object instance can be destructed properly. The implementation for this can often be left empty provided you don't create circular references in objects.
66 |
67 | ```
68 | Sub Paint(ByVal Canvas As Canvas)
69 | ```
70 |
71 | This is the most interesting part for a CustomControl. As such, it gets its own section, see [Painting / drawing to your control](painting.html)
72 |
73 | ***
74 |
75 | ## Minimum set of properties
76 |
77 | As twinBASIC doesn't yet support inheritance, you must expose a set of common properties (class fields) for all CustomControls:
78 |
79 | ```
80 | Public Name As String
81 | Public Left As CustomControls.PixelCount
82 | Public Top As CustomControls.PixelCount
83 | Public Width As CustomControls.PixelCount
84 | Public Height As CustomControls.PixelCount
85 | Public Anchors As Anchors = New Anchors
86 | Public Dock As CustomControls.DockMode
87 | Public Visible As Boolean
88 | ```
89 |
90 | The form designer and the form engine work with these properties, so it is important to include them in your CustomControl class.
91 |
92 | Note that the form designer works with pixel values which are not DPI-scaled. So the Left/Top/Width/Height properties of your control do not reflect DPI scaling. For example, if your control has a width of 50 pixels, then at DPI 150%, then the actual drawing width is 75 pixels ( see [Painting / drawing to your control](painting.html) ).
93 | ***
94 |
95 | ## Must have a serialization constructor
96 |
97 | CustomControls *must* offer a serialization constructor:
98 |
99 | ```
100 | Public Sub New(Serializer As SerializationInfo)
101 | ```
102 |
103 | The passed in Serializer object offers a `Deserialize()` method that you call in order to load the properties that have been set for your control via the form designer. See [Property Sheet & Object Serialization](propertysheetandserialization.html) for further information.
--------------------------------------------------------------------------------
/docs/_samples/customcontrols/formdesigner.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Form Designer
3 | category: customcontrols
4 | order: 3
5 | ---
6 |
7 |
8 | # Notes about the form designer
9 | For the painting of controls in the form designer, CustomControl instances are instantiated and then release immediately after painting has finished.
--------------------------------------------------------------------------------
/docs/_samples/customcontrols/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Introduction
3 | category: customcontrols
4 | order: 1
5 | ---
6 |
7 | ### Introduction
8 |
9 | twinBASIC now offers experimental support for CustomControls. CustomControls are implemented using the BASIC language, allowing implementers to design controls directly from the twinBASIC environment.
10 |
11 | A few highlights;
12 | - completely custom drawn controls, with no external or third-party dependencies (tiny footprint)
13 | - support 32-bit RGBA for full alpha-transparency
14 | - support high-DPI modes (per-monitor), requiring little thought whilst designing new controls
15 | - full debugging support via the usual twinBASIC integrated debugger
16 | - designed for efficiency so that supporting complex controls with hundreds of elements (e.g. a DataGrid with 100's of cells) is easily possible
17 | - designed for flexibility, allowing for curved corners, multiple borders, background gradients and much more
18 | - the form engine supports anchoring and docking without any considerations needed for CustomControl implementers
19 | - simple property sheet synchronization via the built-in form designer
--------------------------------------------------------------------------------
/docs/_samples/customcontrols/painting.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Painting custom controls
3 | category: customcontrols
4 | order: 3
5 | ---
6 |
7 | # Painting / drawing to your control
8 | ### The ICustomControl.Paint method
9 | This is by far the most important method of a CustomControl. It tells the form engine exactly how you want it to render your control.
10 |
11 | _**TIP: It is highly advisable to look at and experiment with the sample project provided with twinBASIC before trying to implement your own CustomControl.**_
12 |
13 | Private Sub OnPaint(ByVal Canvas As CustomControls.Canvas) _
14 | Implements ICustomControl.Paint
15 |
16 | You are passed a Canvas object that offers the following methods:
17 |
18 | Canvas.Width As Long [Propert-Get]
19 | Canvas.Height As Long [Propert-Get]
20 | Canvas.Dpi As Long [Propert-Get]
21 | Canvas.DpiScaleFactor As Double [Propert-Get]
22 | Canvas.AddElement(Descriptor As ElementDescriptor)
23 |
24 | `Canvas.Width` and `Canvas.Height` are the absolute pixel sizes that your control is drawing to. Unlike your controls Width/Height properties that are not DPI-scaled, the `Canvas.Width` and `Canvas.Height` values **are** DPI-scaled.
25 |
26 | The `Canvas.Dpi` property represents the DPI setting in Windows. If no DPI scaling is in effect, this value is 96. For example, if you have scaling set at 150% on your monitor, then the `Canvas.Dpi` property will be 144.
27 |
28 | The `Canvas.DpiScaleFactor` property gives a floating point value representing the DPI scaling percentage. A value of 1 indicates no scaling. For example, if you have scaling set at 150% on your monitor, then the `Canvas.DpiScaleFactor` property will be 1.5.
29 |
30 | The `Canvas.AddElement` method is used for adding elements to your control. An *element* is considered to be something that the form-engine will render for you. For example, you might have a grid control that displays 100 cells at a time. Each of those cells would be an *element*. Elements can overlap each over (allowing for opacity/transparency). The form engine draws them in the order that you call AddElement, meaning that the last element added will have the highest z-order.
31 | ***
32 | ### AddElement(ElementDescriptor)
33 | The AddElement method takes a single argument; an ElementDescriptor. ElementDescriptor is a UDT that defines exactly how the element will be drawn and how it reacts to events like mouse clicks.
34 |
35 | Public Type ElementDescriptor
36 | OnClick As LongPtr ' event function callback pointer
37 | OnDblClick As LongPtr ' event function callback pointer
38 | OnMouseDown As LongPtr ' event function callback pointer
39 | OnMouseUp As LongPtr ' event function callback pointer
40 | OnMouseEnter As LongPtr ' event function callback pointer
41 | OnMouseLeave As LongPtr ' event function callback pointer
42 | OnMouseMove As LongPtr ' event function callback pointer
43 | OnScrollH As LongPtr ' event function callback pointer
44 | OnScrollV As LongPtr ' event function callback pointer
45 | Left As Long ' pixel offset (control relative, DPI scaled)
46 | Top As Long ' pixel offset (control relative, DPI scaled)
47 | Width As Long ' pixel width (DPI scaled)
48 | Height As Long ' pixel width (DPI scaled)
49 | Cursor As MousePointerConstants ' cursor/pointer icon
50 | TrackingIdX As LongLong ' for tracking this element, passed to events
51 | TrackingIdY As LongLong ' for tracking this element, passed to events
52 | Text As String ' the text to render
53 | TextRenderingOptions As TextRendering ' options to customize text rendering (object)
54 | BackgroundFill As Fill ' options to customize back fill rendering (object)
55 | Corners As Corners ' options to customize corner rendering (object)
56 | Borders As Borders ' options to customize border rendering (object)
57 | End Type
58 | ***
59 | ### Tips
60 | - Each time your OnPaint method is called, you start with a blank canvas.
61 |
62 | - Left/Top/Width/Height can legitimately be outside of the canvas area. For example, negative Left/Top, or a Width/Height past the Canvas.Width/Canvas.Height has no ill-effects. The form engine will clip everything appropriately for you, allowing for much simpler designing of your control.
63 |
64 | - You should put thought into making the Paint routine efficient. Try not to instantiate COM objects, and when drawing multiple similar elements, try to re-use ElementDescriptors by setting up common properties outside of loops (see WaynesGrid for examples of this)
65 |
66 | - TrackingIdX and TrackingIdY are important when you have multiple elements within a control. The two values, when combined, should uniquely represent the element, and must be maintained if your Paint routine is called again. This is needed for supporting events. For example, in a grid control, each cell would have a TrackingIdX / TrackingIdY value associated with it, given the X/Y co-ordinates of the cell.
67 |
68 | - Currently, only mouse events are provided, but focus events are coming soon, as well as keyboard events.
69 |
70 | - You can use class-based event handlers by simply using the `AddressOf MyEvent` which is now possible to use even on class members. You can see this used frequently in the samples, such as WaynesGrid. All mouse events have the following format:
71 | ```
72 | Class MyCustomControl
73 | ...
74 | Private Sub MyClickEvent(ByRef EventInfo As MouseEvent)
75 | MsgBox "You clicked me!"
76 | End Sub
77 |
78 | Private Sub OnPaint(ByVal Canvas As CustomControls.Canvas) _
79 | Implements ICustomControl.Paint
80 | Dim MyDescriptor As ElementDescriptor
81 | MyDescriptor.OnClick = AddressOf MyClickEvent
82 | End Sub
83 | ```
84 | EventInfo (MouseEvent) provides mouse information such as the relative X/Y position of the mouse, plus the TrackingX/Y values discussed earlier.
85 |
86 | - When you call Canvas.AddElement, your element goes into a render pipeline. It is **not** immediately painted to the screen. The render pipeline is compared to the previous render pipeline that was provided by you in the last OnPaint call, and the tB form engine will only redraw areas of the control that have changed. This allows for efficient painting of controls whilst not needing to be concerned about the finer details of how to do partial repainting.
--------------------------------------------------------------------------------
/docs/_samples/customcontrols/propertysheetandserialization.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Property Sheets and Serialization
3 | category: customcontrols
4 | order: 5
5 | ---
6 |
7 | # Property Sheet & Object Serialization
8 | The form designer property sheet will pickup any **_public_** custom properties (fields) that you expose via your CustomControl class. For example, adding a field `Public MyField As Long` will then automatically show up in the control property sheet in the form designer:
9 |
10 | 
11 |
12 | This is then persisted to your project as properties inside your form JSON structure:
13 |
14 | 
15 |
16 | The key to making this work is your serialization constructor, which might look something like this:
17 |
18 | Public Sub New(Serializer As SerializationInfo)
19 | If Not Serializer.Deserialize(Me) Then
20 | InitializeDefaultValues ' you implement this
21 | End If
22 | End Sub
23 | If `Deserialize(Me)` returns `True`, then your class properties were synchronized with the properties set via the form designer. If it returns `False` then the control has just been added to the form, and this gives you an opportunity to setup any suitable default values for your custom public properties. The form designer notices default values you set within the serialization constructor, so that your property sheet is kept in-sync.
24 | ***
25 | ### Default Values
26 | An alternative method for setting up default values is to inline them into the class field definition:
27 |
28 | 
29 |
30 | The `Deserialize(Me)` call inside your serialization constructor will overwrite the property value if the control is being synchronized from the persisted property sheet data.
31 | ***
32 | ### Enumerations
33 | Enumerations that you define in your twinBASIC project are supported. Simply expose a class field with the enumeration:
34 |
35 | 
36 |
37 | Note: Enumerations are persisted to the form JSON structure as strings, so bare this in mind when making changes/updates to a CustomControl so that you don't introduce breaking changes by renaming an enumeration value.
38 | ***
39 | ### Objects
40 | Class objects that you define in your twinBASIC project are supported. You ***must*** supply a ClassId attribute for any exposed object, so that the serialization can identify it.
41 |
42 | 
43 | ***
44 | ### Arrays
45 | Arrays are supported. The form designer allows for adding new elements, removing elements, and re-ordering of elements (via drag/drop).
46 |
47 | 
48 | ***
49 | ### Property Get / Let
50 | Custom property procedures are supported. You will find that using Property Get / Let procedures is required if you want property changes to trigger repainting of your control.
51 |
52 | 
53 |
54 | Note that _**private**_ fields and properties do not form part of the serialization, and so will not appear on the property sheet.
55 | ***
56 | ### Avoid Variants
57 | The serialization does not support Variants or generic Objects. Always use strongly-typed datatypes.
58 | ***
59 | ### Events
60 | Events that you define in your class will be exposed in the Events property sheet:
61 |
62 | 
63 |
64 | At the moment, the form-designer doesn't yet support code-behind-forms, so this feature is not yet complete.
65 | ***
66 | ### Tips
67 | - If you make changes to your CustomControl class, such as exposing new properties or changing how a control is drawn, these changes will get reflected immediately to any open form designers. Form designers will show a 'resync' button when you return to them, once pressed the changes will be apparent.
68 |
69 | - The serialization happens via JSON when running in the IDE, but via a binary format when running in a compiled DLL/EXE. The `SerializationInfo` object that is passed to your serialization constructor is a different implementation when running in the IDE, but this should be transparent to you as a CustomControl implementer.
70 |
71 | - When making changes or updates to a CustomControl always consider backwards compatibility. For example, if you rename an exposed property, the old property values stored via the property sheet won't be deserialized to your new property.
--------------------------------------------------------------------------------
/docs/_samples/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | permalink: /samples/index.html
3 | ---
4 | This is tB samples main page.
5 |
6 |
23 | {% endfor %}
--------------------------------------------------------------------------------
/docs/_samples/packages/createpackage.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Creating a TWINPACK package
3 | category: packages
4 | order: 1
5 | ---
6 |
7 | ### Creating a TWINPACK package
8 |
9 | To create a new TWINPACK package, navigate to the twinBASIC activity panel and choose the option labelled 'Package':
10 |
11 |
12 |
13 |
14 |
15 | Once you've created the project, you should find the extra 'TWINBASIC PACKAGE MANAGER' panel in the main Explorer activity panel:
16 |
17 |
18 |
19 |
20 |
21 | You should now edit the Namespace, Description, Licence and Visibility properties appropriately by using the package manager 'EDIT' links, which will take you to the individual settings in the `Settings` file. Once you've edited them, remember to close (and save) the `Settings` file in order for your changes to be reflected in the package manager panel.
22 |
23 | - **Namespace:** this is the symbol that will be used to group your components in projects that reference your package. For example, a package that provides a series of different dialog classes might use the namespace `Dialogs`.
24 | - **Description:** this is the descriptive text that will appear in the `Settings`->`References` list. If you plan to share this package, it is wise to think carefully about the description so that others can find your package easily through TWINSERV.
25 | - **Licence:** this short text appears in the `Settings`->`References` list, alongside the Description. If you plan to share this package, it is important that you enter this field, and the value you enter here should appropriately match the content of the LICENCE.md file (e.g. 'MIT', 'LGPL' etc).
26 | - **Visibility:** determines whether the package is visible to only you (PRIVATE) or everyone (PUBLIC). The value set here only takes effect when you use the 'PUBLISH THIS PACKAGE' button to publish your package in the package manager service, TWINSERV.
27 |
28 | *If you don't plan to publish your package on TWINSERV, then you don't need to fill in the **Licence** or **Visibility** fields.*
29 |
30 | You can now create components (Class, Module, Interface) in your project as normal, and when you are finished, it's time to finalize the package. You have two options;
31 |
32 |
33 |
34 | ### OPTION 1 - Finalize the package into a TWINPACK file
35 |
36 | Use this option if you want to just create a local TWINPACK file that you can use in other projects. For this, the build process is the same as any ordinary twinBASIC build... just hit the Build button in the TWINBASIC panel:
37 |
38 |
39 |
40 |
41 |
42 | You'll see the build output notification in the `DEBUG CONSOLE`, as seen above.
43 |
44 | Job done. See [Importing a package from a TWINPACK file](https://github.com/WaynePhillipsEA/twinbasic/wiki/twinBASIC-Packages-Importing-a-package-from-a-TWINPACK-file) for referencing and using the TWINPACK file in other twinBASIC projects.
45 |
46 |
47 |
48 | ### OPTION 2 - Publish the package directly to the package manager service (TWINSERV)
49 |
50 | If you're publishing your package onto TWINSERV, you don't need to create the TWINPACK file manually. Just use the 'PUBLISH THIS PACKAGE' button:
51 |
52 |
53 |
54 |
55 |
56 | ***Publishing packages onto TWINSERV requires you to first create a publisher account. If you haven't done so, you'll be prompted to do so at this stage.***
57 |
58 | You will then be prompted to confirm the package details:
59 |
60 |
61 |
62 |
63 |
64 | After pressing `YES`, the package will be uploaded to TWINSERV. Check the `DEBUG CONSOLE` for completion notices:
65 |
66 |
67 |
68 |
69 |
70 | If the package got uploaded successfully, it should be available via TWINSERV within a few moments. If you've created a `PUBLIC` package, others will be able to see and download it at this point.
71 |
72 | See [Importing a package from TWINSERV](https://github.com/WaynePhillipsEA/twinbasic/wiki/twinBASIC-Packages-Importing-a-package-from-TWINSERV) for referencing and using the uploaded packages.
73 |
74 |
75 |
76 |
77 | ### Special files LICENCE.md and CHANGELOG.md
78 |
79 | When you create a new package project, you'll see two additional files created for you in the project filesystem:
80 |
81 |
82 |
83 |
84 |
85 | If you're publishing a `PUBLIC` package to the package manager service, it is important that you edit these two files before publishing. These are both markdown files, and will in future become more accessible to users that are considering using your package from TWINSERV.
--------------------------------------------------------------------------------
/docs/_samples/packages/importpackagefromfile.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Importing a package from a TWINPACK file
3 | category: packages
4 | order: 3
5 | ---
6 |
7 | ### Importing a package from a TWINPACK file
8 |
9 | To import a package directly from a TWINPACK file (instead of using TWINSERV), follow these steps.
10 |
11 | - open the project from which you want to use a package
12 | - open the `Settings` file within it
13 | - navigate to the References section
14 | - select the 'TWINPACK PACKAGES' button
15 | - press the 'Import from file...' button:
16 |
17 |
18 |
19 |
20 | - choose the TWINPACK file you want to import, and then it should appear in the references list (ticked):
21 |
22 |
23 |
24 |
25 | - close and save the `Settings` file to restart the compiler
26 |
27 | Now you're ready to use the package! In the example shown above I added a reference to the TwinLib64 package, and I can now confirm that I can access components from the TwinLib64 package in my code:
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/docs/_samples/packages/importpackagefromtwinserv.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Import a package from TWINSERV
3 | category: packages
4 | order: 4
5 | ---
6 |
7 | ### Importing a package from TWINSERV
8 |
9 | Open the project from which you want to use a package, open the `Settings` file within it and navigate to the References section. Select the 'TWINPACK PACKAGES' button, and all packages that are on the server should be shown:
10 |
11 |
12 |
13 |
14 |
15 | If you tick one of the available packages, it will be downloaded and imported into the project:
16 |
17 |
18 |
19 |
20 |
21 | Once you're finished, save and close the Settings file which will cause the compiler to be restarted. Now you're ready to use the package! In the example shown above I added a reference to the TwinLib64 package, and I can now confirm that I can access components from the TwinLib64 package in my code:
22 |
23 |
24 |
25 |
26 |
27 | Note: I have a couple of PRIVATE packages that I have published, which are only available to me when I am signed in. If you are not already signed in, you will see a warning link that you can click to login:
28 |
29 |
30 |
31 |
32 |
33 | After logging in, press the 'TWINPACK PACKAGES' button again to refresh the list.
--------------------------------------------------------------------------------
/docs/_samples/packages/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: What's a package?
3 | category: packages
4 | order: 1
5 | ---
6 |
7 | ### What's a package?
8 |
9 | In twinBASIC, a *package* is a collection of components that you can reference from another twinBASIC project. The components can be modules, classes or interfaces.
10 |
11 | A twinBASIC package is distributed as a TWINPACK file that contains everything needed by the components in that package. A project that references a TWINPACK package, imports the whole package into the file system of the root project, resulting in no external dependencies.
12 |
13 | With TWINPACK packages you group common components together into their own namespace whilst allowing for convenient code reuse without any of the problems often associated with using external DLL libraries.
14 |
15 | twinBASIC comes complete with a package manager service called TWINSERV, allowing you to easily share and distribute TWINPACK packages to other twinBASIC developers.
16 |
17 | Please be aware that TWINPACK files currently contain the full sourcecode of your packaged components. It is planned that we will in future allow for creating binary (compiled) TWINPACK files for developers that hold an Ultimate edition licence of twinBASIC.
--------------------------------------------------------------------------------
/docs/_samples/packages/updatepackage.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Updating a package
3 | category: packages
4 | order: 5
5 | ---
6 |
7 | ### Updating a package
8 |
9 | #### NOTE: at the moment, the twinBASIC VS Code extension does not notify you about package updates that are available on TWINSERV. This feature is planned, and will be available soon.
10 |
11 | If you find an updated package is available on TWINSERV, you must first remove the old package from your project by deselecting it:
12 |
13 |
14 |
15 |
16 |
17 |
18 | You will then be prompted to remove it from the filesystem:
19 |
20 |
21 |
22 |
23 |
24 |
25 | Select YES. Now, you can add the updated package to your project as usual. See [Importing a package from TWINSERV](https://github.com/WaynePhillipsEA/twinbasic/wiki/twinBASIC-Packages-Importing-a-package-from-TWINSERV).
26 |
27 | #### Don't forget to close the Settings file and save the changes! (which will in turn cause a restart of the compiler).
28 |
--------------------------------------------------------------------------------
/docs/_samples/webview2/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Getting started
3 | category: webview2
4 | order: 1
5 | ---
6 |
7 | ### Getting Started
8 |
9 | #### Package requirements
10 |
11 | To create projects that use WebView2, your projects must include both the `WinNativeForms` package and the `WebView2` package in your projects.
12 |
13 | Both of these packages can be added through the `Project` > `References` menu option, and selecting the `TWINPACK PACKAGES` button. Ensure both packages are ticked, and then close and save the Settings file and restart the compiler.
14 |
15 |
16 |
17 |
18 |
19 | Once you've added the package references, you should find that the WebView2 control is now available to you in the form designer:
20 |
21 |
22 |
23 |
24 |
25 | #### Create a WebView2 control on a form
26 |
27 | We use the WebView2 control just like any ordinary control:
28 |
29 |
30 |
31 |
32 |
33 | #### WebView2 control properties
34 |
35 | There are lots of WebView2 properties and events to experiment with.
36 |
37 |
38 |
39 |
40 | Note that toggling any property will show extra information at the bottom of the properties list to give you a little bit more information. For further information on a particular property, try searching the official WebView2 documentation
41 |
42 | ## Samples
43 |
44 | If you prefer to start with a sample, have a look at `Sample 0. WebView2 Examples`, available in the new-project dialog:
45 |
46 |
47 |
--------------------------------------------------------------------------------
/docs/_samples/webview2/reentrancy.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Information about re-entrancy
3 | category: webview2
4 | order: 3
5 | ---
6 |
7 | ## Information about re-entrancy
8 |
9 | The WebView2 API is very particular about not allowing for re-entrancy from its events (see Threading model for WebView2 apps). This means that when we process events such as `NavigationCompleted` we are ordinarily prohibited from doing anything with the WebView2 object model before returning from that event. So for example, you couldn't navigate to a new URL from within the `NavigivationCompleted` event itself.
10 |
11 | To work around these limitations, our WebView2 implementation defers all event handling by retriggering events through the form message loop. This allows events to be handled and execution control returns to WebView2 immediately, and then our deferred event gets triggered once WebView2 returns to the main message loop.
12 |
13 | Due to the design of our implementation, for the most part you can forget about the re-entrancy limitations imposed by the WebView2 API. However, if you use the `AddObject` feature of WebView2 which allows you to expose a twinBASIC class instance to javascript, then you need to be aware that there are two modes available for the `AddObject` feature.
14 |
15 | #### AddObject(ObjectInstance As Object, UseDeferredInvoke As Boolean)
16 |
17 | If you pass `True` to the `UseDeferredInvoke` parameter of the `AddObject` call, then calls that come in to your class instance from javascript will be treated **asynchronously** and so you cannot return a value to javascript. This is great for event notifications.
18 |
19 | If you pass `False` to the `UseDeferredInvoke` parameter of the `AddObject` call, then calls that come in to your class instance from javascript will be treated **synchronously** and so you can return a value to be consumed by javascript, but you MUST ensure that you don't cause re-entrancy, so you MUST NOT make calls back into the WebView2 control methods and properties. Be warned: if you do make calls back into the WebView2 control when you're not using `UseDeferredInvoke`, then you will cause deadlocks leading to your application becoming unstable and sometimes lingering in the task manager after shutdown.
20 |
21 | Note that it is perfectly acceptable to add two separate objects, one for asynchronous event handling (using `UseDeferredInvoke:=True`) and another for synchronous properties (using `UseDeferredInvoke:=False`).
--------------------------------------------------------------------------------
/docs/_samples/webview2/userdatafolder.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Customize the UserDataFolder
3 | category: webview2
4 | order: 2
5 | ---
6 |
7 | ## Customize the UserDataFolder
8 |
9 | At runtime, WebView2 needs a working folder for storing data used during the session. By default, a folder will be created in the same folder as your executable file, called `.WebView2` (e.g. `MyApp.Exe.WebView2`). If this folder cannot be created, the WebView2 control will not work (you can catch the controls Error event to determine this at runtime).
10 |
11 | This default behaviour is not always appropriate. For example, if you're creating an Addin for Microsoft Access, then you almost certainly will not be allowed to create a folder called `MSACCESS.EXE.WebView2` in the Office sub folder of your systems Program Files folder.
12 |
13 | It is HIGHLY recommended that you override the default behaviour, and instead provide a path that is considered to be safe to use for storing such data. To override the UserDataFolder path at runtime, handle the Create event of the WebView2 control. See the example in `Sample 9. ActiveX Control WebView2 + Monaco` here, where we use the `%APPDATA%\Local` system path:
14 |
15 |
16 |
17 |
18 |
19 | Set the `EnvironmentOptions.UserDataFolder` property to a string containing the output path to use (folder will be created if necessary).
--------------------------------------------------------------------------------
/docs/assets/lazysizes.min.js:
--------------------------------------------------------------------------------
1 | /*! lazysizes - v5.3.2 */
2 |
3 | !function(e){var t=function(u,D,f){"use strict";var k,H;if(function(){var e;var t={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",fastLoadedClass:"ls-is-cached",iframeLoadMode:0,srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:true,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:true,ricTimeout:0,throttleDelay:125};H=u.lazySizesConfig||u.lazysizesConfig||{};for(e in t){if(!(e in H)){H[e]=t[e]}}}(),!D||!D.getElementsByClassName){return{init:function(){},cfg:H,noSupport:true}}var O=D.documentElement,i=u.HTMLPictureElement,P="addEventListener",$="getAttribute",q=u[P].bind(u),I=u.setTimeout,U=u.requestAnimationFrame||I,o=u.requestIdleCallback,j=/^picture$/i,r=["load","error","lazyincluded","_lazyloaded"],a={},G=Array.prototype.forEach,J=function(e,t){if(!a[t]){a[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")}return a[t].test(e[$]("class")||"")&&a[t]},K=function(e,t){if(!J(e,t)){e.setAttribute("class",(e[$]("class")||"").trim()+" "+t)}},Q=function(e,t){var a;if(a=J(e,t)){e.setAttribute("class",(e[$]("class")||"").replace(a," "))}},V=function(t,a,e){var i=e?P:"removeEventListener";if(e){V(t,a)}r.forEach(function(e){t[i](e,a)})},X=function(e,t,a,i,r){var n=D.createEvent("Event");if(!a){a={}}a.instance=k;n.initEvent(t,!i,!r);n.detail=a;e.dispatchEvent(n);return n},Y=function(e,t){var a;if(!i&&(a=u.picturefill||H.pf)){if(t&&t.src&&!e[$]("srcset")){e.setAttribute("srcset",t.src)}a({reevaluate:true,elements:[e]})}else if(t&&t.src){e.src=t.src}},Z=function(e,t){return(getComputedStyle(e,null)||{})[t]},s=function(e,t,a){a=a||e.offsetWidth;while(a49?function(){o(t,{timeout:n});if(n!==H.ricTimeout){n=H.ricTimeout}}:te(function(){I(t)},true);return function(e){var t;if(e=e===true){n=33}if(a){return}a=true;t=r-(f.now()-i);if(t<0){t=0}if(e||t<9){s()}else{I(s,t)}}},ie=function(e){var t,a;var i=99;var r=function(){t=null;e()};var n=function(){var e=f.now()-a;if(e0;if(r&&Z(i,"overflow")!="visible"){a=i.getBoundingClientRect();r=C>a.left&&pa.top-1&&g500&&O.clientWidth>500?500:370:H.expand;k._defEx=u;f=u*H.expFactor;c=H.hFac;A=null;if(w2&&h>2&&!D.hidden){w=f;N=0}else if(h>1&&N>1&&M<6){w=u}else{w=_}}if(l!==n){y=innerWidth+n*c;z=innerHeight+n;s=n*-1;l=n}a=d[t].getBoundingClientRect();if((b=a.bottom)>=s&&(g=a.top)<=z&&(C=a.right)>=s*c&&(p=a.left)<=y&&(b||C||p||g)&&(H.loadHidden||x(d[t]))&&(m&&M<3&&!o&&(h<3||N<4)||W(d[t],n))){R(d[t]);r=true;if(M>9){break}}else if(!r&&m&&!i&&M<4&&N<4&&h>2&&(v[0]||H.preloadAfterLoad)&&(v[0]||!o&&(b||C||p||g||d[t][$](H.sizesAttr)!="auto"))){i=v[0]||d[t]}}if(i&&!r){R(i)}}};var a=ae(t);var S=function(e){var t=e.target;if(t._lazyCache){delete t._lazyCache;return}L(e);K(t,H.loadedClass);Q(t,H.loadingClass);V(t,B);X(t,"lazyloaded")};var i=te(S);var B=function(e){i({target:e.target})};var T=function(e,t){var a=e.getAttribute("data-load-mode")||H.iframeLoadMode;if(a==0){e.contentWindow.location.replace(t)}else if(a==1){e.src=t}};var F=function(e){var t;var a=e[$](H.srcsetAttr);if(t=H.customMedia[e[$]("data-media")||e[$]("media")]){e.setAttribute("media",t)}if(a){e.setAttribute("srcset",a)}};var s=te(function(t,e,a,i,r){var n,s,o,l,u,f;if(!(u=X(t,"lazybeforeunveil",e)).defaultPrevented){if(i){if(a){K(t,H.autosizesClass)}else{t.setAttribute("sizes",i)}}s=t[$](H.srcsetAttr);n=t[$](H.srcAttr);if(r){o=t.parentNode;l=o&&j.test(o.nodeName||"")}f=e.firesLoad||"src"in t&&(s||n||l);u={target:t};K(t,H.loadingClass);if(f){clearTimeout(c);c=I(L,2500);V(t,B,true)}if(l){G.call(o.getElementsByTagName("source"),F)}if(s){t.setAttribute("srcset",s)}else if(n&&!l){if(d.test(t.nodeName)){T(t,n)}else{t.src=n}}if(r&&(s||l)){Y(t,{src:n})}}if(t._lazyRace){delete t._lazyRace}Q(t,H.lazyClass);ee(function(){var e=t.complete&&t.naturalWidth>1;if(!f||e){if(e){K(t,H.fastLoadedClass)}S(u);t._lazyCache=true;I(function(){if("_lazyCache"in t){delete t._lazyCache}},9)}if(t.loading=="lazy"){M--}},true)});var R=function(e){if(e._lazyRace){return}var t;var a=n.test(e.nodeName);var i=a&&(e[$](H.sizesAttr)||e[$]("sizes"));var r=i=="auto";if((r||!m)&&a&&(e[$]("src")||e.srcset)&&!e.complete&&!J(e,H.errorClass)&&J(e,H.lazyClass)){return}t=X(e,"lazyunveilread").detail;if(r){re.updateElem(e,true,e.offsetWidth)}e._lazyRace=true;M++;s(e,t,r,i,a)};var r=ie(function(){H.loadMode=3;a()});var o=function(){if(H.loadMode==3){H.loadMode=2}r()};var l=function(){if(m){return}if(f.now()-e<999){I(l,999);return}m=true;H.loadMode=3;a();q("scroll",o,true)};return{_:function(){e=f.now();k.elements=D.getElementsByClassName(H.lazyClass);v=D.getElementsByClassName(H.lazyClass+" "+H.preloadClass);q("scroll",a,true);q("resize",a,true);q("pageshow",function(e){if(e.persisted){var t=D.querySelectorAll("."+H.loadingClass);if(t.length&&t.forEach){U(function(){t.forEach(function(e){if(e.complete){R(e)}})})}}});if(u.MutationObserver){new MutationObserver(a).observe(O,{childList:true,subtree:true,attributes:true})}else{O[P]("DOMNodeInserted",a,true);O[P]("DOMAttrModified",a,true);setInterval(a,999)}q("hashchange",a,true);["focus","mouseover","click","load","transitionend","animationend"].forEach(function(e){D[P](e,a,true)});if(/d$|^c/.test(D.readyState)){l()}else{q("load",l);D[P]("DOMContentLoaded",a);I(l,2e4)}if(k.elements.length){t();ee._lsFlush()}else{a()}},checkElems:a,unveil:R,_aLSL:o}}(),re=function(){var a;var n=te(function(e,t,a,i){var r,n,s;e._lazysizesWidth=i;i+="px";e.setAttribute("sizes",i);if(j.test(t.nodeName||"")){r=t.getElementsByTagName("source");for(n=0,s=r.length;n summary::before{
78 | content : '−';
79 | }
--------------------------------------------------------------------------------
/docs/images/twinBASICIconTransparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twinbasic/documentation/a9edde28713c6bbed2ff2032f8eaf1b522e60e0a/docs/images/twinBASICIconTransparent.png
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # Work in progress...
2 | Check back soon. The site is under active construction, please don't enter without a hard hat.
3 |
4 |
--------------------------------------------------------------------------------
/docs/samples.md:
--------------------------------------------------------------------------------
1 | This is tB samples main page.
2 |
3 |