Building NEW 'Classic' Controls
- OpenXTalkPaul
- Posts: 2633
- Joined: Sat Sep 11, 2021 4:19 pm
- Contact:
Building NEW 'Classic' Controls
"Classic controls" for those who don't know, are the original Engine controls that we've been using as UI elements in the IDE for ages. You CAN add new styled versions of them, I've added a Gray FilledButton control for example. The method for creating new variations on of 'classics' has been documented elsewhere in the forums here.
I wanted to make a new thread to cover a related, but slightly different topic.
As some may know the 'classics' are getting a bit rusty and have not been updated for recent versions of Mac OS (11+) and Windows 11, and so these UI controls may look slightly off compared to other apps on these systems. These classic controls appear to be some hybrid or emulation of UI components from different OS (could be customized subclass of). Some people may think the best thing would be to update them, which requires editing the C++ engine source and recompiling the engines. I mostly use the text fields, buttons and DataGrid myself but I would prefer to be able to use Widgets for most things, for several reason. One reason is that canvas draw Widgets can render identically on all the platforms, there is no guessing as to how it will appear once deployed to a different OS, even when running inside a web browser using the HTML5 Emscripten engine!
Those classic controls are rendered in such a way that is not sub-pixel/high DPI screen friendly and doesn't look as good as Widgets. Widgets are rendered by libSkia canvas drawing routines with sub-pixel precision! Widgets can ALSO use FFI (foreign Function Interface) in order to create a 'native' view port, and place a OS Native UI kit control inside it, provided that they can have eXtension Builder FFI binding strings created to use them.
You can look to the Browser Widget or other widgets that use 'Native layer' to see how widgets render 'placeholder' graphics when the IDE is in Edit mode, but renders external content (for examplt Native Button, or a Web Page from Chromium Embedded Browser) when the Engine is in 'Run' mode. So it may be possible to create a hybrid control that uses 'Native Layer' for native controls when available, but renders a reasonable look-a-like version when 'Native' is not available.
So I want to have a set of widget based controls that are equivalent to the classic controls in appearance, functionality, properties, but is either rendered by canvas drawing (non 'native layer') and/or using actual Native UI components provided by the OS. I'll use this thread to document this goal.
I spent some time this morning trying to fix the broken 'Mac Native' Widgets that were included in the IDE. Currently these do not render the place-holder graphic at all for some reason. But I'm getting the impression that It may be a bit trickier than I expected to create such a hybrid Native/Emulated Widget as I described. Still looking into it.
Some of these widgets I've collected for this goal have already been created previously but may not have been included in the IDE itself. Here's examples of widgets that were already, some already mobile OS theming options:
https://github.com/livecode/livecode/bl ... button.lcb
https://github.com/livecode/livecode/bl ... button.lcb
https://github.com/livecode/livecode/bl ... essbar.lcb
https://github.com/livecode/livecode/bl ... lector.lcb
I wanted to make a new thread to cover a related, but slightly different topic.
As some may know the 'classics' are getting a bit rusty and have not been updated for recent versions of Mac OS (11+) and Windows 11, and so these UI controls may look slightly off compared to other apps on these systems. These classic controls appear to be some hybrid or emulation of UI components from different OS (could be customized subclass of). Some people may think the best thing would be to update them, which requires editing the C++ engine source and recompiling the engines. I mostly use the text fields, buttons and DataGrid myself but I would prefer to be able to use Widgets for most things, for several reason. One reason is that canvas draw Widgets can render identically on all the platforms, there is no guessing as to how it will appear once deployed to a different OS, even when running inside a web browser using the HTML5 Emscripten engine!
Those classic controls are rendered in such a way that is not sub-pixel/high DPI screen friendly and doesn't look as good as Widgets. Widgets are rendered by libSkia canvas drawing routines with sub-pixel precision! Widgets can ALSO use FFI (foreign Function Interface) in order to create a 'native' view port, and place a OS Native UI kit control inside it, provided that they can have eXtension Builder FFI binding strings created to use them.
You can look to the Browser Widget or other widgets that use 'Native layer' to see how widgets render 'placeholder' graphics when the IDE is in Edit mode, but renders external content (for examplt Native Button, or a Web Page from Chromium Embedded Browser) when the Engine is in 'Run' mode. So it may be possible to create a hybrid control that uses 'Native Layer' for native controls when available, but renders a reasonable look-a-like version when 'Native' is not available.
So I want to have a set of widget based controls that are equivalent to the classic controls in appearance, functionality, properties, but is either rendered by canvas drawing (non 'native layer') and/or using actual Native UI components provided by the OS. I'll use this thread to document this goal.
I spent some time this morning trying to fix the broken 'Mac Native' Widgets that were included in the IDE. Currently these do not render the place-holder graphic at all for some reason. But I'm getting the impression that It may be a bit trickier than I expected to create such a hybrid Native/Emulated Widget as I described. Still looking into it.
Some of these widgets I've collected for this goal have already been created previously but may not have been included in the IDE itself. Here's examples of widgets that were already, some already mobile OS theming options:
https://github.com/livecode/livecode/bl ... button.lcb
https://github.com/livecode/livecode/bl ... button.lcb
https://github.com/livecode/livecode/bl ... essbar.lcb
https://github.com/livecode/livecode/bl ... lector.lcb
- tperry2x
- Posts: 3209
- Joined: Tue Dec 21, 2021 9:10 pm
- Location: Somewhere in deepest darkest Norfolk, England
- Contact:
Re: Building NEW 'Classic' Controls
The other option of course is that we intentionally don't do any native controls. We do like godot does and have custom buttons which are intentionally orange / purple / whatever. At least this would have them all looking the same.
-
- Posts: 30
- Joined: Mon Sep 13, 2021 5:02 am
- Contact:
Re: Building NEW 'Classic' Controls
My own opinion for the 2 cents that it is worth (since we don't have pennies any more in Canada, 2 cents is worth exactly nothing!):
<rant>
Native controls are a distraction for OXT because they are always changing and completely out of control of everyone here. You are setting yourself up on a treadmill to failure because you can never fully catch up and stay caught up. Pick a nice neutral wardrobe of UI elements that are NOT Apple OR Google OR Windows OR any other flavor of Linux and get on with making distinctive products that work for your clients and your software. OXT is not going to be the tool to create the next world changing piece of software or the chosen tool of the next Unicorn startup.
It's meant for real users who have a problem to solve and a wish to get their hands dirty. The color or shape of buttons is not going to matter for their solution, and only a small handful of people will ever see or use their code. If one particular user out of ten thousand absolutely must have a button that looks like Apple, Richmond has shown us that you can make your own that are pixel perfect to whatever your standard is. But the other 9,999 users are more concerned what the button does.
Concentrate on making OXT run on all the platforms - YES. But don't worry about whether it looks different on each one. Function trumps all in my books.
</rant>
<rant>
Native controls are a distraction for OXT because they are always changing and completely out of control of everyone here. You are setting yourself up on a treadmill to failure because you can never fully catch up and stay caught up. Pick a nice neutral wardrobe of UI elements that are NOT Apple OR Google OR Windows OR any other flavor of Linux and get on with making distinctive products that work for your clients and your software. OXT is not going to be the tool to create the next world changing piece of software or the chosen tool of the next Unicorn startup.
It's meant for real users who have a problem to solve and a wish to get their hands dirty. The color or shape of buttons is not going to matter for their solution, and only a small handful of people will ever see or use their code. If one particular user out of ten thousand absolutely must have a button that looks like Apple, Richmond has shown us that you can make your own that are pixel perfect to whatever your standard is. But the other 9,999 users are more concerned what the button does.
Concentrate on making OXT run on all the platforms - YES. But don't worry about whether it looks different on each one. Function trumps all in my books.
</rant>
- OpenXTalkPaul
- Posts: 2633
- Joined: Sat Sep 11, 2021 4:19 pm
- Contact:
Re: Building NEW 'Classic' Controls
Yes I'm starting to lean towards not bothering using any 'Native' widgets to try to use OS provided UI elements (Cocoa, WinUI, GTK, Qt, etc.), or trying to do some hybrid, just for simple controls like buttons, tabs, sliders, etc. Instead just make controls with lots of options/properties so users can style them to look any way they like, and maybe include some preset settings for macOS-style, Windows-style, Linux style, etc. Which I think is what the goal was with those widgets that I linked to above. Those aren't real 'native' controls but they do have settings for emulating native appearance on mobile iOS or Android and a few other options. Take that further and have settings for Desktop appearances, and more options for custom appliance (matching properties of the Engine's classic controls).
I spent some time on trying to fix the missing 'preview' for the macOS native widgets so they show something in edit mode, and also did some experiments this week in trying to create 'hybrid' (native OR Canvas Drawn) controls and it was a real pain. It did not feel like it was worth the trouble, particularly when I can get really close to matching 'native' look just by using the classic controls with a custom settings, and beyond that the widget canvas drawing I believe can allow for damn-near perfect OS appearance matching. The controls could still use scripting or XB FFI to retrieve info that may be needed to Appearance matching such as the host system's text highlighting color or whatever. Additional properties would mean the same controls can still be style in completey original styles not matching any existing OS.
- OpenXTalkPaul
- Posts: 2633
- Joined: Sat Sep 11, 2021 4:19 pm
- Contact:
Re: Building NEW 'Classic' Controls
A problem you may not be aware of is macOS darkMode (and maybe dark themes on other OSes) can render certain custom drawn controls, which are non-adaptable, visually completely unreadable. Think about this: you have set a dark foreground text color on top of an OOP INHERITED light background, and then suddenly the light color background is changed to a dark color (inherited from the OS). Now you have dark colored text on a dark color background, which is visually extremely hard to read. Native controls aren't simply about appearance, they may have OS provided functionality and effects the come with them. And 'Native controls' should automatically adapt to changes in the appearance of the OS theme, unlike custom drawn look-alikes that need to be manually updated to keep up with the latest. As I see it that is the main point in having them, to NOT have to keep chasing the latest OS appearances.Kdjanz wrote: ↑Sat Aug 10, 2024 10:38 pm Native controls are a distraction for OXT because they are always changing and completely out of control of everyone here. You are setting yourself up on a treadmill to failure because you can never fully catch up and stay caught up. Pick a nice neutral wardrobe of UI elements that are NOT Apple OR Google OR Windows OR any other flavor of Linux and get on with making distinctive products that work for your clients and your software. OXT is not going to be the tool to create the next world changing piece of software or the chosen tool of the next Unicorn startup.
I do like my own apps/stacks to typically look native and have native features, at least on macOS/Cocoa because, like I said, it's more than simply a static appearance. I don't personally have any clients or users but myself.
However, for the IDE I have also considered the option to just 'go our own way' and have defaults that are a generic style instead, but that also still include options (properties) so that IDE user can alter them to match whatever appearance they like. That's why I renamed my 'New Classic' control from 'macOSDarkmodeButton' to 'Filled Button' because its just a grey button, it doesn't adapt to user changes to the system appearance mode at all, and looks the same on any OS. I also tried to make new icons for the Tools palette that were non-OS specific on the same reasoning, unlike LC CE or OXT Lite my IDE tools palette has only a single set of icons "OXT IDE' set regardless of the platform its running on.
- tperry2x
- Posts: 3209
- Joined: Tue Dec 21, 2021 9:10 pm
- Location: Somewhere in deepest darkest Norfolk, England
- Contact:
Re: Building NEW 'Classic' Controls
I get that with the inherited colours, and how they are charged by the OS. The same is true for classic controls in Linux, although changing system appearance or theme while the IDE is running will cause a hard crash.
Can't other OS's draw the classic controls the same way Linux does?
I mean, Linux is drawing native controls - so can that method be utilised on MacOS and windows to also provide native controls?
Can't other OS's draw the classic controls the same way Linux does?
I mean, Linux is drawing native controls - so can that method be utilised on MacOS and windows to also provide native controls?
-
- Posts: 163
- Joined: Mon Sep 13, 2021 9:46 pm
- Contact:
Re: Building NEW 'Classic' Controls
Just my opinion
I favor native OS controls
Mic
I favor native OS controls
Mic
- OpenXTalkPaul
- Posts: 2633
- Joined: Sat Sep 11, 2021 4:19 pm
- Contact:
Re: Building NEW 'Classic' Controls
I'm not sure but I don't think that the Linux Engine is really rendering Native GTK controls, more like it's inheriting properties from the OS (GTK). I believe it just does that differently depending on the OS, but it's inconsistent. For example Graphics controls and text fields and drop-down menus on macOS DO inherit the correct foreGround/backGround color from the OS (of course that's only if there's no properties set on the objects), but buttons, Menu buttons tab buttons etc. do not.tperry2x wrote: ↑Sun Aug 11, 2024 6:43 am I get that with the inherited colours, and how they are charged by the OS. The same is true for classic controls in Linux, although changing system appearance or theme while the IDE is running will cause a hard crash.
Can't other OS's draw the classic controls the same way Linux does?
I mean, Linux is drawing native controls - so can that method be utilised on MacOS and windows to also provide native controls?
As you may recall I did do some experimenting with 'Native' GTK Button Widget, and it did look different from a Engine created button, for one thing GTK used a different default font for the button's label. https://openxtalk.org/forum/viewtopic.php?t=678
I didnt know about the hard crash on changing the system theme on Linux, that's not good.
- OpenXTalkPaul
- Posts: 2633
- Joined: Sat Sep 11, 2021 4:19 pm
- Contact:
Re: Building NEW 'Classic' Controls
Here's some screenshots of that button widget, and various other widgets I've collected that could be part of a widget-canvas drawn new-'classic controls' set, along with some classic controls:
There's very good examples of doing this in HH's Button Grid. In fact Hermann Hoch's Button Grid was a pretty awesome piece of work.
I also have a modified version of the Tile Widget used formerly only in the old Start Up center label blocks, renamed rather unimaginatively to 'Tile Plus' so I could experiment with it. You can install it from the OXT Extension Manager Repo (on Desktops with a working Browser Widget) in OXT DPE Dp4
There's color inheritance going on, you can see it auto-toggle between dark/light in a desirable way (unlike the classic control button. The Font names are hard coded in the Widget for iOS/Android/macOS Yosemite (current macOS version when the widget was created), but this could be made into editable property, along with adding more color editing and some layer effects options like drop shadows.
In Button-widget you can see there's options for Text Label OR an SVG Path Icon, there currently isn't both, that could be added in. Could add setting pixel data based icon.
There's very good examples of doing this in HH's Button Grid. In fact Hermann Hoch's Button Grid was a pretty awesome piece of work.
I also have a modified version of the Tile Widget used formerly only in the old Start Up center label blocks, renamed rather unimaginatively to 'Tile Plus' so I could experiment with it. You can install it from the OXT Extension Manager Repo (on Desktops with a working Browser Widget) in OXT DPE Dp4
- tperry2x
- Posts: 3209
- Joined: Tue Dec 21, 2021 9:10 pm
- Location: Somewhere in deepest darkest Norfolk, England
- Contact:
Re: Building NEW 'Classic' Controls
This is brilliant stuff.
How hard is it to integrate this into a 'vanilla' copy of LCC (or OXT Lite) as I'd like to change the 'classic controls' - at least on the mac version, over to this. edit: (Although, there's a very valid point around compatibility raised here)
Or.... here's something else I've been pondering the last few days.
As your OXT DPE edition is mainly MacOS orientated, would it be best to just have the DPE edition as the mac version, and perhaps I only continue with 'Lite' on Windows and Linux?

How hard is it to integrate this into a 'vanilla' copy of LCC (or OXT Lite) as I'd like to change the 'classic controls' - at least on the mac version, over to this. edit: (Although, there's a very valid point around compatibility raised here)
Or.... here's something else I've been pondering the last few days.
As your OXT DPE edition is mainly MacOS orientated, would it be best to just have the DPE edition as the mac version, and perhaps I only continue with 'Lite' on Windows and Linux?
- OpenXTalkPaul
- Posts: 2633
- Joined: Sat Sep 11, 2021 4:19 pm
- Contact:
Re: Building NEW 'Classic' Controls
There's lots of good open source community widgets, there should be no compatibility issues with LC CE or OXT Lite.
I have more than this collected (not installed at the moment) but here's a sampling, all widgets. That one with the OXT IDE Icon set displayed is a 'Palette Grid' widget, it's based on the SVG IconPicker widget used in the IDE.
I have more than this collected (not installed at the moment) but here's a sampling, all widgets. That one with the OXT IDE Icon set displayed is a 'Palette Grid' widget, it's based on the SVG IconPicker widget used in the IDE.
- OpenXTalkPaul
- Posts: 2633
- Joined: Sat Sep 11, 2021 4:19 pm
- Contact:
Re: Building NEW 'Classic' Controls
I did do a quite a few Mac-specific extensions, and I do work on macOS most of the time, so understandable why you'd say that, but I do also have Win 10 / Linux installs for testing, just no time for testing.tperry2x wrote: ↑Tue Aug 13, 2024 8:24 pm This is brilliant stuff.![]()
How hard is it to integrate this into a 'vanilla' copy of LCC (or OXT Lite) as I'd like to change the 'classic controls' - at least on the mac version, over to this. edit: (Although, there's a very valid point around compatibility raised here)
Or.... here's something else I've been pondering the last few days.
As your OXT DPE edition is mainly MacOS orientated, would it be best to just have the DPE edition as the mac version, and perhaps I only continue with 'Lite' on Windows and Linux?
A handful of Extensions libraries that I've built or worked on (FluidSynth, HIDAPI, HunSpell) are cross-platform wrappers. I have tried not to be too Mac-centric, all the non-native-layer widget stuff is cross platform and should render the same on every platform (assuming identical fonts are used), All the rest of the work on IDE has not been platform specific.
There's no problem adding whatever you want of it to your OXT Lite builds, but risk being branded OXT Slightly Over Weight, lol
My biggest problem is finding the time to work on making it a nice cohesive set of controls. There's some good widgets to start from already but they all need work done to make them better and consistent with each other.
-
- Posts: 442
- Joined: Sat Sep 11, 2021 4:37 pm
- Contact:
Re: Building NEW 'Classic' Controls
One benefit with the control rendering scheme implemented by the engine's inventor (compiled to machine code from C++ subclasses) is performance.
If you didn't use MetaCard back in the day it may be hard to appreciate how fast it was, and how much rendering performance has dropped over the years.
The current engine was never optimized for games and other things where rendering performance is crucial. It's now noticeably slower than the scriptable rich-media engine everyone has preinstalled on GUI devices, the browser, so ubiquitous it sets the baseline of expectations.
The implications of rendering speed go beyond just games, though that is a category I'd like to see become practical here once day. Rendering speed affects ALL redrawing, from card-to-card navigation to resizing windows. The time difference with a single control type may not impact much, but as more types are converted from machine code to interpreted code the difference compounds.
I can appreciate the attraction to a certain savings in development cost, but please keep in mind it's a net savings, with trade-offs. Many thousands of lines of C++ classes will need to be rewritten if there was an effort to replace controls across the board.
--
There's also a more subtle issue at play, regarding tool modes. Any control implementation should ideally render equally well regardless of the active tool.
xTalks offer a tool mode so devs can deliver a range of apps. SuperCard introduced the pointer tool, and with their vector graphics were able to include a sample app that was a pretty solid implementation, going far beyond MacDraw in features, rivaling SuperPaint. Seeing that example is among the top three influences that got me excited about what xTalks can do. I wouldn't be in this conversation today if it weren't for SampleDraw.
The pointer tool makes a great many app categories practical to deliver in an xTalk, anything that involves visual layout of objects. I've seen specialized CAD apps, postcard makers, facilities management, mind maps, org charts, and a great many other categories built in xTalks.
All of these remain possible where there is an acceptance of the tool mode as a core part of the language, included not just for IDE makers but for every user.
Somewhere after the turn of the century there was a philosophical shift with the tool property within that company, where it was no longer regarded as a useful language feature but instead treated as belonging exclusively to the IDE maintainers.
This shift is most pervasively evident in the language used to describe the tool mode property: over time it began to be referred to as Design Mode, with the browse tool becoming Run Mode.
This has created an environment where the value of the pointer tool in delivered apps has diminished, going so far as engine maintainers suggesting the most protective way to build apps is for scripters to write their own objects and code to emulate the existing pointer tool in the apps where they need layout features. If you've ever done it, you understand the work involved in such a suggestion.
In actionable terms, this philosophical shift, and the prospect of shifting back, invites us to consider two things:
1. IDE messaging can be designed in a way that doesn't need to prohibit devs from using key language feature like tool modes in their own apps, leaving the door open for a wide range of apoa that are free more cumbersome to build if key language feature must be rewritten in script.
2. If prompts IDE maintainers to consider control rendering methods that work equally well regardless of the current tool for a smoother overall user experience.
Thank you for considering this.
If you didn't use MetaCard back in the day it may be hard to appreciate how fast it was, and how much rendering performance has dropped over the years.
The current engine was never optimized for games and other things where rendering performance is crucial. It's now noticeably slower than the scriptable rich-media engine everyone has preinstalled on GUI devices, the browser, so ubiquitous it sets the baseline of expectations.
The implications of rendering speed go beyond just games, though that is a category I'd like to see become practical here once day. Rendering speed affects ALL redrawing, from card-to-card navigation to resizing windows. The time difference with a single control type may not impact much, but as more types are converted from machine code to interpreted code the difference compounds.
I can appreciate the attraction to a certain savings in development cost, but please keep in mind it's a net savings, with trade-offs. Many thousands of lines of C++ classes will need to be rewritten if there was an effort to replace controls across the board.
--
There's also a more subtle issue at play, regarding tool modes. Any control implementation should ideally render equally well regardless of the active tool.
xTalks offer a tool mode so devs can deliver a range of apps. SuperCard introduced the pointer tool, and with their vector graphics were able to include a sample app that was a pretty solid implementation, going far beyond MacDraw in features, rivaling SuperPaint. Seeing that example is among the top three influences that got me excited about what xTalks can do. I wouldn't be in this conversation today if it weren't for SampleDraw.
The pointer tool makes a great many app categories practical to deliver in an xTalk, anything that involves visual layout of objects. I've seen specialized CAD apps, postcard makers, facilities management, mind maps, org charts, and a great many other categories built in xTalks.
All of these remain possible where there is an acceptance of the tool mode as a core part of the language, included not just for IDE makers but for every user.
Somewhere after the turn of the century there was a philosophical shift with the tool property within that company, where it was no longer regarded as a useful language feature but instead treated as belonging exclusively to the IDE maintainers.
This shift is most pervasively evident in the language used to describe the tool mode property: over time it began to be referred to as Design Mode, with the browse tool becoming Run Mode.
This has created an environment where the value of the pointer tool in delivered apps has diminished, going so far as engine maintainers suggesting the most protective way to build apps is for scripters to write their own objects and code to emulate the existing pointer tool in the apps where they need layout features. If you've ever done it, you understand the work involved in such a suggestion.
In actionable terms, this philosophical shift, and the prospect of shifting back, invites us to consider two things:
1. IDE messaging can be designed in a way that doesn't need to prohibit devs from using key language feature like tool modes in their own apps, leaving the door open for a wide range of apoa that are free more cumbersome to build if key language feature must be rewritten in script.
2. If prompts IDE maintainers to consider control rendering methods that work equally well regardless of the current tool for a smoother overall user experience.
Thank you for considering this.
- tperry2x
- Posts: 3209
- Joined: Tue Dec 21, 2021 9:10 pm
- Location: Somewhere in deepest darkest Norfolk, England
- Contact:
Re: Building NEW 'Classic' Controls
How about another approach. Yes, machine code or C++ is a lot faster to execute than xTalk Script, but of course it's a behemoth to try and edit this engine - and I'm not sure if anyone has had success in compiling a Windows and MacOS version as of yet based on the last livecode community source code.
However, I wondered about C++ plugins. Whereby the IDE loads the C++ plugin externally and loads it into memory. Yes, there's probably a penalty with startup time in the IDE, but the benefits would be:
1. There's only one C++ file to edit, to make changes, rather than having to recompile the engine completely each time.
2. Updates are easier as you just swap out the C++ plugin
3. You retain the execution speed once the C++ plugin is loaded into memory.
This is just conjecture on my part - I'll defer to someone who's more of a C++ whiz
However, I wondered about C++ plugins. Whereby the IDE loads the C++ plugin externally and loads it into memory. Yes, there's probably a penalty with startup time in the IDE, but the benefits would be:
1. There's only one C++ file to edit, to make changes, rather than having to recompile the engine completely each time.
2. Updates are easier as you just swap out the C++ plugin
3. You retain the execution speed once the C++ plugin is loaded into memory.
This is just conjecture on my part - I'll defer to someone who's more of a C++ whiz
- OpenXTalkPaul
- Posts: 2633
- Joined: Sat Sep 11, 2021 4:19 pm
- Contact:
Re: Building NEW 'Classic' Controls
Eh, I'm not sure that's accurate comments in regards to what's actually going on.
LibSkia that draws the widget stuff, it is still C++ compiled code in engine doing the rendering (maybe not the compositing to the card layer), lib LibSkia is exposed to LCB (and can be exposed to script engine too) so it may be called from that intermediate byte code language module that wraps it with binding strings which point to internal engine symbols which then do the work (in the UI thread, not the script execution thread). The intermediation / extra syntax look-up might take a thread CPU clock cycle or two, so sure it's not as fast as machine code, but it's fine. Some render slowdowns can be avoided or mitigated with strategic programming of redresh timing, the coding plays a part in speed.
That's not to say I haven't noticed some degradation in the Engine's rendering speed over the years (try 9.6.1 vs 9.6.3 with Animated GIFs!), and I also certainly wouldn't mind using a rendering library that can do all sorts of GPU acceleration 3D models spinning around all over the place, and convex hull distortions on live video streams. But until someone has the time to try to wrap some amazing 3D modeling or game engine thing, or write an embedded xTalk interpreter into one, I'm happy to play around with libSkia's Canvas drawing and try to a new set controls that have a better shot at having a WYSIWYG appearance on every platform.
Widgets libSkia renders pretty faster even without GPU acceleration, they're better looking, and more capable for rendering a lot of 'objects' than using the equivalent amount of classic controls. I can prove that easily with a real world example. Just try using the classic controls to make a grid of Buttons 128 rows or 128 button columns and see how well the classic controls render vs drawing 128x 128 filled/stroked rectangles in a widget and see what renders faster, you'll be waiting a few seconds for the script/classic control version to appear, my widget version of the same grid renders instantly.
I was just working on a text 'field' widget based on MadPink's nice labelBox (which seems to be gone from his GitHub repos now?), It does auto-magic text wrapping. I'm making it have more exposed properties to the Property Inspector, and it can have a transparent background now. I figured out how to get/expose the widgets text prop so you can 'set the text of widget' as you would the text of a field, or the text of an image (which I've always thought was named badly for 'image file data' that it is, but it's been in the interpreter for decades like that). Previously labelBox had used a custom named property name 'someText' which isn't as good for English-like syntax sentences.
Here's the Widget's XB source if anyone wants to play around with it:
LibSkia that draws the widget stuff, it is still C++ compiled code in engine doing the rendering (maybe not the compositing to the card layer), lib LibSkia is exposed to LCB (and can be exposed to script engine too) so it may be called from that intermediate byte code language module that wraps it with binding strings which point to internal engine symbols which then do the work (in the UI thread, not the script execution thread). The intermediation / extra syntax look-up might take a thread CPU clock cycle or two, so sure it's not as fast as machine code, but it's fine. Some render slowdowns can be avoided or mitigated with strategic programming of redresh timing, the coding plays a part in speed.
That's not to say I haven't noticed some degradation in the Engine's rendering speed over the years (try 9.6.1 vs 9.6.3 with Animated GIFs!), and I also certainly wouldn't mind using a rendering library that can do all sorts of GPU acceleration 3D models spinning around all over the place, and convex hull distortions on live video streams. But until someone has the time to try to wrap some amazing 3D modeling or game engine thing, or write an embedded xTalk interpreter into one, I'm happy to play around with libSkia's Canvas drawing and try to a new set controls that have a better shot at having a WYSIWYG appearance on every platform.
Widgets libSkia renders pretty faster even without GPU acceleration, they're better looking, and more capable for rendering a lot of 'objects' than using the equivalent amount of classic controls. I can prove that easily with a real world example. Just try using the classic controls to make a grid of Buttons 128 rows or 128 button columns and see how well the classic controls render vs drawing 128x 128 filled/stroked rectangles in a widget and see what renders faster, you'll be waiting a few seconds for the script/classic control version to appear, my widget version of the same grid renders instantly.
I was just working on a text 'field' widget based on MadPink's nice labelBox (which seems to be gone from his GitHub repos now?), It does auto-magic text wrapping. I'm making it have more exposed properties to the Property Inspector, and it can have a transparent background now. I figured out how to get/expose the widgets text prop so you can 'set the text of widget' as you would the text of a field, or the text of an image (which I've always thought was named badly for 'image file data' that it is, but it's been in the interpreter for decades like that). Previously labelBox had used a custom named property name 'someText' which isn't as good for English-like syntax sentences.
Here's the Widget's XB source if anyone wants to play around with it:
Code: Select all
/**
Name: mouseUp
Type: message
Name: mouseDown
Type: message
**/
widget org.openxtalk.madpink.labelbox
--required metadata
metadata title is "LabelBox"
metadata author is "MadPink, Paul McClernan"
metadata version is "0.0.2"
metadata preferredSize is "242,130"
metadata svgicon is "M1664 512Q1664 432 1608 376 1552 320 1472 320L1408 320 1408 704 1472 704Q1552 704 1608 648 1664 592 1664 512ZM0 1280L1792 1280Q1792 1386 1717 1461 1642 1536 1536 1536L256 1536Q150 1536 75 1461 0 1386 0 1280ZM1856 512Q1856 671 1743.5 783.5 1631 896 1472 896L1408 896 1408 928Q1408 1020 1342 1086 1276 1152 1184 1152L480 1152Q388 1152 322 1086 256 1020 256 928L256 192Q256 166 275 147 294 128 320 128L1472 128Q1631 128 1743.5 240.5 1856 353 1856 512Z"
--use dependencies
use com.livecode.math
use com.livecode.canvas
use com.livecode.widget
use com.livecode.engine
use com.livecode.foreign
use com.livecode.mathfoundation
use com.livecode.library.widgetutils
--list customizable properties
private variable mText as String
property Text get mText set setText
metadata Text.editor is "com.livecode.pi.text"
metadata Text.user_visible is "true"
metadata Text.default is "A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools.\n\n-Douglas Adams"
metadata Text.section is "Basic"
--metadata for built-in properties:
metadata foregroundColor.editor is "com.livecode.pi.color"
metadata foregroundColor.default is "255,255,255,50"
metadata foregroundColor.section is "Colors"
metadata foregroundColor.label is "Text Color"
metadata backgroundColor.editor is "com.livecode.pi.color"
metadata backgroundColor.default is "140,128,145"
metadata backgroundColor.section is "Colors"
metadata backgroundColor.label is "Background Color"
private variable mBackFillOpacity as Number
property backgroundOpacity get mBackFillOpacity set setBackFillOpacity
metadata backgroundOpacity.editor is "com.livecode.pi.number"
metadata backgroundOpacity.default is "0.5"
metadata backgroundOpacity.min is "0"
metadata backgroundOpacity.max is "1.0"
metadata backgroundOpacity.section is "Colors"
metadata backgroundOpacity.label is "Background Opacity"
handler setBackFillOpacity(in pNum as Number) returns nothing
put pNum into mBackFillOpacity
redraw all
end handler
metadata hiliteColor.editor is "com.livecode.pi.color"
metadata hiliteColor.default is "0,0,0"
metadata hiliteColor.section is "Colors"
metadata hiliteColor.label is "Selected button color"
property boxBorder get mBorder set setBorder
metadata boxBorder.editor is "com.livecode.pi.number"
metadata boxBorder.default is "10"
private variable mBorder as Number
property boxRaidus get mRadius set setRadius
metadata boxRaidus.editor is "com.livecode.pi.number"
metadata boxRaidus.default is "15"
private variable mRadius as Number
-- property textFont get mFont set setTextFont
-- metadata textFont.editor is "com.livecode.pi.font"
-- metadata textFont.default is "Helvetica"
metadata textFont.user_visible is "false"
-- private variable mFont as String
metadata textSize.user_visible is "false"
property labelTextFont get mFont set setTextFont
metadata labelTextFont.editor is "com.livecode.pi.font"
metadata labelTextFont.default is "Helvetica"
metadata labelTextFont.section is "Text"
metadata labelTextFont.label is "Label Text Font"
private variable mFont as String
property labelTextSize get mFontSize set setTextFontSize
metadata labelTextSize.editor is "com.livecode.pi.number"
metadata labelTextSize.default is "12"
metadata labelTextSize.section is "Text"
metadata labelTextSize.label is "Label Text Size"
private variable mFontSize as Number
property textAlign get mAlign set setAlign
metadata textAlign.editor is "com.livecode.pi.enum"
metadata textAlign.options is "top left,top center,top right,center left,center center,center right,bottom left,bottom center,bottom right,"
metadata textAlign.default is "center center"
metadata textAlign.section is "Text"
private variable mAlign as String
--declare variables:
private variable mPaint as Paint
private variable mTextPaint as Paint
/**
Syntax:
set the opaque of <widget> to {true|false}
get the opaque of <widget>
Summary: `true` if the SVG path is filled; `false` otherwise
Description:
Use the `opaque` property to test or control whether the SVG path is
displayed as filled or not.
*/
private variable mIsOpague as Boolean
property "opaque" get mIsOpague set setIsOpaque
metadata opaque.default is "true"
metadata opaque.label is "opaque"
public handler setIsOpaque(in pBoolean as Boolean)
put pBoolean into mIsOpague
redraw all
end handler
----constant:
constant kBuffer is 10
----NEEDED handler, saves the properties of the sidget when stack is saved
public handler OnSave(out rProperties as Array)
put the empty array into rProperties
put mText into rProperties["Text"]
put mBorder into rProperties["boxBorder"]
put mFontSize into rProperties["textSize"]
put mAlign into rProperties["textAlign"]
put mFont into rProperties["textFont"]
end handler
----NEEDED handler, loads the saved properties
public handler OnLoad(in pProperties as Array)
put pProperties["Text"] into mText
put pProperties["boxBorder"] into mBorder
put pProperties["textAlign"] into mAlign
put pProperties["textSize"] into mFontSize
put pProperties["textFont"] into mFont
end handler
--HANDLERS to set properties
private handler setText(in pText as String)
put pText into mText
redraw all
end handler
private handler setRadius(in pNum as Number)
put pNum into mRadius
redraw all
end handler
private handler setAlign(in pText as String)
put pText into mAlign
redraw all
end handler
private handler setBorder(in pNum as Number)
put pNum into mBorder
redraw all
end handler
private handler setTextFont(in pText as String)
put pText into mFont
redraw all
end handler
private handler setTextFontSize(in pNum as Number)
put pNum into mFontSize
redraw all
end handler
--CREATE AND DRAW WIDGET:
--OnCreate This is called when the widget is first created:
public handler OnCreate()
variable tFont as Font
variable tFontSize as Number
variable tFontName as String
put 0.5 into mBackFillOpacity
put my font into tFont
put "A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools.\n\n-Douglas Adams" into mText
put the size of my font into tFontSize
put the name of tFont into tFontName
log [tFontName,tFontSize]
-- default font size 12
end handler
--OnPaint This is called on redraw
public handler OnPaint()
if mIsOpague then
mpDrawBase(my foreground paint,my background paint,mBorder,mRadius)
end if
set the paint of this canvas to my foreground paint
mpWrapTextinRect(rectangle [mBorder*2,mBorder*2,my width-mBorder*2,my height-mBorder*2],mText,mAlign)
-- log [my foreground paint,my background paint,mBorder,mRadius]
end handler
private handler mpDrawBase(in pFore as Paint, in pBack as Paint, in pBorder as Number, in pRadius as Number)
variable tRect as Rectangle
variable tBackColor as Color
set the font of this canvas to font mFont at size mFontSize
put the color of pBack into tBackColor
set the opacity of this canvas to mBackFillOpacity
begin layer on this canvas
set the paint of this canvas to solid paint with tBackColor
put rectangle [0,0,my width,my height] into tRect
fill rounded rectangle path of tRect with radius pRadius on this canvas
end layer on this canvas
set the paint of this canvas to pFore
put rectangle [3,3,my width-3,my height-3] into tRect
fill rounded rectangle path of tRect with radius pRadius on this canvas
set the paint of this canvas to pBack
put rectangle [mBorder,mBorder,my width-mBorder,my height-mBorder] into tRect
fill rounded rectangle path of tRect with radius pRadius on this canvas
end handler
private handler mpWrapTextinRect(in pTextBox as Rectangle,in pText as String,in pAlign as String)
variable tTextW as Number
variable tTextH as Number
variable tMaxRows as Number
variable tWords as List
variable tWord as String
variable tLine as String
variable tTestLine as String
variable tRow as Number
variable tAlign as List
variable tLinesofText as List
split pAlign by " " into tAlign
replace newline with " qzqz " in pText
split pText by " " into tWords
set the font of this canvas to font mFont at size mFontSize
put the height of the layout bounds of text pText on this canvas into tTextH
put the width of pTextBox into tTextW
put the floor of ((the height of pTextBox)/tTextH) into tMaxRows
if tMaxRows = 0 then
return
end if
put 1 into tRow
repeat for each element tWord in tWords
put tLine & tWord into tTestLine
if the width of the layout bounds of text tTestLine on this canvas > tTextW or tWord is "qzqz" then
push tLine onto back of tLinesofText
put "" into tTestLine
if tRow=tMaxRows then
put "" into tLine
exit repeat
end if
add 1 to tRow
if tWord is "qzqz" then
put "" into tLine
else
put tWord & " " into tLine
end if
else
put tTestLine & " " into tLine
end if
end repeat
push tLine onto back of tLinesofText
if element 1 of tAlign is "center" then
add ((the height of pTextBox)-(tMaxRows*tTextH) + (tMaxRows-tRow)*tTextH)/2 to the top of pTextBox
else if element 1 of tAlign is "bottom" then
add ((the height of pTextBox)-(tMaxRows*tTextH) + (tMaxRows-tRow)*tTextH) to the top of pTextBox
end if
put 1 into tRow
repeat for each element tLine in tLinesofText
set the height of pTextBox to tTextH
if element 2 of tAlign is "center" then
fill text tLine at center of pTextBox on this canvas
else if element 2 of tAlign is "right" then
fill text tLine at top right of pTextBox on this canvas
else
fill text tLine at top left of pTextBox on this canvas
end if
add 1 to tRow
add tTextH to the top of pTextBox
end repeat
end handler
public handler OnMouseDown()
post "mouseDown"
end handler
public handler OnMouseUp()
post "mouseUp"
end handler
end widget
- tperry2x
- Posts: 3209
- Joined: Tue Dec 21, 2021 9:10 pm
- Location: Somewhere in deepest darkest Norfolk, England
- Contact:
Re: Building NEW 'Classic' Controls
Could you upload a copy of that stack here Paul, just so I can have a play with it in lite. (With the text widget in). I'd like to see if Lite can handle it or not.
- OpenXTalkPaul
- Posts: 2633
- Joined: Sat Sep 11, 2021 4:19 pm
- Contact:
Re: Building NEW 'Classic' Controls
Which stack?
I just edited the previous post to include the LabelBox Extension current source code. Save that to a .lcb file and compile with Extension Builder, it will make a stack with widget placed for you when you click 'Test Extension" (in the lower part of that stack)
The other stacks I've posted screens from are all using Widgets you probably don't have installed, they won't work unless they are installed, you'll get light gray fill in a rect where the widget should be instead.
-
- Posts: 442
- Joined: Sat Sep 11, 2021 4:37 pm
- Contact:
Re: Building NEW 'Classic' Controls
With HyperCard, SuperCard, OMO, Gain Momentum, Toolbook, Director, Spinnaker Plus, MetaCard, Revolution, and LiveCode, what you describe is the Externals interface.tperry2x wrote: ↑Wed Aug 14, 2024 5:35 pm How about another approach. Yes, machine code or C++ is a lot faster to execute than xTalk Script, but of course it's a behemoth to try and edit this engine - and I'm not sure if anyone has had success in compiling a Windows and MacOS version as of yet based on the last livecode community source code.
However, I wondered about C++ plugins. Whereby the IDE loads the C++ plugin externally and loads it into memory. Yes, there's probably a penalty with startup time in the IDE, but the benefits would be:
1. There's only one C++ file to edit, to make changes, rather than having to recompile the engine completely each time.
2. Updates are easier as you just swap out the C++ plugin
3. You retain the execution speed once the C++ plugin is loaded into memory.
This is just conjecture on my part - I'll defer to someone who's more of a C++ whiz
Indeed nearly all of the key bullet points for the v8 product were externals. They continue to be relied on to this day.
-
- Posts: 442
- Joined: Sat Sep 11, 2021 4:37 pm
- Contact:
Re: Building NEW 'Classic' Controls
My assessment of performance is not mine, merely passed on from the company who made Builder.OpenXTalkPaul wrote: ↑Wed Aug 14, 2024 5:51 pm Eh, I'm not sure that's accurate comments in regards to what's actually going on.
LibSkia that draws the widget stuff, it is still C++ compiled code in engine doing the rendering (maybe not the compositing to the card layer), lib LibSkia is exposed to LCB (and can be exposed to script engine too) so it may be called from that intermediate byte code language module that wraps it with binding strings which point to internal engine symbols which then do the work (in the UI thread, not the script execution thread)....
..
That's not to say I haven't noticed some degradation in the Engine's rendering speed over the years...
If you have rendering metrics that favor Builder replacements for machine code, that would be useful for everyone.
- tperry2x
- Posts: 3209
- Joined: Tue Dec 21, 2021 9:10 pm
- Location: Somewhere in deepest darkest Norfolk, England
- Contact:
Re: Building NEW 'Classic' Controls
Ah, I thought it would be as simple as attaching the 'LabelBox' stack in your screenshot.
Obviously it's not.
So I had a go.
I copied that code and pasted into a text editor, saving it as labelbox.lcb
I then opened up the IDE and went into Tools > Extensions Builder.
From there, I chose 'Open an existing extension' and selected my labelbox.lcb file I'd made earlier.
I noticed it made all manner of other files: I then clicked the "Test Extension" in that Extensions Builder window, and indeed I get a new stack called 'LabelBox'. That's the stack I was after, but I'll come back to that.
At first I thought it hadn't worked, but it is there: Note: the label text font was "" and the label text size was 0.
As soon as I set that to a font (Liberation Sans) and 12 under the label text size, it worked and I could change the other properties through the inspector, just as you would a 'classic control'. So, all good.
But, here's where I come back to my question a little further up. When trying to save the stack, I can't. It goes through the motions of saving a stack - but the stack file never appears. I don't get an error or anything either, which means I lose any changes to this new stack, and have to repeat the entire process through 'Extensions Builder' again.
I had hoped it would be a simple oxtstack file that you could copy & paste the 'LabelBox' out of and into a stack of your choice, but it doesn't work like that

Also, I wondered - do these files then need to all live in a subfolder together somewhere? Sorry for all the foolish questions.
Who is online
Users browsing this forum: No registered users and 1 guest